Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.
| Download
Try doing some basic maths questions in the Lean Theorem Prover. Functions, real numbers, equivalence relations and groups. Click on README.md and then on "Open in CoCalc with one click".
Project: Xena
Views: 18536License: APACHE
/- Copyright (c) 2018 Mario Carneiro. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Mario Carneiro, Johannes Hölzl, Sander Dahmen Dimension of modules and vector spaces. -/ import linear_algebra.basis import set_theory.ordinal noncomputable theory universes u u' u'' v v' w w' variables {K : Type u} {V V₂ V₃ V₄ : Type v} variables {ι : Type w} {ι' : Type w'} {η : Type u''} {φ : η → Type u'} -- TODO: relax these universe constraints open_locale classical section vector_space variables [discrete_field K] [add_comm_group V] [vector_space K V] include K open submodule lattice function set variables (K V) def vector_space.dim : cardinal := cardinal.min (nonempty_subtype.2 (@exists_is_basis K V _ _ _)) (λ b, cardinal.mk b.1) variables {K V} open vector_space section set_option class.instance_max_depth 50 theorem is_basis.le_span (zero_ne_one : (0 : K) ≠ 1) {v : ι → V} {J : set V} (hv : is_basis K v) (hJ : span K J = ⊤) : cardinal.mk (range v) ≤ cardinal.mk J := begin cases le_or_lt cardinal.omega (cardinal.mk J) with oJ oJ, { have := cardinal.mk_range_eq_of_inj (linear_independent.injective zero_ne_one hv.1), let S : J → set ι := λ j, (is_basis.repr hv j).support.to_set, let S' : J → set V := λ j, v '' S j, have hs : range v ⊆ ⋃ j, S' j, { intros b hb, rcases mem_range.1 hb with ⟨i, hi⟩, have : span K J ≤ comap hv.repr (finsupp.supported K K (⋃ j, S j)) := span_le.2 (λ j hj x hx, ⟨_, ⟨⟨j, hj⟩, rfl⟩, hx⟩), rw hJ at this, replace : hv.repr (v i) ∈ (finsupp.supported K K (⋃ j, S j)) := this trivial, rw [hv.repr_eq_single, finsupp.mem_supported, finsupp.support_single_ne_zero zero_ne_one.symm] at this, rw ← hi, apply mem_Union.2, rcases mem_Union.1 (this (mem_singleton _)) with ⟨j, hj⟩, use j, rw mem_image, use i, exact ⟨hj, rfl⟩ }, refine le_of_not_lt (λ IJ, _), suffices : cardinal.mk (⋃ j, S' j) < cardinal.mk (range v), { exact not_le_of_lt this ⟨set.embedding_of_subset hs⟩ }, refine lt_of_le_of_lt (le_trans cardinal.mk_Union_le_sum_mk (cardinal.sum_le_sum _ (λ _, cardinal.omega) _)) _, { exact λ j, le_of_lt (cardinal.lt_omega_iff_finite.2 $ finite_image _ (finset.finite_to_set _)) }, { rwa [cardinal.sum_const, cardinal.mul_eq_max oJ (le_refl _), max_eq_left oJ] } }, { rcases exists_finite_card_le_of_finite_of_linear_independent_of_span (cardinal.lt_omega_iff_finite.1 oJ) hv.1.to_subtype_range _ with ⟨fI, hi⟩, { rwa [← cardinal.nat_cast_le, cardinal.finset_card, finset.coe_to_finset, cardinal.finset_card, finset.coe_to_finset] at hi, }, { rw hJ, apply set.subset_univ } }, end end /-- dimension theorem -/ theorem mk_eq_mk_of_basis {v : ι → V} {v' : ι' → V} (hv : is_basis K v) (hv' : is_basis K v') : cardinal.lift.{w w'} (cardinal.mk ι) = cardinal.lift.{w' w} (cardinal.mk ι') := begin rw ←cardinal.lift_inj.{(max w w') v}, rw [cardinal.lift_lift, cardinal.lift_lift], apply le_antisymm, { convert cardinal.lift_le.{v (max w w')}.2 (hv.le_span zero_ne_one hv'.2), { rw cardinal.lift_max.{w v w'}, apply (cardinal.mk_range_eq_of_inj (hv.injective zero_ne_one)).symm, }, { rw cardinal.lift_max.{w' v w}, apply (cardinal.mk_range_eq_of_inj (hv'.injective zero_ne_one)).symm, }, }, { convert cardinal.lift_le.{v (max w w')}.2 (hv'.le_span zero_ne_one hv.2), { rw cardinal.lift_max.{w' v w}, apply (cardinal.mk_range_eq_of_inj (hv'.injective zero_ne_one)).symm, }, { rw cardinal.lift_max.{w v w'}, apply (cardinal.mk_range_eq_of_inj (hv.injective zero_ne_one)).symm, }, } end theorem is_basis.mk_range_eq_dim {v : ι → V} (h : is_basis K v) : cardinal.mk (range v) = dim K V := begin have := show ∃ v', dim K V = _, from cardinal.min_eq _ _, rcases this with ⟨v', e⟩, rw e, apply cardinal.lift_inj.1, rw cardinal.mk_range_eq_of_inj (h.injective zero_ne_one), convert @mk_eq_mk_of_basis _ _ _ _ _ _ _ _ _ h v'.property end theorem is_basis.mk_eq_dim {v : ι → V} (h : is_basis K v) : cardinal.lift.{w v} (cardinal.mk ι) = cardinal.lift.{v w} (dim K V) := by rw [←h.mk_range_eq_dim, cardinal.mk_range_eq_of_inj (h.injective zero_ne_one)] variables [add_comm_group V₂] [vector_space K V₂] theorem linear_equiv.dim_eq (f : V ≃ₗ[K] V₂) : dim K V = dim K V₂ := by letI := classical.dec_eq V; letI := classical.dec_eq V₂; exact let ⟨b, hb⟩ := exists_is_basis K V in cardinal.lift_inj.1 $ hb.mk_eq_dim.symm.trans (f.is_basis hb).mk_eq_dim @[simp] lemma dim_bot : dim K (⊥ : submodule K V) = 0 := by letI := classical.dec_eq V; rw [← cardinal.lift_inj, ← (@is_basis_empty_bot pempty K V _ _ _ not_nonempty_pempty).mk_eq_dim, cardinal.mk_pempty] @[simp] lemma dim_top : dim K (⊤ : submodule K V) = dim K V := linear_equiv.dim_eq (linear_equiv.of_top _ rfl) lemma dim_of_field (K : Type*) [discrete_field K] : dim K K = 1 := by rw [←cardinal.lift_inj, ← (@is_basis_singleton_one punit K _ _).mk_eq_dim, cardinal.mk_punit] lemma dim_span {v : ι → V} (hv : linear_independent K v) : dim K ↥(span K (range v)) = cardinal.mk (range v) := by rw [←cardinal.lift_inj, ← (is_basis_span hv).mk_eq_dim, cardinal.mk_range_eq_of_inj (@linear_independent.injective ι K V v _ _ _ zero_ne_one hv)] lemma dim_span_set {s : set V} (hs : linear_independent K (λ x, x : s → V)) : dim K ↥(span K s) = cardinal.mk s := by rw [← @set_of_mem_eq _ s, ← subtype.val_range]; exact dim_span hs lemma dim_span_le (s : set V) : dim K (span K s) ≤ cardinal.mk s := begin classical, rcases exists_linear_independent linear_independent_empty (set.empty_subset s) with ⟨b, hb, _, hsb, hlib⟩, have hsab : span K s = span K b, from span_eq_of_le _ hsb (span_le.2 (λ x hx, subset_span (hb hx))), convert cardinal.mk_le_mk_of_subset hb, rw [hsab, dim_span_set hlib] end lemma dim_span_of_finset (s : finset V) : dim K (span K (↑s : set V)) < cardinal.omega := calc dim K (span K (↑s : set V)) ≤ cardinal.mk (↑s : set V) : dim_span_le ↑s ... = s.card : by rw ←cardinal.finset_card ... < cardinal.omega : cardinal.nat_lt_omega _ theorem dim_prod : dim K (V × V₂) = dim K V + dim K V₂ := begin letI := classical.dec_eq V, letI := classical.dec_eq V₂, rcases exists_is_basis K V with ⟨b, hb⟩, rcases exists_is_basis K V₂ with ⟨c, hc⟩, rw [← cardinal.lift_inj, ← @is_basis.mk_eq_dim K (V × V₂) _ _ _ _ _ (is_basis_inl_union_inr hb hc), cardinal.lift_add, cardinal.lift_mk, ← hb.mk_eq_dim, ← hc.mk_eq_dim, cardinal.lift_mk, cardinal.lift_mk, cardinal.add_def (ulift b) (ulift c)], exact cardinal.lift_inj.1 (cardinal.lift_mk_eq.2 ⟨equiv.ulift.trans (equiv.sum_congr (@equiv.ulift b) (@equiv.ulift c)).symm ⟩), end theorem dim_quotient_add_dim (p : submodule K V) : dim K p.quotient + dim K p = dim K V := by classical; exact let ⟨f⟩ := quotient_prod_linear_equiv p in dim_prod.symm.trans f.dim_eq theorem dim_quotient_le (p : submodule K V) : dim K p.quotient ≤ dim K V := by { rw ← dim_quotient_add_dim p, exact cardinal.le_add_right _ _ } /-- rank-nullity theorem -/ theorem dim_range_add_dim_ker (f : V →ₗ[K] V₂) : dim K f.range + dim K f.ker = dim K V := begin haveI := λ (p : submodule K V), classical.dec_eq p.quotient, rw [← f.quot_ker_equiv_range.dim_eq, dim_quotient_add_dim] end lemma dim_range_le (f : V →ₗ[K] V₂) : dim K f.range ≤ dim K V := by rw ← dim_range_add_dim_ker f; exact le_add_right (le_refl _) lemma dim_map_le (f : V →ₗ V₂) (p : submodule K V) : dim K (p.map f) ≤ dim K p := begin have h := dim_range_le (f.comp (submodule.subtype p)), rwa [linear_map.range_comp, range_subtype] at h, end lemma dim_range_of_surjective (f : V →ₗ[K] V₂) (h : surjective f) : dim K f.range = dim K V₂ := begin refine linear_equiv.dim_eq (linear_equiv.of_bijective (submodule.subtype _) _ _), exact linear_map.ker_eq_bot.2 subtype.val_injective, rwa [range_subtype, linear_map.range_eq_top] end lemma dim_eq_surjective (f : V →ₗ[K] V₂) (h : surjective f) : dim K V = dim K V₂ + dim K f.ker := by rw [← dim_range_add_dim_ker f, ← dim_range_of_surjective f h] lemma dim_le_surjective (f : V →ₗ[K] V₂) (h : surjective f) : dim K V₂ ≤ dim K V := by rw [dim_eq_surjective f h]; refine le_add_right (le_refl _) lemma dim_eq_injective (f : V →ₗ[K] V₂) (h : injective f) : dim K V = dim K f.range := by rw [← dim_range_add_dim_ker f, linear_map.ker_eq_bot.2 h]; simp [dim_bot] lemma dim_submodule_le (s : submodule K V) : dim K s ≤ dim K V := by { rw ← dim_quotient_add_dim s, exact cardinal.le_add_left _ _ } lemma dim_le_injective (f : V →ₗ[K] V₂) (h : injective f) : dim K V ≤ dim K V₂ := by { rw [dim_eq_injective f h], exact dim_submodule_le _ } lemma dim_le_of_submodule (s t : submodule K V) (h : s ≤ t) : dim K s ≤ dim K t := dim_le_injective (of_le h) $ assume ⟨x, hx⟩ ⟨y, hy⟩ eq, subtype.eq $ show x = y, from subtype.ext.1 eq section variables [add_comm_group V₃] [vector_space K V₃] variables [add_comm_group V₄] [vector_space K V₄] set_option class.instance_max_depth 70 open linear_map /-- This is mostly an auxiliary lemma for `dim_sup_add_dim_inf_eq` -/ lemma dim_add_dim_split (db : V₃ →ₗ[K] V) (eb : V₄ →ₗ[K] V) (cd : V₂ →ₗ[K] V₃) (ce : V₂ →ₗ[K] V₄) (hde : ⊤ ≤ db.range ⊔ eb.range) (hgd : ker cd = ⊥) (eq : db.comp cd = eb.comp ce) (eq₂ : ∀d e, db d = eb e → (∃c, cd c = d ∧ ce c = e)) : dim K V + dim K V₂ = dim K V₃ + dim K V₄ := have hf : surjective (copair db eb), begin refine (range_eq_top.1 $ top_unique $ _), rwa [← map_top, ← prod_top, map_copair_prod] end, begin conv {to_rhs, rw [← dim_prod, dim_eq_surjective _ hf] }, congr' 1, apply linear_equiv.dim_eq, fapply linear_equiv.of_bijective, { refine cod_restrict _ (pair cd (- ce)) _, { assume c, simp [add_eq_zero_iff_eq_neg], exact linear_map.ext_iff.1 eq c } }, { rw [ker_cod_restrict, ker_pair, hgd, bot_inf_eq] }, { rw [eq_top_iff, range_cod_restrict, ← map_le_iff_le_comap, map_top, range_subtype], rintros ⟨d, e⟩, have h := eq₂ d (-e), simp [add_eq_zero_iff_eq_neg] at ⊢ h, assume hde, rcases h hde with ⟨c, h₁, h₂⟩, refine ⟨c, h₁, _⟩, rw [h₂, _root_.neg_neg] } end lemma dim_sup_add_dim_inf_eq (s t : submodule K V) : dim K (s ⊔ t : submodule K V) + dim K (s ⊓ t : submodule K V) = dim K s + dim K t := dim_add_dim_split (of_le le_sup_left) (of_le le_sup_right) (of_le inf_le_left) (of_le inf_le_right) begin rw [← map_le_map_iff (ker_subtype $ s ⊔ t), map_sup, map_top, ← linear_map.range_comp, ← linear_map.range_comp, subtype_comp_of_le, subtype_comp_of_le, range_subtype, range_subtype, range_subtype], exact le_refl _ end (ker_of_le _ _ _) begin ext ⟨x, hx⟩, refl end begin rintros ⟨b₁, hb₁⟩ ⟨b₂, hb₂⟩ eq, have : b₁ = b₂ := congr_arg subtype.val eq, subst this, exact ⟨⟨b₁, hb₁, hb₂⟩, rfl, rfl⟩ end lemma dim_add_le_dim_add_dim (s t : submodule K V) : dim K (s ⊔ t : submodule K V) ≤ dim K s + dim K t := by rw [← dim_sup_add_dim_inf_eq]; exact le_add_right (le_refl _) end section fintype variable [fintype η] variables [∀i, add_comm_group (φ i)] [∀i, vector_space K (φ i)] open linear_map lemma dim_pi : vector_space.dim K (Πi, φ i) = cardinal.sum (λi, vector_space.dim K (φ i)) := begin choose b hb using assume i, exists_is_basis K (φ i), have : is_basis K (λ (ji : Σ j, b j), std_basis K (λ j, φ j) ji.fst ji.snd.val), by apply pi.is_basis_std_basis _ hb, rw [←cardinal.lift_inj, ← this.mk_eq_dim], simp [λ i, (hb i).mk_range_eq_dim.symm, cardinal.sum_mk] end lemma dim_fun {V η : Type u} [fintype η] [add_comm_group V] [vector_space K V] : vector_space.dim K (η → V) = fintype.card η * vector_space.dim K V := by rw [dim_pi, cardinal.sum_const, cardinal.fintype_card] lemma dim_fun_eq_lift_mul : vector_space.dim K (η → V) = (fintype.card η : cardinal.{max u'' v}) * cardinal.lift.{v u''} (vector_space.dim K V) := by rw [dim_pi, cardinal.sum_const_eq_lift_mul, cardinal.fintype_card, cardinal.lift_nat_cast] lemma dim_fun' : vector_space.dim K (η → K) = fintype.card η := by rw [dim_fun_eq_lift_mul, dim_of_field K, cardinal.lift_one, mul_one, cardinal.nat_cast_inj] lemma dim_fin_fun (n : ℕ) : dim K (fin n → K) = n := by simp [dim_fun'] end fintype lemma exists_mem_ne_zero_of_ne_bot {s : submodule K V} (h : s ≠ ⊥) : ∃ b : V, b ∈ s ∧ b ≠ 0 := begin classical, by_contradiction hex, have : ∀x∈s, (x:V) = 0, { simpa only [not_exists, not_and, not_not, ne.def] using hex }, exact (h $ bot_unique $ assume s hs, (submodule.mem_bot K).2 $ this s hs) end lemma exists_mem_ne_zero_of_dim_pos {s : submodule K V} (h : vector_space.dim K s > 0) : ∃ b : V, b ∈ s ∧ b ≠ 0 := exists_mem_ne_zero_of_ne_bot $ assume eq, by rw [(>), eq, dim_bot] at h; exact lt_irrefl _ h lemma exists_is_basis_fintype (h : dim K V < cardinal.omega) : ∃ s : (set V), (is_basis K (subtype.val : s → V)) ∧ nonempty (fintype s) := begin cases exists_is_basis K V with s hs, rw [←cardinal.lift_lt, ← is_basis.mk_eq_dim hs, cardinal.lift_lt, cardinal.lt_omega_iff_fintype] at h, exact ⟨s, hs, h⟩ end section rank def rank (f : V →ₗ[K] V₂) : cardinal := dim K f.range lemma rank_le_domain (f : V →ₗ[K] V₂) : rank f ≤ dim K V := by rw [← dim_range_add_dim_ker f]; exact le_add_right (le_refl _) lemma rank_le_range (f : V →ₗ[K] V₂) : rank f ≤ dim K V₂ := dim_submodule_le _ lemma rank_add_le (f g : V →ₗ[K] V₂) : rank (f + g) ≤ rank f + rank g := calc rank (f + g) ≤ dim K (f.range ⊔ g.range : submodule K V₂) : begin refine dim_le_of_submodule _ _ _, exact (linear_map.range_le_iff_comap.2 $ eq_top_iff'.2 $ assume x, show f x + g x ∈ (f.range ⊔ g.range : submodule K V₂), from mem_sup.2 ⟨_, mem_image_of_mem _ (mem_univ _), _, mem_image_of_mem _ (mem_univ _), rfl⟩) end ... ≤ rank f + rank g : dim_add_le_dim_add_dim _ _ @[simp] lemma rank_zero : rank (0 : V →ₗ[K] V₂) = 0 := by rw [rank, linear_map.range_zero, dim_bot] lemma rank_finset_sum_le {η} (s : finset η) (f : η → V →ₗ[K] V₂) : rank (s.sum f) ≤ s.sum (λ d, rank (f d)) := @finset.sum_hom_rel _ _ _ _ _ (λa b, rank a ≤ b) f (λ d, rank (f d)) s (le_of_eq rank_zero) (λ i g c h, le_trans (rank_add_le _ _) (add_le_add_left' h)) variables [add_comm_group V₃] [vector_space K V₃] lemma rank_comp_le1 (g : V →ₗ[K] V₂) (f : V₂ →ₗ[K] V₃) : rank (f.comp g) ≤ rank f := begin refine dim_le_of_submodule _ _ _, rw [linear_map.range_comp], exact image_subset _ (subset_univ _) end lemma rank_comp_le2 (g : V →ₗ[K] V₂) (f : V₂ →ₗ V₃) : rank (f.comp g) ≤ rank g := by rw [rank, rank, linear_map.range_comp]; exact dim_map_le _ _ end rank end vector_space section unconstrained_universes variables {E : Type v'} variables [discrete_field K] [add_comm_group V] [vector_space K V] [add_comm_group E] [vector_space K E] open vector_space /-- Version of linear_equiv.dim_eq without universe constraints. -/ theorem linear_equiv.dim_eq_lift (f : V ≃ₗ[K] E) : cardinal.lift.{v v'} (dim K V) = cardinal.lift.{v' v} (dim K E) := begin cases exists_is_basis K V with b hb, rw [← cardinal.lift_inj.1 hb.mk_eq_dim, ← (f.is_basis hb).mk_eq_dim, cardinal.lift_mk], end end unconstrained_universes