-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/LRAT/Internal/Formula/RupAddSound.lean
theorem reduce_fold_fn_preserves_induction_motive {c_arr : Array (Literal (PosFin n))}
    {assignment : Array Assignment}
    (idx : Fin c_arr.size) (res : ReduceResult (PosFin n))
    (ih : ReducePostconditionInductionMotive c_arr assignment idx.1 res) :
  ReducePostconditionInductionMotive c_arr assignment (idx.1 + 1) (reduce_fold_fn assignment res c_arr[idx])

Proof state:
case inl
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
hp : p ⊨ assignment
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
l : Literal (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) (reducedToUnit l)
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
c_arr_idx_eq_true : c_arr[↑idx].snd = true
h : l = (i, b)
j_lt_idx : ↑j < ↑idx
ih2_precondition : ∃ i, ↑i < ↑idx ∧ (p ⊨ c_arr[i])
⊢ p ⊨ l

Tactic:
exact ih.2 l rfl p hp ih2_precondition

Result:
no goals

Proof state:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
res : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) res
⊢ ReducePostconditionInductionMotive c_arr assignment (↑idx + 1) (reduce_fold_fn assignment res c_arr[idx])

Tactic:
simp only [ReducePostconditionInductionMotive, Fin.getElem_fin, forall_exists_index, and_imp, Prod.forall]

Result:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
res : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) res
⊢ (reduce_fold_fn assignment res c_arr[↑idx] = reducedToEmpty →
      ∀ (p : PosFin n → Bool), (∀ (i : Fin c_arr.size), ↑i < ↑idx + 1 → ¬(p ⊨ c_arr[↑i])) ∨ ¬(p ⊨ assignment)) ∧
    ∀ (a : PosFin n) (b : Bool),
      reduce_fold_fn assignment res c_arr[↑idx] = reducedToUnit (a, b) →
        ∀ (p : PosFin n → Bool), p ⊨ assignment → ∀ (x : Fin c_arr.size), ↑x < ↑idx + 1 → p ⊨ c_arr[↑x] → p ⊨ (a, b)

Proof state:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
p : PosFin n → Bool
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
c_arr_idx_eq_false : ¬(!c_arr[↑idx].snd) = true
h : reducedToEmpty = reducedToEmpty
⊢ (∀ (i : Fin c_arr.size), ↑i < ↑idx + 1 → ¬(p ⊨ c_arr[↑i])) ∨ ¬(p ⊨ assignment)

Tactic:
simp only [Bool.not_eq_true', Bool.not_eq_false] at c_arr_idx_eq_false

Result:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
p : PosFin n → Bool
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
h : reducedToEmpty = reducedToEmpty
c_arr_idx_eq_false : c_arr[↑idx].snd = true
⊢ (∀ (i : Fin c_arr.size), ↑i < ↑idx + 1 → ¬(p ⊨ c_arr[↑i])) ∨ ¬(p ⊨ assignment)

Proof state:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
hp : p ⊨ assignment
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
c_arr_idx_eq_true : (!c_arr[↑idx].snd) = true
h : reducedToUnit c_arr[↑idx] = reducedToUnit (i, b)
⊢ p ⊨ (i, b)

Tactic:
simp only [reducedToUnit.injEq] at h

Result:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
hp : p ⊨ assignment
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
c_arr_idx_eq_true : (!c_arr[↑idx].snd) = true
h : c_arr[↑idx] = (i, b)
⊢ p ⊨ (i, b)

Proof state:
case h.inl
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
p : PosFin n → Bool
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = neg
h : reducedToEmpty = reducedToEmpty
c_arr_idx_eq_false : c_arr[↑idx].snd = true
ih1 : ∀ (i : Fin c_arr.size), ↑i < ↑idx → ¬(p ⊨ c_arr[i])
p_entails_assignment : p ⊨ assignment
i : Fin c_arr.size
i_lt_idx_add_one : ↑i < ↑idx + 1
p_entails_c_arr_i : p ⊨ c_arr[↑i]
i_lt_idx : ↑i < ↑idx
⊢ False

Tactic:
exact ih1 i i_lt_idx p_entails_c_arr_i

Result:
no goals

Proof state:
case h.inl
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
p : PosFin n → Bool
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = pos
h : reducedToEmpty = reducedToEmpty
c_arr_idx_eq_false : c_arr[↑idx].snd = false
ih1 : ∀ (i : Fin c_arr.size), ↑i < ↑idx → ¬(p ⊨ c_arr[i])
p_entails_assignment : p ⊨ assignment
i : Fin c_arr.size
i_lt_idx_add_one : ↑i < ↑idx + 1
p_entails_c_arr_i : p ⊨ c_arr[↑i]
i_lt_idx : ↑i < ↑idx
⊢ False

Tactic:
exact ih1 i i_lt_idx p_entails_c_arr_i

Result:
no goals

Proof state:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = pos
h : c_arr[↑idx] = (i, b)
c_arr_idx_eq_true : b = true
hp : hasAssignment (decide (p c_arr[↑idx].fst = false)) pos = false
p_c_arr_idx_eq_false : p i = false
⊢ p ⊨ (i, b)

Tactic:
simp +decide only [h, p_c_arr_idx_eq_false] at hp

Result:
no goals

Proof state:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = pos
h : c_arr[↑idx] = (i, b)
c_arr_idx_eq_true : b = true
hp : hasAssignment (decide (p c_arr[↑idx].fst = false)) pos = false
p_c_arr_idx_eq_false : ¬p c_arr[↑idx].fst = true
⊢ p ⊨ (i, b)

Tactic:
simp only [h, Bool.not_eq_true] at p_c_arr_idx_eq_false

Result:
n : Nat
c_arr : Array (Literal (PosFin n))
assignment : Array Assignment
idx : Fin c_arr.size
i : PosFin n
b : Bool
p : PosFin n → Bool
j : Fin c_arr.size
j_lt_idx_add_one : ↑j < ↑idx + 1
p_entails_c_arr_j : p ⊨ c_arr[↑j]
acc✝ : ReduceResult (PosFin n)
ih : ReducePostconditionInductionMotive c_arr assignment (↑idx) reducedToEmpty
x✝ : Assignment
heq : assignment[c_arr[↑idx].fst.val]! = pos
h : c_arr[↑idx] = (i, b)
c_arr_idx_eq_true : b = true
hp : hasAssignment (decide (p c_arr[↑idx].fst = false)) pos = false
p_c_arr_idx_eq_false : p i = false
⊢ p ⊨ (i, b)