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

Commit 95d33ee

Browse files
committed
refactor(algebra/quadratic_discriminant): drop linearity condition; cleanup (#4656)
Renames: - `discriminant_le_zero` to `discrim_le_zero` - `discriminant_lt_zero` to `discrim_lt_zero`
1 parent 0367467 commit 95d33ee

File tree

2 files changed

+108
-104
lines changed

2 files changed

+108
-104
lines changed

src/algebra/ordered_ring.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,25 @@ lt_of_not_ge (λ ha, absurd h (mul_nonpos_of_nonneg_of_nonpos ha hb).not_lt)
343343
lemma neg_of_mul_pos_right (h : 0 < a * b) (ha : a ≤ 0) : b < 0 :=
344344
lt_of_not_ge (λ hb, absurd h (mul_nonpos_of_nonpos_of_nonneg ha hb).not_lt)
345345

346+
lemma exists_lt_mul_self (a : α) : ∃ x : α, a < x * x :=
347+
begin
348+
by_cases ha : 0 ≤ a,
349+
{ use (a + 1),
350+
calc a = a * 1 : by rw mul_one
351+
... < (a + 1) * (a + 1) : mul_lt_mul (lt_add_one _) (le_add_of_nonneg_left ha)
352+
zero_lt_one (add_nonneg ha zero_le_one) },
353+
{ rw not_le at ha,
354+
use 1,
355+
calc a < 0 : ha
356+
... < 1 * 1 : by simpa only [mul_one] using zero_lt_one }
357+
end
358+
359+
lemma exists_le_mul_self (a : α) : ∃ x : α, a ≤ x * x :=
360+
begin
361+
obtain ⟨x, hx⟩ := exists_lt_mul_self a,
362+
exact ⟨x, le_of_lt hx⟩
363+
end
364+
346365
@[priority 100] -- see Note [lower instance priority]
347366
instance linear_ordered_semiring.to_nontrivial {α : Type*} [linear_ordered_semiring α] :
348367
nontrivial α :=

src/algebra/quadratic_discriminant.lean

Lines changed: 89 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ Copyright (c) 2019 Zhouhang Zhou. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Zhouhang Zhou
55
-/
6+
import algebra.invertible
67
import tactic.linarith
78

89
/-!
@@ -12,78 +13,71 @@ This file defines the discriminant of a quadratic and gives the solution to a qu
1213
1314
## Main definition
1415
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`.
1617
1718
## 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.
2225
2326
## Tags
2427
2528
polynomial, quadratic, discriminant, root
2629
-/
2730

28-
variables {α : Type*}
31+
section ring
32+
variables {R : Type*}
2933

30-
section lemmas
34+
/-- Discriminant of a quadratic -/
35+
def discrim [ring R] (a b c : R) : R := b^2 - 4 * a * c
3136

32-
variables [linear_ordered_field α] {a b c : α}
37+
variables [integral_domain R] {a b c : R}
3338

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 :=
3544
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 }
4057
end
4158

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 :=
4363
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'
5367
end
5468

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
6170

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}
7973

8074
/-- 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) :=
8377
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,
8781
have : x = 2 * a * x / (2 * a) := (mul_div_cancel_left x ne).symm,
8882
have h₁ : 2 * a * ((-b + s) / (2 * a)) = -b + s := mul_div_cancel' _ ne,
8983
have h₂ : 2 * a * ((-b - s) / (2 * a)) = -b - s := mul_div_cancel' _ ne,
@@ -95,7 +89,7 @@ begin
9589
end
9690

9791
/-- 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) :
9993
∃ x, a * x * x + b * x + c = 0 :=
10094
begin
10195
rcases h with ⟨s, hs⟩,
@@ -105,79 +99,70 @@ begin
10599
end
106100

107101
/-- 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) :=
110104
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]
115107
end
116108

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}
126113

127114
/-- 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 :=
130116
have hc : 0 ≤ c, by { have := h 0, linarith },
131117
begin
132118
rw [discrim, pow_two],
133-
cases lt_trichotomy a 0 with ha ha,
119+
obtain ha|rfl|ha : a < 0 ∨ a = 00 < a := lt_trichotomy a 0,
134120
-- 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] } } },
154139
-- 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 } },
158143
-- 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' : 04*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' : 04 * a, by linarith,
149+
have h := (mul_nonneg ha' (h (-(b / a) * (1 / 2)))),
150+
rw this at h, rwa ← neg_nonneg }
166151
end
167152

168153
/--
169154
If a polynomial of degree 2 is always positive, then its discriminant is negative,
170155
at least when the coefficient of the quadratic term is nonzero.
171156
-/
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 :=
174158
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) _,
178161
assume h',
179162
have := h (-b / (2 * a)),
180163
have : a * (-b / (2 * a)) * (-b / (2 * a)) + b * (-b / (2 * a)) + c = 0,
181164
{ rw [quadratic_eq_zero_iff_of_discrim_eq_zero ha h' (-b / (2 * a))] },
182165
linarith
183166
end
167+
168+
end linear_ordered_field

0 commit comments

Comments
 (0)