Documentation

Complexity.Computability.Circuit.Boolean.EvaluationTime

Evaluating circuits in polynomial time #

evalCode evaluates a list of gates (Cslib.Circuits.Program.code) on a list of input values: starting from the inputs, it appends the value of each gate in turn, reading wire i at position i of the values computed so far. On the code of a program it returns the inputs followed by the values of the gates (Cslib.Circuits.Program.evalCode_code), so it evaluates circuits exactly as Cslib.Circuits.Circuit.eval does (Cslib.Circuits.Circuit.eval_eq_getD). It is total: an argument or a wire missing from a malformed list reads a default value.

For De Morgan circuits, evalCode is computable in polynomial time on the binary encoding of gate lists (Cslib.Circuits.Boolean.computableInPolyTime_evalCode), so is reading an output wire given by its binary number (Cslib.Circuits.Boolean.computableInPolyTime_evalOutput). These are certificates for the fun_prop calculus of tidy polynomial-time computations; the evaluators of Complexity.Computability.Circuit.Evaluation carry no runtime bound. Each gate is evaluated by two lookups at wire numbers, which are capped at the number of values computed so far before they are converted to unary, so wire numbers far beyond the circuit cost only their binary length.

The typed evaluation certificate accepts any bit list. It pads short lists with false and truncates long lists to the declared input arity before invoking the raw evaluator. Circuit generation, input preparation, binary wire lookup and evaluation are all included in its cost.

Main definitions #

Main results #

References #

def Cslib.Circuits.evalCode {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) (gates : List (σ.Op × List ℕ)) :

Evaluate the list of gates gates on the input values x: start from x and append the value of each gate in turn, reading wire i at position i of the values computed so far. An argument missing from a gate, or a wire not yet computed, reads d; on the code of a program neither happens (Program.evalCode_code).

Instances For
    @[simp]
    theorem Cslib.Circuits.evalCode_nil {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) :
    evalCode I d x [] = x
    theorem Cslib.Circuits.evalCode_append_singleton {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) (gates : List (σ.Op × List ℕ)) (g : σ.Op × List ℕ) :
    evalCode I d x (gates ++ [g]) = evalCode I d x gates ++ [I g.1 fun (a : Fin (σ.Arity g.1)) => g.2[↑a]?.elim d fun (x_1 : ℕ) => (evalCode I d x gates).getD x_1 d]
    theorem Cslib.Circuits.evalCode_append {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) (gates gates' : List (σ.Op × List ℕ)) :
    evalCode I d x (gates ++ gates') = evalCode I d (evalCode I d x gates) gates'
    @[simp]
    theorem Cslib.Circuits.length_evalCode {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) (gates : List (σ.Op × List ℕ)) :
    (evalCode I d x gates).length = x.length + gates.length

    Each gate adds one value.

    theorem Cslib.Circuits.prefix_evalCode {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) (gates : List (σ.Op × List ℕ)) :
    x <+: evalCode I d x gates

    Evaluating a gate list only appends values.

    theorem Cslib.Circuits.getD_evalCode {σ : Signature} {U : Type u} (I : Interpretation σ U) (d : U) (x : List U) {gates : List (σ.Op × List ℕ)} (h : Program.IsCodeFrom σ x.length 0 gates) {j : ℕ} {gate : σ.Op × List ℕ} (hg : gates[j]? = some gate) :
    (evalCode I d x gates).getD (x.length + j) d = I gate.1 fun (a : Fin (σ.Arity gate.1)) => gate.2[↑a]?.elim d fun (x_1 : ℕ) => (evalCode I d x gates).getD x_1 d

    The value of a gate of a well-formed gate list is its operation applied to the values of its arguments.

    theorem Cslib.Circuits.Wire.getD_append_toNat {U : Type u} {n k : ℕ} (x : Fin n → U) (y : Fin k → U) (d : U) (w : Wire n k) :

    Wire w is at position w.toNat of the inputs followed by the gates.

    theorem Cslib.Circuits.Program.evalCode_code {σ : Signature} {U : Type u} {n k : ℕ} (p : Program σ n k) (I : Interpretation σ U) (d : U) (x : Fin n → U) :

    Evaluation through the code. On the code of a program, evalCode lists the inputs and then the values of the gates.

    theorem Cslib.Circuits.Circuit.eval_eq_getD {σ : Signature} {U : Type u} {n m : ℕ} (c : Circuit σ n m) (I : Interpretation σ U) (d : U) (x : Fin n → U) (j : Fin m) :
    c.eval I x j = (evalCode I d (List.ofFn x) c.code.1).getD (c.outputs j).toNat d

    Evaluation through the code. Output j of a circuit is the value at the number of its output wire after evaluating the gate list.

    Polynomial time #

    Polynomial-time evaluation of De Morgan gate lists, for input bits and a gate list in the binary encoding encGate, both computed in polynomial time.

    The value of wire o after evaluating the De Morgan gate list gates on the input bits x: on the code of a circuit and the number of an output wire, the value of that output (Circuit.eval_eq_getD).

    Instances For

      Output j of a De Morgan circuit is evalOutput at the number of its output wire.

      Polynomial-time evaluation of an output of a De Morgan gate list, for input bits, a gate list in the binary encoding encGate and a binary wire number, all computed in polynomial time.

      Evaluate a typed circuit on an arbitrary bit list by padding or truncating to its input arity. The output wire is read from the circuit's code at the specified output position.

      Evaluate an efficiently computed typed circuit on any efficiently computed bit list. No length premise is needed: missing inputs are false, and inputs past the circuit's arity are ignored. The certificate charges circuit generation, input padding and all evaluation.