Theory Quadratics
section ‹ Quadratics ›
text ‹ This theory shows how to find the roots of a quadratic,
assuming that roots exist (AxEField). ›
theory "Quadratics"
imports Functions AxEField
begin
class Quadratics = Functions + AxEField
begin
abbreviation quadratic :: "'a ⇒ 'a ⇒ 'a ⇒ ('a ⇒ 'a)"
where "quadratic a b c ≡ λ x . a*(sqr x) + b*x + c"
abbreviation qroot :: "'a ⇒ 'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qroot a b c r ≡ (quadratic a b c) r = 0"
abbreviation qroots :: "'a ⇒ 'a ⇒ 'a ⇒ 'a set"
where "qroots a b c ≡ { r . qroot a b c r }"
abbreviation discriminant :: "'a ⇒ 'a ⇒ 'a ⇒ 'a"
where "discriminant a b c ≡ (sqr b) - 4*a*c"
abbreviation qcase1 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase1 a b c ≡ (a = 0 ∧ b = 0 ∧ c = 0)"
abbreviation qcase2 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase2 a b c ≡ (a = 0 ∧ b = 0 ∧ c ≠ 0)"
abbreviation qcase3 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase3 a b c ≡ (a = 0 ∧ b ≠ 0 ∧ (c = 0 ∨ c ≠0))"
abbreviation qcase4 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase4 a b c ≡ (a ≠ 0 ∧ discriminant a b c < 0)"
abbreviation qcase5 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase5 a b c ≡ (a ≠ 0 ∧ discriminant a b c = 0)"
abbreviation qcase6 :: "'a ⇒ 'a ⇒ 'a ⇒ bool"
where "qcase6 a b c ≡ (a ≠ 0 ∧ discriminant a b c > 0)"
lemma lemQuadRootCondition:
assumes "a ≠ 0"
shows "(sqr (2*a*r + b) = discriminant a b c) ⟷ qroot a b c r"
proof -
have "sqr (2*a*r) = (4*a) * (a * sqr r)"
using lemSqrMult local.numeral_sqr mult_assoc sqr.simps(1) sqr.simps(2)
by metis
moreover have "2*(2*a*r)*b = (4*a) * (b*r)"
by (metis dbl_def dbl_simps(5) mult.left_commute mult_2 mult_2_right mult_assoc)
ultimately have s: "sqr (2*a*r) + 2*(2*a*r)*b = (4*a) * ((a * sqr r) + b *r)"
by (simp add: local.distrib_left)
have "sqr(2*a*r + b) = sqr (2*a*r) + 2*(2*a*r)*b + sqr b"
using lemSqrSum by auto
moreover have "… = (4*a) * ((a * sqr r) + b *r) + sqr b" using s by auto
moreover have "… = (4*a) * ((a * sqr r) + b *r + c) - (4*a)*c + sqr b"
by (simp add: distrib_left)
ultimately have eqn1: "sqr(2*a*r + b) = (4*a)*(quadratic a b c r) + (discriminant a b c)"
by (simp add: add_diff_eq diff_add_eq)
{ assume "qroot a b c r"
hence "sqr (2*a*r + b) = discriminant a b c" using eqn1 by simp
}
hence l2r: "qroot a b c r ⟶ sqr (2*a*r + b) = discriminant a b c" by auto
{ assume "sqr (2*a*r + b) = discriminant a b c"
hence "0 = (4*a)*(quadratic a b c r)" using eqn1 by auto
hence "qroot a b c r" by (metis assms divisors_zero zero_neq_numeral)
}
hence "(sqr (2*a*r + b) = discriminant a b c) ⟶ qroot a b c r" by blast
thus ?thesis using l2r by blast
qed
lemma lemQuadraticCasesComplete:
shows "qcase1 a b c ∨ qcase2 a b c ∨ qcase3 a b c ∨ qcase4 a b c ∨
qcase5 a b c ∨ qcase6 a b c"
using not_less_iff_gr_or_eq by blast
lemma lemQCase1:
assumes "qcase1 a b c"
shows "∀ r . qroot a b c r"
using assms by simp
lemma lemQCase2:
assumes "qcase2 a b c"
shows "¬ (∃ r . qroot a b c r)"
by (simp add: assms)
lemma lemQCase3:
assumes "qcase3 a b c"
shows "qroot a b c r ⟷ r = -c/b"
proof -
have "qroot a b c r ⟶ r = -c/b"
proof -
{ assume hyp: "qroot a b c r"
hence "b*r + c = 0" using assms by auto
hence "b*r = -c" by (simp add: local.eq_neg_iff_add_eq_0)
hence "r = -c/b" by (metis assms local.nonzero_mult_div_cancel_left)
}
thus ?thesis by auto
qed
moreover have "r = -c/b ⟶ qroot a b c r" by (simp add: assms)
ultimately show ?thesis by blast
qed
lemma lemQCase4:
assumes "qcase4 a b c"
shows "¬ (∃ r . qroot a b c r)"
proof -
have props: "(a ≠ 0 ∧ discriminant a b c < 0)" using assms by auto
{ assume hyp: "∃ r . qroot a b c r"
then obtain r where r: "qroot a b c r" by auto
hence "sqr (2 * a * r + b) = discriminant a b c"
using props lemQuadRootCondition[of "a" "r" "b" "c"] by auto
hence "sqr (2*a*r + b) < 0" using props by auto
hence "False" using lemSquaresPositive by auto
}
thus ?thesis by auto
qed
lemma lemQCase5:
assumes "qcase5 a b c"
shows "qroot a b c r ⟷ r = -b/(2*a)"
proof -
have "qroot a b c r ⟶ r = -b/(2*a)"
proof -
{ assume hyp: "qroot a b c r"
hence "sqr (2 * a * r + b) = 0"
using assms lemQuadRootCondition[of "a" "r" "b" "c"] by auto
hence "2*a*r + b = 0" by simp
hence "2*a*r = -b" using local.eq_neg_iff_add_eq_0 by auto
moreover have "2*a ≠ 0" using assms by auto
ultimately have "r = ((-b)/(2*a))" by (metis local.nonzero_mult_div_cancel_left)
}
thus ?thesis by auto
qed
moreover have "r = -b/(2*a) ⟶ qroot a b c r"
proof -
{ assume hyp: "r = -b/(2*a)"
hence "(2*a)*r + b = discriminant a b c" by (simp add: assms)
hence "qroot a b c r" using lemQuadRootCondition[of "a" "r" "b" "c"] assms by auto
}
thus ?thesis by auto
qed
ultimately show ?thesis by blast
qed
lemma lemQCase6:
assumes "qcase6 a b c"
and "rd = sqrt (discriminant a b c)"
and "rp = ((-b) + rd) / (2*a)"
and "rm = ((-b) - rd) / (2*a)"
shows "(rp ≠ rm) ∧ qroots a b c = { rp, rm }"
proof -
define d where d: "d = discriminant a b c"
have dpos: "d > 0" using assms d by auto
hence rootd: "hasUniqueRoot d" using AxEField lemSqrt[of "d"] by auto
hence rdprops: "0 ≤ rd ∧ d = sqr rd"
using assms(2) d theI'[of "isNonNegRoot d"] by auto
hence rdnot0: "rd ≠ 0" using assms dpos mult_nonneg_nonpos by auto
hence rdpos: "rd > 0" using rdprops by auto
define pp where pp: "pp = (-b) + rd"
define mm where mm: "mm = (-b) - rd"
have "rd ≠ -rd" using rdnot0 by simp
hence "pp ≠ mm" using pp mm add_left_imp_eq[of "-b" "rd" "-rd"] by auto
moreover have aa: "2*a ≠ 0" using assms by auto
ultimately have "pp/(2*a) ≠ mm/(2*a)" by auto
hence conj1: "rp ≠ rm" using assms pp mm by simp
have conj2: "qroots a b c = {rp, rm}"
proof -
{ fix r assume "r ∈ qroots a b c"
hence "sqr (2*a*r + b) = d"
using assms lemQuadRootCondition d by auto
hence "sqrt d = abs (2*a*r + b)" using lemSqrtOfSquare by blast
moreover have "sqrt d = rd" using d assms by auto
ultimately have rdprops: "rd = abs (2*a*r + b)" by auto
define v :: "'a" where v: "v = 2*a*r + b"
hence vnot0: "v ≠ 0" using rdprops rdnot0 by simp
hence cases: "(v < 0) ∨ (v > 0)" by auto
{ assume "v < 0"
hence "2*a*r + b = -rd" using v rdprops
by (metis local.abs_if local.minus_minus)
hence "2*a*r = (-b) - rd"
by (metis local.add_diff_cancel_right' local.minus_diff_commute)
hence "r = rm" using aa assms(4)
by (metis local.nonzero_mult_div_cancel_left)
}
hence case1: "v < 0 ⟶ r = rm" by auto
{ assume "v > 0"
hence "2*a*r + b = rd" using v rdprops by simp
hence "2*a*r = (-b) + rd" by auto
hence "r = rp" using aa assms(3)
by (metis local.nonzero_mult_div_cancel_left)
}
hence "v > 0 ⟶ r = rp" by auto
hence "r = rm ∨ r = rp" using case1 cases by blast
hence "r ∈ { rm, rp }" by blast
}
hence "∀ r . r ∈ qroots a b c ⟶ r ∈ { rm, rp }" by blast
hence l2r: "qroots a b c ⊆ {rm, rp}" by auto
have rootm: "qroot a b c rm"
proof -
have "rm = ((-b) - rd) / (2*a)" using assms by auto
hence "(2*a)*rm = (-b) - rd" using aa by simp
hence "(2*a)*rm + b = - rd" by (simp add: local.diff_add_eq)
hence "sqr( (2*a)*rm + b ) = sqr rd" by simp
moreover have "… = discriminant a b c"
using assms(2) rootd d lemSquareOfSqrt[of "discriminant a b c" "rd"] by auto
ultimately show ?thesis
using assms lemQuadRootCondition[of "a" "rm" "b" "c"] by auto
qed
have rootp: "qroot a b c rp"
proof -
have "rp = ((-b) + rd) / (2*a)" using assms by auto
hence "(2*a)*rp = (-b) + rd" using aa by simp
hence "(2*a)*rp + b = rd" by (simp add: local.diff_add_eq)
hence "sqr( (2*a)*rp + b ) = sqr rd" by simp
moreover have "… = discriminant a b c"
using assms(2) rootd d lemSquareOfSqrt[of "discriminant a b c" "rd"] by auto
ultimately show ?thesis
using assms lemQuadRootCondition[of "a" "rp" "b" "c"] by auto
qed
hence "{rm, rp} ⊆ qroots a b c" using rootm rootp by auto
thus ?thesis using l2r by blast
qed
thus ?thesis using conj1 by blast
qed
lemma lemQuadraticRootCount:
assumes "¬(qcase1 a b c)"
shows "finite (qroots a b c) ∧ card (qroots a b c) ≤ 2"
proof -
define d where d: "d = discriminant a b c"
have case1: "qcase1 a b c ⟶ ?thesis" using assms by auto
moreover have case2: "qcase2 a b c ⟶ ?thesis" using lemQCase2 by auto
moreover have case3: "qcase3 a b c ⟶ ?thesis" using lemQCase3 by auto
moreover have case4: "qcase4 a b c ⟶ ?thesis" using lemQCase4 by auto
moreover have case5: "qcase5 a b c ⟶ ?thesis" using lemQCase5 by auto
moreover have case6: "qcase6 a b c ⟶ ?thesis" using lemQCase6 card_2_iff by auto
ultimately show ?thesis using lemQuadraticCasesComplete by blast
qed
end
end