The fault-tolerant circuit C′, its ExRecs, good and bad locations, the circuit C̃, local
DefinitionQAlgorithms_Defs_FTCircuitThe fault-tolerant circuit C′, its ExRecs, good and bad locations, the circuit C̃, local
QAlgorithms.FTProtocol.HasUniformDepth
For a fault-tolerance protocol with gadget circuits , one per location kind , this is the proposition that every gadget has the same number of time steps as the preparation gadget:
The error-correction circuit of is not constrained.
QAlgorithms.FTProtocol.gadgetDepth
For a fault-tolerance protocol , this is the natural number
This is the maximum number of time steps (step lists, which may be empty) over the six gadget circuits of . The error-correction circuit is not included.
QAlgorithms.FTProtocol.period
For a fault-tolerance protocol , this is the natural number
The first term is the maximum step count over the six gadget circuits (as above). The second term is the number of time steps of 's error-correction circuit.
QAlgorithms.FTInstance
For a natural number , is a tagged disjoint union with two kinds of elements:
- for an arbitrary pair ;
- for an arbitrary and .
Two elements are equal exactly when they have the same tag and equal data, and this equality is decidable. No bound ties or to any circuit.
QAlgorithms.blockEmb
The inputs are natural numbers and an injective map . Set . Then is the injective map
In words, the index is split into a block number and an offset . Block is sent to block with the same offset. Injectivity follows from that of . If both index sets are empty.
QAlgorithms.ecEmb
The inputs are natural numbers and . Set . Then is the injective map
which places a single block of wires as the -th block.
QAlgorithms.gadgetOffset
The inputs are a fault-tolerance protocol , a located circuit on qubits (a list of time steps, each a list of locations of some kind), and . The value is
The edge cases are:
- step of is taken to be empty if , giving value ;
- if exceeds the length of step , all of its locations are used;
- step of a gadget is taken to be empty (contributing ) if is beyond the gadget's number of steps.
QAlgorithms.gadgetGlobalId
The inputs are a fault-tolerance protocol , a located circuit on qubits, , and a local location id . The value is the pair
Here is the maximum gadget step count plus the step count of 's error-correction circuit. is the total number of locations in step of the gadgets of the first locations of step of , with out-of-range steps counted as empty. No range checks are made on , , , or .
QAlgorithms.ecBlocks
For a located circuit on qubits and , this is the list, in increasing order, of those that satisfy the following: some location in step of has kind different from measurement and acts on (that is, is among the wires of ). If , the step is treated as empty and the list is empty.
QAlgorithms.ecGlobalId
The inputs are a fault-tolerance protocol , , and a local id . The value is the pair
where is the number of locations in step of 's error-correction circuit, and if is beyond its number of steps. In that case the second component is just . Here is the maximum step count over the six gadgets, and is that plus the error-correction step count. No range checks are made.
QAlgorithms.decodedOutcomes
The inputs are:
- a fault-tolerance protocol ;
- a located circuit on qubits;
- a partial outcome assignment .
The result is a partial assignment on ids , defined as follows.
- No location or non-measurement. If has no location at , the value is none. "No location" means or the length of step . If has a location there but its kind is not measurement, the value is also none.
- Measurement location. Let be the list of positions of the measurement locations in the measurement gadget , ordered by step and then by position within the step.
- If is defined for every , the value is the bit
- Otherwise the value is none.
If , the "all defined" test holds vacuously, and the value is of the empty list.
QAlgorithms.gadgetPhaseStep
Inputs.
- is a fault-tolerance protocol. It has a code block size , an ancilla count , a gadget circuit for each location kind , and other fields not used here. acts on wires, where the arity is for cnot and otherwise.
- is a located circuit on wires, with implicit. It is a list of time steps . Each step is a list of locations , and each location has:
- a kind ;
- an injective wire map ;
- a condition , a Boolean function of an outcome record .
- .
Output. The result is a list of pairs (location on wires, tag). It is built as follows. Let be step of ; it is the empty list if is out of range. Write its entries as with -based positions . For each in order, and for each location of step of in order (empty if is out of range), the list contains one entry:
- kind: .
- wires: . Here is the block embedding . It sends position of the -th sub-block of the gadget to position of the block attached to wire . A gadget wire index is first decomposed as .
- condition:
- .
- is the period. is the maximum number of steps over the six gadgets (the value if all are empty), and is the number of steps of 's error-correction circuit.
- is the sum, over the first locations of , of the length of step of (that length is if the step is absent).
- The decoded record is defined at a position as follows. If has a measurement location at , and all values are defined for the measurement ids of (in their list order), then is 's measurement decoder applied to that list of bits. In every other case is undefined.
- tag: "gadget at ".
All these entries are concatenated in the order of , then of .
QAlgorithms.ecPhaseStep
Inputs.
- is a fault-tolerance protocol with block size , ancilla count , and error-correction circuit on wires.
- is a located circuit on wires, with implicit. Its steps are lists of locations; each location carries a kind, an injective wire map into , and a Boolean condition on outcome records .
- .
The list of blocks. Let be the list of wires , in increasing order, such that some location of step of has kind other than measurement and has among its wires. If is out of range the step is taken to be empty, and then is empty.
Output. For each index and wire of , and each location of step of (empty if is out of range), the list contains one entry:
- kind: .
- wires: composed with , i.e. followed by placement into the block of wire .
- condition: , where
- is the maximum step count over 's six gadgets.
- .
- is the length of step of , or if that step is absent.
- tag: "error correction at step on wire ".
The entries are concatenated in the order of , then of .
QAlgorithms.ftTaggedSteps
Inputs. is a fault-tolerance protocol with block size and ancilla count . is a located circuit on wires ( implicit) with steps.
Notation.
- is the maximum number of steps over 's six gadget circuits (the value if all are empty).
- is the number of steps of 's error-correction circuit.
- denotes the gadget-phase step list: for every location of step of , the locations of step of the gadget for 's kind, placed onto the blocks of 's wires and tagged "gadget ", with conditions as defined for
gadgetPhaseStep. - denotes the EC-phase step list: for each wire touched in step by a non-measurement location, the locations of step of the EC circuit, placed on that wire's block and tagged "EC ", as defined for
ecPhaseStep.
Output. A list of time steps on wires, each step a list of (location, tag) pairs, equal to
It has exactly steps.
- If the result is the empty list.
- A gadget phase step with beyond some gadget's length contributes nothing for locations of that kind.
QAlgorithms.ftCircuit
Inputs. is a fault-tolerance protocol with block size and ancilla count . is a located circuit on wires ( implicit) with steps.
Output. The located circuit on wires obtained from the tagged step list of ftTaggedSteps, keeping each location and discarding its tag.
The tagged step list. For each original step , in order, it consists of:
- gadget-phase steps. is the maximum step count over 's six gadgets. Gadget-phase step collects, for every location of 's step , the -th step of the gadget for 's kind. Its wires are mapped so that sub-block , position goes to wire . Its conditions read outcomes at shifted global ids. For gate kinds they are additionally conjoined with 's own condition evaluated on decoded measurement outcomes.
- EC-phase steps. EC-phase step applies the -th step of 's EC circuit to the block of every wire touched in step by a non-measurement location.
QAlgorithms.ftOwner
Inputs.
- is a fault-tolerance protocol.
- is a located circuit on wires ( implicit).
- .
Output. An optional tag.
- Defined case. Consider step of the tagged step list (the empty list if is out of range). If its -th entry (0-based) exists, the output is that entry's tag. The tag is either "gadget ", meaning the location belongs to the gadget replacing location of step of , or "EC ", meaning it belongs to the error-correction block on wire after step .
- Undefined case. If the entry does not exist, the output is "none".
QAlgorithms.ftDecode
Inputs.
- is a fault-tolerance protocol.
- is a located circuit on wires ( implicit).
- is a finite list of bits, the measurement record of the fault-tolerant circuit .
The output-reading map . The measurement ids of a located circuit are the positions of its measurement-kind locations, listed by step and then by position. For a position :
- If is the -th measurement id of and has a -th entry, then is that entry (-based).
- Otherwise is false.
The id map . It is defined by
- , where is the maximum gadget step count and is the EC step count.
- is the sum over the first locations of 's step of the length of step of the gadget for 's kind.
Output. The list indexed by the measurement ids of , in order, whose entry for is
where is 's map from bit lists to a bit.
QAlgorithms.exRecLocs
Inputs.
- is a fault-tolerance protocol.
- is a located circuit on wires ( implicit).
- .
- is a finite set of wires.
The set of all location ids. For a located circuit, this is .
Output.
- No location at . If has no location at position (step , index ), the result is .
- A location at . Otherwise, let be that location, with qubit set (the image of its wire map). The result is the set of location ids of whose owner tag (as given by
ftOwner) satisfies one of the following:- the tag is "gadget " with ;
- the tag is "EC " with and either 's kind is not prep and (a leading EC), or 's kind is not meas, , and (a trailing EC).
Remarks.
- Ids without an owner are excluded. Every id of in fact has one.
- When no leading EC can qualify.
- EC instances exist only for wires touched by a non-measurement location in that step.
QAlgorithms.truncOf
Inputs.
- is a located circuit on wires ( implicit).
- is a finite set of positions in .
- .
Output. A set of wires.
- If has no location at , the result is .
- Otherwise, with the location at and its set of wires, the result is
In words, these are the wires of that are also used by some location of lying in the immediately following step.
QAlgorithms.badAbove
Inputs.
- is a fault-tolerance protocol with fault parameter .
- is a located circuit on wires ( implicit) with steps.
- is a finite set of positions, interpreted as fault positions in .
- .
Definition (recursion on ).
- Base case: .
- Step: let , computed with truncated subtraction, so whenever . Then
- is the length of step ; it is if the step is absent, and then nothing is added.
- is the set of wires of the location at that are also wires of some location in in step , or if there is no location at .
- is the set of ids of belonging to: the gadget replacing ; the EC blocks of step on 's wires (only if is not a prep); and the EC blocks of step on 's wires outside (only if is not a meas).
Effect. Steps are processed from the last () downward. A location is declared bad when strictly more than faults of fall in its truncated extended rectangle.
Edge case. For , step is re-examined at each further iteration.
QAlgorithms.badAssignment
Inputs.
- is a fault-tolerance protocol with fault parameter .
- is a located circuit on wires ( implicit) with steps.
- is a finite set of positions in .
Output. , the result of badAbove after exactly iterations. The recursion examines the steps of , each once, in that order. It has two ingredients:
- Bad locations. A location is added when .
- Truncation. is the set of 's wires shared with locations already declared bad in step .
consists of the ids of belonging to:
- the gadget for ;
- the preceding-step EC blocks on 's wires, unless is a prep;
- the same-step EC blocks on 's wires not in , unless is a meas.
If the result is .
QAlgorithms.liftReg
Inputs.
- is a type, , and is implicit.
- is injective.
- is an arbitrary map from complex matrices indexed by (functions ) to such matrices.
The overwrite operation. For and , agrees with off the range of . At a position it takes the value ; the choice of is unique by injectivity.
Output. The map sending a matrix indexed by to the matrix with entries
Here is the restriction of to the wires .
This is what the definition reduces to when one unfolds it. The definition attaches a trivial one-point environment to , applies the general wire-lifting construction (with adapted to that trivial environment), and removes the environment again.
No property of , such as linearity or complete positivity, is assumed.
QAlgorithms.pairLift
Inputs.
- , and is implicit.
- is injective.
- is an arbitrary map on complex matrices indexed by , i.e. (qubit, environment-symbol) pairs.
The regrouping. Let be the regrouping bijection
Its inverse zips a qubit string and an environment string into .
Output. The map on matrices indexed by (the qubits together with one environment symbol per wire) given by
- .
- , with .
- replaces the entries of at positions by .
So acts jointly on qubits and on the environment symbols attached to those same wires. No property of is assumed.
QAlgorithms.IsTildeErrors
Setting. This is a predicate on four pieces of data:
- , a circuit of "locations" on wires;
- a finite set of location labels;
- a natural number ;
- an error assignment .
The circuit is a list of time steps. Each step is a list of locations. A location has:
- a kind: preparation, Hadamard, , CNOT, measurement, or wait;
- an ordered tuple of distinct wires of length , where for CNOT and otherwise;
- a classical condition.
A label refers to the -th location (0-based) of step . Write for that location; it is "absent" if or is out of range.
The error assignment assigns to each label either "no error" or a linear map on matrices (a superoperator) over the index set . So every wire carries one qubit plus one -level environment symbol.
A superoperator is a channel if there exist a finite and matrices with
The predicate. holds iff for every label both of the following hold:
- If is absent, then is "no error".
- If is a location with wires , then there is a channel on the paired index set with two properties:
- (a) If , then there is a channel on such that . Here the space is regrouped as , and acts on the environment symbols only. Formally this is the paired map with unitary , i.e. conjugation by after applying .
- (b) is the lift of to all wires along .
The lift in (b). The space is regrouped as . The entry of the lifted map applied to is obtained in three steps:
- take the -site submatrix of in which the sites outside are frozen to (rows) and (columns), while the sites vary;
- apply to this submatrix;
- read off the entry at the restrictions and .
In other words, acts on the qubits and environment symbols of the location's own wires, tensored with the identity on all other wires.
Edge cases.
- For labels in , is an arbitrary channel on those paired sites.
- No condition is placed on labels in that are absent from , beyond clause 1.
- If and , all the index sets involved are empty and the conditions on and hold trivially.
QAlgorithms.LocalStochasticModel
A local stochastic model on qubits is a bundle of four pieces of data, with no constraints imposed:
- a natural number , the environment dimension;
- a complex matrix , the initial environment state;
- a real-valued function on finite sets of location labels;
- for each finite set and each label , a superoperator on matrices indexed by .
Nothing requires the following properties:
- that is a density matrix;
- that is nonnegative or sums to ;
- that the are channels or local.
The case is allowed.
QAlgorithms.noisyOutDist
Inputs.
- A location circuit on wires.
- A local stochastic model .
Notation.
- is the finite set of valid labels , with below the number of steps and below the length of step .
- is the number of measurement locations of .
The definition. is the real function on bit strings given by
Here if , and "no error" otherwise.
The output function. is the real part of the trace of the matrix that the noisy run of produces at the outcome record .
The run starts from the classical–quantum state that assigns:
- to the empty record;
- the zero matrix to every other record.
It then processes the steps in order, and the locations within each step in order. At location acting on first wire , with error map (the identity if there is no error), the update is as follows.
- Preparation: replace by , where on qubit .
- Measurement:
- if is non-empty with last bit , the new is , where is with its last bit dropped and on ;
- the new of the empty record is .
- Wait: becomes .
- Gate (Hadamard, , CNOT): becomes if the location's condition holds, and otherwise. Here is the ideal gate on the location's wires. The condition reads the outcome bits recorded in for measurement locations in strictly earlier steps; all other outcomes are "unknown".
No normalisation is applied, and none of the properties of listed above are assumed.
QAlgorithms.IsLocalStochastic
Inputs.
- A location circuit on wires.
- A local stochastic model .
- A real function on labels.
The predicate. is the conjunction of six conditions:
- is a density matrix: positive semidefinite with trace .
- for every finite set of labels.
- whenever .
- .
- Locality. Take any , any , and suppose is a location with wires . Then there is a channel on such that is the lift of along .
- The entry of the lift applied to is obtained by applying to the submatrix of in which the qubits outside the are frozen to those of (rows) and (columns).
- In that submatrix, the location's qubits and the entire shared environment vary.
- The entry is then read at and .
- No condition is imposed for labels in that are not locations of .
- Tail bound. For every ,
Remarks.
- For , condition 6 reads .
- is unconstrained. If for some location of , then condition 6 with cannot hold, because by condition 2 its left side is nonnegative. In that case the predicate is unsatisfiable.
QAlgorithms.LocCircuit.castN
Given a proof that and a location circuit on wires, returns the same circuit regarded as a circuit on wires. It has the same steps, locations, kinds, wires and conditions, transported along the equality.
QAlgorithms.concatCircuit
Inputs.
- A fault-tolerance protocol with code-block size and ancilla count , so each block has wires.
- A level .
- A location circuit on wires.
The recursion. is a location circuit on wires, defined by:
- Level 0: itself, recast to wires.
- Level : applied to the level- circuit , recast from to wires.
The compilation . For a circuit on wires:
- Logical wire becomes the block of physical wires , for .
- Let be the maximum step count of 's six gadgets, and let be the step count of 's error-correction (EC) circuit.
- Each step of is replaced by gadget steps followed by EC steps.
Gadget step contains, for each location of step (in order), the -th step of the gadget for 's kind.
- If that gadget has fewer than steps, it contributes nothing.
- Its wires are mapped blockwise through 's wires.
- Each gadget location's condition is evaluated on outcomes relabelled to global labels. The relabelling is , where the offset is the total length of step of the gadgets of the earlier locations in step .
- If is a gate (Hadamard, , CNOT), the condition is additionally conjoined with 's own condition. That condition is evaluated on decoded outcomes: a measurement location of gets the value of its measurement gadget's outcome list if all of those outcomes are known, and is unknown otherwise.
EC step contains, for each block touched by some non-measurement location of step (in increasing order, indexed by its position ), the -th step of the EC circuit on block . Conditions are relabelled to .
QAlgorithms.concatDecode
Inputs. A protocol , a level , and a location circuit .
The recursion. is a map from bit lists to bit lists, defined by:
- Level 0: the identity.
- Level : , where .
So the outcomes of the top-level circuit are first decoded into level- outcomes, then recursively down to level .
The decoding step. lists one bit for each measurement location of , in 's order of measurement locations. That bit is applied to the list of outcomes, read from , of the measurement-gadget's measurements at their global labels in .
Here is matched positionally against the ordered list of measurement locations of . Any outcome not found, for example because is too short, is read as (false). Bits of beyond that list are ignored.
import Definitions.Def_QAlgorithms_Defs_FaultTolerance
/-!
# The fault-tolerant circuit C′, its ExRecs, good and bad locations, the circuit C̃, local
stochastic error models, concatenation (shared definition layer)
D. Gottesman, *An introduction to quantum error correction and fault-tolerant quantum
computation* (arXiv:0904.2557), cited "Gottesman intro p.N" (PDF pages), §§5.1–5.2, Defs. 6, 7,
10, 12, Thms 8–10.
Layout of `C′ = ftCircuit P C` (Def. 6). Qubit `q` of `C` owns the block of physical qubits
`finProdFinEquiv (q, j)`, `j < n + A`. Time step `s` of `C` becomes `period = D + D_ec` time steps
of `C′`: a gadget phase of `D` steps (`D` the gadget depth; every location of step `s` replaced by
its gadget on the blocks of its qubits, in parallel) followed by an EC phase of `D_ec` steps (the
EC gadget on the block of every qubit whose step-`s` location is not a measurement, in parallel:
the EC between consecutive locations). Within a `C′` step the gadget instances appear in the order
of the `C` locations (resp. of the qubits). A classically controlled gate location of `C` (these
arise in `C^{(k)}`, `k ≥ 1`) becomes its gadget with every location's condition conjoined with the
location's condition on the decoded logical outcomes.
-/
namespace QAlgorithms
open scoped Matrix
namespace FTProtocol
variable (P : FTProtocol)
/-- Gottesman intro p.33 (Def. 6: "C can be divided up into time steps"): all location gadgets have
the same number of time steps, so that the gadgets of one time step of `C` run in parallel without
padding. -/
def HasUniformDepth : Prop :=
∀ κ : LocKind, (P.gadget κ).steps.length = (P.gadget .prep).steps.length
/-- The number of time steps of the gadget phase of `C′`: the largest gadget depth. -/
def gadgetDepth : ℕ :=
[LocKind.prep, .had, .tgate, .cnot, .meas, .wait].foldr (fun κ acc => max (P.gadget κ).steps.length acc) 0
/-- The number of time steps of `C′` per time step of `C`. -/
def period : ℕ :=
P.gadgetDepth + P.ec.steps.length
end FTProtocol
/-- The gadget instances of `C′`: the gadget of the `C` location `ℓ`, or the EC gadget after time
step `s` of `C` on the block of qubit `q`. -/
inductive FTInstance (N : ℕ) where
| gadget (ℓ : ℕ × ℕ)
| ec (s : ℕ) (q : Fin N)
deriving DecidableEq
/-- The physical qubits of the blocks of the qubits `w` of a `C` location: block `i`, position `p`
of the gadget is block `w i`, position `p` of `C′`. -/
def blockEmb (n A : ℕ) {k N : ℕ} (w : Fin k ↪ Fin N) : Fin (k * (n + A)) ↪ Fin (N * (n + A)) :=
⟨fun x => finProdFinEquiv (w (finProdFinEquiv.symm x).1, (finProdFinEquiv.symm x).2), by
intro x y h
have h' := Prod.ext_iff.1 (finProdFinEquiv.injective h)
exact finProdFinEquiv.symm.injective (Prod.ext (w.injective h'.1) h'.2)⟩
/-- The physical qubits of the block of qubit `q`. -/
def ecEmb (n A : ℕ) {N : ℕ} (q : Fin N) : Fin (n + A) ↪ Fin (N * (n + A)) :=
⟨fun p => finProdFinEquiv (q, p), fun _ _ h => (Prod.ext_iff.1 (finProdFinEquiv.injective h)).2⟩
variable {N : ℕ}
/-- The position in its `C′` step at which the gadget of the `C` location `(s, j)` starts, at local
step `d` of the gadget. -/
def gadgetOffset (P : FTProtocol) (C : LocCircuit N) (s j d : ℕ) : ℕ :=
(((C.steps.getD s []).take j).map fun l => ((P.gadget l.kind).steps.getD d []).length).sum
/-- The id in `C′` of the location with local id `lid` of the gadget of the `C` location
`(s, j)`. -/
def gadgetGlobalId (P : FTProtocol) (C : LocCircuit N) (s j : ℕ) (lid : ℕ × ℕ) : ℕ × ℕ :=
(s * P.period + lid.1, gadgetOffset P C s j lid.1 + lid.2)
/-- The qubits of `C` receiving an EC gadget after time step `s`: those whose step-`s` location is
not a measurement (the EC between consecutive locations, Def. 6). -/
def ecBlocks (C : LocCircuit N) (s : ℕ) : List (Fin N) :=
(List.finRange N).filter fun q =>
(C.steps.getD s []).any fun l => decide (l.kind ≠ .meas) && decide (q ∈ l.qubits)
/-- The id in `C′` of the location with local id `lid` of the EC gadget after step `s` on the
`idx`-th block of `ecBlocks C s`. -/
def ecGlobalId (P : FTProtocol) (s idx : ℕ) (lid : ℕ × ℕ) : ℕ × ℕ :=
(s * P.period + P.gadgetDepth + lid.1, idx * (P.ec.steps.getD lid.1 []).length + lid.2)
/-- The decoded logical outcomes of the measurement locations of `C`, read from the outcomes `O`
of `C′` (`none` until every outcome of the measurement gadget is available). -/
def decodedOutcomes (P : FTProtocol) (C : LocCircuit N) (O : ℕ × ℕ → Option Bool) :
ℕ × ℕ → Option Bool :=
fun cid => match C.locAt cid with
| some l =>
if l.kind = .meas then
if ((P.gadget .meas).measIds.map fun lid => O (gadgetGlobalId P C cid.1 cid.2 lid)).all
Option.isSome then
some (P.measDecode ((P.gadget .meas).measIds.map fun lid =>
(O (gadgetGlobalId P C cid.1 cid.2 lid)).getD false))
else none
else none
| none => none
/-- Time step `d` of the gadget phase for time step `s` of `C`, its locations tagged with their
gadget instance. -/
def gadgetPhaseStep (P : FTProtocol) (C : LocCircuit N) (s d : ℕ) :
List (Loc (N * (P.n + P.A)) × FTInstance N) :=
(C.steps.getD s []).zipIdx.flatMap fun p =>
((P.gadget p.1.kind).steps.getD d []).map fun g =>
(⟨g.kind, g.wires.trans (blockEmb P.n P.A p.1.wires),
fun O => g.cond (fun lid => O (gadgetGlobalId P C s p.2 lid)) &&
(if p.1.kind.IsGate then p.1.cond (decodedOutcomes P C O) else true)⟩,
FTInstance.gadget (s, p.2))
/-- Time step `e` of the EC phase after time step `s` of `C`, its locations tagged with their
gadget instance. -/
def ecPhaseStep (P : FTProtocol) (C : LocCircuit N) (s e : ℕ) :
List (Loc (N * (P.n + P.A)) × FTInstance N) :=
(ecBlocks C s).zipIdx.flatMap fun p =>
(P.ec.steps.getD e []).map fun g =>
(⟨g.kind, g.wires.trans (ecEmb P.n P.A p.1),
fun O => g.cond (fun lid => O (ecGlobalId P s p.2 lid))⟩,
FTInstance.ec s p.1)
/-- The time steps of `C′`, every location tagged with its gadget instance. -/
def ftTaggedSteps (P : FTProtocol) (C : LocCircuit N) :
List (List (Loc (N * (P.n + P.A)) × FTInstance N)) :=
(List.range C.steps.length).flatMap fun s =>
(List.range P.gadgetDepth).map (gadgetPhaseStep P C s) ++
(List.range P.ec.steps.length).map (ecPhaseStep P C s)
/-- Gottesman intro p.33 (Def. 6: "a quantum circuit `C′` constructed by replacing each location
`C_i` with a fault-tolerant gadget for `C_i`, and adding fault-tolerant error correction gadgets
between any pair of consecutive locations") and p.34 (Fig. 7): the fault-tolerant circuit for
`C`. -/
def ftCircuit (P : FTProtocol) (C : LocCircuit N) : LocCircuit (N * (P.n + P.A)) :=
⟨(ftTaggedSteps P C).map fun st => st.map Prod.fst⟩
/-- The gadget instance the location `id` of `C′` belongs to. -/
def ftOwner (P : FTProtocol) (C : LocCircuit N) (id : ℕ × ℕ) : Option (FTInstance N) :=
((ftTaggedSteps P C).getD id.1 [])[id.2]?.map Prod.snd
/-- Gottesman intro p.19 ("the final fault-tolerant measurement gadgets will produce classical
information which should … give the same outcome as the original circuit") and p.17 (classical
computation is perfect): the measurement record of `C` decoded from that of `C′`: for each
measurement location of `C` (in `C`'s record order), `measDecode` of the outcomes of its
measurement gadget; EC and other outcomes are discarded. -/
def ftDecode (P : FTProtocol) (C : LocCircuit N) (r : List Bool) : List Bool :=
C.measIds.map fun cid => P.measDecode ((P.gadget .meas).measIds.map fun lid =>
((ftCircuit P C).outcomeAt r (gadgetGlobalId P C cid.1 cid.2 lid)).getD false)
/-- Gottesman intro p.34 (Def. 7) and p.38 (Def. 10): the locations of `C′` in the ExRec of the `C`
location `ℓ`: its gadget, the leading ECs (the EC after the previous step on each of its qubits,
unless `ℓ` is a preparation) and the trailing ECs (the EC after its step on each of its qubits not
in `trunc`, unless `ℓ` is a measurement). `trunc = ∅` is the full ExRec. -/
noncomputable def exRecLocs (P : FTProtocol) (C : LocCircuit N) (ℓ : ℕ × ℕ) (trunc : Finset (Fin N)) :
Finset (ℕ × ℕ) :=
open Classical in
match C.locAt ℓ with
| none => ∅
| some l => (ftCircuit P C).locs.filter fun id =>
match ftOwner P C id with
| some (.gadget ℓ') => ℓ' = ℓ
| some (.ec s q) => q ∈ l.qubits ∧
((l.kind ≠ .prep ∧ s + 1 = ℓ.1) ∨ (l.kind ≠ .meas ∧ s = ℓ.1 ∧ q ∉ trunc))
| none => False
/-- Gottesman intro p.38 (Def. 10): the qubits of the `C` location `ℓ` whose trailing EC is removed
because it is the leading EC of a bad location (of the next time step) in `B`. -/
noncomputable def truncOf (C : LocCircuit N) (B : Finset (ℕ × ℕ)) (ℓ : ℕ × ℕ) : Finset (Fin N) :=
open Classical in
match C.locAt ℓ with
| none => ∅
| some l => l.qubits.filter fun q =>
∃ ℓ' ∈ B, ℓ'.1 = ℓ.1 + 1 ∧ ∃ l', C.locAt ℓ' = some l' ∧ q ∈ l'.qubits
/-- The bad locations among the last `k` time steps of `C`, for the set `S` of faulty locations of
`C′` (Def. 10's recursion, from the end of the circuit backwards). -/
noncomputable def badAbove (P : FTProtocol) (C : LocCircuit N) (S : Finset (ℕ × ℕ)) :
ℕ → Finset (ℕ × ℕ)
| 0 => ∅
| k + 1 =>
open Classical in
badAbove P C S k ∪
((Finset.range (C.steps.getD (C.steps.length - (k + 1)) []).length).image
fun j => (C.steps.length - (k + 1), j)).filter fun ℓ =>
P.t < (S ∩ exRecLocs P C ℓ (truncOf C (badAbove P C S k) ℓ)).card
/-- Gottesman intro p.38 (Def. 10): the set of locations of `C` whose ExRec (full or truncated) is
bad, i.e. contains more than `t` of the faulty locations `S` of `C′`; an ExRec is truncated on the
qubits whose trailing EC is a leading EC of a bad ExRec, determined from the end of the circuit
backwards. -/
noncomputable def badAssignment (P : FTProtocol) (C : LocCircuit N) (S : Finset (ℕ × ℕ)) :
Finset (ℕ × ℕ) :=
badAbove P C S C.steps.length
/-- The superoperator `Ψ` on `k` registers (of type `α`) lifted to `N` registers along `w`, the
identity on the others. -/
noncomputable def liftReg {α : Type*} {k : ℕ} (w : Fin k ↪ Fin N)
(Ψ : Superop (Fin k → α) (Fin k → α)) : Superop (Fin N → α) (Fin N → α) :=
fun X =>
(liftSuperop (E := Unit) w
(fun Y => (Ψ (Y.submatrix (fun x => (x, ())) (fun x => (x, ())))).submatrix Prod.fst Prod.fst)
(X.submatrix Prod.fst Prod.fst)).submatrix (fun x => (x, ())) (fun x => (x, ()))
/-- A superoperator `Ψ` on the (data qubit, syndrome register) pairs of `k` qubits, lifted to the
qubits of `C` with one syndrome register per qubit as environment. -/
noncomputable def pairLift {σ k : ℕ} (w : Fin k ↪ Fin N)
(Ψ : Superop (Fin k → Bool × Fin σ) (Fin k → Bool × Fin σ)) :
Superop (Qubits N × (Fin N → Fin σ)) (Qubits N × (Fin N → Fin σ)) :=
fun X =>
(liftReg w Ψ (X.submatrix (Equiv.arrowProdEquivProdArrow (Fin N) (fun _ => Bool) (fun _ => Fin σ))
(Equiv.arrowProdEquivProdArrow (Fin N) (fun _ => Bool) (fun _ => Fin σ)))).submatrix
(Equiv.arrowProdEquivProdArrow (Fin N) (fun _ => Bool) (fun _ => Fin σ)).symm
(Equiv.arrowProdEquivProdArrow (Fin N) (fun _ => Bool) (fun _ => Fin σ)).symm
/-- Gottesman intro pp.37–39 (eqs. (82), (83), Thm 8): `err` is an error assignment of a circuit
`C̃` for `C` with bad set `B` and syndrome registers `Fin σ` (one per qubit of `C`, the environment;
"`C̃` uses ancilla registers to control the types of `U′` errors"): no error off the locations; at
every location `ℓ`, after its ideal operation, a quantum operation `Ψ` on the qubits of `ℓ` and
their syndrome registers; if `ℓ ∉ B` ("include `C_i` unchanged"), `Ψ` is the identity on the qubits
tensored with a quantum operation `V` on the syndrome registers (eq. (83)); if `ℓ ∈ B`, `Ψ` is
arbitrary (the erroneous `U′` of (82), controlled by the syndrome). -/
def IsTildeErrors (C : LocCircuit N) (B : Finset (ℕ × ℕ)) (σ : ℕ)
(err : ErrAssign N (Fin N → Fin σ)) : Prop :=
∀ ℓ : ℕ × ℕ, (C.locAt ℓ = none → err ℓ = none) ∧
∀ l : Loc N, C.locAt ℓ = some l →
∃ Ψ : Superop (Fin l.kind.arity → Bool × Fin σ) (Fin l.kind.arity → Bool × Fin σ),
IsChannel Ψ ∧
(ℓ ∉ B → ∃ V : Superop (Fin l.kind.arity → Fin σ) (Fin l.kind.arity → Fin σ),
IsChannel V ∧ Ψ = pairedSuperop 1 V) ∧
err ℓ = some (pairLift l.wires Ψ)
/-- Gottesman intro p.40 (Def. 12): an error model on a circuit with `N` qubits: an environment
register `Fin e` in the state `σ0`, the probability `prob S` of faults at precisely the set `S` of
locations, and the errors `err S ℓ` chosen (by an adversary) when the faulty set is `S`; they act
at the locations of `S` in chronological order and may be entangled through the environment. -/
structure LocalStochasticModel (N : ℕ) where
e : ℕ
σ0 : Matrix (Fin e) (Fin e) ℂ
prob : Finset (ℕ × ℕ) → ℝ
err : Finset (ℕ × ℕ) → ℕ × ℕ → Superop (Qubits N × Fin e) (Qubits N × Fin e)
/-- Gottesman intro p.40 (Def. 12): the output distribution of `C` under the error model: the
mixture over the faulty set `S` of the output distributions with the errors at `S`. -/
noncomputable def noisyOutDist (C : LocCircuit N) (M : LocalStochasticModel N) :
(Fin C.measCount → Bool) → ℝ :=
fun r => ∑ S ∈ C.locs.powerset,
M.prob S * C.outDist (fun ℓ => if ℓ ∈ S then some (M.err S ℓ) else none) M.σ0 r
/-- Gottesman intro p.40 (Def. 12): `M` is a local stochastic error model on `C` with error bounds
`bound`: the environment state is a density matrix; `prob` is a probability distribution on the
sets of locations of `C`; each error at a faulty location is any quantum operation on that
location's qubits and the environment; and for every set `R` of locations the probability of
faults on every location of `R` (and possibly elsewhere) is at most `Π_{i ∈ R} p_i`. The side
condition `p_i < 1` of Def. 12 is a separate hypothesis of the statements (Thm 9's induced bounds
(84) may exceed 1). -/
def IsLocalStochastic (C : LocCircuit N) (M : LocalStochasticModel N) (bound : ℕ × ℕ → ℝ) : Prop :=
IsDensityMatrix M.σ0 ∧ (∀ S, 0 ≤ M.prob S) ∧ (∀ S, ¬ S ⊆ C.locs → M.prob S = 0) ∧
∑ S ∈ C.locs.powerset, M.prob S = 1 ∧
(∀ (S : Finset (ℕ × ℕ)) (ℓ : ℕ × ℕ) (l : Loc N), ℓ ∈ S → C.locAt ℓ = some l →
IsLocError l.wires (M.err S ℓ)) ∧
∀ R ⊆ C.locs, ∑ S ∈ C.locs.powerset.filter (fun S => R ⊆ S), M.prob S ≤ ∏ i ∈ R, bound i
/-- Transport of a circuit along an equality of qubit numbers. -/
def LocCircuit.castN {N N' : ℕ} (h : N = N') (C : LocCircuit N) : LocCircuit N' :=
h ▸ C
/-- Gottesman intro p.36 (§5.2: "a sequence of circuits `C^{(k)}`, `k = 1, …, L`, where each `C^{(k)}`
is a fault-tolerant simulation of `C^{(k−1)}`, with `C^{(0)} = C`") and p.42 (proof of Thm 10): the
`L`-level concatenated fault-tolerant circuit for `C`, on `N (n + A)^L` qubits. -/
def concatCircuit (P : FTProtocol) : (L : ℕ) → LocCircuit N → LocCircuit (N * (P.n + P.A) ^ L)
| 0, C => C.castN (by simp)
| L + 1, C => (ftCircuit P (concatCircuit P L C)).castN (by rw [pow_succ, mul_assoc])
/-- The classical decoding of the record of `C^{(L)}` to the record of `C`, level by level. -/
def concatDecode (P : FTProtocol) : (L : ℕ) → LocCircuit N → List Bool → List Bool
| 0, _ => id
| L + 1, C => fun r => concatDecode P L C (ftDecode P (concatCircuit P L C) r)
/-! ### Sanity tests -/
example (P : FTProtocol) : ftCircuit P (⟨[]⟩ : LocCircuit N) = ⟨[]⟩ := by
simp [ftCircuit, ftTaggedSteps]
example (P : FTProtocol) (S : Finset (ℕ × ℕ)) : badAssignment P (⟨[]⟩ : LocCircuit N) S = ∅ := rfl
example (P : FTProtocol) (C : LocCircuit N) : concatDecode P 0 C = id := rfl
example (P : FTProtocol) (r : List Bool) : ftDecode P (⟨[]⟩ : LocCircuit N) r = [] := rfl
example (n A : ℕ) (q : Fin N) (p : Fin (n + A)) :
blockEmb n A (Stabilizer.wire1 q) (finProdFinEquiv (0, p)) = finProdFinEquiv (q, p) := by
show finProdFinEquiv (_, _) = _
rw [Equiv.symm_apply_apply]
rfl
example (C : LocCircuit N) (M : LocalStochasticModel N) (h : C.locs = ∅) (r : Fin C.measCount → Bool) :
noisyOutDist C M r = M.prob ∅ * C.outDist (fun _ => none) M.σ0 r := by
simp [noisyOutDist, h]
end QAlgorithms