Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deprecate circuit.combine and circuit.extend #4208

Merged
merged 50 commits into from
Mar 20, 2021
Merged
Show file tree
Hide file tree
Changes from 45 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
227c6d8
add circuit.compose() method
ajavadia Apr 20, 2020
428b3bd
add inplace arg
ajavadia Apr 21, 2020
40655a8
add tests
ajavadia Apr 21, 2020
84de420
add release note
ajavadia Apr 21, 2020
bd1fc50
missing tests
ajavadia Apr 21, 2020
57a65b6
deprecate circuit.combine() and circuit.extend()
ajavadia Apr 22, 2020
5ad5b7d
fix tests
ajavadia Apr 22, 2020
faad0bb
add release note
ajavadia Apr 22, 2020
f671608
Merge branch 'master' into deprecate-circuit-combine-extend
ajavadia May 1, 2020
70af910
Merge branch 'master' into deprecate-circuit-combine-extend
kdk Jun 30, 2020
ad1f4ae
merge
Jul 12, 2020
2b95850
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 15, 2020
37059d3
unused import
Jul 15, 2020
0b92f7e
Merge branch 'deprecate-circuit-combine-extend' of github.com:ajavadi…
Jul 15, 2020
d42d4e9
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 16, 2020
9a44069
remove repeated method
Jul 16, 2020
a2521ba
inplace
Jul 20, 2020
02a7bd6
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 20, 2020
dd5194d
combine is not inplace
Jul 20, 2020
faade35
Merge branch 'deprecate-circuit-combine-extend' of github.com:ajavadi…
Jul 20, 2020
6a79241
when inplace=True, returns None
Jul 23, 2020
ef99be4
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 23, 2020
dab0e92
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 28, 2020
6ea936a
Merge branch 'master' into deprecate-circuit-combine-extend
Jul 30, 2020
1a96bc0
Update qiskit/circuit/quantumcircuit.py
Aug 4, 2020
eb3fe9b
Update qiskit/circuit/quantumcircuit.py
Aug 4, 2020
8c53b82
Update qiskit/circuit/quantumcircuit.py
Aug 4, 2020
42845b6
Merge branch 'master' of github.com:Qiskit/qiskit-terra into deprecat…
Aug 4, 2020
0df4169
add and iadd
Aug 4, 2020
167febd
Update test/python/circuit/test_circuit_operations.py
Aug 4, 2020
fe1dd45
Update test/python/circuit/test_circuit_operations.py
Aug 4, 2020
5db52f1
reno
Aug 4, 2020
0c447c4
Merge branch 'master' of github.com:Qiskit/qiskit-terra into deprecat…
Aug 11, 2020
7226f51
unused import
Aug 11, 2020
48e8a76
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Aug 21, 2020
541fec9
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Oct 28, 2020
b738d7e
keep extend functionality as before
Cryoris Oct 28, 2020
60ca072
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Nov 4, 2020
58bbbad
update nlocal and deprecate += / + separately
Cryoris Nov 13, 2020
bb1cf0c
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Nov 13, 2020
ff1d038
use deprecate_function
Cryoris Nov 13, 2020
51ded6f
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Feb 17, 2021
4fe23b1
rm deprecated usage in more tests
Cryoris Feb 19, 2021
443c15b
Merge branch 'deprecate-circuit-combine-extend' of github.com:ajavadi…
Cryoris Feb 19, 2021
abc6c6e
rm trailing reno file
Cryoris Feb 19, 2021
d73c504
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Mar 2, 2021
4b40541
rm duplicate import
Cryoris Mar 2, 2021
6408027
Merge branch 'master' into deprecate-circuit-combine-extend
Cryoris Mar 16, 2021
64fb2df
update reno
Cryoris Mar 19, 2021
0545444
Merge branch 'master' into deprecate-circuit-combine-extend
kdk Mar 19, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions qiskit/circuit/library/n_local/n_local.py
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ def add_layer(self,
parametrized_block = self._parametrize_block(block, params=params)
layer.compose(parametrized_block, i)

self += layer
self.compose(layer, inplace=True)
Cryoris marked this conversation as resolved.
Show resolved Hide resolved
else:
# cannot prepend a block currently, just rebuild
self._invalidate()
Expand Down Expand Up @@ -826,7 +826,7 @@ def _build_rotation_layer(self, param_iter, i):
layer.compose(parametrized_block, indices, inplace=True)

# add the layer to the circuit
self += layer
self.compose(layer, inplace=True)

def _build_entanglement_layer(self, param_iter, i):
"""Build an entanglement layer."""
Expand All @@ -842,7 +842,7 @@ def _build_entanglement_layer(self, param_iter, i):
layer.compose(parametrized_block, indices, inplace=True)

# add the layer to the circuit
self += layer
self.compose(layer, inplace=True)

def _build_additional_layers(self, which):
if which == 'appended':
Expand All @@ -861,7 +861,7 @@ def _build_additional_layers(self, which):
for indices in ent:
layer.compose(block, indices, inplace=True)

self += layer
self.compose(layer, inplace=True)

def _build(self) -> None:
"""Build the circuit."""
Expand All @@ -878,7 +878,7 @@ def _build(self) -> None:
# use the initial state circuit if it is not None
if self._initial_state:
circuit = self._initial_state.construct_circuit('circuit', register=self.qregs[0])
self += circuit
self.compose(circuit, inplace=True)

param_iter = iter(self.ordered_parameters)

Expand Down
18 changes: 15 additions & 3 deletions qiskit/circuit/quantumcircuit.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
"""Quantum circuit object."""

import copy
import itertools
import sys
import warnings
import numbers
import multiprocessing as mp
from collections import OrderedDict, defaultdict
from typing import Union
import itertools
import numpy as np
from qiskit.exceptions import QiskitError
from qiskit.utils.multiprocessing import is_main_process
Expand Down Expand Up @@ -521,8 +521,11 @@ def control(self, num_ctrl_qubits=1, label=None, ctrl_state=None):

return controlled_circ

@deprecate_function('The QuantumCircuit.combine() method is being deprecated. '
'Use the compose() method which is more flexible w.r.t '
'circuit register compatibility.')
def combine(self, rhs):
"""Append rhs to self if self contains compatible registers.
"""DEPRECATED - Returns rhs appended to self if self contains compatible registers.

Two circuits are compatible if they contain the same registers
or if they contain different registers with unique names. The
Expand Down Expand Up @@ -559,8 +562,11 @@ def combine(self, rhs):
circuit.global_phase = self.global_phase + rhs.global_phase
return circuit

@deprecate_function('The QuantumCircuit.extend() method is being deprecated. Use the '
'compose() (potentially with the inplace=True argument) and tensor() '
'methods which are more flexible w.r.t circuit register compatibility.')
Cryoris marked this conversation as resolved.
Show resolved Hide resolved
def extend(self, rhs):
"""Append QuantumCircuit to the right hand side if it contains compatible registers.
"""DEPRECATED - Append QuantumCircuit to the RHS if it contains compatible registers.

Two circuits are compatible if they contain the same registers
or if they contain different registers with unique names. The
Expand Down Expand Up @@ -806,10 +812,16 @@ def ancillas(self):
"""
return self._ancillas

@deprecate_function('The QuantumCircuit.__add__() method is being deprecated.'
'Use the compose() method which is more flexible w.r.t '
'circuit register compatibility.')
kdk marked this conversation as resolved.
Show resolved Hide resolved
def __add__(self, rhs):
"""Overload + to implement self.combine."""
return self.combine(rhs)

@deprecate_function('The QuantumCircuit.__iadd__() method is being deprecated. Use the '
'compose() (potentially with the inplace=True argument) and tensor() '
'methods which are more flexible w.r.t circuit register compatibility.')
def __iadd__(self, rhs):
"""Overload += to implement self.extend."""
return self.extend(rhs)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
deprecations:
- |
Two ``QuantumCircuit`` methods ``combine()`` and ``extend()`` are deprecated,
in favor of ``QuantumCircuit.compose()``. The latter allows more flexibility
in composing two circuits that do not have matching registers. It does not,
however, automatically add qubits/clbits unlike the deprecated methods.
kdk marked this conversation as resolved.
Show resolved Hide resolved
4 changes: 2 additions & 2 deletions test/python/basicaer/test_multi_registers_convention.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ def test_circuit_multi(self):
creg0 = ClassicalRegister(2, 'c0')
qreg1 = QuantumRegister(2, 'q1')
creg1 = ClassicalRegister(2, 'c1')
circ = QuantumCircuit(qreg0, qreg1)
circ = QuantumCircuit(qreg0, qreg1, creg0, creg1)
circ.x(qreg0[1])
circ.x(qreg1[0])

meas = QuantumCircuit(qreg0, qreg1, creg0, creg1)
meas.measure(qreg0, creg0)
meas.measure(qreg1, creg1)

qc = circ + meas
qc = circ.compose(meas)

backend_sim = BasicAer.get_backend('qasm_simulator')

Expand Down
8 changes: 4 additions & 4 deletions test/python/circuit/library/test_nlocal.py
Original file line number Diff line number Diff line change
Expand Up @@ -463,11 +463,11 @@ def test_parameters_settable_is_constant(self):
with self.subTest(msg='num_parameters_settable remained constant'):
self.assertEqual(two.num_parameters_settable, len(ordered_params))

def test_iadd_to_circuit(self):
def test_compose_inplace_to_circuit(self):
"""Test adding a two-local to an existing circuit."""
two = TwoLocal(3, ['ry', 'rz'], 'cz', 'full', reps=1, insert_barriers=True)
circuit = QuantumCircuit(3)
circuit += two
circuit.compose(two, inplace=True)

reference = QuantumCircuit(3)
param_iter = iter(two.ordered_parameters)
Expand All @@ -487,11 +487,11 @@ def test_iadd_to_circuit(self):

self.assertCircuitEqual(circuit, reference)

def test_adding_two(self):
def test_composing_two(self):
"""Test adding two two-local circuits."""
entangler_map = [[0, 3], [0, 2]]
two = TwoLocal(4, [], 'cry', entangler_map, reps=1)
circuit = two + two
circuit = two.compose(two)

reference = QuantumCircuit(4)
params = two.ordered_parameters
Expand Down
4 changes: 3 additions & 1 deletion test/python/circuit/test_circuit_multi_registers.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_circuit_multi(self):
creg0 = ClassicalRegister(2, 'c0')
qreg1 = QuantumRegister(2, 'q1')
creg1 = ClassicalRegister(2, 'c1')
circ = QuantumCircuit(qreg0, qreg1)
circ = QuantumCircuit(qreg0, qreg1, creg0, creg1)
circ.x(qreg0[1])
circ.x(qreg1[0])

Expand All @@ -41,6 +41,8 @@ def test_circuit_multi(self):
circ2 = QuantumCircuit()
circ2.add_register(qreg0)
circ2.add_register(qreg1)
circ2.add_register(creg0)
circ2.add_register(creg1)
circ2.x(qreg0[1])
circ2.x(qreg1[0])

Expand Down
54 changes: 34 additions & 20 deletions test/python/circuit/test_circuit_operations.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def test_adding_self(self):
self.assertEqual(['x', 'x'], [x[0].name for x in qc.data])

def test_combine_circuit_common(self):
"""Test combining two circuits with same registers.
"""Test combining two circuits with same registers (inplace=False).
"""
qr = QuantumRegister(2)
cr = ClassicalRegister(2)
Expand All @@ -55,32 +55,39 @@ def test_combine_circuit_common(self):
qc1.h(qr[0])
qc1.measure(qr[0], cr[0])
qc2.measure(qr[1], cr[1])
new_circuit = qc1 + qc2

new_circuit = qc1.combine(qc2)

backend = BasicAer.get_backend('qasm_simulator')
shots = 1024
result = execute(new_circuit, backend=backend, shots=shots, seed_simulator=78).result()
counts = result.get_counts()
target = {'00': shots / 2, '01': shots / 2}
threshold = 0.04 * shots
self.assertDictEqual(qc1.count_ops(), {'h': 1, 'measure': 1}) # no changes "in-place"
self.assertDictEqual(qc2.count_ops(), {'measure': 1}) # no changes "in-place"
self.assertDictAlmostEqual(counts, target, threshold)

def test_combine_circuit_different(self):
"""Test combining two circuits with different registers.
def test_combine_circuit_common_plus(self):
"""Test combining two circuits with same registers (as plus).
"""
qr = QuantumRegister(2)
cr = ClassicalRegister(2)
qc1 = QuantumCircuit(qr)
qc1.x(qr)
qc1 = QuantumCircuit(qr, cr)
kdk marked this conversation as resolved.
Show resolved Hide resolved
qc2 = QuantumCircuit(qr, cr)
qc2.measure(qr, cr)
qc1.h(qr[0])
qc1.measure(qr[0], cr[0])
qc2.measure(qr[1], cr[1])
new_circuit = qc1 + qc2
backend = BasicAer.get_backend('qasm_simulator')
shots = 1024
result = execute(new_circuit, backend=backend, shots=shots,
seed_simulator=78).result()
result = execute(new_circuit, backend=backend, shots=shots, seed_simulator=78).result()
counts = result.get_counts()
target = {'11': shots}
self.assertEqual(counts, target)
target = {'00': shots / 2, '01': shots / 2}
threshold = 0.04 * shots
self.assertDictEqual(qc1.count_ops(), {'h': 1, 'measure': 1}) # no changes "in-place"
self.assertDictEqual(qc2.count_ops(), {'measure': 1}) # no changes "in-place"
self.assertDictAlmostEqual(counts, target, threshold)

def test_combine_circuit_fail(self):
"""Test combining two circuits fails if registers incompatible.
Expand All @@ -99,7 +106,7 @@ def test_combine_circuit_fail(self):
self.assertRaises(CircuitError, qc1.__add__, qcr3)

def test_extend_circuit(self):
"""Test extending a circuit with same registers.
"""Test extending a circuit with same registers (in place add).
"""
qr = QuantumRegister(2)
cr = ClassicalRegister(2)
Expand All @@ -108,33 +115,40 @@ def test_extend_circuit(self):
qc1.h(qr[0])
qc1.measure(qr[0], cr[0])
qc2.measure(qr[1], cr[1])
qc1 += qc2

qc1.extend(qc2)
backend = BasicAer.get_backend('qasm_simulator')
shots = 1024
result = execute(qc1, backend=backend, shots=shots,
seed_simulator=78).result()
counts = result.get_counts()
target = {'00': shots / 2, '01': shots / 2}
threshold = 0.04 * shots
self.assertDictEqual(qc1.count_ops(), {'h': 1, 'measure': 2}) # changes "in-place"
self.assertDictEqual(qc2.count_ops(), {'measure': 1}) # no changes "in-place"
self.assertDictAlmostEqual(counts, target, threshold)

def test_extend_circuit_different_registers(self):
"""Test extending a circuit with different registers.
def test_extend_circuit_iadd(self):
"""Test extending a circuit with same registers (in place add).
"""
qr = QuantumRegister(2)
cr = ClassicalRegister(2)
qc1 = QuantumCircuit(qr)
qc1.x(qr)
qc1 = QuantumCircuit(qr, cr)
qc2 = QuantumCircuit(qr, cr)
qc2.measure(qr, cr)
qc1.h(qr[0])
qc1.measure(qr[0], cr[0])
qc2.measure(qr[1], cr[1])
qc1 += qc2
backend = BasicAer.get_backend('qasm_simulator')
shots = 1024
result = execute(qc1, backend=backend, shots=shots,
seed_simulator=78).result()
counts = result.get_counts()
target = {'11': shots}
self.assertEqual(counts, target)
target = {'00': shots / 2, '01': shots / 2}
threshold = 0.04 * shots
self.assertDictEqual(qc1.count_ops(), {'h': 1, 'measure': 2}) # changes "in-place"
self.assertDictEqual(qc2.count_ops(), {'measure': 1}) # no changes "in-place"
self.assertDictAlmostEqual(counts, target, threshold)

def test_extend_circuit_fail(self):
"""Test extending a circuit fails if registers incompatible.
Expand Down
4 changes: 2 additions & 2 deletions test/python/circuit/test_parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,7 +473,7 @@ def test_circuit_composition(self):
theta = Parameter('θ')
qr = QuantumRegister(1)
cr = ClassicalRegister(1)
qc1 = QuantumCircuit(qr)
qc1 = QuantumCircuit(qr, cr)
qc1.rx(theta, qr)

phi = Parameter('phi')
Expand Down Expand Up @@ -623,7 +623,7 @@ def test_binding_parameterized_circuits_built_in_multiproc(self):
num_processes=num_processes)

for qc in results:
circuit += qc
circuit.compose(qc, inplace=True)

parameter_values = [{x: 1 for x in parameters}]

Expand Down