Circuit

Quantum circuits can be seen as DAGs (Direct Acyclic Graphs) in which the width of the DAG is constant and equal to the number of qubits. Also the indgree and outdegree of quantum gates must always be equal. But many state-of-art quantum circuit libraries use either (a) lists of moments of gates or (b) graphs for representing them, which do not exploit the sparsity of the circuit or already make decisions about their layout (thus not having a layout-independent representation).

Instead Quac uses multi-priority queues to store gates: there is a queue per qubit lane that stores the gates that act on it, and priorities are the order in which they are applied. If a gate acts on multiple qubits, it will contain a priority per qubit. This data structure allows us to store gates in the most compact way while iterating on gates, reversing the circuit, ... are still efficient. It appears to be the perfect data structure for quantum circuits.

Was this really necessary?

No, the bottleneck of quantum circuits is not on their representation but when reading the source code of other quantum circuit libraries, I wasn't convinced by their solutions: graphs, already laid out lists of lists, a serialized list of gates, ... So I came up with multi-priority queues which seem like the perfect fit and as a consequence, the implementation is simple yet efficient.

Quac.CircuitType

A quantum circuit implementation using multi-priority queues.

  • Queues are gate-buffers in qubit lanes.
  • Multi-priority numbers can be retrieved procedurally from gate-lanes encoded inside the gates of the queues.
source

Methods

Base.adjointMethod
Base.adjoint(circuit)

Retrieve the adjoint circuit which fulfills the following equality.

circuit * circuit' == I(n)

Notes

If all gates are hermitian, then the following equality also holds.

circuit * circuit' == circuit' * circuit == I(n)
source
Base.hcatMethod
hcat(circuits::Circuit...)

Join circuits in the temporal dimension.

source
Base.iterateMethod
Base.iterate(circuit::Circuit[, state])

Retrieves next gate from state by travelling through a topologically sorted path.

Arguments

  • circuit::Circuit
  • state (or head) should be a NTuple{N, Int} where N is the number of lanes. Each element is a pointer to the next gate on each lane.
source
Base.push!Method
push!(circuit, gate...)

Appends a gate to the circuit.

source
Base.vcatMethod
vcat(circuits::Circuit...)

Join circuits in the spatial dimension.

source
Quac.connectivityFunction
connectivity([f,] circuit)

Generate connectivity graph between qubits.

Arguments

  • f: Function to filter gates from circuit.
  • circuit: Circuit.
source
Quac.lanesMethod
lanes(circuit)

Return the number of qubit lanes in a circuit.

source
Quac.momentsFunction
moments(circuit)

Return moments (lists of gates that can execute at the same time) of the circuit.

source