Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!linus!philabs!seismo!hao!hplabs!sri-unix!SHardy@SRI-KL
From: SHardy%SRI-KL@sri-unix.UUCP
Newsgroups: net.lang.prolog
Subject: Equal On Terms
Message-ID: <3283@sri-arpa.UUCP>
Date: Mon, 18-Jul-83 11:47:20 EDT
Article-I.D.: sri-arpa.3283
Posted: Mon Jul 18 11:47:20 1983
Date-Received: Fri, 22-Jul-83 20:35:42 EDT
Lines: 39

An earlier message asked how to define a predicate EQUAL on two terms 
that didn't mind if variables were renamed but otherwise wanted the 
terms to be identical, thus:

        equal(A + B, C + D), equal(A + A, C + C)

are true, but not:

        equal(A + A, B + C)

The proposed ``quick and dirty'' solution was something like:

        equal(X, Y) :- assert(temp(1, X)), assert(temp(2, Y)),
                       retract(temp(1, A)), retract(temp(2, B)),
                       numbervars(A, 1, N), numbervars(B, 1, N),
                       A = B.

A ``better'' (I.e. faster) solution is:

      equal(X, Y) :- \+notequal(X, Y).
      notequal(X, Y) :- \+notnotequal(X, Y).
      notnotequal(X, Y) :- numbervars(X, 1, N),
      numbervars(Y, 1, N), X = Y.

This is ``better'' because it doesn't use ASSERT.  It's best to avoid 
Assert because:

        * It is slow - it has to copy the structure being asserted.

        * On the DEC-20, it consumes memory until the procedure doing
          the ASSERT is backtracked over - not just until the item is
          RETRACTed. This might be for the ENTIRE computation.

A useful heuristic is that predicates that side-effect their arguments
in undesirable ways (eg by using NUMBERVARS) can sometimes be rendered
safe by enclosing them in a double negation.

-- Steve Hardy,
   Teknowledge