Documentation

Complexitylib.Circuits.Basic

Boolean Circuit Complexity #

This file defines Boolean circuits parameterized by a basis of operations and establishes the circuit size complexity measure for Boolean functions.

Main definitions #

Main results #

@[reducible, inline]

A BitString of length n.

Equations
Instances For
    @[reducible, inline]

    A family of Boolean functions indexed by input length N.

    Each member maps N-bit strings to a single output bit.

    Equations
    Instances For

      Arity constraint for operations in a basis.

      • unbounded : Arity

        Any number of inputs is allowed.

      • exactly (k : ) : Arity

        Exactly k inputs are required.

      • upto (k : ) : Arity

        At most k inputs are allowed.

      Instances For
        Equations
        Instances For

          Whether n satisfies an arity constraint.

          Equations
          Instances For
            @[implicit_reducible]
            Equations
            • One or more equations did not get rendered due to their size.
            structure Complexity.Basis :

            A basis of Boolean operations.

            Each operation has an arity constraint and an evaluation function that computes the output bit from any valid number of input bits.

            • Op : Type

              The type of operations (e.g., AND, OR, NOT).

            • arity : self.OpArity

              The arity constraint for each operation.

            • eval (op : self.Op) (n : ) : (self.arity op).satisfiedBy nBitString nBool

              Evaluate an operation on n input bits, given that n satisfies the arity.

            Instances For
              structure Complexity.Gate (B : Basis) (W : ) :

              A gate in a circuit over basis B with W wires available as inputs. The gate's fan-in must satisfy the arity constraint of its operation, and each input is wired to one of the W available wires.

              • op : B.Op

                The basis operation this gate computes.

              • fanIn :

                The number of inputs this gate reads.

              • arityOk : (B.arity self.op).satisfiedBy self.fanIn

                Proof that fanIn satisfies the arity constraint of op.

              • inputs : Fin self.fanInFin W

                The wire each of the gate's fanIn inputs is connected to.

              • negated : Fin self.fanInBool

                Per-input negation flag. Negations are free under this library's size convention.

              Instances For
                def Complexity.Gate.eval {B : Basis} {W : } (g : Gate B W) (wireVal : BitString W) :

                Evaluate a gate given a wire-value assignment.

                Equations
                Instances For
                  structure Complexity.Circuit (B : Basis) (N M G : ) [NeZero N] [NeZero M] :

                  A Boolean circuit over basis B with N inputs, M outputs, and G internal gates.

                  All gates reference wires from Fin (N + G). The acyclic field ensures that internal gate i only reads wires 0, …, N + i − 1, preventing cycles.

                  • gates : Fin GGate B (N + G)

                    The internal gates; gate i drives wire N + i.

                  • outputs : Fin MGate B (N + G)

                    The output gates; output bit j is the value of gate outputs j.

                  • acyclic (i : Fin G) (k : Fin (self.gates i).fanIn) : ((self.gates i).inputs k) < N + i

                    Acyclicity: internal gate i only reads wires 0, …, N + i − 1.

                  Instances For
                    @[irreducible]
                    def Complexity.Circuit.wireValue {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (input : BitString N) (w : Fin (N + G)) :

                    Value of wire w when the circuit is fed input.

                    The first N wires carry the primary inputs. Wire N + i carries the output of internal gate i.

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      theorem Complexity.Circuit.wireValue_of_lt {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (input : BitString N) (w : Fin (N + G)) (h : w < N) :
                      c.wireValue input w = input w, h

                      On primary input wires (index < N), wireValue is the corresponding input bit.

                      theorem Complexity.Circuit.wireValue_of_not_lt {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (input : BitString N) (w : Fin (N + G)) (h : ¬w < N) :
                      c.wireValue input w = (c.gates w - N, ).eval (c.wireValue input)

                      On internal gate wires (index ≥ N), wireValue is the evaluation of gate w − N on the values of its input wires.

                      @[irreducible]
                      def Complexity.Circuit.wireDepth {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (w : Fin (N + G)) :

                      Depth of wire w in the circuit DAG.

                      Primary inputs have depth 0. Wire N + i (internal gate i) has depth 1 + max over input wires.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For
                        @[simp]
                        theorem Complexity.Circuit.wireDepth_of_lt {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (w : Fin (N + G)) (h : w < N) :
                        c.wireDepth w = 0

                        Primary input wires (index < N) have depth 0.

                        theorem Complexity.Circuit.wireDepth_of_not_lt {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (w : Fin (N + G)) (h : ¬w < N) :
                        c.wireDepth w = 1 + Fin.foldl (c.gates w - N, ).fanIn (fun (acc : ) (k : Fin (c.gates w - N, ).fanIn) => max acc (c.wireDepth ((c.gates w - N, ).inputs k))) 0

                        Internal gate wires (index ≥ N) have depth 1 + max over their input wires. Unfolds one step of wireDepth for the gate case.

                        def Complexity.Circuit.outputDepth {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (j : Fin M) :

                        Depth contributed by a single output gate: one layer for the gate itself plus the maximum wireDepth of its inputs. Always ≥ 1.

                        Equations
                        Instances For
                          def Complexity.Circuit.depth {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) :

                          Depth of a circuit: the maximum outputDepth over all output gates.

                          Equations
                          Instances For
                            def Complexity.Circuit.eval {B : Basis} {N M G : } [NeZero N] [NeZero M] (c : Circuit B N M G) (input : BitString N) :

                            Evaluate a circuit: map an N-bit input to an M-bit output.

                            Equations
                            Instances For
                              def Complexity.Circuit.size {B : Basis} {N M G : } [NeZero N] [NeZero M] :
                              Circuit B N M G

                              The library's circuit size: internal gates plus output gates.

                              Primary input vertices are not counted, and the negation flags on gate inputs have zero cost. Some texts instead count input vertices and explicit NOT gates; those conventions agree only up to additive/linear overhead, not on exact size bounds.

                              Equations
                              Instances For

                                A basis is complete if every Boolean function can be computed by some circuit over it.

                                Instances
                                  theorem Complexity.CompleteBasis.of_simulation (B₁ B₂ : Basis) [CompleteBasis B₁] (sim : ∀ {N M G : } [inst : NeZero N] [inst_1 : NeZero M] (c : Circuit B₁ N M G), ∃ (G' : ) (c' : Circuit B₂ N M G'), c'.eval = c.eval) :

                                  If every circuit over B₁ can be simulated by a circuit over B₂ (possibly with a different number of internal gates), then completeness of B₁ implies completeness of B₂.

                                  This is the generic tool for proving new bases complete: show you can compile each gate of a known-complete basis into a subcircuit of the new basis.

                                  noncomputable def Complexity.Circuit.sizeComplexity {N : } [NeZero N] (B : Basis) (f : BitString NBool) :

                                  The minimum circuit size over basis B computing a Boolean function f.

                                  A single-output circuit Circuit B N 1 G computes f when (fun x => (c.eval x) 0) = f. The size is G + 1 (internal gates + output gate). Returns 0 if no circuit over B computes f.

                                  Equations
                                  Instances For

                                    For a complete basis, circuit size complexity is always positive.

                                    theorem Complexity.Circuit.sizeComplexity_le {B : Basis} {N : } [NeZero N] {G : } (c : Circuit B N 1 G) (f : BitString NBool) (hf : (fun (x : BitString N) => c.eval x 0) = f) :

                                    Any circuit computing f has size at least sizeComplexity B f.

                                    theorem Complexity.Circuit.sizeComplexity_witness {B : Basis} {N : } [NeZero N] [CompleteBasis B] (f : BitString NBool) :
                                    ∃ (G : ) (c : Circuit B N 1 G), c.size = sizeComplexity B f (fun (x : BitString N) => c.eval x 0) = f

                                    For a complete basis, sizeComplexity is realized by some circuit.