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 Multivariate functions of the form `α^n → α` are isomorphic to multivariate polynomials in `n` variables. -/ import linear_algebra.finsupp_vector_space field_theory.finite data.mv_polynomial noncomputable theory open_locale classical open lattice set linear_map submodule namespace mv_polynomial universes u v variables {σ : Type u} {α : Type v} instance [discrete_field α] : vector_space α (mv_polynomial σ α) := finsupp.vector_space _ _ section variables (σ α) [discrete_field α] (m : ℕ) def restrict_total_degree : submodule α (mv_polynomial σ α) := finsupp.supported _ _ {n | n.sum (λn e, e) ≤ m } lemma mem_restrict_total_degree (p : mv_polynomial σ α) : p ∈ restrict_total_degree σ α m ↔ p.total_degree ≤ m := begin rw [total_degree, finset.sup_le_iff], refl end end section variables (σ α) def restrict_degree (m : ℕ) [discrete_field α] : submodule α (mv_polynomial σ α) := finsupp.supported _ _ {n | ∀i, n i ≤ m } end lemma mem_restrict_degree [discrete_field α] (p : mv_polynomial σ α) (n : ℕ) : p ∈ restrict_degree σ α n ↔ (∀s ∈ p.support, ∀i, (s : σ →₀ ℕ) i ≤ n) := begin rw [restrict_degree, finsupp.mem_supported], refl end lemma mem_restrict_degree_iff_sup [discrete_field α] (p : mv_polynomial σ α) (n : ℕ) : p ∈ restrict_degree σ α n ↔ ∀i, p.degrees.count i ≤ n := begin simp only [mem_restrict_degree, degrees, multiset.count_sup, finsupp.count_to_multiset, finset.sup_le_iff], exact ⟨assume h n s hs, h s hs n, assume h s hs n, h n s hs⟩ end lemma map_range_eq_map {β : Type*} [comm_ring α] [comm_ring β] (p : mv_polynomial σ α) (f : α → β) [is_semiring_hom f]: finsupp.map_range f (is_semiring_hom.map_zero f) p = p.map f := begin rw [← finsupp.sum_single p, finsupp.sum, finsupp.map_range_finset_sum, ← p.support.sum_hom (map f)], { refine finset.sum_congr rfl (assume n _, _), rw [finsupp.map_range_single, ← monomial, ← monomial, map_monomial] }, apply_instance end section variables (σ α) lemma is_basis_monomials [discrete_field α] : is_basis α ((λs, (monomial s 1 : mv_polynomial σ α))) := suffices is_basis α (λ (sa : Σ _, unit), (monomial sa.1 1 : mv_polynomial σ α)), begin apply is_basis.comp this (λ (s : σ →₀ ℕ), ⟨s, punit.star⟩), split, { intros x y hxy, simpa using hxy }, { intros x, rcases x with ⟨x₁, x₂⟩, use x₁, rw punit_eq punit.star x₂ } end, begin apply finsupp.is_basis_single (λ _ _, (1 : α)), intro _, apply is_basis_singleton_one, end end end mv_polynomial namespace mv_polynomial universe u variables (σ : Type u) (α : Type u) [discrete_field α] open_locale classical lemma dim_mv_polynomial : vector_space.dim α (mv_polynomial σ α) = cardinal.mk (σ →₀ ℕ) := by rw [← cardinal.lift_inj, ← (is_basis_monomials σ α).mk_eq_dim] end mv_polynomial namespace mv_polynomial variables {α : Type*} {σ : Type*} variables [discrete_field α] [fintype α] [fintype σ] def indicator (a : σ → α) : mv_polynomial σ α := finset.univ.prod (λn, 1 - (X n - C (a n))^(fintype.card α - 1)) lemma eval_indicator_apply_eq_one (a : σ → α) : eval a (indicator a) = 1 := have 0 < fintype.card α - 1, begin rw [← finite_field.card_units, fintype.card_pos_iff], exact ⟨1⟩ end, by simp only [indicator, (finset.univ.prod_hom (eval a)).symm, eval_sub, is_ring_hom.map_one (eval a), is_semiring_hom.map_pow (eval a), eval_X, eval_C, sub_self, zero_pow this, sub_zero, finset.prod_const_one] lemma eval_indicator_apply_eq_zero (a b : σ → α) (h : a ≠ b) : eval a (indicator b) = 0 := have ∃i, a i ≠ b i, by rwa [(≠), function.funext_iff, not_forall] at h, begin rcases this with ⟨i, hi⟩, simp only [indicator, (finset.univ.prod_hom (eval a)).symm, eval_sub, is_ring_hom.map_one (eval a), is_semiring_hom.map_pow (eval a), eval_X, eval_C, sub_self, finset.prod_eq_zero_iff], refine ⟨i, finset.mem_univ _, _⟩, rw [finite_field.pow_card_sub_one_eq_one, sub_self], rwa [(≠), sub_eq_zero], end lemma degrees_indicator (c : σ → α) : degrees (indicator c) ≤ finset.univ.sum (λs:σ, add_monoid.smul (fintype.card α - 1) {s}) := begin rw [indicator], refine le_trans (degrees_prod _ _) (finset.sum_le_sum $ assume s hs, _), refine le_trans (degrees_sub _ _) _, rw [degrees_one, ← bot_eq_zero, bot_sup_eq], refine le_trans (degrees_pow _ _) (add_monoid.smul_le_smul_of_le_right _ _), refine le_trans (degrees_sub _ _) _, rw [degrees_C, ← bot_eq_zero, sup_bot_eq], exact degrees_X _ end set_option class.instance_max_depth 50 lemma indicator_mem_restrict_degree (c : σ → α) : indicator c ∈ restrict_degree σ α (fintype.card α - 1) := begin rw [mem_restrict_degree_iff_sup, indicator], assume n, refine le_trans (multiset.count_le_of_le _ $ degrees_indicator _) (le_of_eq _), rw [← finset.univ.sum_hom (multiset.count n)], simp only [is_add_monoid_hom.map_smul (multiset.count n), multiset.singleton_eq_singleton, add_monoid.smul_eq_mul, nat.cast_id], transitivity, refine finset.sum_eq_single n _ _, { assume b hb ne, rw [multiset.count_cons_of_ne ne.symm, multiset.count_zero, mul_zero] }, { assume h, exact (h $ finset.mem_univ _).elim }, { rw [multiset.count_cons_self, multiset.count_zero, mul_one] } end section variables (α σ) def evalₗ : mv_polynomial σ α →ₗ[α] (σ → α) → α := ⟨ λp e, p.eval e, assume p q, funext $ assume e, eval_add, assume a p, funext $ assume e, by rw [smul_eq_C_mul, eval_mul, eval_C]; refl ⟩ end section lemma evalₗ_apply (p : mv_polynomial σ α) (e : σ → α) : evalₗ α σ p e = p.eval e := rfl end lemma map_restrict_dom_evalₗ : (restrict_degree σ α (fintype.card α - 1)).map (evalₗ α σ) = ⊤ := begin refine top_unique (submodule.le_def'.2 $ assume e _, mem_map.2 _), refine ⟨finset.univ.sum (λn:σ → α, e n • indicator n), _, _⟩, { exact sum_mem _ (assume c _, smul_mem _ _ (indicator_mem_restrict_degree _)) }, { ext n, simp only [linear_map.map_sum, @pi.finset_sum_apply (σ → α) (λ_, α) _ _ _ _ _, pi.smul_apply, linear_map.map_smul], simp only [evalₗ_apply], transitivity, refine finset.sum_eq_single n _ _, { assume b _ h, rw [eval_indicator_apply_eq_zero _ _ h.symm, smul_zero] }, { assume h, exact (h $ finset.mem_univ n).elim }, { rw [eval_indicator_apply_eq_one, smul_eq_mul, mul_one] } } end end mv_polynomial namespace mv_polynomial universe u variables (σ : Type u) (α : Type u) [fintype σ] [discrete_field α] [fintype α] @[derive [add_comm_group, vector_space α, inhabited]] def R : Type u := restrict_degree σ α (fintype.card α - 1) noncomputable instance decidable_restrict_degree (m : ℕ) : decidable_pred (λn, n ∈ {n : σ →₀ ℕ | ∀i, n i ≤ m }) := by simp only [set.mem_set_of_eq]; apply_instance set_option class.instance_max_depth 60 lemma dim_R : vector_space.dim α (R σ α) = fintype.card (σ → α) := calc vector_space.dim α (R σ α) = vector_space.dim α (↥{s : σ →₀ ℕ | ∀ (n : σ), s n ≤ fintype.card α - 1} →₀ α) : linear_equiv.dim_eq (finsupp.supported_equiv_finsupp {s : σ →₀ ℕ | ∀n:σ, s n ≤ fintype.card α - 1 }) ... = cardinal.mk {s : σ →₀ ℕ | ∀ (n : σ), s n ≤ fintype.card α - 1} : by rw [finsupp.dim_eq, dim_of_field, mul_one] ... = cardinal.mk {s : σ → ℕ | ∀ (n : σ), s n < fintype.card α } : begin refine quotient.sound ⟨equiv.subtype_congr finsupp.equiv_fun_on_fintype $ assume f, _⟩, refine forall_congr (assume n, nat.le_sub_right_iff_add_le _), exact fintype.card_pos_iff.2 ⟨0⟩ end ... = cardinal.mk (σ → {n // n < fintype.card α}) : quotient.sound ⟨@equiv.subtype_pi_equiv_pi σ (λ_, ℕ) (λs n, n < fintype.card α)⟩ ... = cardinal.mk (σ → fin (fintype.card α)) : quotient.sound ⟨equiv.arrow_congr (equiv.refl σ) (equiv.fin_equiv_subtype _).symm⟩ ... = cardinal.mk (σ → α) : begin refine (trunc.induction_on (fintype.equiv_fin α) $ assume (e : α ≃ fin (fintype.card α)), _), refine quotient.sound ⟨equiv.arrow_congr (equiv.refl σ) e.symm⟩ end ... = fintype.card (σ → α) : cardinal.fintype_card _ def evalᵢ : R σ α →ₗ[α] (σ → α) → α := ((evalₗ α σ).comp (restrict_degree σ α (fintype.card α - 1)).subtype) lemma range_evalᵢ : (evalᵢ σ α).range = ⊤ := begin rw [evalᵢ, linear_map.range_comp, range_subtype], exact map_restrict_dom_evalₗ end lemma ker_evalₗ : (evalᵢ σ α).ker = ⊥ := begin refine injective_of_surjective _ _ _ (range_evalᵢ _ _), { rw [dim_R], exact cardinal.nat_lt_omega _ }, { rw [dim_R, dim_fun, dim_of_field, mul_one] } end lemma eq_zero_of_eval_eq_zero (p : mv_polynomial σ α) (h : ∀v:σ → α, p.eval v = 0) (hp : p ∈ restrict_degree σ α (fintype.card α - 1)) : p = 0 := let p' : R σ α := ⟨p, hp⟩ in have p' ∈ (evalᵢ σ α).ker := by rw [mem_ker]; ext v; exact h v, show p'.1 = (0 : R σ α).1, begin rw [ker_evalₗ, mem_bot] at this, rw [this] end end mv_polynomial