@@ -45,6 +45,8 @@ def X : polynomial α := single 1 1
45
45
/-- coeff p n is the coefficient of X^n in p -/
46
46
def coeff (p : polynomial α) := p.to_fun
47
47
48
+ @[simp] lemma coeff_mk (s) (f) (h) : coeff (finsupp.mk s f h : polynomial α) = f := rfl
49
+
48
50
instance [has_repr α] : has_repr (polynomial α) :=
49
51
⟨λ p, if p = 0 then " 0"
50
52
else (p.support.sort (≤)).foldr
@@ -67,6 +69,8 @@ def degree (p : polynomial α) : with_bot ℕ := p.support.sup some
67
69
def degree_lt_wf : well_founded (λp q : polynomial α, degree p < degree q) :=
68
70
inv_image.wf degree (with_bot.well_founded_lt nat.lt_wf)
69
71
72
+ instance : has_well_founded (polynomial α) := ⟨_, degree_lt_wf⟩
73
+
70
74
/-- `nat_degree p` forces `degree p` to ℕ, by defining nat_degree 0 = 0. -/
71
75
def nat_degree (p : polynomial α) : ℕ := (degree p).get_or_else 0
72
76
@@ -80,7 +84,6 @@ lemma single_eq_C_mul_X : ∀{n}, single n a = C a * X^n
80
84
lemma sum_C_mul_X_eq (p : polynomial α) : p.sum (λn a, C a * X^n) = p :=
81
85
eq.trans (sum_congr rfl $ assume n hn, single_eq_C_mul_X.symm) (finsupp.sum_single _)
82
86
83
-
84
87
@[elab_as_eliminator] protected lemma induction_on {M : polynomial α → Prop } (p : polynomial α)
85
88
(h_C : ∀a, M (C a))
86
89
(h_add : ∀p q, M p → M q → M (p + q))
542
545
lemma eq_C_of_degree_eq_zero (h : degree p = 0 ) : p = C (coeff p 0 ) :=
543
546
eq_C_of_degree_le_zero (h ▸ le_refl _)
544
547
548
+ lemma degree_le_zero_iff : degree p ≤ 0 ↔ p = C (coeff p 0 ) :=
549
+ ⟨eq_C_of_degree_le_zero, λ h, h.symm ▸ degree_C_le⟩
550
+
545
551
lemma degree_add_le (p q : polynomial α) : degree (p + q) ≤ max (degree p) (degree q) :=
546
552
calc degree (p + q) = ((p + q).support).sup some : rfl
547
553
... ≤ (p.support ∪ q.support).sup some : sup_mono support_add
@@ -971,6 +977,128 @@ lemma ne_zero_of_monic (h : monic p) : p ≠ 0 :=
971
977
972
978
end nonzero_comm_semiring
973
979
980
+ section comm_semiring
981
+ variables [comm_semiring α] [decidable_eq α] {p q : polynomial α}
982
+
983
+ /-- `dix_X p` return a polynomial `q` such that `q * X + C (p.coeff 0) = p`.
984
+ It can be used in a semiring where the usual division algorithm is not possible -/
985
+ def div_X (p : polynomial α) : polynomial α :=
986
+ { to_fun := λ n, p.coeff (n + 1 ),
987
+ support := ⟨(p.support.filter (> 0 )).1 .map (λ n, n - 1 ),
988
+ multiset.nodup_map_on begin
989
+ simp only [finset.mem_def.symm, finset.mem_erase, finset.mem_filter],
990
+ assume x hx y hy hxy,
991
+ rwa [← @add_right_cancel_iff _ _ 1 , nat.sub_add_cancel hx.2 ,
992
+ nat.sub_add_cancel hy.2 ] at hxy
993
+ end
994
+ (p.support.filter (> 0 )).2 ⟩,
995
+ mem_support_to_fun := λ n,
996
+ suffices (∃ (a : ℕ), (¬coeff p a = 0 ∧ a > 0 ) ∧ a - 1 = n) ↔
997
+ ¬coeff p (n + 1 ) = 0 ,
998
+ by simpa [finset.mem_def.symm, apply_eq_coeff],
999
+ ⟨λ ⟨a, ha⟩, by rw [← ha.2 , nat.sub_add_cancel ha.1 .2 ]; exact ha.1 .1 ,
1000
+ λ h, ⟨n + 1 , ⟨h, nat.succ_pos _⟩, nat.succ_sub_one _⟩⟩ }
1001
+
1002
+ lemma div_X_mul_X_add (p : polynomial α) : div_X p * X + C (p.coeff 0 ) = p :=
1003
+ polynomial.ext.2 $ λ n,
1004
+ nat.cases_on n
1005
+ (by simp)
1006
+ (by simp [coeff_C, nat.succ_ne_zero, coeff_mul_X, div_X])
1007
+
1008
+ @[simp] lemma div_X_C (a : α) : div_X (C a) = 0 :=
1009
+ polynomial.ext.2 $ λ n, by cases n; simp [div_X, coeff_C]; simp [coeff]
1010
+
1011
+ lemma div_X_eq_zero_iff : div_X p = 0 ↔ p = C (p.coeff 0 ) :=
1012
+ ⟨λ h, by simpa [eq_comm, h] using div_X_mul_X_add p,
1013
+ λ h, by rw [h, div_X_C]⟩
1014
+
1015
+ lemma div_X_add : div_X (p + q) = div_X p + div_X q :=
1016
+ polynomial.ext.2 $ by simp [div_X]
1017
+
1018
+ def nonzero_comm_semiring.of_polynomial_ne (h : p ≠ q) : nonzero_comm_semiring α :=
1019
+ { zero_ne_one := λ h01 : 0 = 1 , h $
1020
+ by rw [← mul_one p, ← mul_one q, ← C_1, ← h01, C_0, mul_zero, mul_zero],
1021
+ ..show comm_semiring α, by apply_instance }
1022
+
1023
+ lemma degree_lt_degree_mul_X (hp : p ≠ 0 ) : p.degree < (p * X).degree :=
1024
+ by letI := nonzero_comm_semiring.of_polynomial_ne hp; exact
1025
+ have leading_coeff p * leading_coeff X ≠ 0 , by simpa,
1026
+ by erw [degree_mul_eq' this , degree_eq_nat_degree hp,
1027
+ degree_X, ← with_bot.coe_one, ← with_bot.coe_add, with_bot.coe_lt_coe];
1028
+ exact nat.lt_succ_self _
1029
+
1030
+ lemma degree_div_X_lt (hp0 : p ≠ 0 ) : (div_X p).degree < p.degree :=
1031
+ by letI := nonzero_comm_semiring.of_polynomial_ne hp0; exact
1032
+ calc (div_X p).degree < (div_X p * X + C (p.coeff 0 )).degree :
1033
+ if h : degree p ≤ 0
1034
+ then begin
1035
+ have h' : C (p.coeff 0 ) ≠ 0 , by rwa [← eq_C_of_degree_le_zero h],
1036
+ rw [eq_C_of_degree_le_zero h, div_X_C, degree_zero, zero_mul, zero_add],
1037
+ exact lt_of_le_of_ne lattice.bot_le (ne.symm (mt degree_eq_bot.1 $
1038
+ by simp [h'])),
1039
+ end
1040
+ else
1041
+ have hXp0 : div_X p ≠ 0 ,
1042
+ by simpa [div_X_eq_zero_iff, -not_le, degree_le_zero_iff] using h,
1043
+ have leading_coeff (div_X p) * leading_coeff X ≠ 0 , by simpa,
1044
+ have degree (C (p.coeff 0 )) < degree (div_X p * X),
1045
+ from calc degree (C (p.coeff 0 )) ≤ 0 : degree_C_le
1046
+ ... < 1 : dec_trivial
1047
+ ... = degree (X : polynomial α) : degree_X.symm
1048
+ ... ≤ degree (div_X p * X) :
1049
+ by rw [← zero_add (degree X), degree_mul_eq' this ];
1050
+ exact add_le_add'
1051
+ (by rw [zero_le_degree_iff, ne.def, div_X_eq_zero_iff];
1052
+ exact λ h0, h (h0.symm ▸ degree_C_le))
1053
+ (le_refl _),
1054
+ by rw [add_comm, degree_add_eq_of_degree_lt this ];
1055
+ exact degree_lt_degree_mul_X hXp0
1056
+ ... = p.degree : by rw div_X_mul_X_add
1057
+
1058
+ @[elab_as_eliminator] def rec_on_horner
1059
+ {M : polynomial α → Sort *} : Π (p : polynomial α),
1060
+ M 0 →
1061
+ (Π p a, coeff p 0 = 0 → a ≠ 0 → M p → M (p + C a)) →
1062
+ (Π p, p ≠ 0 → M p → M (p * X)) →
1063
+ M p
1064
+ | p := λ M0 MC MX,
1065
+ if hp : p = 0 then eq.rec_on hp.symm M0
1066
+ else
1067
+ have wf : degree (div_X p) < degree p,
1068
+ from degree_div_X_lt hp,
1069
+ by rw [← div_X_mul_X_add p] at *;
1070
+ exact
1071
+ if hcp0 : coeff p 0 = 0
1072
+ then by rw [hcp0, C_0, add_zero];
1073
+ exact MX _ (λ h : div_X p = 0 , by simpa [h, hcp0] using hp)
1074
+ (rec_on_horner _ M0 MC MX)
1075
+ else MC _ _ (coeff_mul_X_zero _) hcp0 (if hpX0 : div_X p = 0
1076
+ then show M (div_X p * X), by rw [hpX0, zero_mul]; exact M0
1077
+ else MX (div_X p) hpX0 (rec_on_horner _ M0 MC MX))
1078
+ using_well_founded {dec_tac := tactic.assumption}
1079
+
1080
+ @[elab_as_eliminator] lemma degree_pos_induction_on
1081
+ {P : polynomial α → Prop } (p : polynomial α) (h0 : 0 < degree p)
1082
+ (hC : ∀ {a}, a ≠ 0 → P (C a * X))
1083
+ (hX : ∀ {p}, 0 < degree p → P p → P (p * X))
1084
+ (hadd : ∀ {p} {a}, 0 < degree p → P p → P (p + C a)) : P p :=
1085
+ rec_on_horner p
1086
+ (λ h, by rw degree_zero at h; exact absurd h dec_trivial)
1087
+ (λ p a _ _ ih h0,
1088
+ have 0 < degree p,
1089
+ from lt_of_not_ge (λ h, (not_lt_of_ge degree_C_le) $
1090
+ by rwa [eq_C_of_degree_le_zero h, ← C_add] at h0),
1091
+ hadd this (ih this ))
1092
+ (λ p _ ih h0',
1093
+ if h0 : 0 < degree p
1094
+ then hX h0 (ih h0)
1095
+ else by rw [eq_C_of_degree_le_zero (le_of_not_gt h0)] at *;
1096
+ exact hC (λ h : coeff p 0 = 0 ,
1097
+ by simpa [h, not_lt.2 (@lattice.bot_le ( ℕ) _ _)] using h0'))
1098
+ h0
1099
+
1100
+ end comm_semiring
1101
+
974
1102
section comm_ring
975
1103
variables [comm_ring α] [decidable_eq α] {p q : polynomial α}
976
1104
instance : comm_ring (polynomial α) := finsupp.to_comm_ring
@@ -1045,8 +1173,6 @@ calc degree (p - q) = degree (erase (nat_degree q) p + -erase (nat_degree q) q)
1045
1173
: degree_neg (erase (nat_degree q) q) ▸ degree_add_le _ _
1046
1174
... < degree p : max_lt_iff.2 ⟨hd' ▸ degree_erase_lt hp0, hd.symm ▸ degree_erase_lt hq0⟩
1047
1175
1048
- instance : has_well_founded (polynomial α) := ⟨_, degree_lt_wf⟩
1049
-
1050
1176
lemma ne_zero_of_ne_zero_of_monic (hp : p ≠ 0 ) (hq : monic q) : q ≠ 0
1051
1177
| h := begin
1052
1178
rw [h, monic.def, leading_coeff_zero] at hq,
0 commit comments