author | wenzelm |
Thu, 19 Nov 2020 17:50:14 +0100 | |
changeset 72661 | fca4d6abebda |
parent 71567 | 9a29e883a934 |
child 73612 | f28df88c0d00 |
permissions | -rw-r--r-- |
61656 | 1 |
(*:maxLineLen=78:*) |
2 |
||
26869 | 3 |
theory Proof |
63531 | 4 |
imports Main Base |
26869 | 5 |
begin |
6 |
||
58618 | 7 |
chapter \<open>Proofs \label{ch:proofs}\<close> |
26869 | 8 |
|
58618 | 9 |
text \<open> |
61657 | 10 |
Proof commands perform transitions of Isar/VM machine configurations, which |
11 |
are block-structured, consisting of a stack of nodes with three main |
|
12 |
components: logical proof context, current facts, and open goals. Isar/VM |
|
13 |
transitions are typed according to the following three different modes of |
|
14 |
operation: |
|
26870 | 15 |
|
61657 | 16 |
\<^descr> \<open>proof(prove)\<close> means that a new goal has just been stated that is now to |
17 |
be \<^emph>\<open>proven\<close>; the next command may refine it by some proof method, and |
|
18 |
enter a sub-proof to establish the actual result. |
|
64926 | 19 |
|
61657 | 20 |
\<^descr> \<open>proof(state)\<close> is like a nested theory mode: the context may be |
21 |
augmented by \<^emph>\<open>stating\<close> additional assumptions, intermediate results etc. |
|
64926 | 22 |
|
61657 | 23 |
\<^descr> \<open>proof(chain)\<close> is intermediate between \<open>proof(state)\<close> and |
24 |
\<open>proof(prove)\<close>: existing facts (i.e.\ the contents of the special |
|
25 |
@{fact_ref this} register) have been just picked up in order to be used |
|
26 |
when refining the goal claimed next. |
|
26870 | 27 |
|
61657 | 28 |
The proof mode indicator may be understood as an instruction to the writer, |
29 |
telling what kind of operation may be performed next. The corresponding |
|
30 |
typings of proof commands restricts the shape of well-formed proof texts to |
|
31 |
particular command sequences. So dynamic arrangements of commands eventually |
|
32 |
turn out as static texts of a certain structure. |
|
29741 | 33 |
|
61657 | 34 |
\Appref{ap:refcard} gives a simplified grammar of the (extensible) language |
35 |
emerging that way from the different types of proof commands. The main ideas |
|
36 |
of the overall Isar framework are explained in \chref{ch:isar-framework}. |
|
58618 | 37 |
\<close> |
26870 | 38 |
|
39 |
||
58618 | 40 |
section \<open>Proof structure\<close> |
28755 | 41 |
|
58618 | 42 |
subsection \<open>Formal notepad\<close> |
36356
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
43 |
|
58618 | 44 |
text \<open> |
36356
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
45 |
\begin{matharray}{rcl} |
61493 | 46 |
@{command_def "notepad"} & : & \<open>local_theory \<rightarrow> proof(state)\<close> \\ |
36356
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
47 |
\end{matharray} |
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
48 |
|
69597 | 49 |
\<^rail>\<open> |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
50 |
@@{command notepad} @'begin' |
40965
54b6c9e1c157
command 'notepad' replaces former 'example_proof';
wenzelm
parents:
40255
diff
changeset
|
51 |
; |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
52 |
@@{command end} |
69597 | 53 |
\<close> |
40965
54b6c9e1c157
command 'notepad' replaces former 'example_proof';
wenzelm
parents:
40255
diff
changeset
|
54 |
|
61657 | 55 |
\<^descr> @{command "notepad"}~@{keyword "begin"} opens a proof state without any |
56 |
goal statement. This allows to experiment with Isar, without producing any |
|
57 |
persistent result. The notepad is closed by @{command "end"}. |
|
58618 | 58 |
\<close> |
36356
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
59 |
|
5ab0f8859f9f
command 'example_proof' opens an empty proof body;
wenzelm
parents:
36320
diff
changeset
|
60 |
|
58618 | 61 |
subsection \<open>Blocks\<close> |
28755 | 62 |
|
58618 | 63 |
text \<open> |
28755 | 64 |
\begin{matharray}{rcl} |
61493 | 65 |
@{command_def "next"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
66 |
@{command_def "{"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
|
67 |
@{command_def "}"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
|
28755 | 68 |
\end{matharray} |
69 |
||
61657 | 70 |
While Isar is inherently block-structured, opening and closing blocks is |
71 |
mostly handled rather casually, with little explicit user-intervention. Any |
|
72 |
local goal statement automatically opens \<^emph>\<open>two\<close> internal blocks, which are |
|
73 |
closed again when concluding the sub-proof (by @{command "qed"} etc.). |
|
74 |
Sections of different context within a sub-proof may be switched via |
|
75 |
@{command "next"}, which is just a single block-close followed by block-open |
|
76 |
again. The effect of @{command "next"} is to reset the local proof context; |
|
28755 | 77 |
there is no goal focus involved here! |
78 |
||
79 |
For slightly more advanced applications, there are explicit block |
|
61657 | 80 |
parentheses as well. These typically achieve a stronger forward style of |
81 |
reasoning. |
|
28755 | 82 |
|
61657 | 83 |
\<^descr> @{command "next"} switches to a fresh block within a sub-proof, resetting |
84 |
the local context to the initial one. |
|
28755 | 85 |
|
61657 | 86 |
\<^descr> @{command "{"} and @{command "}"} explicitly open and close blocks. Any |
87 |
current facts pass through ``@{command "{"}'' unchanged, while ``@{command |
|
88 |
"}"}'' causes any result to be \<^emph>\<open>exported\<close> into the enclosing context. Thus |
|
89 |
fixed variables are generalized, assumptions discharged, and local |
|
90 |
definitions unfolded (cf.\ \secref{sec:proof-context}). There is no |
|
91 |
difference of @{command "assume"} and @{command "presume"} in this mode of |
|
92 |
forward reasoning --- in contrast to plain backward reasoning with the |
|
93 |
result exported at @{command "show"} time. |
|
58618 | 94 |
\<close> |
28755 | 95 |
|
96 |
||
58618 | 97 |
subsection \<open>Omitting proofs\<close> |
28755 | 98 |
|
58618 | 99 |
text \<open> |
28755 | 100 |
\begin{matharray}{rcl} |
61493 | 101 |
@{command_def "oops"} & : & \<open>proof \<rightarrow> local_theory | theory\<close> \\ |
28755 | 102 |
\end{matharray} |
103 |
||
61657 | 104 |
The @{command "oops"} command discontinues the current proof attempt, while |
105 |
considering the partial proof text as properly processed. This is |
|
106 |
conceptually quite different from ``faking'' actual proofs via @{command_ref |
|
107 |
"sorry"} (see \secref{sec:proof-steps}): @{command "oops"} does not observe |
|
108 |
the proof structure at all, but goes back right to the theory level. |
|
109 |
Furthermore, @{command "oops"} does not produce any result theorem --- there |
|
110 |
is no intended claim to be able to complete the proof in any way. |
|
28755 | 111 |
|
112 |
A typical application of @{command "oops"} is to explain Isar proofs |
|
61657 | 113 |
\<^emph>\<open>within\<close> the system itself, in conjunction with the document preparation |
114 |
tools of Isabelle described in \chref{ch:document-prep}. Thus partial or |
|
115 |
even wrong proof attempts can be discussed in a logically sound manner. Note |
|
116 |
that the Isabelle {\LaTeX} macros can be easily adapted to print something |
|
117 |
like ``\<open>\<dots>\<close>'' instead of the keyword ``@{command "oops"}''. |
|
58618 | 118 |
\<close> |
28755 | 119 |
|
120 |
||
58618 | 121 |
section \<open>Statements\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
122 |
|
58618 | 123 |
subsection \<open>Context elements \label{sec:proof-context}\<close> |
26870 | 124 |
|
58618 | 125 |
text \<open> |
26870 | 126 |
\begin{matharray}{rcl} |
61493 | 127 |
@{command_def "fix"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
128 |
@{command_def "assume"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
|
129 |
@{command_def "presume"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
|
63039 | 130 |
@{command_def "define"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
26870 | 131 |
\end{matharray} |
132 |
||
61657 | 133 |
The logical proof context consists of fixed variables and assumptions. The |
134 |
former closely correspond to Skolem constants, or meta-level universal |
|
135 |
quantification as provided by the Isabelle/Pure logical framework. |
|
136 |
Introducing some \<^emph>\<open>arbitrary, but fixed\<close> variable via ``@{command |
|
137 |
"fix"}~\<open>x\<close>'' results in a local value that may be used in the subsequent |
|
138 |
proof as any other variable or constant. Furthermore, any result \<open>\<turnstile> \<phi>[x]\<close> |
|
139 |
exported from the context will be universally closed wrt.\ \<open>x\<close> at the |
|
140 |
outermost level: \<open>\<turnstile> \<And>x. \<phi>[x]\<close> (this is expressed in normal form using |
|
141 |
Isabelle's meta-variables). |
|
26870 | 142 |
|
61657 | 143 |
Similarly, introducing some assumption \<open>\<chi>\<close> has two effects. On the one hand, |
144 |
a local theorem is created that may be used as a fact in subsequent proof |
|
145 |
steps. On the other hand, any result \<open>\<chi> \<turnstile> \<phi>\<close> exported from the context |
|
146 |
becomes conditional wrt.\ the assumption: \<open>\<turnstile> \<chi> \<Longrightarrow> \<phi>\<close>. Thus, solving an |
|
147 |
enclosing goal using such a result would basically introduce a new subgoal |
|
148 |
stemming from the assumption. How this situation is handled depends on the |
|
149 |
version of assumption command used: while @{command "assume"} insists on |
|
150 |
solving the subgoal by unification with some premise of the goal, @{command |
|
151 |
"presume"} leaves the subgoal unchanged in order to be proved later by the |
|
152 |
user. |
|
26870 | 153 |
|
63039 | 154 |
Local definitions, introduced by ``\<^theory_text>\<open>define x where x = t\<close>'', are achieved |
61657 | 155 |
by combining ``@{command "fix"}~\<open>x\<close>'' with another version of assumption |
156 |
that causes any hypothetical equation \<open>x \<equiv> t\<close> to be eliminated by the |
|
157 |
reflexivity rule. Thus, exporting some result \<open>x \<equiv> t \<turnstile> \<phi>[x]\<close> yields \<open>\<turnstile> |
|
61493 | 158 |
\<phi>[t]\<close>. |
26870 | 159 |
|
69597 | 160 |
\<^rail>\<open> |
63285 | 161 |
@@{command fix} @{syntax vars} |
26870 | 162 |
; |
61658 | 163 |
(@@{command assume} | @@{command presume}) concl prems @{syntax for_fixes} |
164 |
; |
|
165 |
concl: (@{syntax props} + @'and') |
|
166 |
; |
|
167 |
prems: (@'if' (@{syntax props'} + @'and'))? |
|
26870 | 168 |
; |
63285 | 169 |
@@{command define} @{syntax vars} @'where' |
170 |
(@{syntax props} + @'and') @{syntax for_fixes} |
|
69597 | 171 |
\<close> |
26870 | 172 |
|
61657 | 173 |
\<^descr> @{command "fix"}~\<open>x\<close> introduces a local variable \<open>x\<close> that is \<^emph>\<open>arbitrary, |
174 |
but fixed\<close>. |
|
60483 | 175 |
|
61657 | 176 |
\<^descr> @{command "assume"}~\<open>a: \<phi>\<close> and @{command "presume"}~\<open>a: \<phi>\<close> introduce a |
177 |
local fact \<open>\<phi> \<turnstile> \<phi>\<close> by assumption. Subsequent results applied to an enclosing |
|
178 |
goal (e.g.\ by @{command_ref "show"}) are handled as follows: @{command |
|
179 |
"assume"} expects to be able to unify with existing premises in the goal, |
|
180 |
while @{command "presume"} leaves \<open>\<phi>\<close> as new subgoals. |
|
60483 | 181 |
|
61657 | 182 |
Several lists of assumptions may be given (separated by @{keyword_ref |
183 |
"and"}; the resulting list of current facts consists of all of these |
|
184 |
concatenated. |
|
60483 | 185 |
|
63529 | 186 |
A structured assumption like \<^theory_text>\<open>assume "B x" if "A x" for x\<close> is equivalent to |
187 |
\<^theory_text>\<open>assume "\<And>x. A x \<Longrightarrow> B x"\<close>, but vacuous quantification is avoided: a |
|
61658 | 188 |
for-context only effects propositions according to actual use of variables. |
189 |
||
63039 | 190 |
\<^descr> \<^theory_text>\<open>define x where "x = t"\<close> introduces a local (non-polymorphic) definition. |
191 |
In results that are exported from the context, \<open>x\<close> is replaced by \<open>t\<close>. |
|
192 |
||
193 |
Internally, equational assumptions are added to the context in Pure form, |
|
194 |
using \<open>x \<equiv> t\<close> instead of \<open>x = t\<close> or \<open>x \<longleftrightarrow> t\<close> from the object-logic. When |
|
195 |
exporting results from the context, \<open>x\<close> is generalized and the assumption |
|
196 |
discharged by reflexivity, causing the replacement by \<open>t\<close>. |
|
60483 | 197 |
|
63039 | 198 |
The default name for the definitional fact is \<open>x_def\<close>. Several simultaneous |
199 |
definitions may be given as well, with a collective default name. |
|
200 |
||
201 |
\<^medskip> |
|
202 |
It is also possible to abstract over local parameters as follows: \<^theory_text>\<open>define f |
|
203 |
:: "'a \<Rightarrow> 'b" where "f x = t" for x :: 'a\<close>. |
|
58618 | 204 |
\<close> |
26870 | 205 |
|
206 |
||
58618 | 207 |
subsection \<open>Term abbreviations \label{sec:term-abbrev}\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
208 |
|
58618 | 209 |
text \<open> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
210 |
\begin{matharray}{rcl} |
61493 | 211 |
@{command_def "let"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
212 |
@{keyword_def "is"} & : & syntax \\ |
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
213 |
\end{matharray} |
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
214 |
|
61657 | 215 |
Abbreviations may be either bound by explicit @{command "let"}~\<open>p \<equiv> t\<close> |
216 |
statements, or by annotating assumptions or goal statements with a list of |
|
62280 | 217 |
patterns ``\<^theory_text>\<open>(is p\<^sub>1 \<dots> p\<^sub>n)\<close>''. In both cases, higher-order matching is |
61657 | 218 |
invoked to bind extra-logical term variables, which may be either named |
219 |
schematic variables of the form \<open>?x\<close>, or nameless dummies ``@{variable _}'' |
|
220 |
(underscore). Note that in the @{command "let"} form the patterns occur on |
|
221 |
the left-hand side, while the @{keyword "is"} patterns are in postfix |
|
222 |
position. |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
223 |
|
61657 | 224 |
Polymorphism of term bindings is handled in Hindley-Milner style, similar to |
225 |
ML. Type variables referring to local assumptions or open goal statements |
|
226 |
are \<^emph>\<open>fixed\<close>, while those of finished results or bound by @{command "let"} |
|
227 |
may occur in \<^emph>\<open>arbitrary\<close> instances later. Even though actual polymorphism |
|
228 |
should be rarely used in practice, this mechanism is essential to achieve |
|
229 |
proper incremental type-inference, as the user proceeds to build up the Isar |
|
230 |
proof text from left to right. |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
231 |
|
61421 | 232 |
\<^medskip> |
61657 | 233 |
Term abbreviations are quite different from local definitions as introduced |
63039 | 234 |
via @{command "define"} (see \secref{sec:proof-context}). The latter are |
61657 | 235 |
visible within the logic as actual equations, while abbreviations disappear |
236 |
during the input process just after type checking. Also note that @{command |
|
63039 | 237 |
"define"} does not support polymorphism. |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
238 |
|
69597 | 239 |
\<^rail>\<open> |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
240 |
@@{command let} ((@{syntax term} + @'and') '=' @{syntax term} + @'and') |
69597 | 241 |
\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
242 |
|
42705 | 243 |
The syntax of @{keyword "is"} patterns follows @{syntax term_pat} or |
244 |
@{syntax prop_pat} (see \secref{sec:term-decls}). |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
245 |
|
62280 | 246 |
\<^descr> \<^theory_text>\<open>let p\<^sub>1 = t\<^sub>1 and \<dots> p\<^sub>n = t\<^sub>n\<close> binds any text variables in patterns |
247 |
\<open>p\<^sub>1, \<dots>, p\<^sub>n\<close> by simultaneous higher-order matching against terms \<open>t\<^sub>1, \<dots>, |
|
248 |
t\<^sub>n\<close>. |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
249 |
|
62280 | 250 |
\<^descr> \<^theory_text>\<open>(is p\<^sub>1 \<dots> p\<^sub>n)\<close> resembles @{command "let"}, but matches \<open>p\<^sub>1, \<dots>, p\<^sub>n\<close> |
251 |
against the preceding statement. Also note that @{keyword "is"} is not a |
|
252 |
separate command, but part of others (such as @{command "assume"}, |
|
61657 | 253 |
@{command "have"} etc.). |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
254 |
|
61657 | 255 |
Some \<^emph>\<open>implicit\<close> term abbreviations\index{term abbreviations} for goals and |
256 |
facts are available as well. For any open goal, @{variable_ref thesis} |
|
257 |
refers to its object-level statement, abstracted over any meta-level |
|
258 |
parameters (if present). Likewise, @{variable_ref this} is bound for fact |
|
259 |
statements resulting from assumptions or finished goals. In case @{variable |
|
260 |
this} refers to an object-logic statement that is an application \<open>f t\<close>, then |
|
261 |
\<open>t\<close> is bound to the special text variable ``@{variable "\<dots>"}'' (three dots). |
|
262 |
The canonical application of this convenience are calculational proofs (see |
|
263 |
\secref{sec:calculation}). |
|
58618 | 264 |
\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
265 |
|
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
266 |
|
58618 | 267 |
subsection \<open>Facts and forward chaining \label{sec:proof-facts}\<close> |
26870 | 268 |
|
58618 | 269 |
text \<open> |
26870 | 270 |
\begin{matharray}{rcl} |
61493 | 271 |
@{command_def "note"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
272 |
@{command_def "then"} & : & \<open>proof(state) \<rightarrow> proof(chain)\<close> \\ |
|
273 |
@{command_def "from"} & : & \<open>proof(state) \<rightarrow> proof(chain)\<close> \\ |
|
274 |
@{command_def "with"} & : & \<open>proof(state) \<rightarrow> proof(chain)\<close> \\ |
|
275 |
@{command_def "using"} & : & \<open>proof(prove) \<rightarrow> proof(prove)\<close> \\ |
|
276 |
@{command_def "unfolding"} & : & \<open>proof(prove) \<rightarrow> proof(prove)\<close> \\ |
|
63527 | 277 |
@{method_def "use"} & : & \<open>method\<close> \\ |
278 |
@{fact_def "method_facts"} & : & \<open>fact\<close> \\ |
|
26870 | 279 |
\end{matharray} |
280 |
||
61657 | 281 |
New facts are established either by assumption or proof of local statements. |
282 |
Any fact will usually be involved in further proofs, either as explicit |
|
283 |
arguments of proof methods, or when forward chaining towards the next goal |
|
284 |
via @{command "then"} (and variants); @{command "from"} and @{command |
|
285 |
"with"} are composite forms involving @{command "note"}. The @{command |
|
286 |
"using"} elements augments the collection of used facts \<^emph>\<open>after\<close> a goal has |
|
287 |
been stated. Note that the special theorem name @{fact_ref this} refers to |
|
288 |
the most recently established facts, but only \<^emph>\<open>before\<close> issuing a follow-up |
|
289 |
claim. |
|
26870 | 290 |
|
69597 | 291 |
\<^rail>\<open> |
62969 | 292 |
@@{command note} (@{syntax thmdef}? @{syntax thms} + @'and') |
26870 | 293 |
; |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
294 |
(@@{command from} | @@{command with} | @@{command using} | @@{command unfolding}) |
62969 | 295 |
(@{syntax thms} + @'and') |
63527 | 296 |
; |
297 |
@{method use} @{syntax thms} @'in' @{syntax method} |
|
69597 | 298 |
\<close> |
26870 | 299 |
|
61657 | 300 |
\<^descr> @{command "note"}~\<open>a = b\<^sub>1 \<dots> b\<^sub>n\<close> recalls existing facts \<open>b\<^sub>1, \<dots>, b\<^sub>n\<close>, |
301 |
binding the result as \<open>a\<close>. Note that attributes may be involved as well, |
|
302 |
both on the left and right hand sides. |
|
26870 | 303 |
|
61657 | 304 |
\<^descr> @{command "then"} indicates forward chaining by the current facts in order |
305 |
to establish the goal to be claimed next. The initial proof method invoked |
|
306 |
to refine that will be offered the facts to do ``anything appropriate'' (see |
|
307 |
also \secref{sec:proof-steps}). For example, method @{method (Pure) rule} |
|
308 |
(see \secref{sec:pure-meth-att}) would typically do an elimination rather |
|
309 |
than an introduction. Automatic methods usually insert the facts into the |
|
310 |
goal state before operation. This provides a simple scheme to control |
|
311 |
relevance of facts in automated proof search. |
|
60483 | 312 |
|
61657 | 313 |
\<^descr> @{command "from"}~\<open>b\<close> abbreviates ``@{command "note"}~\<open>b\<close>~@{command |
314 |
"then"}''; thus @{command "then"} is equivalent to ``@{command |
|
315 |
"from"}~\<open>this\<close>''. |
|
60483 | 316 |
|
61657 | 317 |
\<^descr> @{command "with"}~\<open>b\<^sub>1 \<dots> b\<^sub>n\<close> abbreviates ``@{command "from"}~\<open>b\<^sub>1 \<dots> b\<^sub>n |
318 |
\<AND> this\<close>''; thus the forward chaining is from earlier facts together |
|
319 |
with the current ones. |
|
60483 | 320 |
|
63527 | 321 |
\<^descr> @{command "using"}~\<open>b\<^sub>1 \<dots> b\<^sub>n\<close> augments the facts to be used by a |
322 |
subsequent refinement step (such as @{command_ref "apply"} or @{command_ref |
|
323 |
"proof"}). |
|
60483 | 324 |
|
61657 | 325 |
\<^descr> @{command "unfolding"}~\<open>b\<^sub>1 \<dots> b\<^sub>n\<close> is structurally similar to @{command |
63821 | 326 |
"using"}, but unfolds definitional equations \<open>b\<^sub>1 \<dots> b\<^sub>n\<close> throughout the goal |
327 |
state and facts. See also the proof method @{method_ref unfold}. |
|
26870 | 328 |
|
63527 | 329 |
\<^descr> \<^theory_text>\<open>(use b\<^sub>1 \<dots> b\<^sub>n in method)\<close> uses the facts in the given method |
330 |
expression. The facts provided by the proof state (via @{command "using"} |
|
331 |
etc.) are ignored, but it is possible to refer to @{fact method_facts} |
|
332 |
explicitly. |
|
333 |
||
334 |
\<^descr> @{fact method_facts} is a dynamic fact that refers to the currently used |
|
335 |
facts of the goal state. |
|
336 |
||
26870 | 337 |
|
61657 | 338 |
Forward chaining with an empty list of theorems is the same as not chaining |
339 |
at all. Thus ``@{command "from"}~\<open>nothing\<close>'' has no effect apart from |
|
340 |
entering \<open>prove(chain)\<close> mode, since @{fact_ref nothing} is bound to the |
|
341 |
empty list of theorems. |
|
26870 | 342 |
|
42626 | 343 |
Basic proof methods (such as @{method_ref (Pure) rule}) expect multiple |
61657 | 344 |
facts to be given in their proper order, corresponding to a prefix of the |
345 |
premises of the rule involved. Note that positions may be easily skipped |
|
346 |
using something like @{command "from"}~\<open>_ \<AND> a \<AND> b\<close>, for example. |
|
347 |
This involves the trivial rule \<open>PROP \<psi> \<Longrightarrow> PROP \<psi>\<close>, which is bound in |
|
348 |
Isabelle/Pure as ``@{fact_ref "_"}'' (underscore). |
|
26870 | 349 |
|
61657 | 350 |
Automated methods (such as @{method simp} or @{method auto}) just insert any |
351 |
given facts before their usual operation. Depending on the kind of procedure |
|
352 |
involved, the order of facts is less significant here. |
|
58618 | 353 |
\<close> |
26870 | 354 |
|
355 |
||
58618 | 356 |
subsection \<open>Goals \label{sec:goals}\<close> |
26870 | 357 |
|
58618 | 358 |
text \<open> |
26870 | 359 |
\begin{matharray}{rcl} |
61493 | 360 |
@{command_def "lemma"} & : & \<open>local_theory \<rightarrow> proof(prove)\<close> \\ |
361 |
@{command_def "theorem"} & : & \<open>local_theory \<rightarrow> proof(prove)\<close> \\ |
|
362 |
@{command_def "corollary"} & : & \<open>local_theory \<rightarrow> proof(prove)\<close> \\ |
|
363 |
@{command_def "proposition"} & : & \<open>local_theory \<rightarrow> proof(prove)\<close> \\ |
|
364 |
@{command_def "schematic_goal"} & : & \<open>local_theory \<rightarrow> proof(prove)\<close> \\ |
|
365 |
@{command_def "have"} & : & \<open>proof(state) | proof(chain) \<rightarrow> proof(prove)\<close> \\ |
|
366 |
@{command_def "show"} & : & \<open>proof(state) | proof(chain) \<rightarrow> proof(prove)\<close> \\ |
|
367 |
@{command_def "hence"} & : & \<open>proof(state) \<rightarrow> proof(prove)\<close> \\ |
|
368 |
@{command_def "thus"} & : & \<open>proof(state) \<rightarrow> proof(prove)\<close> \\ |
|
369 |
@{command_def "print_statement"}\<open>\<^sup>*\<close> & : & \<open>context \<rightarrow>\<close> \\ |
|
26870 | 370 |
\end{matharray} |
371 |
||
61657 | 372 |
From a theory context, proof mode is entered by an initial goal command such |
373 |
as @{command "lemma"}. Within a proof context, new claims may be introduced |
|
374 |
locally; there are variants to interact with the overall proof structure |
|
375 |
specifically, such as @{command have} or @{command show}. |
|
26870 | 376 |
|
61657 | 377 |
Goals may consist of multiple statements, resulting in a list of facts |
378 |
eventually. A pending multi-goal is internally represented as a meta-level |
|
379 |
conjunction (\<open>&&&\<close>), which is usually split into the corresponding number of |
|
380 |
sub-goals prior to an initial method application, via @{command_ref "proof"} |
|
26870 | 381 |
(\secref{sec:proof-steps}) or @{command_ref "apply"} |
61657 | 382 |
(\secref{sec:tactic-commands}). The @{method_ref induct} method covered in |
383 |
\secref{sec:cases-induct} acts on multiple claims simultaneously. |
|
26870 | 384 |
|
61657 | 385 |
Claims at the theory level may be either in short or long form. A short goal |
386 |
merely consists of several simultaneous propositions (often just one). A |
|
387 |
long goal includes an explicit context specification for the subsequent |
|
388 |
conclusion, involving local parameters and assumptions. Here the role of |
|
389 |
each part of the statement is explicitly marked by separate keywords (see |
|
390 |
also \secref{sec:locale}); the local assumptions being introduced here are |
|
391 |
available as @{fact_ref assms} in the proof. Moreover, there are two kinds |
|
392 |
of conclusions: @{element_def "shows"} states several simultaneous |
|
393 |
propositions (essentially a big conjunction), while @{element_def "obtains"} |
|
394 |
claims several simultaneous simultaneous contexts of (essentially a big |
|
395 |
disjunction of eliminated parameters and assumptions, cf.\ |
|
396 |
\secref{sec:obtain}). |
|
26870 | 397 |
|
69597 | 398 |
\<^rail>\<open> |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
399 |
(@@{command lemma} | @@{command theorem} | @@{command corollary} | |
63094
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
400 |
@@{command proposition} | @@{command schematic_goal}) |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
401 |
(long_statement | short_statement) |
26870 | 402 |
; |
60406 | 403 |
(@@{command have} | @@{command show} | @@{command hence} | @@{command thus}) |
60555
51a6997b1384
support 'when' statement, which corresponds to 'presume';
wenzelm
parents:
60484
diff
changeset
|
404 |
stmt cond_stmt @{syntax for_fixes} |
26870 | 405 |
; |
62969 | 406 |
@@{command print_statement} @{syntax modes}? @{syntax thms} |
26870 | 407 |
; |
60483 | 408 |
|
60406 | 409 |
stmt: (@{syntax props} + @'and') |
26870 | 410 |
; |
60555
51a6997b1384
support 'when' statement, which corresponds to 'presume';
wenzelm
parents:
60484
diff
changeset
|
411 |
cond_stmt: ((@'if' | @'when') stmt)? |
51a6997b1384
support 'when' statement, which corresponds to 'presume';
wenzelm
parents:
60484
diff
changeset
|
412 |
; |
63094
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
413 |
short_statement: stmt (@'if' stmt)? @{syntax for_fixes} |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
414 |
; |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
415 |
long_statement: @{syntax thmdecl}? context conclusion |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
416 |
; |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
417 |
context: (@{syntax_ref "includes"}?) (@{syntax context_elem} *) |
26870 | 418 |
; |
60459 | 419 |
conclusion: @'shows' stmt | @'obtains' @{syntax obtain_clauses} |
26870 | 420 |
; |
60459 | 421 |
@{syntax_def obtain_clauses}: (@{syntax par_name}? obtain_case + '|') |
422 |
; |
|
63285 | 423 |
@{syntax_def obtain_case}: @{syntax vars} @'where' |
60459 | 424 |
(@{syntax thmdecl}? (@{syntax prop}+) + @'and') |
69597 | 425 |
\<close> |
26870 | 426 |
|
61657 | 427 |
\<^descr> @{command "lemma"}~\<open>a: \<phi>\<close> enters proof mode with \<open>\<phi>\<close> as main goal, |
428 |
eventually resulting in some fact \<open>\<turnstile> \<phi>\<close> to be put back into the target |
|
63094
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
429 |
context. |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
430 |
|
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
431 |
A @{syntax long_statement} may build up an initial proof context for the |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
432 |
subsequent claim, potentially including local definitions and syntax; see |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
433 |
also @{syntax "includes"} in \secref{sec:bundle} and @{syntax context_elem} |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
434 |
in \secref{sec:locale}. |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
435 |
|
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
436 |
A @{syntax short_statement} consists of propositions as conclusion, with an |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
437 |
option context of premises and parameters, via \<^verbatim>\<open>if\<close>/\<^verbatim>\<open>for\<close> in postfix |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
438 |
notation, corresponding to \<^verbatim>\<open>assumes\<close>/\<^verbatim>\<open>fixes\<close> in the long prefix notation. |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
439 |
|
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
440 |
Local premises (if present) are called ``\<open>assms\<close>'' for @{syntax |
056ea294c256
toplevel theorem statements support 'if'/'for' eigen-context;
wenzelm
parents:
63059
diff
changeset
|
441 |
long_statement}, and ``\<open>that\<close>'' for @{syntax short_statement}. |
60483 | 442 |
|
61657 | 443 |
\<^descr> @{command "theorem"}, @{command "corollary"}, and @{command "proposition"} |
444 |
are the same as @{command "lemma"}. The different command names merely serve |
|
445 |
as a formal comment in the theory source. |
|
36320 | 446 |
|
61657 | 447 |
\<^descr> @{command "schematic_goal"} is similar to @{command "theorem"}, but allows |
448 |
the statement to contain unbound schematic variables. |
|
36320 | 449 |
|
61657 | 450 |
Under normal circumstances, an Isar proof text needs to specify claims |
451 |
explicitly. Schematic goals are more like goals in Prolog, where certain |
|
452 |
results are synthesized in the course of reasoning. With schematic |
|
453 |
statements, the inherent compositionality of Isar proofs is lost, which also |
|
454 |
impacts performance, because proof checking is forced into sequential mode. |
|
60483 | 455 |
|
61657 | 456 |
\<^descr> @{command "have"}~\<open>a: \<phi>\<close> claims a local goal, eventually resulting in a |
457 |
fact within the current logical context. This operation is completely |
|
458 |
independent of any pending sub-goals of an enclosing goal statements, so |
|
459 |
@{command "have"} may be freely used for experimental exploration of |
|
460 |
potential results within a proof body. |
|
60483 | 461 |
|
61657 | 462 |
\<^descr> @{command "show"}~\<open>a: \<phi>\<close> is like @{command "have"}~\<open>a: \<phi>\<close> plus a second |
463 |
stage to refine some pending sub-goal for each one of the finished result, |
|
464 |
after having been exported into the corresponding context (at the head of |
|
465 |
the sub-proof of this @{command "show"} command). |
|
60483 | 466 |
|
61657 | 467 |
To accommodate interactive debugging, resulting rules are printed before |
468 |
being applied internally. Even more, interactive execution of @{command |
|
469 |
"show"} predicts potential failure and displays the resulting error as a |
|
470 |
warning beforehand. Watch out for the following message: |
|
61408
9020a3ba6c9a
@{verbatim [display]} supersedes old alltt/ttbox;
wenzelm
parents:
61338
diff
changeset
|
471 |
@{verbatim [display] \<open>Local statement fails to refine any pending goal\<close>} |
60483 | 472 |
|
62268 | 473 |
\<^descr> @{command "hence"} expands to ``@{command "then"}~@{command "have"}'' and |
474 |
@{command "thus"} expands to ``@{command "then"}~@{command "show"}''. These |
|
475 |
conflations are left-over from early history of Isar. The expanded syntax is |
|
476 |
more orthogonal and improves readability and maintainability of proofs. |
|
60483 | 477 |
|
61657 | 478 |
\<^descr> @{command "print_statement"}~\<open>a\<close> prints facts from the current theory or |
479 |
proof context in long statement form, according to the syntax for @{command |
|
480 |
"lemma"} given above. |
|
26870 | 481 |
|
482 |
||
61657 | 483 |
Any goal statement causes some term abbreviations (such as @{variable_ref |
484 |
"?thesis"}) to be bound automatically, see also \secref{sec:term-abbrev}. |
|
26870 | 485 |
|
60555
51a6997b1384
support 'when' statement, which corresponds to 'presume';
wenzelm
parents:
60484
diff
changeset
|
486 |
Structured goal statements involving @{keyword_ref "if"} or @{keyword_ref |
51a6997b1384
support 'when' statement, which corresponds to 'presume';
wenzelm
parents:
60484
diff
changeset
|
487 |
"when"} define the special fact @{fact_ref that} to refer to these |
61657 | 488 |
assumptions in the proof body. The user may provide separate names according |
489 |
to the syntax of the statement. |
|
58618 | 490 |
\<close> |
26870 | 491 |
|
492 |
||
60483 | 493 |
section \<open>Calculational reasoning \label{sec:calculation}\<close> |
494 |
||
495 |
text \<open> |
|
496 |
\begin{matharray}{rcl} |
|
61493 | 497 |
@{command_def "also"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
498 |
@{command_def "finally"} & : & \<open>proof(state) \<rightarrow> proof(chain)\<close> \\ |
|
499 |
@{command_def "moreover"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
|
500 |
@{command_def "ultimately"} & : & \<open>proof(state) \<rightarrow> proof(chain)\<close> \\ |
|
501 |
@{command_def "print_trans_rules"}\<open>\<^sup>*\<close> & : & \<open>context \<rightarrow>\<close> \\ |
|
502 |
@{attribute trans} & : & \<open>attribute\<close> \\ |
|
503 |
@{attribute sym} & : & \<open>attribute\<close> \\ |
|
504 |
@{attribute symmetric} & : & \<open>attribute\<close> \\ |
|
60483 | 505 |
\end{matharray} |
506 |
||
61657 | 507 |
Calculational proof is forward reasoning with implicit application of |
508 |
transitivity rules (such those of \<open>=\<close>, \<open>\<le>\<close>, \<open><\<close>). Isabelle/Isar maintains an |
|
509 |
auxiliary fact register @{fact_ref calculation} for accumulating results |
|
510 |
obtained by transitivity composed with the current result. Command @{command |
|
511 |
"also"} updates @{fact calculation} involving @{fact this}, while @{command |
|
512 |
"finally"} exhibits the final @{fact calculation} by forward chaining |
|
513 |
towards the next goal statement. Both commands require valid current facts, |
|
514 |
i.e.\ may occur only after commands that produce theorems such as @{command |
|
515 |
"assume"}, @{command "note"}, or some finished proof of @{command "have"}, |
|
516 |
@{command "show"} etc. The @{command "moreover"} and @{command "ultimately"} |
|
517 |
commands are similar to @{command "also"} and @{command "finally"}, but only |
|
518 |
collect further results in @{fact calculation} without applying any rules |
|
519 |
yet. |
|
60483 | 520 |
|
61657 | 521 |
Also note that the implicit term abbreviation ``\<open>\<dots>\<close>'' has its canonical |
522 |
application with calculational proofs. It refers to the argument of the |
|
523 |
preceding statement. (The argument of a curried infix expression happens to |
|
524 |
be its right-hand side.) |
|
60483 | 525 |
|
61657 | 526 |
Isabelle/Isar calculations are implicitly subject to block structure in the |
527 |
sense that new threads of calculational reasoning are commenced for any new |
|
528 |
block (as opened by a local goal, for example). This means that, apart from |
|
529 |
being able to nest calculations, there is no separate \<^emph>\<open>begin-calculation\<close> |
|
530 |
command required. |
|
60483 | 531 |
|
61421 | 532 |
\<^medskip> |
61657 | 533 |
The Isar calculation proof commands may be defined as follows:\<^footnote>\<open>We suppress |
534 |
internal bookkeeping such as proper handling of block-structure.\<close> |
|
60483 | 535 |
|
536 |
\begin{matharray}{rcl} |
|
61493 | 537 |
@{command "also"}\<open>\<^sub>0\<close> & \equiv & @{command "note"}~\<open>calculation = this\<close> \\ |
64926 | 538 |
@{command "also"}\<open>\<^sub>n\<^sub>+\<^sub>1\<close> & \equiv & @{command "note"}~\<open>calculation = trans [OF calculation this]\<close> \\[0.5ex] |
61493 | 539 |
@{command "finally"} & \equiv & @{command "also"}~@{command "from"}~\<open>calculation\<close> \\[0.5ex] |
540 |
@{command "moreover"} & \equiv & @{command "note"}~\<open>calculation = calculation this\<close> \\ |
|
541 |
@{command "ultimately"} & \equiv & @{command "moreover"}~@{command "from"}~\<open>calculation\<close> \\ |
|
60483 | 542 |
\end{matharray} |
543 |
||
69597 | 544 |
\<^rail>\<open> |
62969 | 545 |
(@@{command also} | @@{command finally}) ('(' @{syntax thms} ')')? |
60483 | 546 |
; |
547 |
@@{attribute trans} (() | 'add' | 'del') |
|
69597 | 548 |
\<close> |
60483 | 549 |
|
61657 | 550 |
\<^descr> @{command "also"}~\<open>(a\<^sub>1 \<dots> a\<^sub>n)\<close> maintains the auxiliary @{fact |
551 |
calculation} register as follows. The first occurrence of @{command "also"} |
|
552 |
in some calculational thread initializes @{fact calculation} by @{fact |
|
553 |
this}. Any subsequent @{command "also"} on the same level of block-structure |
|
554 |
updates @{fact calculation} by some transitivity rule applied to @{fact |
|
555 |
calculation} and @{fact this} (in that order). Transitivity rules are picked |
|
556 |
from the current context, unless alternative rules are given as explicit |
|
60483 | 557 |
arguments. |
558 |
||
64926 | 559 |
\<^descr> @{command "finally"}~\<open>(a\<^sub>1 \<dots> a\<^sub>n)\<close> maintains @{fact calculation} in the |
560 |
same way as @{command "also"} and then concludes the current calculational |
|
61657 | 561 |
thread. The final result is exhibited as fact for forward chaining towards |
64926 | 562 |
the next goal. Basically, @{command "finally"} abbreviates @{command |
61657 | 563 |
"also"}~@{command "from"}~@{fact calculation}. Typical idioms for concluding |
60483 | 564 |
calculational proofs are ``@{command "finally"}~@{command |
61657 | 565 |
"show"}~\<open>?thesis\<close>~@{command "."}'' and ``@{command "finally"}~@{command |
566 |
"have"}~\<open>\<phi>\<close>~@{command "."}''. |
|
60483 | 567 |
|
61657 | 568 |
\<^descr> @{command "moreover"} and @{command "ultimately"} are analogous to |
569 |
@{command "also"} and @{command "finally"}, but collect results only, |
|
570 |
without applying rules. |
|
60483 | 571 |
|
61657 | 572 |
\<^descr> @{command "print_trans_rules"} prints the list of transitivity rules (for |
573 |
calculational commands @{command "also"} and @{command "finally"}) and |
|
574 |
symmetry rules (for the @{attribute symmetric} operation and single step |
|
575 |
elimination patters) of the current context. |
|
60483 | 576 |
|
61439 | 577 |
\<^descr> @{attribute trans} declares theorems as transitivity rules. |
60483 | 578 |
|
61657 | 579 |
\<^descr> @{attribute sym} declares symmetry rules, as well as @{attribute |
580 |
"Pure.elim"}\<open>?\<close> rules. |
|
60483 | 581 |
|
61657 | 582 |
\<^descr> @{attribute symmetric} resolves a theorem with some rule declared as |
583 |
@{attribute sym} in the current context. For example, ``@{command |
|
584 |
"assume"}~\<open>[symmetric]: x = y\<close>'' produces a swapped fact derived from that |
|
585 |
assumption. |
|
60483 | 586 |
|
61657 | 587 |
In structured proof texts it is often more appropriate to use an explicit |
588 |
single-step elimination proof, such as ``@{command "assume"}~\<open>x = |
|
589 |
y\<close>~@{command "then"}~@{command "have"}~\<open>y = x\<close>~@{command ".."}''. |
|
60483 | 590 |
\<close> |
591 |
||
592 |
||
58618 | 593 |
section \<open>Refinement steps\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
594 |
|
58618 | 595 |
subsection \<open>Proof method expressions \label{sec:proof-meth}\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
596 |
|
61657 | 597 |
text \<open> |
598 |
Proof methods are either basic ones, or expressions composed of methods via |
|
599 |
``\<^verbatim>\<open>,\<close>'' (sequential composition), ``\<^verbatim>\<open>;\<close>'' (structural composition), |
|
600 |
``\<^verbatim>\<open>|\<close>'' (alternative choices), ``\<^verbatim>\<open>?\<close>'' (try), ``\<^verbatim>\<open>+\<close>'' (repeat at least |
|
601 |
once), ``\<^verbatim>\<open>[\<close>\<open>n\<close>\<^verbatim>\<open>]\<close>'' (restriction to first \<open>n\<close> subgoals). In practice, |
|
602 |
proof methods are usually just a comma separated list of @{syntax |
|
62969 | 603 |
name}~@{syntax args} specifications. Note that parentheses may be dropped |
61657 | 604 |
for single method specifications (with no arguments). The syntactic |
605 |
precedence of method combinators is \<^verbatim>\<open>|\<close> \<^verbatim>\<open>;\<close> \<^verbatim>\<open>,\<close> \<^verbatim>\<open>[]\<close> \<^verbatim>\<open>+\<close> \<^verbatim>\<open>?\<close> (from low |
|
606 |
to high). |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
607 |
|
69597 | 608 |
\<^rail>\<open> |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
609 |
@{syntax_def method}: |
62969 | 610 |
(@{syntax name} | '(' methods ')') (() | '?' | '+' | '[' @{syntax nat}? ']') |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
611 |
; |
62969 | 612 |
methods: (@{syntax name} @{syntax args} | @{syntax method}) + (',' | ';' | '|') |
69597 | 613 |
\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
614 |
|
61657 | 615 |
Regular Isar proof methods do \<^emph>\<open>not\<close> admit direct goal addressing, but refer |
616 |
to the first subgoal or to all subgoals uniformly. Nonetheless, the |
|
617 |
subsequent mechanisms allow to imitate the effect of subgoal addressing that |
|
618 |
is known from ML tactics. |
|
59660
49e498cedd02
support structural composition (THEN_ALL_NEW) for proof methods;
wenzelm
parents:
58619
diff
changeset
|
619 |
|
61421 | 620 |
\<^medskip> |
61657 | 621 |
Goal \<^emph>\<open>restriction\<close> means the proof state is wrapped-up in a way that |
622 |
certain subgoals are exposed, and other subgoals are ``parked'' elsewhere. |
|
623 |
Thus a proof method has no other chance than to operate on the subgoals that |
|
624 |
are presently exposed. |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
625 |
|
61657 | 626 |
Structural composition ``\<open>m\<^sub>1\<close>\<^verbatim>\<open>;\<close>~\<open>m\<^sub>2\<close>'' means that method \<open>m\<^sub>1\<close> is |
627 |
applied with restriction to the first subgoal, then \<open>m\<^sub>2\<close> is applied |
|
628 |
consecutively with restriction to each subgoal that has newly emerged due to |
|
69597 | 629 |
\<open>m\<^sub>1\<close>. This is analogous to the tactic combinator \<^ML_op>\<open>THEN_ALL_NEW\<close> in |
61657 | 630 |
Isabelle/ML, see also @{cite "isabelle-implementation"}. For example, \<open>(rule |
631 |
r; blast)\<close> applies rule \<open>r\<close> and then solves all new subgoals by \<open>blast\<close>. |
|
59660
49e498cedd02
support structural composition (THEN_ALL_NEW) for proof methods;
wenzelm
parents:
58619
diff
changeset
|
632 |
|
61657 | 633 |
Moreover, the explicit goal restriction operator ``\<open>[n]\<close>'' exposes only the |
634 |
first \<open>n\<close> subgoals (which need to exist), with default \<open>n = 1\<close>. For example, |
|
635 |
the method expression ``\<open>simp_all[3]\<close>'' simplifies the first three subgoals, |
|
636 |
while ``\<open>(rule r, simp_all)[]\<close>'' simplifies all new goals that emerge from |
|
61493 | 637 |
applying rule \<open>r\<close> to the originally first one. |
59660
49e498cedd02
support structural composition (THEN_ALL_NEW) for proof methods;
wenzelm
parents:
58619
diff
changeset
|
638 |
|
61421 | 639 |
\<^medskip> |
61657 | 640 |
Improper methods, notably tactic emulations, offer low-level goal addressing |
641 |
as explicit argument to the individual tactic being involved. Here ``\<open>[!]\<close>'' |
|
642 |
refers to all goals, and ``\<open>[n-]\<close>'' to all goals starting from \<open>n\<close>. |
|
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
643 |
|
69597 | 644 |
\<^rail>\<open> |
42705 | 645 |
@{syntax_def goal_spec}: |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
646 |
'[' (@{syntax nat} '-' @{syntax nat} | @{syntax nat} '-' | @{syntax nat} | '!' ) ']' |
69597 | 647 |
\<close> |
58618 | 648 |
\<close> |
28754
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
649 |
|
6f2e67a3dfaa
moved section "Proof method expressions" to proof chapter;
wenzelm
parents:
27141
diff
changeset
|
650 |
|
58618 | 651 |
subsection \<open>Initial and terminal proof steps \label{sec:proof-steps}\<close> |
26870 | 652 |
|
58618 | 653 |
text \<open> |
26870 | 654 |
\begin{matharray}{rcl} |
61493 | 655 |
@{command_def "proof"} & : & \<open>proof(prove) \<rightarrow> proof(state)\<close> \\ |
656 |
@{command_def "qed"} & : & \<open>proof(state) \<rightarrow> proof(state) | local_theory | theory\<close> \\ |
|
657 |
@{command_def "by"} & : & \<open>proof(prove) \<rightarrow> proof(state) | local_theory | theory\<close> \\ |
|
658 |
@{command_def ".."} & : & \<open>proof(prove) \<rightarrow> proof(state) | local_theory | theory\<close> \\ |
|
659 |
@{command_def "."} & : & \<open>proof(prove) \<rightarrow> proof(state) | local_theory | theory\<close> \\ |
|
660 |
@{command_def "sorry"} & : & \<open>proof(prove) \<rightarrow> proof(state) | local_theory | theory\<close> \\ |
|
661 |
@{method_def standard} & : & \<open>method\<close> \\ |
|
26870 | 662 |
\end{matharray} |
663 |
||
61657 | 664 |
Arbitrary goal refinement via tactics is considered harmful. Structured |
665 |
proof composition in Isar admits proof methods to be invoked in two places |
|
666 |
only. |
|
60483 | 667 |
|
61657 | 668 |
\<^enum> An \<^emph>\<open>initial\<close> refinement step @{command_ref "proof"}~\<open>m\<^sub>1\<close> reduces a |
669 |
newly stated goal to a number of sub-goals that are to be solved later. |
|
670 |
Facts are passed to \<open>m\<^sub>1\<close> for forward chaining, if so indicated by |
|
671 |
\<open>proof(chain)\<close> mode. |
|
64926 | 672 |
|
61657 | 673 |
\<^enum> A \<^emph>\<open>terminal\<close> conclusion step @{command_ref "qed"}~\<open>m\<^sub>2\<close> is intended to |
674 |
solve remaining goals. No facts are passed to \<open>m\<^sub>2\<close>. |
|
26870 | 675 |
|
61657 | 676 |
The only other (proper) way to affect pending goals in a proof body is by |
677 |
@{command_ref "show"}, which involves an explicit statement of what is to be |
|
678 |
solved eventually. Thus we avoid the fundamental problem of unstructured |
|
679 |
tactic scripts that consist of numerous consecutive goal transformations, |
|
680 |
with invisible effects. |
|
26870 | 681 |
|
61421 | 682 |
\<^medskip> |
61657 | 683 |
As a general rule of thumb for good proof style, initial proof methods |
684 |
should either solve the goal completely, or constitute some well-understood |
|
685 |
reduction to new sub-goals. Arbitrary automatic proof tools that are prone |
|
686 |
leave a large number of badly structured sub-goals are no help in continuing |
|
687 |
the proof document in an intelligible manner. |
|
26870 | 688 |
|
61657 | 689 |
Unless given explicitly by the user, the default initial method is @{method |
690 |
standard}, which subsumes at least @{method_ref (Pure) rule} or its |
|
691 |
classical variant @{method_ref (HOL) rule}. These methods apply a single |
|
692 |
standard elimination or introduction rule according to the topmost logical |
|
693 |
connective involved. There is no separate default terminal method. Any |
|
694 |
remaining goals are always solved by assumption in the very last step. |
|
26870 | 695 |
|
69597 | 696 |
\<^rail>\<open> |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
697 |
@@{command proof} method? |
26870 | 698 |
; |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
699 |
@@{command qed} method? |
26870 | 700 |
; |
55112
b1a5d603fd12
prefer rail cartouche -- avoid back-slashed quotes;
wenzelm
parents:
55029
diff
changeset
|
701 |
@@{command "by"} method method? |
26870 | 702 |
; |
55112
b1a5d603fd12
prefer rail cartouche -- avoid back-slashed quotes;
wenzelm
parents:
55029
diff
changeset
|
703 |
(@@{command "."} | @@{command ".."} | @@{command sorry}) |
69597 | 704 |
\<close> |
26870 | 705 |
|
61657 | 706 |
\<^descr> @{command "proof"}~\<open>m\<^sub>1\<close> refines the goal by proof method \<open>m\<^sub>1\<close>; facts for |
707 |
forward chaining are passed if so indicated by \<open>proof(chain)\<close> mode. |
|
60483 | 708 |
|
61657 | 709 |
\<^descr> @{command "qed"}~\<open>m\<^sub>2\<close> refines any remaining goals by proof method \<open>m\<^sub>2\<close> |
62268 | 710 |
and concludes the sub-proof by assumption. If the goal had been \<open>show\<close>, some |
711 |
pending sub-goal is solved as well by the rule resulting from the result |
|
712 |
\<^emph>\<open>exported\<close> into the enclosing goal context. Thus \<open>qed\<close> may fail for two |
|
713 |
reasons: either \<open>m\<^sub>2\<close> fails, or the resulting rule does not fit to any |
|
714 |
pending goal\<^footnote>\<open>This includes any additional ``strong'' assumptions as |
|
61657 | 715 |
introduced by @{command "assume"}.\<close> of the enclosing context. Debugging such |
716 |
a situation might involve temporarily changing @{command "show"} into |
|
717 |
@{command "have"}, or weakening the local context by replacing occurrences |
|
718 |
of @{command "assume"} by @{command "presume"}. |
|
60483 | 719 |
|
61657 | 720 |
\<^descr> @{command "by"}~\<open>m\<^sub>1 m\<^sub>2\<close> is a \<^emph>\<open>terminal proof\<close>\index{proof!terminal}; it |
721 |
abbreviates @{command "proof"}~\<open>m\<^sub>1\<close>~@{command "qed"}~\<open>m\<^sub>2\<close>, but with |
|
722 |
backtracking across both methods. Debugging an unsuccessful @{command |
|
723 |
"by"}~\<open>m\<^sub>1 m\<^sub>2\<close> command can be done by expanding its definition; in many |
|
724 |
cases @{command "proof"}~\<open>m\<^sub>1\<close> (or even \<open>apply\<close>~\<open>m\<^sub>1\<close>) is already sufficient |
|
725 |
to see the problem. |
|
26870 | 726 |
|
61657 | 727 |
\<^descr> ``@{command ".."}'' is a \<^emph>\<open>standard proof\<close>\index{proof!standard}; it |
728 |
abbreviates @{command "by"}~\<open>standard\<close>. |
|
26870 | 729 |
|
61657 | 730 |
\<^descr> ``@{command "."}'' is a \<^emph>\<open>trivial proof\<close>\index{proof!trivial}; it |
731 |
abbreviates @{command "by"}~\<open>this\<close>. |
|
60483 | 732 |
|
61657 | 733 |
\<^descr> @{command "sorry"} is a \<^emph>\<open>fake proof\<close>\index{proof!fake} pretending to |
734 |
solve the pending claim without further ado. This only works in interactive |
|
735 |
development, or if the @{attribute quick_and_dirty} is enabled. Facts |
|
736 |
emerging from fake proofs are not the real thing. Internally, the derivation |
|
737 |
object is tainted by an oracle invocation, which may be inspected via the |
|
70560 | 738 |
command @{command "thm_oracles"} (\secref{sec:oracles}). |
60483 | 739 |
|
26870 | 740 |
The most important application of @{command "sorry"} is to support |
741 |
experimentation and top-down proof development. |
|
742 |
||
61657 | 743 |
\<^descr> @{method standard} refers to the default refinement step of some Isar |
744 |
language elements (notably @{command proof} and ``@{command ".."}''). It is |
|
745 |
\<^emph>\<open>dynamically scoped\<close>, so the behaviour depends on the application |
|
746 |
environment. |
|
60618
4c79543cc376
renamed "default" to "standard", to make semantically clear what it is;
wenzelm
parents:
60578
diff
changeset
|
747 |
|
4c79543cc376
renamed "default" to "standard", to make semantically clear what it is;
wenzelm
parents:
60578
diff
changeset
|
748 |
In Isabelle/Pure, @{method standard} performs elementary introduction~/ |
61657 | 749 |
elimination steps (@{method_ref (Pure) rule}), introduction of type classes |
750 |
(@{method_ref intro_classes}) and locales (@{method_ref intro_locales}). |
|
60618
4c79543cc376
renamed "default" to "standard", to make semantically clear what it is;
wenzelm
parents:
60578
diff
changeset
|
751 |
|
61657 | 752 |
In Isabelle/HOL, @{method standard} also takes classical rules into account |
753 |
(cf.\ \secref{sec:classical}). |
|
58618 | 754 |
\<close> |
26870 | 755 |
|
756 |
||
58618 | 757 |
subsection \<open>Fundamental methods and attributes \label{sec:pure-meth-att}\<close> |
26870 | 758 |
|
58618 | 759 |
text \<open> |
61657 | 760 |
The following proof methods and attributes refer to basic logical operations |
761 |
of Isar. Further methods and attributes are provided by several generic and |
|
762 |
object-logic specific tools and packages (see \chref{ch:gen-tools} and |
|
763 |
\partref{part:hol}). |
|
26870 | 764 |
|
765 |
\begin{matharray}{rcl} |
|
61493 | 766 |
@{command_def "print_rules"}\<open>\<^sup>*\<close> & : & \<open>context \<rightarrow>\<close> \\[0.5ex] |
767 |
@{method_def "-"} & : & \<open>method\<close> \\ |
|
768 |
@{method_def "goal_cases"} & : & \<open>method\<close> \\ |
|
70522 | 769 |
@{method_def "subproofs"} & : & \<open>method\<close> \\ |
61493 | 770 |
@{method_def "fact"} & : & \<open>method\<close> \\ |
771 |
@{method_def "assumption"} & : & \<open>method\<close> \\ |
|
772 |
@{method_def "this"} & : & \<open>method\<close> \\ |
|
773 |
@{method_def (Pure) "rule"} & : & \<open>method\<close> \\ |
|
774 |
@{attribute_def (Pure) "intro"} & : & \<open>attribute\<close> \\ |
|
775 |
@{attribute_def (Pure) "elim"} & : & \<open>attribute\<close> \\ |
|
776 |
@{attribute_def (Pure) "dest"} & : & \<open>attribute\<close> \\ |
|
777 |
@{attribute_def (Pure) "rule"} & : & \<open>attribute\<close> \\[0.5ex] |
|
778 |
@{attribute_def "OF"} & : & \<open>attribute\<close> \\ |
|
779 |
@{attribute_def "of"} & : & \<open>attribute\<close> \\ |
|
780 |
@{attribute_def "where"} & : & \<open>attribute\<close> \\ |
|
26870 | 781 |
\end{matharray} |
782 |
||
69597 | 783 |
\<^rail>\<open> |
61166
5976fe402824
renamed method "goals" to "goal_cases" to emphasize its meaning;
wenzelm
parents:
61164
diff
changeset
|
784 |
@@{method goal_cases} (@{syntax name}*) |
60578 | 785 |
; |
70522 | 786 |
@@{method subproofs} @{syntax method} |
787 |
; |
|
62969 | 788 |
@@{method fact} @{syntax thms}? |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
789 |
; |
62969 | 790 |
@@{method (Pure) rule} @{syntax thms}? |
26870 | 791 |
; |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
792 |
rulemod: ('intro' | 'elim' | 'dest') |
62969 | 793 |
((('!' | () | '?') @{syntax nat}?) | 'del') ':' @{syntax thms} |
26870 | 794 |
; |
42596
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
795 |
(@@{attribute intro} | @@{attribute elim} | @@{attribute dest}) |
6c621a9d612a
modernized rail diagrams using @{rail} antiquotation;
wenzelm
parents:
40965
diff
changeset
|
796 |
('!' | () | '?') @{syntax nat}? |
26870 | 797 |
; |
42626 | 798 |
@@{attribute (Pure) rule} 'del' |
26870 | 799 |
; |
62969 | 800 |
@@{attribute OF} @{syntax thms} |
26870 | 801 |
; |
59785 | 802 |
@@{attribute of} @{syntax insts} ('concl' ':' @{syntax insts})? @{syntax for_fixes} |
26870 | 803 |
; |
59853 | 804 |
@@{attribute "where"} @{syntax named_insts} @{syntax for_fixes} |
69597 | 805 |
\<close> |
26870 | 806 |
|
61657 | 807 |
\<^descr> @{command "print_rules"} prints rules declared via attributes @{attribute |
808 |
(Pure) intro}, @{attribute (Pure) elim}, @{attribute (Pure) dest} of |
|
809 |
Isabelle/Pure. |
|
51077 | 810 |
|
61657 | 811 |
See also the analogous @{command "print_claset"} command for similar rule |
812 |
declarations of the classical reasoner (\secref{sec:classical}). |
|
51077 | 813 |
|
61657 | 814 |
\<^descr> ``@{method "-"}'' (minus) inserts the forward chaining facts as premises |
815 |
into the goal, and nothing else. |
|
60578 | 816 |
|
817 |
Note that command @{command_ref "proof"} without any method actually |
|
61657 | 818 |
performs a single reduction step using the @{method_ref (Pure) rule} method; |
819 |
thus a plain \<^emph>\<open>do-nothing\<close> proof step would be ``@{command "proof"}~\<open>-\<close>'' |
|
820 |
rather than @{command "proof"} alone. |
|
60578 | 821 |
|
61657 | 822 |
\<^descr> @{method "goal_cases"}~\<open>a\<^sub>1 \<dots> a\<^sub>n\<close> turns the current subgoals into cases |
823 |
within the context (see also \secref{sec:cases-induct}). The specified case |
|
824 |
names are used if present; otherwise cases are numbered starting from 1. |
|
60578 | 825 |
|
826 |
Invoking cases in the subsequent proof body via the @{command_ref case} |
|
827 |
command will @{command fix} goal parameters, @{command assume} goal |
|
828 |
premises, and @{command let} variable @{variable_ref ?case} refer to the |
|
829 |
conclusion. |
|
60483 | 830 |
|
70522 | 831 |
\<^descr> @{method "subproofs"}~\<open>m\<close> applies the method expression \<open>m\<close> consecutively |
832 |
to each subgoal, constructing individual subproofs internally (analogous to |
|
833 |
``\<^theory_text>\<open>show goal by m\<close>'' for each subgoal of the proof state). Search |
|
834 |
alternatives of \<open>m\<close> are truncated: the method is forced to be deterministic. |
|
835 |
This method combinator impacts the internal construction of proof terms: it |
|
836 |
makes a cascade of let-expressions within the derivation tree and may thus |
|
837 |
improve scalability. |
|
838 |
||
61657 | 839 |
\<^descr> @{method "fact"}~\<open>a\<^sub>1 \<dots> a\<^sub>n\<close> composes some fact from \<open>a\<^sub>1, \<dots>, a\<^sub>n\<close> (or |
840 |
implicitly from the current proof context) modulo unification of schematic |
|
841 |
type and term variables. The rule structure is not taken into account, i.e.\ |
|
842 |
meta-level implication is considered atomic. This is the same principle |
|
843 |
underlying literal facts (cf.\ \secref{sec:syn-att}): ``@{command |
|
844 |
"have"}~\<open>\<phi>\<close>~@{command "by"}~\<open>fact\<close>'' is equivalent to ``@{command |
|
845 |
"note"}~\<^verbatim>\<open>`\<close>\<open>\<phi>\<close>\<^verbatim>\<open>`\<close>'' provided that \<open>\<turnstile> \<phi>\<close> is an instance of some known \<open>\<turnstile> \<phi>\<close> |
|
846 |
in the proof context. |
|
60483 | 847 |
|
61657 | 848 |
\<^descr> @{method assumption} solves some goal by a single assumption step. All |
849 |
given facts are guaranteed to participate in the refinement; this means |
|
850 |
there may be only 0 or 1 in the first place. Recall that @{command "qed"} |
|
851 |
(\secref{sec:proof-steps}) already concludes any remaining sub-goals by |
|
852 |
assumption, so structured proofs usually need not quote the @{method |
|
853 |
assumption} method at all. |
|
60483 | 854 |
|
61657 | 855 |
\<^descr> @{method this} applies all of the current facts directly as rules. Recall |
856 |
that ``@{command "."}'' (dot) abbreviates ``@{command "by"}~\<open>this\<close>''. |
|
60483 | 857 |
|
61657 | 858 |
\<^descr> @{method (Pure) rule}~\<open>a\<^sub>1 \<dots> a\<^sub>n\<close> applies some rule given as argument in |
859 |
backward manner; facts are used to reduce the rule before applying it to the |
|
860 |
goal. Thus @{method (Pure) rule} without facts is plain introduction, while |
|
861 |
with facts it becomes elimination. |
|
60483 | 862 |
|
61657 | 863 |
When no arguments are given, the @{method (Pure) rule} method tries to pick |
864 |
appropriate rules automatically, as declared in the current context using |
|
865 |
the @{attribute (Pure) intro}, @{attribute (Pure) elim}, @{attribute (Pure) |
|
866 |
dest} attributes (see below). This is included in the standard behaviour of |
|
867 |
@{command "proof"} and ``@{command ".."}'' (double-dot) steps (see |
|
868 |
\secref{sec:proof-steps}). |
|
60483 | 869 |
|
61657 | 870 |
\<^descr> @{attribute (Pure) intro}, @{attribute (Pure) elim}, and @{attribute |
871 |
(Pure) dest} declare introduction, elimination, and destruct rules, to be |
|
872 |
used with method @{method (Pure) rule}, and similar tools. Note that the |
|
873 |
latter will ignore rules declared with ``\<open>?\<close>'', while ``\<open>!\<close>'' are used most |
|
874 |
aggressively. |
|
60483 | 875 |
|
61657 | 876 |
The classical reasoner (see \secref{sec:classical}) introduces its own |
877 |
variants of these attributes; use qualified names to access the present |
|
878 |
versions of Isabelle/Pure, i.e.\ @{attribute (Pure) "Pure.intro"}. |
|
60483 | 879 |
|
61657 | 880 |
\<^descr> @{attribute (Pure) rule}~\<open>del\<close> undeclares introduction, elimination, or |
881 |
destruct rules. |
|
51077 | 882 |
|
61657 | 883 |
\<^descr> @{attribute OF}~\<open>a\<^sub>1 \<dots> a\<^sub>n\<close> applies some theorem to all of the given rules |
884 |
\<open>a\<^sub>1, \<dots>, a\<^sub>n\<close> in canonical right-to-left order, which means that premises |
|
885 |
stemming from the \<open>a\<^sub>i\<close> emerge in parallel in the result, without |
|
886 |
interfering with each other. In many practical situations, the \<open>a\<^sub>i\<close> do not |
|
887 |
have premises themselves, so \<open>rule [OF a\<^sub>1 \<dots> a\<^sub>n]\<close> can be actually read as |
|
888 |
functional application (modulo unification). |
|
47498 | 889 |
|
61657 | 890 |
Argument positions may be effectively skipped by using ``\<open>_\<close>'' (underscore), |
891 |
which refers to the propositional identity rule in the Pure theory. |
|
60483 | 892 |
|
61657 | 893 |
\<^descr> @{attribute of}~\<open>t\<^sub>1 \<dots> t\<^sub>n\<close> performs positional instantiation of term |
894 |
variables. The terms \<open>t\<^sub>1, \<dots>, t\<^sub>n\<close> are substituted for any schematic |
|
895 |
variables occurring in a theorem from left to right; ``\<open>_\<close>'' (underscore) |
|
896 |
indicates to skip a position. Arguments following a ``\<open>concl:\<close>'' |
|
897 |
specification refer to positions of the conclusion of a rule. |
|
55143
04448228381d
explicit eigen-context for attributes "where", "of", and corresponding read_instantiate, instantiate_tac;
wenzelm
parents:
55112
diff
changeset
|
898 |
|
61657 | 899 |
An optional context of local variables \<open>\<FOR> x\<^sub>1 \<dots> x\<^sub>m\<close> may be specified: |
900 |
the instantiated theorem is exported, and these variables become schematic |
|
901 |
(usually with some shifting of indices). |
|
60483 | 902 |
|
61657 | 903 |
\<^descr> @{attribute "where"}~\<open>x\<^sub>1 = t\<^sub>1 \<AND> \<dots> x\<^sub>n = t\<^sub>n\<close> performs named |
904 |
instantiation of schematic type and term variables occurring in a theorem. |
|
905 |
Schematic variables have to be specified on the left-hand side (e.g.\ |
|
906 |
\<open>?x1.3\<close>). The question mark may be omitted if the variable name is a plain |
|
907 |
identifier without index. As type instantiations are inferred from term |
|
908 |
instantiations, explicit type instantiations are seldom necessary. |
|
26870 | 909 |
|
61657 | 910 |
An optional context of local variables \<open>\<FOR> x\<^sub>1 \<dots> x\<^sub>m\<close> may be specified |
911 |
as for @{attribute "of"} above. |
|
58618 | 912 |
\<close> |
26870 | 913 |
|
914 |
||
58618 | 915 |
subsection \<open>Defining proof methods\<close> |
28757 | 916 |
|
58618 | 917 |
text \<open> |
28757 | 918 |
\begin{matharray}{rcl} |
61493 | 919 |
@{command_def "method_setup"} & : & \<open>local_theory \<rightarrow> local_theory\<close> \\ |
28757 | 920 |
\end{matharray} |
921 |
||
69597 | 922 |
\<^rail>\<open> |
59783
00b62aa9f430
tuned syntax diagrams -- no duplication of "target";
wenzelm
parents:
59660
diff
changeset
|
923 |
@@{command method_setup} @{syntax name} '=' @{syntax text} @{syntax text}? |
69597 | 924 |
\<close> |
28757 | 925 |
|
61657 | 926 |
\<^descr> @{command "method_setup"}~\<open>name = text description\<close> defines a proof method |
927 |
in the current context. The given \<open>text\<close> has to be an ML expression of type |
|
69597 | 928 |
\<^ML_type>\<open>(Proof.context -> Proof.method) context_parser\<close>, cf.\ basic |
929 |
parsers defined in structure \<^ML_structure>\<open>Args\<close> and \<^ML_structure>\<open>Attrib\<close>. There are also combinators like \<^ML>\<open>METHOD\<close> and \<^ML>\<open>SIMPLE_METHOD\<close> to turn certain tactic forms into official proof methods; the |
|
61657 | 930 |
primed versions refer to tactics with explicit goal addressing. |
28757 | 931 |
|
30547 | 932 |
Here are some example method definitions: |
58618 | 933 |
\<close> |
28757 | 934 |
|
59905 | 935 |
(*<*)experiment begin(*>*) |
58619 | 936 |
method_setup my_method1 = |
937 |
\<open>Scan.succeed (K (SIMPLE_METHOD' (fn i: int => no_tac)))\<close> |
|
938 |
"my first method (without any arguments)" |
|
30547 | 939 |
|
58619 | 940 |
method_setup my_method2 = |
941 |
\<open>Scan.succeed (fn ctxt: Proof.context => |
|
942 |
SIMPLE_METHOD' (fn i: int => no_tac))\<close> |
|
943 |
"my second method (with context)" |
|
30547 | 944 |
|
58619 | 945 |
method_setup my_method3 = |
946 |
\<open>Attrib.thms >> (fn thms: thm list => fn ctxt: Proof.context => |
|
947 |
SIMPLE_METHOD' (fn i: int => no_tac))\<close> |
|
948 |
"my third method (with theorem arguments and context)" |
|
59905 | 949 |
(*<*)end(*>*) |
30547 | 950 |
|
28757 | 951 |
|
60483 | 952 |
section \<open>Proof by cases and induction \label{sec:cases-induct}\<close> |
953 |
||
954 |
subsection \<open>Rule contexts\<close> |
|
955 |
||
956 |
text \<open> |
|
957 |
\begin{matharray}{rcl} |
|
61493 | 958 |
@{command_def "case"} & : & \<open>proof(state) \<rightarrow> proof(state)\<close> \\ |
959 |
@{command_def "print_cases"}\<open>\<^sup>*\<close> & : & \<open>context \<rightarrow>\<close> \\ |
|
960 |
@{attribute_def case_names} & : & \<open>attribute\<close> \\ |
|
961 |
@{attribute_def case_conclusion} & : & \<open>attribute\<close> \\ |
|
962 |
@{attribute_def params} & : & \<open>attribute\<close> \\ |
|
963 |
@{attribute_def consumes} & : & \<open>attribute\<close> \\ |
|
60483 | 964 |
\end{matharray} |
965 |
||
61657 | 966 |
The puristic way to build up Isar proof contexts is by explicit language |
967 |
elements like @{command "fix"}, @{command "assume"}, @{command "let"} (see |
|
968 |
\secref{sec:proof-context}). This is adequate for plain natural deduction, |
|
969 |
but easily becomes unwieldy in concrete verification tasks, which typically |
|
970 |
involve big induction rules with several cases. |
|
60483 | 971 |
|
61657 | 972 |
The @{command "case"} command provides a shorthand to refer to a local |
973 |
context symbolically: certain proof methods provide an environment of named |
|
974 |
``cases'' of the form \<open>c: x\<^sub>1, \<dots>, x\<^sub>m, \<phi>\<^sub>1, \<dots>, \<phi>\<^sub>n\<close>; the effect of |
|
975 |
``@{command "case"}~\<open>c\<close>'' is then equivalent to ``@{command "fix"}~\<open>x\<^sub>1 \<dots> |
|
976 |
x\<^sub>m\<close>~@{command "assume"}~\<open>c: \<phi>\<^sub>1 \<dots> \<phi>\<^sub>n\<close>''. Term bindings may be covered as |
|
977 |
well, notably @{variable ?case} for the main conclusion. |
|
60483 | 978 |
|
61657 | 979 |
By default, the ``terminology'' \<open>x\<^sub>1, \<dots>, x\<^sub>m\<close> of a case value is marked as |
980 |
hidden, i.e.\ there is no way to refer to such parameters in the subsequent |
|
981 |
proof text. After all, original rule parameters stem from somewhere outside |
|
982 |
of the current proof text. By using the explicit form ``@{command |
|
983 |
"case"}~\<open>(c y\<^sub>1 \<dots> y\<^sub>m)\<close>'' instead, the proof author is able to chose local |
|
984 |
names that fit nicely into the current context. |
|
60483 | 985 |
|
61421 | 986 |
\<^medskip> |
61657 | 987 |
It is important to note that proper use of @{command "case"} does not |
988 |
provide means to peek at the current goal state, which is not directly |
|
989 |
observable in Isar! Nonetheless, goal refinement commands do provide named |
|
990 |
cases \<open>goal\<^sub>i\<close> for each subgoal \<open>i = 1, \<dots>, n\<close> of the resulting goal state. |
|
991 |
Using this extra feature requires great care, because some bits of the |
|
992 |
internal tactical machinery intrude the proof text. In particular, parameter |
|
993 |
names stemming from the left-over of automated reasoning tools are usually |
|
994 |
quite unpredictable. |
|
60483 | 995 |
|
996 |
Under normal circumstances, the text of cases emerge from standard |
|
61657 | 997 |
elimination or induction rules, which in turn are derived from previous |
998 |
theory specifications in a canonical way (say from @{command "inductive"} |
|
999 |
definitions). |
|
60483 | 1000 |
|
61421 | 1001 |
\<^medskip> |
61657 | 1002 |
Proper cases are only available if both the proof method and the rules |
1003 |
involved support this. By using appropriate attributes, case names, |
|
1004 |
conclusions, and parameters may be also declared by hand. Thus variant |
|
1005 |
versions of rules that have been derived manually become ready to use in |
|
1006 |
advanced case analysis later. |
|
60483 | 1007 |
|
69597 | 1008 |
\<^rail>\<open> |
62969 | 1009 |
@@{command case} @{syntax thmdecl}? (name | '(' name (('_' | @{syntax name}) *) ')') |
60483 | 1010 |
; |
63019 | 1011 |
@@{attribute case_names} ((@{syntax name} ( '[' (('_' | @{syntax name}) *) ']' ) ? ) +) |
60483 | 1012 |
; |
1013 |
@@{attribute case_conclusion} @{syntax name} (@{syntax name} * ) |
|
1014 |
; |
|
1015 |
@@{attribute params} ((@{syntax name} * ) + @'and') |
|
1016 |
; |
|
1017 |
@@{attribute consumes} @{syntax int}? |
|
69597 | 1018 |
\<close> |
60483 | 1019 |
|
61657 | 1020 |
\<^descr> @{command "case"}~\<open>a: (c x\<^sub>1 \<dots> x\<^sub>m)\<close> invokes a named local context \<open>c: |
1021 |
x\<^sub>1, \<dots>, x\<^sub>m, \<phi>\<^sub>1, \<dots>, \<phi>\<^sub>m\<close>, as provided by an appropriate proof method (such |
|
1022 |
as @{method_ref cases} and @{method_ref induct}). The command ``@{command |
|
1023 |
"case"}~\<open>a: (c x\<^sub>1 \<dots> x\<^sub>m)\<close>'' abbreviates ``@{command "fix"}~\<open>x\<^sub>1 \<dots> |
|
1024 |
x\<^sub>m\<close>~@{command "assume"}~\<open>a.c: \<phi>\<^sub>1 \<dots> \<phi>\<^sub>n\<close>''. Each local fact is qualified by |
|
1025 |
the prefix \<open>a\<close>, and all such facts are collectively bound to the name \<open>a\<close>. |
|
60565 | 1026 |
|
61657 | 1027 |
The fact name is specification \<open>a\<close> is optional, the default is to re-use |
1028 |
\<open>c\<close>. So @{command "case"}~\<open>(c x\<^sub>1 \<dots> x\<^sub>m)\<close> is the same as @{command |
|
1029 |
"case"}~\<open>c: (c x\<^sub>1 \<dots> x\<^sub>m)\<close>. |
|
60483 | 1030 |
|
61657 | 1031 |
\<^descr> @{command "print_cases"} prints all local contexts of the current state, |
1032 |
using Isar proof language notation. |
|
1033 |
||
1034 |
\<^descr> @{attribute case_names}~\<open>c\<^sub>1 \<dots> c\<^sub>k\<close> declares names for the local contexts |
|
1035 |
of premises of a theorem; \<open>c\<^sub>1, \<dots>, c\<^sub>k\<close> refers to the \<^emph>\<open>prefix\<close> of the list |
|
1036 |
of premises. Each of the cases \<open>c\<^sub>i\<close> can be of the form \<open>c[h\<^sub>1 \<dots> h\<^sub>n]\<close> where |
|
1037 |
the \<open>h\<^sub>1 \<dots> h\<^sub>n\<close> are the names of the hypotheses in case \<open>c\<^sub>i\<close> from left to |
|
1038 |
right. |
|
60483 | 1039 |
|
61657 | 1040 |
\<^descr> @{attribute case_conclusion}~\<open>c d\<^sub>1 \<dots> d\<^sub>k\<close> declares names for the |
1041 |
conclusions of a named premise \<open>c\<close>; here \<open>d\<^sub>1, \<dots>, d\<^sub>k\<close> refers to the prefix |
|
1042 |
of arguments of a logical formula built by nesting a binary connective |
|
1043 |
(e.g.\ \<open>\<or>\<close>). |
|
60483 | 1044 |
|
61657 | 1045 |
Note that proof methods such as @{method induct} and @{method coinduct} |
1046 |
already provide a default name for the conclusion as a whole. The need to |
|
1047 |
name subformulas only arises with cases that split into several sub-cases, |
|
1048 |
as in common co-induction rules. |
|
60483 | 1049 |
|
61657 | 1050 |
\<^descr> @{attribute params}~\<open>p\<^sub>1 \<dots> p\<^sub>m \<AND> \<dots> q\<^sub>1 \<dots> q\<^sub>n\<close> renames the innermost |
1051 |
parameters of premises \<open>1, \<dots>, n\<close> of some theorem. An empty list of names may |
|
1052 |
be given to skip positions, leaving the present parameters unchanged. |
|
60483 | 1053 |
|
61657 | 1054 |
Note that the default usage of case rules does \<^emph>\<open>not\<close> directly expose |
1055 |
parameters to the proof context. |
|
60483 | 1056 |
|
61657 | 1057 |
\<^descr> @{attribute consumes}~\<open>n\<close> declares the number of ``major premises'' of a |
1058 |
rule, i.e.\ the number of facts to be consumed when it is applied by an |
|
1059 |
appropriate proof method. The default value of @{attribute consumes} is \<open>n = |
|
1060 |
1\<close>, which is appropriate for the usual kind of cases and induction rules for |
|
1061 |
inductive sets (cf.\ \secref{sec:hol-inductive}). Rules without any |
|
1062 |
@{attribute consumes} declaration given are treated as if @{attribute |
|
61493 | 1063 |
consumes}~\<open>0\<close> had been specified. |
60483 | 1064 |
|
61657 | 1065 |
A negative \<open>n\<close> is interpreted relatively to the total number of premises of |
1066 |
the rule in the target context. Thus its absolute value specifies the |
|
1067 |
remaining number of premises, after subtracting the prefix of major premises |
|
1068 |
as indicated above. This form of declaration has the technical advantage of |
|
1069 |
being stable under more morphisms, notably those that export the result from |
|
1070 |
a nested @{command_ref context} with additional assumptions. |
|
60483 | 1071 |
|
61657 | 1072 |
Note that explicit @{attribute consumes} declarations are only rarely |
1073 |
needed; this is already taken care of automatically by the higher-level |
|
1074 |
@{attribute cases}, @{attribute induct}, and @{attribute coinduct} |
|
1075 |
declarations. |
|
60483 | 1076 |
\<close> |
1077 |
||
1078 |
||
1079 |
subsection \<open>Proof methods\<close> |
|
1080 |
||
1081 |
text \<open> |
|
1082 |
\begin{matharray}{rcl} |
|
61493 | 1083 |
@{method_def cases} & : & \<open>method\<close> \\ |
1084 |
@{method_def induct} & : & \<open>method\<close> \\ |
|
1085 |
@{method_def induction} & : & \<open>method\<close> \\ |
|
1086 |
@{method_def coinduct} & : & \<open>method\<close> \\ |
|
60483 | 1087 |
\end{matharray} |
1088 |
||
61657 | 1089 |
The @{method cases}, @{method induct}, @{method induction}, and @{method |
1090 |
coinduct} methods provide a uniform interface to common proof techniques |
|
1091 |
over datatypes, inductive predicates (or sets), recursive functions etc. The |
|
1092 |
corresponding rules may be specified and instantiated in a casual manner. |
|
1093 |
Furthermore, these methods provide named local contexts that may be invoked |
|
1094 |
via the @{command "case"} proof command within the subsequent proof text. |
|
1095 |
This accommodates compact proof texts even when reasoning about large |
|
1096 |
specifications. |
|
60483 | 1097 |
|
61657 | 1098 |
The @{method induct} method also provides some additional infrastructure in |
1099 |
order to be applicable to structure statements (either using explicit |
|
1100 |
meta-level connectives, or including facts and parameters separately). This |
|
1101 |
avoids cumbersome encoding of ``strengthened'' inductive statements within |
|
1102 |
the object-logic. |
|
60483 | 1103 |
|
61657 | 1104 |
Method @{method induction} differs from @{method induct} only in the names |
1105 |
of the facts in the local context invoked by the @{command "case"} command. |
|
60483 | 1106 |
|
69597 | 1107 |
\<^rail>\<open> |
60483 | 1108 |
@@{method cases} ('(' 'no_simp' ')')? \<newline> |
1109 |
(@{syntax insts} * @'and') rule? |
|
1110 |
; |
|
1111 |
(@@{method induct} | @@{method induction}) |
|
1112 |
('(' 'no_simp' ')')? (definsts * @'and') \<newline> arbitrary? taking? rule? |
|
1113 |
; |
|
1114 |
@@{method coinduct} @{syntax insts} taking rule? |
|
1115 |
; |
|
1116 |
||
62969 | 1117 |
rule: ('type' | 'pred' | 'set') ':' (@{syntax name} +) | 'rule' ':' (@{syntax thm} +) |
60483 | 1118 |
; |
1119 |
definst: @{syntax name} ('==' | '\<equiv>') @{syntax term} | '(' @{syntax term} ')' | @{syntax inst} |
|
1120 |
; |
|
1121 |
definsts: ( definst * ) |
|
1122 |
; |
|
1123 |
arbitrary: 'arbitrary' ':' ((@{syntax term} * ) @'and' +) |
|
1124 |
; |
|
1125 |
taking: 'taking' ':' @{syntax insts} |
|
69597 | 1126 |
\<close> |
60483 | 1127 |
|
61657 | 1128 |
\<^descr> @{method cases}~\<open>insts R\<close> applies method @{method rule} with an |
1129 |
appropriate case distinction theorem, instantiated to the subjects \<open>insts\<close>. |
|
1130 |
Symbolic case names are bound according to the rule's local contexts. |
|
60483 | 1131 |
|
61657 | 1132 |
The rule is determined as follows, according to the facts and arguments |
1133 |
passed to the @{method cases} method: |
|
60483 | 1134 |
|
61421 | 1135 |
\<^medskip> |
60483 | 1136 |
\begin{tabular}{llll} |
1137 |
facts & & arguments & rule \\\hline |
|
61493 | 1138 |
\<open>\<turnstile> R\<close> & @{method cases} & & implicit rule \<open>R\<close> \\ |
60483 | 1139 |
& @{method cases} & & classical case split \\ |
61493 | 1140 |
& @{method cases} & \<open>t\<close> & datatype exhaustion (type of \<open>t\<close>) \\ |
1141 |
\<open>\<turnstile> A t\<close> & @{method cases} & \<open>\<dots>\<close> & inductive predicate/set elimination (of \<open>A\<close>) \\ |
|
1142 |
\<open>\<dots>\<close> & @{method cases} & \<open>\<dots> rule: R\<close> & explicit rule \<open>R\<close> \\ |
|
60483 | 1143 |
\end{tabular} |
61421 | 1144 |
\<^medskip> |
60483 | 1145 |
|
61657 | 1146 |
Several instantiations may be given, referring to the \<^emph>\<open>suffix\<close> of premises |
1147 |
of the case rule; within each premise, the \<^emph>\<open>prefix\<close> of variables is |
|
1148 |
instantiated. In most situations, only a single term needs to be specified; |
|
1149 |
this refers to the first variable of the last premise (it is usually the |
|
1150 |
same for all cases). The \<open>(no_simp)\<close> option can be used to disable |
|
1151 |
pre-simplification of cases (see the description of @{method induct} below |
|
1152 |
for details). |
|
60483 | 1153 |
|
61657 | 1154 |
\<^descr> @{method induct}~\<open>insts R\<close> and @{method induction}~\<open>insts R\<close> are analogous |
1155 |
to the @{method cases} method, but refer to induction rules, which are |
|
60483 | 1156 |
determined as follows: |
1157 |
||
61421 | 1158 |
\<^medskip> |
60483 | 1159 |
\begin{tabular}{llll} |
1160 |
facts & & arguments & rule \\\hline |
|
61493 | 1161 |
& @{method induct} & \<open>P x\<close> & datatype induction (type of \<open>x\<close>) \\ |
1162 |
\<open>\<turnstile> A x\<close> & @{method induct} & \<open>\<dots>\<close> & predicate/set induction (of \<open>A\<close>) \\ |
|
1163 |
\<open>\<dots>\<close> & @{method induct} & \<open>\<dots> rule: R\<close> & explicit rule \<open>R\<close> \\ |
|
60483 | 1164 |
\end{tabular} |
61421 | 1165 |
\<^medskip> |
60483 | 1166 |
|
61657 | 1167 |
Several instantiations may be given, each referring to some part of a mutual |
1168 |
inductive definition or datatype --- only related partial induction rules |
|
1169 |
may be used together, though. Any of the lists of terms \<open>P, x, \<dots>\<close> refers to |
|
1170 |
the \<^emph>\<open>suffix\<close> of variables present in the induction rule. This enables the |
|
1171 |
writer to specify only induction variables, or both predicates and |
|
1172 |
variables, for example. |
|
60483 | 1173 |
|
61657 | 1174 |
Instantiations may be definitional: equations \<open>x \<equiv> t\<close> introduce local |
1175 |
definitions, which are inserted into the claim and discharged after applying |
|
1176 |
the induction rule. Equalities reappear in the inductive cases, but have |
|
1177 |
been transformed according to the induction principle being involved here. |
|
1178 |
In order to achieve practically useful induction hypotheses, some variables |
|
1179 |
occurring in \<open>t\<close> need to be fixed (see below). Instantiations of the form |
|
1180 |
\<open>t\<close>, where \<open>t\<close> is not a variable, are taken as a shorthand for \<open>x \<equiv> t\<close>, |
|
1181 |
where \<open>x\<close> is a fresh variable. If this is not intended, \<open>t\<close> has to be |
|
1182 |
enclosed in parentheses. By default, the equalities generated by |
|
1183 |
definitional instantiations are pre-simplified using a specific set of |
|
1184 |
rules, usually consisting of distinctness and injectivity theorems for |
|
1185 |
datatypes. This pre-simplification may cause some of the parameters of an |
|
1186 |
inductive case to disappear, or may even completely delete some of the |
|
1187 |
inductive cases, if one of the equalities occurring in their premises can be |
|
1188 |
simplified to \<open>False\<close>. The \<open>(no_simp)\<close> option can be used to disable |
|
1189 |
pre-simplification. Additional rules to be used in pre-simplification can be |
|
1190 |
declared using the @{attribute_def induct_simp} attribute. |
|
60483 | 1191 |
|
61657 | 1192 |
The optional ``\<open>arbitrary: x\<^sub>1 \<dots> x\<^sub>m\<close>'' specification generalizes variables |
71567
9a29e883a934
tuned documentation, based on hints by Pedro Sánchez Terraf;
wenzelm
parents:
70560
diff
changeset
|
1193 |
\<open>x\<^sub>1, \<dots>, x\<^sub>m\<close> of the original goal before applying induction. It is possible |
9a29e883a934
tuned documentation, based on hints by Pedro Sánchez Terraf;
wenzelm
parents:
70560
diff
changeset
|
1194 |
to separate variables by ``\<open>and\<close>'' to generalize in goals other than |
9a29e883a934
tuned documentation, based on hints by Pedro Sánchez Terraf;
wenzelm
parents:
70560
diff
changeset
|
1195 |
the first. Thus induction hypotheses may become sufficiently general to get |
9a29e883a934
tuned documentation, based on hints by Pedro Sánchez Terraf;
wenzelm
parents:
70560
diff
changeset
|
1196 |
the proof through. Together with definitional instantiations, one may |
61657 | 1197 |
effectively perform induction over expressions of a certain structure. |
60483 | 1198 |
|
61657 | 1199 |
The optional ``\<open>taking: t\<^sub>1 \<dots> t\<^sub>n\<close>'' specification provides additional |
1200 |
instantiations of a prefix of pending variables in the rule. Such schematic |
|
1201 |
induction rules rarely occur in practice, though. |
|
60483 | 1202 |
|
61657 | 1203 |
\<^descr> @{method coinduct}~\<open>inst R\<close> is analogous to the @{method induct} method, |
1204 |
but refers to coinduction rules, which are determined as follows: |
|
60483 | 1205 |
|
61421 | 1206 |
\<^medskip> |
60483 | 1207 |
\begin{tabular}{llll} |
1208 |
goal & & arguments & rule \\\hline |
|
61493 | 1209 |
& @{method coinduct} & \<open>x\<close> & type coinduction (type of \<open>x\<close>) \\ |
1210 |
\<open>A x\<close> & @{method coinduct} & \<open>\<dots>\<close> & predicate/set coinduction (of \<open>A\<close>) \\ |
|
1211 |
\<open>\<dots>\<close> & @{method coinduct} & \<open>\<dots> rule: R\<close> & explicit rule \<open>R\<close> \\ |
|
60483 | 1212 |
\end{tabular} |
61421 | 1213 |
\<^medskip> |
60483 | 1214 |
|
61657 | 1215 |
Coinduction is the dual of induction. Induction essentially eliminates \<open>A x\<close> |
1216 |
towards a generic result \<open>P x\<close>, while coinduction introduces \<open>A x\<close> starting |
|
1217 |
with \<open>B x\<close>, for a suitable ``bisimulation'' \<open>B\<close>. The cases of a coinduct |
|
1218 |
rule are typically named after the predicates or sets being covered, while |
|
1219 |
the conclusions consist of several alternatives being named after the |
|
1220 |
individual destructor patterns. |
|
60483 | 1221 |
|
61657 | 1222 |
The given instantiation refers to the \<^emph>\<open>suffix\<close> of variables occurring in |
1223 |
the rule's major premise, or conclusion if unavailable. An additional |
|
1224 |
``\<open>taking: t\<^sub>1 \<dots> t\<^sub>n\<close>'' specification may be required in order to specify |
|
1225 |
the bisimulation to be used in the coinduction step. |
|
60483 | 1226 |
|
1227 |
||
1228 |
Above methods produce named local contexts, as determined by the |
|
61657 | 1229 |
instantiated rule as given in the text. Beyond that, the @{method induct} |
1230 |
and @{method coinduct} methods guess further instantiations from the goal |
|
1231 |
specification itself. Any persisting unresolved schematic variables of the |
|
1232 |
resulting rule will render the the corresponding case invalid. The term |
|
1233 |
binding @{variable ?case} for the conclusion will be provided with each |
|
1234 |
case, provided that term is fully specified. |
|
60483 | 1235 |
|
61657 | 1236 |
The @{command "print_cases"} command prints all named cases present in the |
1237 |
current proof state. |
|
60483 | 1238 |
|
61421 | 1239 |
\<^medskip> |
61657 | 1240 |
Despite the additional infrastructure, both @{method cases} and @{method |
1241 |
coinduct} merely apply a certain rule, after instantiation, while conforming |
|
1242 |
due to the usual way of monotonic natural deduction: the context of a |
|
1243 |
structured statement \<open>\<And>x\<^sub>1 \<dots> x\<^sub>m. \<phi>\<^sub>1 \<Longrightarrow> \<dots> \<phi>\<^sub>n \<Longrightarrow> \<dots>\<close> reappears unchanged after |
|
1244 |
the case split. |
|
60483 | 1245 |
|
61657 | 1246 |
The @{method induct} method is fundamentally different in this respect: the |
1247 |
meta-level structure is passed through the ``recursive'' course involved in |
|
1248 |
the induction. Thus the original statement is basically replaced by separate |
|
1249 |
copies, corresponding to the induction hypotheses and conclusion; the |
|
1250 |
original goal context is no longer available. Thus local assumptions, fixed |
|
1251 |
parameters and definitions effectively participate in the inductive |
|
1252 |
rephrasing of the original statement. |
|
60483 | 1253 |
|
1254 |
In @{method induct} proofs, local assumptions introduced by cases are split |
|
61657 | 1255 |
into two different kinds: \<open>hyps\<close> stemming from the rule and \<open>prems\<close> from the |
1256 |
goal statement. This is reflected in the extracted cases accordingly, so |
|
1257 |
invoking ``@{command "case"}~\<open>c\<close>'' will provide separate facts \<open>c.hyps\<close> and |
|
1258 |
\<open>c.prems\<close>, as well as fact \<open>c\<close> to hold the all-inclusive list. |
|
60483 | 1259 |
|
1260 |
In @{method induction} proofs, local assumptions introduced by cases are |
|
61657 | 1261 |
split into three different kinds: \<open>IH\<close>, the induction hypotheses, \<open>hyps\<close>, |
1262 |
the remaining hypotheses stemming from the rule, and \<open>prems\<close>, the |
|
1263 |
assumptions from the goal statement. The names are \<open>c.IH\<close>, \<open>c.hyps\<close> and |
|
1264 |
\<open>c.prems\<close>, as above. |
|
60483 | 1265 |
|
61421 | 1266 |
\<^medskip> |
61657 | 1267 |
Facts presented to either method are consumed according to the number of |
1268 |
``major premises'' of the rule involved, which is usually 0 for plain cases |
|
1269 |
and induction rules of datatypes etc.\ and 1 for rules of inductive |
|
1270 |
predicates or sets and the like. The remaining facts are inserted into the |
|
1271 |
goal verbatim before the actual \<open>cases\<close>, \<open>induct\<close>, or \<open>coinduct\<close> rule is |
|
60483 | 1272 |
applied. |
1273 |
\<close> |
|
1274 |
||
1275 |
||
1276 |
subsection \<open>Declaring rules\<close> |
|
1277 |
||
1278 |
text \<open> |
|
1279 |
\begin{matharray}{rcl} |
|
61493 | 1280 |
@{command_def "print_induct_rules"}\<open>\<^sup>*\<close> & : & \<open>context \<rightarrow>\<close> \\ |
1281 |
@{attribute_def cases} & : & \<open>attribute\<close> \\ |
|
1282 |
@{attribute_def induct} & : & \<open>attribute\<close> \\ |
|
1283 |
@{attribute_def coinduct} & : & \<open>attribute\<close> \\ |
|
60483 | 1284 |
\end{matharray} |
1285 |
||
69597 | 1286 |
\<^rail>\<open> |
60483 | 1287 |
@@{attribute cases} spec |
1288 |
; |
|
1289 |
@@{attribute induct} spec |
|
1290 |
; |
|
1291 |
@@{attribute coinduct} spec |
|
1292 |
; |
|
1293 |
||
62969 | 1294 |
spec: (('type' | 'pred' | 'set') ':' @{syntax name}) | 'del' |
69597 | 1295 |
\<close> |
60483 | 1296 |
|
61657 | 1297 |
\<^descr> @{command "print_induct_rules"} prints cases and induct rules for |
1298 |
predicates (or sets) and types of the current context. |
|
60483 | 1299 |
|
61657 | 1300 |
\<^descr> @{attribute cases}, @{attribute induct}, and @{attribute coinduct} (as |
1301 |
attributes) declare rules for reasoning about (co)inductive predicates (or |
|
1302 |
sets) and types, using the corresponding methods of the same name. Certain |
|
1303 |
definitional packages of object-logics usually declare emerging cases and |
|
60483 | 1304 |
induction rules as expected, so users rarely need to intervene. |
1305 |
||
61657 | 1306 |
Rules may be deleted via the \<open>del\<close> specification, which covers all of the |
1307 |
\<open>type\<close>/\<open>pred\<close>/\<open>set\<close> sub-categories simultaneously. For example, @{attribute |
|
1308 |
cases}~\<open>del\<close> removes any @{attribute cases} rules declared for some type, |
|
1309 |
predicate, or set. |
|
60483 | 1310 |
|
61657 | 1311 |
Manual rule declarations usually refer to the @{attribute case_names} and |
1312 |
@{attribute params} attributes to adjust names of cases and parameters of a |
|
1313 |
rule; the @{attribute consumes} declaration is taken care of automatically: |
|
1314 |
@{attribute consumes}~\<open>0\<close> is specified for ``type'' rules and @{attribute |
|
61493 | 1315 |
consumes}~\<open>1\<close> for ``predicate'' / ``set'' rules. |
60483 | 1316 |
\<close> |
1317 |
||
1318 |
||
60459 | 1319 |
section \<open>Generalized elimination and case splitting \label{sec:obtain}\<close> |
26870 | 1320 |
|
58618 | 1321 |
text \<open> |
26870 | 1322 |
\begin{matharray}{rcl} |
61493 | 1323 |
@{command_def "consider"} & : & \<open>proof(state) | proof(chain) \<rightarrow> proof(prove)\<close> \\ |
1324 |
@{command_def "obtain"} & : & \<open>proof(state) | proof(chain) \<rightarrow> proof(prove)\<close> \\ |
|
1325 |
@{command_def "guess"}\<open>\<^sup>*\<close> & : & \<open>proof(state) | proof(chain) \<rightarrow> proof(prove)\<close> \\ |
|
26870 | 1326 |
\end{matharray} |
1327 |
||
61657 | 1328 |
Generalized elimination means that hypothetical parameters and premises may |
1329 |
be introduced in the current context, potentially with a split into cases. |
|
1330 |
This works by virtue of a locally proven rule that establishes the soundness |
|
1331 |
of this temporary context extension. As representative examples, one may |
|
1332 |
think of standard rules from Isabelle/HOL like this: |
|
60459 | 1333 |
|
61421 | 1334 |
\<^medskip> |
60459 | 1335 |
\begin{tabular}{ll} |
61493 | 1336 |
\<open>\<exists>x. B x \<Longrightarrow> (\<And>x. B x \<Longrightarrow> thesis) \<Longrightarrow> thesis\<close> \\ |
1337 |
\<open>A \<and> B \<Longrightarrow> (A \<Longrightarrow> B \<Longrightarrow> thesis) \<Longrightarrow> thesis\<close> \\ |
|
1338 |
\<open>A \<or> B \<Longrightarrow> (A \<Longrightarrow> thesis) \<Longrightarrow> (B \<Longrightarrow> thesis) \<Longrightarrow> thesis\<close> \\ |
|
60459 | 1339 |
\end{tabular} |
61421 | 1340 |
\<^medskip> |
60459 | 1341 |
|
1342 |
In general, these particular rules and connectives need to get involved at |
|
61657 | 1343 |
all: this concept works directly in Isabelle/Pure via Isar commands defined |
1344 |
below. In particular, the logic of elimination and case splitting is |
|
1345 |
delegated to an Isar proof, which often involves automated tools. |
|
26870 | 1346 |
|
69597 | 1347 |
\<^rail>\<open> |
60459 | 1348 |
@@{command consider} @{syntax obtain_clauses} |
1349 |
; |
|
63285 | 1350 |
@@{command obtain} @{syntax par_name}? @{syntax vars} \<newline> |
63059
3f577308551e
'obtain' supports structured statements (similar to 'define');
wenzelm
parents:
63039
diff
changeset
|
1351 |
@'where' concl prems @{syntax for_fixes} |
3f577308551e
'obtain' supports structured statements (similar to 'define');
wenzelm
parents:
63039
diff
changeset
|
1352 |
; |
3f577308551e
'obtain' supports structured statements (similar to 'define');
wenzelm
parents:
63039
diff
changeset
|
1353 |
concl: (@{syntax props} + @'and') |
3f577308551e
'obtain' supports structured statements (similar to 'define');
wenzelm
parents:
63039
diff
changeset
|
1354 |
; |
3f577308551e
'obtain' supports structured statements (similar to 'define');
wenzelm
parents:
63039
diff
changeset
|
1355 |
prems: (@'if' (@{syntax props'} + @'and'))? |
26870 | 1356 |
; |
63285 | 1357 |
@@{command guess} @{syntax vars} |
69597 | 1358 |
\<close> |
26870 | 1359 |
|
61657 | 1360 |
\<^descr> @{command consider}~\<open>(a) \<^vec>x \<WHERE> \<^vec>A \<^vec>x | (b) |
1361 |
\<^vec>y \<WHERE> \<^vec>B \<^vec>y | \<dots>\<close> states a rule for case splitting |
|
1362 |
into separate subgoals, such that each case involves new parameters and |
|
1363 |
premises. After the proof is finished, the resulting rule may be used |
|
1364 |
directly with the @{method cases} proof method (\secref{sec:cases-induct}), |
|
1365 |
in order to perform actual case-splitting of the proof text via @{command |
|
1366 |
case} and @{command next} as usual. |
|
60459 | 1367 |
|
61657 | 1368 |
Optional names in round parentheses refer to case names: in the proof of the |
1369 |
rule this is a fact name, in the resulting rule it is used as annotation |
|
1370 |
with the @{attribute_ref case_names} attribute. |
|
60459 | 1371 |
|
61421 | 1372 |
\<^medskip> |
61657 | 1373 |
Formally, the command @{command consider} is defined as derived Isar |
1374 |
language element as follows: |
|
60459 | 1375 |
|
26870 | 1376 |
\begin{matharray}{l} |
61493 | 1377 |
@{command "consider"}~\<open>(a) \<^vec>x \<WHERE> \<^vec>A \<^vec>x | (b) \<^vec>y \<WHERE> \<^vec>B \<^vec>y | \<dots> \<equiv>\<close> \\[1ex] |
1378 |
\quad @{command "have"}~\<open>[case_names a b \<dots>]: thesis\<close> \\ |
|
1379 |
\qquad \<open>\<IF> a [Pure.intro?]: \<And>\<^vec>x. \<^vec>A \<^vec>x \<Longrightarrow> thesis\<close> \\ |
|
1380 |
\qquad \<open>\<AND> b [Pure.intro?]: \<And>\<^vec>y. \<^vec>B \<^vec>y \<Longrightarrow> thesis\<close> \\ |
|
1381 |
\qquad \<open>\<AND> \<dots>\<close> \\ |
|
1382 |
\qquad \<open>\<FOR> thesis\<close> \\ |
|
1383 |
\qquad @{command "apply"}~\<open>(insert a b \<dots>)\<close> \\ |
|
26870 | 1384 |
\end{matharray} |
1385 |
||
60459 | 1386 |
See also \secref{sec:goals} for @{keyword "obtains"} in toplevel goal |
61657 | 1387 |
statements, as well as @{command print_statement} to print existing rules in |
1388 |
a similar format. |
|
26870 | 1389 |
|
61657 | 1390 |
\<^descr> @{command obtain}~\<open>\<^vec>x \<WHERE> \<^vec>A \<^vec>x\<close> states a |
1391 |
generalized elimination rule with exactly one case. After the proof is |
|
1392 |
finished, it is activated for the subsequent proof text: the context is |
|
1393 |
augmented via @{command fix}~\<open>\<^vec>x\<close> @{command assume}~\<open>\<^vec>A |
|
1394 |
\<^vec>x\<close>, with special provisions to export later results by discharging |
|
1395 |
these assumptions again. |
|
60459 | 1396 |
|
1397 |
Note that according to the parameter scopes within the elimination rule, |
|
61657 | 1398 |
results \<^emph>\<open>must not\<close> refer to hypothetical parameters; otherwise the export |
1399 |
will fail! This restriction conforms to the usual manner of existential |
|
1400 |
reasoning in Natural Deduction. |
|
60459 | 1401 |
|
61421 | 1402 |
\<^medskip> |
61657 | 1403 |
Formally, the command @{command obtain} is defined as derived Isar language |
1404 |
element as follows, using an instrumented variant of @{command assume}: |
|
26870 | 1405 |
|
60459 | 1406 |
\begin{matharray}{l} |
61493 | 1407 |
@{command "obtain"}~\<open>\<^vec>x \<WHERE> a: \<^vec>A \<^vec>x \<langle>proof\<rangle> \<equiv>\<close> \\[1ex] |
1408 |
\quad @{command "have"}~\<open>thesis\<close> \\ |
|
1409 |
\qquad \<open>\<IF> that [Pure.intro?]: \<And>\<^vec>x. \<^vec>A \<^vec>x \<Longrightarrow> thesis\<close> \\ |
|
1410 |
\qquad \<open>\<FOR> thesis\<close> \\ |
|
1411 |
\qquad @{command "apply"}~\<open>(insert that)\<close> \\ |
|
1412 |
\qquad \<open>\<langle>proof\<rangle>\<close> \\ |
|
1413 |
\quad @{command "fix"}~\<open>\<^vec>x\<close>~@{command "assume"}\<open>\<^sup>* a: \<^vec>A \<^vec>x\<close> \\ |
|
60459 | 1414 |
\end{matharray} |
1415 |
||
61439 | 1416 |
\<^descr> @{command guess} is similar to @{command obtain}, but it derives the |
60459 | 1417 |
obtained context elements from the course of tactical reasoning in the |
1418 |
proof. Thus it can considerably obscure the proof: it is classified as |
|
61477 | 1419 |
\<^emph>\<open>improper\<close>. |
26870 | 1420 |
|
61493 | 1421 |
A proof with @{command guess} starts with a fixed goal \<open>thesis\<close>. The |
61657 | 1422 |
subsequent refinement steps may turn this to anything of the form |
1423 |
\<open>\<And>\<^vec>x. \<^vec>A \<^vec>x \<Longrightarrow> thesis\<close>, but without splitting into new |
|
1424 |
subgoals. The final goal state is then used as reduction rule for the obtain |
|
1425 |
pattern described above. Obtained parameters \<open>\<^vec>x\<close> are marked as |
|
1426 |
internal by default, and thus inaccessible in the proof text. The variable |
|
1427 |
names and type constraints given as arguments for @{command "guess"} specify |
|
1428 |
a prefix of accessible parameters. |
|
26870 | 1429 |
|
60459 | 1430 |
|
61657 | 1431 |
In the proof of @{command consider} and @{command obtain} the local premises |
1432 |
are always bound to the fact name @{fact_ref that}, according to structured |
|
1433 |
Isar statements involving @{keyword_ref "if"} (\secref{sec:goals}). |
|
60459 | 1434 |
|
61657 | 1435 |
Facts that are established by @{command "obtain"} and @{command "guess"} may |
1436 |
not be polymorphic: any type-variables occurring here are fixed in the |
|
1437 |
present context. This is a natural consequence of the role of @{command fix} |
|
1438 |
and @{command assume} in these constructs. |
|
58618 | 1439 |
\<close> |
26870 | 1440 |
|
26869 | 1441 |
end |