Skip to content

Commit

Permalink
Address c_if, Permutation, and transpile parameter deprecations…
Browse files Browse the repository at this point in the history
… in Qiskit 1.3 (#1482)

* `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.
  • Loading branch information
wshanks authored Nov 14, 2024
1 parent 05d7487 commit 3906340
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 30 deletions.
21 changes: 15 additions & 6 deletions qiskit_experiments/framework/composite/parallel_experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,14 +89,23 @@ def _combined_circuits(self, device_layout: bool) -> List[QuantumCircuit]:
# Num qubits will be computed from sub experiments
num_qubits = len(self.physical_qubits)
else:
# Work around for backend coupling map circuit inflation
# Expand the number of qubits similar to how qiskit.transpile does
# Here we progress from most to least specific way of specifying
# the number of qubits: coupling_map->target->backend
#
# TODO: Behave more like a layout transpiler pass and set the
# _layout property on the circuits. Doing this requires accessing
# private attributes of Qiskit or possibly running a layout pass of
# the transpiler if that can be done without too much overhead.
num_qubits = 1 + max(self.physical_qubits)
coupling_map = getattr(self.transpile_options, "coupling_map", None)
if coupling_map is None and self.backend:
coupling_map = self._backend_data.coupling_map
target = getattr(self.transpile_options, "target", None)
if coupling_map is not None:
num_qubits = 1 + max(*self.physical_qubits, np.max(coupling_map))
else:
num_qubits = 1 + max(self.physical_qubits)
num_qubits = max(num_qubits, 1 + np.max(coupling_map))
elif target is not None:
num_qubits = max(num_qubits, target.num_qubits)
elif self.backend:
num_qubits = max(num_qubits, self._backend_data.num_qubits)

joint_circuits = []
sub_qubits = 0
Expand Down
4 changes: 2 additions & 2 deletions qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py
Original file line number Diff line number Diff line change
Expand Up @@ -300,8 +300,8 @@ def cvxpy_linear_lstsq(
idx = 0
for i in range(num_circ_components):
for j in range(num_tomo_components):
model = bms_r[idx] @ cvxpy.vec(rhos_r[idx]) - bms_i[idx] @ cvxpy.vec(
rhos_i[idx]
model = bms_r[idx] @ cvxpy.vec(rhos_r[idx], order="F") - bms_i[idx] @ cvxpy.vec(
rhos_i[idx], order="F"
)
data = probability_data[i, j]
args.append(model - data)
Expand Down
8 changes: 4 additions & 4 deletions qiskit_experiments/library/tomography/fitters/cvxpy_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,8 +234,8 @@ def partial_trace_constaint(
ptr = partial_trace_super(input_dim, output_dim)
vec_cons = np.ravel(constraint, order="F")
return [
ptr @ cvxpy.vec(mat_r) == vec_cons.real.round(12),
ptr @ cvxpy.vec(mat_i) == vec_cons.imag.round(12),
ptr @ cvxpy.vec(mat_r, order="F") == vec_cons.real.round(12),
ptr @ cvxpy.vec(mat_i, order="F") == vec_cons.imag.round(12),
]


Expand Down Expand Up @@ -274,7 +274,7 @@ def trace_preserving_constaint(
output_dim = sdim // input_dim

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

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


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from typing import Union, Optional, Iterable, List, Tuple, Sequence
from itertools import product
from qiskit.circuit import QuantumCircuit, Instruction, ClassicalRegister, Clbit
from qiskit.circuit.library import Permutation
from qiskit.circuit.library import PermutationGate
from qiskit.providers.backend import Backend
from qiskit.quantum_info.operators.base_operator import BaseOperator

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

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

return perm_circ
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
upgrade:
- |
Minor adjustments were made to Qiskit Experiments internals to avoid
deprecation warnings when using Qiskit 1.3. See `#1482
<https://github.com/qiskit-community/qiskit-experiments/pull/1482>_`.
36 changes: 25 additions & 11 deletions test/library/characterization/test_t1.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@

from test.base import QiskitExperimentsTestCase
import numpy as np
from qiskit.circuit import Delay, Parameter
from qiskit.circuit.library import CXGate, Measure, RXGate
from qiskit.qobj.utils import MeasLevel
from qiskit.transpiler import InstructionProperties, Target
from qiskit_ibm_runtime.fake_provider import FakeAthensV2
from qiskit_experiments.test.noisy_delay_aer_simulator import NoisyDelayAerBackend
from qiskit_experiments.framework import ExperimentData, ParallelExperiment
Expand Down Expand Up @@ -249,22 +252,33 @@ def test_t1_low_quality(self):
def test_t1_parallel_exp_transpile(self):
"""Test parallel transpile options for T1 experiment"""
num_qubits = 5
instruction_durations = []
for i in range(num_qubits):
instruction_durations += [
("rx", [i], (i + 1) * 10, "ns"),
("measure", [i], (i + 1) * 1000, "ns"),
]
coupling_map = [[i - 1, i] for i in range(1, num_qubits)]
basis_gates = ["rx", "delay"]
target = Target(num_qubits=num_qubits)
target.add_instruction(
RXGate(Parameter("t")),
properties={
(i,): InstructionProperties(duration=(i + 1) * 10e-9) for i in range(num_qubits)
},
)
target.add_instruction(
Measure(),
properties={
(i,): InstructionProperties(duration=(i + 1) * 1e-6) for i in range(num_qubits)
},
)
target.add_instruction(
Delay(Parameter("t")),
properties={(i,): None for i in range(num_qubits)},
)
target.add_instruction(
CXGate(),
properties={(i - 1, i): None for i in range(1, num_qubits)},
)

exp1 = T1([1], delays=[50e-9, 100e-9, 160e-9])
exp2 = T1([3], delays=[40e-9, 80e-9, 190e-9])
parexp = ParallelExperiment([exp1, exp2], flatten_results=False)
parexp.set_transpile_options(
basis_gates=basis_gates,
instruction_durations=instruction_durations,
coupling_map=coupling_map,
target=target,
scheduling_method="alap",
)

Expand Down
12 changes: 8 additions & 4 deletions test/library/tomography/tomo_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,10 @@ def teleport_circuit(flatten_creg=True):
teleport.measure(0, creg[0])
teleport.measure(1, creg[1])
# Conditionals
teleport.z(2).c_if(creg[0], 1)
teleport.x(2).c_if(creg[1], 1)
with teleport.if_test((creg[0], True)):
teleport.z(2)
with teleport.if_test((creg[1], True)):
teleport.x(2)
return teleport


Expand All @@ -76,8 +78,10 @@ def teleport_bell_circuit(flatten_creg=True):
teleport.h(0)
teleport.measure(0, creg[0])
teleport.measure(1, creg[1])
teleport.z(2).c_if(creg[0], 1)
teleport.x(2).c_if(creg[1], 1)
with teleport.if_test((creg[0], True)):
teleport.z(2)
with teleport.if_test((creg[1], True)):
teleport.x(2)
return teleport


Expand Down

0 comments on commit 3906340

Please sign in to comment.