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:
- a signal vertex for the input
x_ireadsx_iand puts it on its outgoing edge; - a signal vertex for a gate
gputsgapplied to its incoming argument edges on its outgoing edge; - a junction puts its incoming value on both of its outgoing edges;
- the output vertex of
orequires its incoming value to lie inAcc o.
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 #
Frontier.Compiler.network p out I Acc: the constraint network of a program.
Main results #
Frontier.Compiler.accepted_network,Frontier.Compiler.eq_trace: exactness.Frontier.Compiler.connected_of_upstream,loopless: the graph is loopless, and connected when some wire is upstream of every output, in particular when there is one output.Frontier.Compiler.maxDegreeLE: for fan-in at mostr ≥ 2, the degrees are at mostr + 1.Frontier.Compiler.cycleRank_add_ncard_read_le: the cycle rank is at most(r - 1) s + 1 - |read|, wherescounts the inner gates.Frontier.Compiler.card_vertex_le: there are at most2 r s + 3 |O|vertices.
Signals, consumers, and junctions #
A wire is reachable when it is an output or an argument of a reachable gate.
- out
{σ : Cslib.Circuits.Signature}
{n s : ℕ}
{O : Type u_1}
{p : Cslib.Circuits.Program σ n s}
{out : O → Cslib.Circuits.Wire n s}
(o : O)
: Reach p out (out o)
The outputs are reachable.
- arg
{σ : Cslib.Circuits.Signature}
{n s : ℕ}
{O : Type u_1}
{p : Cslib.Circuits.Program σ n s}
{out : O → Cslib.Circuits.Wire n s}
{g : Fin s}
(a : Fin (σ.Arity (p.lines g).op))
: Reach p out (Cslib.Circuits.Wire.gate g) → Reach p out ((p.lines g).wires a)
The arguments of a reachable gate are reachable.
Instances For
The signals: the reachable wires.
Equations
- Complexity.Frontier.Compiler.Signal p out = { w : Cslib.Circuits.Wire n s // Complexity.Frontier.Compiler.Reach p out w }
Instances For
An argument slot of a reachable gate.
Equations
- Complexity.Frontier.Compiler.Slot p out = { t : (g : Fin s) × Fin (σ.Arity (p.lines g).op) // Complexity.Frontier.Compiler.Reach p out (Cslib.Circuits.Wire.gate t.fst) }
Instances For
A consumer: an argument slot of a reachable gate, or an output.
Equations
- Complexity.Frontier.Compiler.Consumer p out = (Complexity.Frontier.Compiler.Slot p out ⊕ O)
Instances For
The signal read by a consumer.
Equations
Instances For
The number of consumers of a signal.
Equations
Instances For
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
- Complexity.Frontier.Compiler.Junction p out = ((w : Complexity.Frontier.Compiler.Signal p out) × Fin (Complexity.Frontier.Compiler.fanout p out w))
Instances For
Junctions correspond to consumers.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The consumer of a junction reads the junction's signal.
The junction of a consumer belongs to the consumed signal.
Every signal has a consumer.
The graph #
The vertices: one per signal, one per junction, and one per output.
- signal
{σ : 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)
: Vertex p out
The vertex of a signal: an input vertex or a gate vertex.
- junction
{σ : 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
A junction.
- output
{σ : Cslib.Circuits.Signature}
{n s : ℕ}
{O : Type u_1}
{p : Cslib.Circuits.Program σ n s}
{out : O → Cslib.Circuits.Wire n s}
(o : O)
: Vertex p out
The vertex of an output, which consumes it.
Instances For
The edges: two per junction.
- feed
{σ : 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)
: Edge p out
The edge into a junction from its predecessor in the chain.
- deliver
{σ : 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)
: Edge p out
The edge from a junction to its consumer.
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
The vertex that consumes through a consumer: a gate vertex or an output vertex.
Equations
Instances For
The vertex feeding a junction: the signal itself for its first junction, and the previous junction otherwise.
Equations
Instances For
No junction feeds itself.
The source of an edge.
Equations
Instances For
The target of an edge.
Equations
Instances For
The signal carried by an edge.
Equations
Instances For
The edge delivering argument a to the reachable gate g.
Equations
Instances For
The edge delivering an output to its output vertex.
Equations
Instances For
The first edge of a signal: the feed edge of its first junction.
Equations
Instances For
An edge leaving a signal vertex is the first edge of that signal.
An edge leaving a junction carries the junction's signal.
The network #
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
- Complexity.Frontier.Compiler.emit I (Cslib.Circuits.Wire.input i) x_4 x x_1 = x i
- Complexity.Frontier.Compiler.emit I (Cslib.Circuits.Wire.gate g) hg x x_1 = I (p.lines g).op fun (a : Fin (σ.Arity (p.lines g).op)) => x_1 (Complexity.Frontier.Compiler.argEdge hg a)
Instances For
The constraint at each vertex.
Equations
- One or more equations did not get rendered due to their size.
- Complexity.Frontier.Compiler.check I Acc (Complexity.Frontier.Compiler.Vertex.output o) x✝¹ x✝ = (x✝ (Complexity.Frontier.Compiler.outEdge o) ∈ Acc o)
Instances For
Each reachable input is read at its signal vertex.
Equations
- One or more equations did not get rendered due to their size.
Instances For
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 #
The run of the program puts the value of each signal on each of its edges.
In a satisfying assignment, the feed edges along the junction chain of a signal all carry the value of its first edge.
In a satisfying assignment, every edge carries the value of the first edge of its signal.
In a satisfying assignment, every signal carries its value in the run of the program.
Uniqueness. A satisfying assignment puts on every edge the value of its signal in the run of the program.
Exactness. The network accepts exactly the inputs on which every output o lies in
Acc o.
Outputs across a cut #
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 #
The graph has no loops.
Degrees #
The edge delivering a slot's signal to its gate.
Equations
Instances For
A gate has at most r slots when the fan-in is at most r.
An edge entering a signal vertex delivers one of the slots of its gate.
Two junctions fed by the same junction are equal.
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 #
Every junction of a signal is joined to the signal along its chain.
Every junction is joined to its signal.
Each output signal is joined to its output vertex.
Each argument of a reachable gate is joined to the gate, along its chain.
A wire upstream of an output is reachable.
A wire upstream of an output is joined to the output vertex.
Every reachable wire is upstream of some output.
The graph is connected when some wire is upstream of every output.
The graph of a circuit with one output is connected.
Counting #
The inputs read by the network are the reachable inputs.
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
The reachable inner gates: reachable gates of positive arity.
Equations
- Complexity.Frontier.Compiler.InnerGate p out = { g : Fin s // Complexity.Frontier.Compiler.Reach p out (Cslib.Circuits.Wire.gate g) ∧ σ.Arity (p.lines g).op ≠ 0 }
Instances For
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.
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.
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.
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.
The number of vertices is at most 2 r s + 3 |O| for fan-in at most r, where s
counts the inner gates.