The document discusses inductive logic programming. It begins with an introduction to inductive reasoning, abduction, and induction. It then discusses concept learning and Mitchell's candidate elimination algorithm for inductive logic programming. The document provides examples of inducing hypotheses from examples and learning the append predicate through recursive least general generalization. It also discusses generalizing clauses through theta-subsumption and computing the least general generalization of two clauses.
The document discusses inductive logic programming. It begins with an introduction to inductive reasoning, abduction, and induction. It then discusses concept learning and Mitchell's candidate elimination algorithm for inductive logic programming. The document provides examples of inducing hypotheses from examples and learning the append predicate through recursive least general generalization. It also discusses generalizing clauses through theta-subsumption and computing the least general generalization of two clauses.
3 Inductive Logic Programming Reasoning with incomplete information default reasoning abduction induction assume normal state of affairs, unless there is evidence to the contrary choose between several explanations that explain an observation generalize a rule from a number of similar observations If something is a bird, it ies. I ipped the switch, but the light doesnt turn on. The bulb mist be broken The sky is full of dark clouds. It will rain. 4 Inductive Logic Programming Inductive reasoning Given: B: background theory (clauses of logic program) P: positive examples (ground facts) N: negative examples (ground facts) Find a hypothesis H such that H covers every positive example given B ! p " P: B # H $ p H does not cover any negative example given B ! n " N: B # H % n 5 Inductive Logic Programming
Concept learning tries to nd a suitable concept in a
description space where descriptions are related via generalization/specialization relationships. Examples are at the bottom of the generalization hierarchy.
A concept is suitable if it covers (generalizes) all positive and
none of the negative examples.
Learning capabilities depend on the characteristics of the
description space: too rough makes learning impossible, too ne leads to trivial concepts (e.g. when the description space supports disjunction).
A well-known algorithm is Mitchells candidate elimination
algorithm where upper and lower bounds of possible solutions are updated according to input examples. 6 Inductive reasoning & learning Inductive Logic Programming Try to adapt the abductive meta-interpreter: inducible/1 denes the set of possible hypothesis induce(E,H) :- induce(E,[],H). induce(true,H,H). induce((A,B),H0,H) :- induce(A,H0,H1), induce(B,H1,H). induce(A,H0,H) :- clause(A,B), induce(B,H0,H). induce(A,H0,H) :- member((A:-B),H0), induce(B,H0,H). induce(A,H0,[(A:-B)|H]) : inducible((A:-B)), not(member((A:-B),H0)), induce(B,H0,H). Inductive reasoning vs abduction Abduction: given a theory T and an observation O, nd an explanation E such that T#E&O 7 Inductive Logic Programming inducible((flies(X):-bird(X),has_feathers(X),has_beak(X))). inducible((flies(X):-has_feathers(X),has_beak(X))). inducible((flies(X):-bird(X),has_beak(X))). inducible((flies(X):-bird(X),has_feathers(X))). inducible((flies(X):-bird(X))). inducible((flies(X):-has_feathers(X))). inducible((flies(X):-has_beak(X))). inducible((flies(X):-true)). bird(tweety). has_feathers(tweety). bird(polly). has_beak(polly). Inductive reasoning vs abduction 8 Inductive Logic Programming Listing all inducible hypothesis is impractical. Better to systematically search the hypothesis space (typically large and possibly innite when functors are involved). Avoid overgeneralisation by including negative examples in search process. ?-induce(flies(tweety),H). H = [(flies(tweety):-bird(tweety),has_feathers(tweety))]; H = [(flies(tweety):-bird(tweety))]; H = [(flies(tweety):-has_feathers(tweety))]; H = [(flies(tweety):-true)]; No more solutions Inductive reasoning vs abduction 9 Inductive Logic Programming example action hypothesis + p(b,[b]) p(X,Y). add clause - p(x,[]) specialize p(X,[V|W]). - p(x,[a,b]) specialize p(X,[X|W]). + p(b,[a,b]) add clause p(X,[X|W]). p(X,[V|W]):-p(X,W). Inductive reasoning: a hypothesis search involving successive generalisation and specialisation steps of a current hypothesis Inductive reasoning ground fact for the predicate of which a denition is to be induced that is either true (+ example) or false (- example) under the intended interpretation 10 Inductive Logic Programming 11 ?- induce_rlgg([ +append([1,2],[3,4],[1,2,3,4]), +append([a],[],[a]), +append([],[],[]), +append([],[1,2,3],[1,2,3]), +append([2],[3,4],[2,3,4]), +append([],[3,4],[3,4]), -append([a],[b],[b]), -append([c],[b],[c,a]), -append([1,2],[],[1,3]) ], Clauses). Learning append/3 RLGG of append([1,2],[3,4],[1,2,3,4]) and append([a],[],[a]) is append([X|Y],Z,[X|U]) :- [append(Y,Z,U)] Covered example: append([1,2],[3,4],[1,2,3,4]) Covered example: append([a],[],[a]) Covered example: append([2],[3,4],[2,3,4]) RLGG of append([],[],[]) and append([],[1,2,3],[1,2,3]) is append([],X,X) :- [] Covered example: append([],[],[]) Covered example: append([],[1,2,3],[1,2,3]) Covered example: append([],[3,4],[3,4]) Clauses = [(append([],X,X) :- []), (append([X|Y],Z,[X|U]) :- [append(Y,Z,U)])] Inductive Logic Programming A clause c1 !-subsumes a clause c2 ! a substitution ! such that c1! " c2 H1;...;Hn :" B1,...,Bm H1 '...' Hn ' B1 '...' Bm element(X,V) :- element(X,Z) !-subsumes element(X,[Y|Z]) :- element(X,Z) using ! = {V " [Y|Z]} a(X) :- b(X) !-subsumes a(X) :- b(X), c(X). using ! = id Generalising clauses: !-subsumption 12 Inductive Logic Programming clause c1 !-subsumes c2 c1 $ c2 H1 is at least as general as H2 given B H1 covers everything covered by H2 given B ! p " P: B # H2 $ p B # H1 $ p B # H1 $ H2 Generalising clauses: !-subsumption versus $ 13 The reverse is not true: list([]). % c0 list([H1,H2|T]) :- list(T). % c1 list([A|B]) :- list(B). % c2 c1 $ c2, but there is no substitution ! such that c1! ( c2 a(X) :- b(X). % c1 p(X) :- p(X). % c2 Inductive Logic Programming theta_subsumes((H1:-B1),(H2:-B2)):- verify((ground((H2:-B2)),H1=H2,subset(B1,B2))). verify(Goal) :- not(not(call(Goal))). ground(Term):- numbervars(Term,0,N). A clause c1 !-subsumes a clause c2 ! a substitution ! such that c1! " c2 14 Generalising clauses: Testing for !-subsumption % instantiate vars in Term to terms of the form % $VAR(i) where i is different for each distinct % var, first i=0, last = N-1 Inductive Logic Programming ?- theta_subsumes((element(X,V):- []), (element(X,V):- [element(X,Z)])). yes. ?- theta_subsumes((element(X,a):- []), (element(X,V):- [])). no. 15 Generalising clauses: Testing for !-subsumption A clause c1 !-subsumes a clause c2 ! a substitution ! such that c1! " c2 Inductive Logic Programming member(1,[1]). member(z,[z,y,x]). member(X,[X|Y]). s u b s u m e s
u s i n g !
=
{ X / 1 ,
Y / [ ] }
s u b s u m e s
u s i n g !
=
{ X / z ,
Y / [ y , x ] }
a1 a2 a3 happens to be the least general (or most specic) generalisation because all other atoms that !-subsume a1 and a2 also !-subsume a3: member(X,[Y|Z]). member(X,Y). 16 Generalising clauses: generalising two clauses Inductive Logic Programming g(f(f(a)),X) g(f(X),f(a)) g(f(X),X) g(f(X),Y) g(f(f(a)),f(a)) t1 is more general than t2 for some substitution !: t1! = t2 greatest lower bound of two terms: unication least upper bound of two terms: anti-unication specialization = applying a substitution generalization = applying an inverse substitution (terms to variables) anti-unication unication 17 Generalising clauses: generalising two clauses Inductive Logic Programming dual of unication compare corresponding argument terms of two atoms, replace by variable if they are different replace subsequent occurrences of same term by same variable ?- anti_unify(2*2=2+2,2*3=3+3,T,[],S1,[],S2). T = 2 * _G191 = _G191 + _G191 S1 = [2 <- _G191] S2 = [3 <- _G191] 18 Generalising clauses: will not compute proper inverse substitutions: not clear which occurrences of 2 are mapped to _G191 (all but the rst) BUT we are only interested in the !-LGG Inductive Logic Programming :- op(600,xfx,<-). anti_unify(Term1,Term2,Term) :- anti_unify(Term1,Term2,Term,[],S1,[],S2). anti_unify(Term1,Term2,Term1,S1,S1,S2,S2) :- Term1 == Term2, !. anti_unify(Term1,Term2,V,S1,S1,S2,S2) :- subs_lookup(S1,S2,Term1,Term2,V), !. anti_unify(Term1,Term2,Term,S10,S1,S20,S2) :- nonvar(Term1), nonvar(Term2), functor(Term1,F,N), functor(Term2,F,N), !, functor(Term,F,N), anti_unify_args(N,Term1,Term2,Term,S10,S1,S20,S2). anti_unify(Term1,Term2,V,S10,[Term1<-V|S10],S20,[Term2<-V|S20]). 19 Generalising clauses: Inductive Logic Programming anti_unify_args(0,Term1,Term2,Term,S1,S1,S2,S2). anti_unify_args(N,Term1,Term2,Term,S10,S1,S20,S2):- N>0, N1 is N-1, arg(N,Term1,Arg1), arg(N,Term2,Arg2), arg(N,Term,ArgN), anti_unify(Arg1,Arg2,ArgN,S10,S11,S20,S21), anti_unify_args(N1,Term1,Term2,Term,S11,S1,S21,S2). subs_lookup([T1<-V|Subs1],[T2<-V|Subs2],Term1,Term2,V) :- T1 == Term1, T2 == Term2, !. subs_lookup([S1|Subs1],[S2|Subs2],Term1,Term2,V):- subs_lookup(Subs1,Subs2,Term1,Term2,V). 20 Generalising clauses: Inductive Logic Programming C1 is more general than C2 for some substitution !: C1! " C2 greatest lower bound of two clauses: !-MGS least upper bound of two clauses: !-LGG specialization = applying a substitution and/or adding a literal generalization = applying an inverse substitution and/or removing a literal anti-unication and/or removing literal unication and/or adding literal m(X,Y) m(X,[Y|Z]) m([X|Y],Z) m(X,Y):-m(Y,X) m(X,[X|Z]) m(X,X) m(X,[Y|Z]):-m(X,Z) 21 Generalising clauses: Inductive Logic Programming similar to, and depends on, anti-unication of atoms but the body of a clause is (logically speaking) unordered therefore have to compare all possible pairs of atoms (one from each body) ?- theta_lgg((element(c,[b,c]):-[element(c,[c])]), (element(d,[b,c,d]):-[element(d,[c,d]),element(d,[d])]), C). C = element(X,[b,c|Y]):-[element(X,[c|Y]),element(X,[X])] obtained by anti-unifying original heads obtained by anti-unifying element(c,[c]) and element(d,[c,d]) obtained by anti-unifying element(c,[c]) and element(d,[d]) 22 Generalising clauses: computing the ! least-general generalization Inductive Logic Programming theta_lgg((H1:-B1),(H2:-B2),(H:-B)):- anti_unify(H1,H2,H,[],S10,[],S20), theta_lgg_bodies(B1,B2,[],B,S10,S1,S20,S2). theta_lgg_bodies([],B2,B,B,S1,S1,S2,S2). theta_lgg_bodies([Lit|B1],B2, B0,B, S10,S1, S20,S2):- theta_lgg_literal(Lit,B2, B0,B00, S10,S11, S20,S21), theta_lgg_bodies(B1,B2, B00,B, S11,S1, S21,S2). theta_lgg_literal(Lit1,[], B,B, S1,S1, S2,S2). theta_lgg_literal(Lit1,[Lit2|B2],B0,B,S10,S1,S20,S2):- same_predicate(Lit1,Lit2), anti_unify(Lit1,Lit2,Lit,S10,S11,S20,S21), theta_lgg_literal(Lit1,B2,[Lit|B0],B, S11, S1,S21,S2). theta_lgg_literal(Lit1,[Lit2|B2],B0,B,S10,S1,S20,S2):- not(same_predicate(Lit1,Lit2)), theta_lgg_literal(Lit1,B2,B0,B,S10,S1,S20,S2). same_predicate(Lit1,Lit2) :- functor(Lit1,P,N), functor(Lit2,P,N). 23 Generalising clauses: computing the ! least-general generalization Inductive Logic Programming ?- theta_lgg((reverse([2,1],[3],[1,2,3]):-[reverse([1],[2,3],[1,2,3])]), (reverse([a],[],[a]):-[reverse([],[a],[a])]), C). C = reverse([X|Y], Z, [U|V]) :- [reverse(Y, [X|Z], [U|V])] rev([2,1],[3],[1,2,3]):-rev([1],[2,3],[1,2,3]) X Y Z U V Y X Z U V rev([a] ,[] ,[a] ):-rev([] ,[a] ,[a] ) 24 Generalising clauses: computing the ! least-general generalization Inductive Logic Programming relative least general generalization rlgg(e1,e2,M) of two positive examples e1 and e2 relative to a partial model M is dened as: rlgg(e1, e2, M) = lgg((e1 :- Conj(M)), (e2 :- Conj(M))) 25 Bottom up induction
conjunction of all positive examples plus ground facts for the background predicates specic-to-general search of the hypothesis space Inductive Logic Programming Generalising clauses: relative least general generalization append([1,2],[3,4],[1,2,3,4]). append([a],[],[a]). append([],[],[]). append([2],[3,4],[2,3,4]). M e1 e2 ?- theta_lgg((append([1,2],[3,4],[1,2,3,4]) :- [append([1,2],[3,4],[1,2,3,4]), append([a],[],[a]), append([],[],[]), append([2],[3,4],[2,3,4])]), (append([a],[],[a]):- [append([1,2],[3,4],[1,2,3,4]), append([a],[],[a]),append([],[],[]), append([2],[3,4],[2,3,4])]), C) rlgg(e1,e2,M) 26 Inductive Logic Programming append([X|Y], Z, [X|U]) :- [ append([2], [3, 4], [2, 3, 4]), append(Y, Z, U), append([V], Z, [V|Z]), append([K|L], [3, 4], [K, M, N|O]), append(L, P, Q), append([], [], []), append(R, [], R), append(S, P, T), append([A], P, [A|P]), append(B, [], B), append([a], [], [a]), append([C|L], P, [C|Q]), append([D|Y], [3, 4], [D, E, F|G]), append(H, Z, I), append([X|Y], Z, [X|U]), append([1, 2], [3, 4], [1, 2, 3, 4]) ] rlgg(e1,e2,M) variables in body are proper subset of variables in head 27 Generalising clauses: relative least general generalization Too Complex!! Inductive Logic Programming rlgg(E1,E2,M,(H:- B)):- anti_unify(E1,E2,H,[],S10,[],S20), varsin(H,V), rlgg_bodies(M,M,[],B,S10,S1,S20,S2,V). rlgg_bodies([],B2,B,B,S1,S1,S2,S2,V). rlgg_bodies([L|B1],B2,B0,B,S10,S1,S20,S2,V):- rlgg_literal(L,B2,B0,B00,S10,S11,S20,S21,V), rlgg_bodies(B1,B2,B00,B,S11,S1,S21,S2,V). 28 Generalising clauses: relative least general generalization (algorithm) rlgg_bodies(B0,B1,BR0,BR,S10,S1,S20,S2,V): rlgg all literals in B0 with all literals in B1, yielding BR (from accumulator BR0) containing only vars in V Inductive Logic Programming rlgg_literal(L1,[],B,B,S1,S1,S2,S2,V). rlgg_literal(L1,[L2|B2],B0,B,S10,S1,S20,S2,V):- same_predicate(L1,L2), anti_unify(L1,L2,L,S10,S11,S20,S21), varsin(L,Vars), var_proper_subset(Vars,V), !, rlgg_literal(L1,B2,[L|B0],B,S11,S1,S21,S2,V). rlgg_literal(L1,[L2|B2],B0,B,S10,S1,S20,S2,V):- rlgg_literal(L1,B2,B0,B,S10,S1,S20,S2,V). 29 Generalising clauses: relative least general generalization (algorithm) Inductive Logic Programming var_remove_one(X,[Y|Ys],Ys) :- X == Y. var_remove_one(X,[Y|Ys],[Y|Zs) :- var_remove_one(X,Ys,Zs). var_proper_subset([],Ys) :- Ys \= []. var_proper_subset([X|Xs],Ys) :- var_remove_one(X,Ys,Zs), var_proper_subset(Xs,Zs). varsin(Term,Vars):- varsin(Term,[],V), sort(V,Vars). varsin(V,Vars,[V|Vars]):- var(V). varsin(Term,V0,V):- functor(Term,F,N), varsin_args(N,Term,V0,V). varsin_args(0,Term,Vars,Vars). varsin_args(N,Term,V0,V):- N>0, N1 is N-1, arg(N,Term,ArgN), varsin(ArgN,V0,V1), varsin_args(N1,Term,V1,V). 30 Generalising clauses: relative least general generalization (algorithm) Inductive Logic Programming ?- rlgg(append([1,2],[3,4],[1,2,3,4]), append([a],[],[a]), [append([1,2],[3,4],[1,2,3,4]), append([a],[],[a]), append([],[],[]), append([2],[3,4],[2,3,4])], (H:- B)). H = append([X|Y], Z, [X|U]) B = [append([2], [3, 4], [2, 3, 4]), append(Y, Z, U), append([], [], []), append([a], [], [a]), append([1, 2], [3, 4], [1, 2, 3, 4])] 31 Generalising clauses: relative least general generalization (algorithm) Inductive Logic Programming construct rlgg of two positive examples remove all positive examples that are extensionally covered by the constructed clause further generalize the clause by removing literals as long as no negative examples are covered 32 Bottom up induction main algorithm Inductive Logic Programming induce_rlgg(Exs,Clauses):- pos_neg(Exs,Poss,Negs), bg_model(BG), append(Poss,BG,Model), induce_rlgg(Poss,Negs,Model,Clauses). induce_rlgg(Poss,Negs,Model,Clauses):- covering(Poss,Negs,Model,[],Clauses). pos_neg([],[],[]). pos_neg([+E|Exs],[E|Poss],Negs):- pos_neg(Exs,Poss,Negs). pos_neg([-E|Exs],Poss,[E|Negs]):- pos_neg(Exs,Poss,Negs). 33 Bottom up induction main algorithm Inductive Logic Programming covering(Poss,Negs,Model,Hyp0,NewHyp) :- construct_hypothesis(Poss,Negs,Model,Hyp), !, remove_pos(Poss,Model,Hyp,NewPoss), covering(NewPoss,Negs,Model,[Hyp|Hyp0],NewHyp). covering(P,N,M,H0,H) :- append(H0,P,H). remove_pos([],M,H,[]). remove_pos([P|Ps],Model,Hyp,NewP) :- covers_ex(Hyp,P,Model), !, write(Covered example: ), write_ln(P), remove_pos(Ps,Model,Hyp,NewP). remove_pos([P|Ps],Model,Hyp,[P|NewP]):- remove_pos(Ps,Model,Hyp,NewP). covers_ex((Head:- Body), Example,Model):- verify((Head=Example, forall(element(L,Body), element(L,Model)))). 34 Bottom up induction main algorithm (covering) Inductive Logic Programming construct_hypothesis([E1,E2|Es],Negs,Model,Clause):- write(RLGG of ), write(E1), write( and ), write(E2), write( is), rlgg(E1,E2,Model,Cl), reduce(Cl,Negs,Model,Clause), !, nl,tab(5), write_ln(Clause). construct_hypothesis([E1,E2|Es],Negs,Model,Clause):- write_ln( too general), construct_hypothesis([E2|Es],Negs,Model,Clause). 35 Bottom up induction main algorithm (hypothesis construction) Inductive Logic Programming reduce((H:-B0),Negs,M,(H:-B)):- setof0(L, (element(L,B0), not(var_element(L,M))), B1), reduce_negs(H,B1,[],B,Negs,M). setof0(X,G,L):- setof(X,G,L),!. setof0(X,G,[]). var_element(X,[Y|Ys]):- X == Y. var_element(X,[Y|Ys]):- var_element(X,Ys). 36 Bottom up induction main algorithm (hypothesis reduction) Inductive Logic Programming covers_neg(Clause,Negs,Model,N) :- element(N,Negs), covers_ex(Clause,N,Model). reduce_negs(H,[L|Rest],B0,B,Negs,Model):- append(B0,Rest,Body), not(covers_neg((H:-Body),Negs,Model,N)), !, reduce_negs(H,Rest,B0,B,Negs,Model). reduce_negs(H,[L|Rest],B0,B,Negs,Model):- reduce_negs(H,Rest,[L|B0],B,Negs,Model). reduce_negs(H,[],Body,Body,Negs,Model):- not(covers_neg((H:- Body),Negs,Model,N)). 37 Bottom up induction main algorithm (hypothesis reduction) Inductive Logic Programming 38 Bottom up induction example RLGG of append([1,2],[3,4],[1,2,3,4]) and append([a],[],[a]) is append([X|Y],Z,[X|U]) :- [append(Y,Z,U)] Covered example: append([1,2],[3,4],[1,2,3,4]) Covered example: append([a],[],[a]) Covered example: append([2],[3,4],[2,3,4]) RLGG of append([],[],[]) and append([],[1,2,3],[1,2,3]) is append([],X,X) :- [] Covered example: append([],[],[]) Covered example: append([],[1,2,3],[1,2,3]) Covered example: append([],[3,4],[3,4]) Clauses = [(append([],X,X) :- []), (append([X|Y],Z,[X|U]) :- [append(Y,Z,U)])] ?- induce_rlgg([ +append([1,2],[3,4],[1,2,3,4]), +append([a],[],[a]), +append([],[],[]), +append([],[1,2,3],[1,2,3]), +append([2],[3,4],[2,3,4]), +append([],[3,4],[3,4]), -append([a],[b],[b]), -append([c],[b],[c,a]), -append([1,2],[],[1,3]) ], Clauses). Inductive Logic Programming 39 Bottom up induction example RLGG of listnum([],[]) and listnum([2,three,4],[two,3,four]) is too general RLGG of listnum([2,three,4],[two,3,four]) and listnum([4],[four]) is listnum([X|Xs],[Y|Ys]):-[num(X,Y),listnum(Xs,Ys)] Covered example: listnum([2,three,4],[two,3,four]) Covered example: listnum([4],[four]) RLGG of listnum([],[]) and listnum([three,4],[3,four]) is too general RLGG of listnum([three,4],[3,four]) and listnum([two],[2]) is listnum([V|Vs],[W|Ws]):-[num(W,V),listnum(Vs,Ws)] Covered example: listnum([three,4],[3,four]) Covered example: listnum([two],[2]) Clauses =[(listnum([V|Vs],[W|Ws]):-[num(W,V),listnum(Vs,Ws)]), (listnum([X|Xs],[Y|Ys]):-[num(X,Y),listnum(Xs,Ys)]),listnum([],[]) ] bg_model([num(1,one),num(2,two), num(3,three), num(4,four), num(5,five)]). ?-induce_rlgg([ +listnum([],[]), +listnum([2,three,4],[two,3,four]), +listnum([4],[four]), +listnum([three,4],[3,four]), +listnum([two],[2]), -listnum([1,4],[1,four]), -listnum([2,three,4],[two]), -listnum([five],[5,5]) ], Clauses). Inductive Logic Programming Start with the most general denition further specialize the clause by adding literals as long as negative examples are covered 40 Top down induction main algorithm Inductive Logic Programming 41 Top down induction main algorithm Inductive Logic Programming 42 induce_spec(Examples,Clauses):- process_examples([],[],Examples,Clauses). % process the examples process_examples(Clauses,Done,[],Clauses). process_examples(Cls1,Done,[Ex|Exs],Clauses):- process_example(Cls1,Done,Ex,Cls2), process_examples(Cls2,[Ex|Done],Exs,Clauses). Top down induction main algorithm literal(append(X,Y,Z),[list(X),list(Y),list(Z)]). term(list([]),[]). term(list([X|Y]),[item(X),list(Y)]). Inductive Logic Programming 43 Top down induction main algorithm process_example(Clauses,Done,+Example,Clauses):- covers(Clauses,Example). process_example(Cls,Done,+Example,Clauses):- not covers(Cls,Example), generalise(Cls,Done,Example,Clauses). process_example(Cls,Done,-Example,Clauses):- covers(Cls,Example), specialise(Cls,Done,Example,Clauses). process_example(Clauses,Done,-Example,Clauses):- not covers(Clauses,Example). covers(Clauses,Example):- prove_d(10,Clauses,Example). prove_d(D,Cls,true):-!. prove_d(D,Cls,(A,B)):-!, prove_d(D,Cls,A), prove_d(D,Cls,B). prove_d(D,Cls,A):- D>0,D1 is D-1, copy_element((A:-B),Cls), prove_d(D1,Cls,B). prove_d(D,Cls,A):- prove_bg(A). prove_bg(true):-!. prove_bg((A,B)):-!, prove_bg(A), prove_bg(B). prove_bg(A):- bg((A:-B)), prove_bg(B). Inductive Logic Programming 44 Top down induction search_clause(Exs,Example,Clause):- literal(Head,Vars), try((Head=Example)), search_clause(3,a((Head:-true),Vars),Exs,Example,Clause). search_clause(D,Current,Exs,Example,Clause):- write(D),write('..'), search_clause_d(D,Current,Exs,Example,Clause),!. search_clause(D,Current,Exs,Example,Clause):- D1 is D+1, !,search_clause(D1,Current,Exs,Example,Clause). search_clause_d(D,a(Clause,Vars),Exs,Example,Clause):- covers_ex(Clause,Example,Exs), % goal not((element(-N,Exs),covers_ex(Clause,N,Exs))),!. search_clause_d(D,Current,Exs,Example,Clause):- D>0,D1 is D-1, specialise_clause(Current,Spec), search_clause_d(D1,Spec,Exs,Example,Clause). generalise(Cls,Done,Example,Clauses):- search_clause(Done,Example,Cl), write('Found clause: '),write(Cl),nl, process_examples([Cl|Cls],[],[+Example|Done],Clauses). generalisation try(Goal):- not(not(Goal)). Inductive Logic Programming % false_clause(Cs,E,E,C) <- C is a false clause in the proof of E (or ok) false_clause(Cls,Exs,true,ok):-!. false_clause(Cls,Exs,(A,B),X):-!, false_clause(Cls,Exs,A,Xa), ( Xa = ok -> false_clause(Cls,Exs,B,X) ; otherwise -> X = Xa ). false_clause(Cls,Exs,E,ok):- element(+E,Exs),!. false_clause(Cls,Exs,A,ok):- bg((A:-B)),!. false_clause(Cls,Exs,A,X):- copy_element((A:-B),Cls), false_clause(Cls,Exs,B,Xb), ( Xb \= ok -> X = Xb ; otherwise -> X = (A:-B) ). 45 Top down induction specialise(Cls,Done,Example,Clauses):- false_clause(Cls,Done,Example,C), remove_one(C,Cls,Cls1), write(' ...refuted: '),write(C),nl, process_examples(Cls1,[],[-Example|Done],Clauses). specialisation Inductive Logic Programming 46 covers_ex((Head:-Body),Example,Exs):- try((Head=Example,covers_ex(Body,Exs))). covers_ex(true,Exs):-!. covers_ex((A,B),Exs):-!, covers_ex(A,Exs), covers_ex(B,Exs). covers_ex(A,Exs):- element(+A,Exs). covers_ex(A,Exs):- prove_bg(A). Top down induction Auxiliaries Inductive Logic Programming 47 apply_subs(a(Clause,Vars),a(Spec,SVars)):- copy_term(a(Clause,Vars),a(Spec,Vs)), apply_subs1(Vs,SVars). apply_subs1(Vars,SVars):- unify_two(Vars,SVars). apply_subs1(Vars,SVars):- subs_term(Vars,SVars). specialise_clause(Current,Spec):- add_literal(Current,Spec). specialise_clause(Current,Spec):- apply_subs(Current,Spec). add_literal(a((H:-true),Vars),a((H:-L),Vars)):-!, literal(L,LVars), proper_subset(LVars,Vars). add_literal(a((H:-B),Vars),a((H:-L,B),Vars)):- literal(L,LVars), proper_subset(LVars,Vars). Top down induction Auxiliaries unify_two([X|Vars],Vars):- element(Y,Vars), X=Y. unify_two([X|Vars],[X|SVars]):- unify_two(Vars,SVars). subs_term(Vars,SVars):- remove_one(X,Vars,Vs), term(Term,TVars), X=Term, append(Vs,TVars,SVars). Inductive Logic Programming 48 Top down induction Example ?-induce_spec([+append([],[b,c],[b,c]), -append([],[a,b],[c,d]), -append([a,b],[c,d],[c,d]), -append([a],[b,c],[d,b,c]), -append([a],[b,c],[a,d,e]), +append([a],[b,c],[a,b,c]) ], Clauses) 3..Found clause: append(X,Y,Z):-true ...refuted: append([],[a,b],[c,d]):-true 3..Found clause: append(X,Y,Y):-true ...refuted: append([a,b],[c,d],[c,d]):-true 3..Found clause: append([],Y,Y):-true 3..4..Found clause: append([X|Xs],Ys,[X|Zs]):- append(Xs,Ys,Zs) Clauses = [ (append([X|Xs],Ys,[X|Zs]):-append(Xs,Ys,Zs)), (append([],Y,Y):-true) ] literal(append(X,Y,Z),[list(X),list(Y),list(Z)]). term(list([]),[]). term(list([X|Y]),[item(X),list(Y)]).