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) 2019 Johannes Hölzl. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Author: Johannes Hölzl Linear structures on function with finite support `α →₀ M`. -/ import data.finsupp linear_algebra.basic noncomputable theory open lattice set linear_map submodule namespace finsupp open_locale classical variables {α : Type*} {M : Type*} {R : Type*} variables [ring R] [add_comm_group M] [module R M] def lsingle (a : α) : M →ₗ[R] (α →₀ M) := ⟨single a, assume a b, single_add, assume c b, (smul_single _ _ _).symm⟩ def lapply (a : α) : (α →₀ M) →ₗ[R] M := ⟨λg, g a, assume a b, rfl, assume a b, rfl⟩ section lsubtype_domain variables (s : set α) def lsubtype_domain : (α →₀ M) →ₗ[R] (s →₀ M) := ⟨subtype_domain (λx, x ∈ s), assume a b, subtype_domain_add, assume c a, ext $ assume a, rfl⟩ lemma lsubtype_domain_apply (f : α →₀ M) : (lsubtype_domain s : (α →₀ M) →ₗ[R] (s →₀ M)) f = subtype_domain (λx, x ∈ s) f := rfl end lsubtype_domain @[simp] lemma lsingle_apply (a : α) (b : M) : (lsingle a : M →ₗ[R] (α →₀ M)) b = single a b := rfl @[simp] lemma lapply_apply (a : α) (f : α →₀ M) : (lapply a : (α →₀ M) →ₗ[R] M) f = f a := rfl @[simp] lemma ker_lsingle (a : α) : (lsingle a : M →ₗ[R] (α →₀ M)).ker = ⊥ := ker_eq_bot.2 (injective_single a) lemma lsingle_range_le_ker_lapply (s t : set α) (h : disjoint s t) : (⨆a∈s, (lsingle a : M →ₗ[R] (α →₀ M)).range) ≤ (⨅a∈t, ker (lapply a)) := begin refine supr_le (assume a₁, supr_le $ assume h₁, range_le_iff_comap.2 _), simp only [(ker_comp _ _).symm, eq_top_iff, le_def', mem_ker, comap_infi, mem_infi], assume b hb a₂ h₂, have : a₁ ≠ a₂ := assume eq, h ⟨h₁, eq.symm ▸ h₂⟩, exact single_eq_of_ne this end lemma infi_ker_lapply_le_bot : (⨅a, ker (lapply a : (α →₀ M) →ₗ[R] M)) ≤ ⊥ := begin simp only [le_def', mem_infi, mem_ker, mem_bot, lapply_apply], exact assume a h, finsupp.ext h end lemma supr_lsingle_range : (⨆a, (lsingle a : M →ₗ[R] (α →₀ M)).range) = ⊤ := begin refine (eq_top_iff.2 $ le_def'.2 $ assume f _, _), rw [← sum_single f], refine sum_mem _ (assume a ha, submodule.mem_supr_of_mem _ a $ set.mem_image_of_mem _ trivial) end lemma disjoint_lsingle_lsingle (s t : set α) (hs : disjoint s t) : disjoint (⨆a∈s, (lsingle a : M →ₗ[R] (α →₀ M)).range) (⨆a∈t, (lsingle a).range) := begin refine disjoint_mono (lsingle_range_le_ker_lapply _ _ $ disjoint_compl s) (lsingle_range_le_ker_lapply _ _ $ disjoint_compl t) (le_trans (le_infi $ assume i, _) infi_ker_lapply_le_bot), classical, by_cases his : i ∈ s, { by_cases hit : i ∈ t, { exact (hs ⟨his, hit⟩).elim }, exact inf_le_right_of_le (infi_le_of_le i $ infi_le _ hit) }, exact inf_le_left_of_le (infi_le_of_le i $ infi_le _ his) end lemma span_single_image (s : set M) (a : α) : submodule.span R (single a '' s) = (submodule.span R s).map (lsingle a) := by rw ← span_image; refl variables (M R) def supported (s : set α) : submodule R (α →₀ M) := begin refine ⟨ {p | ↑p.support ⊆ s }, _, _, _ ⟩, { simp only [subset_def, finset.mem_coe, set.mem_set_of_eq, mem_support_iff, zero_apply], assume h ha, exact (ha rfl).elim }, { assume p q hp hq, refine subset.trans (subset.trans (finset.coe_subset.2 support_add) _) (union_subset hp hq), rw [finset.coe_union] }, { assume a p hp, refine subset.trans (finset.coe_subset.2 support_smul) hp } end variables {M} lemma mem_supported {s : set α} (p : α →₀ M) : p ∈ (supported M R s) ↔ ↑p.support ⊆ s := iff.rfl lemma mem_supported' {s : set α} (p : α →₀ M) : p ∈ supported M R s ↔ ∀ x ∉ s, p x = 0 := by haveI := classical.dec_pred (λ (x : α), x ∈ s); simp [mem_supported, set.subset_def, not_imp_comm] lemma single_mem_supported {s : set α} {a : α} (b : M) (h : a ∈ s) : single a b ∈ supported M R s := set.subset.trans support_single_subset (set.singleton_subset_iff.2 h) lemma supported_eq_span_single [has_one M] (s : set α) : supported R R s = span R ((λ i, single i 1) '' s) := begin refine (span_eq_of_le _ _ (le_def'.2 $ λ l hl, _)).symm, { rintro _ ⟨_, hp, rfl ⟩ , exact single_mem_supported R 1 hp }, { rw ← l.sum_single, refine sum_mem _ (λ i il, _), convert @smul_mem R (α →₀ R) _ _ _ _ (single i 1) (l i) _, { simp }, apply subset_span, apply set.mem_image_of_mem _ (hl il) } end variables (M R) def restrict_dom (s : set α) : (α →₀ M) →ₗ supported M R s := linear_map.cod_restrict _ { to_fun := filter (∈ s), add := λ l₁ l₂, filter_add, smul := λ a l, filter_smul } (λ l, (mem_supported' _ _).2 $ λ x, filter_apply_neg (∈ s) l) variables {M R} section set_option class.instance_max_depth 50 @[simp] theorem restrict_dom_apply (s : set α) (l : α →₀ M) : ((restrict_dom M R s : (α →₀ M) →ₗ supported M R s) l : α →₀ M) = finsupp.filter (∈ s) l := rfl end theorem restrict_dom_comp_subtype (s : set α) : (restrict_dom M R s).comp (submodule.subtype _) = linear_map.id := begin ext l, apply subtype.coe_ext.2, simp, ext a, by_cases a ∈ s, { simp [h] }, { rw [filter_apply_neg (λ x, x ∈ s) _ h], exact ((mem_supported' R l.1).1 l.2 a h).symm } end theorem range_restrict_dom (s : set α) : (restrict_dom M R s).range = ⊤ := begin have := linear_map.range_comp (submodule.subtype _) (restrict_dom M R s), rw [restrict_dom_comp_subtype, linear_map.range_id] at this, exact eq_top_mono (submodule.map_mono le_top) this.symm end theorem supported_mono {s t : set α} (st : s ⊆ t) : supported M R s ≤ supported M R t := λ l h, set.subset.trans h st @[simp] theorem supported_empty : supported M R (∅ : set α) = ⊥ := eq_bot_iff.2 $ λ l h, (submodule.mem_bot R).2 $ by ext; simp [*, mem_supported'] at * @[simp] theorem supported_univ : supported M R (set.univ : set α) = ⊤ := eq_top_iff.2 $ λ l _, set.subset_univ _ theorem supported_Union {δ : Type*} (s : δ → set α) : supported M R (⋃ i, s i) = ⨆ i, supported M R (s i) := begin refine le_antisymm _ (supr_le $ λ i, supported_mono $ set.subset_Union _ _), haveI := classical.dec_pred (λ x, x ∈ (⋃ i, s i)), suffices : ((submodule.subtype _).comp (restrict_dom M R (⋃ i, s i))).range ≤ ⨆ i, supported M R (s i), { rwa [linear_map.range_comp, range_restrict_dom, map_top, range_subtype] at this }, rw [range_le_iff_comap, eq_top_iff], rintro l ⟨⟩, rw mem_coe, apply finsupp.induction l, {exact zero_mem _}, refine λ x a l hl a0, add_mem _ _, haveI := classical.dec_pred (λ x, ∃ i, x ∈ s i), by_cases (∃ i, x ∈ s i); simp [h], { cases h with i hi, exact le_supr (λ i, supported M R (s i)) i (single_mem_supported R _ hi) }, { rw filter_single_of_neg, { simp }, { exact h } } end theorem supported_union (s t : set α) : supported M R (s ∪ t) = supported M R s ⊔ supported M R t := by erw [set.union_eq_Union, supported_Union, supr_bool_eq]; refl theorem supported_Inter {ι : Type*} (s : ι → set α) : supported M R (⋂ i, s i) = ⨅ i, supported M R (s i) := begin refine le_antisymm (le_infi $ λ i, supported_mono $ set.Inter_subset _ _) _, simp [le_def, infi_coe, set.subset_def], exact λ l, set.subset_Inter end section set_option class.instance_max_depth 37 def supported_equiv_finsupp (s : set α) : (supported M R s) ≃ₗ[R] (s →₀ M) := (restrict_support_equiv s).to_linear_equiv begin show is_linear_map R ((lsubtype_domain s : (α →₀ M) →ₗ[R] (s →₀ M)).comp (submodule.subtype (supported M R s))), exact linear_map.is_linear _ end end def lsum (f : α → R →ₗ[R] M) : (α →₀ R) →ₗ[R] M := ⟨λ d, d.sum (λ i, f i), assume d₁ d₂, by simp [sum_add_index], assume a d, by simp [sum_smul_index, smul_sum, -smul_eq_mul, smul_eq_mul.symm]⟩ @[simp] theorem lsum_apply (f : α → R →ₗ[R] M) (l : α →₀ R) : (finsupp.lsum f : (α →₀ R) →ₗ M) l = l.sum (λ b, f b) := rfl section lmap_domain variables {α' : Type*} {α'' : Type*} (M R) def lmap_domain (f : α → α') : (α →₀ M) →ₗ[R] (α' →₀ M) := ⟨map_domain f, assume a b, map_domain_add, map_domain_smul⟩ @[simp] theorem lmap_domain_apply (f : α → α') (l : α →₀ M) : (lmap_domain M R f : (α →₀ M) →ₗ[R] (α' →₀ M)) l = map_domain f l := rfl @[simp] theorem lmap_domain_id : (lmap_domain M R id : (α →₀ M) →ₗ[R] α →₀ M) = linear_map.id := linear_map.ext $ λ l, map_domain_id theorem lmap_domain_comp (f : α → α') (g : α' → α'') : lmap_domain M R (g ∘ f) = (lmap_domain M R g).comp (lmap_domain M R f) := linear_map.ext $ λ l, map_domain_comp theorem supported_comap_lmap_domain (f : α → α') (s : set α') : supported M R (f ⁻¹' s) ≤ (supported M R s).comap (lmap_domain M R f) := λ l (hl : ↑l.support ⊆ f ⁻¹' s), show ↑(map_domain f l).support ⊆ s, begin rw [← set.image_subset_iff, ← finset.coe_image] at hl, exact set.subset.trans map_domain_support hl end theorem lmap_domain_supported [inhabited α] (f : α → α') (s : set α) : (supported M R s).map (lmap_domain M R f) = supported M R (f '' s) := begin refine le_antisymm (map_le_iff_le_comap.2 $ le_trans (supported_mono $ set.subset_preimage_image _ _) (supported_comap_lmap_domain _ _ _ _)) _, intros l hl, refine ⟨(lmap_domain M R (function.inv_fun_on f s) : (α' →₀ M) →ₗ α →₀ M) l, λ x hx, _, _⟩, { rcases finset.mem_image.1 (map_domain_support hx) with ⟨c, hc, rfl⟩, exact function.inv_fun_on_mem (by simpa using hl hc) }, { rw [← linear_map.comp_apply, ← lmap_domain_comp], refine (map_domain_congr $ λ c hc, _).trans map_domain_id, exact function.inv_fun_on_eq (by simpa using hl hc) } end theorem lmap_domain_disjoint_ker (f : α → α') {s : set α} (H : ∀ a b ∈ s, f a = f b → a = b) : disjoint (supported M R s) (lmap_domain M R f).ker := begin rintro l ⟨h₁, h₂⟩, rw [mem_coe, mem_ker, lmap_domain_apply, map_domain] at h₂, simp, ext x, haveI := classical.dec_pred (λ x, x ∈ s), by_cases xs : x ∈ s, { have : finsupp.sum l (λ a, finsupp.single (f a)) (f x) = 0, {rw h₂, refl}, rw [finsupp.sum_apply, finsupp.sum, finset.sum_eq_single x] at this, { simpa [finsupp.single_apply] }, { intros y hy xy, simp [mt (H _ _ (h₁ hy) xs) xy] }, { simp {contextual := tt} } }, { by_contra h, exact xs (h₁ $ finsupp.mem_support_iff.2 h) } end end lmap_domain section total variables (α) {α' : Type*} (M) {M' : Type*} (R) [add_comm_group M'] [module R M'] (v : α → M) {v' : α' → M'} /-- Interprets (l : α →₀ R) as linear combination of the elements in the family (v : α → M) and evaluates this linear combination. -/ protected def total : (α →₀ R) →ₗ M := finsupp.lsum (λ i, linear_map.id.smul_right (v i)) variables {α M v} theorem total_apply (l : α →₀ R) : finsupp.total α M R v l = l.sum (λ i a, a • v i) := rfl @[simp] theorem total_single (c : R) (a : α) : finsupp.total α M R v (single a c) = c • (v a) := by simp [total_apply, sum_single_index] theorem total_range (h : function.surjective v) : (finsupp.total α M R v).range = ⊤ := begin apply range_eq_top.2, intros x, apply exists.elim (h x), exact λ i hi, ⟨single i 1, by simp [hi]⟩ end lemma range_total : (finsupp.total α M R v).range = span R (range v) := begin ext x, split, { intros hx, rw [linear_map.mem_range] at hx, rcases hx with ⟨l, hl⟩, rw ← hl, rw finsupp.total_apply, unfold finsupp.sum, apply sum_mem (span R (range v)), { exact λ i hi, submodule.smul _ _ (subset_span (mem_range_self i)) }, apply_instance }, { apply span_le.2, intros x hx, rcases hx with ⟨i, hi⟩, rw [mem_coe, linear_map.mem_range], use finsupp.single i 1, simp [hi] } end theorem lmap_domain_total (f : α → α') (g : M →ₗ[R] M') (h : ∀ i, g (v i) = v' (f i)) : (finsupp.total α' M' R v').comp (lmap_domain R R f) = g.comp (finsupp.total α M R v) := by ext l; simp [total_apply, finsupp.sum_map_domain_index, add_smul, h] theorem total_emb_domain (f : α ↪ α') (l : α →₀ R) : (finsupp.total α' M' R v') (emb_domain f l) = (finsupp.total α M' R (v' ∘ f)) l := by simp [total_apply, finsupp.sum, support_emb_domain, emb_domain_apply] theorem total_map_domain (f : α → α') (hf : function.injective f) (l : α →₀ R) : (finsupp.total α' M' R v') (map_domain f l) = (finsupp.total α M' R (v' ∘ f)) l := begin have : map_domain f l = emb_domain ⟨f, hf⟩ l, { rw emb_domain_eq_map_domain ⟨f, hf⟩, refl }, rw this, apply total_emb_domain R ⟨f, hf⟩ l end theorem span_eq_map_total (s : set α): span R (v '' s) = submodule.map (finsupp.total α M R v) (supported R R s) := begin apply span_eq_of_le, { intros x hx, rw set.mem_image at hx, apply exists.elim hx, intros i hi, exact ⟨_, finsupp.single_mem_supported R 1 hi.1, by simp [hi.2]⟩ }, { refine map_le_iff_le_comap.2 (λ z hz, _), have : ∀i, z i • v i ∈ span R (v '' s), { intro c, haveI := classical.dec_pred (λ x, x ∈ s), by_cases c ∈ s, { exact smul_mem _ _ (subset_span (set.mem_image_of_mem _ h)) }, { simp [(finsupp.mem_supported' R _).1 hz _ h] } }, refine sum_mem _ _, simp [this] } end theorem mem_span_iff_total {s : set α} {x : M}: x ∈ span R (v '' s) ↔ ∃ l ∈ supported R R s, finsupp.total α M R v l = x := by rw span_eq_map_total; simp variables (α) (M) (v) protected def total_on (s : set α) : supported R R s →ₗ[R] span R (v '' s) := linear_map.cod_restrict _ ((finsupp.total _ _ _ v).comp (submodule.subtype (supported R R s))) $ λ ⟨l, hl⟩, (mem_span_iff_total _).2 ⟨l, hl, rfl⟩ variables {α} {M} {v} theorem total_on_range (s : set α) : (finsupp.total_on α M R v s).range = ⊤ := by rw [finsupp.total_on, linear_map.range, linear_map.map_cod_restrict, ← linear_map.range_le_iff_comap, range_subtype, map_top, linear_map.range_comp, range_subtype]; exact le_of_eq (span_eq_map_total _ _) theorem total_comp (f : α' → α) : (finsupp.total α' M R (v ∘ f)) = (finsupp.total α M R v).comp (lmap_domain R R f) := begin ext l, simp [total_apply], rw sum_map_domain_index; simp [add_smul], end lemma total_comap_domain (f : α → α') (l : α' →₀ R) (hf : set.inj_on f (f ⁻¹' l.support.to_set)) : finsupp.total α M R v (finsupp.comap_domain f l hf) = (l.support.preimage hf).sum (λ i, (l (f i)) • (v i)) := by rw finsupp.total_apply; refl end total protected def dom_lcongr {α₁ : Type*} {α₂ : Type*} (e : α₁ ≃ α₂) : (α₁ →₀ M) ≃ₗ[R] (α₂ →₀ M) := (finsupp.dom_congr e).to_linear_equiv begin change is_linear_map R (lmap_domain M R e : (α₁ →₀ M) →ₗ[R] (α₂ →₀ M)), exact linear_map.is_linear _ end noncomputable def congr {α' : Type*} (s : set α) (t : set α') (e : s ≃ t) : supported M R s ≃ₗ[R] supported M R t := begin haveI := classical.dec_pred (λ x, x ∈ s), haveI := classical.dec_pred (λ x, x ∈ t), refine linear_equiv.trans (finsupp.supported_equiv_finsupp s) (linear_equiv.trans _ (finsupp.supported_equiv_finsupp t).symm), exact finsupp.dom_lcongr e end end finsupp lemma linear_map.map_finsupp_total {R : Type*} {β : Type*} {γ : Type*} [ring R] [add_comm_group β] [module R β] [add_comm_group γ] [module R γ] (f : β →ₗ[R] γ) {ι : Type*} [fintype ι] {g : ι → β} (l : ι →₀ R) : f (finsupp.total ι β R g l) = finsupp.total ι γ R (f ∘ g) l := by simp only [finsupp.total_apply, finsupp.total_apply, finsupp.sum, f.map_sum, f.map_smul]