Skip to content

Commit 76361e7

Browse files
committed
feat(qami): add qami
1 parent d0cf69c commit 76361e7

File tree

2 files changed

+79
-38
lines changed

2 files changed

+79
-38
lines changed

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ requires-python = ">=3.12"
1010

1111
dependencies = [
1212
"yardstiq>=0.1.0",
13-
"scaleway-qaas-client>=0.1.23"
13+
"scaleway-qaas-client>=0.1.23",
14+
"qami,"
1415
]
1516

1617
[project.entry-points."yardstiq.plugins"]

yardstiq_scaleway/scaleway_provider.py

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,37 @@
1-
from typing import Any, Dict, List
1+
import httpx
2+
import time
3+
4+
from typing import List, Union
5+
6+
from qami import (
7+
QuantumProgram,
8+
QuantumProgramResult,
9+
QuantumComputationModel,
10+
QuantumComputationParameters,
11+
)
212

313
from yardstiq.core import (
414
provider,
515
Provider,
616
Backend,
7-
BackendRunResult,
817
BackendAvailability,
9-
ComputationalModel,
1018
)
1119

1220
from scaleway_qaas_client.v1alpha1 import (
1321
QaaSClient,
1422
QaaSPlatform,
1523
QaaSPlatformAvailability,
16-
QaaSJobBackendData,
17-
QaaSJobRunData,
18-
QaaSJobData,
19-
QaaSCircuitData
24+
QaaSJobResult,
2025
)
2126

2227

2328
class ScalewayBackend(Backend):
2429
def __init__(
2530
self, provider: "ScalewayProvider", platform: QaaSPlatform, client: QaaSClient
2631
):
27-
super().__init__(provider=provider, name=platform.name)
32+
super().__init__(
33+
provider=provider, name=platform.name, version=platform.version
34+
)
2835

2936
self.__platform: QaaSPlatform = platform
3037
self.__client: QaaSClient = client
@@ -35,9 +42,11 @@ def allocate(self, **kwargs) -> None:
3542
return
3643

3744
deduplication_id = kwargs.get("deduplication_id", None)
45+
3846
session = self.__client.create_session(
3947
self.__platform.id, deduplication_id=deduplication_id
4048
)
49+
4150
self.__session_id = session.id
4251

4352
def deallocate(self, **kwargs) -> None:
@@ -46,42 +55,73 @@ def deallocate(self, **kwargs) -> None:
4655

4756
self.__client.terminate_session(self.__session_id)
4857

49-
def run(self, model: ComputationalModel, shots : int, **kwargs) -> BackendRunResult:
50-
run_data = QaaSJobRunData(
51-
options={
52-
"shots": shots,
53-
},
54-
circuits=list(
55-
map(
56-
lambda c: QaaSCircuitData(
57-
serialization_format=model.serialization_format,
58-
circuit_serialization=model.serialization,
59-
),
60-
self._circuits,
61-
)
62-
),
63-
)
58+
def run(
59+
self,
60+
program: Union[QuantumProgram, List[QuantumProgram]],
61+
shots: int,
62+
wait: bool,
63+
**kwargs,
64+
) -> List[QuantumProgramResult]:
65+
if not isinstance(program, list):
66+
program = [program]
6467

65-
backend_data = QaaSJobBackendData(
66-
name=self.backend().name,
67-
version=self.backend().version,
68-
)
68+
computation_model = QuantumComputationModel(
69+
programs=program,
70+
backend=None,
71+
client=None,
72+
).to_dict()
6973

70-
data = QaaSJobData.schema().dumps(
71-
QaaSJobData(
72-
backend=backend_data,
73-
run=run_data,
74-
client=None,
75-
)
76-
)
74+
computation_parameters = QuantumComputationParameters(
75+
shots=shots,
76+
).to_dict()
7777

78-
model = self.__client.create_model(model)
78+
model = self.__client.create_model(computation_model)
7979

8080
if not model:
81-
raise RuntimeError("Failed to push circuit data")
81+
raise RuntimeError("Failed to push model data")
8282

8383
job = self.__client.create_job(self.__session_id, model_id=model.id)
8484

85+
if wait:
86+
while job.status in ["waiting", "running"]:
87+
time.sleep(2)
88+
job = self.__client.get_job(job.id)
89+
90+
if job.status == "error":
91+
raise RuntimeError(f"Job failed with error: {job.progress_message}")
92+
93+
raw_results = self.__client.list_job_results(job.id)
94+
95+
program_results = list(
96+
map(
97+
lambda r: QuantumProgramResult.from_json(
98+
self._extract_payload_from_response(r)
99+
),
100+
raw_results,
101+
)
102+
)
103+
104+
if len(program_results) == 1:
105+
return program_results[0]
106+
107+
return program_results
108+
109+
def _extract_payload_from_response(self, job_result: QaaSJobResult) -> str:
110+
result = job_result.result
111+
112+
if result is None or result == "":
113+
url = job_result.url
114+
115+
if url is not None:
116+
resp = httpx.get(url)
117+
resp.raise_for_status()
118+
119+
return resp.text
120+
else:
121+
raise RuntimeError("Got result with empty data and url fields")
122+
else:
123+
return result
124+
85125
@property
86126
def max_qubit_count(self) -> int:
87127
return self.__platform.max_qubit_count
@@ -98,7 +138,7 @@ def availability(self) -> BackendAvailability:
98138
QaaSPlatformAvailability.MAINTENANCE: BackendAvailability.MAINTENANCE,
99139
}
100140
return availability_map.get(
101-
self.__platform.availability, BackendAvailability.UNKOWN_AVAILABILITY
141+
self.__platform.availability, BackendAvailability.UNKNOWN_AVAILABILITY
102142
)
103143

104144

0 commit comments

Comments
 (0)