mirror of https://github.com/Qiskit/qiskit.git
Fix circuit instruction conversion with loose bits (#7365)
Previously, `circuit_to_instruction` and `circuit_to_gate` were finding the number of bits in a circuit by summing the sizes of the registers. This failed if any bits were not in a register, or in more than one register. Instead, we can simply ask the input circuit how many bits it contains.
This commit is contained in:
parent
2af1016f7b
commit
29c62c4bf5
|
@ -18,7 +18,7 @@ from qiskit.exceptions import QiskitError
|
|||
|
||||
|
||||
def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label=None):
|
||||
"""Build a ``Gate`` object from a ``QuantumCircuit``.
|
||||
"""Build a :class:`.Gate` object from a :class:`.QuantumCircuit`.
|
||||
|
||||
The gate is anonymous (not tied to a named quantum register),
|
||||
and so can be inserted into another circuit. The gate will
|
||||
|
@ -73,7 +73,7 @@ def circuit_to_gate(circuit, parameter_map=None, equivalence_library=None, label
|
|||
|
||||
gate = Gate(
|
||||
name=circuit.name,
|
||||
num_qubits=sum(qreg.size for qreg in circuit.qregs),
|
||||
num_qubits=circuit.num_qubits,
|
||||
params=[*parameter_dict.values()],
|
||||
label=label,
|
||||
)
|
||||
|
|
|
@ -19,7 +19,7 @@ from qiskit.circuit.classicalregister import ClassicalRegister, Clbit
|
|||
|
||||
|
||||
def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None, label=None):
|
||||
"""Build an ``Instruction`` object from a ``QuantumCircuit``.
|
||||
"""Build an :class:`~.circuit.Instruction` object from a :class:`.QuantumCircuit`.
|
||||
|
||||
The instruction is anonymous (not tied to a named quantum register),
|
||||
and so can be inserted into another circuit. The instruction will
|
||||
|
@ -48,7 +48,6 @@ def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None
|
|||
|
||||
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
||||
from qiskit.converters import circuit_to_instruction
|
||||
%matplotlib inline
|
||||
|
||||
q = QuantumRegister(3, 'q')
|
||||
c = ClassicalRegister(3, 'c')
|
||||
|
@ -77,8 +76,8 @@ def circuit_to_instruction(circuit, parameter_map=None, equivalence_library=None
|
|||
|
||||
instruction = Instruction(
|
||||
name=circuit.name,
|
||||
num_qubits=sum(qreg.size for qreg in circuit.qregs),
|
||||
num_clbits=sum(creg.size for creg in circuit.cregs),
|
||||
num_qubits=circuit.num_qubits,
|
||||
num_clbits=circuit.num_clbits,
|
||||
params=[*parameter_dict.values()],
|
||||
label=label,
|
||||
)
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
---
|
||||
fixes:
|
||||
- |
|
||||
Fixed an error in the circuit conversion functions
|
||||
:func:`.circuit_to_gate` and :func:`.circuit_to_instruction` (and their
|
||||
associated circuit methods :meth:`.QuantumCircuit.to_gate` and
|
||||
:meth:`.QuantumCircuit.to_instruction`) when acting on a circuit with
|
||||
registerless bits, or bits in more than one register.
|
|
@ -13,7 +13,7 @@
|
|||
"""Tests for the converters."""
|
||||
|
||||
from qiskit import QuantumRegister, QuantumCircuit
|
||||
from qiskit.circuit import Gate
|
||||
from qiskit.circuit import Gate, Qubit
|
||||
from qiskit.test import QiskitTestCase
|
||||
from qiskit.exceptions import QiskitError
|
||||
|
||||
|
@ -35,6 +35,39 @@ class TestCircuitToGate(QiskitTestCase):
|
|||
self.assertIsInstance(gate, Gate)
|
||||
self.assertEqual(gate.definition[0][1], [q[1], q[6]])
|
||||
|
||||
def test_circuit_with_registerless_bits(self):
|
||||
"""Test a circuit with registerless bits can be converted to a gate."""
|
||||
qr1 = QuantumRegister(2)
|
||||
qubits = [Qubit(), Qubit(), Qubit()]
|
||||
qr2 = QuantumRegister(3)
|
||||
circ = QuantumCircuit(qr1, qubits, qr2)
|
||||
circ.cx(3, 5)
|
||||
|
||||
gate = circ.to_gate()
|
||||
self.assertIsInstance(gate, Gate)
|
||||
self.assertEqual(gate.num_qubits, len(qr1) + len(qubits) + len(qr2))
|
||||
gate_definition = gate.definition
|
||||
_, cx_qargs, cx_cargs = gate_definition.data[0]
|
||||
self.assertEqual(cx_qargs, [gate_definition.qubits[3], gate_definition.qubits[5]])
|
||||
self.assertEqual(cx_cargs, [])
|
||||
|
||||
def test_circuit_with_overlapping_registers(self):
|
||||
"""Test that the conversion works when the given circuit has bits that are contained in more
|
||||
than one register."""
|
||||
qubits = [Qubit() for _ in [None] * 10]
|
||||
qr1 = QuantumRegister(bits=qubits[:6])
|
||||
qr2 = QuantumRegister(bits=qubits[4:])
|
||||
circ = QuantumCircuit(qubits, qr1, qr2)
|
||||
circ.cx(3, 5)
|
||||
|
||||
gate = circ.to_gate()
|
||||
self.assertIsInstance(gate, Gate)
|
||||
self.assertEqual(gate.num_qubits, len(qubits))
|
||||
gate_definition = gate.definition
|
||||
_, cx_qargs, cx_cargs = gate_definition.data[0]
|
||||
self.assertEqual(cx_qargs, [gate_definition.qubits[3], gate_definition.qubits[5]])
|
||||
self.assertEqual(cx_cargs, [])
|
||||
|
||||
def test_raises(self):
|
||||
"""test circuit which can't be converted raises"""
|
||||
circ1 = QuantumCircuit(3)
|
||||
|
|
|
@ -16,6 +16,7 @@ import unittest
|
|||
|
||||
from qiskit.converters import circuit_to_instruction
|
||||
from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
|
||||
from qiskit.circuit import Qubit, Clbit
|
||||
from qiskit.circuit import Parameter
|
||||
from qiskit.test import QiskitTestCase
|
||||
from qiskit.exceptions import QiskitError
|
||||
|
@ -67,6 +68,54 @@ class TestCircuitToInstruction(QiskitTestCase):
|
|||
self.assertEqual(inst.definition[1][0].condition, (c[3], False))
|
||||
self.assertEqual(inst.definition[2][0].condition, (c[5], True))
|
||||
|
||||
def test_flatten_circuit_registerless(self):
|
||||
"""Test that the conversion works when the given circuit has bits that are not contained in
|
||||
any register."""
|
||||
qr1 = QuantumRegister(2)
|
||||
qubits = [Qubit(), Qubit(), Qubit()]
|
||||
qr2 = QuantumRegister(3)
|
||||
cr1 = ClassicalRegister(2)
|
||||
clbits = [Clbit(), Clbit(), Clbit()]
|
||||
cr2 = ClassicalRegister(3)
|
||||
circ = QuantumCircuit(qr1, qubits, qr2, cr1, clbits, cr2)
|
||||
circ.cx(3, 5)
|
||||
circ.measure(4, 4)
|
||||
|
||||
inst = circuit_to_instruction(circ)
|
||||
self.assertEqual(inst.num_qubits, len(qr1) + len(qubits) + len(qr2))
|
||||
self.assertEqual(inst.num_clbits, len(cr1) + len(clbits) + len(cr2))
|
||||
inst_definition = inst.definition
|
||||
_, cx_qargs, cx_cargs = inst_definition.data[0]
|
||||
_, measure_qargs, measure_cargs = inst_definition.data[1]
|
||||
self.assertEqual(cx_qargs, [inst_definition.qubits[3], inst_definition.qubits[5]])
|
||||
self.assertEqual(cx_cargs, [])
|
||||
self.assertEqual(measure_qargs, [inst_definition.qubits[4]])
|
||||
self.assertEqual(measure_cargs, [inst_definition.clbits[4]])
|
||||
|
||||
def test_flatten_circuit_overlapping_registers(self):
|
||||
"""Test that the conversion works when the given circuit has bits that are contained in more
|
||||
than one register."""
|
||||
qubits = [Qubit() for _ in [None] * 10]
|
||||
qr1 = QuantumRegister(bits=qubits[:6])
|
||||
qr2 = QuantumRegister(bits=qubits[4:])
|
||||
clbits = [Clbit() for _ in [None] * 10]
|
||||
cr1 = ClassicalRegister(bits=clbits[:6])
|
||||
cr2 = ClassicalRegister(bits=clbits[4:])
|
||||
circ = QuantumCircuit(qubits, clbits, qr1, qr2, cr1, cr2)
|
||||
circ.cx(3, 5)
|
||||
circ.measure(4, 4)
|
||||
|
||||
inst = circuit_to_instruction(circ)
|
||||
self.assertEqual(inst.num_qubits, len(qubits))
|
||||
self.assertEqual(inst.num_clbits, len(clbits))
|
||||
inst_definition = inst.definition
|
||||
_, cx_qargs, cx_cargs = inst_definition.data[0]
|
||||
_, measure_qargs, measure_cargs = inst_definition.data[1]
|
||||
self.assertEqual(cx_qargs, [inst_definition.qubits[3], inst_definition.qubits[5]])
|
||||
self.assertEqual(cx_cargs, [])
|
||||
self.assertEqual(measure_qargs, [inst_definition.qubits[4]])
|
||||
self.assertEqual(measure_cargs, [inst_definition.clbits[4]])
|
||||
|
||||
def test_flatten_parameters(self):
|
||||
"""Verify parameters from circuit are moved to instruction.params"""
|
||||
qr = QuantumRegister(3, "qr")
|
||||
|
|
Loading…
Reference in New Issue