-- Mathlib/.lake/packages/lean4/src/lean/Std/Sat/AIG/RefVecOperator/Fold.lean
theorem fold_decl_eq {aig : AIG α} (target : FoldTarget aig) :
    ∀ idx (h1 : idx < aig.decls.size) (h2),
      (fold aig target).1.decls[idx]'h2
        =
      aig.decls[idx]'h1

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (aig.mkConstCached true).aig.decls[idx✝] = aig.decls[idx✝]

case h1
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < (aig.mkConstCached true).aig.decls.size

Tactic:
rw [LawfulOperator.decl_eq (f := mkConstCached)]

Result:
case h2
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < (aig.mkConstCached true).aig.decls.size

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (fold aig target).aig.decls[idx✝] = aig.decls[idx✝]

Tactic:
unfold fold

Result:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (let res := aig.mkConstCached true;
          let aig_1 := res.aig;
          let acc := res.ref;
          let input := target.vec.cast ⋯;
          fold.go aig_1 acc 0 target.len input target.func).aig.decls[idx✝] =
    aig.decls[idx✝]

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
⊢ ∀ (idx : Nat) (h1 : idx < aig.decls.size) (h2 : idx < (fold aig target).aig.decls.size),
    (fold aig target).aig.decls[idx] = aig.decls[idx]

Tactic:
intros

Result:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (fold aig target).aig.decls[idx✝] = aig.decls[idx✝]

Proof state:
case h2
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < (aig.mkConstCached true).aig.decls.size

Tactic:
apply LawfulOperator.lt_size_of_lt_aig_size (f := mkConstCached)

Result:
case h2.h
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < aig.decls.size

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (fold.go (aig.mkConstCached true).aig (aig.mkConstCached true).ref 0 target.len (target.vec.cast ⋯)
            target.func).aig.decls[idx✝] =
    aig.decls[idx✝]

Tactic:
rw [fold.go_decl_eq]

Result:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (aig.mkConstCached true).aig.decls[idx✝] = aig.decls[idx✝]

case h1
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < (aig.mkConstCached true).aig.decls.size

Proof state:
case h2.h
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ idx✝ < aig.decls.size

Tactic:
assumption

Result:
no goals

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (let res := aig.mkConstCached true;
          let aig_1 := res.aig;
          let acc := res.ref;
          let input := target.vec.cast ⋯;
          fold.go aig_1 acc 0 target.len input target.func).aig.decls[idx✝] =
    aig.decls[idx✝]

Tactic:
dsimp only

Result:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
target : FoldTarget aig
idx✝ : Nat
h1✝ : idx✝ < aig.decls.size
h2✝ : idx✝ < (fold aig target).aig.decls.size
⊢ (fold.go (aig.mkConstCached true).aig (aig.mkConstCached true).ref 0 target.len (target.vec.cast ⋯)
            target.func).aig.decls[idx✝] =
    aig.decls[idx✝]