CMSC671 Artificial Intelligence Project3 Report Zhongli Ding x6082 In this project, I implement both parts of the project using Common Lisp. Identification, Unification and Resolution Methods Summary In this part, we do resolution on a given pair of clauses, this includes three steps: first our program should identify a pair of opposite literals P(arg-list-1) and ~P(arg-list-2), then it should unify the argument lists of these two opposite literals, finally, it generate the resolvent of the two clauses over these pair of opposite literals. 1. Literal Identification In “Definition.lisp”, I give definitions of some basic concepts. At first, I define three sets: “CONST”(constants), “VAR”(variables), and “FUNCSYM”(function symbols). And then I define following functions: isConst(x): If an element x is a member of “CONST”, then it is a constant isVar(x): If an element x is a member of “VAR”, then it is a variable isFuncSym(x): If an element x is a member of “FUNCSYM”, then it is a function symbol isLiteral(x): An element x is a literal if it is a list and its first element is not a list, not a constant, not a variable, and not a function symbol o isFunction(x): An element x is a function if it is a list and its first element is not a list and a function symbol o o o o In “Identification.lisp”, given two clauses, I define some functions to identify all pairs of opposite literals from the two clauses: o isPair(l1,l2): Two literals l1 and l2 are a pair of opposite literals if: either the (car l1) is “not” and the (caadr l1) is equal to (car l2), or vice versa. o inPairset(x,L): If L stands for the list of opposite pairs found, judge whether literal x is in L o identifyPairs(clause1,clause2): For a given pair of clauses, identify each pair of opposite literals using “dolist” loop and the above two functions 2. Unification In “Unification.lisp”, I define all the functions used to implement the Unification Algorithm: o o o o getArgList(x): Get the argument list of a literal or a function x occurs(x,y): Test whether a variable x appears anywhere in function y replaceItem(item1, item2, L): Replace all occurrences of "item1" with "item2" in the list "L" subst-theta(theta, L): Apply a 'mgu' theta to a list 'L' o unify(argList1,argList2) & unify-mgu(argList1,argList2, theta): Unify two argument lists "argList1" and "argList2", return the 'mgu' theta if the two lists are unifiable, return 'NIL' if unifiable but without any bindings, otherwise return 'Faliure' with specific reason o unify-var(x, y): x is a variable, if y is a function and x appears anywhere in y then return 'failure', otherwise return 'x/y' in lisp notation '((x y))’ Unification Algorithm procedure unify(p, q) return unify-mgu(p, q, empty) end{unify} procedure unify-mgu(p, q, theta) /* p and q are two lists of terms and |p| = |q| */ if p = empty then return theta; /* success */ let r = first(p) and s = first(q); if r = s then return unify-mgu(rest(p), rest(q), theta); if r is a variable then temp = unify-var(r, s); else if s is a variable then temp = unify-var(s, r); else if both r and s are functions of the same function name then temp = unify-mgu(arglist(r), arglist(s), empty); else return “failure”; if temp = “failure” then return “failure”; /* p and q are not unifiable */ else { theta = subst-theta(temp, theta) temp; /* apply temp to old theta and then insert it into theta */ return unify(subst-theta(temp,rest(p)), subst-theta(temp,rest(q)), theta); } end{unify-mgu} procedure unify-var(x, y) if y is a function and x appears anywhere in y then return “failure”; else return (x/y) in “((x y))” end{unify-var} 3. Resolution In “Resolution.lisp”, I define the functions to resolve two clauses 'clause1' and 'clause2' if they are resolvable: o removeElement(x, L): Remove every occurrence of an element x from a list L o resolve (clause1,clause2): Resolve two clauses 'clause1' and 'clause2' if they are resolvable and return the resolvent, return "NIL" if completely resolved to a null clause, otherwise return 'Failure' with specific reason. The basic idea is to identify all opposite pairs of the two clauses, then unify every such pair, finally get a resolvent. Results Summary “Input1.lisp”: The input file for this part of the project Following is a very simple summary of the output: Parent Clauses 1. ((p x) (q (f x))),((not (p a)) (r y)) 2. ((p a) (not (q x))),((not (p b)) (q (f b))) 3. ((not (p a)) (q (f x))),((p (f y)) (not (q (g y)))) 4. ((q x a b) (p (f x a) (g x b))),((not (p y (g y b))) (r y)) 5. ((p x (g x) (h b))),((not (p (f u a) v u))) 6. ((poor x) (not (smart x)) (happy x)),((not (happy z)) (exicting z)) 7. ((poor x) (not (smart x)) (happy x)),((not (read y)) (smart y)) 8. ((not (read y)) (smart y)),((not (happy z)) (exicting z)) Resolution Results ((Q (F A)) (R Y)) ((P A) (NOT (P B))) Failure: No unifiable opposite literal pairs! Failure: No unifiable opposite literal pairs! The resolvent is a null clause! ((POOR Z) (NOT (SMART Z)) (EXICTING Z)) ((POOR Y) (HAPPY Y) (NOT (READ Y))) Failure: No opposite literal pairs! Please see the attached result file for details about opposite pairs, “mgu” etc. information Resolution Refutation Proof Procedure Methods Summary A general ”resolution refutation proof procedure”: procedure proof(KB, Q) /* KB is a set of consistent, true FOL sentences, Q is a goal sentence. It returns success(‘yes’) if KB |-- Q, and failure(‘no’) otherwise */ KB = clause(union(KB, {~Q})) /* convert KB and ~Q to clause form */ while null clause is not in KB do pick 2 sentences, S1 and S2, in KB that contain a pair of opposite literals whose argument lists are unifiable /* may using different strategy */ if none can be found then return "failure" resolvent = resolve(S1, S2) KB = union(KB, {resolvent}) return "success " end{resolution} In this part, we extend the above program to a resolution refutation proof procedure using the following “pick up” (depth-first) strategy: 0) Set the axiom set, get the negation of the theorem we want to prove 1) At step 1: The first of the parent clauses is the negation of the theorem, the other parent clause is the first axiom in the axiom set that can be resolved with the first parent clause 2) At step I: The first of the parent clauses is the resolvent got from step I-1, the second is the first axiom in the axiom set that can be resolved with the first parent clause 3) Return "yes" if a null clause is derived, "no" if no more resolution can be performed but a null clause has not been derived In “Proof.lisp”, I define two functions: proof(axioms,theorem) and proof-depth-first(axioms, resolvent) to implement above procedure. Results Summary “Input2.lisp”: The input file for this part of the project Convert axiom into clause form manually using LISP notation: Axioms A1: Ancestor(x1,y1)<=Parent(x1,y1) A2: Ancestor(x2,y2)<=Ancestor(x2,z2),Parent(z2,y2) A3: Relative(x3,y3)<=Ancestor(z3,x3),Ancestor(z3,y3) A4: Parent(Ed,Fred) A5: Parent(Eve,Ed) A6: Parent(Eve Linda) A7: Parent(Adam,Ed) Clauses in LISP notation ((not (Parent x1 y1)) (Ancestor x1 y1)) ((not (Ancestor x2 z2)) (not (Parent z2 y2)) (Ancestor x2 y2)) ((not (Ancestor z3 x3)) (not (Ancestor z3 y3)) (Relative x3 y3)) (Parent Ed Fred) (Parent Eve Ed) (Parent Eve Linda) (Parent Adam Ed) Using the program, I try to prove the following three theorems: Theorems 1. Relative(Ed, Linda) : (Relative Ed Linda) 2. Ancestor(Adam, Fred): (Ancestor Adam Fred) 3. Ancestor(Eve, Fred) : (Ancestor Eve Fred) Results "Proof result:" "YES!" "Proof result:" "NO!" "Proof result:" "NO!" We can see that though theorem2 and theorem3 are theorems of the above axioms, but we can’t derive them by the above proof strategy. For details of the output (resolvents, parent clauses, ‘mgu’s etc), please see the attached result file. Any questions, please contact zding1@cs.umbc.edu