Documentation

Bdd.Basic

@[implicit_reducible]
instance instToStringVector_bdd {k : } {α : Type u} [ToString α] :
Equations
inductive Pointer (m : ) :

Pointer to a BDD node or terminal

Instances For
    @[implicit_reducible]
    instance instFintypePointer {m✝ : } :
    Equations
    @[implicit_reducible]
    instance instReprPointer {m✝ : } :
    Repr (Pointer m✝)
    Equations
    def instReprPointer.repr {m✝ : } :
    Pointer m✝Std.Format
    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      @[implicit_reducible]
      instance instHashablePointer {m✝ : } :
      Equations
      @[implicit_reducible]
      Equations
      • One or more equations did not get rendered due to their size.
      inductive Pointer.le {m : } :
      Pointer mPointer mProp
      Instances For
        @[implicit_reducible]
        instance Pointer.instLE {m : } :
        Equations
        @[implicit_reducible]
        Equations
        structure Node (n m : ) :

        BDD node

        Instances For
          @[implicit_reducible]
          instance instDecidableEqNode {n✝ m✝ : } :
          DecidableEq (Node n✝ m✝)
          Equations
          def instDecidableEqNode.decEq {n✝ m✝ : } (x✝ x✝¹ : Node n✝ m✝) :
          Decidable (x✝ = x✝¹)
          Equations
          • One or more equations did not get rendered due to their size.
          Instances For
            def instReprNode.repr {n✝ m✝ : } :
            Node n✝ m✝Std.Format
            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              @[implicit_reducible]
              instance instReprNode {n✝ m✝ : } :
              Repr (Node n✝ m✝)
              Equations
              @[implicit_reducible]
              instance Node.instToString {n m : } :
              Equations
              structure Bdd (n m : ) :

              Raw BDD

              Instances For
                def instDecidableEqBdd.decEq {n✝ m✝ : } (x✝ x✝¹ : Bdd n✝ m✝) :
                Decidable (x✝ = x✝¹)
                Equations
                Instances For
                  @[implicit_reducible]
                  instance instDecidableEqBdd {n✝ m✝ : } :
                  DecidableEq (Bdd n✝ m✝)
                  Equations
                  @[implicit_reducible]
                  instance Bdd.instToString {n m : } :
                  Equations
                  inductive Edge {n m : } (M : Vector (Node n m) m) :
                  Pointer mPointer mProp
                  Instances For
                    theorem edge_iff {n m : } {M : Vector (Node n m) m} {p q : Pointer m} :
                    Edge M p q ∃ (j : Fin m), p = Pointer.node j (q = M[j].low q = M[j].high)
                    theorem not_terminal_edge {n✝ n✝¹ : } {w : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} {q : Pointer n✝¹} :

                    Terminals have no outgoing edges.

                    def Pointer.toVar {n m : } (M : Vector (Node n m) m) :
                    Pointer mFin n.succ
                    Equations
                    Instances For
                      @[simp]
                      theorem Pointer.toVar_terminal_eq {b : Bool} {n m : } (w : Vector (Node n m) m) :
                      toVar w (terminal b) = n,
                      @[simp]
                      theorem Pointer.toVar_node_eq {n m : } (w : Vector (Node n m) m) {j : Fin m} :
                      (toVar w (node j)) = w[j].var
                      theorem Pointer.toVar_heap_set {n n✝ : } {M : Vector (Node n✝ n) n} {N : Node n✝ n} {i j : Fin n} :
                      i j(toVar (M.set (↑i) N ) (node j)) = (toVar M (node j))
                      theorem Pointer.toVar_heap_set' {n n✝ : } {M : Vector (Node n✝ n) n} {N : Node n✝ n} {i j : Fin n} :
                      i jtoVar (M.set (↑i) N ) (node j) = toVar M (node j)
                      def Pointer.MayPrecede {n m : } (M : Vector (Node n m) m) (p q : Pointer m) :
                      Equations
                      Instances For
                        theorem Pointer.not_terminal_MayPrecede {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} {p : Pointer n✝¹} :

                        Terminals must not precede other pointers.

                        theorem Pointer.MayPrecede_node_terminal {b : Bool} {n m : } (w : Vector (Node n m) m) {j : Fin m} :

                        Non-terminals may precede terminals.

                        def Pointer.Reachable {n m : } (w : Vector (Node n m) m) (a : Pointer m) :
                        Equations
                        Instances For
                          theorem Pointer.Reachable.trans {n✝ n✝¹ : } {v : Vector (Node n✝ n✝¹) n✝¹} {a b c : Pointer n✝¹} (hab : Reachable v a b) (hbc : Reachable v b c) :
                          Reachable v a c
                          @[reducible, inline]
                          abbrev Bdd.RelevantPointer {n m : } (B : Bdd n m) :

                          B.RelevantPointer is the subtype of pointers reachable from B.root.

                          Equations
                          Instances For
                            @[implicit_reducible]
                            instance Bdd.instDecidableEqRelevantPointer {n✝ m✝ : } {B : Bdd n✝ m✝} :
                            Equations
                            def Bdd.toRelevantPointer {n m : } (B : Bdd n m) :
                            Equations
                            Instances For
                              @[reducible, inline]
                              abbrev Bdd.RelevantEdge {n m : } (B : Bdd n m) (p q : B.RelevantPointer) :

                              The Edge relation lifted to RelevantPointers.

                              Equations
                              Instances For
                                theorem Bdd.relevantEdge_of_edge_of_reachable {n m : } {p q : Pointer m} {B : Bdd n m} (e : Edge B.heap p q) (hp : Pointer.Reachable B.heap B.root p) :
                                def Bdd.RelevantMayPrecede {n m : } (B : Bdd n m) (p q : B.RelevantPointer) :

                                The MayPrecede relation lifted to RelevantPointers.

                                Equations
                                Instances For
                                  def Bdd.Ordered {n m : } (B : Bdd n m) :

                                  A BDD is Ordered if all edges relevant from the root respect the variable ordering.

                                  Equations
                                  Instances For
                                    theorem Bdd.Ordered_of_terminal {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} :
                                    { heap := M, root := Pointer.terminal b }.Ordered

                                    Terminals induce Ordered BDDs.

                                    theorem Bdd.Ordered_of_terminal' {n m : } {b : Bool} {B : Bdd n m} :
                                    def OBdd (n m : ) :
                                    Equations
                                    Instances For
                                      def OEdge {n m : } (O U : OBdd n m) :
                                      Equations
                                      Instances For
                                        def Bdd.var {n m : } (B : Bdd n m) :
                                        Equations
                                        Instances For
                                          def OBdd.var {n m : } (O : OBdd n m) :
                                          Equations
                                          Instances For
                                            def OBdd.rav {n m : } (B : OBdd n m) :
                                            Equations
                                            Instances For

                                              The OEdge relation between Ordered BDDs is well-founded.

                                              The OEdge relation between Ordered BDDs is converse well-founded.

                                              @[implicit_reducible]
                                              Equations
                                              theorem Bdd.ordered_of_reachable' {n m : } {p : Pointer m} {B : Bdd n m} :
                                              B.OrderedPointer.Reachable B.heap B.root p{ heap := B.heap, root := p }.Ordered
                                              theorem Bdd.ordered_of_reachable {n m : } {p : Pointer m} {O : OBdd n m} :
                                              Pointer.Reachable (↑O).heap (↑O).root p{ heap := (↑O).heap, root := p }.Ordered
                                              theorem Bdd.ordered_of_relevant {n m : } (O : OBdd n m) (S : (↑O).RelevantPointer) :
                                              { heap := (↑O).heap, root := S }.Ordered

                                              All BDDs in the graph of an Ordered BDD are Ordered.

                                              def Bdd.low {n m : } {j : Fin m} (B : Bdd n m) :
                                              B.root = Pointer.node jBdd n m
                                              Equations
                                              Instances For
                                                theorem Bdd.edge_of_low {n m : } {j : Fin m} (B : Bdd n m) {h : B.root = Pointer.node j} :
                                                Edge B.heap B.root (B.low h).root
                                                def Bdd.high {n m : } {j : Fin m} (B : Bdd n m) :
                                                B.root = Pointer.node jBdd n m
                                                Equations
                                                Instances For
                                                  theorem Bdd.edge_of_high {n m : } {j : Fin m} (B : Bdd n m) {h : B.root = Pointer.node j} :
                                                  Edge B.heap B.root (B.high h).root
                                                  theorem Bdd.reachable_of_edge {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {p q : Pointer n✝¹} :
                                                  Edge M p qPointer.Reachable M p q
                                                  theorem Bdd.ordered_of_relevant' {n m : } {v : Vector (Node n m) m} {q p : Pointer m} {B : Bdd n m} {h : B.heap = v} {r : B.root = q} :
                                                  B.OrderedPointer.Reachable v q p{ heap := v, root := p }.Ordered
                                                  theorem Bdd.ordered_of_edge {n m : } {p : Pointer m} {B : Bdd n m} :
                                                  B.OrderedEdge B.heap B.root p{ heap := B.heap, root := p }.Ordered
                                                  theorem Bdd.high_ordered {n m : } {j : Fin m} {B : Bdd n m} (h : B.root = Pointer.node j) :
                                                  B.Ordered(B.high h).Ordered
                                                  theorem Bdd.low_ordered {n m : } {j : Fin m} {B : Bdd n m} (h : B.root = Pointer.node j) :
                                                  B.Ordered(B.low h).Ordered
                                                  theorem Bdd.low_heap_eq_heap {n m : } {j : Fin m} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                  (B.low h).heap = B.heap
                                                  theorem Bdd.low_root_eq_low {n m : } {j : Fin m} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                  (B.low h).root = B.heap[j].low
                                                  theorem Bdd.high_heap_eq_heap {n m : } {j : Fin m} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                  (B.high h).heap = B.heap
                                                  theorem Bdd.high_root_eq_high {n m : } {j : Fin m} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                  (B.high h).root = B.heap[j].high
                                                  def OBdd.high {n m : } {j : Fin m} (O : OBdd n m) :
                                                  (↑O).root = Pointer.node jOBdd n m
                                                  Equations
                                                  Instances For
                                                    def OBdd.low {n m : } {j : Fin m} (O : OBdd n m) :
                                                    (↑O).root = Pointer.node jOBdd n m
                                                    Equations
                                                    Instances For
                                                      @[simp]
                                                      theorem OBdd.low_heap_eq_heap {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                      (↑(O.low h)).heap = (↑O).heap
                                                      theorem OBdd.low_root_eq_low {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                      (↑(O.low h)).root = (↑O).heap[j].low
                                                      @[simp]
                                                      theorem OBdd.high_heap_eq_heap {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                      (↑(O.high h)).heap = (↑O).heap
                                                      theorem OBdd.high_root_eq_high {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                      (↑(O.high h)).root = (↑O).heap[j].high
                                                      theorem oedge_of_low {n✝ m✝ : } {O : OBdd n✝ m✝} {j : Fin m✝} {h : (↑O).root = Pointer.node j} :
                                                      OEdge O (O.low h)
                                                      theorem oedge_of_high {n✝ m✝ : } {O : OBdd n✝ m✝} {j : Fin m✝} {h : (↑O).root = Pointer.node j} :
                                                      OEdge O (O.high h)
                                                      @[irreducible]
                                                      def OBdd.toTree {n m : } (O : OBdd n m) :
                                                      Equations
                                                      Instances For
                                                        theorem OBdd.evaluate_cast {n m n' : } {I : Vector Bool n'} {O : OBdd n m} (h : n = n') :
                                                        (h O).evaluate I = O.evaluate ( I)
                                                        def OBdd.HSimilar {n m m' : } (O : OBdd n m) (U : OBdd n m') :
                                                        Equations
                                                        Instances For
                                                          def OBdd.Similar {n m : } :
                                                          OBdd n mOBdd n mProp
                                                          Equations
                                                          Instances For
                                                            @[implicit_reducible]

                                                            Similarity of Ordered BDDs is decidable.

                                                            Equations
                                                            @[implicit_reducible]
                                                            instance OBdd.instDecidableHSimilar {n m m' : } (O : OBdd n m) (U : OBdd n m') :
                                                            Equations
                                                            def OBdd.SimilarRP {n m : } (O : OBdd n m) (p q : (↑O).RelevantPointer) :
                                                            Equations
                                                            Instances For
                                                              @[implicit_reducible]
                                                              instance OBdd.instDecidableSimilarRP {n✝ m✝ : } {O : OBdd n✝ m✝} {l r : (↑O).RelevantPointer} :
                                                              Equations

                                                              Isomorphism of Ordered BDDs is an equivalence relation.

                                                              inductive Pointer.Redundant {n m : } (M : Vector (Node n m) m) :

                                                              A pointer is redundant if it point to node N with N.low = N.high.

                                                              Instances For
                                                                @[implicit_reducible]
                                                                Equations
                                                                • One or more equations did not get rendered due to their size.
                                                                def Bdd.NoRedundancy {n m : } (B : Bdd n m) :
                                                                Equations
                                                                Instances For
                                                                  def OBdd.Reduced {n m : } (O : OBdd n m) :

                                                                  A BDD is Reduced if its graph does not contain redundant nodes or distinct similar subgraphs.

                                                                  Equations
                                                                  Instances For
                                                                    theorem transGen_iff_single_and_reflTransGen {α✝ : Type u_1} {r : α✝α✝Prop} {a b : α✝} :
                                                                    Relation.TransGen r a b ∃ (c : α✝), r a c Relation.ReflTransGen r c b
                                                                    def RelevantPointer.var {n m : } {B : Bdd n m} (p : B.RelevantPointer) :
                                                                    Equations
                                                                    Instances For
                                                                      def RelevantPointer.gap {n m : } {B : Bdd n m} (p : B.RelevantPointer) :
                                                                      Equations
                                                                      Instances For
                                                                        theorem RelevantEdge.flip_wellFounded {n✝ m✝ : } {B : Bdd n✝ m✝} (o : B.Ordered) :
                                                                        @[implicit_reducible]
                                                                        Equations
                                                                        @[implicit_reducible]
                                                                        instance OBdd.instDecidableReflTransGen {n m : } (O : OBdd n m) (p : (↑O).RelevantPointer) (q : Pointer m) :
                                                                        Equations
                                                                        @[implicit_reducible]
                                                                        instance Pointer.instDecidableReachable {n m : } (O : OBdd n m) :
                                                                        Equations
                                                                        def OBdd.size {n m : } (O : OBdd n m) :
                                                                        Equations
                                                                        Instances For
                                                                          @[implicit_reducible]
                                                                          Equations
                                                                          @[implicit_reducible]
                                                                          def Pointer.decidableEitherReachable {n m : } (O U : OBdd n m) (h : (↑O).heap = (↑U).heap) :
                                                                          DecidablePred fun (q : Pointer m) => Reachable (↑O).heap (↑O).root q Reachable (↑O).heap (↑U).root q
                                                                          Equations
                                                                          • One or more equations did not get rendered due to their size.
                                                                          Instances For
                                                                            @[implicit_reducible]
                                                                            def OBdd.fintypeEitherRelevantPointer {n m : } (O U : OBdd n m) (h : (↑O).heap = (↑U).heap) :
                                                                            Fintype { q : Pointer m // Pointer.Reachable (↑O).heap (↑O).root q Pointer.Reachable (↑O).heap (↑U).root q }
                                                                            Equations
                                                                            Instances For
                                                                              @[implicit_reducible]

                                                                              Reduced is decidable.

                                                                              Equations
                                                                              theorem eq_of_constant_eq {α : Sort u_1} {β : Sort u_2} {c c' : β} [Inhabited α] :
                                                                              Function.const α c = Function.const α c'c = c'

                                                                              The output of equal constant functions with inhabited domain is equal.

                                                                              theorem Bdd.terminal_or_node {n m : } (B : Bdd n m) :
                                                                              (∃ (b : Bool), B.root = Pointer.terminal b B = { heap := B.heap, root := Pointer.terminal b }) ∃ (j : Fin m), B.root = Pointer.node j B = { heap := B.heap, root := Pointer.node j }
                                                                              theorem OBdd.init_inductionOn {n m : } (t : OBdd n m) {motive : OBdd n mProp} (base : ∀ (b : Bool), motive { heap := (↑t).heap, root := Pointer.terminal b }, ) (step : ∀ (j : Fin m) (hl : { heap := (↑t).heap, root := (↑t).heap[j].low }.Ordered), motive { heap := (↑t).heap, root := (↑t).heap[j].low }, ∀ (hh : { heap := (↑t).heap, root := (↑t).heap[j].high }.Ordered), motive { heap := (↑t).heap, root := (↑t).heap[j].high }, ∀ (h : { heap := (↑t).heap, root := Pointer.node j }.Ordered), motive { heap := (↑t).heap, root := Pointer.node j }, ) :
                                                                              motive t
                                                                              def OBdd.isTerminal {n m : } (O : OBdd n m) :
                                                                              Equations
                                                                              Instances For
                                                                                theorem not_OEdge_of_isTerminal {n m : } {U O : OBdd n m} :
                                                                                theorem Bdd.terminal_relevant_iff {b : Bool} {n m : } {B : Bdd n m} (h : B.root = Pointer.terminal b) (S : B.RelevantPointer) {motive : Pointer mProp} :
                                                                                motive S motive (Pointer.terminal b)

                                                                                The graph induced by a terminal BDD consists of a sole terminal pointer.

                                                                                theorem Bdd.eq_terminal_of_relevant {b : Bool} {n m : } {v : Vector (Node n m) m} {B : Bdd n m} (h : B = { heap := v, root := Pointer.terminal b }) (S : B.RelevantPointer) :
                                                                                theorem OBdd.reduced_of_terminal {n m : } {O : OBdd n m} :

                                                                                Terminal BDDs are reduced.

                                                                                theorem Bdd.reduced_of_terminal {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} {o : { heap := M, root := Pointer.terminal b }.Ordered} :
                                                                                OBdd.Reduced { heap := M, root := Pointer.terminal b }, o
                                                                                theorem OBdd.reduced_of_relevant {n m : } {O : OBdd n m} (S : (↑O).RelevantPointer) :
                                                                                O.ReducedReduced { heap := (↑O).heap, root := S },

                                                                                Sub-BDDs of a reduced BDD are reduced.

                                                                                theorem OBdd.reachable_of_edge {n✝ n✝¹ : } {w : Vector (Node n✝ n✝¹) n✝¹} {p q : Pointer n✝¹} :
                                                                                Edge w p qPointer.Reachable w p q
                                                                                theorem OBdd.ordered_of_edge {n m : } {v : Vector (Node n m) m} {q : Pointer m} {O : OBdd n m} {h : (↑O).heap = v} {r : (↑O).root = q} (p : Pointer m) :
                                                                                Edge v q p{ heap := v, root := p }.Ordered
                                                                                theorem OBdd.ordered_of_low_edge {n n✝ : } {v : Vector (Node n✝ n) n} {j : Fin n} :
                                                                                { heap := v, root := Pointer.node j }.Ordered{ heap := v, root := v[j].low }.Ordered
                                                                                theorem OBdd.ordered_of_high_edge {n n✝ : } {v : Vector (Node n✝ n) n} {j : Fin n} :
                                                                                { heap := v, root := Pointer.node j }.Ordered{ heap := v, root := v[j].high }.Ordered
                                                                                @[simp]
                                                                                theorem OBdd.evaluate_node {n m : } {v : Vector (Node n m) m} {I : Vector Bool n} {j : Fin m} {h : { heap := v, root := Pointer.node j }.Ordered} :
                                                                                evaluate { heap := v, root := Pointer.node j }, h I = if I[v[j].var] = true then evaluate { heap := v, root := v[j].high }, I else evaluate { heap := v, root := v[j].low }, I

                                                                                Spell out OBdd.evaluate for non-terminals.

                                                                                theorem OBdd.evaluate_node' {n m : } {v : Vector (Node n m) m} {j : Fin m} {h : { heap := v, root := Pointer.node j }.Ordered} :
                                                                                evaluate { heap := v, root := Pointer.node j }, h = fun (I : Vector Bool n) => if I[v[j].var] = true then evaluate { heap := v, root := v[j].high }, I else evaluate { heap := v, root := v[j].low }, I
                                                                                @[simp]
                                                                                theorem OBdd.evaluate_terminal {b : Bool} {n m : } {v : Vector (Node n m) m} {h : { heap := v, root := Pointer.terminal b }.Ordered} :

                                                                                Spell out OBdd.evaluate for terminals.

                                                                                theorem OBdd.evaluate_terminal' {b : Bool} {n m : } {O : OBdd n m} :
                                                                                @[simp]
                                                                                theorem OBdd.toTree_terminal {b : Bool} {n m : } {v : Vector (Node n m) m} {h : { heap := v, root := Pointer.terminal b }.Ordered} :
                                                                                theorem OBdd.toTree_terminal' {b : Bool} {n m : } {O : OBdd n m} :
                                                                                theorem OBdd.HSimilar_of_terminal {n m m' : } {b : Bool} {O : OBdd n m} {U : OBdd n m'} :
                                                                                (↑O).root = Pointer.terminal b(↑U).root = Pointer.terminal bO.HSimilar U
                                                                                theorem OBdd.toTree_node {n m : } {O : OBdd n m} {j : Fin m} (h : (↑O).root = Pointer.node j) :
                                                                                theorem OBdd.evaluate_node'' {n m : } {O : OBdd n m} {j : Fin m} (h : (↑O).root = Pointer.node j) :
                                                                                O.evaluate = fun (I : Vector Bool n) => if I[(↑O).heap[j].var] = true then (O.high h).evaluate I else (O.low h).evaluate I
                                                                                theorem OBdd.var_lt_high_var {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                                                O.var < (O.high h).var
                                                                                theorem OBdd.var_lt_low_var {n m : } {j : Fin m} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                                                O.var < (O.low h).var
                                                                                theorem OBdd.independentOf_lt_root {n m : } (O : OBdd n m) (i : Fin O.var) :
                                                                                def OBdd.size' {n m : } :
                                                                                OBdd n m
                                                                                Equations
                                                                                Instances For
                                                                                  theorem OBdd.size_zero_of_terminal {n✝ m✝ : } {O : OBdd n✝ m✝} :
                                                                                  O.isTerminalO.size' = 0
                                                                                  theorem OBdd.high_reduced {n m : } {O : OBdd n m} {j : Fin m} {h : (↑O).root = Pointer.node j} :
                                                                                  O.Reduced(O.high h).Reduced
                                                                                  theorem OBdd.low_reduced {n m : } {O : OBdd n m} {j : Fin m} {h : (↑O).root = Pointer.node j} :
                                                                                  O.Reduced(O.low h).Reduced
                                                                                  theorem OBdd.size_node {n m : } {O : OBdd n m} {j : Fin m} (h : (↑O).root = Pointer.node j) :
                                                                                  O.size' = 1 + (O.low h).size' + (O.high h).size'
                                                                                  theorem OBdd.evaluate_high_eq_evaluate_set_true {n m : } {O : OBdd n m} {j : Fin m} {h : (↑O).root = Pointer.node j} :
                                                                                  (O.high h).evaluate = O.evaluate fun (I : Vector Bool n) => I.set (↑(↑O).heap[j].var) true
                                                                                  theorem OBdd.evaluate_low_eq_evaluate_set_false {n m : } {O : OBdd n m} {j : Fin m} {h : (↑O).root = Pointer.node j} :
                                                                                  (O.low h).evaluate = O.evaluate fun (I : Vector Bool n) => I.set (↑(↑O).heap[j].var) false
                                                                                  theorem OBdd.evaluate_high_eq_of_evaluate_eq_and_var_eq' {n m m' : } {O : OBdd n m} {U : OBdd n m'} {j : Fin m} {i : Fin m'} {ho : (↑O).root = Pointer.node j} {hu : (↑U).root = Pointer.node i} :
                                                                                  O.evaluate = U.evaluate(↑O).heap[j].var = (↑U).heap[i].var(O.high ho).evaluate = (U.high hu).evaluate
                                                                                  theorem OBdd.evaluate_high_eq_of_evaluate_eq_and_var_eq {n m : } {O U : OBdd n m} {j i : Fin m} {ho : (↑O).root = Pointer.node j} {hu : (↑U).root = Pointer.node i} :
                                                                                  O.evaluate = U.evaluate(↑O).heap[j].var = (↑U).heap[i].var(O.high ho).evaluate = (U.high hu).evaluate
                                                                                  theorem OBdd.evaluate_low_eq_of_evaluate_eq_and_var_eq' {n m m' : } {O : OBdd n m} {U : OBdd n m'} {j : Fin m} {i : Fin m'} {ho : (↑O).root = Pointer.node j} {hu : (↑U).root = Pointer.node i} :
                                                                                  O.evaluate = U.evaluate(↑O).heap[j].var = (↑U).heap[i].var(O.low ho).evaluate = (U.low hu).evaluate
                                                                                  theorem OBdd.evaluate_low_eq_of_evaluate_eq_and_var_eq {n m : } {O U : OBdd n m} {j i : Fin m} {ho : (↑O).root = Pointer.node j} {hu : (↑U).root = Pointer.node i} :
                                                                                  O.evaluate = U.evaluate(↑O).heap[j].var = (↑U).heap[i].var(O.low ho).evaluate = (U.low hu).evaluate
                                                                                  theorem OBdd.not_reduced_of_sim_high_low {n m : } {O : OBdd n m} {j : Fin m} (h : (↑O).root = Pointer.node j) :
                                                                                  (O.high h).Similar (O.low h)¬O.Reduced
                                                                                  def OBdd.HIsomorphism {n m n' m' : } (O : OBdd n m) (U : OBdd n' m') :
                                                                                  Equations
                                                                                  • One or more equations did not get rendered due to their size.
                                                                                  Instances For
                                                                                    def OBdd.Isomorphism {n m : } :
                                                                                    OBdd n mOBdd n mProp
                                                                                    Equations
                                                                                    Instances For
                                                                                      def OBdd.RelevantIsomorphism {n m : } (O : OBdd n m) (p q : (↑O).RelevantPointer) :
                                                                                      Equations
                                                                                      Instances For
                                                                                        def OBdd.Reduced' {n m : } (O : OBdd n m) :
                                                                                        Equations
                                                                                        Instances For
                                                                                          theorem OBdd.Canonicity {n m m' : } {O : OBdd n m} {U : OBdd n m'} (ho : O.Reduced) (hu : U.Reduced) :

                                                                                          Reduced OBDDs are canonical.

                                                                                          theorem OBdd.terminal_of_constant {n m : } {b : Bool} (O : OBdd n m) :
                                                                                          O.Reduced(O.evaluate = fun (x : Vector Bool n) => b) → (↑O).root = Pointer.terminal b

                                                                                          The only reduced BDD that denotes a constant function is the terminal BDD.

                                                                                          theorem OBdd.Canonicity_reverse {n m m' : } {O : OBdd n m} {U : OBdd n m'} :
                                                                                          theorem OBdd.not_oedge_reachable {n m : } {O U : OBdd n m} :
                                                                                          OEdge O U¬Pointer.Reachable (↑O).heap (↑U).root (↑O).root

                                                                                          An acyclicity lemma: an edge from O to U implies that O is not reachable from U.

                                                                                          theorem Pointer.Reachable_iff {n m : } {r p : Pointer m} {M : Vector (Node n m) m} :
                                                                                          Reachable M r p r = p ∃ (j : Fin m), r = node j (Reachable M M[j].low p Reachable M M[j].high p)
                                                                                          theorem OBdd.reachable_or_eq_low_high {n m : } {p : Pointer m} {O : OBdd n m} :
                                                                                          Pointer.Reachable (↑O).heap (↑O).root p(↑O).root = p ∃ (j : Fin m) (h : (↑O).root = Pointer.node j), Pointer.Reachable (↑O).heap (↑(O.low h)).root p Pointer.Reachable (↑O).heap (↑(O.high h)).root p
                                                                                          theorem not_isTerminal_of_root_eq_node {n m : } {j : Fin m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                          def OBdd.OReachable {n m : } (a : OBdd n m) :
                                                                                          OBdd n mProp
                                                                                          Equations
                                                                                          Instances For
                                                                                            theorem OBdd.low_oreachable {n m : } {j : Fin m} {O U : OBdd n m} {U_root_def : (↑U).root = Pointer.node j} :
                                                                                            O.OReachable UO.OReachable (U.low U_root_def)
                                                                                            theorem OBdd.high_oreachable {n m : } {j : Fin m} {O U : OBdd n m} {U_root_def : (↑U).root = Pointer.node j} :
                                                                                            O.OReachable UO.OReachable (U.high U_root_def)
                                                                                            theorem OBdd.reachable_node_iff {n m : } {j : Fin m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                            Pointer.Reachable (↑O).heap (↑O).root = fun (q : Pointer m) => Pointer.Reachable (↑O).heap (↑O).root q ¬Pointer.Reachable (↑O).heap (↑(O.low h)).root q ¬Pointer.Reachable (↑O).heap (↑(O.high h)).root q Pointer.Reachable (↑O).heap (↑(O.low h)).root q ¬Pointer.Reachable (↑O).heap (↑(O.high h)).root q Pointer.Reachable (↑O).heap (↑(O.high h)).root q ¬Pointer.Reachable (↑O).heap (↑(O.low h)).root q Pointer.Reachable (↑O).heap (↑(O.low h)).root q Pointer.Reachable (↑O).heap (↑(O.high h)).root q
                                                                                            @[implicit_reducible]
                                                                                            instance OBdd.instFintypeReachableFromNode {n m : } {j : Fin m} (O : OBdd n m) (h : (↑O).root = Pointer.node j) :
                                                                                            Fintype { q : Pointer m // q = (↑O).root Pointer.Reachable (↑O).heap (↑(O.low h)).root q Pointer.Reachable (↑O).heap (↑(O.high h)).root q }
                                                                                            Equations
                                                                                            • One or more equations did not get rendered due to their size.
                                                                                            theorem OBdd.reachable_from_node_iff' {n m : } {j : Fin m} {p : Pointer m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                            Pointer.Reachable (↑O).heap (↑O).root p p = (↑O).root Pointer.Reachable (↑O).heap (↑(O.low h)).root p Pointer.Reachable (↑O).heap (↑(O.high h)).root p
                                                                                            theorem OBdd.card_reachable_node' {n m : } {j : Fin m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                            Fintype.card { p : Pointer m // Pointer.Reachable (↑O).heap (↑O).root p } = Fintype.card { p : Pointer m // p = (↑O).root Pointer.Reachable (↑O).heap (↑(O.low h)).root p Pointer.Reachable (↑O).heap (↑(O.high h)).root p }
                                                                                            theorem OBdd.eq_root_disjoint_reachable_low_or_high {n m : } {j : Fin m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                            Disjoint (fun (x : Pointer m) => x = (↑O).root) fun (p : Pointer m) => Pointer.Reachable (↑O).heap (↑(O.low h)).root p Pointer.Reachable (↑O).heap (↑(O.high h)).root p
                                                                                            theorem OBdd.card_reachable_node {n m : } {j : Fin m} {O : OBdd n m} (h : (↑O).root = Pointer.node j) :
                                                                                            Fintype.card { q : Pointer m // Pointer.Reachable (↑O).heap (↑O).root q } = 1 + Fintype.card { q : Pointer m // Pointer.Reachable (↑(O.low h)).heap (↑(O.low h)).root q Pointer.Reachable (↑(O.high h)).heap (↑(O.high h)).root q }
                                                                                            theorem Bdd.ordered_of_low_high_ordered {n m : } {j : Fin m} {B : Bdd n m} (h : B.root = Pointer.node j) :
                                                                                            (B.low h).OrderedB.var < (B.low h).var(B.high h).OrderedB.var < (B.high h).varB.Ordered
                                                                                            theorem Bdd.ordered_of_ordered_heap_not_reachable_set {n m : } (O : OBdd n m) (i : Fin m) (N : Node n m) :
                                                                                            ¬Pointer.Reachable (↑O).heap (↑O).root (Pointer.node i){ heap := (↑O).heap.set (↑i) N , root := (↑O).root }.Ordered
                                                                                            theorem Pointer.mayPrecede_of_reachable {n m : } {p : Pointer m} {B : Bdd n m} :
                                                                                            B.OrderedReachable B.heap B.root ptoVar B.heap B.root toVar B.heap p
                                                                                            theorem OBdd.reduced_var_dependent {n m : } {O : OBdd n m} {p : Fin n} :
                                                                                            O.Reduced(∀ (i : Fin p), Nary.IndependentOf O.evaluate i, )p (↑O).var
                                                                                            def Bdd.usesVar {n m : } (B : Bdd n m) (i : Fin n) :
                                                                                            Equations
                                                                                            Instances For
                                                                                              theorem Bdd.usesVar_of_high_usesVar {n m : } {j : Fin m} {i : Fin n} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                                                              (B.high h).usesVar iB.usesVar i
                                                                                              theorem Bdd.usesVar_of_low_usesVar {n m : } {j : Fin m} {i : Fin n} {B : Bdd n m} {h : B.root = Pointer.node j} :
                                                                                              (B.low h).usesVar iB.usesVar i
                                                                                              theorem OBdd.usesVar_of_high_usesVar {n m : } {j : Fin m} {i : Fin n} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                                                              (↑(O.high h)).usesVar i(↑O).usesVar i
                                                                                              theorem OBdd.usesVar_of_low_usesVar {n m : } {j : Fin m} {i : Fin n} {O : OBdd n m} {h : (↑O).root = Pointer.node j} :
                                                                                              (↑(O.low h)).usesVar i(↑O).usesVar i
                                                                                              theorem OBdd.dependsOn_of_usesVar_of_reduced {n m : } {j : Fin m} {i : Fin n} {O : OBdd n m} :
                                                                                              O.ReducedPointer.Reachable (↑O).heap (↑O).root (Pointer.node j)(↑O).heap[j].var = i∃ (v : Vector Bool n), O.evaluate v O.evaluate (v.set (↑i) true )
                                                                                              theorem OBdd.usesVar_of_dependsOn {n m : } {v : Vector Bool n} {b : Bool} {O : OBdd n m} {i : Fin n} :
                                                                                              O.evaluate v O.evaluate (v.set (↑i) b )(↑O).usesVar i
                                                                                              theorem OBdd.usesVar_iff_dependsOn_of_reduced {n m : } {i : Fin n} {O : OBdd n m} :
                                                                                              theorem OBdd.usesVar_iff {n m : } (i : Fin n) (O : OBdd n m) :
                                                                                              (↑O).usesVar i ∃ (j : Fin m) (hj : (↑O).root = Pointer.node j), (↑O).heap[j].var = i (↑(O.low hj)).usesVar i (↑(O.high hj)).usesVar i
                                                                                              theorem OBdd.toTree_usesVar {n m : } {i : Fin n} {O : OBdd n m} :
                                                                                              theorem OBdd.evaluate_eq_of_forall_usesVar {n m : } {O : OBdd n m} {I J : Vector Bool n} :
                                                                                              (∀ (i : Fin n), (↑O).usesVar iI[i] = J[i])O.evaluate I = O.evaluate J
                                                                                              theorem Pointer.eq_terminal_of_reachable {n✝ n✝¹ : } {w : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} {p : Pointer n✝¹} :
                                                                                              Reachable w (terminal b) pp = terminal b
                                                                                              theorem Bdd.not_usesVar_of_terminal {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {b : Bool} {i : Fin n✝} :
                                                                                              ¬{ heap := M, root := Pointer.terminal b }.usesVar i
                                                                                              theorem Bdd.not_usesVar_of_var_gt {n m : } {i : Fin n} {M : Vector (Node n m) m} {j : Fin m} :
                                                                                              { heap := M, root := Pointer.node j }.OrderedM[j].var > i¬{ heap := M, root := Pointer.node j }.usesVar i
                                                                                              @[implicit_reducible]
                                                                                              instance OBdd.instDecidableUsesVar {n m : } {O : OBdd n m} :
                                                                                              Equations
                                                                                              theorem Bdd.terminal_of_zero_vars {n m : } {B : Bdd n m} :
                                                                                              n = 0∃ (b : Bool), B.root = Pointer.terminal b
                                                                                              theorem Bdd.terminal_of_zero_heap {n m : } {B : Bdd n m} :
                                                                                              m = 0∃ (b : Bool), B.root = Pointer.terminal b
                                                                                              theorem Pointer.toVar_lt_of_trans_edge_of_ordered {n✝ n✝¹ : } {M : Vector (Node n✝ n✝¹) n✝¹} {x y : Pointer n✝¹} :
                                                                                              { heap := M, root := x }.OrderedRelation.TransGen (Edge M) x ytoVar M x < toVar M y
                                                                                              def Pointer.equiv {m m' : } (p : Pointer m) (p' : Pointer m') :
                                                                                              Equations
                                                                                              Instances For
                                                                                                theorem Pointer.equiv_refl {m : } (p : Pointer m) :
                                                                                                p.equiv p
                                                                                                theorem Pointer.equiv_symm {m m✝ : } {q : Pointer m✝} {p : Pointer m} :
                                                                                                p.equiv qq.equiv p
                                                                                                def Node.equiv {n m n' m' : } (N : Node n m) (N' : Node n' m') :
                                                                                                Equations
                                                                                                Instances For
                                                                                                  theorem Node.equiv_refl {n m : } (N : Node n m) :
                                                                                                  N.equiv N
                                                                                                  theorem Node.equiv_symm {n✝ m✝ : } {N : Node n✝ m✝} {n✝¹ m✝¹ : } {M : Node n✝¹ m✝¹} :
                                                                                                  N.equiv MM.equiv N
                                                                                                  theorem Bdd.ordered_of_ordered_heap_all_reachable_eq {n m m' : } (O : OBdd n m) (B : Bdd n m') :
                                                                                                  (∀ (j : Fin m'), Pointer.Reachable B.heap B.root (Pointer.node j)∃ (hj : j < m), (↑O).heap[j].equiv B.heap[j])(∀ (j : Fin m'), B.root = Pointer.node j∃ (hj : j < m), (↑O).root = Pointer.node j, hj)B.Ordered
                                                                                                  theorem OBdd.toTree_eq_toTree_of_ordered_heap_all_reachable_eq {n m m' : } (O : OBdd n m) (U : OBdd n m') :
                                                                                                  (∀ (j : Fin m'), Pointer.Reachable (↑U).heap (↑U).root (Pointer.node j)∃ (hj : j < m), (↑O).heap[j].equiv (↑U).heap[j])(↑U).root.equiv (↑O).rootO.toTree = U.toTree
                                                                                                  theorem OBdd.evaluate_eq_evaluate_of_ordered_heap_all_reachable_eq {n m m' : } (O : OBdd n m) (U : OBdd n m') :
                                                                                                  (∀ (j : Fin m'), Pointer.Reachable (↑U).heap (↑U).root (Pointer.node j)∃ (hj : j < m), (↑O).heap[j].equiv (↑U).heap[j])(↑U).root.equiv (↑O).rootO.evaluate = U.evaluate
                                                                                                  structure RawBdd.RawNode (n : ) :
                                                                                                  Instances For
                                                                                                    Equations
                                                                                                    Instances For
                                                                                                      theorem RawBdd.RawPointer.bounded_of_le {m m' : } {p : RawPointer} (hm : Bounded m p) (h : m m') :
                                                                                                      Bounded m' p
                                                                                                      theorem RawBdd.RawPointer.cook_equiv {m1 : } {p : RawPointer} {m2 : } {h1 : Bounded m1 p} {h2 : Bounded m2 p} :
                                                                                                      (p.cook ).equiv (p.cook )
                                                                                                      theorem RawBdd.RawPointer.cook_eq {m : } {p : RawPointer} {h1 h2 : Bounded m p} :
                                                                                                      p.cook = p.cook

                                                                                                      cook ignores the Bounded witness: the bound is a Prop, so two cooks of the same raw pointer at the same heap size are equal.

                                                                                                      theorem RawBdd.RawNode.bounded_of_le {n m m' : } {N : RawNode n} (hm : Bounded m N) (h : m m') :
                                                                                                      Bounded m' N
                                                                                                      def RawBdd.RawNode.cook {n m : } (N : RawNode n) (h : Bounded m N) :
                                                                                                      Node n m
                                                                                                      Equations
                                                                                                      Instances For
                                                                                                        theorem RawBdd.RawNode.cook_equiv {n✝ : } {N : RawNode n✝} {m✝ : } {h1 : Bounded m✝ N} {m✝¹ : } {h2 : Bounded m✝¹ N} :
                                                                                                        (N.cook h1).equiv (N.cook h2)
                                                                                                        def RawBdd.cook_heap {n c : } (v : Vector (RawNode n) c) (hh : ∀ (i : Fin c), RawNode.Bounded (↑i) v[i]) :
                                                                                                        Vector (Node n c) c
                                                                                                        Equations
                                                                                                        Instances For
                                                                                                          def RawBdd.toVar_or {n m : } (M : Vector (Node n m) m) :
                                                                                                          Pointer m
                                                                                                          Equations
                                                                                                          Instances For
                                                                                                            @[simp]
                                                                                                            theorem RawBdd.toVar_or_terminal_eq {b : Bool} {i n m : } (w : Vector (Node n m) m) :
                                                                                                            @[simp]
                                                                                                            theorem RawBdd.toVar_or_node_eq {i n m : } (w : Vector (Node n m) m) {j : Fin m} :
                                                                                                            theorem RawBdd.cook_low {n m : } {rn : RawNode n} {h1 : RawPointer.Bounded m rn.lo} {h2 : RawNode.Bounded m rn} :
                                                                                                            rn.lo.cook h1 = (rn.cook h2).low
                                                                                                            theorem RawBdd.cook_high {n m : } {rn : RawNode n} {h1 : RawPointer.Bounded m rn.hi} {h2 : RawNode.Bounded m rn} :
                                                                                                            rn.hi.cook h1 = (rn.cook h2).high
                                                                                                            theorem RawBdd.cook_inj {m : } {p q : RawPointer} {hp : RawPointer.Bounded m p} {hq : RawPointer.Bounded m q} :
                                                                                                            p.cook hp = q.cook hqp = q
                                                                                                            theorem RawBdd.cook_aux {n✝ : } {j : Fin n✝} {a✝ : } {hj : j < a✝} {p : RawPointer} {h1 : RawPointer.Bounded n✝ p} {h2 : RawPointer.Bounded a✝ p} :
                                                                                                            p.cook h1 = Pointer.node jp.cook h2 = Pointer.node j, hj
                                                                                                            theorem RawBdd.push_ordered {n✝ n✝¹ : } {v : Vector (RawNode n✝) n✝¹} {h0 : ∀ (i : Fin n✝¹), RawNode.Bounded (↑i) v[i]} {p : RawPointer} {h1 : RawPointer.Bounded n✝¹ p} {N : RawNode n✝} {h2 : ∀ (i : Fin (n✝¹ + 1)), RawNode.Bounded (↑i) (v.push N)[i]} {h3 : RawPointer.Bounded (n✝¹ + 1) p} :
                                                                                                            { heap := cook_heap v h0, root := p.cook h1 }.Ordered{ heap := cook_heap (v.push N) h2, root := p.cook h3 }.Ordered
                                                                                                            theorem RawBdd.push_evaluate {p : RawPointer} {m✝ : } {hq : RawPointer.Bounded m✝ p} {n✝ : } {N : RawNode n✝} {hp : RawPointer.Bounded (m✝ + 1) p} {v : Vector (RawNode n✝) m✝} {h0 : ∀ (i : Fin (m✝ + 1)), RawNode.Bounded (↑i) (v.push N)[i]} {h1 : ∀ (i : Fin m✝), RawNode.Bounded (↑i) v[i]} {ho : { heap := cook_heap (v.push N) h0, root := p.cook hp }.Ordered} {hu : { heap := cook_heap v h1, root := p.cook hq }.Ordered} :
                                                                                                            OBdd.evaluate { heap := cook_heap (v.push N) h0, root := p.cook hp }, = OBdd.evaluate { heap := cook_heap v h1, root := p.cook },