azure-quantum 2.0.1__tar.gz → 2.1.0__tar.gz
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.
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/PKG-INFO +2 -1
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_version.py +1 -1
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_constants.py +4 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/targets/ionq.py +9 -1
- azure-quantum-2.1.0/azure/quantum/job/job.py +367 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/target.py +1 -1
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/version.py +1 -1
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure_quantum.egg-info/PKG-INFO +2 -1
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure_quantum.egg-info/SOURCES.txt +1 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure_quantum.egg-info/requires.txt +10 -6
- azure-quantum-2.1.0/requirements-cirq.txt +2 -0
- azure-quantum-2.1.0/requirements-pulser.txt +1 -0
- azure-quantum-2.1.0/requirements.txt +10 -0
- azure-quantum-2.0.1/azure/quantum/job/job.py +0 -171
- azure-quantum-2.0.1/requirements-cirq.txt +0 -2
- azure-quantum-2.0.1/requirements.txt +0 -8
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/README.md +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_authentication/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_authentication/_chained.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_authentication/_default.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_authentication/_token.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_client.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_configuration.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_patch.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_serialization.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/_vendor.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/models/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/models/_enums.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/models/_models.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/models/_patch.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/operations/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/operations/_operations.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_client/operations/_patch.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/_workspace_connection_params.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/argument_types/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/argument_types/types.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/chemistry/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/service.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/targets/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/targets/quantinuum.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/cirq/targets/target.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/base_job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/filtered_job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/job_failed_with_results_error.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/session.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/workspace_item.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/workspace_item_factory.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/backend.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/ionq.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/microsoft.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/qci.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/quantinuum.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/backends/rigetti.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/provider.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/results/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/results/resource_estimator.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/storage.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/ionq.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/target.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/job.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/result.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/target.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/params.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/pasqal/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/pasqal/result.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/pasqal/target.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/quantinuum.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/rigetti/__init__.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/rigetti/result.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/rigetti/target.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/target_factory.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/workspace.py +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure_quantum.egg-info/dependency_links.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure_quantum.egg-info/top_level.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/requirements-dev.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/requirements-qiskit.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/requirements-qsharp.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/requirements-quil.txt +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/setup.cfg +0 -0
- {azure-quantum-2.0.1 → azure-quantum-2.1.0}/setup.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: azure-quantum
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Python client for Azure Quantum
|
|
5
5
|
Home-page: https://github.com/microsoft/azure-quantum-python
|
|
6
6
|
Author: Microsoft
|
|
@@ -12,6 +12,7 @@ Requires-Python: >=3.8
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Provides-Extra: cirq
|
|
14
14
|
Provides-Extra: dev
|
|
15
|
+
Provides-Extra: pulser
|
|
15
16
|
Provides-Extra: qiskit
|
|
16
17
|
Provides-Extra: qsharp
|
|
17
18
|
Provides-Extra: quil
|
|
@@ -20,6 +20,8 @@ class EnvironmentVariables:
|
|
|
20
20
|
QUANTUM_ENV = "AZURE_QUANTUM_ENV"
|
|
21
21
|
AZURE_CLIENT_ID = SdkEnvironmentVariables.AZURE_CLIENT_ID
|
|
22
22
|
AZURE_CLIENT_SECRET = SdkEnvironmentVariables.AZURE_CLIENT_SECRET
|
|
23
|
+
AZURE_CLIENT_CERTIFICATE_PATH = SdkEnvironmentVariables.AZURE_CLIENT_CERTIFICATE_PATH
|
|
24
|
+
AZURE_CLIENT_SEND_CERTIFICATE_CHAIN = SdkEnvironmentVariables.AZURE_CLIENT_SEND_CERTIFICATE_CHAIN
|
|
23
25
|
AZURE_TENANT_ID = SdkEnvironmentVariables.AZURE_TENANT_ID
|
|
24
26
|
QUANTUM_TOKEN_FILE = "AZURE_QUANTUM_TOKEN_FILE"
|
|
25
27
|
CONNECTION_STRING = "AZURE_QUANTUM_CONNECTION_STRING"
|
|
@@ -35,6 +37,8 @@ class EnvironmentVariables:
|
|
|
35
37
|
QUANTUM_ENV,
|
|
36
38
|
AZURE_CLIENT_ID,
|
|
37
39
|
AZURE_CLIENT_SECRET,
|
|
40
|
+
AZURE_CLIENT_CERTIFICATE_PATH,
|
|
41
|
+
AZURE_CLIENT_SEND_CERTIFICATE_CHAIN,
|
|
38
42
|
AZURE_TENANT_ID,
|
|
39
43
|
QUANTUM_TOKEN_FILE,
|
|
40
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):
|
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
##
|
|
2
|
+
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
+
# Licensed under the MIT License.
|
|
4
|
+
##
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
import logging
|
|
8
|
+
import time
|
|
9
|
+
import json
|
|
10
|
+
|
|
11
|
+
from typing import TYPE_CHECKING
|
|
12
|
+
|
|
13
|
+
from azure.quantum._client.models import JobDetails
|
|
14
|
+
from azure.quantum.job.job_failed_with_results_error import JobFailedWithResultsError
|
|
15
|
+
from azure.quantum.job.base_job import BaseJob, ContentType, DEFAULT_TIMEOUT
|
|
16
|
+
from azure.quantum.job.filtered_job import FilteredJob
|
|
17
|
+
|
|
18
|
+
__all__ = ["Job", "JobDetails"]
|
|
19
|
+
|
|
20
|
+
logger = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
if TYPE_CHECKING:
|
|
23
|
+
from azure.quantum.workspace import Workspace
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
_log = logging.getLogger(__name__)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class Job(BaseJob, FilteredJob):
|
|
30
|
+
"""Azure Quantum Job that is submitted to a given Workspace.
|
|
31
|
+
|
|
32
|
+
:param workspace: Workspace instance to submit job to
|
|
33
|
+
:type workspace: Workspace
|
|
34
|
+
:param job_details: Job details model,
|
|
35
|
+
contains Job ID, name and other details
|
|
36
|
+
:type job_details: JobDetails
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
_default_poll_wait = 0.2
|
|
40
|
+
|
|
41
|
+
def __init__(self, workspace: "Workspace", job_details: JobDetails, **kwargs):
|
|
42
|
+
self.results = None
|
|
43
|
+
super().__init__(
|
|
44
|
+
workspace=workspace,
|
|
45
|
+
details=job_details,
|
|
46
|
+
**kwargs
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
def submit(self):
|
|
50
|
+
"""Submit a job to Azure Quantum."""
|
|
51
|
+
_log.debug(f"Submitting job with ID {self.id}")
|
|
52
|
+
job = self.workspace.submit_job(self)
|
|
53
|
+
self.details = job.details
|
|
54
|
+
|
|
55
|
+
def refresh(self):
|
|
56
|
+
"""Refreshes the Job's details by querying the workspace."""
|
|
57
|
+
self.details = self.workspace.get_job(self.id).details
|
|
58
|
+
|
|
59
|
+
def has_completed(self) -> bool:
|
|
60
|
+
"""Check if the job has completed."""
|
|
61
|
+
return (
|
|
62
|
+
self.details.status == "Succeeded"
|
|
63
|
+
or self.details.status == "Failed"
|
|
64
|
+
or self.details.status == "Cancelled"
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def wait_until_completed(
|
|
68
|
+
self,
|
|
69
|
+
max_poll_wait_secs=30,
|
|
70
|
+
timeout_secs=None,
|
|
71
|
+
print_progress=True
|
|
72
|
+
) -> None:
|
|
73
|
+
"""Keeps refreshing the Job's details
|
|
74
|
+
until it reaches a finished status.
|
|
75
|
+
|
|
76
|
+
:param max_poll_wait_secs: Maximum poll wait time, defaults to 30
|
|
77
|
+
:type max_poll_wait_secs: int
|
|
78
|
+
:param timeout_secs: Timeout in seconds, defaults to None
|
|
79
|
+
:type timeout_secs: int
|
|
80
|
+
:param print_progress: Print "." to stdout to display progress
|
|
81
|
+
:type print_progress: bool
|
|
82
|
+
:raises: :class:`TimeoutError` If the total poll time exceeds timeout, raise.
|
|
83
|
+
"""
|
|
84
|
+
self.refresh()
|
|
85
|
+
poll_wait = Job._default_poll_wait
|
|
86
|
+
start_time = time.time()
|
|
87
|
+
while not self.has_completed():
|
|
88
|
+
if timeout_secs is not None and (time.time() - start_time) >= timeout_secs:
|
|
89
|
+
raise TimeoutError(f"The wait time has exceeded {timeout_secs} seconds.")
|
|
90
|
+
|
|
91
|
+
logger.debug(
|
|
92
|
+
f"Waiting for job {self.id},"
|
|
93
|
+
+ f"it is in status '{self.details.status}'"
|
|
94
|
+
)
|
|
95
|
+
if print_progress:
|
|
96
|
+
print(".", end="", flush=True)
|
|
97
|
+
time.sleep(poll_wait)
|
|
98
|
+
self.refresh()
|
|
99
|
+
poll_wait = (
|
|
100
|
+
max_poll_wait_secs
|
|
101
|
+
if poll_wait >= max_poll_wait_secs
|
|
102
|
+
else poll_wait * 1.5
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
def get_results(self, timeout_secs: float = DEFAULT_TIMEOUT):
|
|
106
|
+
"""Get job results by downloading the results blob from the
|
|
107
|
+
storage container linked via the workspace.
|
|
108
|
+
|
|
109
|
+
Raises :class:`RuntimeError` if job execution fails.
|
|
110
|
+
|
|
111
|
+
Raises :class:`ValueError` if job output is malformed or output format is not compatible.
|
|
112
|
+
|
|
113
|
+
Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
|
|
114
|
+
but failure results could still be retrieved (e.g. for jobs submitted against "microsoft.dft" target).
|
|
115
|
+
|
|
116
|
+
:param timeout_secs: Timeout in seconds, defaults to 300
|
|
117
|
+
:type timeout_secs: float
|
|
118
|
+
:return: Results dictionary with histogram shots, or raw results if not a json object.
|
|
119
|
+
:rtype: typing.Any
|
|
120
|
+
"""
|
|
121
|
+
if self.results is not None:
|
|
122
|
+
return self.results
|
|
123
|
+
|
|
124
|
+
if not self.has_completed():
|
|
125
|
+
self.wait_until_completed(timeout_secs=timeout_secs)
|
|
126
|
+
|
|
127
|
+
if not self.details.status == "Succeeded":
|
|
128
|
+
if self.details.status == "Failed" and self._allow_failure_results():
|
|
129
|
+
job_blob_properties = self.download_blob_properties(self.details.output_data_uri)
|
|
130
|
+
if job_blob_properties.size > 0:
|
|
131
|
+
job_failure_data = self.download_data(self.details.output_data_uri)
|
|
132
|
+
raise JobFailedWithResultsError("An error occurred during job execution.", job_failure_data)
|
|
133
|
+
|
|
134
|
+
raise RuntimeError(
|
|
135
|
+
f'{"Cannot retrieve results as job execution failed"}'
|
|
136
|
+
+ f"(status: {self.details.status}."
|
|
137
|
+
+ f"error: {self.details.error_data})"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
payload = self.download_data(self.details.output_data_uri)
|
|
141
|
+
try:
|
|
142
|
+
payload = payload.decode("utf8")
|
|
143
|
+
results = json.loads(payload)
|
|
144
|
+
|
|
145
|
+
if self.details.output_data_format == "microsoft.quantum-results.v1":
|
|
146
|
+
if "Histogram" not in results:
|
|
147
|
+
raise ValueError(f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format.")
|
|
148
|
+
|
|
149
|
+
histogram_values = results["Histogram"]
|
|
150
|
+
|
|
151
|
+
if len(histogram_values) % 2 == 0:
|
|
152
|
+
# Re-mapping {'Histogram': ['[0]', 0.50, '[1]', 0.50] } to {'[0]': 0.50, '[1]': 0.50}
|
|
153
|
+
return {histogram_values[i]: histogram_values[i + 1] for i in range(0, len(histogram_values), 2)}
|
|
154
|
+
else:
|
|
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}
|
|
180
|
+
|
|
181
|
+
return results
|
|
182
|
+
except:
|
|
183
|
+
# If errors decoding the data, return the raw payload:
|
|
184
|
+
return payload
|
|
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
|
|
356
|
+
|
|
357
|
+
@classmethod
|
|
358
|
+
def _allow_failure_results(cls) -> bool:
|
|
359
|
+
"""
|
|
360
|
+
Allow to download job results even if the Job status is "Failed".
|
|
361
|
+
|
|
362
|
+
This method can be overridden in derived classes to alter the default
|
|
363
|
+
behaviour.
|
|
364
|
+
|
|
365
|
+
The default is False.
|
|
366
|
+
"""
|
|
367
|
+
return False
|
|
@@ -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.
|
|
192
|
+
return "microsoft.quantum-results.v2"
|
|
193
193
|
|
|
194
194
|
def submit(
|
|
195
195
|
self,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: azure-quantum
|
|
3
|
-
Version: 2.0
|
|
3
|
+
Version: 2.1.0
|
|
4
4
|
Summary: Python client for Azure Quantum
|
|
5
5
|
Home-page: https://github.com/microsoft/azure-quantum-python
|
|
6
6
|
Author: Microsoft
|
|
@@ -12,6 +12,7 @@ Requires-Python: >=3.8
|
|
|
12
12
|
Description-Content-Type: text/markdown
|
|
13
13
|
Provides-Extra: cirq
|
|
14
14
|
Provides-Extra: dev
|
|
15
|
+
Provides-Extra: pulser
|
|
15
16
|
Provides-Extra: qiskit
|
|
16
17
|
Provides-Extra: qsharp
|
|
17
18
|
Provides-Extra: quil
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
azure-core<2.0,>=1.30
|
|
2
|
-
azure-identity<2.0,>=1.
|
|
3
|
-
azure-storage-blob
|
|
2
|
+
azure-identity<2.0,>=1.17
|
|
3
|
+
azure-storage-blob==12.20
|
|
4
4
|
msrest<1.0,>=0.7.1
|
|
5
5
|
numpy<2.0,>=1.21.0
|
|
6
6
|
deprecated<2.0,>=1.2.12
|
|
@@ -8,11 +8,12 @@ Markdown>=3.4.1
|
|
|
8
8
|
python-markdown-math>=0.8
|
|
9
9
|
|
|
10
10
|
[all]
|
|
11
|
-
cirq-core<=1.
|
|
12
|
-
cirq-ionq<=1.
|
|
11
|
+
cirq-core<=1.4.0,>=1.3.0
|
|
12
|
+
cirq-ionq<=1.4.0,>=1.3.0
|
|
13
13
|
vcrpy>=4.3.1
|
|
14
14
|
azure-devtools<2.0,>=1.2.0
|
|
15
15
|
graphviz>=0.20.1
|
|
16
|
+
pulser<0.19,>=0.18
|
|
16
17
|
qiskit-ionq<0.6,>=0.5
|
|
17
18
|
qiskit-qir<0.6,>=0.5
|
|
18
19
|
qiskit<2.0,>=1.0
|
|
@@ -22,14 +23,17 @@ qsharp<2.0,>=1.0.33
|
|
|
22
23
|
pyquil>=3.3.2
|
|
23
24
|
|
|
24
25
|
[cirq]
|
|
25
|
-
cirq-core<=1.
|
|
26
|
-
cirq-ionq<=1.
|
|
26
|
+
cirq-core<=1.4.0,>=1.3.0
|
|
27
|
+
cirq-ionq<=1.4.0,>=1.3.0
|
|
27
28
|
|
|
28
29
|
[dev]
|
|
29
30
|
vcrpy>=4.3.1
|
|
30
31
|
azure-devtools<2.0,>=1.2.0
|
|
31
32
|
graphviz>=0.20.1
|
|
32
33
|
|
|
34
|
+
[pulser]
|
|
35
|
+
pulser<0.19,>=0.18
|
|
36
|
+
|
|
33
37
|
[qiskit]
|
|
34
38
|
qiskit-ionq<0.6,>=0.5
|
|
35
39
|
qiskit-qir<0.6,>=0.5
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
pulser>=0.18,<0.19
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
azure-core>=1.30,<2.0
|
|
2
|
+
azure-identity>=1.17,<2.0
|
|
3
|
+
# TODO: recent versions break recordings.
|
|
4
|
+
# More than one match for "https://mystorage.blob.core.windows.net/.../rawOutputData"
|
|
5
|
+
azure-storage-blob==12.20
|
|
6
|
+
msrest>=0.7.1,<1.0
|
|
7
|
+
numpy>=1.21.0,<2.0
|
|
8
|
+
deprecated>=1.2.12,<2.0
|
|
9
|
+
Markdown>=3.4.1
|
|
10
|
+
python-markdown-math>=0.8
|
|
@@ -1,171 +0,0 @@
|
|
|
1
|
-
##
|
|
2
|
-
# Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3
|
-
# Licensed under the MIT License.
|
|
4
|
-
##
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
import logging
|
|
8
|
-
import time
|
|
9
|
-
import json
|
|
10
|
-
|
|
11
|
-
from typing import TYPE_CHECKING
|
|
12
|
-
|
|
13
|
-
from azure.quantum._client.models import JobDetails
|
|
14
|
-
from azure.quantum.job.job_failed_with_results_error import JobFailedWithResultsError
|
|
15
|
-
from azure.quantum.job.base_job import BaseJob, ContentType, DEFAULT_TIMEOUT
|
|
16
|
-
from azure.quantum.job.filtered_job import FilteredJob
|
|
17
|
-
|
|
18
|
-
__all__ = ["Job", "JobDetails"]
|
|
19
|
-
|
|
20
|
-
logger = logging.getLogger(__name__)
|
|
21
|
-
|
|
22
|
-
if TYPE_CHECKING:
|
|
23
|
-
from azure.quantum.workspace import Workspace
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
_log = logging.getLogger(__name__)
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class Job(BaseJob, FilteredJob):
|
|
30
|
-
"""Azure Quantum Job that is submitted to a given Workspace.
|
|
31
|
-
|
|
32
|
-
:param workspace: Workspace instance to submit job to
|
|
33
|
-
:type workspace: Workspace
|
|
34
|
-
:param job_details: Job details model,
|
|
35
|
-
contains Job ID, name and other details
|
|
36
|
-
:type job_details: JobDetails
|
|
37
|
-
"""
|
|
38
|
-
|
|
39
|
-
_default_poll_wait = 0.2
|
|
40
|
-
|
|
41
|
-
def __init__(self, workspace: "Workspace", job_details: JobDetails, **kwargs):
|
|
42
|
-
self.results = None
|
|
43
|
-
super().__init__(
|
|
44
|
-
workspace=workspace,
|
|
45
|
-
details=job_details,
|
|
46
|
-
**kwargs
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
def submit(self):
|
|
50
|
-
"""Submit a job to Azure Quantum."""
|
|
51
|
-
_log.debug(f"Submitting job with ID {self.id}")
|
|
52
|
-
job = self.workspace.submit_job(self)
|
|
53
|
-
self.details = job.details
|
|
54
|
-
|
|
55
|
-
def refresh(self):
|
|
56
|
-
"""Refreshes the Job's details by querying the workspace."""
|
|
57
|
-
self.details = self.workspace.get_job(self.id).details
|
|
58
|
-
|
|
59
|
-
def has_completed(self) -> bool:
|
|
60
|
-
"""Check if the job has completed."""
|
|
61
|
-
return (
|
|
62
|
-
self.details.status == "Succeeded"
|
|
63
|
-
or self.details.status == "Failed"
|
|
64
|
-
or self.details.status == "Cancelled"
|
|
65
|
-
)
|
|
66
|
-
|
|
67
|
-
def wait_until_completed(
|
|
68
|
-
self,
|
|
69
|
-
max_poll_wait_secs=30,
|
|
70
|
-
timeout_secs=None,
|
|
71
|
-
print_progress=True
|
|
72
|
-
) -> None:
|
|
73
|
-
"""Keeps refreshing the Job's details
|
|
74
|
-
until it reaches a finished status.
|
|
75
|
-
|
|
76
|
-
:param max_poll_wait_secs: Maximum poll wait time, defaults to 30
|
|
77
|
-
:type max_poll_wait_secs: int
|
|
78
|
-
:param timeout_secs: Timeout in seconds, defaults to None
|
|
79
|
-
:type timeout_secs: int
|
|
80
|
-
:param print_progress: Print "." to stdout to display progress
|
|
81
|
-
:type print_progress: bool
|
|
82
|
-
:raises: :class:`TimeoutError` If the total poll time exceeds timeout, raise.
|
|
83
|
-
"""
|
|
84
|
-
self.refresh()
|
|
85
|
-
poll_wait = Job._default_poll_wait
|
|
86
|
-
start_time = time.time()
|
|
87
|
-
while not self.has_completed():
|
|
88
|
-
if timeout_secs is not None and (time.time() - start_time) >= timeout_secs:
|
|
89
|
-
raise TimeoutError(f"The wait time has exceeded {timeout_secs} seconds.")
|
|
90
|
-
|
|
91
|
-
logger.debug(
|
|
92
|
-
f"Waiting for job {self.id},"
|
|
93
|
-
+ f"it is in status '{self.details.status}'"
|
|
94
|
-
)
|
|
95
|
-
if print_progress:
|
|
96
|
-
print(".", end="", flush=True)
|
|
97
|
-
time.sleep(poll_wait)
|
|
98
|
-
self.refresh()
|
|
99
|
-
poll_wait = (
|
|
100
|
-
max_poll_wait_secs
|
|
101
|
-
if poll_wait >= max_poll_wait_secs
|
|
102
|
-
else poll_wait * 1.5
|
|
103
|
-
)
|
|
104
|
-
|
|
105
|
-
def get_results(self, timeout_secs: float = DEFAULT_TIMEOUT):
|
|
106
|
-
"""Get job results by downloading the results blob from the
|
|
107
|
-
storage container linked via the workspace.
|
|
108
|
-
|
|
109
|
-
Raises :class:`RuntimeError` if job execution fails.
|
|
110
|
-
|
|
111
|
-
Raises :class:`azure.quantum.job.JobFailedWithResultsError` if job execution fails,
|
|
112
|
-
but failure results could still be retrieved (e.g. for jobs submitted against "microsoft.dft" target).
|
|
113
|
-
|
|
114
|
-
:param timeout_secs: Timeout in seconds, defaults to 300
|
|
115
|
-
:type timeout_secs: float
|
|
116
|
-
:return: Results dictionary with histogram shots, or raw results if not a json object.
|
|
117
|
-
:rtype: typing.Any
|
|
118
|
-
"""
|
|
119
|
-
if self.results is not None:
|
|
120
|
-
return self.results
|
|
121
|
-
|
|
122
|
-
if not self.has_completed():
|
|
123
|
-
self.wait_until_completed(timeout_secs=timeout_secs)
|
|
124
|
-
|
|
125
|
-
if not self.details.status == "Succeeded":
|
|
126
|
-
if self.details.status == "Failed" and self._allow_failure_results():
|
|
127
|
-
job_blob_properties = self.download_blob_properties(self.details.output_data_uri)
|
|
128
|
-
if job_blob_properties.size > 0:
|
|
129
|
-
job_failure_data = self.download_data(self.details.output_data_uri)
|
|
130
|
-
raise JobFailedWithResultsError("An error occurred during job execution.", job_failure_data)
|
|
131
|
-
|
|
132
|
-
raise RuntimeError(
|
|
133
|
-
f'{"Cannot retrieve results as job execution failed"}'
|
|
134
|
-
+ f"(status: {self.details.status}."
|
|
135
|
-
+ f"error: {self.details.error_data})"
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
payload = self.download_data(self.details.output_data_uri)
|
|
139
|
-
try:
|
|
140
|
-
payload = payload.decode("utf8")
|
|
141
|
-
results = json.loads(payload)
|
|
142
|
-
|
|
143
|
-
if self.details.output_data_format == "microsoft.quantum-results.v1":
|
|
144
|
-
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."
|
|
146
|
-
|
|
147
|
-
histogram_values = results["Histogram"]
|
|
148
|
-
|
|
149
|
-
if len(histogram_values) % 2 == 0:
|
|
150
|
-
# Re-mapping {'Histogram': ['[0]', 0.50, '[1]', 0.50] } to {'[0]': 0.50, '[1]': 0.50}
|
|
151
|
-
return {histogram_values[i]: histogram_values[i + 1] for i in range(0, len(histogram_values), 2)}
|
|
152
|
-
else:
|
|
153
|
-
raise f"\"Histogram\" array has invalid format. Even number of items is expected."
|
|
154
|
-
|
|
155
|
-
return results
|
|
156
|
-
except:
|
|
157
|
-
# If errors decoding the data, return the raw payload:
|
|
158
|
-
return payload
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
@classmethod
|
|
162
|
-
def _allow_failure_results(cls) -> bool:
|
|
163
|
-
"""
|
|
164
|
-
Allow to download job results even if the Job status is "Failed".
|
|
165
|
-
|
|
166
|
-
This method can be overridden in derived classes to alter the default
|
|
167
|
-
behaviour.
|
|
168
|
-
|
|
169
|
-
The default is False.
|
|
170
|
-
"""
|
|
171
|
-
return False
|
|
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
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/job/job_failed_with_results_error.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
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/qiskit/results/resource_estimator.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/__init__.py
RENAMED
|
File without changes
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/__init__.py
RENAMED
|
File without changes
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/job.py
RENAMED
|
File without changes
|
{azure-quantum-2.0.1 → azure-quantum-2.1.0}/azure/quantum/target/microsoft/elements/dft/target.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
|