catalyst.passes.graph_decomposition¶
- graph_decomposition(qnode, gate_set: Iterable[type | str] | dict[type | str, float], fixed_decomps: dict[str, DecompositionRule | str] | None = None, exclude_decomps: dict[str, list[str] | tuple[str, ...]] | None = None, bytecode_rules: str = '/home/docs/checkouts/readthedocs.org/user_builds/xanaduai-catalyst/envs/latest/lib/python3.12/site-packages/catalyst/utils/../resources/decomposition_rules_6039d1257e63dd6a4dc489dc377795572a9b503a.mlirbc', libQPD_path: Path | None = None, libpython_path: Path | None = None, verbose: bool = False)¶
Specify that the
-graph-decompositionMLIR compiler pass for applying the graph-based decomposition should be applied to the decorated QNode duringqjit()compilation.The graph-based decomposition pass decomposes gates into a weighted target
gate_setby applying user-provided and built-in decomposition rules. The graph-based framework allows multiple decomposition rules to be defined for a quantum operation, and the graph solver will determine the optimal decomposition rules to apply, minimizing the overall gate count or the cost according to user-specified weights.The same options are also used by the
-resource-estimateMLIR compiler analysis pass for the graph-based resource estimation.Note
The QNode itself will not be changed or transformed by applying these decorators.
As a result, circuit inspection tools such as
draw()will continue to display the circuit as written in Python.To instead view the optimized circuit, the MLIR must be viewed after the
"QuantumCompilationStage"stage via theget_compilation_stage()function.- Parameters:
fn (QNode) – the QNode to apply the graph decomposition compiler pass to.
gate_set (Iterable[type | str] | dict[type | str, float]) – the set of gates that are permissable after decomposition.
fixed_decomps (dict | None) – map operators to specific decomposition rules that will be applied if the operators need to be decomposed (i.e. when they’re not in the target gate set).
exclude_decomps (dict | None) – map operators to lists of decomposition rules to exclude from this pass’s graph. Rules may be given as names or callables. Excluded rules are still lowered by the frontend and remain available to subsequent passes. Exclusions also apply to rules selected by
fixed_decomps.bytecode_rules (str) – path to the bytecode file containing decomposition rules. Defaults to the built-in decomposition rules.
verbose (bool) – if
True, the pass prints the decomposition rule the solver chose for each operator, along with its cost and the resulting gate counts, to stderr.Falseby default.
- Return type:
QNode
Example
import pennylane as qp import pennylane.numpy as np from catalyst import qjit from catalyst.jax_primitives import decomposition_rule from catalyst.passes import cancel_inverses, graph_decomposition, merge_rotations @decomposition_rule(op_type=qp.PauliX) def x_to_rx(wire: int): qp.RX(np.pi, wire) @decomposition_rule(op_type=qp.PauliY) def y_to_ry(wire: int): qp.RY(np.pi, wire) @decomposition_rule(op_type=qp.Hadamard) def h_to_rx_ry(wire: int): qp.RX(np.pi / 2, wire) qp.RY(np.pi / 2, wire) @qjit(capture=True) @graph_decomposition(gate_set={qp.Rot}) @merge_rotations @graph_decomposition( gate_set={qp.RX, qp.RY}, fixed_decomps={qp.PauliX: x_to_rx, qp.PauliY: y_to_ry, qp.H: h_to_rx_ry}, ) @cancel_inverses @qp.qnode(qp.device("lightning.qubit", wires=2)) def circuit(x: float, y: float): qp.H(0) qp.H(0) qp.RX(x, wires=0) qp.PauliX(0) qp.RY(y, wires=0) qp.PauliY(0) qp.RY(x + y, wires=0) # register custom decomposition rules x_to_rx(int) y_to_ry(int) h_to_rx_ry(int) return qp.state()
>>> qp.specs(circuit, level="device")(1.23, 4.56).resources.gate_types {'Rot': 2}