From 51312ac3b2369ea4b1f94fc90c240dc3f2be89dd Mon Sep 17 00:00:00 2001 From: Cleiton Augusto Date: Tue, 25 Aug 2026 15:24:37 -0400 Subject: [PATCH] test: cover the control on a controlled swap through openqasm2 Regression test for #5192. A controlled swap currently lowers to three CNOTs between the targets, dropping the control, so the exported circuit swaps unconditionally while the simulator does not. The control is |0> on purpose. With the control set, a controlled swap and a plain swap agree, which is why SwapToCX.qke does not catch this: it only covers the uncontrolled case. Asserts that the control qubit appears in some gate rather than pinning a particular decomposition, so it does not constrain how the lowering is fixed. Fails on 0.15.1, passes once the control survives. Signed-off-by: Cleiton Augusto --- python/tests/builder/test_translate.py | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/python/tests/builder/test_translate.py b/python/tests/builder/test_translate.py index cc2a7636d80..701431672fb 100644 --- a/python/tests/builder/test_translate.py +++ b/python/tests/builder/test_translate.py @@ -172,3 +172,30 @@ def inner(): assert "OPENQASM 2.0;" in asm body = asm[asm.index('qreg'):] assert "tdg var0[0];" in body + + +def test_translate_controlled_swap_keeps_control(): + """A controlled swap must not lower to an unconditional swap. + + Reported in #5192: the SwapToCX decomposition read only the two targets and + emitted three CNOTs between them, so the control was dropped and the + exported circuit swapped unconditionally. + + The control has to be |0> for this to be visible. With the control set, a + controlled swap and a plain swap agree, which is why the existing + SwapToCX.qke test does not catch it: it only covers the uncontrolled case. + """ + kernel = cudaq.make_kernel() + q = kernel.qalloc(3) + kernel.x(q[1]) + kernel.cswap(q[0], q[1], q[2]) + asm = cudaq.translate(kernel, format="openqasm2") + + body = "\n".join( + line for line in asm.splitlines() + if line.strip() and not line.strip().startswith( + ("//", "OPENQASM", "include", "qreg", "creg")) + ) + assert "var0[0]" in body, ( + "the control qubit appears in no gate, so the controlled swap was " + f"lowered as an unconditional one:\n{body}")