catalyst.passes.gridsynth¶
- gridsynth(qnode=None, *, epsilon=0.0001, ppr_basis=False)[source]¶
A quantnum compilation pass to discretize single-qubit RZ and PhaseShift gates into the Clifford+T basis or the PPR basis using the Ross-Selinger Gridsynth algorithm. Reference: https://arxiv.org/abs/1403.2975
Note
The actual discretization is only performed during execution time.
- Parameters:
qnode (QNode) – the QNode to apply the gridsynth compiler pass to
epsilon (float) – The maximum permissible operator norm error per rotation gate. Defaults to
1e-4.ppr_basis (bool) – If true, decompose directly to Pauli Product Rotations (PPRs) in QEC dialect. Defaults to
False
- Returns:
Note
The circuit generated from this pass with
ppr_basis=Trueare currently not executable on any backend. This is only for analysis with thenull.qubitdevice and potential future execution when a suitable backend is available.Example
In this example the RZ gate will be converted into a new function, which calls the discretization at execution time.
import pennylane as qml from catalyst import qjit from catalyst.passes import gridsynth pipe = [("pipe", ["quantum-compilation-stage"])] @qjit(pipelines=pipe, target="mlir") @gridsynth @qml.qnode(qml.device("null.qubit", wires=1)) def circuit(): qml.RZ(x, wires=0) return qml.probs() >>> print(circuit.mlir_opt)
Example MLIR Representation:
. . . func.func private @rs_decomposition_get_phase(f64, f64, i1) -> f64 func.func private @rs_decomposition_get_gates(memref<?xindex>, f64, f64, i1) func.func private @rs_decomposition_get_size(f64, f64, i1) -> index func.func private @__catalyst_decompose_RZ_0(%arg0: !quantum.bit, %arg1: f64) -> (!quantum.bit, f64) { . . . %2 = scf.for %arg2 = %c0 to %0 step %c1 iter_args(%arg3 = %arg0) -> (!quantum.bit) { %3 = memref.load %alloc[%arg2] : memref<?xindex> %4 = scf.index_switch %3 -> !quantum.bit case 0 { %out_qubits = quantum.custom "T"() %arg3 : !quantum.bit scf.yield %out_qubits : !quantum.bit } case 1 { %out_qubits = quantum.custom "Hadamard"() %arg3 : !quantum.bit %out_qubits_0 = quantum.custom "T"() %out_qubits : !quantum.bit scf.yield %out_qubits_0 : !quantum.bit } case 2 { %out_qubits = quantum.custom "S"() %arg3 : !quantum.bit %out_qubits_0 = quantum.custom "Hadamard"() %out_qubits : !quantum.bit %out_qubits_1 = quantum.custom "T"() %out_qubits_0 : !quantum.bit scf.yield %out_qubits_1 : !quantum.bit } . . . } } func.func public @circuit_0(%arg0: tensor<f64>) -> tensor<f64> attributes {diff_method = "adjoint", llvm.linkage = #llvm.linkage<internal>, qnode} { . . . %2:2 = call @__catalyst_decompose_RZ_0(%1, %extracted) : (!quantum.bit, f64) -> (!quantum.bit, f64) . . . }