From 91887f6ae11acffa8a07ef967c9503ba4678fd9a Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Wed, 8 Jan 2025 15:20:45 -0800 Subject: [PATCH] Allow mx and my gates in OpenQasm2 translation (#2494) * Allow mx and my gates in OpenQasm2 translation Signed-off-by: Anna Gringauze * Address CR comments Signed-off-by: Anna Gringauze --------- Signed-off-by: Anna Gringauze --- .../cudaq/platform/py_alt_launch_kernel.cpp | 1 + python/tests/backends/test_braket.py | 4 +- .../mlir/test_output_translate_openqasm.py | 174 +++++++++++++++++- .../default/rest/helpers/braket/braket.yml | 2 +- .../rest/helpers/infleqtion/infleqtion.yml | 2 +- 5 files changed, 178 insertions(+), 5 deletions(-) diff --git a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp index e095a6d712..3232e26b11 100644 --- a/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp +++ b/python/runtime/cudaq/platform/py_alt_launch_kernel.cpp @@ -667,6 +667,7 @@ std::string getASM(const std::string &name, MlirModule module, "CHToCX", "CCZToCX", "CRzToCX", "CRyToCX", "CRxToCX", "CR1ToCX", "CCZToCX", "RxAdjToRx", "RyAdjToRy", "RzAdjToRz"}})); + pm.addPass(cudaq::opt::createQuakeToCCPrep()); pm.addNestedPass(createCanonicalizerPass()); pm.addNestedPass(cudaq::opt::createExpandControlVeqs()); pm.addNestedPass(cudaq::opt::createCombineQuantumAllocations()); diff --git a/python/tests/backends/test_braket.py b/python/tests/backends/test_braket.py index 8190c29ba3..e847d19714 100644 --- a/python/tests/backends/test_braket.py +++ b/python/tests/backends/test_braket.py @@ -100,8 +100,8 @@ def single_qubit_gates(): rz(np.pi, q) s(q) t(q) - # mx(q) ## Unsupported - # my(q) ## Unsupported + mx(q) + my(q) mz(q) # Test here is that this runs diff --git a/python/tests/mlir/test_output_translate_openqasm.py b/python/tests/mlir/test_output_translate_openqasm.py index 1ea16b276b..4c510ed489 100644 --- a/python/tests/mlir/test_output_translate_openqasm.py +++ b/python/tests/mlir/test_output_translate_openqasm.py @@ -11,7 +11,7 @@ import cudaq -def test_synth_and_openqasm(): +def test_openqasm2_synth(): @cudaq.kernel def ghz(numQubits: int): @@ -35,3 +35,175 @@ def ghz(numQubits: int): # CHECK: cx var0[1], var0[2]; # CHECK: cx var0[2], var0[3]; # CHECK: cx var0[3], var0[4]; + +def test_openqasm2_gates(): + + @cudaq.kernel + def gates(): + q = cudaq.qubit() + ctrl0 = cudaq.qubit() + ctrl1 = cudaq.qubit() + h(q) + x(q) + y(q) + z(q) + s(q) + t(q) + h.ctrl(ctrl0, q) + z.ctrl(ctrl0, ctrl1, q) + rx.ctrl(np.pi, ctrl0, q) + ry.ctrl(np.pi, ctrl0, q) + rz.ctrl(np.pi, ctrl0, q) + r1.ctrl(np.pi, ctrl0, q) + r1(np.pi, q) + rx(np.pi, q) + rx.adj(np.pi, q) + ry(np.pi, q) + ry.adj(np.pi, q) + rz(np.pi, q) + rz.adj(np.pi, q) + mx(q) + my(q) + mz(q) + + print(cudaq.translate(gates, format="openqasm2")) + +# CHECK: // Code generated by NVIDIA's nvq++ compiler +# CHECK: OPENQASM 2.0; + +# CHECK: include "qelib1.inc"; + +# CHECK: qreg var0[3]; +# CHECK: h var0[0]; +# CHECK: x var0[0]; +# CHECK: y var0[0]; +# CHECK: z var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[0]; +# CHECK: rz(7.853982e-01) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[2], var0[1]; +# CHECK: rz(-7.853982e-01) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: cx var0[2], var0[1]; +# CHECK: rz(7.853982e-01) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rz(7.853982e-01) var0[2]; +# CHECK: rx(1.570796e+00) var0[2]; +# CHECK: rz(0.000000e+00) var0[2]; +# CHECK: rx(-1.570796e+00) var0[2]; +# CHECK: rz(0.000000e+00) var0[2]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(1.570796e+00) var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: ry(1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: ry(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[1]; +# CHECK: rx(1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: rx(-1.570796e+00) var0[1]; +# CHECK: rz(0.000000e+00) var0[1]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(-1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: cx var0[1], var0[0]; +# CHECK: rz(1.570796e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rz(3.141593e+00) var0[0]; +# CHECK: rx(1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(-1.570796e+00) var0[0]; +# CHECK: rz(0.000000e+00) var0[0]; +# CHECK: rx(3.141593e+00) var0[0]; +# CHECK: rx(-3.141593e+00) var0[0]; +# CHECK: ry(3.141593e+00) var0[0]; +# CHECK: ry(-3.141593e+00) var0[0]; +# CHECK: rz(3.141593e+00) var0[0]; +# CHECK: rz(-3.141593e+00) var0[0]; +# CHECK: h var0[0]; +# CHECK: creg var4[1]; +# CHECK: measure var0[0] -> var4[0]; +# CHECK: sdg var0[0]; +# CHECK: h var0[0]; +# CHECK: creg var5[1]; +# CHECK: measure var0[0] -> var5[0]; +# CHECK: creg var6[1]; +# CHECK: measure var0[0] -> var6[0]; diff --git a/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml b/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml index a382d50adf..04db01abee 100644 --- a/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml +++ b/runtime/cudaq/platform/default/rest/helpers/braket/braket.yml @@ -17,7 +17,7 @@ config: # Tell NVQ++ to generate glue code to set the target backend name gen-target-backend: true # Define the lowering pipeline - platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg,canonicalize,multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,R1ToU3,U3ToRotations,CHToCX,CCZToCX,CRzToCX,CRyToCX,CRxToCX,CR1ToCX,RxAdjToRx,RyAdjToRy,RzAdjToRz},func.func(expand-control-veqs,combine-quantum-alloc,canonicalize,combine-measurements)" + platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg,canonicalize,multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,R1ToU3,U3ToRotations,CHToCX,CCZToCX,CRzToCX,CRyToCX,CRxToCX,CR1ToCX,RxAdjToRx,RyAdjToRy,RzAdjToRz},quake-to-cc-prep,func.func(expand-control-veqs,combine-quantum-alloc,canonicalize,combine-measurements)" # Tell the rest-qpu that we are generating OpenQASM 2.0. codegen-emission: qasm2 # Library mode is only for simulators, physical backends must turn this off diff --git a/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml b/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml index fb22981c82..81d151a6f1 100644 --- a/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml +++ b/runtime/cudaq/platform/default/rest/helpers/infleqtion/infleqtion.yml @@ -17,7 +17,7 @@ config: # Tell NVQ++ to generate glue code to set the target backend name gen-target-backend: true # Define the lowering pipeline - platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg),canonicalize,func.func(multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,CCZToCX,CRyToCX,CRxToCX,R1AdjToR1,RxAdjToRx,RyAdjToRy,RzAdjToRz},func.func(memtoreg{quantum=0}),symbol-dce" + platform-lowering-config: "func.func(const-prop-complex,canonicalize,cse,lift-array-alloc),globalize-array-values,func.func(state-prep),unitary-synthesis,canonicalize,apply-op-specialization,aggressive-early-inlining,unrolling-pipeline,func.func(lower-to-cfg),canonicalize,func.func(multicontrol-decomposition),decomposition{enable-patterns=SToR1,TToR1,CCZToCX,CRyToCX,CRxToCX,R1AdjToR1,RxAdjToRx,RyAdjToRy,RzAdjToRz},quake-to-cc-prep,func.func(memtoreg{quantum=0}),symbol-dce" # Tell the rest-qpu that we are generating OpenQASM 2.0. codegen-emission: qasm2 # Library mode is only for simulators, physical backends must turn this off