Major Section: BDD
See bdd for a brief introduction to BDDs in ACL2 and for pointers to other documentation on BDDs in ACL2. Here, we illustrate the use of BDDs in ACL2 by way of some examples. For a further example, see if*.
Let us begin with a really simple example. (We will explain the
:bdd
hint (:vars nil)
below.)
ACL2 !>(thm (equal (if a b c) (if (not a) c b)) :hints (("Goal" :bdd (:vars nil)))) ; Prove with BDDs [Note: A hint was supplied for our processing of the goal above. Thanks!] But simplification with BDDs (7 nodes) reduces this to T, using the :definitions EQUAL and NOT. Q.E.D. Summary Form: ( THM ...) Rules: ((:DEFINITION EQUAL) (:DEFINITION NOT)) Warnings: None Time: 0.18 seconds (prove: 0.05, print: 0.02, other: 0.12) Proof succeeded. ACL2 !>The
:bdd
hint (:vars nil)
indicates that BDDs are to be used
on the indicated goal, and that any so-called ``variable ordering''
may be used: ACL2 may use a convenient order that is far from
optimal. It is beyond the scope of the present documentation to
address the issue of how the user may choose good variable
orderings. Someday our implementation of BDDs may be improved to
include heuristically-chosen variable orderings rather than rather
random ones.Here is a more interesting example.
(defun v-not (x) ; Complement every element of a list of Booleans. (if (consp x) (cons (not (car x)) (v-not (cdr x))) nil)) ; Now we prove a rewrite rule that explains how to open up v-not on ; a consp. (defthm v-not-cons (equal (v-not (cons x y)) (cons (not x) (v-not y)))) ; Finally, we prove for 7-bit lists that v-not is self-inverting. (thm (let ((x (list x0 x1 x2 x3 x4 x5 x6))) (implies (boolean-listp x) (equal (v-not (v-not x)) x))) :hints (("Goal" :bdd ;; Note that this time we specify a variable order. (:vars (x0 x1 x2 x3 x4 x5 x6)))))It turns out that the variable order doesn't seem to matter in this example; using several orders we found that 30 nodes were created, and the proof time was about 1/10 of a second on a (somewhat enhanced) Sparc 2. The same proof took about a minute and a half without any
:bdd
hint! This observation is a bit misleading
perhaps, since the theorem for arbitrary x
,
(thm (implies (boolean-listp x) (equal (v-not (v-not x)) x)))only takes about 1.5 times as long as the
:bdd
proof for 7 bits,
above! Nevertheless, BDDs can be very useful in reducing proof
time, especially when there is no regular structure to facilitate
proof by induction, or when the induction scheme is so complicated
to construct that significant user effort is required to get the
proof by induction to go through.Finally, consider the preceding example, with a :bdd
hint of
(say) (:vars nil)
, but with the rewrite rule v-not-cons
above
disabled. In that case, the proof fails, as we see below. That is
because the BDD algorithm in ACL2 uses hypothesis-free
:
rewrite rules, :
executable-counterpart
s
, and
nonrecursive definitions, but it does not use recursive definitions.
Notice that when we issue the (show-bdd)
command, the system's
response clearly shows that we need a rewrite rule for simplifying
terms of the form (v-not (cons ...))
.
ACL2 !>(thm (let ((x (list x0 x1 x2 x3 x4 x5 x6))) (implies (boolean-listp x) (equal (v-not (v-not x)) x))) :hints (("Goal" :bdd (:vars nil) :in-theory (disable v-not-cons)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] ACL2 Error in ( THM ...): Attempted to create V-NOT node during BDD processing with an argument that is a call of a bdd-constructor, which would produce a non-BDD term (as defined in :DOC bdd-algorithm). See :DOC show-bdd. Summary Form: ( THM ...) Rules: NIL Warnings: None Time: 0.58 seconds (prove: 0.13, print: 0.00, other: 0.45) ******** FAILED ******** See :DOC failure ******** FAILED ******** ACL2 !>(show-bdd) BDD computation on Goal yielded 17 nodes. ============================== BDD computation was aborted on Goal, and hence there is no falsifying assignment that can be constructed. Here is a backtrace of calls, starting with the top-level call and ending with the one that led to the abort. See :DOC show-bdd. (LET ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (IMPLIES (BOOLEAN-LISTP X) (EQUAL (V-NOT (V-NOT X)) X))) alist: ((X6 X6) (X5 X5) (X4 X4) (X3 X3) (X2 X2) (X1 X1) (X0 X0)) (EQUAL (V-NOT (V-NOT X)) X) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (V-NOT (V-NOT X)) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) (V-NOT X) alist: ((X (LIST X0 X1 X2 X3 X4 X5 ...))) ACL2 !>The term that has caused the BDD algorithm to abort is thus
(V-NOT X)
, where X
has the value (LIST X0 X1 X2 X3 X4 X5 ...)
,
i.e., (CONS X0 (LIST X1 X2 X3 X4 X5 ...))
. Thus, we see the utility
of introducing a rewrite rule to simplify terms of the form
(V-NOT (CONS ...))
. The moral of this story is that if you get
an error of the sort shown above, you may find it useful to execute
the command (show-bdd)
and use the result as advice that suggests
the left hand side of a rewrite rule.Here is another sort of failed proof. In this version we have
omitted the hypothesis that the input is a bit vector. Below we use
show-bdd
to see what went wrong, and use the resulting
information to construct a counterexample. This failed proof
corresponds to a slightly modified input theorem, in which x
is
bound to the 4-element list (list x0 x1 x2 x3)
.
ACL2 !>(thm (let ((x (list x0 x1 x2 x3))) (equal (v-not (v-not x)) x)) :hints (("Goal" :bdd ;; This time we do not specify a variable order. (:vars nil)))) [Note: A hint was supplied for our processing of the goal above. Thanks!] ACL2 Error in ( THM ...): The :BDD hint for the current goal has successfully simplified this goal, but has failed to prove it. Consider using (SHOW-BDD) to suggest a counterexample; see :DOC show-bdd. Summary Form: ( THM ...) Rules: NIL Warnings: None Time: 0.18 seconds (prove: 0.07, print: 0.00, other: 0.12) ******** FAILED ******** See :DOC failure ******** FAILED ******** ACL2 !>(show-bdd) BDD computation on Goal yielded 73 nodes. ============================== Falsifying constraints: ((X0 "Some non-nil value") (X1 "Some non-nil value") (X2 "Some non-nil value") (X3 "Some non-nil value") ((EQUAL 'T X0) T) ((EQUAL 'T X1) T) ((EQUAL 'T X2) T) ((EQUAL 'T X3) NIL)) ============================== Term obtained from BDD computation on Goal: (IF X0 (IF X1 (IF X2 (IF X3 (IF # # #) (IF X3 # #)) (IF X2 'NIL (IF X3 # #))) (IF X1 'NIL (IF X2 (IF X3 # #) (IF X2 # #)))) (IF X0 'NIL (IF X1 (IF X2 (IF X3 # #) (IF X2 # #)) (IF X1 'NIL (IF X2 # #))))) ACL2 Query (:SHOW-BDD): Print the term in full? (N, Y, W or ?): n ; I've seen enough. The assignment shown above suggests ; (though not conclusively) that if we bind x3 to a non-nil ; value other than T, and bind x0, x1, and x2 to t, then we ; this may give us a counterexample. ACL2 !>(let ((x0 t) (x1 t) (x2 t) (x3 7)) (let ((x (list x0 x1 x2 x3))) ;; Let's use LIST instead of EQUAL to see how the two ;; lists differ. (list (v-not (v-not x)) x))) ((T T T T) (T T T 7)) ACL2 !>See if* for another example.