-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddResult.lean
theorem insertUnitInvariant_insertUnit {n : Nat} (assignments0 : Array Assignment)
    (assignments0_size : assignments0.size = n) (units : Array (Literal (PosFin n)))
    (assignments : Array Assignment) (assignments_size : assignments.size = n)
    (foundContradiction : Bool) (l : Literal (PosFin n)) :
    InsertUnitInvariant assignments0 assignments0_size units assignments assignments_size →
    let update_res := insertUnit (units, assignments, foundContradiction) l
    have update_res_size : update_res.snd.fst.size = n

Proof state:
case inr.inr.intro.intro.intro.intro.intro.intro.intro.right.right.right
n : Nat
assignments0 : Array Assignment
assignments0_size : assignments0.size = n
units : Array (Literal (PosFin n))
assignments : Array Assignment
assignments_size : assignments.size = n
foundContradiction : Bool
l : Literal (PosFin n)
i : Fin n
i_in_bounds : ↑i < assignments.size
l_in_bounds : l.fst.val < assignments.size
j1 j2 : Fin units.size
i_gt_zero : ↑i > 0
h1 : units[↑j1] = (⟨↑i, ⋯⟩, true)
h2 : units[↑j2] = (⟨↑i, ⋯⟩, false)
h3 : assignments[↑i] = both
h4 : assignments0[↑i] = unassigned
h5 : ∀ (k : Fin units.size), ¬k = j1 → ¬k = j2 → ¬units[↑k].fst.val = ↑i
j1_lt_updatedUnits_size : ↑j1 < (insertUnit (units, assignments, foundContradiction) l).fst.size
j2_lt_updatedUnits_size : ↑j2 < (insertUnit (units, assignments, foundContradiction) l).fst.size
⊢ assignments0[↑i] = unassigned ∧
    ∀
      (k :
        Fin
          (if hasAssignment l.snd assignments[l.fst.val]! = true then (units, assignments, foundContradiction)
              else
                (units.push (l.fst, l.snd), assignments.modify l.fst.val (addAssignment l.snd),
                  foundContradiction || assignments[l.fst.val]! != unassigned)).fst.size),
      ¬k = ⟨↑j1, j1_lt_updatedUnits_size⟩ →
        ¬k = ⟨↑j2, j2_lt_updatedUnits_size⟩ →
          ¬(if hasAssignment l.snd assignments[l.fst.val]! = true then (units, assignments, foundContradiction)
                      else
                        (units.push (l.fst, l.snd), assignments.modify l.fst.val (addAssignment l.snd),
                          foundContradiction || assignments[l.fst.val]! != unassigned)).fst[↑k].fst.val =
              ↑i

Tactic:
constructor

Result:
case inr.inr.intro.intro.intro.intro.intro.intro.intro.right.right.right.left
n : Nat
assignments0 : Array Assignment
assignments0_size : assignments0.size = n
units : Array (Literal (PosFin n))
assignments : Array Assignment
assignments_size : assignments.size = n
foundContradiction : Bool
l : Literal (PosFin n)
i : Fin n
i_in_bounds : ↑i < assignments.size
l_in_bounds : l.fst.val < assignments.size
j1 j2 : Fin units.size
i_gt_zero : ↑i > 0
h1 : units[↑j1] = (⟨↑i, ⋯⟩, true)
h2 : units[↑j2] = (⟨↑i, ⋯⟩, false)
h3 : assignments[↑i] = both
h4 : assignments0[↑i] = unassigned
h5 : ∀ (k : Fin units.size), ¬k = j1 → ¬k = j2 → ¬units[↑k].fst.val = ↑i
j1_lt_updatedUnits_size : ↑j1 < (insertUnit (units, assignments, foundContradiction) l).fst.size
j2_lt_updatedUnits_size : ↑j2 < (insertUnit (units, assignments, foundContradiction) l).fst.size
⊢ assignments0[↑i] = unassigned

case inr.inr.intro.intro.intro.intro.intro.intro.intro.right.right.right.right
n : Nat
assignments0 : Array Assignment
assignments0_size : assignments0.size = n
units : Array (Literal (PosFin n))
assignments : Array Assignment
assignments_size : assignments.size = n
foundContradiction : Bool
l : Literal (PosFin n)
i : Fin n
i_in_bounds : ↑i < assignments.size
l_in_bounds : l.fst.val < assignments.size
j1 j2 : Fin units.size
i_gt_zero : ↑i > 0
h1 : units[↑j1] = (⟨↑i, ⋯⟩, true)
h2 : units[↑j2] = (⟨↑i, ⋯⟩, false)
h3 : assignments[↑i] = both
h4 : assignments0[↑i] = unassigned
h5 : ∀ (k : Fin units.size), ¬k = j1 → ¬k = j2 → ¬units[↑k].fst.val = ↑i
j1_lt_updatedUnits_size : ↑j1 < (insertUnit (units, assignments, foundContradiction) l).fst.size
j2_lt_updatedUnits_size : ↑j2 < (insertUnit (units, assignments, foundContradiction) l).fst.size
⊢ ∀
    (k :
      Fin
        (if hasAssignment l.snd assignments[l.fst.val]! = true then (units, assignments, foundContradiction)
            else
              (units.push (l.fst, l.snd), assignments.modify l.fst.val (addAssignment l.snd),
                foundContradiction || assignments[l.fst.val]! != unassigned)).fst.size),
    ¬k = ⟨↑j1, j1_lt_updatedUnits_size⟩ →
      ¬k = ⟨↑j2, j2_lt_updatedUnits_size⟩ →
        ¬(if hasAssignment l.snd assignments[l.fst.val]! = true then (units, assignments, foundContradiction)
                    else
                      (units.push (l.fst, l.snd), assignments.modify l.fst.val (addAssignment l.snd),
                        foundContradiction || assignments[l.fst.val]! != unassigned)).fst[↑k].fst.val =
            ↑i

Proof state:
case neg
n : Nat
assignments0 : Array Assignment
assignments0_size : assignments0.size = n
units : Array (Literal (PosFin n))
assignments : Array Assignment
assignments_size : assignments.size = n
foundContradiction : Bool
l : Literal (PosFin n)
i : Fin n
i_in_bounds : ↑i < assignments.size
l_in_bounds : l.fst.val < assignments.size
j1 j2 : Fin units.size
i_gt_zero : ↑i > 0
h1 : units[↑j1] = (⟨↑i, ⋯⟩, true)
h2 : units[↑j2] = (⟨↑i, ⋯⟩, false)
h3 : assignments[↑i] = both
h4 : assignments0[↑i] = unassigned
h5 : ∀ (k : Fin units.size), ¬k = j1 → ¬k = j2 → ¬units[↑k].fst.val = ↑i
j1_lt_updatedUnits_size : ↑j1 < (insertUnit (units, assignments, foundContradiction) l).fst.size
j2_lt_updatedUnits_size : ↑j2 < (insertUnit (units, assignments, foundContradiction) l).fst.size
h✝¹ : ¬hasAssignment l.snd assignments[l.fst.val]! = true
h✝ : ¬↑i = l.fst.val
⊢ (assignments.modify l.fst.val (addAssignment l.snd))[↑i] = both

Tactic:
next i_ne_l => rw [Array.getElem_modify_of_ne (Ne.symm i_ne_l), h3]

Result:
no goals