Skip to content

Commit da8e0f7

Browse files
Address c_if, Permutation, and transpile parameter deprecations in Qiskit 1.3 (backport #1482) (#1485)
* `Permutation` instances in tomography experiments have been replaced with `PermutationGate` instances that work the same way for those experiments. The only user facing change should be the avoidance of deprecation warnings in Qiskit 1.3. * `c_if` usage on conditional gates in some tests has been replaced with `if_test` blocks around those gates. * `ParallelExperiment` now considers a `target` transpiler option when determining how large a circuit to make when combining subexperiments into a larger circuit. Previously it considered the number of qubits in a `coupling_map` transpiler option or in the experiment's backend. * Use of `instruction_durations` as a transpile option was replaced with `target` in one test (`instruction_durations` was deprecated as a transpiler parameter). * Add explicit `order="F"` argument to `cvxpy.vec()` calls. This function started issuing a `FutureWarning` in the latest version of cvxpy about the default order changing from F to C. <hr>This is an automatic backport of pull request #1482 done by [Mergify](https://mergify.com). Co-authored-by: Will Shanks <willshanks@us.ibm.com>
1 parent ff52d76 commit da8e0f7

File tree

7 files changed

+63
-30
lines changed

7 files changed

+63
-30
lines changed

qiskit_experiments/framework/composite/parallel_experiment.py

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,14 +89,23 @@ def _combined_circuits(self, device_layout: bool) -> List[QuantumCircuit]:
8989
# Num qubits will be computed from sub experiments
9090
num_qubits = len(self.physical_qubits)
9191
else:
92-
# Work around for backend coupling map circuit inflation
92+
# Expand the number of qubits similar to how qiskit.transpile does
93+
# Here we progress from most to least specific way of specifying
94+
# the number of qubits: coupling_map->target->backend
95+
#
96+
# TODO: Behave more like a layout transpiler pass and set the
97+
# _layout property on the circuits. Doing this requires accessing
98+
# private attributes of Qiskit or possibly running a layout pass of
99+
# the transpiler if that can be done without too much overhead.
100+
num_qubits = 1 + max(self.physical_qubits)
93101
coupling_map = getattr(self.transpile_options, "coupling_map", None)
94-
if coupling_map is None and self.backend:
95-
coupling_map = self._backend_data.coupling_map
102+
target = getattr(self.transpile_options, "target", None)
96103
if coupling_map is not None:
97-
num_qubits = 1 + max(*self.physical_qubits, np.max(coupling_map))
98-
else:
99-
num_qubits = 1 + max(self.physical_qubits)
104+
num_qubits = max(num_qubits, 1 + np.max(coupling_map))
105+
elif target is not None:
106+
num_qubits = max(num_qubits, target.num_qubits)
107+
elif self.backend:
108+
num_qubits = max(num_qubits, self._backend_data.num_qubits)
100109

101110
joint_circuits = []
102111
sub_qubits = 0

qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,8 +300,8 @@ def cvxpy_linear_lstsq(
300300
idx = 0
301301
for i in range(num_circ_components):
302302
for j in range(num_tomo_components):
303-
model = bms_r[idx] @ cvxpy.vec(rhos_r[idx]) - bms_i[idx] @ cvxpy.vec(
304-
rhos_i[idx]
303+
model = bms_r[idx] @ cvxpy.vec(rhos_r[idx], order="F") - bms_i[idx] @ cvxpy.vec(
304+
rhos_i[idx], order="F"
305305
)
306306
data = probability_data[i, j]
307307
args.append(model - data)

qiskit_experiments/library/tomography/fitters/cvxpy_utils.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,8 +234,8 @@ def partial_trace_constaint(
234234
ptr = partial_trace_super(input_dim, output_dim)
235235
vec_cons = np.ravel(constraint, order="F")
236236
return [
237-
ptr @ cvxpy.vec(mat_r) == vec_cons.real.round(12),
238-
ptr @ cvxpy.vec(mat_i) == vec_cons.imag.round(12),
237+
ptr @ cvxpy.vec(mat_r, order="F") == vec_cons.real.round(12),
238+
ptr @ cvxpy.vec(mat_i, order="F") == vec_cons.imag.round(12),
239239
]
240240

241241

@@ -274,7 +274,7 @@ def trace_preserving_constaint(
274274
output_dim = sdim // input_dim
275275

276276
ptr = partial_trace_super(input_dim, output_dim)
277-
cons = [ptr @ cvxpy.vec(arg_r) == np.identity(input_dim).ravel()]
277+
cons = [ptr @ cvxpy.vec(arg_r, order="F") == np.identity(input_dim).ravel()]
278278

279279
if hermitian:
280280
return cons
@@ -286,7 +286,7 @@ def trace_preserving_constaint(
286286
arg_i = mat_i
287287
else:
288288
raise TypeError("Input must be a cvxpy variable or list of variables")
289-
cons.append(ptr @ cvxpy.vec(arg_i) == np.zeros(input_dim**2))
289+
cons.append(ptr @ cvxpy.vec(arg_i, order="F") == np.zeros(input_dim**2))
290290
return cons
291291

292292

qiskit_experiments/library/tomography/tomography_experiment.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from typing import Union, Optional, Iterable, List, Tuple, Sequence
1717
from itertools import product
1818
from qiskit.circuit import QuantumCircuit, Instruction, ClassicalRegister, Clbit
19-
from qiskit.circuit.library import Permutation
19+
from qiskit.circuit.library import PermutationGate
2020
from qiskit.providers.backend import Backend
2121
from qiskit.quantum_info.operators.base_operator import BaseOperator
2222

@@ -278,7 +278,7 @@ def _permute_circuit(self) -> QuantumCircuit:
278278
prep_qargs = list(self._prep_indices)
279279
if len(self._prep_indices) != total_qubits:
280280
prep_qargs += [i for i in range(total_qubits) if i not in self._prep_indices]
281-
perm_circ.append(Permutation(total_qubits, prep_qargs).inverse(), range(total_qubits))
281+
perm_circ.append(PermutationGate(prep_qargs).inverse(), range(total_qubits))
282282

283283
# Apply original circuit
284284
if total_clbits:
@@ -291,6 +291,6 @@ def _permute_circuit(self) -> QuantumCircuit:
291291
meas_qargs = list(self._meas_indices)
292292
if len(self._meas_indices) != total_qubits:
293293
meas_qargs += [i for i in range(total_qubits) if i not in self._meas_indices]
294-
perm_circ.append(Permutation(total_qubits, meas_qargs), range(total_qubits))
294+
perm_circ.append(PermutationGate(meas_qargs), range(total_qubits))
295295

296296
return perm_circ
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
upgrade:
3+
- |
4+
Minor adjustments were made to Qiskit Experiments internals to avoid
5+
deprecation warnings when using Qiskit 1.3. See `#1482
6+
<https://github.com/qiskit-community/qiskit-experiments/pull/1482>_`.

test/library/characterization/test_t1.py

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515

1616
from test.base import QiskitExperimentsTestCase
1717
import numpy as np
18+
from qiskit.circuit import Delay, Parameter
19+
from qiskit.circuit.library import CXGate, Measure, RXGate
1820
from qiskit.qobj.utils import MeasLevel
21+
from qiskit.transpiler import InstructionProperties, Target
1922
from qiskit_ibm_runtime.fake_provider import FakeAthensV2
2023
from qiskit_experiments.test.noisy_delay_aer_simulator import NoisyDelayAerBackend
2124
from qiskit_experiments.framework import ExperimentData, ParallelExperiment
@@ -249,22 +252,33 @@ def test_t1_low_quality(self):
249252
def test_t1_parallel_exp_transpile(self):
250253
"""Test parallel transpile options for T1 experiment"""
251254
num_qubits = 5
252-
instruction_durations = []
253-
for i in range(num_qubits):
254-
instruction_durations += [
255-
("rx", [i], (i + 1) * 10, "ns"),
256-
("measure", [i], (i + 1) * 1000, "ns"),
257-
]
258-
coupling_map = [[i - 1, i] for i in range(1, num_qubits)]
259-
basis_gates = ["rx", "delay"]
255+
target = Target(num_qubits=num_qubits)
256+
target.add_instruction(
257+
RXGate(Parameter("t")),
258+
properties={
259+
(i,): InstructionProperties(duration=(i + 1) * 10e-9) for i in range(num_qubits)
260+
},
261+
)
262+
target.add_instruction(
263+
Measure(),
264+
properties={
265+
(i,): InstructionProperties(duration=(i + 1) * 1e-6) for i in range(num_qubits)
266+
},
267+
)
268+
target.add_instruction(
269+
Delay(Parameter("t")),
270+
properties={(i,): None for i in range(num_qubits)},
271+
)
272+
target.add_instruction(
273+
CXGate(),
274+
properties={(i - 1, i): None for i in range(1, num_qubits)},
275+
)
260276

261277
exp1 = T1([1], delays=[50e-9, 100e-9, 160e-9])
262278
exp2 = T1([3], delays=[40e-9, 80e-9, 190e-9])
263279
parexp = ParallelExperiment([exp1, exp2], flatten_results=False)
264280
parexp.set_transpile_options(
265-
basis_gates=basis_gates,
266-
instruction_durations=instruction_durations,
267-
coupling_map=coupling_map,
281+
target=target,
268282
scheduling_method="alap",
269283
)
270284

test/library/tomography/tomo_utils.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ def teleport_circuit(flatten_creg=True):
5252
teleport.measure(0, creg[0])
5353
teleport.measure(1, creg[1])
5454
# Conditionals
55-
teleport.z(2).c_if(creg[0], 1)
56-
teleport.x(2).c_if(creg[1], 1)
55+
with teleport.if_test((creg[0], True)):
56+
teleport.z(2)
57+
with teleport.if_test((creg[1], True)):
58+
teleport.x(2)
5759
return teleport
5860

5961

@@ -76,8 +78,10 @@ def teleport_bell_circuit(flatten_creg=True):
7678
teleport.h(0)
7779
teleport.measure(0, creg[0])
7880
teleport.measure(1, creg[1])
79-
teleport.z(2).c_if(creg[0], 1)
80-
teleport.x(2).c_if(creg[1], 1)
81+
with teleport.if_test((creg[0], True)):
82+
teleport.z(2)
83+
with teleport.if_test((creg[1], True)):
84+
teleport.x(2)
8185
return teleport
8286

8387

0 commit comments

Comments
 (0)