Using the computed-hint-replacement feature
So far none of our computed hints have used the
The
A non-looping use of the
(if (certain-terms-present clause) '(:computed-hint-replacement t :in-theory (enable lemma25)) '(:computed-hint-replacement t :in-theory (disable lemma25)))
In this hint, if certain terms are present in
Now we will set up a toy to allow us to play with computed hints to understand them more deeply. To follow the discussion it is best to execute the following events.
(defstub wrapper (x) t) (defaxiom wrapper-axiom (wrapper x) :rule-classes nil)
Now submit the following event and watch what happens.
(thm (equal u v) :hints (`(:use (:instance wrapper-axiom (x a)))))
The theorem prover adds
What happens if we do the following?
(thm (equal u v) :hints (`(:computed-hint-replacement t :use (:instance wrapper-axiom (x a)))))
As one might expect, this loops forever: The hint is applied to the child
and adds the hypothesis again. When the hint fires, nothing is actually
changed, since
So let's change the experiment a little. Let's make the hint add the
hypothesis
(thm (equal u v) :hints (`(:use (:instance wrapper-axiom (x ,(car clause))))))
So in this case, the theorem prover changes the goal to
(IMPLIES (WRAPPER (EQUAL U V)) (EQUAL U V))
which then simplifies to
(IMPLIES (WRAPPER NIL) (EQUAL U V))
because the concluding equality can be assumed false in the hypothesis (e.g., think of the contrapositive version). Nothing else happens because the hint has been removed and so is not applicable to the child.
Now consider the following — and be ready to interrupt it and abort!
(thm (equal u v) :hints (`(:computed-hint-replacement t :use (:instance wrapper-axiom (x ,(car clause))))))
This time the hint is not removed and so is applied to the child. So from
Goal' (IMPLIES (WRAPPER (EQUAL U V)) (EQUAL U V))
and then
Goal'' (IMPLIES (AND (WRAPPER (NOT (WRAPPER (EQUAL U V)))) (WRAPPER (EQUAL U V))) (EQUAL U V))
etc.
First, note that the hint is repeatedly applied to its children. That is
because we wrote
As an exercise, let's arrange for the hint to stay around and be applied indefinitely but with a simplification between each use of the hint. To do this we need to pass information from one application of the hint to the next, essentially to say ``stay around but don't fire.''
First, we will define a function to use in the hint. This is more than a mere convenience; it allows the hint to ``reproduce itself'' in the replacement.
(defun wrapper-challenge (clause parity) (if parity `(:computed-hint-replacement ((wrapper-challenge clause nil)) :use (:instance wrapper-axiom (x ,(car clause)))) `(:computed-hint-replacement ((wrapper-challenge clause t)))))
Note that this function is not recursive, even though it uses its own name. That is because the occurrence of its name is in a quoted constant.
Now consider the following. What will it do?
(thm (equal u v) :hints ((wrapper-challenge clause t)))
First, observe that this is a legal hint because it is a term that mentions
only the free variable
Second, the basic cleverness of this hint is that every time it fires it
reproduces itself with the opposite parity. When the parity is
Ok, so what happens when the event above is executed? Try it. You will
see that ACL2 applied the hint the first time. It doesn't get around to
printing the output because an error is caused before it can print. But here
is a blow-by-blow description of what happens. The hint is evaluated on
("Goal" :use (:instance wrapper-axiom (x (equal u v))))
which is applied to this goal. In addition, it produces the new hints argument
:hints ((wrapper-challenge clause nil)).
By applying the
Goal' (implies (wrapper (equal u v)) (equal u v))
but this is not printed because, before printing it, the theorem prover looks for hints to apply to it and finds
(wrapper-challenge clause nil)
That is evaluated and produces a hint exactly as though we had typed:
("Goal'" )
and the new hints argument:
:hints ((wrapper-challenge clause nil)).
But if you supply the hint
So the definition of
:ubt wrapper-challenge (defun wrapper-challenge (cl parity) (if parity `(:computed-hint-replacement ((wrapper-challenge clause nil)) :use (:instance wrapper-axiom (x ,(car cl)))) `(:computed-hint-replacement ((wrapper-challenge clause t)) :expand ((atom zzz))))) (thm (equal u v) :hints ((wrapper-challenge clause t)))
This time, things go as you might have expected!
Goal'' (implies (wrapper nil) (equal u v)).
Simplification gets a chance because when the new hint
Goal''' (IMPLIES (AND (WRAPPER (NOT (WRAPPER NIL))) (WRAPPER NIL)) (EQUAL U V)).
This simplifies, replacing the first
Goal'4' (IMPLIES (WRAPPER NIL) (EQUAL U V)).
The process repeats indefinitely.
So we succeeded in getting a hint to fire indefinitely but allow a full simplification between rounds.