Theory MDP_reward_Util
theory MDP_reward_Util
imports Blinfun_Util
begin
section ‹Auxiliary Lemmas›
subsection ‹Summability›
lemma summable_powser_const:
fixes c :: real
assumes "¦c¦ < 1"
shows "summable (λn. c^n * x)"
using assms
by (auto simp: mult.commute)
subsection ‹Infinite sums›
lemma suminf_split_head':
"summable (f :: nat ⇒ 'x :: real_normed_vector) ⟹ suminf f = f 0 + (∑n. f (Suc n))"
by (auto simp: suminf_split_head)
lemma sum_disc_lim:
assumes "¦c :: real¦ < 1"
shows "(∑x. c^x * B) = B /(1-c)"
by (simp add: assms suminf_geometric summable_geometric suminf_mult2[symmetric])
subsection ‹Bounded Functions›
lemma suminf_apply_bfun:
fixes f :: "nat ⇒ 'c ⇒⇩b real"
assumes "summable f"
shows "(∑i. f i) x = (∑i. f i x)"
by (auto intro!: bounded_linear.suminf assms bounded_linear_intro[where K = 1] abs_le_norm_bfun)
lemma sum_apply_bfun:
fixes f :: "nat ⇒ 'c ⇒⇩b real"
shows "(∑i<n. f i) x = (∑i<n. apply_bfun (f i) x)"
by (induction n) auto
subsection ‹Push-Forward of a Bounded Function›
lemma integrable_bfun_prob_space [simp]:
"integrable (measure_pmf P) (λt. apply_bfun f (F t) :: real)"
proof -
obtain b where "∀t. ¦f (F t)¦ ≤ b"
by (metis norm_le_norm_bfun real_norm_def)
hence "(∫⇧+ x. ennreal ¦f (F x)¦ ∂P) ≤ b"
using nn_integral_mono ennreal_leI
by (auto intro: measure_pmf.nn_integral_le_const)
then show ?thesis
using ennreal_less_top le_less_trans
by (fastforce simp: integrable_iff_bounded)
qed
lift_definition push_exp :: "('b ⇒ 'c pmf) ⇒ ('c ⇒⇩b real) ⇒ ('b ⇒⇩b real)" is
"λc f s. measure_pmf.expectation (c s) f"
using bfun_integral_bound' .
declare push_exp.rep_eq[simp]
lemma norm_push_exp_le_norm: "norm (push_exp d x) ≤ norm x"
proof -
have "⋀s. (∫s'. norm (x s') ∂d s) ≤ norm x"
using measure_pmf.prob_space_axioms norm_le_norm_bfun[of x]
by (auto intro!: prob_space.integral_le_const)
hence aux: "⋀s. norm (∫s'. x s' ∂d s) ≤ norm x"
using integral_norm_bound order_trans by blast
have "norm (push_exp d x) = (⨆s. norm (∫s'. x s' ∂d s))"
unfolding norm_bfun_def'
by auto
also have "… ≤ norm x"
using aux by (fastforce intro!: cSUP_least)
finally show ?thesis .
qed
lemma push_exp_bounded_linear [simp]: "bounded_linear (push_exp d)"
using norm_push_exp_le_norm
by (auto intro!: bounded_linear_intro[where K = 1])
lemma onorm_push_exp [simp]: "onorm (push_exp d) = 1"
proof (intro antisym)
show "onorm (push_exp d) ≤ 1"
using norm_push_exp_le_norm
by (auto intro!: onorm_bound)
next
show "1 ≤ onorm (push_exp d)"
using onorm[of _ 1, OF push_exp_bounded_linear]
by (auto simp: norm_bfun_def')
qed
lemma push_exp_return[simp]: "push_exp return_pmf = id"
by (auto simp: eq_id_iff[symmetric])
subsection ‹Boundedness›
lemma bounded_abs[intro]:
"bounded (X' :: real set) ⟹ bounded (abs ` X')"
by (auto simp: bounded_iff)
lemma bounded_abs_range[intro]:
"bounded (range f :: real set) ⟹ bounded (range (λx. abs (f x)))"
by (auto simp: bounded_iff)
subsection ‹Probability Theory›
lemma integral_measure_pmf_bind:
assumes "(⋀x. ¦(f :: 'b ⇒ real) x¦ ≤ B)"
shows "(∫x. f x ∂((measure_pmf M) ⤜ (λx. measure_pmf (N x)))) = (∫x. ∫y. f y ∂N x ∂M)"
using assms
by (subst integral_bind[of _ "count_space UNIV" B]) (auto simp: measure_pmf_in_subprob_space)
lemma lemma_4_3_1':
assumes "set_pmf p ⊆ W"
and "bounded ((w :: 'c ⇒ real) ` W)"
and "W ≠ {}"
and "measure_pmf.expectation p w = (⨆p ∈ {p. set_pmf p ⊆ W}. measure_pmf.expectation p w)"
shows "∃x ∈ W. measure_pmf.expectation p w = w x"
proof -
have abs_w_le_sup: "y ∈ W ⟹ ¦w y¦ ≤ (⨆x ∈ W. ¦w x¦)" for y
using assms bounded_abs[OF assms(2)]
by (auto intro!: cSUP_upper bounded_imp_bdd_above simp: image_image)
have "False" if "x ∈ set_pmf p" "w x < ⨆(w ` W)" for x
proof -
have ex_gr: "∃x'. x' ∈ W ∧ w x < w x'"
using cSUP_least[of W w "w x"] that assms
by fastforce
let ?s = "λs. (if x = s then SOME x'. x' ∈ W ∧ w x < w x' else s)"
have "measure_pmf.expectation p w < measure_pmf.expectation p (λxa. w (?s xa))"
proof (intro measure_pmf.integral_less_AE[where A = "{x}"])
show "integrable (measure_pmf p) w"
using assms abs_w_le_sup
by (fastforce simp: AE_measure_pmf_iff
intro!: measure_pmf.integrable_const_bound)
show "integrable (measure_pmf p) (λxa. w (?s xa))"
using assms(1) ex_gr someI[where P = "λx'. (x' ∈ W) ∧ (w x < w x')"]
by (fastforce simp: AE_measure_pmf_iff
intro!: abs_w_le_sup measure_pmf.integrable_const_bound)
show "emeasure (measure_pmf p) {x} ≠ 0"
by (simp add: emeasure_pmf_single_eq_zero_iff ‹x ∈ p›)
show "{x} ∈ measure_pmf.events p"
by auto
show "AE xa∈{x} in p. w xa ≠ w (?s xa)" "AE xa in p. w xa ≤ w (?s xa)"
using someI[where P = "λx'. (x' ∈ W) ∧ (w x < w x')"] ex_gr
by (fastforce intro!: AE_pmfI)+
qed
hence "measure_pmf.expectation p w < ⨆((λp. measure_pmf.expectation p w) ` {p. set_pmf p ⊆ W})"
proof (subst less_cSUP_iff, goal_cases)
case 1
then show ?case
using assms(1)
by blast
next
case 2
then show ?case
using abs_w_le_sup
by (fastforce
simp: AE_measure_pmf_iff
intro: cSUP_upper2 bdd_aboveI[where M = "(⨆x∈W. ¦w x¦)"]
intro!: measure_pmf.integral_le_const measure_pmf.integrable_const_bound)
next
case 3
then show ?case
using ex_gr someI[where P = "λx'. (x' ∈ W) ∧ (w x < w x')"] assms(1)
by (auto intro!: exI[of _ "map_pmf ?s p"])
qed
thus False
using assms by auto
qed
hence 1: "x ∈ set_pmf p ⟹ w x = ⨆ (w ` W)" for x
using assms
by (fastforce intro: antisym simp: bounded_imp_bdd_above cSUP_upper)
hence "w (SOME x. x ∈ set_pmf p) = ⨆ (w ` W)"
by (simp add: set_pmf_not_empty some_in_eq)
thus ?thesis
using 1 assms(1) set_pmf_not_empty some_in_eq
by (fastforce intro!: bexI[of _ "SOME x. x ∈ set_pmf p"]
simp: AE_measure_pmf_iff Bochner_Integration.integral_cong_AE[where ?g = "λ_. ⨆ (w ` W)"])
qed
lemma lemma_4_3_1:
assumes "set_pmf p ⊆ W" "integrable (measure_pmf p) w" "bounded ((w :: 'c ⇒ real) ` W)"
shows "measure_pmf.expectation p w ≤ ⨆(w ` W)"
using assms bounded_has_Sup(1) prob_space_measure_pmf
by (fastforce simp: AE_measure_pmf_iff intro!: prob_space.integral_le_const)
lemma bounded_integrable:
assumes "bounded (range v)" "v ∈ borel_measurable (measure_pmf p)"
shows "integrable (measure_pmf p) (v :: 'c ⇒ real)"
using assms
by (auto simp: bounded_iff AE_measure_pmf_iff intro!: measure_pmf.integrable_const_bound)
subsection ‹Argmax›
lemma finite_is_arg_max: "finite X ⟹ X ≠ {} ⟹ ∃x. is_arg_max (f :: 'c ⇒ real) (λx. x ∈ X) x"
unfolding is_arg_max_def
proof (induction rule: finite_induct)
case (insert x F)
then show ?case
proof (cases "∀y ∈ F. f y ≤ f x")
case True
then show ?thesis
by (auto intro!: exI[of _ x])
next
case False
then show ?thesis
using insert by force
qed
qed simp
lemma finite_arg_max_le:
assumes "finite (X :: 'c set)" "X ≠ {}"
shows "s ∈ X ⟹ (f :: 'c ⇒ real) s ≤ f (arg_max_on (f :: 'c ⇒ real) X)"
unfolding arg_max_def arg_max_on_def
by (metis assms(1) assms(2) finite_is_arg_max is_arg_max_linorder someI_ex)
lemma arg_max_on_in:
assumes "finite (X :: 'c set)" "X ≠ {}"
shows "(arg_max_on (f :: 'c ⇒ real) X) ∈ X"
unfolding arg_max_on_def arg_max_def
by (metis assms(1) assms(2) finite_is_arg_max is_arg_max_def someI)
lemma finite_arg_max_eq_Max:
assumes "finite (X :: 'c set)" "X ≠ {}"
shows "(f :: 'c ⇒ real) (arg_max_on f X) = Max (f ` X)"
using assms
by (auto intro!: Max_eqI[symmetric] finite_arg_max_le arg_max_on_in)
lemma arg_max_SUP: "is_arg_max (f :: 'b ⇒ real) (λx. x ∈ X) m ⟹ f m = (⨆(f ` X))"
unfolding is_arg_max_def
by (auto intro!: antisym cSUP_upper bdd_aboveI[of _ "f m"] cSUP_least)
definition "has_max X ≡ ∃x ∈ X. ∀x' ∈ X. x' ≤ x"
definition "has_arg_max f X ≡ ∃x. is_arg_max f (λx. x ∈ X) x"
lemma "has_max ((f :: 'b ⇒ real) ` X) ⟷ has_arg_max f X"
unfolding has_max_def has_arg_max_def is_arg_max_def
using not_less by (auto dest!: leD simp: not_less)
lemma has_arg_max_is_arg_max: "has_arg_max f X ⟹ is_arg_max f (λx. x ∈ X) (arg_max f (λx. x ∈ X))"
unfolding has_arg_max_def arg_max_def
by (auto intro: someI)
lemma has_arg_max_arg_max: "has_arg_max f X ⟹ (arg_max f (λx. x ∈ X)) ∈ X"
unfolding has_arg_max_def arg_max_def is_arg_max_def by (auto intro: someI2_ex)
lemma app_arg_max_ge: "has_arg_max (f :: 'b ⇒ real) X ⟹ x ∈ X ⟹ f x ≤ f (arg_max_on f X)"
unfolding has_arg_max_def arg_max_on_def arg_max_def is_arg_max_def
using someI[where ?P = "λx. x ∈ X ∧ (∄y. y ∈ X ∧ f x < f y)"] le_less_linear
by auto
lemma app_arg_max_eq_SUP: "has_arg_max (f :: 'b ⇒ real) X ⟹ f (arg_max_on f X) = ⨆(f ` X)"
by (simp add: arg_max_SUP arg_max_on_def has_arg_max_is_arg_max)
lemma SUP_is_arg_max:
assumes "x ∈ X" "bdd_above (f ` X)" "(f :: 'c ⇒ real) x = ⨆(f ` X)"
shows "is_arg_max f (λx. x ∈ X) x"
unfolding is_arg_max_def
using not_less assms cSUP_upper[of _ X f]
by auto
lemma is_arg_max_linorderI[intro]: fixes f :: "'c ⇒ 'b :: linorder"
assumes "P x" "⋀y. (P y ⟹ f x ≥ f y)"
shows "is_arg_max f P x"
using assms by (auto simp: is_arg_max_linorder)
lemma is_arg_max_linorderD[dest]: fixes f :: "'c ⇒ 'b :: linorder"
assumes "is_arg_max f P x"
shows "P x" "(P y ⟹ f x ≥ f y)"
using assms by (auto simp: is_arg_max_linorder)
lemma is_arg_max_cong:
assumes "⋀x. P x ⟹ f x = g x"
shows "is_arg_max f P x ⟷ is_arg_max g P x"
unfolding is_arg_max_def using assms by auto
lemma is_arg_max_cong':
assumes "⋀x. P x ⟹ f x = g x"
shows "is_arg_max f P = is_arg_max g P"
using assms by (auto cong: is_arg_max_cong)
lemma is_arg_max_congI:
assumes "is_arg_max f P x" "⋀x. P x ⟹ f x = g x"
shows "is_arg_max g P x"
using is_arg_max_cong assms by force
subsection ‹Contraction Mappings›
definition "is_contraction C ≡ ∃l. 0 ≤ l ∧ l < 1 ∧ (∀v u. dist (C v) (C u) ≤ l * dist v u)"
lemma banach':
fixes C :: "'b :: complete_space ⇒ 'b"
assumes "is_contraction C"
shows "∃!v. C v = v" "⋀v. (λn. (C ^^ n) v) ⇢ (THE v. C v = v)"
proof -
obtain v where C: "C v = v" "∀v'. C v' = v' ⟶ v' = v"
by (metis assms is_contraction_def banach_fix_type)
obtain l where cont: "dist (C v) (C u) ≤ l * dist v u" "0 ≤ l" "l < 1" for v u
using assms is_contraction_def by blast
have *: "⋀n v0. dist ((C ^^ n) v0) v ≤ l ^ n * dist v0 v"
proof -
fix n v0
show "dist ((C ^^ n) v0) v ≤ l ^ n * dist v0 v"
proof (induction n)
case (Suc n)
thus "dist ((C ^^ Suc n) v0) v ≤ l ^ Suc n * dist v0 v"
using ‹0 ≤ l›
by (subst C(1)[symmetric]) (auto simp: algebra_simps intro!: order_trans[OF cont(1)] mult_left_mono)
qed simp
qed
have "(λn. l ^ n) ⇢ 0"
by (simp add: LIMSEQ_realpow_zero ‹0 ≤ l› ‹l < 1›)
hence "⋀v0. (λn. l ^ n * dist v0 v) ⇢ 0"
by (simp add: tendsto_mult_left_zero)
hence "(λn. dist ((C ^^ n) v0) v) ⇢ 0" for v0
using * order_trans abs_ge_self
by (subst Limits.tendsto_0_le[of "(λn. l ^ n * dist v0 v)" _ _ 1])
(fastforce intro!: eventuallyI)+
hence "⋀v0. (λn. (C ^^ n) v0) ⇢ v"
using tendsto_dist_iff by blast
thus "⋀v0. (λn. (C ^^ n) v0) ⇢ (THE v. C v = v)"
by (metis (mono_tags, lifting) C theI')
next
show "∃!v. C v = v"
using assms banach_fix_type unfolding is_contraction_def by blast
qed
lemma contraction_dist:
fixes C :: "'b :: complete_space ⇒ 'b"
assumes "⋀v u. dist (C v) (C u) ≤ c * dist v u"
assumes "0 ≤ c" "c < 1"
shows "(1 - c) * dist v (THE v. C v = v) ≤ dist v (C v)"
proof -
have "is_contraction C"
unfolding is_contraction_def using assms by auto
then obtain v_fix where v_fix: "v_fix = (THE v. C v = v)"
using the1_equality by blast
hence "(λn. (C ^^ n) v) ⇢ v_fix"
using banach'[OF ‹is_contraction C›] by simp
have dist_contr_le_pow: "⋀n. dist ((C ^^ n) v) ((C ^^ Suc n) v) ≤ c ^ n * dist v (C v)"
proof -
fix n
show "dist ((C ^^ n) v) ((C ^^ Suc n) v) ≤ c ^ n * dist v (C v)"
using assms
by (induction n) (auto simp: algebra_simps intro!: order.trans[OF assms(1)] mult_left_mono)
qed
have summable_C: "summable (λi. dist ((C ^^ i) v) ((C ^^ Suc i) v))"
using dist_contr_le_pow assms summable_powser_const
by (intro summable_comparison_test[of "(λi. dist ((C ^^ i) v) ((C ^^ Suc i) v))" "λi. c^i * dist v (C v)"])
auto
have "∀e > 0. dist v v_fix ≤ (∑i. dist ((C ^^ i) v) ((C ^^ (Suc i)) v)) + e"
proof safe
fix e ::real assume "0 < e"
have "∀⇩F n in sequentially. dist ((C^^n) v) v_fix < e"
using ‹(λn. (C ^^ n) v) ⇢ v_fix› ‹0 < e› tendsto_iff by force
then obtain N where "dist ((C^^N) v) v_fix < e"
by fastforce
hence *: "dist v v_fix ≤ dist v ((C^^N) v) + e"
by (metis add_le_cancel_left dist_commute dist_triangle_le less_eq_real_def)
have "dist v ((C^^N) v) ≤ (∑i≤N. dist ((C ^^ i) v) ((C ^^ (Suc i)) v))"
proof (induction N arbitrary: v)
case 0
then show ?case by simp
next
case (Suc N)
have "dist v ((C ^^ Suc N) v) ≤ dist v (C v) + dist (C v) ((C^^(Suc N)) v)"
by metric
also have "… = dist v (C v) + dist (C v) ((C^^N) (C v))"
by (metis funpow_simps_right(2) o_def)
also have "… ≤ dist v (C v) + (∑i≤N. dist ((C ^^ i) (C v)) ((C ^^ Suc i) (C v)))"
using Suc.IH add_le_cancel_left by blast
also have "… ≤ dist v (C v) + (∑i≤N. dist ((C ^^Suc i) v) ((C ^^ (Suc (Suc i))) v))"
by (simp only: funpow_simps_right(2) o_def)
also have "… ≤ (∑i≤Suc N. dist ((C ^^ i) v) ((C ^^ (Suc i)) v))"
by (subst sum.atMost_Suc_shift) simp
finally show "dist v ((C ^^ Suc N) v) ≤ (∑i≤Suc N. dist ((C ^^ i) v) ((C ^^ Suc i) v))" .
qed
moreover have
"(∑i≤N. dist ((C ^^ i) v) ((C ^^ Suc i) v)) ≤ (∑i. dist ((C ^^ i) v) ((C ^^ (Suc i)) v))"
using summable_C
by (auto intro: sum_le_suminf)
ultimately have "dist v ((C^^N) v) ≤ (∑i. dist ((C ^^ i) v) ((C ^^ (Suc i)) v))"
by linarith
thus "dist v v_fix ≤ (∑i. dist ((C ^^ i) v) ((C ^^ Suc i) v)) + e"
using * by fastforce
qed
hence le_suminf: "dist v v_fix ≤ (∑i. dist ((C ^^ i) v) ((C ^^ Suc i) v))"
using field_le_epsilon by blast
have "dist v v_fix ≤ (∑i. c ^ i * dist v (C v))"
using dist_contr_le_pow summable_C assms summable_powser_const
by (auto intro!: order_trans[OF le_suminf] suminf_le)
hence "dist v v_fix ≤ dist v (C v) / (1 - c)"
using sum_disc_lim
by (metis sum_disc_lim abs_of_nonneg assms(2) assms(3))
hence "(1 - c) * dist v v_fix ≤ dist v (C v)"
using assms(3) mult.commute pos_le_divide_eq
by (metis diff_gt_0_iff_gt)
thus ?thesis
using v_fix by blast
qed
subsection ‹Limits›
lemma tendsto_bfun_sandwich:
assumes
"(f :: nat ⇒ 'b ⇒⇩b real) ⇢ x" "(g :: nat ⇒ 'b ⇒⇩b real) ⇢ x"
"eventually (λn. f n ≤ h n) sequentially" "eventually (λn. h n ≤ g n) sequentially"
shows "(h :: nat ⇒ 'b ⇒⇩b real) ⇢ x"
proof -
have 1: "(λn. dist (f n) (g n) + dist (g n) x) ⇢ 0"
using tendsto_dist[OF assms(1) assms(2)] tendsto_dist_iff assms
by (auto intro!: tendsto_add_zero)
have "eventually (λn. dist (h n) (g n) ≤ dist (f n) (g n)) sequentially"
using assms(3) assms(4)
proof eventually_elim
case (elim n)
hence "dist (h n a) (g n a) ≤ dist (f n a) (g n a)" for a
proof -
have "f n a ≤ h n a" "h n a ≤ g n a"
using elim unfolding less_eq_bfun_def by auto
thus ?thesis
using dist_real_def by fastforce
qed
thus ?case
unfolding dist_bfun.rep_eq
by (auto intro!: cSUP_mono bounded_imp_bdd_above simp: dist_real_def bounded_minus_comp bounded_abs_range)
qed
moreover have "eventually (λn. dist (h n) x ≤ dist (h n) (g n) + dist (g n) x) sequentially"
by (simp add: dist_triangle)
ultimately have 2: "eventually (λn. dist (h n) x ≤ dist (f n) (g n) + dist (g n) x) sequentially"
using eventually_elim2 by fastforce
have "(λn. dist (h n) x) ⇢ 0"
proof (subst tendsto_iff, safe)
fix e ::real
assume "e > 0"
hence 3: "∀⇩F xa in sequentially. dist (f xa) (g xa) + dist (g xa) x < e"
using 1
by (auto simp: tendsto_iff)
show "∀⇩F xa in sequentially. dist (dist (h xa) x) 0 < e"
by (rule eventually_mp[OF _ 3]) (fastforce intro: 2 eventually_mono)
qed
thus ?thesis
using tendsto_dist_iff
by auto
qed
subsection ‹Supremum›
lemma SUP_add_le:
assumes "X ≠ {}" "bounded (B ` X)" "bounded (A' ` X)"
shows "(⨆c ∈ X. (B :: 'a ⇒ real) c + A' c) ≤ (⨆b ∈ X. B b) + (⨆a ∈ X. A' a)"
using assms
by (auto simp: add_mono bounded_has_Sup(1) intro!: cSUP_least)+
lemma le_SUP_diff':
assumes ne: "X ≠ {}"
and bdd: "bounded (B ` X)" "bounded (A' ` X)"
and sup_le: "(⨆a ∈ X. (A' :: 'a ⇒ real) a) ≤ (⨆b ∈ X. B b)"
shows "(⨆b ∈ X. B b) - (⨆a ∈ X. (A' :: 'a ⇒ real) a) ≤ (⨆c ∈ X. B c - A' c)"
proof -
have "bounded ((λx. (B x - A' x)) ` X)"
using bdd bounded_minus_comp by blast
have "(⨆b ∈ X. B b) - (⨆a ∈ X. A' a) - e ≤ (⨆c ∈ X. B c - A' c)" if e: "e > 0" for e
proof -
obtain z where z: "(⨆b ∈ X. B b) - e≤ B z" "z ∈ X"
using e ne
by (subst less_cSupE[where ?y = "⨆ (B ` X) - e", where ?X = "B`X"]) fastforce+
hence " ((⨆a ∈ X. A' a) ≤ B z + e)"
using sup_le
by force
hence "A' z ≤ B z + e"
using ‹z ∈ X› bdd bounded_has_Sup(1) by fastforce
thus "(⨆b ∈ X. B b) - (⨆a ∈ X. A' a) -e ≤ (⨆c ∈ X. B c - A' c)"
using ‹bounded ((λx. B x - A' x) ` X)› z bounded_has_Sup(1)[OF bdd(2)]
by (subst cSUP_upper2[where x = z]) (fastforce intro!: bounded_imp_bdd_above)+
qed
thus ?thesis
by (subst field_le_epsilon) fastforce+
qed
lemma le_SUP_diff:
fixes A' :: "'a ⇒ real"
assumes "X ≠ {}" "bounded (B ` X)" "bounded (A' ` X)" "(⨆a ∈ X. A' a) ≤ (⨆b ∈ X. B b)"
shows "0 ≤ (⨆c ∈ X. B c - A' c)"
using assms
by (auto intro!: order.trans[OF _ le_SUP_diff'])
lemma bounded_SUP_mul[simp]:
"X ≠ {} ⟹ 0 ≤ l ⟹ bounded (f ` X) ⟹ (⨆x ∈ X. (l :: real) * f x) = (l * (⨆x ∈ X. f x))"
proof -
assume "X ≠ {} "" bounded (f ` X)" "0 ≤ l"
have "(⨆x ∈ X. ereal l * ereal (f x)) = (l * (⨆x ∈ X. ereal (f x)))"
by (simp add: Sup_ereal_mult_left' ‹0 ≤ l› ‹X ≠ {}›)
obtain b where "∀a ∈X. ¦f a¦ ≤ b"
using ‹bounded (f ` X)› bounded_real by auto
have "∀a ∈X. ¦ereal (f a)¦ ≤ b"
by (simp add: ‹∀a∈X. ¦f a¦ ≤ b›)
hence sup_leb: "(⨆a∈X. ¦ereal (f a)¦)≤ b"
by (simp add: SUP_least)
have "(⨆a∈X. ereal (f a)) ≤ (⨆a∈X. ¦ereal (f a)¦)"
by (auto intro: Complete_Lattices.SUP_mono')
moreover have "-(⨆a∈X. ereal (f a)) ≤ (⨆a∈X. ¦ereal (f a)¦)"
using ‹X ≠ {}›
by (auto intro!: Inf_less_eq cSUP_upper2 simp add: ereal_INF_uminus_eq[symmetric])
ultimately have "¦(⨆a∈X. ereal (f a))¦ ≤ (⨆a∈X. ¦ereal (f a)¦)"
by (auto intro: ereal_abs_leI)
hence "¦⨆a∈X. ereal (f a)¦ ≤ b"
using sup_leb by auto
hence "¦⨆a∈X. ereal (f a)¦ ≠ ∞"
by auto
hence "(⨆x ∈ X. ereal (f x)) = ereal (⨆x ∈ X. (f x))"
using ereal_SUP by metis
hence "(⨆x ∈ X. ereal (l * f x)) = ereal (l * (⨆x ∈ X. f x))"
using ‹(⨆x∈X. ereal l * ereal (f x)) = ereal l * (⨆x∈X. ereal (f x))› by auto
hence "ereal (⨆x ∈ X. l * f x) = ereal (l * (⨆x ∈ X. f x))"
by (simp add: ereal_SUP)
thus ?thesis
by auto
qed
lemma abs_cSUP_le[intro]:
"X ≠ {} ⟹ bounded (F ` X) ⟹ ¦⨆x ∈ X. (F x) :: real¦ ≤ (⨆x ∈ X. ¦F x¦)"
by (auto intro!: cSup_abs_le cSUP_upper2 bounded_imp_bdd_above simp: image_image[symmetric])
section ‹Least argmax›
definition "least_arg_max f P = (LEAST x. is_arg_max f P x)"
lemma least_arg_max_prop: "∃x::'a::wellorder. P x ⟹ finite {x. P x} ⟹ P (least_arg_max (f :: _ ⇒ real) P)"
unfolding least_arg_max_def
apply (rule LeastI2_ex)
using finite_is_arg_max[of "{x. P x}", where f = f]
by auto
lemma is_arg_max_apply_eq: "is_arg_max (f :: _ ⇒ _ :: linorder) P x ⟹ is_arg_max f P y ⟹ f x = f y"
by (auto simp: is_arg_max_def not_less dual_order.eq_iff)
lemma least_arg_max_apply:
assumes "is_arg_max (f :: _ ⇒ _ :: linorder) P (x::_::wellorder)"
shows "f (least_arg_max f P) = f x"
proof -
have "is_arg_max f P (least_arg_max f P)"
by (metis LeastI_ex assms least_arg_max_def)
thus ?thesis
using is_arg_max_apply_eq assms by metis
qed
lemma apply_arg_max_eq_max: "finite {x . P x} ⟹ is_arg_max (f :: _ ⇒ _ :: linorder) P x ⟹ f x = Max (f ` {x. P x})"
by (auto simp: is_arg_max_def intro!: Max_eqI[symmetric])
lemma apply_arg_max_eq_max': "finite X⟹ is_arg_max (f :: _ ⇒ _ :: linorder) (λx. x ∈ X) x ⟹ (MAX x ∈ X. f x) = f x"
by (auto simp: is_arg_max_linorder intro!: Max_eqI)
lemma least_arg_max_is_arg_max: "P ≠ {} ⟹ finite P ⟹ is_arg_max f (λx::_::wellorder. x ∈ P) (least_arg_max (f :: _ ⇒ real) (λx. x ∈ P))"
unfolding least_arg_max_def
apply (rule LeastI_ex)
using finite_is_arg_max
by auto
lemma is_arg_max_const: "is_arg_max (f :: _ ⇒ _ :: linorder) (λy. y = c) x ⟷ x = c"
unfolding is_arg_max_def
by auto
lemma least_arg_max_cong':
assumes "⋀x. is_arg_max f P x = is_arg_max g P x"
shows "least_arg_max f P = least_arg_max g P"
unfolding least_arg_max_def using assms by metis
end