File: Mathlib/Data/List/EditDistance/Defs.lean

full_name: Levenshtein.Cost
code: /-- A cost structure for Levenshtein edit distance. -/
structure Cost (α β δ : Type*) where
  /-- Cost to delete an element from a list. -/
  delete : α → δ
  /-- Cost in insert an element into a list. -/
  insert : β → δ
  /-- Cost to substitute one element for another in a list. -/
  substitute : α → β → δ
goal: Type (max (max u_4 u_5) u_6)

full_name: Levenshtein.Cost.insert
code: /-- A cost structure for Levenshtein edit distance. -/
structure Cost (α β δ : Type*) where
  /-- Cost to delete an element from a list. -/
  delete : α → δ
  /-- Cost in insert an element into a list. -/
  insert : β → δ
  /-- Cost to substitute one element for another in a list. -/
  substitute : α → β → δ
goal: β → δ

full_name: Levenshtein.Cost.delete
code: /-- A cost structure for Levenshtein edit distance. -/
structure Cost (α β δ : Type*) where
  /-- Cost to delete an element from a list. -/
  delete : α → δ
  /-- Cost in insert an element into a list. -/
  insert : β → δ
  /-- Cost to substitute one element for another in a list. -/
  substitute : α → β → δ
goal: α → δ

full_name: Levenshtein.Cost.substitute
code: /-- A cost structure for Levenshtein edit distance. -/
structure Cost (α β δ : Type*) where
  /-- Cost to delete an element from a list. -/
  delete : α → δ
  /-- Cost in insert an element into a list. -/
  insert : β → δ
  /-- Cost to substitute one element for another in a list. -/
  substitute : α → β → δ
goal: α → β → δ

full_name: Levenshtein.defaultCost_substitute
code: /-- The default cost structure, for which all operations cost `1`. -/
@[simps]
def defaultCost [DecidableEq α] : Cost α α ℕ 
goal: Levenshtein.defaultCost.substitute a b = if a = b then 0 else 1

full_name: Levenshtein.defaultCost
code: /-- The default cost structure, for which all operations cost `1`. -/
@[simps]
def defaultCost [DecidableEq α] : Cost α α ℕ 
goal: Levenshtein.Cost α α ℕ

full_name: Levenshtein.defaultCost_delete
code: /-- The default cost structure, for which all operations cost `1`. -/
@[simps]
def defaultCost [DecidableEq α] : Cost α α ℕ 
goal: ∀ (x : α), Levenshtein.defaultCost.delete x = 1

full_name: Levenshtein.defaultCost_insert
code: /-- The default cost structure, for which all operations cost `1`. -/
@[simps]
def defaultCost [DecidableEq α] : Cost α α ℕ 
goal: ∀ (x : α), Levenshtein.defaultCost.insert x = 1

full_name: Levenshtein.instInhabitedCostNatOfDecidableEq
code: instance [DecidableEq α] : Inhabited (Cost α α ℕ) 
goal: Inhabited (Levenshtein.Cost α α ℕ)

full_name: Levenshtein.weightCost_delete
code: /--
Cost structure given by a function.
Delete and insert cost the same, and substitution costs the greater value.
-/
@[simps]
def weightCost (f : α → ℕ) : Cost α α ℕ 
goal: (Levenshtein.weightCost f).delete a = f a

full_name: Levenshtein.weightCost
code: /--
Cost structure given by a function.
Delete and insert cost the same, and substitution costs the greater value.
-/
@[simps]
def weightCost (f : α → ℕ) : Cost α α ℕ 
goal: Levenshtein.Cost α α ℕ

full_name: Levenshtein.weightCost_substitute
code: /--
Cost structure given by a function.
Delete and insert cost the same, and substitution costs the greater value.
-/
@[simps]
def weightCost (f : α → ℕ) : Cost α α ℕ 
goal: (Levenshtein.weightCost f).substitute a b = max (f a) (f b)

full_name: Levenshtein.weightCost_insert
code: /--
Cost structure given by a function.
Delete and insert cost the same, and substitution costs the greater value.
-/
@[simps]
def weightCost (f : α → ℕ) : Cost α α ℕ 
goal: (Levenshtein.weightCost f).insert b = f b

full_name: Levenshtein.stringLengthCost_insert
code: /--
Cost structure for strings, where cost is the length of the token.
-/
@[simps!]
def stringLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLengthCost.insert b = b.length

full_name: Levenshtein.stringLengthCost_delete
code: /--
Cost structure for strings, where cost is the length of the token.
-/
@[simps!]
def stringLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLengthCost.delete a = a.length

full_name: Levenshtein.stringLengthCost_substitute
code: /--
Cost structure for strings, where cost is the length of the token.
-/
@[simps!]
def stringLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLengthCost.substitute a b = max a.length b.length

full_name: Levenshtein.stringLengthCost
code: /--
Cost structure for strings, where cost is the length of the token.
-/
@[simps!]
def stringLengthCost : Cost String String ℕ 
goal: Levenshtein.Cost String String ℕ

full_name: Levenshtein.stringLogLengthCost_insert
code: /--
Cost structure for strings, where cost is the log base 2 length of the token.
-/
@[simps!]
def stringLogLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLogLengthCost.insert b = (b.length + 1).log2

full_name: Levenshtein.stringLogLengthCost
code: /--
Cost structure for strings, where cost is the log base 2 length of the token.
-/
@[simps!]
def stringLogLengthCost : Cost String String ℕ 
goal: Levenshtein.Cost String String ℕ

full_name: Levenshtein.stringLogLengthCost_substitute
code: /--
Cost structure for strings, where cost is the log base 2 length of the token.
-/
@[simps!]
def stringLogLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLogLengthCost.substitute a b = max (a.length + 1).log2 (b.length + 1).log2

full_name: Levenshtein.stringLogLengthCost_delete
code: /--
Cost structure for strings, where cost is the log base 2 length of the token.
-/
@[simps!]
def stringLogLengthCost : Cost String String ℕ 
goal: Levenshtein.stringLogLengthCost.delete a = (a.length + 1).log2

full_name: Levenshtein.impl
code: /--
(Implementation detail for `levenshtein`)

Given a list `xs` and the Levenshtein distances from each suffix of `xs` to some other list `ys`,
compute the Levenshtein distances from each suffix of `xs` to `y :: ys`.

(Note that we don't actually need to know `ys` itself here, so it is not an argument.)

The return value is a list of length `x.length + 1`,
and it is convenient for the recursive calls that we bundle this list
with a proof that it is non-empty.
-/
def impl
    (xs : List α) (y : β) (d : {r : List δ // 0 < r.length}) : {r : List δ // 0 < r.length} 
goal: { r // 0 < r.length }

full_name: Levenshtein.impl_cons
code: theorem impl_cons (w' : 0 < List.length ds) :
    impl C (x :: xs) y ⟨d :: ds, w⟩ =
      let ⟨r, w⟩ := impl C xs y ⟨ds, w'⟩
      ⟨min (C.delete x + r[0]) (min (C.insert y + d) (C.substitute x y + ds[0])) :: r, by simp⟩ 
goal: Levenshtein.impl C (x :: xs) y ⟨d :: ds, w⟩ =
  match Levenshtein.impl C xs y ⟨ds, w'⟩ with
  | ⟨r, w⟩ => ⟨min (C.delete x + r[0]) (min (C.insert y + d) (C.substitute x y + ds[0])) :: r, ⋯⟩

full_name: Levenshtein.impl_cons_fst_zero
code: theorem impl_cons_fst_zero (h : 0 < (impl C (x :: xs) y ⟨d :: ds, w⟩).val.length)
    (w' : 0 < List.length ds) : (impl C (x :: xs) y ⟨d :: ds, w⟩).1[0] =
      let ⟨r, w⟩ := impl C xs y ⟨ds, w'⟩
      min (C.delete x + r[0]) (min (C.insert y + d) (C.substitute x y + ds[0])) 
goal: (Levenshtein.impl C (x :: xs) y ⟨d :: ds, w⟩).val[0] =
  match Levenshtein.impl C xs y ⟨ds, w'⟩ with
  | ⟨r, w⟩ => min (C.delete x + r[0]) (min (C.insert y + d) (C.substitute x y + ds[0]))

full_name: Levenshtein.impl_length
code: theorem impl_length (d : {r : List δ // 0 < r.length}) (w : d.1.length = xs.length + 1) :
    (impl C xs y d).1.length = xs.length + 1 
goal: (Levenshtein.impl C xs y d).val.length = xs.length + 1

full_name: suffixLevenshtein
code: /--
`suffixLevenshtein C xs ys` computes the Levenshtein distance
(using the cost functions provided by a `C : Cost α β δ`)
from each suffix of the list `xs` to the list `ys`.

The first element of this list is the Levenshtein distance from `xs` to `ys`.

Note that if the cost functions do not satisfy the inequalities
* `C.delete a + C.insert b ≥ C.substitute a b`
* `C.substitute a b + C.substitute b c ≥ C.substitute a c`
(or if any values are negative)
then the edit distances calculated here may not agree with the general
geodesic distance on the edit graph.
-/
def suffixLevenshtein (xs : List α) (ys : List β) : {r : List δ // 0 < r.length} 
goal: { r // 0 < r.length }

full_name: suffixLevenshtein_length
code: theorem suffixLevenshtein_length (xs : List α) (ys : List β) :
    (suffixLevenshtein C xs ys).1.length = xs.length + 1 
goal: (suffixLevenshtein C xs ys).val.length = xs.length + 1

full_name: suffixLevenshtein_eq
code: theorem suffixLevenshtein_eq (xs : List α) (y ys) :
    impl C xs y (suffixLevenshtein C xs ys) = suffixLevenshtein C xs (y :: ys) 
goal: Levenshtein.impl C xs y (suffixLevenshtein C xs ys) = suffixLevenshtein C xs (y :: ys)

full_name: levenshtein
code: /--
`levenshtein C xs ys` computes the Levenshtein distance
(using the cost functions provided by a `C : Cost α β δ`)
from the list `xs` to the list `ys`.

Note that if the cost functions do not satisfy the inequalities
* `C.delete a + C.insert b ≥ C.substitute a b`
* `C.substitute a b + C.substitute b c ≥ C.substitute a c`
(or if any values are negative)
then the edit distance calculated here may not agree with the general
geodesic distance on the edit graph.
-/
def levenshtein (xs : List α) (ys : List β) : δ 
goal: δ

full_name: suffixLevenshtein_nil_nil
code: theorem suffixLevenshtein_nil_nil : (suffixLevenshtein C [] []).1 = [0] 
goal: (suffixLevenshtein C [] []).val = [0]

full_name: List.eq_of_length_one
code: theorem List.eq_of_length_one (x : List α) (w : x.length = 1) :
    have : 0 < x.length := lt_of_lt_of_eq Nat.zero_lt_one w.symm
    x = [x[0]] 
goal: let_fun this := ⋯;
x = [x[0]]

full_name: suffixLevenshtein_nil'
code: theorem suffixLevenshtein_nil' (ys : List β) :
    (suffixLevenshtein C [] ys).1 = [levenshtein C [] ys] 
goal: (suffixLevenshtein C [] ys).val = [levenshtein C [] ys]

full_name: suffixLevenshtein_cons₂
code: theorem suffixLevenshtein_cons₂ (xs : List α) (y ys) :
    suffixLevenshtein C xs (y :: ys) = (impl C xs) y (suffixLevenshtein C xs ys) 
goal: suffixLevenshtein C xs (y :: ys) = Levenshtein.impl C xs y (suffixLevenshtein C xs ys)

full_name: suffixLevenshtein_cons₁_aux
code: theorem suffixLevenshtein_cons₁_aux {x y : {r : List δ // 0 < r.length}}
    (w₀ : x.1[0]'x.2 = y.1[0]'y.2) (w : x.1.tail = y.1.tail) : x = y 
goal: x = y

full_name: suffixLevenshtein_cons₁
code: theorem suffixLevenshtein_cons₁
    (x : α) (xs ys) :
    suffixLevenshtein C (x :: xs) ys =
      ⟨levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1, by simp⟩ 
goal: suffixLevenshtein C (x :: xs) ys = ⟨levenshtein C (x :: xs) ys :: (suffixLevenshtein C xs ys).val, ⋯⟩

full_name: suffixLevenshtein_cons₁_fst
code: theorem suffixLevenshtein_cons₁_fst (x : α) (xs ys) :
    (suffixLevenshtein C (x :: xs) ys).1 =
      levenshtein C (x :: xs) ys ::
        (suffixLevenshtein C xs ys).1 
goal: (suffixLevenshtein C (x :: xs) ys).val = levenshtein C (x :: xs) ys :: (suffixLevenshtein C xs ys).val

full_name: suffixLevenshtein_cons_cons_fst_get_zero
code: theorem suffixLevenshtein_cons_cons_fst_get_zero
    (x : α) (xs y ys) (w : 0 < (suffixLevenshtein C (x :: xs) (y :: ys)).val.length) :
    (suffixLevenshtein C (x :: xs) (y :: ys)).1[0]'w =
      let ⟨dx, _⟩ := suffixLevenshtein C xs (y :: ys)
      let ⟨dy, _⟩ := suffixLevenshtein C (x :: xs) ys
      let ⟨dxy, _⟩ := suffixLevenshtein C xs ys
      min
        (C.delete x + dx[0])
        (min
          (C.insert y + dy[0])
          (C.substitute x y + dxy[0])) 
goal: (suffixLevenshtein C (x :: xs) (y :: ys)).val[0] =
  match suffixLevenshtein C xs (y :: ys) with
  | ⟨dx, property⟩ =>
    match suffixLevenshtein C (x :: xs) ys with
    | ⟨dy, property_1⟩ =>
      match suffixLevenshtein C xs ys with
      | ⟨dxy, property_2⟩ => min (C.delete x + dx[0]) (min (C.insert y + dy[0]) (C.substitute x y + dxy[0]))

full_name: suffixLevenshtein_eq_tails_map
code: theorem suffixLevenshtein_eq_tails_map (xs ys) :
    (suffixLevenshtein C xs ys).1 = xs.tails.map fun xs' => levenshtein C xs' ys 
goal: (suffixLevenshtein C xs ys).val = List.map (fun xs' => levenshtein C xs' ys) xs.tails

full_name: levenshtein_nil_nil
code: @[simp]
theorem levenshtein_nil_nil : levenshtein C [] [] = 0 
goal: levenshtein C [] [] = 0

full_name: levenshtein_nil_cons
code: @[simp]
theorem levenshtein_nil_cons (y) (ys) :
    levenshtein C [] (y :: ys) = C.insert y + levenshtein C [] ys 
goal: levenshtein C [] (y :: ys) = C.insert y + levenshtein C [] ys

full_name: levenshtein_cons_nil
code: @[simp]
theorem levenshtein_cons_nil (x : α) (xs : List α) :
    levenshtein C (x :: xs) [] = C.delete x + levenshtein C xs [] 
goal: levenshtein C (x :: xs) [] = C.delete x + levenshtein C xs []

full_name: levenshtein_cons_cons
code: @[simp]
theorem levenshtein_cons_cons
    (x : α) (xs : List α) (y : β) (ys : List β) :
    levenshtein C (x :: xs) (y :: ys) =
      min (C.delete x + levenshtein C xs (y :: ys))
        (min (C.insert y + levenshtein C (x :: xs) ys)
          (C.substitute x y + levenshtein C xs ys)) 
goal: levenshtein C (x :: xs) (y :: ys) =
  min (C.delete x + levenshtein C xs (y :: ys))
    (min (C.insert y + levenshtein C (x :: xs) ys) (C.substitute x y + levenshtein C xs ys))