% Specific to general induction algorithm
% run_specific():-Calls specific_to_general with both H and N initialized to []

run_specific :- specific_to_general([],[]).
% specific_to_general(List_of_hypotheses, List_of_negatives) :- 
%	This is the top level control loop. It reads in a new positive or
% 	negative instance and calls process to update List_of_hypotheses
%	and List_of_negatives. 

specific_to_general(H, N) :-
	write("H = "), write(H),nl,
	write("N = "), write(N),nl,
	write("Enter Instance "),
	process(Instance, H, N, Updated_H, Updated_N),
	specific_to_general(Updated_H, Updated_N).

% process(Instance, List_of_hypotheses, List_of_negatives, 
%	Updated_hypotheses, Updated_negatives) :-
%	updates List_of_hypotheses and List_of_negatives in response to
%	Instance.  

process(positive(Instance), [], N, [Instance], N). 
% Initialize H
process(positive(Instance), H, N, Updated_H, N) :- 
	generalize_set(H,Gen_H, Instance),
	delete(X, Gen_H, (member(Y, Gen_H), more_general(X, Y)), Pruned_H),
	delete(X, Pruned_H, (member(Y, N), covers(X, Y)), Updated_H).	

process(negative(Instance), H, N, Updated_H, [Instance|N]) :- 
		delete(X, H, covers(X, Instance), Updated_H).

process(Input, H, N, H, N):- 
	Input \= positive(_),
	Input \= negative(_),
	write("Enter either positive(Instance) or negative(Instance) "), nl.


generalize_set([], [], _).

	not(covers(Hypothesis, Instance)),
	(bagof(X, generalize(Hypothesis, Instance, X), Updated_head); Updated_head = []),
	generalize_set(Rest,Updated_rest, Instance),
	append(Updated_head, Updated_rest, Updated_H).

	covers(Hypothesis, Instance),
	generalize_set(Rest,Updated_rest, Instance).

generalize([Feature|Rest], [Inst_prop|Rest_inst], [Feature|Rest_gen]) :-
	not(Feature \= Inst_prop),
	generalize(Rest, Rest_inst, Rest_gen).
generalize([Feature|Rest], [Inst_prop|Rest_inst], [_|Rest_gen]) :-
	Feature \= Inst_prop,
	generalize(Rest, Rest_inst, Rest_gen).

% more_general(Feature_vector_1, Feature_vector_2) :- succeeds if
%	Feature_vector_1 is strictly more general than Feature_vector_2
more_general(X, Y) :-  not(covers(Y, X)), covers(X, Y).

% covers(Feature_list_1, Feature_list_2) :- Succeeds if Feature_list_1
%	covers Feature_list_2.  Note that covers, unlike unification is
%	not symmetric: variables in Feature_list_2 will not match constants
%	in Feature_list_1.

covers([H1|T1], [H2|T2]) :-
	var(H1), var(H2), 
	covers(T1, T2).
covers([H1|T1], [H2|T2]) :-
	var(H1), atom(H2), 
	covers(T1, T2).	
covers([H1|T1], [H2|T2]) :-
	atom(H1), atom(H2), H1 = H2,
	covers(T1, T2).

% delete(Element, List1, Goal, List2) :- List2 contains all bindings
%	of Element to a member of List1 except those that cause 
%	Goal to succeed

delete(X, L, Goal, New_L) :-
	(bagof(X, (member(X, L), not(Goal)), New_L);New_L = []).

Close Window