l3lab/ntp-mathlib huggingface dataset:
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
split : e.suff = ys
eq :
  e.bound =
    (List.get ↑(suffixLevenshtein C xs e.suff)
        { val := 0, isLt := (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)) },
      List.length ys)
⊢ EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
rw [split] at eq
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
split : e.suff = ys
eq :
  e.bound =
    (List.get ↑(suffixLevenshtein C xs ys) { val := 0, isLt := (_ : 0 < List.length ↑(suffixLevenshtein C xs ys)) },
      List.length ys)
⊢ EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
exact eq.le
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq :
  e.bound =
    match y :: t, split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
⊢ EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
rw [e.distances_eq] at eq
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq :
  e.bound =
    match y :: t, split with
    | [], split => ((↑(suffixLevenshtein C xs e.suff))[0], List.length ys)
    | x, split =>
      (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
simp only at eq
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
dsimp [EstimatorData.bound]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ e.bound ≤ Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
rw [eq]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff) ≤
    Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }

Next tactic:
simp only [← split]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff) ≤
    Thunk.get
      {
        fn := fun x =>
          (levenshtein C xs (List.reverse (y :: t) ++ e.suff), List.length (List.reverse (y :: t) ++ e.suff)) }

Next tactic:
constructor
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · 

Proof state:
case left
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff).1 ≤
    (Thunk.get
        {
          fn := fun x =>
            (levenshtein C xs (List.reverse (y :: t) ++ e.suff), List.length (List.reverse (y :: t) ++ e.suff)) }).1

Next tactic:
simp only [List.minimum_of_length_pos_le_iff]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      

Proof state:
case left
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ List.minimum ↑(suffixLevenshtein C xs e.suff) ≤
    ↑(Thunk.get
          {
            fn := fun x =>
              (levenshtein C xs (List.reverse (y :: t) ++ e.suff), List.length (List.reverse (y :: t) ++ e.suff)) }).1

Next tactic:
exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · 

Proof state:
case right
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
t : List β
split : List.reverse (y :: t) ++ e.suff = ys
eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff)
⊢ (List.minimum_of_length_pos (_ : 0 < List.length ↑(suffixLevenshtein C xs e.suff)), List.length e.suff).2 ≤
    (Thunk.get
        {
          fn := fun x =>
            (levenshtein C xs (List.reverse (y :: t) ++ e.suff), List.length (List.reverse (y :: t) ++ e.suff)) }).2

Next tactic:
exact List.length_le_of_sublist (List.sublist_append_right _ _)
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
⊢ match EstimatorData.improve { fn := fun x => (levenshtein C xs ys, List.length ys) } e with
  | none =>
    EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e =
      Thunk.get { fn := fun x => (levenshtein C xs ys, List.length ys) }
  | some e' =>
    EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e <
      EstimatorData.bound { fn := fun x => (levenshtein C xs ys, List.length ys) } e'

Next tactic:
dsimp [EstimatorData.improve]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
split : List.reverse [y] ++ e.suff = ys
b_eq :
  e.bound =
    match [y], split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound.1 <
        List.get ↑(Levenshtein.impl C xs y e.distances)
          { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) } ∧
      e.bound.2 ≤ List.length ys ∨
    e.bound.1 ≤
        List.get ↑(Levenshtein.impl C xs y e.distances)
          { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) } ∧
      e.bound.2 < List.length ys

Next tactic:
right
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      right
      

Proof state:
case h
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
split : List.reverse [y] ++ e.suff = ys
b_eq :
  e.bound =
    match [y], split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound.1 ≤
      List.get ↑(Levenshtein.impl C xs y e.distances)
        { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) } ∧
    e.bound.2 < List.length ys

Next tactic:
have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
split : List.reverse [y] ++ e.suff = ys
b_eq :
  e.bound =
    match [y], split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound = (List.minimum_of_length_pos ?m.10308, List.length e.suff)

Next tactic:
simpa using b_eq
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      

Proof state:
case h
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
split : List.reverse [y] ++ e.suff = ys
b_eq✝ :
  e.bound =
    match [y], split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
d_eq : e.distances = suffixLevenshtein C xs e.suff
b_eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
⊢ e.bound.1 ≤
      List.get ↑(Levenshtein.impl C xs y e.distances)
        { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) } ∧
    e.bound.2 < List.length ys

Next tactic:
rw [b_eq]
instance estimator' :
    Estimator (Thunk.mk fun _ => (levenshtein C xs ys, ys.length))
      (LevenshteinEstimator' C xs ys) where
  bound_le e := match e.pre_rev, e.split, e.bound_eq with
  | [], split, eq => by
    simp only [List.reverse_nil, List.nil_append] at split
    rw [e.distances_eq] at eq
    simp only [List.getElem_eq_get] at eq
    rw [split] at eq
    exact eq.le
  | y :: t, split, eq => by
    rw [e.distances_eq] at eq
    simp only at eq
    dsimp [EstimatorData.bound]
    rw [eq]
    simp only [← split]
    constructor
    · simp only [List.minimum_of_length_pos_le_iff]
      exact suffixLevenshtein_minimum_le_levenshtein_append _ _ _
    · exact List.length_le_of_sublist (List.sublist_append_right _ _)
  improve_spec e := by
    dsimp [EstimatorData.improve]
    match e.pre_rev, e.split, e.bound_eq, e.distances_eq with
    | [], split, eq, _ =>
      simp only [List.reverse_nil, List.nil_append] at split
      rw [e.distances_eq] at eq
      simp only [List.getElem_eq_get] at eq
      rw [split] at eq
      exact eq
    | [y], split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff, List.reverse_nil, List.nil_append]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      rw [b_eq]
      

Proof state:
case h
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y : β
split : List.reverse [y] ++ e.suff = ys
b_eq✝ :
  e.bound =
    match [y], split with
    | [], split => ((↑e.distances)[0], List.length ys)
    | x, split => (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
d_eq : e.distances = suffixLevenshtein C xs e.suff
b_eq : e.bound = (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff)
⊢ (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff).1 ≤
      List.get ↑(Levenshtein.impl C xs y e.distances)
        { val := 0, isLt := (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances)) } ∧
    (List.minimum_of_length_pos (_ : 0 < List.length ↑e.distances), List.length e.suff).2 < List.length ys

Next tactic:
constructor