qoro-divi 0.3.3__py3-none-any.whl → 0.3.5__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.
Potentially problematic release.
This version of qoro-divi might be problematic. Click here for more details.
- divi/__init__.py +1 -2
- divi/backends/__init__.py +7 -0
- divi/backends/_circuit_runner.py +46 -0
- divi/{parallel_simulator.py → backends/_parallel_simulator.py} +136 -53
- divi/backends/_qoro_service.py +531 -0
- divi/circuits/__init__.py +5 -0
- divi/circuits/_core.py +226 -0
- divi/{qasm.py → circuits/qasm.py} +21 -2
- divi/{exp → extern}/cirq/_validator.py +9 -7
- divi/qprog/__init__.py +18 -5
- divi/qprog/algorithms/__init__.py +14 -0
- divi/qprog/algorithms/_ansatze.py +311 -0
- divi/qprog/{_qaoa.py → algorithms/_qaoa.py} +69 -41
- divi/qprog/{_vqe.py → algorithms/_vqe.py} +79 -135
- divi/qprog/batch.py +239 -55
- divi/qprog/exceptions.py +9 -0
- divi/qprog/optimizers.py +219 -18
- divi/qprog/quantum_program.py +389 -57
- divi/qprog/workflows/__init__.py +10 -0
- divi/qprog/{_graph_partitioning.py → workflows/_graph_partitioning.py} +3 -34
- divi/qprog/{_qubo_partitioning.py → workflows/_qubo_partitioning.py} +42 -25
- divi/qprog/{_vqe_sweep.py → workflows/_vqe_sweep.py} +59 -26
- divi/reporting/__init__.py +7 -0
- divi/reporting/_pbar.py +112 -0
- divi/{qlogger.py → reporting/_qlogger.py} +37 -2
- divi/{reporter.py → reporting/_reporter.py} +8 -14
- divi/utils.py +49 -10
- {qoro_divi-0.3.3.dist-info → qoro_divi-0.3.5.dist-info}/METADATA +2 -1
- qoro_divi-0.3.5.dist-info/RECORD +69 -0
- divi/_pbar.py +0 -70
- divi/circuits.py +0 -139
- divi/interfaces.py +0 -25
- divi/qoro_service.py +0 -425
- qoro_divi-0.3.3.dist-info/RECORD +0 -62
- /divi/{qpu_system.py → backends/_qpu_system.py} +0 -0
- /divi/{qem.py → circuits/qem.py} +0 -0
- /divi/{exp → extern}/cirq/__init__.py +0 -0
- /divi/{exp → extern}/cirq/_lexer.py +0 -0
- /divi/{exp → extern}/cirq/_parser.py +0 -0
- /divi/{exp → extern}/cirq/_qasm_export.py +0 -0
- /divi/{exp → extern}/cirq/_qasm_import.py +0 -0
- /divi/{exp → extern}/cirq/exception.py +0 -0
- /divi/{exp → extern}/scipy/_cobyla.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/LICENCE.txt +0 -0
- /divi/{exp → extern}/scipy/pyprima/__init__.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/__init__.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/cobyla.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/cobylb.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/geometry.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/initialize.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/trustregion.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/cobyla/update.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/__init__.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/_bounds.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/_linear_constraints.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/_nonlinear_constraints.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/_project.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/checkbreak.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/consts.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/evaluate.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/history.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/infos.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/linalg.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/message.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/powalg.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/preproc.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/present.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/ratio.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/redrho.py +0 -0
- /divi/{exp → extern}/scipy/pyprima/common/selectx.py +0 -0
- {qoro_divi-0.3.3.dist-info → qoro_divi-0.3.5.dist-info}/LICENSE +0 -0
- {qoro_divi-0.3.3.dist-info → qoro_divi-0.3.5.dist-info}/LICENSES/.license-header +0 -0
- {qoro_divi-0.3.3.dist-info → qoro_divi-0.3.5.dist-info}/LICENSES/Apache-2.0.txt +0 -0
- {qoro_divi-0.3.3.dist-info → qoro_divi-0.3.5.dist-info}/WHEEL +0 -0
divi/qoro_service.py
DELETED
|
@@ -1,425 +0,0 @@
|
|
|
1
|
-
# SPDX-FileCopyrightText: 2025 Qoro Quantum Ltd <divi@qoroquantum.de>
|
|
2
|
-
#
|
|
3
|
-
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
-
|
|
5
|
-
import base64
|
|
6
|
-
import gzip
|
|
7
|
-
import json
|
|
8
|
-
import logging
|
|
9
|
-
import time
|
|
10
|
-
from collections.abc import Callable
|
|
11
|
-
from enum import Enum
|
|
12
|
-
from http import HTTPStatus
|
|
13
|
-
|
|
14
|
-
import requests
|
|
15
|
-
from dotenv import dotenv_values
|
|
16
|
-
from requests.adapters import HTTPAdapter, Retry
|
|
17
|
-
|
|
18
|
-
from divi.exp.cirq import validate_qasm_raise
|
|
19
|
-
from divi.interfaces import CircuitRunner
|
|
20
|
-
from divi.qpu_system import QPU, QPUSystem
|
|
21
|
-
|
|
22
|
-
API_URL = "https://app.qoroquantum.net/api"
|
|
23
|
-
MAX_PAYLOAD_SIZE_MB = 0.95
|
|
24
|
-
|
|
25
|
-
session = requests.Session()
|
|
26
|
-
retry_configuration = Retry(
|
|
27
|
-
total=5,
|
|
28
|
-
backoff_factor=0.1,
|
|
29
|
-
status_forcelist=[502],
|
|
30
|
-
allowed_methods=["GET", "POST", "DELETE"],
|
|
31
|
-
)
|
|
32
|
-
|
|
33
|
-
session.mount("http://", HTTPAdapter(max_retries=retry_configuration))
|
|
34
|
-
session.mount("https://", HTTPAdapter(max_retries=retry_configuration))
|
|
35
|
-
|
|
36
|
-
logger = logging.getLogger(__name__)
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
def _raise_with_details(resp: requests.Response):
|
|
40
|
-
try:
|
|
41
|
-
data = resp.json()
|
|
42
|
-
body = json.dumps(data, ensure_ascii=False)
|
|
43
|
-
except ValueError:
|
|
44
|
-
body = resp.text
|
|
45
|
-
msg = f"{resp.status_code} {resp.reason}: {body}"
|
|
46
|
-
raise requests.HTTPError(msg)
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
class JobStatus(Enum):
|
|
50
|
-
PENDING = "PENDING"
|
|
51
|
-
RUNNING = "RUNNING"
|
|
52
|
-
COMPLETED = "COMPLETED"
|
|
53
|
-
FAILED = "FAILED"
|
|
54
|
-
CANCELLED = "CANCELLED"
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
class JobType(Enum):
|
|
58
|
-
EXECUTE = "EXECUTE"
|
|
59
|
-
SIMULATE = "SIMULATE"
|
|
60
|
-
ESTIMATE = "ESTIMATE"
|
|
61
|
-
CIRCUIT_CUT = "CIRCUIT_CUT"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
class MaxRetriesReachedError(Exception):
|
|
65
|
-
"""Exception raised when the maximum number of retries is reached."""
|
|
66
|
-
|
|
67
|
-
def __init__(self, retries):
|
|
68
|
-
self.retries = retries
|
|
69
|
-
self.message = f"Maximum retries reached: {retries} retries attempted"
|
|
70
|
-
super().__init__(self.message)
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def _parse_qpu_systems(json_data: list) -> list[QPUSystem]:
|
|
74
|
-
return [
|
|
75
|
-
QPUSystem(
|
|
76
|
-
name=system_data["name"],
|
|
77
|
-
qpus=[QPU(**qpu) for qpu in system_data.get("qpus", [])],
|
|
78
|
-
access_level=system_data["access_level"],
|
|
79
|
-
)
|
|
80
|
-
for system_data in json_data
|
|
81
|
-
]
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
class QoroService(CircuitRunner):
|
|
85
|
-
|
|
86
|
-
def __init__(
|
|
87
|
-
self,
|
|
88
|
-
auth_token: str | None = None,
|
|
89
|
-
polling_interval: float = 3.0,
|
|
90
|
-
max_retries: int = 5000,
|
|
91
|
-
shots: int = 1000,
|
|
92
|
-
qpu_system_name: str | QPUSystem | None = None,
|
|
93
|
-
use_circuit_packing: bool = False,
|
|
94
|
-
):
|
|
95
|
-
super().__init__(shots=shots)
|
|
96
|
-
|
|
97
|
-
if auth_token is None:
|
|
98
|
-
try:
|
|
99
|
-
auth_token = dotenv_values()["QORO_API_KEY"]
|
|
100
|
-
except KeyError:
|
|
101
|
-
raise ValueError("Qoro API key not provided nor found in a .env file.")
|
|
102
|
-
|
|
103
|
-
self.auth_token = "Bearer " + auth_token
|
|
104
|
-
self.polling_interval = polling_interval
|
|
105
|
-
self.max_retries = max_retries
|
|
106
|
-
self._qpu_system_name = qpu_system_name
|
|
107
|
-
self.use_circuit_packing = use_circuit_packing
|
|
108
|
-
|
|
109
|
-
@property
|
|
110
|
-
def qpu_system_name(self) -> str | QPUSystem | None:
|
|
111
|
-
return self._qpu_system_name
|
|
112
|
-
|
|
113
|
-
@qpu_system_name.setter
|
|
114
|
-
def qpu_system_name(self, system_name: str | QPUSystem | None):
|
|
115
|
-
"""
|
|
116
|
-
Set the QPU system for the service.
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
system_name (str | QPUSystem): The QPU system to set or the name as a string.
|
|
120
|
-
"""
|
|
121
|
-
if isinstance(system_name, str):
|
|
122
|
-
self._qpu_system_name = system_name
|
|
123
|
-
elif isinstance(system_name, QPUSystem):
|
|
124
|
-
self._qpu_system_name = system_name.name
|
|
125
|
-
elif system_name is None:
|
|
126
|
-
self._qpu_system_name = None
|
|
127
|
-
else:
|
|
128
|
-
raise TypeError("Expected a QPUSystem instance or str.")
|
|
129
|
-
|
|
130
|
-
def _make_request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
|
|
131
|
-
"""A centralized helper for making API requests."""
|
|
132
|
-
url = f"{API_URL}/{endpoint}"
|
|
133
|
-
|
|
134
|
-
headers = {"Authorization": self.auth_token}
|
|
135
|
-
|
|
136
|
-
if method.upper() in ["POST", "PUT", "PATCH"]:
|
|
137
|
-
headers["Content-Type"] = "application/json"
|
|
138
|
-
|
|
139
|
-
# Allow overriding default headers
|
|
140
|
-
if "headers" in kwargs:
|
|
141
|
-
headers.update(kwargs.pop("headers"))
|
|
142
|
-
|
|
143
|
-
response = session.request(method, url, headers=headers, **kwargs)
|
|
144
|
-
|
|
145
|
-
# Generic error handling for non-OK statuses
|
|
146
|
-
if response.status_code >= 400:
|
|
147
|
-
raise requests.exceptions.HTTPError(
|
|
148
|
-
f"API Error: {response.status_code} {response.reason} for URL {response.url}"
|
|
149
|
-
)
|
|
150
|
-
|
|
151
|
-
return response
|
|
152
|
-
|
|
153
|
-
def test_connection(self):
|
|
154
|
-
"""Test the connection to the Qoro API"""
|
|
155
|
-
return self._make_request("get", "", timeout=10)
|
|
156
|
-
|
|
157
|
-
def fetch_qpu_systems(self) -> list[QPUSystem]:
|
|
158
|
-
"""
|
|
159
|
-
Get the list of available QPU systems from the Qoro API.
|
|
160
|
-
|
|
161
|
-
Returns:
|
|
162
|
-
List of QPUSystem objects.
|
|
163
|
-
"""
|
|
164
|
-
response = self._make_request("get", "qpusystem/", timeout=10)
|
|
165
|
-
return _parse_qpu_systems(response.json())
|
|
166
|
-
|
|
167
|
-
@staticmethod
|
|
168
|
-
def _compress_data(value) -> bytes:
|
|
169
|
-
return base64.b64encode(gzip.compress(value.encode("utf-8"))).decode("utf-8")
|
|
170
|
-
|
|
171
|
-
def _split_circuits(self, circuits: dict[str, str]) -> list[dict[str, str]]:
|
|
172
|
-
"""
|
|
173
|
-
Splits circuits into chunks by estimating payload size with a simplified,
|
|
174
|
-
consistent overhead calculation.
|
|
175
|
-
Assumes that BASE64 encoding produces ASCI characters, which are 1 byte each.
|
|
176
|
-
"""
|
|
177
|
-
max_payload_bytes = MAX_PAYLOAD_SIZE_MB * 1024 * 1024
|
|
178
|
-
circuit_chunks = []
|
|
179
|
-
current_chunk = {}
|
|
180
|
-
|
|
181
|
-
# Start with size 2 for the opening and closing curly braces '{}'
|
|
182
|
-
current_chunk_size_bytes = 2
|
|
183
|
-
|
|
184
|
-
for key, value in circuits.items():
|
|
185
|
-
compressed_value = self._compress_data(value)
|
|
186
|
-
|
|
187
|
-
item_size_bytes = len(key) + len(compressed_value) + 6
|
|
188
|
-
|
|
189
|
-
# If adding this item would exceed the limit, finalize the current chunk.
|
|
190
|
-
# This check only runs if the chunk is not empty.
|
|
191
|
-
if current_chunk and (
|
|
192
|
-
current_chunk_size_bytes + item_size_bytes > max_payload_bytes
|
|
193
|
-
):
|
|
194
|
-
circuit_chunks.append(current_chunk)
|
|
195
|
-
|
|
196
|
-
# Start a new chunk
|
|
197
|
-
current_chunk = {}
|
|
198
|
-
current_chunk_size_bytes = 2
|
|
199
|
-
|
|
200
|
-
# Add the new item to the current chunk and update its size
|
|
201
|
-
current_chunk[key] = compressed_value
|
|
202
|
-
current_chunk_size_bytes += item_size_bytes
|
|
203
|
-
|
|
204
|
-
# Add the last remaining chunk if it's not empty
|
|
205
|
-
if current_chunk:
|
|
206
|
-
circuit_chunks.append(current_chunk)
|
|
207
|
-
|
|
208
|
-
return circuit_chunks
|
|
209
|
-
|
|
210
|
-
def submit_circuits(
|
|
211
|
-
self,
|
|
212
|
-
circuits: dict[str, str],
|
|
213
|
-
tag: str = "default",
|
|
214
|
-
job_type: JobType = JobType.SIMULATE,
|
|
215
|
-
qpu_system_name: str | None = None,
|
|
216
|
-
override_circuit_packing: bool | None = None,
|
|
217
|
-
):
|
|
218
|
-
"""
|
|
219
|
-
Submit quantum circuits to the Qoro API for execution.
|
|
220
|
-
|
|
221
|
-
Args:
|
|
222
|
-
circuits (dict[str, str]):
|
|
223
|
-
Dictionary mapping unique circuit IDs to QASM circuit strings.
|
|
224
|
-
tag (str, optional):
|
|
225
|
-
Tag to associate with the job for identification. Defaults to "default".
|
|
226
|
-
job_type (JobType, optional):
|
|
227
|
-
Type of job to execute (e.g., SIMULATE, EXECUTE, ESTIMATE, CIRCUIT_CUT). Defaults to JobType.SIMULATE.
|
|
228
|
-
use_packing (bool):
|
|
229
|
-
Whether to use circuit packing optimization. Defaults to False.
|
|
230
|
-
|
|
231
|
-
Raises:
|
|
232
|
-
ValueError: If more than one circuit is submitted for a CIRCUIT_CUT job.
|
|
233
|
-
|
|
234
|
-
Returns:
|
|
235
|
-
str or list[str]:
|
|
236
|
-
The job ID(s) of the created job(s). Returns a single job ID if only one job is created,
|
|
237
|
-
otherwise returns a list of job IDs if the circuits are split into multiple jobs due to payload size.
|
|
238
|
-
"""
|
|
239
|
-
|
|
240
|
-
if job_type == JobType.CIRCUIT_CUT and len(circuits) > 1:
|
|
241
|
-
raise ValueError("Only one circuit allowed for circuit-cutting jobs.")
|
|
242
|
-
|
|
243
|
-
for key, circuit in circuits.items():
|
|
244
|
-
validate_qasm_raise(circuit)
|
|
245
|
-
# if not is_valid_qasm(circuit):
|
|
246
|
-
# raise ValueError(f"Circuit {key} is not a valid QASM string.")
|
|
247
|
-
|
|
248
|
-
circuit_chunks = self._split_circuits(circuits)
|
|
249
|
-
|
|
250
|
-
payload = {
|
|
251
|
-
"shots": self.shots,
|
|
252
|
-
"tag": tag,
|
|
253
|
-
"job_type": job_type.value,
|
|
254
|
-
"qpu_system_name": qpu_system_name or self.qpu_system_name,
|
|
255
|
-
"use_packing": (
|
|
256
|
-
override_circuit_packing
|
|
257
|
-
if override_circuit_packing is not None
|
|
258
|
-
else self.use_circuit_packing
|
|
259
|
-
),
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
job_ids = []
|
|
263
|
-
for chunk in circuit_chunks:
|
|
264
|
-
payload["circuits"] = chunk
|
|
265
|
-
|
|
266
|
-
response = self._make_request(
|
|
267
|
-
"post",
|
|
268
|
-
"job/",
|
|
269
|
-
json=payload,
|
|
270
|
-
timeout=100,
|
|
271
|
-
)
|
|
272
|
-
|
|
273
|
-
if response.status_code == HTTPStatus.CREATED:
|
|
274
|
-
job_ids.append(response.json()["job_id"])
|
|
275
|
-
else:
|
|
276
|
-
_raise_with_details(response)
|
|
277
|
-
|
|
278
|
-
return job_ids if len(job_ids) > 1 else job_ids[0]
|
|
279
|
-
|
|
280
|
-
def delete_job(self, job_ids):
|
|
281
|
-
"""
|
|
282
|
-
Delete a job from the Qoro Database.
|
|
283
|
-
|
|
284
|
-
Args:
|
|
285
|
-
job_id: The ID of the jobs to be deleted
|
|
286
|
-
Returns:
|
|
287
|
-
response: The response from the API
|
|
288
|
-
"""
|
|
289
|
-
if not isinstance(job_ids, list):
|
|
290
|
-
job_ids = [job_ids]
|
|
291
|
-
|
|
292
|
-
responses = [
|
|
293
|
-
self._make_request(
|
|
294
|
-
"delete",
|
|
295
|
-
f"job/{job_id}",
|
|
296
|
-
timeout=50,
|
|
297
|
-
)
|
|
298
|
-
for job_id in job_ids
|
|
299
|
-
]
|
|
300
|
-
|
|
301
|
-
return responses if len(responses) > 1 else responses[0]
|
|
302
|
-
|
|
303
|
-
def get_job_results(self, job_ids):
|
|
304
|
-
"""
|
|
305
|
-
Get the results of a job from the Qoro Database.
|
|
306
|
-
|
|
307
|
-
Args:
|
|
308
|
-
job_id: The ID of the job to get results from
|
|
309
|
-
Returns:
|
|
310
|
-
results: The results of the job
|
|
311
|
-
"""
|
|
312
|
-
if not isinstance(job_ids, list):
|
|
313
|
-
job_ids = [job_ids]
|
|
314
|
-
|
|
315
|
-
responses = [
|
|
316
|
-
self._make_request(
|
|
317
|
-
"get",
|
|
318
|
-
f"job/{job_id}/results",
|
|
319
|
-
timeout=100,
|
|
320
|
-
)
|
|
321
|
-
for job_id in job_ids
|
|
322
|
-
]
|
|
323
|
-
|
|
324
|
-
if all(response.status_code == HTTPStatus.OK for response in responses):
|
|
325
|
-
responses = [response.json() for response in responses]
|
|
326
|
-
return sum(responses, [])
|
|
327
|
-
elif any(
|
|
328
|
-
response.status_code == HTTPStatus.BAD_REQUEST for response in responses
|
|
329
|
-
):
|
|
330
|
-
raise requests.exceptions.HTTPError(
|
|
331
|
-
"400 Bad Request: Job results not available, likely job is still running"
|
|
332
|
-
)
|
|
333
|
-
else:
|
|
334
|
-
for response in responses:
|
|
335
|
-
if response.status_code not in [HTTPStatus.OK, HTTPStatus.BAD_REQUEST]:
|
|
336
|
-
raise requests.exceptions.HTTPError(
|
|
337
|
-
f"{response.status_code}: {response.reason}"
|
|
338
|
-
)
|
|
339
|
-
|
|
340
|
-
def poll_job_status(
|
|
341
|
-
self,
|
|
342
|
-
job_ids: str | list[str],
|
|
343
|
-
loop_until_complete: bool = False,
|
|
344
|
-
on_complete: Callable | None = None,
|
|
345
|
-
verbose: bool = True,
|
|
346
|
-
poll_callback: Callable[[int, str], None] | None = None,
|
|
347
|
-
):
|
|
348
|
-
"""
|
|
349
|
-
Get the status of a job and optionally execute function *on_complete* on the results
|
|
350
|
-
if the status is COMPLETE.
|
|
351
|
-
|
|
352
|
-
Args:
|
|
353
|
-
job_ids: The job id of the jobs to check
|
|
354
|
-
loop_until_complete (bool): A flag to loop until the job is completed
|
|
355
|
-
on_complete (optional): A function to be called when the job is completed
|
|
356
|
-
polling_interval (optional): The time to wait between retries
|
|
357
|
-
verbose (optional): A flag to print the when retrying
|
|
358
|
-
poll_callback (optional): A function for updating progress bars while polling.
|
|
359
|
-
Definition should be `poll_callback(retry_count: int, status: str) -> None`.
|
|
360
|
-
Returns:
|
|
361
|
-
status: The status of the job
|
|
362
|
-
"""
|
|
363
|
-
if not isinstance(job_ids, list):
|
|
364
|
-
job_ids = [job_ids]
|
|
365
|
-
|
|
366
|
-
# Decide once at the start
|
|
367
|
-
if poll_callback:
|
|
368
|
-
update_fn = poll_callback
|
|
369
|
-
elif verbose:
|
|
370
|
-
CYAN = "\033[36m"
|
|
371
|
-
RESET = "\033[0m"
|
|
372
|
-
|
|
373
|
-
update_fn = lambda retry_count, status: logger.info(
|
|
374
|
-
rf"Job {CYAN}{job_ids[0].split('-')[0]}{RESET} is {status}. Polling attempt {retry_count} / {self.max_retries}\r",
|
|
375
|
-
extra={"append": True},
|
|
376
|
-
)
|
|
377
|
-
else:
|
|
378
|
-
update_fn = lambda _, __: None
|
|
379
|
-
|
|
380
|
-
if not loop_until_complete:
|
|
381
|
-
statuses = [
|
|
382
|
-
self._make_request(
|
|
383
|
-
"get",
|
|
384
|
-
f"job/{job_id}/status/",
|
|
385
|
-
timeout=200,
|
|
386
|
-
).json()["status"]
|
|
387
|
-
for job_id in job_ids
|
|
388
|
-
]
|
|
389
|
-
return statuses if len(statuses) > 1 else statuses[0]
|
|
390
|
-
|
|
391
|
-
pending_job_ids = set(job_ids)
|
|
392
|
-
responses = []
|
|
393
|
-
for retry_count in range(1, self.max_retries + 1):
|
|
394
|
-
# Exit early if all jobs are done
|
|
395
|
-
if not pending_job_ids:
|
|
396
|
-
break
|
|
397
|
-
|
|
398
|
-
for job_id in list(pending_job_ids):
|
|
399
|
-
response = self._make_request(
|
|
400
|
-
"get",
|
|
401
|
-
f"job/{job_id}/status/",
|
|
402
|
-
timeout=200,
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
if response.json()["status"] in (
|
|
406
|
-
JobStatus.COMPLETED.value,
|
|
407
|
-
JobStatus.FAILED.value,
|
|
408
|
-
):
|
|
409
|
-
pending_job_ids.remove(job_id)
|
|
410
|
-
responses.append(response)
|
|
411
|
-
|
|
412
|
-
# Exit before sleeping if no jobs are pending
|
|
413
|
-
if not pending_job_ids:
|
|
414
|
-
break
|
|
415
|
-
|
|
416
|
-
time.sleep(self.polling_interval)
|
|
417
|
-
|
|
418
|
-
update_fn(retry_count, response.json()["status"])
|
|
419
|
-
|
|
420
|
-
if not pending_job_ids:
|
|
421
|
-
if on_complete:
|
|
422
|
-
on_complete(responses)
|
|
423
|
-
return JobStatus.COMPLETED
|
|
424
|
-
else:
|
|
425
|
-
raise MaxRetriesReachedError(retry_count)
|
qoro_divi-0.3.3.dist-info/RECORD
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
divi/__init__.py,sha256=WNAlzdjio0M5la_NTGk4-0AFqItI6HEBExRs6ck9j0Y,203
|
|
2
|
-
divi/_pbar.py,sha256=I8AWI93mpcJXIXTIvsa3JghazO65Pmrq-bW2bJTf2Ik,2131
|
|
3
|
-
divi/circuits.py,sha256=OKcwTMXIvCIjvpLvdeQBWGYElcVUNNyA3z8yXnxUXeo,4476
|
|
4
|
-
divi/exp/cirq/__init__.py,sha256=6NjP3TlQn_oNkg8VrKvEIoYQxB5Bx0mLLFOT3SXReTc,371
|
|
5
|
-
divi/exp/cirq/_lexer.py,sha256=x5UArrnN_JEyiq7E02ikq0wdmqZ2vEQ3_FADL1LIhQI,3187
|
|
6
|
-
divi/exp/cirq/_parser.py,sha256=z_bSn4m03-sfRlN8eL99Mo4LnjY-zmR-Xt6UrjzstZc,29279
|
|
7
|
-
divi/exp/cirq/_qasm_export.py,sha256=8C5xLYvIIkQTWWAAYo7ZjwtQjvYXNSflbf5UyUx6YUE,1024
|
|
8
|
-
divi/exp/cirq/_qasm_import.py,sha256=HbehrgfLl3iDdRyWr4o26Bek3ZpN-_dvNVSexl5-aVE,969
|
|
9
|
-
divi/exp/cirq/_validator.py,sha256=552fiXRpiuXc6aoNNXjnv6SWWCAdBAKieQEOTfCQy1s,20484
|
|
10
|
-
divi/exp/cirq/exception.py,sha256=w1w2vSubOGMRmyKBFqXejxfeIAzkPZ6V7gSrDX_ap4A,765
|
|
11
|
-
divi/exp/scipy/_cobyla.py,sha256=cnCf5AsOM8JWIMiujuUbWMNOgmUr3ZET9y04hUyumHs,10937
|
|
12
|
-
divi/exp/scipy/pyprima/LICENCE.txt,sha256=mXN5ssG_U6OR0v0yldznW_PJTtKNZIgu3jDRtRjLDdY,1533
|
|
13
|
-
divi/exp/scipy/pyprima/__init__.py,sha256=WHV_bPKPLakKdP2TdecrbtMrZ7KR3qb1E3m5VkCjLSo,8956
|
|
14
|
-
divi/exp/scipy/pyprima/cobyla/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
|
-
divi/exp/scipy/pyprima/cobyla/cobyla.py,sha256=zIHjhLDkzhijMrzypObgYjQQfelUdxp6VOKQd34m_oU,22281
|
|
16
|
-
divi/exp/scipy/pyprima/cobyla/cobylb.py,sha256=DhOW4SnJ8ihLHybC4-1BK2X-5BFZlndEduuagmXQOVY,42091
|
|
17
|
-
divi/exp/scipy/pyprima/cobyla/geometry.py,sha256=YtGsY-lXAKmsuBj_D59H97Z8acDl7fAJGt4QTEigsiU,10789
|
|
18
|
-
divi/exp/scipy/pyprima/cobyla/initialize.py,sha256=QT9rpkO8IjlljA-z5wPxg7KFWtB_ae38Z7Ww0S-fMpU,9964
|
|
19
|
-
divi/exp/scipy/pyprima/cobyla/trustregion.py,sha256=AD_tdF7VCt6xBrduv0KFr7VgyUoGdIIz4mwde_9dk0g,26021
|
|
20
|
-
divi/exp/scipy/pyprima/cobyla/update.py,sha256=VuwqaE3wXxsGopPAkOAATmesLDUH-8WZrw3iRqu3jzs,14353
|
|
21
|
-
divi/exp/scipy/pyprima/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
|
-
divi/exp/scipy/pyprima/common/_bounds.py,sha256=0tY542ERqX53I5lreyVUy9XVXfNFvt1bx9peKM70U3U,1683
|
|
23
|
-
divi/exp/scipy/pyprima/common/_linear_constraints.py,sha256=piTatWAMPQo-nwFB14VpRQ6JphBgrBL8OjLysBrTlhI,2160
|
|
24
|
-
divi/exp/scipy/pyprima/common/_nonlinear_constraints.py,sha256=evfY-4FWXKcGae658NXfrlSpCtkHRxCqSG-MyO-WDx4,2180
|
|
25
|
-
divi/exp/scipy/pyprima/common/_project.py,sha256=dnQURl2ztxjGDvoYgMZGnEqUGLUoNUvBaLS12p9-qN0,8541
|
|
26
|
-
divi/exp/scipy/pyprima/common/checkbreak.py,sha256=WrW_dAjZI_3iKvvG3eLTJCxcj5HkIksUBtQQ9BUdB_E,3549
|
|
27
|
-
divi/exp/scipy/pyprima/common/consts.py,sha256=PiGCfDRy9fZjmGJBeCg25gULDfe1cv2HkjS6CQujphg,1313
|
|
28
|
-
divi/exp/scipy/pyprima/common/evaluate.py,sha256=vzjNPdGiAFdD8qpUVp_V1b5f3t2pFyr2N-sMSnTE6OI,3156
|
|
29
|
-
divi/exp/scipy/pyprima/common/history.py,sha256=m0cQ7VOGefWWKTPweqx3dvGZiyzGClTB0BjaKY5mOtQ,1362
|
|
30
|
-
divi/exp/scipy/pyprima/common/infos.py,sha256=MzhS3XciMW5fg4ccW8ubZ3Mkdp2qT6sq56GAkYZikXI,704
|
|
31
|
-
divi/exp/scipy/pyprima/common/linalg.py,sha256=HYoy6vYR2AMUVGSKbA8xj9tjvloMofk_s26N34qiFNk,14516
|
|
32
|
-
divi/exp/scipy/pyprima/common/message.py,sha256=G2_hmqxKvZg0aGCXqw3VmXDxrle8k0Grujzb4iiuPLI,10086
|
|
33
|
-
divi/exp/scipy/pyprima/common/powalg.py,sha256=Azla5UC3oPppDcSTub_1auLS_QXQ_aY1Djm4RT3HkV4,6825
|
|
34
|
-
divi/exp/scipy/pyprima/common/preproc.py,sha256=Ye62rhEilf3ah9aiGc6cSLZg77_qAi3FPK2r4XvPxGk,14929
|
|
35
|
-
divi/exp/scipy/pyprima/common/present.py,sha256=caedmqSB5ggGXNfky0A6v6FAdyaEGrbMEJqNh5Cf6l4,147
|
|
36
|
-
divi/exp/scipy/pyprima/common/ratio.py,sha256=taadehpW0c3ULUggH5frIMpvTom53dsEhvFaXrIKvOI,1833
|
|
37
|
-
divi/exp/scipy/pyprima/common/redrho.py,sha256=J6rJILcOoCeo942LUAXxpUvKLarUGNCGdC-zcmIlVHE,1264
|
|
38
|
-
divi/exp/scipy/pyprima/common/selectx.py,sha256=mXVS2L6AuTmbOhpp1KlXwOBR54ttnbjwagYfnXhezJY,14713
|
|
39
|
-
divi/interfaces.py,sha256=P-8lekQIGwbhHv4ewfMFtKYIjmQHu7nmscwAmxsx72U,594
|
|
40
|
-
divi/parallel_simulator.py,sha256=2JCwmootXLtDplplEqtykKc8HiYe6G0zKWemIb-IIdE,8947
|
|
41
|
-
divi/qasm.py,sha256=lfWky4E9qetotVo8BII58svutVVZEV14BntoC14bo40,7384
|
|
42
|
-
divi/qem.py,sha256=o6rMPUcxLuCBitBb8-QcxveUiKZVsP3HMamxyVFLi6M,6805
|
|
43
|
-
divi/qlogger.py,sha256=TcZMaNZXDHguKJGLD6t2bEmP25rkRQVaSS8FLs9U-lI,3822
|
|
44
|
-
divi/qoro_service.py,sha256=CASWEE6ySlFeQ6pHeOZJUUuwnldEVsPakn_4jTFPnX0,14087
|
|
45
|
-
divi/qprog/__init__.py,sha256=av3I0i3VldwblycfQjcXcJHGVY1m05rnsZ0R5iGMCwk,546
|
|
46
|
-
divi/qprog/_graph_partitioning.py,sha256=cYeHQ2VJAeOzooO43dPfWdXjRZPF_UmHR_H2D7VIpnU,23666
|
|
47
|
-
divi/qprog/_qaoa.py,sha256=Cq1AnaS386iGEv8OiHhSkyGkMG1MwfX3_mq2jBXavgI,15950
|
|
48
|
-
divi/qprog/_qubo_partitioning.py,sha256=h2QPDm1pzNYzsrvw0WZ04fb-nOzj8xFqf5YZqOU5FHk,7470
|
|
49
|
-
divi/qprog/_vqe.py,sha256=21KVvf40UGwxuJQ0OJ1YuiFctvEVbJRklilpxgopnkA,10069
|
|
50
|
-
divi/qprog/_vqe_sweep.py,sha256=T5tXVOENn4VlzwUxSR0SGbv1EWVRdy4H9m1M_sLElCk,17286
|
|
51
|
-
divi/qprog/batch.py,sha256=jxeOO5xFecCCmA82GDAtg3mA8PeW_c5O5ooqEcb2-Bg,10093
|
|
52
|
-
divi/qprog/optimizers.py,sha256=sbOxd9VgMroZn1llN5wyIMLEM-a4x_YKJpt34ApaKX8,6453
|
|
53
|
-
divi/qprog/quantum_program.py,sha256=D2L1zjvW_G3O0oNgty3Y_QhIGrJz0V4rzcz6VSoXFME,14779
|
|
54
|
-
divi/qpu_system.py,sha256=teVeG18ukyzMFgbPSr4BLx4MJUHVK382RqZMOy2voFk,374
|
|
55
|
-
divi/reporter.py,sha256=AgB2Mno1sIXF-VhOi8i-LGuWG5FMG1HelMw5cMc84HM,2977
|
|
56
|
-
divi/utils.py,sha256=EEyGakoz33AvU0Rq7iijL8AULMg4FGcGBtmOlpSw-tY,3603
|
|
57
|
-
qoro_divi-0.3.3.dist-info/LICENSE,sha256=NS4JlQrgNwg1bvB3kE5shE-P4cJgnntgl-kClbOpG_Q,10760
|
|
58
|
-
qoro_divi-0.3.3.dist-info/LICENSES/.license-header,sha256=2jN_xtJscqP8LG-NaveY2KHUkfRCC543Y_XjOyKEfWY,105
|
|
59
|
-
qoro_divi-0.3.3.dist-info/LICENSES/Apache-2.0.txt,sha256=yoILHpvVuguUBpk8UwMnzJbcHUUyst9iGNNuEwUtWVc,10270
|
|
60
|
-
qoro_divi-0.3.3.dist-info/METADATA,sha256=txN4vgtVVbI_PuH1vtN70jRHY21S7WL35Bj1eFOxgBA,2428
|
|
61
|
-
qoro_divi-0.3.3.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
62
|
-
qoro_divi-0.3.3.dist-info/RECORD,,
|
|
File without changes
|
/divi/{qem.py → circuits/qem.py}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|