text‹
Proof commands perform transitions of Isar/VM machine configurations, which
are block-structured, consisting of a stack of nodes with three main
components: logical proof context, current facts, and open goals. Isar/VM
transitions are typed according to the following three different modes of
operation:
🪙‹proof(prove)› means that a new goal has just been stated that is now to
be 🪙‹proven›; the next command may refine it by some proof method, and
enter a sub-proof to establish the actual result.
🪙‹proof(state)› is like a nested theory mode: the context may be
augmented by 🪙‹stating› additional assumptions, intermediate results etc.
🪙‹proof(chain)› is intermediate between ‹proof(state)› and ‹proof(prove)›: existing facts (i.e.\ the contents of the special
@{fact_ref this} register) have been just picked up in order to be used
when refining the goal claimed next.
The proof mode indicator may be understood as an instruction to the writer,
telling what kind of operation may be performed next. The corresponding
typings of proof commands restricts the shape of well-formed proof texts to
particular command sequences. So dynamic arrangements of commands eventually
turn out as static texts of a certain structure.
\Appref{ap:refcard} gives a simplified grammar of the (extensible) language
emerging that way from the different types of proof commands. The main ideas
of the overall Isar framework are explained in \chref{ch:isar-framework}. ›
🪙 @{command "notepad"}~@{keyword "begin"} opens a proof state without any
goal statement. This allows to experiment with Isar, without producing any
persistent result. The notepad is closed by @{command "end"}. ›
While Isar is inherently block-structured, opening and closing blocks is
mostly handled rather casually, with little explicit user-intervention. Any
local goal statement automatically opens 🪙‹two› internal blocks, which are
closed again when concluding the sub-proof (by @{command "qed"} etc.).
Sections of different context within a sub-proof may be switched via
@{command "next"}, which is just a single block-close followed by block-open
again. The effect of @{command "next"} is to reset the local proof context;
there is no goal focus involved here!
For slightly more advanced applications, there are explicit block
parentheses as well. These typically achieve a stronger forward style of
reasoning.
🪙 @{command "next"} switches to a fresh block within a sub-proof, resetting
the local context to the initial one.
🪙 @{command "{"} and @{command "}"} explicitly open and close blocks. Any
current facts pass through ``@{command "{"}'' unchanged, while ``@{command
"}"}'' causes any result to be 🪙‹exported› into the enclosing context. Thus
fixed variables are generalized, assumptions discharged, and local
definitions unfolded (cf.\ \secref{sec:proof-context}). There is no
difference of @{command "assume"} and @{command "presume"} in this mode of
forward reasoning --- in contrast to plain backward reasoning with the
result exported at @{command "show"} time. ›
The @{command "oops"} command discontinues the current proof attempt, while
considering the partial proof text as properly processed. This is
conceptually quite different from ``faking'' actual proofs via @{command_ref
"sorry"} (see \secref{sec:proof-steps}): @{command "oops"} does not observe
the proof structure at all, but goes back right to the theory level.
Furthermore, @{command "oops"} does not produce any result theorem --- there
is no intended claim to be able to complete the proof in any way.
A typical application of @{command "oops"} is to explain Isar proofs 🪙‹within› the system itself, in conjunction with the document preparation
tools of Isabelle described in \chref{ch:document-prep}. Thus partial or
even wrong proof attempts can be discussed in a logically sound manner. Note
that the Isabelle {\LaTeX} macros can be easily adapted to print something
like ``‹…›'' instead of the keyword ``@{command "oops"}''. ›
section‹Statements›
subsection‹Context elements \label{sec:proof-context}›
The logical proof context consists of fixed variables and assumptions. The
former closely correspond to Skolem constants, or meta-level universal
quantification as provided by the Isabelle/Pure logical framework.
Introducing some 🪙‹arbitrary, but fixed› variable via ``@{command
"fix"}~‹x›'' results in a local value that may be used in the subsequent
proof as any other variable or constant. Furthermore, any result ‹⊨ φ[x]›
exported from the context will be universally closed wrt.\ ‹x› at the
outermost level: ‹⊨∧x. φ[x]› (this is expressed in normal form using
Isabelle's meta-variables).
Similarly, introducing some assumption ‹χ› has two effects. On the one hand,
a local theorem is created that may be used as a fact in subsequent proof
steps. On the other hand, any result ‹χ ⊨ φ› exported from the context
becomes conditional wrt.\ the assumption: ‹⊨ χ ==> φ›. Thus, solving an
enclosing goal using such a result would basically introduce a new subgoal
stemming from the assumption. How this situation is handled depends on the
version of assumption command used: while @{command "assume"} insists on
solving the subgoal by unification with some premise of the goal, @{command
"presume"} leaves the subgoal unchanged in order to be proved later by the
user.
Local definitions, introduced by ``🪙‹define x where x = t›'', are achieved
by combining ``@{command "fix"}~‹x›'' with another version of assumption
that causes any hypothetical equation ‹x ≡ t› to be eliminated by the
reflexivity rule. Thus, exporting some result ‹x ≡ t ⊨ φ[x]› yields ‹⊨
φ[t]›.
🪙 @{command "fix"}~‹x› introduces a local variable ‹x› that is 🪙‹arbitrary,
but fixed›.
🪙 @{command "assume"}~‹a: φ› and @{command "presume"}~‹a: φ› introduce a
local fact ‹φ ⊨ φ› by assumption. Subsequent results applied to an enclosing
goal (e.g.\ by @{command_ref "show"}) are handled as follows: @{command
"assume"} expects to be able to unify with existing premises in the goal,
while @{command "presume"} leaves ‹φ› as new subgoals.
Several lists of assumptions may be given (separated by @{keyword_ref
"and"}; the resulting list of current facts consists of all of these
concatenated.
A structured assumption like 🪙‹assume "B x" if "A x" for x› is equivalent to 🪙‹assume "∧x. A x ==> B x"›, but vacuous quantification is avoided: a
for-context only effects propositions according to actual use of variables.
🪙🪙‹define x where "x = t"› introduces a local (non-polymorphic) definition.
In results that are exported from the context, ‹x› is replaced by ‹t›.
Internally, equational assumptions are added to the context in Pure form,
using ‹x ≡ t› instead of ‹x = t› or ‹x ⟷ t› from the object-logic. When
exporting results from the context, ‹x› is generalized and the assumption
discharged by reflexivity, causing the replacement by ‹t›.
The default name for the definitional fact is ‹x_def›. Several simultaneous
definitions may be given as well, with a collective default name.
🪙
It is also possible to abstract over local parameters as follows: 🪙‹define f
:: "'a ==> 'b" where "f x = t" for x :: 'a›. ›
Abbreviations may be either bound by explicit @{command "let"}~‹p ≡ t›
statements, or by annotating assumptions or goal statements with a list of
patterns ``🪙‹(is p1… pn)›''. In both cases, higher-order matching is
invoked to bind extra-logical term variables, which may be either named
schematic variables of the form ‹?x›, or nameless dummies ``@{variable _}''
(underscore). Note that in the @{command "let"} form the patterns occur on
the left-hand side, while the @{keyword "is"} patterns are in postfix
position.
Polymorphism of term bindings is handled in Hindley-Milner style, similar to
ML. Type variables referring to local assumptions or open goal statements
are 🪙‹fixed›, while those of finished results or bound by @{command "let"}
may occur in 🪙‹arbitrary› instances later. Even though actual polymorphism
should be rarely used in practice, this mechanism is essential to achieve
proper incremental type-inference, as the user proceeds to build up the Isar
proof text from left to right.
🪙
Term abbreviations are quite different from local definitions as introduced
via @{command "define"} (see \secref{sec:proof-context}). The latter are
visible within the logic as actual equations, while abbreviations disappear
during the input process just after type checking. Also note that @{command
"define"} does not support polymorphism.
The syntax of @{keyword "is"} patterns follows @{syntax term_pat} or
@{syntax prop_pat} (see \secref{sec:term-decls}).
🪙🪙‹let p1 = t1 and … pn = tn› binds any text variables in patterns ‹p1, …, pn› by simultaneous higher-order matching against terms ‹t1, …,
tn›.
🪙🪙‹(is p1… pn)› resembles @{command "let"}, but matches ‹p1, …, pn›
against the preceding statement. Also note that @{keyword "is"} is not a
separate command, but part of others (such as @{command "assume"},
@{command "have"} etc.).
Some 🪙‹implicit› term abbreviations\index{term abbreviations} for goals and
facts are available as well. For any open goal, @{variable_ref thesis}
refers to its object-level statement, abstracted over any meta-level
parameters (if present). Likewise, @{variable_ref this} is bound for fact
statements resulting from assumptions or finished goals. In case @{variable
this} refers to an object-logic statement that is an application ‹f t›, then ‹t› is bound to the special text variable ``@{variable "…"}'' (three dots).
The canonical application of this convenience are calculational proofs (see \secref{sec:calculation}). ›
subsection‹Facts and forward chaining \label{sec:proof-facts}›
New facts are established either by assumption or proof of local statements.
Any fact will usually be involved in further proofs, either as explicit
arguments of proof methods, or when forward chaining towards the next goal
via @{command "then"} (and variants); @{command "from"} and @{command
"with"} are composite forms involving @{command "note"}. The @{command
"using"} elements augments the collection of used facts 🪙‹after› a goal has
been stated. Note that the special theorem name @{fact_ref this} refers to
the most recently established facts, but only 🪙‹before› issuing a follow-up
claim.
🪙 @{command "note"}~‹a = b1… bn› recalls existing facts ‹b1, …, bn›,
binding the result as ‹a›. Note that attributes may be involved as well,
both on the left and right hand sides.
🪙 @{command "then"} indicates forward chaining by the current facts in order
to establish the goal to be claimed next. The initial proof method invoked
to refine that will be offered the facts to do ``anything appropriate'' (see
also \secref{sec:proof-steps}). For example, method @{method (Pure) rule}
(see \secref{sec:pure-meth-att}) would typically do an elimination rather
than an introduction. Automatic methods usually insert the facts into the
goal state before operation. This provides a simple scheme to control
relevance of facts in automated proof search.
🪙 @{command "from"}~‹b› abbreviates ``@{command "note"}~‹b›~@{command
"then"}''; thus @{command "then"} is equivalent to ``@{command
"from"}~‹this›''.
🪙 @{command "with"}~‹b1… bn› abbreviates ``@{command "from"}~‹b1… bn 🪙 this›''; thus the forward chaining is from earlier facts together
with the current ones.
🪙 @{command "using"}~‹b1… bn› augments the facts to be used by a
subsequent refinement step (such as @{command_ref "apply"} or @{command_ref
"proof"}).
🪙 @{command "unfolding"}~‹b1… bn› is structurally similar to @{command
"using"}, but unfolds definitional equations ‹b1… bn› throughout the goal
state and facts. See also the proof method @{method_ref unfold}.
🪙🪙‹(use b1… bn in method)› uses the facts in the given method
expression. The facts provided by the proof state (via @{command "using"}
etc.) are ignored, but it is possible to refer to @{fact method_facts}
explicitly.
🪙 @{fact method_facts} is a dynamic fact that refers to the currently used
facts of the goal state.
Forward chaining with an empty list of theorems is the same as not chaining
at all. Thus ``@{command "from"}~‹nothing›'' has no effect apart from
entering ‹prove(chain)› mode, since @{fact_ref nothing} is bound to the
empty list of theorems.
Basic proof methods (such as @{method_ref (Pure) rule}) expect multiple
facts to be given in their proper order, corresponding to a prefix of the
premises of the rule involved. Note that positions may be easily skipped
using something like @{command "from"}~‹_ 🪙 a 🪙 b›, for example.
This involves the trivial rule ‹PROP ψ ==> PROP ψ›, which is bound in
Isabelle/Pure as ``@{fact_ref "_"}'' (underscore).
Automated methods (such as @{method simp} or @{method auto}) just insert any
given facts before their usual operation. Depending on the kind of procedure
involved, the order of facts is less significant here. ›
From a theory context, proof mode is entered by an initial goal command such
as @{command "lemma"}. Within a proof context, new claims may be introduced
locally; there are variants to interact with the overall proof structure
specifically, such as @{command have} or @{command show}.
Goals may consist of multiple statements, resulting in a list of facts
eventually. A pending multi-goal is internally represented as a meta-level
conjunction (‹&&&›), which is usually split into the corresponding number of
sub-goals prior to an initial method application, via @{command_ref "proof"}
(\secref{sec:proof-steps}) or @{command_ref "apply"}
(\secref{sec:tactic-commands}). The @{method_ref induct} method covered in \secref{sec:cases-induct} acts on multiple claims simultaneously.
Claims at the theory level may be either in short or long form. A short goal
merely consists of several simultaneous propositions (often just one). A
long goal includes an explicit context specification for the subsequent
conclusion, involving local parameters and assumptions. Here the role of
each part of the statement is explicitly marked by separate keywords (see
also \secref{sec:locale}); the local assumptions being introduced here are
available as @{fact_ref assms} in the proof. Moreover, there are two kinds
of conclusions: @{element_def "shows"} states several simultaneous
propositions (essentially a big conjunction), while @{element_def "obtains"}
claims several simultaneous contexts --- essentially a big disjunction of
eliminated parameters and assumptions (see \secref{sec:obtain}).
🪙 @{command "lemma"}~‹a: φ› enters proof mode with ‹φ› as main goal, eventuallyresultinginsomefact\<open>\<turnstile>\<phi>\<close>tobeputbackintothetarget context.
🪙 @{command "print_rules"} prints rules declared via attributes @{attribute
(Pure) intro}, @{attribute (Pure) elim}, @{attribute (Pure) dest} of
Isabelle/Pure.
See also the analogous @{command "print_claset"} command for similar rule
declarations of the classical reasoner (\secref{sec:classical}).
🪙 ``@{method"-"}'' (minus) inserts the forward chaining facts as premises
into the goal, and nothing else.
Note that command @{command_ref "proof"} without any method actually
performs a single reduction step using the @{method_ref (Pure) rule} method; thus a plain 🪙‹do-nothing› proof step would be ``@{command "proof"}~‹-›'' ratherthan@{command"proof"}alone.
(*<*)experiment begin(*>*) method_setup my_method1 = ‹Scan.succeed (K (SIMPLE_METHOD' (fn i: int => no_tac)))› "my first method (without any arguments)"
method_setup my_method2 = ‹Scan.succeed (fn ctxt: Proof.context =>
SIMPLE_METHOD' (fn i: int => no_tac))› "my second method (with context)"
method_setup my_method3 = ‹Attrib.thms >> (fn thms: thm list => fn ctxt: Proof.context =>
SIMPLE_METHOD' (fn i: int => no_tac))› "my third method (with theorem arguments and context)" (*<*)end(*>*)
section‹Proof by cases and induction \label{sec:cases-induct}›
The puristic way to build up Isar proof contexts is by explicit language
elements like @{command "fix"}, @{command "assume"}, @{command "let"} (see \secref{sec:proof-context}). This is adequate for plain natural deduction,
but easily becomes unwieldy in concrete verification tasks, which typically
involve big induction rules with several cases.
The @{command "case"} command provides a shorthand to refer to a local
context symbolically: certain proof methods provide an environment of named
``cases'' of the form ‹c: x1, …, xm, φ1, …, φn›; the effect of
``@{command "case"}~‹c›'' is then equivalent to ``@{command "fix"}~‹x1…
xm›~@{command "assume"}~‹c: φ1… φn›''. Term bindings may be covered as
well, notably @{variable ?case} for the main conclusion.
By default, the ``terminology'' ‹x1, …, xm› of a case value is marked as
hidden, i.e.\ there is no way to refer to such parameters in the subsequent
proof text. After all, original rule parameters stem from somewhere outside
of the current proof text. By using the explicit form ``@{command
"case"}~‹(c y1… ym)›'' instead, the proof author is able to chose local
names that fit nicely into the current context.
🪙
It is important to note that proper use of @{command "case"} does not
provide means to peek at the current goal state, which is not directly
observable in Isar! Nonetheless, goal refinement commands do provide named
cases ‹goali› for each subgoal ‹i = 1, …, n› of the resulting goal state.
Using this extra feature requires great care, because some bits of the
internal tactical machinery intrude the proof text. In particular, parameter
names stemming from the left-over of automated reasoning tools are usually
quite unpredictable.
Under normal circumstances, the text of cases emerge from standard
elimination or induction rules, which in turn are derived from previous
theory specifications in a canonical way (say from @{command "inductive"}
definitions).
🪙
Proper cases are only available if both the proof method and the rules
involved support this. By using appropriate attributes, case names,
conclusions, and parameters may be also declared by hand. Thus variant
versions of rules that have been derived manually become ready to use in
advanced case analysis later.
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.