-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean
theorem sat_of_confirmRupHint_insertRup_fold {n : Nat} (f : DefaultFormula n)
    (f_readyForRupAdd : ReadyForRupAdd f) (c : DefaultClause n) (rupHints : Array Nat)
    (p : PosFin n → Bool) (pf : p ⊨ f) :
    let fc := insertRupUnits f (negate c)
    let confirmRupHint_fold_res := rupHints.foldl (confirmRupHint fc.1.clauses) (fc.1.assignments, [], false, false) 0 rupHints.size
    confirmRupHint_fold_res.2.2.1 = true → p ⊨ c

Proof state:
case intro.intro
n : Nat
f : DefaultFormula n
f_readyForRupAdd : f.ReadyForRupAdd
c : DefaultClause n
rupHints : Array Nat
p : PosFin n → Bool
pf : p ⊨ f
fc : DefaultFormula n × Bool := f.insertRupUnits c.negate
confirmRupHint_fold_res : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool :=
  Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints
confirmRupHint_success : confirmRupHint_fold_res.snd.snd.fst = true
motive : Nat → Array Assignment × CNF.Clause (PosFin n) × Bool × Bool → Prop := fc.fst.ConfirmRupHintFoldEntailsMotive
h_base : motive 0 (fc.fst.assignments, [], false, false)
h_inductive :
  ∀ (idx : Fin rupHints.size) (acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool),
    motive (↑idx) acc →
      fc.fst.ConfirmRupHintFoldEntailsMotive (↑idx + 1) (confirmRupHint fc.fst.clauses acc rupHints[idx])
left✝ : (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst.size = n
h1 :
  Limplies (PosFin n) fc.fst
    (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst
h2 :
  (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).snd.snd.fst = true →
    Incompatible (PosFin n)
      (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst fc.fst
fc_incompatible_confirmRupHint_fold_res :
  Incompatible (PosFin n) fc.fst
    (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst
⊢ p ⊨ c

Tactic:
have fc_unsat :=
  unsat_of_limplies_and_incompatible (PosFin n) fc.1 confirmRupHint_fold_res.1 h1 fc_incompatible_confirmRupHint_fold_res p

Result:
case intro.intro
n : Nat
f : DefaultFormula n
f_readyForRupAdd : f.ReadyForRupAdd
c : DefaultClause n
rupHints : Array Nat
p : PosFin n → Bool
pf : p ⊨ f
fc : DefaultFormula n × Bool := f.insertRupUnits c.negate
confirmRupHint_fold_res : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool :=
  Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints
confirmRupHint_success : confirmRupHint_fold_res.snd.snd.fst = true
motive : Nat → Array Assignment × CNF.Clause (PosFin n) × Bool × Bool → Prop := fc.fst.ConfirmRupHintFoldEntailsMotive
h_base : motive 0 (fc.fst.assignments, [], false, false)
h_inductive :
  ∀ (idx : Fin rupHints.size) (acc : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool),
    motive (↑idx) acc →
      fc.fst.ConfirmRupHintFoldEntailsMotive (↑idx + 1) (confirmRupHint fc.fst.clauses acc rupHints[idx])
left✝ : (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst.size = n
h1 :
  Limplies (PosFin n) fc.fst
    (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst
h2 :
  (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).snd.snd.fst = true →
    Incompatible (PosFin n)
      (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst fc.fst
fc_incompatible_confirmRupHint_fold_res :
  Incompatible (PosFin n) fc.fst
    (Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints).fst
fc_unsat : ¬(p ⊨ fc.fst)
⊢ p ⊨ c

Proof state:
n : Nat
f : DefaultFormula n
f_readyForRupAdd : f.ReadyForRupAdd
c : DefaultClause n
rupHints : Array Nat
p : PosFin n → Bool
pf : p ⊨ f
fc : DefaultFormula n × Bool := f.insertRupUnits c.negate
confirmRupHint_fold_res : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool :=
  Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints
confirmRupHint_success : confirmRupHint_fold_res.snd.snd.fst = true
motive : Nat → Array Assignment × CNF.Clause (PosFin n) × Bool × Bool → Prop := fc.fst.ConfirmRupHintFoldEntailsMotive
⊢ Limplies (PosFin n) (f.insertRupUnits c.negate).fst (f.insertRupUnits c.negate).fst.assignments

Tactic:
have fc_satisfies_AssignmentsInvariant :=
  assignmentsInvariant_insertRupUnits_of_assignmentsInvariant f f_readyForRupAdd (negate c)

Result:
n : Nat
f : DefaultFormula n
f_readyForRupAdd : f.ReadyForRupAdd
c : DefaultClause n
rupHints : Array Nat
p : PosFin n → Bool
pf : p ⊨ f
fc : DefaultFormula n × Bool := f.insertRupUnits c.negate
confirmRupHint_fold_res : Array Assignment × CNF.Clause (PosFin n) × Bool × Bool :=
  Array.foldl (confirmRupHint fc.fst.clauses) (fc.fst.assignments, [], false, false) rupHints
confirmRupHint_success : confirmRupHint_fold_res.snd.snd.fst = true
motive : Nat → Array Assignment × CNF.Clause (PosFin n) × Bool × Bool → Prop := fc.fst.ConfirmRupHintFoldEntailsMotive
fc_satisfies_AssignmentsInvariant : (f.insertRupUnits c.negate).fst.AssignmentsInvariant
⊢ Limplies (PosFin n) (f.insertRupUnits c.negate).fst (f.insertRupUnits c.negate).fst.assignments