l3lab/ntp-mathlib huggingface dataset:
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma liminf_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.liminf (fun i ↦ (xs i).toReal) = (F.liminf xs).toReal := by
  have liminf_le : F.liminf xs ≤ b := by
    apply liminf_le_of_le ⟨0, by simp⟩
    intro y h
    obtain ⟨i, hi⟩ := (Eventually.and h le_b).exists
    exact hi.1.trans hi.2
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.liminf xs).toReal = ENNReal.truncateToReal b (F.liminf xs) := by
    rw [truncateToReal_eq_toReal b_ne_top liminf_le]
  simp_rw [liminf_congr aux, aux']
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
liminf_le : liminf xs F ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (liminf xs F) = truncateToReal b (liminf xs F)
⊢ liminf (fun a => truncateToReal b (xs a)) F = truncateToReal b (liminf xs F)

Next tactic:
have key := Monotone.map_liminf_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma liminf_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.liminf (fun i ↦ (xs i).toReal) = (F.liminf xs).toReal := by
  have liminf_le : F.liminf xs ≤ b := by
    apply liminf_le_of_le ⟨0, by simp⟩
    intro y h
    obtain ⟨i, hi⟩ := (Eventually.and h le_b).exists
    exact hi.1.trans hi.2
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.liminf xs).toReal = ENNReal.truncateToReal b (F.liminf xs) := by
    rw [truncateToReal_eq_toReal b_ne_top liminf_le]
  simp_rw [liminf_congr aux, aux']
  have key := Monotone.map_liminf_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
liminf_le : liminf xs F ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (liminf xs F) = truncateToReal b (liminf xs F)
⊢ ∀ᶠ (x : ℝ≥0∞) in map xs F, (fun x x_1 => x ≤ x_1) x b

Next tactic:
simpa only [eventually_map] using le_b
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma liminf_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.liminf (fun i ↦ (xs i).toReal) = (F.liminf xs).toReal := by
  have liminf_le : F.liminf xs ≤ b := by
    apply liminf_le_of_le ⟨0, by simp⟩
    intro y h
    obtain ⟨i, hi⟩ := (Eventually.and h le_b).exists
    exact hi.1.trans hi.2
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.liminf xs).toReal = ENNReal.truncateToReal b (F.liminf xs) := by
    rw [truncateToReal_eq_toReal b_ne_top liminf_le]
  simp_rw [liminf_congr aux, aux']
  have key := Monotone.map_liminf_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
liminf_le : liminf xs F ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (liminf xs F) = truncateToReal b (liminf xs F)
⊢ ∀ (x : ℝ≥0∞), (fun x x_1 => x ≥ x_1) x 0

Next tactic:
simp
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma liminf_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.liminf (fun i ↦ (xs i).toReal) = (F.liminf xs).toReal := by
  have liminf_le : F.liminf xs ≤ b := by
    apply liminf_le_of_le ⟨0, by simp⟩
    intro y h
    obtain ⟨i, hi⟩ := (Eventually.and h le_b).exists
    exact hi.1.trans hi.2
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.liminf xs).toReal = ENNReal.truncateToReal b (F.liminf xs) := by
    rw [truncateToReal_eq_toReal b_ne_top liminf_le]
  simp_rw [liminf_congr aux, aux']
  have key := Monotone.map_liminf_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
liminf_le : liminf xs F ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (liminf xs F) = truncateToReal b (liminf xs F)
key : truncateToReal b (liminf xs F) = liminf (truncateToReal b ∘ xs) F
⊢ liminf (fun a => truncateToReal b (xs a)) F = truncateToReal b (liminf xs F)

Next tactic:
rw [key]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma liminf_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.liminf (fun i ↦ (xs i).toReal) = (F.liminf xs).toReal := by
  have liminf_le : F.liminf xs ≤ b := by
    apply liminf_le_of_le ⟨0, by simp⟩
    intro y h
    obtain ⟨i, hi⟩ := (Eventually.and h le_b).exists
    exact hi.1.trans hi.2
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.liminf xs).toReal = ENNReal.truncateToReal b (F.liminf xs) := by
    rw [truncateToReal_eq_toReal b_ne_top liminf_le]
  simp_rw [liminf_congr aux, aux']
  have key := Monotone.map_liminf_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
  rw [key]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
liminf_le : liminf xs F ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (liminf xs F) = truncateToReal b (liminf xs F)
key : truncateToReal b (liminf xs F) = liminf (truncateToReal b ∘ xs) F
⊢ liminf (fun a => truncateToReal b (xs a)) F = liminf (truncateToReal b ∘ xs) F

Next tactic:
rfl
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
⊢ limsup (fun i => ENNReal.toReal (xs i)) F = ENNReal.toReal (limsup xs F)

Next tactic:
have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
⊢ ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)

Next tactic:
filter_upwards [le_b] with i i_le_b
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    

Proof state:
case h
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
i : ι
i_le_b : xs i ≤ b
⊢ ENNReal.toReal (xs i) = truncateToReal b (xs i)

Next tactic:
simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
⊢ limsup (fun i => ENNReal.toReal (xs i)) F = ENNReal.toReal (limsup xs F)

Next tactic:
have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
⊢ ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)

Next tactic:
rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
⊢ ∀ (a : ℝ≥0∞), (∀ᶠ (x : ℝ≥0∞) in map (fun n => xs n) F, (fun x x_1 => x ≤ x_1) x a) → (fun x x_1 => x ≤ x_1) 0 a

Next tactic:
simp
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
⊢ limsup (fun i => ENNReal.toReal (xs i)) F = ENNReal.toReal (limsup xs F)

Next tactic:
simp_rw [limsup_congr aux, aux']
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  simp_rw [limsup_congr aux, aux']
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
⊢ limsup (fun a => truncateToReal b (xs a)) F = truncateToReal b (limsup xs F)

Next tactic:
have key := Monotone.map_limsup_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  simp_rw [limsup_congr aux, aux']
  have key := Monotone.map_limsup_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
⊢ ∀ᶠ (x : ℝ≥0∞) in map xs F, (fun x x_1 => x ≤ x_1) x b

Next tactic:
simpa only [eventually_map] using le_b
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  simp_rw [limsup_congr aux, aux']
  have key := Monotone.map_limsup_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by 

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
⊢ ∀ (x : ℝ≥0∞), (fun x x_1 => x ≥ x_1) x 0

Next tactic:
simp
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  simp_rw [limsup_congr aux, aux']
  have key := Monotone.map_limsup_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
key : truncateToReal b (limsup xs F) = limsup (truncateToReal b ∘ xs) F
⊢ limsup (fun a => truncateToReal b (xs a)) F = truncateToReal b (limsup xs F)

Next tactic:
rw [key]
/-- If `xs : ι → ℝ≥0∞` is bounded, then we have `liminf (toReal ∘ xs) = toReal (liminf xs)`. -/
lemma limsup_toReal_eq {ι : Type*} {F : Filter ι} [NeBot F] {b : ℝ≥0∞} (b_ne_top : b ≠ ∞)
    {xs : ι → ℝ≥0∞} (le_b : ∀ᶠ i in F, xs i ≤ b) :
    F.limsup (fun i ↦ (xs i).toReal) = (F.limsup xs).toReal := by
  have aux : ∀ᶠ i in F, (xs i).toReal = ENNReal.truncateToReal b (xs i) := by
    filter_upwards [le_b] with i i_le_b
    simp only [truncateToReal_eq_toReal b_ne_top i_le_b, implies_true]
  have aux' : (F.limsup xs).toReal = ENNReal.truncateToReal b (F.limsup xs) := by
    rw [truncateToReal_eq_toReal b_ne_top (limsup_le_of_le ⟨0, by simp⟩ le_b)]
  simp_rw [limsup_congr aux, aux']
  have key := Monotone.map_limsup_of_continuousAt (F := F) (monotone_truncateToReal b_ne_top) xs
          (continuous_truncateToReal b_ne_top).continuousAt
          ⟨b, by simpa only [eventually_map] using le_b⟩ ⟨0, eventually_of_forall (by simp)⟩
  rw [key]
  

Proof state:
α : Type u_1
β : Type u_2
γ : Type u_3
ι : Type u_4
F : Filter ι
inst✝ : NeBot F
b : ℝ≥0∞
b_ne_top : b ≠ ⊤
xs : ι → ℝ≥0∞
le_b : ∀ᶠ (i : ι) in F, xs i ≤ b
aux : ∀ᶠ (i : ι) in F, ENNReal.toReal (xs i) = truncateToReal b (xs i)
aux' : ENNReal.toReal (limsup xs F) = truncateToReal b (limsup xs F)
key : truncateToReal b (limsup xs F) = limsup (truncateToReal b ∘ xs) F
⊢ limsup (fun a => truncateToReal b (xs a)) F = limsup (truncateToReal b ∘ xs) F

Next tactic:
rfl
theorem birthday_def (x : PGame) :
    birthday x =
      max (lsub.{u, u} fun i => birthday (x.moveLeft i))
        (lsub.{u, u} fun i => birthday (x.moveRight i)) := by
  

Proof state:
x : PGame
⊢ birthday x = max (lsub fun i => birthday (moveLeft x i)) (lsub fun i => birthday (moveRight x i))

Next tactic:
cases x
theorem birthday_def (x : PGame) :
    birthday x =
      max (lsub.{u, u} fun i => birthday (x.moveLeft i))
        (lsub.{u, u} fun i => birthday (x.moveRight i)) := by
  cases x; 

Proof state:
case mk
α✝ β✝ : Type u
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
⊢ birthday (mk α✝ β✝ a✝¹ a✝) =
    max (lsub fun i => birthday (moveLeft (mk α✝ β✝ a✝¹ a✝) i)) (lsub fun i => birthday (moveRight (mk α✝ β✝ a✝¹ a✝) i))

Next tactic:
rw [birthday]
theorem birthday_def (x : PGame) :
    birthday x =
      max (lsub.{u, u} fun i => birthday (x.moveLeft i))
        (lsub.{u, u} fun i => birthday (x.moveRight i)) := by
  cases x; rw [birthday]; 

Proof state:
case mk
α✝ β✝ : Type u
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
⊢ max (lsub fun i => birthday (a✝¹ i)) (lsub fun i => birthday (a✝ i)) =
    max (lsub fun i => birthday (moveLeft (mk α✝ β✝ a✝¹ a✝) i)) (lsub fun i => birthday (moveRight (mk α✝ β✝ a✝¹ a✝) i))

Next tactic:
rfl
theorem birthday_moveLeft_lt {x : PGame} (i : x.LeftMoves) : (x.moveLeft i).birthday < x.birthday :=
  by 

Proof state:
x : PGame
i : LeftMoves x
⊢ birthday (moveLeft x i) < birthday x

Next tactic:
cases x
theorem birthday_moveLeft_lt {x : PGame} (i : x.LeftMoves) : (x.moveLeft i).birthday < x.birthday :=
  by cases x; 

Proof state:
case mk
α✝ β✝ : Type u_1
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
i : LeftMoves (mk α✝ β✝ a✝¹ a✝)
⊢ birthday (moveLeft (mk α✝ β✝ a✝¹ a✝) i) < birthday (mk α✝ β✝ a✝¹ a✝)

Next tactic:
rw [birthday]
theorem birthday_moveLeft_lt {x : PGame} (i : x.LeftMoves) : (x.moveLeft i).birthday < x.birthday :=
  by cases x; rw [birthday]; 

Proof state:
case mk
α✝ β✝ : Type u_1
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
i : LeftMoves (mk α✝ β✝ a✝¹ a✝)
⊢ birthday (moveLeft (mk α✝ β✝ a✝¹ a✝) i) < max (lsub fun i => birthday (a✝¹ i)) (lsub fun i => birthday (a✝ i))

Next tactic:
exact lt_max_of_lt_left (lt_lsub _ i)
theorem birthday_moveRight_lt {x : PGame} (i : x.RightMoves) :
    (x.moveRight i).birthday < x.birthday := by
  

Proof state:
x : PGame
i : RightMoves x
⊢ birthday (moveRight x i) < birthday x

Next tactic:
cases x
theorem birthday_moveRight_lt {x : PGame} (i : x.RightMoves) :
    (x.moveRight i).birthday < x.birthday := by
  cases x; 

Proof state:
case mk
α✝ β✝ : Type u_1
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
i : RightMoves (mk α✝ β✝ a✝¹ a✝)
⊢ birthday (moveRight (mk α✝ β✝ a✝¹ a✝) i) < birthday (mk α✝ β✝ a✝¹ a✝)

Next tactic:
rw [birthday]
theorem birthday_moveRight_lt {x : PGame} (i : x.RightMoves) :
    (x.moveRight i).birthday < x.birthday := by
  cases x; rw [birthday]; 

Proof state:
case mk
α✝ β✝ : Type u_1
a✝¹ : α✝ → PGame
a✝ : β✝ → PGame
i : RightMoves (mk α✝ β✝ a✝¹ a✝)
⊢ birthday (moveRight (mk α✝ β✝ a✝¹ a✝) i) < max (lsub fun i => birthday (a✝¹ i)) (lsub fun i => birthday (a✝ i))

Next tactic:
exact lt_max_of_lt_right (lt_lsub _ i)
theorem lt_birthday_iff {x : PGame} {o : Ordinal} :
    o < x.birthday ↔
      (∃ i : x.LeftMoves, o ≤ (x.moveLeft i).birthday) ∨
        ∃ i : x.RightMoves, o ≤ (x.moveRight i).birthday := by
  

Proof state:
x : PGame
o : Ordinal.{u_1}
⊢ o < birthday x ↔ (∃ i, o ≤ birthday (moveLeft x i)) ∨ ∃ i, o ≤ birthday (moveRight x i)

Next tactic:
constructor