diff --git a/qiskit_experiments/framework/composite/parallel_experiment.py b/qiskit_experiments/framework/composite/parallel_experiment.py index 15805ee828..b3bbaa9877 100644 --- a/qiskit_experiments/framework/composite/parallel_experiment.py +++ b/qiskit_experiments/framework/composite/parallel_experiment.py @@ -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 diff --git a/qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py b/qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py index 2ab3cfb9a3..b8024581da 100644 --- a/qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py +++ b/qiskit_experiments/library/tomography/fitters/cvxpy_lstsq.py @@ -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) diff --git a/qiskit_experiments/library/tomography/fitters/cvxpy_utils.py b/qiskit_experiments/library/tomography/fitters/cvxpy_utils.py index 6415f8db98..030d4e05ee 100644 --- a/qiskit_experiments/library/tomography/fitters/cvxpy_utils.py +++ b/qiskit_experiments/library/tomography/fitters/cvxpy_utils.py @@ -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), ] @@ -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 @@ -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 diff --git a/qiskit_experiments/library/tomography/tomography_experiment.py b/qiskit_experiments/library/tomography/tomography_experiment.py index bced816a49..3af65abe02 100644 --- a/qiskit_experiments/library/tomography/tomography_experiment.py +++ b/qiskit_experiments/library/tomography/tomography_experiment.py @@ -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 @@ -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: @@ -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 diff --git a/releasenotes/notes/qiskit13-deprecations-afece0ceea29f3f7.yaml b/releasenotes/notes/qiskit13-deprecations-afece0ceea29f3f7.yaml new file mode 100644 index 0000000000..d1d142f10c --- /dev/null +++ b/releasenotes/notes/qiskit13-deprecations-afece0ceea29f3f7.yaml @@ -0,0 +1,6 @@ +--- +upgrade: + - | + Minor adjustments were made to Qiskit Experiments internals to avoid + deprecation warnings when using Qiskit 1.3. See `#1482 + _`. diff --git a/test/library/characterization/test_t1.py b/test/library/characterization/test_t1.py index 7f2d46f6ec..f861d4f03d 100644 --- a/test/library/characterization/test_t1.py +++ b/test/library/characterization/test_t1.py @@ -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 @@ -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", ) diff --git a/test/library/tomography/tomo_utils.py b/test/library/tomography/tomo_utils.py index 2a1e75b9ec..bf6210157f 100644 --- a/test/library/tomography/tomo_utils.py +++ b/test/library/tomography/tomo_utils.py @@ -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 @@ -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