ISABELLE COPYRIGHT NOTICE, LICENCE AND DISCLAIMER. Copyright (c) 1986-2024, University of Cambridge, Technische Universitaet Muenchen, and contributors. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the University of Cambridge or the Technische Universitaet Muenchen nor the names of their contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
$HOME/inst/
and then put in your shell config file (like .bashrc
) the following:
export PATH=$HOME/inst/Isabelle2023/bin/:$PATH
export ISABELLE_HOME=$HOME/inst/Isabelle2023
isabelle jedit
to spawn the editor window.
$ISABELLE_HOME/src/HOL/IMP
,
though this shouldn't be strictly necessary.
Each section ends with a downloadable file containing a full theorem that can be loaded into Isabelle.
The theorems are renamed, as Isabelle expects the theorem name to match the name of the file.
Files in the main progression are named in ImpTutorial_$NUMBER.thy
fashion,
files that contain code that is not used in the final program have extra letters after the number.
Snippets that do not contain a theorem definiton are expected to be appended to the previous theorem before the end
,
The code is presented both with pretty typesetting and using raw input values for special symbols.
Tthe latter available by clicking the foldable section under formatted code, and can be copied into an editor as is.
You might need to reload the editor after pasting the code, so the symbols are rendered properly.
Colors are used to mark
keywords
,
definitions
,
constructors
,
variables
,
and symbol inputs
.
\symbol name
.
You might need to wait for a second while the editor searches for the symbol.
All the symbols available for use in Isabelle code are listed in $ISABELLE_HOME/etc/symbols
.
Highlights:
\<Rightarrow>
(⇒) for function definitions\<^sub>
for subscripts$ISABELLE_HOME/src/HOL/IMP/AExp.thy
theory ImpTutorial
imports Main
begin
type_synonym vname = string
type_synonym val = int
type_synonym state = "vname ⇒ val"
datatype aexp =
N int |
V vname |
Plus aexp aexp |
fun aval :: "aexp ⇒ state ⇒ val" where
"aval (N n) s = n" |
"aval (V x) s = s x" |
"aval (Plus a1 a2) s = aval a1 s + aval a2 s"
end
theory ImpTutorial
imports Main
begin
type_synonym vname = string
type_synonym val = int
type_synonym state = "vname \<Rightarrow> val"
datatype aexp =
N int |
V vname |
Plus aexp aexp |
fun aval :: "aexp \<Rightarrow> state \<Rightarrow> val" where
"aval (N n) s = n" |
"aval (V x) s = s x" |
"aval (Plus a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s + aval a\<^sub>2 s"
end
fun asimp_const :: "aexp ⇒ aexp" where
"asimp_const (N n) = N n" |
"asimp_const (V x) = V x" |
"asimp_const (Plus a1 a2) =
(case (asimp_const a1, asimp_const a2) of
(N n1, N n2) ⇒ N (n1 + n2) |
(b1, b2) ⇒ Plus b1 b2)"
fun asimp_const :: "aexp \<Rightarrow> aexp" where
"asimp_const (N n) = N n" |
"asimp_const (V x) = V x" |
"asimp_const (Plus a\<^sub>1 a\<^sub>2) =
(case (asimp_const a\<^sub>1, asimp_const a\<^sub>2) of
(N n\<^sub>1, N n\<^sub>2) \<Rightarrow> N (n\<^sub>1 + n\<^sub>2) |
(b\<^sub>1, b\<^sub>2) \<Rightarrow> Plus b\<^sub>1 b\<^sub>2)"
N
) and unevaluated variables (V
) cannot be simplified.
Addition (Plus
) can only be simplified if both arguments evaluate to numbers,
in which case it evaluates to a number that is the sum of the arguments.
lemma "aval (asimp_const a) s = aval a s"
a = N n
the statement becomes:
aval (asimp_const (N n)) s = aval (N n) s
asimp_const (N n) = N n
aval (N n) s = aval (N n) s
aval
.
Since asimp_const
is defined in the same way for the variable constructor V v
,
the proof goes the same way.
a = Plus a1 a2
and thus
aval (asimp_const (Plus a1 a2)) s = aval (Plus a1 a2) s
asimp_const
. Assume
aval (asimp_const a1) s = aval a1 s
aval (asimp_const a2) s = aval a2 s
asimp_const a1 = N n1
and asimp_const a2 = N n2
,
or at least one doesn't. In the first case, the induction assumptions become
aval (N n1) s = aval a1 s
aval (N n2) s = aval a2 s
asimp_const
(listing 2, lines 4-5)
asimp_const (Plus (N n1) (N n2)) = N (n1 + n2)
aval (N (n1 + n2)) s = aval (Plus a1 a2) s
aval
(listing 1, line 15) we see that the left hand side evaluates to just n1 + n2
.
n1 + n2 = aval (Plus a1 a2) s
aval
(listing 1, line 17), we can expand the right hand side
n1 + n2 = aval a1 s + aval a2 s
n1 + n2 = aval (N n1) s + aval (N n2) s
n1
and n2
.
asimp_const a1 ≠ N n1
and/or asimp_const a2 ≠ N n2
,
asimp_const (Plus a1 a2) = Plus (asimp_const a1) (asimp_const a2)
lemma "aval (asimp_const a) s = aval a s"
apply(induction a)
apply (auto split: aexp.split)
done
theory ImpTutorial
imports Main
begin
type_synonym vname = string
type_synonym val = int
type_synonym state = "vname \<Rightarrow> val"
datatype aexp =
N int |
V vname |
Plus aexp aexp |
Times aexp aexp
fun aval :: "aexp \<Rightarrow> state \<Rightarrow> val" where
"aval (N n) s = n" |
"aval (V x) s = s x" |
"aval (Plus a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s + aval a\<^sub>2 s"
"aval (Times a\<^sub>1 a\<^sub>2) s = aval a\<^sub>1 s * aval a\<^sub>2 s"
end
fun plus :: "aexp \<Rightarrow> aexp \<Rightarrow> aexp" where
"plus (N i\<^sub>1) (N i\<^sub>2) = N (i\<^sub>1 + i\<^sub>2)" |
"plus (N i) a = (if i=0 then a else Plus (N i) a)" |
"plus a (N i) = (if i=0 then a else Plus a (N i))" |
"plus a\<^sub>1 a\<^sub>2 = Plus a\<^sub>1 a\<^sub>2"
fun asimp :: "aexp \ aexp" where
"asimp (N n) = N n" |
"asimp (V x) = V x" |
"asimp (Plus a\<^sub>1 a\<^sub>2) = plus (asimp a\<^sub>1) (asimp a\<^sub>2)"
lemma aval_plus[simp]:
"aval (plus a1 a2) s = aval a1 s + aval a2 s"
apply(induction a1 a2 rule: plus.induct)
apply simp_all (* just for a change from auto *)
done
theorem aval_asimp[simp]:
"aval (asimp a) s = aval a s"
apply(induction a)
apply simp_all
done
end
fun asimp_const :: "aexp \<Rightarrow> aexp" where
"asimp_const (N n) = N n" |
"asimp_const (V x) = V x" |
"asimp_const (Plus a\<^sub>1 a\<^sub>2) =
(case (asimp_const a\<^sub>1, asimp_const a\<^sub>2) of
(N n\<^sub>1, N n\<^sub>2) \<Rightarrow> N (n\<^sub>1 + n\<^sub>2) |
(b\<^sub>1, b\<^sub>2) \<Rightarrow> Plus b\<^sub>1 b\<^sub>2)"