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

Commit dae047e

Browse files
committed
feat(data/polynomial/*): more lemmas, especially for noncommutative rings (#6599)
Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
1 parent b852648 commit dae047e

File tree

9 files changed

+194
-33
lines changed

9 files changed

+194
-33
lines changed

src/algebra/group_power/basic.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,13 @@ end comm_group
377377
lemma zero_pow [monoid_with_zero R] : ∀ {n : ℕ}, 0 < n → (0 : R) ^ n = 0
378378
| (n+1) _ := zero_mul _
379379

380+
lemma zero_pow_eq [monoid_with_zero R] (n : ℕ) : (0 : R)^n = if n = 0 then 1 else 0 :=
381+
begin
382+
split_ifs with h,
383+
{ rw [h, pow_zero], },
384+
{ rw [zero_pow (nat.pos_of_ne_zero h)] },
385+
end
386+
380387
namespace ring_hom
381388

382389
variables [semiring R] [semiring S]

src/algebra/monoid_algebra.lean

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -772,7 +772,6 @@ end derived_instances
772772
section misc_theorems
773773

774774
variables [semiring k]
775-
local attribute [reducible] add_monoid_algebra
776775

777776
lemma mul_apply [has_add G] (f g : add_monoid_algebra k G) (x : G) :
778777
(f * g) x = (f.sum $ λa₁ b₁, g.sum $ λa₂ b₂, if a₁ + a₂ = x then b₁ * b₂ else 0) :=
@@ -788,9 +787,18 @@ lemma support_mul [has_add G] (a b : add_monoid_algebra k G) :
788787
@monoid_algebra.support_mul k (multiplicative G) _ _ _ _
789788

790789
lemma single_mul_single [has_add G] {a₁ a₂ : G} {b₁ b₂ : k} :
791-
(single a₁ b₁ : add_monoid_algebra k G) * single a₂ b₂ = single (a₁ + a₂) (b₁ * b₂) :=
790+
(single a₁ b₁ * single a₂ b₂ : add_monoid_algebra k G) = single (a₁ + a₂) (b₁ * b₂) :=
792791
@monoid_algebra.single_mul_single k (multiplicative G) _ _ _ _ _ _
793792

793+
-- This should be a `@[simp]` lemma, but the simp_nf linter times out if we add this.
794+
-- Probably the correct fix is to make a `[add_]monoid_algebra.single` with the correct type,
795+
-- instead of relying on `finsupp.single`.
796+
lemma single_pow [add_monoid G] {a : G} {b : k} :
797+
∀ n : ℕ, ((single a b)^n : add_monoid_algebra k G) = single (n •ℕ a) (b ^ n)
798+
| 0 := rfl
799+
| (n+1) :=
800+
by rw [pow_succ, pow_succ, single_pow n, single_mul_single, add_comm, add_nsmul, one_nsmul]
801+
794802
/-- Like `finsupp.map_domain_add`, but for the convolutive multiplication we define in this file -/
795803
lemma map_domain_mul {α : Type*} {β : Type*} {α₂ : Type*}
796804
[semiring β] [has_add α] [has_add α₂]
@@ -837,11 +845,11 @@ f.mul_single_apply_aux r _ _ _ $ λ a, by rw [add_zero]
837845

838846
lemma single_mul_apply_aux [has_add G] (f : add_monoid_algebra k G) (r : k) (x y z : G)
839847
(H : ∀ a, x + a = y ↔ a = z) :
840-
(single x r * f) y = r * f z :=
848+
(single x r * f : add_monoid_algebra k G) y = r * f z :=
841849
@monoid_algebra.single_mul_apply_aux k (multiplicative G) _ _ _ _ _ _ _ H
842850

843851
lemma single_zero_mul_apply [add_monoid G] (f : add_monoid_algebra k G) (r : k) (x : G) :
844-
(single 0 r * f) x = r * f x :=
852+
(single 0 r * f : add_monoid_algebra k G) x = r * f x :=
845853
f.single_mul_apply_aux r _ _ _ $ λ a, by rw [zero_add]
846854

847855
lemma lift_nc_smul {R : Type*} [add_monoid G] [semiring R] (f : k →+* R)

src/data/int/cast.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ def cast_ring_hom (α : Type*) [ring α] : ℤ →+* α := ⟨coe, cast_one, cas
109109
lemma cast_commute [ring α] (m : ℤ) (x : α) : commute ↑m x :=
110110
int.cases_on m (λ n, n.cast_commute x) (λ n, ((n+1).cast_commute x).neg_left)
111111

112+
lemma cast_comm [ring α] (m : ℤ) (x : α) : (m : α) * x = x * m :=
113+
(cast_commute m x).eq
114+
112115
lemma commute_cast [ring α] (x : α) (m : ℤ) : commute x m :=
113116
(m.cast_commute x).symm
114117

src/data/nat/cast.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ def cast_ring_hom (α : Type*) [semiring α] : ℕ →+* α :=
136136
lemma cast_commute [semiring α] (n : ℕ) (x : α) : commute ↑n x :=
137137
nat.rec_on n (commute.zero_left x) $ λ n ihn, ihn.add_left $ commute.one_left x
138138

139+
lemma cast_comm [semiring α] (n : ℕ) (x : α) : (n : α) * x = x * n :=
140+
(cast_commute n x).eq
141+
139142
lemma commute_cast [semiring α] (x : α) (n : ℕ) : commute x n :=
140143
(n.cast_commute x).symm
141144

src/data/polynomial/algebra_map.lean

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,6 @@ lemma eval₂_algebra_map_int_X {R : Type*} [ring R] (p : polynomial ℤ) (f : p
9090
-- Unfortunately `f.to_int_alg_hom` doesn't work here, as typeclasses don't match up correctly.
9191
eval₂_algebra_map_X p { commutes' := λ n, by simp, .. f }
9292

93-
section comp
94-
95-
lemma eval₂_comp [comm_semiring S] (f : R →+* S) {x : S} :
96-
eval₂ f x (p.comp q) = eval₂ f (eval₂ f x q) p :=
97-
by rw [comp, p.as_sum_range]; simp [eval₂_finset_sum, eval₂_pow]
98-
99-
lemma eval_comp : (p.comp q).eval a = p.eval (q.eval a) := eval₂_comp _
100-
101-
instance comp.is_semiring_hom : is_semiring_hom (λ q : polynomial R, q.comp p) :=
102-
by unfold comp; apply_instance
103-
104-
end comp
105-
10693
end comm_semiring
10794

10895
section aeval

src/data/polynomial/basic.lean

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@ by simp
6363
/-- `monomial s a` is the monomial `a * X^s` -/
6464
def monomial (n : ℕ) : R →ₗ[R] polynomial R := finsupp.lsingle n
6565

66+
@[simp]
6667
lemma monomial_zero_right (n : ℕ) :
6768
monomial n (0 : R) = 0 :=
6869
finsupp.single_zero
6970

71+
-- This is not a `simp` lemma as `monomial_zero_left` is more general.
72+
lemma monomial_zero_one : monomial 0 (1 : R) = 1 := rfl
73+
7074
lemma monomial_def (n : ℕ) (a : R) : monomial n a = finsupp.single n a := rfl
7175

7276
lemma monomial_add (n : ℕ) (r s : R) :
@@ -77,6 +81,16 @@ lemma monomial_mul_monomial (n m : ℕ) (r s : R) :
7781
monomial n r * monomial m s = monomial (n + m) (r * s) :=
7882
add_monoid_algebra.single_mul_single
7983

84+
@[simp]
85+
lemma monomial_pow (n : ℕ) (r : R) (k : ℕ) :
86+
(monomial n r)^k = monomial (n*k) (r^k) :=
87+
begin
88+
rw mul_comm,
89+
convert add_monoid_algebra.single_pow k,
90+
simp only [nat.cast_id, nsmul_eq_mul],
91+
refl,
92+
end
93+
8094
lemma smul_monomial {S} [semiring S] [semimodule S R] (a : S) (n : ℕ) (b : R) :
8195
a • monomial n b = monomial n (a • b) :=
8296
finsupp.smul_single _ _ _
@@ -87,6 +101,14 @@ by convert @support_add _ _ _ p q
87101
/-- `X` is the polynomial variable (aka indeterminant). -/
88102
def X : polynomial R := monomial 1 1
89103

104+
lemma monomial_one_one_eq_X : monomial 1 (1 : R) = X := rfl
105+
lemma monomial_one_right_eq_X_pow (n : ℕ) : monomial n 1 = X^n :=
106+
begin
107+
induction n with n ih,
108+
{ simp [monomial_zero_one], },
109+
{ rw [pow_succ, ←ih, ←monomial_one_one_eq_X, monomial_mul_monomial, add_comm, one_mul], }
110+
end
111+
90112
/-- `X` commutes with everything, even when the coefficients are noncommutative. -/
91113
lemma X_mul : X * p = p * X :=
92114
by { ext, simp [X, monomial, add_monoid_algebra.mul_apply, sum_single_index, add_comm] }
@@ -104,6 +126,26 @@ by rw [mul_assoc, X_pow_mul, ←mul_assoc]
104126

105127
lemma commute_X (p : polynomial R) : commute X p := X_mul
106128

129+
@[simp]
130+
lemma monomial_mul_X (n : ℕ) (r : R) : monomial n r * X = monomial (n+1) r :=
131+
by erw [monomial_mul_monomial, mul_one]
132+
133+
@[simp]
134+
lemma monomial_mul_X_pow (n : ℕ) (r : R) (k : ℕ) : monomial n r * X^k = monomial (n+k) r :=
135+
begin
136+
induction k with k ih,
137+
{ simp, },
138+
{ simp [ih, pow_succ', ←mul_assoc, add_assoc], },
139+
end
140+
141+
@[simp]
142+
lemma X_mul_monomial (n : ℕ) (r : R) : X * monomial n r = monomial (n+1) r :=
143+
by rw [X_mul, monomial_mul_X]
144+
145+
@[simp]
146+
lemma X_pow_mul_monomial (k n : ℕ) (r : R) : X^k * monomial n r = monomial (n+k) r :=
147+
by rw [X_pow_mul, monomial_mul_X_pow]
148+
107149
/-- coeff p n is the coefficient of X^n in p -/
108150
def coeff (p : polynomial R) : ℕ → R := @coe_fn (ℕ →₀ R) _ p
109151

src/data/polynomial/eval.lean

Lines changed: 118 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,17 @@ lemma eval₂_congr {R S : Type*} [semiring R] [semiring S]
4444
f = g → s = t → φ = ψ → eval₂ f s φ = eval₂ g t ψ :=
4545
by rintro rfl rfl rfl; refl
4646

47+
@[simp] lemma eval₂_at_zero : p.eval₂ f 0 = f (coeff p 0) :=
48+
begin
49+
-- This proof is lame, and the `finsupp` API shows through.
50+
simp only [eval₂_eq_sum, zero_pow_eq, mul_ite, mul_zero, mul_one, finsupp.sum_ite_eq'],
51+
split_ifs,
52+
{ refl, },
53+
{ simp only [not_not, finsupp.mem_support_iff, ne.def] at h,
54+
apply_fun f at h,
55+
simpa using h.symm, },
56+
end
57+
4758
@[simp] lemma eval₂_zero : (0 : polynomial R).eval₂ f x = 0 :=
4859
finsupp.sum_zero_index
4960

@@ -236,6 +247,26 @@ begin
236247
exact P.eval_eq_finset_sum x
237248
end
238249

250+
@[simp] lemma eval₂_at_apply {S : Type*} [semiring S] (f : R →+* S) (r : R) :
251+
p.eval₂ f (f r) = f (p.eval r) :=
252+
begin
253+
rw [eval₂_eq_sum, eval_eq_sum, finsupp.sum, finsupp.sum, f.map_sum],
254+
simp only [f.map_mul, f.map_pow],
255+
end
256+
257+
@[simp] lemma eval₂_at_one {S : Type*} [semiring S] (f : R →+* S) : p.eval₂ f 1 = f (p.eval 1) :=
258+
begin
259+
convert eval₂_at_apply f 1,
260+
simp,
261+
end
262+
263+
@[simp] lemma eval₂_at_nat_cast {S : Type*} [semiring S] (f : R →+* S) (n : ℕ) :
264+
p.eval₂ f n = f (p.eval n) :=
265+
begin
266+
convert eval₂_at_apply f n,
267+
simp,
268+
end
269+
239270
@[simp] lemma eval_C : (C a).eval x = a := eval₂_C _ _
240271

241272
@[simp] lemma eval_nat_cast {n : ℕ} : (n : polynomial R).eval x = n :=
@@ -260,6 +291,35 @@ eval₂_monomial _ _
260291
(s • p).eval x = s * p.eval x :=
261292
eval₂_smul (ring_hom.id _) _ _
262293

294+
@[simp] lemma eval_C_mul : (C a * p).eval x = a * p.eval x :=
295+
begin
296+
apply polynomial.induction_on' p,
297+
{ intros p q ph qh,
298+
simp only [mul_add, eval_add, ph, qh], },
299+
{ intros n b,
300+
simp [mul_assoc], }
301+
end
302+
303+
@[simp] lemma eval_nat_cast_mul {n : ℕ} : ((n : polynomial R) * p).eval x = n * p.eval x :=
304+
by rw [←C_eq_nat_cast, eval_C_mul]
305+
306+
@[simp] lemma eval_mul_X : (p * X).eval x = p.eval x * x :=
307+
begin
308+
apply polynomial.induction_on' p,
309+
{ intros p q ph qh,
310+
simp only [add_mul, eval_add, ph, qh], },
311+
{ intros n a,
312+
simp only [←monomial_one_one_eq_X, monomial_mul_monomial, eval_monomial,
313+
mul_one, pow_succ', mul_assoc], }
314+
end
315+
316+
@[simp] lemma eval_mul_X_pow {k : ℕ} : (p * X^k).eval x = p.eval x * x^k :=
317+
begin
318+
induction k with k ih,
319+
{ simp, },
320+
{ simp [pow_succ', ←mul_assoc, ih], }
321+
end
322+
263323
lemma eval_sum (p : polynomial R) (f : ℕ → R → polynomial R) (x : R) :
264324
(p.sum f).eval x = p.sum (λ n a, (f n a).eval x) :=
265325
eval₂_sum _ _ _ _
@@ -311,6 +371,9 @@ end
311371

312372
@[simp] lemma C_comp : (C a).comp p = C a := eval₂_C _ _
313373

374+
@[simp] lemma nat_cast_comp {n : ℕ} : (n : polynomial R).comp p = n :=
375+
by rw [←C_eq_nat_cast, C_comp]
376+
314377
@[simp] lemma comp_zero : p.comp (0 : polynomial R) = C (p.eval 0) :=
315378
by rw [← C_0, comp_C]
316379

@@ -325,6 +388,40 @@ by rw [← C_1, C_comp]
325388

326389
@[simp] lemma add_comp : (p + q).comp r = p.comp r + q.comp r := eval₂_add _ _
327390

391+
@[simp] lemma monomial_comp (n : ℕ) : (monomial n a).comp p = C a * p^n :=
392+
eval₂_monomial _ _
393+
394+
@[simp] lemma mul_X_comp : (p * X).comp r = p.comp r * r :=
395+
begin
396+
apply polynomial.induction_on' p,
397+
{ intros p q hp hq, simp [hp, hq, add_mul], },
398+
{ intros n b, simp [pow_succ', mul_assoc], }
399+
end
400+
401+
@[simp] lemma X_pow_comp {k : ℕ} : (X^k).comp p = p^k :=
402+
begin
403+
induction k with k ih,
404+
{ simp, },
405+
{ simp [pow_succ', mul_X_comp, ih], },
406+
end
407+
408+
@[simp] lemma mul_X_pow_comp {k : ℕ} : (p * X^k).comp r = p.comp r * r^k :=
409+
begin
410+
induction k with k ih,
411+
{ simp, },
412+
{ simp [ih, pow_succ', ←mul_assoc, mul_X_comp], },
413+
end
414+
415+
@[simp] lemma C_mul_comp : (C a * p).comp r = C a * p.comp r :=
416+
begin
417+
apply polynomial.induction_on' p,
418+
{ intros p q hp hq, simp [hp, hq, mul_add], },
419+
{ intros n b, simp [mul_assoc], }
420+
end
421+
422+
@[simp] lemma nat_cast_mul_comp {n : ℕ} : ((n : polynomial R) * p).comp r = n * p.comp r :=
423+
by rw [←C_eq_nat_cast, C_mul_comp, C_eq_nat_cast]
424+
328425
@[simp] lemma mul_comp {R : Type*} [comm_semiring R] (p q r : polynomial R) :
329426
(p * q).comp r = p.comp r * q.comp r := eval₂_mul _ _
330427

@@ -336,22 +433,12 @@ begin
336433
{ simp [pow_succ, ih], },
337434
end
338435

339-
@[simp] lemma monomial_comp (n : ℕ) : (monomial n a).comp p = C a * p^n :=
340-
eval₂_monomial _ _
341-
342436
@[simp] lemma bit0_comp : comp (bit0 p : polynomial R) q = bit0 (p.comp q) :=
343437
by simp only [bit0, add_comp]
344438

345439
@[simp] lemma bit1_comp : comp (bit1 p : polynomial R) q = bit1 (p.comp q) :=
346440
by simp only [bit1, add_comp, bit0_comp, one_comp]
347441

348-
@[simp] lemma cast_nat_comp (n : ℕ) : comp (n : polynomial R) p = n :=
349-
begin
350-
induction n with n ih,
351-
{ simp, },
352-
{ simp [ih], },
353-
end
354-
355442
lemma comp_assoc {R : Type*} [comm_semiring R] (φ ψ χ : polynomial R) :
356443
(φ.comp ψ).comp χ = φ.comp (ψ.comp χ) :=
357444
begin
@@ -510,6 +597,12 @@ lemma map_sum {ι : Type*} (g : ι → polynomial R) (s : finset ι) :
510597
(∑ i in s, g i).map f = ∑ i in s, (g i).map f :=
511598
eq.symm $ sum_hom _ _
512599

600+
lemma map_comp (p q : polynomial R) : map f (p.comp q) = (map f p).comp (map f q) :=
601+
polynomial.induction_on p
602+
(by simp)
603+
(by simp {contextual := tt})
604+
(by simp [pow_succ', ← mul_assoc, polynomial.comp] {contextual := tt})
605+
513606
@[simp]
514607
lemma eval_zero_map (f : R →+* S) (p : polynomial R) :
515608
(p.map f).eval 0 = f (p.eval 0) :=
@@ -579,12 +672,27 @@ section eval
579672

580673
variables [comm_semiring R] {p q : polynomial R} {x : R}
581674

675+
lemma eval₂_comp [comm_semiring S] (f : R →+* S) {x : S} :
676+
eval₂ f x (p.comp q) = eval₂ f (eval₂ f x q) p :=
677+
by rw [comp, p.as_sum_range]; simp [eval₂_finset_sum, eval₂_pow]
678+
582679
@[simp] lemma eval_mul : (p * q).eval x = p.eval x * q.eval x := eval₂_mul _ _
583680

584681
instance eval.is_semiring_hom : is_semiring_hom (eval x) := eval₂.is_semiring_hom _ _
585682

586683
@[simp] lemma eval_pow (n : ℕ) : (p ^ n).eval x = p.eval x ^ n := eval₂_pow _ _ _
587684

685+
@[simp]
686+
lemma eval_comp : (p.comp q).eval x = p.eval (q.eval x) :=
687+
begin
688+
apply polynomial.induction_on' p,
689+
{ intros r s hr hs, simp [add_comp, hr, hs], },
690+
{ intros n a, simp, }
691+
end
692+
693+
instance comp.is_semiring_hom : is_semiring_hom (λ q : polynomial R, q.comp p) :=
694+
by unfold comp; apply_instance
695+
588696
lemma eval₂_hom [comm_semiring S] (f : R →+* S) (x : R) :
589697
p.eval₂ f (f x) = f (p.eval x) :=
590698
(ring_hom.comp_id f) ▸ (hom_eval₂ p (ring_hom.id R) f x).symm
@@ -637,12 +745,6 @@ begin
637745
exact ring_hom.map_zero f,
638746
end
639747

640-
lemma map_comp (p q : polynomial R) : map f (p.comp q) = (map f p).comp (map f q) :=
641-
polynomial.induction_on p
642-
(by simp)
643-
(by simp {contextual := tt})
644-
(by simp [pow_succ', ← mul_assoc, polynomial.comp] {contextual := tt})
645-
646748
end map
647749

648750
end comm_semiring

src/data/polynomial/monomial.lean

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,12 @@ lemma C_add : C (a + b) = C a + C b := C.map_add a b
4343

4444
lemma C_pow : C (a ^ n) = C a ^ n := C.map_pow a n
4545

46+
@[simp] lemma C_mul_monomial : C a * monomial n b = monomial n (a * b) :=
47+
by simp only [←monomial_zero_left, monomial_mul_monomial, zero_add]
48+
49+
@[simp] lemma monomial_mul_C : monomial n a * C b = monomial n (a * b) :=
50+
by simp only [←monomial_zero_left, monomial_mul_monomial, add_zero]
51+
4652
@[simp]
4753
lemma C_eq_nat_cast (n : ℕ) : C (n : R) = (n : polynomial R) :=
4854
C.map_nat_cast n

0 commit comments

Comments
 (0)