qat.middleend.passes.gates.transform module

class Decompose2QToCNOTs

Bases: TransformPass

Iterates through the list of gates and decomposes any two-qubit gate down to CNOTs.

This applies to any 2Q gate with the exception of ECR, \(ZX(\pi/4)\) and \(ZX(-\pi/4)\), which sit lower in the DAG than CNOTs. The benefit of this pass is that CNOTs have relatively simple ir algebra and allow for easy optimisations. This might later be extended to include ZX-calculus techniques. An example of this is exploiting the fact that a CNOT is involutory, meaning we can cancel two CNOTs that appear sequentially.

run(ir, *args, **kwargs)
Parameters:

ir (QatIR) – QatIR to transform.

class DecomposeToNativeGates(native_gates=None)

Bases: TransformPass

Iterates through the list of gates and decomposes gate into a native gate set.

Default native gates are Z, X_pi_2 and ZX_pi_4.

Parameters:

native_gates (List[GateBase], optional) – A list of native gates to decompose to.

run(ir, *args, **kwargs)
Parameters:

ir (QatIR) – QatIR to transform.

class DecomposeToPulses(model, decompositions=None)

Bases: TransformPass

A simple pass proof-of-concept pass that decomposes gates to pulse instructions.

Each native gate can be written a sequence of pulse instructions. This pass decomposes each gate into the correct instructions. Note that this method will not be supported in the long-term, and will be replaced by something more performant once Qat IR is better established.

A simple first step might be to write an analysis pass that extracts a set of unique gates + qubit(s) targets. For each gate+target pair, it could then determine the set of instructions for pair just once. There is the complication of how to deal with the Rz-gate, which is parameterised. This pass could then be adapted to use the results of this pass to more effeciently decompose instructions.

Initiate the pass with the hardware model.

Parameters:

model (PhysicalHardwareModel) – The hardware model is needed to construct the pulses.

run(ir, *args, **kwargs)
Parameters:

ir (QatIR) – The IR containing gates.

class RemoveRedundantSWAPs

Bases: TransformPass

Indentifies redundant SWAPs at the beginning and the end of a circuit, and removes them. This pass is designed to be used before routing.

SWAP gates can frequently be found in circuits to allow for multi-qubit gates to be applied on qubits that are not connected in the hardware’s topology. However, SWAP gates are expensive to implement (requiring three CNOT gates), and sometimes the same circuit can be implemented through a smart choice of logical-to-physical qubit placement.

Warning

This pass can modify a circuit that is capable of running on the given topology to one that might fail due to gates applied on non-connected qubits. The intention is that this is done before the routing and placement methods are applied to potentially reduce the overall 2Q-gate count.

run(ir, *args, **kwargs)
class SequentialEndMeasurements

Bases: TransformPass

Finds all end measurements and enforces that they happen at different times.

Bubbles end-measurements to the end of the instruction list, and adds a barrier between them.

run(ir, *args, **kwargs)
class Squash1QGates

Bases: TransformPass

Squashes consecutive 1Q qubits into a single \(U(\theta, \phi, \lambda)\) gate.

Iterates through the list of instructions, looking for series of 1Q gates that are not interupted by any non-1Q gates. It then squashes these gates into a single U gate, which will later be composed into native gates.

run(ir, *args, **kwargs)
Parameters:

ir (QatIR) – QatIR to transform.

squash_gate(gates)

Squashes a list of gates into a U gate.

class Squash2QGates

Bases: TransformPass

Squashes consecutive 1Q and 2Q qubits into a single gate.

Iterates through the list of instructions, looking for consecutive 1Q and 2Q gates that act on the same pair of qubits. It then squashes these gates into a single U gate, which will later be composed into native gates.

run(ir, *args, **kwargs)
class SquashCNOTs

Bases: TransformPass

Iterates through a list of gates and removes redundant CNOTs.

If two CNOTs that share the same target and control qubits appear sequentially [note that this means with respect to these two qubits, and not other qubits], then they can be squashed to an identity matrix. This also exploits the fact \(R_{z}(\theta)\) gates that act on the control qubit and \(R_{x}(\theta)\) gates that act on target qubits can be commuted through CNOTs, allowing CNOTs to be cancelled.

This can be considered a simple optimisation using ZX-calculus: in the future, we can build on this more.

run(ir, *args, **kwargs)
Parameters:

ir (QatIR) – QatIR to transform.

class StaggeredEndMeasurements

Bases: TransformPass

Finds all end measurements, and staggers their timings so that no Qubits with couplings have measurements occur at the same time.

Bubbles end-measurements to the end of the instruction list. Some analysis is required to effeciently bundle together non-coupled Qubits.

run(ir, *args, **kwargs)
class SyncEndMeasurements

Bases: TransformPass

Finds and synchronizes all end-circuit measurements to happen at the same time.

Bubbles end-measurements to the end of the instruction list, and adds a barrier before them.

run(ir, *args, **kwargs)