l3lab/ntp-mathlib huggingface dataset:
/-- Three points are collinear if and only if the first or third point equals the second or the
angle between them is 0 or π. -/
theorem collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ ∠ p₁ p₂ p₃ = 0 ∨ ∠ p₁ p₂ p₃ = π := by
  refine' ⟨fun h => _, fun h => _⟩
  · replace h := h.wbtw_or_wbtw_or_wbtw
    by_cases h₁₂ : p₁ = p₂
    · exact Or.inl h₁₂
    by_cases h₃₂ : p₃ = p₂
    · exact Or.inr (Or.inl h₃₂)
    rw [or_iff_right h₁₂, or_iff_right h₃₂]
    rcases h with (h | h | h)
    · exact Or.inr (angle_eq_pi_iff_sbtw.2 ⟨h, Ne.symm h₁₂, Ne.symm h₃₂⟩)
    · exact Or.inl (h.angle₃₁₂_eq_zero_of_ne h₃₂)
    · exact Or.inl (h.angle₂₃₁_eq_zero_of_ne h₁₂)
  · rcases h with (rfl | rfl | h | h)
    · simpa using collinear_pair ℝ p₁ p₃
    · simpa using collinear_pair ℝ p₁ p₃
    · rw [angle_eq_zero_iff_ne_and_wbtw] at h
      rcases h with (⟨-, h⟩ | ⟨-, h⟩)
      · rw [Set.insert_comm]
        

Proof state:
case refine'_2.inr.inr.inl.inl.intro
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : Wbtw ℝ p₂ p₁ p₃
⊢ Collinear ℝ {p₂, p₁, p₃}

Next tactic:
exact h.collinear
/-- Three points are collinear if and only if the first or third point equals the second or the
angle between them is 0 or π. -/
theorem collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ ∠ p₁ p₂ p₃ = 0 ∨ ∠ p₁ p₂ p₃ = π := by
  refine' ⟨fun h => _, fun h => _⟩
  · replace h := h.wbtw_or_wbtw_or_wbtw
    by_cases h₁₂ : p₁ = p₂
    · exact Or.inl h₁₂
    by_cases h₃₂ : p₃ = p₂
    · exact Or.inr (Or.inl h₃₂)
    rw [or_iff_right h₁₂, or_iff_right h₃₂]
    rcases h with (h | h | h)
    · exact Or.inr (angle_eq_pi_iff_sbtw.2 ⟨h, Ne.symm h₁₂, Ne.symm h₃₂⟩)
    · exact Or.inl (h.angle₃₁₂_eq_zero_of_ne h₃₂)
    · exact Or.inl (h.angle₂₃₁_eq_zero_of_ne h₁₂)
  · rcases h with (rfl | rfl | h | h)
    · simpa using collinear_pair ℝ p₁ p₃
    · simpa using collinear_pair ℝ p₁ p₃
    · rw [angle_eq_zero_iff_ne_and_wbtw] at h
      rcases h with (⟨-, h⟩ | ⟨-, h⟩)
      · rw [Set.insert_comm]
        exact h.collinear
      · 

Proof state:
case refine'_2.inr.inr.inl.inr.intro
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : Wbtw ℝ p₂ p₃ p₁
⊢ Collinear ℝ {p₁, p₂, p₃}

Next tactic:
rw [Set.insert_comm, Set.pair_comm]
/-- Three points are collinear if and only if the first or third point equals the second or the
angle between them is 0 or π. -/
theorem collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ ∠ p₁ p₂ p₃ = 0 ∨ ∠ p₁ p₂ p₃ = π := by
  refine' ⟨fun h => _, fun h => _⟩
  · replace h := h.wbtw_or_wbtw_or_wbtw
    by_cases h₁₂ : p₁ = p₂
    · exact Or.inl h₁₂
    by_cases h₃₂ : p₃ = p₂
    · exact Or.inr (Or.inl h₃₂)
    rw [or_iff_right h₁₂, or_iff_right h₃₂]
    rcases h with (h | h | h)
    · exact Or.inr (angle_eq_pi_iff_sbtw.2 ⟨h, Ne.symm h₁₂, Ne.symm h₃₂⟩)
    · exact Or.inl (h.angle₃₁₂_eq_zero_of_ne h₃₂)
    · exact Or.inl (h.angle₂₃₁_eq_zero_of_ne h₁₂)
  · rcases h with (rfl | rfl | h | h)
    · simpa using collinear_pair ℝ p₁ p₃
    · simpa using collinear_pair ℝ p₁ p₃
    · rw [angle_eq_zero_iff_ne_and_wbtw] at h
      rcases h with (⟨-, h⟩ | ⟨-, h⟩)
      · rw [Set.insert_comm]
        exact h.collinear
      · rw [Set.insert_comm, Set.pair_comm]
        

Proof state:
case refine'_2.inr.inr.inl.inr.intro
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : Wbtw ℝ p₂ p₃ p₁
⊢ Collinear ℝ {p₂, p₃, p₁}

Next tactic:
exact h.collinear
/-- Three points are collinear if and only if the first or third point equals the second or the
angle between them is 0 or π. -/
theorem collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ ∠ p₁ p₂ p₃ = 0 ∨ ∠ p₁ p₂ p₃ = π := by
  refine' ⟨fun h => _, fun h => _⟩
  · replace h := h.wbtw_or_wbtw_or_wbtw
    by_cases h₁₂ : p₁ = p₂
    · exact Or.inl h₁₂
    by_cases h₃₂ : p₃ = p₂
    · exact Or.inr (Or.inl h₃₂)
    rw [or_iff_right h₁₂, or_iff_right h₃₂]
    rcases h with (h | h | h)
    · exact Or.inr (angle_eq_pi_iff_sbtw.2 ⟨h, Ne.symm h₁₂, Ne.symm h₃₂⟩)
    · exact Or.inl (h.angle₃₁₂_eq_zero_of_ne h₃₂)
    · exact Or.inl (h.angle₂₃₁_eq_zero_of_ne h₁₂)
  · rcases h with (rfl | rfl | h | h)
    · simpa using collinear_pair ℝ p₁ p₃
    · simpa using collinear_pair ℝ p₁ p₃
    · rw [angle_eq_zero_iff_ne_and_wbtw] at h
      rcases h with (⟨-, h⟩ | ⟨-, h⟩)
      · rw [Set.insert_comm]
        exact h.collinear
      · rw [Set.insert_comm, Set.pair_comm]
        exact h.collinear
    · 

Proof state:
case refine'_2.inr.inr.inr
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : ∠ p₁ p₂ p₃ = π
⊢ Collinear ℝ {p₁, p₂, p₃}

Next tactic:
rw [angle_eq_pi_iff_sbtw] at h
/-- Three points are collinear if and only if the first or third point equals the second or the
angle between them is 0 or π. -/
theorem collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ ∠ p₁ p₂ p₃ = 0 ∨ ∠ p₁ p₂ p₃ = π := by
  refine' ⟨fun h => _, fun h => _⟩
  · replace h := h.wbtw_or_wbtw_or_wbtw
    by_cases h₁₂ : p₁ = p₂
    · exact Or.inl h₁₂
    by_cases h₃₂ : p₃ = p₂
    · exact Or.inr (Or.inl h₃₂)
    rw [or_iff_right h₁₂, or_iff_right h₃₂]
    rcases h with (h | h | h)
    · exact Or.inr (angle_eq_pi_iff_sbtw.2 ⟨h, Ne.symm h₁₂, Ne.symm h₃₂⟩)
    · exact Or.inl (h.angle₃₁₂_eq_zero_of_ne h₃₂)
    · exact Or.inl (h.angle₂₃₁_eq_zero_of_ne h₁₂)
  · rcases h with (rfl | rfl | h | h)
    · simpa using collinear_pair ℝ p₁ p₃
    · simpa using collinear_pair ℝ p₁ p₃
    · rw [angle_eq_zero_iff_ne_and_wbtw] at h
      rcases h with (⟨-, h⟩ | ⟨-, h⟩)
      · rw [Set.insert_comm]
        exact h.collinear
      · rw [Set.insert_comm, Set.pair_comm]
        exact h.collinear
    · rw [angle_eq_pi_iff_sbtw] at h
      

Proof state:
case refine'_2.inr.inr.inr
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : Sbtw ℝ p₁ p₂ p₃
⊢ Collinear ℝ {p₁, p₂, p₃}

Next tactic:
exact h.wbtw.collinear
/-- Three points are collinear if and only if the first or third point equals the second or
the sine of the angle between three points is zero. -/
theorem collinear_iff_eq_or_eq_or_sin_eq_zero {p₁ p₂ p₃ : P} :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ Real.sin (∠ p₁ p₂ p₃) = 0 := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
⊢ Collinear ℝ {p₁, p₂, p₃} ↔ p₁ = p₂ ∨ p₃ = p₂ ∨ sin (∠ p₁ p₂ p₃) = 0

Next tactic:
rw [sin_eq_zero_iff_angle_eq_zero_or_angle_eq_pi,
    collinear_iff_eq_or_eq_or_angle_eq_zero_or_angle_eq_pi]
/-- If the sine of the angle between three points is 0, they are collinear. -/
theorem collinear_of_sin_eq_zero {p₁ p₂ p₃ : P} (h : Real.sin (∠ p₁ p₂ p₃) = 0) :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) := by
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
h : sin (∠ p₁ p₂ p₃) = 0
⊢ Collinear ℝ {p₁, p₂, p₃}

Next tactic:
revert h
/-- If the sine of the angle between three points is 0, they are collinear. -/
theorem collinear_of_sin_eq_zero {p₁ p₂ p₃ : P} (h : Real.sin (∠ p₁ p₂ p₃) = 0) :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) := by
  revert h
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
⊢ sin (∠ p₁ p₂ p₃) = 0 → Collinear ℝ {p₁, p₂, p₃}

Next tactic:
contrapose
/-- If the sine of the angle between three points is 0, they are collinear. -/
theorem collinear_of_sin_eq_zero {p₁ p₂ p₃ : P} (h : Real.sin (∠ p₁ p₂ p₃) = 0) :
    Collinear ℝ ({p₁, p₂, p₃} : Set P) := by
  revert h
  contrapose
  

Proof state:
V : Type u_1
P : Type u_2
inst✝³ : NormedAddCommGroup V
inst✝² : InnerProductSpace ℝ V
inst✝¹ : MetricSpace P
inst✝ : NormedAddTorsor V P
p₁ p₂ p₃ : P
⊢ ¬Collinear ℝ {p₁, p₂, p₃} → ¬sin (∠ p₁ p₂ p₃) = 0

Next tactic:
exact sin_ne_zero_of_not_collinear
instance : Subsingleton (Path PUnit.unit PUnit.unit) :=
  ⟨fun x y => by 

Proof state:
x y : Path PUnit.unit PUnit.unit
⊢ x = y

Next tactic:
ext
instance {x y : FundamentalGroupoid PUnit} : Subsingleton (x ⟶ y) := by
  

Proof state:
x y : FundamentalGroupoid PUnit.{?u.168 + 1}
⊢ Subsingleton (x ⟶ y)

Next tactic:
convert_to Subsingleton (Path.Homotopic.Quotient PUnit.unit PUnit.unit)
instance {x y : FundamentalGroupoid PUnit} : Subsingleton (x ⟶ y) := by
  convert_to Subsingleton (Path.Homotopic.Quotient PUnit.unit PUnit.unit)
  

Proof state:
x y : FundamentalGroupoid PUnit.{?u.248 + 1}
⊢ Subsingleton (Path.Homotopic.Quotient PUnit.unit PUnit.unit)

Next tactic:
apply Quotient.instSubsingletonQuotient
/-- Equivalence of groupoids between fundamental groupoid of punit and punit -/
def punitEquivDiscretePUnit : FundamentalGroupoid PUnit.{u + 1} ≌ Discrete PUnit.{v + 1} :=
  CategoryTheory.Equivalence.mk
    (Functor.star _)
    ((CategoryTheory.Functor.const _).obj ⟨PUnit.unit⟩)
    -- Porting note: was `by decide`
    (NatIso.ofComponents fun _ => eqToIso (by 

Proof state:
x✝ : FundamentalGroupoid PUnit.{u + 1}
⊢ (𝟭 (FundamentalGroupoid PUnit.{u + 1})).obj x✝ =
    (Functor.star (FundamentalGroupoid PUnit.{u + 1}) ⋙
          (Functor.const (Discrete PUnit.{v + 1})).obj { as := PUnit.unit }).obj
      x✝

Next tactic:
simp
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
⊢ match improveUntilAux a p e r with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
rw [Estimator.improveUntilAux]
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
⊢ match
    if p (bound a e) = true then pure e
    else
      match improve a e,
        (_ :
          match improve a e with
          | none => bound a e = Thunk.get a
          | some e' => bound a e < bound a e') with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
by_cases h : p (bound a e)
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · 

Proof state:
case pos
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : p (bound a e) = true
⊢ match
    if p (bound a e) = true then pure e
    else
      match improve a e,
        (_ :
          match improve a e with
          | none => bound a e = Thunk.get a
          | some e' => bound a e < bound a e') with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
simp only [h]
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; 

Proof state:
case pos
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : p (bound a e) = true
⊢ match
    if True then pure e
    else
      match improve a e,
        (_ :
          match improve a e with
          | none => bound a e = Thunk.get a
          | some e' => bound a e < bound a e') with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
exact h
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · 

Proof state:
case neg
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (bound a e) = true
⊢ match
    if p (bound a e) = true then pure e
    else
      match improve a e,
        (_ :
          match improve a e with
          | none => bound a e = Thunk.get a
          | some e' => bound a e < bound a e') with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
simp only [h]
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · simp only [h]
    

Proof state:
case neg
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (bound a e) = true
⊢ match
    if False then pure e
    else
      match improve a e,
        (_ :
          match improve a e with
          | none => bound a e = Thunk.get a
          | some e' => bound a e < bound a e') with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
match improve a e, improve_spec e with
    | none, eq =>
      simp only [Bool.not_eq_true]
      rw [eq] at h
      exact Bool.bool_eq_false h
    | some e', _ =>
      exact Estimator.improveUntilAux_spec a p e' true
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · simp only [h]
    match improve a e, improve_spec e with
    | none, eq =>
      

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (bound a e) = true
eq :
  match none with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'
⊢ match
    if False then pure e
    else
      match none, eq with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
simp only [Bool.not_eq_true]
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · simp only [h]
    match improve a e, improve_spec e with
    | none, eq =>
      simp only [Bool.not_eq_true]
      

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (bound a e) = true
eq :
  match none with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'
⊢ p (Thunk.get a) = false

Next tactic:
rw [eq] at h
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · simp only [h]
    match improve a e, improve_spec e with
    | none, eq =>
      simp only [Bool.not_eq_true]
      rw [eq] at h
      

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (Thunk.get a) = true
eq :
  match none with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'
⊢ p (Thunk.get a) = false

Next tactic:
exact Bool.bool_eq_false h
attribute [local instance] WellFoundedGT.toWellFoundedRelation in
/--
If `Estimator.improveUntil a p e` returns `some e'`, then `bound a e'` satisfies `p`.
Otherwise, that value `a` must not satisfy `p`.
-/
theorem Estimator.improveUntilAux_spec (a : Thunk α) (p : α → Bool)
    [Estimator a ε] [WellFoundedGT (range (bound a : ε → α))] (e : ε) (r : Bool) :
    match Estimator.improveUntilAux a p e r with
    | .error _ => ¬ p a.get
    | .ok e' => p (bound a e') := by
  rw [Estimator.improveUntilAux]
  by_cases h : p (bound a e)
  · simp only [h]; exact h
  · simp only [h]
    match improve a e, improve_spec e with
    | none, eq =>
      simp only [Bool.not_eq_true]
      rw [eq] at h
      exact Bool.bool_eq_false h
    | some e', _ =>
      

Proof state:
α : Type u_2
inst✝² : Preorder α
ε : Type u_1
a : Thunk α
p : α → Bool
inst✝¹ : Estimator a ε
inst✝ : WellFoundedGT ↑(range (bound a))
e : ε
r : Bool
h : ¬p (bound a e) = true
e' : ε
x✝ :
  match some e' with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'
⊢ match
    if False then pure e
    else
      match some e', x✝ with
      | none, x => Except.error (if r = true then none else some e)
      | some e', x => improveUntilAux a p e' true with
  | Except.error a_1 => ¬p (Thunk.get a) = true
  | Except.ok e' => p (bound a e') = true

Next tactic:
exact Estimator.improveUntilAux_spec a p e' true
instance (a b : Thunk ℕ) {εa εb : Type*} [Estimator a εa] [Estimator b εb] :
    Estimator (a + b) (εa × εb) where
  bound_le e :=
    Nat.add_le_add (Estimator.bound_le e.1) (Estimator.bound_le e.2)
  improve_spec e := by
    

Proof state:
α : Type ?u.15813
inst✝² : Preorder α
a b : Thunk ℕ
εa : Type u_1
εb : Type u_2
inst✝¹ : Estimator a εa
inst✝ : Estimator b εb
e : εa × εb
⊢ match improve (a + b) e with
  | none => bound (a + b) e = Thunk.get (a + b)
  | some e' => bound (a + b) e < bound (a + b) e'

Next tactic:
dsimp
instance (a b : Thunk ℕ) {εa εb : Type*} [Estimator a εa] [Estimator b εb] :
    Estimator (a + b) (εa × εb) where
  bound_le e :=
    Nat.add_le_add (Estimator.bound_le e.1) (Estimator.bound_le e.2)
  improve_spec e := by
    dsimp
    

Proof state:
α : Type ?u.15813
inst✝² : Preorder α
a b : Thunk ℕ
εa : Type u_1
εb : Type u_2
inst✝¹ : Estimator a εa
inst✝ : Estimator b εb
e : εa × εb
⊢ match
    match improve a e.1 with
    | some e' => some (e', e.2)
    | none =>
      match improve b e.2 with
      | some e' => some (e.1, e')
      | none => none with
  | none => bound a e.1 + bound b e.2 = Thunk.get a + Thunk.get b
  | some e' => bound a e.1 + bound b e.2 < bound a e'.1 + bound b e'.2

Next tactic:
have s₁ := Estimator.improve_spec (a := a) e.1
instance (a b : Thunk ℕ) {εa εb : Type*} [Estimator a εa] [Estimator b εb] :
    Estimator (a + b) (εa × εb) where
  bound_le e :=
    Nat.add_le_add (Estimator.bound_le e.1) (Estimator.bound_le e.2)
  improve_spec e := by
    dsimp
    have s₁ := Estimator.improve_spec (a := a) e.1
    

Proof state:
α : Type ?u.15813
inst✝² : Preorder α
a b : Thunk ℕ
εa : Type u_1
εb : Type u_2
inst✝¹ : Estimator a εa
inst✝ : Estimator b εb
e : εa × εb
s₁ :
  match improve a e.1 with
  | none => bound a e.1 = Thunk.get a
  | some e' => bound a e.1 < bound a e'
⊢ match
    match improve a e.1 with
    | some e' => some (e', e.2)
    | none =>
      match improve b e.2 with
      | some e' => some (e.1, e')
      | none => none with
  | none => bound a e.1 + bound b e.2 = Thunk.get a + Thunk.get b
  | some e' => bound a e.1 + bound b e.2 < bound a e'.1 + bound b e'.2

Next tactic:
have s₂ := Estimator.improve_spec (a := b) e.2