Logic Programming Introduction o A procedure a set
























- Slides: 24
Logic Programming: Introduction o A procedure: a set of axioms (rules and facts) with identical signature (predicate symbol and arity). o A logic program: a set of procedures (predicates), defining relations in the program domain. procedure program predicate % Signature: parent (Parent, Child) /2 % Purpose: Parent is a parent of Child parent (erik, jonas). parent (lena, jonas). % Signature: male(Person) /1 % Purpose: Person is a male (erik). arity fact rule axioms % Signature: father (Dad, Child) /2 % Purpose: Dad is father of Child father (Dad, Child) : - parent(Dad, Child) , male (Dad). The relation father holds between Dad and Child 1 if parent holds and Dad is male
Logic Programming: Introduction The prolog interpreter operates in a read-eval-print loop. Given a query, it attempts to prove it based on the program: o If it fails, it answers false. o Else, if the query has no variables, it answers true. o Else, it outputs all possible variables assignments found during proof process. % Signature: parent (Parent, Child) /2 % Purpose: Parent is a parent of Child parent (erik, jonas). parent (lena, jonas). % Signature: male(Person) /1 % Purpose: Person is a male (erik). % Signature: father (Dad, Child) /2 % Purpose: Dad is father of Child father (Dad, Child) : - parent(Dad, Child), male (Dad). 2 ? - father (X, Y). X=erik, Y=jonas ? - parent (X, jonas). X=erik ; X=lena query Next possible assignment
Logic Programming: Example 1 – logic circuits An electronic logic circuit combines: o Electric component: resistor, transistor, connect between different connection points. o Connection points: power, ground, or a point connecting one logic gate to another. A program that models electric logic circuits: o Connection points: are individual constants. o Electric components: are relations on constants. Power Resistor (symmetric) Power Connection point N 1 Transistor (asymmetric) N 2 Ground N 3 N 4 Ground 3 N 5
Logic Programming: Example 1 – logic circuits An electronic logic circuit combines: o Electric component: resistor, transistor, connect between different connection points. o Connection points: power, ground, or a point connecting one logic gate to another. A program that models electric logic circuits: o Connection points: are individual constants. o Electric components: are relations on constants. % Signature: transistor (Gate, Source, Drain)/3 % Signature: resistor(End 1, End 2)/2 % Purpose: A resistor component connects two ends % Purpose: … 1 1 resistor(power, n 1). transistor(n 2, ground, n 1). 2 resistor(power, n 2). transistor(n 3, n 4, n 2). 3 resistor(n 1, power). transistor(n 5, ground, n 4). 4 resistor(n 2, power). Note: In contrast to resistor, the order of arguments in transistor is important. Each has a different role. 4
Logic Programming: Example 1 – logic circuits End 1, End 2 % Signature: resistor(End 1, End 2)/2 % Purpose: A resistor component connects two ends 1 resistor(power, n 1). 2 resistor(power, n 2). 3 resistor(n 1, power). 4 resistor(n 2, power). Reminders… o A procedure begins with a contract. o Constants start with lowercase characters. terms o A predicate name is also a constant, which defines a relation between its arguments. o variables start with uppercase characters (‘_’ for wildcard). o Atomic formulas are either true, false or of the form predicate(t 1 , . . . , tn), ti is a term. o A rule is a formula defining a relation that depends on certain conditions. o A fact is an atomic formula which is unconditionally true. 5
Logic Programming: Example 1 – logic circuits End 1, End 2 % Signature: resistor(End 1, End 2)/2 % Purpose: A resistor component connects two ends 1 resistor(power, n 1). 2 resistor(power, n 2). 3 resistor(n 1, power). 4 resistor(n 2, power). Reminders… o A query is a sequence of atomic formulas: ? - resistor(power, n 1), resistor(n 2, power). true; false No more answers “Does an X exist such that resistor holds for (power, X)? ” ? - resistor(power, X). X = n 1 ; Is there another answer? X = n 2; false 6
Logic Programming: Example 1 – logic circuits Combining logic gates to create a NOT logic circuit: o The resistor and transistor relations are based on facts. o They can be combined by a rule to determine whether the not_circuit relation stands for some Input and Output. power resistor Output transistor Input ground 7
Logic Programming: Example 1 – logic circuits Combining logic gates to create a NOT logic circuit: % Signature: not_circuit(Input, Output)/2 % Purpose: not logic circuit. 1. not_circuit(Input, Output) : - transistor(Input, ground, Output) , 2. resistor(power, Output). Rule head: an atomic formula with variables Rule body power resistor Output transistor Input ground Read: “For all Input and Output, not_circuit holds if: • transistor holds for (Input, ground, Output) and • resistor holds for (power, Output). ” 8 ? - not_circuit(X, Y). X=n 2, Y=n 1; false
Logic Programming: Example 1 – logic circuits Combining logic gates to create a NAND logic circuit: % Signature: nand_circuit(Input 1, Input 2, Output)/3 % Purpose: nand logic circuit nand_circuit(Input 1, Input 2, Output) : - transistor(Input 1, X, Output), transistor(Input 2, ground, X), resistor(power, Output). ? - not_circuit(X, Y), nand_circuit(In 1, In 2, X). X = n 2, Y = n 1, Power In 1 = n 3, In 2 = n 5; N 1 false Power Connection point N 2 Ground N 3 N 4 Ground 9 N 5
Semantics: Unification algorithm A program execution is triggered by a query in attempt to prove its goals: o To find a possible proof, the answer-query algorithm is used. o It makes multiple attempts to apply rules on a selected goal. o This is done by applying a unification algorithm, Unify, to the rule head and the goal. 10
Semantics: Unification algorithm Definitions: 1. binding: a non-circular expression, X=t, where X is a variable and t is a term not including X. 2. Substitution: a function from a finite set of variables to a finite set of terms (or bindings). 3. Application of a sub. S to an atomic formula A, replaces vars in A with corresponding terms in S: S = {I=X} A = not_circuit(I, I) , A º S = not_circuit(X, X) B = not_circuit(X, Y) , B º S = not_circuit(X, Y) the result is an instance of A 4. Unifier: a substitution S is called a unifier of formulas A and B if A º S = B º S. For example: S = {I=X} º {X=Y} = {I=Y, X=Y} A º S = not_circuit(Y, Y) B º S = not_circuit(Y, Y) Unify receives two atomic formulas and returns their most general unifier S = {I=5, X=5, Y=5} is a unifier for A and B, but not the most general one. 11
Semantics: Proof trees Executing answer-query: o The interpreter searches for a proof for a given query, a conjunction of goals. o The search is done by building and traversing a proof tree where all possibilities are examined. o The possible outcome is one of the following: § The algorithm finishes, and possible values of the query variables are given. § The algorithm finishes, but there is no proof for the query (false). § The proof attempt loops and never ends. 12
Semantics: Proof trees The tree structure depends on Prolog's goal selection and rule selection policies: ? - G 1, G 2, G 3 1. Query goals (G 1, …, Gn) are at the root of the proof tree. 2. Gsel: select current goal (leftmost order). 3. Rename: the variables in every rule and fact in the program. 4. Rsel: get all rules R such that head(R) can be unified with the goal (program order). 5. Whenever unification succeeds: 5. 1. A new child node is created. 2. The goal is replaced with body(R). R 2 : - A 2…, B 2…, : root G 1, G 2, G 3 A leaf may be created if the goal list is empty (success), or if the goal cannot be proven (failure). 6. Backtracking: When a leaf is reached, the search travels up to the first parent node where another rule can be matched. 13 R 1 : - A 1…, B 1…, : A 1, B 1, G 2, G 3 A 2, B 2, G 3 …
Semantics: Example 2 – A generated proof tree ? - nand_circuit(In 1, In 2, Out). mgu nand_circuit(Input 1, Input 2, Output) : - transistor(Input 1, X, Output), transistor(Input 2, ground, X), resistor(power, Output). nand_circuit(In 1, In 2, Out) { Input 1_1=In 1, Input 2_1= In 2, Output_1= Out} Rule 1 transistor(In 1, X_1, Out), transistor(In 2, ground, X_1), resistor(power, Out) transistor(n 2, ground, n 1). transistor(n 3, n 4, n 2). transistor(n 5, ground, n 4). resistor(power, n 1). { In 1=n 2, X_1=ground, Out=n 1} { In 1=n 5, X_1=ground, Out=n 4} resistor(power, n 2). { In 1=n 3, X_1=n 4, Out=n 2} Fact 1 – transistor Fact 3 – transistor resistor(n 1, power). Fact 2 – transistor resistor(n 2, power). transistor(In 2, ground), resistor(power, n 1) transistor(In 2, ground, n 4), resistor(power, n 2) { In 2=n 5} {In 2=n 2} { In 2=n 3} Fact 3 – Fact 1 – Fact 2 – transistor fail transistor(In 2, ground), resistor(power, n 4) { In 2=n 2} { In 2=n 5} { In 2=n 3} Fact 1 – Fact 3 – Fact 2 – transistor fail resistor(power, n 2) a finite success tree with one success path. 14 true
Semantics: proof trees Possible types of proof trees: o A success tree has at least one success path in it. o A failure tree is one in which every path is a failure path. o A proof tree is an infinite tree if it contains an infinite path. o Otherwise, it is a finite tree. Example: An infinite tree is generated by repeatedly applying the following rule (left recursion): p(X): -p(Y), q(X, Y) ? -p(A) To avoid the infinite path, we could rewrite the rule as follows (tail recursion): p(X): - q(X, Y), p(Y) ? -p(A) 15
Logic Programming: An example: Relational logic programming & SQL operations. o Relational logic programming has no ability to describe composite data, only atoms. o Logic programming is equipped with functors to describe composite data. Q: In the following procedure, which symbols are predicates? Which are functors? % Signature: tree_member(Element, Tree)/ 2 % Purpose: Checks if Element is an element of the binary tree Tree. tree_member (X, tree(X, Left, Right)). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Left). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Right). Predicate A Functor applied to three data items. Q: how to tell a predicate from a functor? • A predicate appears as an identifier of an atomic formula. • A functor is way to construct a term, which is part of an atomic formula. • A functor can be nested, a predicate cannot. NOTE: The same name may be used for both a predicate and a functor! 16
Logic Programming: Unification with functors& SQL operations. An example: Relational logic programming Unification is more complex with functors. Here is an execution of the Unify algorithm, step by step: Unify(A, B) where A = tree_member (tree (X, 10, f(X)), W) ; B = tree_member (tree (Y, Y, Z), f(Z)). Initially, s={} A s= tree_member (tree (X, 10, f(Y)), W ) B s= tree_member (tree (Y, Y , Z ), f(Z)) A s ≠ B s [ Disagreement-set = {X=Y} [ X does not occur in Y � s=s {X=Y} = {X=Y} A s= tree_member (tree (Y, 10, f(Y)), W ) B s= tree_member (tree (Y, Y , Z ), f(Z)) A s ≠ B s [ Disagreement-set = {Y=10} � s=s {Y=10} = {X=10, Y=10} A s= tree_member (tree (10, f(10)), W ) B s= tree_member (tree (10, Z ), f(Z)) A s ≠ B s � Disagreement-set = {Z=f(10)} � s=s {Z=f(10)} = {X=10, Y=10, Z=f(10)} A s= tree_member (tree (10, f(10)), W ) A s ≠ B s= tree_member (tree (10, f(10)), f(f(10))) [ Disagreement-set = {W=f(f(10))} [ s={X=10, Y=10, Z=f(10), W=f(f(10))} A s= tree_member (tree (10, f(10)), f(f(10)) ) B s= tree_member (tree (10, f(10)), f(f(10))) Q: Why check for occurence? 17
Logic Programming: Unification with functors& SQL operations. An example: Relational logic programming A: Consider the following two atomic formulas: A = tree_member (tree (X, Y, f(X)), X ) B = tree_member (tree (Y, Z ), f(Z)) Applying Unify(A, B) will result in a loop: X=Y, Z=f(Y)… A = tree_member (tree (Y, Y, f(Y)), Y ) B = tree_member (tree (Y, Y, f(Y) ), f(f(Y)) ) A = tree_member (tree (f(f(Y)), f(f(f(Y)))), f(f(Y)) ) B = tree_member (tree (f(f(Y)), f(f(f(Y)))), f(f(Y)))) ) … the substitution cannot be successfully solved. 18
Logic Programming: Using fanctors An example: Relational logic programming & SQL operations. % Signature: tree_member(Element, Tree)/ 2 % Purpose: Testing tree membership, checks if Element is % an element of the binary tree Tree. tree_member (X, tree(X, Left, Right)). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Left). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Right). ? - tree_member(1, tree(1, nil)). true ? - tree_member(2, tree(1, tree(2, nil), tree(3, nil))). true. ? - tree_member(1, tree(3, 1, 3)). false. ? - tree_member(X, tree(1, tree(2, nil), tree(3, nil))). X=1; X=2; X=3; false. 19
Full Logic Programming: An example proof tree ? - tree_member(X, tree(1, tree(2, nil), tree(3, nil))) {X_1 = 1, X = 1 Left_1 = tree(2, nil), Right_1 = tree(3, nil, nil)} {X_1 = X, Y_1 = 1, Left_1 = tree(2, nil, nil), Right_1 = tree(3, nil)} tree_member (X, tree(3, nil)) tree_member (X, tree(2, nil)) {X_2 = 2, X = 2 {X_2 = X, Y_2 = 2, Left_2 = nil, Right_2 = nil} tree_member (X, nil) true {X=1} true {X=2} fail % Signature: tree_member(Element, Tree)/ 2 % … tree_member (X, tree(X, Left, Right)). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Left). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Right). 20 fail {X_2 = 3, X = 3 Left_2 = nil, Right_2 = nil} true {X_2 = X, Y_2 = 3, Left_2 = nil, Right_2 = nil} tree_member (X, nil) {X=3} fail
Full Logic Programming: An example proof tree % Signature: tree_member(Element, Tree)/ 2 % Purpose: Testing tree membership, checks if Element is % an element of the binary tree Tree. tree_member (X, tree(X, Left, Right)). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Left). tree_member (X, tree(Y, Left, Right)): - tree_member(X, Right). ? - tree_member(1, T). T = tree(1, _G 445, _G 446) ; T = tree(_G 444, tree(1, _G 449, _G 450), _G 446) ; T = tree(_G 444, tree(_G 448, tree(1, _G 453, _G 454), _G 450), _G 446) ; . . . o Looking for all trees in which 1 is a member, we get an infinite success tree with partially instantiated answers (containing variables). o We use a rule that requires a defined input, but our input is a variable. Possible answers are generated by the proof algorithm. o In this case we call the rule a generator rule. 21
Logic Programming (cont’d): Lists in Prolog are represented by a functor (similar to cons in Scheme): 1. The empty list is represented by the constant - [ ]. 2. The term. (X , Xs) represents a list of which X is the 1 st element and Xs is the rest of its elements. 3. The functor ‘. ’ has an infix representation by the pipe symbol ‘|’ : [X | Xs] For example: [3 | [5 | [] ] ] 4. Lists of known length can be represented as a list of comma-separated expressions: For example: [ X, 2, f(Y) ] or [3 , 5]
Logic Programming (cont’d): Lists Example 1: Implementing a Context Free Grammar in PROLOG: S NP VP Det N V NP | V a | the woman | man saw Q: What language does this CFG represent? ? - s([a, woman, saw, a, man]). true ? -s(X). X = [the, woman, saw, the, woman]; X = [the, woman, saw, the, man]; X = [the, woman, saw, a, woman]; X = [the, woman, saw, a, man]; X = [the, woman, saw] … ? -s([the, man|X]). X = [saw, the, woman]; X = [saw, the, man]; X = [saw, a, woman] … Representation in PROLOG: 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([saw]). % Signature: append(L 1, L 2, L 3)/3 % Purpose: L 3 is the concatenation of L 1, L 2 append([], Xs). append([X|Xs], Ys, [X|Zs]): -append(Xs, Ys, Zs).
Logic Programming (cont’d): Lists Example 1: Implementing a Context Free Grammar in PROLOG: S NP Adj VP Det N V NP VP Det N | Det Adj N vicious | marvelous V NP | V a | the woman | man saw Q: How would we implement the modifications above? Representation in PROLOG: s(Z) : - np(X), vp(Y), append(X, Y, Z). np(Z): - det(X), n(Y), append(X, Y, Z). np(Z): - det(X), adj(W), n(Y), append([X, W, Y], Z). vp(Z): - v(X), np(Y), append(X, Y, Z). vp(Z): - v(Z). adj([vicious]). adj([marvelous]). det([the]). det([a]). vp(Z): - v(X), np(Y), append(X, Y, Z). vp(Z): - v(Z). n([woman]). n([man]). det([the]). det([a]). v([shoots]). n([woman]). n([man]). v([shoots]).