760 likes | 780 Views
Logic Programming. Nai-Wei Lin Department of Computer Science and Information Engineering National Chung Cheng University. Outline. An introduction to logic Predicate calculus Horn clauses Unification and resolution Basic Prolog programming Syntax of Prolog Control in Prolog
E N D
Logic Programming Nai-Wei Lin Department of Computer Science and Information Engineering National Chung Cheng University
Outline • An introduction to logic • Predicate calculus • Horn clauses • Unification and resolution • Basic Prolog programming • Syntax of Prolog • Control in Prolog • Data structures in Prolog • Advanced Prolog programming • Cut • Negation • Higher-order predicates • Incomplete data structures
Logic Programming • Logic programming uses logic as a programming language • Logic programming computes relations instead of functions • Logic programming is declarative programming
Relations and Functions Let A and B be sets • A relation from A to B is a subset of A × B. • A function from A to B is a relation R from A to B such that for each a A, there exists one and only one b B such that (a,b) R. • Functions are special cases of relations. • Example: A = {a1, a2, a3, a4} B = {b1, b2, b3} R = {(a1,b1), (a2,b2), (a2,b3), (a4,b3)} F = {(a1,b1), (a2,b2), (a3,b3), (a4,b3)}
Propositions 1. Boolean values true and false are propositions. 2. A symbol is a proposition which has value true or false. 3. If p and q are propositions, then so are (a) p: negation of p,(b) pq: conjunction of p and q,(c) pq: disjunction of p and q, and (d) pq: implication from p to q.
Predicates Each predicate denotes a relation among constants. Each predicate is defined as a set of terms. Terms are relation instances whose arguments can be constants or existential quantified () or universal quantified () variables Examples: parent(ted, derek). parent(ted, dena). parent(ted, dustin). parent(derek, adams). X,Y.(parent(X,Y) ancestor(X, Y)). X,Y.(Z.parent (X,Z) ancestor(Z,Y) ancestor(X,Y)).
Theorem Proving • Predicates as axioms • Queries as theorems • Answering queries as proving theorems
An Example parent(ted, derek). parent(ted, dena). parent(ted, dustin). parent(derek, adams). X,Y.(parent(X,Y) ancestor(X, Y)). X,Y.( Z.parent(X, Z) ancestor(Z, Y) ancestor(X, Y)). parent(ted, derek)? X.parent(ted, X)? X,Y.parent(X, Y)? X.ancestor(ted, X)?
Resolution Inference Rule • Predicates as axioms • Queries as theorems • Resolution as the inference rule p, pq┝ q • Proving theorems by backward deduction
Horn Clauses • The set of Horn clauses is a subset of predicate calculus • Each of the implication in the Horn clauses is in the form ofp1 ,…, pnqwhere n 0 • Resolution inference rule can be efficiently used only for Horn clauses
A Notation for Horn Clauses Facts (universal): <fact> ::= <term>. parent(ted, derek). Rules (universal or existential): <rule>::= <term> :- <terms>. ancestor(X, Y) :- parent(X, Y). ancestor(X, Y):- parent(X, Z), ancestor(Z, Y). Queries (existential): <query> ::= ?- <terms>. ?- parent(ted, X). ?- ancestor(ted, X).
Clauses and Predicates A clause is a fact or a rule A literal is a relation occurrence in a clause Clause head is the literal before ‘ :- ’ in a clause Clause body consists of the literals after ‘ :- ’ in a clause A predicate is the set of clauses whose head has the same predicate symbol and arity (number of arguments)
An Example parent(ted, derek). parent(ted, dena). parent(ted, dustin). parent(derek, adams). ancestor(X, Y) :- parent(X,Y). ancestor(X, Y) :- parent(X, Z), ancestor(Z, Y).
Substitution • A substitution is a function from variables to terms {X → ted, Y → derek} • Rules for applying a substitution σ to a term: 1. σ(X) = U, if X →U is in σ 2. σ(X) = X, otherwise 3. σ(f(T1,T2)) = f(U1,U2), if σ(T1) = U1, σ(T2) = U2 {X → ted, Y → derek}(X) = ted {X → ted, Y → derek}(Z) = Z {X → ted, Y → derek}(parent(X,Y)) = parent(ted,derek)
Instances • A term U is an instance of a term T if U = σ(T) for some substitution σ parent(ted,derek) is an instance of parent (X, derek) parent(X,derek) is an instance of parent (X, Y)
Unification • Terms T1 and T2 unify if σ(T1) = σ(T2) for some substitution σ • Substitution σ is called a unifier of T1 and T2. {H → a, T → b} (f(a , T)) = {H → a, T → b} (f(H, b)) = f(a, b)
Most General Unifier • Substitution σ is the most general unifier of T1 and T2 if for all other unifiers σ’ , σ’(T1) is an instance of σ(T1). {X1 → a, X2 → Z, Y1 → a, Y2 → Z }(f(X1,X2,c)) = {X1 → a, X2 → Z, Y1 → a, Y2 → Z }(f(Y1,Y2,c)) = f(a, Z, c) {X1 → a, X2 → b, Y1 → a, Y2 → b }(f(X1,X2,c)) = {X1 → a, X2 → b, Y1 → a, Y2 → b }(f(Y1,Y2,c)) = f(a, b, c) {Z → b}(f(a, Z, c)) = f(a, b, c)
Resolution Let Qi = a1, a2, …, an be a query and b :- b1, b2, …, bm be a rule. If σis the most general unifier of a1 and b, and Qi+1 = σ(b1, b2, …, bm, a2, …, an), then we say Qi is reduced to Qi+1 via a resolution step.
An Example The most general unifier for the query ancestor (X, adams) and the rule ancestor (X, Y) :- parent (X, Y) is σ = {Y → adams } Hence, the query after the resolution of these two is σ(parent(X, Y)) = parent(X, adams)
Computation • A computation for a query Q with respect to a set of predicates is a (possibly infinite) sequence of queriesQ = Q0, …, Qi, Qi+1, … such that each Qi is reduced to the query Qi+1 via a resolution step. ?- ancestor(X, adams). ?- parent(X, adams). true σ = {Y → adams} σ = {X → derek}
Computation • If a computation C has an infinite sequence of queries, then C does not terminate. • If a computation C with queriesQ0, …, Qn is maximal, and Qn = true, then C is said to succeed with answer substitution n … 1 restricted to the variables occurring in Q0. • Otherwise, C is said to fail.
An Example • ?- ancestor (X, adams). ancestor (X, Y) :- parent (X, Y). σ1 = {Y → adams} σ1(parent(X, Y)) = parent(X, adams) ?- parent(X, adams). • ?- parent (X, adams). parent (derek,adams). σ2 = {X → derek} trueσ = σ2σ1 = {X → derek, Y → adams} ={X → derek}
Prolog • Prolog is a general programming language for logic programming • Prolog also includes some imperative features for efficiency • Prolog uses the same syntactic form for both programs and data
Prolog • The first Prolog system was developed in early 1970’s by Alain Colmerauer and his group at the University of Marseille-Aix as a specialized theorem prover for natural language processing. • The first efficient Prolog was developed in late 1970’s by David Warren and his group in University of Edinburgh.
Prolog Syntax Terms: < term > ::= < number > | < variable > | < symbol > | < symbol > (<terms>) < terms > ::= < term > | < term > , < terms > Examples: 1, 1994 N, N1, _, _1 ted, derek parent(X, Y) +(2, *(3, 4)), 2 + 3 * 4
A Typical Session ?- consult( ‘family.pl’). yes ?- parent(ted,derek). yes ?- parent(ted,X). X = derek; X = dena; X= dustin; no ?- parent(ted, X). X = derek yes return next solution stop returning solutions
A Typical Session ?- parent(X, Y). X = ted, Y = derek; X = ted, Y = dena; X = ted, Y = dustin; X = derek, Y = adams; no ?- ancestor(X, Y). X = ted, Y = derek; X = ted, Y = dena; X = ted, Y = dustin; X = derek, Y = adams; X = ted, Y = adams; no ?- halt.
Control in Prolog • Try clauses from top to bottom • Resolve literals from left to right
σ1 = {X→derek} true σ2 = {X→dena} true σ3 = {X→dustin} true false An Example parent(ted, derek). parent(ted, dena). parent(ted, dustin). parent(derek, adams). ?- parent(ted,X). X = derek; X = dena; X = dustin; no parent(ted,X).
An Example parent (ted, derek). parent (derek, adams). ancestor(X, Y) :- parent(X, Y). ancestor(X, Y) :- parent (X, Z), ancestor (Z, Y). ?- ancestor (X, adams). σ1= {X → X_1, Y_1 → adams} σ1(parent(X_1, Y_1)) = parent (X_1, adams) ?- parent (X_1, adams). σ2= {X_1 → derek} σ = σ2σ1 = {X → derek} X = derek; (succeed)
An Example ancestor(X,adams). σ1= {X→X_1,Y_1→adams} σ1= {X→X_1,Y_1→adams} parent (X_1, adams). parent(X_1, Z_1), ancestor(Z_1, adams)). σ2= {X_1 → derek} true false
An Example ?- ancestor(X, adams). σ1 = {X X_1, Y_1 adams} σ1(parent(X_1, Z_1), ancestor(Z_1, Y_1)) = parent(X_1, Z_1), ancestor(Z_1, adams)) ?- parent(X_1, Z_1), ancestor(Z_1, adams). σ2 = {X_1 ted, Z_1 derek} σ2(ancestor(Z_1, adams)) = ancestor(derek, adams) ?- ancestor(derek, adams). σ3 = {X_2 derek, Y_2 adams} σ3(parent(X_2, Y_2)) = parent(derek, adams) ?- parent(derek, adams).σ4 = { } σ = σ4σ3 σ2σ1 = {X,X_1ted, Y_1,Y_2adams, Z_1,X_2derek} X = ted; (succeed)
An Example parent(X_1, Z_1), ancestor(Z_1, adams). σ2= {X_1 derek, Z_1 adams} σ2= {X_1 ted, Z_1 derek} ancestor(derek, adams). ancestor(adams, adams). σ3 = {X_2 derek, Y_2 adams} σ3 = {X_2 derek, Y_2 adams} parent(derek, adams). parent(derek, Z_2), ancestor(Z_2, adams). σ4= { } false true
An Example ?- ancester(derek, adams). σ3 = {X_2 derek,Y_2 adams} σ3(parent(X_2, Z_2), ancestor(Z_2, Y_2)) = parent(derek, Z_2), ancestor(Z_2, adams) ?- parent(derek, Z_2), ancestor(Z_2, adams). σ4 = {Z_2 adams} σ4(ancestor(Z_2, adams)) = ancestor(adams, adams) ?- ancestor(adams, adams). σ5 = {X_3adams,Y_3adams} σ5(parent(X_3, Y_3)) = parent(adams, adams) ?- parent(adams, adams). (fail)
An Example parent(derek, Z_2), ancestor(Z_2, adams). σ4 = {Z_2 adams} ancestor(adams, adams). false σ5 = {X_3adams,Y_3adams} σ5 = {X_3adams,Y_3adams} parent(adams, adams). parent(adams, Z_3), ancestor(Z_3, adams). false false
An Example ?- ancestor(adams, adams). σ5 = {X_3 adams,Y_3 adams} σ5(parent(X_3, Z_3), ancestor(Z_3, Y_3)) = parent(adams, Z_3), ancestor(Z_3, adams) ?- parent(adams, Z_3), ancestor(Z_3, adams). (fail) parent(adams, Z_3), ancestor(Z_3, adams). false false
An Example ?- parent(X_1, Z_1), ancestor(Z_1, adams). σ2 = {X_1 derek, Z_1 adams} σ2(ancestor(Z_1, adams)) = ancestor(adams, adams) ?- ancestor(adams, adams). σ3 = {X_2 adams, Y_2 adams} σ3(parent(X_2, Y_2)) = parent(adams, adams) ?- parent(adams, adams).(fail)
An Example ancestor(adams, adams). σ3 = {X_2 adams,Y_2 adams} σ3 = {X_2 adams,Y_2 adams} parent (adams, adams). parent(adams, Z_1), ancestor(Z_1, adams)). false false false false
An Example ?- ancestor(adams, adams). σ3 = {X_2 adams, Y_2 adams} σ3(parent(X_2, Z_2), ancestor(Z_2, Y_2)) = parent(adams, Z_2), ancestor(Z_2, adams) ?- parent(adams, Z_1), ancestor(Z_1, adams). (fail)
Prolog Search Tree ancestor(X,adams) σ1= {X→X_1,Y_1→adams} parent(X_1,adams) parent(X_1,Z_1),ancestor(Z_1,adams) σ2= {X_1→derek} σ2 = {X_1ted,Z_1derek} σ2 = {X_1derek,Z_1adams} fail succeed ancestor(derek,adams) ancestor(adams,adams) X = derekσ3 = {X_2derek,Y_2adams} parent(derek,adams) parent(derek,Z_2),ancestor(Z_2,adams) fail fail σ4 = { } σ4 = {Z_2 adams} fail succeed fail ancestor(adams, adams) X = ted σ5 = {X_3adams,Y_3adams} parent(adams,adams) parent(adams,Z_3),ancestor(Z_3,adams) fail fail fail fail
Literal Order Affects Trees append([ ], L, L). append([H|X ], Y, [ H|Z ]) :- append (X, Y, Z). prefix(X, Z) :- append (X, Y, Z). suffix (Y, Z) :- append (X, Y, Z). ?-suffix( [a], L), prefix (L, [a, b, c]). L = [a]; -- non-terminating – ?-suffix ([a], L). L = [a]; L = [_1, a]; L = [_1, _2, a]; …
Literal Order Affects Trees suffix ([a], L), prefix (L, [a, b, c]) append(X_1, [a], L), prefix (L, [a, b, c]) prefix([a], [a,b,c]) append(X_2, [a], Z_2), prefix([H_2|Z_2], [a, b, c]) append([a], Y_2, [a, b, c]) prefix([H_2|[a]], [a, b, c]) fail … fail append([ ], Y_3, [b, c]) append([H_2|[a]], Y_3, [a, b, c]) succeed fail fail fail
Literal Order Affects Trees suffix ([a], L), prefix (L, [a, b, c]) L = [a] prefix([a], [a, b, c]) succeed L = [_1,a] prefix([_1,a], [a, b, c]) fail L = [_1,_2,a] prefix([_1,_2,a], [a, b, c]) fail ...
Literal Order Affects Trees append([ ], L, L). append([H|X ], Y, [ H|Z ]) :- append (X, Y, Z). prefix(X, Z) :- append (X, Y, Z). suffix (Y, Z) :- append (X, Y, Z). ?- prefix(L, [a, b, c]), suffix ([a], L). L = [a]; no
Literal Order Affects Trees prefix (L, [a, b, c]), suffix ([a], L) append (L, Y_1, [a, b, c]), suffix ([a], L) suffix([a], [ ]) append(X_2, Y_2, [b, c]), suffix ([a], [a|X_2]) append(X_3, [a], []) suffix([a], [a]) append(X_3, Y_3, [c]), suffix ([a], [a,b|X_3]) fail fail append(X_4, [a], [a]) succeed fail fail …
Literal Order Affects Trees prefix (L, [a, b, c]), suffix ([a], L) L = [ ] suffix([a], [ ]) L = [a] fail suffix([a], [a]) succeed L = [a,b] suffix ([a], [a,b]) L = [a,b,c] fail suffix ([a], [a,b,c]) fail
Clause Order Affects Search append([ ], L, L). append([H|X], Y, [H|Z]) :- append(X, Y, Z). append2([H|X], Y, [H|Z]) :- append2(X, Y, Z). append2([ ], L, L). ?- append(X, [a], Z). X = [ ], Z = [a]; X = [_1 ], Z = [_1, a]; X = [_1, _2 ], Z = [_1, _2, a]; … ?- append2(X, [a], Z). -- non-terminating --
Clause Order Affects Search append(X, [c], Z) append2(X, [c], Z) succeed succeed append(X_1, [c], Z_1) append2(X_1, [c], Z_1) succeedsucceed append (X_2, [c], Z_2) append2(X_2, [c], Z_2)
Terms as Data Function symbols (functors) represent data Lists: [] [a, b, c] .(a, .(b, .(c, [] ))) .(H , T) [H | T] [a | [b, c ]] [a, b | [c]] [a, b, c | [] ] Trees: leaf nonleaf(leaf, leaf) nonleaf(leaf, nonleaf(leaf, leaf ))
An Example append([ ], L, L). append([H|X], Y, [H|Z]) :- append (X, Y, Z). ?- append([ ], [ ], R). R = [ ]; no ?- append([ ], [a, b], R) . R = [a, b]; no ?- append ([a, b], [c, d], R). R = [a, b, c, d]; no ?- append (X, Y, [a, b] ). X = [ ], Y = [a, b]; X = [a], Y = [b]; X = [a, b], Y = [ ]; no