Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit 8fa9125

Browse files
adomanijcommelinurkud
committed
feat(data/polynomial/degree/erase_lead): definition and basic lemmas (#4527)
erase_lead serves as the reduction step in an induction, breaking off one monomial from a polynomial. It is used in a later PR to prove that reverse is a multiplicative monoid map on polynomials. Co-authored-by: Johan Commelin <johan@commelin.net> Co-authored-by: Yury G. Kudryashov <urkud@urkud.name>
1 parent 0bfc68f commit 8fa9125

File tree

6 files changed

+212
-5
lines changed

6 files changed

+212
-5
lines changed

src/data/finset/basic.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ theorem subset_def {s₁ s₂ : finset α} : s₁ ⊆ s₂ ↔ s₁.1 ⊆ s₂.1
100100

101101
@[simp] theorem subset.refl (s : finset α) : s ⊆ s := subset.refl _
102102

103+
theorem subset_of_eq {s t : finset α} (h : s = t) : s ⊆ t := h ▸ subset.refl _
104+
103105
theorem subset.trans {s₁ s₂ s₃ : finset α} : s₁ ⊆ s₂ → s₂ ⊆ s₃ → s₁ ⊆ s₃ := subset.trans
104106

105107
theorem superset.trans {s₁ s₂ s₃ : finset α} : s₁ ⊇ s₂ → s₂ ⊇ s₃ → s₁ ⊇ s₃ :=
@@ -1641,6 +1643,14 @@ theorem card_erase_lt_of_mem [decidable_eq α] {a : α} {s : finset α} :
16411643
theorem card_erase_le [decidable_eq α] {a : α} {s : finset α} :
16421644
card (erase s a) ≤ card s := card_erase_le
16431645

1646+
theorem pred_card_le_card_erase [decidable_eq α] {a : α} {s : finset α} :
1647+
card s - 1 ≤ card (erase s a) :=
1648+
begin
1649+
by_cases h : a ∈ s,
1650+
{ rw [card_erase_of_mem h], refl },
1651+
{ rw [erase_eq_of_not_mem h], apply nat.sub_le }
1652+
end
1653+
16441654
@[simp] theorem card_range (n : ℕ) : card (range n) = n := card_range n
16451655

16461656
@[simp] theorem card_attach {s : finset α} : card (attach s) = card s := multiset.card_attach

src/data/finsupp/basic.lean

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ lemma ext_iff {f g : α →₀ β} : f = g ↔ (∀a:α, f a = g a) :=
102102
⟨assume h, ext $ assume a, by_contradiction $ λ H, (finset.ext_iff.1 h a).1 $
103103
mem_support_iff.2 H, by rintro rfl; refl⟩
104104

105+
lemma card_support_eq_zero {f : α →₀ β} : card f.support = 0 ↔ f = 0 :=
106+
by simp
107+
105108
instance finsupp.decidable_eq [decidable_eq α] [decidable_eq β] : decidable_eq (α →₀ β) :=
106109
assume f g, decidable_of_iff (f.support = g.support ∧ (∀a∈f.support, f a = g a))
107110
⟨assume ⟨h₁, h₂⟩, ext $ assume a,
@@ -174,6 +177,15 @@ assume b₁ b₂ eq,
174177
have (single a b₁ : α →₀ β) a = (single a b₂ : α →₀ β) a, by rw eq,
175178
by rwa [single_eq_same, single_eq_same] at this
176179

180+
lemma eq_single_iff {f : α →₀ β} {a b} : f = single a b ↔ f.support ⊆ {a} ∧ f a = b :=
181+
begin
182+
refine ⟨λ h, h.symm ▸ ⟨support_single_subset, single_eq_same⟩, _⟩,
183+
rintro ⟨h, rfl⟩,
184+
ext x,
185+
by_cases hx : a = x; simp only [hx, single_eq_same, single_eq_of_ne, ne.def, not_false_iff],
186+
exact not_mem_support_iff.1 (mt (λ hx, (mem_singleton.1 (h hx)).symm) hx)
187+
end
188+
177189
lemma single_eq_single_iff (a₁ a₂ : α) (b₁ b₂ : β) :
178190
single a₁ b₁ = single a₂ b₂ ↔ ((a₁ = a₂ ∧ b₁ = b₂) ∨ (b₁ = 0 ∧ b₂ = 0)) :=
179191
begin
@@ -219,6 +231,22 @@ lemma unique_ext_iff [unique α] {f g : α →₀ β} : f = g ↔ f (default α
219231
single a b = single a' b' ↔ b = b' :=
220232
by rw [unique_ext_iff, unique.eq_default a, unique.eq_default a', single_eq_same, single_eq_same]
221233

234+
lemma support_eq_singleton {f : α →₀ β} {a : α} :
235+
f.support = {a} ↔ f a ≠ 0 ∧ f = single a (f a) :=
236+
⟨λ h, ⟨mem_support_iff.1 $ h.symm ▸ finset.mem_singleton_self a,
237+
eq_single_iff.2 ⟨subset_of_eq h, rfl⟩⟩, λ h, h.2.symm ▸ support_single_ne_zero h.1
238+
239+
lemma support_eq_singleton' {f : α →₀ β} {a : α} :
240+
f.support = {a} ↔ ∃ b ≠ 0, f = single a b :=
241+
⟨λ h, let h := support_eq_singleton.1 h in ⟨_, h.1, h.2⟩,
242+
λ ⟨b, hb, hf⟩, hf.symm ▸ support_single_ne_zero hb⟩
243+
244+
lemma card_support_eq_one {f : α →₀ β} : card f.support = 1 ↔ ∃ a, f a ≠ 0 ∧ f = single a (f a) :=
245+
by simp only [card_eq_one, support_eq_singleton]
246+
247+
lemma card_support_eq_one' {f : α →₀ β} : card f.support = 1 ↔ ∃ a (b ≠ 0), f = single a b :=
248+
by simp only [card_eq_one, support_eq_singleton']
249+
222250
end single
223251

224252
/-! ### Declarations about `on_finset` -/
@@ -442,6 +470,10 @@ begin
442470
{ rw [erase_ne hs] }
443471
end
444472

473+
@[simp] lemma erase_zero [has_zero β] (a : α) :
474+
erase a (0 : α →₀ β) = 0 :=
475+
by rw [← support_eq_empty, support_erase, support_zero, erase_empty]
476+
445477
end erase
446478

447479
/-!

src/data/polynomial/basic.lean

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,18 +137,18 @@ begin
137137
exact finset.subset.refl {n}, },
138138
end
139139

140-
lemma monomial_eq_X_pow (n) : X^n = monomial n (1:R) :=
140+
lemma X_pow_eq_monomial (n) : X ^ n = monomial n (1:R) :=
141141
begin
142142
induction n with n hn,
143-
{ refl, },
144-
{ conv_rhs {rw nat.succ_eq_add_one, congr, skip, rw ← mul_one (1:R)},
145-
rw [← monomial_mul_monomial, ← hn, pow_succ, X_mul, X], },
143+
{ refl, },
144+
{ conv_rhs {rw nat.succ_eq_add_one, congr, skip, rw ← mul_one (1:R)},
145+
rw [← monomial_mul_monomial, ← hn, pow_succ, X_mul, X], },
146146
end
147147

148148
lemma support_X_pow (H : ¬ (1:R) = 0) (n : ℕ) : (X^n : polynomial R).support = singleton n :=
149149
begin
150150
convert support_monomial n 1 H,
151-
exact monomial_eq_X_pow n,
151+
exact X_pow_eq_monomial n,
152152
end
153153

154154
lemma support_X_empty (H : (1:R)=0) : (X : polynomial R).support = ∅ :=

src/data/polynomial/degree.lean

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Chris Hughes, Johannes Hölzl, Scott Morrison, Jens Wagemaker
55
-/
66
import data.polynomial.eval
7+
import tactic.interval_cases
78

89
/-!
910
# Theory of degrees of polynomials
@@ -148,6 +149,25 @@ end
148149

149150
end injective
150151

152+
section
153+
variable {f : polynomial R}
154+
155+
lemma monomial_nat_degree_leading_coeff_eq_self (h : f.support.card ≤ 1) :
156+
monomial f.nat_degree f.leading_coeff = f :=
157+
begin
158+
interval_cases f.support.card with H,
159+
{ have : f = 0 := finsupp.card_support_eq_zero.1 H,
160+
simp [this] },
161+
{ obtain ⟨n, x, hx, rfl : f = monomial n x⟩ := finsupp.card_support_eq_one'.1 H,
162+
simp [hx] }
163+
end
164+
165+
lemma C_mul_X_pow_eq_self (h : f.support.card ≤ 1) :
166+
C f.leading_coeff * X^f.nat_degree = f :=
167+
by rw [C_mul_X_pow_eq_monomial, monomial_nat_degree_leading_coeff_eq_self h]
168+
169+
end
170+
151171
end degree
152172
end semiring
153173

src/data/polynomial/degree/basic.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,10 @@ if h : a = 0 then by rw [h, C_0, zero_mul]; exact bot_le else le_of_eq (degree_m
173173
@[simp] lemma nat_degree_C_mul_X_pow (n : ℕ) (a : R) (ha : a ≠ 0) : nat_degree (C a * X ^ n) = n :=
174174
nat_degree_eq_of_degree_eq_some (degree_monomial n ha)
175175

176+
@[simp] lemma nat_degree_monomial (i : ℕ) (r : R) (hr : r ≠ 0) :
177+
nat_degree (monomial i r) = i :=
178+
by rw [← C_mul_X_pow_eq_monomial, nat_degree_C_mul_X_pow i r hr]
179+
176180
lemma coeff_eq_zero_of_degree_lt (h : degree p < n) : coeff p n = 0 :=
177181
not_not.1 (mt le_degree_of_ne_zero (not_le_of_gt h))
178182

@@ -540,6 +544,9 @@ begin
540544
exact @finsupp.single_eq_same _ _ _ n a }
541545
end
542546

547+
@[simp] lemma leading_coeff_monomial' (a : R) (n : ℕ) : leading_coeff (monomial n a) = a :=
548+
by rw [← C_mul_X_pow_eq_monomial, leading_coeff_monomial]
549+
543550
@[simp] lemma leading_coeff_C (a : R) : leading_coeff (C a) = a :=
544551
suffices leading_coeff (C a * X^0) = a, by rwa [pow_zero, mul_one] at this,
545552
leading_coeff_monomial a 0
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/-
2+
Copyright (c) 2020 Damiano Testa. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Damiano Testa
5+
-/
6+
import data.polynomial.degree.basic
7+
import data.polynomial.degree.trailing_degree
8+
9+
/-!
10+
# Erase the leading term of a univariate polynomial
11+
12+
## Definition
13+
14+
* `erase_lead f`: the polynomial `f - leading term of f`
15+
16+
`erase_lead` serves as reduction step in an induction, shaving off one monomial from a polynomial.
17+
The definition is set up so that it does not mention subtraction in the definition,
18+
and thus works for polynomials over semirings as well as rings.
19+
-/
20+
21+
noncomputable theory
22+
open_locale classical
23+
24+
open polynomial finsupp finset
25+
26+
namespace polynomial
27+
28+
variables {R : Type*} [semiring R] {f : polynomial R}
29+
30+
/-- `erase_lead f` for a polynomial `f` is the polynomial obtained by
31+
subtracting from `f` the leading term of `f`. -/
32+
def erase_lead (f : polynomial R) : polynomial R :=
33+
finsupp.erase f.nat_degree f
34+
35+
section erase_lead
36+
37+
lemma erase_lead_support (f : polynomial R) :
38+
f.erase_lead.support = f.support.erase f.nat_degree :=
39+
-- `rfl` fails because LHS uses `nat.decidable_eq` but RHS is classical.
40+
by convert rfl
41+
42+
lemma erase_lead_coeff (i : ℕ) :
43+
f.erase_lead.coeff i = if i = f.nat_degree then 0 else f.coeff i :=
44+
-- `rfl` fails because LHS uses `nat.decidable_eq` but RHS is classical.
45+
by convert rfl
46+
47+
@[simp] lemma erase_lead_coeff_nat_degree : f.erase_lead.coeff f.nat_degree = 0 :=
48+
finsupp.erase_same
49+
50+
lemma erase_lead_coeff_of_ne (i : ℕ) (hi : i ≠ f.nat_degree) :
51+
f.erase_lead.coeff i = f.coeff i :=
52+
finsupp.erase_ne hi
53+
54+
@[simp] lemma erase_lead_zero : erase_lead (0 : polynomial R) = 0 :=
55+
finsupp.erase_zero _
56+
57+
@[simp] lemma erase_lead_add_monomial_nat_degree_leading_coeff (f : polynomial R) :
58+
f.erase_lead + monomial f.nat_degree f.leading_coeff = f :=
59+
begin
60+
ext i,
61+
simp only [erase_lead_coeff, coeff_monomial, coeff_add, @eq_comm _ _ i],
62+
split_ifs with h,
63+
{ subst i, simp only [leading_coeff, zero_add] },
64+
{ exact add_zero _ }
65+
end
66+
67+
@[simp] lemma erase_lead_add_C_mul_X_pow (f : polynomial R) :
68+
f.erase_lead + (C f.leading_coeff) * X ^ f.nat_degree = f :=
69+
by rw [C_mul_X_pow_eq_monomial, erase_lead_add_monomial_nat_degree_leading_coeff]
70+
71+
@[simp] lemma self_sub_monomial_nat_degree_leading_coeff {R : Type*} [ring R] (f : polynomial R) :
72+
f - monomial f.nat_degree f.leading_coeff = f.erase_lead :=
73+
(eq_sub_iff_add_eq.mpr (erase_lead_add_monomial_nat_degree_leading_coeff f)).symm
74+
75+
@[simp] lemma self_sub_C_mul_X_pow {R : Type*} [ring R] (f : polynomial R) :
76+
f - (C f.leading_coeff) * X ^ f.nat_degree = f.erase_lead :=
77+
by rw [C_mul_X_pow_eq_monomial, self_sub_monomial_nat_degree_leading_coeff]
78+
79+
lemma erase_lead_ne_zero (f0 : 2 ≤ f.support.card) : erase_lead f ≠ 0 :=
80+
begin
81+
rw [ne.def, ← finsupp.card_support_eq_zero, erase_lead_support],
82+
exact (zero_lt_one.trans_le $ (nat.sub_le_sub_right f0 1).trans
83+
finset.pred_card_le_card_erase).ne.symm
84+
end
85+
86+
@[simp] lemma nat_degree_not_mem_erase_lead_support : f.nat_degree ∉ (erase_lead f).support :=
87+
by convert not_mem_erase _ _
88+
89+
lemma ne_nat_degree_of_mem_erase_lead_support {a : ℕ} (h : a ∈ (erase_lead f).support) :
90+
a ≠ f.nat_degree :=
91+
by { rintro rfl, exact nat_degree_not_mem_erase_lead_support h }
92+
93+
lemma erase_lead_support_card_lt (h : f ≠ 0) : (erase_lead f).support.card < f.support.card :=
94+
begin
95+
rw erase_lead_support,
96+
exact card_lt_card (erase_ssubset $ nat_degree_mem_support_of_nonzero h)
97+
end
98+
99+
@[simp] lemma erase_lead_monomial (i : ℕ) (r : R) :
100+
erase_lead (monomial i r) = 0 :=
101+
begin
102+
by_cases hr : r = 0,
103+
{ subst r, simp only [monomial_zero_right, erase_lead_zero] },
104+
{ rw [erase_lead, nat_degree_monomial _ _ hr, monomial, erase_single] }
105+
end
106+
107+
@[simp] lemma erase_lead_C (r : R) : erase_lead (C r) = 0 :=
108+
erase_lead_monomial _ _
109+
110+
@[simp] lemma erase_lead_X : erase_lead (X : polynomial R) = 0 :=
111+
erase_lead_monomial _ _
112+
113+
@[simp] lemma erase_lead_X_pow (n : ℕ) : erase_lead (X ^ n : polynomial R) = 0 :=
114+
by rw [X_pow_eq_monomial, erase_lead_monomial]
115+
116+
@[simp] lemma erase_lead_C_mul_X_pow (r : R) (n : ℕ) : erase_lead (C r * X ^ n) = 0 :=
117+
by rw [C_mul_X_pow_eq_monomial, erase_lead_monomial]
118+
119+
lemma erase_lead_degree_le : (erase_lead f).degree ≤ f.degree :=
120+
begin
121+
rw degree_le_iff_coeff_zero,
122+
intros i hi,
123+
rw erase_lead_coeff,
124+
split_ifs with h, { refl },
125+
apply coeff_eq_zero_of_degree_lt hi
126+
end
127+
128+
lemma erase_lead_nat_degree_le : (erase_lead f).nat_degree ≤ f.nat_degree :=
129+
nat_degree_le_nat_degree erase_lead_degree_le
130+
131+
lemma erase_lead_nat_degree_lt (f0 : 2 ≤ f.support.card) :
132+
(erase_lead f).nat_degree < f.nat_degree :=
133+
lt_of_le_of_ne erase_lead_nat_degree_le $ ne_nat_degree_of_mem_erase_lead_support $
134+
nat_degree_mem_support_of_nonzero $ erase_lead_ne_zero f0
135+
136+
end erase_lead
137+
138+
end polynomial

0 commit comments

Comments
 (0)