qat.middleend.decompositions.base module
- class DecompositionBase(end_nodes=None, extend_end_nodes=None)
Bases:
object
Decomposition objects implement the rules for decomposing gates into native gates.
The object should be equipped with a
decompose_op()
method that is implemented using single dispatch. This allows us to register a decomposition for each relevant gate / operation type. Note that decompositions should be implemented carefully, and form a directed acyclic graph (DAG) that terminates atNativeGate
nodes.Assumming all relevant nodes are implemented, an operation can be decomposed to a series of native gates / operations using the
decompose()
method, which will recursively calldecompose_op()
.As a rule of thumb, try not to use logic on gate angles to define the decomposition. They should be kept general. If there are instances where a choice of angle(s) can be decomposed more effeciently, a transformation pass should be used to substitute the gate. This is done to allow predictable behaviour, and has parameterised circuits in mind.
- Parameters:
end_nodes¶ (
Optional
[list
[QubitInstruction
]]) – Optionally specify the nodes to end the decomposition recursion at. Defaults todecompositions.end_nodes
.extend_end_nodes¶ (
Optional
[list
[QubitInstruction
]]) – By default the decomposition will recurse until all gates are aNativeGate
. You can optionally add additional (nonNativeGate
) gates to terminate at. This argument should only be specified ifend_nodes=None
.
- decompose(gate, *args)
Recursively decomposes an instruction into a product of native gates.
- Parameters:
gate¶ (
QubitInstruction
) – Gate to decompose.
- decompose_op(gate, *args)
Implements the definition of a decomposition of a qubit operation.
The definition does not have to be in terms of end nodes, but decompositions must form a DAG. For example,
CNOT -> {ECR, X, Z} -> {ZX_pi_4, Z_phase, X_pi_2} U -> {x_pi_2, Z_phase}
- end_nodes = ()