qiskit 2.0.3__cp39-abi3-macosx_11_0_arm64.whl → 2.1.0__cp39-abi3-macosx_11_0_arm64.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/__init__.py +19 -1
- qiskit/_accelerate.abi3.so +0 -0
- qiskit/circuit/__init__.py +104 -20
- qiskit/circuit/_add_control.py +57 -31
- qiskit/circuit/_classical_resource_map.py +4 -0
- qiskit/circuit/annotation.py +504 -0
- qiskit/circuit/classical/expr/__init__.py +1 -1
- qiskit/circuit/classical/expr/expr.py +104 -446
- qiskit/circuit/classical/expr/visitors.py +6 -0
- qiskit/circuit/classical/types/types.py +7 -130
- qiskit/circuit/controlflow/box.py +32 -7
- qiskit/circuit/delay.py +11 -9
- qiskit/circuit/library/arithmetic/adders/adder.py +4 -4
- qiskit/circuit/library/arithmetic/multipliers/multiplier.py +2 -2
- qiskit/circuit/library/arithmetic/piecewise_chebyshev.py +8 -4
- qiskit/circuit/library/arithmetic/piecewise_linear_pauli_rotations.py +23 -15
- qiskit/circuit/library/arithmetic/piecewise_polynomial_pauli_rotations.py +22 -14
- qiskit/circuit/library/arithmetic/quadratic_form.py +6 -0
- qiskit/circuit/library/arithmetic/weighted_adder.py +43 -24
- qiskit/circuit/library/basis_change/qft.py +2 -2
- qiskit/circuit/library/blueprintcircuit.py +6 -0
- qiskit/circuit/library/boolean_logic/inner_product.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_and.py +2 -2
- qiskit/circuit/library/boolean_logic/quantum_or.py +3 -3
- qiskit/circuit/library/boolean_logic/quantum_xor.py +2 -2
- qiskit/circuit/library/data_preparation/_z_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/_zz_feature_map.py +2 -2
- qiskit/circuit/library/data_preparation/pauli_feature_map.py +2 -2
- qiskit/circuit/library/fourier_checking.py +2 -2
- qiskit/circuit/library/generalized_gates/diagonal.py +5 -1
- qiskit/circuit/library/generalized_gates/gms.py +5 -1
- qiskit/circuit/library/generalized_gates/linear_function.py +2 -2
- qiskit/circuit/library/generalized_gates/permutation.py +5 -1
- qiskit/circuit/library/generalized_gates/uc.py +1 -1
- qiskit/circuit/library/generalized_gates/unitary.py +21 -2
- qiskit/circuit/library/graph_state.py +2 -2
- qiskit/circuit/library/grover_operator.py +2 -2
- qiskit/circuit/library/hidden_linear_function.py +2 -2
- qiskit/circuit/library/iqp.py +2 -2
- qiskit/circuit/library/n_local/efficient_su2.py +2 -2
- qiskit/circuit/library/n_local/evolved_operator_ansatz.py +1 -1
- qiskit/circuit/library/n_local/excitation_preserving.py +7 -9
- qiskit/circuit/library/n_local/n_local.py +4 -3
- qiskit/circuit/library/n_local/pauli_two_design.py +2 -2
- qiskit/circuit/library/n_local/real_amplitudes.py +2 -2
- qiskit/circuit/library/n_local/two_local.py +2 -2
- qiskit/circuit/library/overlap.py +2 -2
- qiskit/circuit/library/pauli_evolution.py +3 -2
- qiskit/circuit/library/phase_estimation.py +2 -2
- qiskit/circuit/library/standard_gates/dcx.py +11 -12
- qiskit/circuit/library/standard_gates/ecr.py +21 -24
- qiskit/circuit/library/standard_gates/equivalence_library.py +232 -96
- qiskit/circuit/library/standard_gates/global_phase.py +5 -6
- qiskit/circuit/library/standard_gates/h.py +22 -45
- qiskit/circuit/library/standard_gates/i.py +1 -1
- qiskit/circuit/library/standard_gates/iswap.py +13 -31
- qiskit/circuit/library/standard_gates/p.py +19 -26
- qiskit/circuit/library/standard_gates/r.py +11 -17
- qiskit/circuit/library/standard_gates/rx.py +21 -45
- qiskit/circuit/library/standard_gates/rxx.py +7 -22
- qiskit/circuit/library/standard_gates/ry.py +21 -39
- qiskit/circuit/library/standard_gates/ryy.py +13 -28
- qiskit/circuit/library/standard_gates/rz.py +18 -35
- qiskit/circuit/library/standard_gates/rzx.py +7 -22
- qiskit/circuit/library/standard_gates/rzz.py +7 -19
- qiskit/circuit/library/standard_gates/s.py +44 -39
- qiskit/circuit/library/standard_gates/swap.py +25 -38
- qiskit/circuit/library/standard_gates/sx.py +34 -41
- qiskit/circuit/library/standard_gates/t.py +18 -27
- qiskit/circuit/library/standard_gates/u.py +8 -24
- qiskit/circuit/library/standard_gates/u1.py +28 -52
- qiskit/circuit/library/standard_gates/u2.py +9 -9
- qiskit/circuit/library/standard_gates/u3.py +24 -40
- qiskit/circuit/library/standard_gates/x.py +190 -336
- qiskit/circuit/library/standard_gates/xx_minus_yy.py +12 -50
- qiskit/circuit/library/standard_gates/xx_plus_yy.py +13 -52
- qiskit/circuit/library/standard_gates/y.py +19 -23
- qiskit/circuit/library/standard_gates/z.py +31 -38
- qiskit/circuit/parameter.py +14 -5
- qiskit/circuit/parameterexpression.py +109 -75
- qiskit/circuit/quantumcircuit.py +172 -99
- qiskit/circuit/quantumcircuitdata.py +1 -0
- qiskit/circuit/random/__init__.py +37 -2
- qiskit/circuit/random/utils.py +445 -56
- qiskit/circuit/tools/pi_check.py +5 -13
- qiskit/compiler/transpiler.py +1 -1
- qiskit/converters/circuit_to_instruction.py +2 -2
- qiskit/dagcircuit/dagnode.py +8 -3
- qiskit/primitives/__init__.py +2 -2
- qiskit/primitives/base/base_estimator.py +2 -2
- qiskit/primitives/containers/data_bin.py +0 -3
- qiskit/primitives/containers/observables_array.py +192 -108
- qiskit/primitives/primitive_job.py +29 -10
- qiskit/providers/fake_provider/generic_backend_v2.py +2 -0
- qiskit/qasm3/__init__.py +106 -12
- qiskit/qasm3/ast.py +15 -1
- qiskit/qasm3/exporter.py +59 -36
- qiskit/qasm3/printer.py +12 -0
- qiskit/qpy/__init__.py +182 -6
- qiskit/qpy/binary_io/circuits.py +256 -24
- qiskit/qpy/binary_io/parse_sympy_repr.py +5 -0
- qiskit/qpy/binary_io/schedules.py +12 -32
- qiskit/qpy/binary_io/value.py +36 -18
- qiskit/qpy/common.py +11 -3
- qiskit/qpy/formats.py +17 -1
- qiskit/qpy/interface.py +52 -12
- qiskit/qpy/type_keys.py +7 -1
- qiskit/quantum_info/__init__.py +10 -0
- qiskit/quantum_info/operators/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/__init__.py +1 -0
- qiskit/quantum_info/operators/symplectic/clifford_circuits.py +26 -0
- qiskit/quantum_info/operators/symplectic/pauli.py +2 -2
- qiskit/result/sampled_expval.py +3 -1
- qiskit/synthesis/__init__.py +10 -0
- qiskit/synthesis/arithmetic/__init__.py +1 -1
- qiskit/synthesis/arithmetic/adders/__init__.py +1 -0
- qiskit/synthesis/arithmetic/adders/draper_qft_adder.py +6 -2
- qiskit/synthesis/arithmetic/adders/rv_ripple_carry_adder.py +156 -0
- qiskit/synthesis/discrete_basis/generate_basis_approximations.py +14 -126
- qiskit/synthesis/discrete_basis/solovay_kitaev.py +161 -121
- qiskit/synthesis/evolution/lie_trotter.py +10 -7
- qiskit/synthesis/evolution/product_formula.py +10 -7
- qiskit/synthesis/evolution/qdrift.py +10 -7
- qiskit/synthesis/evolution/suzuki_trotter.py +10 -7
- qiskit/synthesis/multi_controlled/__init__.py +4 -0
- qiskit/synthesis/multi_controlled/mcx_synthesis.py +402 -178
- qiskit/synthesis/multi_controlled/multi_control_rotation_gates.py +14 -15
- qiskit/synthesis/qft/qft_decompose_lnn.py +7 -25
- qiskit/synthesis/unitary/qsd.py +80 -9
- qiskit/transpiler/__init__.py +10 -3
- qiskit/transpiler/instruction_durations.py +2 -20
- qiskit/transpiler/passes/__init__.py +5 -2
- qiskit/transpiler/passes/layout/dense_layout.py +26 -6
- qiskit/transpiler/passes/layout/disjoint_utils.py +1 -166
- qiskit/transpiler/passes/layout/sabre_layout.py +22 -3
- qiskit/transpiler/passes/layout/sabre_pre_layout.py +1 -1
- qiskit/transpiler/passes/layout/vf2_layout.py +49 -13
- qiskit/transpiler/passes/layout/vf2_utils.py +10 -0
- qiskit/transpiler/passes/optimization/__init__.py +1 -1
- qiskit/transpiler/passes/optimization/optimize_1q_decomposition.py +2 -1
- qiskit/transpiler/passes/optimization/optimize_clifford_t.py +68 -0
- qiskit/transpiler/passes/optimization/template_matching/template_substitution.py +3 -9
- qiskit/transpiler/passes/routing/sabre_swap.py +4 -2
- qiskit/transpiler/passes/routing/star_prerouting.py +106 -81
- qiskit/transpiler/passes/scheduling/__init__.py +1 -1
- qiskit/transpiler/passes/scheduling/alignments/check_durations.py +1 -1
- qiskit/transpiler/passes/scheduling/padding/__init__.py +1 -0
- qiskit/transpiler/passes/scheduling/padding/context_aware_dynamical_decoupling.py +876 -0
- qiskit/transpiler/passes/synthesis/__init__.py +1 -0
- qiskit/transpiler/passes/synthesis/clifford_unitary_synth_plugin.py +123 -0
- qiskit/transpiler/passes/synthesis/hls_plugins.py +494 -93
- qiskit/transpiler/passes/synthesis/plugin.py +4 -0
- qiskit/transpiler/passes/synthesis/solovay_kitaev_synthesis.py +27 -22
- qiskit/transpiler/passmanager_config.py +3 -0
- qiskit/transpiler/preset_passmanagers/builtin_plugins.py +149 -28
- qiskit/transpiler/preset_passmanagers/common.py +101 -0
- qiskit/transpiler/preset_passmanagers/generate_preset_pass_manager.py +6 -0
- qiskit/transpiler/preset_passmanagers/level3.py +2 -2
- qiskit/transpiler/target.py +15 -2
- qiskit/utils/optionals.py +6 -5
- qiskit/visualization/circuit/_utils.py +5 -3
- qiskit/visualization/circuit/latex.py +9 -2
- qiskit/visualization/circuit/matplotlib.py +26 -4
- qiskit/visualization/circuit/qcstyle.py +9 -157
- qiskit/visualization/dag/__init__.py +13 -0
- qiskit/visualization/dag/dagstyle.py +103 -0
- qiskit/visualization/dag/styles/__init__.py +13 -0
- qiskit/visualization/dag/styles/color.json +10 -0
- qiskit/visualization/dag/styles/plain.json +5 -0
- qiskit/visualization/dag_visualization.py +169 -98
- qiskit/visualization/style.py +223 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/METADATA +7 -6
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/RECORD +178 -169
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/entry_points.txt +6 -0
- qiskit/synthesis/discrete_basis/commutator_decompose.py +0 -265
- qiskit/synthesis/discrete_basis/gate_sequence.py +0 -421
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/WHEEL +0 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/licenses/LICENSE.txt +0 -0
- {qiskit-2.0.3.dist-info → qiskit-2.1.0.dist-info}/top_level.txt +0 -0
qiskit/qasm3/__init__.py
CHANGED
@@ -226,7 +226,10 @@ available on this module, if you wish to build on top of it:
|
|
226
226
|
``stdgates.inc`` include file.
|
227
227
|
"""
|
228
228
|
|
229
|
+
from __future__ import annotations
|
230
|
+
|
229
231
|
import functools
|
232
|
+
import typing
|
230
233
|
import warnings
|
231
234
|
|
232
235
|
from qiskit._accelerate import qasm3 as _qasm3
|
@@ -234,11 +237,13 @@ from qiskit.circuit import library
|
|
234
237
|
from qiskit.exceptions import ExperimentalWarning
|
235
238
|
from qiskit.utils import optionals as _optionals
|
236
239
|
|
240
|
+
from .._accelerate.qasm3 import CustomGate
|
241
|
+
from .exceptions import QASM3Error, QASM3ExporterError, QASM3ImporterError
|
237
242
|
from .experimental import ExperimentalFeatures
|
238
243
|
from .exporter import Exporter
|
239
|
-
from .exceptions import QASM3Error, QASM3ImporterError, QASM3ExporterError
|
240
|
-
from .._accelerate.qasm3 import CustomGate
|
241
244
|
|
245
|
+
if typing.TYPE_CHECKING:
|
246
|
+
from qiskit.circuit import annotation, QuantumCircuit
|
242
247
|
|
243
248
|
STDGATES_INC_GATES = (
|
244
249
|
CustomGate(library.PhaseGate, "p", 1, 1),
|
@@ -303,11 +308,15 @@ def dump(circuit, stream, **kwargs) -> None:
|
|
303
308
|
|
304
309
|
|
305
310
|
@_optionals.HAS_QASM3_IMPORT.require_in_call("loading from OpenQASM 3")
|
306
|
-
def load(
|
311
|
+
def load(
|
312
|
+
filename: str, *, annotation_handlers: dict[str, annotation.OpenQASM3Serializer] | None = None
|
313
|
+
) -> QuantumCircuit:
|
307
314
|
"""Load an OpenQASM 3 program from the file ``filename``.
|
308
315
|
|
309
316
|
Args:
|
310
317
|
filename: the filename to load the program from.
|
318
|
+
annotation_handlers: a mapping whose keys are (parent) namespaces and values are serializers
|
319
|
+
that can handle children of those namesapces. Requires ``qiskit_qasm3_import>=0.6.0``.
|
311
320
|
|
312
321
|
Returns:
|
313
322
|
QuantumCircuit: a circuit representation of the OpenQASM 3 program.
|
@@ -315,24 +324,25 @@ def load(filename: str):
|
|
315
324
|
Raises:
|
316
325
|
QASM3ImporterError: if the OpenQASM 3 file is invalid, or cannot be represented by a
|
317
326
|
:class:`.QuantumCircuit`.
|
318
|
-
"""
|
319
|
-
|
320
|
-
import qiskit_qasm3_import
|
321
327
|
|
328
|
+
.. versionadded:: 2.1
|
329
|
+
The ``annotation_handlers`` argument. This requires ``qiskit_qasm3_import>=0.6.0``.
|
330
|
+
"""
|
322
331
|
with open(filename, "r") as fptr:
|
323
332
|
program = fptr.read()
|
324
|
-
|
325
|
-
return qiskit_qasm3_import.parse(program)
|
326
|
-
except qiskit_qasm3_import.ConversionError as exc:
|
327
|
-
raise QASM3ImporterError(str(exc)) from exc
|
333
|
+
return loads(program, annotation_handlers=annotation_handlers)
|
328
334
|
|
329
335
|
|
330
336
|
@_optionals.HAS_QASM3_IMPORT.require_in_call("loading from OpenQASM 3")
|
331
|
-
def loads(
|
337
|
+
def loads(
|
338
|
+
program: str, *, annotation_handlers: dict[str, annotation.OpenQASM3Serializer] | None = None
|
339
|
+
) -> QuantumCircuit:
|
332
340
|
"""Load an OpenQASM 3 program from the given string.
|
333
341
|
|
334
342
|
Args:
|
335
343
|
program: the OpenQASM 3 program.
|
344
|
+
annotation_handlers: a mapping whose keys are (parent) namespaces and values are serializers
|
345
|
+
that can handle children of those namesapces. Requires ``qiskit_qasm3_import>=0.6.0``.
|
336
346
|
|
337
347
|
Returns:
|
338
348
|
QuantumCircuit: a circuit representation of the OpenQASM 3 program.
|
@@ -340,12 +350,23 @@ def loads(program: str):
|
|
340
350
|
Raises:
|
341
351
|
QASM3ImporterError: if the OpenQASM 3 file is invalid, or cannot be represented by a
|
342
352
|
:class:`.QuantumCircuit`.
|
353
|
+
|
354
|
+
.. versionadded:: 2.1
|
355
|
+
The ``annotation_handlers`` argument. This requires ``qiskit_qasm3_import>=0.6.0``.
|
343
356
|
"""
|
344
357
|
|
345
358
|
import qiskit_qasm3_import
|
346
359
|
|
360
|
+
kwargs = {}
|
361
|
+
if annotation_handlers is not None:
|
362
|
+
if getattr(qiskit_qasm3_import, "VERSION_PARTS", (0, 0)) < (0, 6):
|
363
|
+
raise QASM3ImporterError(
|
364
|
+
"need 'qiskit_qasm3_import>=0.6.0' to handle annotations, but you have "
|
365
|
+
+ qiskit_qasm3_import.__version__
|
366
|
+
)
|
367
|
+
kwargs["annotation_handlers"] = annotation_handlers
|
347
368
|
try:
|
348
|
-
return qiskit_qasm3_import.parse(program)
|
369
|
+
return qiskit_qasm3_import.parse(program, **kwargs)
|
349
370
|
except qiskit_qasm3_import.ConversionError as exc:
|
350
371
|
raise QASM3ImporterError(str(exc)) from exc
|
351
372
|
|
@@ -370,3 +391,76 @@ def load_experimental(pathlike_or_filelike, /, *, custom_gates=None, include_pat
|
|
370
391
|
category=ExperimentalWarning,
|
371
392
|
)
|
372
393
|
return _qasm3.load(pathlike_or_filelike, custom_gates=custom_gates, include_path=include_path)
|
394
|
+
|
395
|
+
|
396
|
+
@functools.wraps(_qasm3.dumps)
|
397
|
+
def dumps_experimental(
|
398
|
+
circuit,
|
399
|
+
*,
|
400
|
+
includes=None,
|
401
|
+
basis_gates=None,
|
402
|
+
disable_constants=True,
|
403
|
+
alias_classical_registers=False,
|
404
|
+
allow_aliasing=False,
|
405
|
+
indent=" ",
|
406
|
+
):
|
407
|
+
"""<overridden by functools.wraps>"""
|
408
|
+
warnings.warn(
|
409
|
+
"This is an experimental version of serialization of a :class:`~qiskit.circuit.QuantumCircuit`"
|
410
|
+
" object in an OpenQASM 3 string."
|
411
|
+
" Beware that its interface might change, and it might be missing features.",
|
412
|
+
category=ExperimentalWarning,
|
413
|
+
)
|
414
|
+
if includes is None:
|
415
|
+
includes = ["stdgates.inc"]
|
416
|
+
if basis_gates is None:
|
417
|
+
basis_gates = ["U"]
|
418
|
+
return _qasm3.dumps(
|
419
|
+
circuit,
|
420
|
+
{
|
421
|
+
"includes": includes,
|
422
|
+
"basis_gates": basis_gates,
|
423
|
+
"disable_constants": disable_constants,
|
424
|
+
"alias_classical_registers": alias_classical_registers,
|
425
|
+
"allow_aliasing": allow_aliasing,
|
426
|
+
"indent": indent,
|
427
|
+
},
|
428
|
+
)
|
429
|
+
|
430
|
+
|
431
|
+
@functools.wraps(_qasm3.dump)
|
432
|
+
def dump_experimental(
|
433
|
+
circuit,
|
434
|
+
stream,
|
435
|
+
*,
|
436
|
+
includes=None,
|
437
|
+
basis_gates=None,
|
438
|
+
disable_constants=True,
|
439
|
+
alias_classical_registers=False,
|
440
|
+
allow_aliasing=False,
|
441
|
+
indent=" ",
|
442
|
+
):
|
443
|
+
"""<overridden by functools.wraps>"""
|
444
|
+
warnings.warn(
|
445
|
+
"This is an experimental version of serialization of a :class:`~qiskit.circuit.QuantumCircuit`"
|
446
|
+
" object in an OpenQASM 3 string."
|
447
|
+
" Beware that its interface might change, and it might be missing features.",
|
448
|
+
category=ExperimentalWarning,
|
449
|
+
)
|
450
|
+
if includes is None:
|
451
|
+
includes = ["stdgates.inc"]
|
452
|
+
if basis_gates is None:
|
453
|
+
basis_gates = ["U"]
|
454
|
+
|
455
|
+
return _qasm3.dump(
|
456
|
+
circuit,
|
457
|
+
stream,
|
458
|
+
{
|
459
|
+
"includes": includes,
|
460
|
+
"basis_gates": basis_gates,
|
461
|
+
"disable_constants": disable_constants,
|
462
|
+
"alias_classical_registers": alias_classical_registers,
|
463
|
+
"allow_aliasing": allow_aliasing,
|
464
|
+
"indent": indent,
|
465
|
+
},
|
466
|
+
)
|
qiskit/qasm3/ast.py
CHANGED
@@ -54,6 +54,16 @@ class Pragma(ASTNode):
|
|
54
54
|
self.content = content
|
55
55
|
|
56
56
|
|
57
|
+
class Annotation(ASTNode):
|
58
|
+
"""An annotation."""
|
59
|
+
|
60
|
+
__slots__ = ("namespace", "payload")
|
61
|
+
|
62
|
+
def __init__(self, namespace: str, payload: str):
|
63
|
+
self.namespace = namespace
|
64
|
+
self.payload = payload
|
65
|
+
|
66
|
+
|
57
67
|
class CalibrationGrammarDeclaration(Statement):
|
58
68
|
"""
|
59
69
|
calibrationGrammarDeclaration
|
@@ -701,15 +711,19 @@ class WhileLoopStatement(Statement):
|
|
701
711
|
class BoxStatement(Statement):
|
702
712
|
"""Like ``box[duration] { statements* }``."""
|
703
713
|
|
704
|
-
|
714
|
+
# TODO: the `annotations` field maybe should move to `Statement` if it becomes more generally
|
715
|
+
# supported.
|
716
|
+
__slots__ = ("annotations", "duration", "body")
|
705
717
|
|
706
718
|
def __init__(
|
707
719
|
self,
|
708
720
|
body: ProgramBlock,
|
709
721
|
duration: Expression | None = None,
|
722
|
+
annotations: Sequence[Annotation] = (),
|
710
723
|
):
|
711
724
|
self.body = body
|
712
725
|
self.duration = duration
|
726
|
+
self.annotations = tuple(annotations)
|
713
727
|
|
714
728
|
|
715
729
|
class BreakStatement(Statement):
|
qiskit/qasm3/exporter.py
CHANGED
@@ -27,6 +27,7 @@ from typing import Iterable, List, Sequence, Union
|
|
27
27
|
from qiskit._accelerate.circuit import StandardGate
|
28
28
|
from qiskit.circuit import (
|
29
29
|
library,
|
30
|
+
Annotation,
|
30
31
|
Barrier,
|
31
32
|
CircuitInstruction,
|
32
33
|
Clbit,
|
@@ -42,6 +43,7 @@ from qiskit.circuit import (
|
|
42
43
|
Bit,
|
43
44
|
Register,
|
44
45
|
)
|
46
|
+
from qiskit.circuit.annotation import iter_namespaces, OpenQASM3Serializer
|
45
47
|
from qiskit.circuit.classical import expr, types
|
46
48
|
from qiskit.circuit.controlflow import (
|
47
49
|
BoxOp,
|
@@ -136,6 +138,7 @@ class Exporter:
|
|
136
138
|
allow_aliasing: bool = None,
|
137
139
|
indent: str = " ",
|
138
140
|
experimental: ExperimentalFeatures = ExperimentalFeatures(0),
|
141
|
+
annotation_handlers: dict[str, OpenQASM3Serializer] | None = None,
|
139
142
|
):
|
140
143
|
"""
|
141
144
|
Args:
|
@@ -172,6 +175,10 @@ class Exporter:
|
|
172
175
|
set to the empty string to disable indentation.
|
173
176
|
experimental: any experimental features to enable during the export. See
|
174
177
|
:class:`ExperimentalFeatures` for more details.
|
178
|
+
annotation_handlers: a mapping of namespaces to annotation serializers. When an
|
179
|
+
:class:`.Annotation` object is encountered, the most specific namespace in this
|
180
|
+
mapping that matches the annotation's :attr:`~.Annotation.namespace` attribute will
|
181
|
+
be used to serialize it.
|
175
182
|
"""
|
176
183
|
self.basis_gates = basis_gates
|
177
184
|
self.disable_constants = disable_constants
|
@@ -181,6 +188,7 @@ class Exporter:
|
|
181
188
|
self.includes = list(includes)
|
182
189
|
self.indent = indent
|
183
190
|
self.experimental = experimental
|
191
|
+
self.annotation_handlers = {} if annotation_handlers is None else annotation_handlers
|
184
192
|
|
185
193
|
def dumps(self, circuit):
|
186
194
|
"""Convert the circuit to OpenQASM 3, returning the result as a string."""
|
@@ -197,6 +205,7 @@ class Exporter:
|
|
197
205
|
disable_constants=self.disable_constants,
|
198
206
|
allow_aliasing=self.allow_aliasing,
|
199
207
|
experimental=self.experimental,
|
208
|
+
annotation_handlers=self.annotation_handlers,
|
200
209
|
)
|
201
210
|
BasicPrinter(stream, indent=self.indent, experimental=self.experimental).visit(
|
202
211
|
builder.build_program()
|
@@ -225,43 +234,43 @@ _CANONICAL_CONTROLLED_STANDARD_GATES = {
|
|
225
234
|
# Mapping of symbols defined by `stdgates.inc` to their gate definition source.
|
226
235
|
_KNOWN_INCLUDES = {
|
227
236
|
"stdgates.inc": {
|
228
|
-
"p": _CANONICAL_STANDARD_GATES[StandardGate.
|
229
|
-
"x": _CANONICAL_STANDARD_GATES[StandardGate.
|
230
|
-
"y": _CANONICAL_STANDARD_GATES[StandardGate.
|
231
|
-
"z": _CANONICAL_STANDARD_GATES[StandardGate.
|
232
|
-
"h": _CANONICAL_STANDARD_GATES[StandardGate.
|
233
|
-
"s": _CANONICAL_STANDARD_GATES[StandardGate.
|
234
|
-
"sdg": _CANONICAL_STANDARD_GATES[StandardGate.
|
235
|
-
"t": _CANONICAL_STANDARD_GATES[StandardGate.
|
236
|
-
"tdg": _CANONICAL_STANDARD_GATES[StandardGate.
|
237
|
-
"sx": _CANONICAL_STANDARD_GATES[StandardGate.
|
238
|
-
"rx": _CANONICAL_STANDARD_GATES[StandardGate.
|
239
|
-
"ry": _CANONICAL_STANDARD_GATES[StandardGate.
|
240
|
-
"rz": _CANONICAL_STANDARD_GATES[StandardGate.
|
241
|
-
"cx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
242
|
-
"cy": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
243
|
-
"cz": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
244
|
-
"cp": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
245
|
-
"crx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
246
|
-
"cry": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
247
|
-
"crz": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
248
|
-
"ch": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
249
|
-
"swap": _CANONICAL_STANDARD_GATES[StandardGate.
|
250
|
-
"ccx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
251
|
-
"cswap": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
252
|
-
"cu": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
253
|
-
"CX": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
254
|
-
"phase": _CANONICAL_STANDARD_GATES[StandardGate.
|
255
|
-
"cphase": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.
|
256
|
-
"id": _CANONICAL_STANDARD_GATES[StandardGate.
|
257
|
-
"u1": _CANONICAL_STANDARD_GATES[StandardGate.
|
258
|
-
"u2": _CANONICAL_STANDARD_GATES[StandardGate.
|
259
|
-
"u3": _CANONICAL_STANDARD_GATES[StandardGate.
|
237
|
+
"p": _CANONICAL_STANDARD_GATES[StandardGate.Phase],
|
238
|
+
"x": _CANONICAL_STANDARD_GATES[StandardGate.X],
|
239
|
+
"y": _CANONICAL_STANDARD_GATES[StandardGate.Y],
|
240
|
+
"z": _CANONICAL_STANDARD_GATES[StandardGate.Z],
|
241
|
+
"h": _CANONICAL_STANDARD_GATES[StandardGate.H],
|
242
|
+
"s": _CANONICAL_STANDARD_GATES[StandardGate.S],
|
243
|
+
"sdg": _CANONICAL_STANDARD_GATES[StandardGate.Sdg],
|
244
|
+
"t": _CANONICAL_STANDARD_GATES[StandardGate.T],
|
245
|
+
"tdg": _CANONICAL_STANDARD_GATES[StandardGate.Tdg],
|
246
|
+
"sx": _CANONICAL_STANDARD_GATES[StandardGate.SX],
|
247
|
+
"rx": _CANONICAL_STANDARD_GATES[StandardGate.RX],
|
248
|
+
"ry": _CANONICAL_STANDARD_GATES[StandardGate.RY],
|
249
|
+
"rz": _CANONICAL_STANDARD_GATES[StandardGate.RZ],
|
250
|
+
"cx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CX][1],
|
251
|
+
"cy": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CY][1],
|
252
|
+
"cz": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CZ][1],
|
253
|
+
"cp": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CPhase][1],
|
254
|
+
"crx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CRX][1],
|
255
|
+
"cry": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CRY][1],
|
256
|
+
"crz": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CRZ][1],
|
257
|
+
"ch": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CH][1],
|
258
|
+
"swap": _CANONICAL_STANDARD_GATES[StandardGate.Swap],
|
259
|
+
"ccx": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CCX][3],
|
260
|
+
"cswap": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CSwap][1],
|
261
|
+
"cu": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CU][1],
|
262
|
+
"CX": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CX][1],
|
263
|
+
"phase": _CANONICAL_STANDARD_GATES[StandardGate.Phase],
|
264
|
+
"cphase": _CANONICAL_CONTROLLED_STANDARD_GATES[StandardGate.CPhase][1],
|
265
|
+
"id": _CANONICAL_STANDARD_GATES[StandardGate.I],
|
266
|
+
"u1": _CANONICAL_STANDARD_GATES[StandardGate.U1],
|
267
|
+
"u2": _CANONICAL_STANDARD_GATES[StandardGate.U2],
|
268
|
+
"u3": _CANONICAL_STANDARD_GATES[StandardGate.U3],
|
260
269
|
},
|
261
270
|
}
|
262
271
|
|
263
272
|
_BUILTIN_GATES = {
|
264
|
-
"U": _CANONICAL_STANDARD_GATES[StandardGate.
|
273
|
+
"U": _CANONICAL_STANDARD_GATES[StandardGate.U],
|
265
274
|
}
|
266
275
|
|
267
276
|
|
@@ -563,6 +572,7 @@ class QASM3Builder:
|
|
563
572
|
disable_constants,
|
564
573
|
allow_aliasing,
|
565
574
|
experimental=ExperimentalFeatures(0),
|
575
|
+
annotation_handlers=None,
|
566
576
|
):
|
567
577
|
self.scope = BuildScope(
|
568
578
|
quantumcircuit,
|
@@ -582,6 +592,7 @@ class QASM3Builder:
|
|
582
592
|
self.includes = includeslist
|
583
593
|
self.basis_gates = basis_gates
|
584
594
|
self.experimental = experimental
|
595
|
+
self.annotation_handlers = {} if annotation_handlers is None else annotation_handlers
|
585
596
|
|
586
597
|
@contextlib.contextmanager
|
587
598
|
def new_scope(self, circuit: QuantumCircuit, qubits: Iterable[Qubit], clbits: Iterable[Clbit]):
|
@@ -991,8 +1002,8 @@ class QASM3Builder:
|
|
991
1002
|
measurement = ast.QuantumMeasurement(
|
992
1003
|
[self._lookup_bit(operand) for operand in instruction.qubits]
|
993
1004
|
)
|
994
|
-
|
995
|
-
nodes = [ast.QuantumMeasurementAssignment(
|
1005
|
+
clbit = self._lookup_bit(instruction.clbits[0])
|
1006
|
+
nodes = [ast.QuantumMeasurementAssignment(clbit, measurement)]
|
996
1007
|
elif isinstance(instruction.operation, Reset):
|
997
1008
|
nodes = [
|
998
1009
|
ast.QuantumReset(self._lookup_bit(operand)) for operand in instruction.qubits
|
@@ -1090,10 +1101,13 @@ class QASM3Builder:
|
|
1090
1101
|
"""Build a :class:`.BoxOp` into a :class:`.ast.BoxStatement`."""
|
1091
1102
|
duration = self.build_duration(instruction.operation.duration, instruction.operation.unit)
|
1092
1103
|
body_circuit = instruction.operation.blocks[0]
|
1104
|
+
annotations = [
|
1105
|
+
self.build_annotation(annotation) for annotation in instruction.operation.annotations
|
1106
|
+
]
|
1093
1107
|
with self.new_scope(body_circuit, instruction.qubits, instruction.clbits):
|
1094
1108
|
# TODO: handle no-op qubits (see https://github.com/openqasm/openqasm/issues/584).
|
1095
1109
|
body = ast.ProgramBlock(self.build_current_scope())
|
1096
|
-
return ast.BoxStatement(body, duration)
|
1110
|
+
return ast.BoxStatement(body, duration, annotations=annotations)
|
1097
1111
|
|
1098
1112
|
def build_while_loop(self, instruction: CircuitInstruction) -> ast.WhileLoopStatement:
|
1099
1113
|
"""Build a :obj:`.WhileLoopOp` into a :obj:`.ast.WhileLoopStatement`."""
|
@@ -1129,6 +1143,15 @@ class QASM3Builder:
|
|
1129
1143
|
body_ast = ast.ProgramBlock(self.build_current_scope())
|
1130
1144
|
return ast.ForLoopStatement(indexset_ast, loop_parameter_ast, body_ast)
|
1131
1145
|
|
1146
|
+
def build_annotation(self, annotation: Annotation) -> ast.Annotation:
|
1147
|
+
"""Use the custom serializers to construct an annotation object."""
|
1148
|
+
for namespace in iter_namespaces(annotation.namespace):
|
1149
|
+
if (serializer := self.annotation_handlers.get(namespace, None)) is not None and (
|
1150
|
+
payload := serializer.dump(annotation)
|
1151
|
+
) is not NotImplemented:
|
1152
|
+
return ast.Annotation(annotation.namespace, payload)
|
1153
|
+
raise QASM3ExporterError(f"No configured annotation serializer could handle {annotation}")
|
1154
|
+
|
1132
1155
|
def _lookup_variable_for_expression(self, var):
|
1133
1156
|
if isinstance(var, Bit):
|
1134
1157
|
return self._lookup_bit(var)
|
qiskit/qasm3/printer.py
CHANGED
@@ -205,6 +205,13 @@ class BasicPrinter:
|
|
205
205
|
def _visit_Pragma(self, node: ast.Pragma) -> None:
|
206
206
|
self._write_statement(f"#pragma {node.content}")
|
207
207
|
|
208
|
+
def _visit_Annotation(self, node: ast.Annotation) -> None:
|
209
|
+
self._start_line()
|
210
|
+
self.stream.write(f"@{node.namespace}")
|
211
|
+
if node.payload:
|
212
|
+
self.stream.write(f" {node.payload}")
|
213
|
+
self._end_line()
|
214
|
+
|
208
215
|
def _visit_CalibrationGrammarDeclaration(self, node: ast.CalibrationGrammarDeclaration) -> None:
|
209
216
|
self._write_statement(f'defcalgrammar "{node.name}"')
|
210
217
|
|
@@ -597,6 +604,11 @@ class BasicPrinter:
|
|
597
604
|
self.stream.write("default")
|
598
605
|
|
599
606
|
def _visit_BoxStatement(self, node: ast.BoxStatement) -> None:
|
607
|
+
# The OpenQASM 3 spec doesn't specify any ordering between annotations. We choose to
|
608
|
+
# write and interpret them like Python decorators, where the "first" annotation is written
|
609
|
+
# closest to the box itself.
|
610
|
+
for annotation in reversed(node.annotations):
|
611
|
+
self.visit(annotation)
|
600
612
|
self._start_line()
|
601
613
|
self.stream.write("box")
|
602
614
|
if node.duration is not None:
|
qiskit/qpy/__init__.py
CHANGED
@@ -99,6 +99,7 @@ API documentation
|
|
99
99
|
|
100
100
|
.. autofunction:: load
|
101
101
|
.. autofunction:: dump
|
102
|
+
.. autofunction:: get_qpy_version
|
102
103
|
|
103
104
|
These functions will raise a custom subclass of :exc:`.QiskitError` if they encounter problems
|
104
105
|
during serialization or deserialization.
|
@@ -139,6 +140,10 @@ load that QPY file with qiskit-terra 0.19.0 and a hypothetical qiskit-terra
|
|
139
140
|
0.29.0. However, loading that QPY file with 0.18.0 is not supported and may not
|
140
141
|
work.
|
141
142
|
|
143
|
+
Note that circuit metadata and custom :class:`.Annotation` objects are serialized and deserialized
|
144
|
+
by user-supplied classes, as the objects themselves are completely user-custom, so the forwards- and
|
145
|
+
backwards-compatibility of these is limited by what the user provides.
|
146
|
+
|
142
147
|
If a feature being loaded is deprecated in the corresponding qiskit release, QPY will
|
143
148
|
raise a :exc:`~.QPYLoadingDeprecatedFeatureWarning` informing of the deprecation period
|
144
149
|
and how the feature will be internally handled.
|
@@ -194,9 +199,21 @@ of QPY in qiskit-terra 0.18.0.
|
|
194
199
|
* - Qiskit (qiskit-terra for < 1.0.0) version
|
195
200
|
- :func:`.dump` format(s) output versions
|
196
201
|
- :func:`.load` maximum supported version (older format versions can always be read)
|
202
|
+
* - 2.1.0
|
203
|
+
- 13, 14, 15
|
204
|
+
- 15
|
205
|
+
* - 2.0.2
|
206
|
+
- 13, 14
|
207
|
+
- 14
|
208
|
+
* - 2.0.1
|
209
|
+
- 13, 14
|
210
|
+
- 14
|
197
211
|
* - 2.0.0
|
198
212
|
- 13, 14
|
199
213
|
- 14
|
214
|
+
* - 1.4.3
|
215
|
+
- 10, 11, 12, 13
|
216
|
+
- 13
|
200
217
|
* - 1.4.2
|
201
218
|
- 10, 11, 12, 13
|
202
219
|
- 13
|
@@ -387,17 +404,175 @@ All values use network byte order [#f1]_ (big endian) for cross platform
|
|
387
404
|
compatibility.
|
388
405
|
|
389
406
|
The file header is immediately followed by the circuit payloads.
|
390
|
-
Each individual circuit is composed of the following parts:
|
407
|
+
Each individual circuit is composed of the following parts in order from top to bottom:
|
408
|
+
|
409
|
+
.. code-block:: text
|
391
410
|
|
392
|
-
|
411
|
+
HEADER
|
412
|
+
METADATA
|
413
|
+
REGISTERS
|
414
|
+
ANNOTATION_HEADER
|
415
|
+
STANDALONE_VARS
|
416
|
+
CUSTOM_DEFINITIONS
|
417
|
+
INSTRUCTIONS
|
393
418
|
|
394
|
-
|
395
|
-
``REGISTERS`` and ``
|
419
|
+
.. versionchanged:: QPY 15
|
420
|
+
``ANNOTATION_HEADER`` was added between ``REGISTERS`` and ``STANDALONE_VARS``.
|
421
|
+
|
422
|
+
.. versionchanged:: QPY 12
|
423
|
+
``STANDALONE_VARS`` was added between ``REGISTERS`` and ``CUSTOM_DEFINITIONS``.
|
396
424
|
|
397
425
|
There is a circuit payload for each circuit (where the total number is dictated
|
398
426
|
by ``num_circuits`` in the file header). There is no padding between the
|
399
427
|
circuits in the data.
|
400
428
|
|
429
|
+
.. _qpy_version_15:
|
430
|
+
|
431
|
+
Version 15
|
432
|
+
----------
|
433
|
+
|
434
|
+
Version 15 adds the concept of custom annotations to the payload format. QPY itself does not
|
435
|
+
specify how annotations are serialized or deserialized, as they are custom user objects. The format
|
436
|
+
does co-operate with sub-serializers, however.
|
437
|
+
|
438
|
+
Version 15 adds the ``ANNOTATION_HEADER`` field between the ``STANDALONE_VARS`` and
|
439
|
+
``CUSTOM_DEFINITIONS`` fields in the top level of a single circuit payload. It modifies the
|
440
|
+
interpretation of one field of the ``INSTRUCTION`` struct in an ABI-compatible manner, and adds a
|
441
|
+
``INSTRUCTION_ANNOTATIONS`` trailer to ``INSTRUCTION`` which is present conditional on a set bit in
|
442
|
+
the ``INSTRUCTION`` payload.
|
443
|
+
|
444
|
+
New ANNOTATION_HEADER
|
445
|
+
~~~~~~~~~~~~~~~~~~~~~
|
446
|
+
|
447
|
+
The ``ANNOTATION_HEADER`` field is a variable-size payload in the header. It begins with an
|
448
|
+
instance of ``ANNOTATION_HEADER_STATIC``, which is the C struct:
|
449
|
+
|
450
|
+
.. code-block:: c
|
451
|
+
|
452
|
+
struct ANNOTATION_HEADER_STATIC {
|
453
|
+
uint32_t num_namespaces;
|
454
|
+
}
|
455
|
+
|
456
|
+
This is immediately followed by ``num_namespaces`` instances of the ``ANNOTATION_STATE`` payload.
|
457
|
+
The order of these is important and should be retained during the deserialization process, as
|
458
|
+
subsequent ``INSTRUCTION_ANNOTATION`` payloads will index into it.
|
459
|
+
|
460
|
+
The ``ANNOTATION_STATE`` payload begins with the fixed C struct:
|
461
|
+
|
462
|
+
.. code-block:: c
|
463
|
+
|
464
|
+
struct ANNOTATION_STATE_HEADER {
|
465
|
+
uint32_t namespace_size;
|
466
|
+
uint64_t state_size;
|
467
|
+
}
|
468
|
+
|
469
|
+
This header is immediately followed by ``namespace_size`` bytes of UTF-8 encoded text, which
|
470
|
+
comprise the namespace. Those bytes are immediately followed by ``state_size`` bytes of arbitrary
|
471
|
+
data. The format of this "state" payload is not defined by QPY. Instead, it is the responsibility
|
472
|
+
of an external object associated with the stored namespace. The format does not dictate how to
|
473
|
+
produce these objects; as annotations are entirely custom, the user must supply the serialization
|
474
|
+
and deserialization methods.
|
475
|
+
|
476
|
+
|
477
|
+
.. _qpy_instruction_v15:
|
478
|
+
|
479
|
+
Changes to INSTRUCTION
|
480
|
+
~~~~~~~~~~~~~~~~~~~~~~
|
481
|
+
|
482
|
+
The ``INSTRUCTION`` struct is modified in an ABI compatible manner to :ref:`its previous definition
|
483
|
+
in version 9 <qpy_instruction_v9>`. The new struct is the C struct (recall that there is no padding
|
484
|
+
between any fields, nor at the end of the struct):
|
485
|
+
|
486
|
+
.. code-block:: c
|
487
|
+
|
488
|
+
struct INSTRUCTION {
|
489
|
+
uint16_t name_size;
|
490
|
+
uint16_t label_size;
|
491
|
+
uint16_t num_parameters;
|
492
|
+
uint32_t num_qargs;
|
493
|
+
uint32_t num_cargs;
|
494
|
+
uint8_t extras_key;
|
495
|
+
uint16_t conditional_reg_name_size;
|
496
|
+
int64_t conditional_value;
|
497
|
+
uint32_t num_ctrl_qubits;
|
498
|
+
uint32_t ctrl_state;
|
499
|
+
}
|
500
|
+
|
501
|
+
where the field ``uint8_t extras_key`` replaces the previous ``uint8_t conditional_key``. The
|
502
|
+
difference is purely in interpretation. The low two bits of the byte are still interpreted as
|
503
|
+
defining the condition and its type. The high bit of the byte is now a flag, indicated whether an
|
504
|
+
``INSTRUCTION_ANNOTATIONS_HEADER`` field is present (if the bit is set) in the trailing data of the
|
505
|
+
``INSTRUCTION`` struct.
|
506
|
+
|
507
|
+
A complete instruction payload appears in the data stream, including trailing objects and without
|
508
|
+
any padding bytes inbetween elements, as:
|
509
|
+
|
510
|
+
.. code-block:: text
|
511
|
+
|
512
|
+
struct INSTRUCTION;
|
513
|
+
uint8_t name[name_size];
|
514
|
+
uint8_t label[label_size];
|
515
|
+
uint8_t register[conditional_reg_name_size]; (1)
|
516
|
+
struct INSTRUCTION_PARAM; (2)
|
517
|
+
struct INSTRUCTION_ARG[num_qargs];
|
518
|
+
struct INSTRUCTION_ARG[num_cargs];
|
519
|
+
struct INSTRUCTION_PARAM[num_parameters];
|
520
|
+
INSTRUCTION_ANNOTATIONS; (3)
|
521
|
+
|
522
|
+
The following notes apply:
|
523
|
+
|
524
|
+
1. if the two low bits of the ``extras_key`` have the value ``2``, indicating the condition is an
|
525
|
+
``EXPRESSION``, the ``conditional_reg_name_size`` is always zero.
|
526
|
+
2. this field is present if and only if the two low bits of the ``extras_key`` have the value ``2``,
|
527
|
+
indicating the condition is an ``EXPRESSION``.
|
528
|
+
3. this field is present if and only if the high bit of the ``extras_key`` is set. This field has
|
529
|
+
a variable size; see :ref:`qpy_instruction_annotations_v15`.
|
530
|
+
|
531
|
+
.. _qpy_instruction_annotations_v15:
|
532
|
+
|
533
|
+
New INSTRUCTION_ANNOTATIONS
|
534
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
535
|
+
|
536
|
+
The ``INSTRUCTION_ANNOTATIONS`` payload begins with the C struct:
|
537
|
+
|
538
|
+
.. code-block:: c
|
539
|
+
|
540
|
+
struct INSTRUCTION_ANNOTATIONS_HEADER {
|
541
|
+
uint32_t num_annotations;
|
542
|
+
}
|
543
|
+
|
544
|
+
This payload is immediately followed by ``num_annotations`` instances of the
|
545
|
+
``INSTRUCTION_ANNOTATION`` payload, which is of a variable size.
|
546
|
+
|
547
|
+
The ``INSRTUCTION_ANNOTATION`` payload is defined by the following C struct plus a trailing number
|
548
|
+
of bytes equal to the ``payload_size``, called ``ANNOTATION_PAYLOAD``.
|
549
|
+
|
550
|
+
.. code-block:: c
|
551
|
+
|
552
|
+
struct INSTRUCTION_ANNOTATION {
|
553
|
+
uint32_t namespace_index;
|
554
|
+
uint32_t payload_size;
|
555
|
+
}
|
556
|
+
|
557
|
+
The ``namespace_index`` is an integer index into the list of defined ``ANNOTATION_NAMESPACE``
|
558
|
+
objects in the ``ANNOTATION_HEADER``. The serialization namespace for an annotation is the UTF-8
|
559
|
+
encoded string in the relevant payload.
|
560
|
+
|
561
|
+
The format of the ``ANNOTATION_PAYLOAD`` object is not specified by QPY. It is defined by an
|
562
|
+
external serialization object associated with the namespace referred to by the ``namespace_index``
|
563
|
+
and its associated serializer state in the ``ANNOTATION_HEADER``.
|
564
|
+
|
565
|
+
|
566
|
+
Changes within PARAM_EXPR_ELEM_V13
|
567
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
568
|
+
|
569
|
+
The struct itself is unchanged. However, for a ``PARAM_EXPR_ELEM_V13`` representing a
|
570
|
+
:meth:`.ParameterExpression.subs` call (with ``op_code = 15``, and therefore ``lhs_type = 'p'`` and
|
571
|
+
``rhs_type = 'n'``), the trailing :ref:`qpy_mapping` now maps keys of the raw bytes of the
|
572
|
+
:class:`.Parameter` UUIDs to the substituted values. Previously (in QPY versions 13 and 14), this
|
573
|
+
mapping stored the parameter names as the keys.
|
574
|
+
|
575
|
+
|
401
576
|
.. _qpy_version_14:
|
402
577
|
|
403
578
|
Version 14
|
@@ -900,6 +1075,7 @@ Python type Type code Payload
|
|
900
1075
|
=========== ========= ============================================================================
|
901
1076
|
|
902
1077
|
|
1078
|
+
.. _qpy_instruction_v9:
|
903
1079
|
|
904
1080
|
Changes to INSTRUCTION
|
905
1081
|
~~~~~~~~~~~~~~~~~~~~~~
|
@@ -941,7 +1117,7 @@ Value Effects
|
|
941
1117
|
|
942
1118
|
2 The instruction has its ``.condition`` field set to a :class:`~.expr.Expr` node. The
|
943
1119
|
``conditional_reg_name_size`` and ``conditional_value`` fields should be ignored. The data
|
944
|
-
following the struct is followed (as in QPY versions less than
|
1120
|
+
following the struct is followed (as in QPY versions less than 9) by ``name_size`` bytes of
|
945
1121
|
UTF-8 string data for the class name and ``label_size`` bytes of UTF-8 string data for the
|
946
1122
|
label (if any). Then, there is one INSTRUCTION_PARAM, which will contain an EXPRESSION. After
|
947
1123
|
that, parsing continues with the INSTRUCTION_ARG structs, as in previous versions of QPY.
|
@@ -1952,7 +2128,7 @@ References
|
|
1952
2128
|
"""
|
1953
2129
|
|
1954
2130
|
from .exceptions import QpyError, UnsupportedFeatureForVersion, QPYLoadingDeprecatedFeatureWarning
|
1955
|
-
from .interface import dump, load
|
2131
|
+
from .interface import dump, load, get_qpy_version
|
1956
2132
|
|
1957
2133
|
# For backward compatibility. Provide, Runtime, Experiment call these private functions.
|
1958
2134
|
from .binary_io import (
|