Theory VS_Modules

(* Title: Examples/Vector_Spaces/VS_Modules.thy
   Author: Mihails Milehins
   Copyright 2021 (C) Mihails Milehins
*)
section‹Modules›
theory VS_Modules
  imports 
    VS_Groups
    Complex_Main
begin



subsectiontext‹module_with›

locale module_with = ab_group_add plusM zeroM minusM uminusM
  for plusM :: "['m, 'm]  'm" (infixl +M 65)
    and zeroM (0M)
    and minusM (infixl -M 65)
    and uminusM (-M _› [81] 80) +
  fixes scale :: "['cr1::comm_ring_1, 'm]  'm" (infixr "*swith" 75)
  assumes scale_right_distrib[algebra_simps]: 
    "a *swith (x +M y) = a *swith x +M a *swith y"
    and scale_left_distrib[algebra_simps]:
      "(a + b) *swith x = a *swith x +M b *swith x"
    and scale_scale[simp]: "a *swith (b *swith x) = (a * b) *swith x"
    and scale_one[simp]: "1 *swith x = x"

lemma module_with_overloaded[ud_with]: "module = module_with (+) 0 (-) uminus"
  unfolding module_def module_with_def module_with_axioms_def
  by (simp add: comm_ring_1_axioms ab_group_add_axioms)

locale module_pair_with =
  M1: module_with plusM_1 zeroM_1 minusM_1 uminusM_1 scale1 +
  M2: module_with plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
  for plusM_1 :: "['m_1, 'm_1]  'm_1" (infixl +M'_1 65)
    and zeroM_1 (0M'_1)
    and minusM_1 (infixl -M'_1 65)
    and uminusM_1 (-M'_1 _› [81] 80)
    and scale1 (infixr *swith'_1 75)
    and plusM_2 :: "['m_2, 'm_2]  'm_2" (infixl +M'_2 65)
    and zeroM_2 (0M'_2)
    and minusM_2 (infixl -M'_2 65)
    and uminusM_2 (-M'_2 _› [81] 80)
    and scale2 (infixr *swith'_2 75)

lemma module_pair_with_overloaded[ud_with]: 
  "module_pair =
    (
      λscale1 scale2.
        module_pair_with (+) 0 (-) uminus scale1 (+) 0 (-) uminus scale2
    )"
  unfolding module_pair_def module_pair_with_def 
  unfolding module_with_overloaded
  ..

locale module_hom_with = 
  M1: module_with plusM_1 zeroM_1 minusM_1 uminusM_1 scale1 +
  M2: module_with plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
  for plusM_1 :: "['m_1, 'm_1]  'm_1" (infixl +M'_1 65)
    and zeroM_1 (0M'_1)
    and minusM_1 (infixl -M'_1 65)
    and uminusM_1 (-M'_1 _› [81] 80)
    and scale1 (infixr *swith'_1 75)
    and plusM_2 :: "['m_2, 'm_2]  'm_2" (infixl +M'_2 65)
    and zeroM_2 (0M'_2)
    and minusM_2 (infixl -M'_2 65)
    and uminusM_2 (-M'_2 _› [81] 80)
    and scale2 (infixr *swith'_2 75) +
  fixes f :: "'m_1  'm_2"
  assumes add: "f (b1 +M_1 b2) = f b1 +M_2 f b2"
    and scale: "f (r *swith_1 b) = r *swith_2 f b"
begin

sublocale module_pair_with ..

end

lemma module_hom_with_overloaded[ud_with]: 
  "module_hom =
    (
      λscale1 scale2.
        module_hom_with (+) 0 (-) uminus scale1 (+) 0 (-) uminus scale2
    )"
  unfolding 
    module_hom_def module_hom_axioms_def 
    module_hom_with_def module_hom_with_axioms_def
  unfolding module_with_overloaded
  ..
ud module.subspace ((with _ _ _ : «subspace» _) [1000, 999, 998, 1000] 10)
ud module.span ((with _ _ _ : «span» _) [1000, 999, 998, 1000] 10)
ud module.dependent 
  ((with _ _ _ _ : «dependent» _) [1000, 999, 998, 997, 1000] 10)
ud module.representation 
  (
    (with _ _ _ _ : «representation» _ _) 
    [1000, 999, 998, 997, 1000, 999] 10
  )

abbreviation independent_with 
  ((with _ _ _ _ : «independent» _) [1000, 999, 998, 997, 1000] 10)
  where 
    "(with zeroCR1 zeroM  scaleM plusM : «independent» s) 
      ¬(with zeroCR1 zeroM scaleM plusM : «dependent» s)"

lemma span_with_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: "right_total A" "bi_unique A"
  shows 
    "(
      A ===> 
      (A ===> A ===> A) ===>
      ((=) ===> A ===> A) ===> 
      rel_set A ===> 
      rel_set A
    ) span.with span.with"
  unfolding span.with_def
proof(intro rel_funI)
  fix p p' z z' X X' and s s'::"'c  _"
  assume transfer_rules[transfer_rule]:   
    "(A ===> A ===> A) p p'" 
    "A z z'" 
    "((=) ===> A ===> A) s s'" 
    "rel_set A X X'"
  have "Domainp A z" using A z z' by force
  have *: "t  X  (xt. Domainp A x)" for t
    by (meson Domainp.DomainI rel_set A X X' rel_setD1 subsetD)
  note swt = sum_with_transfer
    [
      OF assms(1,2,2), 
      THEN rel_funD, 
      THEN rel_funD, 
      THEN rel_funD,  
      THEN rel_funD,  
      OF transfer_rules(1,2)
    ]
  have DsI: "Domainp A (sum_with p z r t)" 
    if "x. x  t  Domainp A (r x)" "t  Collect (Domainp A)" for r t
    by (metis that Domainp_sum_with transfer_rules(1,2))
  from Domainp_apply2I[OF transfer_rules(3)]
  have Domainp_sI: "Domainp A x  Domainp A (s y x)" for x y by auto
  show "rel_set A
    {sum_with p z (λa. s (r a) a) t |t r. finite t  t  X}
        {sum_with p' z' (λa. s' (r a) a) t |t r. finite t  t  X'}"
    apply transfer_prover_start 
    apply transfer_step+
    by (insert *) (auto intro!: DsI Domainp_sI)
qed

lemma dependent_with_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: "right_total A" "bi_unique A"
  shows 
    "(
      (=) ===>
      A ===> 
      (A ===> A ===> A) ===>
      ((=) ===> A ===> A) ===> 
      rel_set A ===> 
      (=)
    ) dependent.with dependent.with"
  unfolding dependent.with_def 
proof(intro rel_funI)
  fix p p' z z' X X' and zb zb' ::'c and s s'::"'c  _"
  assume [transfer_rule]: 
    "(A ===> A ===> A) p p'"
    "A z z'"
    "zb = zb'"
    "((=) ===> A ===> A) s s'" 
    "rel_set A X X'"
  have *: "t  X  (xt. Domainp A x)" for t
    by (meson Domainp.DomainI rel_set A X X' rel_setD1 subsetD)
  show 
    "(
        t u. 
          finite t  
          t  X  
          sum_with p z (λv. s (u v) v) t = z  
          (vt. u v  zb)
     ) =
      (
        t u. 
          finite t  
          t  X'  
          sum_with p' z' (λv. s' (u v) v) t = z'  
          (vt. u v  zb')
      )"
    apply transfer_prover_start
    apply transfer_step+
    by (insert *) (auto intro!: comm_monoid_add_ow.sum_with_closed)
qed

ctr relativization
  synthesis ctr_simps
  assumes [transfer_rule]: "is_equality A" "bi_unique B"
  trp (?'a A) and (?'b B) 
  in subspace_with: subspace.with_def



subsectionmodule_ow›


subsubsection‹Definitions and common properties›


text‹Single module.›

locale module_ow = ab_group_add_ow UM plusM zeroM minusM uminusM
  for UM :: "'m set" 
    and plusM (infixl +M 65)
    and zeroM (0M)
    and minusM (infixl -M 65)
    and uminusM (-M _› [81] 80) +
  fixes scale :: "['cr1::comm_ring_1, 'm]  'm" (infixr "*sM" 75)
  assumes scale_closed[simp, intro]: "x  UM  a *sM x  UM"
    and scale_right_distrib[algebra_simps]: 
    " x  UM; y  UM   a *sM (x +M y) = a *sM x +M a *sM y"
    and scale_left_distrib[algebra_simps]: 
      "x  UM  (a + b) *sM x = a *sM x +M b *sM x"
    and scale_scale[simp]: 
      "x  UM  a *sM (b *sM x) = (a * b) *sM x"
    and scale_one[simp]: "x  UM  1 *sM x = x"
begin

lemma scale_closed'[simp]: "a. xUM. a *sM x  UM" by simp

lemma minus_closed'[simp]: "xUM. yUM. x -M y  UM"
  by (simp add: ab_diff_conv_add_uminus add_closed' uminus_closed)

lemma uminus_closed'[simp]: "xUM. -M x  UM" by (simp add: uminus_closed)

tts_register_sbts (*sM) | UM
  by (rule tts_AB_C_transfer[OF scale_closed])
    (auto simp: bi_unique_eq right_total_eq)

tts_register_sbts plusM | UM
  by (rule tts_AB_C_transfer[OF add_closed])
    (auto simp: bi_unique_eq right_total_eq)

tts_register_sbts zeroM | UM 
  by (meson Domainp.cases zero_closed)

end


text‹Pair of modules.›

locale module_pair_ow = 
  M1: module_ow UM_1 plusM_1 zeroM_1 minusM_1 uminusM_1 scale1 +
  M2: module_ow UM_2 plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
  for UM_1 :: "'m_1 set"
    and plusM_1 (infixl +M'_1 65)
    and zeroM_1 (0M'_1)
    and minusM_1 (infixl -M'_1 65)
    and uminusM_1 (-M'_1 _› [81] 80)
    and scale1 :: "['cr1::comm_ring_1, 'm_1]  'm_1" (infixr *sM'_1 75)
    and UM_2 :: "'m_2 set"
    and plusM_2 (infixl +M'_2 65)
    and zeroM_2 (0M'_2)
    and minusM_2 (infixl -M'_2 65)
    and uminusM_2 (-M'_2 _› [81] 80)
    and scale2 :: "['cr1::comm_ring_1, 'm_2]  'm_2" (infixr *sM'_2 75)


text‹Module homomorphisms.›

locale module_hom_ow = 
  M1: module_ow UM_1 plusM_1 zeroM_1 minusM_1 uminusM_1 scale1 +
  M2: module_ow UM_2 plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
  for UM_1 :: "'m_1 set"
    and plusM_1 (infixl +M'_1 65)
    and zeroM_1 (0M'_1)
    and minusM_1 (infixl -M'_1 65)
    and uminusM_1 (-M'_1 _› [81] 80)
    and scale1 :: "['cr1::comm_ring_1, 'm_1]  'm_1" (infixr *sM'_1 75)
    and UM_2 :: "'m_2 set"
    and plusM_2 (infixl +M'_2 65)
    and zeroM_2 (0M'_2)
    and minusM_2 (infixl -M'_2 65)
    and uminusM_2 (-M'_2 _› [81] 80)
    and scale2 :: "['cr1::comm_ring_1, 'm_2]  'm_2" (infixr *sM'_2 75) +
  fixes f :: "'m_1  'm_2"
  assumes f_closed[simp]: "f ` UM_1  UM_2" 
    and add: " b1  UM_1; b2  UM_1   f (b1 +M_1 b2) = f b1 +M_2 f b2"
    and scale: " r  UCR1; b  UM_1   f (r *sM_1 b) = r *sM_2 f b"
begin

tts_register_sbts f | UM_1 and UM_2 by (rule tts_AB_transfer[OF f_closed])

lemma f_closed'[simp]: "xUM_1. f x  UM_2" using f_closed by blast

sublocale module_pair_ow ..

end


subsubsection‹Transfer.›

lemma module_with_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: "bi_unique B" "right_total B"     
  fixes PP lhs
  defines
    "PP  
      (
        (B ===> B ===> B) ===>
        B ===>
        (B ===> B ===> B) ===>
        (B ===> B) ===>
        ((=) ===> B ===> B) ===>
        (=)
      )"
    and
      "lhs  
        (
          λ plusM zeroM minusM uminusM scale.
          module_ow (Collect (Domainp B)) plusM zeroM minusM uminusM scale
        )"
  shows "PP lhs (module_with)"
proof-
  let ?rhs = 
    "(
      λplusM zeroM minusM uminusM scale.
        (a  UNIV. x  UNIV. scale a x  UNIV) 
         module_with plusM zeroM minusM uminusM scale
    )"
  have "PP lhs ?rhs"
    unfolding 
      PP_def lhs_def
      module_ow_def module_with_def
      module_ow_axioms_def module_with_axioms_def
    apply transfer_prover_start
    apply transfer_step+
    by (intro ext) blast
  then show ?thesis by simp
qed

lemma module_pair_with_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: 
    "bi_unique B1" "right_total B1" "bi_unique B2" "right_total B2"     
  fixes PP lhs
  defines
    "PP  
      (
        (B1 ===> B1 ===> B1) ===>
        B1 ===>
        (B1 ===> B1 ===> B1) ===>
        (B1 ===> B1) ===>
        ((=) ===> B1 ===> B1) ===>
        (B2 ===> B2 ===> B2) ===>
        B2 ===>
        (B2 ===> B2 ===> B2) ===>
        (B2 ===> B2) ===>
        ((=) ===> B2 ===> B2) ===>
        (=)
    )"
    and
      "lhs  
        (
          λ
            plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
            plusM_2 zeroM_2 minusM_2 uminusM_2 scale2.
          module_pair_ow 
            (Collect (Domainp B1)) plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
            (Collect (Domainp B2)) plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
        )"
    shows "PP lhs module_pair_with"
  unfolding PP_def lhs_def
proof(intro rel_funI) 
  let ?rhs = 
    "(
      λ
        plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
        plusM_2 zeroM_2 minusM_2 uminusM_2 scale2.
          (a  UNIV. x  UNIV. scale1 a x  UNIV) 
          (a  UNIV. x  UNIV. scale2 a x  UNIV) 
          module_pair_with 
            plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
            plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
    )"
  fix 
    plusM_1 plusM_1' 
    zeroM_1 zeroM_1' 
    minusM_1 minusM_1' 
    uminusM_1 uminusM_1' 
    plusM_2 plusM_2' 
    zeroM_2 zeroM_2' 
    minusM_2 minusM_2' 
    uminusM_2 uminusM_2' 
    and scale1 :: "'f::comm_ring_1  'a  'a" and scale1' 
    and scale2 :: "'f::comm_ring_1  'c  'c" and scale2'
  assume [transfer_rule]: 
    "(B1 ===> B1 ===> B1) plusM_1 plusM_1'"
    "B1 zeroM_1 zeroM_1'"
    "(B1 ===> B1 ===> B1) minusM_1 minusM_1'"
    "(B1 ===> B1) uminusM_1 uminusM_1'"
    "(B2 ===> B2 ===> B2) plusM_2 plusM_2'"
    "B2 zeroM_2 zeroM_2'"
    "(B2 ===> B2 ===> B2) minusM_2 minusM_2'"
    "(B2 ===> B2) uminusM_2 uminusM_2'"
    "((=) ===> B1 ===> B1) scale1 scale1'"
    "((=) ===> B2 ===> B2) scale2 scale2'"
  show 
    "module_pair_ow 
      (Collect (Domainp B1)) plusM_1 zeroM_1 minusM_1 uminusM_1 scale1 
      (Collect (Domainp B2)) plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
      =
    module_pair_with
      plusM_1' zeroM_1' minusM_1' uminusM_1' scale1'
      plusM_2' zeroM_2' minusM_2' uminusM_2' scale2'"
    unfolding module_pair_ow_def module_pair_with_def
    apply transfer_prover_start
    apply transfer_step+
    by simp
qed

lemma module_hom_with_transfer[transfer_rule]:
  includes lifting_syntax
  assumes [transfer_rule]: 
    "bi_unique B1" "right_total B1" "bi_unique B2" "right_total B2"     
  fixes PP lhs
  defines
    "PP  
      (
        (B1 ===> B1 ===> B1) ===>
        B1 ===>
        (B1 ===> B1 ===> B1) ===>
        (B1 ===> B1) ===>
        ((=) ===> B1 ===> B1) ===>
        (B2 ===> B2 ===> B2) ===>
        B2 ===>
        (B2 ===> B2 ===> B2) ===>
        (B2 ===> B2) ===>
        ((=) ===> B2 ===> B2) ===>
        (B1 ===> B2) ===>
        (=)
      )"
    and
      "lhs  
        (
          λ
            plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
            plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
            f.
          module_hom_ow 
            (Collect (Domainp B1)) plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
            (Collect (Domainp B2)) plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
            f
        )"
    shows "PP lhs module_hom_with"
proof-
  let ?rhs = 
    "(
      λ
        plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
        plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
        f. 
        (x  UNIV. f x  UNIV) 
        module_hom_with
          plusM_1 zeroM_1 minusM_1 uminusM_1 scale1
          plusM_2 zeroM_2 minusM_2 uminusM_2 scale2
          f
    )"
  have "PP lhs ?rhs"
    unfolding 
      PP_def lhs_def 
      module_hom_ow_def module_hom_with_def
      module_hom_ow_axioms_def module_hom_with_axioms_def
    apply transfer_prover_start
    apply transfer_step+
    by (intro ext) blast
  then show ?thesis by simp
qed



subsectionmodule_on›


subsubsection‹Definitions and common properties›

locale module_on =
  fixes UM
    and scale :: "'a::comm_ring_1  'b::ab_group_add  'b" (infixr "*s" 75)
  assumes scale_right_distrib_on[algebra_simps]: 
      " x  UM; y  UM   a *s (x + y) = a *s x + a *s y"
    and scale_left_distrib_on[algebra_simps]: 
      "x  UM  (a + b) *s x = a *s x + b *s x"
    and scale_scale_on[simp]: "x  UM  a *s (b *s x) = (a * b) *s x"
    and scale_one_on[simp]: "x  UM  1 *s x = x"
    and closed_add: " x  UM; y  UM   x + y  UM"
    and closed_zero: "0  UM"
    and closed_scale: "x  UM  a *s x  UM"
begin

lemma S_ne: "UM  {}" using closed_zero by auto

lemma scale_minus_left_on: 
  assumes "x  UM" 
  shows "scale (- a) x = - scale a x" 
  by 
    (
      metis 
        add_cancel_right_right scale_left_distrib_on neg_eq_iff_add_eq_0 assms
    )

lemma closed_uminus: 
  assumes "x  UM"
  shows "-x  UM"
  by (metis assms closed_scale scale_minus_left_on scale_one_on)

sublocale implicitM: ab_group_add_ow UM (+) 0 (-) uminus
  by unfold_locales (simp_all add: closed_add closed_zero closed_uminus)

sublocale implicitM: module_ow UM (+) 0 (-) uminus (*s)
  by unfold_locales 
    (simp_all add: closed_scale scale_right_distrib_on scale_left_distrib_on)

definition subspace :: "'b set  bool"
  where subspace_on_def: "subspace T  
    0  T  (xT. yT. x + y  T)  (c. xT. c *s x  T)"

definition span :: "'b set  'b set"
  where span_on_def: "span b = {sum (λa. r a *s  a) t | t r. finite t  t  b}"

definition dependent :: "'b set  bool"
  where dependent_on_def: "dependent s  
    (t u. finite t  t  s  (sum (λv. u v *s v) t = 0  (vt. u v  0)))"

lemma implicit_subspace_with[tts_implicit]: "subspace.with (+) 0 (*s) = subspace"
  unfolding subspace_on_def subspace.with_def ..

lemma implicit_dependent_with[tts_implicit]: 
  "dependent.with 0 0 (+) (*s) = dependent"
  unfolding dependent_on_def dependent.with_def sum_with ..

lemma implicit_span_with[tts_implicit]: "span.with 0 (+) (*s) = span"
  unfolding span_on_def span.with_def sum_with ..

end

lemma implicit_module_ow[tts_implicit]:
  "module_ow UM (+) 0 (-) uminus = module_on UM"
proof (intro ext iffI)
  fix s::"'a'b'b" assume "module_on UM s"
  then interpret module_on UM s .
  show "module_ow UM (+) 0 (-) uminus s" 
    by (simp add: implicitM.module_ow_axioms)
next
  fix s::"'a'b'b" assume "module_ow UM (+) 0 (-) uminus s"
  then interpret module_ow UM (+) 0 (-) uminus s .
  show "module_on UM s" 
    by (simp add: scale_left_distrib scale_right_distrib module_on.intro)
qed

locale module_pair_on = 
  M1: module_on UM_1 scale1 + M2: module_on UM_2 scale2
  for UM_1:: "'b::ab_group_add set" 
    and UM_2::"'c::ab_group_add set"
    and scale1::"'a::comm_ring_1  _  _" (infixr *s1 75)
    and scale2::"'a::comm_ring_1  _  _" (infixr *s2 75)
begin

sublocale implicitM: module_pair_ow 
  UM_1 (+) 0 (-) uminus scale1 UM_2 (+) 0 (-) uminus scale2
  by unfold_locales

end

lemma implicit_module_pair_ow[tts_implicit]:
  "module_pair_ow UM_1 (+) 0 (-) uminus scale1 UM_2 (+) 0 (-) uminus scale2 = 
    module_pair_on UM_1 UM_2 scale1 scale2"
  unfolding module_pair_ow_def implicit_module_ow module_pair_on_def ..

locale module_hom_on = M1: module_on UM_1 scale1 + M2: module_on UM_2 scale2
  for UM_1 :: "'b::ab_group_add set" and UM_2 :: "'c::ab_group_add set"
    and scale1 :: "'a::comm_ring_1  'b  'b" (infixr *s1 75)
    and scale2 :: "'a::comm_ring_1  'c  'c" (infixr *s2 75) +
  fixes f :: "'b  'c"
  assumes hom_closed: "f ` UM_1  UM_2"
    and add: "b1 b2.  b1  UM_1; b2  UM_1   f (b1 + b2) = f b1 + f b2"
    and scale: "b. b  UM_1  f (r *s1 b) = r *s2 f b"
begin

sublocale module_pair_on UM_1 UM_2 scale1 scale2 by unfold_locales

sublocale implicitM: module_hom_ow 
  UM_1 (+) 0 (-) uminus scale1 UM_2 (+) 0 (-) uminus scale2
  by unfold_locales (simp_all add: hom_closed add scale)
 
end

lemma implicit_module_hom_ow[tts_implicit]:
  "module_hom_ow UM_1 (+) 0 (-) uminus scale1 UM_2 (+) 0 (-) uminus scale2 = 
    module_hom_on UM_1 UM_2 scale1 scale2"
  unfolding 
    module_hom_ow_def 
    module_hom_on_def 
    module_hom_ow_axioms_def
    module_hom_on_axioms_def
    tts_implicit
  by (intro ext) auto



subsection‹Relativization.›

context module_on
begin

tts_context
  tts: (?'b to UM::'b set)
  rewriting ctr_simps
  substituting implicitM.module_ow_axioms
    and implicitM.ab_group_add_ow_axioms
  eliminating ?a  UM and ?B  UM through auto
  applying 
    [
      OF 
        implicitM.carrier_ne 
        implicitM.add_closed' 
        implicitM.minus_closed' 
        implicitM.uminus_closed' 
        implicitM.scale_closed',
      unfolded tts_implicit
    ]
begin

tts_lemma scale_left_commute:
  assumes "x  UM"
  shows "a *s b *s x = b *s a *s x"
    is module.scale_left_commute.

tts_lemma scale_zero_left:
  assumes "x  UM"
  shows "0 *s x = 0"
    is module.scale_zero_left.
    
tts_lemma scale_minus_left:
  assumes "x  UM"
  shows "- a *s x = - (a *s x)"
    is module.scale_minus_left.

tts_lemma scale_left_diff_distrib:
  assumes "x  UM"
  shows "(a - b) *s x = a *s x - b *s x"
    is module.scale_left_diff_distrib.

tts_lemma scale_sum_left:
  assumes "x  UM"
  shows "sum f A *s x = (aA. f a *s x)"
    is module.scale_sum_left.

tts_lemma scale_zero_right: "a *s 0 = 0"
    is module.scale_zero_right.
    
tts_lemma scale_minus_right:
  assumes "x  UM"
  shows "a *s - x = - (a *s x)"
    is module.scale_minus_right.
    
tts_lemma scale_right_diff_distrib:
  assumes "x  UM" and "y  UM"
  shows "a *s (x - y) = a *s x - a *s y"
    is module.scale_right_diff_distrib.

tts_lemma scale_sum_right:
  assumes "range f  UM"
  shows "a *s sum f A = (xA. a *s f x)"
    is module.scale_sum_right.

tts_lemma sum_constant_scale:
  assumes "y  UM"
  shows "(xA. y) = of_nat (card A) *s y"
    is module.sum_constant_scale.

tts_lemma subspace_def:
  assumes "S  UM"
  shows "subspace S =
    (0  S  (x. yS. x *s y  S)  (xS. yS. x + y  S))"
    is module.subspace_def.

tts_lemma subspaceI:
  assumes "S  UM"
    and "0  S"
    and "x y. x  UM; y  UM; x  S; y  S  x + y  S"
    and "c x. x  UM; x  S  c *s x  S"
  shows "subspace S"
    is module.subspaceI.

tts_lemma subspace_single_0: "subspace {0}"
    is module.subspace_single_0.

tts_lemma subspace_0:
  assumes "S  UM" and "subspace S"
  shows "0  S"
    is module.subspace_0.

tts_lemma subspace_add:
  assumes "S  UM" and "subspace S" and "x  S" and "y  S"
  shows "x + y  S"
    is module.subspace_add.

tts_lemma subspace_scale:
  assumes "S  UM" and "subspace S" and "x  S"
  shows "c *s x  S"
    is module.subspace_scale.

tts_lemma subspace_neg:
  assumes "S  UM" and "subspace S" and "x  S"
  shows "- x  S"
    is module.subspace_neg.

tts_lemma subspace_diff:
  assumes "S  UM" and "subspace S" and "x  S" and "y  S"
  shows "x - y  S"
    is module.subspace_diff.

tts_lemma subspace_sum:
  assumes "A  UM"
    and "range f  UM"
    and "subspace A"
    and "x. x  B  f x  A"
  shows "sum f B  A"
    is module.subspace_sum.

tts_lemma subspace_inter:
  assumes "A  UM" and "B  UM" and "subspace A" and "subspace B"
  shows "subspace (A  B)"
    is module.subspace_inter.

tts_lemma span_explicit':
  assumes "b  UM"
  shows "span b = 
    {
      x  UM. f. 
        x = (v{x  UM. f x  0}. f v *s v)  
        finite {x  UM. f x  0}  
        (xUM. f x  0  x  b)
    }"
   is module.span_explicit'.

tts_lemma span_finite:
  assumes "S  UM" and "finite S"
  shows "span S = range (λu. vS. u v *s v)"
    is module.span_finite.

tts_lemma span_induct_alt:
  assumes "x  UM"
    and "S  UM"
    and "x  span S"
    and "h 0"
    and "c x y. x  UM; y  UM; x  S; h y  h (c *s x + y)"
  shows "h x"
    is module.span_induct_alt.

tts_lemma span_mono:
  assumes "B  UM" and "A  B"
  shows "span A  span B"
    is module.span_mono.

tts_lemma span_base:
  assumes "S  UM" and "a  S"
  shows "a  span S"
    is module.span_base.

tts_lemma span_superset:
  assumes "S  UM"
  shows "S  span S"
    is module.span_superset.

tts_lemma span_zero:
  assumes "S  UM"
  shows "0  span S"
    is module.span_zero.

tts_lemma span_add:
  assumes "x  UM"
    and "S  UM"
    and "y  UM"
    and "x  span S"
    and "y  span S"
  shows "x + y  span S"
    is module.span_add.

tts_lemma span_scale:
  assumes "x  UM" and "S  UM" and "x  span S"
  shows "c *s x  span S"
    is module.span_scale.

tts_lemma subspace_span:
  assumes "S  UM"
  shows "subspace (span S)"
    is module.subspace_span.

tts_lemma span_neg:
  assumes "x  UM" and "S  UM" and "x  span S"
  shows "- x  span S"
    is module.span_neg.

tts_lemma span_diff:
  assumes "x  UM"
    and "S  UM"
    and "y  UM"
    and "x  span S"
    and "y  span S"
  shows "x - y  span S"
    is module.span_diff.

tts_lemma span_sum:
  assumes "range f  UM" and "S  UM" and "x. x  A  f x  span S"
  shows "sum f A  span S"
    is module.span_sum.

tts_lemma span_minimal:
  assumes "T  UM" and "S  T" and "subspace T"
  shows "span S  T"
    is module.span_minimal.

tts_lemma span_subspace_induct:
  assumes "x  UM"
    and "S  UM"
    and "P  UM"
    and "x  span S"
    and "subspace P"
    and "x. x  S  x  P"
  shows "x  P"
    given module.span_subspace_induct 
    by simp

tts_lemma span_induct:
  assumes "x  UM"
    and "S  UM"
    and "x  span S"
    and "subspace {x. P x  x  UM}"
    and "x. x  S  P x"
  shows "P x"
    given module.span_induct by blast

tts_lemma span_empty: "span {} = {0}"
    is module.span_empty.

tts_lemma span_subspace:
  assumes "B  UM" and "A  B" and "B  span A" and "subspace B"
  shows "span A = B"
    is module.span_subspace.

tts_lemma span_span:
  assumes "A  UM"
  shows "span (span A) = span A"
    is module.span_span.

tts_lemma span_add_eq:
  assumes "x  UM" and "S  UM" and "y  UM" and "x  span S"
  shows "(x + y  span S) = (y  span S)"
    is module.span_add_eq.

tts_lemma span_add_eq2:
  assumes "y  UM" and "S  UM" and "x  UM" and "y  span S"
  shows "(x + y  span S) = (x  span S)"
    is module.span_add_eq2.

tts_lemma span_singleton:
  assumes "x  UM"
  shows "span {x} = range (λk. k *s x)"
    is module.span_singleton.

tts_lemma span_Un:
  assumes "S  UM" and "T  UM"
  shows "span (S  T) = 
    {x  UM. aUM. bUM. x = a + b  a  span S  b  span T}"
    is module.span_Un.

tts_lemma span_insert:
  assumes "a  UM" and "S  UM"
  shows "span (insert a S) = {x  UM. y. x - y *s a  span S}"
    is module.span_insert.

tts_lemma span_breakdown:
  assumes "S  UM" and "a  UM" and "b  S" and "a  span S"
  shows "x. a - x *s b  span (S - {b})"
    is module.span_breakdown.

tts_lemma span_breakdown_eq:
  assumes "x  UM" and "a  UM" and "S  UM"
  shows "(x  span (insert a S)) = (y. x - y *s a  span S)"
    is module.span_breakdown_eq.

tts_lemma span_clauses:
  "S  UM; a  S  a  span S"
  "S  UM  0  span S"
  "x  UM; S  UM; y  UM; x  span S; y  span S  x + y  span S"
  "x  UM; S  UM; x  span S  c *s x  span S"
  is module.span_clauses.

tts_lemma span_eq_iff:
  assumes "s  UM"
  shows "(span s = s) = subspace s"
    is module.span_eq_iff.

tts_lemma span_eq:
  assumes "S  UM" and "T  UM"
  shows "(span S = span T) = (S  span T  T  span S)"
    is module.span_eq.

tts_lemma eq_span_insert_eq:
  assumes "x  UM" and "y  UM" and "S  UM" and "x - y  span S"
  shows "span (insert x S) = span (insert y S)"
    is module.eq_span_insert_eq.

tts_lemma dependent_mono:
  assumes "A  UM" and "dependent B" and "B  A"
  shows "dependent A"
    is module.dependent_mono.

tts_lemma independent_mono:
  assumes "A  UM" and "¬ dependent A" and "B  A"
  shows "¬ dependent B"
    is module.independent_mono.

tts_lemma dependent_zero:
  assumes "A  UM" and "0  A"
  shows "dependent A"
    is module.dependent_zero.

tts_lemma independent_empty: "¬ dependent {}"
    is module.independent_empty.

tts_lemma independentD:
  assumes "s  UM"
    and "¬ dependent s"
    and "finite t"
    and "t  s"
    and "(vt. u v *s v) = 0"
    and "v  t"
  shows "u v = 0"
    is module.independentD.

tts_lemma independent_Union_directed:
  assumes "C  Pow UM"
    and "c d. c  UM; d  UM; c  C; d  C  c  d  d  c"
    and "c. c  UM; c  C  ¬ dependent c"
  shows "¬ dependent ( C)"
    is module.independent_Union_directed.

tts_lemma dependent_finite:
  assumes "S  UM" and "finite S"
  shows "dependent S = (x. (yS. x y  0)  (vS. x v *s v) = 0)"
    is module.dependent_finite.

tts_lemma independentD_alt:
  assumes "B  UM"
    and "x  UM"
    and "¬ dependent B"
    and "finite {x  UM. X x  0}"
    and "{x  UM. X x  0}  B"
    and "(x | x  UM  X x  0. X x *s x) = 0"
  shows "X x = 0"
    is module.independentD_alt.

tts_lemma spanning_subset_independent:
  assumes "A  UM" and "B  A" and "¬ dependent A" and "A  span B"
  shows "A = B"
    is module.spanning_subset_independent.

tts_lemma unique_representation:
  assumes "basis  UM"
    and "¬ dependent basis"
    and "v. v  UM; f v  0  v  basis"
    and "v. v  UM; g v  0  v  basis"
    and "finite {x  UM. f x  0}"
    and "finite {x  UM. g x  0}"
    and 
      "(v{x  UM. f x  0}. f v *s v) = (v{x  UM. g x  0}. g v *s v)"
  shows "xUM. f x = g x"
    is module.unique_representation[unfolded fun_eq_iff].

tts_lemma independentD_unique:
  assumes "B  UM"
    and "¬ dependent B"
    and "finite {x  UM. X x  0}"
    and "{x  UM. X x  0}  B"
    and "finite {x  UM. Y x  0}"
    and "{x  UM. Y x  0}  B"
    and "(x | x  UM  X x  0. X x *s x) = 
      (x | x  UM  Y x  0. Y x *s x)"
  shows "xUM. X x = Y x"
    is module.independentD_unique[unfolded fun_eq_iff].

tts_lemma subspace_UNIV: "subspace UM"
  is module.subspace_UNIV.

tts_lemma span_UNIV: "span UM = UM"
  is module.span_UNIV.

tts_lemma span_alt:
  assumes "B  UM"
  shows 
    "span B = 
      {
        x  UM. f. 
          x = (x | x  UM  f x  0. f x *s x)  
          finite {x  UM. f x  0}  
          {x  UM. f x  0}  B
      }"
    is module.span_alt.

tts_lemma dependent_alt:
  assumes "B  UM"
  shows "dependent B = 
    (
      f. 
        finite {v  UM. f v  0}  
        {v  UM. f v  0}  B  
        (vUM. f v  0)  
        (x | x  UM  f x  0. f x *s x) = 0
    )"
    is module.dependent_alt.

tts_lemma independent_alt:
  assumes "B  UM"
  shows 
    "(¬ dependent B) = 
      (
        f. 
          finite {x  UM. f x  0}  
          {x  UM. f x  0}  B  
          (x | x  UM  f x  0. f x *s x) = 0  
          (xUM. f x = 0)
    )"
    is module.independent_alt.

tts_lemma subspace_Int:
  assumes "range s  Pow UM" and "i. i  I  subspace (s i)"
  shows "subspace ( (s ` I)  UM)"
    is module.subspace_Int.

tts_lemma subspace_Inter:
  assumes "f  Pow UM" and "Ball f subspace"
  shows "subspace ( f  UM)"
    is module.subspace_Inter.

tts_lemma module_hom_scale_self: "module_hom_on UM UM (*s) (*s) ((*s) c)"
  is module.module_hom_scale_self.

tts_lemma module_hom_scale_left:
  assumes "x  UM"
  shows "module_hom_on UNIV UM (*) (*s) (λr. r *s x)"
  is module.module_hom_scale_left.

tts_lemma module_hom_id: "module_hom_on UM UM (*s) (*s) id"
  is module.module_hom_id.

tts_lemma module_hom_ident: "module_hom_on UM UM (*s) (*s) (λx. x)"
  is module.module_hom_ident.

tts_lemma module_hom_uminus: "module_hom_on UM UM (*s) (*s) uminus"
  is module.module_hom_uminus.

end

tts_context
  tts: (?'b to UM::'b set)
  rewriting ctr_simps
  substituting implicitM.module_ow_axioms
    and implicitM.ab_group_add_ow_axioms
  eliminating ?a  UM and ?B  UM through clarsimp
  applying 
    [
      OF 
        implicitM.carrier_ne
        implicitM.add_closed' 
        implicitM.minus_closed' 
        implicitM.uminus_closed' 
        implicitM.scale_closed',
      unfolded tts_implicit
    ]
begin

tts_lemma span_explicit:
  assumes "b  UM"
  shows "span b = 
    {x  UM. yUM. f. (finite y  y  b)  x = (ay. f a *s a)}"
  given module.span_explicit by auto
    
tts_lemma span_unique:
  assumes "S  UM"
    and "T  UM"
    and "S  T"
    and "subspace T"
    and "T'. T'  UM; S  T'; subspace T'  T  T'"
  shows "span S = T"
    is module.span_unique.
    
tts_lemma dependent_explicit:
  assumes "V  UM"
  shows "dependent V = 
    (UUM. f. finite U  U  V  (vU. f v  0)  (vU. f v *s v) = 0)"
    given module.dependent_explicit by auto

tts_lemma independent_explicit_module:
  assumes "V  UM"
  shows "(¬ dependent V) = 
    (
      UUM. f. vUM. 
        finite U  
        U  V  
        (uU. f u *s u) = 0  
        v  U  
        f v = 0
    )"
    given module.independent_explicit_module by auto

end

end

context module_pair_on 
begin

tts_context
  tts: (?'b to UM_1::'b set) and (?'c to UM_2::'c set)
  rewriting ctr_simps
  substituting M1.implicitM.module_ow_axioms
    and M2.implicitM.module_ow_axioms
    and M1.implicitM.ab_group_add_ow_axioms
    and M2.implicitM.ab_group_add_ow_axioms
    and implicitM.module_pair_ow_axioms
  eliminating through auto
  applying [unfolded tts_implicit]
begin

tts_lemma module_hom_zero: "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. 0)"
    is module_pair.module_hom_zero.

tts_lemma module_hom_add:
  assumes "xUM_1. f x  UM_2"
    and "xUM_1. g x  UM_2"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) f"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) g"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. f x + g x)"
    is module_pair.module_hom_add.
    
tts_lemma module_hom_sub:
  assumes "xUM_1. f x  UM_2"
    and "xUM_1. g x  UM_2"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) f"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) g"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. f x - g x)"
    is module_pair.module_hom_sub.
    
tts_lemma module_hom_neg:
  assumes "xUM_1. f x  UM_2" and "module_hom_on UM_1 UM_2 (*s1) (*s2) f"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. - f x)"
    is module_pair.module_hom_neg.
  
tts_lemma module_hom_scale:
  assumes "xUM_1. f x  UM_2" and "module_hom_on UM_1 UM_2 (*s1) (*s2) f"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. c *s2 f x)"
    is module_pair.module_hom_scale.
    
tts_lemma module_hom_compose_scale:
  assumes "c  UM_2" and "module_hom_on UM_1 UNIV (*s1) (*) f"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. f x *s2 c)"
    is module_pair.module_hom_compose_scale.
    
tts_lemma module_hom_sum:
  assumes "u. vUM_1. f u v  UM_2"
    and "i. i  I  module_hom_on UM_1 UM_2 (*s1) (*s2) (f i)"
    and "I = {}  module_on UM_1 (*s1)  module_on UM_2 (*s2)"
  shows "module_hom_on UM_1 UM_2 (*s1) (*s2) (λx. iI. f i x)"
  is module_pair.module_hom_sum.

tts_lemma module_hom_eq_on_span:
  assumes "xUM_1. f x  UM_2"
    and "xUM_1. g x  UM_2"
    and "B  UM_1"
    and "x  UM_1"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) f"
    and "module_hom_on UM_1 UM_2 (*s1) (*s2) g"
    and "x. x  UM_1; x  B  f x = g x"
    and "x  M1.span B"
  shows "f x = g x"
    is module_pair.module_hom_eq_on_span.

end

end

text‹\newpage›

end