-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Clause.lean
theorem ofArray_eq (arr : Array (Literal (PosFin n)))
    (arrNodup : ∀ i : Fin arr.size, ∀ j : Fin arr.size, i.1 ≠ j.1 → arr[i] ≠ arr[j])
    (c : DefaultClause n) :
    ofArray arr = some c → toList c = Array.toList arr

Proof state:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h✝ :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
h_base : motive arr.size (some empty)
fold_fn : Literal (PosFin n) → Option (DefaultClause n) → Option (DefaultClause n) :=
  fun l acc =>
    match acc with
    | none => none
    | some acc => acc.insert l
h_inductive :
  ∀ (idx : Fin arr.size) (acc : Option (DefaultClause n)), motive (↑idx + 1) acc → motive (↑idx) (fold_fn arr[idx] acc)
hsize : List.length c.clause = arr.size - 0
h :
  ∀ (i : Fin (List.length c.clause)),
    let_fun idx_in_bounds := ⋯;
    List.get c.clause i = arr[0 + ↑i]
i : Nat
l : Literal (PosFin n)
i_in_bounds : ¬i < List.length c.clause
⊢ arr.toList.length ≤ i

Tactic:
dsimp

Result:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h✝ :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
h_base : motive arr.size (some empty)
fold_fn : Literal (PosFin n) → Option (DefaultClause n) → Option (DefaultClause n) :=
  fun l acc =>
    match acc with
    | none => none
    | some acc => acc.insert l
h_inductive :
  ∀ (idx : Fin arr.size) (acc : Option (DefaultClause n)), motive (↑idx + 1) acc → motive (↑idx) (fold_fn arr[idx] acc)
hsize : List.length c.clause = arr.size - 0
h :
  ∀ (i : Fin (List.length c.clause)),
    let_fun idx_in_bounds := ⋯;
    List.get c.clause i = arr[0 + ↑i]
i : Nat
l : Literal (PosFin n)
i_in_bounds : ¬i < List.length c.clause
⊢ arr.size ≤ i

Proof state:
case intro.isFalse.isFalse
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
h_base : motive arr.size (some empty)
fold_fn : Literal (PosFin n) → Option (DefaultClause n) → Option (DefaultClause n) :=
  fun l acc =>
    match acc with
    | none => none
    | some acc => acc.insert l
idx : Fin arr.size
idx_add_one_le_arr_size : ↑idx + 1 ≤ arr.size
c' : DefaultClause n
acc✝ : Option (DefaultClause n)
acc : DefaultClause n
hsize : List.length acc.clause = arr.size - (↑idx + 1)
ih : ∀ (i : Fin (List.length acc.clause)), List.get acc.clause i = arr[↑idx + 1 + ↑i]
h✝¹ : ¬List.contains acc.clause (arr[↑idx].fst, !arr[↑idx].snd) = true
h✝ : ¬List.contains acc.clause arr[↑idx] = true
heq : { clause := arr[↑idx] :: acc.clause, nodupkey := ⋯, nodup := ⋯ } = c'
hsize' : List.length c'.clause = arr.size - ↑idx
⊢ ∀ (i : Fin (List.length c'.clause)),
    let_fun idx_in_bounds := ⋯;
    List.get c'.clause i = arr[↑idx + ↑i]

Tactic:
intro i

Result:
case intro.isFalse.isFalse
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
h_base : motive arr.size (some empty)
fold_fn : Literal (PosFin n) → Option (DefaultClause n) → Option (DefaultClause n) :=
  fun l acc =>
    match acc with
    | none => none
    | some acc => acc.insert l
idx : Fin arr.size
idx_add_one_le_arr_size : ↑idx + 1 ≤ arr.size
c' : DefaultClause n
acc✝ : Option (DefaultClause n)
acc : DefaultClause n
hsize : List.length acc.clause = arr.size - (↑idx + 1)
ih : ∀ (i : Fin (List.length acc.clause)), List.get acc.clause i = arr[↑idx + 1 + ↑i]
h✝¹ : ¬List.contains acc.clause (arr[↑idx].fst, !arr[↑idx].snd) = true
h✝ : ¬List.contains acc.clause arr[↑idx] = true
heq : { clause := arr[↑idx] :: acc.clause, nodupkey := ⋯, nodup := ⋯ } = c'
hsize' : List.length c'.clause = arr.size - ↑idx
i : Fin (List.length c'.clause)
⊢ let_fun idx_in_bounds := ⋯;
  List.get c'.clause i = arr[↑idx + ↑i]

Proof state:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
⊢ c.clause = arr.toList

Tactic:
have h_base : motive arr.size (some empty) := by
  apply Exists.intro <| Nat.le_refl arr.size
  intro c' heq
  simp only [Option.some.injEq] at heq
  have hsize : List.length c'.clause = arr.size- arr.size := by
    simp [← heq, empty]
  apply Exists.intro hsize
  intro i
  simp only [← heq, empty, List.length_nil] at i
  exact Fin.elim0 i

Result:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
motive : Nat → Option (DefaultClause n) → Prop :=
  fun idx acc =>
    ∃ idx_le_arr_size,
      ∀ (c' : DefaultClause n),
        acc = some c' →
          ∃ hsize,
            ∀ (i : Fin (List.length c'.clause)),
              let_fun idx_in_bounds := ⋯;
              List.get c'.clause i = arr[idx + ↑i]
h_base : motive arr.size (some empty)
⊢ c.clause = arr.toList

Proof state:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
⊢ c.toList = arr.toList

Tactic:
rw [toList]

Result:
n : Nat
arr : Array (Literal (PosFin n))
arrNodup : ∀ (i j : Fin arr.size), ↑i ≠ ↑j → arr[i] ≠ arr[j]
c : DefaultClause n
h :
  Array.foldr
      (fun l acc =>
        match acc with
        | none => none
        | some acc => acc.insert l)
      (some empty) arr =
    some c
⊢ c.clause = arr.toList