Documentation

Complexitylib.Circuits.Frontier.Compiler

Compiling a circuit into a constraint network #

Fix a straight-line program p over any signature, output wires out o indexed by a finite type O, an interpretation I of the signature in an alphabet U, and for each output a set Acc o ⊆ U of accepting values. We build a constraint network whose accepted inputs are exactly those on which every output o lies in Acc o. A circuit deciding a set has one output; a circuit computing a function accepts every value at each of its outputs.

Only the reachable wires matter: the outputs and, recursively, the arguments of reachable gates. We call them signals. A signal is consumed by each argument slot of a reachable gate that reads it, and each output is also consumed by its own output vertex. A circuit has unbounded fan-out, but a bounded-degree network cannot give a signal one edge per consumer. So each signal w with consumers c₀, c₁, ... is routed through a chain of junctions j₀, j₁, ..., one per consumer:

  w --- j0 --- j1 --- j2 --- ...
        |      |      |
        c0     c1     c2

Each junction has one feed edge from its predecessor in the chain (the signal itself for j₀) and one deliver edge to its consumer. The constraints are:

Every vertex has degree at most r + 1 when the gates have fan-in at most r ≥ 2; for fan-in two the graph is subcubic. The network records gates as relations: it never evaluates anything, and the constraint of a gate does not care which of its edges a sweep reaches first.

Exactness (accepted_network). The values of a run of the program satisfy the network. Conversely, in a satisfying assignment the junction constraints force all edges of a signal to carry one value, and the gate constraints, read in program order, force that value to be the signal's value in the run (eq_trace). So the satisfying assignment, if any, is unique.

Counting. With C consumers, W signals, and |O| outputs, the network has 2C edges and W + C + |O| vertices, so its cycle rank is C - W - |O| + 1, the number of slots minus the number of signals plus one. A gate of arity k has k slots, so it contributes k - 1 to the cycle rank, and a reachable input contributes -1. Hence the cycle rank is at most (r - 1) s + 1 - m for s gates of fan-in at most r and m reachable inputs. If all gates are binary and reachable and there are no constants, the rank is exactly s + 1 - m, compared with zero for a read-once binary formula on m distinct inputs. Sharing creates cycles; gates create local constraints. Gates of arity zero, the constants, only lower the cycle rank: the count charges only the inner gates, those of positive arity.

Main definitions #

Main results #

Signals, consumers, and junctions #

A wire is reachable when it is an output or an argument of a reachable gate.

Instances For
    @[reducible, inline]

    The signals: the reachable wires.

    Equations
    Instances For
      @[reducible, inline]

      An argument slot of a reachable gate.

      Equations
      Instances For
        @[reducible, inline]

        A consumer: an argument slot of a reachable gate, or an output.

        Equations
        Instances For
          def Complexity.Frontier.Compiler.consumed {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} :
          Consumer p out → Signal p out

          The signal read by a consumer.

          Equations
          Instances For
            noncomputable def Complexity.Frontier.Compiler.fanout {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} (p : Cslib.Circuits.Program σ n s) (out : O → Cslib.Circuits.Wire n s) (w : Signal p out) :

            The number of consumers of a signal.

            Equations
            Instances For
              @[reducible, inline]

              A junction: a copy of a signal for one of its consumers. The junctions of a signal w are numbered 0, ..., fanout w - 1.

              Equations
              Instances For
                noncomputable def Complexity.Frontier.Compiler.junctionEquiv {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] (p : Cslib.Circuits.Program σ n s) (out : O → Cslib.Circuits.Wire n s) :
                Junction p out ≃ Consumer p out

                Junctions correspond to consumers.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  @[simp]

                  The consumer of a junction reads the junction's signal.

                  @[simp]

                  The junction of a consumer belongs to the consumed signal.

                  theorem Complexity.Frontier.Compiler.fanout_pos {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (w : Signal p out) :
                  0 < fanout p out w

                  Every signal has a consumer.

                  The graph #

                  inductive Complexity.Frontier.Compiler.Vertex {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} (p : Cslib.Circuits.Program σ n s) (out : O → Cslib.Circuits.Wire n s) :
                  Type u_1

                  The vertices: one per signal, one per junction, and one per output.

                  Instances For
                    inductive Complexity.Frontier.Compiler.Edge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} (p : Cslib.Circuits.Program σ n s) (out : O → Cslib.Circuits.Wire n s) :

                    The edges: two per junction.

                    Instances For

                      Vertices are signals, junctions, and outputs.

                      Equations
                      • One or more equations did not get rendered due to their size.
                      Instances For

                        Edges are two copies of the junctions.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          def Complexity.Frontier.Compiler.feeder {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (j : Junction p out) :
                          Vertex p out

                          The vertex feeding a junction: the signal itself for its first junction, and the previous junction otherwise.

                          Equations
                          Instances For

                            No junction feeds itself.

                            def Complexity.Frontier.Compiler.Edge.signal {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} :
                            Edge p out → Signal p out

                            The signal carried by an edge.

                            Equations
                            Instances For
                              noncomputable def Complexity.Frontier.Compiler.argEdge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {g : Fin s} (hg : Reach p out (Cslib.Circuits.Wire.gate g)) (a : Fin (σ.Arity (p.lines g).op)) :
                              Edge p out

                              The edge delivering argument a to the reachable gate g.

                              Equations
                              Instances For
                                noncomputable def Complexity.Frontier.Compiler.outEdge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (o : O) :
                                Edge p out

                                The edge delivering an output to its output vertex.

                                Equations
                                Instances For
                                  def Complexity.Frontier.Compiler.head {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (w : Signal p out) :
                                  Edge p out

                                  The first edge of a signal: the feed edge of its first junction.

                                  Equations
                                  Instances For
                                    @[simp]
                                    theorem Complexity.Frontier.Compiler.signal_argEdge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {g : Fin s} (hg : Reach p out (Cslib.Circuits.Wire.gate g)) (a : Fin (σ.Arity (p.lines g).op)) :
                                    (argEdge hg a).signal = ⟨(p.lines g).wires a, ⋯⟩
                                    @[simp]
                                    theorem Complexity.Frontier.Compiler.signal_outEdge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (o : O) :
                                    (outEdge o).signal = ⟨out o, ⋯⟩
                                    @[simp]
                                    @[simp]
                                    theorem Complexity.Frontier.Compiler.eq_head_of_src_eq_signal {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {e : Edge p out} {w : Signal p out} (h : src e = Vertex.signal w) :
                                    e = head w

                                    An edge leaving a signal vertex is the first edge of that signal.

                                    theorem Complexity.Frontier.Compiler.signal_of_src_eq_junction {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {e : Edge p out} {j : Junction p out} (h : src e = Vertex.junction j) :

                                    An edge leaving a junction carries the junction's signal.

                                    The network #

                                    noncomputable def Complexity.Frontier.Compiler.emit {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (w : Cslib.Circuits.Wire n s) :
                                    Reach p out w → (Fin n → U) → (Edge p out → U) → U

                                    The value a signal vertex puts on its outgoing edge: the input itself for an input wire, and the gate's operation applied to its incoming argument edges for a gate wire.

                                    Equations
                                    Instances For
                                      noncomputable def Complexity.Frontier.Compiler.check {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) :
                                      Vertex p out → (Fin n → U) → (Edge p out → U) → Prop

                                      The constraint at each vertex.

                                      Equations
                                      Instances For
                                        noncomputable def Complexity.Frontier.Compiler.site {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (i : Fin n) :
                                        Option (Vertex p out)

                                        Each reachable input is read at its signal vertex.

                                        Equations
                                        • One or more equations did not get rendered due to their size.
                                        Instances For
                                          noncomputable def Complexity.Frontier.Compiler.network {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] (p : Cslib.Circuits.Program σ n s) (out : O → Cslib.Circuits.Wire n s) {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) :
                                          Network U (Fin n) (Vertex p out) (Edge p out)

                                          The constraint network of a program with outputs out, accepting at the output o the values in Acc o.

                                          Equations
                                          • One or more equations did not get rendered due to their size.
                                          Instances For

                                            Exactness #

                                            theorem Complexity.Frontier.Compiler.trace_satisfies {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {x : Fin n → U} (hx : ∀ (o : O), p.trace I x (out o) ∈ Acc o) :
                                            (network p out I Acc).Satisfies x fun (e : Edge p out) => p.trace I x ↑e.signal

                                            The run of the program puts the value of each signal on each of its edges.

                                            theorem Complexity.Frontier.Compiler.feed_eq_head {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} {I : Cslib.Circuits.Interpretation σ U} {Acc : O → Set U} {x : Fin n → U} {α : Edge p out → U} (hα : (network p out I Acc).Satisfies x α) (w : Signal p out) (k : ℕ) (hk : k < fanout p out w) :
                                            α (Edge.feed ⟨w, ⟨k, hk⟩⟩) = α (head w)

                                            In a satisfying assignment, the feed edges along the junction chain of a signal all carry the value of its first edge.

                                            theorem Complexity.Frontier.Compiler.eq_head {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} {I : Cslib.Circuits.Interpretation σ U} {Acc : O → Set U} {x : Fin n → U} {α : Edge p out → U} (hα : (network p out I Acc).Satisfies x α) (e : Edge p out) :
                                            α e = α (head e.signal)

                                            In a satisfying assignment, every edge carries the value of the first edge of its signal.

                                            theorem Complexity.Frontier.Compiler.head_eq_trace {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} {I : Cslib.Circuits.Interpretation σ U} {Acc : O → Set U} {x : Fin n → U} {α : Edge p out → U} (hα : (network p out I Acc).Satisfies x α) (w : Cslib.Circuits.Wire n s) (hw : Reach p out w) :
                                            α (head ⟨w, hw⟩) = p.trace I x w

                                            In a satisfying assignment, every signal carries its value in the run of the program.

                                            theorem Complexity.Frontier.Compiler.eq_trace {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} {I : Cslib.Circuits.Interpretation σ U} {Acc : O → Set U} {x : Fin n → U} {α : Edge p out → U} (hα : (network p out I Acc).Satisfies x α) (e : Edge p out) :
                                            α e = p.trace I x ↑e.signal

                                            Uniqueness. A satisfying assignment puts on every edge the value of its signal in the run of the program.

                                            theorem Complexity.Frontier.Compiler.accepted_network {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) :
                                            (network p out I Acc).accepted = {x : Fin n → U | ∀ (o : O), p.trace I x (out o) ∈ Acc o}

                                            Exactness. The network accepts exactly the inputs on which every output o lies in Acc o.

                                            Outputs across a cut #

                                            theorem Complexity.Frontier.Compiler.trace_out_of_cut {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) {P : Set (Vertex p out)} {x y z : Fin n → U} (hcut : ∀ e ∈ (network p out I fun (x : O) => Set.univ).cut P, p.trace I x ↑e.signal = p.trace I y ↑e.signal) (hzx : Set.EqOn z x ((network p out I fun (x : O) => Set.univ).readIn P)) (hzy : Set.EqOn z y ((network p out I fun (x : O) => Set.univ).readIn P)ᶜ) (o : O) :
                                            (Vertex.output o ∈ P → p.trace I z (out o) = p.trace I x (out o)) ∧ (Vertex.output o ∉ P → p.trace I z (out o) = p.trace I y (out o))

                                            Outputs across a cut. In the network of a program computing a function (every value accepted at every output), let the runs on two inputs x and y agree on the cut of a set of vertices P, and let z read like x at P and like y elsewhere. Then the outputs of z are those of x at the output vertices in P and those of y at the others.

                                            The shape of the graph #

                                            theorem Complexity.Frontier.Compiler.loopless {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) :
                                            (network p out I Acc).Loopless

                                            The graph has no loops.

                                            Degrees #

                                            noncomputable def Complexity.Frontier.Compiler.slotEdge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} (t : Slot p out) :
                                            Edge p out

                                            The edge delivering a slot's signal to its gate.

                                            Equations
                                            Instances For
                                              theorem Complexity.Frontier.Compiler.ncard_slots_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {r : ℕ} (hfan : p.FanInAtMost r) (w : Cslib.Circuits.Wire n s) :

                                              A gate has at most r slots when the fan-in is at most r.

                                              theorem Complexity.Frontier.Compiler.exists_slot_of_tgt_eq_signal {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {e : Edge p out} {w : Signal p out} (h : tgt e = Vertex.signal w) :
                                              ∃ (t : Slot p out), Cslib.Circuits.Wire.gate (↑t).fst = ↑w ∧ e = slotEdge t

                                              An edge entering a signal vertex delivers one of the slots of its gate.

                                              theorem Complexity.Frontier.Compiler.eq_of_feeder_eq_junction {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {j₁ j₂ j : Junction p out} (h₁ : feeder j₁ = Vertex.junction j) (h₂ : feeder j₂ = Vertex.junction j) :
                                              j₁ = j₂

                                              Two junctions fed by the same junction are equal.

                                              theorem Complexity.Frontier.Compiler.maxDegreeLE {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {r : ℕ} (hr : 2 ≤ r) (hfan : p.FanInAtMost r) :
                                              (network p out I Acc).MaxDegreeLE (r + 1)

                                              The degrees are bounded. When the gates have fan-in at most r ≥ 2, every vertex has degree at most r + 1: a gate vertex has its argument edges and one outgoing edge, a junction has three edges, and input vertices and output vertices have one. For fan-in two the graph is subcubic.

                                              Connectivity #

                                              theorem Complexity.Frontier.Compiler.reflTransGen_junction_signal {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) (w : Signal p out) (k : ℕ) (hk : k < fanout p out w) :

                                              Every junction of a signal is joined to the signal along its chain.

                                              theorem Complexity.Frontier.Compiler.reflTransGen_junction {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) (j : Junction p out) :

                                              Every junction is joined to its signal.

                                              theorem Complexity.Frontier.Compiler.reflTransGen_out {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) (o : O) :

                                              Each output signal is joined to its output vertex.

                                              theorem Complexity.Frontier.Compiler.reflTransGen_arg {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {g : Fin s} (hg : Reach p out (Cslib.Circuits.Wire.gate g)) (a : Fin (σ.Arity (p.lines g).op)) :

                                              Each argument of a reachable gate is joined to the gate, along its chain.

                                              theorem Complexity.Frontier.Compiler.reach_of_upstream {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {o : O} {w : Cslib.Circuits.Wire n s} (h : p.Upstream (out o) w) :
                                              Reach p out w

                                              A wire upstream of an output is reachable.

                                              theorem Complexity.Frontier.Compiler.reflTransGen_of_upstream {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {o : O} {w : Cslib.Circuits.Wire n s} (h : p.Upstream (out o) w) (hw : Reach p out w) :

                                              A wire upstream of an output is joined to the output vertex.

                                              theorem Complexity.Frontier.Compiler.exists_upstream {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {w : Cslib.Circuits.Wire n s} (hw : Reach p out w) :
                                              ∃ (o : O), p.Upstream (out o) w

                                              Every reachable wire is upstream of some output.

                                              theorem Complexity.Frontier.Compiler.connected_of_upstream {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {w₀ : Cslib.Circuits.Wire n s} (h₀ : ∀ (o : O), p.Upstream (out o) w₀) :
                                              (network p out I Acc).Connected

                                              The graph is connected when some wire is upstream of every output.

                                              theorem Complexity.Frontier.Compiler.connected {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) [Subsingleton O] :
                                              (network p out I Acc).Connected

                                              The graph of a circuit with one output is connected.

                                              Counting #

                                              theorem Complexity.Frontier.Compiler.read_network {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) :
                                              (network p out I Acc).read = {i : Fin n | Reach p out (Cslib.Circuits.Wire.input i)}

                                              The inputs read by the network are the reachable inputs.

                                              theorem Complexity.Frontier.Compiler.ncard_readAt_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) (v : Vertex p out) :
                                              ((network p out I Acc).readAt v).ncard ≤ 1

                                              Each vertex reads at most one input.

                                              Signals are reachable inputs and reachable gates.

                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Instances For
                                                @[reducible, inline]

                                                The reachable inner gates: reachable gates of positive arity.

                                                Equations
                                                Instances For
                                                  theorem Complexity.Frontier.Compiler.card_slot_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {r : ℕ} (hfan : p.FanInAtMost r) :
                                                  Nat.card (Slot p out) ≤ r * Nat.card (InnerGate p out)

                                                  There are at most r slots per reachable inner gate; constant gates have none.

                                                  There are at least as many reachable gates as reachable inner gates.

                                                  theorem Complexity.Frontier.Compiler.card_edge {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} :
                                                  Nat.card (Edge p out) = 2 * Nat.card (Consumer p out)

                                                  The cardinalities of the network, in terms of signals and consumers.

                                                  Every signal has a consumer, so there are at least as many consumers as signals.

                                                  theorem Complexity.Frontier.Compiler.card_edge_add_ncard_read_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {r : ℕ} (hfan : p.FanInAtMost r) :
                                                  Nat.card (Edge p out) + (network p out I Acc).read.ncard ≤ Nat.card (Vertex p out) + (r - 1) * p.innerGates.card

                                                  The edge count. For fan-in at most r, the edges of the network and the inputs it reads number at most (r - 1) s more than its vertices, where s counts the inner gates.

                                                  theorem Complexity.Frontier.Compiler.cycleRank_add_ncard_read_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {U : Type u_2} (I : Cslib.Circuits.Interpretation σ U) (Acc : O → Set U) {r : ℕ} (hfan : p.FanInAtMost r) (hconn : (network p out I Acc).Connected) :
                                                  (network p out I Acc).cycleRank + (network p out I Acc).read.ncard ≤ (r - 1) * p.innerGates.card + 1

                                                  The cycle rank. For fan-in at most r, if the network is connected, its cycle rank and the number of inputs it reads add up to at most (r - 1) s + 1, where s counts the inner gates. For fan-in two, the cycle rank is at most s + 1 - m for m reachable inputs.

                                                  theorem Complexity.Frontier.Compiler.card_vertex_le {σ : Cslib.Circuits.Signature} {n s : ℕ} {O : Type u_1} [Finite O] {p : Cslib.Circuits.Program σ n s} {out : O → Cslib.Circuits.Wire n s} {r : ℕ} (hfan : p.FanInAtMost r) :

                                                  The number of vertices is at most 2 r s + 3 |O| for fan-in at most r, where s counts the inner gates.