catalyst.passes.ions_decomposition¶
- ions_decomposition(qnode)[source]¶
Specify that the
--ions-decompositionMLIR compiler pass should be applied to the decorated QNode duringqjit()compilation.This compiler pass decomposes the gates from the set {T, S, PauliZ, Hadamard, PhaseShift, RZ, CNOT} into gates from the set {RX, RY, MS}, where MS is the Mølmer–Sørensen gate, commonly used by trapped-ion quantum devices.
Note
Unlike PennyLane circuit transformations, 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
"QuantumCompilationPass"stage via theget_compilation_stage()function.- Parameters:
fn (QNode) – the QNode to apply the ions-decomposition pass to
- Return type:
QNode
Example
import pennylane as qml from pennylane.devices import NullQubit import catalyst from catalyst import qjit from catalyst.debug import get_compilation_stage @qjit(keep_intermediate=True) @catalyst.passes.ions_decomposition @qml.qnode(NullQubit(2)) def circuit(): qml.Hadamard(wires=[0]) qml.CNOT(wires=[0, 1]) return qml.expval(qml.PauliY(wires=0))
>>> print(get_compilation_stage(circuit, stage="QuantumCompilationPass")) module @circuit { func.func public @jit_circuit() -> tensor<f64> attributes {llvm.emit_c_interface} { %0 = call @circuit_0() : () -> tensor<f64> return %0 : tensor<f64> } func.func public @circuit_0() -> tensor<f64> attributes {diff_method = "parameter-shift", llvm.linkage = #llvm.linkage<internal>, qnode} { %c0_i64 = arith.constant 0 : i64 %cst = arith.constant 0.000000e+00 : f64 %cst_0 = arith.constant 1.5707963267948966 : f64 %cst_1 = arith.constant 3.1415926535897931 : f64 %cst_2 = arith.constant -1.5707963267948966 : f64 quantum.device shots(%c0_i64) ["catalyst/runtime/build/lib/librtd_null_qubit.so", "NullQubit", "{'shots': 0}"] %0 = quantum.alloc( 2) : !quantum.reg %1 = quantum.extract %0[ 0] : !quantum.reg -> !quantum.bit %out_qubits = quantum.custom "RX"(%cst) %1 : !quantum.bit %out_qubits_3 = quantum.custom "RY"(%cst_0) %out_qubits : !quantum.bit %out_qubits_4 = quantum.custom "RX"(%cst_1) %out_qubits_3 : !quantum.bit %2 = quantum.extract %0[ 1] : !quantum.reg -> !quantum.bit %out_qubits_5 = quantum.custom "RY"(%cst_0) %out_qubits_4 : !quantum.bit %out_qubits_6:2 = quantum.custom "MS"(%cst_0) %out_qubits_5, %2 : !quantum.bit, !quantum.bit %out_qubits_7 = quantum.custom "RX"(%cst_2) %out_qubits_6#0 : !quantum.bit %out_qubits_8 = quantum.custom "RY"(%cst_2) %out_qubits_6#1 : !quantum.bit %out_qubits_9 = quantum.custom "RY"(%cst_2) %out_qubits_7 : !quantum.bit %3 = quantum.namedobs %out_qubits_8[ PauliY] : !quantum.obs %4 = quantum.expval %3 : f64 %from_elements = tensor.from_elements %4 : tensor<f64> %5 = quantum.insert %0[ 0], %out_qubits_8 : !quantum.reg, !quantum.bit %6 = quantum.insert %5[ 1], %out_qubits_9 : !quantum.reg, !quantum.bit quantum.dealloc %6 : !quantum.reg quantum.device_release return %from_elements : tensor<f64> } func.func @setup() { quantum.init return } func.func @teardown() { quantum.finalize return } }
You can see that the Hadamard gate has been decomposed to RX(0)RY(pi/2)RX(pi):
%cst = arith.constant 0.000000e+00 : f64 %cst_0 = arith.constant 1.5707963267948966 : f64 %cst_1 = arith.constant 3.1415926535897931 : f64 ... %out_qubits = quantum.custom "RX"(%cst) %1 : !quantum.bit %out_qubits_3 = quantum.custom "RY"(%cst_0) %out_qubits : !quantum.bit %out_qubits_4 = quantum.custom "RX"(%cst_1) %out_qubits_3 : !quantum.bit
and that the CNOT gate has been decomposed to its corresponding circuit implementation using the RX, RY and MS gates:
%cst_0 = arith.constant 1.5707963267948966 : f64 %cst_2 = arith.constant -1.5707963267948966 : f64 ... %out_qubits_5 = quantum.custom "RY"(%cst_0) %out_qubits_4 : !quantum.bit %out_qubits_6:2 = quantum.custom "MS"(%cst_0) %out_qubits_5, %2 : !quantum.bit, !quantum.bit %out_qubits_7 = quantum.custom "RX"(%cst_2) %out_qubits_6#0 : !quantum.bit %out_qubits_8 = quantum.custom "RY"(%cst_2) %out_qubits_6#1 : !quantum.bit %out_qubits_9 = quantum.custom "RY"(%cst_2) %out_qubits_7 : !quantum.bit