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 +1 -1
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/circuit/__init__.py +4 -3
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +1 -1
- qiskit/circuit/library/n_local/two_local.py +1 -1
- qiskit/circuit/parameterexpression.py +3 -0
- qiskit/circuit/parametervector.py +22 -16
- qiskit/circuit/quantumcircuit.py +33 -49
- qiskit/dagcircuit/dagcircuit.py +1 -1
- qiskit/primitives/__init__.py +4 -4
- qiskit/providers/backend.py +0 -6
- qiskit/pulse/builder.py +2 -2
- qiskit/qasm2/parse.py +8 -0
- qiskit/qasm3/exporter.py +2 -2
- qiskit/qpy/__init__.py +2 -2
- qiskit/qpy/binary_io/value.py +1 -1
- qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +1 -1
- qiskit/transpiler/passes/layout/vf2_layout.py +10 -4
- qiskit/transpiler/passes/layout/vf2_utils.py +2 -2
- qiskit/transpiler/preset_passmanagers/__init__.py +27 -1
- qiskit/transpiler/target.py +1 -1
- qiskit/visualization/pulse_v2/device_info.py +58 -31
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/METADATA +1 -1
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/RECORD +760 -760
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/LICENSE.txt +0 -0
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/WHEEL +0 -0
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/entry_points.txt +0 -0
- {qiskit-1.1.0.dist-info → qiskit-1.1.1.dist-info}/top_level.txt +0 -0
qiskit/VERSION.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.1.
|
1
|
+
1.1.1
|
qiskit/_accelerate.abi3.so
CHANGED
Binary file
|
qiskit/circuit/__init__.py
CHANGED
@@ -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.
|
822
|
-
field, and may assume that these are numeric
|
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
|
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", "
|
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
|
81
|
+
return iter(self.params)
|
89
82
|
|
90
83
|
def __len__(self):
|
91
|
-
return self.
|
84
|
+
return len(self._params)
|
92
85
|
|
93
86
|
def __str__(self):
|
94
|
-
return f"{self.name}, {[str(item) for item in self.params
|
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
|
-
|
103
|
-
|
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
|
-
|
119
|
+
else:
|
120
|
+
del self._params[length:]
|
qiskit/circuit/quantumcircuit.py
CHANGED
@@ -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
|
-
|
3336
|
-
|
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
|
-
|
3342
|
-
|
3343
|
-
|
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
|
-
|
3359
|
-
|
3360
|
-
|
3361
|
-
|
3362
|
-
|
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
|
-
|
3377
|
-
|
3378
|
-
|
3379
|
-
|
3380
|
-
|
3381
|
-
|
3382
|
-
|
3383
|
-
|
3384
|
-
|
3385
|
-
|
3386
|
-
|
3387
|
-
|
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.
|
qiskit/dagcircuit/dagcircuit.py
CHANGED
qiskit/primitives/__init__.py
CHANGED
@@ -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)>,
|
qiskit/providers/backend.py
CHANGED
@@ -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
|
78
|
-
normal Qiskit schedule
|
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:
|
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_}'")
|
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
|
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
|
-
-
|
141
|
+
- 11
|
142
142
|
* - 1.0.1
|
143
143
|
- 10, 11
|
144
144
|
- 11
|
qiskit/qpy/binary_io/value.py
CHANGED
@@ -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
|
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
|
115
|
-
|
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
|
qiskit/transpiler/target.py
CHANGED
@@ -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
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
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].
|
141
|
-
except
|
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.
|
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
|