-- Mathlib/.lake/packages/lean4/src/lean/Std/Sat/AIG/CachedLemmas.lean
theorem mkGateCached.go_eval_eq_mkGate_eval {aig : AIG α} {input : GateInput aig} :
    ⟦go aig input, assign⟧ = ⟦aig.mkGate input, assign⟧

Proof state:
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
assign : α → Bool
aig : AIG α
input : aig.GateInput
x✝⁴ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝² : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
x✝³ x✝² : Decl α
linv✝ rinv✝ : Bool
heq : aig.decls[input.rhs.ref.gate] = Decl.const true
heq✝¹ : input.lhs.inv = false
heq✝ : input.rhs.inv = false
x✝¹ : aig.decls[input.lhs.ref.gate] = Decl.const false → False
x✝ : aig.decls[input.lhs.ref.gate] = Decl.const true → False
⊢ ⟦assign,
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }⟧ =
    ⟦assign, aig.mkGate input⟧

Tactic:
simp_all [denote_idx_const heq]

Result:
no goals

Proof state:
case h_2.h_1
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
assign : α → Bool
aig : AIG α
input : aig.GateInput
x✝² : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝² : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
x✝¹ x✝ : Decl α
linv✝ rinv✝ : Bool
heq✝¹ : aig.decls[input.lhs.ref.gate] = Decl.const true
heq✝ : input.lhs.inv = true
⊢ ⟦assign, { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false⟧ = ⟦assign, aig.mkGate input⟧

Tactic:
next heq _ =>
simp_all [denote_idx_const heq]

Result:
no goals

Proof state:
case intro
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
assign : α → Bool
aig : AIG α
input : aig.GateInput
x✝¹⁰ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝ : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
x✝⁹ x✝⁸ : Decl α
linv✝ rinv✝ : Bool
x✝⁷ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = true → False
x✝⁶ : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = false → False
x✝⁵ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.rhs.inv = true → False
x✝⁴ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.rhs.inv = false → False
x✝³ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝² : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = true → input.rhs.inv = false → False
x✝¹ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.lhs.inv = false → input.rhs.inv = true → False
h✝ : ¬(input.lhs.ref.gate == input.rhs.ref.gate && input.lhs.inv == false && input.rhs.inv == false) = true
hinv : input.lhs.inv = !input.rhs.inv
hifeq : input.lhs.ref = input.rhs.ref
⊢ ⟦assign, { decls := aig.decls, cache := aig.cache, invariant := ⋯ }.mkConstCached false⟧ = ⟦assign, aig.mkGate input⟧

Tactic:
simp [hifeq, hinv]

Result:
no goals

Proof state:
case intro.intro
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
assign : α → Bool
aig : AIG α
input : aig.GateInput
x✝¹⁰ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝ : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
x✝⁹ x✝⁸ : Decl α
linv✝ rinv✝ : Bool
x✝⁷ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = true → False
x✝⁶ : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = false → False
x✝⁵ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.rhs.inv = true → False
x✝⁴ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.rhs.inv = false → False
x✝³ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝² : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = true → input.rhs.inv = false → False
x✝¹ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.lhs.inv = false → input.rhs.inv = true → False
hrinv : input.rhs.inv = false
hifeq : input.lhs.ref.gate = input.rhs.ref.gate
hlinv : input.lhs.inv = false
⊢ ⟦assign,
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }⟧ =
    ⟦assign, aig.mkGate input⟧

Tactic:
replace hifeq : input.lhs.ref = input.rhs.ref := by
  rcases input with ⟨⟨⟨_, _⟩, _⟩, ⟨⟨_, _⟩, _⟩⟩
  simpa using hifeq

Result:
case intro.intro
α : Type
inst✝¹ : Hashable α
inst✝ : DecidableEq α
assign : α → Bool
aig : AIG α
input : aig.GateInput
x✝¹⁰ : Option (CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv))
heq✝ : aig.cache.get? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
x✝⁹ x✝⁸ : Decl α
linv✝ rinv✝ : Bool
x✝⁷ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = true → False
x✝⁶ : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = false → False
x✝⁵ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.rhs.inv = true → False
x✝⁴ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.rhs.inv = false → False
x✝³ : aig.decls[input.lhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝² : aig.decls[input.lhs.ref.gate] = Decl.const false → input.lhs.inv = true → input.rhs.inv = false → False
x✝¹ : aig.decls[input.rhs.ref.gate] = Decl.const true → input.lhs.inv = false → input.rhs.inv = false → False
x✝ : aig.decls[input.rhs.ref.gate] = Decl.const false → input.lhs.inv = false → input.rhs.inv = true → False
hrinv : input.rhs.inv = false
hlinv : input.lhs.inv = false
hifeq : input.lhs.ref = input.rhs.ref
⊢ ⟦assign,
      { aig := { decls := aig.decls, cache := aig.cache, invariant := ⋯ },
        ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }⟧ =
    ⟦assign, aig.mkGate input⟧