iqm-pulla 11.17.0__py3-none-any.whl → 12.0.1__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/pulla/utils_qiskit.py CHANGED
@@ -17,6 +17,7 @@ from __future__ import annotations
17
17
 
18
18
  from collections import Counter
19
19
  from collections.abc import Collection, Sequence
20
+ from datetime import date
20
21
  from typing import TYPE_CHECKING
21
22
 
22
23
  from iqm.qiskit_iqm.iqm_backend import IQMBackendBase
@@ -27,14 +28,14 @@ from qiskit.providers import JobStatus, JobV1, Options
27
28
  from qiskit.result import Counts, Result
28
29
 
29
30
  from iqm.cpc.interface.compiler import Circuit, CircuitExecutionOptions, HeraldingMode
30
- from iqm.pulla.interface import StationControlResult, TaskStatus
31
+ from iqm.pulla.pulla import JobStatus as IQMServerJobStatus
31
32
 
32
33
  if TYPE_CHECKING:
33
34
  from iqm.qiskit_iqm.iqm_backend import DynamicQuantumArchitecture
34
35
  from iqm.qiskit_iqm.iqm_provider import IQMBackend
35
36
 
36
37
  from iqm.cpc.compiler.compiler import Compiler
37
- from iqm.pulla.pulla import Pulla
38
+ from iqm.pulla.pulla import Pulla, SweepJob
38
39
 
39
40
 
40
41
  def qiskit_circuits_to_pulla(
@@ -105,41 +106,36 @@ def qiskit_to_pulla(
105
106
 
106
107
  # create a compiler containing all the required station information
107
108
  compiler = pulla.get_standard_compiler(
108
- calibration_set=pulla.fetch_calibration_set_by_id(run_request.calibration_set_id),
109
+ calibration_set_values=pulla.fetch_calibration_set_values_by_id(run_request.calibration_set_id),
109
110
  )
110
- compiler.component_mapping = (
111
- None
112
- if run_request.qubit_mapping is None
113
- else {m.logical_name: m.physical_name for m in run_request.qubit_mapping}
114
- )
115
-
111
+ compiler.component_mapping = run_request.qubit_mapping
116
112
  # We can be certain run_request contains only Circuit objects, because we created it
117
113
  # right in this method with qiskit.QuantumCircuit objects
118
114
  circuits: list[Circuit] = [c for c in run_request.circuits if isinstance(c, Circuit)]
119
115
  return circuits, compiler
120
116
 
121
117
 
122
- def station_control_result_to_qiskit(
123
- station_control_result: StationControlResult,
118
+ def sweep_job_to_qiskit(
119
+ job: SweepJob,
124
120
  *,
125
121
  shots: int,
126
122
  execution_options: CircuitExecutionOptions,
127
123
  ) -> Result:
128
- """Convert a Station Control result to a Qiskit Result.
124
+ """Convert a completed Pulla job to a Qiskit Result.
129
125
 
130
126
  Args:
131
- station_control_result: The Station Control result to convert.
132
- shots: number of shots requested
127
+ job: The completed job to convert.
128
+ shots: Number of shots requested.
133
129
  execution_options: Circuit execution options used to produce the result.
134
130
 
135
131
  Returns:
136
132
  The equivalent Qiskit Result.
137
133
 
138
134
  """
139
- if station_control_result.result is None:
135
+ result = job.result()
136
+ if result is None:
140
137
  raise ValueError(
141
- f"Cannot format station control result without result."
142
- f'Job status is "{station_control_result.status.value.upper()}"'
138
+ f'Cannot format Qiskit result without result measurements. Job status is "{job.status.upper()}"'
143
139
  )
144
140
 
145
141
  used_heralding = execution_options.heralding_mode == HeraldingMode.NONE
@@ -149,19 +145,22 @@ def station_control_result_to_qiskit(
149
145
  # TODO: Proper naming instead of "index"
150
146
  (
151
147
  f"{index}",
152
- IQMJob._format_measurement_results(
148
+ IQMJob._iqm_format_measurement_results(
153
149
  circuit_measurements, requested_shots=shots, expect_exact_shots=used_heralding
154
150
  ),
155
151
  )
156
- for index, circuit_measurements in enumerate(station_control_result.result)
152
+ for index, circuit_measurements in enumerate(result)
157
153
  ]
158
154
 
159
155
  result_dict = {
160
- "backend_name": "",
156
+ "backend_name": "IQMPullaBackend",
161
157
  "backend_version": "",
162
158
  "qobj_id": "",
163
- "job_id": str(station_control_result.sweep_id),
164
- "success": station_control_result.status == TaskStatus.READY,
159
+ "job_id": str(job.job_id),
160
+ "success": job.status == IQMServerJobStatus.COMPLETED,
161
+ "date": date.today().isoformat(),
162
+ "status": str(job.status),
163
+ "timeline": job.data.timeline.copy(),
165
164
  "results": [
166
165
  {
167
166
  "shots": len(measurement_results),
@@ -172,19 +171,10 @@ def station_control_result_to_qiskit(
172
171
  "metadata": {},
173
172
  },
174
173
  "header": {"name": name},
175
- "calibration_set_id": None,
176
- # TODO: calibration set id is known to Pulla, but not the compiler; this is probably good, because
177
- # the compiler is not conceptually linked to the storage of calibration data (id being the property of
178
- # the storage). We need to find a nice way to pass calibration set id to this function.
174
+ "calibration_set_id": job.data.compilation.calibration_set_id if job.data.compilation else None,
179
175
  }
180
176
  for name, measurement_results in batch_results
181
177
  ],
182
- "date": None,
183
- "status": station_control_result.status.value,
184
- "timestamps": {
185
- "start_time": station_control_result.start_time,
186
- "end_time": station_control_result.end_time,
187
- },
188
178
  }
189
179
  return Result.from_dict(result_dict)
190
180
 
@@ -200,26 +190,27 @@ class IQMPullaBackend(IQMBackendBase):
200
190
  """
201
191
 
202
192
  def __init__(self, architecture: DynamicQuantumArchitecture, pulla: Pulla, compiler: Compiler):
203
- super().__init__(architecture)
193
+ super().__init__(architecture, name="IQMPullaBackend")
204
194
  self.pulla = pulla
205
- self.name = "IQMPullaBackend"
206
195
  self.compiler = compiler
207
196
 
208
- def run(self, run_input, **options): # noqa: ANN001, ANN201
197
+ def run(self, run_input: QuantumCircuit | list[QuantumCircuit], shots: int = 1024, **options) -> DummyJob:
209
198
  # Convert Qiskit circuits to Pulla circuits
210
199
  pulla_circuits = qiskit_circuits_to_pulla(run_input, self._idx_to_qb)
211
200
 
212
201
  # Compile the circuits, build settings and execute
213
202
  playlist, context = self.compiler.compile(pulla_circuits)
214
- shots = options.get("shots")
215
203
  settings, context = self.compiler.build_settings(context, shots=shots)
216
- # Get the response data from Station Control
217
- response_data = self.pulla.execute(playlist, context, settings, verbose=False)
204
+
205
+ # submit the playlist for execution
206
+ job = self.pulla.submit_playlist(playlist, settings, context=context)
207
+ # wait for the job to finish, no timeout (user can use Ctrl-C to stop)
208
+ # TODO it would be better if we did not wait and instead returned a Qiskit JobV1 containing
209
+ # a SweepJob that can be used to actually track the job.
210
+ job.wait_for_completion(timeout_secs=0.0)
218
211
 
219
212
  # Convert the response data to a Qiskit result
220
- qiskit_result = station_control_result_to_qiskit(
221
- response_data, shots=shots, execution_options=context["options"]
222
- )
213
+ qiskit_result = sweep_job_to_qiskit(job, shots=shots, execution_options=context["options"])
223
214
 
224
215
  # Return a dummy job object that can be used to retrieve the result
225
216
  dummy_job = DummyJob(self, qiskit_result)
@@ -227,7 +218,7 @@ class IQMPullaBackend(IQMBackendBase):
227
218
 
228
219
  @classmethod
229
220
  def _default_options(cls) -> Options:
230
- return Options(shots=1024)
221
+ return Options()
231
222
 
232
223
  @property
233
224
  def max_circuits(self) -> int | None:
@@ -240,15 +231,15 @@ class DummyJob(JobV1):
240
231
  The ``job_id`` is the same as the ``sweep_id`` of the ``StationControlResult``.
241
232
  """
242
233
 
243
- def __init__(self, backend, qiskit_result): # noqa: ANN001
234
+ def __init__(self, backend: IQMBackend, qiskit_result: Result) -> None:
244
235
  super().__init__(backend=backend, job_id=qiskit_result.job_id)
245
236
  self.qiskit_result = qiskit_result
246
237
 
247
- def result(self): # noqa: ANN201
238
+ def result(self) -> Result:
248
239
  return self.qiskit_result
249
240
 
250
- def status(self): # noqa: ANN201
241
+ def status(self) -> JobStatus:
251
242
  return JobStatus.DONE
252
243
 
253
- def submit(self): # noqa: ANN201
244
+ def submit(self) -> None:
254
245
  return None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: iqm-pulla
3
- Version: 11.17.0
3
+ Version: 12.0.1
4
4
  Summary: Client library for pulse-level access to an IQM quantum computer
5
5
  Author-email: IQM Finland Oy <developers@meetiqm.com>
6
6
  License: Apache License
@@ -205,42 +205,33 @@ License: Apache License
205
205
  See the License for the specific language governing permissions and
206
206
  limitations under the License.
207
207
 
208
- Project-URL: Documentation, https://iqm-finland.github.io/docs/iqm-pulla/
208
+ Project-URL: Documentation, https://docs.meetiqm.com/iqm-pulla/
209
209
  Project-URL: Homepage, https://pypi.org/project/iqm-pulla/
210
210
  Classifier: Development Status :: 4 - Beta
211
211
  Classifier: Programming Language :: Python :: 3 :: Only
212
212
  Classifier: Topic :: Scientific/Engineering :: Physics
213
213
  Classifier: Intended Audience :: Science/Research
214
214
  Classifier: License :: OSI Approved :: Apache Software License
215
- Requires-Python: <3.12,>=3.11
215
+ Requires-Python: <3.13,>=3.11
216
216
  Description-Content-Type: text/x-rst
217
217
  License-File: LICENSE.txt
218
218
  License-File: AUTHORS.rst
219
- Requires-Dist: iqm-exa-common <28,>=27
220
- Requires-Dist: iqm-station-control-client <12,>=11
221
- Requires-Dist: iqm-pulse <13,>=12
222
219
  Requires-Dist: iqm-data-definitions <3.0,>=2.18
223
220
  Requires-Dist: pylatexenc ==2.10
224
221
  Requires-Dist: pydantic <3.0,>=2.10.4
222
+ Requires-Dist: iqm-client <34,>=33.0.1
223
+ Requires-Dist: iqm-exa-common <28,>=27.4.1
224
+ Requires-Dist: iqm-pulse <13,>=12.7.1
225
+ Requires-Dist: iqm-station-control-client <13,>=12.0.1
225
226
  Provides-Extra: notebook
226
- Requires-Dist: iqm-exa-common <28,>=27 ; extra == 'notebook'
227
- Requires-Dist: iqm-station-control-client <12,>=11 ; extra == 'notebook'
228
- Requires-Dist: iqm-pulse <13,>=12 ; extra == 'notebook'
229
227
  Requires-Dist: notebook <7,>=6.4.11 ; extra == 'notebook'
230
228
  Requires-Dist: matplotlib <4,>=3.6.3 ; extra == 'notebook'
231
229
  Requires-Dist: nbclient ~=0.5.10 ; extra == 'notebook'
232
230
  Provides-Extra: qir
233
- Requires-Dist: iqm-exa-common <28,>=27 ; extra == 'qir'
234
- Requires-Dist: iqm-station-control-client <12,>=11 ; extra == 'qir'
235
- Requires-Dist: iqm-pulse <13,>=12 ; extra == 'qir'
236
231
  Requires-Dist: iqm-pyqir ==0.12.0 ; extra == 'qir'
237
- Requires-Dist: iqm-qiskit-qir ==0.8.0 ; extra == 'qir'
232
+ Requires-Dist: qiskit <2.2,>=1.0 ; extra == 'qir'
238
233
  Provides-Extra: qiskit
239
- Requires-Dist: iqm-exa-common <28,>=27 ; extra == 'qiskit'
240
- Requires-Dist: iqm-station-control-client <12,>=11 ; extra == 'qiskit'
241
- Requires-Dist: iqm-pulse <13,>=12 ; extra == 'qiskit'
242
- Requires-Dist: iqm-client <33,>=32 ; extra == 'qiskit'
243
- Requires-Dist: iqm-client[qiskit] <33,>=32 ; extra == 'qiskit'
234
+ Requires-Dist: iqm-client[qiskit] <34,>=33.0.1 ; extra == 'qiskit'
244
235
 
245
236
  IQM Pulla
246
237
  #########
@@ -286,11 +277,11 @@ e2e testing is execution of all user guides (Jupyter notebooks). User guides cov
286
277
  so we achieve two things: end-to-end-test Pulla as a client library, and make sure the user guides are correct.
287
278
  (Server-side use of Pulla is e2e-tested as part of CoCoS.)
288
279
 
289
- You have to provide CoCoS and Station Control URLs as environment variables:
280
+ You have to provide IQM Server URL as environment variable:
290
281
 
291
282
  .. code-block:: bash
292
283
 
293
- COCOS_URL=<COCOS_URL> STATION_CONTROL_URL=<SC_URL> tox -e e2e
284
+ IQM_SERVER_URL=<IQM_SERVER_URL> tox -e e2e
294
285
 
295
286
  Notebooks are executed using `jupyter execute` command. It does not print any output if there are no errors. If you want
296
287
  to run a particular notebook and see the output cells printed in the terminal, you can use ``nbconvert`` with ``jq``
@@ -0,0 +1,27 @@
1
+ iqm/cpc/__init__.py,sha256=mml8qMgjIQcfcfumrYu2lIfl30ZPSwaN3adn8CdRd3w,1079
2
+ iqm/cpc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ iqm/cpc/compiler/__init__.py,sha256=ieYyHzb2IyevDm5swU--rPMsh5GdUtLrw8773Cd0ens,678
4
+ iqm/cpc/compiler/compiler.py,sha256=hnS-3HWUWe92rxg4K-HtPSK_0p2Yarqj5tJrWYnAj3o,22338
5
+ iqm/cpc/compiler/dd.py,sha256=F665HjKZbSC_Jlvkn9bRauMYiv7uDBtIfQ-o2yKXtaY,21820
6
+ iqm/cpc/compiler/errors.py,sha256=tz-8g1QtDvCAPmAjjCYK3FoULrazkpSTmXIvyqukaT4,1949
7
+ iqm/cpc/compiler/standard_stages.py,sha256=MjhdjXmF9SSc9acaVITC3yVt8od2xK4o2SjKYqHXYm8,35451
8
+ iqm/cpc/compiler/station_settings.py,sha256=iS7z9rRQpSx5SVWsICDOOX__u9-VOT527VfswtxujEM,18711
9
+ iqm/cpc/interface/__init__.py,sha256=mvhNx1I9K5Sg40CwPntWj35M3Bni__23PWEw_qYaXtQ,611
10
+ iqm/cpc/interface/compiler.py,sha256=LTsxIy8RfS7O_Y2ZApMUuSLKG-1hRlfbwC7_wAsprd8,5758
11
+ iqm/pulla/__init__.py,sha256=fj5Qh8R9K-z6q5g9-CySBZsG8d33nU7hCHrqIIB8_-0,901
12
+ iqm/pulla/calibration.py,sha256=9Dp7-gIyj8ppIJujmUjXYk0i7xDepes405lUXlLeJQU,3375
13
+ iqm/pulla/interface.py,sha256=xX9peCpOfc-AcOvrWJcGGGeJ5seiVuqbN9h87t1oH-U,1826
14
+ iqm/pulla/pulla.py,sha256=b5lsrMo04CB8cjdhcrgmGMb-Yhw9siNpqF-2mKTVww8,13219
15
+ iqm/pulla/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ iqm/pulla/quantum_architecture.py,sha256=jj9zqK9CcODedR69p8zLSj3qDfzIxI_f9rb8s07GKaM,6377
17
+ iqm/pulla/utils.py,sha256=By-VFbKAuyaPEac73FuP64r9h5oFm76n_6BvK_Gq1IY,28874
18
+ iqm/pulla/utils_cirq.py,sha256=VtdO356D2RAh2lSVdaPm3ClJ9-nvC4jzhR9hP5QSQhI,793
19
+ iqm/pulla/utils_dd.py,sha256=SxYAuRBgvYELKjeXpFbP4mM0xCCivDk7WUHw7oEXfMo,1695
20
+ iqm/pulla/utils_qir.py,sha256=4jlzN9bZK6_BX5tlAcSbZosKTxAbAAwOfIrd0GgZZ0Y,11625
21
+ iqm/pulla/utils_qiskit.py,sha256=y6B0ByuUXMn75z0wncuANlirgrlZxYGbt2QrMnhxso4,9099
22
+ iqm_pulla-12.0.1.dist-info/AUTHORS.rst,sha256=iCStz7WP5Jk7uMnn9jRA4ybS14X4yeUW2SsWE-OTaRk,328
23
+ iqm_pulla-12.0.1.dist-info/LICENSE.txt,sha256=cCj_biRA4Q8A77vxR8AuvAf-DZ5G79yxR_3lYY6TrmA,11333
24
+ iqm_pulla-12.0.1.dist-info/METADATA,sha256=AqLxmi9u1JX2z3SzOy5IgBMvDo3QqhFeEQjkfftSwsI,17100
25
+ iqm_pulla-12.0.1.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
26
+ iqm_pulla-12.0.1.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
27
+ iqm_pulla-12.0.1.dist-info/RECORD,,
@@ -1,27 +0,0 @@
1
- iqm/cpc/__init__.py,sha256=mml8qMgjIQcfcfumrYu2lIfl30ZPSwaN3adn8CdRd3w,1079
2
- iqm/cpc/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- iqm/cpc/compiler/__init__.py,sha256=ieYyHzb2IyevDm5swU--rPMsh5GdUtLrw8773Cd0ens,678
4
- iqm/cpc/compiler/compiler.py,sha256=NRmy_G4gECUWT1916iNLsI0NMAt2Nh5ZZXtiNzAw9R8,22398
5
- iqm/cpc/compiler/dd.py,sha256=Kf5fIZtLHT74oiVpF1vtVNN0mbrjc2KPwVJL0sSSMzE,21802
6
- iqm/cpc/compiler/errors.py,sha256=tz-8g1QtDvCAPmAjjCYK3FoULrazkpSTmXIvyqukaT4,1949
7
- iqm/cpc/compiler/standard_stages.py,sha256=wW_pvSwrth9PdTLeTunCKNhz33xPXxJ0f9K8918O1pw,34776
8
- iqm/cpc/compiler/station_settings.py,sha256=KUq_ZswTYE4AsS6LaKXRwlPbP0jsZ0j7pH2qQv0ifrc,18621
9
- iqm/cpc/interface/__init__.py,sha256=mvhNx1I9K5Sg40CwPntWj35M3Bni__23PWEw_qYaXtQ,611
10
- iqm/cpc/interface/compiler.py,sha256=zxUyalyiBIQA9EUK_fDGNq0SZ5OwfxQdB6Xk5BDDMVk,9797
11
- iqm/pulla/__init__.py,sha256=fj5Qh8R9K-z6q5g9-CySBZsG8d33nU7hCHrqIIB8_-0,901
12
- iqm/pulla/calibration.py,sha256=c_SNlTxXC0y-ahDY7JY53N7SofU5WUWMrNBogtdfHl4,4523
13
- iqm/pulla/interface.py,sha256=XZ_uOWyxlZBmil5-Z02R6rZ1dsR5t43xr6oL01DAows,3614
14
- iqm/pulla/pulla.py,sha256=kgcyoMe9a9VvD9Y7HLvFdaQaax8vJkP_OVRd7sftvjo,16166
15
- iqm/pulla/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- iqm/pulla/quantum_architecture.py,sha256=jj9zqK9CcODedR69p8zLSj3qDfzIxI_f9rb8s07GKaM,6377
17
- iqm/pulla/utils.py,sha256=gRl_IbNk_Kom9iZryHX6CjxNRIlCppBl3-ot7_766Fw,28644
18
- iqm/pulla/utils_cirq.py,sha256=VtdO356D2RAh2lSVdaPm3ClJ9-nvC4jzhR9hP5QSQhI,793
19
- iqm/pulla/utils_dd.py,sha256=SxYAuRBgvYELKjeXpFbP4mM0xCCivDk7WUHw7oEXfMo,1695
20
- iqm/pulla/utils_qir.py,sha256=uNEiqBczv7rX8tAqcg7TX-si0P-ZdDcPTMOVfi5eb28,11567
21
- iqm/pulla/utils_qiskit.py,sha256=pbb2fEJAdxqd6hW9_Qgvpvy0P2H81zTJ1QLahe4Tx6U,9482
22
- iqm_pulla-11.17.0.dist-info/AUTHORS.rst,sha256=iCStz7WP5Jk7uMnn9jRA4ybS14X4yeUW2SsWE-OTaRk,328
23
- iqm_pulla-11.17.0.dist-info/LICENSE.txt,sha256=cCj_biRA4Q8A77vxR8AuvAf-DZ5G79yxR_3lYY6TrmA,11333
24
- iqm_pulla-11.17.0.dist-info/METADATA,sha256=ZWZSpSW6SS7kSxr8t70AiLCka2aL1YPypL6JyHYKQFg,17701
25
- iqm_pulla-11.17.0.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
26
- iqm_pulla-11.17.0.dist-info/top_level.txt,sha256=NB4XRfyDS6_wG9gMsyX-9LTU7kWnTQxNvkbzIxGv3-c,4
27
- iqm_pulla-11.17.0.dist-info/RECORD,,