Theory Second_Derivative_Test
section ‹Second-Order Conditions›
theory Second_Derivative_Test
imports First_Order_Conditions
begin
subsection ‹Necessary Condition›
lemma snd_derivative_nonneg_at_local_min_necessary:
fixes f :: "real ⇒ real"
assumes C2_cont_diff_at_xmin: "C_k_on 2 f (U :: real set)"
assumes min_in_U: "(x_min :: real) ∈ U"
assumes loc_min: "local_minimizer f x_min"
shows "deriv (deriv f) x_min ≥ 0"
proof -
have "(∃ ε. 0 < ε ∧ {x_min - ε .. x_min + ε} ⊂ U)"
proof -
have "(∃ ε. 0 < ε ∧ ball x_min ε ⊂ U)"
by (smt C2_cont_diff_at_xmin C_k_on_def assms(2) ball_subset_cball cball_eq_ball_iff
open_contains_cball_eq order_le_less_trans psubsetI)
then show ?thesis
by (metis Elementary_Metric_Spaces.open_ball cball_eq_atLeastAtMost centre_in_ball
open_contains_cball order_trans_rules(21))
qed
then obtain ε where ε_pos: "0 < ε" and ε_def: "{x_min - ε .. x_min + ε} ⊂ U"
by blast
have f_diff: "(∀y ∈ U. (f has_real_derivative (deriv f) y) (at y))"
using C2_cont_diff C2_cont_diff_at_xmin by blast
have f'_diff: "(∀y ∈ U. (deriv f has_real_derivative (deriv (deriv f)) y) (at y))"
using C2_cont_diff C2_cont_diff_at_xmin by blast
have f''_contin: "continuous_on U (deriv (deriv f))"
using C2_cont_diff assms(1) by blast
have f'_0: "(deriv f) x_min = 0"
using Fermat's_theorem_on_stationary_points
by (meson assms(2,3) f_diff has_field_derivative_imp_has_derivative)
obtain δ where δ_pos: "δ > 0" and δ_prop: "∀h. ¦h¦ < δ ⟶ f (x_min + h) ≥ f x_min"
by (meson assms(3) local_minimizer_neighborhood)
from f'_0 have second_deriv_limit_at_x_min:
"((λh. (deriv f (x_min + h)) / h) ⤏ deriv (deriv f) x_min) (at 0)"
by (smt (verit, best) DERIV_def Lim_cong_within assms(2) f'_diff)
show ?thesis
proof(rule ccontr)
assume "¬ 0 ≤ deriv (deriv f) x_min"
then have BWOC: "0 > deriv (deriv f) x_min"
by auto
then obtain Δ where Δ_pos: "Δ > 0" and
Δ_def: "∀δ. 0 < δ ∧ δ ≤ Δ ⟶ (∀y. ¦y - x_min¦ < δ ⟶ deriv (deriv f) y < 0)"
by (metis C2_cont_diff_at_xmin C_k_on_def min_in_U at_within_open cont_at_neg_imp_loc_neg'
continuous_on_eq_continuous_within f''_contin)
obtain h where h_def: "h = min ε (min (δ/2) Δ)" and h_pos: "0 < h"
using ε_pos δ_pos Δ_pos by fastforce
have h_lt: "h ≤ ε ∧ h < δ ∧ h ≤ Δ"
using δ_pos h_def by linarith
have neigh_in_U: "x_min + h ∈ {x_min - ε .. x_min + ε}"
using h_def h_pos by fastforce
have "f (x_min + h) < f x_min"
proof(rule DERIV_neg_imp_decreasing_open[where a = x_min and f = f and b = "x_min + h"])
show "x_min < x_min + h"
using h_pos by simp
next
have "{x_min..x_min + h} ⊂ U"
using ε_def dual_order.strict_trans2 neigh_in_U by auto
then show "continuous_on {x_min..x_min + h} f"
by (meson C2_cont_diff C2_cont_diff_at_xmin continuous_on_subset
differentiable_imp_continuous_on le_less)
next
show "⋀x. ⟦x_min < x; x < x_min + h⟧ ⟹ ∃y. (f has_real_derivative y) (at x) ∧ y < 0"
proof -
fix x :: real
assume x_min_lt_x: "x_min < x"
assume x_lt_xmin_pls_h: "x < x_min + h"
have xmin_x_subset: "{x_min .. x} ⊆ {x_min - ε .. x_min + ε}"
using neigh_in_U x_lt_xmin_pls_h by auto
have "∃z > x_min. z < x ∧ deriv f (x) - deriv f x_min = (x - x_min) * deriv(deriv f) z"
proof(rule MVT2)
show "x_min < x"
using x_min_lt_x by auto
next
fix y :: real
assume x_min_leq_y: "x_min ≤ y"
assume y_leq_x: "y ≤ x"
from xmin_x_subset have "y ∈ U"
using ε_def atLeastAtMost_iff x_min_leq_y y_leq_x by blast
then show "(deriv f has_real_derivative deriv (deriv f) y) (at y)"
using f'_diff by blast
qed
then obtain z where z_gt_x_min: "z > x_min" and
z_lt_x: "z < x" and
z_def: "deriv f (x) - deriv f x_min = (x - x_min) * deriv (deriv f) z"
by blast
then have mvt_f': "deriv f (x) = (x - x_min) * deriv (deriv f) z"
by (simp add: f'_0)
then have x_diff_xmin_pos: "x - x_min > 0"
using `x_min < x` by simp
then have left_bound_satisfied: "¦z - x_min¦ < x - x_min"
using ‹x_min < z› ‹z < x› by auto
then have "x - x_min < h"
using `x < x_min + h` by simp
then have "¦z - x_min¦ < h"
using left_bound_satisfied by fastforce
then have "deriv (deriv f) z < 0"
using Δ_def h_lt h_pos by blast
then have "deriv f x < 0"
by (metis x_diff_xmin_pos mvt_f' mult_pos_neg)
moreover have "x ∈ U"
using xmin_x_subset
by (meson ε_def atLeastAtMost_iff dual_order.strict_iff_not
subset_eq verit_comp_simplify(2) x_min_lt_x)
ultimately show "∃y. (f has_real_derivative y) (at x) ∧ y < 0"
using f_diff by blast
qed
qed
then show False
by (smt (verit, best) δ_prop h_lt h_pos)
qed
qed
subsection ‹Sufficient Condition›
lemma second_derivative_test:
fixes f :: "real ⇒ real" and a :: real and b :: real and x_min :: real
assumes valid_interval: "a < b"
assumes twice_continuously_differentiable: "C_k_on 2 f {a <..< b}"
assumes min_exists: "x_min ∈ {a <..< b}"
assumes fst_deriv_req: "(deriv f) x_min = 0"
assumes snd_deriv_req: "deriv (deriv f) x_min > 0"
shows loc_min: "local_minimizer f x_min"
proof -
from twice_continuously_differentiable
have f''_cont: "continuous_on {a <..< b} (deriv (deriv f))"
by (metis C_k_on_def Suc_1 lessI nat.simps(2) second_derivative_alt_def)
then obtain Δ where Δ_pos: "Δ > 0"
and Δ_prop: "∀δ. 0 < δ ∧ δ ≤ Δ ⟶ (∀y. ¦y - x_min¦ < δ ⟶ deriv (deriv f) y > 0)"
by (metis assms(3,5) at_within_open cont_at_pos_imp_loc_pos' continuous_on_eq_continuous_within
open_real_greaterThanLessThan)
obtain δ where δ_min: "δ = min Δ (min ((x_min - a) / 2) ((b - x_min) / 2))"
by blast
have δ_pos: "δ > 0"
proof (cases "δ = Δ")
show "δ = Δ ⟹ 0 < δ"
by (simp add: Δ_pos)
next
assume "δ ≠ Δ"
then have "δ = min ((x_min - a) / 2) ((b - x_min) / 2)"
using δ_min by linarith
then show "0 < δ"
using min_exists by force
qed
have neigh_of_x_min_contained_in_ab: "a < x_min - δ ∧ x_min + δ < b"
by (smt (z3) δ_min δ_pos field_sum_of_halves)
have local_min: "∀x. ¦x - x_min¦ < δ ⟶ f x ≥ f x_min"
proof clarify
fix x
assume A: "¦x - x_min¦ < δ"
consider (eq) "x = x_min" | (lt) "x < x_min" | (gt) "x > x_min"
by linarith
then show "f x ≥ f x_min"
proof cases
case eq
then show ?thesis
by simp
next
case lt
have a_lt_x_and_xmin_lt_b: "a < x ∧ x_min < b"
using A neigh_of_x_min_contained_in_ab by linarith
have "f x > f x_min"
proof (rule DERIV_neg_imp_decreasing_open[where a = x])
show "x < x_min"
by (simp add: lt)
next
fix y :: real
assume x_lt_y: "x < y"
assume y_lt_x_min: "y < x_min"
have "∃z > y. z < x_min ∧ deriv f x_min - deriv f y = (x_min - y) * deriv (deriv f) z"
proof (rule MVT2[where a = y and b = x_min and f = "deriv f" and f' = "deriv (deriv f)"])
show "y < x_min"
by (simp add: y_lt_x_min)
next
fix z :: real
assume y_lt_z: "y ≤ z"
assume z_lt_x_min: "z ≤ x_min"
show "(deriv f has_real_derivative (deriv (deriv f)) z) (at z)"
proof (subst C2_cont_diff[where f = f, where U = "{a <..< b}"])
show "C_k_on 2 f {a<..<b}"
by (simp add: assms(2))
show "z ∈ {a<..<b}" and True
using a_lt_x_and_xmin_lt_b x_lt_y y_lt_z z_lt_x_min by auto
qed
qed
then obtain z where
z_props: "y < z" "z < x_min" and
eq: "deriv f x_min - deriv f y = (x_min - y) * deriv (deriv f) z"
by blast
have "deriv f x_min = 0"
using fst_deriv_req by simp
hence "deriv f y = - (x_min - y) * deriv (deriv f) z"
using eq by linarith
moreover have "x_min - x > 0"
using lt by simp
have "deriv (deriv f) z > 0"
by (smt (verit) A Δ_prop δ_min x_lt_y z_props)
ultimately have "deriv f y < 0"
by (simp add: mult_less_0_iff y_lt_x_min)
then show "∃z. (f has_real_derivative z) (at y) ∧ z < 0"
by (meson C2_cont_diff a_lt_x_and_xmin_lt_b assms(2) dual_order.strict_trans
greaterThanLessThan_iff x_lt_y y_lt_x_min)
next
have "continuous_on {a <..< b} f"
by (simp add: C2_cont_diff assms(2) differentiable_imp_continuous_on)
then show "continuous_on {x..x_min} f"
by (smt (verit, del_insts) a_lt_x_and_xmin_lt_b atLeastAtMost_iff
continuous_on_subset greaterThanLessThan_iff subsetI)
qed
then show "f x_min ≤ f x"
by simp
next
case gt
have a_lt_xmin_and_x_lt_b: "a < x_min ∧ x < b"
using A ‹a < x_min - δ ∧ x_min + δ < b› by linarith
have "f x > f x_min"
proof (rule DERIV_pos_imp_increasing_open[where a = x_min])
show "x_min < x"
by (simp add: gt)
next
fix y :: real
assume y_gt_xmin: "x_min < y"
assume y_lt_x: "y < x"
have "∃z > x_min. z < y ∧ deriv f y - deriv f x_min = (y - x_min) * deriv (deriv f) z"
proof (rule MVT2[where a = x_min and b = y and f = "deriv f" and f' = "deriv (deriv f)"])
show "x_min < y"
by (simp add: y_gt_xmin)
next
fix z :: real
assume z_ge_xmin: "x_min ≤ z"
assume z_le_y: "z ≤ y"
show "(deriv f has_real_derivative (deriv (deriv f)) z) (at z)"
proof (subst C2_cont_diff[where f = f and U = "{a<..<b}"])
show "C_k_on 2 f {a<..<b}"
by (simp add: assms(2))
show "z ∈ {a<..<b}" and True
using a_lt_xmin_and_x_lt_b y_lt_x z_ge_xmin z_le_y by auto
qed
qed
then obtain z where
z_props: "x_min < z" "z < y"
and eq: "deriv f y - deriv f x_min = (y - x_min) * deriv (deriv f) z"
by blast
have "deriv f x_min = 0"
using fst_deriv_req by simp
hence "deriv f y = (y - x_min) * deriv (deriv f) z"
using eq by simp
moreover have "y - x_min > 0"
using y_gt_xmin by simp
moreover have "deriv (deriv f) z > 0"
by (smt (verit, best) A Δ_prop δ_min y_lt_x z_props(1,2))
ultimately have "deriv f y > 0"
by auto
then show "∃d. (f has_real_derivative d) (at y) ∧ d > 0"
by (meson C2_cont_diff a_lt_xmin_and_x_lt_b assms(2) dual_order.strict_trans
greaterThanLessThan_iff y_lt_x y_gt_xmin)
next
have "continuous_on {a <..< b} f"
by (simp add: C2_cont_diff assms(2) differentiable_imp_continuous_on)
then show "continuous_on {x_min..x} f"
by (smt (verit, del_insts) a_lt_xmin_and_x_lt_b atLeastAtMost_iff
continuous_on_subset greaterThanLessThan_iff subsetI)
qed
then show ?thesis
by simp
qed
qed
show ?thesis
by (rule local_minimizer_from_neighborhood, smt δ_pos local_min)
qed
end