Theory VS_Vector_Spaces

(* Title: Examples/Vector_Spaces/VS_Vector_Spaces.thy
   Author: Mihails Milehins
   Copyright 2021 (C) Mihails Milehins
*)
section‹Vector spaces›
theory VS_Vector_Spaces
  imports VS_Modules
begin



subsection‹‹vector_space_with››

locale vector_space_with = ab_group_add plusVS zeroVS minusVS uminusVS
  for plusVS :: "['vs, 'vs] ⇒ 'vs" (infixl ‹+VS› 65)
    and zeroVS (‹0VS›)
    and minusVS (infixl ‹-VS› 65)
    and uminusVS (‹-VS _› [81] 80) +
  fixes scale :: "['f::field, 'vs] ⇒ 'vs" (infixr ‹*swith› 75)
  assumes scale_right_distrib[algebra_simps]: 
    "a *swith (x +VS y) = a *swith x +VS a *swith y"
    and scale_left_distrib[algebra_simps]:
      "(a + b) *swith x = a *swith x +VS b *swith x"
    and scale_scale[simp]: "a *swith (b *swith x) = (a * b) *swith x"
    and scale_one[simp]: "1 *swith x = x"
begin

notation plusVS (infixl ‹+VS› 65)
  and zeroVS (‹0VS›)
  and minusVS (infixl ‹-VS› 65)
  and uminusVS (‹-VS _› [81] 80)
  and scale (infixr ‹*swith› 75)
  
end

lemma vector_space_with_overloaded[ud_with]: 
  "vector_space = vector_space_with (+) 0 (-) uminus"
  unfolding vector_space_def vector_space_with_def vector_space_with_axioms_def
  by (simp add: field_axioms ab_group_add_axioms)

locale vector_space_pair_with =
  VS1: vector_space_with plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 +
  VS2: vector_space_with plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  for plusVS_1 :: "['vs_1, 'vs_1] ⇒ 'vs_1" (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1"  (infixr ‹*swith'_1› 75)
    and plusVS_2 :: "['vs_2, 'vs_2] ⇒ 'vs_2" (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*swith'_2› 75)

lemma vector_space_pair_with_overloaded[ud_with]: 
  "vector_space_pair = 
    (
      λscale1 scale2. 
        vector_space_pair_with (+) 0 (-) uminus scale1 (+) 0 (-) uminus scale2
    )"
  unfolding vector_space_pair_def vector_space_pair_with_def 
  unfolding vector_space_with_overloaded
  ..

locale linear_with =
  VS1: vector_space_with plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 +
  VS2: vector_space_with plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 +
  module_hom_with 
    plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
    plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
    f 
  for plusVS_1 :: "['vs_1, 'vs_1] ⇒ 'vs_1" (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1"  (infixr ‹*swith'_1› 75)
    and plusVS_2 :: "['vs_2, 'vs_2] ⇒ 'vs_2" (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*swith'_2› 75)
    and f :: "'vs_1 ⇒ 'vs_2"

lemma linear_with_overloaded[ud_with]: 
  "Vector_Spaces.linear = 
    (
      λscale1 scale2. 
        linear_with (+) 0 (-) uminus scale1 (+) 0 (-) uminus scale2
    )"
  unfolding 
    Vector_Spaces.linear_def linear_with_def 
    vector_space_with_overloaded module_hom_with_overloaded
  ..

locale finite_dimensional_vector_space_with = 
  vector_space_with plusVS zeroVS minusVS uminusVS scale
  for plusVS :: "['vs, 'vs] ⇒ 'vs"
    and zeroVS 
    and minusVS 
    and uminusVS 
    and scale :: "['f::field, 'vs] ⇒ 'vs" +
  fixes basis :: "'vs set"
  assumes finite_basis: "finite basis"
    and independent_basis: "independent_with 0 0VS (+VS) (*swith) basis"
    and span_basis: "span.with 0VS (+VS) (*swith) basis = UNIV"

lemma finite_dimensional_vector_space_with_overloaded[ud_with]: 
  "finite_dimensional_vector_space = 
    finite_dimensional_vector_space_with (+) 0 (-) uminus"
  unfolding
    finite_dimensional_vector_space_def
    finite_dimensional_vector_space_axioms_def
    finite_dimensional_vector_space_with_def
    finite_dimensional_vector_space_with_axioms_def
  by (intro ext)
    (
      auto simp: 
        vector_space_with_overloaded 
        dependent.with 
        module_iff_vector_space
        span.with 
    )

locale finite_dimensional_vector_space_pair_1_with = 
  VS1: finite_dimensional_vector_space_with 
    plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1 +
  VS2: vector_space_with 
    plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  for plusVS_1 :: "['vs_1, 'vs_1] ⇒ 'vs_1" (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*swith'_1› 75)
    and basis1
    and plusVS_2 :: "['vs_2, 'vs_2] ⇒ 'vs_2" (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*swith'_2› 75)

lemma finite_dimensional_vector_space_pair_1_with_overloaded[ud_with]: 
  "finite_dimensional_vector_space_pair_1 = 
    (
      λscale1 basis1 scale2. 
        finite_dimensional_vector_space_pair_1_with 
          (+) 0 (-) uminus scale1 basis1 (+) 0 (-) uminus scale2
    )"
  unfolding
    finite_dimensional_vector_space_pair_1_def
    finite_dimensional_vector_space_pair_1_with_def    
    vector_space_with_overloaded
  by (simp add: finite_dimensional_vector_space_with_overloaded)

locale finite_dimensional_vector_space_pair_with = 
  VS1: finite_dimensional_vector_space_with 
    plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1 +
  VS2: finite_dimensional_vector_space_with 
    plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 basis2
  for plusVS_1 :: "['vs_1, 'vs_1] ⇒ 'vs_1" (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*swith'_1› 75)
    and basis1
    and plusVS_2 :: "['vs_2, 'vs_2] ⇒ 'vs_2" (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*swith'_2› 75)
    and basis2

lemma finite_dimensional_vector_space_pair_with_overloaded[ud_with]: 
  "finite_dimensional_vector_space_pair = 
    (
      λscale1 basis1 scale2 basis2. 
        finite_dimensional_vector_space_pair_with 
          (+) 0 (-) uminus scale1 basis1 (+) 0 (-) uminus scale2 basis2
    )"
  unfolding
    finite_dimensional_vector_space_pair_def
    finite_dimensional_vector_space_pair_with_def
    finite_dimensional_vector_space_with_overloaded
  ..



subsection‹‹vector_space_ow››


subsubsection‹Definitions and common properties›


text‹Single vector space.›

locale vector_space_ow = ab_group_add_ow UVS plusVS zeroVS minusVS uminusVS
  for UVS :: "'vs set" 
    and plusVS (infixl ‹+VS› 65)
    and zeroVS (‹0VS›)
    and minusVS (infixl ‹-VS› 65)
    and uminusVS (‹-VS _› [81] 80) +
  fixes scale :: "['f::field, 'vs] ⇒ 'vs" (infixr ‹*sow› 75)
  assumes scale_closed[simp, intro]: "x ∈ UVS ⟹ a *sow x ∈ UVS"
    and scale_right_distrib[algebra_simps]: 
    "⟦ x ∈ UVS; y ∈ UVS ⟧ ⟹ a *sow (x +VS y) = a *sow x +VS a *sow y"
    and scale_left_distrib[algebra_simps]: 
      "x ∈ UVS ⟹ (a + b) *sow x = a *sow x +VS b *sow x"
    and scale_scale[simp]: 
      "x ∈ UVS ⟹ a *sow (b *sow x) = (a * b) *sow x"
    and scale_one[simp]: "x ∈ UVS ⟹ 1 *sow x = x"
begin

lemma scale_closed'[simp]: "∀a. ∀x∈UVS. a *sow x ∈ UVS" by simp

lemma minus_closed'[simp]: "∀x∈UVS. ∀y∈UVS. x -VS y ∈ UVS"
  by (simp add: ab_diff_conv_add_uminus add_closed' uminus_closed)

lemma uminus_closed'[simp]: "∀x∈UVS. -VS x ∈ UVS" by (simp add: uminus_closed)

tts_register_sbts ‹(*sow)› | UVS
  by (rule tts_AB_C_transfer[OF scale_closed]) 
    (auto simp: bi_unique_eq right_total_eq)

sublocale implicitVS: module_ow UVS plusVS zeroVS minusVS uminusVS scale
  by unfold_locales (simp_all add: scale_right_distrib scale_left_distrib)

end

ud ‹vector_space.dim›
ud dim' ‹dim›


text‹Pair of vector spaces.›

locale vector_space_pair_ow = 
  VS1: vector_space_ow UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 +
  VS2: vector_space_ow UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  for UVS_1 :: "'vs_1 set"
    and plusVS_1 (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*sow'_1› 75)
    and UVS_2 :: "'vs_2 set"
    and plusVS_2 (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*sow'_2› 75)
begin

sublocale implicitVS: module_pair_ow 
  UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
  UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  by unfold_locales

end


text‹Linear map.›

locale linear_ow =
  VS1: vector_space_ow UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 +
  VS2: vector_space_ow UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 +
  module_hom_ow 
    UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
    UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
    f 
  for UVS_1 :: "'vs_1 set"
    and plusVS_1 (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*sow'_1› 75)
    and UVS_2 :: "'vs_2 set"
    and plusVS_2 (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*sow'_2› 75)
    and f :: "'vs_1 ⇒ 'vs_2"
begin

sublocale implicitVS: vector_space_pair_ow
  UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
  UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  by unfold_locales

end


text‹Single finite dimensional vector space.›

locale finite_dimensional_vector_space_ow = 
  vector_space_ow UVS plusVS zeroVS minusVS uminusVS scale
  for UVS :: "'vs set"
    and plusVS (infixl ‹+VS› 65)
    and zeroVS (‹0VS›)
    and minusVS (infixl ‹-VS› 65)
    and uminusVS (‹-VS _› [81] 80) 
    and scale :: "['f::field, 'vs] ⇒ 'vs" (infixr ‹*sow› 75) +
  fixes basis :: "'vs set"
  assumes basis_closed: "basis ⊆ UVS"
    and finite_basis: "finite basis"
    and independent_basis: "independent_with 0 zeroVS plusVS scale basis"
    and span_basis: "span.with zeroVS plusVS scale basis = UVS"


text‹Pair of finite dimensional vector spaces.›

locale finite_dimensional_vector_space_pair_1_ow =
  VS1: finite_dimensional_vector_space_ow
    UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1 +
  VS2: vector_space_ow 
    UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
  for UVS_1 :: "'vs_1 set"
    and plusVS_1 (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*sow'_1› 75)
    and basis1
    and UVS_2 :: "'vs_2 set"
    and plusVS_2 (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*sow'_2› 75)

locale finite_dimensional_vector_space_pair_ow = 
  VS1: finite_dimensional_vector_space_ow 
    UVS_1 plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1 + 
  VS2: finite_dimensional_vector_space_ow 
    UVS_2 plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 basis2
  for UVS_1 :: "'vs_1 set"
    and plusVS_1 (infixl ‹+VS'_1› 65)
    and zeroVS_1 (‹0VS'_1›)
    and minusVS_1 (infixl ‹-VS'_1› 65)
    and uminusVS_1 (‹-VS'_1 _› [81] 80)
    and scale1 :: "['f::field, 'vs_1] ⇒ 'vs_1" (infixr ‹*sow'_1› 75)
    and basis1
    and UVS_2 :: "'vs_2 set"
    and plusVS_2 (infixl ‹+VS'_2› 65)
    and zeroVS_2 (‹0VS'_2›)
    and minusVS_2 (infixl ‹-VS'_2› 65)
    and uminusVS_2 (‹-VS'_2 _› [81] 80)
    and scale2 :: "['f::field, 'vs_2] ⇒ 'vs_2" (infixr ‹*sow'_2› 75)
    and basis2


subsubsection‹Transfer.›

lemma vector_space_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 ≡ 
        (
          λplusVS zeroVS minusVS uminusVS scale.
            vector_space_ow 
              (Collect (Domainp B)) plusVS zeroVS minusVS uminusVS scale
        )"
  shows "PP lhs vector_space_with"
proof-
  let ?rhs = 
    "(
      λplusVS zeroVS minusVS uminusVS scale.
        (∀a ∈ UNIV. ∀x ∈ UNIV. scale a x ∈ UNIV) ∧
         vector_space_with plusVS zeroVS minusVS uminusVS scale
    )"
  have "PP lhs ?rhs"
    unfolding 
      PP_def lhs_def
      vector_space_ow_def vector_space_with_def
      vector_space_ow_axioms_def vector_space_with_axioms_def
    apply transfer_prover_start
    apply transfer_step+
    by (intro ext) blast
  then show ?thesis by simp
qed

lemma vector_space_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 ≡ 
        (
          λ
            plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2.
          vector_space_pair_ow 
            (Collect (Domainp B1)) plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            (Collect (Domainp B2)) plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
        )"
    shows "PP lhs vector_space_pair_with"
  unfolding PP_def lhs_def
  unfolding vector_space_pair_ow_def vector_space_pair_with_def
  by transfer_prover

lemma linear_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 ≡ 
        (
          λ
            plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
            f.
          linear_ow 
            (Collect (Domainp B1)) plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            (Collect (Domainp B2)) plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
            f
        )
      "
    shows "PP lhs linear_with"
  unfolding PP_def lhs_def
  unfolding linear_ow_def linear_with_def
  by transfer_prover

lemma linear_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) ===>
        (B ===> B ===> B) ===>
        B ===>
        (B ===> B ===> B) ===>
        (B ===> B) ===>
        ((=) ===> B ===> B) ===>
        (B ===> B) ===>
        (=)
    )"
    and
      "lhs ≡ 
        (
          λ
            plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
            f.
          linear_ow 
            (Collect (Domainp B)) plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1
            (Collect (Domainp B)) plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
            f
        )
      "
    shows "PP lhs linear_with"
  unfolding PP_def lhs_def
  using assms(1,2) by (rule linear_with_transfer[OF assms(1,2)])

lemma finite_dimensional_vector_space_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) ===>
        rel_set B ===>
        (=)
      )"
    and
      "lhs ≡ 
        (
          λplusVS zeroVS minusVS uminusVS scale basis.
            finite_dimensional_vector_space_ow 
              (Collect (Domainp B)) plusVS zeroVS minusVS uminusVS scale basis
        )"
    shows "PP lhs finite_dimensional_vector_space_with"
proof-
  let ?rhs = 
    "(
      λplusVS zeroVS minusVS uminusVS scale basis.
        basis ⊆ UNIV ∧
        finite_dimensional_vector_space_with 
          plusVS zeroVS minusVS uminusVS scale basis
    )"
  have "PP lhs ?rhs"
    unfolding 
      PP_def lhs_def
      finite_dimensional_vector_space_ow_def 
      finite_dimensional_vector_space_with_def
      finite_dimensional_vector_space_ow_axioms_def
      finite_dimensional_vector_space_with_axioms_def
    apply transfer_prover_start
    apply transfer_step+
    by blast
  then show ?thesis by simp
qed

lemma finite_dimensional_vector_space_pair_1_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) ===>
        rel_set B1 ===>
        (B2 ===> B2 ===> B2) ===>
        B2 ===>
        (B2 ===> B2 ===> B2) ===>
        (B2 ===> B2) ===>
        ((=) ===> B2 ===> B2) ===>
        (=)
    )"
    and
      "lhs ≡ 
        (
          λ
            plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1
            plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2.
          finite_dimensional_vector_space_pair_1_ow 
            (Collect (Domainp B1)) 
              plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1
            (Collect (Domainp B2)) 
              plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2
        )"
    shows "PP lhs finite_dimensional_vector_space_pair_1_with"
  unfolding PP_def lhs_def
  unfolding 
    finite_dimensional_vector_space_pair_1_ow_def
    finite_dimensional_vector_space_pair_1_with_def
  by transfer_prover

lemma finite_dimensional_vector_space_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) ===>
        rel_set B1 ===>
        (B2 ===> B2 ===> B2) ===>
        B2 ===>
        (B2 ===> B2 ===> B2) ===>
        (B2 ===> B2) ===>
        ((=) ===> B2 ===> B2) ===>
        rel_set B2 ===>
        (=)
      )"
    and
      "lhs ≡ 
        (
          λ
            plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1
            plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 basis2.
          finite_dimensional_vector_space_pair_ow 
            (Collect (Domainp B1)) 
              plusVS_1 zeroVS_1 minusVS_1 uminusVS_1 scale1 basis1
            (Collect (Domainp B2)) 
              plusVS_2 zeroVS_2 minusVS_2 uminusVS_2 scale2 basis2
        )"
    shows "PP lhs finite_dimensional_vector_space_pair_with"
  unfolding PP_def lhs_def
  unfolding 
    finite_dimensional_vector_space_pair_ow_def
    finite_dimensional_vector_space_pair_with_def
  by transfer_prover



subsection‹‹vector_space_on››

locale vector_space_on = module_on UVS scale
  for UVS and scale :: "'a::field ⇒ 'b::ab_group_add ⇒ 'b" (infixr ‹*s› 75)
begin

notation scale (infixr ‹*s› 75)

sublocale implicitVS: vector_space_ow UVS ‹(+)› 0 ‹(-)› uminus scale
  by unfold_locales 
    (simp_all add: scale_right_distrib_on scale_left_distrib_on)

lemmas ab_group_add_ow_axioms = implicitM.ab_group_add_ow_axioms
lemmas vector_space_ow_axioms = implicitVS.vector_space_ow_axioms

definition dim :: "'b set ⇒ nat"
  where "dim V = (if ∃b⊆UVS. ¬ dependent b ∧ span b = span V
    then card (SOME b. b ⊆ UVS ∧ ¬ dependent b ∧ span b = span V)
    else 0)"

end

lemma vector_space_on_alt_def: "vector_space_on UVS = module_on UVS"
  unfolding vector_space_on_def module_on_def
  by auto

lemma implicit_vector_space_ow[tts_implicit]:
  "vector_space_ow UVS (+) 0 (-) uminus = vector_space_on UVS"
proof(intro ext, rule iffI)
  fix s :: "'a ⇒ 'b ⇒ 'b" 
  assume "vector_space_ow UVS (+) 0 (-) uminus s"
  then interpret vector_space_ow UVS ‹(+)› 0 ‹(-)› uminus s .
  show "vector_space_on UVS s"
    by 
      (
        simp add: 
          scale_left_distrib 
          scale_right_distrib
          module_on_def 
          vector_space_on_def
      )
qed (rule vector_space_on.vector_space_ow_axioms)

locale linear_on = 
  VS1: vector_space_on UM_1 scale1 +
  VS2: vector_space_on UM_2 scale2 +
  module_hom_on UM_1 UM_2 scale1 scale2 f
  for UM_1 UM_2 and scale1::"'a::field ⇒ 'b ⇒ 'b::ab_group_add"
    and scale2::"'a::field ⇒ 'c ⇒ 'c::ab_group_add"
    and f

lemma implicit_linear_on[tts_implicit]:
  "linear_ow UM_1 (+) 0 minus uminus scale1 UM_2 (+) 0 (-) uminus scale2 = 
    linear_on UM_1 UM_2 scale1 scale2"
  unfolding linear_ow_def linear_on_def tts_implicit ..

locale finite_dimensional_vector_space_on =
  vector_space_on UVS scale 
  for UVS :: "'b::ab_group_add set" 
    and scale :: "'a::field ⇒ 'b ⇒ 'b" +
  fixes basis :: "'b set"
  assumes finite_basis: "finite basis"
    and independent_basis: "¬ dependent basis"
    and span_basis: "span basis = UVS" 
    and basis_subset: "basis ⊆ UVS"
begin

sublocale implicitVS: 
  finite_dimensional_vector_space_ow UVS ‹(+)› 0 ‹(-)› uminus scale basis
  by unfold_locales 
    (
      simp_all add: 
        finite_basis 
        implicit_dependent_with 
        independent_basis  
        implicit_span_with
        span_basis
        basis_subset
    )

end

lemma implicit_finite_dimensional_vector_space_on[tts_implicit]:
  "finite_dimensional_vector_space_ow UVS (+) 0 minus uminus scale basis = 
    finite_dimensional_vector_space_on UVS scale basis"
  unfolding 
    finite_dimensional_vector_space_ow_def 
    finite_dimensional_vector_space_on_def  
    finite_dimensional_vector_space_ow_axioms_def
    finite_dimensional_vector_space_on_axioms_def  
    vector_space_on_alt_def
    tts_implicit
  by (metis module_on.implicit_dependent_with module_on.implicit_span_with)  

locale vector_space_pair_on = 
  VS1: vector_space_on UM_1 scale1 +
  VS2: vector_space_on UM_2 scale2
  for UM_1:: "'b::ab_group_add set" and UM_2::"'c::ab_group_add set"
    and scale1::"'a::field ⇒ _ ⇒ _" (infixr ‹*s1› 75) 
    and scale2::"'a ⇒ _ ⇒ _" (infixr ‹*s2› 75)
begin

notation scale1 (infixr ‹*s1› 75)
notation scale2 (infixr ‹*s2› 75)

sublocale module_pair_on UM_1 UM_2 scale1 scale2 by unfold_locales

sublocale implicitVS: 
  vector_space_pair_ow 
    UM_1 ‹(+)› 0 ‹(-)› uminus scale1 
    UM_2 ‹(+)› 0 ‹(-)› uminus scale2
  by unfold_locales

end

lemma implicit_vector_space_pair_on[tts_implicit]:
  "vector_space_pair_ow 
    UM_1 (+) 0 (-) uminus scale1 
    UM_2 (+) 0 (-) uminus scale2 = 
    vector_space_pair_on UM_1 UM_2 scale1 scale2"
  unfolding vector_space_pair_ow_def vector_space_pair_on_def tts_implicit ..

locale finite_dimensional_vector_space_pair_1_on =
  VS1: finite_dimensional_vector_space_on UM_1 scale1 basis1 +
  VS2: vector_space_on UM_2 scale2
  for UM_1 UM_2
    and scale1::"'a::field ⇒ 'b::ab_group_add ⇒ 'b"
    and scale2::"'a::field ⇒ 'c::ab_group_add ⇒ 'c"
    and basis1
begin

sublocale vector_space_pair_on UM_1 UM_2 scale1 scale2 by unfold_locales

sublocale implicitVS:
  finite_dimensional_vector_space_pair_1_ow 
    UM_1 ‹(+)› 0 ‹(-)› uminus scale1 basis1 UM_2 ‹(+)› 0 ‹(-)› uminus scale2
  by unfold_locales

end

lemma implicit_finite_dimensional_vector_space_pair_1_on[tts_implicit]:
  "finite_dimensional_vector_space_pair_1_ow 
    UM_1 (+) 0 minus uminus scale1 basis1 UM_2 (+) 0 (-) uminus scale2 = 
    finite_dimensional_vector_space_pair_1_on UM_1 UM_2 scale1 scale2 basis1"
  unfolding 
    finite_dimensional_vector_space_pair_1_ow_def 
    finite_dimensional_vector_space_pair_1_on_def 
    tts_implicit 
    ..

locale finite_dimensional_vector_space_pair_on =
  VS1: finite_dimensional_vector_space_on UM_1 scale1 basis1 +
  VS2: finite_dimensional_vector_space_on UM_2 scale2 basis2
  for UM_1 UM_2
    and scale1::"'a::field ⇒ 'b::ab_group_add ⇒ 'b"
    and scale2::"'a::field ⇒ 'c::ab_group_add ⇒ 'c"
    and basis1 basis2
begin

sublocale finite_dimensional_vector_space_pair_1_on UM_1 UM_2 scale1 scale2 
  by unfold_locales

sublocale implicitVS: 
  finite_dimensional_vector_space_pair_ow 
    UM_1 ‹(+)› 0 ‹(-)› uminus scale1 basis1 
    UM_2 ‹(+)› 0 ‹(-)› uminus scale2 basis2
  by unfold_locales

end

lemma implicit_finite_dimensional_vector_space_pair_on[tts_implicit]:
  "finite_dimensional_vector_space_pair_ow 
      UM_1 (+) 0 minus uminus scale1 basis1 
      UM_2 (+) 0 (-) uminus scale2 basis2 = 
    finite_dimensional_vector_space_pair_on 
      UM_1 UM_2 scale1 scale2 basis1 basis2"
  unfolding 
    finite_dimensional_vector_space_pair_ow_def 
    finite_dimensional_vector_space_pair_on_def 
    tts_implicit 
    ..



subsection‹Relativization : part I›

context vector_space_on
begin

tts_context
  tts: (?'b to ‹UVS::'b set›)
  rewriting ctr_simps
  substituting ab_group_add_ow_axioms
    and vector_space_ow_axioms
    and implicitM.module_ow_axioms
  applying 
    [
      OF 
        implicitM.carrier_ne 
        implicitM.add_closed' 
        implicitM.zero_closed 
        implicitVS.minus_closed' 
        implicitVS.uminus_closed' 
        implicitVS.scale_closed',
      unfolded tts_implicit
    ]
begin

tts_lemma linear_id: "linear_on UVS UVS (*s) (*s) id"
  is vector_space.linear_id.

tts_lemma linear_ident: "linear_on UVS UVS (*s) (*s) (λx. x)"
  is vector_space.linear_ident.
    
tts_lemma linear_scale_self: "linear_on UVS UVS (*s) (*s) ((*s) c)"
  is vector_space.linear_scale_self.
    
tts_lemma linear_scale_left:
  assumes "x ∈ UVS"
  shows "linear_on UNIV UVS (*) (*s) (λr. r *s x)"
    is vector_space.linear_scale_left.
    
tts_lemma linear_uminus: "linear_on UVS UVS (*s) (*s) uminus"
    is vector_space.linear_uminus.
    
tts_lemma linear_imp_scale["consumes" - 1, "case_names" "1"]:
  assumes "range D ⊆ UVS"
    and "linear_on UNIV UVS (*) (*s) D"
    and "⋀d. ⟦d ∈ UVS; D = (λx. x *s d)⟧ ⟹ thesis"
  shows thesis
    is vector_space.linear_imp_scale.

tts_lemma scale_eq_0_iff:
  assumes "x ∈ UVS"
  shows "(a *s x = 0) = (a = 0 ∨ x = 0)"
    is vector_space.scale_eq_0_iff.

tts_lemma scale_left_imp_eq:
  assumes "x ∈ UVS" and "y ∈ UVS" and "a ≠ 0" and "a *s x = a *s y"
  shows "x = y"
    is vector_space.scale_left_imp_eq.

tts_lemma scale_right_imp_eq:
  assumes "x ∈ UVS" and "x ≠ 0" and "a *s x = b *s x"
  shows "a = b"
    is vector_space.scale_right_imp_eq.

tts_lemma scale_cancel_left:
  assumes "x ∈ UVS" and "y ∈ UVS"
  shows "(a *s x = a *s y) = (x = y ∨ a = 0)"
    is vector_space.scale_cancel_left.

tts_lemma scale_cancel_right:
  assumes "x ∈ UVS"
  shows "(a *s x = b *s x) = (a = b ∨ x = 0)"
    is vector_space.scale_cancel_right.

tts_lemma injective_scale:
  assumes "c ≠ 0"
  shows "inj_on ((*s) c) UVS"
    is vector_space.injective_scale.

tts_lemma dependent_def:
  assumes "P ⊆ UVS"
  shows "dependent P = (∃x∈P. x ∈ span (P - {x}))"
    is vector_space.dependent_def.

tts_lemma dependent_single:
  assumes "x ∈ UVS"
  shows "dependent {x} = (x = 0)"
    is vector_space.dependent_single.

tts_lemma in_span_insert:
  assumes "a ∈ UVS"
    and "b ∈ UVS"
    and "S ⊆ UVS"
    and "a ∈ span (insert b S)"
    and "a ∉ span S"
  shows "b ∈ span (insert a S)"
    is vector_space.in_span_insert.

tts_lemma dependent_insertD:
  assumes "a ∈ UVS" and "S ⊆ UVS" and "a ∉ span S" and "dependent (insert a S)"
  shows "dependent S"
    is vector_space.dependent_insertD.

tts_lemma independent_insertI:
  assumes "a ∈ UVS" and "S ⊆ UVS" and "a ∉ span S" and "¬ dependent S"
  shows "¬ dependent (insert a S)"
    is vector_space.independent_insertI.

tts_lemma independent_insert:
  assumes "a ∈ UVS" and "S ⊆ UVS"
  shows "(¬ dependent (insert a S)) = 
    (if a ∈ S then ¬ dependent S else ¬ dependent S ∧ a ∉ span S)"
    is vector_space.independent_insert.

tts_lemma maximal_independent_subset_extend["consumes" - 1, "case_names" "1"]:
  assumes "S ⊆ UVS"
    and "V ⊆ UVS"
    and "S ⊆ V"
    and "¬ dependent S"
    and "⋀B. ⟦B ⊆ UVS; S ⊆ B; B ⊆ V; ¬ dependent B; V ⊆ span B⟧ ⟹ thesis"
  shows thesis
    is vector_space.maximal_independent_subset_extend.

tts_lemma maximal_independent_subset["consumes" - 1, "case_names" "1"]:
  assumes "V ⊆ UVS"
    and "⋀B. ⟦B ⊆ UVS; B ⊆ V; ¬ dependent B; V ⊆ span B⟧ ⟹ thesis"
  shows thesis
    is vector_space.maximal_independent_subset.

tts_lemma in_span_delete:
  assumes "a ∈ UVS"
    and "S ⊆ UVS"
    and "b ∈ UVS"
    and "a ∈ span S"
    and "a ∉ span (S - {b})"
  shows "b ∈ span (insert a (S - {b}))"
    is vector_space.in_span_delete.

tts_lemma span_redundant:
  assumes "x ∈ UVS" and "S ⊆ UVS" and "x ∈ span S"
  shows "span (insert x S) = span S"
    is vector_space.span_redundant.

tts_lemma span_trans:
  assumes "x ∈ UVS"
    and "S ⊆ UVS"
    and "y ∈ UVS"
    and "x ∈ span S"
    and "y ∈ span (insert x S)"
  shows "y ∈ span S"
    is vector_space.span_trans.

tts_lemma span_insert_0:
  assumes "S ⊆ UVS"
  shows "span (insert 0 S) = span S"
    is vector_space.span_insert_0.

tts_lemma span_delete_0:
  assumes "S ⊆ UVS"
  shows "span (S - {0}) = span S"
    is vector_space.span_delete_0.

tts_lemma span_image_scale:
  assumes "S ⊆ UVS" and "finite S" and "⋀x. ⟦x ∈ UVS; x ∈ S⟧ ⟹ c x ≠ 0"
  shows "span ((λx. c x *s x) ` S) = span S"
    is vector_space.span_image_scale.

tts_lemma exchange_lemma:
  assumes "T ⊆ UVS"
    and "S ⊆ UVS"
    and "finite T"
    and "¬dependent S"
    and "S ⊆ span T"
  shows "∃t'∈Pow UVS. 
    card t' = card T ∧ finite t' ∧ S ⊆ t' ∧ t' ⊆ S ∪ T ∧ S ⊆ span t'"
    is vector_space.exchange_lemma.

tts_lemma independent_span_bound:
  assumes "T ⊆ UVS"
    and "S ⊆ UVS"
    and "finite T"
    and "¬ dependent S"
    and "S ⊆ span T"
  shows "finite S ∧ card S ≤ card T"
    is vector_space.independent_span_bound.

tts_lemma independent_explicit_finite_subsets:
  assumes "A ⊆ UVS"
  shows "(¬ dependent A) = 
    (
      ∀x⊆UVS. 
        x ⊆ A ⟶ 
        finite x ⟶ 
        (∀f. (∑v∈x. f v *s v) = 0 ⟶ (∀x∈x. f x = 0))
    )"
    given vector_space.independent_explicit_finite_subsets by auto

tts_lemma independent_if_scalars_zero:
  assumes "A ⊆ UVS"
    and "finite A"
    and "⋀f x. ⟦x ∈ UVS; (∑x∈A. f x *s x) = 0; x ∈ A⟧ ⟹ f x = 0"
  shows "¬ dependent A"
    is vector_space.independent_if_scalars_zero.

tts_lemma subspace_sums:
  assumes "S ⊆ UVS" and "T ⊆ UVS" and "subspace S" and "subspace T"
  shows "subspace {x ∈ UVS. ∃a∈UVS. ∃b∈UVS. x = a + b ∧ a ∈ S ∧ b ∈ T}"
    is vector_space.subspace_sums.

tts_lemma bij_if_span_eq_span_bases:
  assumes "B ⊆ UVS"
    and "C ⊆ UVS"
    and "¬dependent B"
    and "¬dependent C"
    and "span B = span C"
  shows "∃x. bij_betw x B C ∧ (∀a∈UVS. x a ∈ UVS)"
    given vector_space.bij_if_span_eq_span_bases by blast

end

end



subsection‹Transfer: ‹dim››

context vector_space_on
begin

lemma dim_eq_card:
  assumes "B ⊆ UVS"
    and "V ⊆ UVS"
    and BV: "span B = span V" 
    and B: "¬dependent B"
  shows "dim V = card B"
proof-
  define p where "p b ≡ b ⊆ UVS ∧ ¬dependent b ∧ span b = span V" for b
  from assms have "p (SOME B. p B)"
    by (intro someI[of p B], unfold p_def) simp
  then have "∃f. bij_betw f B (SOME B. p B) ∧ (∀x∈UVS. f x ∈ UVS)"
    by (subst (asm) p_def, intro bij_if_span_eq_span_bases) (simp_all add: assms)
  then have "card B = card (SOME B. p B)" by (auto intro: bij_betw_same_card)
  then show ?thesis using assms(1,3,4) unfolding dim_def p_def by auto
qed

lemma dim_transfer[transfer_rule]: 
  includes lifting_syntax                               
  assumes [transfer_domain_rule]: "Domainp A = (λx. x ∈ UVS)"
    and [transfer_rule]: "right_total A" "bi_unique A"
    and [transfer_rule]: "(A ===> A ===> A) plus plus'"
    and [transfer_rule]: "((=) ===> A ===> A) scale scale'"
    and [transfer_rule]: "A 0 zero'"
  shows "(rel_set A ===> (=)) dim (dim.with plus' zero' 0 scale')"
proof(rule rel_funI)
  
  (* preliminaries *)
  have rt_rlA: "right_total (rel_set A)"
    using assms using right_total_rel_set by auto
  have Dom_rsA: "Domainp (rel_set A) x = (x ⊆ UVS)" for x
    by (meson Domainp_set assms(1) in_mono subsetI)

  (* hypothesis and preliminary derived results *)
  fix V V' assume [transfer_rule]: "rel_set A V V'"
  with assms have subset: "V ⊆ UVS" 
    by (metis Domainp.DomainI rel_setD1 subsetI)
  then have "span V ⊆ UVS" by (simp add: span_minimal subspace_UNIV)

  (* convenience definitions *)
  define P' where "P' =
    (
      ∃b. 
        (with 0 zero' plus' scale' : «independent» b) ∧ 
        (with zero' plus' scale' : «span» b) = 
          (with zero' plus' scale' : «span» V')
    )"
  define P where "P = 
    (∃b⊆UVS. ¬ dependent b ∧ span b = span V)"
  have "P = P'" 
    unfolding P_def P'_def by (transfer, unfold tts_implicit) blast
  define f where "f b = (b ⊆ UVS ∧ ¬ dependent b ∧ span b = span V)" for b
  define f' where "f' b = (b ⊆ UVS ∧ f b)" for b
  have "f = f'" unfolding f'_def f_def by simp
  define g where "g b = 
    (
      (with 0 zero' plus' scale' : «independent» b) ∧ 
      (with zero' plus' scale': «span» b) = 
      (with zero' plus' scale' : «span» V')
    )"
    for b
  define g' where "g' b = (b ⊆ UNIV ∧ g b)" for b
  have "g = g'" unfolding g_def g'_def by simp

  (* towards Eps_unique_transfer_lemma *)
  have fg[transfer_rule]: "(rel_set A ===> (=)) f g"
    unfolding ‹g = g'› 
    unfolding f_def g'_def g_def tts_implicit[symmetric]
    apply transfer_prover_start
    apply transfer_step+
    by simp
  have ex_Dom_rsA: "∃x. Domainp (rel_set A) x ∧ f x"
    unfolding Dom_rsA f_def 
    by 
      (
        meson   
          ‹span V ⊆ UVS› 
          maximal_independent_subset 
          span_subspace 
          subspace_span 
          subset
      )
  have card_xy: "⋀x y. ⟦g x; g y⟧ ⟹ card x = card y"
    by (transfer, unfold f_def) (metis dim_eq_card)

  (* main *)
  show "dim V = dim.with plus' zero' 0 scale' V'"
  proof(cases ‹P'›)
    case True
    then have P unfolding ‹P = P'› .
    then have dim: "dim V = card (SOME b. f b)"
      unfolding dim_def P_def f_def by simp
    from True have dw: "dim.with plus' zero' 0 scale' V' = card (SOME b. g b)"
      unfolding dim.with_def P'_def g_def by simp
    from Eps_unique_transfer_lemma[
        OF rt_rlA fg card_transfer[OF ‹bi_unique A›] ex_Dom_rsA card_xy, 
        simplified,
        unfolded Dom_rsA,
        folded f'_def ‹f = f'›
        ]
    show "dim V = dim.with plus' zero' 0 scale' V'" 
      unfolding dim dw by simp
  next
    case False
    then have "¬P" unfolding ‹P = P'› .
    then have dim: "dim V = 0" unfolding dim_def P_def by auto 
    moreover from False have dw: "dim.with plus' zero'  0 scale' V' = 0"
      unfolding dim.with_def P'_def g_def by auto
    ultimately show ?thesis by simp
  qed

qed

end



subsection‹Relativization: part II›

context vector_space_on
begin

tts_context
  tts: (?'b to ‹UVS::'b set›)
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and 
      (
        ‹?scale::?'a::field ⇒?'b::ab_group_add⇒?'b::ab_group_add› to 
        ‹(*s)::'a⇒'b⇒'b›
      )
    and (‹0::?'b::ab_group_add› to ‹0::'b›)
  rewriting ctr_simps
  substituting ab_group_add_ow_axioms 
    and vector_space_ow_axioms
    and implicitM.module_ow_axioms
  eliminating ‹?a ∈ ?A› and ‹?B ⊆ ?C› through auto
  applying 
    [
      OF 
        implicitM.carrier_ne 
        implicitVS.minus_closed' 
        implicitVS.uminus_closed', 
      unfolded tts_implicit
     ]
begin

tts_lemma dim_unique:
  assumes "V ⊆ UVS"
    and "B ⊆ V"
    and "V ⊆ span B"
    and "¬ dependent B"
    and "card B = n"
  shows "dim V = n"
    is vector_space.dim_unique.
    
tts_lemma basis_card_eq_dim:
  assumes "V ⊆ UVS" and "B ⊆ V" and "V ⊆ span B" and "¬ dependent B"
  shows "card B = dim V"
    is vector_space.basis_card_eq_dim.
    
tts_lemma dim_eq_card_independent:
  assumes "B ⊆ UVS" and "¬ dependent B"
  shows "dim B = card B"
    is vector_space.dim_eq_card_independent.

tts_lemma dim_span:
  assumes "S ⊆ UVS"
  shows "dim (span S) = dim S"
    is vector_space.dim_span.

tts_lemma dim_span_eq_card_independent:
  assumes "B ⊆ UVS" and "¬ dependent B"
  shows "dim (span B) = card B"
    is vector_space.dim_span_eq_card_independent.

tts_lemma dim_le_card:
  assumes "V ⊆ UVS" and "W ⊆ UVS" and "V ⊆ span W" and "finite W"
  shows "dim V ≤ card W"
    is vector_space.dim_le_card.

tts_lemma span_eq_dim:
  assumes "S ⊆ UVS" and "T ⊆ UVS" and "span S = span T"
  shows "dim S = dim T"
    is vector_space.span_eq_dim.

tts_lemma dim_le_card':
  assumes "s ⊆ UVS" and "finite s"
  shows "dim s ≤ card s"
    is vector_space.dim_le_card'.

tts_lemma span_card_ge_dim:
  assumes "V ⊆ UVS" and "B ⊆ V" and "V ⊆ span B" and "finite B"
  shows "dim V ≤ card B"
    is vector_space.span_card_ge_dim.

end

tts_context
  tts: (?'b to ‹UVS::'b set›) 
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and (‹?scale::?'a::field ⇒?'b::ab_group_add⇒?'b› to ‹(*s)::'a⇒'b⇒'b›)
    and (‹0::?'b::ab_group_add› to ‹0::'b›)
  rewriting ctr_simps
  substituting ab_group_add_ow_axioms 
    and vector_space_ow_axioms
    and implicitM.module_ow_axioms
  applying 
    [
      OF 
        implicitM.carrier_ne 
        implicitVS.minus_closed' 
        implicitVS.uminus_closed', 
        unfolded tts_implicit
     ]
begin
  
tts_lemma basis_exists:
  assumes "V ⊆ UVS"
    and "⋀B. 
      ⟦
        B ⊆ UVS; 
        B ⊆ V; 
        ¬ dependent B; 
        V ⊆ span B; 
        card B = dim V
      ⟧ ⟹ thesis"
  shows thesis
    is vector_space.basis_exists.

end

end

context finite_dimensional_vector_space_on 
begin

tts_context
  tts: (?'b to ‹UVS::'b set›)
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and (‹?scale::?'a::field ⇒?'b::ab_group_add⇒?'b› to ‹(*s)::'a⇒'b⇒'b›)
    and (‹0::?'b::ab_group_add› to ‹0::'b›)
  rewriting ctr_simps
  substituting ab_group_add_ow_axioms
    and vector_space_ow_axioms
    and implicitVS.finite_dimensional_vector_space_ow_axioms
    and implicitM.module_ow_axioms
  eliminating ‹?a ∈ ?A› and ‹?B ⊆ ?C› through auto
  applying 
    [
      OF 
        implicitM.carrier_ne 
        implicitVS.minus_closed' 
        implicitVS.uminus_closed' 
        basis_subset, 
      unfolded tts_implicit
    ]
begin

tts_lemma finiteI_independent:
  assumes "B ⊆ UVS" and "¬ dependent B"
  shows "finite B"
  is finite_dimensional_vector_space.finiteI_independent.

tts_lemma dim_empty: "dim {} = 0"
  is finite_dimensional_vector_space.dim_empty.
    
tts_lemma dim_insert:
  assumes "x ∈ UVS" and "S ⊆ UVS"
  shows "dim (insert x S) = (if x ∈ span S then dim S else dim S + 1)"
    is finite_dimensional_vector_space.dim_insert.
    
tts_lemma dim_singleton:
  assumes "x ∈ UVS"
  shows "dim {x} = (if x = 0 then 0 else 1)"
    is finite_dimensional_vector_space.dim_singleton.

tts_lemma choose_subspace_of_subspace["consumes" - 1, "case_names" "1"]:
  assumes "S ⊆ UVS"
    and "n ≤ dim S"
    and "⋀T. ⟦T ⊆ UVS; subspace T; T ⊆ span S; dim T = n⟧ ⟹ thesis"
  shows thesis
    is finite_dimensional_vector_space.choose_subspace_of_subspace.

tts_lemma basis_subspace_exists["consumes" - 1, "case_names" "1"]:
  assumes "S ⊆ UVS"
    and "subspace S"
    and "⋀B. 
      ⟦
        B ⊆ UVS; 
        finite B; 
        B ⊆ S; 
        ¬ dependent B; 
        span B = S; 
        card B = dim S
      ⟧ ⟹ thesis"
  shows thesis
    is finite_dimensional_vector_space.basis_subspace_exists.

tts_lemma dim_mono:
  assumes "V ⊆ UVS" and "W ⊆ UVS" and "V ⊆ span W"
  shows "dim V ≤ dim W"
    is finite_dimensional_vector_space.dim_mono.

tts_lemma dim_subset:
  assumes "T ⊆ UVS" and "S ⊆ T"
  shows "dim S ≤ dim T"
    is finite_dimensional_vector_space.dim_subset.

tts_lemma dim_eq_0:
  assumes "S ⊆ UVS"
  shows "(dim S = 0) = (S ⊆ {0})"
    is finite_dimensional_vector_space.dim_eq_0.

tts_lemma dim_UNIV: "dim UVS = card basis"
    is finite_dimensional_vector_space.dim_UNIV.

tts_lemma independent_card_le_dim:
  assumes "V ⊆ UVS" and "B ⊆ V" and "¬ dependent B"
  shows "card B ≤ dim V"
    is finite_dimensional_vector_space.independent_card_le_dim.

tts_lemma card_ge_dim_independent:
  assumes "V ⊆ UVS" and "B ⊆ V" and "¬ dependent B" and "dim V ≤ card B"
  shows "V ⊆ span B"
    is finite_dimensional_vector_space.card_ge_dim_independent.

tts_lemma card_le_dim_spanning:
  assumes "V ⊆ UVS"
    and "B ⊆ V"
    and "V ⊆ span B"
    and "finite B"
    and "card B ≤ dim V"
  shows "¬ dependent B"
    is finite_dimensional_vector_space.card_le_dim_spanning.

tts_lemma card_eq_dim:
  assumes "V ⊆ UVS" and "B ⊆ V" and "card B = dim V" and "finite B"
  shows "(¬ dependent B) = (V ⊆ span B)"
    is finite_dimensional_vector_space.card_eq_dim.

tts_lemma subspace_dim_equal:
  assumes "T ⊆ UVS"
    and "subspace S"
    and "subspace T"
    and "S ⊆ T"
    and "dim T ≤ dim S"
  shows "S = T"
    is finite_dimensional_vector_space.subspace_dim_equal.

tts_lemma dim_eq_span:
  assumes "T ⊆ UVS" and "S ⊆ T" and "dim T ≤ dim S"
  shows "span S = span T"
    is finite_dimensional_vector_space.dim_eq_span.

tts_lemma dim_psubset:
  assumes "S ⊆ UVS" and "T ⊆ UVS" and "span S ⊂ span T"
  shows "dim S < dim T"
    is finite_dimensional_vector_space.dim_psubset.

tts_lemma indep_card_eq_dim_span:
  assumes "B ⊆ UVS" and "¬ dependent B"
  shows "finite B ∧ card B = dim (span B)"
    is finite_dimensional_vector_space.indep_card_eq_dim_span.

tts_lemma independent_bound_general:
  assumes "S ⊆ UVS" and "¬ dependent S"
  shows "finite S ∧ card S ≤ dim S"
    is finite_dimensional_vector_space.independent_bound_general.

tts_lemma independent_explicit:
  assumes "B ⊆ UVS"
  shows "(¬ dependent B) = 
    (finite B ∧ (∀x. (∑v∈B. x v *s v) = 0 ⟶ (∀a∈B. x a = 0)))"
    is finite_dimensional_vector_space.independent_explicit.

tts_lemma dim_sums_Int:
  assumes "S ⊆ UVS" and "T ⊆ UVS" and "subspace S" and "subspace T"
  shows 
    "dim {x ∈ UVS. ∃y∈UVS. ∃z∈UVS. x = y + z ∧ y ∈ S ∧ z ∈ T} + dim (S ∩ T) = 
      dim S + dim T"
    is finite_dimensional_vector_space.dim_sums_Int.

tts_lemma dependent_biggerset_general:
  assumes "S ⊆ UVS" and "finite S ⟹ dim S < card S"
  shows "dependent S"
    is finite_dimensional_vector_space.dependent_biggerset_general.

tts_lemma subset_le_dim:
  assumes "S ⊆ UVS" and "T ⊆ UVS" and "S ⊆ span T"
  shows "dim S ≤ dim T"
    is finite_dimensional_vector_space.subset_le_dim.

tts_lemma linear_inj_imp_surj:
  assumes "∀x∈UVS. f x ∈ UVS"
    and "linear_on UVS UVS (*s) (*s) f"
    and "inj_on f UVS"
  shows "f ` UVS = UVS"
    is finite_dimensional_vector_space.linear_inj_imp_surj.

tts_lemma linear_surj_imp_inj:
  assumes "∀x∈UVS. f x ∈ UVS"
    and "linear_on UVS UVS (*s) (*s) f"
    and "f ` UVS = UVS"
  shows "inj_on f UVS"
    is finite_dimensional_vector_space.linear_surj_imp_inj.

tts_lemma linear_inverse_left:
  assumes "∀x∈UVS. f x ∈ UVS"
    and "∀x∈UVS. f' x ∈ UVS"
    and "linear_on UVS UVS (*s) (*s) f"
    and "linear_on UVS UVS (*s) (*s) f'"
  shows "(∀x∈UVS. (f ∘ f') x = id x) = (∀x∈UVS. (f' ∘ f) x = id x)"
    is finite_dimensional_vector_space.linear_inverse_left[unfolded fun_eq_iff].

tts_lemma left_inverse_linear:
  assumes "∀x∈UVS. f x ∈ UVS"
    and "∀x∈UVS. g x ∈ UVS"
    and "linear_on UVS UVS (*s) (*s) f"
    and "∀x∈UVS. (g ∘ f) x = id x"
  shows "linear_on UVS UVS (*s) (*s) g"
    is finite_dimensional_vector_space.left_inverse_linear[unfolded fun_eq_iff].

tts_lemma right_inverse_linear:
  assumes "∀x∈UVS. f x ∈ UVS"
    and "∀x∈UVS. g x ∈ UVS"
    and "linear_on UVS UVS (*s) (*s) f"
    and "∀x∈UVS. (f ∘ g) x = id x"
  shows "linear_on UVS UVS (*s) (*s) g"
    is finite_dimensional_vector_space.right_inverse_linear[unfolded fun_eq_iff].

end

end

context vector_space_pair_on 
begin

tts_context
  tts: (?'b to ‹UM_1::'b set›) and (?'c to ‹UM_2::'c set›) 
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and (‹?s1.0::?'a::field ⇒?'b::ab_group_add⇒?'b› to ‹(*s1)::'a⇒'b⇒'b›)
    and (‹0::?'b::ab_group_add› to ‹0::'b›) 
    and (‹(+)::?'c::ab_group_add⇒?'c⇒?'c› to ‹(+)::'c⇒'c⇒'c›)
    and (‹?s2.0::?'a::field ⇒?'c::ab_group_add⇒?'c› to ‹(*s2)::'a⇒'c⇒'c›)
    and (‹0::?'c::ab_group_add› to ‹0::'c›)
  rewriting ctr_simps
  substituting VS1.ab_group_add_ow_axioms
    and VS1.vector_space_ow_axioms
    and VS2.ab_group_add_ow_axioms
    and VS2.vector_space_ow_axioms
    and implicitVS.vector_space_pair_ow_axioms
    and VS1.implicitM.module_ow_axioms
    and VS2.implicitM.module_ow_axioms
  eliminating ‹?a ∈ UM_1› and ‹?B ⊆ UM_1› and ‹?a ∈ UM_2› and ‹?B ⊆ UM_2› 
    through auto
  applying  
    [
      OF 
        VS1.implicitM.carrier_ne VS2.implicitM.carrier_ne 
        VS1.implicitM.minus_closed' VS1.implicitM.uminus_closed' 
        VS2.implicitVS.minus_closed' VS2.implicitVS.uminus_closed',
      unfolded tts_implicit
    ]
begin

tts_lemma linear_add:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "b1 ∈ UM_1"
    and "b2 ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "f (b1 + b2) = f b1 + f b2"
    is vector_space_pair.linear_add.

tts_lemma linear_scale:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "b ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "f (r *s1 b) = r *s2 f b"
    is vector_space_pair.linear_scale.
    
tts_lemma linear_neg:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "x ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "f (- x) = - f x"
    is vector_space_pair.linear_neg.
    
tts_lemma linear_diff:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "x ∈ UM_1"
    and "y ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "f (x - y) = f x - f y"
    is vector_space_pair.linear_diff.
    
tts_lemma linear_sum:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "range g ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "f (sum g S) = (∑a∈S. f (g a))"
is vector_space_pair.linear_sum.

tts_lemma linear_inj_on_iff_eq_0:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "s ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS1.subspace s"
  shows "inj_on f s = (∀x∈s. f x = 0 ⟶ x = 0)"
    is vector_space_pair.linear_inj_on_iff_eq_0.

tts_lemma linear_inj_iff_eq_0:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "inj_on f UM_1 = (∀x∈UM_1. f x = 0 ⟶ x = 0)"
    is vector_space_pair.linear_inj_iff_eq_0.

tts_lemma linear_subspace_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS1.subspace S"
  shows "VS2.subspace (f ` S)"
    is vector_space_pair.linear_subspace_image.

tts_lemma linear_subspace_kernel:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "VS1.subspace {x ∈ UM_1. f x = 0}"
    is vector_space_pair.linear_subspace_kernel.

tts_lemma linear_span_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "VS2.span (f ` S) = f ` VS1.span S"
    is vector_space_pair.linear_span_image.

tts_lemma linear_dependent_inj_imageD:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "s ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS2.dependent (f ` s)"
    and "inj_on f (VS1.span s)"
  shows "VS1.dependent s"
    is vector_space_pair.linear_dependent_inj_imageD.

tts_lemma linear_eq_0_on_span:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "b ⊆ UM_1"
    and "x ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "⋀x. ⟦x ∈ UM_1; x ∈ b⟧ ⟹ f x = 0"
    and "x ∈ VS1.span b"
  shows "f x = 0"
    is vector_space_pair.linear_eq_0_on_span.

tts_lemma linear_independent_injective_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "s ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "¬ VS1.dependent s"
    and "inj_on f (VS1.span s)"
  shows "¬ VS2.dependent (f ` s)"
    is vector_space_pair.linear_independent_injective_image.

tts_lemma linear_inj_on_span_independent_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "B ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "¬ VS2.dependent (f ` B)"
    and "inj_on f B"
  shows "inj_on f (VS1.span B)"
    is vector_space_pair.linear_inj_on_span_independent_image.

tts_lemma linear_inj_on_span_iff_independent_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "B ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "¬ VS2.dependent (f ` B)"
  shows "inj_on f (VS1.span B) = inj_on f B"
    is vector_space_pair.linear_inj_on_span_iff_independent_image.

tts_lemma linear_subspace_linear_preimage:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS2.subspace S"
  shows "VS1.subspace {x ∈ UM_1. f x ∈ S}"
    is vector_space_pair.linear_subspace_linear_preimage.

tts_lemma linear_spans_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "V ⊆ UM_1"
    and "B ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "V ⊆ VS1.span B"
  shows "f ` V ⊆ VS2.span (f ` B)"
    is vector_space_pair.linear_spans_image.

tts_lemma linear_spanning_surjective_image:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "UM_1 ⊆ VS1.span S"
    and "f ` UM_1 = UM_2"
  shows "UM_2 ⊆ VS2.span (f ` S)"
    is vector_space_pair.linear_spanning_surjective_image.

tts_lemma linear_eq_on_span:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "∀x∈UM_1. g x ∈ UM_2"
    and "B ⊆ UM_1"
    and "x ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "linear_on UM_1 UM_2 (*s1) (*s2) g"
    and "⋀x. ⟦x ∈ UM_1; x ∈ B⟧ ⟹ f x = g x"
    and "x ∈ VS1.span B"
  shows "f x = g x"
    is vector_space_pair.linear_eq_on_span.

tts_lemma linear_compose_scale_right:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. c *s2 f x)"
    is vector_space_pair.linear_compose_scale_right.

tts_lemma linear_compose_add:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "∀x∈UM_1. g x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "linear_on UM_1 UM_2 (*s1) (*s2) g"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. f x + g x)"
    is vector_space_pair.linear_compose_add.

tts_lemma linear_zero:
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. 0)"
    is vector_space_pair.linear_zero.

tts_lemma linear_compose_sub:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "∀x∈UM_1. g x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "linear_on UM_1 UM_2 (*s1) (*s2) g"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. f x - g x)"
    is vector_space_pair.linear_compose_sub.

tts_lemma linear_compose_neg:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. - f x)"
    is vector_space_pair.linear_compose_neg.

tts_lemma linear_compose_scale:
  assumes "c ∈ UM_2"
    and "linear_on UM_1 UNIV (*s1) (*) f"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. f x *s2 c)"
    is vector_space_pair.linear_compose_scale.

tts_lemma linear_indep_image_lemma:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "B ⊆ UM_1"
    and "x ∈ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "finite B"
    and "¬ VS2.dependent (f ` B)"
    and "inj_on f B"
    and "x ∈ VS1.span B"
    and "f x = 0"
  shows "x = 0"
    is vector_space_pair.linear_indep_image_lemma.

tts_lemma linear_eq_on:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "∀x∈UM_1. g x ∈ UM_2"
    and "x ∈ UM_1"
    and "B ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "linear_on UM_1 UM_2 (*s1) (*s2) g"
    and "x ∈ VS1.span B"
    and "⋀b. ⟦b ∈ UM_1; b ∈ B⟧ ⟹ f b = g b"
  shows "f x = g x"
    is vector_space_pair.linear_eq_on.

tts_lemma linear_compose_sum:
  assumes "∀x. ∀y∈UM_1. f x y ∈ UM_2"
    and "∀x∈S. linear_on UM_1 UM_2 (*s1) (*s2) (f x)"
  shows "linear_on UM_1 UM_2 (*s1) (*s2) (λx. ∑a∈S. f a x)"
    is vector_space_pair.linear_compose_sum.

tts_lemma linear_independent_extend_subspace:
  assumes "B ⊆ UM_1"
    and "∀x∈UM_1. f x ∈ UM_2"
    and "¬ VS1.dependent B"
  shows 
    "∃x.
      (∀a∈UM_1. x a ∈ UM_2) ∧ 
      linear_on UM_1 UM_2 (*s1) (*s2) x ∧ 
      (∀a∈B. x a = f a) ∧ 
      x ` UM_1 = VS2.span (f ` B)"
    given vector_space_pair.linear_independent_extend_subspace by auto

tts_lemma linear_independent_extend:
  assumes "B ⊆ UM_1"
    and "∀x∈UM_1. f x ∈ UM_2"
    and "¬ VS1.dependent B"
  shows 
    "∃x. 
      (∀a∈UM_1. x a ∈ UM_2) ∧ 
      (∀a∈B. x a = f a) ∧ 
      linear_on UM_1 UM_2 (*s1) (*s2) x"
    given vector_space_pair.linear_independent_extend by auto

tts_lemma linear_exists_left_inverse_on:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "V ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS1.subspace V"
    and "inj_on f V"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      x ` UM_2 ⊆ V ∧ 
      (∀a∈V. x (f a) = a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_exists_left_inverse_on by auto

tts_lemma linear_exists_right_inverse_on:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "V ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS1.subspace V"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      x ` UM_2 ⊆ V ∧ 
      (∀a∈f ` V. f (x a) = a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_exists_right_inverse_on by auto

tts_lemma linear_inj_on_left_inverse:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "inj_on f (VS1.span S)"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      x ` UM_2 ⊆ VS1.span S ∧ 
      (∀a∈VS1.span S. x (f a) = a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_inj_on_left_inverse by auto

tts_lemma linear_surj_right_inverse:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "T ⊆ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS2.span T ⊆ f ` VS1.span S"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      x ` UM_2 ⊆ VS1.span S ∧ 
      (∀a∈VS2.span T. f (x a) = a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_surj_right_inverse by auto

tts_lemma finite_basis_to_basis_subspace_isomorphism:
  assumes "S ⊆ UM_1"
    and "T ⊆ UM_2"
    and "VS1.subspace S"
    and "VS2.subspace T"
    and "VS1.dim S = VS2.dim T"
    and "finite B"
    and "B ⊆ S"
    and "¬ VS1.dependent B"
    and "S ⊆ VS1.span B"
    and "card B = VS1.dim S"
    and "finite C"
    and "C ⊆ T"
    and "¬ VS2.dependent C"
    and "T ⊆ VS2.span C"
    and "card C = VS2.dim T"
  shows 
    "∃x. 
      (∀a∈UM_1. x a ∈ UM_2) ∧ 
      linear_on UM_1 UM_2 (*s1) (*s2) x ∧ 
      x ` B = C ∧ 
      inj_on x S ∧ x ` S = T"
    given vector_space_pair.finite_basis_to_basis_subspace_isomorphism by auto

tts_lemma linear_subspace_vimage:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "VS2.subspace S"
  shows "VS1.subspace (f -` S ∩ UM_1)"
    is vector_space_pair.linear_subspace_vimage.

tts_lemma linear_injective_left_inverse:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "inj_on f UM_1"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      (∀a∈UM_1. (x ∘ f) a = id a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_injective_left_inverse[unfolded fun_eq_iff]
  by auto

tts_lemma linear_surjective_right_inverse:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "f ` UM_1 = UM_2"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      (∀a∈UM_2. (f ∘ x) a = id a) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x"
    given vector_space_pair.linear_surjective_right_inverse[unfolded fun_eq_iff]
  by auto

end

end

context finite_dimensional_vector_space_pair_1_on 
begin

tts_context
  tts: (?'b to ‹UM_1::'b set›) and (?'c to ‹UM_2::'c set›) 
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and (‹?s1.0::?'a::field ⇒?'b::ab_group_add⇒?'b› to ‹(*s1)::'a⇒'b⇒'b›)
    and (‹0::?'b::ab_group_add› to ‹0::'b›) 
    and (‹(+)::?'c::ab_group_add⇒?'c⇒?'c› to ‹(+)::'c⇒'c⇒'c›)
    and (‹?s2.0::?'a::field ⇒?'c::ab_group_add⇒?'c› to ‹(*s2)::'a⇒'c⇒'c›)
    and (‹0::?'c::ab_group_add› to ‹0::'c›)
  rewriting ctr_simps
  substituting VS1.ab_group_add_ow_axioms
    and VS1.vector_space_ow_axioms
    and VS2.ab_group_add_ow_axioms
    and VS2.vector_space_ow_axioms
    and implicitVS.vector_space_pair_ow_axioms
    and VS1.implicitM.module_ow_axioms
    and VS2.implicitM.module_ow_axioms 
    and implicitVS.finite_dimensional_vector_space_pair_1_ow_axioms
  applying  
    [
      OF 
        VS1.implicitM.carrier_ne VS2.implicitM.carrier_ne 
        VS1.implicitVS.minus_closed' VS1.implicitVS.uminus_closed' 
        VS2.implicitVS.minus_closed' VS2.implicitVS.uminus_closed'
        VS1.basis_subset,
      unfolded tts_implicit
    ]
begin

tts_lemma lt_dim_image_eq:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "inj_on f (VS1.span S)"
  shows "VS2.dim (f ` S) = VS1.dim S"
    is finite_dimensional_vector_space_pair_1.dim_image_eq.

tts_lemma lt_dim_image_le:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "S ⊆ UM_1"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
  shows "VS2.dim (f ` S) ≤ VS1.dim S"
    is finite_dimensional_vector_space_pair_1.dim_image_le.

end

end

context finite_dimensional_vector_space_pair_on 
begin

tts_context
  tts: (?'b to ‹UM_1::'b set›) and (?'c to ‹UM_2::'c set›) 
  sbterms: (‹(+)::?'b::ab_group_add⇒?'b⇒?'b› to ‹(+)::'b⇒'b⇒'b›)
    and (‹?s1.0::?'a::field ⇒?'b::ab_group_add⇒?'b› to ‹(*s1)::'a⇒'b⇒'b›)
    and (‹0::?'b::ab_group_add› to ‹0::'b›) 
    and (‹(+)::?'c::ab_group_add⇒?'c⇒?'c› to ‹(+)::'c⇒'c⇒'c›)
    and (‹?s2.0::?'a::field ⇒?'c::ab_group_add⇒?'c› to ‹(*s2)::'a⇒'c⇒'c›)
    and (‹0::?'c::ab_group_add› to ‹0::'c›)
  rewriting ctr_simps
  substituting VS1.ab_group_add_ow_axioms
    and VS1.vector_space_ow_axioms
    and VS2.ab_group_add_ow_axioms
    and VS2.vector_space_ow_axioms
    and implicitVS.vector_space_pair_ow_axioms
    and VS1.implicitM.module_ow_axioms
    and VS2.implicitM.module_ow_axioms 
    and implicitVS.finite_dimensional_vector_space_pair_ow_axioms
  applying  
    [
      OF 
        VS1.implicitM.carrier_ne VS2.implicitM.carrier_ne 
        VS1.implicitVS.minus_closed' VS1.implicitVS.uminus_closed' 
        VS2.implicitVS.minus_closed' VS2.implicitVS.uminus_closed'
        VS1.basis_subset VS2.basis_subset,
      unfolded tts_implicit
    ]
begin

tts_lemma linear_surjective_imp_injective:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "f ` UM_1 = UM_2"
    and "VS2.dim UM_2 = VS1.dim UM_1"
  shows "inj_on f UM_1"
    is finite_dimensional_vector_space_pair.linear_surjective_imp_injective.

tts_lemma linear_injective_imp_surjective:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "inj_on f UM_1"
    and "VS2.dim UM_2 = VS1.dim UM_1"
  shows "f ` UM_1 = UM_2"
    is finite_dimensional_vector_space_pair.linear_injective_imp_surjective.

tts_lemma linear_injective_isomorphism:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "inj_on f UM_1"
    and "VS2.dim UM_2 = VS1.dim UM_1"
  shows 
    "∃x. 
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x ∧ 
      (∀a∈UM_1. x (f a) = a) ∧ 
      (∀a∈UM_2. f (x a) = a)"
    given finite_dimensional_vector_space_pair.linear_injective_isomorphism
  by auto

tts_lemma linear_surjective_isomorphism:
  assumes "∀x∈UM_1. f x ∈ UM_2"
    and "linear_on UM_1 UM_2 (*s1) (*s2) f"
    and "f ` UM_1 = UM_2"
    and "VS2.dim UM_2 = VS1.dim UM_1"
  shows 
    "∃x.
      (∀a∈UM_2. x a ∈ UM_1) ∧ 
      linear_on UM_2 UM_1 (*s2) (*s1) x ∧ 
      (∀a∈UM_1. x (f a) = a) ∧ 
      (∀a∈UM_2. f (x a) = a)"
    given finite_dimensional_vector_space_pair.linear_surjective_isomorphism
  by auto

tts_lemma basis_to_basis_subspace_isomorphism:
  assumes "S ⊆ UM_1"
    and "T ⊆ UM_2"
    and "B ⊆ UM_1"
    and "C ⊆ UM_2"
    and "VS1.subspace S"
    and "VS2.subspace T"
    and "VS1.dim S = VS2.dim T"
    and "B ⊆ S"
    and "¬ VS1.dependent B"
    and "S ⊆ VS1.span B"
    and "card B = VS1.dim S"
    and "C ⊆ T"
    and "¬ VS2.dependent C"
    and "T ⊆ VS2.span C"
    and "card C = VS2.dim T"
  shows
    "∃x.
      (∀a∈UM_1. x a ∈ UM_2) ∧
      linear_on UM_1 UM_2 (*s1) (*s2) x ∧
      x ` B = C ∧
      inj_on x S ∧
      x ` S = T"
  given finite_dimensional_vector_space_pair.basis_to_basis_subspace_isomorphism
  by auto

tts_lemma subspace_isomorphism:
  assumes "S ⊆ UM_1"
    and "T ⊆ UM_2"
    and "VS1.subspace S"
    and "VS2.subspace T"
    and "VS1.dim S = VS2.dim T"
  shows "∃x.
    (∀a∈UM_1. x a ∈ UM_2) ∧
    (inj_on x S ∧ x ` S = T) ∧
    linear_on UM_1 UM_2 (*s1) (*s2) x"
    given finite_dimensional_vector_space_pair.subspace_isomorphism by auto

end

end

text‹\newpage›

end