Up to index of Isabelle/HOL/HOL-Algebra/example_Z4Z2
theory example_Z4Z2(* Title: code_generation/example_Z2Z4.thy ID: $Id: exampleZ2Z4.thy $ Author: Jesus Aransay *) theory example_Z4Z2 imports "BPL_classes_2008" "Efficient_Nat" (*"/usr/local/Isabelle2008/src/HOL/Library/Efficient_Nat"*) begin section{*An example of the BPL: a reduction from $Z^{4}$ to $Z^{2}$*} text{*We fit a concrete example of the BPL into the code previously generated*} text{*The example is the following: we have a "big" differential group, $D = Z^4$, with componentwise addition, and a differential defined as $d_{D} x = (0, 2*fst (x), 0, thrd (x))$; the homotopy operator is given by $h x = (0, 0, frth x, 0)$ and the perturbation is $\delta_{D} x = (0, fst (x) + thrd (x), 0, fst (x))$; the nilpotency condition in this example is globally satisfied for $n = 2$*} text{*This means that $\forall x. (\delta_{D} \circ h)^{2} (x) = 0$; we will later prove this in Isabelle.*} text{*The small differential group is defined as $C = Z^2$, with componentwise addition, and a differential defined as $d_{C} (x) = (0, fst (x) + fst (x))$*} text{*Then, $f (x) = (fst (x), snd (x))$, $g (x) = (fst (x), snd (x), 0, 0)$ and $h (x) = (0, 0, frth (x), 0)$*} text{*In order to apply the example in Isabelle, we first define a type representing the 4-tuples, which will be our representation of $Z^4$*} text{*The following definitions and concrete syntax have been mainly extracted from file @{text Product_Type.thy}, resembling the ones given there for pairs.*} text{*The generic product was not instantiable with a single parameter type (@{typ int} in our case), since this gave place to a too restrictive instance. This is why we produced our own single parameterized product type for pairs and four tuples.*} text{*The data type has been defined just to allow us to generate code, which means that a very small number of facts are available about it*} subsection {* Type definition for $Z^2$*} text{*The following type definition represents tuples. We will use it to represent $Z^2$. There exists already a type representing products in HOL, but it cannot be \emph{instantiated} with a single parameter type (in our case, $Z$), since the type obtained is too restrictive with respect to the type representation.*} text{*Therefore, we defined our own product type with only a single type parameter.*} text{*This type will be also used later to obtain a type representing $Z^4$.*} datatype 'a SProd = SPair 'a 'a text{*Some basic definitions over the previous type:*} definition fst_spair :: "'a SProd => 'a" where "fst_spair p = (THE a. EX b. p = SPair a b)" definition snd_spair :: "'a SProd => 'a" where "snd_spair p == (THE b. EX a. p = SPair a b)" text{*We omit the previous definitions from the code generator, since they do not have an executable content.*} lemmas [code del] = fst_spair_def snd_spair_def subsection {* Concrete syntax *} text{*Special syntax for the produced type:*} translations "[(x, y)]" == "SPair x y" instance SProd :: (type) type .. subsection {* Lemmas and proof tool setup *} lemma SPair_eq [iff]: "([(a, b)] = [(a', b')]) = (a = a' & b = b')" by simp lemma fst_spair_conv [simp,code]: "fst_spair [(a, b)] = a" unfolding fst_spair_def by blast lemma snd_spair_conv [simp,code]: "snd_spair [(a, b)] = b" unfolding snd_spair_def by blast lemma fst_spair_eqD: "fst_spair [(x, y)] = a ==> x = a" by simp lemma snd_spair_eqD: "snd_spair [(x, y)] = a ==> y = a" by simp lemma surjective_spair: "p = [(fst_spair p, snd_spair p)]" -- "Do not add as rewrite rule: invalidates some proofs in IMP" by (cases p) simp lemma split_SPair_all: "(!!x. PROP P x) == (!!a b. PROP P [(a, b)])" proof fix a b assume "!!x. PROP P x" then show "PROP P [(a, b)]" . next fix x assume "!!a b. PROP P [(a, b)]" show "PROP P x" using surjective_spair [of "x::'a SProd"] using `PROP P [(fst_spair (x::'a SProd), snd_spair x)]` by simp qed text{*We now prove that the introduced datatype is an instance of the type classes needed in the BPL*} text{*As far as @{typ int} is not a type class, but a type constructor, we will use @{term ring} as a type class.*} text{*Therefore, we prove that our type constructor @{text SProd} with suitable operations is a valid instance of the type class @{text "(ring) diff_group_add"}*} text{*Being @{typ int} a valid instance of @{term ring}, we can then, in the code generation phase, replace @{term ring} with the concrete structure @{typ int}*} instance SProd :: (eq) eq .. lemma [code func]: "[(x1::'a::eq, x2)] = [(y1, y2)] <-> x1 = y1 ∧ x2 = y2" by auto instantiation SProd :: ("{eq,ring}") ab_semigroup_add begin definition SProd_plus_def: "a + b = [( (fst_spair a + fst_spair b), (snd_spair a + snd_spair b))]" instance by default (simp_all add: split_SPair_all SProd_plus_def) end instantiation SProd :: ("{eq,ring}") comm_monoid_add begin definition SProd_zero_def: "0 = [(0, 0)]" instance by default (simp_all add: split_SPair_all SProd_plus_def SProd_zero_def) end instantiation SProd :: ("{eq,ring}") ab_group_add begin definition SProd_uminus_def: "- x = [( - fst_spair x, - snd_spair x)]" definition SProd_minus_def: "(x::'a SProd) - y = (x + (- y))" instance apply default unfolding split_SPair_all unfolding SProd_zero_def unfolding SProd_minus_def unfolding SProd_uminus_def unfolding SProd_plus_def by simp_all end instantiation SProd:: ("{eq,ring}") diff_group_add begin definition SProd_diff_def: "diff x ≡ [( 0, fst_spair x + fst_spair x)]" instance apply default unfolding split_SPair_all unfolding expand_fun_eq unfolding o_apply unfolding SProd_diff_def unfolding SProd_plus_def unfolding SProd_zero_def by simp_all end subsection{*Type definition for $Z^4$*} datatype 'a Quad_type_const = Quad "'a SProd" "'a SProd" subsection {*Definitions over the given type.*} definition fst_quad :: "'a Quad_type_const => 'a" where "fst_quad p == THE a. EX b c e. p = Quad (SPair a b) (SPair c e)" definition snd_quad :: "'a Quad_type_const => 'a" where "snd_quad p == THE b. EX a c e. p = Quad (SPair a b) (SPair c e)" definition thrd_quad :: "'a Quad_type_const => 'a" where "thrd_quad p == THE c. EX a b e. p = Quad (SPair a b) (SPair c e)" definition frth_quad :: "'a Quad_type_const => 'a" where "frth_quad p == THE e. EX a b c. p = Quad (SPair a b) (SPair c e)" text{*We delete the previous definitions from the code genrator setup, soince they do not have an executable meaning.*} lemmas [code del] = fst_quad_def snd_quad_def thrd_quad_def frth_quad_def subsection {*Concrete syntax.*} translations "[(x, y, z, t)]" == "Quad (SPair x y) (SPair z t)" instance Quad_type_const :: (type) type .. subsection {* Lemmas and proof tool setup.*} lemma "[(a, b, c, e)] = [(a', b', c', e')] = (a = a' & b = b' & c = c' & e = e')" by simp lemma Quad_eq [iff]: "([(a, b, c, e)] = [(a', b', c', e')]) = (a = a' & b = b' & c = c' & e = e')" by auto lemma fst_quad_conv [simp,code]: "fst_quad [(a, b, c, e)] = a" unfolding fst_quad_def by blast lemma snd_quad_conv [simp,code]: "snd_quad [(a, b, c, e)] = b" unfolding snd_quad_def by blast lemma thrd_quad_conv [simp,code]: "thrd_quad [(a, b, c, e)] = c" unfolding thrd_quad_def by blast lemma frth_quad_conv [simp,code]: "frth_quad [(a, b, c, e)] = e" unfolding frth_quad_def by blast lemma fst_quad_eqD: "fst_quad [(x, y, z, t)] = a ==> x = a" by simp lemma snd_quad_eqD: "snd_quad [(x, y, z, t)] = a ==> y = a" by simp lemma thrd_quad_eqD: "thrd_quad [(x, y, z, t)] = a ==> z = a" by simp lemma frth_quad_eqD: "frth_quad [(x, y, z, t)] = a ==> t = a" by simp lemma surjective_quad: "p = [(fst_quad p, snd_quad p, thrd_quad p, frth_quad p)]" proof (cases p) fix SProd1 SProd2 show "p = Quad SProd1 SProd2 ==> p = Quad (SPair (fst_quad p) (snd_quad p)) (SPair (thrd_quad p) (frth_quad p))" by (cases SProd1, cases SProd2, auto simp add: surjective_spair) qed lemma split_Quad_all: "(!!x. PROP P x) == (!!a b c e. PROP P [(a, b, c, e)])" proof fix a b c e assume "!!x. PROP P x" then show "PROP P [(a, b, c, e)]" . next fix x assume "!!a b c e. PROP P [(a, b, c, e)]" from `PROP P [(fst_quad (x::'a Quad_type_const), snd_quad x, thrd_quad x, frth_quad x)]` sym [OF surjective_quad [of "x::'a Quad_type_const"]] show "PROP P x" by simp qed text{*We now prove that the introduced four tuples data type is an instance of the type classes needed in the BPL*} text{*As far as @{typ int} is not a type class, but a type constructor, we will use @{text ring} as a type class.*} text{*Therefore, we prove that our type constructor @{text "Quad_type_const"} with suitable operations is a valid instance of the type class @{text [break] "(ring) diff_group_add_pert_hom_bound_exist"}*} text{*Being @{typ int} a valid instance of @{text ring}, we can then, in the code generation phase, replace @{text ring} by its concrete structure @{text int}*} text{*Note that giving an instance of @{text [break] diff_group_add_pert_hom_bound_exist} requires proving that @{text [break] "(ring) diff_group_add_pert_hom_bound_exist"} is a differential group, with a perturbation and a homotopy operator, which also satisfy the nilpotency condition. This type class contains all definitions involved in the specification of the series @{term [locale=diff_group_add_pert_hom_bound_exist] "Φ"} and @{term [locale=diff_group_add_pert_hom_bound_exist] "Ψ"}*} instance Quad_type_const :: (eq) eq .. lemma [code func]: "[(x1::'a::eq, x2, x3, x4)] = [(y1, y2, y3, y4)] <-> x1 = y1 ∧ x2 = y2 ∧ x3 = y3 ∧ x4 = y4" by auto instantiation Quad_type_const :: ("{eq,ring}") ab_semigroup_add begin definition Quad_type_const_plus_def: "a + b = [( (fst_quad a + fst_quad b), (snd_quad a + snd_quad b), (thrd_quad a + thrd_quad b), (frth_quad a + frth_quad b))]" instance by default (simp_all add: split_Quad_all Quad_type_const_plus_def) end instantiation Quad_type_const :: ("{eq,ring}") comm_monoid_add begin definition Quad_type_const_zero_def: "0 ≡ [( 0, 0, 0, 0)]" instance by default (simp_all add: split_Quad_all Quad_type_const_plus_def Quad_type_const_zero_def) end instantiation Quad_type_const :: ("{eq,ring}") ab_group_add begin definition Quad_type_const_uminus_def: "- x = [( - fst_quad x, - snd_quad x, - thrd_quad x, - frth_quad x)]" definition Quad_type_const_minus_def: "(x::'a Quad_type_const) - y = x + (- y)" instance apply default unfolding Quad_type_const_uminus_def unfolding Quad_type_const_plus_def unfolding Quad_type_const_zero_def unfolding Quad_type_const_minus_def unfolding Quad_type_const_uminus_def unfolding Quad_type_const_plus_def by simp_all end instantiation Quad_type_const :: ("{eq,ring}") diff_group_add begin definition Quad_type_const_diff_def: "diff x ≡ [( 0, fst_quad x + fst_quad x, 0, thrd_quad x)]" instance apply default unfolding expand_fun_eq unfolding o_apply unfolding Quad_type_const_diff_def unfolding Quad_type_const_plus_def unfolding Quad_type_const_zero_def unfolding Quad_type_const_minus_def unfolding Quad_type_const_uminus_def by simp_all end instantiation Quad_type_const :: ("{eq,ring}") diff_group_add_pert begin definition Quad_type_const_pert_def: "pert x ≡ [( 0, fst_quad x + thrd_quad x, 0, fst_quad x)]" instance apply default unfolding Quad_type_const_pert_def unfolding Quad_type_const_plus_def apply simp unfolding diff_group_add_def unfolding diff_group_add_axioms_def unfolding ab_group_add_def unfolding ab_group_add_axioms_def unfolding comm_monoid_add_def unfolding comm_monoid_add_axioms_def unfolding ab_semigroup_add_def unfolding ab_semigroup_add_axioms_def unfolding semigroup_add_def unfolding Quad_type_const_plus_def unfolding Quad_type_const_zero_def unfolding Quad_type_const_uminus_def Quad_type_const_minus_def unfolding Quad_type_const_diff_def unfolding Quad_type_const_plus_def unfolding expand_fun_eq by (simp add: sym [OF surjective_quad]) end instantiation Quad_type_const :: ("{eq,ring}") diff_group_add_pert_hom begin definition Quad_type_const_hom_oper_def: "hom_oper x ≡ [( 0, 0, frth_quad x, 0)]" instance apply default unfolding split_Quad_all unfolding Quad_type_const_hom_oper_def unfolding Quad_type_const_plus_def unfolding Quad_type_const_zero_def unfolding Quad_type_const_minus_def unfolding Quad_type_const_uminus_def unfolding expand_fun_eq by auto end lemma funpow_2: shows "f^(2::nat) = f o f" unfolding numerals (3) unfolding funpow.simps (2) unfolding funpow.simps (1) unfolding o_id .. instantiation Quad_type_const :: ("{eq,ring}") diff_group_add_pert_hom_bound_exist begin instance proof default show "∀x::'a Quad_type_const. ∃n. (α ^ n) x = 0" proof (rule allI) fix x :: "'a Quad_type_const" show "∃n. (α ^ n) x = (0)" unfolding α_def unfolding Quad_type_const_pert_def unfolding Quad_type_const_hom_oper_def unfolding Quad_type_const_uminus_def unfolding Quad_type_const_zero_def apply (rule exI [of _ "2::nat"]) unfolding funpow_2 by simp qed qed end subsection{*Code generation and examples of execution*} definition foos :: "int Quad_type_const" where "foos = Φ [((5::int), 3, 8, 9)]" definition foos_2:: "int Quad_type_const" where "foos_2 = Φ [((5::int), (- 6), 8, 9)]" definition foos_3:: "int Quad_type_const" where "foos_3 = Ψ [((5::int), 3, 8, 9)]" definition foos_4:: "int Quad_type_const" where "foos_4 = Ψ [((5::int), (- 6), 8, 9)]" definition foos_local_bound_alpha :: nat where "foos_local_bound_alpha = local_bound α [((5::int), 3, 8, 9)]" definition foos_f :: "int Quad_type_const => int SProd" where "foos_f = f' (λx::int Quad_type_const. (SPair (fst_quad x) (snd_quad x)))" definition foos_f2:: "int SProd" where "foos_f2 = foos_f [((4::int), 23, 17, 1)]" definition foos_g:: "int SProd => int Quad_type_const" where "foos_g = g' (λx::int SProd. [(fst_spair x, snd_spair x, 0, 0)])" definition foos_g2:: "int Quad_type_const" where "foos_g2 = foos_g [((15::int), 8)]" definition foos_h:: "int Quad_type_const => int Quad_type_const" where "foos_h = (h'::(int Quad_type_const => int Quad_type_const))" definition foos_h2:: "int Quad_type_const" where "foos_h2 = foos_h [((12::int), 22, 19, 6)]" definition foos_dC':: "(int SProd => int SProd)" where "foos_dC' = dC' (λx::int Quad_type_const. SPair (fst_quad x) (snd_quad x)) (λx::int SProd. [(fst_spair x, snd_spair x, 0, 0)])" definition foos_dC'2 :: "int SProd" where "foos_dC'2 = foos_dC' [((5::int), 3)]" export_code foos foos_2 foos_local_bound_alpha foos_3 foos_4 foos_f foos_f2 foos_g foos_g2 foos_h foos_h2 foos_dC' foos_dC'2 in SML module_name "ExampleZ4Z2" file "example_Z4Z2.ML" use "example_Z4Z2.ML" ML "open ExampleZ4Z2" ML "foos" ML "foos_2" ML "foos_3" ML "foos_4" ML "foos_f2" ML "foos_g2" ML "foos_h2" ML "foos_dC'2" ML "foos_local_bound_alpha" end
lemma
fst_spair p = (THE a. ∃b. p = SPair a b)
snd_spair p == THE b. ∃a. p = SPair a b
lemma SPair_eq:
([(a, b)] = [(a', b')]) = (a = a' ∧ b = b')
lemma fst_spair_conv:
fst_spair [(a, b)] = a
lemma snd_spair_conv:
snd_spair [(a, b)] = b
lemma fst_spair_eqD:
fst_spair [(x, y)] = a ==> x = a
lemma snd_spair_eqD:
snd_spair [(x, y)] = a ==> y = a
lemma surjective_spair:
p = [(fst_spair p, snd_spair p)]
lemma split_SPair_all:
(!!x. PROP P x) == (!!a b. PROP P [(a, b)])
lemma
([(x1.0, x2.0)] = [(y1.0, y2.0)]) = (x1.0 = y1.0 ∧ x2.0 = y2.0)
lemma
fst_quad p == THE a. ∃b c e. p = Quad [(a, b)] [(c, e)]
snd_quad p == THE b. ∃a c e. p = Quad [(a, b)] [(c, e)]
thrd_quad p == THE c. ∃a b e. p = Quad [(a, b)] [(c, e)]
frth_quad p == THE e. ∃a b c. p = Quad [(a, b)] [(c, e)]
lemma
([(a, b, c, e)] = [(a', b', c', e')]) = (a = a' ∧ b = b' ∧ c = c' ∧ e = e')
lemma Quad_eq:
([(a, b, c, e)] = [(a', b', c', e')]) = (a = a' ∧ b = b' ∧ c = c' ∧ e = e')
lemma fst_quad_conv:
fst_quad [(a, b, c, e)] = a
lemma snd_quad_conv:
snd_quad [(a, b, c, e)] = b
lemma thrd_quad_conv:
thrd_quad [(a, b, c, e)] = c
lemma frth_quad_conv:
frth_quad [(a, b, c, e)] = e
lemma fst_quad_eqD:
fst_quad [(x, y, z, t)] = a ==> x = a
lemma snd_quad_eqD:
snd_quad [(x, y, z, t)] = a ==> y = a
lemma thrd_quad_eqD:
thrd_quad [(x, y, z, t)] = a ==> z = a
lemma frth_quad_eqD:
frth_quad [(x, y, z, t)] = a ==> t = a
lemma surjective_quad:
p = [(fst_quad p, snd_quad p, thrd_quad p, frth_quad p)]
lemma split_Quad_all:
(!!x. PROP P x) == (!!a b c e. PROP P [(a, b, c, e)])
lemma
([(x1.0, x2.0, x3.0, x4.0)] = [(y1.0, y2.0, y3.0, y4.0)]) =
(x1.0 = y1.0 ∧ x2.0 = y2.0 ∧ x3.0 = y3.0 ∧ x4.0 = y4.0)
lemma funpow_2:
f ^ 2 = f o f