mirror of https://github.com/Qiskit/qiskit.git
Add `.clear()` and `.copy_empty_like()` functionality to QuantumCircuit. (#8134)
* Add .copy_empty_like and .clear to QuantumCircuit * Simplify copy_empty_like in QuantumCircuit * Update docstring for copy_empty_like in QuantumCircuit * Deepcopy global_phase for copy_empty_like in QuantumCircuit * Add tests and refactor * Add release note * Add .copy_empty_like and .clear to QuantumCircuit * Simplify copy_empty_like in QuantumCircuit * Update docstring for copy_empty_like in QuantumCircuit * Deepcopy global_phase for copy_empty_like in QuantumCircuit * Add tests and refactor * Add release note * Update docstring Co-authored-by: Julien Gacon <gaconju@gmail.com> * Update docstring Co-authored-by: Julien Gacon <gaconju@gmail.com> * Update docstring Co-authored-by: Julien Gacon <gaconju@gmail.com> * Update test to check metadta and calibrations * Add tests for circuit name * Update releasenotes/notes/clear-circuit-b8edd4126f47d75a.yaml Co-authored-by: Matthew Treinish <mtreinish@kortar.org> Co-authored-by: Julien Gacon <gaconju@gmail.com> Co-authored-by: Matthew Treinish <mtreinish@kortar.org> Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
This commit is contained in:
parent
bcd98951ea
commit
f47cd45e29
|
@ -2118,18 +2118,9 @@ class QuantumCircuit:
|
|||
Returns:
|
||||
QuantumCircuit: a deepcopy of the current circuit, with the specified name
|
||||
"""
|
||||
cpy = copy.copy(self)
|
||||
# copy registers correctly, in copy.copy they are only copied via reference
|
||||
cpy.qregs = self.qregs.copy()
|
||||
cpy.cregs = self.cregs.copy()
|
||||
cpy._qubits = self._qubits.copy()
|
||||
cpy._ancillas = self._ancillas.copy()
|
||||
cpy._clbits = self._clbits.copy()
|
||||
cpy._qubit_indices = self._qubit_indices.copy()
|
||||
cpy._clbit_indices = self._clbit_indices.copy()
|
||||
cpy = self.copy_empty_like(name)
|
||||
|
||||
instr_instances = {id(instr): instr for instr, _, __ in self._data}
|
||||
|
||||
instr_copies = {id_: instr.copy() for id_, instr in instr_instances.items()}
|
||||
|
||||
cpy._parameter_table = ParameterTable(
|
||||
|
@ -2147,6 +2138,35 @@ class QuantumCircuit:
|
|||
for inst, qargs, cargs in self._data
|
||||
]
|
||||
|
||||
return cpy
|
||||
|
||||
def copy_empty_like(self, name: Optional[str] = None) -> "QuantumCircuit":
|
||||
"""Return a copy of self with the same structure but empty.
|
||||
|
||||
That structure includes:
|
||||
* name, calibrations and other metadata
|
||||
* global phase
|
||||
* all the qubits and clbits, including the registers
|
||||
|
||||
Args:
|
||||
name (str): Name for the copied circuit. If None, then the name stays the same.
|
||||
|
||||
Returns:
|
||||
QuantumCircuit: An empty copy of self.
|
||||
"""
|
||||
cpy = copy.copy(self)
|
||||
# copy registers correctly, in copy.copy they are only copied via reference
|
||||
cpy.qregs = self.qregs.copy()
|
||||
cpy.cregs = self.cregs.copy()
|
||||
cpy._qubits = self._qubits.copy()
|
||||
cpy._ancillas = self._ancillas.copy()
|
||||
cpy._clbits = self._clbits.copy()
|
||||
cpy._qubit_indices = self._qubit_indices.copy()
|
||||
cpy._clbit_indices = self._clbit_indices.copy()
|
||||
|
||||
cpy._parameter_table = ParameterTable()
|
||||
cpy._data = []
|
||||
|
||||
cpy._calibrations = copy.deepcopy(self._calibrations)
|
||||
cpy._metadata = copy.deepcopy(self._metadata)
|
||||
|
||||
|
@ -2154,6 +2174,14 @@ class QuantumCircuit:
|
|||
cpy.name = name
|
||||
return cpy
|
||||
|
||||
def clear(self) -> None:
|
||||
"""Clear all instructions in self.
|
||||
|
||||
Clearing the circuits will keep the metadata and calibrations.
|
||||
"""
|
||||
self._data.clear()
|
||||
self._parameter_table.clear()
|
||||
|
||||
def _create_creg(self, length: int, name: str) -> ClassicalRegister:
|
||||
"""Creates a creg, checking if ClassicalRegister with same name exists"""
|
||||
if name in [creg.name for creg in self.cregs]:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
---
|
||||
features:
|
||||
- |
|
||||
Added a new method :py:meth:`.QuantumCircuit.clear` which is used to to erase all instructions
|
||||
from a QuantumCircuit. We clear both the data and the parameter table.
|
||||
- |
|
||||
Added a new method :py:meth:`QuantumCircuit.copy_empty_like` which is used to get a cleared copy of a
|
||||
:class:`~.QuantumCircuit` instnace. This is logically equivalent to `qc.copy().clear()` however, it is done
|
||||
avoiding a deepcopy of the original QuantumCircuit, and therefore it is more efficient. This functionality
|
||||
already implemented for :class:`~.DAGCircuit`, and retains all relevant circuit properties other than the
|
||||
instructions and associated parameters (e.g. registers, bits, name, metadata). Unlike the
|
||||
:meth:`.DAGCircuit.copy_empty_like` method, this new :class:`~.QuantumCircuit` method allows for
|
||||
an optional parameter to update the name of the copied circuit, mimicking ``qc.copy(name)``.
|
|
@ -27,6 +27,7 @@ from qiskit.circuit.quantumregister import AncillaQubit, AncillaRegister, Qubit
|
|||
from qiskit.test import QiskitTestCase
|
||||
from qiskit.circuit.library.standard_gates import SGate
|
||||
from qiskit.quantum_info import Operator
|
||||
from qiskit.pulse import Schedule, Play, Gaussian, DriveChannel
|
||||
|
||||
|
||||
@ddt
|
||||
|
@ -478,6 +479,41 @@ class TestCircuitOperations(QiskitTestCase):
|
|||
self.assertEqual(len(qc.cregs), 1)
|
||||
self.assertEqual(len(copied.cregs), 2)
|
||||
|
||||
def test_copy_empty_like_circuit(self):
|
||||
"""Test copy_empty_like method makes a clear copy."""
|
||||
qr = QuantumRegister(2)
|
||||
cr = ClassicalRegister(2)
|
||||
qc = QuantumCircuit(qr, cr, global_phase=1.0, name="qc", metadata={"key": "value"})
|
||||
qc.h(qr[0])
|
||||
qc.measure(qr[0], cr[0])
|
||||
qc.measure(qr[1], cr[1])
|
||||
sched = Schedule(Play(Gaussian(160, 0.1, 40), DriveChannel(0)))
|
||||
qc.add_calibration("h", [0, 1], sched)
|
||||
copied = qc.copy_empty_like()
|
||||
qc.clear()
|
||||
|
||||
self.assertEqual(qc, copied)
|
||||
self.assertEqual(qc.global_phase, copied.global_phase)
|
||||
self.assertEqual(qc.name, copied.name)
|
||||
self.assertEqual(qc.metadata, copied.metadata)
|
||||
self.assertEqual(qc.calibrations, copied.calibrations)
|
||||
|
||||
copied = qc.copy_empty_like("copy")
|
||||
self.assertEqual(copied.name, "copy")
|
||||
|
||||
def test_clear_circuit(self):
|
||||
"""Test clear method deletes instructions in circuit."""
|
||||
qr = QuantumRegister(2)
|
||||
cr = ClassicalRegister(2)
|
||||
qc = QuantumCircuit(qr, cr)
|
||||
qc.h(qr[0])
|
||||
qc.measure(qr[0], cr[0])
|
||||
qc.measure(qr[1], cr[1])
|
||||
qc.clear()
|
||||
|
||||
self.assertEqual(len(qc.data), 0)
|
||||
self.assertEqual(len(qc._parameter_table), 0)
|
||||
|
||||
def test_measure_active(self):
|
||||
"""Test measure_active
|
||||
Applies measurements only to non-idle qubits. Creates a ClassicalRegister of size equal to
|
||||
|
|
Loading…
Reference in New Issue