Skip to content

Instantly share code, notes, and snippets.

@jcommelin
Created July 12, 2019 12:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jcommelin/a521437d3886968db4a54154da503f3e to your computer and use it in GitHub Desktop.
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
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