CS156
Chris Pollett
April 4, 2012
The basic idea is we want to reduce the first-order case to the propositional case. To do this:
One new wrinkle is that we now might need to come up with substitution lists between two atomic formula `G(vec(t))`, `G(vec(s))` for the terms `t_1, ..., t_n` and `s_1`, ..., `s_n`. Unification is an algorithm for doing this.
If x is a list let head(x) denote the first element of the list, x[0], and tail(x) denote x[1:]. The code below relies on Unify-var which is on the next slide.
Unify(x, y, S) x - a variable, constant, term or list y - a variable, constant, term, or list S - a substitution so far if(S == fail) return fail if (x(S) == y(S)) return S else if ( var? (x)) return Unify-var(x, y, S) else if ( var? (y)) return Unify-var(y, x, S) else if ( term? (x) and term? (y)) return (Unify(args (x), args(y), Unify( op(x), op(y), S)) else if (list? (x) and list? (y) ) return (Unify(tail(x), tail(y), Unify(head(x), head(y), S))) else return fail
As an example of what I mean by op, consider x:=((z*z) +35). Here op is the top operation, so +. args(x) := (z*z, 35), so contains two terms: the left and right symbol of +.
Here Unify-var is defined as:
Unify-var(var, y, S) var - a variable y - an expression S - a substitution if(var |-> val) exists in S return Unify(val, x, S) else if (x |-> val) exists in S return Unify(var, val, S) else if (occur-ck? (var, x)) return fail; else return ( append((var |-> x), S))
Suppose x is f(var), then var occurs in f(var) in the above and occur-ck of (var, x) is true! (note: prolog doesn't do occur-ck's)
Consider:
num(0). num(s(X)) :- num(X) |?- num(s (s (X))) (returns fail, because of the occurs check)
As an example of unify in action, consider:
x' = g(h(x, y), z) y' = g(w, t(v))
Initially, S is (). Since x' and y' are both terms, we return
Unify((h(x, y), z), (w, t(v)), Unify(g(a, b), g(a, b)))
Notice that a, b are new variable names. The second Unify will return S = (), since both g(a, b) are the same thing.
So now we try to unify two lists (h(x, y), z), (w, t(v)).
So we will do Unify( (z), (t(v)), Unify (Unify (h(x, y), w, S). S is still ().
Now we call Unify-var (w, h(x,y), S).
This statement will return (w |-> h(x, y)). We now need to unify (z) and (t(v)) with respect to the substitution (w |-> h(x,y')). When we get the final recursive answer, we will have ( (z |-> t(v)), (w |-> h(x,y)) )