@@ -3,6 +3,7 @@ Copyright (c) 2019 Zhouhang Zhou. All rights reserved.
3
3
Released under Apache 2.0 license as described in the file LICENSE.
4
4
Authors: Zhouhang Zhou
5
5
-/
6
+ import algebra.invertible
6
7
import tactic.linarith
7
8
8
9
/-!
@@ -12,78 +13,71 @@ This file defines the discriminant of a quadratic and gives the solution to a qu
12
13
13
14
## Main definition
14
15
15
- The discriminant of a quadratic `a*x* x + b* x + c` is `b* b - 4*a* c`.
16
+ - `discrim a b c`: the discriminant of a quadratic `a * x * x + b * x + c` is `b * b - 4 * a * c`.
16
17
17
18
## Main statements
18
- • Roots of a quadratic can be written as `(-b + s) / (2 * a)` or `(-b - s) / (2 * a)`,
19
- where `s` is the square root of the discriminant.
20
- • If the discriminant has no square root, then the corresponding quadratic has no root.
21
- • If a quadratic is always non-negative, then its discriminant is non-positive.
19
+
20
+ - `quadratic_eq_zero_iff`: roots of a quadratic can be written as
21
+ `(-b + s) / (2 * a)` or `(-b - s) / (2 * a)`, where `s` is the square root of the discriminant.
22
+ - `quadratic_ne_zero_of_discrim_ne_square`: if the discriminant has no square root,
23
+ then the corresponding quadratic has no root.
24
+ - `discrim_le_zero`: if a quadratic is always non-negative, then its discriminant is non-positive.
22
25
23
26
## Tags
24
27
25
28
polynomial, quadratic, discriminant, root
26
29
-/
27
30
28
- variables {α : Type *}
31
+ section ring
32
+ variables {R : Type *}
29
33
30
- section lemmas
34
+ /-- Discriminant of a quadratic -/
35
+ def discrim [ring R] (a b c : R) : R := b^2 - 4 * a * c
31
36
32
- variables [linear_ordered_field α ] {a b c : α }
37
+ variables [integral_domain R ] {a b c : R }
33
38
34
- lemma exists_le_mul_self : ∀ a : α, ∃ x : α, a ≤ x * x :=
39
+ /--
40
+ A quadratic has roots if and only if its discriminant equals some square.
41
+ -/
42
+ lemma quadratic_eq_zero_iff_discrim_eq_square (h2 : (2 : R) ≠ 0 ) (ha : a ≠ 0 ) (x : R) :
43
+ a * x * x + b * x + c = 0 ↔ discrim a b c = (2 * a * x + b) ^ 2 :=
35
44
begin
36
- classical, -- TODO: otherwise linarith performance sucks
37
- assume a, cases le_total 1 a with ha ha,
38
- { use a, exact le_mul_of_one_le_left (by linarith) ha },
39
- { use 1 , linarith }
45
+ split,
46
+ { assume h,
47
+ calc discrim a b c
48
+ = 4 * a * (a * x * x + b * x + c) + b * b - 4 * a * c : by { rw [h, discrim], ring }
49
+ ... = (2 *a*x + b)^2 : by ring },
50
+ { assume h,
51
+ have ha : 2 * 2 * a ≠ 0 := mul_ne_zero (mul_ne_zero h2 h2) ha,
52
+ apply mul_left_cancel' ha,
53
+ calc
54
+ 2 * 2 * a * (a * x * x + b * x + c) = (2 * a * x + b) ^ 2 - (b ^ 2 - 4 * a * c) : by ring
55
+ ... = 0 : by { rw [← h, discrim], ring }
56
+ ... = 2 *2 *a*0 : by ring }
40
57
end
41
58
42
- lemma exists_lt_mul_self : ∀ a : α, ∃ x : α, a < x * x :=
59
+ /-- A quadratic has no root if its discriminant has no square root. -/
60
+ lemma quadratic_ne_zero_of_discrim_ne_square (h2 : (2 : R) ≠ 0 ) (ha : a ≠ 0 )
61
+ (h : ∀ s : R, discrim a b c ≠ s * s) (x : R) :
62
+ a * x * x + b * x + c ≠ 0 :=
43
63
begin
44
- classical, -- todo: otherwise linarith performance sucks
45
- assume a, rcases (exists_le_mul_self a) with ⟨x, hx⟩,
46
- cases le_total 0 x with hx' hx',
47
- { use (x + 1 ),
48
- have : (x+1 )*(x+1 ) = x*x + 2 *x + 1 , {ring},
49
- exact lt_of_le_of_lt hx (by rw this ; linarith) },
50
- { use (x - 1 ),
51
- have : (x-1 )*(x-1 ) = x*x - 2 *x + 1 , {ring},
52
- exact lt_of_le_of_lt hx (by rw this ; linarith) }
64
+ assume h',
65
+ rw [quadratic_eq_zero_iff_discrim_eq_square h2 ha, pow_two] at h',
66
+ exact h _ h'
53
67
end
54
68
55
- end lemmas
56
-
57
- variables [linear_ordered_field α] {a b c x : α}
58
-
59
- /-- Discriminant of a quadratic -/
60
- def discrim [ring α] (a b c : α) : α := b^2 - 4 * a * c
69
+ end ring
61
70
62
- /--
63
- A quadratic has roots if and only if its discriminant equals some square.
64
- -/
65
- lemma quadratic_eq_zero_iff_discrim_eq_square (ha : a ≠ 0 ) :
66
- ∀ x : α, a * x * x + b * x + c = 0 ↔ discrim a b c = (2 * a * x + b)^2 :=
67
- by classical; exact -- TODO: otherwise linarith performance sucks
68
- assume x, iff.intro
69
- (assume h, calc
70
- discrim a b c = 4 *a*(a*x*x + b*x + c) + b*b - 4 *a*c : by rw [h, discrim]; ring
71
- ... = (2 *a*x + b)^2 : by ring)
72
- (assume h,
73
- have ha : 2 *2 *a ≠ 0 := mul_ne_zero (mul_ne_zero two_ne_zero two_ne_zero) ha,
74
- mul_left_cancel' ha $
75
- calc
76
- 2 * 2 * a * (a * x * x + b * x + c) = (2 *a*x + b)^2 - (b^2 - 4 *a*c) : by ring
77
- ... = 0 : by { rw [← h, discrim], ring }
78
- ... = 2 *2 *a*0 : by ring)
71
+ section field
72
+ variables {K : Type *} [field K] [invertible (2 : K)] {a b c x : K}
79
73
80
74
/-- Roots of a quadratic -/
81
- lemma quadratic_eq_zero_iff (ha : a ≠ 0 ) {s : α } (h : discrim a b c = s * s) :
82
- ∀ x : α, a * x * x + b * x + c = 0 ↔ x = (-b + s) / (2 * a) ∨ x = (-b - s) / (2 * a) := assume x,
75
+ lemma quadratic_eq_zero_iff (ha : a ≠ 0 ) {s : K } (h : discrim a b c = s * s) (x : K ) :
76
+ a * x * x + b * x + c = 0 ↔ x = (-b + s) / (2 * a) ∨ x = (-b - s) / (2 * a) :=
83
77
begin
84
- classical, -- TODO: otherwise linarith performance sucks
85
- rw [quadratic_eq_zero_iff_discrim_eq_square ha, h, pow_two, mul_self_eq_mul_self_iff],
86
- have ne : 2 * a ≠ 0 := mul_ne_zero two_ne_zero ha,
78
+ have h2 : ( 2 : K) ≠ 0 := nonzero_of_invertible 2 ,
79
+ rw [quadratic_eq_zero_iff_discrim_eq_square h2 ha, h, pow_two, mul_self_eq_mul_self_iff],
80
+ have ne : 2 * a ≠ 0 := mul_ne_zero h2 ha,
87
81
have : x = 2 * a * x / (2 * a) := (mul_div_cancel_left x ne).symm,
88
82
have h₁ : 2 * a * ((-b + s) / (2 * a)) = -b + s := mul_div_cancel' _ ne,
89
83
have h₂ : 2 * a * ((-b - s) / (2 * a)) = -b - s := mul_div_cancel' _ ne,
95
89
end
96
90
97
91
/-- A quadratic has roots if its discriminant has square roots -/
98
- lemma exist_quadratic_eq_zero (ha : a ≠ 0 ) (h : ∃ s, discrim a b c = s * s) :
92
+ lemma exists_quadratic_eq_zero (ha : a ≠ 0 ) (h : ∃ s, discrim a b c = s * s) :
99
93
∃ x, a * x * x + b * x + c = 0 :=
100
94
begin
101
95
rcases h with ⟨s, hs⟩,
@@ -105,79 +99,70 @@ begin
105
99
end
106
100
107
101
/-- Root of a quadratic when its discriminant equals zero -/
108
- lemma quadratic_eq_zero_iff_of_discrim_eq_zero (ha : a ≠ 0 ) (h : discrim a b c = 0 ) :
109
- ∀ x : α, a * x * x + b * x + c = 0 ↔ x = -b / (2 * a) := assume x,
102
+ lemma quadratic_eq_zero_iff_of_discrim_eq_zero (ha : a ≠ 0 ) (h : discrim a b c = 0 ) (x : K) :
103
+ a * x * x + b * x + c = 0 ↔ x = -b / (2 * a) :=
110
104
begin
111
- classical, -- TODO: otherwise linarith performance sucks
112
- have : discrim a b c = 0 * 0 := eq.trans h (by ring),
113
- rw quadratic_eq_zero_iff ha this ,
114
- simp
105
+ have : discrim a b c = 0 * 0 , by rw [h, mul_zero],
106
+ rw [quadratic_eq_zero_iff ha this , add_zero, sub_zero, or_self]
115
107
end
116
108
117
- /-- A quadratic has no root if its discriminant has no square root. -/
118
- lemma quadratic_ne_zero_of_discrim_ne_square (ha : a ≠ 0 ) (h : ∀ s : α, discrim a b c ≠ s * s) :
119
- ∀ (x : α), a * x * x + b * x + c ≠ 0 :=
120
- begin
121
- assume x h',
122
- rw [quadratic_eq_zero_iff_discrim_eq_square ha, pow_two] at h',
123
- have := h _,
124
- contradiction
125
- end
109
+ end field
110
+
111
+ section linear_ordered_field
112
+ variables {K : Type *} [linear_ordered_field K] {a b c : K}
126
113
127
114
/-- If a polynomial of degree 2 is always nonnegative, then its discriminant is nonpositive -/
128
- lemma discriminant_le_zero {a b c : α} (h : ∀ x : α, 0 ≤ a*x*x + b*x + c) : discrim a b c ≤ 0 :=
129
- by classical; exact -- TODO: otherwise linarith performance sucks
115
+ lemma discrim_le_zero (h : ∀ x : K, 0 ≤ a * x * x + b * x + c) : discrim a b c ≤ 0 :=
130
116
have hc : 0 ≤ c, by { have := h 0 , linarith },
131
117
begin
132
118
rw [discrim, pow_two],
133
- cases lt_trichotomy a 0 with ha ha ,
119
+ obtain ha|rfl|ha : a < 0 ∨ a = 0 ∨ 0 < a := lt_trichotomy a 0 ,
134
120
-- if a < 0
135
- by_cases hb : b = 0 ,
136
- { rw hb at *,
137
- rcases exists_lt_mul_self (-c/a) with ⟨x, hx⟩,
138
- have := mul_lt_mul_of_neg_left hx ha,
139
- rw [mul_div_cancel' _ (ne_of_lt ha), ← mul_assoc] at this ,
140
- have h₂ := h x, linarith },
141
- { by_cases hc' : c = 0 ,
142
- { rw hc' at *,
143
- have : -(a*-b*-b + b*-b + 0 ) = (1 -a)*(b*b), {ring},
144
- have h := h (-b), rw [← neg_nonpos, this ] at h,
145
- have : b * b ≤ 0 := nonpos_of_mul_nonpos_left h (by linarith),
146
- linarith },
147
- { have h := h (-c/b),
148
- have : a*(-c/b)*(-c/b) + b*(-c/b) + c = a*((c/b)*(c/b)),
149
- { rw mul_div_cancel' _ hb, ring },
150
- rw this at h,
151
- have : 0 ≤ a := nonneg_of_mul_nonneg_right h (mul_self_pos $ div_ne_zero hc' hb),
152
- linarith [ha] } },
153
- cases ha with ha ha,
121
+ { by_cases hb : b = 0 ,
122
+ { rw hb at *,
123
+ rcases exists_lt_mul_self (-c / a) with ⟨x, hx⟩,
124
+ have := mul_lt_mul_of_neg_left hx ha,
125
+ rw [mul_div_cancel' _ (ne_of_lt ha), ← mul_assoc] at this ,
126
+ have h₂ := h x, linarith },
127
+ { by_cases hc' : c = 0 ,
128
+ { rw hc' at *,
129
+ have : -(a * -b * -b + b * -b + 0 ) = (1 - a) * (b * b), {ring},
130
+ have h := h (-b), rw [← neg_nonpos, this ] at h,
131
+ have : b * b ≤ 0 := nonpos_of_mul_nonpos_left h (by linarith),
132
+ linarith },
133
+ { have h := h (-c / b),
134
+ have : a * (-c / b) * (-c / b) + b * (-c / b) + c = a * ((c / b) * (c / b)),
135
+ { rw mul_div_cancel' _ hb, ring },
136
+ rw this at h,
137
+ have : 0 ≤ a := nonneg_of_mul_nonneg_right h (mul_self_pos $ div_ne_zero hc' hb),
138
+ linarith [ha] } } },
154
139
-- if a = 0
155
- by_cases hb : b = 0 ,
156
- { rw [ha, hb], linarith },
157
- { have := h ((-c- 1 )/ b), rw [ha, mul_div_cancel' _ hb] at this , linarith },
140
+ { by_cases hb : b = 0 ,
141
+ { rw [hb], linarith },
142
+ { have := h ((-c - 1 ) / b), rw [mul_div_cancel' _ hb] at this , linarith } },
158
143
-- if a > 0
159
- have := calc
160
- 4 *a * (a* (-(b/a)*( 1 / 2 ))* (-(b/a)*( 1 / 2 )) + b* (-(b/a)*( 1 / 2 )) + c)
161
- = (a*(b/ a)) * (a*(b/ a)) - 2 *(a*(b/ a))* b + 4 *a* c : by ring
162
- ... = -(b* b - 4 *a* c) : by { simp only [mul_div_cancel' b (ne_of_gt ha)], ring },
163
- have ha' : 0 ≤ 4 * a, { linarith} ,
164
- have h := (mul_nonneg ha' (h (-(b/ a) * (1 / 2 )))),
165
- rw this at h, rwa ← neg_nonneg
144
+ { have := calc
145
+ 4 * a * (a * (-(b / a) * ( 1 / 2 )) * (-(b / a) * ( 1 / 2 )) + b * (-(b / a) * ( 1 / 2 )) + c)
146
+ = (a * (b / a)) * (a * (b / a)) - 2 * (a * (b / a)) * b + 4 * a * c : by ring
147
+ ... = -(b * b - 4 * a * c) : by { simp only [mul_div_cancel' b (ne_of_gt ha)], ring },
148
+ have ha' : 0 ≤ 4 * a, by linarith,
149
+ have h := (mul_nonneg ha' (h (-(b / a) * (1 / 2 )))),
150
+ rw this at h, rwa ← neg_nonneg }
166
151
end
167
152
168
153
/--
169
154
If a polynomial of degree 2 is always positive, then its discriminant is negative,
170
155
at least when the coefficient of the quadratic term is nonzero.
171
156
-/
172
- lemma discriminant_lt_zero {a b c : α} (ha : a ≠ 0 ) (h : ∀ x : α, 0 < a*x*x + b*x + c) :
173
- discrim a b c < 0 :=
157
+ lemma discrim_lt_zero (ha : a ≠ 0 ) (h : ∀ x : K, 0 < a * x * x + b * x + c) : discrim a b c < 0 :=
174
158
begin
175
- classical, -- TODO: otherwise linarith performance sucks
176
- have : ∀ x : α, 0 ≤ a*x*x + b*x + c := assume x, le_of_lt (h x),
177
- refine lt_of_le_of_ne (discriminant_le_zero this ) _,
159
+ have : ∀ x : K, 0 ≤ a*x*x + b*x + c := assume x, le_of_lt (h x),
160
+ refine lt_of_le_of_ne (discrim_le_zero this ) _,
178
161
assume h',
179
162
have := h (-b / (2 * a)),
180
163
have : a * (-b / (2 * a)) * (-b / (2 * a)) + b * (-b / (2 * a)) + c = 0 ,
181
164
{ rw [quadratic_eq_zero_iff_of_discrim_eq_zero ha h' (-b / (2 * a))] },
182
165
linarith
183
166
end
167
+
168
+ end linear_ordered_field
0 commit comments