# Logic Programming – Part 2 Lists Backtracking Optimization (via the cut operator) Meta-Circular Interpreters.

## Presentation on theme: "Logic Programming – Part 2 Lists Backtracking Optimization (via the cut operator) Meta-Circular Interpreters."— Presentation transcript:

Logic Programming – Part 2 Lists Backtracking Optimization (via the cut operator) Meta-Circular Interpreters

Lists – Basic Examples [] – The empty list [X,2,f(Y)] – A 3 element list [X|Xs] – A list starting with X. Xs is a list as well. Example - [3,5] may be written as [3|5|[]]

Lists – CFG with Prolog Question: Which sentences can be constructed using this grammar? s -> np vp np -> det n vp -> v np | v det -> a | the n -> woman | man v -> shoots s -> np vp np -> det n vp -> v np | v det -> a | the n -> woman | man v -> shoots

Lists – CFG with Prolog Lets make relations out of it: s(Z) :- np(X), vp(Y), append(X,Y,Z). np(Z) :- det(X), n(Y), append(X,Y,Z). vp(Z) :- v(X), np(Y), append(X,Y,Z). vp(Z) :- v(Z). det([the]). det([a]). n([woman]). n([man]). v([shoots]). s -> np vp np -> det n vp -> v np | v det -> a | the n -> woman | man v -> shoots s -> np vp np -> det n vp -> v np | v det -> a | the n -> woman | man v -> shoots

Lists – CFG with Prolog We can ask simple queries like: Prolog generates entire sentences! s([a,woman,shoots,a,man]). yes ?-s(X). X = [the,woman,shoots,the,woman] ; X = [the,woman,shoots,the,man] ; X = [the,woman,shoots,a,woman] ; X = [the,woman,shoots,a,man] ; X = [the,woman,shoots] … ?-s(X). X = [the,woman,shoots,the,woman] ; X = [the,woman,shoots,the,man] ; X = [the,woman,shoots,a,woman] ; X = [the,woman,shoots,a,man] ; X = [the,woman,shoots] … ?-s([the,man|X]). X = [the,man,shoots,the,woman] ; X = [the,man,shoots,the,man] ; X = [the,man,shoots,a,woman] … ?-s([the,man|X]). X = [the,man,shoots,the,woman] ; X = [the,man,shoots,the,man] ; X = [the,man,shoots,a,woman] …

Lists – The date Relation In this example we’ll work with dates We assume, for simplicity that a date comprises of a week day and an hour We define the possible week days and hours with lists: week_day(['Sun', 'Mon', 'Tue','Wed','Thu','Fri','Sat']). hour([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]). week_day(['Sun', 'Mon', 'Tue','Wed','Thu','Fri','Sat']). hour([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]).

Lists – The date Relation Question: How can we tell if hour 2 is before hour 9? Answer: 1. We can only do so by checking precedence in the lists above 2. A < relation isn’t really possible to implement (There’s a more detailed answer in the PS document) week_day(['Sun', 'Mon', 'Tue','Wed','Thu','Fri','Sat']). hour([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]). week_day(['Sun', 'Mon', 'Tue','Wed','Thu','Fri','Sat']). hour([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]).

Lists – The date Relation Some queries: date([H,W]) :- hour(Hour_list), member(H, Hour_list), week_day(Weekday_list), member(W, Weekday_list). dateLT( date([_,W1]), date([_,W2]) ) :- week_day(Weekday_list), precedes(W1,W2,Weekday_list). dateLT( date([H1,W]), date([H2,W]) ) :- hour(Hour_list), precedes(H1,H2,Hour_list). date([H,W]) :- hour(Hour_list), member(H, Hour_list), week_day(Weekday_list), member(W, Weekday_list). dateLT( date([_,W1]), date([_,W2]) ) :- week_day(Weekday_list), precedes(W1,W2,Weekday_list). dateLT( date([H1,W]), date([H2,W]) ) :- hour(Hour_list), precedes(H1,H2,Hour_list). date([1,'Sun']). true dateLT(date([5,'Mon']), date([1,'Tue'])). true date([1,'Sun']). true dateLT(date([5,'Mon']), date([1,'Tue'])). true

Lists – The date Relation precedes is defined using append /2 Notice that the first argument is a list of lists This version of append is a strong pattern matcher precedes(X,Y,Z) :- append( [_,[X],_,[Y],_], Z).

Lists – Merging date Lists Merge 2 ordered date-lists % Signature: merge(Xs, Ys, Zs)/3 % purpose: Zs is an ordered list of dates obtained % by merging the ordered lists of dates Xs and Ys. merge([X|Xs], [Y|Ys], [X|Zs]) :- dateLT(X,Y), merge(Xs, [Y|Ys],Zs). merge([X|Xs], [X|Ys], [X,X|Zs]) :- merge(Xs, Ys, Zs). merge([X|Xs],[Y|Ys],[Y|Zs]) :- dateLT(Y,X), merge( [X|Xs],Ys, Zs). merge(Xs,[ ], Xs). merge([ ],Ys, Ys). % Signature: merge(Xs, Ys, Zs)/3 % purpose: Zs is an ordered list of dates obtained % by merging the ordered lists of dates Xs and Ys. merge([X|Xs], [Y|Ys], [X|Zs]) :- dateLT(X,Y), merge(Xs, [Y|Ys],Zs). merge([X|Xs], [X|Ys], [X,X|Zs]) :- merge(Xs, Ys, Zs). merge([X|Xs],[Y|Ys],[Y|Zs]) :- dateLT(Y,X), merge( [X|Xs],Ys, Zs). merge(Xs,[ ], Xs). merge([ ],Ys, Ys). ?- merge( [date([5,'Sun']), date([5,'Mon'])], X, [date([2, 'Sun']), date([5,'Sun']), date([5, 'Mon'])]). X = [date([2, 'Sun'])] ?- merge( [date([5,'Sun']), date([5,'Mon'])], X, [date([2, 'Sun']), date([5,'Sun']), date([5, 'Mon'])]). X = [date([2, 'Sun'])]

merge([d1,d3,d5],[d2,d3],Xs) { X_1=d1,Xs_1=[d3,d5], Y_1=d2,Ys_1=[d3], Xs=[d1|Zs_1] } Rule 1 dateLT(d1,d2), merge([d3,d5], [d2,d3],Zs_1) true merge([d3,d5], [d3],Zs_2) dateLT(d2,d3), merge([d3,d5], [d3],Zs_2) Rule 2 – failure branch… Rule 1 – failure branch… { X_3=d3,Xs_3=[d5],Ys_3=[], Zs_2=[d3,d3|Zs_3] } Rule 2 Rule 1 – failure branch… merge([d5], [],Zs_3) { Xs_4=[d5], Zs_3=[d5] } Fact 4 Rule 2 – failure branch… Rule 3 – failure branch… { X_2=d3,Xs_2=[d5], Y_2=d2,Ys_2=[d3], Zs_1=[d2|Zs_2] } Rule 3

Backtracking Optimization - Cut The cut operator (denoted ‘!’) allows to prune trees from unwanted branches. A cut prunes all the goals below it A cut prunes all alternative solutions of goals to the left of it A cut does not affect the goals to it’s right The cut operator is a goal that always succeeds

Example - Merge with Cut In the merge example, only 1 of the 3 first rules can be true. There is no reason to try to others. Modify rule 1: merge([X|Xs],[Y|Ys], [X|Zs]) :- dateLT(X,Y), !, merge (Xs, [Y |Ys],Zs). merge([d1,d3,d5],[d2,d3],Xs) dateLT(d1,d2), !, merge([d3,d5], [d2,d3],Zs_1) !, merge([d3,d5], [d2,d3],Zs_1) Rule 2 – failure branch… Rule 3 – failure branch…

Another Example How many results does this query return? Why does this happen? The query fits both rules 4 and 5 How can we avoid this? Add cut to rule 4 ?- merge([],[],X). merge(Xs, [ ],Xs) :- !. X = []; No X = []; No

Meta-Circular Interpreters We have seen 3 different interpreters in class Version 1 is trivial We can’t control the computation this way solve( A ) :- A.

Interpreter Version 2 clause finds the first rule unifying with A with body B % Signature: solve(Goal)/1 % Purpose: Goal is true if it is true when posed to the original program P. solve(true). solve( (A, B) ) :- solve(A), solve(B). solve(A) :- A\=true, clause(A, B), solve(B). % Signature: solve(Goal)/1 % Purpose: Goal is true if it is true when posed to the original program P. solve(true). solve( (A, B) ) :- solve(A), solve(B). solve(A) :- A\=true, clause(A, B), solve(B). ?- clause( parent(X,isaac),Body). X = abrahamBody = true ?- clause(ancestor(abraham, P),Body). P = Y, Body = parent(abraham, Y) ; P = Z, Body = parent(abraham, Y), ancestor(Y, Z) ?- clause( parent(X,isaac),Body). X = abrahamBody = true ?- clause(ancestor(abraham, P),Body). P = Y, Body = parent(abraham, Y) ; P = Z, Body = parent(abraham, Y), ancestor(Y, Z)

{ } Rule 3 solve solve(ancestor(abraham, P)) clause(ancestor(abraham, P), B_1), solve(B_1) {,, } Rule 1 ancestor solve(parent(abraham, P)) { } Rule 3 solve {, } Fact 1 parent solve(parent(abraham,Y_2), ancestor(Y_2, P)) { } Rule 2 ancestor { } Rule 2 solve clause(parent(abraham, P), B_3), solve(B_3). solve(true) true solve( parent(abraham,Y_2)), solve(ancestor(Y_2, P)) clause(parent(abraham, Y_2), B_4), solve(B_4) solve(ancestor(Y_2, P)) Fact 1 solve { } { } Rule 3 solve {, } Fact 1 parent solve(true), solve(ancestor(issac, P))

Interpreter Version 3 In this version we control the goal selection order by using a stack of goals Preprocessing – The given program is converted into a program with a single predicate rule Queries are checked against the new program

Interpreter Version 3 Sample converted program: % Signature: solve(Goal)/1 % Purpose: Goal is true if it is true when posed to the original program P. 1. solve(Goal) :- solve(Goal, []). % Signature: solve(Goal, Rest_of_goals)/2 1.solve([],[]). 2.solve([],[G | Goals]):- solve(G, Goals). 3.solve([A|B],Goals):- append(B, Goals, Goals1), solve(A, Goals1). 4.solve( A, Goals) :- rule(A, B), solve(B, Goals). % Signature: solve(Goal)/1 % Purpose: Goal is true if it is true when posed to the original program P. 1. solve(Goal) :- solve(Goal, []). % Signature: solve(Goal, Rest_of_goals)/2 1.solve([],[]). 2.solve([],[G | Goals]):- solve(G, Goals). 3.solve([A|B],Goals):- append(B, Goals, Goals1), solve(A, Goals1). 4.solve( A, Goals) :- rule(A, B), solve(B, Goals). %rule (Head, BodyList)/2 1. rule( member(X, [X|Xs] ), [] ). 2. rule( member(X, [Y|Ys] ), [member(X, Ys)] ).

{,,, } Rule 2 rule {,, } Rule 3 rule { } Rule of append {, } Rule 4 solve {,,, } Rule 1 rule { } Rule 1 solve solve(member(X, [a, b, c])) solve(member(X, [a, b, c]), []) {, } Rule 4 solve rule(member(X, [a, b, c], B_2), solve(B_2, [] ) solve([],[]) {,,, } Rule 1 rule true { } Rule 1 solve solve( [member(X, [b,c])], [] ) append([], [], Goals1_4), solve(member(X, [b,c]), Goals1_4). solve(member(X, [b,c]), []). rule(member(X,[b,c]), B_5), solve(B_5, []) solve([],[]) true { } Rule 1 solve

Download ppt "Logic Programming – Part 2 Lists Backtracking Optimization (via the cut operator) Meta-Circular Interpreters."

Similar presentations