azure-quantum 2.0.2.dev0__py3-none-any.whl → 2.1.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.
@@ -6,4 +6,4 @@
6
6
  # Changes may cause incorrect behavior and will be lost if the code is regenerated.
7
7
  # --------------------------------------------------------------------------
8
8
 
9
- VERSION = "2.0.2.dev0"
9
+ VERSION = "2.1.1"
@@ -21,6 +21,7 @@ class EnvironmentVariables:
21
21
  AZURE_CLIENT_ID = SdkEnvironmentVariables.AZURE_CLIENT_ID
22
22
  AZURE_CLIENT_SECRET = SdkEnvironmentVariables.AZURE_CLIENT_SECRET
23
23
  AZURE_CLIENT_CERTIFICATE_PATH = SdkEnvironmentVariables.AZURE_CLIENT_CERTIFICATE_PATH
24
+ AZURE_CLIENT_SEND_CERTIFICATE_CHAIN = SdkEnvironmentVariables.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN
24
25
  AZURE_TENANT_ID = SdkEnvironmentVariables.AZURE_TENANT_ID
25
26
  QUANTUM_TOKEN_FILE = "AZURE_QUANTUM_TOKEN_FILE"
26
27
  CONNECTION_STRING = "AZURE_QUANTUM_CONNECTION_STRING"
@@ -37,6 +38,7 @@ class EnvironmentVariables:
37
38
  AZURE_CLIENT_ID,
38
39
  AZURE_CLIENT_SECRET,
39
40
  AZURE_CLIENT_CERTIFICATE_PATH,
41
+ AZURE_CLIENT_SEND_CERTIFICATE_CHAIN,
40
42
  AZURE_TENANT_ID,
41
43
  QUANTUM_TOKEN_FILE,
42
44
  CONNECTION_STRING,
@@ -2,7 +2,7 @@
2
2
  # Copyright (c) Microsoft Corporation.
3
3
  # Licensed under the MIT License.
4
4
  ##
5
- from typing import TYPE_CHECKING, Any, Dict, Union
5
+ from typing import TYPE_CHECKING, Any, Dict, Union, Optional
6
6
 
7
7
  try:
8
8
  import cirq
@@ -71,6 +71,14 @@ class _IonQClient:
71
71
  def delete_job(self, job_id: str):
72
72
  azure_job = self._workspace.get_job(job_id)
73
73
  self._workspace.cancel_job(azure_job)
74
+
75
+ def get_results(
76
+ self, job_id: str, sharpen: Optional[bool] = None, extra_query_params: Optional[dict] = None
77
+ ):
78
+ azure_job = self._workspace.get_job(job_id)
79
+ job_result = azure_job.get_results()
80
+ return job_result["histogram"]
81
+
74
82
 
75
83
 
76
84
  class IonQTarget(IonQ, CirqTarget):
azure/quantum/job/job.py CHANGED
@@ -108,6 +108,8 @@ class Job(BaseJob, FilteredJob):
108
108
 
109
109
  Raises :class:`RuntimeError` if job execution fails.
110
110
 
111
+ Raises :class:`ValueError` if job output is malformed or output format is not compatible.
112
+
111
113
  Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
112
114
  but failure results could still be retrieved (e.g. for jobs submitted against "microsoft.dft" target).
113
115
 
@@ -142,7 +144,7 @@ class Job(BaseJob, FilteredJob):
142
144
 
143
145
  if self.details.output_data_format == "microsoft.quantum-results.v1":
144
146
  if "Histogram" not in results:
145
- raise f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format."
147
+ raise ValueError(f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
146
148
 
147
149
  histogram_values = results["Histogram"]
148
150
 
@@ -150,13 +152,207 @@ class Job(BaseJob, FilteredJob):
150
152
  # Re-mapping {'Histogram': ['[0]', 0.50, '[1]', 0.50] } to {'[0]': 0.50, '[1]': 0.50}
151
153
  return {histogram_values[i]: histogram_values[i + 1] for i in range(0, len(histogram_values), 2)}
152
154
  else:
153
- raise f"\"Histogram\" array has invalid format. Even number of items is expected."
155
+ raise ValueError(f"\"Histogram\" array has invalid format. Even number of items is expected.")
156
+ elif self.details.output_data_format == "microsoft.quantum-results.v2":
157
+ if "DataFormat" not in results or results["DataFormat"] != "microsoft.quantum-results.v2":
158
+ raise ValueError(f"\"DataFormat\" was expected to be \"microsoft.quantum-results.v2\" in the Job results for \"{self.details.output_data_format}\" output format.")
159
+
160
+ if "Results" not in results:
161
+ raise ValueError(f"\"Results\" field was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
162
+
163
+ if len(results["Results"]) < 1:
164
+ raise ValueError("\"Results\" array was expected to contain at least one item")
165
+
166
+ results = results["Results"][0]
167
+
168
+ if "Histogram" not in results:
169
+ raise ValueError(f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
170
+
171
+ if "Shots" not in results:
172
+ raise ValueError(f"\"Shots\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
173
+
174
+ histogram_values = results["Histogram"]
175
+
176
+ total_count = len(results["Shots"])
177
+
178
+ # Re-mapping object {'Histogram': [{"Outcome": [0], "Display": '[0]', "Count": 500}, {"Outcome": [1], "Display": '[1]', "Count": 500}]} to {'[0]': 0.50, '[1]': 0.50}
179
+ return {outcome["Display"]: outcome["Count"] / total_count for outcome in histogram_values}
154
180
 
155
181
  return results
156
182
  except:
157
183
  # If errors decoding the data, return the raw payload:
158
184
  return payload
159
185
 
186
+ def get_results_histogram(self, timeout_secs: float = DEFAULT_TIMEOUT):
187
+ """Get job results histogram by downloading the results blob from the storage container linked via the workspace.
188
+
189
+ Raises :class:`RuntimeError` if job execution fails.
190
+
191
+ Raises :class:`ValueError` if job output is malformed or output format is not compatible.
192
+
193
+ Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
194
+ but failure results could still be retrieved (e.g. for jobs submitted against "microsoft.dft" target).
195
+
196
+ :param timeout_secs: Timeout in seconds, defaults to 300
197
+ :type timeout_secs: float
198
+ :return: Results dictionary with histogram shots, or raw results if not a json object.
199
+ :rtype: typing.Any
200
+ """
201
+ if self.results is not None:
202
+ return self.results
203
+
204
+ if not self.has_completed():
205
+ self.wait_until_completed(timeout_secs=timeout_secs)
206
+
207
+ if not self.details.status == "Succeeded":
208
+ if self.details.status == "Failed" and self._allow_failure_results():
209
+ job_blob_properties = self.download_blob_properties(self.details.output_data_uri)
210
+ if job_blob_properties.size > 0:
211
+ job_failure_data = self.download_data(self.details.output_data_uri)
212
+ raise JobFailedWithResultsError("An error occurred during job execution.", job_failure_data)
213
+
214
+ raise RuntimeError(
215
+ f'{"Cannot retrieve results as job execution failed"}'
216
+ + f"(status: {self.details.status}."
217
+ + f"error: {self.details.error_data})"
218
+ )
219
+
220
+ payload = self.download_data(self.details.output_data_uri)
221
+ try:
222
+ payload = payload.decode("utf8")
223
+ results = json.loads(payload)
224
+
225
+ if self.details.output_data_format == "microsoft.quantum-results.v2":
226
+ if "DataFormat" not in results or results["DataFormat"] != "microsoft.quantum-results.v2":
227
+ raise ValueError(f"\"DataFormat\" was expected to be \"microsoft.quantum-results.v2\" in the Job results for \"{self.details.output_data_format}\" output format.")
228
+ if "Results" not in results:
229
+ raise ValueError(f"\"Results\" field was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
230
+
231
+ if len(results["Results"]) < 1:
232
+ raise ValueError("\"Results\" array was expected to contain at least one item")
233
+
234
+ results = results["Results"]
235
+
236
+ if len(results) == 1:
237
+ results = results[0]
238
+ if "Histogram" not in results:
239
+ raise ValueError(f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
240
+
241
+ histogram_values = results["Histogram"]
242
+ outcome_keys = self._process_outcome(histogram_values)
243
+
244
+ # Re-mapping object {'Histogram': [{"Outcome": [0], "Display": '[0]', "Count": 500}, {"Outcome": [1], "Display": '[1]', "Count": 500}]} to {'[0]': {"Outcome": [0], "Count": 500}, '[1]': {"Outcome": [1], "Count": 500}}
245
+ return {hist_val["Display"]: {"outcome": outcome, "count": hist_val["Count"]} for outcome, hist_val in zip(outcome_keys, histogram_values)}
246
+
247
+ else:
248
+ # This is handling the BatchResults edge case
249
+ resultsArray = []
250
+ for i, result in enumerate(results):
251
+ if "Histogram" not in result:
252
+ raise ValueError(f"\"Histogram\" array was expected to be in the Job results for result {i} for \"{self.details.output_data_format}\" output format.")
253
+
254
+ histogram_values = result["Histogram"]
255
+ outcome_keys = self._process_outcome(histogram_values)
256
+
257
+ # Re-mapping object {'Histogram': [{"Outcome": [0], "Display": '[0]', "Count": 500}, {"Outcome": [1], "Display": '[1]', "Count": 500}]} to {'[0]': {"Outcome": [0], "Count": 500}, '[1]': {"Outcome": [1], "Count": 500}}
258
+ resultsArray.append({hist_val["Display"]: {"outcome": outcome, "count": hist_val["Count"]} for outcome, hist_val in zip(outcome_keys, histogram_values)})
259
+
260
+ return resultsArray
261
+
262
+ else:
263
+ raise ValueError(f"Getting a results histogram with counts instead of probabilities is not a supported feature for jobs using the \"{self.details.output_data_format}\" output format.")
264
+
265
+ except Exception as e:
266
+ raise e
267
+
268
+ def get_results_shots(self, timeout_secs: float = DEFAULT_TIMEOUT):
269
+ """Get job results per shot data by downloading the results blob from the
270
+ storage container linked via the workspace.
271
+
272
+ Raises :class:`RuntimeError` if job execution fails.
273
+
274
+ Raises :class:`ValueError` if job output is malformed or output format is not compatible.
275
+
276
+ Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
277
+ but failure results could still be retrieved (e.g. for jobs submitted against "microsoft.dft" target).
278
+
279
+ :param timeout_secs: Timeout in seconds, defaults to 300
280
+ :type timeout_secs: float
281
+ :return: Results dictionary with histogram shots, or raw results if not a json object.
282
+ :rtype: typing.Any
283
+ """
284
+ if self.results is not None:
285
+ return self.results
286
+
287
+ if not self.has_completed():
288
+ self.wait_until_completed(timeout_secs=timeout_secs)
289
+
290
+ if not self.details.status == "Succeeded":
291
+ if self.details.status == "Failed" and self._allow_failure_results():
292
+ job_blob_properties = self.download_blob_properties(self.details.output_data_uri)
293
+ if job_blob_properties.size > 0:
294
+ job_failure_data = self.download_data(self.details.output_data_uri)
295
+ raise JobFailedWithResultsError("An error occurred during job execution.", job_failure_data)
296
+
297
+ raise RuntimeError(
298
+ f'{"Cannot retrieve results as job execution failed"}'
299
+ + f"(status: {self.details.status}."
300
+ + f"error: {self.details.error_data})"
301
+ )
302
+
303
+ payload = self.download_data(self.details.output_data_uri)
304
+ try:
305
+ payload = payload.decode("utf8")
306
+ results = json.loads(payload)
307
+
308
+ if self.details.output_data_format == "microsoft.quantum-results.v2":
309
+ if "DataFormat" not in results or results["DataFormat"] != "microsoft.quantum-results.v2":
310
+ raise ValueError(f"\"DataFormat\" was expected to be \"microsoft.quantum-results.v2\" in the Job results for \"{self.details.output_data_format}\" output format.")
311
+ if "Results" not in results:
312
+ raise ValueError(f"\"Results\" field was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
313
+
314
+ results = results["Results"]
315
+
316
+ if len(results) < 1:
317
+ raise ValueError("\"Results\" array was expected to contain at least one item")
318
+
319
+ if len(results) == 1:
320
+ result = results[0]
321
+ if "Shots" not in result:
322
+ raise ValueError(f"\"Shots\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
323
+
324
+ return [self._convert_tuples(shot) for shot in result["Shots"]]
325
+ else:
326
+ # This is handling the BatchResults edge case
327
+ shotsArray = []
328
+ for i, result in enumerate(results):
329
+ if "Shots" not in result:
330
+ raise ValueError(f"\"Shots\" array was expected to be in the Job results for result {i} of \"{self.details.output_data_format}\" output format.")
331
+ shotsArray.append([self._convert_tuples(shot) for shot in result["Shots"]])
332
+
333
+ return shotsArray
334
+ else:
335
+ raise ValueError(f"Individual shot results are not supported for jobs using the \"{self.details.output_data_format}\" output format.")
336
+ except Exception as e:
337
+ raise e
338
+
339
+ def _process_outcome(self, histogram_results):
340
+ return [self._convert_tuples(v['Outcome']) for v in histogram_results]
341
+
342
+ def _convert_tuples(self, data):
343
+ if isinstance(data, dict):
344
+ # Check if the dictionary represents a tuple
345
+ if all(isinstance(k, str) and k.startswith("Item") for k in data.keys()):
346
+ # Convert the dictionary to a tuple
347
+ return tuple(self._convert_tuples(data[f"Item{i+1}"]) for i in range(len(data)))
348
+ else:
349
+ raise "Malformed tuple output"
350
+ elif isinstance(data, list):
351
+ # Recursively process list elements
352
+ return [self._convert_tuples(item) for item in data]
353
+ else:
354
+ # Return the data as is (int, string, etc.)
355
+ return data
160
356
 
161
357
  @classmethod
162
358
  def _allow_failure_results(cls) -> bool:
@@ -7,10 +7,8 @@
7
7
 
8
8
  from azure.quantum.qiskit.backends.ionq import (
9
9
  IonQBackend,
10
- IonQQPUBackend,
11
10
  IonQAriaBackend,
12
11
  IonQSimulatorBackend,
13
- IonQQPUQirBackend,
14
12
  IonQAriaQirBackend,
15
13
  IonQForteBackend,
16
14
  IonQForteQirBackend,
@@ -279,6 +279,7 @@ class AzureQirBackend(AzureBackendBase):
279
279
  "blob_name": "inputData",
280
280
  "content_type": "qir.v1",
281
281
  "input_data_format": "qir.v1",
282
+ "output_data_format": "microsoft.quantum-results.v2",
282
283
  }
283
284
 
284
285
  def run(
@@ -34,15 +34,12 @@ logger = logging.getLogger(__name__)
34
34
 
35
35
  __all__ = [
36
36
  "IonQBackend",
37
- "IonQQPUBackend",
38
37
  "IonQSimulatorBackend",
39
38
  "IonQAriaBackend",
40
39
  "IonQForteBackend",
41
40
  "IonQQirBackend",
42
41
  "IonQSimulatorQirBackend",
43
42
  "IonQSimulatorNativeBackend",
44
- "IonQQPUQirBackend",
45
- "IonQQPUNativeBackend",
46
43
  "IonQAriaQirBackend",
47
44
  "IonQForteQirBackend",
48
45
  "IonQAriaNativeBackend",
@@ -133,38 +130,6 @@ class IonQSimulatorQirBackend(IonQQirBackendBase):
133
130
  super().__init__(configuration=configuration, provider=provider, **kwargs)
134
131
 
135
132
 
136
- class IonQQPUQirBackend(IonQQirBackendBase):
137
- backend_names = ("ionq.qpu",)
138
-
139
- def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs):
140
- """Base class for interfacing with an IonQ QPU backend"""
141
-
142
- default_config = BackendConfiguration.from_dict(
143
- {
144
- "backend_name": name,
145
- "backend_version": __version__,
146
- "simulator": False,
147
- "local": False,
148
- "coupling_map": None,
149
- "description": "IonQ QPU on Azure Quantum",
150
- "basis_gates": ionq_basis_gates,
151
- "memory": False,
152
- "n_qubits": 11,
153
- "conditional": False,
154
- "max_shots": 10000,
155
- "max_experiments": 1,
156
- "open_pulse": False,
157
- "gates": [{"name": "TODO", "parameters": [], "qasm_def": "TODO"}],
158
- "azure": self._azure_config(),
159
- }
160
- )
161
- logger.info("Initializing IonQQPUQirBackend")
162
- configuration: BackendConfiguration = kwargs.pop(
163
- "configuration", default_config
164
- )
165
- super().__init__(configuration=configuration, provider=provider, **kwargs)
166
-
167
-
168
133
  class IonQAriaQirBackend(IonQQirBackendBase):
169
134
  backend_names = ("ionq.qpu.aria-1", "ionq.qpu.aria-2")
170
135
 
@@ -361,55 +326,6 @@ class IonQSimulatorNativeBackend(IonQSimulatorBackend):
361
326
  return config
362
327
 
363
328
 
364
- class IonQQPUBackend(IonQBackend):
365
- backend_names = ("ionq.qpu",)
366
-
367
- def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs):
368
- """Base class for interfacing with an IonQ QPU backend"""
369
- gateset = kwargs.pop("gateset", "qis")
370
- default_config = BackendConfiguration.from_dict(
371
- {
372
- "backend_name": name,
373
- "backend_version": __version__,
374
- "simulator": False,
375
- "local": False,
376
- "coupling_map": None,
377
- "description": "IonQ QPU on Azure Quantum",
378
- "basis_gates": GATESET_MAP[gateset],
379
- "memory": False,
380
- "n_qubits": 11,
381
- "conditional": False,
382
- "max_shots": 10000,
383
- "max_experiments": 1,
384
- "open_pulse": False,
385
- "gates": [{"name": "TODO", "parameters": [], "qasm_def": "TODO"}],
386
- "azure": self._azure_config(),
387
- "gateset": gateset,
388
- }
389
- )
390
- logger.info("Initializing IonQQPUBackend")
391
- configuration: BackendConfiguration = kwargs.pop(
392
- "configuration", default_config
393
- )
394
- super().__init__(configuration=configuration, provider=provider, **kwargs)
395
-
396
-
397
- class IonQQPUNativeBackend(IonQQPUBackend):
398
- def __init__(self, name: str, provider: "AzureQuantumProvider", **kwargs):
399
- if "gateset" not in kwargs:
400
- kwargs["gateset"] = "native"
401
- super().__init__(name, provider, **kwargs)
402
-
403
- def _azure_config(self) -> Dict[str, str]:
404
- config = super()._azure_config()
405
- config.update(
406
- {
407
- "is_default": False,
408
- }
409
- )
410
- return config
411
-
412
-
413
329
  class IonQAriaBackend(IonQBackend):
414
330
  backend_names = ("ionq.qpu.aria-1", "ionq.qpu.aria-2")
415
331
 
@@ -15,7 +15,7 @@ from .backend import (
15
15
  from qiskit.providers.models import BackendConfiguration
16
16
  from qiskit.providers import Options, Provider
17
17
 
18
- QIR_BASIS_GATES = [
18
+ QIR_BASIS_GATES = [
19
19
  "measure",
20
20
  "m",
21
21
  "barrier",
@@ -119,7 +119,7 @@ class QuantinuumSyntaxCheckerQirBackend(QuantinuumQirBackendBase):
119
119
  "coupling_map": None,
120
120
  "description": f"Quantinuum Syntax Checker on Azure Quantum",
121
121
  "basis_gates": QUANTINUUM_BASIS_GATES,
122
- "memory": False,
122
+ "memory": True,
123
123
  "n_qubits": self._get_n_qubits(name),
124
124
  "conditional": False,
125
125
  "max_shots": None,
@@ -156,7 +156,7 @@ class QuantinuumEmulatorQirBackend(QuantinuumQirBackendBase):
156
156
  "coupling_map": None,
157
157
  "description": f"Quantinuum emulator on Azure Quantum",
158
158
  "basis_gates": QUANTINUUM_BASIS_GATES,
159
- "memory": False,
159
+ "memory": True,
160
160
  "n_qubits": self._get_n_qubits(name),
161
161
  "conditional": False,
162
162
  "max_shots": None,
@@ -193,7 +193,7 @@ class QuantinuumQPUQirBackend(QuantinuumQirBackendBase):
193
193
  "coupling_map": None,
194
194
  "description": f"Quantinuum QPU on Azure Quantum",
195
195
  "basis_gates": QUANTINUUM_BASIS_GATES,
196
- "memory": False,
196
+ "memory": True,
197
197
  "n_qubits": self._get_n_qubits(name),
198
198
  "conditional": False,
199
199
  "max_shots": 10000,
@@ -23,7 +23,7 @@ QIR_BASIS_GATES = [
23
23
  "ry",
24
24
  "rz",
25
25
  "s",
26
- "sdg",
26
+ "sdg,"
27
27
  "t",
28
28
  "tdg",
29
29
  "x",
@@ -86,7 +86,7 @@ class RigettiSimulatorBackend(RigettiBackend):
86
86
  "coupling_map": None,
87
87
  "description": "Rigetti simulator on Azure Quantum",
88
88
  "basis_gates": QIR_BASIS_GATES,
89
- "memory": False,
89
+ "memory": True,
90
90
  "n_qubits": RigettiTarget.num_qubits(name),
91
91
  "conditional": False,
92
92
  "max_shots": 10000,
@@ -118,7 +118,7 @@ class RigettiQPUBackend(RigettiBackend):
118
118
  "coupling_map": None,
119
119
  "description": "Rigetti QPU on Azure Quantum",
120
120
  "basis_gates": QIR_BASIS_GATES,
121
- "memory": False,
121
+ "memory": True,
122
122
  "n_qubits": RigettiTarget.num_qubits(name),
123
123
  "conditional": False,
124
124
  "max_shots": 10000,
@@ -273,45 +273,32 @@ class AzureQuantumJob(JobV1):
273
273
 
274
274
  def _translate_microsoft_v2_results(self):
275
275
  """ Translate Microsoft's batching job results histograms into a format that can be consumed by qiskit libraries. """
276
- az_result = self._azure_job.get_results()
277
-
278
- if not "DataFormat" in az_result:
279
- raise ValueError("DataFormat missing from Job results")
280
-
281
- if not "Results" in az_result:
282
- raise ValueError("Results missing from Job results")
283
-
276
+ az_result_histogram = self._azure_job.get_results_histogram()
277
+ az_result_shots = self._azure_job.get_results_shots()
278
+
279
+ # If it is a non-batched result, format to be in batch format so we can have one code path
280
+ if isinstance(az_result_histogram, dict):
281
+ az_result_histogram = [az_result_histogram]
282
+ az_result_shots = [az_result_shots]
283
+
284
284
  histograms = []
285
- results = az_result["Results"]
286
- for circuit_results in results:
285
+
286
+ for (histogram, shots) in zip(az_result_histogram, az_result_shots):
287
287
  counts = {}
288
288
  probabilities = {}
289
289
 
290
- if not "TotalCount" in circuit_results:
291
- raise ValueError("TotalCount missing from Job results")
290
+ total_count = len(shots)
292
291
 
293
- total_count = circuit_results["TotalCount"]
294
-
295
- if total_count <= 0:
296
- raise ValueError("TotalCount must be a positive non-zero integer")
297
-
298
- if not "Histogram" in circuit_results:
299
- raise ValueError("Histogram missing from Job results")
300
-
301
- histogram = circuit_results["Histogram"]
302
- for result in histogram:
303
- if not "Display" in result:
304
- raise ValueError("Dispaly missing from histogram result")
305
-
306
- if not "Count" in result:
307
- raise ValueError("Count missing from histogram result")
308
-
309
- bitstring = AzureQuantumJob._qir_to_qiskit_bitstring(result["Display"])
310
- count = result["Count"]
292
+ for (display, result) in histogram.items():
293
+ bitstring = AzureQuantumJob._qir_to_qiskit_bitstring(display)
294
+ count = result["count"]
311
295
  probability = count / total_count
312
296
  counts[bitstring] = count
313
297
  probabilities[bitstring] = probability
314
- histograms.append((total_count, {"counts": counts, "probabilities": probabilities}))
298
+
299
+ formatted_shots = [AzureQuantumJob._qir_to_qiskit_bitstring(shot) for shot in shots]
300
+
301
+ histograms.append((total_count, {"counts": counts, "probabilities": probabilities, "memory": formatted_shots}))
315
302
  return histograms
316
303
 
317
304
  def _get_entry_point_names(self):
@@ -15,7 +15,6 @@ from azure.quantum._client.models import CostEstimate, UsageEvent
15
15
 
16
16
  COST_1QUBIT_GATE_MAP = {
17
17
  "ionq.simulator" : 0.0,
18
- "ionq.qpu" : 0.00003,
19
18
  "ionq.qpu.aria-1" : 0.0002205,
20
19
  "ionq.qpu.aria-2" : 0.0002205,
21
20
  "ionq.qpu.forte-1" : 0.0002205
@@ -23,7 +22,6 @@ COST_1QUBIT_GATE_MAP = {
23
22
 
24
23
  COST_2QUBIT_GATE_MAP = {
25
24
  "ionq.simulator" : 0.0,
26
- "ionq.qpu" : 0.0003,
27
25
  "ionq.qpu.aria-1" : 0.00098,
28
26
  "ionq.qpu.aria-2" : 0.00098,
29
27
  "ionq.qpu.forte-1" : 0.00098
@@ -31,7 +29,6 @@ COST_2QUBIT_GATE_MAP = {
31
29
 
32
30
  MIN_PRICE_MAP = {
33
31
  "ionq.simulator" : 0.0,
34
- "ionq.qpu" : 1.0,
35
32
  "ionq.qpu.aria-1" : 97.5,
36
33
  "ionq.qpu.aria-2" : 97.5,
37
34
  "ionq.qpu.forte-1" : 97.5
@@ -47,7 +44,6 @@ def int_to_bitstring(k: int, num_qubits: int, measured_qubit_ids: List[int]):
47
44
  class IonQ(Target):
48
45
  """IonQ target."""
49
46
  target_names = (
50
- "ionq.qpu",
51
47
  "ionq.simulator",
52
48
  "ionq.qpu.aria-1",
53
49
  "ionq.qpu.aria-2",
@@ -141,10 +137,6 @@ class IonQ(Target):
141
137
 
142
138
  Specify pricing details for your area to get most accurate results.
143
139
  By default, this function charges depending on the target:
144
- ionq.qpu:
145
- price_1q = 0.00003 USD for a single-qubit gate.
146
- price_2q = 0.0003 USD for a two-qubit gate.
147
- min_price = 1 USD, total minimum price per circuit.
148
140
  ionq.qpu.aria-1:
149
141
  price_1q = 0.00022 USD for a single-qubit gate.
150
142
  price_2q = 0.00098 USD for a two-qubit gate.
@@ -189,7 +189,7 @@ target '{self.name}' of provider '{self.provider_id}' not found."
189
189
 
190
190
  def _qir_output_data_format(self) -> str:
191
191
  """"Fallback output data format in case of QIR job submission."""
192
- return "microsoft.quantum-results.v1"
192
+ return "microsoft.quantum-results.v2"
193
193
 
194
194
  def submit(
195
195
  self,
azure/quantum/version.py CHANGED
@@ -5,4 +5,4 @@
5
5
  # Copyright (c) Microsoft Corporation. All rights reserved.
6
6
  # Licensed under the MIT License.
7
7
  ##
8
- __version__ = "2.0.2.dev0"
8
+ __version__ = "2.1.1"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: azure-quantum
3
- Version: 2.0.2.dev0
3
+ Version: 2.1.1
4
4
  Summary: Python client for Azure Quantum
5
5
  Home-page: https://github.com/microsoft/azure-quantum-python
6
6
  Author: Microsoft
@@ -10,44 +10,47 @@ Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
11
  Requires-Python: >=3.8
12
12
  Description-Content-Type: text/markdown
13
- Requires-Dist: azure-core <2.0,>=1.30
14
- Requires-Dist: azure-identity <2.0,>=1.15
15
- Requires-Dist: azure-storage-blob <13.0,>=12.19
16
- Requires-Dist: msrest <1.0,>=0.7.1
17
- Requires-Dist: numpy <2.0,>=1.21.0
18
- Requires-Dist: deprecated <2.0,>=1.2.12
19
- Requires-Dist: Markdown >=3.4.1
20
- Requires-Dist: python-markdown-math >=0.8
13
+ Requires-Dist: azure-core<2.0,>=1.30
14
+ Requires-Dist: azure-identity<2.0,>=1.17
15
+ Requires-Dist: azure-storage-blob==12.20
16
+ Requires-Dist: msrest<1.0,>=0.7.1
17
+ Requires-Dist: numpy<2.0,>=1.21.0
18
+ Requires-Dist: deprecated<2.0,>=1.2.12
19
+ Requires-Dist: Markdown>=3.4.1
20
+ Requires-Dist: python-markdown-math>=0.8
21
21
  Provides-Extra: all
22
- Requires-Dist: cirq-core <=1.2.0,>=1.1.0 ; extra == 'all'
23
- Requires-Dist: cirq-ionq <=1.2.0,>=1.1.0 ; extra == 'all'
24
- Requires-Dist: vcrpy >=4.3.1 ; extra == 'all'
25
- Requires-Dist: azure-devtools <2.0,>=1.2.0 ; extra == 'all'
26
- Requires-Dist: graphviz >=0.20.1 ; extra == 'all'
27
- Requires-Dist: qiskit-ionq <0.6,>=0.5 ; extra == 'all'
28
- Requires-Dist: qiskit-qir <0.6,>=0.5 ; extra == 'all'
29
- Requires-Dist: qiskit <2.0,>=1.0 ; extra == 'all'
30
- Requires-Dist: Markdown <4.0,>=3.4.1 ; extra == 'all'
31
- Requires-Dist: python-markdown-math <1.0,>=0.8.0 ; extra == 'all'
32
- Requires-Dist: qsharp <2.0,>=1.0.33 ; extra == 'all'
33
- Requires-Dist: pyquil >=3.3.2 ; extra == 'all'
22
+ Requires-Dist: cirq-core<=1.4.1,>=1.3.0; extra == "all"
23
+ Requires-Dist: cirq-ionq<=1.4.1,>=1.3.0; extra == "all"
24
+ Requires-Dist: vcrpy>=4.3.1; extra == "all"
25
+ Requires-Dist: azure-devtools<2.0,>=1.2.0; extra == "all"
26
+ Requires-Dist: graphviz>=0.20.1; extra == "all"
27
+ Requires-Dist: pulser<0.19,>=0.18; extra == "all"
28
+ Requires-Dist: qiskit-ionq<0.6,>=0.5; extra == "all"
29
+ Requires-Dist: qiskit-qir<0.6,>=0.5; extra == "all"
30
+ Requires-Dist: qiskit<2.0,>=1.0; extra == "all"
31
+ Requires-Dist: Markdown<4.0,>=3.4.1; extra == "all"
32
+ Requires-Dist: python-markdown-math<1.0,>=0.8.0; extra == "all"
33
+ Requires-Dist: qsharp<2.0,>=1.0.33; extra == "all"
34
+ Requires-Dist: pyquil>=3.3.2; extra == "all"
34
35
  Provides-Extra: cirq
35
- Requires-Dist: cirq-core <=1.2.0,>=1.1.0 ; extra == 'cirq'
36
- Requires-Dist: cirq-ionq <=1.2.0,>=1.1.0 ; extra == 'cirq'
36
+ Requires-Dist: cirq-core<=1.4.1,>=1.3.0; extra == "cirq"
37
+ Requires-Dist: cirq-ionq<=1.4.1,>=1.3.0; extra == "cirq"
37
38
  Provides-Extra: dev
38
- Requires-Dist: vcrpy >=4.3.1 ; extra == 'dev'
39
- Requires-Dist: azure-devtools <2.0,>=1.2.0 ; extra == 'dev'
40
- Requires-Dist: graphviz >=0.20.1 ; extra == 'dev'
39
+ Requires-Dist: vcrpy>=4.3.1; extra == "dev"
40
+ Requires-Dist: azure-devtools<2.0,>=1.2.0; extra == "dev"
41
+ Requires-Dist: graphviz>=0.20.1; extra == "dev"
42
+ Provides-Extra: pulser
43
+ Requires-Dist: pulser<0.19,>=0.18; extra == "pulser"
41
44
  Provides-Extra: qiskit
42
- Requires-Dist: qiskit-ionq <0.6,>=0.5 ; extra == 'qiskit'
43
- Requires-Dist: qiskit-qir <0.6,>=0.5 ; extra == 'qiskit'
44
- Requires-Dist: qiskit <2.0,>=1.0 ; extra == 'qiskit'
45
- Requires-Dist: Markdown <4.0,>=3.4.1 ; extra == 'qiskit'
46
- Requires-Dist: python-markdown-math <1.0,>=0.8.0 ; extra == 'qiskit'
45
+ Requires-Dist: qiskit-ionq<0.6,>=0.5; extra == "qiskit"
46
+ Requires-Dist: qiskit-qir<0.6,>=0.5; extra == "qiskit"
47
+ Requires-Dist: qiskit<2.0,>=1.0; extra == "qiskit"
48
+ Requires-Dist: Markdown<4.0,>=3.4.1; extra == "qiskit"
49
+ Requires-Dist: python-markdown-math<1.0,>=0.8.0; extra == "qiskit"
47
50
  Provides-Extra: qsharp
48
- Requires-Dist: qsharp <2.0,>=1.0.33 ; extra == 'qsharp'
51
+ Requires-Dist: qsharp<2.0,>=1.0.33; extra == "qsharp"
49
52
  Provides-Extra: quil
50
- Requires-Dist: pyquil >=3.3.2 ; extra == 'quil'
53
+ Requires-Dist: pyquil>=3.3.2; extra == "quil"
51
54
 
52
55
  ![Azure Quantum logo](https://raw.githubusercontent.com/microsoft/qdk-python/main/azure-quantum/Azure-Quantum-logo.png)
53
56
 
@@ -1,8 +1,8 @@
1
1
  azure/quantum/__init__.py,sha256=Za8xZY4lzFkW8m4ero-bqrfN437D2NRukM77ukb4GPM,508
2
- azure/quantum/_constants.py,sha256=Zn-kuQJSv39dxxzR46j2uohUjgb7yO65I3mv7TYe1_Q,3350
2
+ azure/quantum/_constants.py,sha256=nDL_QrGdI_Zz_cvTB9nVgfE7J6A_Boo1ollMYqsiEBs,3499
3
3
  azure/quantum/_workspace_connection_params.py,sha256=KoT90U89Dj6pVwAKp_ENJL1hyTF0oQe7w0QioOGvjXg,21685
4
4
  azure/quantum/storage.py,sha256=_4bMniDk9LrB_K5CQwuCivJFZXdmhRvU2b6Z3xxXw9I,12556
5
- azure/quantum/version.py,sha256=U17DBbQlfUbmtQd2F-Sk6TP2QCSXomvFcDB5jWsVgF8,240
5
+ azure/quantum/version.py,sha256=Coj6I0Ob9qyOnI9ZILCP7HgWjW9i1sKe8cKFlGG2tpY,235
6
6
  azure/quantum/workspace.py,sha256=1__iZTe59ozAsAGJ4nECxmk_211Dm8ALJi-MFIdrg4o,23438
7
7
  azure/quantum/_authentication/__init__.py,sha256=bniNZlS0hMIjO_y7DevGBAS6MixyA5pbPHcdGipUWM4,236
8
8
  azure/quantum/_authentication/_chained.py,sha256=0rdohB_fVGFHUhlly9sGxqQTBTZGpGxtlBqNHDFbAqE,4848
@@ -14,7 +14,7 @@ azure/quantum/_client/_configuration.py,sha256=5uktKtZxoVVAoSyeL0VNGS9AfPERp-9rU
14
14
  azure/quantum/_client/_patch.py,sha256=YTV6yZ9bRfBBaw2z7v4MdzR-zeHkdtKkGb4SU8C25mE,694
15
15
  azure/quantum/_client/_serialization.py,sha256=KJSS6KWgnKcz-cENQCmWZ9Ziv303lnBbLwFIpYZeKFU,81097
16
16
  azure/quantum/_client/_vendor.py,sha256=h8ByiyZ4cCQyFxqnuhTQdv1Rms3dVjKsrgZDzwMcSJ0,996
17
- azure/quantum/_client/_version.py,sha256=I7nsV9lWPbP1VpRXyWk25izFFVlnMQ3LyLMOfDRmYiU,500
17
+ azure/quantum/_client/_version.py,sha256=TiawyRl0ZgDLdomi_95Tde-7-8YvRIBanwy954TaOpA,495
18
18
  azure/quantum/_client/models/__init__.py,sha256=c1PRpzNsQTcDk4GkrFMMIlwNQQa2c0p5N0Lzd-23YBA,2100
19
19
  azure/quantum/_client/models/_enums.py,sha256=omj_B8_E8ONzTHg5hLgDlFYibRRbdr9sEN298im_otA,2977
20
20
  azure/quantum/_client/models/_models.py,sha256=wktCM5oBVfwQetNoHobL1wNsC3knXV-HmqBq_Q77Kw4,41810
@@ -29,34 +29,34 @@ azure/quantum/cirq/__init__.py,sha256=AJT_qCdxfqgeiPmqmbxQgCzETCOIJyHYoy6pCs-Osk
29
29
  azure/quantum/cirq/job.py,sha256=Wm52HFYel9Di6xGdzDdYfBLM3ZklaE1qOQ9YNg87eeY,3031
30
30
  azure/quantum/cirq/service.py,sha256=1L2seZt26ENQY973vIa6aex7SsWpCu6YkpClsr6AteY,8880
31
31
  azure/quantum/cirq/targets/__init__.py,sha256=cpb677Kg1V5cdI0kdgkLafI8xfwYZZYx0tc6qc024gE,574
32
- azure/quantum/cirq/targets/ionq.py,sha256=xCabcYklH9wW1TFBzpMdxvipzqhKWCYbtcgNqDHbPXM,6804
32
+ azure/quantum/cirq/targets/ionq.py,sha256=-M7aL-1XYmV3qF6eUYd-FR800NIEvrcY1Pty5vM7XDc,7101
33
33
  azure/quantum/cirq/targets/quantinuum.py,sha256=t7L5prczDQJlzStth6Rh6r35DX1Z8J_my-VJxLBp2n4,4537
34
34
  azure/quantum/cirq/targets/target.py,sha256=1EEog72dFZoiOTQP7obOrCuO3VH0yjXGAIMeO6bm22o,2184
35
35
  azure/quantum/job/__init__.py,sha256=nFuOsG25a8WzYFLwA2fhA0JMNWtblfDjV5WRgB6UQbw,829
36
36
  azure/quantum/job/base_job.py,sha256=NwtI-dcpOfKp-ANnLAPKQVgT3t9BEv_MQSp1N47oKM0,13876
37
37
  azure/quantum/job/filtered_job.py,sha256=qZfxTuDp0hzK4wermn4GRzLxnDy4yM-j6oZQ3D0O4vI,1877
38
- azure/quantum/job/job.py,sha256=UcNkD8qwJ7leQ99xvWegssUMsuHDOkhZwKyvG2Caag8,6390
38
+ azure/quantum/job/job.py,sha256=D6MMOUEvx_qLdyr7vU1t62MUNMapOnFgcMBYCt7-TXM,17721
39
39
  azure/quantum/job/job_failed_with_results_error.py,sha256=bSqOZ0c6FNbS9opvwkCXG9mfTkAiyZRvp_YA3V-ktEs,1597
40
40
  azure/quantum/job/session.py,sha256=EEJVKEEB5g0yyH963aaR0GY0Cd0axrX-49gwDWxBcfE,11961
41
41
  azure/quantum/job/workspace_item.py,sha256=lyBIJCtUfIZMGJYJkX7Se8IDnXhXe4JU0RnqzSuhhI4,1380
42
42
  azure/quantum/job/workspace_item_factory.py,sha256=QRWyrtgcKZqUucJOFi9V_SYMV3lj6S74tGRrPtk3NE0,1200
43
43
  azure/quantum/qiskit/__init__.py,sha256=gjKsmRwtVNcbbsuOvy2wT0ASELh5NXGmuwaEwjZcVQo,314
44
- azure/quantum/qiskit/job.py,sha256=PHgEIY7dOQtpfo-J--frj-PVX3OWr8llfBUv9VClLNg,14370
44
+ azure/quantum/qiskit/job.py,sha256=e_5BRaa9teiIOqqqNfEpZSL2MSBhBIivMO_JbLhU7fs,13960
45
45
  azure/quantum/qiskit/provider.py,sha256=q3wFL_mrgT2pwEOxkqXf7632WTX6b7NTLKCwx6E796c,10946
46
- azure/quantum/qiskit/backends/__init__.py,sha256=OjcYgOyhVjsw-AngJmZLKtBKntzeIJnvvfWW5dv-Gw4,1163
47
- azure/quantum/qiskit/backends/backend.py,sha256=uzm5KOxVsjFVLZwLDtJJhBhys-D4ZbsmPmOsTSiStwk,20467
48
- azure/quantum/qiskit/backends/ionq.py,sha256=rxAhWvXrAMuFbdg72qDy_MKIx8EuCV7BvKCgwQwpogY,18024
46
+ azure/quantum/qiskit/backends/__init__.py,sha256=DBC6GgYa5Y0p5xu5ADqlOXs7zp8_RDTJ86qKhuzXfG0,1118
47
+ azure/quantum/qiskit/backends/backend.py,sha256=6B0wQWqQghzXMUFaKna6pTe7letLoKzbtq04kYY0YOk,20534
48
+ azure/quantum/qiskit/backends/ionq.py,sha256=Wve2rqaCUcqQlS52iearbwJMNXrQU50Edr8ZSEUc-8s,14896
49
49
  azure/quantum/qiskit/backends/microsoft.py,sha256=7Nw-z8KoIBOBXbP8aqhmhAeW9TENrwwkZk6LD31M9F0,3478
50
- azure/quantum/qiskit/backends/qci.py,sha256=LVw0_8Wh-lNdeoCtoBWeSxrUw3xbGyVSdSocWUOmYsU,4893
51
- azure/quantum/qiskit/backends/quantinuum.py,sha256=zIXdrIEjYGPVsytdjy_wOsw_8viA06_PYnkwsuV3RC4,13437
52
- azure/quantum/qiskit/backends/rigetti.py,sha256=EOLiXfcNLXvhPDenuzbygAIvLUepNwa0CFG17cZlFFw,4322
50
+ azure/quantum/qiskit/backends/qci.py,sha256=1VVFk1qXQMwQvDCKLfIrQHa-ZLehjkOsbQQszQUhVzI,4894
51
+ azure/quantum/qiskit/backends/quantinuum.py,sha256=F1ujfrEaqi1NfaTd2jfP1li5FaGzhEG8ds34OB71RDo,13434
52
+ azure/quantum/qiskit/backends/rigetti.py,sha256=j354MUvJkp9pYKtpEL202UjRvynvbgXsj5BjILBlPaQ,4320
53
53
  azure/quantum/qiskit/results/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  azure/quantum/qiskit/results/resource_estimator.py,sha256=pAP5ZpVxdzNekQ_qXfSdSKYWWuqL_Vq7WK6pWU4wbEQ,814
55
55
  azure/quantum/target/__init__.py,sha256=F0nIEJdlbczmxAdtvPDWf8J1Y33_XjPzloliHeWpJos,689
56
- azure/quantum/target/ionq.py,sha256=f6V_Ce09RHU56NmCdwcupDDjSxA3kDVodjwEBvpWrvg,8130
56
+ azure/quantum/target/ionq.py,sha256=Jy-y8b7ctjnxLrsBGb1ECdX-hZEB8r0BR1mrNg1a6SE,7814
57
57
  azure/quantum/target/params.py,sha256=oI-35HUEMCskNjpxCJU3tjL664K-TxqAg5LA5xU0nso,9130
58
58
  azure/quantum/target/quantinuum.py,sha256=Om6K3SOiMRqCb20TzOhUPAEcsdHs4gzO15kXOM5LTrU,7612
59
- azure/quantum/target/target.py,sha256=mb-z640nMU2S0YkHxVulE-ahz0imCr1Z_VCDspsd-HU,13868
59
+ azure/quantum/target/target.py,sha256=7gUbv2w08AX2I5gKJrN3d-DipDOZzuGx63k0u_P_zho,13868
60
60
  azure/quantum/target/target_factory.py,sha256=jjZ9zxWaNDkcvslKV02GSP8rtXwStJ7EmVXQSOFh_j8,5266
61
61
  azure/quantum/target/microsoft/__init__.py,sha256=36kM2YlWv69AzAfUA5wMdWyYRSaCMwX2Ajhffpzx67g,570
62
62
  azure/quantum/target/microsoft/job.py,sha256=GM4OA-rxFUqQzsH8V59pVc4BmBaPYvd99E26pyPwxto,1249
@@ -72,7 +72,7 @@ azure/quantum/target/pasqal/target.py,sha256=DMt2uYeCeaUFh7vlnf687VOoRStXCWL-6Mk
72
72
  azure/quantum/target/rigetti/__init__.py,sha256=I1vyzZBYGI540pauTqJd0RSSyTShGqkEL7Yjo25_RNY,378
73
73
  azure/quantum/target/rigetti/result.py,sha256=65mtAZxfdNrTWNjWPqgfwt2BZN6Nllo4g_bls7-Nm68,2334
74
74
  azure/quantum/target/rigetti/target.py,sha256=wL2RkOHKUT7YL6dHBvlO1UiKm1fhnehS3SSGCcarwf8,7048
75
- azure_quantum-2.0.2.dev0.dist-info/METADATA,sha256=CVf7VA0lAqHGCgyEFXP5Aq1XCSAMDAvl70ozYaKFZV4,7277
76
- azure_quantum-2.0.2.dev0.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
77
- azure_quantum-2.0.2.dev0.dist-info/top_level.txt,sha256=S7DhWV9m80TBzAhOFjxDUiNbKszzoThbnrSz5MpbHSQ,6
78
- azure_quantum-2.0.2.dev0.dist-info/RECORD,,
75
+ azure_quantum-2.1.1.dist-info/METADATA,sha256=OTRXnQREuxSMGNFLgjX1jiZYs5DSX7MhGv6yhTm_r9Y,7339
76
+ azure_quantum-2.1.1.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
77
+ azure_quantum-2.1.1.dist-info/top_level.txt,sha256=S7DhWV9m80TBzAhOFjxDUiNbKszzoThbnrSz5MpbHSQ,6
78
+ azure_quantum-2.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: bdist_wheel (0.44.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5