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
    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]
      constructor
      · 

Proof state:
case h.left
α β δ : 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)) }

Next tactic:
refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        

Proof state:
case h.left
α β δ : 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.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y e.distances))

Next tactic:
simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        

Proof state:
case h.left
α β δ : 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 ↑(suffixLevenshtein C xs e.suff) ≤
    List.minimum ↑(Levenshtein.impl C xs y (suffixLevenshtein C xs e.suff))

Next tactic:
apply le_suffixLevenshtein_cons_minimum
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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · 

Proof state:
case h.right
α β δ : 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).2 < List.length ys

Next tactic:
simp [← 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]
    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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      

Proof state:
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq :
  e.bound =
    match y₁ :: 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)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound.1 < List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y₁ e.distances)) ∧
      e.bound.2 ≤ Nat.succ (List.length e.suff) ∨
    e.bound.1 ≤ List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y₁ e.distances)) ∧
      e.bound.2 < Nat.succ (List.length e.suff)

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
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      rw [b_eq]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      right
      

Proof state:
case h
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq :
  e.bound =
    match y₁ :: 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)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound.1 ≤ List.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y₁ e.distances)) ∧
    e.bound.2 < Nat.succ (List.length e.suff)

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
        simpa using b_eq
      rw [b_eq]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      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₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq :
  e.bound =
    match y₁ :: 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)
d_eq : e.distances = suffixLevenshtein C xs e.suff
⊢ e.bound = (List.minimum_of_length_pos ?m.11664, 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
      rw [b_eq]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      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₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq✝ :
  e.bound =
    match y₁ :: 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)
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.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y₁ e.distances)) ∧
    e.bound.2 < Nat.succ (List.length e.suff)

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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      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₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq✝ :
  e.bound =
    match y₁ :: 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)
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.minimum_of_length_pos (_ : 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 <
      Nat.succ (List.length 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
    · 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]
      constructor
      · refine (?_ : _ ≤ _).trans (List.minimum_of_length_pos_le_getElem _)
        simp only [List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos, d_eq]
        apply le_suffixLevenshtein_cons_minimum
      · simp [← split]
    | y₁ :: y₂ :: t, split, b_eq, d_eq =>
      simp only [EstimatorData.bound, Prod.lt_iff]
      right
      have b_eq : e.bound = (List.minimum_of_length_pos _, List.length e.suff) := by
        simpa using b_eq
      rw [b_eq]
      constructor
      · 

Proof state:
case h.left
α β δ : Type
inst✝ : CanonicallyLinearOrderedAddCommMonoid δ
C : Levenshtein.Cost α β δ
xs : List α
ys : List β
e : LevenshteinEstimator' C xs ys
y₁ y₂ : β
t : List β
split : List.reverse (y₁ :: y₂ :: t) ++ e.suff = ys
b_eq✝ :
  e.bound =
    match y₁ :: 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)
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.minimum_of_length_pos (_ : 0 < List.length ↑(Levenshtein.impl C xs y₁ e.distances))

Next tactic:
simp only [d_eq, List.minimum_of_length_pos_le_iff, List.coe_minimum_of_length_pos]