This is documentation for ACL2 Version 3.3
Copyright (C) 2007  University of Texas at Austin

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

Written by:  Matt Kaufmann and J Strother Moore
Department of Computer Sciences
University of Texas at Austin
Austin, TX 78712-1188 U.S.A.

EQUIVALENCE    mark a relation as an equivalence relation

See RULE-CLASSES for a general discussion of rule classes and
how they are used to build rules from formulas.  An example :corollary
formula from which a :equivalence rule might be built is as follows.
(We assume that r-equal has been defined.)

     Example:
     (and (booleanp (r-equal x y))
          (r-equal x x)
          (implies (r-equal x y) (r-equal y x))
          (implies (and (r-equal x y)
                        (r-equal y z))
                   (r-equal x z))).

Also see DEFEQUIV.

     General Form:
     (and (booleanp (equiv x y))
          (equiv x x)
          (implies (equiv x y) (equiv y x))
          (implies (and (equiv x y)
                        (equiv y z))
                   (equiv x z)))

except that the order of the conjuncts and terms and the choice of
variable symbols is unimportant.  The effect of such a rule is to
identify equiv as an equivalence relation.  Note that only Boolean
2-place function symbols can be treated as equivalence relations.  See
CONGRUENCE and see REFINEMENT for closely related
concepts.

The macro form (defequiv equiv) is an abbreviation for a defthm of
rule-class :equivalence that establishes that equiv is an equivalence
relation.  It generates the formula shown above.  See DEFEQUIV.

When equiv is marked as an equivalence relation, its reflexivity,
symmetry, and transitivity are built into the system in a deeper way
than via :rewrite rules.  More importantly, after equiv has been shown
to be an equivalence relation, lemmas about equiv, e.g.,

     (implies hyps (equiv lhs rhs)),

when stored as :rewrite rules, cause the system to rewrite certain
occurrences of (instances of) lhs to (instances of) rhs.  Roughly
speaking, an occurrence of lhs in the kth argument of some
fn-expression, (fn ... lhs' ...), can be rewritten to produce (fn ...
rhs' ...), provided the system "knows" that the value of fn is
unaffected by equiv-substitution in the kth argument.  Such knowledge
is communicated to the system via "congruence lemmas."

For example, suppose that r-equal is known to be an equivalence
relation.  The :congruence lemma

     (implies (r-equal s1 s2)
              (equal (fn s1 n) (fn s2 n)))

informs the rewriter that, while rewriting the first argument of
fn-expressions, it is permitted to use r-equal rewrite-rules.  See
CONGRUENCE for details about :congruence lemmas.
Interestingly, congruence lemmas are automatically created when an
equivalence relation is stored, saying that either of the equivalence
relation's arguments may be replaced by an equivalent argument.  That
is, if the equivalence relation is fn, we store congruence rules that
state the following fact:

     (implies (and (fn x1 y1)
                   (fn x2 y2))
              (iff (fn x1 x2) (fn y1 y2)))

Another aspect of equivalence relations is that of "refinement."  We
say equiv1 "refines" equiv2 iff (equiv1 x y) implies (equiv2 x y).
:refinement rules permit you to establish such connections between your
equivalence relations.  The value of refinements is that if the system
is trying to rewrite something while maintaining equiv2 it is permitted
to use as a :rewrite rule any refinement of equiv2.  Thus, if equiv1 is
a refinement of equiv2 and there are equiv1 rewrite-rules available,
they can be brought to bear while maintaining equiv2.  See
REFINEMENT.

The system initially has knowledge of two equivalence relations,
equality, denoted by the symbol equal, and propositional equivalence,
denoted by iff.  Equal is known to be a refinement of all equivalence
relations and to preserve equality across all arguments of all
functions.

Typically there are five steps involved in introducing and using a new
equivalence relation, equiv.

     (1) Define equiv,

     (2) prove the :equivalence lemma about equiv,

     (3) prove the :congruence lemmas that show where equiv can be used
     to maintain known relations,

     (4) prove the :refinement lemmas that relate equiv to known
     relations other than equal, and

     (5) develop the theory of conditional :rewrite rules that drive
     equiv rewriting.

More will be written about this as we develop the techniques.  For now,
here is an example that shows how to make use of equivalence relations
in rewriting.

Among the theorems proved below is

     (defthm insert-sort-is-id
       (perm (insert-sort x) x))

Here perm is defined as usual with delete and is proved to be an
equivalence relation and to be a congruence relation for cons and
member.

Then we prove the lemma

     (defthm insert-is-cons
       (perm (insert a x) (cons a x)))

which you must think of as you would (insert a x) = (cons a x).

Now prove (perm (insert-sort x) x).  The base case is trivial.  The
induction step is

        (consp x)
      & (perm (insert-sort (cdr x)) (cdr x))

     -> (perm (insert-sort x) x).

Opening insert-sort makes the conclusion be

        (perm (insert (car x) (insert-sort (cdr x))) x).

Then apply the induction hypothesis (rewriting (insert-sort (cdr x)) to
(cdr x)), to make the conclusion be

     (perm (insert (car x) (cdr x)) x)

Then apply insert-is-cons to get (perm (cons (car x) (cdr x)) x).  But
we know that (cons (car x) (cdr x)) is x, so we get (perm x x) which is
trivial, since perm is an equivalence relation.

Here are the events.

     (encapsulate (((lt * *) => *))
       (local (defun lt (x y) (declare (ignore x y)) nil))
       (defthm lt-non-symmetric (implies (lt x y) (not (lt y x)))))

     (defun insert (x lst)
       (cond ((atom lst) (list x))
             ((lt x (car lst)) (cons x lst))
             (t (cons (car lst) (insert x (cdr lst))))))

     (defun insert-sort (lst)
       (cond ((atom lst) nil)
             (t (insert (car lst) (insert-sort (cdr lst))))))

     (defun del (x lst)
       (cond ((atom lst) nil)
             ((equal x (car lst)) (cdr lst))
             (t (cons (car lst) (del x (cdr lst))))))

     (defun mem (x lst)
       (cond ((atom lst) nil)
             ((equal x (car lst)) t)
             (t (mem x (cdr lst)))))

     (defun perm (lst1 lst2)
       (cond ((atom lst1) (atom lst2))
             ((mem (car lst1) lst2)
              (perm (cdr lst1) (del (car lst1) lst2)))
             (t nil)))

     (defthm perm-reflexive
       (perm x x))

     (defthm perm-cons
       (implies (mem a x)
                (equal (perm x (cons a y))
                       (perm (del a x) y)))
       :hints (("Goal" :induct (perm x y))))

     (defthm perm-symmetric
       (implies (perm x y) (perm y x)))

     (defthm mem-del
       (implies (mem a (del b x)) (mem a x)))

     (defthm perm-mem
       (implies (and (perm x y)
                     (mem a x))
                (mem a y)))

     (defthm mem-del2
       (implies (and (mem a x)
                     (not (equal a b)))
                (mem a (del b x))))

     (defthm comm-del
       (equal (del a (del b x)) (del b (del a x))))

     (defthm perm-del
       (implies (perm x y)
                (perm (del a x) (del a y))))

     (defthm perm-transitive
       (implies (and (perm x y) (perm y z)) (perm x z)))

     (defequiv perm)

     (in-theory (disable perm
                         perm-reflexive
                         perm-symmetric
                         perm-transitive))

     (defcong perm perm (cons x y) 2)

     (defcong perm iff (mem x y) 2)

     (defthm atom-perm
       (implies (not (consp x)) (perm x nil))
       :rule-classes :forward-chaining
       :hints (("Goal" :in-theory (enable perm))))

     (defthm insert-is-cons
       (perm (insert a x) (cons a x)))

     (defthm insert-sort-is-id
       (perm (insert-sort x) x))

     (defun app (x y) (if (consp x) (cons (car x) (app (cdr x) y)) y))

     (defun rev (x)
       (if (consp x) (app (rev (cdr x)) (list (car x))) nil))

     (defcong perm perm (app x y) 2)

     (defthm app-cons
       (perm (app a (cons b c)) (cons b (app a c))))

     (defthm app-commutes
       (perm (app a b) (app b a)))

     (defcong perm perm (app x y) 1
       :hints (("Goal" :induct (app y x))))

     (defthm rev-is-id (perm (rev x) x))

     (defun == (x y)
       (if (consp x)
           (if (consp y)
               (and (equal (car x) (car y))
                    (== (cdr x) (cdr y)))
               nil)
           (not (consp y))))

     (defthm ==-reflexive (== x x))

     (defthm ==-symmetric (implies (== x y) (== y x)))

     (defequiv ==)

     (in-theory (disable ==-symmetric ==-reflexive))

     (defcong == == (cons x y) 2)

     (defcong == iff (consp x) 1)

     (defcong == == (app x y) 2)

     (defcong == == (app x y) 1)

     (defthm rev-rev (== (rev (rev x)) x))

FORWARD-CHAINING    make a rule to forward chain when a certain trigger arises

See RULE-CLASSES for a general discussion of rule classes and
how they are used to build rules from formulas.  An example :corollary
formula from which a :forward-chaining rule might be built is:

     Example:
     (implies (and (p x) (r x))        when (p a) appears in a formula to be
              (q (f x)))               simplified, try to establish (r a) and
                                       if successful, add (q (f a)) to the
                                       known assumptions

To specify the triggering terms provide a non-empty list of terms as
the value of the :trigger-terms field of the rule class object.

     General Form:
     Any theorem, provided an acceptable triggering term exists.

Forward chaining rules are generated from the corollary term as
follows.  If that term has the form (implies hyp concl), then the let
expressions in concl (formally, lambda expressions) are expanded away,
and the result is treated as a conjunction, with one forward chaining
rule with hypothesis hyp created for each conjunct.  In the other case,
where the corollary term is not an implies, we process it as we process
the conclusion in the first case.

The :trigger-terms field of a :forward-chaining rule class object
should be a non-empty list of terms, if provided, and should have
certain properties described below.  If the :trigger-terms field is not
provided, it defaults to the singleton list containing the "atom" of
the first hypothesis of the formula.  (The atom of (not x) is x; the
atom of any other term is the term itself.)  If there are no hypotheses
and no :trigger-terms were provided, an error is caused.

A triggering term is acceptable if it is not a variable, a quoted
constant, a lambda application, a let-expression, or a not-expression,
and every variable symbol in the conclusion of the theorem either
occurs in the hypotheses or occurs in the trigger.

:Forward-chaining rules are used by the simplifier before it begins to
rewrite the literals of the goal.  (Forward chaining is thus carried
out from scratch for each goal.)  If any term in the goal is an
instance of a trigger of some forward chaining rule, we try to
establish the hypotheses of that forward chaining theorem (from the
negation of the goal).  To relieve a hypothesis we only use type
reasoning, evaluation of ground terms, and presence among our known
assumptions.  We do not use rewriting.  So-called free variables in
hypotheses are treated specially; see FREE-VARIABLES.  If all
hypotheses are relieved, we add the instantiated conclusion to our
known assumptions.

_Caution_.  Forward chaining does not actually add terms to the goals
displayed during proof attempts.  Instead, it extends an associated
_context_, called "assumptions" in the preceding paragraph, that ACL2
builds from the goal currently being proved.  The context starts out
with "obvious" consequences of the negation of the goal.  For example,
if the goal is

     (implies (and (p x) (q (f x)))
              (c x))

then the context notes that (p x) and (q (f x)) are non-nil and

(c x) is nil.  Forward chaining is then used to expand the context.
For example, if a forward chaining rule has (f x) as a trigger term and
has body (implies (p x) (r (f x))), then the context is extended by
binding (r (f x)) to non-nil.  Note however that since (r (f x)) is put
into the context, not the goal, it is _not_ further simplified.  If f
is an enabled nonrecursive function symbol then this forward chaining
rule may well be useless, since calls of f may be expanded away.

However, forward-chaining does support the linear arithmetic reasoning
package.  For example, suppose that forward-chaining puts (< (f x) (g
x)) into the context.  Then this inequality also goes into the linear
arithmetic data base, together with suitable instances of linear lemmas
whose trigger term is a call of g.  See LINEAR.

FREE-VARIABLES    free variables in rules

As described elsewhere (see RULE-CLASSES), ACL2 rules are
treated as implications for which there are zero or more hypotheses hj
to prove.  In particular, rules of class :rewrite may look like this:

     (implies (and h1 ... hn)
              (fn lhs rhs))

Variables of hi are said to occur _free_ in the above :rewrite rule if
they do not occur in lhs or in any hj with j<i.  (To be precise, here
we are only discussing those variables that are not in the scope of a
let/let*/lambda that binds them.)  We also refer to these as the _free
variables_ of the rule.  ACL2 issues a warning or error when there are
free variables in a rule, as described below.  (Variables of rhs may be
considered free if they do not occur in lhs or in any hj.  But we do
not consider those in this discussion.)

In general, the _free variables_ of rules are those variables occurring
in their hypotheses (not let/let*/lambda-bound) that are not bound when
the rule is applied.  For rules of class :linear and :forward-chaining,
variables are bound by a trigger term.  (See RULE-CLASSES for a
discussion of the :trigger-terms field).  For rules of class
:type-prescription, variables are bound by the :typed-term field.

Let us discuss the method for relieving hypotheses of rewrite rules with
free variables.  Similar considerations apply to linear and
forward-chaining rules, while for other rules (in particular,
type-prescription rules), only one binding is tried, much as described
in the discussion about :once below.

See FREE-VARIABLES-EXAMPLES for more examples of how this all
works, including illustration of how the user can exercise some control
over it.  In particular, see FREE-VARIABLES-EXAMPLES-REWRITE
for an explanation of output from the break-rewrite facility in the
presence of rewriting failures involving free variables.

We begin with an example.  Does the proof of the thm below succeed?

     (defstub p2 (x y) t)

     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (equal (p2 x z) t))
       :rule-classes ((:rewrite :match-free :all)))

     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

Consider what happens when the proof of the thm is attempted.  The ACL2
rewriter attempts to apply rule p2-trans to the conclusion, (p2 a d).
So, it binds variables x and z from the left-hand side of the
conclusion of p2-trans to terms a and d, respectively, and then
attempts to relieve the hypotheses of p2-trans.  The first hypothesis of
p2-trans, (p2 x y), is considered first.  Variable y is free in that
hypothesis, i.e., it has not yet been bound.  Since x is bound to a,
the rewriter looks through the context for a binding of y such that (p2
a y) is true, and it so happens that it first finds the term (p2 a b),
thus binding y to b.  Now it goes on to the next hypothesis, (p2 y z).
At this point y and z have already been bound to b and d; but (p2 b d)
cannot be proved.

So, in order for the proof of the thm to succeed, the rewriter needs to
backtrack and look for another way to instantiate the first hypothesis
of p2-trans.  Because :match-free :all has been specified, backtracking
does take place.  This time y is bound to c, and the subsequent
instantiated hypothesis becomes (p2 c d), which is true.  The
application of rule (p2-trans) succeeds and the theorem is proved.

If instead :match-free :all had been replaced by :match-free :once in
rule p2-trans, then backtracking would not occur, and the proof of the
thm would fail.

Next we describe in detail the steps used by the rewriter in dealing
with free variables.

ACL2 uses the following sequence of steps to relieve a hypothesis with
free variables, except that steps (1) and (3) are skipped for
:forward-chaining rules and step (3) is skipped for :type-prescription
rules.  First, if the hypothesis is of the form (force hyp0) or
(case-split hyp0), then replace it with hyp0.  (1) Suppose the
hypothesis has the form (equiv var term) where var is free and no
variable of term is free, and either equiv is equal or else equiv is a
known equivalence relation and term is a call of double-rewrite.  Then
bind var to the result of rewriting term in the current context.  (2)
Look for a binding of the free variables of the hypothesis so that the
corresponding instance of the hypothesis is known to be true in the
current context.  (3) Search all enabled, hypothesis-free rewrite rules
of the form (equiv lhs rhs), where lhs has no variables (other than
those bound by let, let*, or lambda), rhs is known to be true in the
current context, and equiv is typically equal but can be any equivalence
relation appropriate for the current context (see CONGRUENCE);
then attempt to bind the free variables so that the instantiated
hypothesis is lhs.  If all attempts fail and the original hypothesis is
a call of force or case-split, where forcing is enabled (see
FORCE) then the hypothesis is relieved, but in the split-off goals,
all free variables are bound to unusual names that call attention to
this odd situation.

When a rewrite or linear rule has free variables in the hypotheses, the
user generally needs to specify whether to consider only the first
instance found in steps (2) and (3) above, or instead to consider them
all.  Below we discuss how to specify these two options as ":once" or
":all" (the default), respectively.

Is it better to specify :once or :all?  We believe that :all is
generally the better choice because of its greater power, provided the
user does not introduce a large number of rules with free variables,
which has been known to slow down the prover due to combinatorial
explosion in the search (Steps (2) and (3) above).

Either way, it is good practice to put the "more substantial" hypotheses
first, so that the most likely bindings of free variables will be found
first (in the case of :all) or found at all (in the case of :once).  For
example, a rewrite rule like

     (implies (and (p1 x y)
                   (p2 x y))
              (equal (bar x) (bar-prime x)))

may never succeed if p1 is nonrecursive and enabled, since we may well
not find calls of p1 in the current context.  If however p2 is disabled
or recursive, then the above rule may apply if the two hypotheses are
switched.  For in that case, we can hope for a match of (p2 x y) in the
current context that therefore binds x and y; then the rewriter's full
power may be brought to bear to prove (p1 x y) for that x and y.

Moreover, the ordering of hypotheses can affect the efficiency of the
rewriter.  For example, the rule

     (implies (and (rationalp y)
                   (foo x y))
              (equal (bar x) (bar-prime x)))

may well be sub-optimal.  Presumably the intention is to rewrite (bar x)
to (bar-prime x) in a context where (foo x y) is explicitly known to be
true for some rational number y.  But y will be bound first to the
first term found in the current context that is known to represent a
rational number.  If the 100th such y that is found is the first one
for which (foo x y) is known to be true, then wasted work will have
been done on behalf of the first 99 such terms y -- unless :once has
been specified, in which case the rule will simply fail after the first
binding of y for which (rationalp y) is known to be true.  Thus, a
better form of the above rule is almost certainly the following.

     (implies (and (foo x y)
                   (rationalp y))
              (equal (bar x) (bar-prime x)))

_Specifying `once' or `all'._ One method for specifying :once or :all
for free-variable matching is to provide the :match-free field of the
:rule-classes of the rule, for example, (:rewrite :match-free :all).
See RULE-CLASSES.  However, there are global events that can be
used to specify :once or :all; see SET-MATCH-FREE-DEFAULT and
see ADD-MATCH-FREE-OVERRIDE.  Here are some examples.

     (set-match-free-default :once)    ; future rules without a :match-free field
                                       ; are stored as :match-free :once (but this
                                       ; behavior is local to a book)
     (add-match-free-override :once t) ; existing rules are treated as
                                       ; :match-free :once regardless of their
                                       ; original :match-free fields
     (add-match-free-override :once (:rewrite foo) (:rewrite bar . 2))
                                       ; the two indicated rules are treated as
                                       ; :match-free :once regardless of their
                                       ; original :match-free fields

_Some history._ Before Version  2.7 the ACL2 rewriter performed Step (2)
above first.  More significantly, it always acted as though :once had
been specified.  That is, if Step (2) did not apply, then the rewriter
took the first binding it found using either Steps (1) or (3), in that
order, and proceeded to relieve the remaining hypotheses without trying
any other bindings of the free variables of that hypothesis.

FREE-VARIABLES-EXAMPLES    examples pertaining to free variables in rules

The examples in the two sub-topics of this topic illustrate the
handling of free variables in rules of class :rewrite (see
FREE-VARIABLES-EXAMPLES-REWRITE]) and of class :forward-chaining (see
FREE-VARIABLES-EXAMPLES-FORWARD-CHAINING]), respectively.
These implicitly illustrate free-variable handling in rules of class
:linear as well.  Also see FREE-VARIABLES and see
RULE-CLASSES.

FREE-VARIABLES-EXAMPLES-FORWARD-CHAINING    examples pertaining to free variables in forward-chaining rules

The following examples illustrate ACL2's handling of free variables in
forward-chaining rules, as well as user control over how such free
variables are handled.  See FREE-VARIABLES for a background
discussion.

     ; First let us introduce a transitive operation, op, and prove a
     ; forward-chaining rule stating the transitivity of op.

     (encapsulate
      (((op * *) => *))
      (local (defun op (x y) (< x y)))
      (defthm transitivity-of-op
        (implies (and (op x y) (op y z)) (op x z))
        :rule-classes :forward-chaining))

     ; The following theorem is proved by forward chaining, using the above rule.

     (thm
      (implies (and (op u v) (op v w) (op v a))
               (op u w)))

     ; The proof of the theorem just above succeeds because the term (op u v)
     ; triggers the application of forward-chaining rule transitivity-of-op,
     ; binding x to u and y to v.  Free variable z of that rule is bound to both w
     ; and to a, resulting in the addition of both (op u w) and (op u a) to the
     ; context.  However, (op v a) happens to be at the front of the context, so
     ; if only one free-variable binding had been allowed, then z would have only
     ; been bound to a, not to w, as we now illustrate.

     (add-match-free-override :once (:forward-chaining transitivity-of-op))

     (thm ; FAILS!
      (implies (and (op u v) (op v w) (op v a))
               (op u w)))

     :ubt! 1

     ; Starting over, this time we prove transitivity-of-op as a :match-free :once
     ; forward-chaining rule.  Note that the presence of :match-free eliminates
     ; the free-variables warning that we got the first time.

     (encapsulate
      (((op * *) => *))
      (local (defun op (x y) (< x y)))
      (defthm transitivity-of-op
        (implies (and (op x y) (op y z)) (op x z))
        :rule-classes ((:forward-chaining :match-free :once))))

     (thm ; FAILS!
      (implies (and (op u v) (op v w) (op v a))
               (op u w)))

     ; Notice that if we swap the order of the last two hypotheses the theorem
     ; goes through, because this time (op v w) is first in the context.

     (thm ; SUCCEEDS!
      (implies (and (op u v) (op v a) (op v w))
               (op u w)))

     :u

     ; Now let's try setting the default to :once.

     (set-match-free-default :once)

     ; We still get a free-variables warning when we admit this forward-chaining rule.

     (encapsulate
      (((op * *) => *))
      (local (defun op (x y) (< x y)))
      (defthm transitivity-of-op
        (implies (and (op x y) (op y z)) (op x z))
        :rule-classes ((:forward-chaining))))

     ; This theorem fails--as it should.

     (thm ; FAILS!
      (implies (and (op u v) (op v w) (op v a))
               (op u w)))

     ; But if we convert this rule (or here, all possible rules) to :all rules,
     ; then the proof succeeds.

     (add-match-free-override :all t)

     (thm ; SUCCEEDS!
      (implies (and (op u v) (op v w) (op v a))
               (op u w)))

     ; Now let's test a relatively slow :all case (the next thm below).

     :ubt! 1

     (encapsulate
      (((op1 *) => *)
       ((op3 * * *) => *))
      (local (defun op1 (x) (declare (ignore x)) t))
      (local (defun op3 (x0 x1 x2)
               (declare (ignore x0 x1 x2))
               t))
      (defthm op1-op3-property
        (implies (and (op1 x0) (op1 x1) (op1 x2))
                 (op3 x0 x1 x2))
        :rule-classes ((:forward-chaining :match-free :all))))

     ; The following succeeds, but takes a little time (about a second in one run).

     (thm (implies
           (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
                (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
                (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
                (op1 a17) (op1 a18) (op1 a19) (op1 a20))
           (op3 a5 a6 a0)))

     (add-match-free-override :once t)

     ; The same theorem now fails because of the add-match-free-override, but is
     ; more than an order of magnitude faster.

     (thm (implies
           (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
                (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
                (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
                (op1 a17) (op1 a18) (op1 a19) (op1 a20))
           (op3 a5 a6 a0)))

     ; A slight variant succeeds in a negligible amount of time (still with the
     ; :once override above).

     (thm (implies
           (and (op1 a0) (op1 a1) (op1 a2) (op1 a3) (op1 a4) (op1 a5)
                (op1 a6) (op1 a7) (op1 a8) (op1 a9) (op1 a10) (op1 a11)
                (op1 a12) (op1 a13) (op1 a14) (op1 a15) (op1 a16)
                (op1 a17) (op1 a18) (op1 a19) (op1 a20))
           (op3 a5 a20 a20)))

     ; Reality check: This shouldn't give a free-variables warning, and everything
     ; should work great since there are no free variables with this trigger term.

     :ubt! 1

     (encapsulate
      (((op1 *) => *)
       ((op7 * * * * * * *) => *))
      (local (defun op1 (x)
               (declare (ignore x))
               t))
      (local (defun op7 (x0 x1 x2 x3 x4 x5 x6)
               (declare (ignore x0 x1 x2 x3 x4 x5 x6))
               t))
      (defthm op1-op7-property
        (implies (and (op1 x0) (op1 x1) (op1 x2)
                      (op1 x3) (op1 x4) (op1 x5) (op1 x6))
                 (op7 x0 x1 x2 x3 x4 x5 x6))
        :rule-classes ((:forward-chaining
                        :trigger-terms ((op7 x0 x1 x2 x3 x4 x5 x6))))))

     ; The following then succeeds, and very quickly.

     (thm (implies (and (op1 a0) (op1 a1) (op1 a2)
                        (op1 a3) (op1 a4) (op1 a5) (op1 a6))
                   (op7 a4 a6 a5 a6 a6 a6 a6)))

FREE-VARIABLES-EXAMPLES-REWRITE    examples pertaining to free variables in rewrite rules

The following examples illustrate ACL2's handling of free variables in
rewrite rules, as well as user control over how such free variables are
handled.  See FREE-VARIABLES for a background discussion.

     (defstub p2 (x y) t) ; introduce unconstrained function

     ; Get warning because of free variable.  This would be an error if you had
     ; first executed (set-match-free-error t) in order to force yourself to
     ; specify :match-free (illustrated later, below).
     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (p2 x z)))

     ; Succeeds.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     ; The following causes an error because p2-trans is not a rune.
     (add-match-free-override :once p2-trans)

     ; After the following, the rewrite rule p2-trans will only allow one
     ; attempt per hypothesis to bind free variables.
     (add-match-free-override :once (:rewrite p2-trans))

     ; Now this same theorem fails to be proved.  Here's why.  The
     ; context for proving (p2 a d) happens to include the hypotheses in
     ; reverse order.  So when the first hypothesis of p2-trans, namely
     ; (p2 x y), is relieved, where x is bound to a (as we are attempting
     ; to rewrite the current literal (p2 a d)), we find (p2 a b) in the
     ; context before (p2 a c) and hence y is bound to b.  The
     ; instantiated second hypothesis of p2-trans is thus (p2 b d), and
     ; the proof fails.  Before the add-match-free-override form above,
     ; the proof succeeded because the rewriter was allowed to backtrack
     ; and find the other binding for the first hypothesis of p2-trans,
     ; namely, y bound to c.  Then the instantiated second hypothesis of
     ; p2-trans is (p2 c d), which is known to be true in the current
     ; context.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     ; Return to original behavior for binding free variables.
     (add-match-free-override :all t)

     ; Succeeds once again.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     (u) ; undo (add-match-free-override :all t)

     ; This is an error, since no further arguments should appear after
     ; :clear.
     (add-match-free-override :clear t)

     ; Return all rules to original behavior for binding free variables,
     ; regardless of which previous add-match-free-override forms have
     ; been executed.
     (add-match-free-override :clear)

     ; This succeeds just as it did originally.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     (ubt! 'p2-trans) ; back to the start, except retain the defstub

     ; Require that :match-free be specified for :linear and :rewrite rules with
     ; free variables.
     (set-match-free-error t)

     ; Fails because :match-free is missing.
     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (p2 x z)))

     ; Fails because :match-free must be followed by :once or :all.
     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (p2 x z))
       :rule-classes ((:rewrite :match-free nil)))

     ; Succeeds, this time with no warning at all.
     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (p2 x z))
       :rule-classes ((:rewrite :match-free :once)))

     ; Fails because we only bind once (see earlier long comment).
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     ; Treat p2-trans as though `:match-free :all' had been specified.
     (add-match-free-override :all (:rewrite p2-trans))

     ; Succeeds since more than one binding is allowed for p2-trans.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     (u)
     (u)

     ; Specify that future :linear and :rewrite rules with free variables
     ; that do not have :match-free specified are treated as though
     ; `:match-free :once' were specified.
     (set-match-free-default :once)

     ; Succeeds without error since `:match-free' is specified, as described
     ; above.  But there is a warning, since :match-free is not specified for this
     ; :rewrite rule.
     (defaxiom p2-trans
       (implies (and (p2 x y)
                     (p2 y z))
                (p2 x z)))

     ; Fails since only single bindings are allowed for p2-trans.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     ; Treat p2-trans as though `:match-free :all' had been specified.
     (add-match-free-override :all t)

     ; Succeeds.
     (thm (implies (and (p2 a c)
                        (p2 a b)
                        (p2 c d))
                   (p2 a d)))

     ;;; Test searching of ground units, i.e. rewrite rules without
     ;;; variables on the left side of the conclusion, for use in
     ;;; relieving hypotheses with free variables.  This is a very
     ;;; contrived example.

     (ubt! 1) ; back to the start

     (encapsulate
      (((p1 *) => *)
       ((p2 * *) => *)
       ((p3 *) => *)
       ((a) => *)
       ((b) => *))
      (local (defun p1 (x) x))
      (local (defun p2 (x y) (list x y)))
      (local (defun p3 (x) x))
      (local (defun a () 0))
      (local (defun b () 0)))

     ; Allow default of :match-free :all (form may be omitted).
     (set-match-free-error nil)

     (defaxiom ax1
       (implies (and (p2 x y)
                     (p1 y))
                (p3 x)))

     (defaxiom p2-a-b
       (p2 (a) (b)))

     (defaxiom p2-a-a
       (p2 (a) (a)))

     (defaxiom p1-b
       (p1 (b)))

     ; Succeeds; see long comment below on next attempt to prove this
     ; theorem.
     (thm (implies (p2 (a) y)
                   (p3 (a))))

     ; Now ax1 will only relieve hypothesis (p2 x y) for one binding of y:
     (add-match-free-override :once t)

     ; Fails when ax1 attempts to rewrite the conclusion to true, because
     ; the most recent ground unit for hypothesis (p2 x y) with x bound
     ; to (a) is rule p2-a-a, which binds y to (a).  If more than one ground
     ; unit could be used then we would backtrack and apply rule p2-a-b,
     ; which binds y to (b) and hence hypothesis (p1 y) of ax1 is
     ; relieved by rule p1-b.
     (thm (implies (p2 (a) y)
                   (p3 (a))))

     ; Return rules to original :match-free behavior.
     (add-match-free-override :clear)

     ; Succeeds once again.
     (thm (implies (p2 (a) y)
                   (p3 (a))))

     ; Just for kicks, change the behavior of a built-in rule irrelevant
     ; to the proof at hand.
     (add-match-free-override :once (:rewrite string<-l-trichotomy))

     ; Still succeeds.
     (thm (implies (p2 (a) y)
                   (p3 (a))))

     ;;;;;;;;;;

FINALLY, here is an example illustrating the use of the break-rewrite
facility to get information about handling of free variables by the
rewriter.  Explanation is given after this (edited) transcript.  Input
begins on lines with a prompt (search for "ACL2"); the rest is output.

     ACL2 !>(encapsulate
             ((p1 (u x) t)
              (bad (x) t)
              (p2 (x y z) t)
              (bar (x y) t)
              (foo (x y) t)
              (poo (x y) t)
              (prop (u) t))

             (local (defun p1 (u x) (declare (ignore u x)) nil))
             (local (defun bad (x) (declare (ignore x)) nil))
             (local (defun p2 (x y z) (declare (ignore x y z)) nil))
             (local (defun bar (x y) (declare (ignore x y)) nil))
             (local (defun foo (x y) (declare (ignore x y)) nil))
             (local (defun poo (x y) (declare (ignore x y)) nil))
             (local (defun prop (u) (declare (ignore u)) t))

             (defthm foo-poo
               (implies (syntaxp (equal y 'y3))
                        (equal (foo x y)
                               (poo x y))))

             (defthm lemma-1
               (implies (and (p1 u x)
                             (bad x)
                             (p2 x y z)
                             (bar x y)
                             (equal x x) ; admittedly silly!
                             (foo x y))
                        (prop u))
               :rule-classes ((:rewrite :match-free :all))))

     ; [[ output omitted ]]

     Summary
     Form:  ( ENCAPSULATE ((P1 ...) ...) ...)
     Rules: NIL
     Warnings:  Subsume and Non-rec
     Time:  0.08 seconds (prove: 0.00, print: 0.01, other: 0.06)
      T
     ACL2 !>:brr t
     The monitored runes are:
     NIL
      T
     ACL2 !>:monitor (:rewrite lemma-1) t
     (((:REWRITE LEMMA-1) 'T))
     ACL2 !>(thm (implies (and (p1 u0 x1)
                               (bad x1)
                               (bad x3)
                               (bar x3 y1)
                               (bar x3 y3)
                               (p1 u0 x2)
                               (p1 u0 x3)
                               (p2 x3 y1 z1)
                               (p2 x3 y3 z1))
                          (prop u0)))

     (1 Breaking (:REWRITE LEMMA-1) on (PROP U0):
     1 ACL2 >:eval

     1x (:REWRITE LEMMA-1) failed because :HYP 1 contains free variables.
     The following display summarizes the attempts to relieve hypotheses
     by binding free variables; see :DOC free-variables and see :DOC set-
     brr-term-evisc-tuple.

         [1] X : X1
     Failed because :HYP 3 contains free variables Y and Z, for which no
     suitable bindings were found.
         [1] X : X2
     Failed because :HYP 2 rewrote to (BAD X2).
         [1] X : X3
             [3] Z : Z1
                 Y : Y1
     Failed because :HYP 6 rewrote to (FOO X3 Y1).
             [3] Z : Z1
                 Y : Y3
     Failed because :HYP 6 rewrote to (POO X3 Y3).

     1 ACL2 >:unify-subst
          U : U0
     1 ACL2 >

The :eval command above asks the rewriter to attempt to apply the
rewrite rule lemma-1 to the term (prop u0), shown just above the line
with :eval.  As we can see at the end, the variable u in the conclusion
of lemma-1 is being bound to the variable u0 in the conjecture.  The
first hypothesis of lemma-1 is (p1 u x), so the rewriter looks for some
x for which (p1 u0 x) is known to be true.  It finds x1, and then goes
on to consider the second hypothesis, (bad x).  Since the theorem we
are proving has (bad x1) in the hypothesis and x is currently bound to
x1, the rewriter is satisfied and moves on to the third hypothesis of
lemma-1, (p2 x y z).  However, x is bound to x1 and there are no
instances of y and z for which (p2 x1 y z) is known in the current
context.  All of the above analysis is summarized in the first part of
the output from :eval above:

         [1] X : X1
     Failed because :HYP 3 contains free variables Y and Z, for which no
     suitable bindings were found.

Thus, the binding of x to x1 on behalf of the first hypothesis has
failed.

The rewriter now backs up to look for other values of x that satisfy the
first hypothesis, and finds x2 because our current theorem has a
hypothesis of (p1 u0 x2).  But this time, the second hypothesis of
lemma-1, (bad x), is not known to be true for x; that is, (bad x2) does
not rewrite to t; in fact, it rewrites to itself.  That explains the
next part of the output from :eval above:

         [1] X : X2
     Failed because :HYP 2 rewrote to (BAD X2).

The rewriter now backs up again to look for other values of x that
satisfy the first hypothesis, and finds x3 because our current theorem
has a hypothesis of (p1 u0 x3).  This time, the second hypothesis of
lemma-1 is not a problem, and moreover, the rewriter is able to bind y
and z to y1 and z1, respectively, in order to satisfy the third
hypothesis, (p2 x y z): that is, (p2 x2 y1 z1) is known in the current
context.  That explains more of the above output from :eval:

         [1] X : X3
             [3] Z : Z1
                 Y : Y1

Unfortunately, the sixth hypothesis, (foo x y), rewrites to itself
under the above bindings:

     Failed because :HYP 6 rewrote to (FOO X3 Y1).

So the rewriter looks for other bindings to satisfy the third
hypothesis and finds these.

             [3] Z : Z1
                 Y : Y3

This time, the sixth hypothesis can be rewritten under the above
bindings, from (foo x3 y3) to (poo x3 y3) by lemma foo-poo, but still
not to t.

     Failed because :HYP 6 rewrote to (POO X3 Y3).

There are no more free variable bindings to try, so this concludes the
output from :eval.

GENERALIZE    make a rule to restrict generalizations

See RULE-CLASSES for a general discussion of rule classes and
how they are used to build rules from formulas.  An example :corollary
formula from which a :generalize rule might be built is:

     Example:
     any theorem

     General Form:
     any theorem

To use such a :generalize rule, the system waits until it has decided
to generalize some term, term, by replacing it with some new variable
v.  If any :generalize formula can be instantiated so that some
non-variable subterm becomes term, then that instance of the formula is
added as a hypothesis.

At the moment, the best description of how ACL2 :generalize rules are
used may be found in the discussion of "Generalize Rules," page 248 of
A Computational Logic Handbook, or "Generalization," page 132 of
"Computer-Aided Reasoning: An Approach."