Skip to content

Commit 94e2af2

Browse files
committed
feat(qio): update to qio
1 parent a890d3c commit 94e2af2

File tree

4 files changed

+54
-109
lines changed

4 files changed

+54
-109
lines changed

examples/run_aqt_estimator.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,7 @@ def cost_function(
6363
Return the estimated expectation value of the Hamiltonian
6464
on the state prepared by the Ansatz circuit.
6565
"""
66-
return float(
67-
estimator.run([(ansatz, hamiltonian, params)]).result().values[0]
68-
)
66+
return float(estimator.run([(ansatz, hamiltonian, params)]).result().values[0])
6967

7068

7169
# Run the VQE using the SciPy minimizer routine

qiskit_scaleway/backends/aqt/backend.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
1514
from qiskit.providers import Options
1615

1716
from qiskit_scaleway.backends import BaseBackend
Lines changed: 51 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Copyright 2024 Scaleway
1+
# Copyright 2025 Scaleway
22
#
33
# Licensed under the Apache License, Version 2.0 (the "License");
44
# you may not use this file except in compliance with the License.
@@ -12,32 +12,31 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414
import time
15-
import zlib
1615
import httpx
17-
import json
18-
import numpy as np
1916
import randomname
2017

2118
from typing import List, Union, Optional, Dict
2219

23-
from qiskit import qasm3, QuantumCircuit
20+
from qiskit import QuantumCircuit
2421
from qiskit.result import Result
2522
from qiskit.providers import JobV1
2623
from qiskit.providers import JobError, JobTimeoutError, JobStatus
2724

2825
from qiskit_scaleway.versions import USER_AGENT
2926

27+
from qio.core import (
28+
QuantumProgram,
29+
QuantumProgramResult,
30+
QuantumComputationModel,
31+
QuantumComputationParameters,
32+
QuantumNoiseModel,
33+
BackendData,
34+
ClientData,
35+
)
36+
3037
from scaleway_qaas_client.v1alpha1 import (
3138
QaaSClient,
3239
QaaSJobResult,
33-
QaaSJobData,
34-
QaaSJobClientData,
35-
QaaSCircuitData,
36-
QaaSJobRunData,
37-
QaaSJobBackendData,
38-
QaaSCircuitSerializationFormat,
39-
QaaSNoiseModelData,
40-
QaaSNoiseModelSerializationFormat,
4140
)
4241

4342

@@ -78,59 +77,39 @@ def submit(self, session_id: str) -> None:
7877
options = self._config.copy()
7978
shots = options.pop("shots")
8079

81-
run_data = QaaSJobRunData(
82-
options={
83-
"shots": shots,
84-
"memory": options.pop("memory", False),
85-
},
86-
circuits=list(
87-
map(
88-
lambda c: QaaSCircuitData(
89-
serialization_format=QaaSCircuitSerializationFormat.QASM_V3,
90-
circuit_serialization=qasm3.dumps(c),
91-
),
92-
self._circuits,
93-
)
94-
),
95-
)
80+
programs = map(lambda c: QuantumProgram.from_qiskit_circuit(c), self._circuits)
9681

9782
noise_model = options.pop("noise_model", None)
9883
if noise_model:
99-
noise_model_dict = _encode_numpy_complex(noise_model.to_dict(False))
100-
noise_model = QaaSNoiseModelData(
101-
serialization_format=QaaSNoiseModelSerializationFormat.AER_COMPRESSED_JSON,
102-
noise_model_serialization=zlib.compress(
103-
json.dumps(noise_model_dict).encode()
104-
),
105-
)
106-
### Uncomment to use standard JSON serialization, provided there is no more issue with AER deserialization logic
107-
# noise_model = QaaSNoiseModelData(
108-
# serialization_format = QaaSNoiseModelSerializationFormat.JSON,
109-
# noise_model_serialization = json.dumps(noise_model.to_dict(True)).encode()
110-
# )
111-
###
112-
113-
backend_data = QaaSJobBackendData(
84+
noise_model = QuantumNoiseModel.from_qiskit_aer_noise_model(noise_model)
85+
86+
backend_data = BackendData(
11487
name=self.backend().name,
11588
version=self.backend().version,
11689
options=options,
90+
frozenset=True,
11791
)
11892

119-
client_data = QaaSJobClientData(
93+
client_data = ClientData(
12094
user_agent=USER_AGENT,
95+
frozenset=True,
12196
)
12297

123-
data = QaaSJobData.schema().dumps(
124-
QaaSJobData(
125-
backend=backend_data,
126-
run=run_data,
127-
client=client_data,
128-
noise_model=noise_model,
129-
)
130-
)
98+
computation_model_dict = QuantumComputationModel(
99+
programs=programs,
100+
backend=backend_data,
101+
client=client_data,
102+
noise_model=noise_model,
103+
frozenset=True,
104+
).to_dict()
105+
106+
computation_parameters_dict = QuantumComputationParameters(
107+
shots=shots,
108+
frozenset=True,
109+
).to_dict()
131110

132111
model = self._client.create_model(
133-
payload=data,
112+
payload=computation_model_dict,
134113
)
135114

136115
if not model:
@@ -140,7 +119,7 @@ def submit(self, session_id: str) -> None:
140119
name=self._name,
141120
session_id=session_id,
142121
model_id=model.id,
143-
parameters={"shots": shots},
122+
parameters=computation_parameters_dict,
144123
).id
145124

146125
def result(
@@ -151,37 +130,28 @@ def result(
151130

152131
job_results = self._wait_for_result(timeout, fetch_interval)
153132

154-
def __make_result_from_payload(payload: str) -> Result:
155-
payload_dict = json.loads(payload)
156-
157-
return Result.from_dict(
158-
{
159-
"results": payload_dict["results"],
160-
"backend_name": self.backend().name,
161-
"backend_version": self.backend().version,
162-
"job_id": self._job_id,
163-
"qobj_id": ", ".join(x.name for x in self._circuits),
164-
"success": payload_dict["success"],
165-
"header": payload_dict.get("header"),
166-
"metadata": payload_dict.get("metadata"),
167-
}
168-
)
169-
170-
qiskit_results = list(
133+
program_results = list(
171134
map(
172-
lambda r: __make_result_from_payload(
173-
self._extract_payload_from_response(r)
135+
lambda r: self._extract_payload_from_response(r).to_qiskit_result(
136+
**{
137+
"backend_name": self.backend().name,
138+
"backend_version": self.backend().version,
139+
"job_id": self._job_id,
140+
"qobj_id": ", ".join(x.name for x in self._circuits),
141+
}
174142
),
175143
job_results,
176144
)
177145
)
178146

179-
if len(qiskit_results) == 1:
180-
return qiskit_results[0]
147+
if len(program_results) == 1:
148+
return program_results[0]
181149

182-
return qiskit_results
150+
return program_results
183151

184-
def _extract_payload_from_response(self, job_result: QaaSJobResult) -> str:
152+
def _extract_payload_from_response(
153+
self, job_result: QaaSJobResult
154+
) -> QuantumProgramResult:
185155
result = job_result.result
186156

187157
if result is None or result == "":
@@ -190,12 +160,11 @@ def _extract_payload_from_response(self, job_result: QaaSJobResult) -> str:
190160
if url is not None:
191161
resp = httpx.get(url)
192162
resp.raise_for_status()
193-
194-
return resp.text
163+
result = resp.text
195164
else:
196-
raise Exception("Got result with empty data and url fields")
197-
else:
198-
return result
165+
raise RuntimeError("Got result with empty data and url fields")
166+
167+
return QuantumProgramResult.from_json(result)
199168

200169
def _wait_for_result(
201170
self, timeout: Optional[int], fetch_interval: int
@@ -217,25 +186,3 @@ def _wait_for_result(
217186
raise JobError("Job error")
218187

219188
time.sleep(fetch_interval)
220-
221-
222-
def _encode_numpy_complex(obj):
223-
"""
224-
Recursively traverses a structure and converts numpy arrays and
225-
complex numbers into a JSON-serializable format.
226-
"""
227-
if isinstance(obj, np.ndarray):
228-
return {
229-
"__ndarray__": True,
230-
"data": _encode_numpy_complex(obj.tolist()), # Recursively encode data
231-
"dtype": obj.dtype.name,
232-
"shape": obj.shape,
233-
}
234-
elif isinstance(obj, (complex, np.complex128)):
235-
return {"__complex__": True, "real": obj.real, "imag": obj.imag}
236-
elif isinstance(obj, dict):
237-
return {key: _encode_numpy_complex(value) for key, value in obj.items()}
238-
elif isinstance(obj, (list, tuple)):
239-
return [_encode_numpy_complex(item) for item in obj]
240-
else:
241-
return obj

requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ qiskit-aer~=0.17
33
randomname>=0.2.1
44
dataclasses-json>=0.6.4
55
dataclasses>=0.6
6-
scaleway-qaas-client>=0.1.23
6+
scaleway-qaas-client>=0.1.23
7+
qio>=0.1.0

0 commit comments

Comments
 (0)