Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/Archive-of-Formal-Proofs/thys/MDP-Rewards/   (Sammlung formaler Beweise Version 2026-5©)  Datei vom 31.4.2026 mit Größe 65 kB image not shown  

Quelle  MDP_reward.thy

  Sprache: Isabelle
 

(* Author: Maximilian Schäffeler *)

theory MDP_reward
  imports
    Bounded_Functions
    MDP_reward_Util
    Blinfun_Util
    MDP_disc
begin

section Markov Decision Processes with Rewards

locale MDP_reward = discrete_MDP A K
  for
    A and 
    K :: "'s ::countable × 'a ::countable ==> 's pmf" +
  fixes
    r :: "('s × 'a) ==> real" and
    l :: real
  assumes
    zero_le_disc [simp]: "0 l" and
    r_bounded: "bounded (range r)"
begin

text 
  extension to the basic MDPs is formalized with another locale.
  assumes the existence of a reward function @{term r} which takes a state-action pair to a real
 . We assume that the function is bounded @{prop r_bounded}.

 , we fix a discounting factor @{term l}, where @{term "0 l l < 1"}.
 


subsection Util
subsubsection Basic Properties of rewards
lemma r_bfun: "r bfun"
  using r_bounded
  by auto

lemma r_bounded': "bounded (r ` X)"
  by (auto intro: r_bounded bounded_subset)

definition "rM = (sa. r sa)"

lemma abs_r_le_rM"r sa rM"
  using bounded_norm_le_SUP_norm r_bounded rM_def by fastforce

lemma abs_rM_eq_rM [simp]: "rM = rM"
  using abs_r_le_rM by fastforce

lemma rM_nonneg"0 rM"
  using abs_rM_eq_rM by linarith

lemma measurable_r_nth [measurable]: "(λt. r (t !! i)) borel_measurable S"
  by measurable

lemma integrable_r_nth [simp]: "integrable (T p s) (λt. r (t !! i))"
  by (fastforce simp: bounded_iff intro: abs_r_le_rM)

lemma expectation_abs_r_le: "measure_pmf.expectation d (λa. r (s, a)) rM"
  using abs_r_le_rM
  by (fastforce intro!: measure_pmf.integral_le_const measure_pmf.integrable_const_bound)

lemma abs_exp_r_le: "measure_pmf.expectation d r rM"
  using abs_r_le_rM
  by (fastforce intro!: measure_pmf.integral_le_const order.trans[OF integral_abs_bound] measure_pmf.integrable_const_bound)

subsubsection Infinite disounted sums
lemma abs_disc_eq[simp]: "l ^ i * x = l ^ i * x"
  by (auto simp: abs_mult)

lemma norm_l_pow_eq[simp]: "norm (l^t *R F) = l^t * norm F"
  by auto

subsection Total Reward for Single Traces

abbreviation "ν_trace_fin t N i < N. l ^ i * r (t !! i)"
abbreviation "ν_trace t i. l ^ i * r (t !! i)"

lemma abs_ν_trace_fin_le: "ν_trace_fin t N (i < N. l^i * rM)"
  by (auto intro!: sum_mono order.trans[OF sum_abs] mult_left_mono abs_r_le_rM)

lemma measurable_suminf_reward[measurable]: "ν_trace borel_measurable S"
  by measurable

lemma integrable_ν_trace_fin: "integrable (T p s) (λt. ν_trace_fin t N)"
  by (fastforce simp: bounded_iff intro: abs_ν_trace_fin_le)


context 
  fixes p :: "('s, 'a) pol"
begin

subsection Expected Finite-Horizon Discounted Reward
definition "ν_fin n s = t. ν_trace_fin t n T p s"

lemma abs_ν_fin_le: "ν_fin N s (i<N. l^i * rM)"
  unfolding ν_fin_def
  using abs_ν_trace_fin_le
  by (fastforce intro!: prob_space.integral_le_const order_trans[OF integral_abs_bound])

lemma ν_fin_bfun: "(λs. ν_fin N s) bfun"
  by (auto intro!: abs_ν_fin_le)

lift_definition νb_fin :: "nat ==> 's ==>b real" is ν_fin
  using ν_fin_bfun .

lemma ν_fin_Suc[simp]: "ν_fin (Suc n) s = ν_fin n s + l ^ n * t. r (t !! n) T p s"
  by (simp add: ν_fin_def)

lemma ν_fin_zero[simp]: "ν_fin 0 s = 0"
  by (simp add: ν_fin_def)

lemma ν_fin_eq_Pn: "ν_fin n s = (i<n. l^i * measure_pmf.expectation (Pn' p s i) r)"
  by (induction n) (auto simp: Pn'_eq_T integral_distr)
end

subsection Expected Total Discounted Reward

definition "ν p s = lim (λn. ν_fin p n s)"

lemmas ν_eq_lim = ν_def

lemma ν_eq_Pn: "ν p s = (i. l^i * measure_pmf.expectation (Pn' p s i) r)"
  by (simp add: ν_fin_eq_Pn ν_eq_lim suminf_eq_lim)


subsection Reward of a Decision Rule
context 
  fixes d :: "('s, 'a) dec"
begin
abbreviation "r_dec s a. r (s, a) d s"

lemma abs_r_dec_le: "r_dec s rM"
  using expectation_abs_r_le integral_abs_bound order_trans by fast

lemma r_dec_eq_r_K0: "r_dec s = measure_pmf.expectation (K0' d s) r"
  by (simp add: K0'_def)

lemma r_dec_bfun: "r_dec bfun"
  using abs_r_dec_le by (auto intro!: bfun_normI)

lift_definition r_decb :: "'s ==>b real" is "r_dec"
  using r_dec_bfun .

declare r_decb.rep_eq[simp] bfun.Bfun_inverse[simp]

lemma norm_r_dec_le: "norm r_decb rM"
  by (simp add: abs_r_dec_le norm_bound)
end

lemma r_dec_det [simp]: "r_dec (mk_dec_det d) s = r (s, d s)"
  unfolding mk_dec_det_def by auto

subsection Transition Probability Matrix for MDPs

context
  fixes p :: "nat ==> ('s, 'a) dec"
begin
definition "PX n = push_exp (λs. Xn' (mk_markovian p) s n)"

lemma PX_0[simp]: "PX 0 = id"
  by (simp add: PX_def)

lemma PX_bounded_linear[simp]: "bounded_linear (PX t)"
  unfolding PX_def by simp

lemma norm_PX [simp]: "onorm (PX t) = 1"
  unfolding PX_def by simp

lemma norm_PX_apply[simp]: "norm (PX n x) norm x"
  using onorm[OF PX_bounded_linearby simp

lemma PX_bound_r"norm (PX t (r_decb (p t))) rM"
  using norm_PX_apply norm_r_dec_le order.trans by blast

lemma PX_bounded_r"bounded (range (λt. (PX t (r_decb (p t)))))"
  using PX_bound_r by (auto intro!: boundedI)

end

lemma ν_fin_elem: "ν_fin (mk_markovian p) n s = (i<n. l^i * PX p i (r_decb (p i)) s)"
  unfolding PX_def ν_fin_eq_Pn Pn'_markovian_eq_Xn'_bind measure_pmf_bind
  using measure_pmf_in_subprob_algebra abs_r_le_rM
  by (subst integral_bind) (auto simp: r_dec_eq_r_K0)

lemma νb_fin_eq_PXb_fin (mk_markovian p) n = (i<n. l^i *R PX p i (r_decb (p i)))"
  by (auto simp: ν_fin_elem sum_apply_bfun νb_fin.rep_eq)

lemma ν_fin_eq_PX"ν_fin (mk_markovian p) n = (i<n. l^i *R PX p i (r_decb (p i)))"
  by (metis νb_fin.rep_eq νb_fin_eq_PX)


text 
 {term "P1 d v"} defines for each state the expected value of @{term v}
  taking a single step in the MDP according to the decision rule @{term d}.
 


context
  fixes d :: "('s, 'a) dec"
begin
lift_definition P1 :: "('s ==>b real) ==>L ('s ==>b real)" is "push_exp (K_st d)"
  using push_exp_bounded_linear .

lemma P1_bfun_one [simp]:"P1 1 = 1"
  by (auto simp: P1.rep_eq)

lemma P1_pow_bfun_one [simp]: "(P1^^t) 1 = 1"
  by (induction t) auto

lemma P1_pow: "blinfun_apply (P1 ^^ n) = blinfun_apply P1 ^^ n"
  by (induction n) auto

lemma norm_P1 [simp]: "norm P1 = 1"
  by (simp add: norm_blinfun.rep_eq P1.rep_eq)
end

lemma PX_Suc"PX p (Suc n) v = P1 (p 0) ((PX (λn. p (Suc n)) n) v)"
  unfolding PX_def P1.rep_eq
  by (fastforce intro!: abs_le_norm_bfun integral_bind[where K = "count_space UNIV"]
      simp: measure_pmf_in_subprob_algebra measure_pmf_bind Suc_Xn'_markovian)

lemma PX_Suc': "PX p (Suc n) v = PX p n (P1 (p n) v)"
proof (induction n arbitrary: p)
  case 0
  thus ?case
    by (simp add: PX_Suc)
next
  case (Suc n)
  thus ?case 
    by (metis PX_Suc)
qed

lemma PX_const"PX (λ_. d) n = P1 d ^^ n"
  by (induction n) (auto simp add: P1_pow PX_Suc)

lemma PX_sconst"PX (λ_. p) n = P1 p ^^n"
  using PX_const.

lemma norm_P_n[simp]: "onorm (P1 d ^^ n) = 1"
  using norm_PX[of "λ_. d"by (auto simp: PX_sconst)

lemma norm_P1_pow [simp]: "norm (P1 d ^^ t) = 1"
  by (simp add: norm_blinfun.rep_eq)

lemma PX_Suc_n_elem"PX p n (P1 (p n) v) = PX p (Suc n) v"
  using PX_SucP1.rep_eq by auto

lemma P1_eq_PX_one"blinfun_apply (P1 (p 0)) = PX p 1"
  by (auto simp: PX_SucP1.rep_eq)


lemma P1_pos: "0 u ==> 0 P1 d u"
  by (auto simp: P1.rep_eq less_eq_bfun_def)

lemma P1_nonneg: "nonneg_blinfun (P1 d)"
  by (simp add: P1_pos nonneg_blinfun_def)

lemma P1_n_pos: "0 u ==> 0 (P1 d ^^ n) u"
  by (induction n) (auto simp: P1.rep_eq less_eq_bfun_def)

lemma P1_n_nonneg: "nonneg_blinfun (P1 d ^^ n)"
  by (simp add: P1_n_pos nonneg_blinfun_def)

lemma P1_n_disc_pos: "0 u ==> 0 (l^n *R P1 d ^^n) u"
  by (auto simp: P1_n_pos scaleR_nonneg_nonneg blinfun.scaleR_left)

lemma P1_sum_pos: "0 u ==> 0 (tn. l^t *R (P1 d ^^ t)) u"
  using P1_n_pos P1_pos
  by (induction n) (auto simp: blinfun.add_left blinfun.scaleR_left scaleR_nonneg_nonneg)

lemma P1_sum_ge: 
  assumes "0 u" 
  shows "u (tn. l^t *R P1 d ^^t) u"
  using P1_n_disc_pos[OF assms, of "Suc _"]
  by (induction n) (auto intro: add_increasing2 simp add: blinfun.add_left)


subsection The Bellman Operator
definition "L d v r_decb d + l *R P1 d v"

lemma norm_L_le: "norm (L d v) rM + l * norm v"
  using norm_blinfun[of "P1 d"] norm_P1 norm_r_dec_le
  by (auto intro!: norm_add_rule_thm mult_left_mono simp: L_def)

lemma abs_L_le: "L d v s rM + l * norm v"
  using order.trans[OF norm_le_norm_bfun norm_L_le] by auto

subsubsection Bellman Operator for Single Actions
abbreviation "La a v s r (s, a) + l * measure_pmf.expectation (K (s,a)) v"

lemma La_le:
  fixes v :: "'s ==>b real"
  shows "La a v s rM + l * norm v"
  using abs_r_le_rM
  by (fastforce intro: order_trans[OF abs_triangle_ineq] order_trans[OF integral_abs_bound]  
      add_mono mult_mono measure_pmf.integral_le_const abs_le_norm_bfun 
      simp: abs_mult)

lemma La_bounded:
  "bounded (range (λa. La a (apply_bfun v) s))"
  using La_le by (auto intro!: boundedI)

lemma La_int
  fixes d :: "'a pmf" and v :: "'s ==>b real"
  shows "(a. La a v s d) = (a. r (s, a) d) + l * a. s'. v s' K (s, a) d"
proof (subst Bochner_Integration.integral_add)
  show "integrable d (λa. r (s, a))"
    using abs_r_le_rM by (fastforce intro!: bounded_integrable simp: bounded_iff)
  show "integrable d (λa. l * s'. v s' K (s, a))"
    by (intro bounded_integrable) 
      (auto intro!: mult_mono order_trans[OF integral_abs_bound] boundedI[of _ "l * norm v"]
        measure_pmf.integral_le_const simp: abs_le_norm_bfun abs_mult)
qed auto

lemma L_eq_La"L d v s = measure_pmf.expectation (d s) (λa. La a v s)"
  unfolding La_int L_def K_st_def P1.rep_eq
  by (auto simp: measure_pmf_bind integral_measure_pmf_bind[where B = "norm v"] abs_le_norm_bfun)

lemma L_eq_La_det"L (mk_dec_det d) v s = La (d s) v s"
  by (auto simp: L_eq_La mk_dec_det_def)

lemma La_eq_L"measure_pmf.expectation p (λa. La a (apply_bfun v) s) =
  L (λt. if t = s then p else return_pmf (SOME a. a A t)) v s"
  unfolding L_eq_La by auto

lemma L_le: "L d v s rM + l * norm v"
  unfolding L_def
  using norm_P1 norm_blinfun[of "(P1 d)"] abs_r_dec_le
  by (fastforce intro: order_trans[OF le_norm_bfun] add_mono mult_left_mono dest: abs_le_D1)

lemma La_le': "La a (apply_bfun v) s rM + l * norm v"
  using La_le abs_le_D1 by blast


subsection Optimality Equations

definition "L (v :: 's ==>b real) s = (d DR. L d v s)"

lemma L_bfun: "L v bfun"
  unfolding L_def using abs_L_le ex_dec by (fastforce intro!: cSup_abs_le bfun_normI)

lift_definition Lb :: "('s ==>b real) ==> 's ==>b real" is L
  using L_bfun .

lemma L_bounded[simp, intro]: "bounded (range (λp. L p v s))"
  using abs_L_le by (auto intro!: boundedI)

lemma L_bounded'[simp, intro]: "bounded ((λp. L p v s) ` X)"
  by (auto intro: bounded_subset)

lemma L_bdd_above[simp, intro]: "bdd_above ((λp. L p v s) ` X)"
  by (auto intro: bounded_imp_bdd_above)

lemma L_le_Lb"is_dec d ==> L d v Lb v"
  by (fastforce simp: Lb.rep_eq L_def intro!: cSUP_upper)

subsubsection Equivalences involving @{const Lb}

lemma SUP_step_MR_eq:
  "L v s = (pa {pa. set_pmf pa A s}. (a. La a v s measure_pmf pa))"
  unfolding L_def
proof (intro antisym)
  show "(dDR. L d v s) (pa {pa. set_pmf pa A s}. a. La a v s measure_pmf pa)"
  proof (rule cSUP_mono)
    show "DR {}"
      using DR_ne .
  next show "bdd_above ((λpa. a. La a v s measure_pmf pa) ` {pa. set_pmf pa A s})"
      using La_bounded La_le
      by (auto intro!: order_trans[OF integral_abs_bound] 
          bounded_imp_bdd_above boundedI[where B = "rM + l * norm v"
          measure_pmf.integral_le_const bounded_integrable)
  next show "m{pa. set_pmf pa A s}. L n v s a. La a v s measure_pmf m" if "n DR" for n
      using that
      by (fastforce simp: L_eq_La La_int is_dec_def)
  qed
next
  have aux: "{pa. set_pmf pa A s} {}"
    using DR_ne is_dec_def by auto
  show "(pa{pa. set_pmf pa A s}. a. La a v s measure_pmf pa) (dDR. L d v s)"
  proof (intro cSUP_least[OF aux] cSUP_upper2)
    fix n 
    assume h: "n {pa. set_pmf pa A s}"
    let ?p = "(λs'. if s = s' then n else SOME a. set_pmf a A s')"
    have aux: "a. set_pmf a A sa" for sa
      using ex_dec is_dec_def by blast
    show "?p DR"
      unfolding is_dec_def using h someI_ex[OF aux] by auto
    thus "(a. La a v s n) L ?p v s"
      by (auto simp: L_eq_La)
    show "bdd_above ((λd. L d v s) ` DR)"
      by (fastforce intro!: bounded_imp_bdd_above simp: bounded_def)
  next
  qed
qed

lemma Lb_eq_SUP_La"Lb v s = (p {p. set_pmf p A s}. a. La a v s measure_pmf p)"
  using SUP_step_MR_eq Lb.rep_eq by presburger

lemma SUP_step_det_eq: "(d DD. L (mk_dec_det d) v s) = (a A s. La a v s)"
proof (intro antisym cSUP_mono)
  show "bdd_above ((λa. La a v s) ` A s)"
    using La_bounded by (fastforce intro!: bounded_imp_bdd_above simp: bounded_def)
  show "bdd_above ((λd. L (mk_dec_det d) v s) ` DD)"
    by (auto intro!: bounded_imp_bdd_above boundedI abs_L_le)
  show "mA s. L (mk_dec_det n) v s La m v s" if "n DD" for n
    using that is_dec_det_def by (auto simp: L_eq_La_det intro: bexI[of _ "n s"])
  show "mDD. La n v s L (mk_dec_det m) v s" if "n A s" for n
    using that A_ne
    by (fastforce simp: L_eq_La_det is_dec_det_def some_in_eq
        intro!: bexI[of _ "λs'. if s = s' then _ else SOME a. a A s'"])
qed (auto simp: A_ne)

lemma integrable_La"integrable (measure_pmf x) (λa. La a (apply_bfun v) s)"
proof (intro Bochner_Integration.integrable_add integrable_mult_right)
  show "integrable (measure_pmf x) (λx. r (s, x))"
    using abs_r_le_rM 
    by (auto intro: measure_pmf.integrable_const_bound[of _ "rM"])
next
  show "integrable (measure_pmf x) (λx. measure_pmf.expectation (K (s, x)) v)"
    by (auto intro!: bounded_integrable boundedI order.trans[OF integral_abs_bound] 
        measure_pmf.integral_le_const abs_le_norm_bfun)
qed

lemma SUP_La_eq_det:
  fixes v :: "'s ==>b real"
  shows "(p{p. set_pmf p A s}. a. La a v s measure_pmf p) = (aA s. La a v s)"
proof (intro antisym)
  show "(pa{pa. set_pmf pa A s}. measure_pmf.expectation pa (λa. La a v s))
     (aA s. La a v s)"
    using ex_dec is_dec_def integrable_La A_ne La_bounded
    by (fastforce intro: bounded_range_subset intro!: cSUP_least lemma_4_3_1)
  show "(aA s. La a v s) (p{p. set_pmf p A s}. a. La a v s measure_pmf p)"
    unfolding SUP_step_MR_eq[symmetric] SUP_step_det_eq[symmetric] L_def
    using ex_dec_det by (fastforce intro!: cSUP_mono)
qed

lemma L_eq_SUP_det: "L v s = (d DD. L (mk_dec_det d) v s)"
  using SUP_step_MR_eq SUP_step_det_eq SUP_La_eq_det by auto

lemma Lb_eq_SUP_det"Lb v s = (d DD. L (mk_dec_det d) v s)"
  using L_eq_SUP_det unfolding Lb.rep_eq by auto


subsection Monotonicity

lemma PX_mono[intro]: "a b ==> PX p n a PX p n b"
  by (fastforce simp: PX_def intro: integral_mono)

lemma P1_mono[intro]: "a b ==> P1 p a P1 p b"
  using P1_nonneg by auto

lemma L_mono[intro]: "u v ==> L d u L d v"
  unfolding L_def by (auto intro: scaleR_left_mono)

lemma Lb_mono[intro]: "u v ==> Lb u Lb v"
  using  ex_dec L_mono[of u v] 
  by (fastforce intro!: cSUP_mono simp: Lb.rep_eq L_def)

lemma step_mono:
  assumes "Lb v v" "d DR"
  shows "L d v v"
  using assms L_le_Lb order.trans by blast

lemma step_mono_elem_det:
  assumes "v Lb v" "e > 0"
  shows "dDD. v L (mk_dec_det d) v + e *R 1"
proof -
  have "v s (aA s. La a v s)" for s
    using SUP_step_det_eq Lb_eq_SUP_det assms(1by fastforce
  hence "aA s. v s - e < La a v s" for s
    using A_ne La_le'
    by (subst less_cSUP_iff[symmetric]) (fastforce simp: assms add_strict_increasing algebra_simps intro!: bdd_above.I2)+
  hence aux: "aA s. v s La a v s + e" for s
    by (auto simp: diff_less_eq intro: less_imp_le)
  then obtain d where "is_dec_det d" "v s L (mk_dec_det d) v s + e" for s
    by (metis L_eq_La_det is_dec_det_def)
  thus ?thesis
    by fastforce
qed

lemma step_mono_elem:
  assumes "v Lb v" "e > 0"
  shows "dDR. v L d v + e *R 1"
  using assms step_mono_elem_det by blast

lemma PX_L_le:
  assumes "Lb v v" "p ΠMR"
  shows "PX p n (L (p n) v) PX p n v"
  using assms step_mono by auto

end

locale MDP_reward_disc = MDP_reward A K r l
  for
    A and 
    K :: "'s ::countable × 'a ::countable ==> 's pmf" and
    r l +
  assumes
    disc_lt_one [simp]: "l < 1"
begin

definition "is_opt_act v s = is_arg_max (λa. La a v s) (λa. a A s)"
abbreviation "opt_acts v s {a. is_opt_act v s a}"

lemma summable_disc [intro, simp]: "summable (λi. l ^ i * x)"
  by (simp add: mult.commute)

lemma summable_r_disc[intro, simp]:
  "summable (λi. l ^ i * r (sa i))"
  "summable (λi. l ^ i * r (sa i))"
  "summable (λi. l ^ i * r (sa i))"
proof -
  show "summable (λi. l ^ i * r (sa i))"
    using abs_r_le_rM
    by (fastforce intro!: mult_left_mono summable_comparison_test'[OF summable_disc])
  thus "summable (λi. l ^ i * r (sa i))" "summable (λi. l ^ i * r (sa i))"
    by (auto intro: summable_rabs_cancel)
qed

lemma summable_norm_disc_I[intro]:
  assumes "summable (λt. (l^t * norm F))"
  shows "summable (λt. norm (l^t *R F))"
  using assms by auto

lemma summable_norm_disc_I'[intro]:
  assumes "summable (λt. (l^t * norm (F t)))"
  shows "summable (λt. norm (l^t *R F t))"
  using assms by auto

lemma summable_discI [intro]:
  assumes "bounded (range F)"
  shows "summable (λt. l^t * norm (F t))"
proof -
  obtain b where "norm (F x) b" for x
    using assms by (auto simp: bounded_iff)
  thus ?thesis
    using Abel_lemma[of l 1 F b] by (auto simp: mult.commute)
qed

lemma summable_disc_reward [intro]:
  assumes "bounded (range (F :: nat ==> 'b :: banach))"
  shows "summable (λt. l^t *R (F t))"
  using assms by (auto intro: summable_norm_cancel)

lemma summable_norm_bfun_disc: "summable (λt. l^t * norm (apply_bfun f t))"
  using norm_le_norm_bfun
  by (auto simp: mult.commute[of "l^_"] intro!: Abel_lemma[of _ 1 _ "norm f"])

lemma summable_bfun_disc [simp]: "summable (λt. l^t * (apply_bfun f t))"
proof -
  have "norm (l^t * apply_bfun f t) = l^t * norm (apply_bfun f t)" for t
    by (auto simp: abs_mult)
  hence "summable (λt. norm (l^t * (apply_bfun f t)))"
    by (auto simp only: abs_mult)
  thus ?thesis
    by (auto intro: summable_norm_cancel)
qed

lemma norm_bfun_disc_le: "norm f B ==> (x. l^x * norm (apply_bfun f x)) (x. l^x * B)"
  by (fastforce intro!: suminf_le mult_left_mono norm_le_norm_bfun intro: order.trans)

lemma norm_bfun_disc_le': "norm f B ==> (x. l^x * (apply_bfun f x)) (x. l^x * B)"
  by (auto simp: mult_left_mono intro!: suminf_le order.trans[OF _ norm_bfun_disc_le])

lemma sum_disc_lim_l: "(x. l^x * B) = B /(1-l)"
  by (simp add: suminf_mult2[symmetric] summable_geometric suminf_geometric[of l])

lemma sum_disc_bound: "(x. l^x * apply_bfun f x) (norm f) /(1-l)"
  using norm_bfun_disc_le' sum_disc_lim  by auto

lemma sum_disc_bound':
  fixes f :: "nat ==> 'b ==>b real"
  assumes h: "n. norm (f n) B"
  shows "norm (x. l^x *R f x) B /(1-l)"
proof -
  have "norm (x. l^x *R f x) (x. norm (l^x *R f x))"
    using h
    by (fastforce intro!: boundedI summable_norm)
  also have " (x. l^x * B)"
    using h
    by (auto intro!: suminf_le boundedI simp: mult_mono')
  also have " = B /(1-l)"
    by (simp add: sum_disc_lim)
  finally show "norm (x. l^x *R f x) B /(1-l)" .
qed


lemma abs_ν_trace_le: "ν_trace t (i. l ^ i * rM)"
  by (auto intro!: abs_r_le_rM mult_left_mono order_trans[OF summable_rabs] suminf_le)

lemma integrable_ν_trace: "integrable (T p s) ν_trace"
  by (fastforce simp: bounded_iff intro: abs_ν_trace_le)

context 
  fixes p :: "('s, 'a) pol"
begin

lemma ν_eq_ν_trace: "ν p s = t. ν_trace t T p s"
proof -
  have "(λn. ν_fin p n s) <---- t. ν_trace t T p s"
    unfolding ν_fin_def
  proof(intro integral_dominated_convergence)
    show "AE x in T p s. ν_trace_fin x <---- ν_trace x"
      using summable_LIMSEQ by blast
  next
    have "(i<N. l ^ i * rM) (N. l ^ N * rM)" for N
      by (auto intro: sum_le_suminf simp: rM_nonneg)
    thus "AE x in T p s. norm (ν_trace_fin x N) (N. l ^ N * rM)" for N
      using order_trans[OF abs_ν_trace_fin_le] by fastforce
  qed auto
  thus ?thesis
    using ν_eq_lim limI by fastforce
qed

lemma abs_ν_le: "ν p s (i. l^i * rM)"
  unfolding ν_eq_Pn
  using abs_exp_r_le
  by (fastforce intro!: order.trans[OF summable_rabs] suminf_le summable_comparison_test'[OF summable_disc] mult_left_mono)

lemma ν_le: "ν p s (i. l^i * rM)"
  by (auto intro: abs_ν_le abs_le_D1)

(* 6.1.2 in Puterman *)
lemma ν_bfun: "ν p bfun"
  by (auto intro!: abs_ν_le)

lift_definition νb :: "'s ==>b real" is "ν p"
  using ν_bfun by blast

lemma norm_ν_le: "norm νb rM / (1-l)"
  using abs_ν_le sum_disc_lim
  by (auto simp: νb.rep_eq norm_bfun_def' intro: cSUP_least)
end

lemma ν_as_markovian: "ν (mk_markovian (as_markovian p (return_pmf s))) s = ν p s"
  by (auto simp: ν_eq_Pn Pn_as_markovian_eq Pn'_def)

lemma νb_as_markovianb (mk_markovian (as_markovian p (return_pmf s))) s = νb p s"
  using ν_as_markovian by (auto simp: νb.rep_eq)

subsection Optimal Reward

definition "ν_MD s p ΠMD. ν (mk_markovian_det p) s"
definition "ν_opt s p ΠHR. ν p s"

lemma ν_opt_bfun: "ν_opt bfun"
  using abs_ν_le policies_ne 
  by (fastforce simp: ν_opt_def intro!: order_trans[OF cSup_abs_le] bfun_normI)

lift_definition νb_opt :: "'s ==>b real" is ν_opt
  using ν_opt_bfun .

lemma νb_opt_eqb_opt s = (p ΠHR. νb p s)"
  using νb.rep_eq νb_opt.rep_eq ν_opt_def by presburger

lemma ν_le_ν_opt [intro]:
  assumes "is_policy p"
  shows "ν p s ν_opt s"
  unfolding ν_opt_def using abs_ν_le assms
  by (force intro: cSUP_upper intro!: bounded_imp_bdd_above boundedI)

lemma νb_le_opt [intro]: "p ΠHR ==> νb p νb_opt"
  using ν_le by (fastforce simp: νb.rep_eq νb_opt.rep_eq)

lemma νb_le_opt_MD [intro]: "p ΠMD ==> νb (mk_markovian_det p) νb_opt"
  by (auto simp: mk_markovian_det_def is_dec_det_def is_dec_def is_policy_def)

lemma νb_le_opt_DD [intro]: "is_dec_det d ==> νb (mk_stationary_det d) νb_opt"
  by (auto simp add: is_policy_def mk_markovian_def)

lemma νb_le_opt_DR [intro]: "is_dec d ==> νb (mk_stationary d) νb_opt"
  by (auto simp add: is_policy_def mk_markovian_def)

lemma νb_opt_eq_MRb_opt s = (p ΠMR. νb (mk_markovian p) s)"
proof (rule antisym)
  show b_opt s (pΠMR. νb (mk_markovian p) s)"
    unfolding νb_opt_eq
  proof (rule cSUP_mono)
    show HR {}"
      using policies_ne by simp
    show "bdd_above ((λp. νb (mk_markovian p) s) ` ΠMR)"
      by (auto intro!: boundedI bounded_imp_bdd_above abs_ν_le simp: νb.rep_eq) 
    show "n ΠHR ==> mΠMR. νb n s νb (mk_markovian m) s" for n
      using is_ΠMR_as_markovian by (subst νb_as_markovian[symmetric]) fastforce     
  qed
  show "(pΠMR. νb (mk_markovian p) s) νb_opt s"
    using ΠMR_ne ΠMR_imp_policies 
    by (auto intro!: cSUP_mono bounded_imp_bdd_above boundedI abs_ν_le simp: νb_opt_eq  νb.rep_eq)
qed

lemma summable_norm_disc_reward'[simp]: "summable (λt. l^t * norm (PX p t (r_decb (p t))))"
  using PX_bounded_r by auto

lemma summable_disc_reward_PX [simp]: "summable (λt. l^t *R PX p t (r_decb (p t)))"
  using summable_disc_reward PX_bounded_r by blast

lemma disc_reward_tendsto:
  "(λn. t<n. l^t *R PX p t (r_decb (p t))) <---- (t. l^t *R PX p t (r_decb (p t)))"
  by (simp add: summable_LIMSEQ)

lemma ν_eq_PX"ν (mk_markovian p) = (i. l^i *R PX p i (r_decb (p i)))"
proof -
  have "ν (mk_markovian p) s = (i. l^i * PX p i (r_decb (p i)) s)" for s
    unfolding νb.rep_eq PX_def ν_eq_Pn Pn'_markovian_eq_Xn'_bind measure_pmf_bind
    using measure_pmf_in_subprob_algebra abs_r_le_rM
    by (subst integral_bind) (auto simp: r_dec_eq_r_K0)
  thus ?thesis
    by (auto simp: suminf_apply_bfun)
qed

lemma νb_eq_PXb (mk_markovian p) = (i. l^i *R PX p i (r_decb (p i)))"
  by (auto simp: ν_eq_PX νb.rep_eq)

lemma νb_fin_tendsto_νb"(νb_fin (mk_markovian p)) <---- νb (mk_markovian p)"
  using disc_reward_tendsto νb_eq_PX νb_fin_eq_PX
  by presburger

lemma norm_P1_l_less: "norm (l *R P1 d) < 1"
  by auto
lemma disc_P1_tendsto: "(λn. (tn. l^t *R P1 d ^^t)) <---- (t. l^t *R P1 d ^^t)"
  by (fastforce simp: bounded_iff intro: summable_LIMSEQ')

lemma disc_P1_lim: "lim (λn. (tn. l^t *R P1 d ^^ t)) = (t. l^t *R P1 d ^^t)"
  using limI disc_P1_tendsto
  by blast

lemma convergent_disc_P1"convergent (λn. (tn. l^t *R P1 d ^^t))"
  using convergentI disc_P1_tendsto 
  by blast

lemma P1_suminf_ge: 
  assumes "0 u" shows "u (t. l^t *R P1 d ^^t) u"
proof -
  have aux: "x. (λn. (tn. l^t *R P1 d ^^t) u x) <---- (t. l^t *R P1 d ^^t) u x"
    using bfun_tendsto_apply_bfun disc_P1_lim lim_blinfun_apply[OF convergent_disc_P1
    by fastforce
  have "n. u (tn. l^t *R P1 d ^^t) u"
    using P1_sum_ge[OF assms] by auto
  thus ?thesis
    by (auto intro!: LIMSEQ_le_const[OF aux])
qed

lemma P1_suminf_pos: 
  assumes "0 u" 
  shows "0 (t. l^t *R P1 d ^^t) u"
  using P1_suminf_ge[of u] assms order.trans by auto

lemma lemma_6_1_2_b:
  assumes "v u"
  shows "(t. l^t *R P1 d ^^t) v (t. l^t *R P1 d ^^t) u"
proof -
  have "0 (n. l ^ n *R P1 d ^^ n) (u - v)"
    using P1_suminf_pos assms by simp
  thus ?thesis
    by (simp add: blinfun.diff_right)
qed

lemma ν_stationary: b (mk_stationary d) = (t. l^t *R (P1 d ^^ t)) (r_decb d)"
proof -
  have b (mk_stationary d) = (t. (l ^ t *R (P1 d ^^ t)) (r_decb d))"
    by (simp add: νb_eq_PX scaleR_blinfun.rep_eq PX_sconst)
  also have "... = (t. (l ^ t *R (P1 d ^^ t))) (r_decb d)"
    by (subst bounded_linear.suminf[where f = "λx. blinfun_apply x (r_decb d)"]) 
      (auto intro!: bounded_linear.suminf boundedI)
  finally show ?thesis .
qed

lemma ν_stationary_inv: b (mk_stationary d) = invL (id_blinfun - l *R P1 d) (r_decb d)"
  by (auto simp: ν_stationary invL_inf_sum blincomp_scaleR_right)


text The value of a markovian policy can be expressed in terms of @{const L}.

lemma ν_step: b (mk_markovian p) = L (p 0) (νb (mk_markovian (λn. p (Suc n))))"
proof -
  have s: "summable (λt. l^t *R (PX p (Suc t) (r_decb (p (Suc t)))))"
    using PX_bound_r by (auto intro!: boundedI[of _ rM])
  have 
    b (mk_markovian p) = r_decb (p 0) + (t. l ^ (Suc t) *R PX p (Suc t) (r_decb (p (Suc t))))"
    by (subst suminf_split_head) (auto simp: νb_eq_PX)
  also have 
    " = r_decb (p 0) + l *R (t. P1 (p 0) (l^t *R PX (λn. p (Suc n)) t (r_decb (p (Suc t)))))"
    using suminf_scaleR_right[OF s] by (auto simp: PX_Suc blinfun.scaleR_right)
  also have 
    " = L (p 0) (νb (mk_markovian (λn. p (Suc n))))"
    using blinfun.bounded_linear_right bounded_linear.suminf[of "blinfun_apply (P1 (p 0))"]
    by (fastforce simp add: νb_eq_PX L_def)
  finally show ?thesis .
qed

lemma L_ν_fixb (mk_stationary d) = L d (νb (mk_stationary d))"
  using ν_step .

lemma L_fix_ν:
  assumes "L p v = v"
  shows "v = νb (mk_stationary p)"
proof -
  have "r_decb p = (id_blinfun - l *R P1 p) v"
    using assms by (auto simp: eq_diff_eq L_def blinfun.diff_left blinfun.scaleR_left)
  hence "v = (t. (l *R P1 p)^^t) (r_decb p)"
    using inv_norm_le'(2)[OF norm_P1_l_less] by auto
  thus "v = νb (mk_stationary p)"
    by (auto simp: ν_stationary blincomp_scaleR_right)
qed

lemma L_ν_fix_iff: "L d v = v v = νb (mk_stationary d)"
  using L_fix_ν L_ν_fix by auto

subsection Properties of Solutions of the Optimality Equations

abbreviation "Pd p n v l^n *R PX p n v"

lemma Pd_lim"(λn. (Pd p n v)) <---- 0"
proof -
  have "(λn. l^n * norm v) <---- 0"
    by (auto intro!: tendsto_eq_intros)
  moreover have "norm (Pd p n v) l^n * norm v" for p n
    by (simp add: mult_mono')
  ultimately have "(λn. norm (Pd p n v)) <---- 0" for p
    by (auto simp: Lim_transform_bound[where g = "λn. (l^n * norm v)"])
  thus "(λn. (Pd p n v)) <---- 0" for p
    using tendsto_norm_zero_cancel by fast
qed



(* 6.2.2 a) in Puterman *)

lemma L_dec_ge_opt:
  assumes "Lb v v"
  shows b_opt v"
proof -
  have b (mk_markovian p) v" if "p ΠMR" for p
  proof -
    let ?p = "mk_markovian p"
    have aux: b_fin ?p n + l^n *R PX p n v v" for n
    proof (induction n)
      case (Suc n)
      have "PX p n (r_decb (p n)) + l *R (PX p (Suc n) v) PX p n v"
        using PX_L_le assms that by (simp add: PX_Suc_n_elem L_def linear_simps)
      hence b_fin ?p (n + 1) + l^(n + 1) *R (PX p (n + 1) v) νb_fin ?p n + l^n *R (PX p n v)"
        by (auto simp del: scaleR_scaleR intro: scaleR_left_mono simp: νb_fin_eq_PX 
            mult.commute[of l] scaleR_add_right[symmetric] scaleR_scaleR[symmetric])
      also have " v"
        using Suc.IH by (auto simp: νb_fin_eq_PX)
      finally show ?case
        by auto
    qed (auto simp: νb_fin_eq_PX)
    have 1"(λn. (νb_fin ?p n + Pd p n v) s) <---- νb ?p s" for s
      using bfun_tendsto_apply_bfun Limits.tendsto_add[OF νb_fin_tendsto_νb Pd_limby fastforce
    have b ?p s v s" for s
      using that aux assms by (fastforce intro!: lim_mono[OF _ 1, of  _ _ "λn. v s"])
    thus ?thesis
      using that by blast
  qed
  thus ?thesis
    using policies_ne by (fastforce simp: is_policy_def νb_opt_eq_MR intro!: cSUP_least)
qed

lemma L_inc_le_opt:
  assumes "v Lb v"
  shows "v νb_opt"
proof -
  have le_elem: "v s νb_opt s + (e/(1-l))" if "e > 0" for s e
  proof -
    obtain d where "d DR" and hd: "v L d v + e *R 1"
      using assms step_mono_elem e > 0 by blast
    let ?Pinf = "(i. l^i *R P1 d^^i)"
    have "v r_decb d + l *R (P1 d) v + e *R 1"
      using hd L_def by fastforce
    hence "(id_blinfun - l *R P1 d) v r_decb d + e *R 1"
      by (auto simp: blinfun.diff_left blinfun.scaleR_left algebra_simps)
    hence "?Pinf ((id_blinfun - l *R P1 d) v) ?Pinf (r_decb d + e *R 1)"
      using lemma_6_1_2_b P1_def hd by auto
    hence "v ?Pinf (r_decb d + e *R 1)"
      using inv_norm_le'(2)[of "l *R P1 d"by (auto simp: blincomp_scaleR_right)
    also have " = νb (mk_stationary d) + e *R ?Pinf 1"
      by (simp add: ν_stationary blinfun.add_right blinfun.scaleR_right)
    also have " = νb (mk_stationary d) + e *R (i. (l^i *R ((P1 d^^i))) 1)"
      using convergent_disc_P1 
      by (auto simp: summable_iff_convergent' bounded_linear.suminf[of "λx. blinfun_apply x 1"])
    also have " = νb (mk_stationary d) + e *R (i. (l^i *R 1))"
      by (auto simp: scaleR_blinfun.rep_eq)
    also have " b (mk_stationary d) + (e / (1-l)) *R 1)"
      by (auto simp: bounded_linear.suminf[symmetric, where f = "λx. x *R 1"
          suminf_geometric bounded_linear_scaleR_left summable_geometric)
    finally have "v s b (mk_stationary d) + (e/(1-l)) *R 1) s"
      by auto
    thus "v s νb_opt s + (e/(1-l))"
      using d DR νb_le_opt
      by (auto simp: is_policy_def mk_markovian_def less_eq_bfun_def intro: order_trans)
  qed
  have "v s νb_opt s + e" if "e > 0" for s e
  proof -
    have "e * (1 - l) > 0"
      by (simp add: 0 < e)
    thus "v s νb_opt s + e"
      using disc_lt_one that le_elem by (fastforce split: if_splits)
  qed
  thus ?thesis
    by (fastforce intro: field_le_epsilon)
qed    
lemma L_fix_imp_opt:
  assumes "v = Lb v"
  shows "v = νb_opt"
  using assms dual_order.antisym[OF L_dec_ge_opt L_inc_le_opt] by auto

lemma bounded_P: "bounded (P1 ` X)"
  by (auto simp: bounded_iff)

subsection Solutions to the Optimality Equation
subsubsection @{const Lb} and @{const L} are Contraction Mappings
declare bounded_apply_blinfun[intro] bounded_apply_bfun'[intro]

lemma contraction_L"dist (Lb v) (Lb u) l * dist v u"
proof -
  have "dist (Lb v s) (Lb u s) l * dist v u" if "Lb u s Lb v s" for s v u
  proof -
    have "dist (Lb v s) (Lb u s) (d DR. L d v s - L d u s)"
      using ex_dec that by (fastforce intro!: le_SUP_diff' simp: dist_real_def Lb.rep_eq L_def)
    also have " = (d DR. l * (P1 d (v - u) s))"
      by (auto simp: L_def right_diff_distrib blinfun.diff_right)
    also have " = l * (d DR. P1 d (v - u) s)"
      using DR_ne bounded_P by (fastforce intro: bounded_SUP_mul)
    also have " l * norm (d DR. P1 d (v - u) s)"
      by (simp add: mult_left_mono)
    also have " l * (d DR. norm ((P1 d (v - u)) s))"
    proof -
      have "bounded ((λx. norm ((P1 x (v - u)) s)) ` DR)"
        using bounded_apply_bfun' bounded_P bounded_apply_blinfun bounded_norm_comp by metis
      thus ?thesis
        using DR_ne ex_dec bounded_norm_comp by (fastforce intro!: mult_left_mono)
    qed
    also have " l * (p DR. norm (P1 p ((v - u))))"
      using DR_ne abs_le_norm_bfun bounded_P
      by (fastforce simp: bounded_norm_comp intro!: bounded_imp_bdd_above mult_left_mono cSUP_mono)
    also have " l * (p DR. norm ((v - u)))"
      using norm_push_exp_le_norm DR_ne
      by (fastforce simp: P1.rep_eq intro!: mult_left_mono cSUP_mono)
    also have " = l * dist v u"
      by (auto simp: dist_norm)
    finally show ?thesis .
  qed
  hence "Lb u s Lb v s ==> dist (Lb v s) (Lb u s) l * dist v u" 
    "Lb v s Lb u s ==> dist (Lb v s) (Lb u s) l * dist v u" for u v s
    by (fastforce simp: dist_commute)+
  thus ?thesis
    using linear[of "Lb u _"by (fastforce intro: dist_bound)
qed

lemma is_contraction_L"is_contraction Lb"
  using contraction_L zero_le_disc disc_lt_one unfolding is_contraction_def by blast

lemma contraction_L: "dist (L p v) (L p u) l * dist v u"
proof -
  have aux: "L p v s - L p u s l * dist v u" if lea: "L p v s L p u s" for v s u
  proof -
    have "L p v s - L p u s = (l *R (P1 p v - P1 p u)) s"
      by (simp add: L_def scale_right_diff_distrib)
    also have " l * norm (P1 p (v - u) s)"
      by (auto simp: blinfun.diff_right intro!: mult_left_mono)
    also have " l * norm (P1 p (v - u))"
      using abs_le_norm_bfun by (auto intro!: mult_left_mono)
    also have " l * dist v u"
      by (simp add: P1.rep_eq mult_left_mono norm_push_exp_le_norm dist_norm)
    finally show ?thesis
      by auto
  qed
  have "dist (L p v s) (L p u s) l * dist v u" for v s u
    using aux[of v _ u] aux[of u _ v]
    by (cases "L p v s L p u s") (auto simp: dist_real_def dist_commute)
  thus "dist (L p v) (L p u) l * dist v u"
    by (simp add: dist_bound)
qed

lemma is_contraction_L: "is_contraction (L p)"
  unfolding is_contraction_def using contraction_L disc_lt_one zero_le_disc by blast

subsubsection Existence of a Fixpoint of @{const Lb}
lemma Lb_conv:
  "!v. Lb v = v" "(λn. (Lb ^^ n) v) <---- (THE v. Lb v = v)"
  using banach'[OF is_contraction_Lby auto

lemma Lb_fix_iff_opt [simp]: "Lb v = v v = νb_opt"
  using banach'(1) is_contraction_L L_fix_imp_opt by metis

lemma νb_opt_fixb_opt = (THE v. Lb v = v)"
  by auto

lemma Lb_opt [simp]: "Lb νb_opt = νb_opt"
  by auto

lemma Lb_lim"(λn. (Lb ^^ n) v) <---- νb_opt"
  using Lb_conv(2) νb_opt_fix by presburger

lemma thm_6_2_6: b p = νb_opt Lbb p) = νb p"
  by force

lemma thm_6_2_6': "ν p = ν_opt Lbb p) = νb p"
  using thm_6_2_6 νb.rep_eq νb_opt.rep_eq by fastforce

subsection Existence of Optimal Policies

definition "ν_improving v d (s. is_arg_max (λd. (L d v) s) (λd. d DR) d)"

lemma ν_improving_iff: "ν_improving v d d DR (d' DR. s. L d' v s L d v s)"
  by (auto simp: ν_improving_def is_arg_max_linorder)

lemma ν_improving_D_MR[dest]: "ν_improving v d ==> d DR"
  by (auto simp add: ν_improving_iff)

lemma ν_improving_ge: "ν_improving v d ==> d' DR ==> L d' v s L d v s"
  by (auto simp: ν_improving_iff)

lemma ν_improving_imp_Lb"ν_improving v d ==> Lb v = L d v"
  by (fastforce intro!: cSup_eq_maximum simp: ν_improving_iff Lb.rep_eq L_def)

lemma Lb_imp_ν_improving: 
  assumes "d DR" "Lb v = L d v"
  shows "ν_improving v d"
  using assms L_le_Lb by (auto simp: ν_improving_iff assms(2)[symmetric])

lemma ν_improving_alt:
  assumes "d DR"
  shows "ν_improving v d Lb v = L d v"
  using Lb_imp_ν_improving ν_improving_imp_Lb assms by blast

definition "ν_conserving d = ν_improving (νb_opt) d"

lemma ν_conserving_iff: "ν_conserving d d DR (d' DR. s. L d' νb_opt s L d νb_opt s)"
  by (auto simp: ν_conserving_def ν_improving_iff)

lemma ν_conserving_ge: "ν_conserving d ==> d' DR ==> L d' νb_opt s L d νb_opt s"
  by (auto simp: ν_conserving_iff intro: ν_improving_ge)

lemma ν_conserving_imp_Lb [simp]: "ν_conserving d ==> L d νb_opt = νb_opt"
  using ν_improving_imp_Lb by (fastforce simp: ν_conserving_def)

lemma Lb_imp_ν_conserving:
  assumes "d DR" "Lb νb_opt = L d νb_opt"
  shows "ν_conserving d"
  using Lb_imp_ν_improving assms by (auto simp: ν_conserving_def)

lemma ν_conserving_alt: 
  assumes "d DR"
  shows "ν_conserving d Lb νb_opt = L d νb_opt"
  unfolding ν_conserving_def using ν_improving_alt assms by auto

lemma ν_conserving_alt':
  assumes "d DR"
  shows "ν_conserving d L d νb_opt = νb_opt"
  using assms ν_conserving_alt by auto

subsubsection Conserving Decision Rules are Optimal

theorem ex_improving_imp_conserving:
  assumes "v. d. ν_improving v (mk_dec_det d)"
  shows "d. ν_conserving (mk_dec_det d)"
  by (simp add: assms ν_conserving_def)

theorem conserving_imp_opt[simp]:
  assumes "ν_conserving (mk_dec_det d)"
  shows b (mk_stationary_det d) = νb_opt"
  using L_ν_fix_iff ν_conserving_imp_Lb[OF assms] by simp

lemma conserving_imp_opt':
  assumes "d. ν_conserving (mk_dec_det d)"
  shows "d DD. (νb (mk_stationary_det d)) = νb_opt"
  using assms by (fastforce simp: ν_conserving_def)

theorem improving_att_imp_det_opt:
  assumes "v. d. ν_improving v (mk_dec_det d)"
  shows b_opt s = (d DD. νb (mk_stationary_det d) s)"
proof -
  obtain d where d: "ν_conserving (mk_dec_det d)"
    using assms ex_improving_imp_conserving by auto
  hence "d DD"
    using ν_conserving_iff is_dec_mk_dec_det_iff by blast
  thus ?thesis
    using ΠMR_imp_policies νb_le_opt
    by (fastforce intro!: cSup_eq_maximum[where z = b_opt s", symmetric]
        simp: conserving_imp_opt[OF d] image_iff)
qed


lemma Lb_sup_att_dec:
  assumes "d DR" "Lb v = L d v"
  shows "d' DD. Lb v = L (mk_dec_det d') v"
proof -
  have "a A s. L d v s = La a v s" for s
    unfolding L_eq_La
    using assms is_dec_def La_bounded A_ne Lb.rep_eq L_def
    by (intro lemma_4_3_1') 
      (auto intro: bounded_range_subset simp: assms(2)[symmetric] L_eq_La[symmetric] SUP_step_MR_eq)
  then obtain d' where d: "d' s A s" "L d v s = La (d' s) v s" for s
    by metis
  thus ?thesis
    using assms d
    by (fastforce simp: is_dec_det_def mk_dec_det_def L_eq_La)
qed

lemma Lb_sup_att_dec':
  assumes "d DR" "Lb v = L d v"
  shows "d' DD. ν_improving v (mk_dec_det d')"
  using Lb_sup_att_dec ν_improving_alt assms by force

subsubsection Deterministic Decision Rules are Optimal

lemma opt_imp_opt_dec_det:
  assumes "p ΠHR" b p = νb_opt" 
  shows "d DD. νb (mk_stationary_det d) = νb_opt"
proof -
  have aux: "L (as_markovian p (return_pmf s) 0) νb_opt s = νb_opt s" for s
  proof -
    let ?ps = "as_markovian p (return_pmf s)"
    have markovian_suc_le: b (mk_markovian (λn. as_markovian p (return_pmf s) (Suc n))) νb_opt"
      using is_ΠMR_as_markovian assms by (auto simp: is_policy_def mk_markovian_def)
    have aux_le: "x f g. f g ==> apply_bfun f x apply_bfun g x"
      unfolding less_eq_bfun_def by auto
    have b_opt s = νb (mk_markovian ?ps) s"
      using assms νb_as_markovian by metis
    also have " = L (?ps 0) (νb (mk_markovian (λn. ?ps (Suc n)))) s"
      using ν_step by blast
    also have " L (?ps 0) (νb_opt) s"
      unfolding L_def using markovian_suc_le P1_mono by (auto intro!: mult_left_mono)
    finally have b_opt s L (?ps 0) (νb_opt) s" .
    have "as_markovian p (return_pmf s) 0 DR"
      using is_ΠMR_as_markovian assms by fast
    have "L (?ps 0) νb_opt νb_opt"
      using ?ps 0 DR L_le_Lb[of "?ps 0" b_opt"by simp
    thus "L (?ps 0) νb_opt s = νb_opt s"
      using νb_opt s (L (?ps 0) νb_opt) s by (auto intro!: antisym)
  qed
  have "L (p []) v s = L (as_markovian p (return_pmf s) 0) v s" for v s
    by (auto simp: L_def P1.rep_eq K_st_def)
  hence "L (p []) νb_opt = νb_opt"
    using aux by auto
  hence "d DD. L (mk_dec_det d) νb_opt = νb_opt"
    using Lb_sup_att_dec assms(1Lb_opt is_policy_def mem_Collect_eq by metis
  thus ?thesis
    using conserving_imp_opt' ν_conserving_alt' by blast
qed

subsubsection Optimal Decision Rules for Finite Action Spaces

(* 6.2.10 *)
lemma ex_opt_act: 
assumes "s. finite (A s)"
shows "a A s. La a (v :: _ ==>b _) s = Lb v s"
      unfolding Lb.rep_eq L_eq_SUP_det SUP_step_det_eq
      using arg_max_on_in[OF assms A_ne]
      by (auto simp: cSup_eq_Sup_fin Sup_fin_Max assms A_ne finite_arg_max_eq_Max[symmetric])

lemma ex_opt_dec_det:
assumes "s. finite (A s)"
shows "d DD. L (mk_dec_det d) (v :: _ ==>b _) = Lb v"
  unfolding is_dec_det_def mk_dec_det_def
  using ex_opt_act[OF assms]  someI_ex
  apply (auto intro!: exI[of _ λs. SOME a. a A s La a v s = Lb v s] bfun_eqI)
   apply (smt (verit, best) someI_ex)
  apply (subst L_eq_La)
  apply (subst expectation_return_pmf)
  by (smt (verit, best) someI_ex)

lemma thm_6_2_10:
  assumes "s. finite (A s)"
  shows "d DD. νb_opt = νb (mk_stationary_det d)"
  using assms conserving_imp_opt' Lb_opt L_ν_fix_iff ex_opt_dec_det 
  by metis

subsubsection Existence of Epsilon-Optimal Policies

lemma ex_det_eps:
  assumes "0 < e"
  shows "d DD. Lb v L (mk_dec_det d) v + e *R 1"
proof -
  have "a A s. Lb v s La a v s + e" for s
  proof -
    have "bdd_above ((λa. La a v s) ` A s)"
      using La_le by (auto intro!: boundedI bounded_imp_bdd_above)
    hence "a A s. Lb v s - e < La a v s"
      unfolding Lb.rep_eq L_eq_SUP_det SUP_step_det_eq
      by (auto simp: less_cSUP_iff[OF A_ne, symmetric] 0 < e)
    thus "a A s. Lb v s La a v s + e"
      by force
  qed
  thus ?thesis
    unfolding mk_dec_det_def is_dec_det_def
    by (auto simp: L_def P1.rep_eq bind_return_pmf K_st_def less_eq_bfun_def) metis
qed

lemma thm_6_2_11:
  assumes "eps > 0"
  shows "d DD. νb_opt νb (mk_stationary_det d) + eps *R 1"
proof -
  have "(1-l) * eps > 0"
    by (simp add: assms)
  then obtain d where "d DD" and d: "Lb νb_opt L (mk_dec_det d) νb_opt + ((1-l)*eps) *R 1"
    using ex_det_eps[of _ νb_optby auto
  let ?d = "mk_dec_det d"
  let ?lK = "l *R P1 ?d"
  let ?lK_opt = "l *R P1 ?d νb_opt"
  have b_opt r_decb ?d + ?lK_opt + ((1-l)*eps) *R 1"
    using L_def L_fix_imp_opt d by simp
  hence b_opt - ?lK_opt - ((1-l)*eps) *R 1 r_decb ?d"
    by (simp add: cancel_ab_semigroup_add_class.diff_right_commute diff_le_eq)
  hence "(i. ?lK ^^ i) (νb_opt - ?lK_opt - ((1-l)*eps) *R 1) νb (mk_stationary ?d)"
    using lemma_6_1_2_b suminf_cong by (simp add: blincomp_scaleR_right ν_stationary)
  hence "((i. ?lK ^^ i) oL (id_blinfun - ?lK)) νb_opt - (i. ?lK ^^ i) (((1-l)*eps) *R 1)
    b (mk_stationary ?d))"
    by (simp add: blinfun.diff_right blinfun.diff_left blinfun.scaleR_left)
  hence le: b_opt - (i. ?lK ^^ i) (((1-l)*eps) *R 1) νb (mk_stationary ?d)"
    by (auto simp: inv_norm_le')
  have s: "summable (λi. (l *R P1 ?d)^^i)"
    using convergent_disc_P1 summable_iff_convergent'
    by (simp add: blincomp_scaleR_right summable_iff_convergent')
  have "(i. ?lK ^^ i) (((1-l)*eps) *R 1) = eps *R 1"
  proof -
    have "(i. ?lK ^^ i) (((1-l)*eps) *R 1) = ((1-l)*eps) *R (i. ?lK^^i) 1"
      using blinfun.scaleR_right by blast
    also have " = ((1-l)*eps) *R (i. (?lK^^i) 1) "
      using s by (auto simp: bounded_linear.suminf[of "λx. blinfun_apply x 1"])
    also have " = ((1-l)*eps) *R (i. (l ^ i)) *R 1"
      by (auto simp: blinfun.scaleR_left blincomp_scaleR_right bounded_linear_scaleR_left 
          bounded_linear.suminf[of "λx. x *R 1"])
    also have " = ((1-l)*eps) *R (1 / (1-l)) *R 1"
      by (simp add: suminf_geometric)
    also have " = eps *R 1"
      using disc_lt_one 0 < (1 - l) * eps by auto
    finally show ?thesis .
  qed
  thus ?thesis
    using d DD diff_le_eq le
    by auto
qed

lemma ex_det_dist_eps:
  assumes "0 < (e :: real)"
  shows "d DD. dist (Lb v) (L (mk_dec_det d) v) e"
proof -
  obtain d where "d DD" "L (mk_dec_det d) v (Lb v)" 
    and h2: "Lb v L (mk_dec_det d) v + e *R 1"
    using assms ex_det_eps L_le_Lb by blast
  hence "0 Lb v - L (mk_dec_det d) v"
    by simp
  moreover have "Lb v - L (mk_dec_det d) v e *R 1"
    using h2 by (simp add: add.commute diff_le_eq)
  ultimately have "s. (Lb v) s - L (mk_dec_det d) v s e"
    unfolding less_eq_bfun_def by auto
  hence "dist (Lb v) (L (mk_dec_det d) v) e"
    unfolding dist_bfun.rep_eq by (auto intro!: cSUP_least simp: dist_real_def)
  thus ?thesis
    using d DD
    by auto
qed

lemma less_imp_ex_add_le: "(x :: real) < y ==> eps>0. x + eps y"
  by (meson field_le_epsilon less_le_not_le nle_le)

lemma νb_opt_le_detb_opt s (d DD. νb (mk_stationary_det d) s)"
proof (subst le_cSUP_iff, safe)
  fix y
  assume "y < νb_opt s"
  then obtain eps where 1"y νb_opt s - eps" and "eps > 0"
    using less_imp_ex_add_le by force
  hence "eps / 2 > 0" by auto
  obtain d where "d DD" and b_opt s νb (mk_stationary_det d) s + eps / 2"
    using thm_6_2_11[OF eps / 2 > 0by fastforce
  hence "y < νb (mk_stationary_det d) s"
    using eps > 0 by (auto simp: diff_less_eq intro: le_less_trans[OF 1])
  thus "iDD. y < νb (mk_stationary_det i) s"
    using d DD by blast
next
  show "DD = {} ==> False"
    using D_det_ne by blast
  show "bdd_above ((λd. νb (mk_stationary_det d) s) ` DD)"
    by (auto intro!: bounded_imp_bdd_above boundedI abs_ν_le simp: νb.rep_eq)
qed

lemma νb_opt_eq_detb_opt s = (d DD. νb (mk_stationary_det d) s)"
  using νb_le_opt_DD D_det_ne
  by (fastforce intro!: antisym[OF νb_opt_le_det] cSUP_least)

(* unused, delete? *)
lemma lemma_6_3_1_a:
  assumes "v0 bfun"
  shows "uniform_limit UNIV (λn. ((λv. L (Bfun v)) ^^ n) v0) ν_opt sequentially"
proof -
  have L_Bfun_eq: "v0 bfun ==> ((λv. L (Bfun v))^^n) v0 = (Lb ^^n) (Bfun v0)" for n
    by (induction n) (auto simp: Lb.rep_eq apply_bfun_inverse)
  have "uniform_limit UNIV (λn. (Lb ^^ n) (Bfun v0)) νb_opt sequentially"
    by (intro tendsto_bfun_uniform_limit[OF Lb_lim])
  hence "uniform_limit UNIV (λn. (Lb ^^ n) (Bfun v0)) ν_opt sequentially"
    by (simp add: ν_opt_bfun νb_opt.rep_eq)
  thus ?thesis
    by (auto simp: assms L_Bfun_eq)
qed

lemma dist_Suc_tendsto_zero:
  assumes "(λn. f n) <---- (y::_::real_normed_vector)"
  shows "(λn. dist (f n) (f (Suc n))) <---- 0"
  using assms tendsto_diff tendsto_norm LIMSEQ_Suc by (fastforce simp: dist_norm)

lemma dist_Lb_tendsto"(λn. dist ((Lb^^n) v) ((Lb^^(Suc n)) v)) <---- 0"
  using Lb_lim by (fast intro!: dist_Suc_tendsto_zero)

definition "max_L_ex s v has_arg_max (λa. La a v s) (A s)"

lemma νb_fin_zero[simp]: b_fin p 0 = 0"
  by (auto simp: νb_fin.rep_eq)

lemma νb_fin_Suc[simp]: 
  b_fin (mk_stationary d) (Suc n) = νb_fin (mk_stationary d) n + ((l *R P1 d)^^ n) (r_decb d)"
  by (auto simp: PX_sconst νb_fin.rep_eq ν_fin_eq_PX blincomp_scaleR_right blinfun.scaleR_left)

lemma νb_fin_eqb_fin (mk_stationary d) n = (i < n. ((l *R P1 d)^^ i)) (r_decb d)"
  by (induction n) (auto simp add: plus_blinfun.rep_eq)

lemma L_iter: "(L d ^^ m) v = νb_fin (mk_stationary d) m + ((l *R P1 d)^^ m) v"
proof (induction m arbitrary: v)
  case (Suc m)
  have "(L d ^^ Suc m) v = (L d ^^ m) (L d v)"
    by (simp add: funpow_Suc_right del: funpow.simps)
  also have " = νb_fin (mk_stationary d) m + ((l *R P1 d) ^^ m) (L d v)"
    using Suc by simp
  also have " = νb_fin (mk_stationary d) (Suc m) + ((l *R P1 d) ^^ Suc m) v"
    unfolding L_def 
    by (auto simp: P1_pow blinfun.bilinear_simps blincomp_scaleR_right funpow_swap1) 
  finally show ?case .
qed simp

lemma bounded_stationary_νb_fin"bounded ((λx. (νb_fin (mk_stationary x) N) s) ` X)"
  using νb_fin.rep_eq abs_ν_fin_le by (auto intro!: boundedI)

lemma bounded_disc_P1"bounded ((λx. (((l *R P1 x) ^^ m) v) s) ` X)"
  by (auto simp: PX_const[symmetric] blinfun.bilinear_simps blincomp_scaleR_right 
      intro!: boundedI[of _  "l ^ m * norm v"] mult_left_mono order.trans[OF abs_le_norm_bfun])

lemma bounded_disc_P1': "bounded ((λx. ((P1 x ^^ m) v) s) ` X)"
  by (auto simp: PX_const[symmetric] intro!: boundedI[of _  "norm v"] order.trans[OF abs_le_norm_bfun])

lemma L_iter_le_Lb"is_dec d ==> (L d ^^ n) v (Lb ^^ n) v"
  using order_trans[OF L_mono L_le_Lbby (induction n) auto

end

subsection More Restrictive MDP Locales
locale MDP_fin_acts = discrete_MDP +
  assumes "s. finite (A s)"

locale MDP_att_L = MDP_reward_disc A K r l
  for
    A and 
    K :: "'s ::countable × 'a ::countable ==> 's pmf" and
    r and l +
  assumes Sup_att: "max_L_ex (s :: 's) v"
begin
theorem Lb_eq_argmax_La:
  fixes v :: "'s ==>b real"
  assumes "is_arg_max (λa. La a v s) (λa. a A s) a"
  shows "Lb v s = La a v s"
  using La_le assms A_ne Lb.rep_eq L_eq_SUP_det SUP_step_det_eq
  by (auto intro!: cSUP_upper2 antisym cSUP_least simp: is_arg_max_linorder)

lemma La_le_arg_max"a A s ==> La a v s La (arg_max_on (λa. La a v s) (A s)) v s"
  using Sup_att app_arg_max_ge[OF Sup_att[unfolded max_L_ex_def]]
  by (simp add: arg_max_on_def)

lemma arg_max_on_in: "has_arg_max f Q ==> arg_max_on f Q Q"
  using has_arg_max_arg_max by (auto simp: arg_max_on_def)

lemma Lb_eq_La_max"Lb v s = La (arg_max_on (λa. La a v s) (A s)) v s"
  using app_arg_max_eq_SUP[symmetric] Sup_att max_L_ex_def 
  by (auto simp: Lb_eq_SUP_det SUP_step_det_eq)

lemma ex_opt_det: "d DD. Lb v = L (mk_dec_det d) v"
proof -
  define d where "d = (λs. arg_max_on (λa. La a v s) (A s))"
  have "Lb v s = L (mk_dec_det d) v s" for s
    by (auto simp: d_def Lb_eq_La_max L_eq_La_det)
  moreover have "d DD"
    using Sup_att arg_max_on_in by (auto simp: d_def is_dec_det_def max_L_ex_def)
  ultimately show ?thesis
    by auto
qed

lemma ex_improving_det: "d DD. ν_improving v (mk_dec_det d)"
  using ν_improving_alt ex_opt_det by auto
end

locale MDP_act = discrete_MDP A K for A :: "'s::countable ==> 'a::countable set" and K +
  fixes arb_act ::  "'a set ==> 'a"
  assumes arb_act_in[simp]: "X {} ==> arb_act X X" 

locale MDP_act_disc = MDP_act A K + MDP_att_L A K r l
  for A :: "'s::countable ==> 'a::countable set" and K r l
begin


lemma is_opt_act_some: "is_opt_act v s (arb_act (opt_acts v s))"
  using arb_act_in[of "{a. is_arg_max (λa. La a v s) (λa. a A s) a}"] Sup_att has_arg_max_def
  unfolding max_L_ex_def is_opt_act_def by auto

lemma some_opt_acts_in_A: "arb_act (opt_acts v s) A s"
  using is_opt_act_some unfolding is_opt_act_def is_arg_max_def by auto

lemma ν_improving_opt_acts: "ν_improving v0 (mk_dec_det (λs. arb_act (opt_acts (apply_bfun v0) s)))"
  using is_opt_act_def is_opt_act_some some_opt_acts_in_A
  by (subst ν_improving_alt) (fastforce simp: L_eq_La_det Lb_eq_argmax_La is_dec_det_def)+

end

locale MDP_finite_type = MDP_reward_disc A K r l
  for A and K :: "'s :: finite × 'a :: finite ==> 's pmf" and r l

end

Messung V0.5 in Prozent
C=70 H=91 G=80

¤ Dauer der Verarbeitung: 0.30 Sekunden  (vorverarbeitet am  2026-06-10) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.