qml.transforms.decompose¶
- decompose(tape, gate_set=None, max_expansion=None)[source]¶
Decomposes a quantum circuit into a user-specified gate set.
- Parameters
tape (QuantumScript or QNode or Callable) – a quantum circuit.
gate_set (Iterable[str or type] or Callable, optional) – The target gate set specified as either (1) a sequence of operator types and/or names or (2) a function that returns
True
if the operator belongs to the target gate set. Defaults toNone
, in which case the gate set is considered to be all available quantum operators.max_expansion (int, optional) – The maximum depth of the decomposition. Defaults to None. If
None
, the circuit will be decomposed until the target gate set is reached.
- Returns
The decomposed circuit. The output type is explained in
qml.transform
.- Return type
qnode (QNode) or quantum function (Callable) or tuple[List[QuantumScript], function]
Note
This function does not guarantee a decomposition to the target gate set. If an operation with no defined decomposition is encountered during decomposition, it will be left in the circuit even if it does not belong in the target gate set. In this case, a
UserWarning
will be raised. To suppress this warning, simply add the operator to the gate set.See also
qml.devices.preprocess.decompose
for a transform that is intended for device developers. This function will decompose a quantum circuit into a set of basis gates available on a specific device architecture.Example
Consider the following tape:
>>> ops = [qml.IsingXX(1.2, wires=(0,1))] >>> tape = qml.tape.QuantumScript(ops, measurements=[qml.expval(qml.Z(0))])
You can decompose the circuit into a set of gates:
>>> batch, fn = qml.transforms.decompose(tape, gate_set={qml.CNOT, qml.RX}) >>> batch[0].circuit [CNOT(wires=[0, 1]), RX(1.2, wires=[0]), CNOT(wires=[0, 1]), expval(Z(0))]
You can also apply the transform directly on a
QNode
:from functools import partial @partial(qml.transforms.decompose, gate_set={qml.Toffoli, "RX", "RZ"}) @qml.qnode(qml.device("default.qubit")) def circuit(): qml.Hadamard(wires=[0]) qml.Toffoli(wires=[0,1,2]) return qml.expval(qml.Z(0))
Since the Hadamard gate is not defined in our gate set, it will be decomposed into rotations:
>>> print(qml.draw(circuit)()) 0: ──RZ(1.57)──RX(1.57)──RZ(1.57)─╭●─┤ <Z> 1: ───────────────────────────────├●─┤ 2: ───────────────────────────────╰X─┤
You can also use a function to build a decomposition gate set:
@partial(qml.transforms.decompose, gate_set=lambda op: len(op.wires)<=2) @qml.qnode(qml.device("default.qubit")) def circuit(): qml.Hadamard(wires=[0]) qml.Toffoli(wires=[0,1,2]) return qml.expval(qml.Z(0))
The circuit will be decomposed into single or two-qubit operators,
>>> print(qml.draw(circuit)()) 0: ──H────────╭●───────────╭●────╭●──T──╭●─┤ <Z> 1: ────╭●─────│─────╭●─────│───T─╰X──T†─╰X─┤ 2: ──H─╰X──T†─╰X──T─╰X──T†─╰X──T──H────────┤
You can use the
max_expansion
argument to control the number of decomposition stages applied to the circuit. By default, the function will decompose the circuit until the desired gate set is reached.The example below demonstrates how the user can visualize the decomposition in stages:
phase = 1 target_wires = [0] unitary = qml.RX(phase, wires=0).matrix() n_estimation_wires = 3 estimation_wires = range(1, n_estimation_wires + 1) @qml.qnode(qml.device("default.qubit")) def circuit(): # Start in the |+> eigenstate of the unitary qml.Hadamard(wires=target_wires) qml.QuantumPhaseEstimation( unitary, target_wires=target_wires, estimation_wires=estimation_wires, )
>>> print(qml.draw(qml.transforms.decompose(circuit, max_expansion=0))()) 0: ──H─╭QuantumPhaseEstimation─┤ 1: ────├QuantumPhaseEstimation─┤ 2: ────├QuantumPhaseEstimation─┤ 3: ────╰QuantumPhaseEstimation─┤
>>> print(qml.draw(qml.transforms.decompose(circuit, max_expansion=1))()) 0: ──H─╭U(M0)⁴─╭U(M0)²─╭U(M0)¹───────┤ 1: ──H─╰●──────│───────│───────╭QFT†─┤ 2: ──H─────────╰●──────│───────├QFT†─┤ 3: ──H─────────────────╰●──────╰QFT†─┤
>>> print(qml.draw(qml.transforms.decompose(circuit, max_expansion=2))()) 0: ──H──RZ(11.00)──RY(1.14)─╭X──RY(-1.14)──RZ(-9.42)─╭X──RZ(-1.57)──RZ(1.57)──RY(1.00)─╭X──RY(-1.00) 1: ──H──────────────────────╰●───────────────────────╰●────────────────────────────────│──────────── 2: ──H─────────────────────────────────────────────────────────────────────────────────╰●─────────── 3: ──H────────────────────────────────────────────────────────────────────────────────────────────── ───RZ(-6.28)─╭X──RZ(4.71)──RZ(1.57)──RY(0.50)─╭X──RY(-0.50)──RZ(-6.28)─╭X──RZ(4.71)───────────────── ─────────────│────────────────────────────────│────────────────────────│──╭SWAP†──────────────────── ─────────────╰●───────────────────────────────│────────────────────────│──│─────────────╭(Rϕ(1.57))† ──────────────────────────────────────────────╰●───────────────────────╰●─╰SWAP†─────H†─╰●────────── ────────────────────────────────────┤ ──────╭(Rϕ(0.79))†─╭(Rϕ(1.57))†──H†─┤ ───H†─│────────────╰●───────────────┤ ──────╰●────────────────────────────┤