-- Mathlib/.lake/packages/lean4/src/lean/Std/Tactic/BVDecide/Bitblast/BoolExpr/Circuit.lean
theorem go_decl_eq (idx) (aig : AIG β) (h : idx < aig.decls.size) (hbounds) :
    (ofBoolExprCached.go aig expr atomHandler).val.aig.decls[idx]'hbounds = aig.decls[idx]

Proof state:
case gate
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
g : Gate
lhs rhs : BoolExpr α
lih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig lhs atomHandler).val.aig.decls.size),
    (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
rih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig rhs atomHandler).val.aig.decls.size),
    (go aig rhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls.size
this✝ : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
this :
  (go aig lhs atomHandler).val.aig.decls.size ≤ (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls.size
⊢ (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls[idx] = aig.decls[idx]

Tactic:
specialize lih aig (by omega) (by omega)

Result:
case gate
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
g : Gate
lhs rhs : BoolExpr α
rih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig rhs atomHandler).val.aig.decls.size),
    (go aig rhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls.size
this✝ : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
this :
  (go aig lhs atomHandler).val.aig.decls.size ≤ (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls.size
lih : (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
⊢ (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls[idx] = aig.decls[idx]

Proof state:
case gate.and
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
lhs rhs : BoolExpr α
aig : AIG β
h : idx < aig.decls.size
this✝ : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
this :
  (go aig lhs atomHandler).val.aig.decls.size ≤ (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate Gate.and lhs rhs) atomHandler).val.aig.decls.size
lih : (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
rih :
  (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls[idx] = (go aig lhs atomHandler).val.aig.decls[idx]
⊢ ((go (go aig lhs atomHandler).1.aig rhs atomHandler).1.aig.mkAndCached
            { lhs := (go aig lhs atomHandler).1.ref.cast ⋯,
              rhs := (go (go aig lhs atomHandler).1.aig rhs atomHandler).1.ref }).aig.decls[idx] =
    aig.decls[idx]

Tactic:
rw [AIG.LawfulOperator.decl_eq (f := mkAndCached), rih, lih]

Result:
no goals

Proof state:
case gate.beq
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
lhs rhs : BoolExpr α
aig : AIG β
h : idx < aig.decls.size
this✝ : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
this :
  (go aig lhs atomHandler).val.aig.decls.size ≤ (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate Gate.beq lhs rhs) atomHandler).val.aig.decls.size
lih : (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
rih :
  (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls[idx] = (go aig lhs atomHandler).val.aig.decls[idx]
⊢ ((go (go aig lhs atomHandler).1.aig rhs atomHandler).1.aig.mkBEqCached
            { lhs := (go aig lhs atomHandler).1.ref.cast ⋯,
              rhs := (go (go aig lhs atomHandler).1.aig rhs atomHandler).1.ref }).aig.decls[idx] =
    aig.decls[idx]

Tactic:
rw [AIG.LawfulOperator.decl_eq (f := mkBEqCached), rih, lih]

Result:
no goals

Proof state:
case gate
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
g : Gate
lhs rhs : BoolExpr α
lih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig lhs atomHandler).val.aig.decls.size),
    (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
rih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig rhs atomHandler).val.aig.decls.size),
    (go aig rhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls.size
this : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
⊢ (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls[idx] = aig.decls[idx]

Tactic:
have := go_le_size atomHandler rhs (go aig lhs atomHandler).val.aig

Result:
case gate
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
g : Gate
lhs rhs : BoolExpr α
lih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig lhs atomHandler).val.aig.decls.size),
    (go aig lhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
rih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig rhs atomHandler).val.aig.decls.size),
    (go aig rhs atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls.size
this✝ : aig.decls.size ≤ (go aig lhs atomHandler).val.aig.decls.size
this :
  (go aig lhs atomHandler).val.aig.decls.size ≤ (go (go aig lhs atomHandler).val.aig rhs atomHandler).val.aig.decls.size
⊢ (go aig (BoolExpr.gate g lhs rhs) atomHandler).val.aig.decls[idx] = aig.decls[idx]

Proof state:
case not
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
expr : BoolExpr α
ih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig expr atomHandler).val.aig.decls.size),
    (go aig expr atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig expr.not atomHandler).val.aig.decls.size
⊢ (go aig expr.not atomHandler).val.aig.decls[idx] = aig.decls[idx]

Tactic:
simp only [go]

Result:
case not
α β : Type
inst✝² : Hashable β
inst✝¹ : DecidableEq β
atomHandler : AIG β → α → Entrypoint β
inst✝ : LawfulOperator β (fun x => α) atomHandler
idx : Nat
expr : BoolExpr α
ih :
  ∀ (aig : AIG β) (h : idx < aig.decls.size) (hbounds : idx < (go aig expr atomHandler).val.aig.decls.size),
    (go aig expr atomHandler).val.aig.decls[idx] = aig.decls[idx]
aig : AIG β
h : idx < aig.decls.size
hbounds : idx < (go aig expr.not atomHandler).val.aig.decls.size
⊢ ((go aig expr atomHandler).1.aig.mkNotCached (go aig expr atomHandler).1.ref).aig.decls[idx] = aig.decls[idx]