iqm-client 32.1.1__py3-none-any.whl → 33.0.0__py3-none-any.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.
- iqm/cirq_iqm/devices/iqm_device_metadata.py +2 -1
- iqm/cirq_iqm/examples/demo_common.py +1 -1
- iqm/cirq_iqm/examples/demo_iqm_execution.py +3 -3
- iqm/cirq_iqm/iqm_sampler.py +47 -29
- iqm/cirq_iqm/serialize.py +1 -1
- iqm/cirq_iqm/transpiler.py +3 -1
- iqm/iqm_client/__init__.py +0 -2
- iqm/iqm_client/errors.py +6 -17
- iqm/iqm_client/iqm_client.py +199 -602
- iqm/iqm_client/models.py +20 -611
- iqm/iqm_client/transpile.py +11 -8
- iqm/iqm_client/validation.py +18 -9
- iqm/iqm_server_client/__init__.py +14 -0
- iqm/iqm_server_client/errors.py +6 -0
- iqm/iqm_server_client/iqm_server_client.py +755 -0
- iqm/iqm_server_client/models.py +179 -0
- iqm/iqm_server_client/py.typed +0 -0
- iqm/qiskit_iqm/__init__.py +8 -0
- iqm/qiskit_iqm/examples/bell_measure.py +2 -2
- iqm/qiskit_iqm/examples/transpile_example.py +9 -4
- iqm/qiskit_iqm/fake_backends/fake_adonis.py +2 -1
- iqm/qiskit_iqm/fake_backends/fake_aphrodite.py +2 -1
- iqm/qiskit_iqm/fake_backends/fake_apollo.py +2 -1
- iqm/qiskit_iqm/fake_backends/fake_deneb.py +2 -1
- iqm/qiskit_iqm/fake_backends/iqm_fake_backend.py +8 -7
- iqm/qiskit_iqm/iqm_backend.py +3 -4
- iqm/qiskit_iqm/iqm_circuit_validation.py +8 -7
- iqm/qiskit_iqm/iqm_job.py +106 -88
- iqm/qiskit_iqm/iqm_move_layout.py +2 -1
- iqm/qiskit_iqm/iqm_naive_move_pass.py +114 -55
- iqm/qiskit_iqm/iqm_provider.py +49 -36
- iqm/qiskit_iqm/iqm_target.py +4 -6
- iqm/qiskit_iqm/qiskit_to_iqm.py +62 -25
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/METADATA +4 -14
- iqm_client-33.0.0.dist-info/RECORD +63 -0
- iqm/iqm_client/api.py +0 -90
- iqm/iqm_client/authentication.py +0 -206
- iqm_client-32.1.1.dist-info/RECORD +0 -60
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/AUTHORS.rst +0 -0
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/LICENSE.txt +0 -0
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/WHEEL +0 -0
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/entry_points.txt +0 -0
- {iqm_client-32.1.1.dist-info → iqm_client-33.0.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Copyright 2025 IQM client developers
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
# you may not use this file except in compliance with the License.
|
|
5
|
+
# You may obtain a copy of the License at
|
|
6
|
+
#
|
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
#
|
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
# See the License for the specific language governing permissions and
|
|
13
|
+
# limitations under the License.
|
|
14
|
+
"""Data models used by IQMServerClient."""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from datetime import datetime
|
|
19
|
+
from enum import StrEnum
|
|
20
|
+
from typing import Literal, TypeAlias
|
|
21
|
+
from uuid import UUID
|
|
22
|
+
|
|
23
|
+
from pydantic import BaseModel, Field
|
|
24
|
+
|
|
25
|
+
from iqm.station_control.interface.models import ObservationSetWithObservations
|
|
26
|
+
from iqm.station_control.interface.pydantic_base import PydanticBase
|
|
27
|
+
|
|
28
|
+
CalibrationSet: TypeAlias = ObservationSetWithObservations
|
|
29
|
+
QualityMetricSet: TypeAlias = ObservationSetWithObservations
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
# Keep 'str' for potential new sources
|
|
33
|
+
Source: TypeAlias = Literal["iqm-server", "iqm-station-control"] | str
|
|
34
|
+
"""Type indicating the source of a particular job-related object from the server."""
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class QuantumComputer(PydanticBase):
|
|
38
|
+
"""Quantum computer attributes."""
|
|
39
|
+
|
|
40
|
+
id: UUID
|
|
41
|
+
"""Unique ID of the quantum computer."""
|
|
42
|
+
alias: str
|
|
43
|
+
"""Quantum computer alias that can be used as a substitute for id in API calls."""
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
class ListQuantumComputersResponse(PydanticBase):
|
|
47
|
+
"""Response of GET /v1/quantum-computers"""
|
|
48
|
+
|
|
49
|
+
quantum_computers: list[QuantumComputer]
|
|
50
|
+
"""List of available quantum computers."""
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
class ProgressInfo(PydanticBase):
|
|
54
|
+
"""Progress information about completing an arbitrary task.
|
|
55
|
+
|
|
56
|
+
Used e.g. for tracking job completion.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
value: int
|
|
60
|
+
"""Current progress indicator value."""
|
|
61
|
+
max_value: int
|
|
62
|
+
"""When we hit this, the task is done."""
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
class JobExecution(PydanticBase):
|
|
66
|
+
"""Progress information about job execution."""
|
|
67
|
+
|
|
68
|
+
progress: dict[str, ProgressInfo]
|
|
69
|
+
"""Mapping from label to its progress information (value, max_value)."""
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class JobCompilation(PydanticBase):
|
|
73
|
+
"""Progress information about job compilation."""
|
|
74
|
+
|
|
75
|
+
calibration_set_id: UUID | None = None
|
|
76
|
+
"""ID of the calibration set used by the compiler."""
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class JobMessage(PydanticBase):
|
|
80
|
+
"""Message log for a job."""
|
|
81
|
+
|
|
82
|
+
source: Source
|
|
83
|
+
"""Source of the message."""
|
|
84
|
+
message: str
|
|
85
|
+
"""Content of the message."""
|
|
86
|
+
|
|
87
|
+
def __str__(self) -> str:
|
|
88
|
+
"""Prettyprinting."""
|
|
89
|
+
return f"{self.source}: {self.message}"
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class JobError(PydanticBase):
|
|
93
|
+
"""Error log for a job."""
|
|
94
|
+
|
|
95
|
+
source: Source
|
|
96
|
+
"""Source of the error."""
|
|
97
|
+
message: str
|
|
98
|
+
"""Verbose error message."""
|
|
99
|
+
error_code: str | None = None
|
|
100
|
+
"""Short error code classifying the error category."""
|
|
101
|
+
|
|
102
|
+
def __str__(self) -> str:
|
|
103
|
+
"""Prettyprinting."""
|
|
104
|
+
return f"{self.source}: {self.error_code}: {self.message}"
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class TimelineEntry(BaseModel):
|
|
108
|
+
"""Timeline entry for a job."""
|
|
109
|
+
|
|
110
|
+
source: Source
|
|
111
|
+
"""Source of the timeline entry."""
|
|
112
|
+
status: str
|
|
113
|
+
"""Name of the execution step that was reached."""
|
|
114
|
+
timestamp: datetime
|
|
115
|
+
"""Time at which ``status`` was reached."""
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
class JobStatus(StrEnum):
|
|
119
|
+
"""Job statuses in IQMServer."""
|
|
120
|
+
|
|
121
|
+
WAITING = "waiting"
|
|
122
|
+
"""Job is in a queue, waiting to be executed."""
|
|
123
|
+
PROCESSING = "processing"
|
|
124
|
+
"""Job is being executed."""
|
|
125
|
+
COMPLETED = "completed"
|
|
126
|
+
"""Job has completed successfully."""
|
|
127
|
+
FAILED = "failed"
|
|
128
|
+
"""Job has failed."""
|
|
129
|
+
CANCELLED = "cancelled"
|
|
130
|
+
"""Job has been cancelled by the user or the admin."""
|
|
131
|
+
|
|
132
|
+
@classmethod
|
|
133
|
+
def terminal_statuses(cls) -> frozenset[JobStatus]:
|
|
134
|
+
"""Statuses from which the execution can't continue."""
|
|
135
|
+
return frozenset({cls.COMPLETED, cls.FAILED, cls.CANCELLED})
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
# Note: there is another, related JobData class for StationControlClient
|
|
139
|
+
class JobData(PydanticBase):
|
|
140
|
+
"""Status, artifacts and metadata of a job."""
|
|
141
|
+
|
|
142
|
+
id: UUID
|
|
143
|
+
"""Unique ID of the job."""
|
|
144
|
+
status: JobStatus
|
|
145
|
+
"""Current job status."""
|
|
146
|
+
execution: JobExecution | None = None
|
|
147
|
+
"""Execution information for the job."""
|
|
148
|
+
compilation: JobCompilation | None = None
|
|
149
|
+
"""Compilation information for the job."""
|
|
150
|
+
messages: list[JobMessage] = Field(default=[])
|
|
151
|
+
"""Informational messages for the job."""
|
|
152
|
+
errors: list[JobError] = Field(default=[])
|
|
153
|
+
"""Errors for a failed job."""
|
|
154
|
+
queue_position: int | None = None
|
|
155
|
+
"""Iff the status is JobStatus.WAITING, the number of jobs ahead of this job in the queue.
|
|
156
|
+
Otherwise None."""
|
|
157
|
+
timeline: list[TimelineEntry] = Field(default=[])
|
|
158
|
+
"""Server-side statuses reached by the job so far. May include statuses from several services."""
|
|
159
|
+
|
|
160
|
+
def find_timeline_entry(
|
|
161
|
+
self,
|
|
162
|
+
*,
|
|
163
|
+
status: str,
|
|
164
|
+
source: Source | None = None,
|
|
165
|
+
) -> TimelineEntry | None:
|
|
166
|
+
"""Search the timeline for an entry matching the given criteria.
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
status: Status of the searched timeline entry.
|
|
170
|
+
source: Source of the searched timeline entry. If None, accepts any source.
|
|
171
|
+
|
|
172
|
+
Returns:
|
|
173
|
+
The first matching entry or ``None`` if the job timeline does not have any matching entries.
|
|
174
|
+
|
|
175
|
+
"""
|
|
176
|
+
for timeline_entry in self.timeline:
|
|
177
|
+
if timeline_entry.status == status and (timeline_entry.source == source or source is None):
|
|
178
|
+
return timeline_entry
|
|
179
|
+
return None
|
|
File without changes
|
iqm/qiskit_iqm/__init__.py
CHANGED
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Qiskit adapter for IQM's quantum computers."""
|
|
15
15
|
|
|
16
|
+
import warnings
|
|
17
|
+
|
|
16
18
|
from iqm.qiskit_iqm.fake_backends import IQMErrorProfile, IQMFakeAdonis, IQMFakeAphrodite, IQMFakeApollo, IQMFakeDeneb
|
|
17
19
|
from iqm.qiskit_iqm.fake_backends.iqm_fake_backend import IQMFakeBackend
|
|
18
20
|
from iqm.qiskit_iqm.iqm_circuit import IQMCircuit
|
|
@@ -23,4 +25,10 @@ from iqm.qiskit_iqm.iqm_provider import IQMBackend, IQMProvider, __version__
|
|
|
23
25
|
from iqm.qiskit_iqm.iqm_transpilation import IQMOptimizeSingleQubitGates, optimize_single_qubit_gates
|
|
24
26
|
from iqm.qiskit_iqm.move_gate import MoveGate
|
|
25
27
|
from iqm.qiskit_iqm.transpiler_plugins import * # noqa: F403
|
|
28
|
+
from packaging.version import Version
|
|
26
29
|
from qiskit import __version__ as qiskit_version
|
|
30
|
+
|
|
31
|
+
if Version(qiskit_version) < Version("2.0.0"):
|
|
32
|
+
warnings.warn(
|
|
33
|
+
DeprecationWarning("Support for Qiskit versions < 2.0 is deprecated and will be removed in a future release.")
|
|
34
|
+
)
|
|
@@ -27,7 +27,7 @@ def bell_measure(server_url: str, token: str | None = None, shots: int = 1000) -
|
|
|
27
27
|
"""Execute a quantum circuit that prepares and measures a generalized Bell (aka GHZ) state.
|
|
28
28
|
|
|
29
29
|
Args:
|
|
30
|
-
server_url: URL of the IQM
|
|
30
|
+
server_url: URL of the IQM Server used for execution
|
|
31
31
|
token: API token for authentication. If not given, uses :env:`IQM_TOKEN`.
|
|
32
32
|
shots: Requested number of shots.
|
|
33
33
|
|
|
@@ -66,7 +66,7 @@ def bell_measure(server_url: str, token: str | None = None, shots: int = 1000) -
|
|
|
66
66
|
if __name__ == "__main__":
|
|
67
67
|
argparser = argparse.ArgumentParser()
|
|
68
68
|
argparser.add_argument(
|
|
69
|
-
"--url", required=True, help='IQM
|
|
69
|
+
"--url", required=True, help='IQM Server URL, for example "https://cocos.resonance.meetiqm.com/garnet"'
|
|
70
70
|
)
|
|
71
71
|
argparser.add_argument(
|
|
72
72
|
"--token",
|
|
@@ -18,15 +18,20 @@ https://docs.meetiqm.com/iqm-client/user_guide_qiskit.html
|
|
|
18
18
|
|
|
19
19
|
import argparse
|
|
20
20
|
|
|
21
|
-
from iqm.qiskit_iqm.iqm_provider import IQMProvider
|
|
21
|
+
from iqm.qiskit_iqm.iqm_provider import IQMBackend, IQMProvider
|
|
22
22
|
from qiskit import QuantumCircuit, transpile
|
|
23
23
|
|
|
24
24
|
|
|
25
|
+
def num_connected_qubits(backend: IQMBackend) -> int:
|
|
26
|
+
"""Return the size of the largest connected component of the backend coupling map."""
|
|
27
|
+
return max(backend.coupling_map.connected_components(), key=lambda cmap: cmap.size()).size()
|
|
28
|
+
|
|
29
|
+
|
|
25
30
|
def transpile_example(server_url: str) -> tuple[QuantumCircuit, dict[str, int]]:
|
|
26
31
|
"""Run a GHZ circuit transpiled using the Qiskit transpile function.
|
|
27
32
|
|
|
28
33
|
Args:
|
|
29
|
-
server_url: URL of the IQM
|
|
34
|
+
server_url: URL of the IQM Server used for execution
|
|
30
35
|
|
|
31
36
|
Returns:
|
|
32
37
|
transpiled circuit, a mapping of bitstrings representing qubit measurement results to counts for each result
|
|
@@ -34,7 +39,7 @@ def transpile_example(server_url: str) -> tuple[QuantumCircuit, dict[str, int]]:
|
|
|
34
39
|
"""
|
|
35
40
|
backend = IQMProvider(server_url).get_backend()
|
|
36
41
|
|
|
37
|
-
num_qubits = min(backend
|
|
42
|
+
num_qubits = min(num_connected_qubits(backend), 5) # use at most 5 qubits
|
|
38
43
|
circuit = QuantumCircuit(num_qubits)
|
|
39
44
|
circuit.h(0)
|
|
40
45
|
for i in range(1, num_qubits):
|
|
@@ -51,7 +56,7 @@ if __name__ == "__main__":
|
|
|
51
56
|
argparser = argparse.ArgumentParser()
|
|
52
57
|
argparser.add_argument(
|
|
53
58
|
"--url",
|
|
54
|
-
help="IQM
|
|
59
|
+
help="IQM Server URL",
|
|
55
60
|
# For example https://cocos.resonance.meetiqm.com/garnet
|
|
56
61
|
default="https://<IQM SERVER>",
|
|
57
62
|
)
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Fake backend for IQM's 5-qubit Adonis architecture."""
|
|
15
15
|
|
|
16
|
-
from iqm.iqm_client import StaticQuantumArchitecture
|
|
17
16
|
from iqm.qiskit_iqm.fake_backends.iqm_fake_backend import IQMErrorProfile, IQMFakeBackend
|
|
18
17
|
|
|
18
|
+
from iqm.station_control.interface.models import StaticQuantumArchitecture
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
def IQMFakeAdonis() -> IQMFakeBackend:
|
|
21
22
|
"""Return IQMFakeBackend instance representing IQM's Adonis architecture."""
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Fake (i.e. simulated) backend for IQM's 54-qubit Aphrodite architecture"""
|
|
15
15
|
|
|
16
|
-
from iqm.iqm_client import StaticQuantumArchitecture
|
|
17
16
|
from iqm.qiskit_iqm.fake_backends.iqm_fake_backend import IQMErrorProfile, IQMFakeBackend
|
|
18
17
|
|
|
18
|
+
from iqm.station_control.interface.models import StaticQuantumArchitecture
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
def IQMFakeAphrodite() -> IQMFakeBackend:
|
|
21
22
|
"""Return IQMFakeBackend instance representing IQM's Aphrodite architecture."""
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Fake (i.e. simulated) backend for IQM's 20-qubit Apollo architecture"""
|
|
15
15
|
|
|
16
|
-
from iqm.iqm_client import StaticQuantumArchitecture
|
|
17
16
|
from iqm.qiskit_iqm.fake_backends.iqm_fake_backend import IQMErrorProfile, IQMFakeBackend
|
|
18
17
|
|
|
18
|
+
from iqm.station_control.interface.models import StaticQuantumArchitecture
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
def IQMFakeApollo() -> IQMFakeBackend:
|
|
21
22
|
"""Return IQMFakeBackend instance representing IQM's Apollo architecture."""
|
|
@@ -13,9 +13,10 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Fake backend for IQM's 6-qubit Deneb architecture."""
|
|
15
15
|
|
|
16
|
-
from iqm.iqm_client import StaticQuantumArchitecture
|
|
17
16
|
from iqm.qiskit_iqm.fake_backends.iqm_fake_backend import IQMErrorProfile, IQMFakeBackend
|
|
18
17
|
|
|
18
|
+
from iqm.station_control.interface.models import StaticQuantumArchitecture
|
|
19
|
+
|
|
19
20
|
|
|
20
21
|
def IQMFakeDeneb() -> IQMFakeBackend:
|
|
21
22
|
"""Return IQMFakeBackend instance representing IQM's Deneb architecture."""
|
|
@@ -20,13 +20,6 @@ from dataclasses import dataclass
|
|
|
20
20
|
from itertools import permutations
|
|
21
21
|
from uuid import UUID
|
|
22
22
|
|
|
23
|
-
from iqm.iqm_client import (
|
|
24
|
-
DynamicQuantumArchitecture,
|
|
25
|
-
GateImplementationInfo,
|
|
26
|
-
GateInfo,
|
|
27
|
-
Locus,
|
|
28
|
-
StaticQuantumArchitecture,
|
|
29
|
-
)
|
|
30
23
|
from iqm.qiskit_iqm.iqm_backend import IQM_TO_QISKIT_GATE_NAME, IQMBackendBase
|
|
31
24
|
from iqm.qiskit_iqm.iqm_circuit_validation import validate_circuit
|
|
32
25
|
from iqm.qiskit_iqm.iqm_transpilation import IQMReplaceGateWithUnitaryPass
|
|
@@ -37,6 +30,14 @@ from qiskit_aer import AerSimulator
|
|
|
37
30
|
from qiskit_aer.noise import NoiseModel, QuantumError
|
|
38
31
|
from qiskit_aer.noise.errors import depolarizing_error, thermal_relaxation_error
|
|
39
32
|
|
|
33
|
+
from iqm.station_control.interface.models import (
|
|
34
|
+
DynamicQuantumArchitecture,
|
|
35
|
+
GateImplementationInfo,
|
|
36
|
+
GateInfo,
|
|
37
|
+
Locus,
|
|
38
|
+
StaticQuantumArchitecture,
|
|
39
|
+
)
|
|
40
|
+
|
|
40
41
|
|
|
41
42
|
def _dqa_from_sqa(
|
|
42
43
|
sqa: StaticQuantumArchitecture,
|
iqm/qiskit_iqm/iqm_backend.py
CHANGED
|
@@ -19,14 +19,13 @@ from abc import ABC
|
|
|
19
19
|
import logging
|
|
20
20
|
from typing import Final
|
|
21
21
|
|
|
22
|
-
from iqm.iqm_client import
|
|
23
|
-
DynamicQuantumArchitecture,
|
|
24
|
-
ObservationFinder,
|
|
25
|
-
)
|
|
22
|
+
from iqm.iqm_client import ObservationFinder
|
|
26
23
|
from iqm.qiskit_iqm.iqm_target import IQMTarget
|
|
27
24
|
from qiskit.providers import BackendV2
|
|
28
25
|
from qiskit.transpiler import Target
|
|
29
26
|
|
|
27
|
+
from iqm.station_control.interface.models import DynamicQuantumArchitecture
|
|
28
|
+
|
|
30
29
|
IQM_TO_QISKIT_GATE_NAME: Final[dict[str, str]] = {"prx": "r", "cz": "cz"}
|
|
31
30
|
logger = logging.getLogger(__name__)
|
|
32
31
|
|
|
@@ -13,26 +13,27 @@
|
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
"""Helper functions for circuit validation."""
|
|
15
15
|
|
|
16
|
-
from iqm.iqm_client import Circuit as IQMClientCircuit
|
|
17
|
-
from iqm.iqm_client import MoveGateValidationMode
|
|
18
16
|
from iqm.iqm_client.validation import validate_circuit_instructions
|
|
19
17
|
from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
|
|
20
18
|
from iqm.qiskit_iqm.qiskit_to_iqm import serialize_instructions
|
|
21
19
|
from qiskit import QuantumCircuit
|
|
22
20
|
|
|
21
|
+
from iqm.pulse import Circuit
|
|
22
|
+
from iqm.station_control.interface.models import MoveGateValidationMode
|
|
23
|
+
|
|
23
24
|
|
|
24
25
|
def validate_circuit( # noqa: ANN201
|
|
25
26
|
circuit: QuantumCircuit,
|
|
26
27
|
backend: IQMBackendBase,
|
|
27
28
|
validate_moves: MoveGateValidationMode | None = None,
|
|
28
|
-
|
|
29
|
+
qubit_index_to_name: dict[int, str] | None = None,
|
|
29
30
|
):
|
|
30
31
|
"""Validate a circuit against the backend."""
|
|
31
|
-
if
|
|
32
|
-
|
|
33
|
-
new_circuit =
|
|
32
|
+
if qubit_index_to_name is None:
|
|
33
|
+
qubit_index_to_name = backend._idx_to_qb
|
|
34
|
+
new_circuit = Circuit(
|
|
34
35
|
name="Validation circuit",
|
|
35
|
-
instructions=tuple(serialize_instructions(circuit=circuit, qubit_index_to_name=
|
|
36
|
+
instructions=tuple(serialize_instructions(circuit=circuit, qubit_index_to_name=qubit_index_to_name)),
|
|
36
37
|
metadata=None,
|
|
37
38
|
)
|
|
38
39
|
if validate_moves is None:
|