91
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 1
theory Ind_Code
224
+ − 2
imports "../Base" "../FirstSteps" Ind_General_Scheme
91
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 3
begin
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 4
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 5
section {* The Gory Details\label{sec:code} *}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 6
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 7
text {*
237
+ − 8
As mentioned before the code falls roughly into three parts: the code that deals
+ − 9
with the definitions, with the induction principles and with the introduction
+ − 10
rules. In addition there are some administrative functions that string everything
+ − 11
together.
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 12
*}
208
+ − 13
+ − 14
subsection {* Definitions *}
+ − 15
+ − 16
text {*
237
+ − 17
We first have to produce for each predicate the user specifies an appropriate
+ − 18
definition, whose general form is
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 19
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 20
@{text [display] "pred \<equiv> \<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 21
208
+ − 22
and then ``register'' the definition inside a local theory.
237
+ − 23
To do the latter, we use the following wrapper for the function
256
+ − 24
@{ML [index] define in LocalTheory}. The wrapper takes a predicate name, a syntax
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 25
annotation and a term representing the right-hand side of the definition.
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 26
*}
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 27
237
+ − 28
ML %linenosgray{*fun make_defn ((predname, mx), trm) lthy =
164
+ − 29
let
237
+ − 30
val arg = ((predname, mx), (Attrib.empty_binding, trm))
176
+ − 31
val ((_, (_ , thm)), lthy') = LocalTheory.define Thm.internalK arg lthy
164
+ − 32
in
176
+ − 33
(thm, lthy')
164
+ − 34
end*}
+ − 35
+ − 36
text {*
237
+ − 37
It returns the definition (as a theorem) and the local theory in which the
256
+ − 38
definition has been made. In Line 4, @{ML [index] internalK in Thm} is a flag
+ − 39
attached to the theorem (others possibile flags are @{ML [index] definitionK in Thm}
+ − 40
and @{ML [index] axiomK in Thm}). These flags just classify theorems and have no
237
+ − 41
significant meaning, except for tools that, for example, find theorems in
+ − 42
the theorem database.\footnote{FIXME: put in the section about theorems.} We
256
+ − 43
also use @{ML [index] empty_binding in Attrib} in Line 3, since the definitions for
237
+ − 44
our inductive predicates are not meant to be seen by the user and therefore
+ − 45
do not need to have any theorem attributes. A testcase for this function is
164
+ − 46
*}
+ − 47
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 48
local_setup %gray {* fn lthy =>
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 49
let
237
+ − 50
val arg = ((@{binding "My_True"}, NoSyn), @{term True})
210
+ − 51
val (def, lthy') = make_defn arg lthy
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 52
in
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 53
writeln (string_of_thm_no_vars lthy' def); lthy'
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 54
end *}
164
+ − 55
+ − 56
text {*
237
+ − 57
which introduces the definition @{thm My_True_def} and then prints it out.
208
+ − 58
Since we are testing the function inside \isacommand{local\_setup}, i.e., make
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 59
actual changes to the ambient theory, we can query the definition with the usual
183
+ − 60
command \isacommand{thm}:
179
+ − 61
+ − 62
\begin{isabelle}
237
+ − 63
\isacommand{thm}~@{thm [source] "My_True_def"}\\
+ − 64
@{text ">"}~@{thm "My_True_def"}
179
+ − 65
\end{isabelle}
164
+ − 66
208
+ − 67
The next two functions construct the right-hand sides of the definitions,
237
+ − 68
which are terms whose general form is:
179
+ − 69
190
+ − 70
@{text [display] "\<lambda>zs. \<forall>preds. orules \<longrightarrow> pred zs"}
179
+ − 71
237
+ − 72
When constructing these terms, the variables @{text "zs"} need to be chosen so
+ − 73
that they do not occur in the @{text orules} and also be distinct from the
+ − 74
@{text "preds"}.
208
+ − 75
183
+ − 76
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 77
The first function, named @{text defn_aux}, constructs the term for one
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 78
particular predicate (the argument @{text "pred"} in the code below). The
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 79
number of arguments of this predicate is determined by the number of
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 80
argument types given in @{text "arg_tys"}. The other arguments of the
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 81
function are the @{text orules} and all the @{text "preds"}.
164
+ − 82
*}
+ − 83
210
+ − 84
ML %linenosgray{*fun defn_aux lthy orules preds (pred, arg_tys) =
164
+ − 85
let
+ − 86
fun mk_all x P = HOLogic.all_const (fastype_of x) $ lambda x P
+ − 87
+ − 88
val fresh_args =
176
+ − 89
arg_tys
164
+ − 90
|> map (pair "z")
179
+ − 91
|> Variable.variant_frees lthy (preds @ orules)
164
+ − 92
|> map Free
+ − 93
in
+ − 94
list_comb (pred, fresh_args)
+ − 95
|> fold_rev (curry HOLogic.mk_imp) orules
+ − 96
|> fold_rev mk_all preds
+ − 97
|> fold_rev lambda fresh_args
+ − 98
end*}
+ − 99
+ − 100
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 101
The function @{text mk_all} in Line 3 is just a helper function for constructing
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 102
universal quantifications. The code in Lines 5 to 9 produces the fresh @{text
190
+ − 103
"zs"}. For this it pairs every argument type with the string
184
+ − 104
@{text [quotes] "z"} (Line 7); then generates variants for all these strings
190
+ − 105
so that they are unique w.r.t.~to the predicates and @{text "orules"} (Line 8);
184
+ − 106
in Line 9 it generates the corresponding variable terms for the unique
+ − 107
strings.
164
+ − 108
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 109
The unique variables are applied to the predicate in Line 11 using the
183
+ − 110
function @{ML list_comb}; then the @{text orules} are prefixed (Line 12); in
+ − 111
Line 13 we quantify over all predicates; and in line 14 we just abstract
208
+ − 112
over all the @{text "zs"}, i.e., the fresh arguments of the
190
+ − 113
predicate. A testcase for this function is
164
+ − 114
*}
+ − 115
179
+ − 116
local_setup %gray{* fn lthy =>
176
+ − 117
let
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 118
val def = defn_aux lthy eo_orules eo_preds (e_pred, e_arg_tys)
173
+ − 119
in
239
+ − 120
writeln (Syntax.string_of_term lthy def); lthy
179
+ − 121
end *}
173
+ − 122
91
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 123
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 124
where we use the shorthands defined in Figure~\ref{fig:shorthands}.
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 125
The testcase calls @{ML defn_aux} for the predicate @{text "even"} and prints
208
+ − 126
out the generated definition. So we obtain as printout
179
+ − 127
+ − 128
@{text [display]
+ − 129
"\<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))
+ − 130
\<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z"}
+ − 131
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 132
If we try out the function with the rules for freshness
210
+ − 133
*}
+ − 134
+ − 135
local_setup %gray{* fn lthy =>
239
+ − 136
(writeln (Syntax.string_of_term lthy
210
+ − 137
(defn_aux lthy fresh_orules [fresh_pred] (fresh_pred, fresh_arg_tys)));
+ − 138
lthy) *}
+ − 139
+ − 140
text {*
+ − 141
we obtain
+ − 142
+ − 143
@{term [display]
+ − 144
"\<lambda>z za. \<forall>fresh. (\<forall>a b. \<not> a = b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
+ − 145
(\<forall>a s t. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
+ − 146
(\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
+ − 147
(\<forall>a b t. \<not> a = b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh z za"}
+ − 148
+ − 149
237
+ − 150
The second function, named @{text defns}, has to iterate the function
210
+ − 151
@{ML defn_aux} over all predicates. The argument @{text "preds"} is again
237
+ − 152
the list of predicates as @{ML_type term}s; the argument @{text
+ − 153
"prednames"} is the list of binding names of the predicates; @{text mxs}
+ − 154
are the list of syntax, or mixfix, annotations for the predicates;
+ − 155
@{text "arg_tyss"} is the list of argument-type-lists.
164
+ − 156
*}
+ − 157
237
+ − 158
ML %linenosgray{*fun defns rules preds prednames mxs arg_typss lthy =
164
+ − 159
let
+ − 160
val thy = ProofContext.theory_of lthy
+ − 161
val orules = map (ObjectLogic.atomize_term thy) rules
210
+ − 162
val defs = map (defn_aux lthy orules preds) (preds ~~ arg_typss)
164
+ − 163
in
237
+ − 164
fold_map make_defn (prednames ~~ mxs ~~ defs) lthy
164
+ − 165
end*}
+ − 166
+ − 167
text {*
184
+ − 168
The user will state the introduction rules using meta-implications and
237
+ − 169
meta-quanti\-fications. In Line 4, we transform these introduction rules
+ − 170
into the object logic (since definitions cannot be stated with
184
+ − 171
meta-connectives). To do this transformation we have to obtain the theory
+ − 172
behind the local theory (Line 3); with this theory we can use the function
256
+ − 173
@{ML [index] atomize_term in ObjectLogic} to make the transformation (Line 4). The call
210
+ − 174
to @{ML defn_aux} in Line 5 produces all right-hand sides of the
237
+ − 175
definitions. The actual definitions are then made in Line 7. The result of
+ − 176
the function is a list of theorems and a local theory (the theorems are
+ − 177
registered with the local theory). A testcase for this function is
164
+ − 178
*}
+ − 179
179
+ − 180
local_setup %gray {* fn lthy =>
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 181
let
208
+ − 182
val (defs, lthy') =
237
+ − 183
defns eo_rules eo_preds eo_prednames eo_mxs eo_arg_tyss lthy
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 184
in
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 185
writeln (string_of_thms_no_vars lthy' defs); lthy
179
+ − 186
end *}
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 187
179
+ − 188
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 189
where we feed into the function all parameters corresponding to
184
+ − 190
the @{text even}-@{text odd} example. The definitions we obtain
+ − 191
are:
179
+ − 192
210
+ − 193
@{text [display, break]
+ − 194
"even \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))
+ − 195
\<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> even z,
+ − 196
odd \<equiv> \<lambda>z. \<forall>even odd. (even 0) \<longrightarrow> (\<forall>n. odd n \<longrightarrow> even (Suc n))
+ − 197
\<longrightarrow> (\<forall>n. even n \<longrightarrow> odd (Suc n)) \<longrightarrow> odd z"}
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 198
208
+ − 199
Note that in the testcase we return the local theory @{text lthy}
+ − 200
(not the modified @{text lthy'}). As a result the test case has no effect
210
+ − 201
on the ambient theory. The reason is that if we introduce the
+ − 202
definition again, we pollute the name space with two versions of @{text "even"}
208
+ − 203
and @{text "odd"}.
164
+ − 204
210
+ − 205
This completes the code for introducing the definitions. Next we deal with
208
+ − 206
the induction principles.
+ − 207
*}
+ − 208
210
+ − 209
subsection {* Induction Principles *}
208
+ − 210
+ − 211
text {*
215
+ − 212
Recall that the manual proof for the induction principle
+ − 213
of @{text "even"} was:
179
+ − 214
*}
176
+ − 215
210
+ − 216
lemma manual_ind_prin_even:
209
+ − 217
assumes prem: "even z"
+ − 218
shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
176
+ − 219
apply(atomize (full))
209
+ − 220
apply(cut_tac prem)
176
+ − 221
apply(unfold even_def)
+ − 222
apply(drule spec[where x=P])
+ − 223
apply(drule spec[where x=Q])
+ − 224
apply(assumption)
+ − 225
done
+ − 226
179
+ − 227
text {*
190
+ − 228
The code for automating such induction principles has to accomplish two tasks:
184
+ − 229
constructing the induction principles from the given introduction
190
+ − 230
rules and then automatically generating proofs for them using a tactic.
183
+ − 231
+ − 232
The tactic will use the following helper function for instantiating universal
184
+ − 233
quantifiers.
179
+ − 234
*}
176
+ − 235
179
+ − 236
ML{*fun inst_spec ctrm =
+ − 237
Drule.instantiate' [SOME (ctyp_of_term ctrm)] [NONE, SOME ctrm] @{thm spec}*}
164
+ − 238
+ − 239
text {*
184
+ − 240
This helper function instantiates the @{text "?x"} in the theorem
208
+ − 241
@{thm spec} with a given @{ML_type cterm}. We call this helper function
215
+ − 242
in the following tactic, called @{text inst_spec_tac}\label{fun:instspectac}.
164
+ − 243
*}
+ − 244
183
+ − 245
ML{*fun inst_spec_tac ctrms =
+ − 246
EVERY' (map (dtac o inst_spec) ctrms)*}
+ − 247
+ − 248
text {*
212
+ − 249
This tactic expects a list of @{ML_type cterm}s. It allows us in the
+ − 250
proof below to instantiate the three quantifiers in the assumption.
184
+ − 251
*}
183
+ − 252
184
+ − 253
lemma
224
+ − 254
fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
+ − 255
shows "\<forall>x y z. P x y z \<Longrightarrow> True"
176
+ − 256
apply (tactic {*
212
+ − 257
inst_spec_tac [@{cterm "a::nat"},@{cterm "b::nat"},@{cterm "c::nat"}] 1 *})
179
+ − 258
txt {*
183
+ − 259
We obtain the goal state
179
+ − 260
+ − 261
\begin{minipage}{\textwidth}
+ − 262
@{subgoals}
+ − 263
\end{minipage}*}
164
+ − 264
(*<*)oops(*>*)
+ − 265
+ − 266
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 267
The complete tactic for proving the induction principles can now
183
+ − 268
be implemented as follows:
163
2319cff107f0
removed rep_ss, and used dest_ss instead; some very slight changes to simple_inductive
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 269
*}
2319cff107f0
removed rep_ss, and used dest_ss instead; some very slight changes to simple_inductive
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 270
210
+ − 271
ML %linenosgray{*fun ind_tac defs prem insts =
176
+ − 272
EVERY1 [ObjectLogic.full_atomize_tac,
208
+ − 273
cut_facts_tac prem,
164
+ − 274
K (rewrite_goals_tac defs),
183
+ − 275
inst_spec_tac insts,
164
+ − 276
assume_tac]*}
+ − 277
179
+ − 278
text {*
215
+ − 279
We have to give it as arguments the definitions, the premise (a list of
+ − 280
formulae) and the instantiations. The premise is @{text "even n"} in lemma
+ − 281
@{thm [source] manual_ind_prin_even}; in our code it will always be a list
+ − 282
consisting of a single formula. Compare this tactic with the manual proof
+ − 283
for the lemma @{thm [source] manual_ind_prin_even}: as you can see there is
+ − 284
almost a one-to-one correspondence between the \isacommand{apply}-script and
+ − 285
the @{ML ind_tac}. Two testcases for this tactic are:
183
+ − 286
*}
+ − 287
210
+ − 288
lemma automatic_ind_prin_even:
208
+ − 289
assumes prem: "even z"
+ − 290
shows "P 0 \<Longrightarrow> (\<And>m. Q m \<Longrightarrow> P (Suc m)) \<Longrightarrow> (\<And>m. P m \<Longrightarrow> Q (Suc m)) \<Longrightarrow> P z"
210
+ − 291
by (tactic {* ind_tac eo_defs @{thms prem}
+ − 292
[@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}] *})
+ − 293
+ − 294
lemma automatic_ind_prin_fresh:
+ − 295
assumes prem: "fresh z za"
+ − 296
shows "(\<And>a b. a \<noteq> b \<Longrightarrow> P a (Var b)) \<Longrightarrow>
+ − 297
(\<And>a t s. \<lbrakk>P a t; P a s\<rbrakk> \<Longrightarrow> P a (App t s)) \<Longrightarrow>
+ − 298
(\<And>a t. P a (Lam a t)) \<Longrightarrow>
+ − 299
(\<And>a b t. \<lbrakk>a \<noteq> b; P a t\<rbrakk> \<Longrightarrow> P a (Lam b t)) \<Longrightarrow> P z za"
+ − 300
by (tactic {* ind_tac @{thms fresh_def} @{thms prem}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 301
[@{cterm "P::string\<Rightarrow>trm\<Rightarrow>bool"}] *})
210
+ − 302
164
+ − 303
165
+ − 304
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 305
While the tactic for proving the induction principles is relatively simple,
237
+ − 306
it will be a bit more work to construct the goals from the introduction rules
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 307
the user provides. Therefore let us have a closer look at the first
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 308
proved theorem:
209
+ − 309
+ − 310
\begin{isabelle}
210
+ − 311
\isacommand{thm}~@{thm [source] automatic_ind_prin_even}\\
+ − 312
@{text "> "}~@{thm automatic_ind_prin_even}
209
+ − 313
\end{isabelle}
+ − 314
210
+ − 315
The variables @{text "z"}, @{text "P"} and @{text "Q"} are schematic
215
+ − 316
variables (since they are not quantified in the lemma). These
+ − 317
variables must be schematic, otherwise they cannot be instantiated
+ − 318
by the user. To generate these schematic variables we use a common trick
+ − 319
in Isabelle programming: we first declare them as \emph{free},
+ − 320
\emph{but fixed}, and then use the infrastructure to turn them into
+ − 321
schematic variables.
+ − 322
+ − 323
In general we have to construct for each predicate @{text "pred"} a goal
+ − 324
of the form
179
+ − 325
+ − 326
@{text [display]
208
+ − 327
"pred ?zs \<Longrightarrow> rules[preds := ?Ps] \<Longrightarrow> ?P ?zs"}
180
+ − 328
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 329
where the predicates @{text preds} are replaced in @{text rules} by new
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 330
distinct variables @{text "?Ps"}. We also need to generate fresh arguments
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 331
@{text "?zs"} for the predicate @{text "pred"} and the @{text "?P"} in
215
+ − 332
the conclusion.
190
+ − 333
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 334
We generate these goals in two steps. The first function, named @{text prove_ind},
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 335
expects that the introduction rules are already appropriately substituted. The argument
208
+ − 336
@{text "srules"} stands for these substituted rules; @{text cnewpreds} are
+ − 337
the certified terms coresponding to the variables @{text "?Ps"}; @{text
210
+ − 338
"pred"} is the predicate for which we prove the induction principle;
208
+ − 339
@{text "newpred"} is its replacement and @{text "arg_tys"} are the argument
+ − 340
types of this predicate.
165
+ − 341
*}
+ − 342
210
+ − 343
ML %linenosgray{*fun prove_ind lthy defs srules cnewpreds ((pred, newpred), arg_tys) =
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 344
let
190
+ − 345
val zs = replicate (length arg_tys) "z"
179
+ − 346
val (newargnames, lthy') = Variable.variant_fixes zs lthy;
190
+ − 347
val newargs = map Free (newargnames ~~ arg_tys)
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 348
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 349
val prem = HOLogic.mk_Trueprop (list_comb (pred, newargs))
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 350
val goal = Logic.list_implies
183
+ − 351
(srules, HOLogic.mk_Trueprop (list_comb (newpred, newargs)))
178
fb8f22dd8ad0
adapted to latest Attrib.setup changes and more work on the simple induct chapter
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 352
in
179
+ − 353
Goal.prove lthy' [] [prem] goal
210
+ − 354
(fn {prems, ...} => ind_tac defs prems cnewpreds)
179
+ − 355
|> singleton (ProofContext.export lthy' lthy)
+ − 356
end *}
+ − 357
180
+ − 358
text {*
190
+ − 359
In Line 3 we produce names @{text "zs"} for each type in the
183
+ − 360
argument type list. Line 4 makes these names unique and declares them as
215
+ − 361
free, but fixed, variables in the local theory @{text "lthy'"}.
212
+ − 362
That means they are not schematic variables (yet).
210
+ − 363
In Line 5 we construct the terms corresponding to these variables.
208
+ − 364
The variables are applied to the predicate in Line 7 (this corresponds
190
+ − 365
to the first premise @{text "pred zs"} of the induction principle).
+ − 366
In Line 8 and 9, we first construct the term @{text "P zs"}
212
+ − 367
and then add the (substituted) introduction rules as preconditions. In
+ − 368
case that no introduction rules are given, the conclusion of this
+ − 369
implication needs to be wrapped inside a @{term Trueprop}, otherwise
+ − 370
the Isabelle's goal mechanism will fail.\footnote{FIXME: check with
+ − 371
Stefan...is this so?}
180
+ − 372
208
+ − 373
In Line 11 we set up the goal to be proved; in the next line we call the
+ − 374
tactic for proving the induction principle. As mentioned before, this tactic
+ − 375
expects the definitions, the premise and the (certified) predicates with
+ − 376
which the introduction rules have been substituted. The code in these two
+ − 377
lines will return a theorem. However, it is a theorem
184
+ − 378
proved inside the local theory @{text "lthy'"}, where the variables @{text
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 379
"zs"} are free, but fixed (see Line 4). By exporting this theorem from @{text
210
+ − 380
"lthy'"} (which contains the @{text "zs"} as free variables) to @{text
208
+ − 381
"lthy"} (which does not), we obtain the desired schematic variables @{text "?zs"}.
+ − 382
A testcase for this function is
190
+ − 383
*}
180
+ − 384
190
+ − 385
local_setup %gray{* fn lthy =>
+ − 386
let
210
+ − 387
val newpreds = [@{term "P::nat\<Rightarrow>bool"}, @{term "Q::nat\<Rightarrow>bool"}]
190
+ − 388
val cnewpreds = [@{cterm "P::nat\<Rightarrow>bool"}, @{cterm "Q::nat\<Rightarrow>bool"}]
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 389
val newpred = @{term "P::nat\<Rightarrow>bool"}
210
+ − 390
val srules = map (subst_free (eo_preds ~~ newpreds)) eo_rules
190
+ − 391
val intro =
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 392
prove_ind lthy eo_defs srules cnewpreds ((e_pred, newpred), e_arg_tys)
190
+ − 393
in
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 394
writeln (string_of_thm lthy intro); lthy
210
+ − 395
end *}
184
+ − 396
190
+ − 397
text {*
210
+ − 398
This prints out the theorem:
190
+ − 399
+ − 400
@{text [display]
+ − 401
" \<lbrakk>even ?z; P 0; \<And>n. Q n \<Longrightarrow> P (Suc n); \<And>n. P n \<Longrightarrow> Q (Suc n)\<rbrakk> \<Longrightarrow> P ?z"}
+ − 402
210
+ − 403
The export from @{text lthy'} to @{text lthy} in Line 13 above
+ − 404
has correctly turned the free, but fixed, @{text "z"} into a schematic
209
+ − 405
variable @{text "?z"}; the variables @{text "P"} and @{text "Q"} are not yet
208
+ − 406
schematic.
190
+ − 407
+ − 408
We still have to produce the new predicates with which the introduction
210
+ − 409
rules are substituted and iterate @{ML prove_ind} over all
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 410
predicates. This is what the second function, named @{text inds} does.
180
+ − 411
*}
165
+ − 412
210
+ − 413
ML %linenosgray{*fun inds rules defs preds arg_tyss lthy =
164
+ − 414
let
+ − 415
val Ps = replicate (length preds) "P"
183
+ − 416
val (newprednames, lthy') = Variable.variant_fixes Ps lthy
164
+ − 417
183
+ − 418
val thy = ProofContext.theory_of lthy'
164
+ − 419
184
+ − 420
val tyss' = map (fn tys => tys ---> HOLogic.boolT) arg_tyss
165
+ − 421
val newpreds = map Free (newprednames ~~ tyss')
164
+ − 422
val cnewpreds = map (cterm_of thy) newpreds
184
+ − 423
val srules = map (subst_free (preds ~~ newpreds)) rules
164
+ − 424
+ − 425
in
210
+ − 426
map (prove_ind lthy' defs srules cnewpreds)
184
+ − 427
(preds ~~ newpreds ~~ arg_tyss)
183
+ − 428
|> ProofContext.export lthy' lthy
165
+ − 429
end*}
+ − 430
184
+ − 431
text {*
208
+ − 432
In Line 3, we generate a string @{text [quotes] "P"} for each predicate.
184
+ − 433
In Line 4, we use the same trick as in the previous function, that is making the
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 434
@{text "Ps"} fresh and declaring them as free, but fixed, in
184
+ − 435
the new local theory @{text "lthy'"}. From the local theory we extract
+ − 436
the ambient theory in Line 6. We need this theory in order to certify
208
+ − 437
the new predicates. In Line 8, we construct the types of these new predicates
190
+ − 438
using the given argument types. Next we turn them into terms and subsequently
+ − 439
certify them (Line 9 and 10). We can now produce the substituted introduction rules
256
+ − 440
(Line 11) using the function @{ML [index] subst_free}. Line 14 and 15 just iterate
190
+ − 441
the proofs for all predicates.
184
+ − 442
From this we obtain a list of theorems. Finally we need to export the
208
+ − 443
fixed variables @{text "Ps"} to obtain the schematic variables @{text "?Ps"}
184
+ − 444
(Line 16).
+ − 445
+ − 446
A testcase for this function is
+ − 447
*}
+ − 448
+ − 449
local_setup %gray {* fn lthy =>
+ − 450
let
210
+ − 451
val ind_thms = inds eo_rules eo_defs eo_preds eo_arg_tyss lthy
184
+ − 452
in
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 453
writeln (string_of_thms lthy ind_thms); lthy
190
+ − 454
end *}
165
+ − 455
176
+ − 456
184
+ − 457
text {*
+ − 458
which prints out
+ − 459
+ − 460
@{text [display]
210
+ − 461
"even ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
+ − 462
(\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?P1 ?z,
+ − 463
odd ?z \<Longrightarrow> ?P1 0 \<Longrightarrow>
+ − 464
(\<And>m. ?Pa1 m \<Longrightarrow> ?P1 (Suc m)) \<Longrightarrow> (\<And>m. ?P1 m \<Longrightarrow> ?Pa1 (Suc m)) \<Longrightarrow> ?Pa1 ?z"}
184
+ − 465
208
+ − 466
Note that now both, the @{text "?Ps"} and the @{text "?zs"}, are schematic
210
+ − 467
variables. The numbers attached to these variables have been introduced by
+ − 468
the pretty-printer and are \emph{not} important for the user.
184
+ − 469
210
+ − 470
This completes the code for the induction principles. The final peice
+ − 471
of reasoning infrastructure we need are the introduction rules.
208
+ − 472
*}
+ − 473
+ − 474
subsection {* Introduction Rules *}
+ − 475
+ − 476
text {*
212
+ − 477
Constructing the goals for the introduction rules is easy: they
+ − 478
are just the rules given by the user. However, their proofs are
+ − 479
quite a bit more involved than the ones for the induction principles.
+ − 480
To explain the general method, our running example will be
+ − 481
the introduction rule
208
+ − 482
212
+ − 483
\begin{isabelle}
+ − 484
@{prop "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"}
+ − 485
\end{isabelle}
+ − 486
+ − 487
about freshness for lambdas. In order to ease somewhat
+ − 488
our work here, we use the following two helper functions.
184
+ − 489
*}
+ − 490
165
+ − 491
ML{*val all_elims = fold (fn ct => fn th => th RS inst_spec ct)
+ − 492
val imp_elims = fold (fn th => fn th' => [th', th] MRS @{thm mp})*}
+ − 493
190
+ − 494
text {*
212
+ − 495
To see what these functions do, let us suppose we have the following three
190
+ − 496
theorems.
+ − 497
*}
+ − 498
+ − 499
lemma all_elims_test:
224
+ − 500
fixes P::"nat \<Rightarrow> nat \<Rightarrow> nat \<Rightarrow> bool"
+ − 501
shows "\<forall>x y z. P x y z" sorry
190
+ − 502
+ − 503
lemma imp_elims_test:
224
+ − 504
shows "A \<longrightarrow> B \<longrightarrow> C" sorry
190
+ − 505
+ − 506
lemma imp_elims_test':
224
+ − 507
shows "A" "B" sorry
190
+ − 508
+ − 509
text {*
+ − 510
The function @{ML all_elims} takes a list of (certified) terms and instantiates
+ − 511
theorems of the form @{thm [source] all_elims_test}. For example we can instantiate
210
+ − 512
the quantifiers in this theorem with @{term a}, @{term b} and @{term c} as follows:
190
+ − 513
+ − 514
@{ML_response_fake [display, gray]
+ − 515
"let
+ − 516
val ctrms = [@{cterm \"a::nat\"}, @{cterm \"b::nat\"}, @{cterm \"c::nat\"}]
+ − 517
val new_thm = all_elims ctrms @{thm all_elims_test}
+ − 518
in
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 519
writeln (string_of_thm_no_vars @{context} new_thm)
190
+ − 520
end"
+ − 521
"P a b c"}
+ − 522
215
+ − 523
Note the difference with @{ML inst_spec_tac} from Page~\pageref{fun:instspectac}:
+ − 524
@{ML inst_spec_tac} is a tactic which operates on a goal state; in contrast
+ − 525
@{ML all_elims} operates on theorems.
+ − 526
190
+ − 527
Similarly, the function @{ML imp_elims} eliminates preconditions from implications.
210
+ − 528
For example we can eliminate the preconditions @{text "A"} and @{text "B"} from
+ − 529
@{thm [source] imp_elims_test}:
190
+ − 530
+ − 531
@{ML_response_fake [display, gray]
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 532
"writeln (string_of_thm_no_vars @{context}
190
+ − 533
(imp_elims @{thms imp_elims_test'} @{thm imp_elims_test}))"
+ − 534
"C"}
+ − 535
212
+ − 536
Now we set up the proof for the introduction rule as follows:
190
+ − 537
*}
+ − 538
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 539
lemma fresh_Lam:
224
+ − 540
shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
210
+ − 541
(*<*)oops(*>*)
+ − 542
+ − 543
text {*
212
+ − 544
The first step in the proof will be to expand the definitions of freshness
210
+ − 545
and then introduce quantifiers and implications. For this we
+ − 546
will use the tactic
+ − 547
*}
+ − 548
212
+ − 549
ML %linenosgray{*fun expand_tac defs =
210
+ − 550
ObjectLogic.rulify_tac 1
+ − 551
THEN rewrite_goals_tac defs
+ − 552
THEN (REPEAT (resolve_tac [@{thm allI}, @{thm impI}] 1)) *}
+ − 553
+ − 554
text {*
212
+ − 555
The function in Line 2 ``rulifies'' the lemma. This will turn out to
215
+ − 556
be important later on. Applying this tactic in our proof of @{text "fresh_Lem"}
210
+ − 557
*}
+ − 558
+ − 559
(*<*)
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 560
lemma fresh_Lam:
224
+ − 561
shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
210
+ − 562
(*>*)
+ − 563
apply(tactic {* expand_tac @{thms fresh_def} *})
209
+ − 564
+ − 565
txt {*
215
+ − 566
gives us the goal state
210
+ − 567
209
+ − 568
\begin{isabelle}
210
+ − 569
@{subgoals [display]}
209
+ − 570
\end{isabelle}
210
+ − 571
215
+ − 572
As you can see, there are parameters (namely @{text "a"}, @{text "b"} and
+ − 573
@{text "t"}) which come from the introduction rule and parameters (in the
+ − 574
case above only @{text "fresh"}) which come from the universal
+ − 575
quantification in the definition @{term "fresh a (App t s)"}. Similarly,
+ − 576
there are assumptions that come from the premises of the rule (namely the
+ − 577
first two) and assumptions from the definition of the predicate (assumption
+ − 578
three to six). We need to treat these parameters and assumptions
+ − 579
differently. In the code below we will therefore separate them into @{text
+ − 580
"params1"} and @{text params2}, respectively @{text "prems1"} and @{text
+ − 581
"prems2"}. To do this separation, it is best to open a subproof with the
256
+ − 582
tactic @{ML [index] SUBPROOF}, since this tactic provides us with the parameters (as
215
+ − 583
list of @{ML_type cterm}s) and the assumptions (as list of @{ML_type thm}s).
+ − 584
The problem we have to overcome with @{ML SUBPROOF}
+ − 585
is, however, that this tactic always expects us to completely discharge the
+ − 586
goal (see Section~\ref{sec:simpletacs}). This is inconvenient for our
+ − 587
gradual explanation of the proof here. To circumvent this inconvenience we
+ − 588
use the following modified tactic:
210
+ − 589
*}
+ − 590
(*<*)oops(*>*)
+ − 591
ML{*fun SUBPROOF_test tac ctxt = (SUBPROOF tac ctxt 1) ORELSE all_tac*}
+ − 592
+ − 593
text {*
+ − 594
If the tactic inside @{ML SUBPROOF} fails, then the overall tactic will
+ − 595
still succeed. With this testing tactic, we can gradually implement
212
+ − 596
all necessary proof steps inside a subproof. Once we are finished, we
+ − 597
just have to replace it with @{ML SUBPROOF}.
210
+ − 598
*}
+ − 599
+ − 600
text_raw {*
+ − 601
\begin{figure}[t]
+ − 602
\begin{minipage}{\textwidth}
+ − 603
\begin{isabelle}
+ − 604
*}
+ − 605
ML{*fun chop_print params1 params2 prems1 prems2 ctxt =
+ − 606
let
250
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 607
val s = ["Params1 from the rule:", string_of_cterms ctxt params1]
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 608
@ ["Params2 from the predicate:", string_of_cterms ctxt params2]
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 609
@ ["Prems1 from the rule:"] @ (map (string_of_thm ctxt) prems1)
ab9e09076462
some polishing; added together with Jasmin more examples to the pretty printing section
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 610
@ ["Prems2 from the predicate:"] @ (map (string_of_thm ctxt) prems2)
210
+ − 611
in
+ − 612
s |> separate "\n"
+ − 613
|> implode
239
+ − 614
|> writeln
210
+ − 615
end*}
+ − 616
text_raw{*
+ − 617
\end{isabelle}
+ − 618
\end{minipage}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 619
\caption{A helper function that prints out the parameters and premises that
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 620
need to be treated differently.\label{fig:chopprint}}
210
+ − 621
\end{figure}
+ − 622
*}
+ − 623
+ − 624
text {*
+ − 625
First we calculate the values for @{text "params1/2"} and @{text "prems1/2"}
212
+ − 626
from @{text "params"} and @{text "prems"}, respectively. To better see what is
+ − 627
going in our example, we will print out these values using the printing
210
+ − 628
function in Figure~\ref{fig:chopprint}. Since the tactic @{ML SUBPROOF} will
+ − 629
supply us the @{text "params"} and @{text "prems"} as lists, we can
256
+ − 630
separate them using the function @{ML [index] chop}.
210
+ − 631
*}
+ − 632
+ − 633
ML{*fun chop_test_tac preds rules =
+ − 634
SUBPROOF_test (fn {params, prems, context, ...} =>
+ − 635
let
+ − 636
val (params1, params2) = chop (length params - length preds) params
+ − 637
val (prems1, prems2) = chop (length prems - length rules) prems
+ − 638
in
+ − 639
chop_print params1 params2 prems1 prems2 context; no_tac
+ − 640
end) *}
+ − 641
+ − 642
text {*
212
+ − 643
For the separation we can rely on the fact that Isabelle deterministically
+ − 644
produces parameters and premises in a goal state. The last parameters
+ − 645
that were introduced come from the quantifications in the definitions
+ − 646
(see the tactic @{ML expand_tac}).
210
+ − 647
Therefore we only have to subtract the number of predicates (in this
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 648
case only @{text "1"}) from the lenghts of all parameters. Similarly
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 649
with the @{text "prems"}: the last premises in the goal state come from
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 650
unfolding the definition of the predicate in the conclusion. So we can
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 651
just subtract the number of rules from the number of all premises.
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 652
Applying this tactic in our example
209
+ − 653
*}
+ − 654
210
+ − 655
(*<*)
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 656
lemma fresh_Lam:
224
+ − 657
shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
210
+ − 658
apply(tactic {* expand_tac @{thms fresh_def} *})
+ − 659
(*>*)
+ − 660
apply(tactic {* chop_test_tac [fresh_pred] fresh_rules @{context} *})
+ − 661
(*<*)oops(*>*)
+ − 662
+ − 663
text {*
+ − 664
gives
209
+ − 665
210
+ − 666
\begin{isabelle}
+ − 667
@{text "Params1 from the rule:"}\\
+ − 668
@{text "a, b, t"}\\
+ − 669
@{text "Params2 from the predicate:"}\\
+ − 670
@{text "fresh"}\\
+ − 671
@{text "Prems1 from the rule:"}\\
+ − 672
@{term "a \<noteq> b"}\\
+ − 673
@{text [break]
+ − 674
"\<forall>fresh.
+ − 675
(\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
+ − 676
(\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
+ − 677
(\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
+ − 678
(\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}\\
+ − 679
@{text "Prems2 from the predicate:"}\\
+ − 680
@{term "\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)"}\\
+ − 681
@{term "\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)"}\\
+ − 682
@{term "\<forall>a t. fresh a (Lam a t)"}\\
+ − 683
@{term "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)"}
+ − 684
\end{isabelle}
208
+ − 685
192
+ − 686
210
+ − 687
We now have to select from @{text prems2} the premise
+ − 688
that corresponds to the introduction rule we prove, namely:
+ − 689
212
+ − 690
@{term [display] "\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam a t)"}
210
+ − 691
+ − 692
To use this premise with @{ML rtac}, we need to instantiate its
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 693
quantifiers (with @{text params1}) and transform it into rule
256
+ − 694
format (using @{ML [index] rulify in ObjectLogic}. So we can modify the
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 695
subproof as follows:
210
+ − 696
*}
+ − 697
212
+ − 698
ML %linenosgray{*fun apply_prem_tac i preds rules =
210
+ − 699
SUBPROOF_test (fn {params, prems, context, ...} =>
+ − 700
let
+ − 701
val (params1, params2) = chop (length params - length preds) params
+ − 702
val (prems1, prems2) = chop (length prems - length rules) prems
+ − 703
in
+ − 704
rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
+ − 705
THEN print_tac ""
+ − 706
THEN no_tac
+ − 707
end) *}
+ − 708
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 709
text {*
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 710
The argument @{text i} corresponds to the number of the
215
+ − 711
introduction we want to prove. We will later on let it range
212
+ − 712
from @{text 0} to the number of @{text "rules - 1"}.
+ − 713
Below we apply this function with @{text 3}, since
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 714
we are proving the fourth introduction rule.
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 715
*}
210
+ − 716
+ − 717
(*<*)
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 718
lemma fresh_Lam:
224
+ − 719
shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
210
+ − 720
apply(tactic {* expand_tac @{thms fresh_def} *})
+ − 721
(*>*)
+ − 722
apply(tactic {* apply_prem_tac 3 [fresh_pred] fresh_rules @{context} *})
+ − 723
(*<*)oops(*>*)
+ − 724
+ − 725
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 726
Since we print out the goal state just after the application of
212
+ − 727
@{ML rtac} (Line 8), we can see the goal state we obtain:
210
+ − 728
+ − 729
\begin{isabelle}
+ − 730
@{text "1."}~@{prop "a \<noteq> b"}\\
+ − 731
@{text "2."}~@{prop "fresh a t"}
+ − 732
\end{isabelle}
+ − 733
215
+ − 734
As expected there are two subgoals, where the first comes from the
212
+ − 735
non-recursive premise of the introduction rule and the second comes
215
+ − 736
from the recursive one. The first goal can be solved immediately
212
+ − 737
by @{text "prems1"}. The second needs more work. It can be solved
+ − 738
with the other premise in @{text "prems1"}, namely
+ − 739
210
+ − 740
+ − 741
@{term [break,display]
+ − 742
"\<forall>fresh.
+ − 743
(\<forall>a b. a \<noteq> b \<longrightarrow> fresh a (Var b)) \<longrightarrow>
+ − 744
(\<forall>a t s. fresh a t \<longrightarrow> fresh a s \<longrightarrow> fresh a (App t s)) \<longrightarrow>
+ − 745
(\<forall>a t. fresh a (Lam a t)) \<longrightarrow>
+ − 746
(\<forall>a b t. a \<noteq> b \<longrightarrow> fresh a t \<longrightarrow> fresh a (Lam b t)) \<longrightarrow> fresh a t"}
+ − 747
+ − 748
but we have to instantiate it appropriately. These instantiations
+ − 749
come from @{text "params1"} and @{text "prems2"}. We can determine
+ − 750
whether we are in the simple or complicated case by checking whether
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 751
the topmost connective is an @{text "\<forall>"}. The premises in the simple
212
+ − 752
case cannot have such a quantification, since the first step
+ − 753
of @{ML "expand_tac"} was to ``rulify'' the lemma.
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 754
The premise of the complicated case must have at least one @{text "\<forall>"}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 755
coming from the quantification over the @{text preds}. So
210
+ − 756
we can implement the following function
+ − 757
*}
+ − 758
+ − 759
ML{*fun prepare_prem params2 prems2 prem =
+ − 760
rtac (case prop_of prem of
165
+ − 761
_ $ (Const (@{const_name All}, _) $ _) =>
210
+ − 762
prem |> all_elims params2
+ − 763
|> imp_elims prems2
+ − 764
| _ => prem) *}
+ − 765
+ − 766
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 767
which either applies the premise outright (the default case) or if
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 768
it has an outermost universial quantification, instantiates it first
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 769
with @{text "params1"} and then @{text "prems1"}. The following
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 770
tactic will therefore prove the lemma completely.
210
+ − 771
*}
+ − 772
+ − 773
ML{*fun prove_intro_tac i preds rules =
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 774
SUBPROOF (fn {params, prems, ...} =>
210
+ − 775
let
+ − 776
val (params1, params2) = chop (length params - length preds) params
+ − 777
val (prems1, prems2) = chop (length prems - length rules) prems
+ − 778
in
+ − 779
rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
+ − 780
THEN EVERY1 (map (prepare_prem params2 prems2) prems1)
+ − 781
end) *}
+ − 782
+ − 783
text {*
212
+ − 784
Note that the tactic is now @{ML SUBPROOF}, not @{ML SUBPROOF_test}.
215
+ − 785
The full proof of the introduction rule is as follows:
210
+ − 786
*}
+ − 787
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 788
lemma fresh_Lam:
224
+ − 789
shows "\<And>a b t. \<lbrakk>a \<noteq> b; fresh a t\<rbrakk> \<Longrightarrow> fresh a (Lam b t)"
210
+ − 790
apply(tactic {* expand_tac @{thms fresh_def} *})
+ − 791
apply(tactic {* prove_intro_tac 3 [fresh_pred] fresh_rules @{context} 1 *})
+ − 792
done
+ − 793
+ − 794
text {*
215
+ − 795
Phew! ...Unfortunately, not everything is done yet. If you look closely
212
+ − 796
at the general principle outlined for the introduction rules in
+ − 797
Section~\ref{sec:nutshell}, we have not yet dealt with the case where
+ − 798
recursive premises have preconditions. The introduction rule
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 799
of the accessible part is such a rule.
210
+ − 800
*}
+ − 801
+ − 802
lemma accpartI:
224
+ − 803
shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
210
+ − 804
apply(tactic {* expand_tac @{thms accpart_def} *})
+ − 805
apply(tactic {* chop_test_tac [acc_pred] acc_rules @{context} *})
+ − 806
apply(tactic {* apply_prem_tac 0 [acc_pred] acc_rules @{context} *})
+ − 807
+ − 808
txt {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 809
Here @{ML chop_test_tac} prints out the following
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 810
values for @{text "params1/2"} and @{text "prems1/2"}
210
+ − 811
+ − 812
\begin{isabelle}
+ − 813
@{text "Params1 from the rule:"}\\
+ − 814
@{text "x"}\\
+ − 815
@{text "Params2 from the predicate:"}\\
+ − 816
@{text "P"}\\
+ − 817
@{text "Prems1 from the rule:"}\\
+ − 818
@{text "R ?y x \<Longrightarrow> \<forall>P. (\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x) \<longrightarrow> P ?y"}\\
+ − 819
@{text "Prems2 from the predicate:"}\\
+ − 820
@{term "\<forall>x. (\<forall>y. R y x \<longrightarrow> P y) \<longrightarrow> P x"}\\
+ − 821
\end{isabelle}
+ − 822
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 823
and after application of the introduction rule
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 824
using @{ML apply_prem_tac}, we are in the goal state
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 825
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 826
\begin{isabelle}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 827
@{text "1."}~@{term "\<And>y. R y x \<Longrightarrow> P y"}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 828
\end{isabelle}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 829
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 830
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 831
*}(*<*)oops(*>*)
210
+ − 832
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 833
text {*
212
+ − 834
In order to make progress, we have to use the precondition
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 835
@{text "R y x"} (in general there can be many of them). The best way
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 836
to get a handle on these preconditions is to open up another subproof,
212
+ − 837
since the preconditions will then be bound to @{text prems}. Therfore we
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 838
modify the function @{ML prepare_prem} as follows
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 839
*}
210
+ − 840
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 841
ML %linenosgray{*fun prepare_prem params2 prems2 ctxt prem =
210
+ − 842
SUBPROOF (fn {prems, ...} =>
+ − 843
let
+ − 844
val prem' = prems MRS prem
+ − 845
in
+ − 846
rtac (case prop_of prem' of
+ − 847
_ $ (Const (@{const_name All}, _) $ _) =>
+ − 848
prem' |> all_elims params2
+ − 849
|> imp_elims prems2
+ − 850
| _ => prem') 1
+ − 851
end) ctxt *}
+ − 852
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 853
text {*
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 854
In Line 4 we use the @{text prems} from the @{ML SUBPROOF} and resolve
212
+ − 855
them with @{text prem}. In the simple cases, that is where the @{text prem}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 856
comes from a non-recursive premise of the rule, @{text prems} will be
256
+ − 857
just the empty list and the function @{ML [index] MRS} does nothing. Similarly, in the
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 858
cases where the recursive premises of the rule do not have preconditions.
212
+ − 859
In case there are preconditions, then Line 4 discharges them. After
+ − 860
that we can proceed as before, i.e., check whether the outermost
+ − 861
connective is @{text "\<forall>"}.
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 862
212
+ − 863
The function @{ML prove_intro_tac} only needs to be changed so that it
+ − 864
gives the context to @{ML prepare_prem} (Line 8). The modified version
+ − 865
is below.
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 866
*}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 867
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 868
ML %linenosgray{*fun prove_intro_tac i preds rules =
210
+ − 869
SUBPROOF (fn {params, prems, context, ...} =>
+ − 870
let
+ − 871
val (params1, params2) = chop (length params - length preds) params
+ − 872
val (prems1, prems2) = chop (length prems - length rules) prems
+ − 873
in
+ − 874
rtac (ObjectLogic.rulify (all_elims params1 (nth prems2 i))) 1
+ − 875
THEN EVERY1 (map (prepare_prem params2 prems2 context) prems1)
+ − 876
end) *}
+ − 877
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 878
text {*
212
+ − 879
With these two functions we can now also prove the introduction
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 880
rule for the accessible part.
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 881
*}
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 882
210
+ − 883
lemma accpartI:
224
+ − 884
shows "\<And>R x. (\<And>y. R y x \<Longrightarrow> accpart R y) \<Longrightarrow> accpart R x"
210
+ − 885
apply(tactic {* expand_tac @{thms accpart_def} *})
+ − 886
apply(tactic {* prove_intro_tac 0 [acc_pred] acc_rules @{context} 1 *})
+ − 887
done
+ − 888
190
+ − 889
text {*
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 890
Finally we need two functions that string everything together. The first
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 891
function is the tactic that performs the proofs.
190
+ − 892
*}
+ − 893
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 894
ML %linenosgray{*fun intro_tac defs rules preds i ctxt =
165
+ − 895
EVERY1 [ObjectLogic.rulify_tac,
+ − 896
K (rewrite_goals_tac defs),
184
+ − 897
REPEAT o (resolve_tac [@{thm allI}, @{thm impI}]),
210
+ − 898
prove_intro_tac i preds rules ctxt]*}
165
+ − 899
190
+ − 900
text {*
215
+ − 901
Lines 2 to 4 in this tactic correspond to the function @{ML expand_tac}.
+ − 902
Some testcases for this tactic are:
190
+ − 903
*}
+ − 904
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 905
lemma even0_intro:
224
+ − 906
shows "even 0"
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 907
by (tactic {* intro_tac eo_defs eo_rules eo_preds 0 @{context} *})
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 908
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 909
lemma evenS_intro:
224
+ − 910
shows "\<And>m. odd m \<Longrightarrow> even (Suc m)"
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 911
by (tactic {* intro_tac eo_defs eo_rules eo_preds 1 @{context} *})
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 912
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 913
lemma fresh_App:
224
+ − 914
shows "\<And>a t s. \<lbrakk>fresh a t; fresh a s\<rbrakk> \<Longrightarrow> fresh a (App t s)"
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 915
by (tactic {*
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 916
intro_tac @{thms fresh_def} fresh_rules [fresh_pred] 1 @{context} *})
190
+ − 917
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 918
text {*
215
+ − 919
The second function sets up in Line 4 the goals to be proved (this is easy
212
+ − 920
for the introduction rules since they are exactly the rules
+ − 921
given by the user) and iterates @{ML intro_tac} over all
+ − 922
introduction rules.
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 923
*}
173
+ − 924
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 925
ML %linenosgray{*fun intros rules preds defs lthy =
165
+ − 926
let
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 927
fun intros_aux (i, goal) =
165
+ − 928
Goal.prove lthy [] [] goal
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 929
(fn {context, ...} => intro_tac defs rules preds i context)
165
+ − 930
in
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 931
map_index intros_aux rules
164
+ − 932
end*}
+ − 933
212
+ − 934
text {*
256
+ − 935
The iteration is done with the function @{ML [index] map_index} since we
212
+ − 936
need the introduction rule together with its number (counted from
+ − 937
@{text 0}). This completes the code for the functions deriving the
+ − 938
reasoning infrastructure. It remains to implement some administrative
+ − 939
code that strings everything together.
+ − 940
*}
+ − 941
215
+ − 942
subsection {* Administrative Functions *}
+ − 943
+ − 944
text {*
+ − 945
We have produced various theorems (definitions, induction principles and
+ − 946
introduction rules), but apart from the definitions, we have not yet
+ − 947
registered them with the theorem database. This is what the functions
256
+ − 948
@{ML [index] note in LocalTheory} does.
215
+ − 949
+ − 950
+ − 951
For convenience, we use the following
+ − 952
three wrappers this function:
+ − 953
*}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 954
215
+ − 955
ML{*fun reg_many qname ((name, attrs), thms) =
+ − 956
LocalTheory.note Thm.theoremK
+ − 957
((Binding.qualify false qname name, attrs), thms)
+ − 958
+ − 959
fun reg_single1 qname ((name, attrs), thm) =
+ − 960
reg_many qname ((name, attrs), [thm])
176
+ − 961
215
+ − 962
fun reg_single2 name attrs (qname, thm) =
+ − 963
reg_many (Binding.name_of qname) ((name, attrs), [thm]) *}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 964
215
+ − 965
text {*
+ − 966
The function that ``holds everything together'' is @{text "add_inductive"}.
+ − 967
Its arguments are the specification of the predicates @{text "pred_specs"}
+ − 968
and the introduction rules @{text "rule_spec"}.
+ − 969
*}
211
d5accbc67e1b
more work on simple inductive and marked all sections that are still seriously incomplete with TBD
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 970
186
371e4375c994
made the Ackermann function example safer and included suggestions from MW
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 971
ML %linenosgray{*fun add_inductive pred_specs rule_specs lthy =
165
+ − 972
let
237
+ − 973
val mxs = map snd pred_specs
165
+ − 974
val pred_specs' = map fst pred_specs
+ − 975
val prednames = map fst pred_specs'
+ − 976
val preds = map (fn (p, ty) => Free (Binding.name_of p, ty)) pred_specs'
215
+ − 977
val tyss = map (binder_types o fastype_of) preds
163
2319cff107f0
removed rep_ss, and used dest_ss instead; some very slight changes to simple_inductive
Christian Urban <urbanc@in.tum.de>
diff
changeset
+ − 978
215
+ − 979
val (namesattrs, rules) = split_list rule_specs
165
+ − 980
237
+ − 981
val (defs, lthy') = defns rules preds prednames mxs tyss lthy
+ − 982
val ind_prins = inds rules defs preds tyss lthy'
210
+ − 983
val intro_rules = intros rules preds defs lthy'
91
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 984
165
+ − 985
val mut_name = space_implode "_" (map Binding.name_of prednames)
215
+ − 986
val case_names = map (Binding.name_of o fst) namesattrs
165
+ − 987
in
215
+ − 988
lthy' |> reg_many mut_name ((@{binding "intros"}, []), intro_rules)
237
+ − 989
||>> reg_many mut_name ((@{binding "inducts"}, []), ind_prins)
215
+ − 990
||>> fold_map (reg_single1 mut_name) (namesattrs ~~ intro_rules)
+ − 991
||>> fold_map (reg_single2 @{binding "induct"}
+ − 992
[Attrib.internal (K (RuleCases.case_names case_names)),
+ − 993
Attrib.internal (K (RuleCases.consumes 1)),
+ − 994
Attrib.internal (K (Induct.induct_pred ""))])
237
+ − 995
(prednames ~~ ind_prins)
215
+ − 996
|> snd
165
+ − 997
end*}
91
667a0943c40b
added a section that will eventually describe the code
Christian Urban <urbanc@in.tum.de>
parents:
diff
changeset
+ − 998
215
+ − 999
text {*
+ − 1000
In Line 3 the function extracts the syntax annotations from the predicates.
+ − 1001
Lines 4 to 6 extract the names of the predicates and generate
+ − 1002
the variables terms (with types) corresponding to the predicates.
+ − 1003
Line 7 produces the argument types for each predicate.
+ − 1004
+ − 1005
Line 9 extracts the introduction rules from the specifications
+ − 1006
and stores also in @{text namesattrs} the names and attributes the
+ − 1007
user may have attached to these rules.
+ − 1008
+ − 1009
Line 11 produces the definitions and also registers the definitions
+ − 1010
in the local theory @{text "lthy'"}. The next two lines produce
+ − 1011
the induction principles and the introduction rules (all of them
+ − 1012
as theorems). Both need the local theory @{text lthy'} in which
+ − 1013
the definitions have been registered.
+ − 1014
+ − 1015
Lines 15 produces the name that is used to register the introduction
+ − 1016
rules. It is costum to collect all introduction rules under
+ − 1017
@{text "string.intros"}, whereby @{text "string"} stands for the
+ − 1018
@{text [quotes] "_"}-separated list of predicate names (for example
+ − 1019
@{text "even_odd"}. Also by custom, the case names in intuction
+ − 1020
proofs correspond to the names of the introduction rules. These
+ − 1021
are generated in Line 16.
+ − 1022
237
+ − 1023
Lines 18 and 19 now add to @{text "lthy'"} all the introduction rules
+ − 1024
und induction principles under the name @{text "mut_name.intros"} and
+ − 1025
@{text "mut_name.inducts"}, respectively (see previous paragraph).
+ − 1026
+ − 1027
Line 20 add further every introduction rule under its own name
215
+ − 1028
(given by the user).\footnote{FIXME: what happens if the user did not give
237
+ − 1029
any name.} Line 21 registers the induction principles. For this we have
256
+ − 1030
to use some specific attributes. The first @{ML [index] case_names in RuleCases}
215
+ − 1031
corresponds to the case names that are used by Isar to reference the proof
+ − 1032
obligations in the induction. The second @{ML "consumes 1" in RuleCases}
+ − 1033
indicates that the first premise of the induction principle (namely
+ − 1034
the predicate over which the induction proceeds) is eliminated.
+ − 1035
+ − 1036
This completes all the code and fits in with the ``front end'' described
237
+ − 1037
in Section~\ref{sec:interface}.\footnote{FIXME: Describe @{ML Induct.induct_pred}.
+ − 1038
Why the mut-name?
224
+ − 1039
What does @{ML Binding.qualify} do?}
124
+ − 1040
*}
219
+ − 1041
(*<*)end(*>*)