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  

Quelle  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 "(\jnj 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 i\I. 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 i\I. 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 a\A. of_nat a :: real)"
proof (intro antisym)
  show "(SUP a\A. 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 a\A. 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 i\I. sup c (f i)) = sup c (SUP i\I. f i)"
  using SUP_sup_distrib[of "\_. c" I f] by simp

lemma (in complete_lattice) SUP_sup_const2:
  "I \ {} \ (SUP i\I. sup (f i) c) = sup (SUP i\I. 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 "\y\0. 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 "0 \ a" "0 \ b" then show "(a \ b) = (\c\Collect ((\) 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: "x \ 0 \ e2ennreal x = 0"
  unfolding zero_ennreal_def e2ennreal_def by (simp add: max_absorb1)

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

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

lemma ereal_ennreal_cases:
  obtains b where "0 \ a" "a = enn2ereal b" | "a < 0"
  using e2ennreal'_inverse[of a, symmetric] by (cases "0 \ 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) \ (\i\I. 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 "0 \ 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]: "0 \ (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]: "1 \ (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 \ (\i\I. f i) < top \ (\i\I. f i < top)"
  by (induction I rule: finite_induct) auto

lemma ennreal_sum_eq_top[simp]:
  fixes f :: "'a \ ennreal"
  shows "finite I \ (\i\I. f i) = top \ (\i\I. 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 \ (\i\A. f i = 0))"
  by (induction A rule: infinite_finite_induct) auto

lemma ennreal_prod_eq_top:
  fixes f :: "'a \ ennreal"
  shows "(\i\I. f i) = top \ (finite I \ ((\i\I. f i \ 0) \ (\i\I. 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]: "x \ 0 \ x * top = (top :: ennreal)"
  by (subst ennreal_mult_eq_top_iff) auto

lemma ennreal_top_mult_right [simp]: "x \ 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: "c \ 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: "x \ 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 "y \ 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 "y \ 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 "c \ 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 "a \ 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 "b \ 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: "a \ 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 "b \ 0 \ b \ top \ (a * b) / b = a"
  by (fact mult_divide_eq_ennreal)

lemma ennreal_add_diff_cancel:
  fixes a b :: ennreal
  shows "b \ \ \ (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 "c \ 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 "a \ 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 "a \ 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]: "a \ 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 "a \ 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]: "a \ 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 \ (\q\0. 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) \ (\i\I. 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 "(\x\x # 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) \ (\i\A. 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  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 x\X. 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 "\y\X. 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]: "(\i\I. 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 "\z\Collect ((\) 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 *: "\\<^sub>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  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 \\<^sub>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 \ \k\I. \n\N. f i n \ f k n \ f j n \ f k n"
  shows "(\n. SUP i\I. f i n) = (SUP i\I. \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] suminf_nonneg summable_ereal_pos  {}
             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 i\I. f i) = (SUP i\I. 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 i\I. f i) * c = (SUP i\I. f i * c ::ennreal)"
  using SUP_mult_left_ennreal by (simp add: mult.commute)

lemma SUP_divide_ennreal: "(SUP i\I. f i) / c = (SUP i\I. 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 "\i\UNIV. 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. \i\I. 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 x\I. c - f x) = c - (INF x\I. 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 a\A. of_nat a :: ennreal)"
proof (intro antisym)
  show "(SUP a\A. 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 a\A. of_nat a::ennreal)"
    by (intro SUP_upper)
qed

lemma ennreal_tendsto_const_minus:
  fixes g :: "'a \ ennreal"
  assumes ae: "\\<^sub>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. \q\0. 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: "\\<^sub>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]  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:
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=99 H=93 G=95

¤ Dauer der Verarbeitung: 0.43 Sekunden  ¤

*© 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.