(*
Copyright 2018

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*)
theory AbstractFloat
  imports reassembly_machine.Machine
begin

definition signed_greater_than :: "'a :: len word \<Rightarrow> 'a :: len word \<Rightarrow> bool" ("(_/ >s _)" [50, 51] 50)
  where "a >s b \<equiv> a \<noteq> b \<and> \<not>(a <s b)"
declare signed_greater_than_def[symmetric,simp add]

definition signed_le :: "'a :: len word \<Rightarrow> 'a :: len word \<Rightarrow> bool" ("(_/ \<le>s _)" [50, 51] 50)
  where "a \<le>s b \<equiv> a = b \<or> a <s b"
declare signed_le_def[symmetric,simp add]

lemma signed_not_le[simp]:
  shows "\<not> a \<le>s b \<longleftrightarrow> a >s b"
  unfolding signed_le_def signed_greater_than_def
  by metis

subsection "Making a float"

text \<open> Make a float from a sign-bit, an exponent and a mantissa. \<close>
fun mk_float :: "bool \<times> nat \<times> nat \<Rightarrow> 64 word"
  where "mk_float (s,e,m) = ((if s then 1 else 0) << 63) OR (of_nat e AND mask 11 << 52) OR (of_nat m AND mask 52)"

text \<open> Simplify @{term mk_float} only when it is given concrete values. \<close>
lemmas mk_float_simps_numeral[simp] =
  mk_float.simps[of True 0 0]
  mk_float.simps[of True 0 1]
  mk_float.simps[of True 0 "numeral m"]
  mk_float.simps[of True 1 0]
  mk_float.simps[of True 1 1]
  mk_float.simps[of True 1 "numeral m"]
  mk_float.simps[of True "numeral n" 0]
  mk_float.simps[of True "numeral n" 1]
  mk_float.simps[of True "numeral n" "numeral m"]
  mk_float.simps[of False 0 0]
  mk_float.simps[of False 0 1]
  mk_float.simps[of False 0 "numeral m"]
  mk_float.simps[of False 1 0]
  mk_float.simps[of False 1 1]
  mk_float.simps[of False 1 "numeral m"]
  mk_float.simps[of False "numeral n" 0]
  mk_float.simps[of False "numeral n" 1]
  mk_float.simps[of False "numeral n" "numeral m"]
  for n m
declare mk_float.simps[simp del]

text \<open>Constants and Accessor Functions\<close>

definition plus_zero :: "64 word" ("0\<^sup>+")
  where "plus_zero \<equiv> mk_float (False,0,0)"

definition minus_zero :: "64 word" ("0\<^sup>-")
  where "minus_zero \<equiv> mk_float (True,0,0)"

definition plus_infty :: "64 word" ("\<infinity>\<^sup>+")
  where "plus_infty \<equiv> mk_float (False,2^12 - 1,0)"

definition minus_infty :: "64 word" ("\<infinity>\<^sup>-")
  where "minus_infty \<equiv> mk_float (True,2^12 - 1,0)"

definition exp :: "64 word \<Rightarrow> 64 word"
  where "exp w \<equiv> \<langle>62,52\<rangle>w"

definition mant :: "64 word \<Rightarrow> 64 word"
  where "mant w \<equiv> \<langle>51,0\<rangle>w"

definition sign :: "64 word \<Rightarrow> bool"
  where "sign \<equiv> msb"

definition isNaN :: "64 word \<Rightarrow> bool"
  where "isNaN w \<equiv> exp w = 2^12-1"

definition float_abs :: "'a::len0 word \<Rightarrow> 'a::len0 word" ("\<bar>_\<bar>\<^sup>f")
  where "\<bar>w\<bar>\<^sup>f \<equiv> set_bit w (LENGTH('a) - 1)  False"

(*
lemma sign_mk_float:
  shows "sign (mk_float (s,e,m)) = s"
  unfolding sign_def
  by (auto simp add: msb_nth mk_float.simps test_bit_of_take_bits word_ao_nth nth_shiftl)

lemma exp_mk_float:
  shows "exp (mk_float (s,e,m)) = ((of_nat e)::64 word) AND mask 11"
  unfolding exp_def
  apply word_bitwise
  by (auto simp add: mk_float.simps test_bit_of_take_bits word_ao_nth nth_shiftl)

lemma mant_mk_float:
  shows "mant (mk_float (s,e,m)) = ((of_nat m)::64 word) AND mask 52"
  unfolding mant_def
  apply word_bitwise
  apply (auto simp add: mk_float.simps test_bit_of_take_bits word_ao_nth nth_shiftl simp del: take_bits_bitAND)
  by (simp only: numeral_2_eq_2)+
*)

datatype float_cmp = Unordered | GT | LT | EQ

text \<open>
  For the following functions, we do not yet have an implementation.
  We constraint them according the IEEE 754 standard.
\<close>

locale abstract_float =
  fixes float_plus :: "64 word \<Rightarrow> 64 word \<Rightarrow> 64 word" (infixl "+\<^sup>f" 65)
    and float_minus :: "64 word \<Rightarrow> 64 word \<Rightarrow> 64 word" (infixl "-\<^sup>f" 65)
    and float_times:: "64 word \<Rightarrow> 64 word \<Rightarrow> 64 word" (infixl "*\<^sup>f" 65)
    and float_div :: "64 word \<Rightarrow> 64 word \<Rightarrow> 64 word" (infixl "div\<^sup>f" 65)
    and float_mod :: "64 word \<Rightarrow> 64 word \<Rightarrow> 64 word" (infixl "mod\<^sup>f" 70)
    and float_ucmp :: "64 word \<Rightarrow> 64 word \<Rightarrow> float_cmp"
assumes plus_plus_zero [simp]: "x +\<^sup>f 0\<^sup>+ = x"
    and plus_minus_zero[simp]: "x +\<^sup>f 0\<^sup>- = x"
    and div_zero [simp]: "x \<notin> {0\<^sup>-,0\<^sup>+} \<Longrightarrow> 0\<^sup>- div\<^sup>f \<bar>x\<bar>\<^sup>f = 0\<^sup>-"
    and isNan_div_0_0: "x \<in> {0\<^sup>-,0\<^sup>+} \<Longrightarrow> y \<in> {0\<^sup>-,0\<^sup>+} \<Longrightarrow> isNaN (x div\<^sup>f y)"
    and div_by_plus_zero:  "x \<notin> {0\<^sup>-,0\<^sup>+} \<Longrightarrow> x div\<^sup>f 0\<^sup>+ = (if sign x then \<infinity>\<^sup>- else \<infinity>\<^sup>+)"
    and div_by_minus_zero: "x \<notin> {0\<^sup>-,0\<^sup>+} \<Longrightarrow> x div\<^sup>f 0\<^sup>- = (if sign x then \<infinity>\<^sup>+ else \<infinity>\<^sup>-)"
    and times_by_plus_zero [simp]: "x *\<^sup>f 0\<^sup>+ = (if sign x then 0\<^sup>- else 0\<^sup>+)"
    and time_by_neg_zero [simp]: "x *\<^sup>f 0\<^sup>- = (if sign x then 0\<^sup>+ else 0\<^sup>-)"
    and times_plus_zero: "0\<^sup>+ *\<^sup>f x = (if sign x then 0\<^sup>- else 0\<^sup>+)"
    and times_neg_zero: "0\<^sup>- *\<^sup>f x = (if sign x then 0\<^sup>+ else 0\<^sup>-)"
begin

end

lemma bit_AND_bit_pattern_is_float_abs_bit32[simp]:
  fixes w :: "32 word"
  shows "w AND 2147483647 = \<bar>w\<bar>\<^sup>f"
  apply (word_bitwise)
  by (auto simp add: word_ao_nth float_abs_def test_bit_set_gen)
lemma bit_AND_bit_pattern_is_float_abs_bit64[simp]:
  fixes a :: "64 word"
  shows "a AND 9223372036854775807 = \<bar>a\<bar>\<^sup>f"
  unfolding float_abs_def
  apply word_bitwise
  by (auto simp add: test_bit_set_gen del: )

end


(*   This file is a part of IsarMathLib -
    a library of formalized mathematics for Isabelle/Isar.

    Copyright (C) 2006  Slawomir Kolodynski

    This program is free software; Redistribution and use in source and binary forms,
    with or without modification, are permitted provided that the following conditions are met:

   1. Redistributions of source code must retain the above copyright notice,
   this list of conditions and the following disclaimer.
   2. 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.
   3. The name of the author may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.

*)

section \<open>Complex numbers\<close>

theory Complex_ZF imports func_ZF_1 OrderedField_ZF

begin

text\<open>The goal of this theory is to define complex numbers
  and prove that the Metamath complex numbers axioms hold.\<close>

subsection\<open>From complete ordered fields to complex numbers\<close>

text\<open>This section consists mostly of definitions and a proof
  context for talking about complex numbers.
  Suppose we have a set $R$ with binary operations $A$ and
  $M$ and a relation $r$ such that the quadruple $(R,A,M,r)$
  forms a complete ordered field.
  The next definitions take $(R,A,M,r)$ and
  construct the sets that represent the structure of complex numbers:
  the carrier ($\mathbb{C}=R\times R$), binary operations of
  addition and multiplication of complex numbers and the order
  relation on $\mathbb{R}=R\times 0$.
  The \<open>ImCxAdd, ReCxAdd, ImCxMul, ReCxMul\<close> are helper
  meta-functions representing the imaginary part of a sum of
  complex numbers, the real part of a sum of real numbers, the
  imaginary part of a product of
  complex numbers and the real part of a product of real numbers,
  respectively. The actual operations (subsets of $(R\times R)\times R$
  are named \<open>CplxAdd\<close> and \<open>CplxMul\<close>.

  When $R$ is an ordered field, it comes with an order relation.
  This induces a natural strict order relation on
  $\{\langle x,0\rangle : x\in R\}\subseteq R\times R$. We call the
  set $\{\langle x,0\rangle : x\in R\}$ \<open>ComplexReals(R,A)\<close>
  and the strict order relation \<open>CplxROrder(R,A,r)\<close>.
  The order on the real axis of complex numbers is defined
  as the relation induced on it by the
  canonical projection on the first coordinate and the order
  we have on the real numbers.
  OK, lets repeat this slower.
  We start with the order relation $r$ on a (model of) real numbers $R$.
  We want to define an order relation on a subset of complex
  numbers, namely on $R\times \{0\}$. To do that we use the notion of
  a relation induced by a mapping. The mapping here is
  $f:R\times \{0\}\rightarrow R, f\langle x,0 \rangle = x$
  which is defined under a name of
  \<open>SliceProjection\<close> in \<open>func_ZF.thy\<close>.
  This defines a relation $r_1$ (called \<open>InducedRelation(f,r)\<close>,
  see \<open>func_ZF\<close>) on $R\times \{0\}$ such that
  $ \langle \langle x, 0\rangle, \langle y,0\rangle
  \in r_1$ iff $\langle x,y\rangle \in r$. This way we get what we call
  \<open>CplxROrder(R,A,r)\<close>. However, this is not the
  end of the story, because Metamath uses strict inequalities in its axioms,
  rather than weak ones like IsarMathLib (mostly). So we need to take
  the strict version of this order relation. This is done in
  the syntax definition of \<open>\<lsr>\<close> in the definition of
  \<open>complex0\<close> context. Since Metamath proves a lot of theorems
  about the real numbers extended with $+\infty$ and $-\infty$, we define
  the notation for inequalites on the extended real line as well.
\<close>

text\<open>A helper expression representing the real part
  of the sum of two complex numbers.\<close>

definition
  "ReCxAdd(R,A,a,b) \<equiv> A`\<langle>fst(a),fst(b)\<rangle>"

text\<open>An expression representing the imaginary part of the sum
  of two complex numbers.\<close>

definition
  "ImCxAdd(R,A,a,b) \<equiv> A`\<langle>snd(a),snd(b)\<rangle>"

text\<open>The set (function) that is the binary operation that adds complex numbers.\<close>

definition
  "CplxAdd(R,A) \<equiv>
  {\<langle>p, \<langle> ReCxAdd(R,A,fst(p),snd(p)),ImCxAdd(R,A,fst(p),snd(p)) \<rangle> \<rangle>.
  p\<in>(R\<times>R)\<times>(R\<times>R)}"

text\<open>The expression representing the imaginary part of the
  product of complex numbers.\<close>

definition
  "ImCxMul(R,A,M,a,b) \<equiv> A`\<langle>M`\<langle>fst(a),snd(b)\<rangle>, M`\<langle>snd(a),fst(b)\<rangle> \<rangle>"

text\<open>The expression representing the real part of the
  product of complex numbers.\<close>

definition
  "ReCxMul(R,A,M,a,b) \<equiv>
  A`\<langle>M`\<langle>fst(a),fst(b)\<rangle>,GroupInv(R,A)`(M`\<langle>snd(a),snd(b)\<rangle>)\<rangle>"

text\<open>The function (set) that represents the binary operation of
  multiplication of complex numbers.\<close>

definition
  "CplxMul(R,A,M) \<equiv>
  { \<langle>p, \<langle>ReCxMul(R,A,M,fst(p),snd(p)),ImCxMul(R,A,M,fst(p),snd(p))\<rangle> \<rangle>.
  p \<in> (R\<times>R)\<times>(R\<times>R)}"

text\<open>The definition real numbers embedded in the complex plane.\<close>

definition
  "ComplexReals(R,A) \<equiv> R\<times>{TheNeutralElement(R,A)}"

text\<open>Definition of order relation on the real line.\<close>

definition
  "CplxROrder(R,A,r) \<equiv>
  InducedRelation(SliceProjection(ComplexReals(R,A)),r)"

text\<open>The next locale defines proof context and notation that will be
  used for complex numbers.\<close>

locale complex0 =
  fixes R and A and M and r
  assumes R_are_reals: "IsAmodelOfReals(R,A,M,r)"

  fixes complex ("\<complex>")
  defines complex_def[simp]: "\<complex> \<equiv> R\<times>R"

  fixes rone ("\<one>\<^sub>R")
  defines rone_def[simp]: "\<one>\<^sub>R \<equiv> TheNeutralElement(R,M)"

  fixes rzero ("\<zero>\<^sub>R")
  defines rzero_def[simp]: "\<zero>\<^sub>R \<equiv> TheNeutralElement(R,A)"

  fixes one ("\<one>")
  defines one_def[simp]: "\<one> \<equiv> \<langle>\<one>\<^sub>R, \<zero>\<^sub>R\<rangle>"

  fixes zero ("\<zero>")
  defines zero_def[simp]: "\<zero> \<equiv> \<langle>\<zero>\<^sub>R, \<zero>\<^sub>R\<rangle>"

  fixes iunit ("\<i>")
  defines iunit_def[simp]: "\<i> \<equiv> \<langle>\<zero>\<^sub>R,\<one>\<^sub>R\<rangle>"

  fixes creal ("\<real>")
  defines creal_def[simp]: "\<real> \<equiv> {\<langle>r,\<zero>\<^sub>R\<rangle>. r\<in>R}"

  fixes rmul (infixl "\<rmu>" 71)
  defines rmul_def[simp]: "a \<rmu> b \<equiv> M`\<langle>a,b\<rangle>"

  fixes radd (infixl "\<ra>" 69)
  defines radd_def[simp]: "a \<ra> b \<equiv> A`\<langle>a,b\<rangle>"

  fixes rneg ("\<rm> _" 70)
  defines rneg_def[simp]: "\<rm> a \<equiv>  GroupInv(R,A)`(a)"

  fixes ca (infixl "\<ca>" 69)
  defines ca_def[simp]: "a \<ca> b \<equiv> CplxAdd(R,A)`\<langle>a,b\<rangle>"

  fixes cm (infixl "\<cdot>" 71)
  defines cm_def[simp]: "a \<cdot> b \<equiv> CplxMul(R,A,M)`\<langle>a,b\<rangle>"

  fixes cdiv (infixl "\<cdiv>" 70)
  defines cdiv_def[simp]: "a \<cdiv> b \<equiv> \<Union> { x \<in> \<complex>. b \<cdot> x = a }"

  fixes sub (infixl "\<cs>" 69)
  defines sub_def[simp]: "a \<cs> b \<equiv> \<Union> { x \<in> \<complex>. b \<ca> x = a }"

  fixes cneg ("\<cn>_" 95)
  defines cneg_def[simp]: "\<cn> a \<equiv> \<zero> \<cs> a"

  fixes lessr (infix "\<lsr>" 68)
  defines lessr_def[simp]:
  "a \<lsr> b \<equiv> \<langle>a,b\<rangle> \<in> StrictVersion(CplxROrder(R,A,r))"

  fixes cpnf ("\<cpnf>")
  defines cpnf_def[simp]: "\<cpnf> \<equiv> \<complex>"

  fixes cmnf ("\<cmnf>")
  defines cmnf_def[simp]: "\<cmnf> \<equiv> {\<complex>}"

  fixes cxr ("\<real>\<^sup>*")
  defines cxr_def[simp]: "\<real>\<^sup>* \<equiv> \<real> \<union> {\<cpnf>,\<cmnf>}"

  fixes cxn ("\<nat>")
  defines cxn_def[simp]:
  "\<nat> \<equiv> \<Inter> {N \<in> Pow(\<real>). \<one> \<in> N \<and> (\<forall>n. n\<in>N \<longrightarrow> n\<ca>\<one> \<in> N)}"

  fixes cltrrset ("\<cltrrset>")
  defines cltrrset_def[simp]:
  "\<cltrrset> \<equiv>  StrictVersion(CplxROrder(R,A,r)) \<inter> \<real>\<times>\<real> \<union>
  {\<langle>\<cmnf>,\<cpnf>\<rangle>} \<union> (\<real>\<times>{\<cpnf>}) \<union> ({\<cmnf>}\<times>\<real> )"

  fixes cltrr (infix "\<ls>" 68)
  defines cltrr_def[simp]: "a \<ls> b \<equiv> \<langle>a,b\<rangle> \<in> \<cltrrset>"

  fixes lsq (infix "\<lsq>" 68)
  defines lsq_def[simp]: "a \<lsq> b \<equiv> \<not> (b \<ls> a)"

  fixes two ("\<two>")
  defines two_def[simp]: "\<two> \<equiv> \<one> \<ca> \<one>"

  fixes three ("\<three>")
  defines three_def[simp]: "\<three> \<equiv> \<two>\<ca>\<one>"

  fixes four ("\<four>")
  defines four_def[simp]: "\<four> \<equiv> \<three>\<ca>\<one>"

  fixes five ("\<five>")
  defines five_def[simp]: "\<five> \<equiv> \<four>\<ca>\<one>"

  fixes six ("\<six>")
  defines six_def[simp]: "\<six> \<equiv> \<five>\<ca>\<one>"

  fixes seven ("\<seven>")
  defines seven_def[simp]: "\<seven> \<equiv> \<six>\<ca>\<one>"

  fixes eight ("\<eight>")
  defines eight_def[simp]: "\<eight> \<equiv> \<seven>\<ca>\<one>"

  fixes nine ("\<nine>")
  defines nine_def[simp]: "\<nine> \<equiv> \<eight>\<ca>\<one>"

subsection\<open>Axioms of complex numbers\<close>

text\<open>In this section we will prove that all Metamath's axioms of complex
  numbers hold in the \<open>complex0\<close> context.\<close>

text\<open>The next lemma lists some contexts that are valid in the \<open>complex0\<close>
  context.\<close>

lemma (in complex0) valid_cntxts: shows
  "field1(R,A,M,r)"
  "field0(R,A,M)"
  "ring1(R,A,M,r)"
  "group3(R,A,r)"
  "ring0(R,A,M)"
  "M {is commutative on} R"
  "group0(R,A)"
proof -
  from R_are_reals have I: "IsAnOrdField(R,A,M,r)"
    using IsAmodelOfReals_def by simp
  then show "field1(R,A,M,r)" using OrdField_ZF_1_L2 by simp
  then show "ring1(R,A,M,r)" and I: "field0(R,A,M)"
    using field1.axioms ring1_def field1.OrdField_ZF_1_L1B
    by auto
  then show "group3(R,A,r)" using ring1.OrdRing_ZF_1_L4
    by simp
  from I have "IsAfield(R,A,M)" using field0.Field_ZF_1_L1
    by simp
  then have "IsAring(R,A,M)" and "M {is commutative on} R"
    using IsAfield_def by auto
  then show "ring0(R,A,M)" and "M {is commutative on} R"
    using ring0_def by auto
  then show "group0(R,A)" using ring0.Ring_ZF_1_L1
    by simp
qed

text\<open>The next lemma shows the definition of real and imaginary part of
  complex sum and product in a more readable form using notation defined
  in \<open>complex0\<close> locale.\<close>

lemma (in complex0) cplx_mul_add_defs: shows
  "ReCxAdd(R,A,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) = a \<ra> c"
  "ImCxAdd(R,A,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) = b \<ra> d"
  "ImCxMul(R,A,M,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) = a\<rmu>d \<ra> b\<rmu>c"
  "ReCxMul(R,A,M,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) =  a\<rmu>c \<ra> (\<rm>b\<rmu>d)"
proof -
  let ?z\<^sub>1 = "\<langle>a,b\<rangle>"
  let ?z\<^sub>2 = "\<langle>c,d\<rangle>"
  have "ReCxAdd(R,A,?z\<^sub>1,?z\<^sub>2) \<equiv>  A`\<langle>fst(?z\<^sub>1),fst(?z\<^sub>2)\<rangle>"
   by (rule ReCxAdd_def)
  moreover have "ImCxAdd(R,A,?z\<^sub>1,?z\<^sub>2) \<equiv>  A`\<langle>snd(?z\<^sub>1),snd(?z\<^sub>2)\<rangle>"
    by (rule ImCxAdd_def)
  moreover have
    "ImCxMul(R,A,M,?z\<^sub>1,?z\<^sub>2) \<equiv> A`\<langle>M`<fst(?z\<^sub>1),snd(?z\<^sub>2)>,M`<snd(?z\<^sub>1),fst(?z\<^sub>2)>\<rangle>"
    by (rule ImCxMul_def)
  moreover have
    "ReCxMul(R,A,M,?z\<^sub>1,?z\<^sub>2) \<equiv>
    A`\<langle>M`<fst(?z\<^sub>1),fst(?z\<^sub>2)>,GroupInv(R,A)`(M`\<langle>snd(?z\<^sub>1),snd(?z\<^sub>2)\<rangle>)\<rangle>"
    by (rule ReCxMul_def)
  ultimately show
    "ReCxAdd(R,A,?z\<^sub>1,?z\<^sub>2) =  a \<ra> c"
    "ImCxAdd(R,A,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) = b \<ra> d"
    "ImCxMul(R,A,M,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) = a\<rmu>d \<ra> b\<rmu>c"
    "ReCxMul(R,A,M,\<langle>a,b\<rangle>,\<langle>c,d\<rangle>) =  a\<rmu>c \<ra> (\<rm>b\<rmu>d)"
    by auto
qed

text\<open>Real and imaginary parts of sums and products of complex numbers
  are real.\<close>

lemma (in complex0) cplx_mul_add_types:
  assumes A1: "z\<^sub>1 \<in> \<complex>"   "z\<^sub>2 \<in> \<complex>"
  shows
  "ReCxAdd(R,A,z\<^sub>1,z\<^sub>2) \<in> R"
  "ImCxAdd(R,A,z\<^sub>1,z\<^sub>2) \<in> R"
  "ImCxMul(R,A,M,z\<^sub>1,z\<^sub>2) \<in> R"
  "ReCxMul(R,A,M,z\<^sub>1,z\<^sub>2) \<in> R"
proof -
  let ?a = "fst(z\<^sub>1)"
  let ?b = "snd(z\<^sub>1)"
  let ?c = "fst(z\<^sub>2)"
  let ?d = "snd(z\<^sub>2)"
  from A1 have "?a \<in> R"  "?b \<in> R"  "?c \<in> R"  "?d \<in> R"
    by auto
  then have
    "?a \<ra> ?c \<in> R"
    "?b \<ra> ?d \<in> R"
    "?a\<rmu>?d \<ra> ?b\<rmu>?c \<in> R"
    "?a\<rmu>?c \<ra> (\<rm> ?b\<rmu>?d) \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L4 by auto
  with A1 show
    "ReCxAdd(R,A,z\<^sub>1,z\<^sub>2) \<in> R"
    "ImCxAdd(R,A,z\<^sub>1,z\<^sub>2) \<in> R"
    "ImCxMul(R,A,M,z\<^sub>1,z\<^sub>2) \<in> R"
    "ReCxMul(R,A,M,z\<^sub>1,z\<^sub>2) \<in> R"
    using cplx_mul_add_defs by auto
qed

text\<open>Complex reals are complex. Recall the definition of \<open>\<real>\<close>
  in the \<open>complex0\<close> locale.\<close>

lemma (in complex0) axresscn: shows "\<real> \<subseteq> \<complex>"
  using valid_cntxts group0.group0_2_L2 by auto

text\<open>Complex $1$ is not complex $0$.\<close>

lemma (in complex0) ax1ne0: shows "\<one> \<noteq> \<zero>"
proof -
  have "IsAfield(R,A,M)" using valid_cntxts field0.Field_ZF_1_L1
    by simp
  then show "\<one> \<noteq> \<zero>" using IsAfield_def by auto
qed

text\<open>Complex addition is a complex valued binary
  operation on complex numbers.\<close>

lemma (in complex0) axaddopr: shows "CplxAdd(R,A): \<complex> \<times> \<complex> \<rightarrow> \<complex>"
proof -
  have "\<forall>p \<in> \<complex>\<times>\<complex>.
    \<langle>ReCxAdd(R,A,fst(p),snd(p)),ImCxAdd(R,A,fst(p),snd(p))\<rangle> \<in> \<complex>"
    using cplx_mul_add_types by simp
  then have
    "{\<langle>p,\<langle>ReCxAdd(R,A,fst(p),snd(p)),ImCxAdd(R,A,fst(p),snd(p))\<rangle> \<rangle>.
    p \<in> \<complex>\<times>\<complex>}: \<complex>\<times>\<complex> \<rightarrow> \<complex>"
    by (rule ZF_fun_from_total)
  then show "CplxAdd(R,A): \<complex> \<times> \<complex> \<rightarrow> \<complex>" using CplxAdd_def by simp
qed

text\<open>Complex multiplication is a complex valued binary
  operation on complex numbers.\<close>

lemma (in complex0) axmulopr: shows "CplxMul(R,A,M): \<complex> \<times> \<complex> \<rightarrow> \<complex>"
proof -
  have "\<forall>p \<in> \<complex>\<times>\<complex>.
    \<langle>ReCxMul(R,A,M,fst(p),snd(p)),ImCxMul(R,A,M,fst(p),snd(p))\<rangle> \<in> \<complex>"
    using cplx_mul_add_types by simp
  then have
   "{\<langle>p,\<langle>ReCxMul(R,A,M,fst(p),snd(p)),ImCxMul(R,A,M,fst(p),snd(p))\<rangle>\<rangle>.
    p \<in> \<complex>\<times>\<complex>}: \<complex>\<times>\<complex> \<rightarrow> \<complex>" by (rule ZF_fun_from_total)
  then show "CplxMul(R,A,M): \<complex> \<times> \<complex> \<rightarrow> \<complex>" using CplxMul_def by simp
qed

text\<open>What are the values of omplex addition and multiplication
  in terms of their real and imaginary parts?\<close>

lemma (in complex0) cplx_mul_add_vals:
  assumes A1: "a\<in>R"  "b\<in>R"  "c\<in>R"  "d\<in>R"
  shows
  "\<langle>a,b\<rangle> \<ca> \<langle>c,d\<rangle> = \<langle>a \<ra> c, b \<ra> d\<rangle>"
  "\<langle>a,b\<rangle> \<cdot> \<langle>c,d\<rangle> = \<langle>a\<rmu>c \<ra> (\<rm>b\<rmu>d), a\<rmu>d \<ra> b\<rmu>c\<rangle>"
proof -
  let ?S = "CplxAdd(R,A)"
  let ?P = "CplxMul(R,A,M)"
  let ?p = "\<langle> \<langle>a,b\<rangle>, \<langle>c,d\<rangle> \<rangle>"
  from A1 have "?S : \<complex> \<times> \<complex> \<rightarrow> \<complex>" and "?p \<in> \<complex> \<times> \<complex>"
    using axaddopr by auto
  moreover have
    "?S = {\<langle>p, <ReCxAdd(R,A,fst(p),snd(p)),ImCxAdd(R,A,fst(p),snd(p))>\<rangle>.
    p \<in> \<complex> \<times> \<complex>}"
    using CplxAdd_def by simp
  ultimately have "?S`(?p) = \<langle>ReCxAdd(R,A,fst(?p),snd(?p)),ImCxAdd(R,A,fst(?p),snd(?p))\<rangle>"
    by (rule ZF_fun_from_tot_val)
  then show "\<langle>a,b\<rangle> \<ca> \<langle>c,d\<rangle> = \<langle>a \<ra> c, b \<ra> d\<rangle>"
    using cplx_mul_add_defs by simp
  from A1 have "?P : \<complex> \<times> \<complex> \<rightarrow> \<complex>" and "?p \<in> \<complex> \<times> \<complex>"
    using axmulopr by auto
  moreover have
    "?P = {\<langle>p, \<langle>ReCxMul(R,A,M,fst(p),snd(p)),ImCxMul(R,A,M,fst(p),snd(p))\<rangle> \<rangle>.
    p \<in> \<complex> \<times> \<complex>}"
    using CplxMul_def by simp
  ultimately have
    "?P`(?p) = \<langle>ReCxMul(R,A,M,fst(?p),snd(?p)),ImCxMul(R,A,M,fst(?p),snd(?p))\<rangle>"
    by (rule ZF_fun_from_tot_val)
  then show "\<langle>a,b\<rangle> \<cdot> \<langle>c,d\<rangle> = \<langle>a\<rmu>c \<ra> (\<rm>b\<rmu>d), a\<rmu>d \<ra> b\<rmu>c\<rangle>"
    using cplx_mul_add_defs by simp
qed

text\<open>Complex multiplication is commutative.\<close>

lemma (in complex0) axmulcom: assumes A1: "a \<in> \<complex>"  "b \<in> \<complex>"
  shows "a\<cdot>b = b\<cdot>a"
  using assms cplx_mul_add_vals valid_cntxts ring0.Ring_ZF_1_L4
      field0.field_mult_comm by auto

text\<open>A sum of complex numbers is complex.\<close>

lemma (in complex0) axaddcl: assumes "a \<in> \<complex>"  "b \<in> \<complex>"
  shows "a\<ca>b \<in> \<complex>"
  using assms axaddopr apply_funtype by simp

text\<open>A product of complex numbers is complex.\<close>

lemma (in complex0) axmulcl: assumes "a \<in> \<complex>"  "b \<in> \<complex>"
  shows  "a\<cdot>b \<in> \<complex>"
  using assms axmulopr apply_funtype by simp

text\<open>Multiplication is distributive with respect to
  addition.\<close>

lemma (in complex0) axdistr:
  assumes A1: "a \<in> \<complex>"  "b \<in> \<complex>"  "c \<in> \<complex>"
  shows "a\<cdot>(b \<ca> c) = a\<cdot>b \<ca> a\<cdot>c"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?a\<^sub>i = "snd(a)"
  let ?b\<^sub>r = "fst(b)"
  let ?b\<^sub>i = "snd(b)"
  let ?c\<^sub>r = "fst(c)"
  let ?c\<^sub>i = "snd(c)"
  from A1 have T:
    "?a\<^sub>r \<in> R"  "?a\<^sub>i \<in> R"  "?b\<^sub>r \<in> R"  "?b\<^sub>i \<in> R"  "?c\<^sub>r \<in> R"  "?c\<^sub>i \<in> R"
    "?b\<^sub>r\<ra>?c\<^sub>r \<in> R"  "?b\<^sub>i\<ra>?c\<^sub>i \<in> R"
    "?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i) \<in> R"
    "?a\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?c\<^sub>i) \<in> R"
    "?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r \<in> R"
    "?a\<^sub>r\<rmu>?c\<^sub>i \<ra> ?a\<^sub>i\<rmu>?c\<^sub>r \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L4 by auto
  with A1 have "a\<cdot>(b \<ca> c) =
    \<langle>?a\<^sub>r\<rmu>(?b\<^sub>r\<ra>?c\<^sub>r) \<ra> (\<rm>?a\<^sub>i\<rmu>(?b\<^sub>i\<ra>?c\<^sub>i)),?a\<^sub>r\<rmu>(?b\<^sub>i\<ra>?c\<^sub>i) \<ra> ?a\<^sub>i\<rmu>(?b\<^sub>r\<ra>?c\<^sub>r)\<rangle>"
    using cplx_mul_add_vals by auto
  moreover from T have
    "?a\<^sub>r\<rmu>(?b\<^sub>r\<ra>?c\<^sub>r) \<ra> (\<rm>?a\<^sub>i\<rmu>(?b\<^sub>i\<ra>?c\<^sub>i)) =
    ?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i) \<ra> (?a\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?c\<^sub>i))"
    and
    "?a\<^sub>r\<rmu>(?b\<^sub>i\<ra>?c\<^sub>i) \<ra> ?a\<^sub>i\<rmu>(?b\<^sub>r\<ra>?c\<^sub>r) =
    ?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r \<ra> (?a\<^sub>r\<rmu>?c\<^sub>i \<ra> ?a\<^sub>i\<rmu>?c\<^sub>r)"
    using valid_cntxts ring0.Ring_ZF_2_L6 by auto
  moreover from A1 T have
    "\<langle>?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i) \<ra> (?a\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?c\<^sub>i)),
    ?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r \<ra> (?a\<^sub>r\<rmu>?c\<^sub>i \<ra> ?a\<^sub>i\<rmu>?c\<^sub>r)\<rangle> =
    a\<cdot>b \<ca> a\<cdot>c"
    using cplx_mul_add_vals by auto
  ultimately show "a\<cdot>(b \<ca> c) = a\<cdot>b \<ca> a\<cdot>c"
    by simp
qed

text\<open>Complex addition is commutative.\<close>

lemma (in complex0) axaddcom: assumes "a \<in> \<complex>"  "b \<in> \<complex>"
  shows "a\<ca>b = b\<ca>a"
  using assms cplx_mul_add_vals valid_cntxts ring0.Ring_ZF_1_L4
  by auto

text\<open>Complex addition is associative.\<close>

lemma (in complex0) axaddass: assumes A1: "a \<in> \<complex>"  "b \<in> \<complex>"  "c \<in> \<complex>"
  shows "a \<ca> b \<ca> c = a \<ca> (b \<ca> c)"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?a\<^sub>i = "snd(a)"
  let ?b\<^sub>r = "fst(b)"
  let ?b\<^sub>i = "snd(b)"
  let ?c\<^sub>r = "fst(c)"
  let ?c\<^sub>i = "snd(c)"
  from A1 have T:
    "?a\<^sub>r \<in> R"  "?a\<^sub>i \<in> R"  "?b\<^sub>r \<in> R"  "?b\<^sub>i \<in> R"  "?c\<^sub>r \<in> R"  "?c\<^sub>i \<in> R"
    "?a\<^sub>r\<ra>?b\<^sub>r \<in> R"  "?a\<^sub>i\<ra>?b\<^sub>i \<in> R"
    "?b\<^sub>r\<ra>?c\<^sub>r \<in> R"  "?b\<^sub>i\<ra>?c\<^sub>i \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L4 by auto
  with A1 have "a \<ca> b \<ca> c = \<langle>?a\<^sub>r\<ra>?b\<^sub>r\<ra>?c\<^sub>r,?a\<^sub>i\<ra>?b\<^sub>i\<ra>?c\<^sub>i\<rangle>"
    using cplx_mul_add_vals by auto
  also from A1 T have "\<dots> = a \<ca> (b \<ca> c)"
    using valid_cntxts ring0.Ring_ZF_1_L11 cplx_mul_add_vals
    by auto
  finally show "a \<ca> b \<ca> c = a \<ca> (b \<ca> c)"
    by simp
qed

text\<open>Complex multiplication is associative.\<close>

lemma (in complex0) axmulass: assumes A1: "a \<in> \<complex>"  "b \<in> \<complex>"  "c \<in> \<complex>"
  shows "a \<cdot> b \<cdot> c = a \<cdot> (b \<cdot> c)"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?a\<^sub>i = "snd(a)"
  let ?b\<^sub>r = "fst(b)"
  let ?b\<^sub>i = "snd(b)"
  let ?c\<^sub>r = "fst(c)"
  let ?c\<^sub>i = "snd(c)"
  from A1 have T:
    "?a\<^sub>r \<in> R"  "?a\<^sub>i \<in> R"  "?b\<^sub>r \<in> R"  "?b\<^sub>i \<in> R"  "?c\<^sub>r \<in> R"  "?c\<^sub>i \<in> R"
    "?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i) \<in> R"
    "?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r \<in> R"
    "?b\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?b\<^sub>i\<rmu>?c\<^sub>i) \<in> R"
    "?b\<^sub>r\<rmu>?c\<^sub>i \<ra> ?b\<^sub>i\<rmu>?c\<^sub>r \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L4  by auto
  with A1 have "a \<cdot> b \<cdot> c =
    \<langle>(?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i))\<rmu>?c\<^sub>r \<ra> (\<rm>(?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r)\<rmu>?c\<^sub>i),
    (?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i))\<rmu>?c\<^sub>i \<ra> (?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r)\<rmu>?c\<^sub>r\<rangle>"
    using cplx_mul_add_vals by auto
  moreover from A1 T have
    "\<langle>?a\<^sub>r\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?b\<^sub>i\<rmu>?c\<^sub>i)) \<ra> (\<rm>?a\<^sub>i\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>i \<ra> ?b\<^sub>i\<rmu>?c\<^sub>r)),
    ?a\<^sub>r\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>i \<ra> ?b\<^sub>i\<rmu>?c\<^sub>r) \<ra> ?a\<^sub>i\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?b\<^sub>i\<rmu>?c\<^sub>i))\<rangle> =
    a \<cdot> (b \<cdot> c)"
    using cplx_mul_add_vals by auto
  moreover from T have
    "?a\<^sub>r\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?b\<^sub>i\<rmu>?c\<^sub>i)) \<ra> (\<rm>?a\<^sub>i\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>i \<ra> ?b\<^sub>i\<rmu>?c\<^sub>r)) =
    (?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i))\<rmu>?c\<^sub>r \<ra> (\<rm>(?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r)\<rmu>?c\<^sub>i)"
    and
    "?a\<^sub>r\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>i \<ra> ?b\<^sub>i\<rmu>?c\<^sub>r) \<ra> ?a\<^sub>i\<rmu>(?b\<^sub>r\<rmu>?c\<^sub>r \<ra> (\<rm>?b\<^sub>i\<rmu>?c\<^sub>i)) =
    (?a\<^sub>r\<rmu>?b\<^sub>r \<ra> (\<rm>?a\<^sub>i\<rmu>?b\<^sub>i))\<rmu>?c\<^sub>i \<ra> (?a\<^sub>r\<rmu>?b\<^sub>i \<ra> ?a\<^sub>i\<rmu>?b\<^sub>r)\<rmu>?c\<^sub>r"
    using valid_cntxts ring0.Ring_ZF_2_L6 by auto
  ultimately show "a \<cdot> b \<cdot> c = a \<cdot> (b \<cdot> c)"
    by auto
qed

text\<open>Complex $1$ is real. This really means that the pair
  $\langle 1,0 \rangle$ is on the real axis.\<close>

lemma (in complex0) ax1re: shows "\<one> \<in> \<real>"
  using valid_cntxts ring0.Ring_ZF_1_L2 by simp

text\<open>The imaginary unit is a "square root" of $-1$ (that is, $i^2 +1 =0$).
\<close>

lemma (in complex0) axi2m1: shows "\<i>\<cdot>\<i> \<ca> \<one> = \<zero>"
  using valid_cntxts ring0.Ring_ZF_1_L2 ring0.Ring_ZF_1_L3
  cplx_mul_add_vals ring0.Ring_ZF_1_L6 group0.group0_2_L6
  by simp

text\<open>$0$ is the neutral element of complex addition.\<close>

lemma (in complex0) ax0id: assumes "a \<in> \<complex>"
  shows "a \<ca> \<zero> = a"
  using assms cplx_mul_add_vals valid_cntxts
    ring0.Ring_ZF_1_L2 ring0.Ring_ZF_1_L3
  by auto

text\<open>The imaginary unit is a complex number.\<close>

lemma (in complex0) axicn: shows "\<i> \<in> \<complex>"
  using valid_cntxts ring0.Ring_ZF_1_L2 by auto

text\<open>All complex numbers have additive inverses.\<close>

lemma (in complex0) axnegex: assumes A1: "a \<in> \<complex>"
  shows "\<exists>x\<in>\<complex>. a \<ca> x  = \<zero>"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?a\<^sub>i = "snd(a)"
  let ?x = "\<langle>\<rm>?a\<^sub>r, \<rm>?a\<^sub>i\<rangle>"
  from A1 have T:
    "?a\<^sub>r \<in> R"   "?a\<^sub>i \<in> R"   "(\<rm>?a\<^sub>r) \<in> R"   "(\<rm>?a\<^sub>r) \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L3 by auto
  then have "?x \<in> \<complex>" using valid_cntxts ring0.Ring_ZF_1_L3
    by auto
  moreover from A1 T have "a \<ca> ?x = \<zero>"
    using cplx_mul_add_vals valid_cntxts ring0.Ring_ZF_1_L3
    by auto
  ultimately show "\<exists>x\<in>\<complex>. a \<ca> x  = \<zero>"
    by auto
qed

text\<open>A non-zero complex number has a multiplicative inverse.\<close>

lemma (in complex0) axrecex: assumes A1: "a \<in> \<complex>" and A2: "a\<noteq>\<zero>"
  shows "\<exists>x\<in>\<complex>. a\<cdot>x = \<one>"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?a\<^sub>i = "snd(a)"
  let ?m = "?a\<^sub>r\<rmu>?a\<^sub>r \<ra> ?a\<^sub>i\<rmu>?a\<^sub>i"
  from A1 have T1: "?a\<^sub>r \<in> R"   "?a\<^sub>i \<in> R" by auto
  moreover from A1 A2 have "?a\<^sub>r \<noteq> \<zero>\<^sub>R \<or> ?a\<^sub>i \<noteq> \<zero>\<^sub>R"
    by auto
  ultimately have "\<exists>c\<in>R. ?m\<rmu>c = \<one>\<^sub>R"
    using valid_cntxts field1.OrdField_ZF_1_L10
    by auto
  then obtain c where I: "c\<in>R" and II: "?m\<rmu>c = \<one>\<^sub>R"
    by auto
  let ?x = "\<langle>?a\<^sub>r\<rmu>c, \<rm>?a\<^sub>i\<rmu>c\<rangle>"
  from T1 I have T2: "?a\<^sub>r\<rmu>c \<in> R"  "(\<rm>?a\<^sub>i\<rmu>c) \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L4 ring0.Ring_ZF_1_L3
    by auto
  then have "?x \<in> \<complex>" by auto
  moreover from A1 T1 T2 I II have "a\<cdot>?x = \<one>"
    using cplx_mul_add_vals valid_cntxts ring0.ring_rearr_3_elemA
    by auto
  ultimately show "\<exists>x\<in>\<complex>. a\<cdot>x = \<one>" by auto
qed

text\<open>Complex $1$ is a right neutral element for multiplication.\<close>

lemma (in complex0) ax1id: assumes A1: "a \<in> \<complex>"
  shows "a\<cdot>\<one> = a"
  using assms valid_cntxts ring0.Ring_ZF_1_L2 cplx_mul_add_vals
    ring0.Ring_ZF_1_L3 ring0.Ring_ZF_1_L6 by auto

text\<open>A formula for sum of (complex) real numbers.\<close>

lemma (in complex0) sum_of_reals: assumes "a\<in>\<real>"  "b\<in>\<real>"
  shows
  "a \<ca> b = \<langle>fst(a) \<ra> fst(b),\<zero>\<^sub>R\<rangle>"
  using assms valid_cntxts ring0.Ring_ZF_1_L2 cplx_mul_add_vals
    ring0.Ring_ZF_1_L3 by auto

text\<open>The sum of real numbers is real.\<close>

lemma (in complex0) axaddrcl: assumes A1: "a\<in>\<real>"  "b\<in>\<real>"
  shows "a \<ca> b \<in> \<real>"
  using assms sum_of_reals valid_cntxts ring0.Ring_ZF_1_L4
  by auto

text\<open>The formula for the product of (complex) real numbers.\<close>

lemma (in complex0) prod_of_reals: assumes A1: "a\<in>\<real>"  "b\<in>\<real>"
  shows "a \<cdot> b = \<langle>fst(a)\<rmu>fst(b),\<zero>\<^sub>R\<rangle>"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?b\<^sub>r = "fst(b)"
  from A1 have T:
    "?a\<^sub>r \<in> R" "?b\<^sub>r \<in> R"  "\<zero>\<^sub>R \<in> R"  "?a\<^sub>r\<rmu>?b\<^sub>r \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L2 ring0.Ring_ZF_1_L4
    by auto
  with A1 show "a \<cdot> b = \<langle>?a\<^sub>r\<rmu>?b\<^sub>r,\<zero>\<^sub>R\<rangle>"
    using cplx_mul_add_vals valid_cntxts ring0.Ring_ZF_1_L2
      ring0.Ring_ZF_1_L6 ring0.Ring_ZF_1_L3 by auto
qed

text\<open>The product of (complex) real numbers is real.\<close>

lemma (in complex0) axmulrcl: assumes "a\<in>\<real>"  "b\<in>\<real>"
  shows "a \<cdot> b \<in> \<real>"
  using assms prod_of_reals valid_cntxts ring0.Ring_ZF_1_L4
  by auto

text\<open>The existence of a real negative of a real number.\<close>

lemma (in complex0) axrnegex: assumes A1: "a\<in>\<real>"
  shows "\<exists> x \<in> \<real>. a \<ca> x = \<zero>"
proof -
  let ?a\<^sub>r = "fst(a)"
  let ?x = "\<langle>\<rm>?a\<^sub>r,\<zero>\<^sub>R\<rangle>"
  from A1 have T:
    "?a\<^sub>r \<in> R"  "(\<rm>?a\<^sub>r) \<in> R"  "\<zero>\<^sub>R \<in> R"
    using valid_cntxts ring0.Ring_ZF_1_L3 ring0.Ring_ZF_1_L2
    by auto
  then have "?x\<in> \<real>" by auto
  moreover from A1 T have "a \<ca> ?x = \<zero>"
    using cplx_mul_add_vals valid_cntxts ring0.Ring_ZF_1_L3
    by auto
  ultimately show "\<exists>x\<in>\<real>. a \<ca> x = \<zero>" by auto
qed

text\<open>Each nonzero real number has a real inverse\<close>

lemma (in complex0) axrrecex:
  assumes A1:  "a \<in> \<real>"   "a \<noteq> \<zero>"
  shows "\<exists>x\<in>\<real>. a \<cdot> x = \<one>"
proof -
  let ?R\<^sub>0 = "R-{\<zero>\<^sub>R}"
  let ?a\<^sub>r = "fst(a)"
  let ?y = "GroupInv(?R\<^sub>0,restrict(M,?R\<^sub>0\<times>?R\<^sub>0))`(?a\<^sub>r)"
  from A1 have T: "\<langle>?y,\<zero>\<^sub>R\<rangle> \<in> \<real>" using valid_cntxts field0.Field_ZF_1_L5
    by auto
  moreover from A1 T have "a \<cdot> \<langle>?y,\<zero>\<^sub>R\<rangle> = \<one>"
    using prod_of_reals valid_cntxts
    field0.Field_ZF_1_L5 field0.Field_ZF_1_L6 by auto
  ultimately show "\<exists> x \<in> \<real>. a \<cdot> x = \<one>" by auto
qed

text\<open>Our \<open>\<real>\<close> symbol is the real axis on the complex plane.\<close>

lemma (in complex0) real_means_real_axis: shows "\<real> = ComplexReals(R,A)"
  using ComplexReals_def by auto

text\<open>The \<open>CplxROrder\<close> thing is a relation on the complex reals.
\<close>

lemma (in complex0) cplx_ord_on_cplx_reals:
  shows "CplxROrder(R,A,r) \<subseteq> \<real>\<times>\<real>"
  using ComplexReals_def slice_proj_bij real_means_real_axis
    CplxROrder_def InducedRelation_def by auto

text\<open>The strict version of the complex relation is a
  relation on complex reals.\<close>

lemma (in complex0) cplx_strict_ord_on_cplx_reals:
  shows "StrictVersion(CplxROrder(R,A,r)) \<subseteq> \<real>\<times>\<real>"
  using cplx_ord_on_cplx_reals strict_ver_rel by simp

text\<open>The \<open>CplxROrder\<close> thing is a relation on the complex reals.
  Here this is formulated as a statement that in \<open>complex0\<close> context
  $a<b$ implies that $a,b$ are complex reals\<close>

lemma (in complex0) strict_cplx_ord_type: assumes "a \<lsr> b"
  shows "a\<in>\<real>"  "b\<in>\<real>"
  using assms CplxROrder_def def_of_strict_ver InducedRelation_def
    slice_proj_bij ComplexReals_def real_means_real_axis
  by auto

text\<open>A more readable version of the definition of the strict order
  relation on the real axis. Recall that in the \<open>complex0\<close>
  context $r$ denotes the (non-strict) order relation on the underlying
  model of real numbers.\<close>

lemma (in complex0) def_of_real_axis_order: shows
  "\<langle>x,\<zero>\<^sub>R\<rangle> \<lsr> \<langle>y,\<zero>\<^sub>R\<rangle> \<longleftrightarrow> \<langle>x,y\<rangle> \<in> r \<and> x\<noteq>y"
proof
  let ?f = "SliceProjection(ComplexReals(R,A))"
  assume A1: "\<langle>x,\<zero>\<^sub>R\<rangle> \<lsr> \<langle>y,\<zero>\<^sub>R\<rangle>"
  then have "\<langle> ?f`\<langle>x,\<zero>\<^sub>R\<rangle>, ?f`\<langle>y,\<zero>\<^sub>R\<rangle> \<rangle> \<in> r \<and> x \<noteq> y"
    using CplxROrder_def def_of_strict_ver def_of_ind_relA
    by simp
  moreover from A1 have "\<langle>x,\<zero>\<^sub>R\<rangle> \<in> \<real>"  "\<langle>y,\<zero>\<^sub>R\<rangle> \<in> \<real>"
    using strict_cplx_ord_type by auto
  ultimately show "\<langle>x,y\<rangle> \<in> r \<and> x\<noteq>y"
    using slice_proj_bij ComplexReals_def by simp
next assume A1: "\<langle>x,y\<rangle> \<in> r \<and> x\<noteq>y"
  let ?f = "SliceProjection(ComplexReals(R,A))"
  have "?f : \<real> \<rightarrow> R"
    using ComplexReals_def slice_proj_bij real_means_real_axis
    by simp
  moreover from A1 have T: "\<langle>x,\<zero>\<^sub>R\<rangle> \<in> \<real>"   "\<langle>y,\<zero>\<^sub>R\<rangle> \<in> \<real>"
    using valid_cntxts ring1.OrdRing_ZF_1_L3 by auto
  moreover from A1 T have "\<langle> ?f`\<langle>x,\<zero>\<^sub>R\<rangle>, ?f`\<langle>y,\<zero>\<^sub>R\<rangle> \<rangle> \<in> r"
    using slice_proj_bij ComplexReals_def by simp
  ultimately have "\<langle> \<langle>x,\<zero>\<^sub>R\<rangle>, \<langle>y,\<zero>\<^sub>R\<rangle> \<rangle> \<in> InducedRelation(?f,r)"
    using def_of_ind_relB by simp
  with A1 show "\<langle>x,\<zero>\<^sub>R\<rangle> \<lsr> \<langle>y,\<zero>\<^sub>R\<rangle>"
    using CplxROrder_def def_of_strict_ver
    by simp
qed

text\<open>The (non strict) order on complex reals is antisymmetric,
  transitive and total.\<close>

lemma (in complex0) cplx_ord_antsym_trans_tot: shows
  "antisym(CplxROrder(R,A,r))"
  "trans(CplxROrder(R,A,r))"
  "CplxROrder(R,A,r) {is total on} \<real>"
proof -
  let ?f = "SliceProjection(ComplexReals(R,A))"
  have "?f \<in> ord_iso(\<real>,CplxROrder(R,A,r),R,r)"
    using ComplexReals_def slice_proj_bij real_means_real_axis
      bij_is_ord_iso CplxROrder_def by simp
  moreover have "CplxROrder(R,A,r) \<subseteq> \<real>\<times>\<real>"
    using cplx_ord_on_cplx_reals by simp
  moreover have I:
    "antisym(r)"   "r {is total on} R"   "trans(r)"
    using valid_cntxts ring1.OrdRing_ZF_1_L1 IsAnOrdRing_def
      IsLinOrder_def by auto
  ultimately show
    "antisym(CplxROrder(R,A,r))"
    "trans(CplxROrder(R,A,r))"
    "CplxROrder(R,A,r) {is total on} \<real>"
    using ord_iso_pres_antsym ord_iso_pres_tot ord_iso_pres_trans
    by auto
qed

text\<open>The trichotomy law for the strict order on the complex
  reals.\<close>

lemma (in complex0) cplx_strict_ord_trich:
  assumes "a \<in> \<real>"  "b \<in> \<real>"
  shows "Exactly_1_of_3_holds(a\<lsr>b, a=b, b\<lsr>a)"
  using assms cplx_ord_antsym_trans_tot strict_ans_tot_trich
  by simp

text\<open>The strict order on the complex reals is kind of
  antisymetric.\<close>

lemma (in complex0) pre_axlttri: assumes A1: "a \<in> \<real>"   "b \<in> \<real>"
  shows "a \<lsr> b \<longleftrightarrow> \<not>(a=b \<or> b \<lsr> a)"
proof -
  from A1 have "Exactly_1_of_3_holds(a\<lsr>b, a=b, b\<lsr>a)"
    by (rule cplx_strict_ord_trich)
  then show "a \<lsr> b \<longleftrightarrow> \<not>(a=b \<or> b \<lsr> a)"
    by (rule Fol1_L8A)
qed

text\<open>The strict order on complex reals is transitive.\<close>

lemma (in complex0) cplx_strict_ord_trans:
  shows "trans(StrictVersion(CplxROrder(R,A,r)))"
  using cplx_ord_antsym_trans_tot strict_of_transB by simp

text\<open>The strict order on complex reals is transitive - the explicit version
  of \<open>cplx_strict_ord_trans\<close>.\<close>

lemma (in complex0) pre_axlttrn:
  assumes A1: "a \<lsr> b"   "b \<lsr> c"
  shows "a \<lsr> c"
proof -
  let ?s = "StrictVersion(CplxROrder(R,A,r))"
  from A1 have
    "trans(?s)"   "\<langle>a,b\<rangle> \<in> ?s \<and> \<langle>b,c\<rangle> \<in> ?s"
    using cplx_strict_ord_trans by auto
  then have "\<langle>a,c\<rangle> \<in> ?s" by (rule Fol1_L3)
  then show "a \<lsr> c" by simp
qed

text\<open>The strict order on complex reals is preserved by translations.\<close>

lemma (in complex0) pre_axltadd:
  assumes A1: "a \<lsr> b" and A2: "c \<in> \<real>"
  shows "c\<ca>a \<lsr> c\<ca>b"
proof -
  from A1 have T: "a\<in>\<real>"  "b\<in>\<real>" using strict_cplx_ord_type
    by auto
  with A1 A2 show "c\<ca>a \<lsr> c\<ca>b"
    using def_of_real_axis_order valid_cntxts
      group3.group_strict_ord_transl_inv sum_of_reals
    by auto
qed

text\<open>The set of positive complex reals is closed with respect to
  multiplication.\<close>

lemma (in complex0) pre_axmulgt0: assumes A1: "\<zero> \<lsr> a"   "\<zero> \<lsr> b"
  shows "\<zero> \<lsr> a\<cdot>b"
proof -
  from A1 have T: "a\<in>\<real>"  "b\<in>\<real>" using strict_cplx_ord_type
    by auto
  with A1 show "\<zero> \<lsr> a\<cdot>b"
    using def_of_real_axis_order valid_cntxts field1.pos_mul_closed
      def_of_real_axis_order prod_of_reals
    by auto
qed

text\<open>The order on complex reals is linear and complete.\<close>

lemma (in complex0) cmplx_reals_ord_lin_compl: shows
  "CplxROrder(R,A,r) {is complete}"
  "IsLinOrder(\<real>,CplxROrder(R,A,r))"
proof -
  have "SliceProjection(\<real>) \<in> bij(\<real>,R)"
    using slice_proj_bij ComplexReals_def real_means_real_axis
    by simp
  moreover have "r \<subseteq> R\<times>R" using valid_cntxts ring1.OrdRing_ZF_1_L1
    IsAnOrdRing_def by simp
  moreover from R_are_reals have
    "r {is complete}" and "IsLinOrder(R,r)"
    using IsAmodelOfReals_def valid_cntxts ring1.OrdRing_ZF_1_L1
    IsAnOrdRing_def by auto
  ultimately show
    "CplxROrder(R,A,r) {is complete}"
    "IsLinOrder(\<real>,CplxROrder(R,A,r))"
    using CplxROrder_def real_means_real_axis ind_rel_pres_compl
      ind_rel_pres_lin by auto
qed

text\<open>The property of the strict order on complex reals
  that corresponds to completeness.\<close>

lemma (in complex0) pre_axsup: assumes A1: "X \<subseteq> \<real>"   "X \<noteq> 0" and
  A2: "\<exists>x\<in>\<real>. \<forall>y\<in>X. y \<lsr> x"
  shows
  "\<exists>x\<in>\<real>. (\<forall>y\<in>X. \<not>(x \<lsr> y)) \<and> (\<forall>y\<in>\<real>. (y \<lsr> x \<longrightarrow> (\<exists>z\<in>X. y \<lsr> z)))"
proof -
  let ?s = "StrictVersion(CplxROrder(R,A,r))"
  have
    "CplxROrder(R,A,r) \<subseteq> \<real>\<times>\<real>"
    "IsLinOrder(\<real>,CplxROrder(R,A,r))"
    "CplxROrder(R,A,r) {is complete}"
    using cplx_ord_on_cplx_reals cmplx_reals_ord_lin_compl
    by auto
  moreover note A1
  moreover have "?s = StrictVersion(CplxROrder(R,A,r))"
    by simp
  moreover from A2 have "\<exists>u\<in>\<real>. \<forall>y\<in>X. \<langle>y,u\<rangle> \<in> ?s"
    by simp
  ultimately have
    "\<exists>x\<in>\<real>. ( \<forall>y\<in>X. \<langle>x,y\<rangle> \<notin> ?s ) \<and>
    (\<forall>y\<in>\<real>. \<langle>y,x\<rangle> \<in> ?s \<longrightarrow> (\<exists>z\<in>X. \<langle>y,z\<rangle> \<in> ?s))"
    by (rule strict_of_compl)
  then show "(\<exists>x\<in>\<real>. (\<forall>y\<in>X. \<not>(x \<lsr> y)) \<and>
    (\<forall>y\<in>\<real>. (y \<lsr> x \<longrightarrow> (\<exists>z\<in>X. y \<lsr> z))))"
    by simp
qed

end


theory topo_operators_derivative
  imports topo_operators_basic
begin
nitpick_params[assms=true, user_axioms=true, show_all, expect=genuine, format=3] (*default Nitpick settings*)

subsection \<open>Derivative and coherence\<close>

text\<open>\noindent{In this section we investigate two related operators, namely the `derivative' (or `derived set')
and the (Cantorian) `coherence' of a set. The derivative of a set is the set of its accumulation (aka. limit)
points. The coherence of a set A is the set formed by those limit points of A belonging to A.
For the derivative operator we draw upon the works by Kuratowski @{cite Kuratowski1} and
(in more detail) by Zarycki @{cite Zarycki3}; cf.~also McKinsey \& Tarski @{cite AOT}.
For the (Cantorian) coherence operator we follow the treatment given by Zarycki in @{cite Zarycki2}.}\<close>

subsubsection \<open>Derivative conditions\<close>

text\<open>\noindent{The derivative conditions overlap partly with Kuratowski closure conditions @{cite Kuratowski1}.
We try to make both notations coincide when possible.}\<close>

abbreviation "Der_1 \<phi>  \<equiv> Cl_1 \<phi>"
abbreviation "Der_1a \<phi> \<equiv> Cl_1a \<phi>"
abbreviation "Der_1b \<phi> \<equiv> Cl_1b \<phi>"
abbreviation "Der_2 \<phi>  \<equiv> Cl_5 \<phi>" \<comment>\<open> follows from Cl-2 \<close>
abbreviation "Der_3 \<phi>  \<equiv> Cl_3 \<phi>"
abbreviation "Der_4 \<phi>  \<equiv> Cl_4' \<phi>"
definition   "Der_4e \<phi> \<equiv> \<forall>A. \<phi>(\<phi> A) \<^bold>\<preceq> (\<phi> A \<^bold>\<or> A)"
definition   "Der_5 \<phi> \<equiv> \<forall>A. (\<phi> A \<^bold>\<preceq> A) \<and> (A \<^bold>\<preceq> \<phi>\<^sup>d A) \<longrightarrow> (A \<^bold>\<approx> \<^bold>\<bottom> \<or> A \<^bold>\<approx> \<^bold>\<top>)"

text\<open>\noindent{Some remarks:
Condition Der-2 basically says (when assuming other derivative axioms) that the space is dense-in-itself,
i.e. that all points are accumulation points (no point is isolated) w.r.t the whole space.
Der-4 is a weakened (left-to-right) variant of Cl-4.
Condition Der-4e corresponds to a (weaker) condition than Der-4 and is used in more recent literature
(in particular in the works of Leo Esakia @{cite Esakia}).
When other derivative axioms are assumed, Der-5 above as used by Zarycki @{cite Zarycki3} says that
the only clopen sets in the space are the top and bottom elements (empty set and universe, resp.).
We verify some properties:}\<close>

lemma Der4e_rel: "Der_4 \<phi> \<Longrightarrow> Der_4e \<phi>" by (simp add: IDEMb_def Der_4e_def conn)
lemma PD1: "Der_1b \<phi> \<Longrightarrow> \<forall>A B. A \<^bold>\<preceq> B \<longrightarrow> \<phi> A \<^bold>\<preceq> \<phi> B" using MONO_def MONO_ADDIb by auto
lemma PD2: "Der_1b \<phi> \<Longrightarrow> \<forall>A B. A \<^bold>\<preceq> B \<longrightarrow> \<phi>\<^sup>d A \<^bold>\<preceq> \<phi>\<^sup>d B" using CI1b MONO_def MONO_MULTa dual_def by fastforce
lemma PD3: "Der_1b \<phi> \<Longrightarrow> \<forall>A B. \<phi>(A \<^bold>\<and> B) \<^bold>\<preceq> \<phi> A \<^bold>\<and> \<phi> B" unfolding conn by (metis (no_types, lifting) PD1)
lemma PD4: "Der_1 \<phi> \<Longrightarrow> \<forall>A B. (\<phi> A \<^bold>\<leftharpoonup> \<phi> B) \<^bold>\<preceq> \<phi>(A \<^bold>\<leftharpoonup> B)" using Cl_6_def PC6 by metis
lemma PD5: "Der_4 \<phi> \<Longrightarrow> \<forall>A. \<phi>(\<phi>(\<^bold>\<midarrow>(\<phi> A))) \<^bold>\<preceq> \<phi>(\<^bold>\<midarrow>(\<phi> A))" unfolding IDEMb_def by blast
text\<open>\noindent{Observe that the lemmas below require Der-2 as premise:}\<close>
lemma PD6: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> \<forall>A. \<phi>\<^sup>d A \<^bold>\<preceq> \<phi> A" unfolding ADDI_def dNOR_def dual_def conn by fastforce
lemma PD7: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> \<forall>A. \<phi>(\<phi>\<^sup>d A) \<^bold>\<preceq> \<phi>(\<phi> A)" by (metis (mono_tags, lifting) PC1 PD1 PD6)
lemma PD8: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi> \<Longrightarrow> \<forall>A. \<phi>(\<phi>\<^sup>d A) \<^bold>\<preceq> \<phi> A" by (meson IDEMb_def PD7)
lemma PD9: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi> \<Longrightarrow> \<forall>A. \<phi>\<^sup>d A \<^bold>\<preceq> \<phi>\<^sup>d(\<phi> A)" by (metis CI4' IDEMa_def PC1 PD2 PD6)
lemma PD10: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi> \<Longrightarrow> \<forall>A. \<phi>\<^sup>d A \<^bold>\<preceq> \<phi>(\<phi>\<^sup>d A)" using CI4' IDEMa_def PD6 by metis
lemma PD11: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi> \<Longrightarrow> \<forall>A. \<^bold>\<midarrow>(\<phi> A) \<^bold>\<preceq> \<phi>(\<^bold>\<midarrow>(\<phi> A))" using IDEMb_def PD6 dual_def unfolding conn by metis
lemma PD12: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi> \<Longrightarrow> \<forall>A. (\<phi>\<^sup>d A) \<^bold>\<and> (\<phi> A) \<^bold>\<approx> \<phi>\<^sup>d(A \<^bold>\<and> (\<phi> A))" proof -
 assume der1: "Der_1 \<phi>" and der2: "Der_2 \<phi>" and der4: "Der_4 \<phi>"
  { fix A
    from der1 have "let M=\<^bold>\<midarrow>A ; N=\<^bold>\<midarrow>(\<phi> A) in \<phi>(M \<^bold>\<or> N) \<^bold>\<approx> (\<phi> M) \<^bold>\<or> (\<phi> N)" unfolding ADDI_def by simp
    hence aux: "\<^bold>\<midarrow>(\<phi>(\<^bold>\<midarrow>A) \<^bold>\<or> \<phi>(\<^bold>\<midarrow>(\<phi> A))) \<^bold>\<approx> \<^bold>\<midarrow>(\<phi> (\<^bold>\<midarrow>A \<^bold>\<or> \<^bold>\<midarrow>(\<phi> A)))" unfolding dual_def conn by simp
    have "(\<phi>\<^sup>d A \<^bold>\<and> \<phi> A) = (\<phi>\<^sup>d A \<^bold>\<and> \<phi>\<^sup>d(\<phi> A))" using PD6 PD9 der1 der2 der4 unfolding conn by metis
    also have "... = \<^bold>\<midarrow>(\<phi>(\<^bold>\<midarrow>A) \<^bold>\<or> \<phi>(\<^bold>\<midarrow>(\<phi> A)))" unfolding dual_def conn by simp
    also from aux have "... = \<^bold>\<midarrow>(\<phi> (\<^bold>\<midarrow>A \<^bold>\<or> \<^bold>\<midarrow>(\<phi> A)))" unfolding dual_def by blast
    also have "... = \<phi>\<^sup>d(A \<^bold>\<and> (\<phi> A))" unfolding dual_def conn by simp
    finally have "(\<phi>\<^sup>d A) \<^bold>\<and> (\<phi> A) \<^bold>\<approx> \<phi>\<^sup>d(A \<^bold>\<and> (\<phi> A))" by simp
 } thus ?thesis by simp
qed

text\<open>\noindent{The conditions below can serve to axiomatize a derivative operator. Different authors consider different
sets of conditions. We define below some corresponding to Zarycki @{cite Zarycki3}, Kuratowski @{cite Kuratowski1}
@{cite Zarycki2}, McKinsey \& Tarski @{cite AOT}, and Esakia @{cite Esakia}, respectively.}\<close>
abbreviation "\
z \<phi>  \<equiv> Der_1 \<phi> \<and> Der_2 \<phi> \<and> Der_3 \<phi> \<and> Der_4 \<phi> \<and> Der_5 \<phi>"
abbreviation "\
k \<phi>  \<equiv> Der_1 \<phi> \<and> Der_2 \<phi> \<and> Der_3 \<phi> \<and> Der_4 \<phi>"
abbreviation "\
mt \<phi> \<equiv> Der_1 \<phi>           \<and> Der_3 \<phi> \<and> Der_4 \<phi>"
abbreviation "\
e \<phi>  \<equiv> Der_1 \<phi>           \<and> Der_3 \<phi> \<and> Der_4e \<phi>"

text\<open>\noindent{Our `default' derivative operator will coincide with @{text "\
k"} from Kuratowski (also Zarycki).
However, for proving theorems we will employ the weaker variant Der-4e instead of Der-4 whenever possible.
We start by defining a dual operator and verifying some dualities; we then define conversion operators.
Observe that conditions Der-2 and  Der-5 are not used in the rest of this subsection.
Der-2 will be required later when working with the coherence operator.}\<close>
abbreviation "\
 \<phi> \<equiv> \
k \<phi>"
abbreviation "\<Sigma> \<phi> \<equiv> Int_1 \<phi> \<and> Int_3 \<phi> \<and> Int_4' \<phi> \<and> Int_5 \<phi>" \<comment>\<open> 'dual-derivative' operator \<close>

lemma SD_dual1: "\<Sigma>(\<phi>) \<Longrightarrow> \
(\<phi>\<^sup>d)" using IC1 IC4' IC3 IC5 by simp
lemma SD_dual2: "\<Sigma>(\<phi>\<^sup>d) \<Longrightarrow> \
(\<phi>)" using IC1 IC4' IC3 IC5 dual_symm by metis
lemma DS_dual1: "\
(\<phi>) \<Longrightarrow> \<Sigma>(\<phi>\<^sup>d)" using CI1 CI4' CI3 CI5 by simp
lemma DS_dual2: "\
(\<phi>\<^sup>d) \<Longrightarrow> \<Sigma>(\<phi>)" using CI1 CI4' CI3 CI5 dual_symm by metis
lemma DS_dual: "\
(\<phi>) = \<Sigma>(\<phi>\<^sup>d)"  using SD_dual2 DS_dual1 by smt

text\<open>\noindent{Closure operator as derived from derivative.}\<close>
definition Cl_der::"(\<sigma>\<Rightarrow>\<sigma>)\<Rightarrow>(\<sigma>\<Rightarrow>\<sigma>)" ("\<C>\<^sub>D") where  "\<C>\<^sub>D \<D> \<equiv> \<lambda>A. A \<^bold>\<or> \<D>(A)"
text\<open>\noindent{Verify properties:}\<close>
lemma CD1a: "Der_1a \<D> \<Longrightarrow> Cl_1a (\<C>\<^sub>D \<D>)" unfolding Cl_der_def ADDI_a_def conn by auto

text\<open>\noindent{Interior operator as derived from (dual) derivative.}\<close>
definition Int_der::"(\<sigma>\<Rightarrow>\<sigma>)\<Rightarrow>(\<sigma>\<Rightarrow>\<sigma>)" ("\\<^sub>D") where "\\<^sub>D \<D> \<equiv> \<lambda>A. A \<^bold>\<and> \<D>\<^sup>d(A)"
text\<open>\noindent{Verify definition:}\<close>
lemma Int_der_def2: "\\<^sub>D \<D> = (\<lambda>\<phi>. \<phi> \<^bold>\<leftharpoonup> \<D>(\<^bold>\<midarrow>\<phi>))" unfolding Int_der_def dual_def conn by simp
lemma dual_der1: "\<C>\<^sub>D \<D> \<equiv> (\\<^sub>D \<D>)\<^sup>d" unfolding Cl_der_def Int_der_def dual_def conn by simp
lemma dual_der2: "\\<^sub>D \<D> \<equiv> (\<C>\<^sub>D \<D>)\<^sup>d" unfolding Cl_der_def Int_der_def dual_def conn by simp
text\<open>\noindent{Verify properties:}\<close>
lemma ID1: "Der_1 \<D> \<Longrightarrow> Int_1 (\\<^sub>D \<D>)" using Int_der_def MULT_def ADDI_def CI1 unfolding conn by auto
lemma ID1a: "Der_1a \<D> \<Longrightarrow> Int_1b (\\<^sub>D \<D>)" by (simp add: CI1a dual_der2 CD1a)
lemma ID1b: "Der_1b \<D> \<Longrightarrow> Int_1a (\\<^sub>D \<D>)" by (simp add: CI1b dual_der2 CD1b)
lemma ID2: "Int_2 (\\<^sub>D \<D>)" unfolding Int_der_def dEXP_def conn by simp
lemma ID3: "Der_3 \<D> \<Longrightarrow> Int_3 (\\<^sub>D \<D>)" by (simp add: CI3 CD3 dual_der2)
lemma ID4: "Der_1 \<D> \<Longrightarrow> Der_4e \<D> \<Longrightarrow> Int_4 (\\<^sub>D \<D>)" using CI4 CD4 dual_der2 by simp
lemma ID4a: "Der_1a \<D> \<Longrightarrow> Der_4e \<D> \<Longrightarrow> Int_4 (\\<^sub>D \<D>)" by (simp add: CI4 dual_der2 CD4a)
lemma "Der_1b \<D> \<Longrightarrow> Der_4 \<D> \<Longrightarrow> Int_4 (\\<^sub>D \<D>)" nitpick oops (*countermodel*)

text\<open>\noindent{Border operator as derived from (dual) derivative.}\<close>
definition Br_der::"(\<sigma>\<Rightarrow>\<sigma>)\<Rightarrow>(\<sigma>\<Rightarrow>\<sigma>)" ("\\<^sub>D") where "\\<^sub>D \<D> \<equiv> \<lambda>A. A \<^bold>\<leftharpoonup> \<D>\<^sup>d(A)"
text\<open>\noindent{Verify definition:}\<close>
lemma Br_der_def2: "\\<^sub>D \<D> = (\<lambda>A. A \<^bold>\<and> \<D>(\<^bold>\<midarrow>A))" unfolding Br_der_def dual_def conn by simp
text\<open>\noindent{Verify properties:}\<close>
lemma BD1: "Der_1 \<D> \<Longrightarrow> Br_1 (\\<^sub>D \<D>)" using Br_der_def Br_1_def CI1 MULT_def conn by auto
lemma BD2: "Der_3 \<D> \<Longrightarrow> Br_2 (\\<^sub>D \<D>)" using Br_der_def Br_2_def CI3 dNOR_def unfolding conn by auto
lemma BD3: "Der_1b \<D> \<Longrightarrow> Der_4e \<D> \<Longrightarrow> Br_3 (\\<^sub>D \<D>)" using dual_def Der_4e_def MONO_ADDIb MONO_def  unfolding Br_der_def Br_3_def conn by smt

text\<open>\noindent{Frontier operator as derived from derivative.}\<close>
definition Fr_der::"(\<sigma>\<Rightarrow>\<sigma>)\<Rightarrow>(\<sigma>\<Rightarrow>\<sigma>)" ("\<F>\<^sub>D") where "\<F>\<^sub>D \<D> \<equiv> \<lambda>A. (A \<^bold>\<leftharpoonup> \<D>\<^sup>d(A)) \<^bold>\<or> (\<D>(A) \<^bold>\<leftharpoonup> A)"
text\<open>\noindent{Verify definition:}\<close>
lemma Fr_der_def2: "\<F>\<^sub>D \<D> = (\<lambda>A. (A \<^bold>\<or> \<D>(A)) \<^bold>\<and> (\<^bold>\<midarrow>A \<^bold>\<or> \<D>(\<^bold>\<midarrow>A)))" unfolding Fr_der_def dual_def conn by auto
text\<open>\noindent{Verify properties:}\<close>
lemma FD1a: "Der_1a \<D> \<Longrightarrow> Fr_1a(\<F>\<^sub>D \<D>)" unfolding Fr_1a_def Fr_der_def using CI1a MULT_b_def conn by auto
lemma FD1b: "Der_1b \<D> \<Longrightarrow> Fr_1b(\<F>\<^sub>D \<D>)" unfolding Fr_1b_def Fr_der_def using CI1b MULT_a_def conn by smt
lemma FD1: "Der_1 \<D> \<Longrightarrow> Fr_1(\<F>\<^sub>D \<D>)" unfolding Fr_1_def Fr_der_def using CI1 MULT_def conn by auto
lemma FD2: "Fr_2(\<F>\<^sub>D \<D>)" using dual_def dual_symm unfolding Fr_2_def Fr_der_def conn by metis
lemma FD3: "Der_3 \<D> \<Longrightarrow> Fr_3(\<F>\<^sub>D \<D>)" by (simp add: NOR_def Fr_der_def conn)
lemma FD4: "Der_1 \<D> \<Longrightarrow> Der_4e \<D> \<Longrightarrow> Fr_4(\<F>\<^sub>D \<D>)" by (metis CD1b CD2 CD4 Cl_8_def Cl_der_def Fr_4_def Fr_der_def2 PC1 PC8 meet_def)

text\<open>\noindent{Note that the derivative operation cannot be obtained from interior, closure, border, nor frontier.
In this respect the derivative is a fundamental operation.}\<close>

subsubsection \<open>Infinitary conditions\<close>

text\<open>\noindent{The corresponding infinitary condition on derivative operators is inherited from the one for closure.}\<close>
abbreviation "Der_inf \<phi> \<equiv> Cl_inf(\<phi>)"

lemma CD_inf: "Der_inf \<phi> \<Longrightarrow> Cl_inf(\<C>\<^sub>D \<phi>)" unfolding iADDI_a_def by (smt Cl_der_def Fr_2_def Ra_restr_ex compl_def dom_compl_def2 iDM_b join_def meet_def supremum_def)
lemma ID_inf: "Der_inf \<phi> \<Longrightarrow> Int_inf(\\<^sub>D \<phi>)" by (simp add: CD_inf dual_der2 iADDI_MULT_dual1)

text\<open>\noindent{This condition is indeed strong enough as to entail closure of some fixed-point predicates under infimum/supremum.}\<close>
lemma fp_ID_inf_closed: "Der_inf \<phi> \<Longrightarrow> infimum_closed (fp (\\<^sub>D \<phi>))" by (metis (full_types) ID2 ID_inf Ra_restr_all dEXP_def iMULT_b_def inf_char)
lemma fp_CD_sup_closed: "Der_inf \<phi> \<Longrightarrow> supremum_closed (fp (\<C>\<^sub>D \<phi>))" by (metis (full_types) CD_inf Cl_der_def Ra_restr_ex iADDI_a_def join_def supremum_def)

subsubsection \<open>Coherence conditions\<close>
text\<open>\noindent{We finish this section by introducing the `coherence' operator (Cantor's `Koherenz') as discussed
by Zarycki in @{cite Zarycki2}. As happens with the derivative operator, the coherence operator cannot
be derived from interior, closure, border, nor frontier.}\<close>

definition "Kh_1 \<phi> \<equiv> ADDI_b \<phi>"
definition "Kh_2 \<phi> \<equiv> dEXP \<phi>"
definition "Kh_3 \<phi> \<equiv> \<forall>A. \<phi>(\<phi>\<^sup>d A) \<^bold>\<approx> \<phi>\<^sup>d(\<phi> A)"

lemma PK1: "Kh_1 \<phi> \<equiv> MONO \<phi>" using ADDI_b_def Kh_1_def MONO_ADDIb by auto
lemma PK2: "Kh_1 \<phi> \<equiv> \<forall>A B. \<phi>(A \<^bold>\<and> B) \<^bold>\<preceq> (\<phi> A) \<^bold>\<and> (\<phi> B)" using MULT_a_def MONO_MULTa PK1 by auto
lemma PK3: "Kh_2 \<phi> \<Longrightarrow> \<phi> \<^bold>\<bottom> \<^bold>\<approx> \<^bold>\<bottom>" using Kh_2_def dEXP_def unfolding conn by auto
lemma PK4: "Kh_1 \<phi> \<Longrightarrow>  Kh_3 \<phi> \<Longrightarrow> \<phi> \<^bold>\<top> \<^bold>\<approx> \<^bold>\<top>" using MONO_def PK1 dual_def unfolding Kh_3_def conn by metis
lemma PK5: "Kh_2 \<phi> \<Longrightarrow>  \<forall>A. \<phi>(\<^bold>\<midarrow>A) \<^bold>\<preceq> \<^bold>\<midarrow>(\<phi> A)" unfolding Kh_2_def dEXP_def conn by metis
lemma PK6: "Kh_1 \<phi> \<Longrightarrow> Kh_2 \<phi> \<Longrightarrow>  \<forall>A B. \<phi>(A \<^bold>\<leftharpoonup> B) \<^bold>\<preceq> (\<phi> A) \<^bold>\<leftharpoonup> (\<phi> B)" unfolding conn by (metis (no_types, lifting) Kh_2_def dEXP_def MONO_def PK1)

text\<open>\noindent{Coherence operator as derived from derivative (requires conditions Der-2 and Der-4).}\<close>
definition Kh_der::"(\<sigma>\<Rightarrow>\<sigma>)\<Rightarrow>(\<sigma>\<Rightarrow>\<sigma>)" ("\<K>\<^sub>D") where "\<K>\<^sub>D \<D> \<equiv> \<lambda>A. A \<^bold>\<and> (\<D> A)"
text\<open>\noindent{Verify properties:}\<close>
lemma KD1: "Der_1 \<phi> \<Longrightarrow> Kh_1 (\<K>\<^sub>D \<phi>)" using PC1 PD3 PK2 ADDI_def Kh_der_def unfolding conn by (metis (full_types))
lemma KD2: "Kh_2 (\<K>\<^sub>D \<phi>)" by (simp add: Kh_2_def dEXP_def Kh_der_def conn)
lemma KD3: "Der_1 \<phi> \<Longrightarrow> Der_2 \<phi> \<Longrightarrow> Der_4 \<phi>  \<Longrightarrow> Kh_3 (\<K>\<^sub>D \<phi>)" proof -
 assume der1: "Der_1 \<phi>" and der2: "Der_2 \<phi>" and der4: "Der_4 \<phi>"
  { fix A
    from der1 have aux1: "let M=A ; N=(\<phi>\<^sup>d A) in \<phi>(M \<^bold>\<or> N) \<^bold>\<approx> (\<phi> M \<^bold>\<or> \<phi> N)" unfolding ADDI_def by simp
    from der1 der2 der4 have aux2: "(\<phi>\<^sup>d A) \<^bold>\<and> (\<phi> A) \<^bold>\<approx> \<phi>\<^sup>d(A \<^bold>\<and> \<phi> A)" using PD12 by simp
    have "(\<K>\<^sub>D \<phi>)((\<K>\<^sub>D \<phi>)\<^sup>d A) = (\<^bold>\<midarrow>(\<^bold>\<midarrow>A \<^bold>\<and> \<phi> (\<^bold>\<midarrow>A)) \<^bold>\<and> \<phi> (\<^bold>\<midarrow>(\<^bold>\<midarrow>A \<^bold>\<and> \<phi> (\<^bold>\<midarrow>A))))" unfolding Kh_der_def dual_def by simp
    also have "... = (A \<^bold>\<or> \<phi>\<^sup>d A) \<^bold>\<and> \<phi>(A \<^bold>\<or> \<phi>\<^sup>d A)" unfolding dual_def conn by simp
    also from aux1 have "... = (A \<^bold>\<or> \<phi>\<^sup>d A) \<^bold>\<and> (\<phi> A \<^bold>\<or> \<phi>(\<phi>\<^sup>d A))" unfolding conn by meson
    also have "... = (A \<^bold>\<and> \<phi> A) \<^bold>\<or> \<phi>\<^sup>d A" using PD6 PD8 der1 der2 der4 unfolding conn by blast
    also have "... = (A \<^bold>\<and> \<phi> A) \<^bold>\<or> (\<phi>\<^sup>d A \<^bold>\<and> \<phi> A)" using PD6 der1 der2 unfolding conn by blast
    also have "... = (A \<^bold>\<or> \<phi>\<^sup>d A) \<^bold>\<and> (\<phi> A)" unfolding conn by auto
    also from aux2 have "... = (A \<^bold>\<and> \<phi> A) \<^bold>\<or> \<phi>\<^sup>d(A \<^bold>\<and> \<phi> A)" unfolding dual_def conn by meson
    also have "... = \<^bold>\<midarrow>(\<^bold>\<midarrow>(A \<^bold>\<and> \<phi> A) \<^bold>\<and> \<phi> (\<^bold>\<midarrow>(A \<^bold>\<and> \<phi> A)))" unfolding dual_def conn by simp
    also have "... = (\<K>\<^sub>D \<phi>)\<^sup>d((\<K>\<^sub>D \<phi>) A)" unfolding Kh_der_def dual_def by simp
    finally have "(\<K>\<^sub>D \<phi>)((\<K>\<^sub>D \<phi>)\<^sup>d A) \<^bold>\<approx> (\<K>\<^sub>D \<phi>)\<^sup>d((\<K>\<^sub>D \<phi>) A)" by simp
 } thus ?thesis unfolding Kh_3_def by simp
qed

end


(*  Title:      HOL/HOLCF/IOA/Asig.thy
    Author:     Olaf Müller, Tobias Nipkow & Konrad Slind
*)

section \<open>Action signatures\<close>

theory Asig
imports Main
begin

type_synonym 'a signature = "'a set \<times> 'a set \<times> 'a set"

definition inputs :: "'action signature \<Rightarrow> 'action set"
  where asig_inputs_def: "inputs = fst"

definition outputs :: "'action signature \<Rightarrow> 'action set"
  where asig_outputs_def: "outputs = fst \<circ> snd"

definition internals :: "'action signature \<Rightarrow> 'action set"
  where asig_internals_def: "internals = snd \<circ> snd"

definition actions :: "'action signature \<Rightarrow> 'action set"
  where "actions asig = inputs asig \<union> outputs asig \<union> internals asig"

definition externals :: "'action signature \<Rightarrow> 'action set"
  where "externals asig = inputs asig \<union> outputs asig"

definition locals :: "'action signature \<Rightarrow> 'action set"
  where "locals asig = internals asig \<union> outputs asig"

definition is_asig :: "'action signature \<Rightarrow> bool"
  where "is_asig triple \<longleftrightarrow>
    inputs triple \<inter> outputs triple = {} \<and>
    outputs triple \<inter> internals triple = {} \<and>
    inputs triple \<inter> internals triple = {}"

definition mk_ext_asig :: "'action signature \<Rightarrow> 'action signature"
  where "mk_ext_asig triple = (inputs triple, outputs triple, {})"

lemmas asig_projections = asig_inputs_def asig_outputs_def asig_internals_def

lemma asig_triple_proj:
  "outputs (a, b, c) = b \<and>
   inputs (a, b, c) = a \<and>
   internals (a, b, c) = c"
  by (simp add: asig_projections)

lemma int_and_ext_is_act: "a \<notin> internals S \<Longrightarrow> a \<notin> externals S \<Longrightarrow> a \<notin> actions S"
  by (simp add: externals_def actions_def)

lemma ext_is_act: "a \<in> externals S \<Longrightarrow> a \<in> actions S"
  by (simp add: externals_def actions_def)

lemma int_is_act: "a \<in> internals S \<Longrightarrow> a \<in> actions S"
  by (simp add: asig_internals_def actions_def)

lemma inp_is_act: "a \<in> inputs S \<Longrightarrow> a \<in> actions S"
  by (simp add: asig_inputs_def actions_def)

lemma out_is_act: "a \<in> outputs S \<Longrightarrow> a \<in> actions S"
  by (simp add: asig_outputs_def actions_def)

lemma ext_and_act: "x \<in> actions S \<and> x \<in> externals S \<longleftrightarrow> x \<in> externals S"
  by (fast intro!: ext_is_act)

lemma not_ext_is_int: "is_asig S \<Longrightarrow> x \<in> actions S \<Longrightarrow> x \<notin> externals S \<longleftrightarrow> x \<in> internals S"
  by (auto simp add: actions_def is_asig_def externals_def)

lemma not_ext_is_int_or_not_act: "is_asig S \<Longrightarrow> x \<notin> externals S \<longleftrightarrow> x \<in> internals S \<or> x \<notin> actions S"
  by (auto simp add: actions_def is_asig_def externals_def)

lemma int_is_not_ext:"is_asig S \<Longrightarrow> x \<in> internals S \<Longrightarrow> x \<notin> externals S"
  by (auto simp add: externals_def actions_def is_asig_def)

end


(*****************************************************************************
 * Featherweight-OCL --- A Formal Semantics for UML-OCL Version OCL 2.5
 *                       for the OMG Standard.
 *                       http://www.brucker.ch/projects/hol-testgen/
 *
 * UML_Integer.thy --- Library definitions.
 * This file is part of HOL-TestGen.
 *
 * Copyright (c) 2012-2015 Université Paris-Saclay, Univ. Paris-Sud, France
 *               2013-2015 IRT SystemX, France
 *
 * 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 copyright holders nor the names of its
 *       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.
 ******************************************************************************)

theory  UML_Integer
imports "../UML_PropertyProfiles"
begin

section\<open>Basic Type Integer: Operations\<close>

subsection\<open>Fundamental Predicates on Integers: Strict Equality \label{sec:integer-strict-eq}\<close>

text\<open>The last basic operation belonging to the fundamental infrastructure
of a value-type in OCL is the weak equality, which is defined similar
to the @{typ "('\<AA>)Boolean"}-case as strict extension of the strong equality:\<close>
overloading StrictRefEq \<equiv> "StrictRefEq :: [('\<AA>)Integer,('\<AA>)Integer] \<Rightarrow> ('\<AA>)Boolean"
begin
  definition StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r[code_unfold] :
    "(x::('\<AA>)Integer) \<doteq> y \<equiv> \<lambda> \<tau>. if (\<upsilon> x) \<tau> = true \<tau> \<and> (\<upsilon> y) \<tau> = true \<tau>
                                  then (x \<triangleq> y) \<tau>
                                  else invalid \<tau>"
end

text\<open>Property proof in terms of @{term "profile_bin\<^sub>S\<^sub>t\<^sub>r\<^sub>o\<^sub>n\<^sub>g\<^sub>E\<^sub>q_\<^sub>v_\<^sub>v"}\<close>
interpretation  StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>S\<^sub>t\<^sub>r\<^sub>o\<^sub>n\<^sub>g\<^sub>E\<^sub>q_\<^sub>v_\<^sub>v "\<lambda> x y. (x::('\<AA>)Integer) \<doteq> y"
         by unfold_locales (auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r)

subsection\<open>Basic Integer Constants\<close>

text\<open>Although the remaining part of this library reasons about
integers abstractly, we provide here as example some convenient shortcuts.\<close>

definition OclInt0 ::"('\<AA>)Integer" ("\<zero>")  where      "\<zero> = (\<lambda> _ . \<lfloor>\<lfloor>0::int\<rfloor>\<rfloor>)"
definition OclInt1 ::"('\<AA>)Integer" ("\<one>")  where      "\<one> = (\<lambda> _ . \<lfloor>\<lfloor>1::int\<rfloor>\<rfloor>)"
definition OclInt2 ::"('\<AA>)Integer" ("\<two>")  where      "\<two> = (\<lambda> _ . \<lfloor>\<lfloor>2::int\<rfloor>\<rfloor>)"
text\<open>Etc.\<close>
text_raw\<open>\isatagafp\<close>
definition OclInt3 ::"('\<AA>)Integer" ("\<three>")  where      "\<three> = (\<lambda> _ . \<lfloor>\<lfloor>3::int\<rfloor>\<rfloor>)"
definition OclInt4 ::"('\<AA>)Integer" ("\<four>")  where      "\<four> = (\<lambda> _ . \<lfloor>\<lfloor>4::int\<rfloor>\<rfloor>)"
definition OclInt5 ::"('\<AA>)Integer" ("\<five>")  where      "\<five> = (\<lambda> _ . \<lfloor>\<lfloor>5::int\<rfloor>\<rfloor>)"
definition OclInt6 ::"('\<AA>)Integer" ("\<six>")  where      "\<six> = (\<lambda> _ . \<lfloor>\<lfloor>6::int\<rfloor>\<rfloor>)"
definition OclInt7 ::"('\<AA>)Integer" ("\<seven>")  where      "\<seven> = (\<lambda> _ . \<lfloor>\<lfloor>7::int\<rfloor>\<rfloor>)"
definition OclInt8 ::"('\<AA>)Integer" ("\<eight>")  where      "\<eight> = (\<lambda> _ . \<lfloor>\<lfloor>8::int\<rfloor>\<rfloor>)"
definition OclInt9 ::"('\<AA>)Integer" ("\<nine>")  where      "\<nine> = (\<lambda> _ . \<lfloor>\<lfloor>9::int\<rfloor>\<rfloor>)"
definition OclInt10 ::"('\<AA>)Integer" ("\<one>\<zero>")where      "\<one>\<zero> = (\<lambda> _ . \<lfloor>\<lfloor>10::int\<rfloor>\<rfloor>)"

subsection\<open>Validity and Definedness Properties\<close>

lemma  "\<delta>(null::('\<AA>)Integer) = false" by simp
lemma  "\<upsilon>(null::('\<AA>)Integer) = true"  by simp

lemma [simp,code_unfold]: "\<upsilon> (\<lambda>_. \<lfloor>\<lfloor>n\<rfloor>\<rfloor>) = true"
by(simp add:valid_def true_def
               bot_fun_def bot_option_def)

(* ecclectic proofs to make examples executable *)
lemma [simp,code_unfold]: "\<delta> \<zero> = true" by(simp add:OclInt0_def)
lemma [simp,code_unfold]: "\<upsilon> \<zero> = true" by(simp add:OclInt0_def)
lemma [simp,code_unfold]: "\<delta> \<one> = true" by(simp add:OclInt1_def)
lemma [simp,code_unfold]: "\<upsilon> \<one> = true" by(simp add:OclInt1_def)
lemma [simp,code_unfold]: "\<delta> \<two> = true" by(simp add:OclInt2_def)
lemma [simp,code_unfold]: "\<upsilon> \<two> = true" by(simp add:OclInt2_def)
lemma [simp,code_unfold]: "\<delta> \<six> = true" by(simp add:OclInt6_def)
lemma [simp,code_unfold]: "\<upsilon> \<six> = true" by(simp add:OclInt6_def)
lemma [simp,code_unfold]: "\<delta> \<eight> = true" by(simp add:OclInt8_def)
lemma [simp,code_unfold]: "\<upsilon> \<eight> = true" by(simp add:OclInt8_def)
lemma [simp,code_unfold]: "\<delta> \<nine> = true" by(simp add:OclInt9_def)
lemma [simp,code_unfold]: "\<upsilon> \<nine> = true" by(simp add:OclInt9_def)

text_raw\<open>\endisatagafp\<close>

subsection\<open>Arithmetical Operations\<close>

subsubsection\<open>Definition\<close>
text\<open>Here is a common case of a built-in operation on built-in types.
Note that the arguments must be both defined (non-null, non-bot).\<close>
text\<open>Note that we can not follow the lexis of the OCL Standard for Isabelle
technical reasons; these operators are heavily overloaded in the HOL library
that a further overloading would lead to heavy technical buzz in this
document.
\<close>
definition OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer" (infix "+\<^sub>i\<^sub>n\<^sub>t" 40)
where "x +\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> + \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor>
                       else invalid \<tau> "
interpretation OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>d_\<^sub>d "(+\<^sub>i\<^sub>n\<^sub>t)" "\<lambda> x y. \<lfloor>\<lfloor>\<lceil>\<lceil>x\<rceil>\<rceil> + \<lceil>\<lceil>y\<rceil>\<rceil>\<rfloor>\<rfloor>"
         by unfold_locales (auto simp:OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def bot_option_def null_option_def)

definition OclMinus\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer" (infix "-\<^sub>i\<^sub>n\<^sub>t" 41)
where "x -\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> - \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor>
                       else invalid \<tau> "
interpretation OclMinus\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>d_\<^sub>d "(-\<^sub>i\<^sub>n\<^sub>t)" "\<lambda> x y. \<lfloor>\<lfloor>\<lceil>\<lceil>x\<rceil>\<rceil> - \<lceil>\<lceil>y\<rceil>\<rceil>\<rfloor>\<rfloor>"
         by   unfold_locales  (auto simp:OclMinus\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def bot_option_def null_option_def)

definition OclMult\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer" (infix "*\<^sub>i\<^sub>n\<^sub>t" 45)
where "x *\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> * \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor>
                       else invalid \<tau>"
interpretation OclMult\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>d_\<^sub>d "OclMult\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r" "\<lambda> x y. \<lfloor>\<lfloor>\<lceil>\<lceil>x\<rceil>\<rceil> * \<lceil>\<lceil>y\<rceil>\<rceil>\<rfloor>\<rfloor>"
         by   unfold_locales  (auto simp:OclMult\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def bot_option_def null_option_def)

text\<open>Here is the special case of division, which is defined as invalid for division
by zero.\<close>
definition OclDivision\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer" (infix "div\<^sub>i\<^sub>n\<^sub>t" 45)
where "x div\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then if y \<tau> \<noteq> OclInt0 \<tau> then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> div \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor> else invalid \<tau>
                       else invalid \<tau> "
(* TODO: special locale setup.*)

definition OclModulus\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer" (infix "mod\<^sub>i\<^sub>n\<^sub>t" 45)
where "x mod\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then if y \<tau> \<noteq> OclInt0 \<tau> then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> mod \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor> else invalid \<tau>
                       else invalid \<tau> "
(* TODO: special locale setup.*)

definition OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Boolean" (infix "<\<^sub>i\<^sub>n\<^sub>t" 35)
where "x <\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> < \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor>
                       else invalid \<tau> "
interpretation OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>d_\<^sub>d "(<\<^sub>i\<^sub>n\<^sub>t)" "\<lambda> x y. \<lfloor>\<lfloor>\<lceil>\<lceil>x\<rceil>\<rceil> < \<lceil>\<lceil>y\<rceil>\<rceil>\<rfloor>\<rfloor>"
         by   unfold_locales  (auto simp:OclLess\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def bot_option_def null_option_def)

definition OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r ::"('\<AA>)Integer \<Rightarrow> ('\<AA>)Integer \<Rightarrow> ('\<AA>)Boolean" (infix "\<le>\<^sub>i\<^sub>n\<^sub>t" 35)
where "x \<le>\<^sub>i\<^sub>n\<^sub>t y \<equiv> \<lambda> \<tau>. if (\<delta> x) \<tau> = true \<tau> \<and> (\<delta> y) \<tau> = true \<tau>
                       then \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil> \<le> \<lceil>\<lceil>y \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor>
                       else invalid \<tau> "
interpretation OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r : profile_bin\<^sub>d_\<^sub>d "(\<le>\<^sub>i\<^sub>n\<^sub>t)" "\<lambda> x y. \<lfloor>\<lfloor>\<lceil>\<lceil>x\<rceil>\<rceil> \<le> \<lceil>\<lceil>y\<rceil>\<rceil>\<rfloor>\<rfloor>"
         by   unfold_locales  (auto simp:OclLe\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def bot_option_def null_option_def)

subsubsection\<open>Basic Properties\<close>

lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_commute: "(X +\<^sub>i\<^sub>n\<^sub>t Y) = (Y +\<^sub>i\<^sub>n\<^sub>t X)"
  by(rule ext,auto simp:true_def false_def OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def invalid_def
                   split: option.split option.split_asm
                          bool.split bool.split_asm)

subsubsection\<open>Execution with Invalid or Null or Zero as Argument\<close>

lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_zero1[simp,code_unfold] :
"(x +\<^sub>i\<^sub>n\<^sub>t \<zero>) = (if \<upsilon> x and not (\<delta> x) then invalid else x endif)"
 proof (rule ext, rename_tac \<tau>, case_tac "(\<upsilon> x and not (\<delta> x)) \<tau> = true \<tau>")
  fix \<tau> show "(\<upsilon> x and not (\<delta> x)) \<tau> = true \<tau> \<Longrightarrow>
              (x +\<^sub>i\<^sub>n\<^sub>t \<zero>) \<tau> = (if \<upsilon> x and not (\<delta> x) then invalid else x endif) \<tau>"
   apply(subst OclIf_true', simp add: OclValid_def)
  by (metis OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def OclNot_defargs OclValid_def foundation5 foundation9)
 next fix \<tau>
  have A: "\<And>\<tau>. (\<tau> \<Turnstile> not (\<upsilon> x and not (\<delta> x))) = (x \<tau> = invalid \<tau> \<or> \<tau> \<Turnstile> \<delta> x)"
  by (metis OclNot_not OclOr_def defined5 defined6 defined_not_I foundation11 foundation18'
            foundation6 foundation7 foundation9 invalid_def)
  have B: "\<tau> \<Turnstile> \<delta> x \<Longrightarrow> \<lfloor>\<lfloor>\<lceil>\<lceil>x \<tau>\<rceil>\<rceil>\<rfloor>\<rfloor> = x \<tau>"
   apply(cases "x \<tau>", metis bot_option_def foundation16)
   apply(rename_tac x', case_tac x', metis bot_option_def foundation16 null_option_def)
  by(simp)
  show "(x +\<^sub>i\<^sub>n\<^sub>t \<zero>) \<tau> = (if \<upsilon> x and not (\<delta> x) then invalid else x endif) \<tau>"
    when "\<tau> \<Turnstile> not (\<upsilon> x and not (\<delta> x))"
   apply(insert that, subst OclIf_false', simp, simp add: A, auto simp: OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_def OclInt0_def)
     (* *)
     apply(simp add: foundation16'[simplified OclValid_def])
    apply(simp add: B)
  by(simp add: OclValid_def)
qed(metis OclValid_def defined5 defined6 defined_and_I defined_not_I foundation9)

lemma OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_zero2[simp,code_unfold] :
"(\<zero> +\<^sub>i\<^sub>n\<^sub>t x) = (if \<upsilon> x and not (\<delta> x) then invalid else x endif)"
by(subst OclAdd\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r_commute, simp)

(* TODO Basic proproperties for multiplication, division, modulus. *)

subsection\<open>Test Statements\<close>
text\<open>Here follows a list of code-examples, that explain the meanings
of the above definitions by compilation to code and execution to @{term "True"}.\<close>

Assert "\<tau> \<Turnstile> ( \<nine> \<le>\<^sub>i\<^sub>n\<^sub>t \<one>\<zero> )"
Assert "\<tau> \<Turnstile> (( \<four> +\<^sub>i\<^sub>n\<^sub>t \<four> ) \<le>\<^sub>i\<^sub>n\<^sub>t \<one>\<zero> )"
Assert "\<tau> |\<noteq> (( \<four> +\<^sub>i\<^sub>n\<^sub>t ( \<four> +\<^sub>i\<^sub>n\<^sub>t \<four> )) <\<^sub>i\<^sub>n\<^sub>t \<one>\<zero> )"
Assert "\<tau> \<Turnstile> not (\<upsilon> (null +\<^sub>i\<^sub>n\<^sub>t \<one>)) "
Assert "\<tau> \<Turnstile> (((\<nine> *\<^sub>i\<^sub>n\<^sub>t \<four>) div\<^sub>i\<^sub>n\<^sub>t \<one>\<zero>) \<le>\<^sub>i\<^sub>n\<^sub>t  \<four>) "
Assert "\<tau> \<Turnstile> not (\<delta> (\<one> div\<^sub>i\<^sub>n\<^sub>t \<zero>)) "
Assert "\<tau> \<Turnstile> not (\<upsilon> (\<one> div\<^sub>i\<^sub>n\<^sub>t \<zero>)) "

lemma integer_non_null [simp]: "((\<lambda>_. \<lfloor>\<lfloor>n\<rfloor>\<rfloor>) \<doteq> (null::('\<AA>)Integer)) = false"
by(rule ext,auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def
                         bot_fun_def bot_option_def null_fun_def null_option_def StrongEq_def)

lemma null_non_integer [simp]: "((null::('\<AA>)Integer) \<doteq> (\<lambda>_. \<lfloor>\<lfloor>n\<rfloor>\<rfloor>)) = false"
by(rule ext,auto simp: StrictRefEq\<^sub>I\<^sub>n\<^sub>t\<^sub>e\<^sub>g\<^sub>e\<^sub>r valid_def
                         bot_fun_def bot_option_def null_fun_def null_option_def StrongEq_def)

lemma OclInt0_non_null [simp,code_unfold]: "(\<zero> \<doteq> null) = false" by(simp add: OclInt0_def)
lemma null_non_OclInt0 [simp,code_unfold]: "(null \<doteq> \<zero>) = false" by(simp add: OclInt0_def)
lemma OclInt1_non_null [simp,code_unfold]: "(\<one> \<doteq> null) = false" by(simp add: OclInt1_def)
lemma null_non_OclInt1 [simp,code_unfold]: "(null \<doteq> \<one>) = false" by(simp add: OclInt1_def)
lemma OclInt2_non_null [simp,code_unfold]: "(\<two> \<doteq> null) = false" by(simp add: OclInt2_def)
lemma null_non_OclInt2 [simp,code_unfold]: "(null \<doteq> \<two>) = false" by(simp add: OclInt2_def)
lemma OclInt6_non_null [simp,code_unfold]: "(\<six> \<doteq> null) = false" by(simp add: OclInt6_def)
lemma null_non_OclInt6 [simp,code_unfold]: "(null \<doteq> \<six>) = false" by(simp add: OclInt6_def)
lemma OclInt8_non_null [simp,code_unfold]: "(\<eight> \<doteq> null) = false" by(simp add: OclInt8_def)
lemma null_non_OclInt8 [simp,code_unfold]: "(null \<doteq> \<eight>) = false" by(simp add: OclInt8_def)
lemma OclInt9_non_null [simp,code_unfold]: "(\<nine> \<doteq> null) = false" by(simp add: OclInt9_def)
lemma null_non_OclInt9 [simp,code_unfold]: "(null \<doteq> \<nine>) = false" by(simp add: OclInt9_def)

text\<open>Here follows a list of code-examples, that explain the meanings
of the above definitions by compilation to code and execution to @{term "True"}.\<close>

text\<open>Elementary computations on Integer\<close>

Assert "\<tau> \<Turnstile> ((\<zero> <\<^sub>i\<^sub>n\<^sub>t \<two>) and (\<zero> <\<^sub>i\<^sub>n\<^sub>t \<one>))"

Assert "\<tau> \<Turnstile> \<one> <> \<two>"
Assert "\<tau> \<Turnstile> \<two> <> \<one>"
Assert "\<tau> \<Turnstile> \<two> \<doteq> \<two>"

Assert "\<tau> \<Turnstile> \<upsilon> \<four>"
Assert "\<tau> \<Turnstile> \<delta> \<four>"
Assert "\<tau> \<Turnstile> \<upsilon> (null::('\<AA>)Integer)"
Assert "\<tau> \<Turnstile> (invalid \<triangleq> invalid)"
Assert "\<tau> \<Turnstile> (null \<triangleq> null)"
Assert "\<tau> \<Turnstile> (\<four> \<triangleq> \<four>)"
Assert "\<tau> |\<noteq> (\<nine> \<triangleq> \<one>\<zero>)"
Assert "\<tau> |\<noteq> (invalid \<triangleq> \<one>\<zero>)"
Assert "\<tau> |\<noteq> (null \<triangleq> \<one>\<zero>)"
Assert "\<tau> |\<noteq> (invalid \<doteq> (invalid::('\<AA>)Integer))"   (* Without typeconstraint not executable.*)
Assert "\<tau> |\<noteq> \<upsilon> (invalid \<doteq> (invalid::('\<AA>)Integer))" (* Without typeconstraint not executable.*)
Assert "\<tau> |\<noteq> (invalid <> (invalid::('\<AA>)Integer))"   (* Without typeconstraint not executable.*)
Assert "\<tau> |\<noteq> \<upsilon> (invalid <> (invalid::('\<AA>)Integer))" (* Without typeconstraint not executable.*)
Assert "\<tau> \<Turnstile> (null \<doteq> (null::('\<AA>)Integer) )" (* Without typeconstraint not executable.*)
Assert "\<tau> \<Turnstile> (null \<doteq> (null::('\<AA>)Integer) )" (* Without typeconstraint not executable.*)
Assert "\<tau> \<Turnstile> (\<four> \<doteq> \<four>)"
Assert "\<tau> |\<noteq> (\<four> <> \<four>)"
Assert "\<tau> |\<noteq> (\<four> \<doteq> \<one>\<zero>)"
Assert "\<tau> \<Turnstile> (\<four> <> \<one>\<zero>)"
Assert "\<tau> |\<noteq> (\<zero> <\<^sub>i\<^sub>n\<^sub>t null)"
Assert "\<tau> |\<noteq> (\<delta> (\<zero> <\<^sub>i\<^sub>n\<^sub>t null))"

end