First-Order Theorem Proving, Unification




CS156

Chris Pollett

April 4, 2012

Outline

Introduction

Using First-Order Logic

Example 1st Order Knowledge bases

KBs, First-Order Proofs

Soundness and Completeness

Theorem Proving in First-Order Logic

The basic idea is we want to reduce the first-order case to the propositional case. To do this:

  1. Convert `KB ^^ neg alpha` using some of the operations previously described into prenex normal form:
    `forall vec(x) exists vec(y) forall vec(z) ... G(vec(x), vec(y), vec(z), ...)`
    where `G` does not involve quantifiers.
  2. Introduce new function symbols for `forall exists` blocks. For example,
    `forall x_1 forall x_2, exists y_1, exists y_2, exists y_3 G(x_1, x_2, y_1, y_2, y_3) => forall x_1 forall x_2,G(x_1, x_2, f_1(x_1, x_2), f_2(x_1, x_2), f_3(x_1, x_2))`
  3. Once get open formulas without any quantifiers, convert to CNF and try to use resolution algorithm.

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.

Unification Algorithm

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 +.

Unify-var

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)

Example

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)) )