qiskit 1.1.0__cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl → 1.1.1__cp38-abi3-manylinux_2_17_i686.manylinux2014_i686.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
qiskit/VERSION.txt CHANGED
@@ -1 +1 @@
1
- 1.1.0
1
+ 1.1.1
Binary file
@@ -816,10 +816,11 @@ method <https://numpy.org/devdocs/user/basics.interoperability.html#the-array-me
816
816
  ``__array__``. This is used by :meth:`Gate.to_matrix`, and has the signature:
817
817
 
818
818
  .. currentmodule:: None
819
- .. py:method:: __array__(dtype=None, copy=None)
819
+ .. py:method:: object.__array__(dtype=None, copy=None)
820
820
 
821
- Return a Numpy array representing the gate. This can use the gate's :attr:`~Instruction.params`
822
- field, and may assume that these are numeric values (assuming the subclass expects that) and not
821
+ Return a Numpy array representing the gate. This can use the gate's
822
+ :attr:`~qiskit.circuit.Instruction.params` field, and may assume that these are numeric
823
+ values (assuming the subclass expects that) and not
823
824
  :ref:`compile-time parameters <circuit-compile-time-parameters>`.
824
825
 
825
826
  For greatest efficiency, the returned array should default to a dtype of :class:`complex`.
@@ -97,7 +97,7 @@ class PauliFeatureMap(NLocal):
97
97
  >>> from qiskit.circuit.library import EfficientSU2
98
98
  >>> prep = PauliFeatureMap(3, reps=3, paulis=['Z', 'YY', 'ZXZ'])
99
99
  >>> wavefunction = EfficientSU2(3)
100
- >>> classifier = prep.compose(wavefunction
100
+ >>> classifier = prep.compose(wavefunction)
101
101
  >>> classifier.num_parameters
102
102
  27
103
103
  >>> classifier.count_ops()
@@ -110,7 +110,7 @@ class TwoLocal(NLocal):
110
110
 
111
111
  >>> entangler_map = [[0, 3], [0, 2]] # entangle the first and last two-way
112
112
  >>> two = TwoLocal(4, [], 'cry', entangler_map, reps=1)
113
- >>> circuit = two + two
113
+ >>> circuit = two.compose(two)
114
114
  >>> print(circuit.decompose().draw()) # note, that the parameters are the same!
115
115
  q_0: ─────■───────────■───────────■───────────■──────
116
116
  │ │ │ │
@@ -439,6 +439,9 @@ class ParameterExpression:
439
439
  raise TypeError("could not cast expression to int") from exc
440
440
 
441
441
  def __hash__(self):
442
+ if not self._parameter_symbols:
443
+ # For fully bound expressions, fall back to the underlying value
444
+ return hash(self.numeric())
442
445
  return hash((self._parameter_keys, self._symbol_expr))
443
446
 
444
447
  def __copy__(self):
@@ -50,11 +50,10 @@ class ParameterVectorElement(Parameter):
50
50
  class ParameterVector:
51
51
  """ParameterVector class to quickly generate lists of parameters."""
52
52
 
53
- __slots__ = ("_name", "_params", "_size", "_root_uuid")
53
+ __slots__ = ("_name", "_params", "_root_uuid")
54
54
 
55
55
  def __init__(self, name, length=0):
56
56
  self._name = name
57
- self._size = length
58
57
  self._root_uuid = uuid4()
59
58
  root_uuid_int = self._root_uuid.int
60
59
  self._params = [
@@ -76,32 +75,38 @@ class ParameterVector:
76
75
  return self._params.index(value)
77
76
 
78
77
  def __getitem__(self, key):
79
- if isinstance(key, slice):
80
- start, stop, step = key.indices(self._size)
81
- return self.params[start:stop:step]
82
-
83
- if key > self._size:
84
- raise IndexError(f"Index out of range: {key} > {self._size}")
85
78
  return self.params[key]
86
79
 
87
80
  def __iter__(self):
88
- return iter(self.params[: self._size])
81
+ return iter(self.params)
89
82
 
90
83
  def __len__(self):
91
- return self._size
84
+ return len(self._params)
92
85
 
93
86
  def __str__(self):
94
- return f"{self.name}, {[str(item) for item in self.params[: self._size]]}"
87
+ return f"{self.name}, {[str(item) for item in self.params]}"
95
88
 
96
89
  def __repr__(self):
97
90
  return f"{self.__class__.__name__}(name={self.name}, length={len(self)})"
98
91
 
99
92
  def resize(self, length):
100
- """Resize the parameter vector.
101
-
102
- If necessary, new elements are generated. If length is smaller than before, the
103
- previous elements are cached and not re-generated if the vector is enlarged again.
93
+ """Resize the parameter vector. If necessary, new elements are generated.
94
+
95
+ Note that the UUID of each :class:`.Parameter` element will be generated
96
+ deterministically given the root UUID of the ``ParameterVector`` and the index
97
+ of the element. In particular, if a ``ParameterVector`` is resized to
98
+ be smaller and then later resized to be larger, the UUID of the later
99
+ generated element at a given index will be the same as the UUID of the
100
+ previous element at that index.
104
101
  This is to ensure that the parameter instances do not change.
102
+
103
+ >>> from qiskit.circuit import ParameterVector
104
+ >>> pv = ParameterVector("theta", 20)
105
+ >>> elt_19 = pv[19]
106
+ >>> rv.resize(10)
107
+ >>> rv.resize(20)
108
+ >>> pv[19] == elt_19
109
+ True
105
110
  """
106
111
  if length > len(self._params):
107
112
  root_uuid_int = self._root_uuid.int
@@ -111,4 +116,5 @@ class ParameterVector:
111
116
  for i in range(len(self._params), length)
112
117
  ]
113
118
  )
114
- self._size = length
119
+ else:
120
+ del self._params[length:]
@@ -45,7 +45,7 @@ from qiskit.circuit.parameter import Parameter
45
45
  from qiskit.circuit.exceptions import CircuitError
46
46
  from . import _classical_resource_map
47
47
  from ._utils import sort_parameters
48
- from .controlflow import ControlFlowOp
48
+ from .controlflow import ControlFlowOp, _builder_utils
49
49
  from .controlflow.builder import CircuitScopeInterface, ControlFlowBuilderBlock
50
50
  from .controlflow.break_loop import BreakLoopOp, BreakLoopPlaceholder
51
51
  from .controlflow.continue_loop import ContinueLoopOp, ContinueLoopPlaceholder
@@ -3307,6 +3307,9 @@ class QuantumCircuit:
3307
3307
  ) -> int:
3308
3308
  """Return circuit depth (i.e., length of critical path).
3309
3309
 
3310
+ .. warning::
3311
+ This operation is not well defined if the circuit contains control-flow operations.
3312
+
3310
3313
  Args:
3311
3314
  filter_function: A function to decide which instructions count to increase depth.
3312
3315
  Should take as a single positional input a :class:`CircuitInstruction`.
@@ -3332,59 +3335,40 @@ class QuantumCircuit:
3332
3335
 
3333
3336
  assert qc.depth(lambda instr: len(instr.qubits) > 1) == 1
3334
3337
  """
3335
- # Assign each bit in the circuit a unique integer
3336
- # to index into op_stack.
3337
- bit_indices: dict[Qubit | Clbit, int] = {
3338
- bit: idx for idx, bit in enumerate(self.qubits + self.clbits)
3338
+ obj_depths = {
3339
+ obj: 0 for objects in (self.qubits, self.clbits, self.iter_vars()) for obj in objects
3339
3340
  }
3340
3341
 
3341
- # If no bits, return 0
3342
- if not bit_indices:
3343
- return 0
3342
+ def update_from_expr(objects, node):
3343
+ for var in expr.iter_vars(node):
3344
+ if var.standalone:
3345
+ objects.add(var)
3346
+ else:
3347
+ objects.update(_builder_utils.node_resources(var).clbits)
3344
3348
 
3345
- # A list that holds the height of each qubit
3346
- # and classical bit.
3347
- op_stack = [0] * len(bit_indices)
3348
-
3349
- # Here we are playing a modified version of
3350
- # Tetris where we stack gates, but multi-qubit
3351
- # gates, or measurements have a block for each
3352
- # qubit or cbit that are connected by a virtual
3353
- # line so that they all stacked at the same depth.
3354
- # Conditional gates act on all cbits in the register
3355
- # they are conditioned on.
3356
- # The max stack height is the circuit depth.
3357
3349
  for instruction in self._data:
3358
- levels = []
3359
- reg_ints = []
3360
- for ind, reg in enumerate(instruction.qubits + instruction.clbits):
3361
- # Add to the stacks of the qubits and
3362
- # cbits used in the gate.
3363
- reg_ints.append(bit_indices[reg])
3364
- if filter_function(instruction):
3365
- levels.append(op_stack[reg_ints[ind]] + 1)
3366
- else:
3367
- levels.append(op_stack[reg_ints[ind]])
3368
- # Assuming here that there is no conditional
3369
- # snapshots or barriers ever.
3370
- if getattr(instruction.operation, "condition", None):
3371
- # Controls operate over all bits of a classical register
3372
- # or over a single bit
3373
- if isinstance(instruction.operation.condition[0], Clbit):
3374
- condition_bits = [instruction.operation.condition[0]]
3350
+ objects = set(itertools.chain(instruction.qubits, instruction.clbits))
3351
+ if (condition := getattr(instruction.operation, "condition", None)) is not None:
3352
+ objects.update(_builder_utils.condition_resources(condition).clbits)
3353
+ if isinstance(condition, expr.Expr):
3354
+ update_from_expr(objects, condition)
3375
3355
  else:
3376
- condition_bits = instruction.operation.condition[0]
3377
- for cbit in condition_bits:
3378
- idx = bit_indices[cbit]
3379
- if idx not in reg_ints:
3380
- reg_ints.append(idx)
3381
- levels.append(op_stack[idx] + 1)
3382
-
3383
- max_level = max(levels)
3384
- for ind in reg_ints:
3385
- op_stack[ind] = max_level
3386
-
3387
- return max(op_stack)
3356
+ objects.update(_builder_utils.condition_resources(condition).clbits)
3357
+ elif isinstance(instruction.operation, SwitchCaseOp):
3358
+ update_from_expr(objects, expr.lift(instruction.operation.target))
3359
+ elif isinstance(instruction.operation, Store):
3360
+ update_from_expr(objects, instruction.operation.lvalue)
3361
+ update_from_expr(objects, instruction.operation.rvalue)
3362
+
3363
+ # If we're counting this as adding to depth, do so. If not, it still functions as a
3364
+ # data synchronisation point between the objects (think "barrier"), so the depths still
3365
+ # get updated to match the current max over the affected objects.
3366
+ new_depth = max((obj_depths[obj] for obj in objects), default=0)
3367
+ if filter_function(instruction):
3368
+ new_depth += 1
3369
+ for obj in objects:
3370
+ obj_depths[obj] = new_depth
3371
+ return max(obj_depths.values(), default=0)
3388
3372
 
3389
3373
  def width(self) -> int:
3390
3374
  """Return number of qubits plus clbits in circuit.
@@ -544,7 +544,7 @@ class DAGCircuit:
544
544
 
545
545
  def remove_qregs(self, *qregs):
546
546
  """
547
- Remove classical registers from the circuit, leaving underlying bits
547
+ Remove quantum registers from the circuit, leaving underlying bits
548
548
  in place.
549
549
 
550
550
  Raises:
@@ -153,12 +153,12 @@ Here is an example of how a sampler is used.
153
153
  # collect 128 shots from the Bell circuit
154
154
  job = sampler.run([bell], shots=128)
155
155
  job_result = job.result()
156
- print(f"The primitive-job finished with result {job_result}"))
156
+ print(f"The primitive-job finished with result {job_result}")
157
157
 
158
158
  # run a sampler job on the parameterized circuits
159
- job2 = sampler.run([(pqc, theta1), (pqc2, theta2)]
159
+ job2 = sampler.run([(pqc, theta1), (pqc2, theta2)])
160
160
  job_result = job2.result()
161
- print(f"The primitive-job finished with result {job_result}"))
161
+ print(f"The primitive-job finished with result {job_result}")
162
162
 
163
163
 
164
164
  Overview of EstimatorV1
@@ -214,7 +214,7 @@ Here is an example of how the estimator is used.
214
214
  # calculate [ <psi1(theta1)|H1|psi1(theta1)> ]
215
215
  job = estimator.run([psi1], [H1], [theta1])
216
216
  job_result = job.result() # It will block until the job finishes.
217
- print(f"The primitive-job finished with result {job_result}"))
217
+ print(f"The primitive-job finished with result {job_result}")
218
218
 
219
219
  # calculate [ <psi1(theta1)|H1|psi1(theta1)>,
220
220
  # <psi2(theta2)|H2|psi2(theta2)>,
@@ -88,12 +88,6 @@ class BackendV1(Backend, ABC):
88
88
  This next bit is necessary just because autosummary generally won't summarise private
89
89
  methods; changing that behaviour would have annoying knock-on effects through all the
90
90
  rest of the documentation, so instead we just hard-code the automethod directive.
91
-
92
- In addition to the public abstract methods, subclasses should also implement the following
93
- private methods:
94
-
95
- .. automethod:: _default_options
96
- :noindex:
97
91
  """
98
92
  self._configuration = configuration
99
93
  self._options = self._default_options()
qiskit/pulse/builder.py CHANGED
@@ -74,8 +74,8 @@ a pulse:
74
74
 
75
75
  The builder initializes a :class:`.pulse.Schedule`, ``pulse_prog``
76
76
  and then begins to construct the program within the context. The output pulse
77
- schedule will survive after the context is exited and can be transpiled and executed like a
78
- normal Qiskit schedule using ``backend.run(transpile(pulse_prog, backend))``.
77
+ schedule will survive after the context is exited and can be used like a
78
+ normal Qiskit schedule.
79
79
 
80
80
  Pulse programming has a simple imperative style. This leaves the programmer
81
81
  to worry about the raw experimental physics of pulse programming and not
qiskit/qasm2/parse.py CHANGED
@@ -16,6 +16,8 @@ import dataclasses
16
16
  import math
17
17
  from typing import Iterable, Callable
18
18
 
19
+ import numpy as np
20
+
19
21
  from qiskit.circuit import (
20
22
  Barrier,
21
23
  CircuitInstruction,
@@ -30,6 +32,7 @@ from qiskit.circuit import (
30
32
  Reset,
31
33
  library as lib,
32
34
  )
35
+ from qiskit.quantum_info import Operator
33
36
  from qiskit._accelerate.qasm2 import (
34
37
  OpCode,
35
38
  UnaryOpCode,
@@ -315,6 +318,11 @@ class _DefinedGate(Gate):
315
318
  raise ValueError(f"received invalid bytecode to build gate: {op}")
316
319
  self._definition = qc
317
320
 
321
+ def __array__(self, dtype=None, copy=None):
322
+ if copy is False:
323
+ raise ValueError("unable to avoid copy while creating an array as requested")
324
+ return np.asarray(Operator(self.definition), dtype=dtype)
325
+
318
326
  # It's fiddly to implement pickling for PyO3 types (the bytecode stream), so instead if we need
319
327
  # to pickle ourselves, we just eagerly create the definition and pickle that.
320
328
 
qiskit/qasm3/exporter.py CHANGED
@@ -837,7 +837,7 @@ class QASM3Builder:
837
837
  statements.append(self.build_if_statement(instruction))
838
838
  elif isinstance(instruction.operation, SwitchCaseOp):
839
839
  statements.extend(self.build_switch_statement(instruction))
840
- else: # pragma: no cover
840
+ else:
841
841
  raise RuntimeError(f"unhandled control-flow construct: {instruction.operation}")
842
842
  continue
843
843
  # Build the node, ignoring any condition.
@@ -1130,7 +1130,7 @@ def _build_ast_type(type_: types.Type) -> ast.ClassicalType:
1130
1130
  return ast.BoolType()
1131
1131
  if type_.kind is types.Uint:
1132
1132
  return ast.UintType(type_.width)
1133
- raise RuntimeError(f"unhandled expr type '{type_}'") # pragma: no cover
1133
+ raise RuntimeError(f"unhandled expr type '{type_}'")
1134
1134
 
1135
1135
 
1136
1136
  class _ExprBuilder(expr.ExprVisitor[ast.Expression]):
qiskit/qpy/__init__.py CHANGED
@@ -127,7 +127,7 @@ with. The following table lists the QPY versions that were supported in every
127
127
  Qiskit (and qiskit-terra prior to Qiskit 1.0.0) release going back to the introduction
128
128
  of QPY in qiskit-terra 0.18.0.
129
129
 
130
- .. list-table: QPY Format Version History
130
+ .. list-table:: QPY Format Version History
131
131
  :header-rows: 1
132
132
 
133
133
  * - Qiskit (qiskit-terra for < 1.0.0) version
@@ -138,7 +138,7 @@ of QPY in qiskit-terra 0.18.0.
138
138
  - 12
139
139
  * - 1.0.2
140
140
  - 10, 11
141
- - 12
141
+ - 11
142
142
  * - 1.0.1
143
143
  - 10, 11
144
144
  - 11
@@ -45,7 +45,7 @@ def _write_parameter_vec(file_obj, obj):
45
45
  struct.pack(
46
46
  formats.PARAMETER_VECTOR_ELEMENT_PACK,
47
47
  len(name_bytes),
48
- obj._vector._size,
48
+ len(obj._vector),
49
49
  obj.uuid.bytes,
50
50
  obj._index,
51
51
  )
@@ -54,7 +54,7 @@ class SparsePauliOp(LinearOp):
54
54
  :class:`~qiskit.quantum_info.Operator` in terms of N-qubit
55
55
  :class:`~qiskit.quantum_info.PauliList` and complex coefficients.
56
56
 
57
- It can be used for performing operator arithmetic for hundred of qubits
57
+ It can be used for performing operator arithmetic for hundreds of qubits
58
58
  if the number of non-zero Pauli basis terms is sufficiently small.
59
59
 
60
60
  The Pauli basis components are stored as a
@@ -104,15 +104,21 @@ class VF2Layout(AnalysisPass):
104
104
  limit on the number of trials will be set.
105
105
  target (Target): A target representing the backend device to run ``VF2Layout`` on.
106
106
  If specified it will supersede a set value for ``properties`` and
107
- ``coupling_map``.
107
+ ``coupling_map`` if the :class:`.Target` contains connectivity constraints. If the value
108
+ of ``target`` models an ideal backend without any constraints then the value of
109
+ ``coupling_map``
110
+ will be used.
108
111
 
109
112
  Raises:
110
113
  TypeError: At runtime, if neither ``coupling_map`` or ``target`` are provided.
111
114
  """
112
115
  super().__init__()
113
116
  self.target = target
114
- if target is not None:
115
- self.coupling_map = self.target.build_coupling_map()
117
+ if (
118
+ target is not None
119
+ and (target_coupling_map := self.target.build_coupling_map()) is not None
120
+ ):
121
+ self.coupling_map = target_coupling_map
116
122
  else:
117
123
  self.coupling_map = coupling_map
118
124
  self.properties = properties
@@ -145,7 +151,7 @@ class VF2Layout(AnalysisPass):
145
151
  )
146
152
  # Filter qubits without any supported operations. If they don't support any operations
147
153
  # They're not valid for layout selection
148
- if self.target is not None:
154
+ if self.target is not None and self.target.qargs is not None:
149
155
  has_operations = set(itertools.chain.from_iterable(self.target.qargs))
150
156
  to_remove = set(range(len(cm_nodes))).difference(has_operations)
151
157
  if to_remove:
@@ -145,7 +145,7 @@ def score_layout(
145
145
  def build_average_error_map(target, properties, coupling_map):
146
146
  """Build an average error map used for scoring layouts pre-basis translation."""
147
147
  num_qubits = 0
148
- if target is not None:
148
+ if target is not None and target.qargs is not None:
149
149
  num_qubits = target.num_qubits
150
150
  avg_map = ErrorMap(len(target.qargs))
151
151
  elif coupling_map is not None:
@@ -157,7 +157,7 @@ def build_average_error_map(target, properties, coupling_map):
157
157
  # object
158
158
  avg_map = ErrorMap(0)
159
159
  built = False
160
- if target is not None:
160
+ if target is not None and target.qargs is not None:
161
161
  for qargs in target.qargs:
162
162
  if qargs is None:
163
163
  continue
@@ -99,8 +99,34 @@ def generate_preset_pass_manager(
99
99
  This function is used to quickly generate a preset pass manager. A preset pass
100
100
  manager are the default pass managers used by the :func:`~.transpile`
101
101
  function. This function provides a convenient and simple method to construct
102
- a standalone :class:`~.PassManager` object that mirrors what the transpile
102
+ a standalone :class:`~.PassManager` object that mirrors what the :func:`~.transpile`
103
+ function internally builds and uses.
103
104
 
105
+ The target constraints for the pass manager construction can be specified through a :class:`.Target`
106
+ instance, a :class:`.BackendV1` or :class:`.BackendV2` instance, or via loose constraints
107
+ (``basis_gates``, ``inst_map``, ``coupling_map``, ``backend_properties``, ``instruction_durations``,
108
+ ``dt`` or ``timing_constraints``).
109
+ The order of priorities for target constraints works as follows: if a ``target``
110
+ input is provided, it will take priority over any ``backend`` input or loose constraints.
111
+ If a ``backend`` is provided together with any loose constraint
112
+ from the list above, the loose constraint will take priority over the corresponding backend
113
+ constraint. This behavior is independent of whether the ``backend`` instance is of type
114
+ :class:`.BackendV1` or :class:`.BackendV2`, as summarized in the table below. The first column
115
+ in the table summarizes the potential user-provided constraints, and each cell shows whether
116
+ the priority is assigned to that specific constraint input or another input
117
+ (`target`/`backend(V1)`/`backend(V2)`).
118
+
119
+ ============================ ========= ======================== =======================
120
+ User Provided target backend(V1) backend(V2)
121
+ ============================ ========= ======================== =======================
122
+ **basis_gates** target basis_gates basis_gates
123
+ **coupling_map** target coupling_map coupling_map
124
+ **instruction_durations** target instruction_durations instruction_durations
125
+ **inst_map** target inst_map inst_map
126
+ **dt** target dt dt
127
+ **timing_constraints** target timing_constraints timing_constraints
128
+ **backend_properties** target backend_properties backend_properties
129
+ ============================ ========= ======================== =======================
104
130
 
105
131
  Args:
106
132
  optimization_level (int): The optimization level to generate a
@@ -890,7 +890,7 @@ class Target(Mapping):
890
890
  return False
891
891
  if qargs not in self._gate_map[operation_name]:
892
892
  return False
893
- return getattr(self._gate_map[operation_name][qargs], "_calibration") is not None
893
+ return getattr(self._gate_map[operation_name][qargs], "_calibration", None) is not None
894
894
 
895
895
  def get_calibration(
896
896
  self,
@@ -40,7 +40,7 @@ from typing import Dict, List, Union, Optional
40
40
 
41
41
  from qiskit import pulse
42
42
  from qiskit.providers import BackendConfigurationError
43
- from qiskit.providers.backend import Backend
43
+ from qiskit.providers.backend import Backend, BackendV2
44
44
 
45
45
 
46
46
  class DrawerBackendInfo(ABC):
@@ -106,40 +106,67 @@ class OpenPulseBackendInfo(DrawerBackendInfo):
106
106
  Returns:
107
107
  OpenPulseBackendInfo: New configured instance.
108
108
  """
109
- configuration = backend.configuration()
110
- defaults = backend.defaults()
111
-
112
- # load name
113
- name = backend.name()
114
-
115
- # load cycle time
116
- dt = configuration.dt
117
-
118
- # load frequencies
119
109
  chan_freqs = {}
120
-
121
- chan_freqs.update(
122
- {pulse.DriveChannel(qind): freq for qind, freq in enumerate(defaults.qubit_freq_est)}
123
- )
124
- chan_freqs.update(
125
- {pulse.MeasureChannel(qind): freq for qind, freq in enumerate(defaults.meas_freq_est)}
126
- )
127
- for qind, u_lo_mappers in enumerate(configuration.u_channel_lo):
128
- temp_val = 0.0 + 0.0j
129
- for u_lo_mapper in u_lo_mappers:
130
- temp_val += defaults.qubit_freq_est[u_lo_mapper.q] * u_lo_mapper.scale
131
- chan_freqs[pulse.ControlChannel(qind)] = temp_val.real
132
-
133
- # load qubit channel mapping
134
110
  qubit_channel_map = defaultdict(list)
135
- for qind in range(configuration.n_qubits):
136
- qubit_channel_map[qind].append(configuration.drive(qubit=qind))
137
- qubit_channel_map[qind].append(configuration.measure(qubit=qind))
138
- for tind in range(configuration.n_qubits):
111
+
112
+ if hasattr(backend, "configuration") and hasattr(backend, "defaults"):
113
+ configuration = backend.configuration()
114
+ defaults = backend.defaults()
115
+
116
+ name = configuration.backend_name
117
+ dt = configuration.dt
118
+
119
+ # load frequencies
120
+ chan_freqs.update(
121
+ {
122
+ pulse.DriveChannel(qind): freq
123
+ for qind, freq in enumerate(defaults.qubit_freq_est)
124
+ }
125
+ )
126
+ chan_freqs.update(
127
+ {
128
+ pulse.MeasureChannel(qind): freq
129
+ for qind, freq in enumerate(defaults.meas_freq_est)
130
+ }
131
+ )
132
+ for qind, u_lo_mappers in enumerate(configuration.u_channel_lo):
133
+ temp_val = 0.0 + 0.0j
134
+ for u_lo_mapper in u_lo_mappers:
135
+ temp_val += defaults.qubit_freq_est[u_lo_mapper.q] * u_lo_mapper.scale
136
+ chan_freqs[pulse.ControlChannel(qind)] = temp_val.real
137
+
138
+ # load qubit channel mapping
139
+ for qind in range(configuration.n_qubits):
140
+ qubit_channel_map[qind].append(configuration.drive(qubit=qind))
141
+ qubit_channel_map[qind].append(configuration.measure(qubit=qind))
142
+ for tind in range(configuration.n_qubits):
143
+ try:
144
+ qubit_channel_map[qind].extend(configuration.control(qubits=(qind, tind)))
145
+ except BackendConfigurationError:
146
+ pass
147
+ elif isinstance(backend, BackendV2):
148
+ # Pure V2 model doesn't contain channel frequency information.
149
+ name = backend.name
150
+ dt = backend.dt
151
+
152
+ # load qubit channel mapping
153
+ for qind in range(backend.num_qubits):
154
+ # channels are NotImplemented by default so we must catch arbitrary error.
155
+ try:
156
+ qubit_channel_map[qind].append(backend.drive_channel(qind))
157
+ except Exception: # pylint: disable=broad-except
158
+ pass
139
159
  try:
140
- qubit_channel_map[qind].extend(configuration.control(qubits=(qind, tind)))
141
- except BackendConfigurationError:
160
+ qubit_channel_map[qind].append(backend.measure_channel(qind))
161
+ except Exception: # pylint: disable=broad-except
142
162
  pass
163
+ for tind in range(backend.num_qubits):
164
+ try:
165
+ qubit_channel_map[qind].extend(backend.control_channel(qubits=(qind, tind)))
166
+ except Exception: # pylint: disable=broad-except
167
+ pass
168
+ else:
169
+ raise RuntimeError("Backend object not yet supported")
143
170
 
144
171
  return OpenPulseBackendInfo(
145
172
  name=name, dt=dt, channel_frequency_map=chan_freqs, qubit_channel_map=qubit_channel_map
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: qiskit
3
- Version: 1.1.0
3
+ Version: 1.1.1
4
4
  Summary: An open-source SDK for working with quantum computers at the level of extended quantum circuits, operators, and primitives.
5
5
  Author-email: Qiskit Development Team <qiskit@us.ibm.com>
6
6
  License: Apache 2.0