Skip to content

Commit

Permalink
Fix classical-synthesis label ordering with registerless=False (#9536
Browse files Browse the repository at this point in the history
…) (#10647)

* follow the Tweedledum convention on endianness

* reno

* add test

* optional dep

* docstring

* reno

* attempt to fix sphinx

---------

Co-authored-by: Julien Gacon <gaconju@gmail.com>
(cherry picked from commit 287ac5c)

Co-authored-by: Luciano Bello <bel@zurich.ibm.com>
  • Loading branch information
mergify[bot] and 1ucian0 authored Aug 16, 2023
1 parent 67061ae commit c1ee974
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 5 deletions.
1 change: 0 additions & 1 deletion qiskit/circuit/classicalfunction/classicalfunction.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ def _define(self):
def qregs(self):
"""The list of qregs used by the classicalfunction"""
qregs = [QuantumRegister(1, name=arg) for arg in self.args if self.types[0][arg] == "Int1"]
qregs.reverse()
if self.types[0]["return"] == "Int1":
qregs.append(QuantumRegister(1, name="return"))
return qregs
3 changes: 1 addition & 2 deletions qiskit/circuit/classicalfunction/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,7 @@ def tweedledum2qiskit(tweedledum_circuit, name=None, qregs=None):
QuantumCircuit: The Tweedledum circuit converted to a Qiskit circuit.
Raises:
ClassicalFunctionCompilerError: If there a gate in the Tweedledum circuit has no Qiskit
equivalent.
ClassicalFunctionCompilerError: If a gate in the Tweedledum circuit has no Qiskit equivalent.
"""
if qregs:
qiskit_qc = QuantumCircuit(*qregs, name=name)
Expand Down
40 changes: 40 additions & 0 deletions releasenotes/notes/fix_9363-445db8fde1244e57.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
fixes:
- |
Fixed `#9363 <https://github.com/Qiskit/qiskit-terra/issues/9363>`__.
by labeling the non-registerless synthesis in the order that Tweedledum
returns. For example, compare this example before and after the fix::
from qiskit.circuit import QuantumCircuit
from qiskit.circuit.classicalfunction import BooleanExpression
boolean_exp = BooleanExpression.from_dimacs_file("simple_v3_c2.cnf")
circuit = QuantumCircuit(boolean_exp.num_qubits)
circuit.append(boolean_exp, range(boolean_exp.num_qubits))
circuit.draw("text")
from qiskit.circuit.classicalfunction import classical_function
from qiskit.circuit.classicalfunction.types import Int1
@classical_function
def grover_oracle(a: Int1, b: Int1, c: Int1) -> Int1:
return (a and b and not c)
quantum_circuit = grover_oracle.synth(registerless=False)
print(quantum_circuit.draw())
Which would print
.. parsed-literal::
Before After
c: ──■── a: ──■──
│ │
b: ──■── b: ──■──
│ │
a: ──o── c: ──o──
┌─┴─┐ ┌─┴─┐
return: ┤ X ├ return: ┤ X ├
└───┘ └───┘
4 changes: 2 additions & 2 deletions test/python/classical_function_compiler/test_synthesis.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ def test_grover_oracle_arg_regs(self):
qr_c = QuantumRegister(1, "c")
qr_d = QuantumRegister(1, "d")
qr_return = QuantumRegister(1, "return")
expected = QuantumCircuit(qr_d, qr_c, qr_b, qr_a, qr_return)
expected = QuantumCircuit(qr_a, qr_b, qr_c, qr_d, qr_return)
expected.append(
XGate().control(4, ctrl_state="1010"),
[qr_d[0], qr_c[0], qr_b[0], qr_a[0], qr_return[0]],
[qr_a[0], qr_b[0], qr_c[0], qr_d[0], qr_return[0]],
)

self.assertEqual(quantum_circuit.name, "grover_oracle")
Expand Down
30 changes: 30 additions & 0 deletions test/python/visualization/test_circuit_text_drawer.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@
CPhaseGate,
)
from qiskit.transpiler.passes import ApplyLayout
from qiskit.utils.optionals import HAS_TWEEDLEDUM
from .visualization import path_to_diagram_reference, QiskitVisualizationTestCase

if HAS_TWEEDLEDUM:
from qiskit.circuit.classicalfunction import classical_function
from qiskit.circuit.classicalfunction.types import Int1


class TestTextDrawerElement(QiskitTestCase):
"""Draw each element"""
Expand Down Expand Up @@ -1216,6 +1221,31 @@ def test_text_spacing_2378(self):
circuit.rz(11111, qr[2])
self.assertEqual(str(_text_circuit_drawer(circuit)), expected)

@unittest.skipUnless(HAS_TWEEDLEDUM, "Tweedledum is required for these tests.")
def test_text_synth_no_registerless(self):
"""Test synthesis's label when registerless=False.
See https://github.com/Qiskit/qiskit-terra/issues/9363"""
expected = "\n".join(
[
" ",
" a: |0>──■──",
" │ ",
" b: |0>──■──",
" │ ",
" c: |0>──o──",
" ┌─┴─┐",
"return: |0>┤ X ├",
" └───┘",
]
)

@classical_function
def grover_oracle(a: Int1, b: Int1, c: Int1) -> Int1:
return a and b and not c

circuit = grover_oracle.synth(registerless=False)
self.assertEqual(str(_text_circuit_drawer(circuit)), expected)


class TestTextDrawerLabels(QiskitTestCase):
"""Gates with labels."""
Expand Down

0 comments on commit c1ee974

Please sign in to comment.