File: FAILED-FORCING.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 (160 lines) | stat: -rw-r--r-- 8,016 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
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
<html>
<head><title>FAILED-FORCING.html  --  ACL2 Version 3.1</title></head>
<body text=#000000 bgcolor="#FFFFFF">
<h2>FAILED-FORCING</h2>how to deal with a proof <a href="FAILURE.html">failure</a> in a forcing round
<pre>Major Section:  <a href="MISCELLANEOUS.html">MISCELLANEOUS</a>
</pre><p>

See <a href="FORCING-ROUND.html">forcing-round</a> for a background discussion of the notion of
forcing rounds.  When a proof fails during a forcing round it means
that the ``gist'' of the proof succeeded but some ``technical
detail'' failed.  The first question you must ask yourself is
whether the <a href="FORCE.html">force</a>d goals are indeed theorems.  We discuss the
possibilities below.
<p>
If you believe the <a href="FORCE.html">force</a>d goals are theorems, you should follow the
usual methodology for ``fixing'' failed ACL2 proofs, e.g., the
identification of key lemmas and their timely and proper use as
rules.  See <a href="FAILURE.html">failure</a> and see <a href="PROOF-TREE.html">proof-tree</a>.<p>

The rules designed for the goals of forcing rounds are often just
what is needed to prove the <a href="FORCE.html">force</a>d hypothesis at the time it is
<a href="FORCE.html">force</a>d.  Thus, you may find that when the system has been ``taught''
how to prove the goals of the forcing round no forcing round is
needed.  This is intended as a feature to help structure the
discovery of the necessary rules.<p>

If a hint must be provided to prove a goal in a forcing round, the
appropriate ``goal specifier'' (the string used to identify the goal
to which the hint is to be applied) is just the text printed on the
line above the formula, e.g., <code>"[1]Subgoal *1/3''"</code>.
See <a href="GOAL-SPEC.html">goal-spec</a>.<p>

If you solve a forcing problem by giving explicit <a href="HINTS.html">hints</a> for the
goals of forcing rounds, you might consider whether you could avoid
forcing the assumption in the first place by giving those <a href="HINTS.html">hints</a> in
the appropriate places of the main proof.  This is one reason that
we print out the origins of each <a href="FORCE.html">force</a>d assumption.  An argument
against this style, however, is that an assumption might be <a href="FORCE.html">force</a>d
in hundreds of places in the main goal and proved only once in the
forcing round, so that by delaying the proof you actually save time.<p>

We now turn to the possibility that some goal in the forcing round
is not a theorem.<p>

There are two possibilities to consider.  The first is that the
original theorem has insufficient hypotheses to ensure that all the
<a href="FORCE.html">force</a>d hypotheses are in fact always true.  The ``fix'' in this case
is to amend the original conjecture so that it has adequate
hypotheses.<p>

A more difficult situation can arise and that is when the conjecture
has sufficient hypotheses but they are not present in the forcing
round goal.  This can be caused by what we call ``premature''
forcing.<p>

Because ACL2 rewrites from the inside out, it is possible that it
will <a href="FORCE.html">force</a> hypotheses while the context is insufficient to establish
them.  Consider trying to prove <code>(p x (foo x))</code>.  We first rewrite the
formula in an empty context, i.e., assuming nothing.  Thus, we
rewrite <code>(foo x)</code> in an empty context.  If rewriting <code>(foo x)</code> <a href="FORCE.html">force</a>s
anything, that <a href="FORCE.html">force</a>d assumption will have to be proved in an empty
context.  This will likely be impossible.<p>

On the other hand, suppose we did not attack <code>(foo x)</code> until after we
had expanded <code>p</code>.  We might find that the value of its second
argument, <code>(foo x)</code>, is relevant only in some cases and in those cases
we might be able to establish the hypotheses <a href="FORCE.html">force</a>d by <code>(foo x)</code>.  Our
premature forcing is thus seen to be a consequence of our ``over
eager'' rewriting.<p>

Here, just for concreteness, is an example you can try.  In this
example, <code>(foo x)</code> rewrites to <code>x</code> but has a <a href="FORCE.html">force</a>d hypothesis of
<code>(rationalp x)</code>.  <code>P</code> does a case split on that very hypothesis
and uses its second argument only when <code>x</code> is known to be rational.
Thus, the hypothesis for the <code>(foo x)</code> rewrite is satisfied.  On
the false branch of its case split, <code>p</code> simplies to <code>(p1 x)</code> which
can be proved under the assumption that <code>x</code> is not rational.<p>


<pre>
(defun p1 (x) (not (rationalp x)))
(defun p (x y)(if (rationalp x) (equal x y) (p1 x)))
(defun foo (x) x)
(defthm foo-rewrite (implies (force (rationalp x)) (equal (foo x) x)))
(in-theory (disable foo))
</pre>

The attempt then to do <code>(thm (p x (foo x)))</code> <a href="FORCE.html">force</a>s the unprovable
goal <code>(rationalp x)</code>.<p>

Since all ``formulas'' are presented to the theorem prover as single
terms with no hypotheses (e.g., since <code><a href="IMPLIES.html">implies</a></code> is a function), this
problem would occur routinely were it not for the fact that the
theorem prover expands certain ``simple'' definitions immediately
without doing anything that can cause a hypothesis to be <a href="FORCE.html">force</a>d.
See <a href="SIMPLE.html">simple</a>.  This does not solve the problem, since it is
possible to hide the propositional structure arbitrarily deeply.
For example, one could define <code>p</code>, above, recursively so that the test
that <code>x</code> is rational and the subsequent first ``real'' use of <code>y</code>
occurred arbitrarily deeply.<p>

Therefore, the problem remains: what do you do if an impossible goal
is <a href="FORCE.html">force</a>d and yet you know that the original conjecture was
adequately protected by hypotheses?<p>

One alternative is to disable forcing entirely.
See <a href="DISABLE-FORCING.html">disable-forcing</a>.  Another is to <a href="DISABLE.html">disable</a> the rule that
caused the <a href="FORCE.html">force</a>.<p>

A third alternative is to prove that the negation of the main goal
implies the <a href="FORCE.html">force</a>d hypothesis.  For example,

<pre>
(defthm not-p-implies-rationalp
  (implies (not (p x (foo x))) (rationalp x))
  :rule-classes nil)
</pre>

Observe that we make no rules from this formula.  Instead, we
merely <code>:use</code> it in the subgoal where we must establish <code>(rationalp x)</code>.

<pre>
(thm (p x (foo x))
     :hints (("Goal" :use not-p-implies-rationalp)))
</pre>

When we said, above, that <code>(p x (foo x))</code> is first rewritten in an
empty context we were misrepresenting the situation slightly.  When
we rewrite a literal we know what literal we are rewriting and we
implicitly assume it false.  This assumption is ``dangerous'' in
that it can lead us to simplify our goal to <code>nil</code> and give up -- we
have even seen people make the mistake of assuming the negation of
what they wished to prove and then via a very complicated series of
transformations convince themselves that the formula is false.
Because of this ``tail biting'' we make very weak use of the
negation of our goal.  But the use we make of it is sufficient to
establish the <a href="FORCE.html">force</a>d hypothesis above.<p>

A fourth alternative is to weaken your desired theorem so as to make
explicit the required hypotheses, e.g., to prove

<pre>
(defthm rationalp-implies-main
  (implies (rationalp x) (p x (foo x)))
  :rule-classes nil)
</pre>

This of course is unsatisfying because it is not what you
originally intended.  But all is not lost.  You can now prove your
main theorem from this one, letting the <code><a href="IMPLIES.html">implies</a></code> here provide the
necessary case split.

<pre>
(thm (p x (foo x))
     :hints (("Goal" :use rationalp-implies-main)))
</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>