qp.labs.transforms.make_rz_to_phase_gradient_decomp

make_rz_to_phase_gradient_decomp(angle_wires, phase_grad_wires, work_wires)[source]

Custom decomposition rule for RZ gates

This is a temporary workaround before moving to capture as default frontend, which unlocks dynamic wire allocation. Here, we explicitly provide the necessary wires for the phase gradient decomposition of RZ. This way, this function can be used in a workflow context that explicitly uses those wires to generate this decomposition rule, which can then be used as alt_decomps or fixed_decomp within decompose() (when using the graph-based decomposition system).

Parameters:
  • angle_wires (Wires) – wires that encode the binary representation of the rotation angle

  • phase_grad_wires (Wires) – wires that carry a phase gradient state

  • work_wires (Wires) – additional work wires for SemiAdder decomposition

Returns:

decomposition rule to be used within decompose().

Return type:

qp.decomposition.DecompositionRule

Example

In this example we decompose a circuit containing only a single RZ gate using the custom decomposition rule that we generate from within the context of the example, where all auxiliary wires exist.

import pennylane as qp
from pennylane.labs.transforms import make_rz_to_phase_gradient_decomp
import numpy as np

qp.decomposition.enable_graph()

prec = 3
phi = (1/2 + 1/4 + 1/8) * 2 * np.pi # binary rep is (111)

angle_wires = qp.wires.Wires([f"aux_{i}" for i in range(prec)])
phase_grad_wires = qp.wires.Wires([f"qft_{i}" for i in range(prec)])
work_wires = qp.wires.Wires([f"work_{i}" for i in range(prec - 1)])

custom_decomp = make_rz_to_phase_gradient_decomp(
    angle_wires, phase_grad_wires, work_wires
)

@qp.transforms.decompose(
        gate_set={"C(BasisEmbedding)", "SemiAdder", "CNOT", "GlobalPhase"},
        fixed_decomps={qp.RZ: custom_decomp}
)
@qp.qnode(qp.device("null.qubit"))
def circuit():
    qp.RZ(phi, 0)
    return qp.state()

specs = qp.specs(circuit)()["resources"].gate_types

The resulting circuit corresponds to the phase gradient decomposition of RZ, containing two CNOT fanouts corresponding to the binary representation of the angle (111 in this case), the SemiAdder, and a GlobalPhase.

>>> specs
{'GlobalPhase': 1, 'C(BasisEmbedding)': 2, 'SemiAdder': 1}
>>> print(qp.draw(circuit)())
     0: ─╭GlobalPhase(2.75)─╭●──────────────╭●───┤  State
 aux_0: ─├GlobalPhase(2.75)─├|Ψ⟩─╭SemiAdder─├|Ψ⟩─┤  State
 aux_1: ─├GlobalPhase(2.75)─├|Ψ⟩─├SemiAdder─├|Ψ⟩─┤  State
 aux_2: ─├GlobalPhase(2.75)─╰|Ψ⟩─├SemiAdder─╰|Ψ⟩─┤  State
 qft_0: ─├GlobalPhase(2.75)──────├SemiAdder──────┤  State
 qft_1: ─├GlobalPhase(2.75)──────├SemiAdder──────┤  State
 qft_2: ─├GlobalPhase(2.75)──────├SemiAdder──────┤  State
work_0: ─├GlobalPhase(2.75)──────├SemiAdder──────┤  State
work_1: ─╰GlobalPhase(2.75)──────╰SemiAdder──────┤  State