Skip to content

Commit

Permalink
Fix UnitarySynthesis for 3+ qubits when compiled for a backend (Qis…
Browse files Browse the repository at this point in the history
…kit#13591)

* Fix unitary synthesis for 3+ q

* Update releasenotes/notes/fix-unitary-synthesis-3q-2b2de5305bfd11ff.yaml

Co-authored-by: Alexander Ivrii <[email protected]>

* add more tests

* use == over equiv

---------

Co-authored-by: Alexander Ivrii <[email protected]>
  • Loading branch information
Cryoris and alexanderivrii authored Jan 7, 2025
1 parent 0eeba0d commit 86a5325
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 1 deletion.
3 changes: 2 additions & 1 deletion crates/accelerate/src/unitary_synthesis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,8 @@ fn py_run_main_loop(
None,
None,
)?;
out_dag = synth_dag;
let out_qargs = dag.get_qargs(packed_instr.qubits);
apply_synth_dag(py, &mut out_dag, out_qargs, &synth_dag)?;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
fixes:
- |
Fixed a bug in the :class:`.UnitarySynthesis` transpiler pass, where blocks of
:class:`.UnitaryGate`\s on 3 qubits or more were not correctly synthesized.
This led, e.g., to the circuit being overwritten with the last processed block or
to internal panics when encountering measurements after such a block.
Fixed `#13586 <https://github.com/Qiskit/qiskit/issues/13586>`__.
51 changes: 51 additions & 0 deletions test/python/transpiler/test_unitary_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,9 @@
RYYGate,
RZZGate,
RXXGate,
PauliEvolutionGate,
)
from qiskit.quantum_info import SparsePauliOp
from qiskit.circuit import Measure
from qiskit.circuit.controlflow import IfElseOp
from qiskit.circuit import Parameter, Gate
Expand Down Expand Up @@ -1050,6 +1052,55 @@ def test_qsd(self, opt):
qc_transpiled = transpile(qc, target=target, optimization_level=opt)
self.assertTrue(np.allclose(mat, Operator(qc_transpiled).data))

def test_3q_with_measure(self):
"""Test 3-qubit synthesis with measurements."""
backend = FakeBackend5QV2()

qc = QuantumCircuit(3, 1)
qc.unitary(np.eye(2**3), range(3))
qc.measure(0, 0)

qc_transpiled = transpile(qc, backend)
self.assertTrue(qc_transpiled.size, 1)
self.assertTrue(qc_transpiled.count_ops().get("measure", 0), 1)

def test_3q_series(self):
"""Test a series of 3-qubit blocks."""
backend = GenericBackendV2(5, basis_gates=["u", "cx"])

x = QuantumCircuit(3)
x.x(2)
x_mat = Operator(x)

qc = QuantumCircuit(3)
qc.unitary(x_mat, range(3))
qc.unitary(np.eye(2**3), range(3))

tqc = transpile(qc, backend, optimization_level=0, initial_layout=[0, 1, 2])

expected = np.kron(np.eye(2**2), x_mat)
self.assertEqual(Operator(tqc), Operator(expected))

def test_3q_measure_all(self):
"""Regression test of #13586."""
hamiltonian = SparsePauliOp.from_list(
[("IXX", 1), ("IYY", 1), ("IZZ", 1), ("XXI", 1), ("YYI", 1), ("ZZI", 1)]
)

qc = QuantumCircuit(3)
qc.x([1, 2])
op = PauliEvolutionGate(hamiltonian, time=1)
qc.append(op.power(8), [0, 1, 2])
qc.measure_all()

backend = GenericBackendV2(5, basis_gates=["u", "cx"])
tqc = transpile(qc, backend)

ops = tqc.count_ops()
self.assertIn("u", ops)
self.assertIn("cx", ops)
self.assertIn("measure", ops)


if __name__ == "__main__":
unittest.main()

0 comments on commit 86a5325

Please sign in to comment.