header {* Basic theory of vector spaces, using locales *}

theory VectorSpace
imports Main
  "~~/src/HOL/Algebra/Module"
  "~~/src/HOL/Algebra/Coset"
  RingModuleFacts
  MonoidSums
  LinearCombinations
  SumSpaces
begin

subsection {* Basic definitions and facts carried over from modules*}
text {*A @{text "vectorspace"} is a module where the ring is a field.
Note that we switch notation from $(R, M)$ to $(K, V)$.*}
locale vectorspace =
  module: module K V + field: field K
  for K and V

(*
Use sets for bases, and functions from the sets to carrier K
represent the coefficients.
*)

text {*A @{text "subspace"} of a vectorspace is a nonempty subset
that is closed under addition and scalar multiplication. These properties
have already been defined in submodule. Caution: W is a set, while V is
a module record. To get W as a vectorspace, write vs W.*}
locale subspace =
  fixes K and W and V (structure)
  assumes vs: "vectorspace K V"
      and submod: "submodule K W V"

lemma (in vectorspace) is_module[simp]:
  "subspace K W V\<Longrightarrow>submodule K W V"
by (unfold subspace_def, auto)

text {*We introduce some basic facts and definitions copied from module.
We introduce some abbreviations, to match convention.*}
abbreviation (in vectorspace) vs::"'c set \<Rightarrow> ('a, 'c, 'd) module_scheme"
  where "vs W \<equiv> V\<lparr>carrier :=W\<rparr>"

lemma (in vectorspace) carrier_vs_is_self [simp]:
  "carrier (vs W) = W"
  by auto

lemma (in vectorspace) subspace_is_vs:
  fixes W::"'c set"
  assumes 0: "subspace K W V"
  shows "vectorspace K (vs W)"
proof -
  from 0 show ?thesis
    apply (unfold vectorspace_def subspace_def, auto)
    by (intro submodule_is_module, auto)
qed

abbreviation (in module) subspace_sum:: "['c set, 'c set] \<Rightarrow> 'c set"
  where "subspace_sum W1 W2 \<equiv>submodule_sum W1 W2"

lemma (in vectorspace) vs_zero_lin_dep:
  assumes h2: "S\<subseteq>carrier V" and h3: "lin_indpt S"
  shows "\<zero>\<^bsub>V\<^esub> \<notin> S"
proof -
  have vs: "vectorspace K V"..
  from vs have nonzero: "carrier K \<noteq>{\<zero>\<^bsub>K\<^esub>}"
    by (metis one_zeroI zero_not_one)
  from h2 h3 nonzero show ?thesis by (rule zero_nin_lin_indpt)
qed

text {*A @{text "linear_map"} is a module homomorphism between 2 vectorspaces
over the same field.*}
locale linear_map =
  V: vectorspace K V + W: vectorspace K W
  + mod_hom: mod_hom K V W T
    for K and V and W and T

context linear_map
begin
lemmas T_hom = f_hom
lemmas T_add = f_add
lemmas T_smult = f_smult
lemmas T_im = f_im
lemmas T_neg = f_neg
lemmas T_minus = f_minus
lemmas T_ker = f_ker

abbreviation imT:: "'e set"
  where "imT \<equiv> mod_hom.im"

abbreviation kerT:: "'c set"
  where "kerT \<equiv> mod_hom.ker"

lemmas T0_is_0[simp] = f0_is_0

lemma kerT_is_subspace: "subspace K ker V"
proof -
  have vs: "vectorspace K V"..
  from vs show ?thesis
    apply (unfold subspace_def, auto)
    by (rule ker_is_submodule)
qed

text {*For any set $S$, the space of functions $S\to K$ forms a vector space.*}
lemma (in vectorspace) func_space_is_vs:
  fixes S
  shows "vectorspace K (func_space S)"
proof -
  have 0: "field K"..
  have 1: "module K (func_space S)" by (rule func_space_is_module)
  from 0 1 show ?thesis by (unfold vectorspace_def module_def, auto)
qed

lemma direct_sum_is_vs:
  fixes K V1 V2
  assumes h1: "vectorspace K V1" and h2: "vectorspace K V2"
  shows "vectorspace K (direct_sum V1 V2)"
proof -
  from h1 h2 have mod: "module K (direct_sum V1 V2)" by (unfold vectorspace_def, intro direct_sum_is_module, auto)
  from mod h1 show ?thesis by (unfold vectorspace_def, auto)
qed

lemma inj1_linear:
  fixes K V1 V2
  assumes h1: "vectorspace K V1" and h2: "vectorspace K V2"
  shows "linear_map K V1 (direct_sum V1 V2) (inj1 V1 V2)"
proof -
  from h1 h2 have mod: "mod_hom K V1 (direct_sum V1 V2) (inj1 V1 V2)" by (unfold vectorspace_def, intro inj1_hom, auto)
  from mod h1 h2 show ?thesis
    by (unfold linear_map_def vectorspace_def , auto, intro direct_sum_is_module, auto)
qed

lemma inj2_linear:
  fixes K V1 V2
  assumes h1: "vectorspace K V1" and h2: "vectorspace K V2"
  shows "linear_map K V2 (direct_sum V1 V2) (inj2 V1 V2)"
proof -
  from h1 h2 have mod: "mod_hom K V2 (direct_sum V1 V2) (inj2 V1 V2)" by (unfold vectorspace_def, intro inj2_hom, auto)
  from mod h1 h2 show ?thesis
    by (unfold linear_map_def vectorspace_def , auto, intro direct_sum_is_module, auto)
qed

text {*For subspaces $V_1,V_2\subseteq V$, the map $V_1\oplus V_2\to V$ given by $(v_1,v_2)\mapsto
v_1+v_2$ is linear.*}
lemma (in vectorspace) sum_map_linear:
  fixes V1 V2
  assumes h1: "subspace K V1 V" and h2: "subspace K V2 V"
  shows "linear_map K (direct_sum (vs V1) (vs V2)) V (\<lambda> v. (fst v) \<oplus>\<^bsub>V\<^esub> (snd v))"
proof -
  from h1 h2 have mod: "mod_hom K (direct_sum (vs V1) (vs V2)) V (\<lambda> v. (fst v) \<oplus>\<^bsub>V\<^esub> (snd v))"
    by ( intro sum_map_hom, unfold subspace_def, auto)
  from mod h1 h2 show ?thesis
    apply (unfold linear_map_def, auto) apply (intro direct_sum_is_vs subspace_is_vs, auto)..
qed

lemma (in vectorspace) sum_is_subspace:
  fixes W1 W2
  assumes h1: "subspace K W1 V" and h2: "subspace K W2 V"
  shows "subspace K (subspace_sum W1 W2) V"
proof -
  from h1 h2 have mod: "submodule K (submodule_sum W1 W2) V"
    by ( intro sum_is_submodule, unfold subspace_def, auto)
  from mod h1 h2 show ?thesis
    by (unfold subspace_def, auto)
qed

text {*If $W_1,W_2\subseteq V$ are subspaces, $W_1\subseteq W_1 + W_2$*}
lemma (in vectorspace) in_sum_vs:
  fixes W1 W2
  assumes h1: "subspace K W1 V" and h2: "subspace K W2 V"
  shows "W1 \<subseteq> subspace_sum W1 W2"
proof -
  from h1 h2 show ?thesis by (intro in_sum, unfold subspace_def, auto)
qed

lemma (in vectorspace) vsum_comm:
  fixes W1 W2
  assumes h1: "subspace K W1 V" and h2: "subspace K W2 V"
  shows "(subspace_sum W1 W2) = (subspace_sum W2 W1)"
proof -
  from h1 h2 show ?thesis by (intro msum_comm, unfold subspace_def, auto)
qed

text {*If $W_1,W_2\subseteq V$ are subspaces, then $W_1+W_2$ is the minimal subspace such that
both $W_1\subseteq W$ and $W_2\subseteq W$.*}
lemma (in vectorspace) vsum_is_minimal:
  fixes W W1 W2
  assumes h1: "subspace K W1 V" and h2: "subspace K W2 V" and h3: "subspace K W V"
  shows "(subspace_sum W1 W2) \<subseteq> W \<longleftrightarrow> W1 \<subseteq> W \<and> W2 \<subseteq> W"
proof -
  from h1 h2 h3 show ?thesis by (intro sum_is_minimal, unfold subspace_def, auto)
qed

lemma (in vectorspace) span_is_subspace:
  fixes S
  assumes h2: "S\<subseteq>carrier V"
  shows "subspace K (span S) V"
proof -
  have 0: "vectorspace K V"..
  from h2 have 1: "submodule K (span S) V" by (rule span_is_submodule)
  from 0 1 show ?thesis by (unfold subspace_def mod_hom_def linear_map_def, auto)
qed

subsubsection {* Facts specific to vector spaces *}

text {*If $av = w$ and $a\neq 0$, $v=a^{-1}w$.*}
lemma (in vectorspace) mult_inverse:
  assumes h1: "a\<in>carrier K" and h2: "v\<in>carrier V" and h3: "a \<odot>\<^bsub>V\<^esub> v = w" and h4: "a\<noteq>\<zero>\<^bsub>K\<^esub>"
  shows "v = (inv\<^bsub>K\<^esub> a )\<odot>\<^bsub>V\<^esub> w"
proof -
  from h1 h2 h3 have 1: "w\<in>carrier V" by auto
  from h3 1 have 2: "(inv\<^bsub>K\<^esub> a )\<odot>\<^bsub>V\<^esub>(a \<odot>\<^bsub>V\<^esub> v) =(inv\<^bsub>K\<^esub> a )\<odot>\<^bsub>V\<^esub>w" by auto
  from h1 h4 have 3: "inv\<^bsub>K\<^esub> a\<in>carrier K" by auto
  interpret g: group "(units_group K)" by (rule units_form_group)
  have f: "field K"..
  from f h1 h4 have 4: "a\<in>Units K"
    by (unfold field_def field_axioms_def, simp)
  from 4 h1 h4 have 5: "((inv\<^bsub>K\<^esub> a) \<otimes>\<^bsub>K\<^esub>a) = \<one>\<^bsub>K\<^esub>"
    by (intro Units_l_inv, auto)
  from 5 have 6: "(inv\<^bsub>K\<^esub> a )\<odot>\<^bsub>V\<^esub>(a \<odot>\<^bsub>V\<^esub> v) = v"
  proof -
    from h1 h2 h4 have 7: "(inv\<^bsub>K\<^esub> a )\<odot>\<^bsub>V\<^esub>(a \<odot>\<^bsub>V\<^esub> v) =(inv\<^bsub>K\<^esub> a \<otimes>\<^bsub>K\<^esub>a) \<odot>\<^bsub>V\<^esub> v" by (auto simp add: smult_assoc1)
    from 5 h2 have 8: "(inv\<^bsub>K\<^esub> a \<otimes>\<^bsub>K\<^esub>a) \<odot>\<^bsub>V\<^esub> v = v" by auto
    from 7 8 show ?thesis by auto
  qed
  from 2 6 show ?thesis by auto
qed

text {*If $w\in S$ and $\sum_{w\in S} a_ww=0$, we have $v=\sum_{w\not\in S}a_v^{-1}a_ww$*}
lemma (in vectorspace) lincomb_isolate:
  fixes A v
  assumes h1: "finite A" and h2: "A\<subseteq>carrier V"  and h3: "a\<in>A\<rightarrow>carrier K" and h4: "v\<in>A"
    and h5: "a v \<noteq> \<zero>\<^bsub>K\<^esub>" and h6: "lincomb a A=\<zero>\<^bsub>V\<^esub>"
  shows "v=lincomb (\<lambda>w. \<ominus>\<^bsub>K\<^esub>(inv\<^bsub>K\<^esub> (a v)) \<otimes>\<^bsub>K\<^esub> a w) (A-{v})" and "v\<in> span (A-{v})"
proof -
  from h1 h2 h3 h4 have 1: "lincomb a A = ((a v) \<odot>\<^bsub>V\<^esub> v) \<oplus>\<^bsub>V\<^esub> lincomb a (A-{v})"
    by (rule lincomb_del2)
  from 1 have 2: "\<zero>\<^bsub>V\<^esub>= ((a v) \<odot>\<^bsub>V\<^esub> v) \<oplus>\<^bsub>V\<^esub> lincomb a (A-{v})" by (simp add: h6)
  from h1 h2 h3 have 5: "lincomb a (A-{v}) \<in>carrier V" by auto (*intro lincomb_closed*)
  from 2 h1 h2 h3 h4 have 3: " \<ominus>\<^bsub>V\<^esub> lincomb a (A-{v}) = ((a v) \<odot>\<^bsub>V\<^esub> v)"
    by (auto intro!: M.minus_equality)
  have 6: "v = (\<ominus>\<^bsub>K\<^esub> (inv\<^bsub>K\<^esub> (a v))) \<odot>\<^bsub>V\<^esub> lincomb a (A-{v})"
  proof -
    from h2 h3 h4 h5 3 have 7: "v = inv\<^bsub>K\<^esub> (a v) \<odot>\<^bsub>V\<^esub> (\<ominus>\<^bsub>V\<^esub> lincomb a (A-{v}))"
      by (intro mult_inverse, auto)
    from assms have 8: "inv\<^bsub>K\<^esub> (a v)\<in>carrier K" by auto
    from assms 5 8 have 9: "inv\<^bsub>K\<^esub> (a v) \<odot>\<^bsub>V\<^esub> (\<ominus>\<^bsub>V\<^esub> lincomb a (A-{v}))
      = (\<ominus>\<^bsub>K\<^esub> (inv\<^bsub>K\<^esub> (a v))) \<odot>\<^bsub>V\<^esub> lincomb a (A-{v})"
        by (simp add: smult_assoc_simp smult_minus_1_back r_minus)
    from 7 9 show ?thesis by auto
  qed
  from h1 have 10: "finite (A-{v})" by auto
  from assms have 11 : "(\<ominus>\<^bsub>K\<^esub> (inv\<^bsub>K\<^esub> (a v)))\<in> carrier K" by auto
  from assms have 12: "lincomb (\<lambda>w. \<ominus>\<^bsub>K\<^esub>(inv\<^bsub>K\<^esub> (a v)) \<otimes>\<^bsub>K\<^esub> a w) (A-{v}) =
    (\<ominus>\<^bsub>K\<^esub> (inv\<^bsub>K\<^esub> (a v))) \<odot>\<^bsub>V\<^esub> lincomb a (A-{v})"
    by (intro lincomb_smult, auto)
  from 6 12 show "v=lincomb (\<lambda>w. \<ominus>\<^bsub>K\<^esub>(inv\<^bsub>K\<^esub> (a v)) \<otimes>\<^bsub>K\<^esub> a w) (A-{v})" by auto
  with assms show "v\<in> span (A-{v})"
    unfolding span_def
    by (force simp add: 11 ring_subset_carrier)
qed

text {*The map $(S\to K)\mapsto V$ given by $(a_v)_{v\in S}\mapsto \sum_{v\in S} a_v v$ is linear.*}
lemma (in vectorspace) lincomb_is_linear:
  fixes S
  assumes h: "finite S" and h2: "S\<subseteq>carrier V"
  shows "linear_map K (func_space S) V (\<lambda>a. lincomb a S)"
proof -
  have 0: "vectorspace K V"..
  from h h2 have 1: "mod_hom K (func_space S) V (\<lambda>a. lincomb a S)" by (rule lincomb_is_mod_hom)
  from 0 1 show ?thesis by (unfold vectorspace_def mod_hom_def linear_map_def, auto)
qed

subsection {* Basic facts about span and linear independence *}

text {*If $S$ is linearly independent, then $v\in \text{span}S$ iff $S\cup \{v\}$ is linearly
dependent. *}
theorem (in vectorspace) lin_dep_iff_in_span:
  fixes A v S
  assumes  h1: "S \<subseteq> carrier V" and h2: "lin_indpt S" and h3: "v\<in> carrier V" and h4: "v\<notin>S"
  shows "v\<in> span S \<longleftrightarrow> lin_dep (S \<union> {v})"
proof -
  let ?T = "S \<union> {v}"
  have 0: "v\<in>?T " by auto
  from h1 h3 have h1_1: "?T \<subseteq> carrier V" by auto
  have a1:"lin_dep ?T \<Longrightarrow> v\<in> span S"
  proof -
    assume a11: "lin_dep ?T"
    from a11 obtain a w A where a: "(finite A \<and> A\<subseteq>?T \<and> (a\<in> (A\<rightarrow>carrier K)) \<and> (lincomb a A = \<zero>\<^bsub>V\<^esub>) \<and> (w\<in>A) \<and> (a w\<noteq> \<zero>\<^bsub>K\<^esub>))"
      by (metis lin_dep_def)
    from assms a have nz2: "\<exists>v\<in>A-S. a v\<noteq>\<zero>\<^bsub>K\<^esub>"
      by (intro lincomb_must_include[where ?v="w" and ?T="S\<union>{v}"], auto)
    from a nz2 have singleton: "{v}=A-S" by auto
    from singleton nz2 have nz3: "a v\<noteq>\<zero>\<^bsub>K\<^esub>" by auto
(*Can modularize this whole section out. "solving for one variable"*)
    let ?b="(\<lambda>w. \<ominus>\<^bsub>K\<^esub> (inv\<^bsub>K\<^esub> (a v)) \<otimes>\<^bsub>K\<^esub> (a w))"
    from singleton have Ains: "(A\<inter>S) = A-{v}" by auto
    from assms a singleton nz3 have a31: "v= lincomb ?b (A\<inter>S)"
      apply (subst Ains)
      by (intro lincomb_isolate(1), auto)
    from a a31 nz3 singleton show ?thesis
      apply (unfold span_def, auto)
      apply (rule_tac x="?b" in exI)
      apply (rule_tac x="A\<inter>S" in exI)
      by (auto intro!: m_closed)
  qed
  have a2: "v\<in> (span S) \<Longrightarrow> lin_dep ?T"
  proof -
    assume inspan: "v\<in> (span S)"
    from inspan obtain a A where a: "A\<subseteq>S \<and> finite A \<and> (v = lincomb a A)\<and> a\<in>A\<rightarrow>carrier K" by (simp add: span_def, auto)
    let ?b = "\<lambda> w. if (w=v) then (\<ominus>\<^bsub>K\<^esub> \<one>\<^bsub>K\<^esub>) else a w" (*consider -v + \sum a_w w*)
    have lc0: " lincomb ?b (A\<union>{v})=\<zero>\<^bsub>V\<^esub>"
    proof -
      from assms a have lc_ins: "lincomb ?b (A\<union>{v}) = ((?b v) \<odot>\<^bsub>V\<^esub> v) \<oplus>\<^bsub>V\<^esub> lincomb ?b A"
        by (intro lincomb_insert, auto)
      from assms a have lc_elim: "lincomb ?b A=lincomb a A" by (intro lincomb_elim_if, auto)
      from assms lc_ins lc_elim a show ?thesis by (simp add: M.l_neg smult_minus_1)
    qed
    from  a lc0 show ?thesis
      apply (unfold lin_dep_def)
      apply (rule_tac x="A\<union>{v}" in exI)
      apply (rule_tac x="?b" in exI)
      apply (rule_tac x="v" in exI)
      by auto
  qed
  from a1 a2 show ?thesis by auto
qed

text {*If $v\in \text{span} A$ then $\text{span}A =\text{span}(A\cup \{v\})$*}
lemma (in vectorspace) already_in_span:
  fixes v A
  assumes  inC: "A\<subseteq>carrier V" and inspan: "v\<in>span A"
  shows "span A= span (A\<union>{v})"
proof -
  from inC inspan have dir1: "span A \<subseteq> span (A\<union>{v})" by (intro span_is_monotone, auto)

  from inC have inown: "A\<subseteq>span A" by (rule in_own_span)
  from inC have subm: "submodule K (span A) V" by (rule span_is_submodule)
  from inown inspan subm have dir2: "span (A \<union> {v}) \<subseteq> span A" by (intro span_is_subset, auto)

  from dir1 dir2 show ?thesis by auto
qed

subsection {* The Replacement Theorem*}

text {*If $A,B\subseteq V$ are finite, $A$ is linearly independent, $B$ generates $W$,
and $A\subseteq W$, then there exists $C\subseteq V$ disjoint from $A$ such that
$\text{span}(A\cup C) = W$ and $|C|\le |B|-|A|$. In other words, we can complete
any linearly independent set to a generating set of $W$ by adding at most $|B|-|A|$ more elements. *}

  show ?case
  proof (cases "v\<in> C'")
    case True
    have vinC': "v\<in>C'" by fact
    from vinC' v have seteq: "A - {v} \<union> C' = A \<union> (C' - {v})" by auto
    from C' seteq have spaneq: "span (A \<union> (C' - {v})) = span (B)" by algebra
    from Suc.prems Suc.hyps C' vinC' v spaneq show ?thesis
      apply (rule_tac x="C'-{v}" in exI)
      apply (subgoal_tac "card C' >0")
       by auto
  next
    case False
    have f: "v\<notin>C'" by fact
    from A v C' have "\<exists>a. a\<in>(?A'\<union>C')\<rightarrow>carrier K \<and>  lincomb a (?A' \<union> C') =v"
      by (intro finite_in_span, auto)
    from this obtain a where a: "a\<in>(?A'\<union>C')\<rightarrow>carrier K \<and> v= lincomb a (?A' \<union> C')" by metis
    let ?b="(\<lambda> w. if (w=v) then \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub> else a w)"
    from a have b: "?b\<in>A\<union>C'\<rightarrow>carrier K" by auto
    from v have rewrite_ins: "A\<union>C'=(?A'\<union>C')\<union>{v}" by auto
    from f have "v\<notin>?A'\<union>C'" by auto
    from this A C' v a f have lcb: "lincomb ?b (A \<union> C') = \<zero>\<^bsub>V\<^esub>"
      apply (subst rewrite_ins)
      apply (subst lincomb_insert)
           apply (simp_all add: ring_subset_carrier coeff_in_ring)
        apply (auto split: split_if_asm)
      apply (subst lincomb_elim_if)
          by (auto simp add: smult_minus_1 l_neg ring_subset_carrier)
(*NOTE: l_neg got deleted from the simp rules, but it is very useful.*)
    from C' f have rewrite_minus: "C'=(A\<union>C')-A" by auto
    from A C' b lcb v have exw: "\<exists>w\<in> C'. ?b w\<noteq>\<zero>\<^bsub>K\<^esub>"
      apply (subst rewrite_minus)
      apply (intro lincomb_must_include[where ?T="A\<union>C'" and ?v="v"])
              by auto
    from exw obtain w where w: "w\<in> C'" "?b w\<noteq>\<zero>\<^bsub>K\<^esub>" by auto
    from A C' w f b lcb have w_in: "w\<in>span ((A\<union> C') -{w})"
      apply (intro lincomb_isolate[where a="?b"])
           by auto
    have spaneq2: "span (A\<union>(C'-{w})) = span B"
    proof -
      have 1: "span (?A'\<union>C') = span (A\<union> C')" (*adding v doesn't change the span*)
        proof -
          from A C' v have m1: "span (?A'\<union>C') = span ((?A'\<union> C')\<union>{v})"
            apply (intro already_in_span)
             by auto
          from f m1 show ?thesis by (metis rewrite_ins)
        qed
      have 2: "span (A\<union> (C'-{w})) = span (A\<union> C')" (*removing w doesn't change the span*)
      proof -
        from C' w(1) f have b60: "A\<union> (C'-{w}) = (A\<union> C') -{w}" by auto
        from  w(1) have b61: "A\<union> C'= (A\<union> C' -{w})\<union>{w}" by auto
        from A C'  w_in show ?thesis
          apply (subst b61)
          apply (subst b60)
          apply (intro already_in_span)
           by auto
        qed
    from C' 1 2 show ?thesis by auto
  qed(* "span (A\<union>(C'-{w})) = span B"*)
    from A C' w f v spaneq2 show ?thesis
      apply (rule_tac x="C'-{w}" in exI)
      apply (subgoal_tac "card C' >0")
       by auto
  qed
qed

subsection {* Defining dimension and bases. *}

text {*Finite dimensional is defined as having a finite generating set.*}
definition (in vectorspace) fin_dim:: "bool"
  where "fin_dim = (\<exists> A. ((finite A) \<and> (A \<subseteq> carrier V) \<and> (gen_set A)))"

text {*The dimension is the size of the smallest generating set. For equivalent
characterizations see below.*}
definition (in vectorspace) dim:: "nat"
  where "dim = (LEAST n. (\<exists> A. ((finite A) \<and> (card A = n) \<and> (A \<subseteq> carrier V) \<and> (gen_set A))))"

text {*A @{text "basis"} is a linearly independent generating set.*}
definition (in vectorspace) basis:: "'c set \<Rightarrow> bool"
  where "basis A = ((lin_indpt A) \<and> (gen_set A)\<and> (A\<subseteq>carrier V))"

text {*From the replacement theorem, any linearly independent set is smaller than any generating set.*}
lemma (in vectorspace) li_smaller_than_gen:
  fixes A B
  assumes h1: "finite A" and h2: "finite B" and h3: "A\<subseteq>carrier V" and h4: "B\<subseteq>carrier V"
    and h5: "lin_indpt A" and h6: "gen_set B"
  shows "card A \<le> card B"
proof -
  from h3 h6 have 1: "A\<subseteq>span B" by  auto
  from h1 h2 h4 h5 1 obtain C where
    2: "finite C \<and> C\<subseteq>carrier V \<and> C\<subseteq>span B \<and> C\<inter>A={} \<and> int (card C) \<le> int (card B) - int (card A) \<and> (span (A \<union> C) = span B)"
    by (metis replacement)
  from 2 show ?thesis by arith
qed

text {*The dimension is the cardinality of any basis. (In particular, all bases are the same size.)*}
lemma (in vectorspace) dim_basis:
  fixes A
  assumes  fin: "finite A" and h2: "basis A"
  shows "dim = card A"
proof -
  have 0: "\<And>B m. ((finite B) \<and> (card B = m) \<and> (B \<subseteq> carrier V) \<and> (gen_set B)) \<Longrightarrow> card A \<le> m"
  proof -
    fix B m
    assume 1: "((finite B) \<and> (card B = m) \<and> (B \<subseteq> carrier V) \<and> (gen_set B))"
    from 1 fin h2 have 2: "card A \<le> card B"
      apply (unfold basis_def)
      apply (intro li_smaller_than_gen)
           by auto
    from 1 2 show "?thesis B m" by auto
  qed
  from fin h2 0 show ?thesis
    apply (unfold dim_def basis_def)
    apply (intro Least_equality)
     apply (rule_tac x="A" in exI)
     by auto
qed

(*can define more generally with posets*)
text {*A @{text "maximal"} set with respect to $P$ is such that if $B\supseteq A$ and $P$ is also
satisfied for $B$, then $B=A$.*}
definition maximal::"'a set \<Rightarrow> ('a set \<Rightarrow> bool) \<Rightarrow> bool"
  where "maximal A P = ((P A) \<and> (\<forall>B. B\<supseteq>A \<and> P B \<longrightarrow> B = A))"

text {*A @{text "minimal"} set with respect to $P$ is such that if $B\subseteq A$ and $P$ is also
satisfied for $B$, then $B=A$.*}
definition minimal::"'a set \<Rightarrow> ('a set \<Rightarrow> bool) \<Rightarrow> bool"
  where "minimal A P = ((P A) \<and> (\<forall>B. B\<subseteq>A \<and> P B \<longrightarrow> B = A))"

text {*A maximal linearly independent set is a generating set.*}
lemma (in vectorspace) max_li_is_gen:
  fixes A
  assumes h1: "maximal A (\<lambda>S. S\<subseteq>carrier V \<and> lin_indpt S)"
  shows "gen_set A"
proof (rule ccontr)
  assume 0: "\<not>(gen_set A)"
  from h1 have 1: " A\<subseteq> carrier V \<and> lin_indpt A" by (unfold maximal_def, auto)
  from 1 have 2: "span A \<subseteq> carrier V" by (intro span_is_subset2, auto)
  from 0 1 2 have 3: "\<exists>v. v\<in>carrier V \<and> v \<notin> (span A)"
    by auto
  from 3 obtain v where 4: "v\<in>carrier V \<and> v \<notin> (span A)" by auto
  have 5: "v\<notin>A"
  proof -
    from h1 1 have 51: "A\<subseteq>span A" apply (intro in_own_span) by auto
    from 4 51 show ?thesis by auto
  qed
  from lin_dep_iff_in_span have 6: "\<And>S v. S \<subseteq> carrier V\<and> lin_indpt S \<and> v\<in> carrier V \<and> v\<notin>S
    \<and> v\<notin> span S \<Longrightarrow>  (lin_indpt (S \<union> {v}))" by auto
  from 1 4 5 have 7: "lin_indpt (A \<union> {v})" apply (intro 6) by auto
(*  assumes h0:"finite S" and h1: "S \<subseteq> carrier V" and h2: "lin_indpt S" and h3: "v\<in> carrier V" and h4: "v\<notin>S"
  shows "v\<in> span S \<longleftrightarrow>  \<not> (lin_indpt (S \<union> {v}))"*)
  have 9: "\<not>(maximal A (\<lambda>S. S\<subseteq>carrier V \<and> lin_indpt S))"
  proof -
    from 1 4 5 7 have 8: "(\<exists>B. A \<subseteq> B  \<and> B \<subseteq> carrier V \<and> lin_indpt B \<and> B \<noteq> A)"
      apply (rule_tac x="A\<union>{v}" in exI)
      by auto
    from 8 show ?thesis
      apply (unfold maximal_def)
      by simp
  qed
  from h1 9 show False by auto
qed

text {*A minimal generating set is linearly independent.*}
lemma (in vectorspace) min_gen_is_li:
  fixes A
  assumes h1: "minimal A (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S)"
  shows "lin_indpt A"
proof (rule ccontr)
  assume 0: "\<not>lin_indpt A"
  from h1 have 1: " A\<subseteq> carrier V \<and> gen_set A" by (unfold minimal_def, auto)
  from 1 have 2: "span A = carrier V" by auto
  from 0 1 obtain a v A' where
    3: "finite A' \<and> A'\<subseteq>A \<and> a \<in> A' \<rightarrow> carrier K \<and> LinearCombinations.module.lincomb V a A' = \<zero>\<^bsub>V\<^esub> \<and> v \<in> A' \<and> a v \<noteq> \<zero>\<^bsub>K\<^esub>"
    by (unfold lin_dep_def, auto)
  have 4: "gen_set (A-{v})"
  proof -
    from 1 3 have 5: "v\<in>span (A'-{v})"
      apply (intro lincomb_isolate[where a="a" and v="v"])
           by auto
    from 3 5 have 51: "v\<in>span (A-{v})"
      apply (intro subsetD[where ?A="span (A'-{v})" and ?B="span (A-{v})" and ?c="v"])
       by (intro span_is_monotone, auto)
    from 1 have 6: "A\<subseteq>span A" apply (intro in_own_span) by auto
    from 1 51 have 7: "span (A-{v}) = span ((A-{v})\<union>{v})" apply (intro already_in_span) by auto
    from 3 have 8: "A =  ((A-{v})\<union>{v})" by auto
    from 2 7 8 have 9:"span (A-{v}) = carrier V" by auto (*can't use 3 directly :( *)
    from 9 show ?thesis  by auto
  qed
  have 10: "\<not>(minimal A (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S))"
  proof -
    from 1 3 4 have 11: "(\<exists>B. A \<supseteq> B \<and> B \<subseteq> carrier V \<and> gen_set B \<and> B \<noteq> A)"
      apply (rule_tac x="A-{v}" in exI)
      by auto
    from 11 show ?thesis
      apply (unfold minimal_def)
      by auto
  qed
  from h1 10 show False by auto
qed

text {*Given that some finite set satisfies $P$, there is a minimal set that satisfies $P$.*}
lemma minimal_exists:
  fixes A P
  assumes h1: "finite A" and h2: "P A"
  shows "\<exists>B. B\<subseteq>A \<and> minimal B P"
using h1 h2
proof (induct "card A"  arbitrary: A rule: less_induct)
case (less A)
  show ?case
  proof (cases "card A = 0")
  case True
    from True less.hyps less.prems show ?thesis
      apply (rule_tac x="{}" in exI)
      apply (unfold minimal_def)
      by  auto
  next
  case False
    show ?thesis
    proof (cases "minimal A P")
      case True
        then show ?thesis
          apply (rule_tac x="A" in exI)
          by auto
      next
      case False
        have 2: "\<not>minimal A P" by fact
        from less.prems 2 have 3: "\<exists>B. P B \<and> B \<subseteq> A \<and> B\<noteq>A"
          apply (unfold minimal_def)
          by auto
        from 3 obtain B where 4: "P B \<and> B \<subset> A \<and> B\<noteq>A" by auto
        from 4 have 5: "card B < card A" by (metis less.prems(1) psubset_card_mono)
        from less.hyps less.prems 3 4 5 have 6: "\<exists>C\<subseteq>B. minimal C P"
          apply (intro less.hyps)
            apply auto
          by (metis rev_finite_subset)
        from 6 obtain C where 7: "C\<subseteq>B \<and> minimal C P" by auto
        from 4 7 show ?thesis
          apply (rule_tac x="C" in exI)
          apply (unfold minimal_def)
          by auto
     qed
   qed
qed

text {*If $V$ is finite-dimensional, then any linearly independent set is finite.*}
lemma (in vectorspace) fin_dim_li_fin:
  assumes fd: "fin_dim" and li: "lin_indpt A" and inC: "A\<subseteq>carrier V"
  shows fin: "finite A"
proof (rule ccontr)
  assume A: "\<not>finite A"
  from fd obtain C where C: "finite C \<and> C\<subseteq>carrier V \<and> gen_set C" by (unfold fin_dim_def, auto)
  from A obtain B where B: "B\<subseteq>A\<and> finite B \<and> card B = card C + 1"
    by (metis infinite_arbitrarily_large)
  from B li have liB: "lin_indpt B"
    by (intro subset_li_is_li[where ?A="A" and ?B="B"], auto)
  from B C liB inC have "card B \<le> card C" by (intro li_smaller_than_gen, auto)
  from this B show False by auto
qed

text {*If $V$ is finite-dimensional (has a finite generating set), then a finite basis exists.*}
lemma (in vectorspace) finite_basis_exists:
  assumes h1: "fin_dim"
  shows "\<exists>\<beta>. finite \<beta> \<and> basis \<beta>"
proof -
  from h1 obtain A where 1: "finite A \<and> A\<subseteq>carrier V \<and> gen_set A" by (metis fin_dim_def)
  hence 2: "\<exists>\<beta>. \<beta>\<subseteq>A \<and> minimal \<beta> (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S)"
    apply (intro minimal_exists)
     by auto
  then obtain \<beta> where 3: "\<beta>\<subseteq>A \<and> minimal \<beta> (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S)" by auto
  hence 4: "lin_indpt \<beta>" apply (intro min_gen_is_li) by auto
  moreover from 3 have 5: "gen_set \<beta> \<and> \<beta>\<subseteq>carrier V" apply (unfold minimal_def) by auto
  moreover from 1 3 have 6: "finite \<beta>" by (auto simp add: finite_subset)
  ultimately show ?thesis apply (unfold basis_def) by auto
qed
text{*
The proof is as follows.
\begin{enumerate}
\item Because $V$ is finite-dimensional, there is a finite generating set
(we took this as our definition of finite-dimensional).
\item Hence, there is a minimal $\beta \subseteq A$ such that $\beta$ generates $V$.
\item $\beta$ is linearly independent because a minimal generating set is linearly independent.
\end{enumerate}
Finally, $\beta$ is a basis because it is both generating and linearly independent.
*}

text {*Any linearly independent set has cardinality at most equal to the dimension.*}
lemma (in vectorspace) li_le_dim:
  fixes A
  assumes fd: "fin_dim" and c: "A\<subseteq>carrier V" and l: "lin_indpt A"
  shows "finite A" "card A \<le> dim"
proof  -
  from fd c l show fa: "finite A" by (intro fin_dim_li_fin, auto)
  from fd obtain \<beta> where 1: "finite \<beta> \<and> basis \<beta>"
    by (metis finite_basis_exists)
  from assms fa 1 have 2: "card A \<le> card \<beta>"
    apply (intro li_smaller_than_gen, auto)
      by (unfold basis_def, auto)
  from assms 1 have 3: "dim = card \<beta>" by (intro dim_basis, auto)
  from 2 3 show "card A \<le> dim" by auto
qed

text {*Any generating set has cardinality at least equal to the dimension.*}
lemma (in vectorspace) gen_ge_dim:
  fixes A
  assumes fa: "finite A" and c: "A\<subseteq>carrier V" and l: "gen_set A"
  shows "card A \<ge> dim"
proof  -
  from assms have fd: "fin_dim" by (unfold fin_dim_def, auto)
  from fd obtain \<beta> where 1: "finite \<beta> \<and> basis \<beta>" by (metis finite_basis_exists)
  from assms 1 have 2: "card A \<ge> card \<beta>"
    apply (intro li_smaller_than_gen, auto)
     by (unfold basis_def, auto)
  from assms 1 have 3: "dim = card \<beta>" by (intro dim_basis, auto)
  from 2 3 show ?thesis by auto
qed

text {*If there is an upper bound on the cardinality of sets satisfying $P$, then there is a maximal
set satisfying $P$.*}
lemma maximal_exists:
  fixes P B N
  assumes maxc: "\<And>A. P A \<Longrightarrow> finite A \<and> (card A \<le>N)" and b: "P B"
  shows "\<exists>A. finite A \<and> maximal A P"
proof -
(*take the maximal*)
  let ?S="{card A| A. P A}"
  let ?n="Max ?S"
  from maxc have 1:"finite ?S"
    apply (simp add: finite_nat_set_iff_bounded_le) by auto
  from 1 have 2: "?n\<in>?S"
    by (metis (mono_tags, lifting) Collect_empty_eq Max_in b)
  from assms 2 have 3: "\<exists>A. P A \<and> finite A \<and> card A = ?n"
    by auto
  from 3 obtain A where 4: "P A \<and> finite A \<and> card A = ?n" by auto
  from 1 maxc have 5: "\<And>A. P A \<Longrightarrow> finite A \<and> (card A \<le>?n)"
    by (metis (mono_tags, lifting) Max.coboundedI mem_Collect_eq)
  from 4 5 have 6: "maximal A P"
    apply (unfold maximal_def)
    by (metis card_seteq)
  from 4 6 show ?thesis by auto
qed

text {*Any maximal linearly independent set is a basis.*}
lemma (in vectorspace) max_li_is_basis:
  fixes A
  assumes h1: "maximal A (\<lambda>S. S\<subseteq>carrier V \<and> lin_indpt S)"
  shows "basis A"
proof -
  from h1 have 1: "gen_set A" by (rule max_li_is_gen)
  from assms 1 show ?thesis by (unfold basis_def maximal_def, auto)
qed

text {*Any minimal linearly independent set is a generating set.*}
lemma (in vectorspace) min_gen_is_basis:
  fixes A
  assumes h1: "minimal A (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S)"
  shows "basis A"
proof -
  from h1 have 1: "lin_indpt A" by (rule min_gen_is_li)
  from assms 1 show ?thesis by (unfold basis_def minimal_def, auto)
qed

text {*Any linearly independent set with cardinality at least the dimension is a basis.*}
lemma (in vectorspace) dim_li_is_basis:
  fixes A
  assumes fd: "fin_dim" and fa: "finite A" and ca: "A\<subseteq>carrier V" and li: "lin_indpt A"
    and d: "card A \<ge> dim" (*\<ge>*)
  shows "basis A"
proof -
  from fd have 0: "\<And>S. S\<subseteq>carrier V \<and> lin_indpt S \<Longrightarrow> finite S \<and> card S \<le>dim"
    by (auto intro: li_le_dim)
(*fin_dim_li_fin*)
  from 0 assms have h1:  "finite A \<and> maximal A (\<lambda>S.  S\<subseteq>carrier V \<and> lin_indpt S)"
    apply (unfold maximal_def)
    apply auto
    by (metis card_seteq eq_iff)
  from h1 show ?thesis by (auto intro: max_li_is_basis)
qed

text {*Any generating set with cardinality at most the dimension is a basis.*}
lemma (in vectorspace) dim_gen_is_basis:
  fixes A
  assumes fa: "finite A" and ca: "A\<subseteq>carrier V" and li: "gen_set A"
    and d: "card A \<le> dim"
  shows "basis A"
proof -
  have 0: "\<And>S. finite S\<and> S\<subseteq>carrier V \<and> gen_set S \<Longrightarrow> card S \<ge>dim"
    by (intro gen_ge_dim, auto)
(*li_le_dim*)
  from 0 assms have h1:  "minimal A (\<lambda>S. finite S \<and> S\<subseteq>carrier V \<and> gen_set S)"
    apply (unfold minimal_def)
    apply auto
    by (metis card_seteq eq_iff)
  (*slightly annoying: we have to get rid of "finite S" inside.*)
  from h1 have h: "\<And>B. B \<subseteq> A \<and> B \<subseteq> carrier V \<and> LinearCombinations.module.gen_set K V B \<Longrightarrow> B = A"
  proof -
    fix B
    assume asm: "B \<subseteq> A \<and> B \<subseteq> carrier V \<and> LinearCombinations.module.gen_set K V B"
    from asm h1 have "finite B"
      apply (unfold minimal_def)
       apply (intro finite_subset[where ?A="B" and ?B="A"])
       by auto
    from h1 asm this show "?thesis B" apply (unfold minimal_def) by simp
  qed
  from h1 h have h2: "minimal A (\<lambda>S. S\<subseteq>carrier V \<and> gen_set S)"
    apply (unfold minimal_def)
    by presburger
  from h2 show ?thesis by (rule min_gen_is_basis)
qed

text {*$\beta$ is a basis iff for all $v\in V$, there exists a unique $(a_v)_{v\in S}$ such that
$\sum_{v\in S} a_v v=v$.*}
lemma (in vectorspace) basis_criterion:
  assumes A_fin: "finite A" and AinC: "A\<subseteq>carrier V"
  shows "basis A <-> (\<forall>v. v\<in> carrier V \<longrightarrow>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v))"
proof -
  have 1: "\<not>(\<forall>v.  v\<in> carrier V \<longrightarrow>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v)) \<Longrightarrow> \<not>basis A"
  proof -
    assume "\<not>(\<forall>v.  v\<in> carrier V \<longrightarrow>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v))"
    then obtain v where v: "v\<in> carrier V \<and> \<not>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v)" by metis
    (*either there is more than 1 rep, or no reps*)
    from v have vinC: "v\<in>carrier V" by auto
    from v have "\<not>(\<exists> a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v) \<or>  (\<exists> a b.
      a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v \<and> b\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb b A = v
      \<and> a\<noteq>b)" by metis
    then show ?thesis
    proof
      assume a: "\<not>(\<exists> a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v)"
      from A_fin AinC have "\<And>a. a\<in>A \<rightarrow> carrier K \<Longrightarrow> lincomb a A = lincomb (restrict a A) A"
        unfolding lincomb_def restrict_def
        by (simp cong: finsum_cong add: ring_subset_carrier coeff_in_ring)
      with a have "\<not>(\<exists> a.  a\<in>A \<rightarrow> carrier K \<and> lincomb a A = v)" by auto
      with A_fin AinC have "v\<notin>span A"
        using finite_in_span by blast
      with AinC v show "\<not>(basis A)" by (unfold basis_def, auto)
    next
      assume a2: "(\<exists> a b.
        a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v \<and> b\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb b A = v
        \<and> a\<noteq>b)"
      then obtain a b where ab: "a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v \<and> b\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb b A = v
        \<and> a\<noteq>b" by metis
      from ab obtain w where w: "w\<in>A \<and> a w \<noteq> b w" apply (unfold PiE_def, auto)
        by (metis extensionalityI)
      let ?c="\<lambda> x. (if x\<in>A then ((a x) \<ominus>\<^bsub>K\<^esub> (b x)) else undefined)"
      from ab have a_fun: "a\<in>A \<rightarrow> carrier K"
               and b_fun: "b\<in>A \<rightarrow> carrier K"
        by (unfold PiE_def, auto)
      from w a_fun b_fun have abinC: "a w \<in>carrier K" "b w \<in>carrier K" by auto

      from abinC w have nz: "a w \<ominus>\<^bsub>K\<^esub> b w \<noteq> \<zero>\<^bsub>K\<^esub>"
        by auto (*uses M.minus_other_side*)
      from A_fin AinC a_fun b_fun ab vinC have a_b:
      "LinearCombinations.module.lincomb V (\<lambda>x. if x \<in> A then a x \<ominus>\<^bsub>K\<^esub> b x else undefined) A = \<zero>\<^bsub>V\<^esub>"
        by (simp cong: lincomb_cong add: coeff_in_ring lincomb_diff)
      from A_fin AinC ab w v nz a_b have "lin_dep A"
        apply (intro lin_dep_crit[where ?A="A" and ?a="?c" and ?v="w"])
             apply (auto simp add: PiE_def)
        by auto
      thus "\<not>basis A" by (unfold basis_def, auto)
    qed
  qed
  have 2: "(\<forall>v. v\<in> carrier V \<longrightarrow>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v)) \<Longrightarrow> basis A"
  proof -
    assume b1: "(\<forall>v. v\<in> carrier V \<longrightarrow>(\<exists>! a.  a\<in>A \<rightarrow>\<^sub>E carrier K \<and> lincomb a A = v))"
      (is "(\<forall>v. v\<in> carrier V \<longrightarrow>(\<exists>! a.  ?Q a v))")
    from b1 have b2: "(\<forall>v.  v\<in> carrier V \<longrightarrow>(\<exists> a.  a\<in>A \<rightarrow> carrier K \<and> lincomb a A = v))"
      apply (unfold PiE_def)
      by blast
    from A_fin AinC b2 have "gen_set A"
      apply (unfold span_def)
      by blast
    from b1 have A_li: "lin_indpt A"
    proof -
      let ?z="\<lambda> x. (if (x\<in>A) then \<zero>\<^bsub>K\<^esub> else undefined)"
      from A_fin AinC have zero: "?Q ?z \<zero>\<^bsub>V\<^esub>"
        by (unfold PiE_def extensional_def lincomb_def, auto simp add: ring_subset_carrier)
        (*uses finsum_all0*)
      from A_fin AinC show ?thesis
      proof (rule finite_lin_indpt2)
        fix a
        assume a_fun: "a \<in> A \<rightarrow> carrier K" and
          lc_a: "LinearCombinations.module.lincomb V a A = \<zero>\<^bsub>V\<^esub>"
        from a_fun have a_res: "restrict a A \<in> A \<rightarrow>\<^sub>E carrier K" by auto
        from a_fun A_fin AinC lc_a have
          lc_a_res: "LinearCombinations.module.lincomb V (restrict a A) A = \<zero>\<^bsub>V\<^esub>"
          apply (unfold lincomb_def restrict_def)
          by (simp cong: finsum_cong2 add: coeff_in_ring ring_subset_carrier)
        from a_fun a_res lc_a_res zero b1 have "restrict a A = ?z" by auto
        from this show "\<forall>v\<in>A. a v = \<zero>\<^bsub>K\<^esub>"
          apply (unfold restrict_def)
          by meson
      qed
    qed
    have A_gen: "gen_set A"
    proof -
      from AinC have dir1: "span A\<subseteq>carrier V" by (rule span_is_subset2)
      have dir2: "carrier V\<subseteq>span A"
      proof (auto)
        fix v
        assume v: "v\<in>carrier V"
        from v b2 obtain a where "a\<in>A \<rightarrow> carrier K \<and> lincomb a A = v" by auto
        from this A_fin AinC show "v\<in>span A" by (subst finite_span, auto)
      qed
      from dir1 dir2 show ?thesis by auto
    qed
    from A_li A_gen AinC show "basis A" by (unfold basis_def, auto)
  qed
  from 1 2 show ?thesis by satx
qed

subsection {* The rank-nullity (dimension) theorem*}

text {*If $V$ is finite-dimensional and $T:V\to W$ is a linear map, then $\text{dim}(\text{im}(T))+
\text{dim}(\text{ker}(T)) = \text{dim} V$.*}
theorem (in linear_map) rank_nullity:
  assumes fd: "V.fin_dim"
  shows "(vectorspace.dim K (W.vs imT)) + (vectorspace.dim K (V.vs kerT)) = V.dim"
proof -
  -- "First interpret kerT, imT as vectorspaces"
  have subs_ker: "subspace K kerT V" by (intro kerT_is_subspace)
  from subs_ker have vs_ker: "vectorspace K (V.vs kerT)" by (rule V.subspace_is_vs)
  from vs_ker interpret ker: vectorspace K "(V.vs kerT)" by auto
  have kerInC: "kerT\<subseteq>carrier V" by (unfold ker_def, auto)

  have subs_im: "subspace K imT W" by (intro imT_is_subspace)
  from subs_im have vs_im: "vectorspace K (W.vs imT)" by (rule W.subspace_is_vs)
  from vs_im interpret im: vectorspace K "(W.vs imT)" by auto
  have imInC: "imT\<subseteq>carrier W" by (unfold im_def, auto)
  (* obvious fact *)
  have zero_same[simp]: "\<zero>\<^bsub>V.vs kerT\<^esub> = \<zero>\<^bsub>V\<^esub>" apply (unfold ker_def) by auto
  -- "Show ker T has a finite basis. This is not obvious. Show that any linearly independent set
has size at most that of V. There exists a maximal linearly independent set, which is the basis."
  have every_li_small: "\<And>A. (A \<subseteq> kerT)\<and> ker.lin_indpt A \<Longrightarrow>
    finite A \<and> card A \<le> V.dim"
  proof -
    fix A
    assume eli_asm: "(A \<subseteq> kerT)\<and> ker.lin_indpt A"
    (*annoying: I can't just use subst V.module.span_li_not_depend(2) in the show ?thesis
    statement because it doesn't appear in the conclusion.*)
    note V.module.span_li_not_depend(2)[where ?N="kerT" and ?S="A"]
    from this subs_ker fd eli_asm kerInC show "?thesis A"
      apply (intro conjI)
       by (auto intro!: V.li_le_dim)
  qed
  from every_li_small have exA:
    "\<exists>A. finite A \<and> maximal A (\<lambda>S. S\<subseteq>carrier (V.vs kerT) \<and> ker.lin_indpt S)"
    apply (intro maximal_exists[where ?N="V.dim" and ?B="{}"])
     apply auto
    by (unfold ker.lin_dep_def, auto)
  from exA obtain A where A:" finite A \<and> maximal A (\<lambda>S. S\<subseteq>carrier (V.vs kerT) \<and> ker.lin_indpt S)"
    by blast
  hence finA: "finite A" and Ainker: "A\<subseteq>carrier (V.vs kerT)" and AinC: "A\<subseteq>carrier V"
    by (unfold maximal_def ker_def, auto)
  --"We obtain the basis A of kerT. It is also linearly independent when considered in V rather
than kerT"
  from A have Abasis: "ker.basis A"
    by (intro ker.max_li_is_basis, auto)
  from subs_ker Abasis have spanA: "V.module.span A = kerT"
    apply (unfold ker.basis_def)
    by (subst sym[OF V.module.span_li_not_depend(1)[where ?N="kerT"]], auto)
  from Abasis have Akerli: "ker.lin_indpt A"
    apply (unfold ker.basis_def)
    by auto
  from subs_ker Ainker Akerli have Ali: "V.module.lin_indpt A"
    by (auto simp add: V.module.span_li_not_depend(2))
  txt{* Use the replacement theorem to find C such that $A\cup C$ is a basis of V.*}
  from fd obtain B where B: "finite B\<and> V.basis B" by (metis V.finite_basis_exists)
  from B have Bfin: "finite B" and Bbasis:"V.basis B" by auto
  from B have Bcard: "V.dim = card B" by (intro V.dim_basis, auto)
  from Bbasis have 62: "V.module.span B = carrier V"
    by (unfold V.basis_def, auto)
  from A Abasis Ali B vs_ker have "\<exists>C. finite C \<and> C\<subseteq>carrier V \<and> C\<subseteq> V.module.span B \<and> C\<inter>A={}
      \<and> int (card C) \<le> (int (card B)) - (int (card A)) \<and> (V.module.span (A \<union> C) = V.module.span B)"
    apply (intro V.replacement)
    apply (unfold vectorspace.basis_def V.basis_def)
      by (unfold ker_def, auto)
  txt {* From replacement we got $|C|\leq |B|-|A|$. Equality must actually hold, because no generating set
can be smaller than $B$. Now $A\cup C$ is a maximal generating set, hence a basis; its cardinality
equals the dimension. *}
  txt {* We claim that $T(C)$ is basis for $\text{im}(T)$.*}
  then obtain C where C: "finite C \<and> C\<subseteq>carrier V \<and> C\<subseteq> V.module.span B \<and> C\<inter>A={}
    \<and> int (card C) \<le> (int (card B)) - (int (card A)) \<and> (V.module.span (A \<union> C) = V.module.span B)" by auto
  hence Cfin: "finite C" and CinC: "C\<subseteq>carrier V" and CinspanB: " C\<subseteq>V.module.span B" and CAdis: "C\<inter>A={}"
    and Ccard: "int (card C) \<le> (int (card B)) - (int (card A))"
    and ACspanB: "(V.module.span (A \<union> C) = V.module.span B)" by auto
  from C have cardLe: "card A + card C \<le> card B" by auto
  from B C have ACgen: "V.module.gen_set (A\<union>C)" apply (unfold V.basis_def) by auto
  from finA C ACgen AinC B have cardGe: "card (A\<union>C) \<ge> card B" by (intro V.li_smaller_than_gen, unfold V.basis_def, auto)
  from finA C have cardUn: "card (A\<union>C)\<le>  card A + card C"
    by (metis Int_commute card_Un_disjoint le_refl)
  from cardLe cardUn cardGe Bcard have cardEq:
    "card (A\<union>C) = card A + card C"
    "card (A\<union>C) = card B"
    "card (A\<union>C) = V.dim"
    by auto
  from Abasis C cardEq have disj: "A\<inter>C={}" by auto
  from finA AinC C cardEq 62 have ACfin: "finite (A\<union>C)" and ACbasis: "V.basis (A\<union>C)"
    by (auto intro!: V.dim_gen_is_basis)
  have lm: "linear_map K V W T"..
  txt {*Let $C'$ be the image of $C$ under $T$. We will show $C'$ is a basis for $\text{im}(T)$.*}
  let ?C' = "T`C"
  from Cfin have C'fin: "finite ?C'" by auto
  from AinC C have cim: "?C'\<subseteq>imT" by (unfold im_def, auto)

  txt {* "There is a subtle detail: we first have to show $T$ is injective on $C$.*}
  txt {*We establish that no nontrivial linear combination of $C$ can have image 0 under $T$,
because that would mean it is a linear combination of $A$, giving that $A\cup C$ is linearly dependent,
contradiction. We use this result in 2 ways: (1) if $T$ is not injective on $C$, then we obtain $v$, $w\in C$
such that $v-w$ is in the kernel, contradiction, (2) if $T(C)$ is linearly dependent,
taking the inverse image of that linear combination gives a linear combination of $C$ in the kernel,
contradiction. Hence $T$ is injective on $C$ and $T(C)$ is linearly independent.*}
  have lc_in_ker: "\<And>d D v. \<lbrakk>D\<subseteq>C; d\<in>D\<rightarrow>carrier K; T (V.module.lincomb d D) = \<zero>\<^bsub>W\<^esub>;
    v\<in>D; d v \<noteq>\<zero>\<^bsub>K\<^esub>\<rbrakk>\<Longrightarrow>False"
  proof -
    fix d D v
    assume D: "D\<subseteq>C" and d: "d\<in>D\<rightarrow>carrier K" and T0: "T (V.module.lincomb d D) = \<zero>\<^bsub>W\<^esub>"
      and v: "v\<in>D" and dvnz: "d v \<noteq>\<zero>\<^bsub>K\<^esub>"
    from D Cfin have Dfin: "finite D"  by (auto intro: finite_subset)
    from D CinC have DinC: "D\<subseteq>carrier V" by auto
    from T0 d Dfin DinC have lc_d: "V.module.lincomb d D\<in>kerT"
      by (unfold ker_def, auto)
    from lc_d spanA AinC have  "\<exists>a' A'. A'\<subseteq>A \<and> a'\<in>A'\<rightarrow>carrier K \<and>
       V.module.lincomb a' A'= V.module.lincomb d D"
      by (intro V.module.in_span, auto)
    then obtain a' A' where a': "A'\<subseteq>A \<and> a'\<in>A'\<rightarrow>carrier K \<and>
      V.module.lincomb d D = V.module.lincomb a' A'"
      by metis
    hence  A'sub: "A'\<subseteq>A" and a'fun: "a'\<in>A'\<rightarrow>carrier K"
      and a'_lc:"V.module.lincomb d D = V.module.lincomb a' A'"  by auto
    from a' finA Dfin have A'fin: "finite (A')"  by (auto intro: finite_subset)
    from AinC A'sub have A'inC: "A'\<subseteq>carrier V" by auto
    let ?e = "(\<lambda>v. if v \<in> A' then a' v else \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<otimes>\<^bsub>K\<^esub> d v)"
    from a'fun d have e_fun: "?e \<in> A' \<union> D \<rightarrow> carrier K"
      apply (unfold Pi_def)
      by auto
    from
      A'fin Dfin (*finiteness*)
      A'inC DinC (*in carrier*)
      a'fun d e_fun (*coefficients valid*)
      disj D A'sub (*A and C disjoint*)
    have lccomp1:
      "V.module.lincomb a' A' \<oplus>\<^bsub>V\<^esub> \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<odot>\<^bsub>V\<^esub> V.module.lincomb d D =
        V.module.lincomb (\<lambda>v. if v\<in>A' then a' v else \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<otimes>\<^bsub>K\<^esub> d v) (A'\<union>D)"
      apply (subst sym[OF V.module.lincomb_smult])
          apply (simp_all)
      apply (subst V.module.lincomb_union2)
           by (auto)
    from
      A'fin (*finiteness*)
      A'inC (*in carrier*)
      a'fun (*coefficients valid*)
    have lccomp2:
      "V.module.lincomb a' A' \<oplus>\<^bsub>V\<^esub> \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<odot>\<^bsub>V\<^esub> V.module.lincomb d D =
      \<zero>\<^bsub>V\<^esub>"
      by (simp add: a'_lc
        V.module.smult_minus_1  V.module.M.r_neg)
    from lccomp1 lccomp2 have lc0: "V.module.lincomb (\<lambda>v. if v\<in>A' then a' v else \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<otimes>\<^bsub>K\<^esub> d v) (A'\<union>D)
      =\<zero>\<^bsub>V\<^esub>" by auto
    from disj a' v D have v_nin: "v\<notin>A'" by auto
    from A'fin Dfin (*finiteness*)
      A'inC DinC (*in carrier*)
      e_fun d (*coefficients valid*)
      A'sub D disj (*A' D are disjoint subsets*)
      v dvnz (*d v is nonzero coefficient*)
      lc0
    have AC_ld: "V.module.lin_dep (A\<union>C)"
      apply (intro V.module.lin_dep_crit[where ?A="A'\<union>D" and
        ?S="A\<union>C" and ?a="\<lambda>v. if v\<in>A' then a' v else \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>\<otimes>\<^bsub>K\<^esub> d v" and ?v="v"])
           by (auto dest: integral)
    from AC_ld ACbasis show False by (unfold V.basis_def, auto)
  qed
  have C'_card: "inj_on T C" "card C = card ?C'"
  proof -
    show "inj_on T C"
    proof (rule ccontr)
      assume "\<not>inj_on T C"
      then obtain v w where "v\<in>C" "w\<in>C" "v\<noteq>w" "T v = T w" by (unfold inj_on_def, auto)
      from this CinC show False
        apply (intro lc_in_ker[where ?D="{v,w}" and ?d="\<lambda>x. if x=v then \<one>\<^bsub>K\<^esub> else \<ominus>\<^bsub>K\<^esub>\<one>\<^bsub>K\<^esub>"
          and ?v="v"])
            by (auto simp add: V.module.lincomb_def hom_sum ring_subset_carrier
              W.module.smult_minus_1 r_neg T_im)
    qed
    from this Cfin show "card C = card ?C'"
      by (metis card_image)
  qed
  let ?f="the_inv_into C T"
  have f: "\<And>x. x\<in>C \<Longrightarrow> ?f (T x) = x" "\<And>y. y\<in>?C' \<Longrightarrow> T (?f y) = y"
    apply (insert C'_card(1))
     apply (metis the_inv_into_f_f)
    by (metis f_the_inv_into_f)
(*We show C' is a basis for the image. First we show it is linearly independent.*)
  have C'_li: "im.lin_indpt ?C'"
  proof (rule ccontr)
    assume Cld: "\<not>im.lin_indpt ?C'"
    from Cld cim subs_im have CldW: "W.module.lin_dep ?C'"
      apply (subst sym[OF W.module.span_li_not_depend(2)[where ?S="T`C" and ?N="imT"]])
        by auto
    from C CldW have "\<exists>c' v'. (c'\<in> (?C'\<rightarrow>carrier K)) \<and> (W.module.lincomb c' ?C' = \<zero>\<^bsub>W\<^esub>)
      \<and> (v'\<in>?C') \<and> (c' v'\<noteq> \<zero>\<^bsub>K\<^esub>)" by (intro W.module.finite_lin_dep, auto)
    then obtain c' v' where c': "(c'\<in> (?C'\<rightarrow>carrier K)) \<and> (W.module.lincomb c' ?C' = \<zero>\<^bsub>W\<^esub>)
      \<and> (v'\<in>?C') \<and> (c' v'\<noteq> \<zero>\<^bsub>K\<^esub>)" by auto
    hence c'fun: "(c'\<in> (?C'\<rightarrow>carrier K))" and c'lc: "(W.module.lincomb c' ?C' = \<zero>\<^bsub>W\<^esub>)" and
      v':"(v'\<in>?C')" and cvnz: "(c' v'\<noteq> \<zero>\<^bsub>K\<^esub>)" by auto
(*can't get c' directly with metis/auto with W.module.finite_lin_dep*)
    txt {*We take the inverse image of $C'$ under $T$ to get a linear combination of $C$ that is
in the kernel and hence a linear combination of $A$. This contradicts $A\cup C$ being linearly
independent. *}
    let ?c="\<lambda>v. c' (T v)"
    from c'fun have c_fun: "?c\<in> C\<rightarrow>carrier K" by auto
    from Cfin (*C finite*)
      c_fun c'fun (*coefficients valid*)
      C'_card (*bijective*)
      CinC (*C in carrier*)
      f (*inverse to T*)
      c'lc (*lc c' = 0*)
    have "T (V.module.lincomb ?c C) = \<zero>\<^bsub>W\<^esub>"
      apply (unfold V.module.lincomb_def W.module.lincomb_def)
      apply (subst hom_sum, auto)
      apply (simp cong: finsum_cong add: ring_subset_carrier coeff_in_ring)
      apply (subst finsum_reindex[where ?f="\<lambda>w. c' w \<odot>\<^bsub>W\<^esub> w" and ?h="T" and ?A="C", THEN sym])
         by auto
    with f c'fun cvnz v' show False
      by (intro lc_in_ker[where ?D="C" and ?d="?c" and ?v="?f v'"], auto)
  qed
  have C'_gen: "im.gen_set ?C'"
  proof -
    have C'_span: "span ?C' = imT"
    proof (rule equalityI)
      from cim subs_im show "W.module.span ?C' \<subseteq> imT"
        by (intro span_is_subset, unfold subspace_def, auto)
    next
      show "imT\<subseteq>W.module.span ?C'"
      proof (auto)
        fix w
        assume w: "w\<in>imT"
        from this finA Cfin AinC CinC obtain v where v_inC: "v\<in>carrier V" and w_eq_T_v: "w= T v"
          by (unfold im_def image_def, auto)
        from finA Cfin AinC CinC v_inC ACgen have "\<exists>a.  a \<in> A\<union>C \<rightarrow> carrier K\<and> V.module.lincomb a (A\<union>C) = v"
          by (intro V.module.finite_in_span, auto)
        then obtain a where
          a_fun: "a \<in> A\<union>C \<rightarrow> carrier K" and
          lc_a_v: "v= V.module.lincomb a (A\<union>C)"
          by auto
        let ?a'="\<lambda>v. a (?f v)"
        from finA Cfin AinC CinC a_fun disj Ainker f C'_card have Tv: "T v = W.module.lincomb ?a' ?C'"
          apply (subst lc_a_v)
          apply (subst V.module.lincomb_union, simp_all) (*Break up the union A\<union>C*)
          apply (unfold lincomb_def V.module.lincomb_def)
          apply (subst hom_sum, auto) (*Take T inside the sum over A*)
          apply (simp add: subsetD coeff_in_ring
            hom_sum (*Take T inside the sum over C*)
            T_ker (*all terms become 0 because the vectors are in the kernel.*)
            )
          apply (subst finsum_reindex[where ?h="T" and ?f="\<lambda>v. ?a' v\<odot>\<^bsub>W\<^esub> v"], auto)
           by (auto cong: finsum_cong simp add: coeff_in_ring ring_subset_carrier)
        from a_fun f have a'_fun: "?a'\<in>?C' \<rightarrow> carrier K" by auto
        from C'fin CinC this w_eq_T_v a'_fun Tv show "w \<in> LinearCombinations.module.span K W (T ` C)"
          by (subst finite_span, auto)
      qed
    qed
    from this subs_im CinC show ?thesis
      apply (subst span_li_not_depend(1))
        by (unfold im_def subspace_def, auto)
  qed
  from C'_li C'_gen C cim have C'_basis: "im.basis  (T`C)"
    by (unfold im.basis_def, auto)
  have C_card_im: "card C = (vectorspace.dim K (W.vs imT))"
    using C'_basis C'_card(2) C'fin im.dim_basis by auto
  from finA Abasis have  "ker.dim = card A" by (rule ker.dim_basis)
  with C_card_im cardEq show ?thesis by auto
qed

end


theory Prelude_Bounded
imports "$HETS_LIB/Isabelle/MainHC"
uses "$HETS_LIB/Isabelle/prelude"
begin

ML "Header.initialize
    [\"Ax1\", \"Ax2\", \"Ax3\", \"Ax4\", \"NotFalse\", \"NotTrue\",
     \"AndFalse\", \"AndTrue\", \"AndSym\", \"OrDef\", \"OtherwiseDef\",
     \"NotFalse1\", \"NotTrue1\", \"notNot1\", \"notNot2\",
     \"EqualTDef\", \"EqualSymDef\", \"EqualReflex\", \"EqualTransT\",
     \"DiffDef\", \"DiffTDef\", \"DiffFDef\", \"TE1\", \"TE2\", \"TE3\",
     \"TE4\", \"IBE1\", \"IBE2\", \"IBE3\", \"IBE4\", \"IBE5\",
     \"IBE6\", \"IBE7\", \"IBE8\", \"IUE1\", \"IUE2\", \"IOE01\",
     \"IOE02\", \"IOE03\", \"IOE04\", \"IOE05\", \"IOE06\", \"IOE07\",
     \"IOE08\", \"IOE09\", \"LeIrreflexivity\", \"LeTAsymmetry\",
     \"LeTTransitive\", \"LeTTotal\", \"GeDef\", \"GeIrreflexivity\",
     \"GeTAsymmetry\", \"GeTTransitive\", \"GeTTotal\", \"LeqDef\",
     \"LeqReflexivity\", \"LeqTTransitive\", \"LeqTTotal\", \"GeqDef\",
     \"GeqReflexivity\", \"GeqTTransitive\", \"GeqTTotal\",
     \"EqTSOrdRel\", \"EqFSOrdRel\", \"EqTOrdRel\", \"EqFOrdRel\",
     \"LeTGeTRel\", \"LeFGeFRel\", \"LeqTGetTRel\", \"LeqFGetFRel\",
     \"GeTLeTRel\", \"GeFLeFRel\", \"GeqTLeqTRel\", \"GeqFLeqFRel\",
     \"LeTGeFEqFRel\", \"LeFGeTEqTRel\", \"LeqTGeFRel\", \"LeqFGeTRel\",
     \"GeTLeFEqFRel\", \"GeFLeTEqTRel\", \"GeqTLeFRel\", \"GeqFLeTRel\",
     \"LeqTLeTEqTRel\", \"LeqFLeFEqFRel\", \"GeqTGeTEqTRel\",
     \"GeqFGeFEqFRel\", \"LeTGeqFRel\", \"GeTLeqFRel\", \"LeLeqDiff\",
     \"LeLtDef\", \"LeEqDef\", \"LeGtDef\", \"LqLtDef\", \"LqEqDef\",
     \"LqGtDef\", \"GeLtDef\", \"GeEqDef\", \"GeGtDef\", \"GqLtDef\",
     \"GqEqDef\", \"GqGtDef\", \"MaxYDef\", \"MaxXDef\", \"MinXDef\",
     \"MinYDef\", \"MaxSym\", \"MinSym\", \"TO1\", \"TO2\", \"TO3\",
     \"TO4\", \"TO5\", \"TO6\", \"TO7\", \"IOO13\", \"IOO14\",
     \"IOO15\", \"IOO16\", \"IOO17\", \"IOO18\", \"IOO19\", \"IOO20\",
     \"IOO21\", \"IOO22\", \"IOO23\", \"IOO24\", \"IOO25\", \"IOO26\",
     \"IOO27\", \"IOO28\", \"IOO29\", \"IOO30\", \"IOO31\", \"IOO32\",
     \"IOO33\", \"IBO5\", \"IBO6\", \"IBO7\", \"IBO8\", \"IBO9\",
     \"IBO10\", \"IBO11\", \"IBO12\", \"IUO01\", \"IUO02\", \"IUO03\",
     \"IUO04\", \"IUO05\", \"IUO06\", \"IUO07\"]"

typedecl Nat
typedecl Unit

datatype Bool = X_False ("False''") | X_True ("True''")
datatype Ordering = EQ | GT | LT

consts
Not__X :: "Bool => Bool" ("(Not''/ _)" [56] 56)
X__XAmpXAmp__X :: "Bool => Bool => Bool" ("(_/ &&/ _)" [54,54] 52)
X__XEqXEq__X :: "'a => 'a => Bool" ("(_/ ==''/ _)" [54,54] 52)
X__XGtXEq__X :: "'a => 'a => Bool" ("(_/ >=''/ _)" [54,54] 52)
X__XGt__X :: "'a => 'a => Bool" ("(_/ >''/ _)" [54,54] 52)
X__XLtXEq__X :: "'a => 'a => Bool" ("(_/ <=''/ _)" [54,54] 52)
X__XLt__X :: "'a => 'a => Bool" ("(_/ <''/ _)" [54,54] 52)
X__XSlashXEq__X :: "'a => 'a => Bool" ("(_/ '/=/ _)" [54,54] 52)
X__XVBarXVBar__X :: "Bool => Bool => Bool" ("(_/ ||/ _)" [54,54] 52)
X_max :: "'a => 'a => 'a"
X_min :: "'a => 'a => 'a"
compare :: "'a => 'a => Ordering"
maxBound :: "'a"
minBound :: "'a"
otherwiseH :: "Bool"

instance Bool:: type ..
instance Nat:: type ..
instance Ordering:: type ..
instance Unit:: type ..

axioms
NotFalse [rule_format] : "Not' False' = True'"

NotTrue [rule_format] : "Not' True' = False'"

AndFalse [rule_format] : "ALL x. False' && x = False'"

AndTrue [rule_format] : "ALL x. True' && x = x"

AndSym [rule_format] : "ALL x. ALL y. x && y = y && x"

OrDef [rule_format] :
"ALL x. ALL y. x || y = Not' (Not' x && Not' y)"

OtherwiseDef [rule_format] : "otherwiseH = True'"

NotFalse1 [rule_format] : "ALL x. Not' x = True' = (x = False')"

NotTrue1 [rule_format] : "ALL x. Not' x = False' = (x = True')"

notNot1 [rule_format] : "ALL x. (~ x = True') = (Not' x = True')"

notNot2 [rule_format] : "ALL x. (~ x = False') = (Not' x = False')"

EqualTDef [rule_format] : "ALL x. ALL y. x = y --> x ==' y = True'"

EqualSymDef [rule_format] : "ALL x. ALL y. x ==' y = y ==' x"

EqualReflex [rule_format] : "ALL x. x ==' x = True'"

EqualTransT [rule_format] :
"ALL x.
 ALL y.
 ALL z. x ==' y = True' & y ==' z = True' --> x ==' z = True'"

DiffDef [rule_format] : "ALL x. ALL y. x /= y = Not' (x ==' y)"

DiffTDef [rule_format] :
"ALL x. ALL y. x /= y = True' = (Not' (x ==' y) = True')"

DiffFDef [rule_format] :
"ALL x. ALL y. x /= y = False' = (x ==' y = True')"

TE1 [rule_format] : "ALL x. ALL y. x ==' y = False' --> ~ x = y"

TE2 [rule_format] :
"ALL x. ALL y. Not' (x ==' y) = True' = (x ==' y = False')"

TE3 [rule_format] :
"ALL x. ALL y. Not' (x ==' y) = False' = (x ==' y = True')"

TE4 [rule_format] :
"ALL x. ALL y. (~ x ==' y = True') = (x ==' y = False')"

IBE1 [rule_format] : "True' ==' True' = True'"

IBE2 [rule_format] : "False' ==' False' = True'"

IBE3 [rule_format] : "False' ==' True' = False'"

IBE4 [rule_format] : "True' ==' False' = False'"

IBE5 [rule_format] : "True' /= False' = True'"

IBE6 [rule_format] : "False' /= True' = True'"

IBE7 [rule_format] : "Not' (True' ==' False') = True'"

IBE8 [rule_format] : "Not' Not' (True' ==' False') = False'"

IUE1 [rule_format] : "() ==' () = True'"

IUE2 [rule_format] : "() /= () = False'"

IOE01 [rule_format] : "LT ==' LT = True'"

IOE02 [rule_format] : "EQ ==' EQ = True'"

IOE03 [rule_format] : "GT ==' GT = True'"

IOE04 [rule_format] : "LT ==' EQ = False'"

IOE05 [rule_format] : "LT ==' GT = False'"

IOE06 [rule_format] : "EQ ==' GT = False'"

IOE07 [rule_format] : "LT /= EQ = True'"

IOE08 [rule_format] : "LT /= GT = True'"

IOE09 [rule_format] : "EQ /= GT = True'"

LeIrreflexivity [rule_format] :
"ALL x. ALL y. x ==' y = True' --> x <' y = False'"

LeTAsymmetry [rule_format] :
"ALL x. ALL y. x <' y = True' --> y <' x = False'"

LeTTransitive [rule_format] :
"ALL x.
 ALL y. ALL z. x <' y = True' & y <' z = True' --> x <' z = True'"

LeTTotal [rule_format] :
"ALL x. ALL y. (x <' y = True' | y <' x = True') | x ==' y = True'"

GeDef [rule_format] : "ALL x. ALL y. x >' y = y <' x"

GeIrreflexivity [rule_format] :
"ALL x. ALL y. x ==' y = True' --> x >' y = False'"

GeTAsymmetry [rule_format] :
"ALL x. ALL y. x >' y = True' --> y >' x = False'"

GeTTransitive [rule_format] :
"ALL x.
 ALL y. ALL z. (x >' y) && (y >' z) = True' --> x >' z = True'"

GeTTotal [rule_format] :
"ALL x. ALL y. ((x >' y) || (y >' x)) || (x ==' y) = True'"

LeqDef [rule_format] :
"ALL x. ALL y. x <=' y = (x <' y) || (x ==' y)"

LeqReflexivity [rule_format] : "ALL x. x <=' x = True'"

LeqTTransitive [rule_format] :
"ALL x.
 ALL y. ALL z. (x <=' y) && (y <=' z) = True' --> x <=' z = True'"

LeqTTotal [rule_format] :
"ALL x. ALL y. (x <=' y) && (y <=' x) = x ==' y"

GeqDef [rule_format] :
"ALL x. ALL y. x >=' y = (x >' y) || (x ==' y)"

GeqReflexivity [rule_format] : "ALL x. x >=' x = True'"

GeqTTransitive [rule_format] :
"ALL x.
 ALL y. ALL z. (x >=' y) && (y >=' z) = True' --> x >=' z = True'"

GeqTTotal [rule_format] :
"ALL x. ALL y. (x >=' y) && (y >=' x) = x ==' y"

EqTSOrdRel [rule_format] :
"ALL x.
 ALL y. x ==' y = True' = (x <' y = False' & x >' y = False')"

EqFSOrdRel [rule_format] :
"ALL x.
 ALL y. x ==' y = False' = (x <' y = True' | x >' y = True')"

EqTOrdRel [rule_format] :
"ALL x.
 ALL y. x ==' y = True' = (x <=' y = True' & x >=' y = True')"

EqFOrdRel [rule_format] :
"ALL x.
 ALL y. x ==' y = False' = (x <=' y = True' | x >=' y = True')"

LeTGeTRel [rule_format] :
"ALL x. ALL y. x <' y = True' = (y >' x = True')"

LeFGeFRel [rule_format] :
"ALL x. ALL y. x <' y = False' = (y >' x = False')"

LeqTGetTRel [rule_format] :
"ALL x. ALL y. x <=' y = True' = (y >=' x = True')"

LeqFGetFRel [rule_format] :
"ALL x. ALL y. x <=' y = False' = (y >=' x = False')"

GeTLeTRel [rule_format] :
"ALL x. ALL y. x >' y = True' = (y <' x = True')"

GeFLeFRel [rule_format] :
"ALL x. ALL y. x >' y = False' = (y <' x = False')"

GeqTLeqTRel [rule_format] :
"ALL x. ALL y. x >=' y = True' = (y <=' x = True')"

GeqFLeqFRel [rule_format] :
"ALL x. ALL y. x >=' y = False' = (y <=' x = False')"

LeTGeFEqFRel [rule_format] :
"ALL x.
 ALL y. x <' y = True' = (x >' y = False' & x ==' y = False')"

LeFGeTEqTRel [rule_format] :
"ALL x.
 ALL y. x <' y = False' = (x >' y = True' | x ==' y = True')"

LeqTGeFRel [rule_format] :
"ALL x. ALL y. x <=' y = True' = (x >' y = False')"

LeqFGeTRel [rule_format] :
"ALL x. ALL y. x <=' y = False' = (x >' y = True')"

GeTLeFEqFRel [rule_format] :
"ALL x.
 ALL y. x >' y = True' = (x <' y = False' & x ==' y = False')"

GeFLeTEqTRel [rule_format] :
"ALL x.
 ALL y. x >' y = False' = (x <' y = True' | x ==' y = True')"

GeqTLeFRel [rule_format] :
"ALL x. ALL y. x >=' y = True' = (x <' y = False')"

GeqFLeTRel [rule_format] :
"ALL x. ALL y. x >=' y = False' = (x <' y = True')"

LeqTLeTEqTRel [rule_format] :
"ALL x.
 ALL y. x <=' y = True' = (x <' y = True' | x ==' y = True')"

LeqFLeFEqFRel [rule_format] :
"ALL x.
 ALL y. x <=' y = False' = (x <' y = False' & x ==' y = False')"

GeqTGeTEqTRel [rule_format] :
"ALL x.
 ALL y. x >=' y = True' = (x >' y = True' | x ==' y = True')"

GeqFGeFEqFRel [rule_format] :
"ALL x.
 ALL y. x >=' y = False' = (x >' y = False' & x ==' y = False')"

LeTGeqFRel [rule_format] :
"ALL x. ALL y. x <' y = True' = (x >=' y = False')"

GeTLeqFRel [rule_format] :
"ALL x. ALL y. x >' y = True' = (x <=' y = False')"

LeLeqDiff [rule_format] :
"ALL x. ALL y. x <' y = (x <=' y) && (x /= y)"

LeLtDef [rule_format] :
"ALL x.
 ALL y. compare x y = LT = (x <' y = True' & x ==' y = False')"

LeEqDef [rule_format] :
"ALL x.
 ALL y. compare x y = EQ = (x <' y = False' & y <' x = False')"

LeGtDef [rule_format] :
"ALL x.
 ALL y. compare x y = GT = (x >' y = True' & x ==' y = False')"

LqLtDef [rule_format] :
"ALL x.
 ALL y. (compare x y = LT | compare x y = EQ) = (x <=' y = True')"

LqEqDef [rule_format] :
"ALL x.
 ALL y. compare x y = EQ = (x <=' y = True' & y <=' x = True')"

LqGtDef [rule_format] :
"ALL x. ALL y. compare x y = GT = (x <=' y = False')"

GeLtDef [rule_format] :
"ALL x.
 ALL y. compare x y = LT = (x >' y = False' & x ==' y = False')"

GeEqDef [rule_format] :
"ALL x.
 ALL y. compare x y = EQ = (x >' y = False' & y >' x = False')"

GeGtDef [rule_format] :
"ALL x.
 ALL y. compare x y = GT = (x >' y = True' & x ==' y = False')"

GqLtDef [rule_format] :
"ALL x. ALL y. compare x y = LT = (x >=' y = False')"

GqEqDef [rule_format] :
"ALL x.
 ALL y. compare x y = EQ = (x >=' y = True' & y >=' x = True')"

GqGtDef [rule_format] :
"ALL x.
 ALL y. (compare x y = GT | compare x y = EQ) = (x >=' y = True')"

MaxYDef [rule_format] :
"ALL x. ALL y. X_max x y = y = (x <=' y = True')"

MaxXDef [rule_format] :
"ALL x. ALL y. X_max x y = x = (y <=' x = True')"

MinXDef [rule_format] :
"ALL x. ALL y. X_min x y = x = (x <=' y = True')"

MinYDef [rule_format] :
"ALL x. ALL y. X_min x y = y = (y <=' x = True')"

MaxSym [rule_format] :
"ALL x. ALL y. X_max x y = y = (X_max y x = y)"

MinSym [rule_format] :
"ALL x. ALL y. X_min x y = y = (X_min y x = y)"

TO1 [rule_format] :
"ALL x.
 ALL y. (x ==' y = True' | x <' y = True') = (x <=' y = True')"

TO2 [rule_format] :
"ALL x. ALL y. x ==' y = True' --> x <' y = False'"

TO3 [rule_format] :
"ALL x. ALL y. Not' Not' (x <' y) = True' | Not' (x <' y) = True'"

TO4 [rule_format] :
"ALL x. ALL y. x <' y = True' --> Not' (x ==' y) = True'"

TO5 [rule_format] :
"ALL w.
 ALL x.
 ALL y.
 ALL z.
 (x <' y = True' & y <' z = True') & z <' w = True' -->
 x <' w = True'"

TO6 [rule_format] :
"ALL x. ALL z. z <' x = True' --> Not' (x <' z) = True'"

TO7 [rule_format] :
"ALL x. ALL y. x <' y = True' = (y >' x = True')"

IOO13 [rule_format] : "LT <' EQ = True'"

IOO14 [rule_format] : "EQ <' GT = True'"

IOO15 [rule_format] : "LT <' GT = True'"

IOO16 [rule_format] : "LT <=' EQ = True'"

IOO17 [rule_format] : "EQ <=' GT = True'"

IOO18 [rule_format] : "LT <=' GT = True'"

IOO19 [rule_format] : "EQ >=' LT = True'"

IOO20 [rule_format] : "GT >=' EQ = True'"

IOO21 [rule_format] : "GT >=' LT = True'"

IOO22 [rule_format] : "EQ >' LT = True'"

IOO23 [rule_format] : "GT >' EQ = True'"

IOO24 [rule_format] : "GT >' LT = True'"

IOO25 [rule_format] : "X_max LT EQ = EQ"

IOO26 [rule_format] : "X_max EQ GT = GT"

IOO27 [rule_format] : "X_max LT GT = GT"

IOO28 [rule_format] : "X_min LT EQ = LT"

IOO29 [rule_format] : "X_min EQ GT = EQ"

IOO30 [rule_format] : "X_min LT GT = LT"

IOO31 [rule_format] : "compare LT LT = EQ"

IOO32 [rule_format] : "compare EQ EQ = EQ"

IOO33 [rule_format] : "compare GT GT = EQ"

IBO5 [rule_format] : "False' <' True' = True'"

IBO6 [rule_format] : "False' >=' True' = False'"

IBO7 [rule_format] : "True' >=' False' = True'"

IBO8 [rule_format] : "True' <' False' = False'"

IBO9 [rule_format] : "X_max False' True' = True'"

IBO10 [rule_format] : "X_min False' True' = False'"

IBO11 [rule_format] : "compare True' True' = EQ"

IBO12 [rule_format] : "compare False' False' = EQ"

IUO01 [rule_format] : "() <=' () = True'"

IUO02 [rule_format] : "() <' () = False'"

IUO03 [rule_format] : "() >=' () = True'"

IUO04 [rule_format] : "() >' () = False'"

IUO05 [rule_format] : "() = ()"

IUO06 [rule_format] : "() = ()"

IUO07 [rule_format] : "compare () () = EQ"

declare NotFalse [simp]
declare NotTrue [simp]
declare AndFalse [simp]
declare AndTrue [simp]
declare EqualReflex [simp]
declare IBE1 [simp]
declare IBE2 [simp]
declare IBE3 [simp]
declare IBE4 [simp]
declare IBE5 [simp]
declare IBE6 [simp]
declare IBE7 [simp]
declare IBE8 [simp]
declare IOE01 [simp]
declare IOE02 [simp]
declare IOE03 [simp]
declare IOE04 [simp]
declare IOE05 [simp]
declare IOE06 [simp]
declare IOE07 [simp]
declare IOE08 [simp]
declare IOE09 [simp]
declare LeIrreflexivity [simp]
declare LeTAsymmetry [simp]
declare GeIrreflexivity [simp]
declare GeTAsymmetry [simp]
declare GeTTransitive [simp]
declare GeTTotal [simp]
declare LeqReflexivity [simp]
declare LeqTTransitive [simp]
declare LeqTTotal [simp]
declare GeqReflexivity [simp]
declare GeqTTransitive [simp]
declare GeqTTotal [simp]
declare TO2 [simp]
declare TO4 [simp]
declare TO6 [simp]
declare IOO13 [simp]
declare IOO14 [simp]
declare IOO15 [simp]
declare IOO16 [simp]
declare IOO17 [simp]
declare IOO18 [simp]
declare IOO19 [simp]
declare IOO20 [simp]
declare IOO21 [simp]
declare IOO22 [simp]
declare IOO23 [simp]
declare IOO24 [simp]
declare IOO25 [simp]
declare IOO26 [simp]
declare IOO27 [simp]
declare IOO28 [simp]
declare IOO29 [simp]
declare IOO30 [simp]
declare IOO31 [simp]
declare IOO32 [simp]
declare IOO33 [simp]
declare IBO5 [simp]
declare IBO6 [simp]
declare IBO7 [simp]
declare IBO8 [simp]
declare IBO9 [simp]
declare IBO10 [simp]
declare IBO11 [simp]
declare IBO12 [simp]

theorem Ax1 : "minBound = False'"
by auto

ML "Header.record \"Ax1\""

theorem Ax2 : "maxBound = True'"
by auto

ML "Header.record \"Ax2\""

theorem Ax3 : "minBound = LT"
by auto

ML "Header.record \"Ax3\""

theorem Ax4 : "maxBound = GT"
by auto

ML "Header.record \"Ax4\""

end