Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Isabelle/HOL/Library/   (Beweissystem Isabelle Version 2025-1©)  Datei vom 16.11.2025 mit Größe 88 kB image not shown  

Quellcode-Bibliothek Extended_Nonnegative_Real.thy

  Sprache: Isabelle
 

(*  Title:      HOL/Library/Extended_Nonnegative_Real.thy
  Author: Johannes Hölzl
*)

section The type of non-negative extended real numbers

theory Extended_Nonnegative_Real
  imports Extended_Real Indicator_Function
begin

lemma ereal_ineq_diff_add:
  assumes "b (-::ereal)" "a b"
  shows "a = b + (a-b)"
by (metis add.commute assms ereal_eq_minus_iff ereal_minus_le_iff ereal_plus_eq_PInfty)

lemma Limsup_const_add:
  fixes c :: "'a::{complete_linorder, linorder_topology, topological_monoid_add, ordered_ab_semigroup_add}"
  shows "F bot ==> Limsup F (λx. c + f x) = c + Limsup F f"
  by (intro Limsup_compose_continuous_mono monoI add_mono continuous_intros) auto

lemma Liminf_const_add:
  fixes c :: "'a::{complete_linorder, linorder_topology, topological_monoid_add, ordered_ab_semigroup_add}"
  shows "F bot ==> Liminf F (λx. c + f x) = c + Liminf F f"
  by (intro Liminf_compose_continuous_mono monoI add_mono continuous_intros) auto

lemma Liminf_add_const:
  fixes c :: "'a::{complete_linorder, linorder_topology, topological_monoid_add, ordered_ab_semigroup_add}"
  shows "F bot ==> Liminf F (λx. f x + c) = Liminf F f + c"
  by (intro Liminf_compose_continuous_mono monoI add_mono continuous_intros) auto

lemma sums_offset:
  fixes f g :: "nat ==> 'a :: {t2_space, topological_comm_monoid_add}"
  assumes "(λn. f (n + i)) sums l" shows "f sums (l + (j
proof  -
  have "(λk. (nj<----
l + (j
    using assms by (auto intro!: tendsto_add simp: sums_def)
  moreover have "(jn∑j for k :: nat
  proof -
    have "(jj=i..∑j=0..
      by (subst sum.union_disjoint[symmetric]) (auto intro!: sum.cong)
    also have "(j=i..j(λn. n + i)`{0..
      unfolding image_add_atLeastLessThan by simp
    finally show ?thesis
      by (auto simp: inj_on_def atLeast0LessThan sum.reindex)
  qed
  ultimately have "(λk. (n<---- l + (j
    by simp
  then show ?thesis
    unfolding sums_def by (rule LIMSEQ_offset)
qed

lemma suminf_offset:
  fixes f g :: "nat ==> 'a :: {t2_space, topological_comm_monoid_add}"
  shows "summable (λj. f (j + i)) ==> suminf f = (j. f (j + i)) + (j
  by (intro sums_unique[symmetric] sums_offset summable_sums)

lemma eventually_at_left_1: "(z::real. 0 < z ==> z < 1 ==> P z) ==> eventually P (at_left 1)"
  by (subst eventually_at_left[of 0]) (auto intro: exI[of _ 0])

lemma mult_eq_1:
  fixes a b :: "'a :: {ordered_semiring, comm_monoid_mult}"
  shows "0 a ==> a 1 ==> b 1 ==> a * b = 1 (a = 1 b = 1)"
  by (metis mult.left_neutral eq_iff mult.commute mult_right_mono)

lemma ereal_add_diff_cancel:
  fixes a b :: ereal
  shows "b ==> (a + b) - b = a"
  by (cases a b rule: ereal2_cases) auto

lemma add_top:
  fixes x :: "'a::{order_top, ordered_comm_monoid_add}"
  shows "0 x ==> x + top = top"
  by (intro top_le add_increasing order_refl)

lemma top_add:
  fixes x :: "'a::{order_top, ordered_comm_monoid_add}"
  shows "0 x ==> top + x = top"
  by (intro top_le add_increasing2 order_refl)

lemma le_lfp: "mono f ==> x lfp f ==> f x lfp f"
  by (subst lfp_unfold) (auto dest: monoD)

lemma lfp_transfer:
  assumes α: "sup_continuous α" and f: "sup_continuous f" and mg: "mono g"
  assumes bot: "α bot lfp g" and eq: "x. x lfp f ==> α (f x) = g (α x)"
  shows "α (lfp f) = lfp g"
proof (rule antisym)
  note mf = sup_continuous_mono[OF f]
  have f_le_lfp: "(f ^^ i) bot lfp f" for i
    by (induction i) (auto intro: le_lfp mf)

  have "α ((f ^^ i) bot) lfp g" for i
    by (induction i) (auto simp: bot eq f_le_lfp intro!: le_lfp mg)
  then show "α (lfp f) lfp g"
    unfolding sup_continuous_lfp[OF f]
    by (simp add: SUP_least α[THEN sup_continuousD] mf mono_funpow)
  show "lfp g α (lfp f)"
    by (rule lfp_lowerbound) (simp add: eq[symmetric] lfp_fixpoint[OF mf])
qed

lemma sup_continuous_applyD: "sup_continuous f ==> sup_continuous (λx. f x h)"
  using sup_continuous_apply[THEN sup_continuous_compose] .

lemma sup_continuous_SUP[order_continuous_intros]:
  fixes M :: "_ ==> _ ==> 'a::complete_lattice"
  assumes M: "i. i I ==> sup_continuous (M i)"
  shows  "sup_continuous (SUP iI. M i)"
  unfolding sup_continuous_def by (auto simp add: sup_continuousD [OF M] image_comp intro: SUP_commute)

lemma sup_continuous_apply_SUP[order_continuous_intros]:
  fixes M :: "_ ==> _ ==> 'a::complete_lattice"
  shows "(i. i I ==> sup_continuous (M i)) ==> sup_continuous (λx. SUP iI. M i x)"
  unfolding SUP_apply[symmetric] by (rule sup_continuous_SUP)

lemma sup_continuous_lfp'[order_continuous_intros]:
  assumes 1: "sup_continuous f"
  assumes 2: "g. sup_continuous g ==> sup_continuous (f g)"
  shows "sup_continuous (lfp f)"
proof -
  have "sup_continuous ((f ^^ i) bot)" for i
  proof (induction i)
    case (Suc i) then show ?case
      by (auto intro!: 2)
  qed (simp add: bot_fun_def sup_continuous_const)
  then show ?thesis
    unfolding sup_continuous_lfp[OF 1] by (intro order_continuous_intros)
qed

lemma sup_continuous_lfp''[order_continuous_intros]:
  assumes 1: "s. sup_continuous (f s)"
  assumes 2: "g. sup_continuous g ==> sup_continuous (λs. f s (g s))"
  shows "sup_continuous (λx. lfp (f x))"
proof -
  have "sup_continuous (λx. (f x ^^ i) bot)" for i
  proof (induction i)
    case (Suc i) then show ?case
      by (auto intro!: 2)
  qed (simp add: bot_fun_def sup_continuous_const)
  then show ?thesis
    unfolding sup_continuous_lfp[OF 1] by (intro order_continuous_intros)
qed

lemma mono_INF_fun:
    "(x y. mono (F x y)) ==> mono (λz x. INF y X x. F x y z :: 'a :: complete_lattice)"
  by (auto intro!: INF_mono[OF bexI] simp: le_fun_def mono_def)

lemma continuous_on_cmult_ereal:
  "c::ereal ==> continuous_on A f ==> continuous_on A (λx. c * f x)"
  using tendsto_cmult_ereal[of c f "f x" "at x within A" for x]
  by (auto simp: continuous_on_def simp del: tendsto_cmult_ereal)

lemma real_of_nat_Sup:
  assumes "A {}" "bdd_above A"
  shows "of_nat (Sup A) = (SUP aA. of_nat a :: real)"
proof (intro antisym)
  show "(SUP aA. of_nat a::real) of_nat (Sup A)"
    using assms by (intro cSUP_least of_nat_mono) (auto intro: cSup_upper)
  have "Sup A A"
    using assms by (auto simp: Sup_nat_def bdd_above_nat)
  then show "of_nat (Sup A) (SUP aA. of_nat a::real)"
    by (intro cSUP_upper bdd_above_image_mono assms) (auto simp: mono_def)
qed

lemma (in complete_lattice) SUP_sup_const1:
  "I {} ==> (SUP iI. sup c (f i)) = sup c (SUP iI. f i)"
  using SUP_sup_distrib[of "λ_. c" I f] by simp

lemma (in complete_lattice) SUP_sup_const2:
  "I {} ==> (SUP iI. sup (f i) c) = sup (SUP iI. f i) c"
  using SUP_sup_distrib[of f I "λ_. c"by simp

lemma one_less_of_natD:
  assumes "(1::'a::linordered_semidom) < of_nat n" shows "1 < n"
  by (cases n) (use assms in auto)

subsection Defining the extended non-negative reals

text Basic definitions and type class setup

typedef ennreal = "{x :: ereal. 0 x}"
  morphisms enn2ereal e2ennreal'
  by auto

definition "e2ennreal x = e2ennreal' (max 0 x)"

lemma enn2ereal_range: "e2ennreal ` {0..} = UNIV"
proof -
  have "y0. x = e2ennreal y" for x
    by (cases x) (auto simp: e2ennreal_def max_absorb2)
  then show ?thesis
    by (auto simp: image_iff Bex_def)
qed

lemma type_definition_ennreal': "type_definition enn2ereal e2ennreal {x. 0 x}"
  using type_definition_ennreal
  by (auto simp: type_definition_def e2ennreal_def max_absorb2)

setup_lifting type_definition_ennreal'

declare [[coercion e2ennreal]]

instantiation ennreal :: complete_linorder
begin

lift_definition top_ennreal :: ennreal is top by (rule top_greatest)
lift_definition bot_ennreal :: ennreal is 0 by (rule order_refl)
lift_definition sup_ennreal :: "ennreal ==> ennreal ==> ennreal" is sup by (rule le_supI1)
lift_definition inf_ennreal :: "ennreal ==> ennreal ==> ennreal" is inf by (rule le_infI)

lift_definition Inf_ennreal :: "ennreal set ==> ennreal" is "Inf"
  by (rule Inf_greatest)

lift_definition Sup_ennreal :: "ennreal set ==> ennreal" is "sup 0 Sup"
  by auto

lift_definition less_eq_ennreal :: "ennreal ==> ennreal ==> bool" is "()" .
lift_definition less_ennreal :: "ennreal ==> ennreal ==> bool" is "(<)" .

instance
  by standard
     (transfer; auto simp: Inf_lower Inf_greatest Sup_upper Sup_least le_max_iff_disj max.absorb1)+

end

lemma pcr_ennreal_enn2ereal[simp]: "pcr_ennreal (enn2ereal x) x"
  by (simp add: ennreal.pcr_cr_eq cr_ennreal_def)

lemma rel_fun_eq_pcr_ennreal: "rel_fun (=) pcr_ennreal f g f = enn2ereal g"
  by (auto simp: rel_fun_def ennreal.pcr_cr_eq cr_ennreal_def)

instantiation ennreal :: infinity
begin

definition infinity_ennreal :: ennreal
  where [simp]: " = (top::ennreal)"

instance ..

end

instantiation ennreal :: "{semiring_1_no_zero_divisors, comm_semiring_1}"
begin

lift_definition one_ennreal :: ennreal is 1 by simp
lift_definition zero_ennreal :: ennreal is 0 by simp
lift_definition plus_ennreal :: "ennreal ==> ennreal ==> ennreal" is "(+)" by simp
lift_definition times_ennreal :: "ennreal ==> ennreal ==> ennreal" is "(*)" by simp


instance
  by standard (transfer; auto simp: field_simps ereal_right_distrib)+

end

instantiation ennreal :: minus
begin

lift_definition minus_ennreal :: "ennreal ==> ennreal ==> ennreal" is "λa b. max 0 (a - b)"
  by simp

instance ..

end

instance ennreal :: numeral ..

instantiation ennreal :: inverse
begin

lift_definition inverse_ennreal :: "ennreal ==> ennreal" is inverse
  by (rule inverse_ereal_ge0I)

definition divide_ennreal :: "ennreal ==> ennreal ==> ennreal"
  where "x div y = x * inverse (y :: ennreal)"

instance ..

end

lemma ennreal_zero_less_one: "0 < (1::ennreal)" 🍋 TODO: remove
  by transfer auto

instance ennreal :: dioid
proof (standard; transfer)
  fix a b :: ereal assume " a" " b" then show "(a  b) = (cCollect (() 0). b = a + c)"
    unfolding ereal_ex_split Bex_def
    by (cases a b rule: ereal2_cases) (auto intro!: exI[of _ "real_of_ereal (b - a)"])
qed

instance ennreal :: ordered_comm_semiring
  by standard
     (transfer; auto intro: add_mono mult_mono mult_ac ereal_left_distrib ereal_mult_left_mono)+

instance ennreal :: linordered_nonzero_semiring
proof
  fix a b::ennreal
  show "a < b ==> a + 1 < b + 1"
    by transfer (simp add: add_right_mono ereal_add_cancel_right less_le)
qed (transfer; simp)

instance ennreal :: strict_ordered_ab_semigroup_add
proof
  fix a b c d :: ennreal show "a < b ==> c < d ==> a + c < b + d"
    by transfer (auto intro!: ereal_add_strict_mono)
qed

declare [[coercion "of_nat :: nat ==> ennreal"]]

lemma e2ennreal_neg: " 0 ==> e2ennreal x = 0"
  unfolding zero_ennreal_def e2ennreal_def by (simp add: max_absorb1)

lemma e2ennreal_mono: " y ==> e2ennreal x  e2ennreal y"
  by (cases " x" " y" rule: bool.exhaust[case_product bool.exhaust])
     (auto simp: e2ennreal_neg less_eq_ennreal.abs_eq eq_onp_def)

lemma enn2ereal_nonneg[simp]: " enn2ereal x"
  using ennreal.enn2ereal[of x] by simp

lemma ereal_ennreal_cases:
  obtains b where " a" "a = enn2ereal b" | "a < 0"
  using e2ennreal'_inverse[of a, symmetric] by (cases " a") (auto intro: enn2ereal_nonneg)

lemma rel_fun_liminf[transfer_rule]: "rel_fun (rel_fun (=) pcr_ennreal) pcr_ennreal liminf liminf"
proof -
  have "x y. rel_fun (=) pcr_ennreal x y  pcr_ennreal (sup 0 (liminf x)) (liminf y) ==>
        x y. rel_fun (=) pcr_ennreal x y  pcr_ennreal (liminf x) (liminf y)"
    by (auto simp: comp_def Liminf_bounded rel_fun_eq_pcr_ennreal)
  moreover have "rel_fun (rel_fun (=) pcr_ennreal) pcr_ennreal (λx. sup 0 (liminf x)) liminf"
    unfolding liminf_SUP_INF[abs_def] by (transfer_prover_start, transfer_step+; simp)
  ultimately show ?thesis
    by (simp add: rel_fun_def)
qed

lemma rel_fun_limsup[transfer_rule]: "rel_fun (rel_fun (=) pcr_ennreal) pcr_ennreal limsup limsup"
proof -
  have [simp]: "max 0 (SUP x{n..}. enn2ereal (y x)) = (SUP x{n..}. enn2ereal (y x))" for n::nat and y
    by (meson SUP_upper atLeast_iff enn2ereal_nonneg max.absorb2 nle_le order_trans)
  have "rel_fun (rel_fun (=) pcr_ennreal) pcr_ennreal (λx. INF n. sup 0 (SUP i{n..}. x i)) limsup"
    unfolding limsup_INF_SUP[abs_def] by (transfer_prover_start, transfer_step+; simp)
  moreover
  have "x y. [rel_fun (=) pcr_ennreal x y;
                pcr_ennreal (INF n::nat. max 0 (Sup (x ` {n..}))) (INF n. Sup (y ` {n..}))]
           ==> pcr_ennreal (INF n. Sup (x ` {n..})) (INF n. Sup (y ` {n..}))"
    by (auto simp: comp_def rel_fun_eq_pcr_ennreal)
  ultimately show ?thesis
    by (simp add: limsup_INF_SUP rel_fun_def)
qed

lemma sum_enn2ereal[simp]: "(i. i  I ==> 0  f i) ==> (iI. enn2ereal (f i)) = enn2ereal (sum f I)"
  by (induction I rule: infinite_finite_induct) (auto simp: sum_nonneg zero_ennreal.rep_eq plus_ennreal.rep_eq)

lemma transfer_e2ennreal_sum [transfer_rule]:
  "rel_fun (rel_fun (=) pcr_ennreal) (rel_fun (=) pcr_ennreal) sum sum"
  by (auto intro!: rel_funI simp: rel_fun_eq_pcr_ennreal comp_def)

lemma enn2ereal_of_nat[simp]: "enn2ereal (of_nat n) = ereal n"
  by (induction n) (auto simp: zero_ennreal.rep_eq one_ennreal.rep_eq plus_ennreal.rep_eq)

lemma enn2ereal_numeral[simp]: "enn2ereal (numeral a) = numeral a"
  by (metis enn2ereal_of_nat numeral_eq_ereal of_nat_numeral)

lemma transfer_numeral[transfer_rule]: "pcr_ennreal (numeral a) (numeral a)"
  by (metis enn2ereal_numeral pcr_ennreal_enn2ereal)

subsection Cancellation simprocs

lemma ennreal_add_left_cancel: "a + b = a + c  a = (::ennreal)  b = c"
  unfolding infinity_ennreal_def by transfer (simp add: top_ereal_def ereal_add_cancel_left)

lemma ennreal_add_left_cancel_le: "a + b  a + c  a = (::ennreal)  b  c"
  unfolding infinity_ennreal_def by transfer (simp add: ereal_add_le_add_iff top_ereal_def disj_commute)

lemma ereal_add_left_cancel_less:
  fixes a b c :: ereal
  shows " a ==> 0  b ==> a + b < a + c  a    b < c"
  by (cases a b c rule: ereal3_cases) auto

lemma ennreal_add_left_cancel_less: "a + b < a + c  a  (::ennreal)  b < c"
  unfolding infinity_ennreal_def
  by transfer (simp add: top_ereal_def ereal_add_left_cancel_less)

ML
 structure Cancel_Ennreal_Common =
 struct
  (* copied from src/HOL/Tools/nat_numeral_simprocs.ML *)
  fun find_first_t _ _ [] = raise TERM("find_first_t", [])
    | find_first_t past u (t::terms) =
          if u aconv t then (rev past @ terms)
          else find_first_t (t::past) u terms

  fun dest_summing (Const (🍋Groups.plus, _) $ t $ u, ts) =
        dest_summing (t, dest_summing (u, ts))
    | dest_summing (t, ts) = t :: ts

  val mk_sum = Arith_Data.long_mk_sum
  fun dest_sum t = dest_summing (t, [])
  val find_first = find_first_t []
  val trans_tac = Numeral_Simprocs.trans_tac
  val norm_ss =
    simpset_of (put_simpset HOL_basic_ss 🍋
      |> Simplifier.add_simps @{thms ac_simps add_0_left add_0_right})
  fun norm_tac ctxt = ALLGOALS (simp_tac (put_simpset norm_ss ctxt))
  fun simplify_meta_eq ctxt cancel_th th =
    Arith_Data.simplify_meta_eq [] ctxt
      ([th, cancel_th] MRS trans)
  fun mk_eq (a, b) = HOLogic.mk_Trueprop (HOLogic.mk_eq (a, b))
end

structure Eq_Ennreal_Cancel = ExtractCommonTermFun
(open Cancel_Ennreal_Common
  val mk_bal = HOLogic.mk_eq
  val dest_bal = HOLogic.dest_bin 🍋HOL.eq 🍋ennreal
  fun simp_conv _ _ = SOME @{thm ennreal_add_left_cancel}
)

structure Le_Ennreal_Cancel = ExtractCommonTermFun
(open Cancel_Ennreal_Common
  val mk_bal = HOLogic.mk_binrel 🍋Orderings.less_eq
  val dest_bal = HOLogic.dest_bin 🍋Orderings.less_eq 🍋ennreal
  fun simp_conv _ _ = SOME @{thm ennreal_add_left_cancel_le}
)

structure Less_Ennreal_Cancel = ExtractCommonTermFun
(open Cancel_Ennreal_Common
  val mk_bal = HOLogic.mk_binrel 🍋Orderings.less
  val dest_bal = HOLogic.dest_bin 🍋Orderings.less 🍋ennreal
  fun simp_conv _ _ = SOME @{thm ennreal_add_left_cancel_less}
)
\

simproc_setup ennreal_eq_cancel
  ("(l::ennreal) + m = n" | "(l::ennreal) = m + n") =
  K (fn ctxt => fn ct => Eq_Ennreal_Cancel.proc ctxt (Thm.term_of ct))

simproc_setup ennreal_le_cancel
  ("(l::ennreal) + m  n" | "(l::ennreal)  m + n") =
  K (fn ctxt => fn ct => Le_Ennreal_Cancel.proc ctxt (Thm.term_of ct))

simproc_setup ennreal_less_cancel
  ("(l::ennreal) + m < n" | "(l::ennreal) < m + n") =
  K (fn ctxt => fn ct => Less_Ennreal_Cancel.proc ctxt (Thm.term_of ct))


subsection Order with top

lemma ennreal_zero_less_top[simp]: "0 < (top::ennreal)"
  by transfer (simp add: top_ereal_def)

lemma ennreal_one_less_top[simp]: "1 < (top::ennreal)"
  by transfer (simp add: top_ereal_def)

lemma ennreal_zero_neq_top[simp]: " (top::ennreal)"
  by transfer (simp add: top_ereal_def)

lemma ennreal_top_neq_zero[simp]: "(top::ennreal)  0"
  by transfer (simp add: top_ereal_def)

lemma ennreal_top_neq_one[simp]: "top  (1::ennreal)"
  by transfer (simp add: top_ereal_def one_ereal_def flip: ereal_max)

lemma ennreal_one_neq_top[simp]: " (top::ennreal)"
  by transfer (simp add: top_ereal_def one_ereal_def flip: ereal_max)

lemma ennreal_add_less_top[simp]:
  fixes a b :: ennreal
  shows "a + b < top  a < top  b < top"
  by transfer (auto simp: top_ereal_def)

lemma ennreal_add_eq_top[simp]:
  fixes a b :: ennreal
  shows "a + b = top  a = top  b = top"
  by transfer (auto simp: top_ereal_def)

lemma ennreal_sum_less_top[simp]:
  fixes f :: "'a ==> ennreal"
  shows "finite I ==> (iI. f i) < top  (iI. f i < top)"
  by (induction I rule: finite_induct) auto

lemma ennreal_sum_eq_top[simp]:
  fixes f :: "'a ==> ennreal"
  shows "finite I ==> (iI. f i) = top  (iI. f i = top)"
  by (induction I rule: finite_induct) auto

lemma ennreal_mult_eq_top_iff:
  fixes a b :: ennreal
  shows "a * b = top  (a = top  b  0)  (b = top  a  0)"
  by transfer (auto simp: top_ereal_def)

lemma ennreal_top_eq_mult_iff:
  fixes a b :: ennreal
  shows "top = a * b  (a = top  b  0)  (b = top  a  0)"
  using ennreal_mult_eq_top_iff[of a b] by auto

lemma ennreal_mult_less_top:
  fixes a b :: ennreal
  shows "a * b < top  (a = 0  b = 0  (a < top  b < top))"
  by transfer (auto simp add: top_ereal_def)

lemma top_power_ennreal: "top ^ n = (if n = 0 then 1 else top :: ennreal)"
  by (induction n) (simp_all add: ennreal_mult_eq_top_iff)

lemma ennreal_prod_eq_0[simp]:
  fixes f :: "'a ==> ennreal"
  shows "(prod f A = 0) = (finite A  (iA. f i = 0))"
  by (induction A rule: infinite_finite_induct) auto

lemma ennreal_prod_eq_top:
  fixes f :: "'a ==> ennreal"
  shows "(iI. f i) = top  (finite I  ((iI. f i  0)  (iI. f i = top)))"
  by (induction I rule: infinite_finite_induct) (auto simp: ennreal_mult_eq_top_iff)

lemma ennreal_top_mult: "top * a = (if a = 0 then 0 else top :: ennreal)"
  by (simp add: ennreal_mult_eq_top_iff)

lemma ennreal_mult_top: "a * top = (if a = 0 then 0 else top :: ennreal)"
  by (simp add: ennreal_mult_eq_top_iff)

lemma enn2ereal_eq_top_iff[simp]: "enn2ereal x =   x = top"
  by transfer (simp add: top_ereal_def)

lemma enn2ereal_top[simp]: "enn2ereal top = "
  by transfer (simp add: top_ereal_def)

lemma e2ennreal_infty[simp]: "e2ennreal  = top"
  by (simp add: top_ennreal.abs_eq top_ereal_def)

lemma ennreal_top_minus[simp]: "top - x = (top::ennreal)"
  by transfer (auto simp: top_ereal_def max_def)

lemma minus_top_ennreal: "x - top = (if x = top then top else 0:: ennreal)"
  by transfer (use ereal_eq_minus_iff top_ereal_def in force)

lemma bot_ennreal: "bot = (0::ennreal)"
  by transfer rule

lemma ennreal_of_nat_neq_top[simp]: "of_nat i  (top::ennreal)"
  by (induction i) auto

lemma numeral_eq_of_nat: "(numeral a::ennreal) = of_nat (numeral a)"
  by simp

lemma of_nat_less_top: "of_nat i < (top::ennreal)"
  using less_le_trans[of "of_nat i" "of_nat (Suc i)" "top::ennreal"]
  by simp

lemma top_neq_numeral[simp]: "top  (numeral i::ennreal)"
  using of_nat_less_top[of "numeral i"] by simp

lemma ennreal_numeral_less_top[simp]: "numeral i < (top::ennreal)"
  using of_nat_less_top[of "numeral i"] by simp

lemma ennreal_add_bot[simp]: "bot + x = (x::ennreal)"
  by transfer simp

lemma add_top_right_ennreal [simp]: "x + top = (top :: ennreal)"
  by (cases x) auto

lemma add_top_left_ennreal [simp]: "top + x = (top :: ennreal)"
  by (cases x) auto

lemma ennreal_top_mult_left [simp]: " 0 ==> x * top = (top :: ennreal)"
  by (subst ennreal_mult_eq_top_iff) auto

lemma ennreal_top_mult_right [simp]: " 0 ==> top * x = (top :: ennreal)"
  by (subst ennreal_mult_eq_top_iff) auto


lemma power_top_ennreal [simp]: "n > 0 ==> top ^ n = (top :: ennreal)"
  by (induction n) auto

lemma power_eq_top_ennreal_iff: "x ^ n = top  x = (top :: ennreal)  n > 0"
  by (induction n) (auto simp: ennreal_mult_eq_top_iff)

lemma ennreal_mult_le_mult_iff: " 0 ==> c  top ==> c * a  c * b  a  (b :: ennreal)"
  including ennreal.lifting
  by (transfer, subst ereal_mult_le_mult_iff) (auto simp: top_ereal_def)

lemma power_mono_ennreal: " y ==> x ^ n  (y ^ n :: ennreal)"
  by (induction n) (auto intro!: mult_mono)

instance ennreal :: semiring_char_0
proof (standard, safe intro!: linorder_injI)
  have *: "1 + of_nat k  (0::ennreal)" for k
    using add_pos_nonneg[OF zero_less_one, of "of_nat k :: ennreal"] by auto
  fix x y :: nat assume "x < y" "of_nat x = (of_nat y::ennreal)" then show False
    by (auto simp add: less_iff_Suc_add *)
qed

subsection Arithmetic

lemma ennreal_minus_zero[simp]: "a - (0::ennreal) = a"
  by transfer (auto simp: max_def)

lemma ennreal_add_diff_cancel_right[simp]:
  fixes x y z :: ennreal shows " top ==> (x + y) - y = x"
  by transfer (metis ereal_eq_minus_iff max_absorb2 not_MInfty_nonneg top_ereal_def)

lemma ennreal_add_diff_cancel_left[simp]:
  fixes x y z :: ennreal shows " top ==> (y + x) - y = x"
  by (simp add: add.commute)

lemma
  fixes a b :: ennreal
  shows "a - b = 0 ==> a  b"
  by transfer (metis ereal_diff_gr0 le_cases max.absorb2 not_less)

lemma ennreal_minus_cancel:
  fixes a b c :: ennreal
  shows " top ==> a  c ==> b  c ==> c - a = c - b ==> a = b"
  by (metis ennreal_add_diff_cancel_left ennreal_add_diff_cancel_right ennreal_add_eq_top less_eqE)

lemma sup_const_add_ennreal:
  fixes a b c :: "ennreal"
  shows "sup (c + a) (c + b) = c + sup a b"
  by transfer (metis add_left_mono le_cases sup.absorb2 sup.orderE)

lemma ennreal_diff_add_assoc:
  fixes a b c :: ennreal
  shows " b ==> c + b - a = c + (b - a)"
  by (metis add.left_commute ennreal_add_diff_cancel_left ennreal_add_eq_top ennreal_top_minus less_eqE)

lemma mult_divide_eq_ennreal:
  fixes a b :: ennreal
  shows " 0 ==> b  top ==> (a * b) / b = a"
  unfolding divide_ennreal_def
  apply transfer
  by (metis abs_ereal_ge0 divide_ereal_def ereal_divide_eq ereal_times_divide_eq top_ereal_def)

lemma divide_mult_eq: " 0 ==> a   ==> x * a / (b * a) = x / (b::ennreal)"
  unfolding divide_ennreal_def infinity_ennreal_def
  apply transfer
  subgoal for a b c
    by (cases a b c rule: ereal3_cases) (auto simp: top_ereal_def)
  done

lemma ennreal_mult_divide_eq:
  fixes a b :: ennreal
  shows " 0 ==> b  top ==> (a * b) / b = a"
  by (fact mult_divide_eq_ennreal)

lemma ennreal_add_diff_cancel:
  fixes a b :: ennreal
  shows "  ==> (a + b) - b = a"
  by simp

lemma ennreal_minus_eq_0:
  "a - b = 0 ==> a  (b::ennreal)"
  by transfer (metis ereal_diff_gr0 le_cases max.absorb2 not_less)

lemma ennreal_mono_minus_cancel:
  fixes a b c :: ennreal
  shows "a - b  a - c ==> a < top ==> b  a ==> c  a ==> c  b"
  by transfer
     (auto simp add: ereal_diff_positive top_ereal_def dest: ereal_mono_minus_cancel)

lemma ennreal_mono_minus:
  fixes a b c :: ennreal
  shows " b ==> a - b  a - c"
  by transfer (meson ereal_minus_mono max.mono order_refl)

lemma ennreal_minus_pos_iff:
  fixes a b :: ennreal
  shows "a < top  b < top ==> 0 < a - b ==> b < a"
  by transfer (use add.left_neutral ereal_minus_le_iff less_irrefl not_less in fastforce)

lemma ennreal_inverse_top[simp]: "inverse top = (0::ennreal)"
  by transfer (simp add: top_ereal_def ereal_inverse_eq_0)

lemma ennreal_inverse_zero[simp]: "inverse 0 = (top::ennreal)"
  by transfer (simp add: top_ereal_def ereal_inverse_eq_0)

lemma ennreal_top_divide: "top / (x::ennreal) = (if x = top then 0 else top)"
  unfolding divide_ennreal_def
  by transfer (simp add: top_ereal_def ereal_inverse_eq_0 ereal_0_gt_inverse)

lemma ennreal_zero_divide[simp]: "0 / (x::ennreal) = 0"
  by (simp add: divide_ennreal_def)

lemma ennreal_divide_zero[simp]: "x / (0::ennreal) = (if x = 0 then 0 else top)"
  by (simp add: divide_ennreal_def ennreal_mult_top)

lemma ennreal_divide_top[simp]: "x / (top::ennreal) = 0"
  by (simp add: divide_ennreal_def ennreal_top_mult)

lemma ennreal_times_divide: "a * (b / c) = a * b / (c::ennreal)"
  unfolding divide_ennreal_def
  by transfer (simp add: divide_ereal_def[symmetric] ereal_times_divide_eq)

lemma ennreal_zero_less_divide: "0 < a / b  (0 < a  b < (top::ennreal))"
  unfolding divide_ennreal_def
  by transfer (auto simp: ereal_zero_less_0_iff top_ereal_def ereal_0_gt_inverse)

lemma add_divide_distrib_ennreal: "(a + b) / c = a / c + b / (c :: ennreal)"
  by (simp add: divide_ennreal_def ring_distribs)

lemma divide_right_mono_ennreal:
  fixes a b c :: ennreal
  shows " b ==> a / c  b / c"
  unfolding divide_ennreal_def by (intro mult_mono) auto

lemma ennreal_mult_strict_right_mono: "(a::ennreal) < c ==> 0 < b ==> b < top ==> a * b < c * b"
  by transfer (auto intro!: ereal_mult_strict_right_mono)

lemma ennreal_indicator_less[simp]:
  "indicator A x  (indicator B x::ennreal)  (x  A  x  B)"
  by (simp add: indicator_def not_le)

lemma ennreal_inverse_positive: "0 < inverse x  (x::ennreal)  top"
  by transfer (simp add: ereal_0_gt_inverse top_ereal_def)

lemma ennreal_inverse_mult': "((0 < b  a < top)  (0 < a  b < top)) ==> inverse (a * b::ennreal) = inverse a * inverse b"
  apply transfer
  subgoal for a b
    by (cases a b rule: ereal2_cases) (auto simp: top_ereal_def)
  done

lemma ennreal_inverse_mult: "a < top ==> b < top ==> inverse (a * b::ennreal) = inverse a * inverse b"
  by (simp add: ennreal_inverse_mult')

lemma ennreal_inverse_1[simp]: "inverse (1::ennreal) = 1"
  by transfer simp

lemma ennreal_inverse_eq_0_iff[simp]: "inverse (a::ennreal) = 0  a = top"
  by (metis ennreal_inverse_positive not_gr_zero)

lemma ennreal_inverse_eq_top_iff[simp]: "inverse (a::ennreal) = top  a = 0"
  by transfer (simp add: top_ereal_def)

lemma ennreal_divide_eq_0_iff[simp]: "(a::ennreal) / b = 0  (a = 0  b = top)"
  by (simp add: divide_ennreal_def)

lemma ennreal_divide_eq_top_iff: "(a::ennreal) / b = top  ((a  0  b = 0)  (a = top  b  top))"
  by (auto simp add: divide_ennreal_def ennreal_mult_eq_top_iff)

lemma one_divide_one_divide_ennreal[simp]: "1 / (1 / c) = (c::ennreal)"
  including ennreal.lifting
  unfolding divide_ennreal_def
  by transfer auto

lemma ennreal_mult_left_cong:
  "((a::ennreal)  0 ==> b = c) ==> a * b = a * c"
  by (cases "a = 0") simp_all

lemma ennreal_mult_right_cong:
  "((a::ennreal)  0 ==> b = c) ==> b * a = c * a"
  by (cases "a = 0") simp_all

lemma ennreal_zero_less_mult_iff: "0 < a * b  0 < a  0 < (b::ennreal)"
  using not_gr_zero by fastforce

lemma less_diff_eq_ennreal:
  fixes a b c :: ennreal
  shows "b < top  c < top ==> a < b - c  a + c < b"
  apply transfer
  subgoal for a b c
    by (cases a b c rule: ereal3_cases) (auto split: split_max)
  done

lemma diff_add_cancel_ennreal:
  fixes a b :: ennreal shows " b ==> b - a + a = b"
  unfolding infinity_ennreal_def
  by transfer (metis (no_types) add.commute ereal_diff_positive ereal_ineq_diff_add max_def not_MInfty_nonneg)

lemma ennreal_diff_self[simp]: " top ==> a - a = (0::ennreal)"
  by (meson ennreal_minus_pos_iff less_imp_neq not_gr_zero top.not_eq_extremum)

lemma ennreal_minus_mono:
  fixes a b c :: ennreal
  shows " c ==> d  b ==> a - b  c - d"
  by transfer (meson ereal_minus_mono max.mono order_refl)

lemma ennreal_minus_eq_top[simp]: "a - (b::ennreal) = top  a = top"
  by (metis add_top diff_add_cancel_ennreal ennreal_mono_minus ennreal_top_minus zero_le)

lemma ennreal_divide_self[simp]: " 0 ==> a < top ==> a / a = (1::ennreal)"
  by (metis mult_1 mult_divide_eq_ennreal top.not_eq_extremum)

subsection Coercion from 🍋real to 🍋ennreal\
 
 lift_definition ennreal :: "real ==> ennreal" is "sup 0 ereal"
  by simp
 
 declare [[coercion ennreal]]
 
 lemma ennreal_cong: "x = y ==> ennreal x = ennreal y"
  by simp
 
 lemma ennreal_cases[cases type: ennreal]:
  fixes x :: ennreal
  obtains (real) r :: real where "0 r" "x = ennreal r" | (top) "x = top"
  apply transfer
  subgoal for x thesis
  by (cases x) (auto simp: top_ereal_def)
  done
 
 lemmas ennreal2_cases = ennreal_cases[case_product ennreal_cases]
 lemmas ennreal3_cases = ennreal_cases[case_product ennreal2_cases]
 
 lemma ennreal_neq_top[simp]: "ennreal r top"
  by transfer (simp add: top_ereal_def zero_ereal_def flip: ereal_max)
 
 lemma top_neq_ennreal[simp]: "top ennreal r"
  using ennreal_neq_top[of r] by (auto simp del: ennreal_neq_top)
 
 lemma ennreal_less_top[simp]: "ennreal x < top"
  by transfer (simp add: top_ereal_def max_def)
 
 lemma ennreal_neg: "x 0 ==> ennreal x = 0"
  by transfer (simp add: max.absorb1)
 
 lemma ennreal_inj[simp]:
  "0 a ==> 0 b ==> ennreal a = ennreal b a = b"
  by (transfer fixing: a b) (auto simp: max_absorb2)
 
 lemma ennreal_le_iff[simp]: "0 y ==> ennreal x ennreal y x y"
  by (auto simp: ennreal_def zero_ereal_def less_eq_ennreal.abs_eq eq_onp_def split: split_max)
 
 lemma le_ennreal_iff: "0 r ==> x ennreal r (q0. x = ennreal q q r)"
  by (cases x) (auto simp: top_unique)
 
 lemma ennreal_less_iff: "0 r ==> ennreal r < ennreal q r < q"
  unfolding not_le[symmetric] by auto
 
 lemma ennreal_eq_zero_iff[simp]: "0 x ==> ennreal x = 0 x = 0"
  by transfer (auto simp: max_absorb2)
 
 lemma ennreal_less_zero_iff[simp]: "0 < ennreal x 0 < x"
  by transfer (auto simp: max_def)
 
 lemma ennreal_lessI: "0 < q ==> r < q ==> ennreal r < ennreal q"
  by (cases "0 r") (auto simp: ennreal_less_iff ennreal_neg)
 
 lemma ennreal_leI: "x y ==> ennreal x ennreal y"
  by (cases "0 y") (auto simp: ennreal_neg)
 
 lemma enn2ereal_ennreal[simp]: "0 x ==> enn2ereal (ennreal x) = x"
  by transfer (simp add: max_absorb2)
 
 lemma e2ennreal_enn2ereal[simp]: "e2ennreal (enn2ereal x) = x"
  by (simp add: e2ennreal_def max_absorb2 ennreal.enn2ereal_inverse)
 
 lemma enn2ereal_e2ennreal: "x 0 ==> enn2ereal (e2ennreal x) = x"
 by (metis e2ennreal_enn2ereal ereal_ennreal_cases not_le)
 
 lemma e2ennreal_ereal [simp]: "e2ennreal (ereal x) = ennreal x"
 by (metis e2ennreal_def enn2ereal_inverse ennreal.rep_eq sup_ereal_def)
 
 lemma ennreal_0[simp]: "ennreal 0 = 0"
  by (simp add: ennreal_def zero_ennreal.abs_eq)
 
 lemma ennreal_1[simp]: "ennreal 1 = 1"
  by transfer (simp add: max_absorb2)
 
 lemma ennreal_eq_0_iff: "ennreal x = 0 x 0"
  by (cases "0 x") (auto simp: ennreal_neg)
 
 lemma ennreal_le_iff2: "ennreal x ennreal y ((0 y x y) (x 0 y 0))"
  by (cases "0 y") (auto simp: ennreal_eq_0_iff ennreal_neg)
 
 lemma ennreal_eq_1[simp]: "ennreal x = 1 x = 1"
  by (cases "0 x") (auto simp: ennreal_neg simp flip: ennreal_1)
 
 lemma ennreal_le_1[simp]: "ennreal x 1 x 1"
  by (cases "0 x") (auto simp: ennreal_neg simp flip: ennreal_1)
 
 lemma ennreal_ge_1[simp]: "ennreal x 1 x 1"
  by (cases "0 x") (auto simp: ennreal_neg simp flip: ennreal_1)
 
 lemma one_less_ennreal[simp]: "1 < ennreal x 1 < x"
  by (meson ennreal_le_1 linorder_not_le)
 
 lemma ennreal_plus[simp]:
  "0 a ==> 0 b ==> ennreal (a + b) = ennreal a + ennreal b"
  by (transfer fixing: a b) (auto simp: max_absorb2)
 
 lemma add_mono_ennreal: "x < ennreal y ==> x' < ennreal y' ==> x + x' < ennreal (y + y')"
  by (metis (full_types) add_strict_mono ennreal_less_zero_iff ennreal_plus less_le not_less zero_le)
 
 lemma sum_ennreal[simp]: "(i. i I ==> 0 f i) ==> (iI. ennreal (f i)) = ennreal (sum f I)"
  by (induction I rule: infinite_finite_induct) (auto simp: sum_nonneg)
 
 lemma sum_list_ennreal[simp]:
  assumes "x. x set xs ==> f x 0"
  shows "sum_list (map (λx. ennreal (f x)) xs) = ennreal (sum_list (map f xs))"
 using assms
 proof (induction xs)
  case (Cons x xs)
  from Cons have "(xx # xs. ennreal (f x)) = ennreal (f x) + ennreal (sum_list (map f xs))"
  by simp
  also from Cons.prems have " = ennreal (f x + sum_list (map f xs))"
  by (intro ennreal_plus [symmetric] sum_list_nonneg) auto
  finally show ?case by simp
 qed simp_all
 
 lemma ennreal_of_nat_eq_real_of_nat: "of_nat i = ennreal (of_nat i)"
  by (induction i) simp_all
 
 lemma of_nat_le_ennreal_iff[simp]: "0 r ==> of_nat i ennreal r of_nat i r"
  by (simp add: ennreal_of_nat_eq_real_of_nat)
 
 lemma ennreal_le_of_nat_iff[simp]: "ennreal r of_nat i r of_nat i"
  by (simp add: ennreal_of_nat_eq_real_of_nat)
 
 lemma ennreal_indicator: "ennreal (indicator A x) = indicator A x"
  by (auto split: split_indicator)
 
 lemma ennreal_numeral[simp]: "ennreal (numeral n) = numeral n"
  using ennreal_of_nat_eq_real_of_nat[of "numeral n"] by simp
 
 lemma ennreal_less_numeral_iff [simp]: "ennreal n < numeral w n < numeral w"
  by (metis ennreal_less_iff ennreal_numeral less_le not_less zero_less_numeral)
 
 lemma numeral_less_ennreal_iff [simp]: "numeral w < ennreal n numeral w < n"
  using ennreal_less_iff zero_le_numeral by fastforce
 
 lemma numeral_le_ennreal_iff [simp]: "numeral n ennreal m numeral n m"
  by (metis not_le ennreal_less_numeral_iff)
 
 lemma min_ennreal: "0 x ==> 0 y ==> min (ennreal x) (ennreal y) = ennreal (min x y)"
  by (auto split: split_min)
 
 lemma ennreal_half[simp]: "ennreal (1/2) = inverse 2"
  by transfer auto
 
 lemma ennreal_minus: "0 q ==> ennreal r - ennreal q = ennreal (r - q)"
  by transfer (simp add: zero_ereal_def flip: ereal_max)
 
 lemma ennreal_minus_top[simp]: "ennreal a - top = 0"
  by (simp add: minus_top_ennreal)
 
 lemma e2eenreal_enn2ereal_diff [simp]:
  "e2ennreal(enn2ereal x - enn2ereal y) = x - y" for x y
 by (cases x, cases y, auto simp add: ennreal_minus e2ennreal_neg)
 
 lemma ennreal_mult: "0 a ==> 0 b ==> ennreal (a * b) = ennreal a * ennreal b"
  by transfer (simp add: max_absorb2)
 
 lemma ennreal_mult': "0 a ==> ennreal (a * b) = ennreal a * ennreal b"
  by (cases "0 b") (auto simp: ennreal_mult ennreal_neg mult_nonneg_nonpos)
 
 lemma indicator_mult_ennreal: "indicator A x * ennreal r = ennreal (indicator A x * r)"
  by (simp split: split_indicator)
 
 lemma ennreal_mult'': "0 b ==> ennreal (a * b) = ennreal a * ennreal b"
  by (cases "0 a") (auto simp: ennreal_mult ennreal_neg mult_nonpos_nonneg)
 
 lemma numeral_mult_ennreal: "0 x ==> numeral b * ennreal x = ennreal (numeral b * x)"
  by (simp add: ennreal_mult)
 
 lemma ennreal_power: "0 r ==> ennreal r ^ n = ennreal (r ^ n)"
  by (induction n) (auto simp: ennreal_mult)
 
 lemma power_eq_top_ennreal: "x ^ n = top (n 0 (x::ennreal) = top)"
  using not_gr_zero power_eq_top_ennreal_iff by force
 
 lemma inverse_ennreal: "0 < r ==> inverse (ennreal r) = ennreal (inverse r)"
  by transfer (simp add: max.absorb2)
 
 lemma divide_ennreal: "0 r ==> 0 < q ==> ennreal r / ennreal q = ennreal (r / q)"
  by (simp add: divide_ennreal_def inverse_ennreal ennreal_mult[symmetric] inverse_eq_divide)
 
 lemma ennreal_inverse_power: "inverse (x ^ n :: ennreal) = inverse x ^ n"
 proof (cases x rule: ennreal_cases)
  case top with power_eq_top_ennreal[of x n] show ?thesis
  by (cases "n = 0") auto
 next
  case (real r) then show ?thesis
  proof (cases "x = 0")
  case False then show ?thesis
  by (smt (verit, best) ennreal_0 ennreal_power inverse_ennreal
  inverse_nonnegative_iff_nonnegative power_inverse real zero_less_power)
  qed (simp add: top_power_ennreal)
 qed
 
 lemma power_divide_distrib_ennreal [algebra_simps]:
  "(x / y) ^ n = x ^ n / (y ^ n :: ennreal)"
  by (simp add: divide_ennreal_def ennreal_inverse_power power_mult_distrib)
 
 lemma ennreal_divide_numeral: "0 x ==> ennreal x / numeral b = ennreal (x / numeral b)"
  by (subst divide_ennreal[symmetric]) auto
 
 lemma prod_ennreal: "(i. i A ==> 0 f i) ==> (iA. ennreal (f i)) = ennreal (prod f A)"
  by (induction A rule: infinite_finite_induct)
  (auto simp: ennreal_mult prod_nonneg)
 
 lemma prod_mono_ennreal:
  assumes "x. x A ==> f x (g x :: ennreal)"
  shows "prod f A prod g A"
  using assms by (induction A rule: infinite_finite_induct) (auto intro!: mult_mono)
 
 lemma mult_right_ennreal_cancel: "a * ennreal c = b * ennreal c (a = b c 0)"
  by (metis ennreal_eq_0_iff mult_divide_eq_ennreal mult_eq_0_iff top_neq_ennreal)
 
 lemma ennreal_le_epsilon:
  "(e::real. y < top ==> 0 < e ==> x y + ennreal e) ==> x y"
  apply (cases y rule: ennreal_cases)
  apply (cases x rule: ennreal_cases)
  apply (auto simp flip: ennreal_plus simp add: top_unique intro: zero_less_one field_le_epsilon)
  done
 
 lemma ennreal_rat_dense:
  fixes x y :: ennreal
  shows "x < y ==> r::rat. x < real_of_rat r real_of_rat r < y"
 proof transfer
  fix x y :: ereal assume xy: "0 x" "0 y" "x < y"
  moreover
  from ereal_dense3[OF x < y]
  obtain r where r: "x < ereal (real_of_rat r)" "ereal (real_of_rat r) < y"
  by auto
  then have "0 r"
  using le_less_trans[OF 0 x x < ereal (real_of_rat r)] by auto
  with r show "r. x < (sup 0 ereal) (real_of_rat r) (sup 0 ereal) (real_of_rat r) < y"
  by (intro exI[of _ r]) (auto simp: max_absorb2)
 qed
 
 lemma ennreal_Ex_less_of_nat: "(x::ennreal) < top ==> n. x < of_nat n"
  by (cases x rule: ennreal_cases)
  (auto simp: ennreal_of_nat_eq_real_of_nat ennreal_less_iff reals_Archimedean2)
 
 subsection Coercion from 🍋ennreal to 🍋real\
 
 definition "enn2real x = real_of_ereal (enn2ereal x)"
 
 lemma enn2real_nonneg[simp]: "0 enn2real x"
  by (auto simp: enn2real_def intro!: real_of_ereal_pos enn2ereal_nonneg)
 
 lemma enn2real_mono: "a b ==> b < top ==> enn2real a enn2real b"
  by (auto simp add: enn2real_def less_eq_ennreal.rep_eq intro!: real_of_ereal_positive_mono enn2ereal_nonneg)
 
 lemma enn2real_of_nat[simp]: "enn2real (of_nat n) = n"
  by (auto simp: enn2real_def)
 
 lemma enn2real_ennreal[simp]: "0 r ==> enn2real (ennreal r) = r"
  by (simp add: enn2real_def)
 
 lemma ennreal_enn2real[simp]: "r < top ==> ennreal (enn2real r) = r"
  by (cases r rule: ennreal_cases) auto
 
 lemma real_of_ereal_enn2ereal[simp]: "real_of_ereal (enn2ereal x) = enn2real x"
  by (simp add: enn2real_def)
 
 lemma enn2real_top[simp]: "enn2real top = 0"
  unfolding enn2real_def top_ennreal.rep_eq top_ereal_def by simp
 
 lemma enn2real_0[simp]: "enn2real 0 = 0"
  unfolding enn2real_def zero_ennreal.rep_eq by simp
 
 lemma enn2real_1[simp]: "enn2real 1 = 1"
  unfolding enn2real_def one_ennreal.rep_eq by simp
 
 lemma enn2real_numeral[simp]: "enn2real (numeral n) = (numeral n)"
  unfolding enn2real_def by simp
 
 lemma enn2real_mult: "enn2real (a * b) = enn2real a * enn2real b"
  unfolding enn2real_def
  by (simp del: real_of_ereal_enn2ereal add: times_ennreal.rep_eq)
 
 lemma enn2real_leI: "0 B ==> x ennreal B ==> enn2real x B"
  by (cases x rule: ennreal_cases) (auto simp: top_unique)
 
 lemma enn2real_positive_iff: "0 < enn2real x (0 < x x < top)"
  by (cases x rule: ennreal_cases) auto
 
 lemma enn2real_eq_posreal_iff[simp]: "c > 0 ==> enn2real x = c x = c"
  by (cases x) auto
 
 lemma ennreal_enn2real_if: "ennreal (enn2real r) = (if r = top then 0 else r)"
  by(auto intro!: ennreal_enn2real simp add: less_top)
 
 subsection Coercion from 🍋enat to 🍋ennreal\
 
 
 definition ennreal_of_enat :: "enat ==> ennreal"
 where
  "ennreal_of_enat n = (case n of ==> top | enat n ==> of_nat n)"
 
 declare [[coercion ennreal_of_enat]]
 declare [[coercion "of_nat :: nat ==> ennreal"]]
 
 lemma ennreal_of_enat_infty[simp]: "ennreal_of_enat = "
  by (simp add: ennreal_of_enat_def)
 
 lemma ennreal_of_enat_enat[simp]: "ennreal_of_enat (enat n) = of_nat n"
  by (simp add: ennreal_of_enat_def)
 
 lemma ennreal_of_enat_0[simp]: "ennreal_of_enat 0 = 0"
  using ennreal_of_enat_enat[of 0] unfolding enat_0 by simp
 
 lemma ennreal_of_enat_1[simp]: "ennreal_of_enat 1 = 1"
  using ennreal_of_enat_enat[of 1] unfolding enat_1 by simp
 
 lemma ennreal_top_neq_of_nat[simp]: "(top::ennreal) of_nat i"
  using ennreal_of_nat_neq_top[of i] by metis
 
 lemma ennreal_of_enat_inj[simp]: "ennreal_of_enat i = ennreal_of_enat j i = j"
  by (cases i j rule: enat.exhaust[case_product enat.exhaust]) auto
 
 lemma ennreal_of_enat_le_iff[simp]: "ennreal_of_enat m ennreal_of_enat n m n"
  by (auto simp: ennreal_of_enat_def top_unique split: enat.split)
 
 lemma of_nat_less_ennreal_of_nat[simp]: "of_nat n ennreal_of_enat x of_nat n x"
  by (cases x) (auto simp: of_nat_eq_enat)
 
 lemma ennreal_of_enat_Sup: "ennreal_of_enat (Sup X) = (SUP xX. ennreal_of_enat x)"
 proof -
  have "ennreal_of_enat (Sup X) (SUP x X. ennreal_of_enat x)"
  unfolding Sup_enat_def
  proof (clarsimp, intro conjI impI)
  fix x assume "finite X" "X {}"
  then show "ennreal_of_enat (Max X) (SUP x X. ennreal_of_enat x)"
  by (intro SUP_upper Max_in)
  next
  assume "infinite X" "X {}"
  have "yX. r < ennreal_of_enat y" if r: "r < top" for r
  proof -
  obtain n where n: "r < of_nat n"
  using ennreal_Ex_less_of_nat[OF r] ..
  have "¬ (X enat ` {.. n})"
  using infinite X by (auto dest: finite_subset)
  then obtain x where x: "x X" "x enat ` {..n}"
  by blast
  then have "of_nat n x"
  by (cases x) (auto simp: of_nat_eq_enat)
  with x show ?thesis
  by (auto intro!: bexI[of _ x] less_le_trans[OF n])
  qed
  then have "(SUP x X. ennreal_of_enat x) = top"
  by simp
  then show "top (SUP x X. ennreal_of_enat x)"
  unfolding top_unique by simp
  qed
  then show ?thesis
  by (auto intro!: antisym Sup_least intro: Sup_upper)
 qed
 
 lemma ennreal_of_enat_eSuc[simp]: "ennreal_of_enat (eSuc x) = 1 + ennreal_of_enat x"
  by (cases x) (auto simp: eSuc_enat)
 
(* Contributed by Dominique Unruh *)
lemma ennreal_of_enat_plus[simp]: ennreal_of_enat (a+b) = ennreal_of_enat a + ennreal_of_enat b
proof (induct a)
  case (enat nat)
  with enat.simps show ?case
    by (smt (verit, del_insts) add.commute add_top_left_ennreal enat.exhaust enat_defs(4) ennreal_of_enat_def of_nat_add)
qed auto

(* Contributed by Dominique Unruh *)
lemma sum_ennreal_of_enat[simp]: "(iI. ennreal_of_enat (f i)) = ennreal_of_enat (sum f I)"
  by (induct I rule: infinite_finite_induct) (auto simp: sum_nonneg)


subsection Topology on 🍋ennreal\
 
 lemma enn2ereal_Iio: "enn2ereal -` {.. a then {..< e2ennreal a} else {})"
  using enn2ereal_nonneg
  by (cases a rule: ereal_ennreal_cases)
  (auto simp add: vimage_def set_eq_iff ennreal.enn2ereal_inverse less_ennreal.rep_eq e2ennreal_def
  simp del: enn2ereal_nonneg
  intro: le_less_trans less_imp_le)
 
 lemma enn2ereal_Ioi: "enn2ereal -` {a <..} = (if 0 a then {e2ennreal a <..} else UNIV)"
  by (cases a rule: ereal_ennreal_cases)
  (auto simp add: vimage_def set_eq_iff ennreal.enn2ereal_inverse less_ennreal.rep_eq e2ennreal_def
  intro: less_le_trans)
 
 instantiation ennreal :: linear_continuum_topology
 begin
 
 definition open_ennreal :: "ennreal set ==> bool"
  where "(open :: ennreal set ==> bool) = generate_topology (range lessThan range greaterThan)"
 
 instance
 proof
  show "a b::ennreal. a b"
  using zero_neq_one by (intro exI)
  show "x y::ennreal. x < y ==> z>x. z < y"
  proof transfer
  fix x y :: ereal
  assume *: "0 x"
  assume "x < y"
  from dense[OF this] obtain z where "x < z z < y" ..
  with * show "zCollect (() 0). x < z z < y"
  by (intro bexI[of _ z]) auto
  qed
 qed (rule open_ennreal_def)
 
 end
 
 lemma continuous_on_e2ennreal: "continuous_on A e2ennreal"
 proof (rule continuous_on_subset)
  show "continuous_on ({0..} {..0}) e2ennreal"
  proof (rule continuous_on_closed_Un)
  show "continuous_on {0 ..} e2ennreal"
  by (simp add: continuous_onI_mono e2ennreal_mono enn2ereal_range)
  show "continuous_on {.. 0} e2ennreal"
  by (metis atMost_iff continuous_on_cong continuous_on_const e2ennreal_neg)
  qed auto
 qed auto
 
 lemma continuous_at_e2ennreal: "continuous (at x within A) e2ennreal"
  using continuous_on_e2ennreal continuous_on_imp_continuous_within top.extremum
  by blast
 
 lemma continuous_on_enn2ereal: "continuous_on UNIV enn2ereal"
  by (rule continuous_on_generate_topology[OF open_generated_order])
  (auto simp add: enn2ereal_Iio enn2ereal_Ioi)
 
 lemma continuous_at_enn2ereal: "continuous (at x within A) enn2ereal"
  by (meson UNIV_I continuous_at_imp_continuous_at_within
  continuous_on_enn2ereal continuous_on_eq_continuous_within)
 
 lemma sup_continuous_e2ennreal[order_continuous_intros]:
  assumes f: "sup_continuous f" shows "sup_continuous (λx. e2ennreal (f x))"
 proof (rule sup_continuous_compose[OF _ f])
  show "sup_continuous e2ennreal"
  by (simp add: continuous_at_e2ennreal continuous_at_left_imp_sup_continuous e2ennreal_mono mono_def)
 qed
 
 lemma sup_continuous_enn2ereal[order_continuous_intros]:
  assumes f: "sup_continuous f" shows "sup_continuous (λx. enn2ereal (f x))"
 proof (rule sup_continuous_compose[OF _ f])
  show "sup_continuous enn2ereal"
  by (simp add: continuous_at_enn2ereal continuous_at_left_imp_sup_continuous less_eq_ennreal.rep_eq mono_def)
 qed
 
 lemma sup_continuous_mult_left_ennreal':
  fixes c :: "ennreal"
  shows "sup_continuous (λx. c * x)"
  unfolding sup_continuous_def
  by transfer (auto simp: SUP_ereal_mult_left max.absorb2 SUP_upper2)
 
 lemma sup_continuous_mult_left_ennreal[order_continuous_intros]:
  "sup_continuous f ==> sup_continuous (λx. c * f x :: ennreal)"
  by (rule sup_continuous_compose[OF sup_continuous_mult_left_ennreal'])
 
 lemma sup_continuous_mult_right_ennreal[order_continuous_intros]:
  "sup_continuous f ==> sup_continuous (λx. f x * c :: ennreal)"
  using sup_continuous_mult_left_ennreal[of f c] by (simp add: mult.commute)
 
 lemma sup_continuous_divide_ennreal[order_continuous_intros]:
  fixes f g :: "'a::complete_lattice ==> ennreal"
  shows "sup_continuous f ==> sup_continuous (λx. f x / c)"
  unfolding divide_ennreal_def by (rule sup_continuous_mult_right_ennreal)
 
 lemma transfer_enn2ereal_continuous_on [transfer_rule]:
  "rel_fun (=) (rel_fun (rel_fun (=) pcr_ennreal) (=)) continuous_on continuous_on"
 proof -
  have "continuous_on A f" if "continuous_on A (λx. enn2ereal (f x))" for A and f :: "'a ==> ennreal"
  using continuous_on_compose2[OF continuous_on_e2ennreal[of "{0..}"] that]
  by (auto simp: ennreal.enn2ereal_inverse subset_eq e2ennreal_def max_absorb2)
  moreover
  have "continuous_on A (λx. enn2ereal (f x))" if "continuous_on A f" for A and f :: "'a ==> ennreal"
  using continuous_on_compose2[OF continuous_on_enn2ereal that] by auto
  ultimately
  show ?thesis
  by (auto simp add: rel_fun_def ennreal.pcr_cr_eq cr_ennreal_def)
 qed
 
 lemma transfer_sup_continuous[transfer_rule]:
  "(rel_fun (rel_fun (=) pcr_ennreal) (=)) sup_continuous sup_continuous"
 proof (safe intro!: rel_funI dest!: rel_fun_eq_pcr_ennreal[THEN iffD1])
  show "sup_continuous (enn2ereal f) ==> sup_continuous f" for f :: "'a ==> _"
  using sup_continuous_e2ennreal[of "enn2ereal f"] by simp
  show "sup_continuous f ==> sup_continuous (enn2ereal f)" for f :: "'a ==> _"
  using sup_continuous_enn2ereal[of f] by (simp add: comp_def)
 qed
 
 lemma continuous_on_ennreal[tendsto_intros]:
  "continuous_on A f ==> continuous_on A (λx. ennreal (f x))"
  by transfer (auto intro!: continuous_on_max continuous_on_const continuous_on_ereal)
 
 lemma tendsto_ennrealD:
  assumes lim: "((λx. ennreal (f x)) ---> ennreal x) F"
  assumes *: "🪙F x in F. 0 f x" and x: "0 x"
  shows "(f ---> x) F"
 proof -
  have "((λx. enn2ereal (ennreal (f x))) ---> enn2ereal (ennreal x)) F
  (f ---> enn2ereal (ennreal x)) F"
  using "*" eventually_mono
  by (intro tendsto_cong) fastforce
  then show ?thesis
  using assms(1) continuous_at_enn2ereal isCont_tendsto_compose x by fastforce
 qed
 
 lemma tendsto_ennreal_iff [simp]:
  ((λx. ennreal (f x)) ---> ennreal x) F (f ---> x) F (is ?P ?Q)
  if 🪙F x in F. 0 f x 0 x
 proof
  assume ?P
  then show ?Q
  using that by (rule tendsto_ennrealD)
 next
  assume ?Q
  have continuous_on UNIV ereal
  using continuous_on_ereal [of _ id] by simp
  then have continuous_on UNIV (e2ennreal ereal)
  by (rule continuous_on_compose) (simp_all add: continuous_on_e2ennreal)
  then have ((λx. (e2ennreal ereal) (f x)) ---> (e2ennreal ereal) x) F
  using ?Q by (rule continuous_on_tendsto_compose) simp_all
  then show ?P
  by (simp flip: e2ennreal_ereal)
 qed
 
 lemma tendsto_enn2ereal_iff[simp]: "((λi. enn2ereal (f i)) ---> enn2ereal x) F (f ---> x) F"
  using continuous_on_enn2ereal[THEN continuous_on_tendsto_compose, of f x F]
  continuous_on_e2ennreal[THEN continuous_on_tendsto_compose, of "λx. enn2ereal (f x)" "enn2ereal x" F UNIV]
  by auto
 
 lemma ennreal_tendsto_0_iff: "(n. f n 0) ==> ((λn. ennreal (f n)) <---- 0) (f <---- 0)"
  by (metis (mono_tags) ennreal_0 eventuallyI order_refl tendsto_ennreal_iff)
 
 lemma continuous_on_add_ennreal:
  fixes f g :: "'a::topological_space ==> ennreal"
  shows "continuous_on A f ==> continuous_on A g ==> continuous_on A (λx. f x + g x)"
  by (transfer fixing: A) (auto intro!: tendsto_add_ereal_nonneg simp: continuous_on_def)
 
 lemma continuous_on_inverse_ennreal[continuous_intros]:
  fixes f :: "'a::topological_space ==> ennreal"
  shows "continuous_on A f ==> continuous_on A (λx. inverse (f x))"
 proof (transfer fixing: A)
  show "pred_fun top (() 0) f ==> continuous_on A (λx. inverse (f x))" if "continuous_on A f"
  for f :: "'a ==> ereal"
  using continuous_on_compose2[OF continuous_on_inverse_ereal that] by (auto simp: subset_eq)
 qed
 
 instance ennreal :: topological_comm_monoid_add
 proof
  show "((λx. fst x + snd x) ---> a + b) (nhds a ×🪙F nhds b)" for a b :: ennreal
  using continuous_on_add_ennreal[of UNIV fst snd]
  using tendsto_at_iff_tendsto_nhds[symmetric, of "λx::(ennreal × ennreal). fst x + snd x"]
  by (auto simp: continuous_on_eq_continuous_at)
  (simp add: isCont_def nhds_prod[symmetric])
 qed
 
 lemma sup_continuous_add_ennreal[order_continuous_intros]:
  fixes f g :: "'a::complete_lattice ==> ennreal"
  shows "sup_continuous f ==> sup_continuous g ==> sup_continuous (λx. f x + g x)"
  by transfer (auto intro!: sup_continuous_add)
 
 lemma ennreal_suminf_lessD: "(i. f i :: ennreal) < x ==> f i < x"
  using le_less_trans[OF sum_le_suminf[OF summableI, of "{i}" f]] by simp
 
 lemma sums_ennreal[simp]: "(i. 0 f i) ==> 0 x ==> (λi. ennreal (f i)) sums ennreal x f sums x"
  unfolding sums_def by (simp add: always_eventually sum_nonneg)
 
 lemma summable_suminf_not_top: "(i. 0 f i) ==> (i. ennreal (f i)) top ==> summable f"
  using summable_sums[OF summableI, of "λi. ennreal (f i)"]
  by (cases "i. ennreal (f i)" rule: ennreal_cases)
  (auto simp: summable_def)
 
 lemma suminf_ennreal[simp]:
  "(i. 0 f i) ==> (i. ennreal (f i)) top ==> (i. ennreal (f i)) = ennreal (i. f i)"
  by (rule sums_unique[symmetric]) (simp add: summable_suminf_not_top suminf_nonneg summable_sums)
 
 lemma sums_enn2ereal[simp]: "(λi. enn2ereal (f i)) sums enn2ereal x f sums x"
  unfolding sums_def by (simp add: always_eventually sum_nonneg)
 
 lemma suminf_enn2ereal[simp]: "(i. enn2ereal (f i)) = enn2ereal (suminf f)"
  by (metis summableI summable_sums sums_enn2ereal sums_unique)
 
 lemma transfer_e2ennreal_suminf [transfer_rule]: "rel_fun (rel_fun (=) pcr_ennreal) pcr_ennreal suminf suminf"
  by (auto simp: rel_funI rel_fun_eq_pcr_ennreal comp_def)
 
 lemma ennreal_suminf_cmult[simp]: "(i. r * f i) = r * (i. f i::ennreal)"
  by transfer (auto intro!: suminf_cmult_ereal)
 
 lemma ennreal_suminf_multc[simp]: "(i. f i * r) = (i. f i::ennreal) * r"
  using ennreal_suminf_cmult[of r f] by (simp add: ac_simps)
 
 lemma ennreal_suminf_divide[simp]: "(i. f i / r) = (i. f i::ennreal) / r"
  by (simp add: divide_ennreal_def)
 
 lemma ennreal_suminf_neq_top: "summable f ==> (i. 0 f i) ==> (i. ennreal (f i)) top"
  using sums_ennreal[of f "suminf f"]
  by (simp add: suminf_nonneg flip: sums_unique summable_sums_iff del: sums_ennreal)
 
 lemma suminf_ennreal_eq:
  "(i. 0 f i) ==> f sums x ==> (i. ennreal (f i)) = ennreal x"
  using suminf_nonneg[of f] sums_unique[of f x]
  by (intro sums_unique[symmetric]) (auto simp: summable_sums_iff)
 
 lemma ennreal_suminf_bound_add:
  fixes f :: "nat ==> ennreal"
  shows "(N. (n x) ==> suminf f + y x"
  by transfer (auto intro!: suminf_bound_add)
 
 lemma ennreal_suminf_SUP_eq_directed:
  fixes f :: "'a ==> nat ==> ennreal"
  assumes *: "N i j. i I ==> j I ==> finite N ==> kI. nN. f i n f k n f j n f k n"
  shows "(n. SUP iI. f i n) = (SUP iI. n. f i n)"
 proof cases
  assume "I {}"
  then obtain i where "i I" by auto
  from * show ?thesis
  by (transfer fixing: I)
  (auto simp: max_absorb2 SUP_upper2[OF i I] suminf_nonneg summable_ereal_pos I {}
  intro!: suminf_SUP_eq_directed)
 qed (simp add: bot_ennreal)
 
 lemma INF_ennreal_add_const:
  fixes f g :: "nat ==> ennreal"
  shows "(INF i. f i + c) = (INF i. f i) + c"
  using continuous_at_Inf_mono[of "λx. x + c" "f`UNIV"]
  using continuous_add[of "at_right (Inf (range f))", of "λx. x" "λx. c"]
  by (auto simp: mono_def image_comp)
 
 lemma INF_ennreal_const_add:
  fixes f g :: "nat ==> ennreal"
  shows "(INF i. c + f i) = c + (INF i. f i)"
  using INF_ennreal_add_const[of f c] by (simp add: ac_simps)
 
 lemma SUP_mult_left_ennreal: "c * (SUP iI. f i) = (SUP iI. c * f i ::ennreal)"
 proof cases
  assume "I {}" then show ?thesis
  by transfer (auto simp add: SUP_ereal_mult_left max_absorb2 SUP_upper2)
 qed (simp add: bot_ennreal)
 
 lemma SUP_mult_right_ennreal: "(SUP iI. f i) * c = (SUP iI. f i * c ::ennreal)"
  using SUP_mult_left_ennreal by (simp add: mult.commute)
 
 lemma SUP_divide_ennreal: "(SUP iI. f i) / c = (SUP iI. f i / c ::ennreal)"
  using SUP_mult_right_ennreal by (simp add: divide_ennreal_def)
 
 lemma ennreal_SUP_of_nat_eq_top: "(SUP x. of_nat x :: ennreal) = top"
 proof (intro antisym top_greatest le_SUP_iff[THEN iffD2] allI impI)
  fix y :: ennreal assume "y < top"
  then obtain r where "y = ennreal r"
  by (cases y rule: ennreal_cases) auto
  then show "iUNIV. y < of_nat i"
  using reals_Archimedean2[of "max 1 r"] zero_less_one
  by (simp add: ennreal_Ex_less_of_nat)
 qed
 
 lemma ennreal_SUP_eq_top:
  fixes f :: "'a ==> ennreal"
  assumes "n. iI. of_nat n f i"
  shows "(SUP i I. f i) = top"
 proof -
  have "(SUP x. of_nat x :: ennreal) (SUP i I. f i)"
  using assms by (auto intro!: SUP_least intro: SUP_upper2)
  then show ?thesis
  by (auto simp: ennreal_SUP_of_nat_eq_top top_unique)
 qed
 
 lemma ennreal_INF_const_minus:
  fixes f :: "'a ==> ennreal"
  shows "I {} ==> (SUP xI. c - f x) = c - (INF xI. f x)"
  by (transfer fixing: I)
  (simp add: sup_max[symmetric] SUP_sup_const1 SUP_ereal_minus_right del: sup_ereal_def)
 
 lemma of_nat_Sup_ennreal:
  assumes "A {}" "bdd_above A"
  shows "of_nat (Sup A) = (SUP aA. of_nat a :: ennreal)"
 proof (intro antisym)
  show "(SUP aA. of_nat a::ennreal) of_nat (Sup A)"
  by (intro SUP_least of_nat_mono) (auto intro: cSup_upper assms)
  have "Sup A A"
  using assms by (auto simp: Sup_nat_def bdd_above_nat)
  then show "of_nat (Sup A) (SUP aA. of_nat a::ennreal)"
  by (intro SUP_upper)
 qed
 
 lemma ennreal_tendsto_const_minus:
  fixes g :: "'a ==> ennreal"
  assumes ae: "🪙F x in F. g x c"
  assumes g: "((λx. c - g x) ---> 0) F"
  shows "(g ---> c) F"
 proof (cases c rule: ennreal_cases)
  case top with tendsto_unique[OF _ g, of "top"] show ?thesis
  by (cases "F = bot") auto
 next
  case (real r)
  then have "x. q0. g x c (g x = ennreal q q r)"
  by (auto simp: le_ennreal_iff)
  then obtain f where *: "0 f x" "g x = ennreal (f x)" "f x r" if "g x c" for x
  by metis
  from ae have ae2: "🪙F x in F. c - g x = ennreal (r - f x) f x r g x = ennreal (f x) 0 f x"
  proof eventually_elim
  fix x assume "g x c" with *[of x] 0 r show "c - g x = ennreal (r - f x) f x r g x = ennreal (f x) 0 f x"
  by (auto simp: real ennreal_minus)
  qed
  with g have "((λx. ennreal (r - f x)) ---> ennreal 0) F"
  by (auto simp add: tendsto_cong eventually_conj_iff)
  with ae2 have "((λx. r - f x) ---> 0) F"
  by (subst (asm) tendsto_ennreal_iff) (auto elim: eventually_mono)
  then have "(f ---> r) F"
  by (rule Lim_transform2[OF tendsto_const])
  with ae2 have "((λx. ennreal (f x)) ---> ennreal r) F"
  by (subst tendsto_ennreal_iff) (auto elim: eventually_mono simp: real)
  with ae2 show ?thesis
  by (auto simp: real tendsto_cong eventually_conj_iff)
 qed
 
 lemma ennreal_SUP_add:
  fixes f g :: "nat ==> ennreal"
  shows "incseq f ==> incseq g ==> (SUP i. f i + g i) = Sup (f ` UNIV) + Sup (g ` UNIV)"
  unfolding incseq_def le_fun_def
  by transfer
  (simp add: SUP_ereal_add incseq_def le_fun_def max_absorb2 SUP_upper2)
 
 lemma ennreal_SUP_sum:
  fixes f :: "'a ==> nat ==> ennreal"
  shows "(i. i I ==> incseq (f i)) ==> (SUP n. iI. f i n) = (iI. SUP n. f i n)"
  unfolding incseq_def
  by transfer
  (simp add: SUP_ereal_sum incseq_def SUP_upper2 max_absorb2 sum_nonneg)
 
 lemma ennreal_liminf_minus:
  fixes f :: "nat ==> ennreal"
  shows "(n. f n c) ==> liminf (λn. c - f n) = c - limsup f"
  apply transfer
  apply (simp add: ereal_diff_positive liminf_ereal_cminus)
  by (metis max.absorb2 ereal_diff_positive Limsup_bounded eventually_sequentiallyI)
 
 lemma ennreal_continuous_on_cmult:
  "(c::ennreal) < top ==> continuous_on A f ==> continuous_on A (λx. c * f x)"
  by (transfer fixing: A) (auto intro: continuous_on_cmult_ereal)
 
 lemma ennreal_tendsto_cmult:
  "(c::ennreal) < top ==> (f ---> x) F ==> ((λx. c * f x) ---> c * x) F"
  by (rule continuous_on_tendsto_compose[where g=f, OF ennreal_continuous_on_cmult, where s=UNIV])
  (auto simp: continuous_on_id)
 
 lemma tendsto_ennrealI[intro, simp, tendsto_intros]:
  "(f ---> x) F ==> ((λx. ennreal (f x)) ---> ennreal x) F"
  by (auto simp: ennreal_def
  intro!: continuous_on_tendsto_compose[OF continuous_on_e2ennreal[of UNIV]] tendsto_max)
 
 lemma tendsto_enn2erealI [tendsto_intros]:
  assumes "(f ---> l) F"
  shows "((λi. enn2ereal(f i)) ---> enn2ereal l) F"
 using tendsto_enn2ereal_iff assms by auto
 
 lemma tendsto_e2ennrealI [tendsto_intros]:
  assumes "(f ---> l) F"
  shows "((λi. e2ennreal(f i)) ---> e2ennreal l) F"
 proof -
  have *: "e2ennreal (max x 0) = e2ennreal x" for x
  by (simp add: e2ennreal_def max.commute)
  have "((λi. max (f i) 0) ---> max l 0) F"
  using assms by (intro tendsto_intros) auto
  then have "((λi. enn2ereal(e2ennreal (max (f i) 0))) ---> enn2ereal (e2ennreal (max l 0))) F"
  by (subst enn2ereal_e2ennreal, auto)+
  then have "((λi. e2ennreal (max (f i) 0)) ---> e2ennreal (max l 0)) F"
  using tendsto_enn2ereal_iff by auto
  then show ?thesis
  unfolding * by auto
 qed
 
 lemma ennreal_suminf_minus:
  fixes f g :: "nat ==> ennreal"
  shows "(i. g i f i) ==> suminf f top ==> suminf g top ==> (i. f i - g i) = suminf f - suminf g"
  by transfer
  (auto simp add: ereal_diff_positive suminf_le_pos top_ereal_def intro!: suminf_ereal_minus)
 
 lemma ennreal_Sup_countable_SUP:
  "A {} ==> f::nat ==> ennreal. incseq f range f A Sup A = (SUP i. f i)"
  unfolding incseq_def
  apply transfer
  subgoal for A
  using Sup_countable_SUP[of A]
  by (force simp add: incseq_def[symmetric] SUP_upper2 image_subset_iff Sup_upper2 cong: conj_cong)
  done
 
 lemma ennreal_Inf_countable_INF:
  "A {} ==> f::nat ==> ennreal. decseq f range f A Inf A = (INF i. f i)"
  unfolding decseq_def
  apply transfer
  subgoal for A
  using Inf_countable_INF[of A] by (simp flip: decseq_def) blast
  done
 
 lemma ennreal_SUP_countable_SUP:
  "A {} ==> f::nat ==> ennreal. range f g`A Sup (g ` A) = Sup (f ` UNIV)"
  using ennreal_Sup_countable_SUP [of "g`A"] by auto
 
 lemma of_nat_tendsto_top_ennreal: "(λn::nat. of_nat n :: ennreal) <---- top"
  using LIMSEQ_SUP[of "of_nat :: nat ==> ennreal"]
  by (simp add: ennreal_SUP_of_nat_eq_top incseq_def)
 
 lemma SUP_sup_continuous_ennreal:
  fixes f :: "ennreal ==> 'a::complete_lattice"
  assumes f: "sup_continuous f" and "I {}"
  shows "(SUP iI. f (g i)) = f (SUP iI. g i)"
 proof (rule antisym)
  show "(SUP iI. f (g i)) f (SUP iI. g i)"
  by (rule mono_SUP[OF sup_continuous_mono[OF f]])
  from ennreal_Sup_countable_SUP[of "g`I"] I {}
  obtain M :: "nat ==> ennreal" where "incseq M" and M: "range M g ` I" and eq: "(SUP i I. g i) = (SUP i. M i)"
  by auto
  have "f (SUP i I. g i) = (SUP i range M. f i)"
  unfolding eq sup_continuousD[OF f mono M] by (simp add: image_comp)
  also have " (SUP i I. f (g i))"
  by (smt (verit) M SUP_le_iff dual_order.refl image_iff subsetD)
  finally show "f (SUP i I. g i) (SUP i I. f (g i))" .
 qed
 
 lemma ennreal_suminf_SUP_eq:
  fixes f :: "nat ==> nat ==> ennreal"
  shows "(i. incseq (λn. f n i)) ==> (i. SUP n. f n i) = (SUP n. i. f n i)"
  by (metis ennreal_suminf_SUP_eq_directed incseqD nat_le_linear)
 
 lemma ennreal_SUP_add_left:
  fixes c :: ennreal
  shows "I {} ==> (SUP iI. f i + c) = (SUP iI. f i) + c"
  apply transfer
  apply (simp add: SUP_ereal_add_left)
  by (metis SUP_upper all_not_in_conv add_increasing2 max.absorb2 max.bounded_iff)
 
 lemma ennreal_SUP_const_minus:
  fixes f :: "'a ==> ennreal"
  shows "I {} ==> c < top ==> (INF xI. c - f x) = c - (SUP xI. f x)"
  apply (transfer fixing: I)
  unfolding ex_in_conv[symmetric]
  apply (auto simp add: SUP_upper2 sup_absorb2 simp flip: sup_ereal_def)
  apply (subst INF_ereal_minus_right[symmetric])
  apply (auto simp del: sup_ereal_def simp add: sup_INF)
  done
 
(* Contributed by Dominique Unruh *)
lemma isCont_ennreal[simp]: isCont ennreal x
  unfolding continuous_within tendsto_def
  using tendsto_ennrealI topological_tendstoD
  by (blast intro: sequentially_imp_eventually_within)

(* Contributed by Dominique Unruh *)
lemma isCont_ennreal_of_enat[simp]: isCont ennreal_of_enat x
proof -
  have continuous_at_open:
    🍋 Copied lemma from 🪙HOL-Analysis to avoid dependency.
      "continuous (at x) f  (t. open t  f x  t --> (s. open s  x  s  (x'  s. (f x')  t)))" for f :: enat ==> 'z::topological_space
    unfolding continuous_within_topological [of x UNIV f]
    unfolding imp_conjL
    by (intro all_cong imp_cong ex_cong conj_cong refl) auto
  show ?thesis
  proof (subst continuous_at_open, intro allI impI, cases x = )
    case True

    fix t assume open t ennreal_of_enat x t
    then have y<. {y <.. } t
      by (rule_tac open_left[where y=0]) (auto simp: True)
    then obtain y where {y<..} t and y
      by fastforce
    from y
    obtain x' where x'y: ennreal_of_enat x' > y and x'
      by (metis enat.simps(3) ennreal_Ex_less_of_nat ennreal_of_enat_enat infinity_ennreal_def top.not_eq_extremum)
    define s where s = {x'<..}
    have open s
      by (simp add: s_def)
    moreover have x s
      by (simp add: x' s_def True)
    moreover have ennreal_of_enat z t if z s for z
      by (metis x'y {y<..} t ennreal_of_enat_le_iff greaterThan_iff le_less_trans less_imp_le not_less s_def subsetD that)
    ultimately show s. open s x s (zs. ennreal_of_enat z t)
      by auto
  next
    case False
    fix t assume asm: open t ennreal_of_enat x t
    define s where s = {x}
    have open s
      using False open_enat_iff s_def by blast
    then show s. open s x s (zs. ennreal_of_enat z t)
      using asm s_def by blast
  qed
qed

subsection Approximation lemmas

lemma INF_approx_ennreal:
  fixes x::ennreal and e::real
  assumes "e > 0"
  assumes "x = (INF i  A. f i)"
  assumes " "
  shows " A. f i < x + e"
  using INF_less_iff assms by fastforce

lemma SUP_approx_ennreal:
  fixes x::ennreal and e::real
  assumes "e > 0" " {}"
  assumes SUP: "x = (SUP i  A. f i)"
  assumes " "
  shows " A. x < f i + e"
proof -
  have "x < x + e"
    using 0 x by (cases x) auto
  also have "x + e = (SUP i  A. f i + e)"
    unfolding SUP ennreal_SUP_add_left[OF A {}] ..
  finally show ?thesis
    unfolding less_SUP_iff .
qed

lemma ennreal_approx_SUP:
  fixes x::ennreal
  assumes f_bound: "i. i  A ==> f i  x"
  assumes approx: "e. (e::real) > 0 ==>  A. x  f i + e"
  shows "x = (SUP i  A. f i)"
proof (rule antisym)
  show " (SUP iA. f i)"
  proof (rule ennreal_le_epsilon)
    fix e :: real assume "0 < e"
    from approx[OF this] obtain i where " A" and *: " f i + ennreal e"
      by blast
    from * have " f i + e"
      by simp
    also have "  (SUP iA. f i) + e"
      by (intro add_mono i A SUP_upper order_refl)
    finally show " (SUP iA. f i) + e" .
  qed
qed (intro SUP_least f_bound)

lemma ennreal_approx_INF:
  fixes x::ennreal
  assumes f_bound: "i. i  A ==> x  f i"
  assumes approx: "e. (e::real) > 0 ==>  A. f i  x + e"
  shows "x = (INF i  A. f i)"
proof (rule antisym)
  show "(INF iA. f i)  x"
  proof (rule ennreal_le_epsilon)
    fix e :: real assume "0 < e"
    from approx[OF this] obtain i where "iA" "f i  x + ennreal e"
      by blast
    then have "(INF iA. f i)  f i"
      by (intro INF_lower)
    also have "  x + e"
      by fact
    finally show "(INF iA. f i)  x + e" .
  qed
qed (intro INF_greatest f_bound)

lemma ennreal_approx_unit:
  "(a::ennreal. 0 < a ==> a < 1 ==> a * z  y) ==> z  y"
  using SUP_mult_right_ennreal[of "λx. x" "{0 <..< 1}" z]
  by (smt (verit) SUP_least Sup_greaterThanLessThan greaterThanLessThan_iff
      image_ident mult_1 zero_less_one)

lemma suminf_ennreal2:
  "(i. 0  f i) ==> summable f ==> (i. ennreal (f i)) = ennreal (i. f i)"
  using suminf_ennreal_eq by blast

lemma less_top_ennreal: "x < top  (r0. x = ennreal r)"
  by (cases x) auto

lemma enn2real_less_iff[simp]: "x < top ==> enn2real x < c  x < c"
  using ennreal_less_iff less_top_ennreal by auto

lemma enn2real_le_iff[simp]: "[x < top; c > 0] ==> enn2real x  c  x  c"
  by (cases x) auto

lemma enn2real_less:
  assumes "enn2real e < r" " top" shows "e < ennreal r"
  using enn2real_less_iff assms top.not_eq_extremum by blast

lemma enn2real_le:
  assumes "enn2real e  r" " top" shows " ennreal r"
  by (metis assms enn2real_less ennreal_enn2real_if eq_iff less_le)

lemma tendsto_top_iff_ennreal:
  fixes f :: "'a ==> ennreal"
  shows "(f ---> top) F  (l0. eventually (λx. ennreal l < f x) F)"
  by (auto simp: less_top_ennreal order_tendsto_iff )

lemma ennreal_tendsto_top_eq_at_top:
  "((λz. ennreal (f z)) ---> top) F  (LIM z F. f z :> at_top)"
  unfolding filterlim_at_top_dense tendsto_top_iff_ennreal
  using ennreal_less_iff eventually_mono allE[of _ "max 0 _"]
  by (smt (verit) linorder_not_less order_refl order_trans)

lemma tendsto_0_if_Limsup_eq_0_ennreal:
  fixes f :: "==> ennreal"
  shows "Limsup F f = 0 ==> (f ---> 0) F"
  using Liminf_le_Limsup[of F f] tendsto_iff_Liminf_eq_Limsup[of F f 0]
  by (cases "F = bot") auto

lemma diff_le_self_ennreal[simp]: "a - b  (a::ennreal)"
  by (cases a b rule: ennreal2_cases) (auto simp: ennreal_minus)

lemma ennreal_ineq_diff_add: " a ==> a = b + (a - b::ennreal)"
  by transfer (auto simp: ereal_diff_positive max.absorb2 ereal_ineq_diff_add)

lemma ennreal_mult_strict_left_mono: "(a::ennreal) < c ==> 0 < b ==> b < top ==> b * a < b * c"
  by transfer (auto intro!: ereal_mult_strict_left_mono)

lemma ennreal_between: "0 < e ==> 0 < x ==> x < top ==> x - e < (x::ennreal)"
  by transfer (auto intro!: ereal_between)

lemma minus_less_iff_ennreal: "b < top ==> b  a ==> a - b < c  a < c + (b::ennreal)"
  by transfer
     (auto simp: top_ereal_def ereal_minus_less le_less)

lemma tendsto_zero_ennreal:
  assumes ev: "r. 0 < r ==> 🪙F x in F. f x < ennreal r"
  shows "(f ---> 0) F"
proof (rule order_tendstoI)
  fix e::ennreal assume "e > 0"
  obtain e'::real where "e' > 0" "ennreal e' < e"
    using 0 < e dense[of 0 "if e = top then 1 else (enn2real e)"]
    by (cases e) (auto simp: ennreal_less_iff)
  from ev[OF e' > 0] show "🪙F x in F. f x < e"
    by eventually_elim (insert ennreal e' < e, auto)
qed simp

lifting_update ennreal.lifting
lifting_forget ennreal.lifting


subsection 🍋ennreal theorems

lemma neq_top_trans: fixes x y :: ennreal shows "[ y  top; x  y ] ==> x  top"
  by (auto simp: top_unique)

lemma diff_diff_ennreal: fixes a b :: ennreal shows " b ==> b   ==> b - (b - a) = a"
  by (cases a b rule: ennreal2_cases) (auto simp: ennreal_minus top_unique)

lemma ennreal_less_one_iff[simp]: "ennreal x < 1  x < 1"
  by (cases " x") (auto simp: ennreal_neg ennreal_less_iff simp flip: ennreal_1)

lemma SUP_const_minus_ennreal:
  fixes f :: "'a ==> ennreal" shows " {} ==> (SUP xI. c - f x) = c - (INF xI. f x)"
  including ennreal.lifting
  by (transfer fixing: I)
     (simp add: SUP_sup_distrib[symmetric] SUP_ereal_minus_right
           flip: sup_ereal_def)

lemma zero_minus_ennreal[simp]: "0 - (a::ennreal) = 0"
  including ennreal.lifting
  by transfer (simp split: split_max)

lemma diff_diff_commute_ennreal:
  fixes a b c :: ennreal shows "a - b - c = a - c - b"
  by (cases a b c rule: ennreal3_cases) (simp_all add: ennreal_minus field_simps)

lemma diff_gr0_ennreal: "b < (a::ennreal) ==> 0 < a - b"
  including ennreal.lifting by transfer (auto simp: ereal_diff_gr0 ereal_diff_positive split: split_max)

lemma divide_le_posI_ennreal:
  fixes x y z :: ennreal
  shows "x > 0 ==> z  x * y ==> z / x  y"
  by (cases x y z rule: ennreal3_cases)
     (auto simp: divide_ennreal ennreal_mult[symmetric] field_simps top_unique)

lemma add_diff_eq_ennreal:
  fixes x y z :: ennreal
  shows " y ==> x + (y - z) = x + y - z"
  using ennreal_diff_add_assoc by auto

lemma add_diff_inverse_ennreal:
  fixes x y :: ennreal shows " y ==> x + (y - x) = y"
  by (cases x) (simp_all add: top_unique add_diff_eq_ennreal)

lemma add_diff_eq_iff_ennreal[simp]:
  fixes x y :: ennreal shows "x + (y - x) = y  x  y"
  by (metis ennreal_ineq_diff_add le_iff_add)

lemma add_diff_le_ennreal: "a + b - c  a + (b - c::ennreal)"
  apply (cases a b c rule: ennreal3_cases)
  subgoal for a' b' c'
    by (cases " b' - c'") (simp_all add: ennreal_minus top_add ennreal_neg flip: ennreal_plus)
  apply (simp_all add: top_add flip: ennreal_plus)
  done

lemma diff_eq_0_ennreal: "a < top ==> a  b ==> a - b = (0::ennreal)"
  using ennreal_minus_pos_iff gr_zeroI not_less by blast

lemma diff_diff_ennreal': fixes x y z :: ennreal shows " y ==> y - z  x ==> x - (y - z) = x + z - y"
  by (cases x; cases y; cases z)
     (auto simp add: top_add add_top minus_top_ennreal ennreal_minus top_unique
           simp flip: ennreal_plus)

lemma diff_diff_ennreal'': fixes x y z :: ennreal
  shows " y ==> x - (y - z) = (if y - z  x then x + z - y else 0)"
  by (cases x; cases y; cases z)
     (auto simp add: top_add add_top minus_top_ennreal ennreal_minus top_unique ennreal_neg
           simp flip: ennreal_plus)

lemma power_less_top_ennreal: fixes x :: ennreal shows "x ^ n < top  x < top  n = 0"
  using power_eq_top_ennreal top.not_eq_extremum
  by blast

lemma ennreal_divide_times: "(a / b) * c = a * (c / b :: ennreal)"
  by (simp add: mult.commute ennreal_times_divide)

lemma diff_less_top_ennreal: "a - b < top   a < (top :: ennreal)"
  by (cases a; cases b) (auto simp: ennreal_minus)

lemma divide_less_ennreal: " 0 ==> b < top ==> a / b < c  a < (c * b :: ennreal)"
  by (cases a; cases b; cases c)
     (auto simp: divide_ennreal ennreal_mult[symmetric] ennreal_less_iff field_simps ennreal_top_mult ennreal_top_divide)

lemma one_less_numeral[simp]: "1 < (numeral n::ennreal)  (num.One < n)"
  by simp

lemma divide_eq_1_ennreal: "a / b = (1::ennreal)  (b  top  b  0  b = a)"
  by (cases a ; cases b; cases "b = 0") (auto simp: ennreal_top_divide divide_ennreal split: if_split_asm)

lemma ennreal_mult_cancel_left: "(a * b = a * c) = (a = top  b  0  c  0  a = 0  b = (c::ennreal))"
  by (cases a; cases b; cases c) (auto simp: ennreal_mult[symmetric] ennreal_mult_top ennreal_top_mult)

lemma ennreal_minus_if: "ennreal a - ennreal b = ennreal (if 0  b then (if b  a then a - b else 0) else a)"
  by (auto simp: ennreal_minus ennreal_neg)

lemma ennreal_plus_if: "ennreal a + ennreal b = ennreal (if 0  a then (if 0  b then a + b else a) else b)"
  by (auto simp: ennreal_neg)

lemma ennreal_diff_le_mono_left: " b ==> a - c  (b::ennreal)"
  using ennreal_mono_minus[of 0 c a, THEN order_trans, of b] by simp

lemma ennreal_minus_le_iff: "a - b  c  (a  b + (c::ennreal)  (a = top  b = top  c = top))"
  by (cases a; cases b; cases c)
     (auto simp: top_unique top_add add_top ennreal_minus simp flip: ennreal_plus)

lemma ennreal_le_minus_iff: " b - c  (a + c  (b::ennreal)  (a = 0  b  c))"
  by (cases a; cases b; cases c)
     (auto simp: top_unique top_add add_top ennreal_minus ennreal_le_iff2
           simp flip: ennreal_plus)

lemma diff_add_eq_diff_diff_swap_ennreal: "x - (y + z :: ennreal) = x - y - z"
  by (cases x; cases y; cases z)
     (auto simp: ennreal_minus_if add_top top_add simp flip: ennreal_plus)

lemma diff_add_assoc2_ennreal: " a ==> (a - b + c::ennreal) = a + c - b"
  by (cases a; cases b; cases c)
     (auto simp add: ennreal_minus_if ennreal_plus_if add_top top_add top_unique simp del: ennreal_plus)

lemma diff_gt_0_iff_gt_ennreal: "0 < a - b  (a = top  b = top  b < (a::ennreal))"
  by (cases a; cases b) (auto simp: ennreal_minus_if ennreal_less_iff)

lemma diff_eq_0_iff_ennreal: "(a - b::ennreal) = 0  (a < top  a  b)"
  by (cases a) (auto simp: ennreal_minus_eq_0 diff_eq_0_ennreal)

lemma add_diff_self_ennreal: "a + (b - a::ennreal) = (if a  b then b else a)"
  by (auto simp: diff_eq_0_iff_ennreal less_top)

lemma diff_add_self_ennreal: "(b - a + a::ennreal) = (if a  b then b else a)"
  by (auto simp: diff_add_cancel_ennreal diff_eq_0_iff_ennreal less_top)

lemma ennreal_minus_cancel_iff:
  fixes a b c :: ennreal
  shows "a - b = a - c  (b = c  (a  b  a  c)  a = top)"
  by (cases a; cases b; cases c) (auto simp: ennreal_minus_if)

text The next lemma is wrong for $a = top$, for $b = c = 1$ for instance.

lemma ennreal_right_diff_distrib:
  fixes a b c :: ennreal
  assumes " top"
  shows "a * (b - c) = a * b - a * c"
  apply (cases a; cases b; cases c)
         apply (use assms in auto simp add: ennreal_mult_top ennreal_minus ennreal_mult' [symmetric])
  apply (simp add: algebra_simps)
  done

lemma SUP_diff_ennreal:
  "c < top ==> (SUP iI. f i - c :: ennreal) = (SUP iI. f i) - c"
  by (auto intro!: SUP_eqI ennreal_minus_mono SUP_least intro: SUP_upper
           simp: ennreal_minus_cancel_iff ennreal_minus_le_iff less_top[symmetric])

lemma ennreal_SUP_add_right:
  fixes c :: ennreal shows " {} ==> c + (SUP iI. f i) = (SUP iI. c + f i)"
  using ennreal_SUP_add_left[of I f c] by (simp add: add.commute)

lemma SUP_add_directed_ennreal:
  fixes f g :: "==> ennreal"
  assumes directed: "i j. i  I ==> j  I ==> kI. f i + g j  f k + g k"
  shows "(SUP iI. f i + g i) = (SUP iI. f i) + (SUP iI. g i)"
proof (cases "I = {}")
  case False
  show ?thesis
  proof (rule antisym)
    show "(SUP iI. f i + g i)  (SUP iI. f i) + (SUP iI. g i)"
      by (rule SUP_least; intro add_mono SUP_upper)
  next
    have "(SUP iI. f i) + (SUP iI. g i) = (SUP iI. f i + (SUP iI. g i))"
      by (intro ennreal_SUP_add_left[symmetric] I {})
    also have " = (SUP iI. (SUP jI. f i + g j))"
      using I {} by (simp add: ennreal_SUP_add_right)
    also have "  (SUP iI. f i + g i)"
      using directed by (intro SUP_least) (blast intro: SUP_upper2)
    finally show "(SUP iI. f i) + (SUP iI. g i)  (SUP iI. f i + g i)" .
  qed
qed (simp add: bot_ereal_def)


lemma enn2real_eq_0_iff: "enn2real x = 0  x = 0  x = top"
  by (cases x) auto

lemma continuous_on_diff_ennreal:
  "continuous_on A f ==> continuous_on A g ==> (x. x  A ==> f x  top) ==> (x. x  A ==> g x  top) ==> continuous_on A (λz. f z - g z::ennreal)"
  including ennreal.lifting
proof (transfer fixing: A, simp add: top_ereal_def)
  fix f g :: "'a ==> ereal" assume "x. 0  f x" "x. 0  g x" "continuous_on A f" "continuous_on A g"
  moreover assume "f x  " "g x  " if " A" for x
  ultimately show "continuous_on A (λz. max 0 (f z - g z))"
    by (intro continuous_on_max continuous_on_const continuous_on_diff_ereal) auto
qed

lemma tendsto_diff_ennreal:
  "(f ---> x) F ==> (g ---> y) F ==> x  top ==> y  top ==> ((λz. f z - g z::ennreal) ---> x - y) F"
  using continuous_on_tendsto_compose[where f="λx. fst x - snd x::ennreal" and s="{(x, y). x  top  y  top}" and g="λx. (f x, g x)" and l="(x, y)" and F="F",
    OF continuous_on_diff_ennreal]
  by (auto simp: tendsto_Pair eventually_conj_iff less_top order_tendstoD continuous_on_fst continuous_on_snd continuous_on_id)

declare lim_real_of_ereal [tendsto_intros]

lemma tendsto_enn2real [tendsto_intros]:
  assumes "(u ---> ennreal l) F" " 0"
  shows "((λn. enn2real (u n)) ---> l) F"
  unfolding enn2real_def
  by (metis assms enn2ereal_ennreal lim_real_of_ereal tendsto_enn2erealI)

end

Messung V0.5 in Prozent
C=54 H=72 G=63

¤ 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.0.129Bemerkung:  (vorverarbeitet am  2026-04-27) ¤

*Bot Zugriff






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.