Theorem: AIG.mkGateCached_le_size
Proof state before:
α : Type
inst✝² : BEq α
inst✝¹ : Hashable α
inst✝ : DecidableEq α
aig : AIG α
input : aig.GateInput
⊢ aig.decls.size ≤
    (match aig.cache.find? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) with
          | some hit =>
            { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ }, ref := { gate := hit.idx, hgate := ⋯ } }
          | none =>
            match aig.decls[input.lhs.ref.gate], aig.decls[input.rhs.ref.gate], input.lhs.inv, input.rhs.inv with
            | Decl.const true, x, true, x_1 => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
            | Decl.const false, x, false, x_1 =>
              { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
            | x, Decl.const true, x_1, true => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
            | x, Decl.const false, x_1, false =>
              { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
            | Decl.const true, x, false, false =>
              { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
                ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
            | Decl.const false, x, true, false =>
              { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
                ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
            | x, Decl.const true, false, false =>
              { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
                ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
            | x, Decl.const false, false, true =>
              { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
                ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
            | x, x_1, x_2, x_3 =>
              {
                aig :=
                  {
                    decls :=
                      aig.decls.push (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                    cache :=
                      Cache.insert aig.decls aig.cache
                        (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                    inv := ⋯ },
                ref := { gate := aig.decls.size, hgate := ⋯ } }).aig.decls.size
Tactic:
split
Proof state after:
case h_1
α : Type
inst✝² : BEq α
inst✝¹ : Hashable α
inst✝ : DecidableEq α
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))
hit✝ : CacheHit aig.decls (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv)
heq✝ : aig.cache.find? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = some hit✝
⊢ aig.decls.size ≤
    { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
            ref := { gate := hit✝.idx, hgate := ⋯ } }.aig.decls.size

case h_2
α : Type
inst✝² : BEq α
inst✝¹ : Hashable α
inst✝ : DecidableEq α
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.find? (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv) = none
⊢ aig.decls.size ≤
    (match aig.decls[input.lhs.ref.gate], aig.decls[input.rhs.ref.gate], input.lhs.inv, input.rhs.inv with
          | Decl.const true, x, true, x_1 => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
          | Decl.const false, x, false, x_1 => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
          | x, Decl.const true, x_1, true => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
          | x, Decl.const false, x_1, false => { decls := aig.decls, cache := aig.cache, inv := ⋯ }.mkConstCached false
          | Decl.const true, x, false, false =>
            { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
              ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
          | Decl.const false, x, true, false =>
            { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
              ref := { gate := input.rhs.ref.gate, hgate := ⋯ } }
          | x, Decl.const true, false, false =>
            { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
              ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
          | x, Decl.const false, false, true =>
            { aig := { decls := aig.decls, cache := aig.cache, inv := ⋯ },
              ref := { gate := input.lhs.ref.gate, hgate := ⋯ } }
          | x, x_1, x_2, x_3 =>
            {
              aig :=
                { decls := aig.decls.push (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                  cache :=
                    Cache.insert aig.decls aig.cache
                      (Decl.gate input.lhs.ref.gate input.rhs.ref.gate input.lhs.inv input.rhs.inv),
                  inv := ⋯ },
              ref := { gate := aig.decls.size, hgate := ⋯ } }).aig.decls.size