Created
July 12, 2019 12:14
-
-
Save jcommelin/a521437d3886968db4a54154da503f3e to your computer and use it in GitHub Desktop.
Stuck on defining the inverse of a power series using well-founded recursion
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import data.finsupp order.complete_lattice algebra.ordered_group data.mv_polynomial | |
import algebra.order_functions | |
namespace multiset | |
variables {α : Type*} [decidable_eq α] | |
def to_finsupp (s : multiset α) : α →₀ ℕ := | |
{ support := s.to_finset, | |
to_fun := λ a, s.count a, | |
mem_support_to_fun := λ a, | |
begin | |
rw mem_to_finset, | |
convert not_iff_not_of_iff (count_eq_zero.symm), | |
rw not_not | |
end } | |
@[simp] lemma to_finsupp_support (s : multiset α) : | |
s.to_finsupp.support = s.to_finset := rfl | |
@[simp] lemma to_finsupp_apply (s : multiset α) (a : α) : | |
s.to_finsupp a = s.count a := rfl | |
@[simp] lemma to_finsupp_zero : | |
to_finsupp (0 : multiset α) = 0 := | |
finsupp.ext $ λ a, count_zero a | |
@[simp] lemma to_finsupp_add (s t : multiset α) : | |
to_finsupp (s + t) = to_finsupp s + to_finsupp t := | |
finsupp.ext $ λ a, count_add a s t | |
namespace to_finsupp | |
instance : is_add_monoid_hom (to_finsupp : multiset α → α →₀ ℕ) := | |
{ map_zero := to_finsupp_zero, | |
map_add := to_finsupp_add } | |
end to_finsupp | |
@[simp] lemma to_finsupp_to_multiset (s : multiset α) : | |
s.to_finsupp.to_multiset = s := | |
ext.2 $ λ a, by rw [finsupp.count_to_multiset, to_finsupp_apply] | |
end multiset | |
namespace finsupp | |
variables {σ : Type*} {α : Type*} [decidable_eq σ] | |
instance [preorder α] [has_zero α] : preorder (σ →₀ α) := | |
{ le := λ f g, ∀ s, f s ≤ g s, | |
le_refl := λ f s, le_refl _, | |
le_trans := λ f g h Hfg Hgh s, le_trans (Hfg s) (Hgh s) } | |
instance [partial_order α] [has_zero α] : partial_order (σ →₀ α) := | |
{ le_antisymm := λ f g hfg hgf, finsupp.ext $ λ s, le_antisymm (hfg s) (hgf s), | |
.. finsupp.preorder } | |
instance [ordered_cancel_comm_monoid α] [decidable_eq α] : | |
add_left_cancel_semigroup (σ →₀ α) := | |
{ add_left_cancel := λ a b c h, finsupp.ext $ λ s, | |
by { rw finsupp.ext_iff at h, exact add_left_cancel (h s) }, | |
.. finsupp.add_monoid } | |
instance [ordered_cancel_comm_monoid α] [decidable_eq α] : | |
add_right_cancel_semigroup (σ →₀ α) := | |
{ add_right_cancel := λ a b c h, finsupp.ext $ λ s, | |
by { rw finsupp.ext_iff at h, exact add_right_cancel (h s) }, | |
.. finsupp.add_monoid } | |
instance [ordered_cancel_comm_monoid α] [decidable_eq α] : | |
ordered_cancel_comm_monoid (σ →₀ α) := | |
{ add_le_add_left := λ a b h c s, add_le_add_left (h s) (c s), | |
le_of_add_le_add_left := λ a b c h s, le_of_add_le_add_left (h s), | |
.. finsupp.add_comm_monoid, .. finsupp.partial_order, | |
.. finsupp.add_left_cancel_semigroup, .. finsupp.add_right_cancel_semigroup } | |
attribute [simp] to_multiset_zero to_multiset_add | |
@[simp] lemma to_multiset_to_finsupp (f : σ →₀ ℕ) : | |
f.to_multiset.to_finsupp = f := | |
ext $ λ s, by rw [multiset.to_finsupp_apply, count_to_multiset] | |
def diagonal (f : σ →₀ ℕ) : finset ((σ →₀ ℕ) × (σ →₀ ℕ)) := | |
((multiset.diagonal f.to_multiset).map (prod.map multiset.to_finsupp multiset.to_finsupp)).to_finset | |
lemma mem_diagonal {f : σ →₀ ℕ} {p : (σ →₀ ℕ) × (σ →₀ ℕ)} : | |
p ∈ diagonal f ↔ p.1 + p.2 = f := | |
begin | |
erw [multiset.mem_to_finset, multiset.mem_map], | |
split, | |
{ rintros ⟨⟨a, b⟩, h, rfl⟩, | |
rw multiset.mem_diagonal at h, | |
simpa using congr_arg multiset.to_finsupp h }, | |
{ intro h, | |
refine ⟨⟨p.1.to_multiset, p.2.to_multiset⟩, _, _⟩, | |
{ simpa using congr_arg to_multiset h }, | |
{ rw [prod.map, to_multiset_to_finsupp, to_multiset_to_finsupp, prod.mk.eta] } } | |
end | |
lemma swap_mem_diagonal {n : σ →₀ ℕ} {f} (hf : f ∈ diagonal n) : f.swap ∈ diagonal n := | |
by simpa [mem_diagonal, add_comm] using hf | |
@[simp] lemma diagonal_zero : diagonal (0 : σ →₀ ℕ) = {(0,0)} := rfl | |
lemma to_multiset_strict_mono : strict_mono (@to_multiset σ _) := | |
λ m n h, | |
begin | |
rw lt_iff_le_and_ne at h ⊢, cases h with h₁ h₂, | |
split, | |
{ rw multiset.le_iff_count, intro s, rw [count_to_multiset, count_to_multiset], exact h₁ s }, | |
{ intro H, apply h₂, replace H := congr_arg multiset.to_finsupp H, simpa using H } | |
end | |
lemma sum_lt_of_lt (m n : σ →₀ ℕ) (h : m < n) : | |
m.sum (λ _, id) < n.sum (λ _, id) := | |
begin | |
rw [← card_to_multiset, ← card_to_multiset], | |
apply multiset.card_lt_of_lt, | |
exact to_multiset_strict_mono _ _ h | |
end | |
variable (σ) | |
def lt_wf : well_founded (@has_lt.lt (σ →₀ ℕ) _) := | |
subrelation.wf (sum_lt_of_lt) $ inv_image.wf _ nat.lt_wf | |
-- instance : has_well_founded (σ →₀ ℕ) := | |
-- { r := (<), | |
-- wf := lt_wf σ } | |
end finsupp | |
/-- Multivariate power series, where `σ` is the index set of the variables | |
and `α` is the coefficient ring.-/ | |
def mv_power_series (σ : Type*) (α : Type*) := (σ →₀ ℕ) → α | |
namespace mv_power_series | |
open finsupp | |
variables {σ : Type*} {α : Type*} [decidable_eq σ] | |
def coeff (n : σ →₀ ℕ) (φ : mv_power_series σ α) := φ n | |
@[extensionality] lemma ext {φ ψ : mv_power_series σ α} (h : ∀ n, coeff n φ = coeff n ψ) : φ = ψ := | |
funext h | |
lemma ext_iff {φ ψ : mv_power_series σ α} : φ = ψ ↔ (∀ n, coeff n φ = coeff n ψ) := | |
⟨λ h n, congr_arg (coeff n) h, ext⟩ | |
variables [comm_semiring α] | |
def monomial (n : σ →₀ ℕ) (a : α) : mv_power_series σ α := λ m, if m = n then a else 0 | |
lemma coeff_monomial (m n : σ →₀ ℕ) (a : α) : | |
coeff m (monomial n a) = if m = n then a else 0 := rfl | |
@[simp] lemma coeff_monomial' (n : σ →₀ ℕ) (a : α) : | |
coeff n (monomial n a) = a := if_pos rfl | |
def C (a : α) : mv_power_series σ α := monomial 0 a | |
lemma coeff_C (n : σ →₀ ℕ) (a : α) : | |
coeff n (C a : mv_power_series σ α) = if n = 0 then a else 0 := rfl | |
@[simp] lemma coeff_C_zero (a : α) : coeff 0 (C a : mv_power_series σ α) = a := | |
coeff_monomial' 0 a | |
@[simp] lemma monomial_zero (a : α) : (monomial 0 a : mv_power_series σ α) = C a := rfl | |
def X (s : σ) : mv_power_series σ α := monomial (single s 1) 1 | |
lemma coeff_X (n : σ →₀ ℕ) (s : σ) : | |
coeff n (X s : mv_power_series σ α) = if n = (single s 1) then 1 else 0 := rfl | |
lemma coeff_X' (s t : σ) : | |
coeff (single t 1) (X s : mv_power_series σ α) = if t = s then 1 else 0 := | |
if h : t = s then by simp [h, coeff_X] else | |
begin | |
rw [coeff_X, if_neg h], | |
split_ifs with H, | |
{ have := @finsupp.single_apply σ ℕ _ _ _ t s 1, | |
rw [if_neg h, H, finsupp.single_apply, if_pos rfl] at this, | |
exfalso, exact one_ne_zero this, }, | |
{ refl } | |
end | |
@[simp] lemma coeff_X'' (s : σ) : | |
coeff (single s 1) (X s : mv_power_series σ α) = 1 := | |
by rw [coeff_X', if_pos rfl] | |
section ring | |
variables (σ) (α) (n : σ →₀ ℕ) (φ ψ : mv_power_series σ α) | |
def zero : mv_power_series σ α := λ n, 0 | |
instance : has_zero (mv_power_series σ α) := ⟨zero σ α⟩ | |
@[simp] lemma coeff_zero : coeff n (0 : mv_power_series σ α) = 0 := rfl | |
@[simp] lemma C_zero : (C 0 : mv_power_series σ α) = 0 := | |
ext $ λ n, if h : n = 0 then by simp [h] else by rw [coeff_C, if_neg h, coeff_zero] | |
def one : mv_power_series σ α := C 1 | |
instance : has_one (mv_power_series σ α) := ⟨one σ α⟩ | |
@[simp] lemma coeff_one : | |
coeff n (1 : mv_power_series σ α) = if n = 0 then 1 else 0 := rfl | |
@[simp] lemma coeff_one_zero : coeff 0 (1 : mv_power_series σ α) = 1 := | |
coeff_C_zero 1 | |
@[simp] lemma C_one : (C 1 : mv_power_series σ α) = 1 := rfl | |
def add (φ ψ : mv_power_series σ α) : mv_power_series σ α := | |
λ n, coeff n φ + coeff n ψ | |
instance : has_add (mv_power_series σ α) := ⟨add σ α⟩ | |
variables {σ α} | |
@[simp] lemma coeff_add : coeff n (φ + ψ) = coeff n φ + coeff n ψ := rfl | |
@[simp] lemma zero_add : (0 : mv_power_series σ α) + φ = φ := ext $ λ n, zero_add _ | |
@[simp] lemma add_zero : φ + 0 = φ := ext $ λ n, add_zero _ | |
lemma add_comm : φ + ψ = ψ + φ := ext $ λ n, add_comm _ _ | |
lemma add_assoc (φ₁ φ₂ φ₃ : mv_power_series σ α) : | |
(φ₁ + φ₂) + φ₃ = φ₁ + (φ₂ + φ₃) := | |
ext $ λ n, by simp | |
@[simp] lemma monomial_add (n : σ →₀ ℕ) (a b : α) : | |
(monomial n (a + b) : mv_power_series σ α) = monomial n a + monomial n b := | |
ext $ λ m, if h : m = n then by simp [h] else by simp [coeff_monomial, if_neg h] | |
@[simp] lemma C_add (a b : α) : (C (a + b) : mv_power_series σ α) = C a + C b := | |
monomial_add 0 a b | |
variables (σ α) | |
def mul (φ ψ : mv_power_series σ α) : mv_power_series σ α := | |
λ n, (finsupp.diagonal n).sum (λ p, coeff p.1 φ * coeff p.2 ψ) | |
instance : has_mul (mv_power_series σ α) := ⟨mul σ α⟩ | |
variables {σ α} | |
lemma coeff_mul : | |
coeff n (φ * ψ) = (finsupp.diagonal n).sum (λ p, coeff p.1 φ * coeff p.2 ψ) := rfl | |
@[simp] lemma C_mul (a b : α) : (C (a * b) : mv_power_series σ α) = C a * C b := | |
ext $ λ n, | |
begin | |
rw [coeff_C, coeff_mul], | |
split_ifs, | |
{ subst n, erw [diagonal_zero, finset.sum_singleton, coeff_C_zero, coeff_C_zero] }, | |
{ rw finset.sum_eq_zero, | |
rintros ⟨i,j⟩ hij, | |
rw mem_diagonal at hij, rw [coeff_C, coeff_C], | |
split_ifs; try {simp * at *; done} } | |
end | |
@[simp] lemma zero_mul : (0 : mv_power_series σ α) * φ = 0 := | |
ext $ λ n, by simp [coeff_mul] | |
@[simp] lemma mul_zero : φ * 0 = 0 := | |
ext $ λ n, by simp [coeff_mul] | |
lemma mul_comm : φ * ψ = ψ * φ := | |
ext $ λ n, finset.sum_bij (λ p hp, p.swap) | |
(λ p hp, swap_mem_diagonal hp) | |
(λ p hp, mul_comm _ _) | |
(λ p q hp hq H, by simpa using congr_arg prod.swap H) | |
(λ p hp, ⟨p.swap, swap_mem_diagonal hp, p.swap_swap.symm⟩) | |
@[simp] lemma one_mul : (1 : mv_power_series σ α) * φ = φ := | |
ext $ λ n, | |
begin | |
have H : ((0 : σ →₀ ℕ), n) ∈ (diagonal n) := by simp [mem_diagonal], | |
rw [coeff_mul, ← finset.insert_erase H, finset.sum_insert (finset.not_mem_erase _ _), | |
coeff_one_zero, one_mul, finset.sum_eq_zero, _root_.add_zero], | |
rintros ⟨i,j⟩ hij, | |
rw [finset.mem_erase, mem_diagonal] at hij, | |
rw [coeff_one, if_neg, _root_.zero_mul], | |
intro H, apply hij.1, simp * at * | |
end | |
@[simp] lemma mul_one : φ * 1 = φ := | |
by rw [mul_comm, one_mul] | |
lemma mul_add (φ₁ φ₂ φ₃ : mv_power_series σ α) : | |
φ₁ * (φ₂ + φ₃) = φ₁ * φ₂ + φ₁ * φ₃ := | |
ext $ λ n, by simp only [coeff_mul, coeff_add, mul_add, finset.sum_add_distrib] | |
lemma add_mul (φ₁ φ₂ φ₃ : mv_power_series σ α) : | |
(φ₁ + φ₂) * φ₃ = φ₁ * φ₃ + φ₂ * φ₃ := | |
ext $ λ n, by simp only [coeff_mul, coeff_add, add_mul, finset.sum_add_distrib] | |
lemma mul_assoc (φ₁ φ₂ φ₃ : mv_power_series σ α) : | |
(φ₁ * φ₂) * φ₃ = φ₁ * (φ₂ * φ₃) := | |
ext $ λ n, | |
begin | |
simp only [coeff_mul], | |
have := @finset.sum_sigma ((σ →₀ ℕ) × (σ →₀ ℕ)) α _ _ (diagonal n) | |
(λ p, diagonal (p.1)) (λ x, coeff x.2.1 φ₁ * coeff x.2.2 φ₂ * coeff x.1.2 φ₃), | |
convert this.symm using 1; clear this, | |
{ apply finset.sum_congr rfl, | |
intros p hp, exact finset.sum_mul }, | |
have := @finset.sum_sigma ((σ →₀ ℕ) × (σ →₀ ℕ)) α _ _ (diagonal n) | |
(λ p, diagonal (p.2)) (λ x, coeff x.1.1 φ₁ * (coeff x.2.1 φ₂ * coeff x.2.2 φ₃)), | |
convert this.symm using 1; clear this, | |
{ apply finset.sum_congr rfl, intros p hp, rw finset.mul_sum }, | |
apply finset.sum_bij, | |
swap 5, | |
{ rintros ⟨⟨i,j⟩, ⟨k,l⟩⟩ H, exact ⟨(k, l+j), (l, j)⟩ }, | |
{ rintros ⟨⟨i,j⟩, ⟨k,l⟩⟩ H, simp only [finset.mem_sigma, mem_diagonal] at H ⊢, finish }, | |
{ rintros ⟨⟨i,j⟩, ⟨k,l⟩⟩ H, rw mul_assoc }, | |
{ rintros ⟨⟨a,b⟩, ⟨c,d⟩⟩ ⟨⟨i,j⟩, ⟨k,l⟩⟩ H₁ H₂, | |
simp only [finset.mem_sigma, mem_diagonal, | |
and_imp, prod.mk.inj_iff, add_comm, heq_iff_eq] at H₁ H₂ ⊢, | |
finish }, | |
{ rintros ⟨⟨i,j⟩, ⟨k,l⟩⟩ H, refine ⟨⟨(i+k, l), (i, k)⟩, _, _⟩; | |
{ simp only [finset.mem_sigma, mem_diagonal] at H ⊢, finish } } | |
end | |
instance : comm_semiring (mv_power_series σ α) := | |
{ mul_one := mul_one, | |
one_mul := one_mul, | |
add_assoc := add_assoc, | |
zero_add := zero_add, | |
add_zero := add_zero, | |
add_comm := add_comm, | |
mul_assoc := mul_assoc, | |
mul_zero := mul_zero, | |
zero_mul := zero_mul, | |
mul_comm := mul_comm, | |
left_distrib := mul_add, | |
right_distrib := add_mul, | |
.. mv_power_series.has_zero σ α, | |
.. mv_power_series.has_one σ α, | |
.. mv_power_series.has_add σ α, | |
.. mv_power_series.has_mul σ α } | |
instance C.is_semiring_hom : is_semiring_hom (C : α → mv_power_series σ α) := | |
{ map_zero := C_zero _ _, | |
map_one := C_one _ _, | |
map_add := C_add, | |
map_mul := C_mul } | |
instance coeff.is_add_monoid_hom : is_add_monoid_hom (coeff n : mv_power_series σ α → α) := | |
{ map_zero := coeff_zero _ _ _, | |
map_add := coeff_add n } | |
instance : semimodule α (mv_power_series σ α) := | |
{ smul := λ a φ, C a * φ, | |
one_smul := λ φ, one_mul _, | |
mul_smul := λ a b φ, by simp only [C_mul, mul_assoc], | |
smul_add := λ a φ ψ, mul_add _ _ _, | |
smul_zero := λ a, mul_zero _, | |
add_smul := λ a b φ, by simp only [C_add, add_mul], | |
zero_smul := λ φ, by simp only [zero_mul, C_zero] } | |
end ring | |
-- TODO(jmc): once adic topology lands, show that this is complete | |
end mv_power_series | |
namespace mv_power_series | |
variables {σ : Type*} {α : Type*} [decidable_eq σ] [comm_ring α] | |
protected def neg (φ : mv_power_series σ α) : mv_power_series σ α := λ n, - coeff n φ | |
instance : has_neg (mv_power_series σ α) := ⟨mv_power_series.neg⟩ | |
@[simp] lemma coeff_neg (φ : mv_power_series σ α) (n) : coeff n (- φ) = - coeff n φ := rfl | |
lemma add_left_neg (φ : mv_power_series σ α) : (-φ) + φ = 0 := | |
ext $ λ n, by rw [coeff_add, coeff_zero, coeff_neg, add_left_neg] | |
instance : comm_ring (mv_power_series σ α) := | |
{ add_left_neg := add_left_neg, | |
.. mv_power_series.has_neg, .. mv_power_series.comm_semiring } | |
instance C.is_ring_hom : is_ring_hom (C : α → mv_power_series σ α) := | |
{ map_one := C_one _ _, | |
map_add := C_add, | |
map_mul := C_mul } | |
instance coeff.is_add_group_hom (n : σ →₀ ℕ) : | |
is_add_group_hom (coeff n : mv_power_series σ α → α) := | |
{ map_add := coeff_add n } | |
instance : module α (mv_power_series σ α) := | |
{ ..mv_power_series.semimodule } | |
def inv_of_unit (φ : mv_power_series σ α) (u : units α) (h : coeff 0 φ = u) : mv_power_series σ α | |
| n := if n = 0 then ↑u⁻¹ else | |
- ↑u⁻¹ * finset.sum (n.diagonal) (λ (x : (σ →₀ ℕ) × (σ →₀ ℕ)), | |
if h : x.1 < n then inv_of_unit x.1 * coeff x.2 φ else 0) | |
using_well_founded { rel_tac := λ _ _, `[exact ⟨_, finsupp.lt_wf σ⟩] } | |
end mv_power_series |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment