File: MBT.html

package info (click to toggle)
acl2 3.1-1
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 36,712 kB
  • ctags: 38,396
  • sloc: lisp: 464,023; makefile: 5,470; sh: 86; csh: 47; cpp: 25; ansic: 22
file content (116 lines) | stat: -rw-r--r-- 5,252 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
<html>
<head><title>MBT.html  --  ACL2 Version 3.1</title></head>
<body text=#000000 bgcolor="#FFFFFF">
<h2>MBT</h2>introduce a test not to be evaluated
<pre>Major Section:  <a href="PROGRAMMING.html">PROGRAMMING</a>
</pre><p>

The macro <code>mbt</code> (``must be true'') can be used in order to add code in
order to admit function definitions in <code>:</code><code><a href="LOGIC.html">logic</a></code> mode, without paying
a cost in execution efficiency.  Examples below illustrate its intended use.<p>

Semantically, <code>(mbt x)</code> equals <code>x</code>.  However, in raw Lisp <code>(mbt x)</code>
ignores <code>x</code> entirely, and macroexpands to <code>t</code>.  ACL2's <a href="GUARD.html">guard</a>
verification mechanism ensures that the raw Lisp code is only evaluated when
appropriate, since a guard proof obligation <code>(equal x t)</code> is generated.
See <a href="VERIFY-GUARDS.html">verify-guards</a> and, for general discussion of guards, see <a href="GUARD.html">guard</a>.<p>

Also see <a href="MBE.html">mbe</a>, which stands for ``must be equal.''  Although <code>mbt</code> is more
natural in many cases, <code>mbe</code> has more general applicability.  In fact,
<code>(mbt x)</code> is essentially defined to be <code>(mbe :logic x :exec t)</code>.
<p>
We can illustrate the use of <code>mbt</code> on the following generic example, where
<code>&lt;g&gt;</code>, <code>&lt;test&gt;</code>, <code>&lt;rec-x&gt;</code>, and <code>&lt;base&gt;</code> are intended to be terms
involving only the variable <code>x</code>.

<pre>
(defun foo (x)
  (declare (xargs :guard &lt;g&gt;))
  (if &lt;test&gt;
      (foo &lt;rec-x&gt;)
    &lt;base&gt;))
</pre>

In order to admit this function, ACL2 needs to discharge the proof obligation
that <code>&lt;rec-x&gt;</code> is smaller than <code>x</code>, namely:

<pre>
(implies &lt;test&gt;
         (o&lt; (acl2-count <code>&lt;rec-x&gt;</code>)
              (acl2-count x)))
</pre>

But suppose we need to know that <code>&lt;g&gt;</code> is true in order to prove this.
Since <code>&lt;g&gt;</code> is only the <a href="GUARD.html">guard</a>, it is not part of the logical
definition of <code>foo</code>.  A solution is to add the guard to the definition of
<code>foo</code>, as follows.

<pre>
(defun foo (x)
  (declare (xargs :guard &lt;g&gt;))
  (if (mbt &lt;g&gt;)
      (if &lt;test&gt;
          (foo &lt;rec-x&gt;)
        &lt;base&gt;)
    nil))
</pre>

If we do this using <code>&lt;g&gt;</code> rather than <code>(mbt &lt;g&gt;)</code>, then evaluation of
every recursive call of <code>foo</code> will cause the evaluation of (the appropriate
instance of) <code>&lt;g&gt;</code>.  But since <code>(mbt &lt;g&gt;)</code> expands to <code>t</code> in raw Lisp,
then once we verify the guards of <code>foo</code>, the evaluations of <code>&lt;g&gt;</code> will be
avoided (except at the top level, when we check the guard before allowing
evaluation to take place in Common Lisp).<p>

Other times, the guard isn't the issue, but rather, the problem is that a
recursive call has an argument that itself is a recursive call.  For example,
suppose that <code>&lt;rec-x&gt;</code> is of the form <code>(foo &lt;expr&gt;)</code>.  There is no way we
can hope to discharge the termination proof obligation shown above.  A
standard solution is to add some version of this test:

<pre>
(mbt (o&lt; (acl2-count <code>&lt;rec-x&gt;</code>) (acl2-count x)))
</pre>

Here is a specific example based on one sent by Vernon Austel.

<pre>
(defun recurX2 (n)
  (declare (xargs :guard (and (integerp n) (&lt;= 0 n))
                  :verify-guards nil))
  (cond ((zp n) 0)
        (t (let ((call (recurX2 (1- n))))
             (if (mbt (&lt; (acl2-count call) n))
                 (recurX2 call)
               1 ;; this branch is never actually taken
               )))))<p>

(defthm recurX2-0
 (equal (recurX2 n) 0))<p>

(verify-guards recurX2)
</pre>

If you <code>(</code><code><a href="TRACE$.html">trace$</a></code><code> acl2-count)</code>, you will see that evaluation of
<code>(recurX2 2)</code> causes several calls of <code><a href="ACL2-COUNT.html">acl2-count</a></code> before the
<code><a href="VERIFY-GUARDS.html">verify-guards</a></code>.  But this evaluation does not call <code>acl2-count</code> after
the <code>verify-guards</code>, because the ACL2 evaluation mechanism uses raw Lisp to
do the evaluation, and the form <code>(mbt (&lt; (acl2-count call) n))</code>
macroexpands to <code>t</code> in Common Lisp.<p>

You may occasionally get warnings when you compile functions defined using
<code>mbt</code>.  (For commands that invoke the compiler, see <a href="COMP.html">comp</a> and
see <a href="CERTIFY-BOOK.html">certify-book</a>.)  These can be inhibited by using an <code>ignorable</code>
<code><a href="DECLARE.html">declare</a></code> form.  Here is a simple but illustrative example.  Note that
the declarations can optionally be separated into two <code><a href="DECLARE.html">declare</a></code> forms.

<pre>
(defun foo (x y)
  (declare (ignorable x)
           (xargs :guard (equal x t)))
  (and (mbt x) y))
</pre>

<br><br><br><a href="acl2-doc.html"><img src="llogo.gif"></a> <a href="acl2-doc-index.html"><img src="index.gif"></a>
</body>
</html>