1
#|-*-Lisp-*-=================================================================|#
3
#| coi: Computational Object Inference |#
5
#|===========================================================================|#
1
; Computational Object Inference
2
; Copyright (C) 2005-2014 Kookamara LLC
7
; 11410 Windermere Meadows
8
; Austin, TX 78759, USA
9
; http://www.kookamara.com/
11
; License: (An MIT/X11-style license)
13
; Permission is hereby granted, free of charge, to any person obtaining a
14
; copy of this software and associated documentation files (the "Software"),
15
; to deal in the Software without restriction, including without limitation
16
; the rights to use, copy, modify, merge, publish, distribute, sublicense,
17
; and/or sell copies of the Software, and to permit persons to whom the
18
; Software is furnished to do so, subject to the following conditions:
20
; The above copyright notice and this permission notice shall be included in
21
; all copies or substantial portions of the Software.
23
; THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24
; IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25
; FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
26
; AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27
; LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28
; FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29
; DEALINGS IN THE SOFTWARE.
9
34
(in-package "ADVISER")
10
35
(include-book "misc/symbol-btree" :dir :system)
11
36
(include-book "../symbol-fns/symbol-fns")
16
a extensible hint suggestion daemon~/
18
Adviser is a a hint computation service. When the adviser book is loaded,
19
this service is installed into the ACL2 world as a default hint. This
20
service is consulted when goals becomes stable under simplification during
21
your proof attempts. In other words, before destructor elimination,
22
generalization, and so forth are tried, the theorem prover will now first
23
consult the Adviser service and see if any hints is available. ~/
25
When the Adviser is consulted, it examines the goal that ACL2 is stuck on
26
and checks to see if it can give any suggestions. To make these
27
suggestions, Adviser consults its own database of rules. These rules are
28
kept in a new ACL2 ~il[table] that Adviser manages, and efficiently stored
29
using the btree library that comes with ACL2 (see
30
books/misc/symbol-btree.lisp).
32
This database oriented approach has two advantages. First, users can extend
33
Adviser's knowledge by adding new rules, without having to understand the
34
tricky details of how computed hints work. (These rules are added through a
35
new event called ~il[defadvice], which intentionally looks a lot like
36
defthm). Second, by using a database of triggers, a single pass over each
37
goal is sufficient to determine if advice is necessary. In contrast, if
38
everyone created their own computed hints, we would have multiple passes
41
~l[defadvice] for information on adding rules to Adviser.")
46
adds a rule to the Adviser database~/
37
(include-book "xdoc/top" :dir :system)
38
(defmacro defxdoc (&rest args)
39
`(acl2::defxdoc ,@args))
41
; The following legacy doc strings were replaced Nov. 2014 by
42
; auto-generated defxdoc forms below.
45
; ":Doc-Section Adviser
47
; a extensible hint suggestion daemon~/
49
; Adviser is a a hint computation service. When the adviser book is loaded,
50
; this service is installed into the ACL2 world as a default hint. This
51
; service is consulted when goals becomes stable under simplification during
52
; your proof attempts. In other words, before destructor elimination,
53
; generalization, and so forth are tried, the theorem prover will now first
54
; consult the Adviser service and see if any hints is available. ~/
56
; When the Adviser is consulted, it examines the goal that ACL2 is stuck on
57
; and checks to see if it can give any suggestions. To make these
58
; suggestions, Adviser consults its own database of rules. These rules are
59
; kept in a new ACL2 ~il[table] that Adviser manages, and efficiently stored
60
; using the btree library that comes with ACL2 (see
61
; books/misc/symbol-btree.lisp).
63
; This database oriented approach has two advantages. First, users can extend
64
; Adviser's knowledge by adding new rules, without having to understand the
65
; tricky details of how computed hints work. (These rules are added through a
66
; new event called ~il[adviser::defadvice], which intentionally looks a lot
67
; like defthm). Second, by using a database of triggers, a single pass over
68
; each goal is sufficient to determine if advice is necessary. In contrast,
69
; if everyone created their own computed hints, we would have multiple passes
72
; ~l[adviser::defadvice] for information on adding rules to Adviser.")
75
; ":Doc-Section Adviser
77
; adds a rule to the Adviser database~/
81
; (defadvice rule-name term
82
; :rule-classes rule-classes)
85
; where ~c[name] is a new symbolic name ~l[name], ~c[term] is a term alleged to
86
; be a useful piece of advice, and ~c[rule-classes] describe the type of advice
87
; being added and when to suggest hints of this nature.~/
89
; When Adviser is first loaded, no rules are installed in its database, so it
90
; will never suggest any hints. To make Adviser useful, rules must be added to
91
; it using defadvice. In principle, many types of advice could be added to the
92
; Adviser service, and in the future other classes of advice might be added.
93
; But, for now, the only understood rule class is :pick-a-point.
95
; ~l[adviser::pick-a-point] for documentation and examples about :pick-a-point
99
; ":Doc-Section Adviser
101
; make some :pick-a-point rules~/
105
; (defadvice subbag-by-multiplicity
106
; (implies (bag-hyps)
107
; (subbagp (subbag) (superbag))))
110
; I described how the pick-a-point method can be useful for proving subsets in
111
; the 2004 ACL2 Workshop Paper: Finite Set Theory based on Fully Ordered Lists.
112
; Essentially, the idea is to you should be able to prove (subset x y) by just
113
; knowing that forall a, (in a x) implies (in a y). Since writing that paper,
114
; I have found the pick a point method to be widely useful in other contexts
115
; that involve extending a predicate to some data structure.
117
; Often we will have some simple predicate, say ~c[integerp], which we will
118
; want to extend over some datastructure, say a list. The result is a new,
119
; recursively defined predicate, say ~c[all-integerp]. Of course, it should be
120
; obvious that if every member of the list satisfies ~c[integerp], then the
121
; entire list satisfies ~c[all-integerp]. But, we can't write a :rewrite rule
125
; (equal (all-integerp x)
126
; (forall a (implies (member a x) (integerp a))))
129
; Because all of the variables in our :rewrite rules must be universally
130
; quantified. The :pick-a-point rules in Adviser are designed to make exactly
131
; this kind of reduction. As an example, I'll now elaborate on how to set up
132
; such a reduction for ~c[all-integerp]. You will find that many other ideas,
133
; such as subsets, subtree, subbag relations, and so forth, are basically just
134
; copies of this idea.
136
; We begin with our definition of all-integerp. (We do not use integer-listp
137
; because it requires its argument to be a true-listp.)
140
; (defun all-integerp (x)
142
; (and (integerp (car x))
143
; (all-integerp (cdr x)))
147
; Our first task is to write our ``forall'' statement as a constraint theorem
148
; about encapsulated functions. Becuase we are quantifying over all ``a'', it
149
; will be a variable in this constrained theorem. However, since ``x'' is not
150
; being quantified, we will create a constrained function for it. For reasons
151
; we will explain later, we will also have one more constrianed function called
152
; ``hyps''. In all, we come up with the following encapsulate:
156
; (((intlist-hyps) => *)
157
; ((intlist-list) => *))
158
; (local (defun intlist-hyps () nil))
159
; (local (defun intlist-list () nil))
160
; (defthm intlist-constraint
161
; (implies (and (intlist-hyps)
162
; (member intlist-element (intlist-list)))
163
; (integerp intlist-element))
164
; :rule-classes nil))
167
; Our next goal is to prove that, given this constraint, it must be the case
168
; that (integer-listp (intlist-list)) is true. The proof is not entirely
169
; straightforward, but follows the same script each time. Basically, we first
170
; set up a ``badguy'' function that will go through and find an element that
171
; violates our constraint if one exists. We show that the badguy finds such
172
; an element whenever ``all-integerp'' is not satisifed. Then, we just use
173
; the instance of our constraint to show that all-integerp must be true for
177
; (local (defun badguy (x)
180
; (if (integerp (car x))
184
; (local (defthm badguy-works
185
; (implies (not (all-integerp x))
186
; (and (member (badguy x) x)
187
; (not (integerp (badguy x)))))))
189
; (defthm intlist-by-membership-driver
190
; (implies (intlist-hyps)
191
; (all-integerp (intlist-list)))
194
; :use (:instance intlist-constraint
195
; (intlist-element (badguy (intlist-list)))))))
198
; At this point, we have essentially shown ACL2 that ``all-integerp`` can
199
; be shown as long as we can show our constraint is true. The missing step
200
; is for ACL2 to actually try this approach for us. But we can't write a
201
; rewrite rule that says ``try to functionally instantiate this theorem
202
; whenever you are trying to prove (all-integerp x).''
204
; That's where Adviser comes in. We just give it the following rule:
207
; (ADVISER::defadvice intlist-by-membership
208
; (implies (intlist-hyps)
209
; (all-integerp (intlist-list)))
210
; :rule-classes (:pick-a-point :driver intlist-by-membership-driver))
213
; Because we used defadvice, rather than defthm, this rule is for Adviser
214
; to add to its database. Adviser will set up a new trigger for
215
; all-integerp, and whenever it sees that trigger as the target that we
216
; are trying to prove, it will functionally instantiate the driver theorem.
217
; We can now conduct membership based proofs of all-integerp.
219
; For example, in the following script we can prove that (all-integerp (rev x))
220
; exactly when (all-integerp x) without inducting over either function,
221
; because we can just consider membership.
224
; (defthm equal-of-booleans-rewrite
225
; (implies (and (booleanp x)
229
; :rule-classes ((:rewrite :backchain-limit-lst 0)))
231
; (defthm member-of-all-integerp-1
232
; (implies (and (member a x)
236
; (defthm member-of-all-integerp-2
237
; (implies (and (all-integerp x)
238
; (not (integerp a)))
239
; (not (member a x))))
241
; (in-theory (disable all-integerp))
246
; (append (rev (cdr x))
249
; (defthm member-of-rev
250
; (iff (member a (rev x))
252
; :hints((\"Goal\" :in-theory (enable rev))))
257
; (local (defthm lemma1
258
; (implies (all-integerp x)
259
; (all-integerp (rev x)))))
261
; (local (defthm lemma2
262
; (implies (all-integerp (rev x))
264
; :hints((\"Subgoal 1\" :use (:instance member-of-all-integerp-1
265
; (a intlist-element)
268
; (defthm all-integerp-of-rev
269
; (equal (all-integerp (rev x))
274
(defxdoc adviser::adviser
275
:parents (adviser::adviser)
276
:short "A extensible hint suggestion daemon"
277
:long "<p>Adviser is a a hint computation service. When the adviser book is
278
loaded, this service is installed into the ACL2 world as a default hint. This
279
service is consulted when goals becomes stable under simplification during
280
your proof attempts. In other words, before destructor elimination,
281
generalization, and so forth are tried, the theorem prover will now first
282
consult the Adviser service and see if any hints is available.</p>
284
<p>When the Adviser is consulted, it examines the goal that ACL2 is stuck on
285
and checks to see if it can give any suggestions. To make these suggestions,
286
Adviser consults its own database of rules. These rules are kept in a new
287
ACL2 @(see table) that Adviser manages, and efficiently stored using the btree
288
library that comes with ACL2 (see books/misc/symbol-btree.lisp).</p>
290
<p>This database oriented approach has two advantages. First, users can
291
extend Adviser's knowledge by adding new rules, without having to understand
292
the tricky details of how computed hints work. (These rules are added through
293
a new event called @(see adviser::defadvice), which intentionally looks a lot
294
like defthm). Second, by using a database of triggers, a single pass over
295
each goal is sufficient to determine if advice is necessary. In contrast, if
296
everyone created their own computed hints, we would have multiple passes over
299
<p>See @(see adviser::defadvice) for information on adding rules to
302
(defxdoc adviser::defadvice
303
:parents (adviser::adviser)
304
:short "Adds a rule to the Adviser database"
50
(defadvice rule-name term
307
(defadvice rule-name term
51
308
:rule-classes rule-classes)
54
where ~c[name] is a new symbolic name ~l[name], ~c[term] is a term alleged to
55
be a useful piece of advice, and ~c[rule-classes] describe the type of advice
56
being added and when to suggest hints of this nature.~/
58
When Adviser is first loaded, no rules are installed in its database, so it
59
will never suggest any hints. To make Adviser useful, rules must be added to
60
it using defadvice. In principle, many types of advice could be added to the
61
Adviser service, and in the future other classes of advice might be added.
62
But, for now, the only understood rule class is :pick-a-point.
64
~l[pick-a-point] for documentation and examples about :pick-a-point rules.")
69
make some :pick-a-point rules~/
311
<p>where @('name') is a new symbolic name See @(see name), @('term') is a term
312
alleged to be a useful piece of advice, and @('rule-classes') describe the
313
type of advice being added and when to suggest hints of this nature.</p>
315
<p>When Adviser is first loaded, no rules are installed in its database, so it
316
will never suggest any hints. To make Adviser useful, rules must be added to
317
it using defadvice. In principle, many types of advice could be added to the
318
Adviser service, and in the future other classes of advice might be added.
319
But, for now, the only understood rule class is :pick-a-point.</p>
321
<p>See @(see adviser::pick-a-point) for documentation and examples about
322
:pick-a-point rules.</p>")
324
(defxdoc adviser::pick-a-point
325
:parents (adviser::adviser)
326
:short "Make some :pick-a-point rules"
73
329
(defadvice subbag-by-multiplicity
74
330
(implies (bag-hyps)
75
331
(subbagp (subbag) (superbag))))
78
I described how the pick-a-point method can be useful for proving subsets in
79
the 2004 ACL2 Workshop Paper: Finite Set Theory based on Fully Ordered Lists.
80
Essentially, the idea is to you should be able to prove (subset x y) by just
81
knowing that forall a, (in a x) implies (in a y). Since writing that paper,
82
I have found the pick a point method to be widely useful in other contexts
83
that involve extending a predicate to some data structure.
85
Often we will have some simple predicate, say ~c[integerp], which we will
86
want to extend over some datastructure, say a list. The result is a new,
87
recursively defined predicate, say ~c[all-integerp]. Of course, it should be
88
obvious that if every member of the list satisfies ~c[integerp], then the
89
entire list satisfies ~c[all-integerp]. But, we can't write a :rewrite rule
334
<p>I described how the pick-a-point method can be useful for proving subsets
335
in the 2004 ACL2 Workshop Paper: Finite Set Theory based on Fully Ordered
336
Lists. Essentially, the idea is to you should be able to prove (subset x y)
337
by just knowing that forall a, (in a x) implies (in a y). Since writing that
338
paper, I have found the pick a point method to be widely useful in other
339
contexts that involve extending a predicate to some data structure.</p>
341
<p>Often we will have some simple predicate, say @('integerp'), which we will
342
want to extend over some datastructure, say a list. The result is a new,
343
recursively defined predicate, say @('all-integerp'). Of course, it should be
344
obvious that if every member of the list satisfies @('integerp'), then the
345
entire list satisfies @('all-integerp'). But, we can't write a :rewrite rule
93
349
(equal (all-integerp x)
94
350
(forall a (implies (member a x) (integerp a))))
97
Because all of the variables in our :rewrite rules must be universally
98
quantified. The :pick-a-point rules in Adviser are designed to make exactly
99
this kind of reduction. As an example, I'll now elaborate on how to set up
100
such a reduction for ~c[all-integerp]. You will find that many other ideas,
101
such as subsets, subtree, subbag relations, and so forth, are basically just
104
We begin with our definition of all-integerp. (We do not use integer-listp
105
because it requires its argument to be a true-listp.)
353
<p>Because all of the variables in our :rewrite rules must be universally
354
quantified. The :pick-a-point rules in Adviser are designed to make exactly
355
this kind of reduction. As an example, I'll now elaborate on how to set up
356
such a reduction for @('all-integerp'). You will find that many other ideas,
357
such as subsets, subtree, subbag relations, and so forth, are basically just
358
copies of this idea.</p>
360
<p>We begin with our definition of all-integerp. (We do not use integer-listp
361
because it requires its argument to be a true-listp.)</p>
108
364
(defun all-integerp (x)
110
366
(and (integerp (car x))
111
367
(all-integerp (cdr x)))
115
Our first task is to write our ``forall'' statement as a constraint theorem
116
about encapsulated functions. Becuase we are quantifying over all ``a'', it
117
will be a variable in this constrained theorem. However, since ``x'' is not
118
being quantified, we will create a constrained function for it. For reasons
119
we will explain later, we will also have one more constrianed function called
120
``hyps''. In all, we come up with the following encapsulate:
371
<p>Our first task is to write our ``forall'' statement as a constraint theorem
372
about encapsulated functions. Becuase we are quantifying over all ``a'', it
373
will be a variable in this constrained theorem. However, since ``x'' is not
374
being quantified, we will create a constrained function for it. For reasons
375
we will explain later, we will also have one more constrianed function called
376
``hyps''. In all, we come up with the following encapsulate:</p>
124
380
(((intlist-hyps) => *)
125
381
((intlist-list) => *))