Documentation

Std.Sat.AIG.If

Besides introducing a way to construct an if statement in an AIG, this module also demonstrates a style of writing Lean code that minimizes the risk of linearity issues on the AIG.

The idea is to always keep one aig variable around that contains the AIG and continously shadow it. However, applying multiple operations to the AIG does often require Ref.cast to use other inputs or Refs created by previous operations in later ones. Applying a Ref.cast would usually require keeping around the old AIG to state the theorem statement. Luckily in this situation Lean is usually always able to infer the theorem statement on it's own. For this reason the style goes as follows:

let res := someLawfulOperator aig input
let aig := res.aig
let ref := res.ref
have := LawfulOperator.le_size (f := mkIfCached) ..
let input1 := input1.cast this
let input2 := input2.cast this
-- ...
-- Next `LawfulOperator` application

This style also generalizes to applications of LawfulVecOperators.

def Std.Sat.AIG.mkIfCached {α : Type} [Hashable α] [DecidableEq α] (aig : Std.Sat.AIG α) (input : aig.TernaryInput) :
Equations
  • One or more equations did not get rendered due to their size.
Instances For
    instance Std.Sat.AIG.instLawfulOperatorTernaryInputMkIfCached {α : Type} [Hashable α] [DecidableEq α] :
    Std.Sat.AIG.LawfulOperator α Std.Sat.AIG.TernaryInput Std.Sat.AIG.mkIfCached
    Equations
    • Std.Sat.AIG.instLawfulOperatorTernaryInputMkIfCached = { le_size := , decl_eq := }
    theorem Std.Sat.AIG.if_as_bool (d : Bool) (l : Bool) (r : Bool) :
    (if d = true then l else r) = (d && l || !d && r)
    @[simp]
    theorem Std.Sat.AIG.denote_mkIfCached {α : Type} [Hashable α] [DecidableEq α] {assign : αBool} {aig : Std.Sat.AIG α} {input : aig.TernaryInput} :
    assign, aig.mkIfCached input = if assign, { aig := aig, ref := input.discr } = true then assign, { aig := aig, ref := input.lhs } else assign, { aig := aig, ref := input.rhs }
    structure Std.Sat.AIG.RefVec.IfInput {α : Type} [Hashable α] [DecidableEq α] (aig : Std.Sat.AIG α) (w : Nat) :
    • discr : aig.Ref
    • lhs : aig.RefVec w
    • rhs : aig.RefVec w
    Instances For
      Equations
      Instances For
        @[irreducible]
        def Std.Sat.AIG.RefVec.ite.go {α : Type} [Hashable α] [DecidableEq α] {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) :
        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          @[irreducible]
          theorem Std.Sat.AIG.RefVec.ite.go_le_size {α : Type} [Hashable α] [DecidableEq α] {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) :
          aig.decls.size (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig.decls.size
          @[irreducible]
          theorem Std.Sat.AIG.RefVec.ite.go_decl_eq {α : Type} [Hashable α] [DecidableEq α] {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) (idx : Nat) (h1 : idx < aig.decls.size) (h2 : idx < (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig.decls.size) :
          (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig.decls[idx] = aig.decls[idx]
          instance Std.Sat.AIG.RefVec.instLawfulVecOperatorIfInputIte {α : Type} [Hashable α] [DecidableEq α] :
          Std.Sat.AIG.LawfulVecOperator α Std.Sat.AIG.RefVec.IfInput fun {len : Nat} => Std.Sat.AIG.RefVec.ite
          Equations
          • Std.Sat.AIG.RefVec.instLawfulVecOperatorIfInputIte = { le_size := , decl_eq := }
          @[irreducible]
          theorem Std.Sat.AIG.RefVec.ite.go_get_aux {α : Type} [Hashable α] [DecidableEq α] {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) (idx : Nat) (hidx : idx < curr) (hfoo : aig.decls.size (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig.decls.size) :
          (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).vec.get idx = (s.get idx hidx).cast hfoo
          theorem Std.Sat.AIG.RefVec.ite.go_get {α : Type} [Hashable α] [DecidableEq α] {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) (idx : Nat) (hidx : idx < curr) :
          (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).vec.get idx = (s.get idx hidx).cast
          theorem Std.Sat.AIG.RefVec.ite.go_denote_mem_prefix {α : Type} [Hashable α] [DecidableEq α] {assign : αBool} {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) (start : Nat) (hstart : start < aig.decls.size) :
          assign, { aig := (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig, ref := { gate := start, hgate := } } = assign, { aig := aig, ref := { gate := start, hgate := hstart } }
          @[irreducible]
          theorem Std.Sat.AIG.RefVec.ite.denote_go {α : Type} [Hashable α] [DecidableEq α] {assign : αBool} {w : Nat} (aig : Std.Sat.AIG α) (curr : Nat) (hcurr : curr w) (discr : aig.Ref) (lhs : aig.RefVec w) (rhs : aig.RefVec w) (s : aig.RefVec curr) (idx : Nat) (hidx1 : idx < w) :
          curr idxassign, { aig := (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).aig, ref := (Std.Sat.AIG.RefVec.ite.go aig curr hcurr discr lhs rhs s).vec.get idx hidx1 } = if assign, { aig := aig, ref := discr } = true then assign, { aig := aig, ref := lhs.get idx hidx1 } else assign, { aig := aig, ref := rhs.get idx hidx1 }
          @[simp]
          theorem Std.Sat.AIG.RefVec.denote_ite {α : Type} [Hashable α] [DecidableEq α] {w : Nat} {assign : αBool} {aig : Std.Sat.AIG α} {input : Std.Sat.AIG.RefVec.IfInput aig w} (idx : Nat) (hidx : idx < w) :
          assign, { aig := (Std.Sat.AIG.RefVec.ite aig input).aig, ref := (Std.Sat.AIG.RefVec.ite aig input).vec.get idx hidx } = if assign, { aig := aig, ref := input.discr } = true then assign, { aig := aig, ref := input.lhs.get idx hidx } else assign, { aig := aig, ref := input.rhs.get idx hidx }