l3lab/ntp-mathlib huggingface dataset:
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    

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'
s₂ :
  match improve b e.2 with
  | none => bound b e.2 = Thunk.get b
  | some e' => bound b e.2 < bound b 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:
revert s₁ s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    

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 e.1 with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match improve b e.2 with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b 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:
cases h₁ : improve a e.fst
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> 

Proof state:
case none
α : 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
h₁ : improve a e.1 = none
⊢ (match none with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match improve b e.2 with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match none 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:
cases h₂ : improve b e.snd
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> 

Proof state:
case some
α : 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
val✝ : εa
h₁ : improve a e.1 = some val✝
⊢ (match some val✝ with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match improve b e.2 with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match some val✝ 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:
cases h₂ : improve b e.snd
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> 

Proof state:
case none.none
α : 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
h₁ : improve a e.1 = none
h₂ : improve b e.2 = none
⊢ (match none with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match none with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match none with
        | some e' => some (e', e.2)
        | none =>
          match none 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:
intro s₁ s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> 

Proof state:
case none.some
α : 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
h₁ : improve a e.1 = none
val✝ : εb
h₂ : improve b e.2 = some val✝
⊢ (match none with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match some val✝ with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match none with
        | some e' => some (e', e.2)
        | none =>
          match some val✝ 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:
intro s₁ s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> 

Proof state:
case some.none
α : 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
val✝ : εa
h₁ : improve a e.1 = some val✝
h₂ : improve b e.2 = none
⊢ (match some val✝ with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match none with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match some val✝ with
        | some e' => some (e', e.2)
        | none =>
          match none 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:
intro s₁ s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> 

Proof state:
case some.some
α : 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
val✝¹ : εa
h₁ : improve a e.1 = some val✝¹
val✝ : εb
h₂ : improve b e.2 = some val✝
⊢ (match some val✝¹ with
    | none => bound a e.1 = Thunk.get a
    | some e' => bound a e.1 < bound a e') →
    (match some val✝ with
      | none => bound b e.2 = Thunk.get b
      | some e' => bound b e.2 < bound b e') →
      match
        match some val✝¹ with
        | some e' => some (e', e.2)
        | none =>
          match some val✝ 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:
intro s₁ s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> 

Proof state:
case none.none
α : 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
h₁ : improve a e.1 = none
h₂ : improve b e.2 = none
s₁ :
  match none with
  | none => bound a e.1 = Thunk.get a
  | some e' => bound a e.1 < bound a e'
s₂ :
  match none with
  | none => bound b e.2 = Thunk.get b
  | some e' => bound b e.2 < bound b e'
⊢ match
    match none with
    | some e' => some (e', e.2)
    | none =>
      match none 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:
simp_all only
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> 

Proof state:
case none.some
α : 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
h₁ : improve a e.1 = none
val✝ : εb
h₂ : improve b e.2 = some val✝
s₁ :
  match none with
  | none => bound a e.1 = Thunk.get a
  | some e' => bound a e.1 < bound a e'
s₂ :
  match some val✝ with
  | none => bound b e.2 = Thunk.get b
  | some e' => bound b e.2 < bound b e'
⊢ match
    match none with
    | some e' => some (e', e.2)
    | none =>
      match some val✝ 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:
simp_all only
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> 

Proof state:
case some.none
α : 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
val✝ : εa
h₁ : improve a e.1 = some val✝
h₂ : improve b e.2 = none
s₁ :
  match some val✝ with
  | none => bound a e.1 = Thunk.get a
  | some e' => bound a e.1 < bound a e'
s₂ :
  match none with
  | none => bound b e.2 = Thunk.get b
  | some e' => bound b e.2 < bound b e'
⊢ match
    match some val✝ with
    | some e' => some (e', e.2)
    | none =>
      match none 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:
simp_all only
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> 

Proof state:
case some.some
α : 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
val✝¹ : εa
h₁ : improve a e.1 = some val✝¹
val✝ : εb
h₂ : improve b e.2 = some val✝
s₁ :
  match some val✝¹ with
  | none => bound a e.1 = Thunk.get a
  | some e' => bound a e.1 < bound a e'
s₂ :
  match some val✝ with
  | none => bound b e.2 = Thunk.get b
  | some e' => bound b e.2 < bound b e'
⊢ match
    match some val✝¹ with
    | some e' => some (e', e.2)
    | none =>
      match some val✝ 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:
simp_all only
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> simp_all only
    · 

Proof state:
case none.some
α : 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
h₁ : improve a e.1 = none
val✝ : εb
h₂ : improve b e.2 = some val✝
s₁ : bound a e.1 = Thunk.get a
s₂ : bound b e.2 < bound b val✝
⊢ Thunk.get a + bound b e.2 < Thunk.get a + bound b val✝

Next tactic:
apply Nat.add_lt_add_left s₂
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> simp_all only
    · apply Nat.add_lt_add_left s₂
    · 

Proof state:
case some.none
α : 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
val✝ : εa
h₁ : improve a e.1 = some val✝
h₂ : improve b e.2 = none
s₁ : bound a e.1 < bound a val✝
s₂ : bound b e.2 = Thunk.get b
⊢ bound a e.1 + Thunk.get b < bound a val✝ + Thunk.get b

Next tactic:
apply Nat.add_lt_add_right s₁
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
    have s₂ := Estimator.improve_spec (a := b) e.2
    revert s₁ s₂
    cases h₁ : improve a e.fst <;> cases h₂ : improve b e.snd <;> intro s₁ s₂ <;> simp_all only
    · apply Nat.add_lt_add_left s₂
    · apply Nat.add_lt_add_right s₁
    · 

Proof state:
case some.some
α : 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
val✝¹ : εa
h₁ : improve a e.1 = some val✝¹
val✝ : εb
h₂ : improve b e.2 = some val✝
s₁ : bound a e.1 < bound a val✝¹
s₂ : bound b e.2 < bound b val✝
⊢ bound a e.1 + bound b e.2 < bound a val✝¹ + bound b e.2

Next tactic:
apply Nat.add_lt_add_right s₁
instance [Estimator a ε] : WellFoundedGT (range (bound a : ε → α)) :=
  let f : range (bound a : ε → α) ↪o { x // x ≤ a.get } :=
    Subtype.orderEmbedding (by 

Proof state:
α : Type ?u.18596
β : Type ?u.18599
inst✝³ : PartialOrder α
inst✝² : PartialOrder β
inst✝¹ : ∀ (a : α), WellFoundedGT { x // x ≤ a }
a : Thunk α
ε : Type ?u.18719
inst✝ : Estimator a ε
⊢ ∀ a_1 ∈ range (bound a), a_1 ≤ Thunk.get a

Next tactic:
rintro _ ⟨e, rfl⟩
instance [Estimator a ε] : WellFoundedGT (range (bound a : ε → α)) :=
  let f : range (bound a : ε → α) ↪o { x // x ≤ a.get } :=
    Subtype.orderEmbedding (by rintro _ ⟨e, rfl⟩; 

Proof state:
case intro
α : Type ?u.18596
β : Type ?u.18599
inst✝³ : PartialOrder α
inst✝² : PartialOrder β
inst✝¹ : ∀ (a : α), WellFoundedGT { x // x ≤ a }
a : Thunk α
ε : Type ?u.18719
inst✝ : Estimator a ε
e : ε
⊢ bound a e ≤ Thunk.get a

Next tactic:
exact Estimator.bound_le e
/-- Given an estimator for a pair, we can extract an estimator for the first factor. -/
-- This isn't an instance as at the sole use case we need to provide
-- the instance arguments by hand anyway.
def Estimator.fstInst [DecidableRel ((· : α) < ·)] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }]
    (a : Thunk α) (b : Thunk β) {ε : Type*} (i : Estimator (a.prod b) ε) :
    Estimator a (Estimator.fst (a.prod b) ε) where
  bound_le e := (Estimator.bound_le e.inner : bound (a.prod b) e.inner ≤ (a.get, b.get)).1
  improve_spec e := by
    

Proof state:
α : Type ?u.21167
β : Type ?u.21170
inst✝⁴ : PartialOrder α
inst✝³ : PartialOrder β
inst✝² : ∀ (a : α), WellFoundedGT { x // x ≤ a }
inst✝¹ : DecidableRel fun x x_1 => x < x_1
inst✝ : ∀ (p : α × β), WellFoundedGT { q // q ≤ p }
a : Thunk α
b : Thunk β
ε : Type u_1
i : Estimator (Thunk.prod a b) ε
e : fst (Thunk.prod a b) ε
⊢ match improve a e with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'

Next tactic:
let bd := (bound (a.prod b) e.inner).1
/-- Given an estimator for a pair, we can extract an estimator for the first factor. -/
-- This isn't an instance as at the sole use case we need to provide
-- the instance arguments by hand anyway.
def Estimator.fstInst [DecidableRel ((· : α) < ·)] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }]
    (a : Thunk α) (b : Thunk β) {ε : Type*} (i : Estimator (a.prod b) ε) :
    Estimator a (Estimator.fst (a.prod b) ε) where
  bound_le e := (Estimator.bound_le e.inner : bound (a.prod b) e.inner ≤ (a.get, b.get)).1
  improve_spec e := by
    let bd := (bound (a.prod b) e.inner).1
    

Proof state:
α : Type ?u.21167
β : Type ?u.21170
inst✝⁴ : PartialOrder α
inst✝³ : PartialOrder β
inst✝² : ∀ (a : α), WellFoundedGT { x // x ≤ a }
inst✝¹ : DecidableRel fun x x_1 => x < x_1
inst✝ : ∀ (p : α × β), WellFoundedGT { q // q ≤ p }
a : Thunk α
b : Thunk β
ε : Type u_1
i : Estimator (Thunk.prod a b) ε
e : fst (Thunk.prod a b) ε
bd : α := (bound (Thunk.prod a b) e.inner).1
⊢ match improve a e with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'

Next tactic:
have := Estimator.improveUntil_spec (a.prod b) (fun p => bd < p.1) e.inner
/-- Given an estimator for a pair, we can extract an estimator for the first factor. -/
-- This isn't an instance as at the sole use case we need to provide
-- the instance arguments by hand anyway.
def Estimator.fstInst [DecidableRel ((· : α) < ·)] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }]
    (a : Thunk α) (b : Thunk β) {ε : Type*} (i : Estimator (a.prod b) ε) :
    Estimator a (Estimator.fst (a.prod b) ε) where
  bound_le e := (Estimator.bound_le e.inner : bound (a.prod b) e.inner ≤ (a.get, b.get)).1
  improve_spec e := by
    let bd := (bound (a.prod b) e.inner).1
    have := Estimator.improveUntil_spec (a.prod b) (fun p => bd < p.1) e.inner
    

Proof state:
α : Type ?u.21167
β : Type ?u.21170
inst✝⁴ : PartialOrder α
inst✝³ : PartialOrder β
inst✝² : ∀ (a : α), WellFoundedGT { x // x ≤ a }
inst✝¹ : DecidableRel fun x x_1 => x < x_1
inst✝ : ∀ (p : α × β), WellFoundedGT { q // q ≤ p }
a : Thunk α
b : Thunk β
ε : Type u_1
i : Estimator (Thunk.prod a b) ε
e : fst (Thunk.prod a b) ε
bd : α := (bound (Thunk.prod a b) e.inner).1
this :
  match improveUntil (Thunk.prod a b) (fun p => decide (bd < p.1)) e.inner with
  | Except.error a_1 => ¬decide (bd < (Thunk.get (Thunk.prod a b)).1) = true
  | Except.ok e' => decide (bd < (bound (Thunk.prod a b) e').1) = true
⊢ match improve a e with
  | none => bound a e = Thunk.get a
  | some e' => bound a e < bound a e'

Next tactic:
revert this
/-- Given an estimator for a pair, we can extract an estimator for the first factor. -/
-- This isn't an instance as at the sole use case we need to provide
-- the instance arguments by hand anyway.
def Estimator.fstInst [DecidableRel ((· : α) < ·)] [∀ (p : α × β), WellFoundedGT { q // q ≤ p }]
    (a : Thunk α) (b : Thunk β) {ε : Type*} (i : Estimator (a.prod b) ε) :
    Estimator a (Estimator.fst (a.prod b) ε) where
  bound_le e := (Estimator.bound_le e.inner : bound (a.prod b) e.inner ≤ (a.get, b.get)).1
  improve_spec e := by
    let bd := (bound (a.prod b) e.inner).1
    have := Estimator.improveUntil_spec (a.prod b) (fun p => bd < p.1) e.inner
    revert this
    

Proof state:
α : Type ?u.21167
β : Type ?u.21170
inst✝⁴ : PartialOrder α
inst✝³ : PartialOrder β
inst✝² : ∀ (a : α), WellFoundedGT { x // x ≤ a }
inst✝¹ : DecidableRel fun x x_1 => x < x_1
inst✝ : ∀ (p : α × β), WellFoundedGT { q // q ≤ p }
a : Thunk α
b : Thunk β
ε : Type u_1
i : Estimator (Thunk.prod a b) ε
e : fst (Thunk.prod a b) ε
bd : α := (bound (Thunk.prod a b) e.inner).1
⊢ (match improveUntil (Thunk.prod a b) (fun p => decide (bd < p.1)) e.inner with
    | Except.error a_1 => ¬decide (bd < (Thunk.get (Thunk.prod a b)).1) = true
    | Except.ok e' => decide (bd < (bound (Thunk.prod a b) e').1) = true) →
    match improve a e with
    | none => bound a e = Thunk.get a
    | some e' => bound a e < bound a e'

Next tactic:
simp only [EstimatorData.improve, decide_eq_true_eq]