author | oheimb |
Tue, 23 Apr 1996 16:58:21 +0200 | |
changeset 1672 | 2c109cd2fdd0 |
parent 1387 | 9bcad9c22fd4 |
child 1860 | 71bfeecfa96c |
permissions | -rw-r--r-- |
104 | 1 |
%% $Id$ |
2 |
\chapter{Simplification} \label{simp-chap} |
|
3 |
\index{simplification|(} |
|
4 |
||
5 |
This chapter describes Isabelle's generic simplification package, which |
|
323 | 6 |
provides a suite of simplification tactics. It performs conditional and |
7 |
unconditional rewriting and uses contextual information (`local |
|
8 |
assumptions'). It provides a few general hooks, which can provide |
|
9 |
automatic case splits during rewriting, for example. The simplifier is set |
|
10 |
up for many of Isabelle's logics: {\tt FOL}, {\tt ZF}, {\tt LCF} and {\tt |
|
11 |
HOL}. |
|
104 | 12 |
|
13 |
||
286 | 14 |
\section{Simplification sets}\index{simplification sets} |
104 | 15 |
The simplification tactics are controlled by {\bf simpsets}. These consist |
16 |
of five components: rewrite rules, congruence rules, the subgoaler, the |
|
323 | 17 |
solver and the looper. The simplifier should be set up with sensible |
18 |
defaults so that most simplifier calls specify only rewrite rules. |
|
19 |
Experienced users can exploit the other components to streamline proofs. |
|
20 |
||
104 | 21 |
|
332 | 22 |
\subsection{Rewrite rules} |
23 |
\index{rewrite rules|(} |
|
323 | 24 |
Rewrite rules are theorems expressing some form of equality: |
25 |
\begin{eqnarray*} |
|
26 |
Suc(\Var{m}) + \Var{n} &=& \Var{m} + Suc(\Var{n}) \\ |
|
27 |
\Var{P}\conj\Var{P} &\bimp& \Var{P} \\ |
|
714 | 28 |
\Var{A} \un \Var{B} &\equiv& \{x.x\in \Var{A} \disj x\in \Var{B}\} |
323 | 29 |
\end{eqnarray*} |
30 |
{\bf Conditional} rewrites such as $\Var{m}<\Var{n} \Imp \Var{m}/\Var{n} = |
|
31 |
0$ are permitted; the conditions can be arbitrary terms. The infix |
|
32 |
operation \ttindex{addsimps} adds new rewrite rules, while |
|
33 |
\ttindex{delsimps} deletes rewrite rules from a simpset. |
|
104 | 34 |
|
323 | 35 |
Internally, all rewrite rules are translated into meta-equalities, theorems |
36 |
with conclusion $lhs \equiv rhs$. Each simpset contains a function for |
|
37 |
extracting equalities from arbitrary theorems. For example, |
|
38 |
$\neg(\Var{x}\in \{\})$ could be turned into $\Var{x}\in \{\} \equiv |
|
39 |
False$. This function can be installed using \ttindex{setmksimps} but only |
|
40 |
the definer of a logic should need to do this; see \S\ref{sec:setmksimps}. |
|
41 |
The function processes theorems added by \ttindex{addsimps} as well as |
|
42 |
local assumptions. |
|
104 | 43 |
|
44 |
||
332 | 45 |
\begin{warn} |
1101 | 46 |
The simplifier will accept all standard rewrite rules: those |
47 |
where all unknowns are of base type. Hence ${\Var{i}+(\Var{j}+\Var{k})} = |
|
714 | 48 |
{(\Var{i}+\Var{j})+\Var{k}}$ is ok. |
49 |
||
50 |
It will also deal gracefully with all rules whose left-hand sides are |
|
51 |
so-called {\em higher-order patterns}~\cite{Nipkow-LICS-93}. These are terms |
|
52 |
in $\beta$-normal form (this will always be the case unless you have done |
|
53 |
something strange) where each occurrence of an unknown is of the form |
|
54 |
$\Var{F}(x@1,\dots,x@n)$, where the $x@i$ are distinct bound variables. |
|
55 |
Hence $(\forall x.\Var{P}(x) \land \Var{Q}(x)) \bimp (\forall x.\Var{P}(x)) |
|
56 |
\land (\forall x.\Var{Q}(x))$ is also ok, in both directions. |
|
57 |
||
58 |
In some rare cases the rewriter will even deal with quite general rules: for |
|
59 |
example ${\Var{f}(\Var{x})\in range(\Var{f})} = True$ rewrites $g(a) \in |
|
60 |
range(g)$ to $True$, but will fail to match $g(h(b)) \in range(\lambda |
|
61 |
x.g(h(x)))$. However, you can replace the offending subterms (in our case |
|
62 |
$\Var{f}(\Var{x})$, which is not a pattern) by adding new variables and |
|
63 |
conditions: $\Var{y} = \Var{f}(\Var{x}) \Imp \Var{y}\in range(\Var{f}) |
|
64 |
= True$ is acceptable as a conditional rewrite rule since conditions can |
|
65 |
be arbitrary terms. |
|
66 |
||
67 |
There is no restriction on the form of the right-hand sides. |
|
104 | 68 |
\end{warn} |
69 |
||
332 | 70 |
\index{rewrite rules|)} |
71 |
||
72 |
\subsection{*Congruence rules}\index{congruence rules} |
|
104 | 73 |
Congruence rules are meta-equalities of the form |
74 |
\[ \List{\dots} \Imp |
|
75 |
f(\Var{x@1},\ldots,\Var{x@n}) \equiv f(\Var{y@1},\ldots,\Var{y@n}). |
|
76 |
\] |
|
323 | 77 |
This governs the simplification of the arguments of~$f$. For |
104 | 78 |
example, some arguments can be simplified under additional assumptions: |
79 |
\[ \List{\Var{P@1} \bimp \Var{Q@1};\; \Var{Q@1} \Imp \Var{P@2} \bimp \Var{Q@2}} |
|
80 |
\Imp (\Var{P@1} \imp \Var{P@2}) \equiv (\Var{Q@1} \imp \Var{Q@2}) |
|
81 |
\] |
|
323 | 82 |
Given this rule, the simplifier assumes $Q@1$ and extracts rewrite rules |
83 |
from it when simplifying~$P@2$. Such local assumptions are effective for |
|
698
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
84 |
rewriting formulae such as $x=0\imp y+x=y$. The local assumptions are also |
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
85 |
provided as theorems to the solver; see page~\pageref{sec:simp-solver} below. |
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
86 |
|
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
87 |
Here are some more examples. The congruence rule for bounded quantifiers |
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
88 |
also supplies contextual information, this time about the bound variable: |
286 | 89 |
\begin{eqnarray*} |
90 |
&&\List{\Var{A}=\Var{B};\; |
|
91 |
\Forall x. x\in \Var{B} \Imp \Var{P}(x) = \Var{Q}(x)} \Imp{} \\ |
|
92 |
&&\qquad\qquad |
|
93 |
(\forall x\in \Var{A}.\Var{P}(x)) = (\forall x\in \Var{B}.\Var{Q}(x)) |
|
94 |
\end{eqnarray*} |
|
323 | 95 |
The congruence rule for conditional expressions can supply contextual |
96 |
information for simplifying the arms: |
|
104 | 97 |
\[ \List{\Var{p}=\Var{q};~ \Var{q} \Imp \Var{a}=\Var{c};~ |
98 |
\neg\Var{q} \Imp \Var{b}=\Var{d}} \Imp |
|
99 |
if(\Var{p},\Var{a},\Var{b}) \equiv if(\Var{q},\Var{c},\Var{d}) |
|
100 |
\] |
|
698
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
101 |
A congruence rule can also {\em prevent\/} simplification of some arguments. |
104 | 102 |
Here is an alternative congruence rule for conditional expressions: |
103 |
\[ \Var{p}=\Var{q} \Imp |
|
104 |
if(\Var{p},\Var{a},\Var{b}) \equiv if(\Var{q},\Var{a},\Var{b}) |
|
105 |
\] |
|
106 |
Only the first argument is simplified; the others remain unchanged. |
|
107 |
This can make simplification much faster, but may require an extra case split |
|
108 |
to prove the goal. |
|
109 |
||
286 | 110 |
Congruence rules are added using \ttindexbold{addeqcongs}. Their conclusion |
104 | 111 |
must be a meta-equality, as in the examples above. It is more |
112 |
natural to derive the rules with object-logic equality, for example |
|
113 |
\[ \List{\Var{P@1} \bimp \Var{Q@1};\; \Var{Q@1} \Imp \Var{P@2} \bimp \Var{Q@2}} |
|
114 |
\Imp (\Var{P@1} \imp \Var{P@2}) \bimp (\Var{Q@1} \imp \Var{Q@2}), |
|
115 |
\] |
|
286 | 116 |
Each object-logic should define an operator called \ttindex{addcongs} that |
117 |
expects object-equalities and translates them into meta-equalities. |
|
104 | 118 |
|
323 | 119 |
\subsection{*The subgoaler} |
104 | 120 |
The subgoaler is the tactic used to solve subgoals arising out of |
121 |
conditional rewrite rules or congruence rules. The default should be |
|
122 |
simplification itself. Occasionally this strategy needs to be changed. For |
|
123 |
example, if the premise of a conditional rule is an instance of its |
|
124 |
conclusion, as in $Suc(\Var{m}) < \Var{n} \Imp \Var{m} < \Var{n}$, the |
|
125 |
default strategy could loop. |
|
126 |
||
127 |
The subgoaler can be set explicitly with \ttindex{setsubgoaler}. For |
|
128 |
example, the subgoaler |
|
129 |
\begin{ttbox} |
|
332 | 130 |
fun subgoal_tac ss = assume_tac ORELSE' |
131 |
resolve_tac (prems_of_ss ss) ORELSE' |
|
104 | 132 |
asm_simp_tac ss; |
133 |
\end{ttbox} |
|
332 | 134 |
tries to solve the subgoal by assumption or with one of the premises, calling |
104 | 135 |
simplification only if that fails; here {\tt prems_of_ss} extracts the |
136 |
current premises from a simpset. |
|
137 |
||
698
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
138 |
\subsection{*The solver}\label{sec:simp-solver} |
286 | 139 |
The solver is a tactic that attempts to solve a subgoal after |
140 |
simplification. Typically it just proves trivial subgoals such as {\tt |
|
323 | 141 |
True} and $t=t$. It could use sophisticated means such as {\tt |
142 |
fast_tac}, though that could make simplification expensive. The solver |
|
143 |
is set using \ttindex{setsolver}. |
|
286 | 144 |
|
323 | 145 |
Rewriting does not instantiate unknowns. For example, rewriting cannot |
146 |
prove $a\in \Var{A}$ since this requires instantiating~$\Var{A}$. The |
|
147 |
solver, however, is an arbitrary tactic and may instantiate unknowns as it |
|
148 |
pleases. This is the only way the simplifier can handle a conditional |
|
149 |
rewrite rule whose condition contains extra variables. |
|
150 |
||
151 |
\index{assumptions!in simplification} |
|
286 | 152 |
The tactic is presented with the full goal, including the asssumptions. |
153 |
Hence it can use those assumptions (say by calling {\tt assume_tac}) even |
|
154 |
inside {\tt simp_tac}, which otherwise does not use assumptions. The |
|
155 |
solver is also supplied a list of theorems, namely assumptions that hold in |
|
156 |
the local context. |
|
104 | 157 |
|
323 | 158 |
The subgoaler is also used to solve the premises of congruence rules, which |
159 |
are usually of the form $s = \Var{x}$, where $s$ needs to be simplified and |
|
160 |
$\Var{x}$ needs to be instantiated with the result. Hence the subgoaler |
|
161 |
should call the simplifier at some point. The simplifier will then call the |
|
162 |
solver, which must therefore be prepared to solve goals of the form $t = |
|
163 |
\Var{x}$, usually by reflexivity. In particular, reflexivity should be |
|
164 |
tried before any of the fancy tactics like {\tt fast_tac}. |
|
165 |
||
166 |
It may even happen that, due to simplification, the subgoal is no longer an |
|
167 |
equality. For example $False \bimp \Var{Q}$ could be rewritten to |
|
168 |
$\neg\Var{Q}$. To cover this case, the solver could try resolving with the |
|
169 |
theorem $\neg False$. |
|
104 | 170 |
|
171 |
\begin{warn} |
|
172 |
If the simplifier aborts with the message {\tt Failed congruence proof!}, |
|
323 | 173 |
then the subgoaler or solver has failed to prove a premise of a |
698
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
174 |
congruence rule. This should never occur; it indicates that some |
23734672dc12
updated discussion of congruence rules in first section
lcp
parents:
332
diff
changeset
|
175 |
congruence rule, or possibly the subgoaler or solver, is faulty. |
104 | 176 |
\end{warn} |
177 |
||
323 | 178 |
|
179 |
\subsection{*The looper} |
|
104 | 180 |
The looper is a tactic that is applied after simplification, in case the |
181 |
solver failed to solve the simplified goal. If the looper succeeds, the |
|
182 |
simplification process is started all over again. Each of the subgoals |
|
183 |
generated by the looper is attacked in turn, in reverse order. A |
|
184 |
typical looper is case splitting: the expansion of a conditional. Another |
|
185 |
possibility is to apply an elimination rule on the assumptions. More |
|
186 |
adventurous loopers could start an induction. The looper is set with |
|
187 |
\ttindex{setloop}. |
|
188 |
||
189 |
||
190 |
\begin{figure} |
|
323 | 191 |
\index{*simpset ML type} |
192 |
\index{*simp_tac} |
|
193 |
\index{*asm_simp_tac} |
|
194 |
\index{*asm_full_simp_tac} |
|
195 |
\index{*addeqcongs} |
|
196 |
\index{*addsimps} |
|
197 |
\index{*delsimps} |
|
198 |
\index{*empty_ss} |
|
199 |
\index{*merge_ss} |
|
200 |
\index{*setsubgoaler} |
|
201 |
\index{*setsolver} |
|
202 |
\index{*setloop} |
|
203 |
\index{*setmksimps} |
|
204 |
\index{*prems_of_ss} |
|
205 |
\index{*rep_ss} |
|
104 | 206 |
\begin{ttbox} |
207 |
infix addsimps addeqcongs delsimps |
|
208 |
setsubgoaler setsolver setloop setmksimps; |
|
209 |
||
210 |
signature SIMPLIFIER = |
|
211 |
sig |
|
212 |
type simpset |
|
213 |
val simp_tac: simpset -> int -> tactic |
|
214 |
val asm_simp_tac: simpset -> int -> tactic |
|
133 | 215 |
val asm_full_simp_tac: simpset -> int -> tactic\smallskip |
216 |
val addeqcongs: simpset * thm list -> simpset |
|
217 |
val addsimps: simpset * thm list -> simpset |
|
218 |
val delsimps: simpset * thm list -> simpset |
|
104 | 219 |
val empty_ss: simpset |
220 |
val merge_ss: simpset * simpset -> simpset |
|
221 |
val setsubgoaler: simpset * (simpset -> int -> tactic) -> simpset |
|
222 |
val setsolver: simpset * (thm list -> int -> tactic) -> simpset |
|
223 |
val setloop: simpset * (int -> tactic) -> simpset |
|
224 |
val setmksimps: simpset * (thm -> thm list) -> simpset |
|
225 |
val prems_of_ss: simpset -> thm list |
|
226 |
val rep_ss: simpset -> \{simps: thm list, congs: thm list\} |
|
227 |
end; |
|
228 |
\end{ttbox} |
|
323 | 229 |
\caption{The simplifier primitives} \label{SIMPLIFIER} |
104 | 230 |
\end{figure} |
231 |
||
232 |
||
233 |
\section{The simplification tactics} \label{simp-tactics} |
|
323 | 234 |
\index{simplification!tactics} |
235 |
\index{tactics!simplification} |
|
104 | 236 |
|
237 |
The actual simplification work is performed by the following tactics. The |
|
238 |
rewriting strategy is strictly bottom up, except for congruence rules, which |
|
239 |
are applied while descending into a term. Conditions in conditional rewrite |
|
240 |
rules are solved recursively before the rewrite rule is applied. |
|
241 |
||
242 |
There are three basic simplification tactics: |
|
323 | 243 |
\begin{ttdescription} |
104 | 244 |
\item[\ttindexbold{simp_tac} $ss$ $i$] simplifies subgoal~$i$ using the rules |
245 |
in~$ss$. It may solve the subgoal completely if it has become trivial, |
|
246 |
using the solver. |
|
247 |
||
323 | 248 |
\item[\ttindexbold{asm_simp_tac}]\index{assumptions!in simplification} |
249 |
is like \verb$simp_tac$, but extracts additional rewrite rules from the |
|
250 |
assumptions. |
|
104 | 251 |
|
332 | 252 |
\item[\ttindexbold{asm_full_simp_tac}] |
253 |
is like \verb$asm_simp_tac$, but also simplifies the assumptions one by |
|
254 |
one. Working from left to right, it uses each assumption in the |
|
255 |
simplification of those following. |
|
323 | 256 |
\end{ttdescription} |
1213 | 257 |
\begin{warn} |
258 |
Since \verb$asm_full_simp_tac$ works from left to right, it sometimes |
|
259 |
misses opportunities for simplification: given the subgoal |
|
260 |
\begin{ttbox} |
|
261 |
{\out [| P(f(a)); f(a) = t |] ==> ...} |
|
262 |
\end{ttbox} |
|
263 |
\verb$asm_full_simp_tac$ will not simplify the first assumption using the |
|
264 |
second but will leave the assumptions unchanged. See |
|
265 |
\S\ref{sec:reordering-asms} for ways around this problem. |
|
266 |
\end{warn} |
|
104 | 267 |
Using the simplifier effectively may take a bit of experimentation. The |
268 |
tactics can be traced with the ML command \verb$trace_simp := true$. To |
|
269 |
remind yourself of what is in a simpset, use the function \verb$rep_ss$ to |
|
270 |
return its simplification and congruence rules. |
|
271 |
||
286 | 272 |
\section{Examples using the simplifier} |
323 | 273 |
\index{examples!of simplification} |
104 | 274 |
Assume we are working within {\tt FOL} and that |
323 | 275 |
\begin{ttdescription} |
276 |
\item[Nat.thy] |
|
277 |
is a theory including the constants $0$, $Suc$ and $+$, |
|
278 |
\item[add_0] |
|
279 |
is the rewrite rule $0+\Var{n} = \Var{n}$, |
|
280 |
\item[add_Suc] |
|
281 |
is the rewrite rule $Suc(\Var{m})+\Var{n} = Suc(\Var{m}+\Var{n})$, |
|
282 |
\item[induct] |
|
283 |
is the induction rule $\List{\Var{P}(0);\; \Forall x. \Var{P}(x)\Imp |
|
284 |
\Var{P}(Suc(x))} \Imp \Var{P}(\Var{n})$. |
|
285 |
\item[FOL_ss] |
|
286 |
is a basic simpset for {\tt FOL}.% |
|
332 | 287 |
\footnote{These examples reside on the file {\tt FOL/ex/Nat.ML}.} |
323 | 288 |
\end{ttdescription} |
104 | 289 |
|
290 |
We create a simpset for natural numbers by extending~{\tt FOL_ss}: |
|
291 |
\begin{ttbox} |
|
292 |
val add_ss = FOL_ss addsimps [add_0, add_Suc]; |
|
293 |
\end{ttbox} |
|
323 | 294 |
|
295 |
\subsection{A trivial example} |
|
286 | 296 |
Proofs by induction typically involve simplification. Here is a proof |
297 |
that~0 is a right identity: |
|
104 | 298 |
\begin{ttbox} |
299 |
goal Nat.thy "m+0 = m"; |
|
300 |
{\out Level 0} |
|
301 |
{\out m + 0 = m} |
|
302 |
{\out 1. m + 0 = m} |
|
286 | 303 |
\end{ttbox} |
304 |
The first step is to perform induction on the variable~$m$. This returns a |
|
305 |
base case and inductive step as two subgoals: |
|
306 |
\begin{ttbox} |
|
104 | 307 |
by (res_inst_tac [("n","m")] induct 1); |
308 |
{\out Level 1} |
|
309 |
{\out m + 0 = m} |
|
310 |
{\out 1. 0 + 0 = 0} |
|
311 |
{\out 2. !!x. x + 0 = x ==> Suc(x) + 0 = Suc(x)} |
|
312 |
\end{ttbox} |
|
286 | 313 |
Simplification solves the first subgoal trivially: |
104 | 314 |
\begin{ttbox} |
315 |
by (simp_tac add_ss 1); |
|
316 |
{\out Level 2} |
|
317 |
{\out m + 0 = m} |
|
318 |
{\out 1. !!x. x + 0 = x ==> Suc(x) + 0 = Suc(x)} |
|
319 |
\end{ttbox} |
|
320 |
The remaining subgoal requires \ttindex{asm_simp_tac} in order to use the |
|
321 |
induction hypothesis as a rewrite rule: |
|
322 |
\begin{ttbox} |
|
323 |
by (asm_simp_tac add_ss 1); |
|
324 |
{\out Level 3} |
|
325 |
{\out m + 0 = m} |
|
326 |
{\out No subgoals!} |
|
327 |
\end{ttbox} |
|
328 |
||
323 | 329 |
\subsection{An example of tracing} |
330 |
Let us prove a similar result involving more complex terms. The two |
|
331 |
equations together can be used to prove that addition is commutative. |
|
104 | 332 |
\begin{ttbox} |
333 |
goal Nat.thy "m+Suc(n) = Suc(m+n)"; |
|
334 |
{\out Level 0} |
|
335 |
{\out m + Suc(n) = Suc(m + n)} |
|
336 |
{\out 1. m + Suc(n) = Suc(m + n)} |
|
286 | 337 |
\end{ttbox} |
338 |
We again perform induction on~$m$ and get two subgoals: |
|
339 |
\begin{ttbox} |
|
104 | 340 |
by (res_inst_tac [("n","m")] induct 1); |
341 |
{\out Level 1} |
|
342 |
{\out m + Suc(n) = Suc(m + n)} |
|
343 |
{\out 1. 0 + Suc(n) = Suc(0 + n)} |
|
286 | 344 |
{\out 2. !!x. x + Suc(n) = Suc(x + n) ==>} |
345 |
{\out Suc(x) + Suc(n) = Suc(Suc(x) + n)} |
|
346 |
\end{ttbox} |
|
347 |
Simplification solves the first subgoal, this time rewriting two |
|
348 |
occurrences of~0: |
|
349 |
\begin{ttbox} |
|
104 | 350 |
by (simp_tac add_ss 1); |
351 |
{\out Level 2} |
|
352 |
{\out m + Suc(n) = Suc(m + n)} |
|
286 | 353 |
{\out 1. !!x. x + Suc(n) = Suc(x + n) ==>} |
354 |
{\out Suc(x) + Suc(n) = Suc(Suc(x) + n)} |
|
104 | 355 |
\end{ttbox} |
356 |
Switching tracing on illustrates how the simplifier solves the remaining |
|
357 |
subgoal: |
|
358 |
\begin{ttbox} |
|
359 |
trace_simp := true; |
|
360 |
by (asm_simp_tac add_ss 1); |
|
323 | 361 |
\ttbreak |
104 | 362 |
{\out Rewriting:} |
363 |
{\out Suc(x) + Suc(n) == Suc(x + Suc(n))} |
|
323 | 364 |
\ttbreak |
104 | 365 |
{\out Rewriting:} |
366 |
{\out x + Suc(n) == Suc(x + n)} |
|
323 | 367 |
\ttbreak |
104 | 368 |
{\out Rewriting:} |
369 |
{\out Suc(x) + n == Suc(x + n)} |
|
323 | 370 |
\ttbreak |
104 | 371 |
{\out Rewriting:} |
372 |
{\out Suc(Suc(x + n)) = Suc(Suc(x + n)) == True} |
|
323 | 373 |
\ttbreak |
104 | 374 |
{\out Level 3} |
375 |
{\out m + Suc(n) = Suc(m + n)} |
|
376 |
{\out No subgoals!} |
|
377 |
\end{ttbox} |
|
286 | 378 |
Many variations are possible. At Level~1 (in either example) we could have |
379 |
solved both subgoals at once using the tactical \ttindex{ALLGOALS}: |
|
104 | 380 |
\begin{ttbox} |
381 |
by (ALLGOALS (asm_simp_tac add_ss)); |
|
382 |
{\out Level 2} |
|
383 |
{\out m + Suc(n) = Suc(m + n)} |
|
384 |
{\out No subgoals!} |
|
385 |
\end{ttbox} |
|
386 |
||
323 | 387 |
\subsection{Free variables and simplification} |
104 | 388 |
Here is a conjecture to be proved for an arbitrary function~$f$ satisfying |
323 | 389 |
the law $f(Suc(\Var{n})) = Suc(f(\Var{n}))$: |
104 | 390 |
\begin{ttbox} |
391 |
val [prem] = goal Nat.thy |
|
392 |
"(!!n. f(Suc(n)) = Suc(f(n))) ==> f(i+j) = i+f(j)"; |
|
393 |
{\out Level 0} |
|
394 |
{\out f(i + j) = i + f(j)} |
|
395 |
{\out 1. f(i + j) = i + f(j)} |
|
323 | 396 |
\ttbreak |
286 | 397 |
{\out val prem = "f(Suc(?n)) = Suc(f(?n))} |
398 |
{\out [!!n. f(Suc(n)) = Suc(f(n))]" : thm} |
|
323 | 399 |
\end{ttbox} |
400 |
In the theorem~{\tt prem}, note that $f$ is a free variable while |
|
401 |
$\Var{n}$ is a schematic variable. |
|
402 |
\begin{ttbox} |
|
104 | 403 |
by (res_inst_tac [("n","i")] induct 1); |
404 |
{\out Level 1} |
|
405 |
{\out f(i + j) = i + f(j)} |
|
406 |
{\out 1. f(0 + j) = 0 + f(j)} |
|
407 |
{\out 2. !!x. f(x + j) = x + f(j) ==> f(Suc(x) + j) = Suc(x) + f(j)} |
|
408 |
\end{ttbox} |
|
409 |
We simplify each subgoal in turn. The first one is trivial: |
|
410 |
\begin{ttbox} |
|
411 |
by (simp_tac add_ss 1); |
|
412 |
{\out Level 2} |
|
413 |
{\out f(i + j) = i + f(j)} |
|
414 |
{\out 1. !!x. f(x + j) = x + f(j) ==> f(Suc(x) + j) = Suc(x) + f(j)} |
|
415 |
\end{ttbox} |
|
416 |
The remaining subgoal requires rewriting by the premise, so we add it to |
|
323 | 417 |
{\tt add_ss}:% |
418 |
\footnote{The previous simplifier required congruence rules for function |
|
419 |
variables like~$f$ in order to simplify their arguments. It was more |
|
420 |
general than the current simplifier, but harder to use and slower. The |
|
421 |
present simplifier can be given congruence rules to realize non-standard |
|
422 |
simplification of a function's arguments, but this is seldom necessary.} |
|
104 | 423 |
\begin{ttbox} |
424 |
by (asm_simp_tac (add_ss addsimps [prem]) 1); |
|
425 |
{\out Level 3} |
|
426 |
{\out f(i + j) = i + f(j)} |
|
427 |
{\out No subgoals!} |
|
428 |
\end{ttbox} |
|
429 |
||
1213 | 430 |
\subsection{Reordering assumptions} |
431 |
\label{sec:reordering-asms} |
|
432 |
\index{assumptions!reordering} |
|
433 |
||
434 |
As mentioned above, \ttindex{asm_full_simp_tac} may require the assumptions |
|
435 |
to be permuted to be more effective. Given the subgoal |
|
436 |
\begin{ttbox} |
|
437 |
{\out 1. [| P(f(a)); Q; f(a) = t; R |] ==> S} |
|
438 |
\end{ttbox} |
|
439 |
we can rotate the assumptions two positions to the right |
|
440 |
\begin{ttbox} |
|
441 |
by (rotate_tac ~2 1); |
|
442 |
\end{ttbox} |
|
443 |
to obtain |
|
444 |
\begin{ttbox} |
|
445 |
{\out 1. [| f(a) = t; R; P(f(a)); Q |] ==> S} |
|
446 |
\end{ttbox} |
|
447 |
which enables \verb$asm_full_simp_tac$ to simplify \verb$P(f(a))$ to |
|
448 |
\verb$P(t)$. |
|
449 |
||
450 |
Since rotation alone cannot produce arbitrary permutations, you can also pick |
|
451 |
out a particular assumption which needs to be rewritten and move it the the |
|
452 |
right end of the assumptions. In the above case rotation can be replaced by |
|
453 |
\begin{ttbox} |
|
454 |
by (dres_inst_tac [("psi","P(f(a))")] asm_rl 1); |
|
455 |
\end{ttbox} |
|
456 |
which is more directed and leads to |
|
457 |
\begin{ttbox} |
|
458 |
{\out 1. [| Q; f(a) = t; R; P(f(a)) |] ==> S} |
|
459 |
\end{ttbox} |
|
460 |
||
461 |
Note that reordering assumptions usually leads to brittle proofs and should |
|
462 |
therefore be avoided. Future versions of \verb$asm_full_simp_tac$ may remove |
|
463 |
the need for such manipulations. |
|
286 | 464 |
|
332 | 465 |
\section{Permutative rewrite rules} |
323 | 466 |
\index{rewrite rules!permutative|(} |
467 |
||
468 |
A rewrite rule is {\bf permutative} if the left-hand side and right-hand |
|
469 |
side are the same up to renaming of variables. The most common permutative |
|
470 |
rule is commutativity: $x+y = y+x$. Other examples include $(x-y)-z = |
|
471 |
(x-z)-y$ in arithmetic and $insert(x,insert(y,A)) = insert(y,insert(x,A))$ |
|
472 |
for sets. Such rules are common enough to merit special attention. |
|
473 |
||
474 |
Because ordinary rewriting loops given such rules, the simplifier employs a |
|
475 |
special strategy, called {\bf ordered rewriting}\index{rewriting!ordered}. |
|
476 |
There is a built-in lexicographic ordering on terms. A permutative rewrite |
|
477 |
rule is applied only if it decreases the given term with respect to this |
|
478 |
ordering. For example, commutativity rewrites~$b+a$ to $a+b$, but then |
|
479 |
stops because $a+b$ is strictly less than $b+a$. The Boyer-Moore theorem |
|
480 |
prover~\cite{bm88book} also employs ordered rewriting. |
|
481 |
||
482 |
Permutative rewrite rules are added to simpsets just like other rewrite |
|
483 |
rules; the simplifier recognizes their special status automatically. They |
|
484 |
are most effective in the case of associative-commutative operators. |
|
485 |
(Associativity by itself is not permutative.) When dealing with an |
|
486 |
AC-operator~$f$, keep the following points in mind: |
|
487 |
\begin{itemize}\index{associative-commutative operators} |
|
488 |
\item The associative law must always be oriented from left to right, namely |
|
489 |
$f(f(x,y),z) = f(x,f(y,z))$. The opposite orientation, if used with |
|
490 |
commutativity, leads to looping! Future versions of Isabelle may remove |
|
491 |
this restriction. |
|
492 |
||
493 |
\item To complete your set of rewrite rules, you must add not just |
|
494 |
associativity~(A) and commutativity~(C) but also a derived rule, {\bf |
|
495 |
left-commutativity} (LC): $f(x,f(y,z)) = f(y,f(x,z))$. |
|
496 |
\end{itemize} |
|
497 |
Ordered rewriting with the combination of A, C, and~LC sorts a term |
|
498 |
lexicographically: |
|
499 |
\[\def\maps#1{\stackrel{#1}{\longmapsto}} |
|
500 |
(b+c)+a \maps{A} b+(c+a) \maps{C} b+(a+c) \maps{LC} a+(b+c) \] |
|
501 |
Martin and Nipkow~\cite{martin-nipkow} discuss the theory and give many |
|
502 |
examples; other algebraic structures are amenable to ordered rewriting, |
|
503 |
such as boolean rings. |
|
504 |
||
505 |
\subsection{Example: sums of integers} |
|
506 |
This example is set in Isabelle's higher-order logic. Theory |
|
507 |
\thydx{Arith} contains the theory of arithmetic. The simpset {\tt |
|
508 |
arith_ss} contains many arithmetic laws including distributivity |
|
509 |
of~$\times$ over~$+$, while {\tt add_ac} is a list consisting of the A, C |
|
510 |
and LC laws for~$+$. Let us prove the theorem |
|
511 |
\[ \sum@{i=1}^n i = n\times(n+1)/2. \] |
|
512 |
% |
|
513 |
A functional~{\tt sum} represents the summation operator under the |
|
514 |
interpretation ${\tt sum}(f,n+1) = \sum@{i=0}^n f(i)$. We extend {\tt |
|
515 |
Arith} using a theory file: |
|
516 |
\begin{ttbox} |
|
517 |
NatSum = Arith + |
|
1387 | 518 |
consts sum :: [nat=>nat, nat] => nat |
323 | 519 |
rules sum_0 "sum(f,0) = 0" |
520 |
sum_Suc "sum(f,Suc(n)) = f(n) + sum(f,n)" |
|
521 |
end |
|
522 |
\end{ttbox} |
|
332 | 523 |
After declaring {\tt open NatSum}, we make the required simpset by adding |
323 | 524 |
the AC-rules for~$+$ and the axioms for~{\tt sum}: |
525 |
\begin{ttbox} |
|
526 |
val natsum_ss = arith_ss addsimps ([sum_0,sum_Suc] \at add_ac); |
|
527 |
{\out val natsum_ss = SS \{\ldots\} : simpset} |
|
528 |
\end{ttbox} |
|
529 |
Our desired theorem now reads ${\tt sum}(\lambda i.i,n+1) = |
|
530 |
n\times(n+1)/2$. The Isabelle goal has both sides multiplied by~$2$: |
|
531 |
\begin{ttbox} |
|
532 |
goal NatSum.thy "Suc(Suc(0))*sum(\%i.i,Suc(n)) = n*Suc(n)"; |
|
533 |
{\out Level 0} |
|
534 |
{\out Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n)} |
|
535 |
{\out 1. Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n)} |
|
536 |
\end{ttbox} |
|
537 |
Induction should not be applied until the goal is in the simplest form: |
|
538 |
\begin{ttbox} |
|
539 |
by (simp_tac natsum_ss 1); |
|
540 |
{\out Level 1} |
|
541 |
{\out Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n)} |
|
542 |
{\out 1. n + (n + (sum(\%i. i, n) + sum(\%i. i, n))) = n + n * n} |
|
543 |
\end{ttbox} |
|
544 |
Ordered rewriting has sorted the terms in the left-hand side. |
|
545 |
The subgoal is now ready for induction: |
|
546 |
\begin{ttbox} |
|
547 |
by (nat_ind_tac "n" 1); |
|
548 |
{\out Level 2} |
|
549 |
{\out Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n)} |
|
550 |
{\out 1. 0 + (0 + (sum(\%i. i, 0) + sum(\%i. i, 0))) = 0 + 0 * 0} |
|
551 |
\ttbreak |
|
552 |
{\out 2. !!n1. n1 + (n1 + (sum(\%i. i, n1) + sum(\%i. i, n1))) =} |
|
553 |
{\out n1 + n1 * n1 ==>} |
|
554 |
{\out Suc(n1) +} |
|
555 |
{\out (Suc(n1) + (sum(\%i. i, Suc(n1)) + sum(\%i. i, Suc(n1)))) =} |
|
556 |
{\out Suc(n1) + Suc(n1) * Suc(n1)} |
|
557 |
\end{ttbox} |
|
558 |
Simplification proves both subgoals immediately:\index{*ALLGOALS} |
|
559 |
\begin{ttbox} |
|
560 |
by (ALLGOALS (asm_simp_tac natsum_ss)); |
|
561 |
{\out Level 3} |
|
562 |
{\out Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n)} |
|
563 |
{\out No subgoals!} |
|
564 |
\end{ttbox} |
|
565 |
If we had omitted {\tt add_ac} from the simpset, simplification would have |
|
566 |
failed to prove the induction step: |
|
567 |
\begin{ttbox} |
|
568 |
Suc(Suc(0)) * sum(\%i. i, Suc(n)) = n * Suc(n) |
|
569 |
1. !!n1. n1 + (n1 + (sum(\%i. i, n1) + sum(\%i. i, n1))) = |
|
570 |
n1 + n1 * n1 ==> |
|
571 |
n1 + (n1 + (n1 + sum(\%i. i, n1) + (n1 + sum(\%i. i, n1)))) = |
|
572 |
n1 + (n1 + (n1 + n1 * n1)) |
|
573 |
\end{ttbox} |
|
574 |
Ordered rewriting proves this by sorting the left-hand side. Proving |
|
575 |
arithmetic theorems without ordered rewriting requires explicit use of |
|
576 |
commutativity. This is tedious; try it and see! |
|
577 |
||
578 |
Ordered rewriting is equally successful in proving |
|
579 |
$\sum@{i=1}^n i^3 = n^2\times(n+1)^2/4$. |
|
580 |
||
581 |
||
582 |
\subsection{Re-orienting equalities} |
|
583 |
Ordered rewriting with the derived rule {\tt symmetry} can reverse equality |
|
584 |
signs: |
|
585 |
\begin{ttbox} |
|
586 |
val symmetry = prove_goal HOL.thy "(x=y) = (y=x)" |
|
587 |
(fn _ => [fast_tac HOL_cs 1]); |
|
588 |
\end{ttbox} |
|
589 |
This is frequently useful. Assumptions of the form $s=t$, where $t$ occurs |
|
590 |
in the conclusion but not~$s$, can often be brought into the right form. |
|
591 |
For example, ordered rewriting with {\tt symmetry} can prove the goal |
|
592 |
\[ f(a)=b \conj f(a)=c \imp b=c. \] |
|
593 |
Here {\tt symmetry} reverses both $f(a)=b$ and $f(a)=c$ |
|
594 |
because $f(a)$ is lexicographically greater than $b$ and~$c$. These |
|
595 |
re-oriented equations, as rewrite rules, replace $b$ and~$c$ in the |
|
596 |
conclusion by~$f(a)$. |
|
597 |
||
598 |
Another example is the goal $\neg(t=u) \imp \neg(u=t)$. |
|
599 |
The differing orientations make this appear difficult to prove. Ordered |
|
600 |
rewriting with {\tt symmetry} makes the equalities agree. (Without |
|
601 |
knowing more about~$t$ and~$u$ we cannot say whether they both go to $t=u$ |
|
602 |
or~$u=t$.) Then the simplifier can prove the goal outright. |
|
603 |
||
604 |
\index{rewrite rules!permutative|)} |
|
605 |
||
606 |
||
607 |
\section{*Setting up the simplifier}\label{sec:setting-up-simp} |
|
608 |
\index{simplification!setting up} |
|
286 | 609 |
|
610 |
Setting up the simplifier for new logics is complicated. This section |
|
323 | 611 |
describes how the simplifier is installed for intuitionistic first-order |
612 |
logic; the code is largely taken from {\tt FOL/simpdata.ML}. |
|
286 | 613 |
|
323 | 614 |
The simplifier and the case splitting tactic, which reside on separate |
615 |
files, are not part of Pure Isabelle. They must be loaded explicitly: |
|
286 | 616 |
\begin{ttbox} |
617 |
use "../Provers/simplifier.ML"; |
|
618 |
use "../Provers/splitter.ML"; |
|
619 |
\end{ttbox} |
|
620 |
||
621 |
Simplification works by reducing various object-equalities to |
|
323 | 622 |
meta-equality. It requires rules stating that equal terms and equivalent |
623 |
formulae are also equal at the meta-level. The rule declaration part of |
|
624 |
the file {\tt FOL/ifol.thy} contains the two lines |
|
625 |
\begin{ttbox}\index{*eq_reflection theorem}\index{*iff_reflection theorem} |
|
286 | 626 |
eq_reflection "(x=y) ==> (x==y)" |
627 |
iff_reflection "(P<->Q) ==> (P==Q)" |
|
628 |
\end{ttbox} |
|
323 | 629 |
Of course, you should only assert such rules if they are true for your |
286 | 630 |
particular logic. In Constructive Type Theory, equality is a ternary |
631 |
relation of the form $a=b\in A$; the type~$A$ determines the meaning of the |
|
332 | 632 |
equality essentially as a partial equivalence relation. The present |
323 | 633 |
simplifier cannot be used. Rewriting in {\tt CTT} uses another simplifier, |
634 |
which resides in the file {\tt typedsimp.ML} and is not documented. Even |
|
635 |
this does not work for later variants of Constructive Type Theory that use |
|
636 |
intensional equality~\cite{nordstrom90}. |
|
286 | 637 |
|
638 |
||
639 |
\subsection{A collection of standard rewrite rules} |
|
640 |
The file begins by proving lots of standard rewrite rules about the logical |
|
323 | 641 |
connectives. These include cancellation and associative laws. To prove |
642 |
them easily, it defines a function that echoes the desired law and then |
|
286 | 643 |
supplies it the theorem prover for intuitionistic \FOL: |
644 |
\begin{ttbox} |
|
645 |
fun int_prove_fun s = |
|
646 |
(writeln s; |
|
647 |
prove_goal IFOL.thy s |
|
648 |
(fn prems => [ (cut_facts_tac prems 1), |
|
649 |
(Int.fast_tac 1) ])); |
|
650 |
\end{ttbox} |
|
651 |
The following rewrite rules about conjunction are a selection of those |
|
652 |
proved on {\tt FOL/simpdata.ML}. Later, these will be supplied to the |
|
653 |
standard simpset. |
|
654 |
\begin{ttbox} |
|
655 |
val conj_rews = map int_prove_fun |
|
656 |
["P & True <-> P", "True & P <-> P", |
|
657 |
"P & False <-> False", "False & P <-> False", |
|
658 |
"P & P <-> P", |
|
659 |
"P & ~P <-> False", "~P & P <-> False", |
|
660 |
"(P & Q) & R <-> P & (Q & R)"]; |
|
661 |
\end{ttbox} |
|
662 |
The file also proves some distributive laws. As they can cause exponential |
|
663 |
blowup, they will not be included in the standard simpset. Instead they |
|
323 | 664 |
are merely bound to an \ML{} identifier, for user reference. |
286 | 665 |
\begin{ttbox} |
666 |
val distrib_rews = map int_prove_fun |
|
667 |
["P & (Q | R) <-> P&Q | P&R", |
|
668 |
"(Q | R) & P <-> Q&P | R&P", |
|
669 |
"(P | Q --> R) <-> (P --> R) & (Q --> R)"]; |
|
670 |
\end{ttbox} |
|
671 |
||
672 |
||
673 |
\subsection{Functions for preprocessing the rewrite rules} |
|
323 | 674 |
\label{sec:setmksimps} |
675 |
% |
|
286 | 676 |
The next step is to define the function for preprocessing rewrite rules. |
677 |
This will be installed by calling {\tt setmksimps} below. Preprocessing |
|
678 |
occurs whenever rewrite rules are added, whether by user command or |
|
679 |
automatically. Preprocessing involves extracting atomic rewrites at the |
|
680 |
object-level, then reflecting them to the meta-level. |
|
681 |
||
682 |
To start, the function {\tt gen_all} strips any meta-level |
|
683 |
quantifiers from the front of the given theorem. Usually there are none |
|
684 |
anyway. |
|
685 |
\begin{ttbox} |
|
686 |
fun gen_all th = forall_elim_vars (#maxidx(rep_thm th)+1) th; |
|
687 |
\end{ttbox} |
|
688 |
The function {\tt atomize} analyses a theorem in order to extract |
|
689 |
atomic rewrite rules. The head of all the patterns, matched by the |
|
690 |
wildcard~{\tt _}, is the coercion function {\tt Trueprop}. |
|
691 |
\begin{ttbox} |
|
692 |
fun atomize th = case concl_of th of |
|
693 |
_ $ (Const("op &",_) $ _ $ _) => atomize(th RS conjunct1) \at |
|
694 |
atomize(th RS conjunct2) |
|
695 |
| _ $ (Const("op -->",_) $ _ $ _) => atomize(th RS mp) |
|
696 |
| _ $ (Const("All",_) $ _) => atomize(th RS spec) |
|
697 |
| _ $ (Const("True",_)) => [] |
|
698 |
| _ $ (Const("False",_)) => [] |
|
699 |
| _ => [th]; |
|
700 |
\end{ttbox} |
|
701 |
There are several cases, depending upon the form of the conclusion: |
|
702 |
\begin{itemize} |
|
703 |
\item Conjunction: extract rewrites from both conjuncts. |
|
704 |
||
705 |
\item Implication: convert $P\imp Q$ to the meta-implication $P\Imp Q$ and |
|
706 |
extract rewrites from~$Q$; these will be conditional rewrites with the |
|
707 |
condition~$P$. |
|
708 |
||
709 |
\item Universal quantification: remove the quantifier, replacing the bound |
|
710 |
variable by a schematic variable, and extract rewrites from the body. |
|
711 |
||
712 |
\item {\tt True} and {\tt False} contain no useful rewrites. |
|
713 |
||
714 |
\item Anything else: return the theorem in a singleton list. |
|
715 |
\end{itemize} |
|
716 |
The resulting theorems are not literally atomic --- they could be |
|
323 | 717 |
disjunctive, for example --- but are broken down as much as possible. See |
286 | 718 |
the file {\tt ZF/simpdata.ML} for a sophisticated translation of |
719 |
set-theoretic formulae into rewrite rules. |
|
104 | 720 |
|
286 | 721 |
The simplified rewrites must now be converted into meta-equalities. The |
323 | 722 |
rule {\tt eq_reflection} converts equality rewrites, while {\tt |
286 | 723 |
iff_reflection} converts if-and-only-if rewrites. The latter possibility |
724 |
can arise in two other ways: the negative theorem~$\neg P$ is converted to |
|
323 | 725 |
$P\equiv{\tt False}$, and any other theorem~$P$ is converted to |
286 | 726 |
$P\equiv{\tt True}$. The rules {\tt iff_reflection_F} and {\tt |
727 |
iff_reflection_T} accomplish this conversion. |
|
728 |
\begin{ttbox} |
|
729 |
val P_iff_F = int_prove_fun "~P ==> (P <-> False)"; |
|
730 |
val iff_reflection_F = P_iff_F RS iff_reflection; |
|
731 |
\ttbreak |
|
732 |
val P_iff_T = int_prove_fun "P ==> (P <-> True)"; |
|
733 |
val iff_reflection_T = P_iff_T RS iff_reflection; |
|
734 |
\end{ttbox} |
|
735 |
The function {\tt mk_meta_eq} converts a theorem to a meta-equality |
|
736 |
using the case analysis described above. |
|
737 |
\begin{ttbox} |
|
738 |
fun mk_meta_eq th = case concl_of th of |
|
739 |
_ $ (Const("op =",_)$_$_) => th RS eq_reflection |
|
740 |
| _ $ (Const("op <->",_)$_$_) => th RS iff_reflection |
|
741 |
| _ $ (Const("Not",_)$_) => th RS iff_reflection_F |
|
742 |
| _ => th RS iff_reflection_T; |
|
743 |
\end{ttbox} |
|
744 |
The three functions {\tt gen_all}, {\tt atomize} and {\tt mk_meta_eq} will |
|
745 |
be composed together and supplied below to {\tt setmksimps}. |
|
746 |
||
747 |
||
748 |
\subsection{Making the initial simpset} |
|
749 |
It is time to assemble these items. We open module {\tt Simplifier} to |
|
323 | 750 |
gain access to its components. We define the infix operator |
751 |
\ttindexbold{addcongs} to insert congruence rules; given a list of theorems, |
|
752 |
it converts their conclusions into meta-equalities and passes them to |
|
753 |
\ttindex{addeqcongs}. |
|
286 | 754 |
\begin{ttbox} |
755 |
open Simplifier; |
|
756 |
\ttbreak |
|
757 |
infix addcongs; |
|
758 |
fun ss addcongs congs = |
|
759 |
ss addeqcongs (congs RL [eq_reflection,iff_reflection]); |
|
760 |
\end{ttbox} |
|
761 |
The list {\tt IFOL_rews} contains the default rewrite rules for first-order |
|
762 |
logic. The first of these is the reflexive law expressed as the |
|
323 | 763 |
equivalence $(a=a)\bimp{\tt True}$; the rewrite rule $a=a$ is clearly useless. |
286 | 764 |
\begin{ttbox} |
765 |
val IFOL_rews = |
|
766 |
[refl RS P_iff_T] \at conj_rews \at disj_rews \at not_rews \at |
|
767 |
imp_rews \at iff_rews \at quant_rews; |
|
768 |
\end{ttbox} |
|
769 |
The list {\tt triv_rls} contains trivial theorems for the solver. Any |
|
770 |
subgoal that is simplified to one of these will be removed. |
|
771 |
\begin{ttbox} |
|
772 |
val notFalseI = int_prove_fun "~False"; |
|
773 |
val triv_rls = [TrueI,refl,iff_refl,notFalseI]; |
|
774 |
\end{ttbox} |
|
323 | 775 |
% |
286 | 776 |
The basic simpset for intuitionistic \FOL{} starts with \ttindex{empty_ss}. |
777 |
It preprocess rewrites using {\tt gen_all}, {\tt atomize} and {\tt |
|
778 |
mk_meta_eq}. It solves simplified subgoals using {\tt triv_rls} and |
|
779 |
assumptions. It uses \ttindex{asm_simp_tac} to tackle subgoals of |
|
780 |
conditional rewrites. It takes {\tt IFOL_rews} as rewrite rules. |
|
781 |
Other simpsets built from {\tt IFOL_ss} will inherit these items. |
|
323 | 782 |
In particular, {\tt FOL_ss} extends {\tt IFOL_ss} with classical rewrite |
783 |
rules such as $\neg\neg P\bimp P$. |
|
286 | 784 |
\index{*setmksimps}\index{*setsolver}\index{*setsubgoaler} |
785 |
\index{*addsimps}\index{*addcongs} |
|
786 |
\begin{ttbox} |
|
787 |
val IFOL_ss = |
|
788 |
empty_ss |
|
789 |
setmksimps (map mk_meta_eq o atomize o gen_all) |
|
790 |
setsolver (fn prems => resolve_tac (triv_rls \at prems) ORELSE' |
|
791 |
assume_tac) |
|
792 |
setsubgoaler asm_simp_tac |
|
793 |
addsimps IFOL_rews |
|
794 |
addcongs [imp_cong]; |
|
795 |
\end{ttbox} |
|
796 |
This simpset takes {\tt imp_cong} as a congruence rule in order to use |
|
797 |
contextual information to simplify the conclusions of implications: |
|
798 |
\[ \List{\Var{P}\bimp\Var{P'};\; \Var{P'} \Imp \Var{Q}\bimp\Var{Q'}} \Imp |
|
799 |
(\Var{P}\imp\Var{Q}) \bimp (\Var{P'}\imp\Var{Q'}) |
|
800 |
\] |
|
801 |
By adding the congruence rule {\tt conj_cong}, we could obtain a similar |
|
802 |
effect for conjunctions. |
|
803 |
||
804 |
||
805 |
\subsection{Case splitting} |
|
323 | 806 |
To set up case splitting, we must prove the theorem below and pass it to |
807 |
\ttindexbold{mk_case_split_tac}. The tactic \ttindexbold{split_tac} uses |
|
808 |
{\tt mk_meta_eq}, defined above, to convert the splitting rules to |
|
809 |
meta-equalities. |
|
286 | 810 |
\begin{ttbox} |
811 |
val meta_iffD = |
|
812 |
prove_goal FOL.thy "[| P==Q; Q |] ==> P" |
|
813 |
(fn [prem1,prem2] => [rewtac prem1, rtac prem2 1]) |
|
814 |
\ttbreak |
|
815 |
fun split_tac splits = |
|
816 |
mk_case_split_tac meta_iffD (map mk_meta_eq splits); |
|
817 |
\end{ttbox} |
|
818 |
% |
|
323 | 819 |
The splitter replaces applications of a given function; the right-hand side |
820 |
of the replacement can be anything. For example, here is a splitting rule |
|
821 |
for conditional expressions: |
|
286 | 822 |
\[ \Var{P}(if(\Var{Q},\Var{x},\Var{y})) \bimp (\Var{Q} \imp \Var{P}(\Var{x})) |
823 |
\conj (\lnot\Var{Q} \imp \Var{P}(\Var{y})) |
|
824 |
\] |
|
323 | 825 |
Another example is the elimination operator (which happens to be |
826 |
called~$split$) for Cartesian products: |
|
286 | 827 |
\[ \Var{P}(split(\Var{f},\Var{p})) \bimp (\forall a~b. \Var{p} = |
828 |
\langle a,b\rangle \imp \Var{P}(\Var{f}(a,b))) |
|
829 |
\] |
|
830 |
Case splits should be allowed only when necessary; they are expensive |
|
831 |
and hard to control. Here is a typical example of use, where {\tt |
|
832 |
expand_if} is the first rule above: |
|
833 |
\begin{ttbox} |
|
834 |
by (simp_tac (prop_rec_ss setloop (split_tac [expand_if])) 1); |
|
835 |
\end{ttbox} |
|
836 |
||
104 | 837 |
|
838 |
||
839 |
\index{simplification|)} |
|
840 |
||
286 | 841 |