azure-quantum 0.29.2__py3-none-any.whl → 1.0.0__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.
- azure/quantum/_client/_version.py +1 -1
- azure/quantum/cirq/service.py +7 -0
- azure/quantum/cirq/targets/quantinuum.py +1 -1
- azure/quantum/job/__init__.py +1 -0
- azure/quantum/job/base_job.py +41 -15
- azure/quantum/job/job.py +35 -1
- azure/quantum/job/job_failed_with_results_error.py +41 -0
- azure/quantum/qiskit/backends/backend.py +130 -35
- azure/quantum/qiskit/backends/ionq.py +65 -5
- azure/quantum/qiskit/backends/qci.py +35 -2
- azure/quantum/qiskit/backends/quantinuum.py +25 -4
- azure/quantum/qiskit/backends/rigetti.py +8 -1
- azure/quantum/qiskit/job.py +7 -16
- azure/quantum/qiskit/provider.py +18 -2
- azure/quantum/storage.py +2 -1
- azure/quantum/target/__init__.py +1 -0
- azure/quantum/target/ionq.py +37 -12
- azure/quantum/target/microsoft/elements/dft/__init__.py +4 -0
- azure/quantum/target/microsoft/elements/dft/job.py +46 -0
- azure/quantum/target/microsoft/elements/dft/target.py +66 -0
- azure/quantum/target/microsoft/target.py +36 -9
- azure/quantum/target/params.py +1 -1
- azure/quantum/target/pasqal/target.py +16 -2
- azure/quantum/target/quantinuum.py +34 -9
- azure/quantum/target/rigetti/target.py +21 -3
- azure/quantum/target/solvers.py +7 -1
- azure/quantum/target/target.py +82 -0
- azure/quantum/target/target_factory.py +0 -2
- azure/quantum/version.py +1 -1
- azure/quantum/workspace.py +11 -8
- {azure_quantum-0.29.2.dist-info → azure_quantum-1.0.0.dist-info}/METADATA +3 -5
- azure_quantum-1.0.0.dist-info/RECORD +86 -0
- azure/quantum/_client/aio/__init__.py +0 -23
- azure/quantum/_client/aio/_client.py +0 -124
- azure/quantum/_client/aio/_configuration.py +0 -89
- azure/quantum/_client/aio/_patch.py +0 -20
- azure/quantum/_client/aio/operations/__init__.py +0 -29
- azure/quantum/_client/aio/operations/_operations.py +0 -1291
- azure/quantum/_client/aio/operations/_patch.py +0 -20
- azure/quantum/aio/__init__.py +0 -14
- azure/quantum/aio/_authentication/__init__.py +0 -9
- azure/quantum/aio/_authentication/_chained.py +0 -94
- azure/quantum/aio/_authentication/_default.py +0 -212
- azure/quantum/aio/_authentication/_token.py +0 -81
- azure/quantum/aio/job/__init__.py +0 -1
- azure/quantum/aio/job/base_job.py +0 -326
- azure/quantum/aio/job/job.py +0 -104
- azure/quantum/aio/optimization/__init__.py +0 -11
- azure/quantum/aio/optimization/online_problem.py +0 -17
- azure/quantum/aio/optimization/problem.py +0 -102
- azure/quantum/aio/optimization/streaming_problem.py +0 -280
- azure/quantum/aio/storage.py +0 -390
- azure/quantum/aio/target/__init__.py +0 -19
- azure/quantum/aio/target/ionq.py +0 -47
- azure/quantum/aio/target/quantinuum.py +0 -47
- azure/quantum/aio/target/solvers.py +0 -96
- azure/quantum/aio/target/target.py +0 -68
- azure/quantum/aio/target/target_factory.py +0 -72
- azure/quantum/aio/target/toshiba.py +0 -6
- azure/quantum/aio/workspace.py +0 -337
- azure_quantum-0.29.2.dist-info/RECORD +0 -110
- {azure_quantum-0.29.2.dist-info → azure_quantum-1.0.0.dist-info}/WHEEL +0 -0
- {azure_quantum-0.29.2.dist-info → azure_quantum-1.0.0.dist-info}/top_level.txt +0 -0
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
5
|
|
|
6
|
-
from typing import Dict
|
|
6
|
+
from typing import Dict, List, Union
|
|
7
|
+
from azure.quantum.qiskit.job import AzureQuantumJob
|
|
7
8
|
from azure.quantum.version import __version__
|
|
8
9
|
import warnings
|
|
9
10
|
|
|
@@ -62,8 +63,13 @@ def _get_n_qubits(name):
|
|
|
62
63
|
UserWarning(f"Number of qubits not known for target {name}. Defaulting to 20."))
|
|
63
64
|
return 20
|
|
64
65
|
|
|
66
|
+
_QUANTINUUM_COUNT_INPUT_PARAM_NAME = "count"
|
|
67
|
+
_DEFAULT_SHOTS_COUNT = 500
|
|
65
68
|
|
|
66
69
|
class QuantinuumQirBackendBase(AzureQirBackend):
|
|
70
|
+
|
|
71
|
+
_SHOTS_PARAM_NAME = _QUANTINUUM_COUNT_INPUT_PARAM_NAME
|
|
72
|
+
|
|
67
73
|
@abstractmethod
|
|
68
74
|
def __init__(
|
|
69
75
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
@@ -72,7 +78,12 @@ class QuantinuumQirBackendBase(AzureQirBackend):
|
|
|
72
78
|
|
|
73
79
|
@classmethod
|
|
74
80
|
def _default_options(cls) -> Options:
|
|
75
|
-
return Options(
|
|
81
|
+
return Options(
|
|
82
|
+
**{
|
|
83
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT
|
|
84
|
+
},
|
|
85
|
+
targetCapability="BasicExecution",
|
|
86
|
+
)
|
|
76
87
|
|
|
77
88
|
def _azure_config(self) -> Dict[str, str]:
|
|
78
89
|
config = super()._azure_config()
|
|
@@ -204,6 +215,8 @@ class QuantinuumQPUQirBackend(QuantinuumQirBackendBase):
|
|
|
204
215
|
class QuantinuumBackend(AzureBackend):
|
|
205
216
|
"""Base class for interfacing with a Quantinuum (formerly Honeywell) backend in Azure Quantum"""
|
|
206
217
|
|
|
218
|
+
_SHOTS_PARAM_NAME = _QUANTINUUM_COUNT_INPUT_PARAM_NAME
|
|
219
|
+
|
|
207
220
|
@abstractmethod
|
|
208
221
|
def __init__(
|
|
209
222
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
@@ -212,7 +225,11 @@ class QuantinuumBackend(AzureBackend):
|
|
|
212
225
|
|
|
213
226
|
@classmethod
|
|
214
227
|
def _default_options(cls):
|
|
215
|
-
return Options(
|
|
228
|
+
return Options(
|
|
229
|
+
**{
|
|
230
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
231
|
+
},
|
|
232
|
+
)
|
|
216
233
|
|
|
217
234
|
def _azure_config(self) -> Dict[str, str]:
|
|
218
235
|
return {
|
|
@@ -241,6 +258,10 @@ class QuantinuumBackend(AzureBackend):
|
|
|
241
258
|
:type count: int
|
|
242
259
|
"""
|
|
243
260
|
if count is not None:
|
|
261
|
+
warnings.warn(
|
|
262
|
+
"The 'count' parameter will be deprecated. Please, use 'shots' parameter instead.",
|
|
263
|
+
category=DeprecationWarning,
|
|
264
|
+
)
|
|
244
265
|
shots = count
|
|
245
266
|
|
|
246
267
|
if shots is None:
|
|
@@ -249,7 +270,7 @@ class QuantinuumBackend(AzureBackend):
|
|
|
249
270
|
input_data = circuit.qasm()
|
|
250
271
|
workspace = self.provider().get_workspace()
|
|
251
272
|
target = workspace.get_targets(self.name())
|
|
252
|
-
return target.estimate_cost(input_data,
|
|
273
|
+
return target.estimate_cost(input_data, shots=shots)
|
|
253
274
|
|
|
254
275
|
def _get_n_qubits(self, name):
|
|
255
276
|
return _get_n_qubits(name)
|
|
@@ -42,9 +42,13 @@ logger = logging.getLogger(__name__)
|
|
|
42
42
|
__all__ = ["RigettiSimulatorBackend" "RigettiQPUBackend"]
|
|
43
43
|
|
|
44
44
|
|
|
45
|
+
_DEFAULT_SHOTS_COUNT = 500
|
|
46
|
+
|
|
45
47
|
class RigettiBackend(AzureQirBackend):
|
|
46
48
|
"""Base class for interfacing with a Rigetti backend in Azure Quantum"""
|
|
47
49
|
|
|
50
|
+
_SHOTS_PARAM_NAME = "count"
|
|
51
|
+
|
|
48
52
|
@abstractmethod
|
|
49
53
|
def __init__(
|
|
50
54
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
@@ -53,7 +57,10 @@ class RigettiBackend(AzureQirBackend):
|
|
|
53
57
|
|
|
54
58
|
@classmethod
|
|
55
59
|
def _default_options(cls):
|
|
56
|
-
|
|
60
|
+
other_options = {
|
|
61
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
62
|
+
}
|
|
63
|
+
return Options(targetCapability="BasicExecution", **other_options)
|
|
57
64
|
|
|
58
65
|
def _azure_config(self) -> Dict[str, str]:
|
|
59
66
|
config = super()._azure_config()
|
azure/quantum/qiskit/job.py
CHANGED
|
@@ -229,26 +229,17 @@ class AzureQuantumJob(JobV1):
|
|
|
229
229
|
|
|
230
230
|
def _format_microsoft_results(self, sampler_seed=None):
|
|
231
231
|
""" Translate Microsoft's job results histogram into a format that can be consumed by qiskit libraries. """
|
|
232
|
-
|
|
232
|
+
histogram = self._azure_job.get_results()
|
|
233
233
|
shots = self._shots_count()
|
|
234
234
|
|
|
235
|
-
if not 'Histogram' in az_result:
|
|
236
|
-
raise "Histogram missing from Job results"
|
|
237
|
-
|
|
238
|
-
histogram = az_result['Histogram']
|
|
239
235
|
counts = {}
|
|
240
236
|
probabilities = {}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
value = histogram[i + 1]
|
|
249
|
-
probabilities[bitstring] = value
|
|
250
|
-
else:
|
|
251
|
-
raise "Invalid number of items in Job results' histogram."
|
|
237
|
+
|
|
238
|
+
for key in histogram.keys():
|
|
239
|
+
bitstring = AzureQuantumJob._qir_to_qiskit_bitstring(key)
|
|
240
|
+
|
|
241
|
+
value = histogram[key]
|
|
242
|
+
probabilities[bitstring] = value
|
|
252
243
|
|
|
253
244
|
if self.backend().configuration().simulator:
|
|
254
245
|
counts = self._draw_random_sample(sampler_seed, probabilities, shots)
|
azure/quantum/qiskit/provider.py
CHANGED
|
@@ -31,7 +31,23 @@ QISKIT_USER_AGENT = "azure-quantum-qiskit"
|
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
class AzureQuantumProvider(Provider):
|
|
34
|
-
|
|
34
|
+
"""
|
|
35
|
+
Class for interfacing with the Azure Quantum service
|
|
36
|
+
using Qiskit quantum circuits
|
|
37
|
+
"""
|
|
38
|
+
def __init__(self, workspace: Workspace=None, **kwargs):
|
|
39
|
+
"""AzureQuantumService class
|
|
40
|
+
|
|
41
|
+
:param workspace: Azure Quantum workspace. If missing it will create a new Workspace passing `kwargs` to the constructor. Defaults to None.
|
|
42
|
+
:type workspace: Workspace, optional
|
|
43
|
+
"""
|
|
44
|
+
if kwargs is not None and len(kwargs) > 0:
|
|
45
|
+
from warnings import warn
|
|
46
|
+
warn(f"""Consider passing \"workspace\" argument explicitly.
|
|
47
|
+
The ability to initialize AzureQuantumProvider with arguments {', '.join(f'"{argName}"' for argName in kwargs)} is going to be deprecated in future versions.""",
|
|
48
|
+
DeprecationWarning,
|
|
49
|
+
stacklevel=2)
|
|
50
|
+
|
|
35
51
|
if workspace is None:
|
|
36
52
|
workspace = Workspace(**kwargs)
|
|
37
53
|
|
|
@@ -43,7 +59,7 @@ class AzureQuantumProvider(Provider):
|
|
|
43
59
|
def get_workspace(self) -> Workspace:
|
|
44
60
|
return self._workspace
|
|
45
61
|
|
|
46
|
-
def get_backend(self, name=None, **kwargs):
|
|
62
|
+
def get_backend(self, name=None, **kwargs) -> AzureBackendBase:
|
|
47
63
|
"""Return a single backend matching the specified filtering.
|
|
48
64
|
Args:
|
|
49
65
|
name (str): name of the backend.
|
azure/quantum/storage.py
CHANGED
|
@@ -14,6 +14,7 @@ from azure.storage.blob import (
|
|
|
14
14
|
generate_blob_sas,
|
|
15
15
|
generate_container_sas,
|
|
16
16
|
BlobType,
|
|
17
|
+
BlobProperties
|
|
17
18
|
)
|
|
18
19
|
from datetime import datetime, timedelta
|
|
19
20
|
from enum import Enum
|
|
@@ -196,7 +197,7 @@ def download_blob(blob_url: str) -> Any:
|
|
|
196
197
|
return response
|
|
197
198
|
|
|
198
199
|
|
|
199
|
-
def download_blob_properties(blob_url: str) ->
|
|
200
|
+
def download_blob_properties(blob_url: str) -> BlobProperties:
|
|
200
201
|
"""Downloads the blob properties from Azure for the given blob URI"""
|
|
201
202
|
blob_client = BlobClient.from_blob_url(blob_url)
|
|
202
203
|
logger.info(
|
azure/quantum/target/__init__.py
CHANGED
|
@@ -11,6 +11,7 @@ from .ionq import IonQ
|
|
|
11
11
|
from .quantinuum import Quantinuum
|
|
12
12
|
from .rigetti import Rigetti
|
|
13
13
|
from .pasqal import Pasqal
|
|
14
|
+
from .microsoft.elements.dft import MicrosoftElementsDft, MicrosoftElementsDftJob
|
|
14
15
|
|
|
15
16
|
# Default targets to use when there is no target class
|
|
16
17
|
# associated with a given target ID
|
azure/quantum/target/ionq.py
CHANGED
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
5
|
from typing import Any, Dict, List
|
|
6
|
+
from warnings import warn
|
|
6
7
|
|
|
7
|
-
from azure.quantum.target.target import
|
|
8
|
+
from azure.quantum.target.target import (
|
|
9
|
+
Target,
|
|
10
|
+
_determine_shots_or_deprecated_num_shots,
|
|
11
|
+
)
|
|
8
12
|
from azure.quantum.job.job import Job
|
|
9
13
|
from azure.quantum.workspace import Workspace
|
|
10
14
|
from azure.quantum._client.models import CostEstimate, UsageEvent
|
|
@@ -50,6 +54,8 @@ class IonQ(Target):
|
|
|
50
54
|
"ionq.qpu.forte-1"
|
|
51
55
|
)
|
|
52
56
|
|
|
57
|
+
_SHOTS_PARAM_NAME = "shots"
|
|
58
|
+
|
|
53
59
|
def __init__(
|
|
54
60
|
self,
|
|
55
61
|
workspace: Workspace,
|
|
@@ -78,7 +84,7 @@ class IonQ(Target):
|
|
|
78
84
|
self,
|
|
79
85
|
circuit: Dict[str, Any] = None,
|
|
80
86
|
name: str = "ionq-job",
|
|
81
|
-
|
|
87
|
+
shots: int = None,
|
|
82
88
|
input_params: Dict[str, Any] = None,
|
|
83
89
|
**kwargs
|
|
84
90
|
) -> Job:
|
|
@@ -89,8 +95,8 @@ class IonQ(Target):
|
|
|
89
95
|
:type circuit: Dict[str, Any]
|
|
90
96
|
:param name: Job name
|
|
91
97
|
:type name: str
|
|
92
|
-
:param
|
|
93
|
-
:type
|
|
98
|
+
:param shots: Number of shots, defaults to None
|
|
99
|
+
:type shots: int
|
|
94
100
|
:param input_params: Optional input params dict
|
|
95
101
|
:type input_params: Dict[str, Any]
|
|
96
102
|
:return: Azure Quantum job
|
|
@@ -103,13 +109,18 @@ class IonQ(Target):
|
|
|
103
109
|
)
|
|
104
110
|
if input_params is None:
|
|
105
111
|
input_params = {}
|
|
106
|
-
if num_shots is not None:
|
|
107
|
-
input_params = input_params.copy()
|
|
108
|
-
input_params["shots"] = num_shots
|
|
109
112
|
|
|
113
|
+
num_shots = kwargs.pop("num_shots", None)
|
|
114
|
+
|
|
115
|
+
shots = _determine_shots_or_deprecated_num_shots(
|
|
116
|
+
shots=shots,
|
|
117
|
+
num_shots=num_shots,
|
|
118
|
+
)
|
|
119
|
+
|
|
110
120
|
return super().submit(
|
|
111
121
|
input_data=input_data,
|
|
112
122
|
name=name,
|
|
123
|
+
shots=shots,
|
|
113
124
|
input_params=input_params,
|
|
114
125
|
**kwargs
|
|
115
126
|
)
|
|
@@ -117,10 +128,11 @@ class IonQ(Target):
|
|
|
117
128
|
def estimate_cost(
|
|
118
129
|
self,
|
|
119
130
|
circuit: Dict[str, Any],
|
|
120
|
-
num_shots: int,
|
|
131
|
+
num_shots: int = None,
|
|
121
132
|
price_1q: float = None,
|
|
122
133
|
price_2q: float = None,
|
|
123
|
-
min_price: float = None
|
|
134
|
+
min_price: float = None,
|
|
135
|
+
shots: int = None
|
|
124
136
|
) -> CostEstimate:
|
|
125
137
|
"""Estimate the cost of submitting a circuit to IonQ targets.
|
|
126
138
|
Optionally, you can provide the number of gate and measurement operations
|
|
@@ -156,7 +168,20 @@ class IonQ(Target):
|
|
|
156
168
|
:type price_2q: float, optional
|
|
157
169
|
:param min_price: The minimum price for running a job.
|
|
158
170
|
:type min_price: float, optional
|
|
171
|
+
:param shots: Number of shots, defaults to None
|
|
172
|
+
:type shots: int
|
|
159
173
|
"""
|
|
174
|
+
|
|
175
|
+
if num_shots is None and shots is None:
|
|
176
|
+
raise ValueError("The 'shots' parameter has to be specified")
|
|
177
|
+
|
|
178
|
+
if num_shots is not None:
|
|
179
|
+
warn(
|
|
180
|
+
"The 'num_shots' parameter will be deprecated. Please, use 'shots' parameter instead.",
|
|
181
|
+
category=DeprecationWarning,
|
|
182
|
+
)
|
|
183
|
+
shots = num_shots
|
|
184
|
+
|
|
160
185
|
def is_1q_gate(gate: Dict[str, Any]):
|
|
161
186
|
return "controls" not in gate and "control" not in gate
|
|
162
187
|
|
|
@@ -185,7 +210,7 @@ class IonQ(Target):
|
|
|
185
210
|
N_1q = sum(map(is_1q_gate, gates))
|
|
186
211
|
N_2q = sum(map(num_2q_gates, filter(is_multi_q_gate, gates)))
|
|
187
212
|
|
|
188
|
-
price = (price_1q * N_1q + price_2q * N_2q) *
|
|
213
|
+
price = (price_1q * N_1q + price_2q * N_2q) * shots
|
|
189
214
|
price = max(price, min_price)
|
|
190
215
|
|
|
191
216
|
return CostEstimate(
|
|
@@ -195,7 +220,7 @@ class IonQ(Target):
|
|
|
195
220
|
dimension_name="1Q Gate Shot",
|
|
196
221
|
measure_unit="1q gate shot",
|
|
197
222
|
amount_billed=0.0,
|
|
198
|
-
amount_consumed=N_1q *
|
|
223
|
+
amount_consumed=N_1q * shots,
|
|
199
224
|
unit_price=0.0
|
|
200
225
|
),
|
|
201
226
|
UsageEvent(
|
|
@@ -203,7 +228,7 @@ class IonQ(Target):
|
|
|
203
228
|
dimension_name="2Q Gate Shot",
|
|
204
229
|
measure_unit="2q gate shot",
|
|
205
230
|
amount_billed=0.0,
|
|
206
|
-
amount_consumed=N_2q *
|
|
231
|
+
amount_consumed=N_2q * shots,
|
|
207
232
|
unit_price=0.0
|
|
208
233
|
)
|
|
209
234
|
],
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import collections.abc
|
|
2
|
+
from typing import Any, Dict, Union
|
|
3
|
+
from azure.quantum.job import JobFailedWithResultsError
|
|
4
|
+
from azure.quantum.job.job import Job, DEFAULT_TIMEOUT
|
|
5
|
+
from azure.quantum._client.models import JobDetails
|
|
6
|
+
|
|
7
|
+
class MicrosoftElementsDftJob(Job):
|
|
8
|
+
"""
|
|
9
|
+
A dedicated job class for jobs from the microsoft.dft target.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, workspace, job_details: JobDetails, **kwargs):
|
|
13
|
+
super().__init__(workspace, job_details, **kwargs)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def get_results(self, timeout_secs: float = DEFAULT_TIMEOUT) -> Dict[str, Any]:
|
|
17
|
+
try:
|
|
18
|
+
job_results = super().get_results(timeout_secs)
|
|
19
|
+
return job_results["results"]
|
|
20
|
+
except JobFailedWithResultsError as e:
|
|
21
|
+
failure_results = e.get_failure_results()
|
|
22
|
+
if MicrosoftElementsDftJob._is_dft_failure_results(failure_results):
|
|
23
|
+
error = failure_results["results"][0]["error"]
|
|
24
|
+
message = f'{e.get_message()} Error type: {error["error_type"]}. Message: {error["error_message"]}'
|
|
25
|
+
raise JobFailedWithResultsError(message, failure_results) from None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@classmethod
|
|
29
|
+
def _allow_failure_results(cls) -> bool:
|
|
30
|
+
"""
|
|
31
|
+
Allow to download job results even if the Job status is "Failed".
|
|
32
|
+
"""
|
|
33
|
+
return True
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def _is_dft_failure_results(failure_results: Union[Dict[str, Any], str]) -> bool:
|
|
38
|
+
return isinstance(failure_results, dict) \
|
|
39
|
+
and "results" in failure_results \
|
|
40
|
+
and isinstance(failure_results["results"], collections.abc.Sequence) \
|
|
41
|
+
and len(failure_results["results"]) > 0 \
|
|
42
|
+
and isinstance(failure_results["results"][0], dict) \
|
|
43
|
+
and "error" in failure_results["results"][0] \
|
|
44
|
+
and isinstance(failure_results["results"][0]["error"], dict) \
|
|
45
|
+
and "error_type" in failure_results["results"][0]["error"] \
|
|
46
|
+
and "error_message" in failure_results["results"][0]["error"]
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
|
|
3
|
+
from azure.quantum.job.base_job import ContentType
|
|
4
|
+
from azure.quantum.job.job import Job
|
|
5
|
+
from azure.quantum.target.target import Target
|
|
6
|
+
from azure.quantum.workspace import Workspace
|
|
7
|
+
from azure.quantum.target.params import InputParams
|
|
8
|
+
from typing import Any, Dict, Type, Union
|
|
9
|
+
from .job import MicrosoftElementsDftJob
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class MicrosoftElementsDft(Target):
|
|
13
|
+
"""
|
|
14
|
+
Microsoft Elements Dft target from the microsoft-elements provider.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
target_names = [
|
|
18
|
+
"microsoft.dft"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
workspace: "Workspace",
|
|
25
|
+
name: str = "microsoft.dft",
|
|
26
|
+
**kwargs
|
|
27
|
+
):
|
|
28
|
+
# There is only a single target name for this target
|
|
29
|
+
assert name == self.target_names[0]
|
|
30
|
+
|
|
31
|
+
# make sure to not pass argument twice
|
|
32
|
+
kwargs.pop("provider_id", None)
|
|
33
|
+
|
|
34
|
+
super().__init__(
|
|
35
|
+
workspace=workspace,
|
|
36
|
+
name=name,
|
|
37
|
+
input_data_format="microsoft.xyz.v1",
|
|
38
|
+
output_data_format="microsoft.dft-results.v1",
|
|
39
|
+
provider_id="microsoft-elements",
|
|
40
|
+
content_type=ContentType.text_plain,
|
|
41
|
+
**kwargs
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def submit(self,
|
|
46
|
+
input_data: Any,
|
|
47
|
+
name: str = "azure-quantum-dft-job",
|
|
48
|
+
shots: int = None,
|
|
49
|
+
input_params: Union[Dict[str, Any], InputParams, None] = None,
|
|
50
|
+
**kwargs) -> MicrosoftElementsDftJob:
|
|
51
|
+
|
|
52
|
+
if shots is not None:
|
|
53
|
+
warnings.warn("The 'shots' parameter is ignored in Microsoft Elements Dft job.")
|
|
54
|
+
|
|
55
|
+
return super().submit(
|
|
56
|
+
input_data=input_data,
|
|
57
|
+
name=name,
|
|
58
|
+
shots=shots,
|
|
59
|
+
input_params=input_params,
|
|
60
|
+
**kwargs
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@classmethod
|
|
65
|
+
def _get_job_class(cls) -> Type[Job]:
|
|
66
|
+
return MicrosoftElementsDftJob
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
5
|
import re
|
|
6
|
+
import warnings
|
|
6
7
|
from dataclasses import dataclass, field
|
|
7
|
-
from typing import Any, Dict, Optional, Type, Union
|
|
8
|
+
from typing import Any, Dict, Optional, Type, Union, List
|
|
9
|
+
|
|
8
10
|
from ...job import Job
|
|
9
11
|
from ...job.base_job import ContentType
|
|
10
12
|
from ...workspace import Workspace
|
|
@@ -12,8 +14,6 @@ from ..params import InputParams, InputParamsItem, AutoValidatingParams, \
|
|
|
12
14
|
validating_field
|
|
13
15
|
from ..target import Target
|
|
14
16
|
from . import MicrosoftEstimatorJob
|
|
15
|
-
from typing import List
|
|
16
|
-
|
|
17
17
|
|
|
18
18
|
class QubitParams:
|
|
19
19
|
GATE_US_E3 = "qubit_gate_us_e3"
|
|
@@ -377,11 +377,32 @@ class MicrosoftEstimator(Target):
|
|
|
377
377
|
**kwargs
|
|
378
378
|
)
|
|
379
379
|
|
|
380
|
-
def submit(
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
380
|
+
def submit(
|
|
381
|
+
self,
|
|
382
|
+
input_data: Any,
|
|
383
|
+
name: str = "azure-quantum-job",
|
|
384
|
+
shots: int = None,
|
|
385
|
+
input_params: Union[Dict[str, Any], InputParams, None] = None,
|
|
386
|
+
**kwargs,
|
|
387
|
+
) -> Job:
|
|
388
|
+
"""
|
|
389
|
+
Submit an estimation job
|
|
390
|
+
|
|
391
|
+
:param input_data: Input data
|
|
392
|
+
:type input_data: Any
|
|
393
|
+
:param name: Job name
|
|
394
|
+
:type name: str
|
|
395
|
+
:param shots: Number of shots. Ignored in estimation. Defaults to None
|
|
396
|
+
:type shots: int
|
|
397
|
+
:param input_params: Input parameters
|
|
398
|
+
:type input_params: Dict[str, Any]
|
|
399
|
+
:return: Azure Quantum job
|
|
400
|
+
:rtype: Job
|
|
401
|
+
"""
|
|
402
|
+
|
|
403
|
+
if shots is not None:
|
|
404
|
+
warnings.warn("The 'shots' parameter is ignored in resource estimation job.")
|
|
405
|
+
|
|
385
406
|
try:
|
|
386
407
|
from qiskit import QuantumCircuit, transpile
|
|
387
408
|
from qiskit_qir import to_qir_module
|
|
@@ -393,7 +414,13 @@ class MicrosoftEstimator(Target):
|
|
|
393
414
|
(module, _) = to_qir_module(input_data, record_output=False)
|
|
394
415
|
input_data = module.bitcode
|
|
395
416
|
finally:
|
|
396
|
-
return super().submit(
|
|
417
|
+
return super().submit(
|
|
418
|
+
input_data=input_data,
|
|
419
|
+
name=name,
|
|
420
|
+
shots=shots,
|
|
421
|
+
input_params=input_params,
|
|
422
|
+
**kwargs
|
|
423
|
+
)
|
|
397
424
|
|
|
398
425
|
@classmethod
|
|
399
426
|
def _get_job_class(cls) -> Type[Job]:
|
azure/quantum/target/params.py
CHANGED
|
@@ -180,7 +180,7 @@ class InputParams(InputParamsItem):
|
|
|
180
180
|
"""
|
|
181
181
|
Class to define input parameters.
|
|
182
182
|
|
|
183
|
-
This class allows to define
|
|
183
|
+
This class allows to define input parameters for non-batching and batching
|
|
184
184
|
jobs. The instance represents a batching job, if and only if num_items is
|
|
185
185
|
set to some positive number less or equal to MAX_NUM_ITEMS.
|
|
186
186
|
|
|
@@ -64,6 +64,8 @@ class Pasqal(Target):
|
|
|
64
64
|
|
|
65
65
|
target_names = tuple(target.value for target in PasqalTarget)
|
|
66
66
|
|
|
67
|
+
_SHOTS_PARAM_NAME = "count"
|
|
68
|
+
|
|
67
69
|
def __init__(
|
|
68
70
|
self,
|
|
69
71
|
workspace: Workspace,
|
|
@@ -91,6 +93,7 @@ class Pasqal(Target):
|
|
|
91
93
|
self,
|
|
92
94
|
input_data: Any,
|
|
93
95
|
name: str = "azure-quantum-job",
|
|
96
|
+
shots: int = None,
|
|
94
97
|
input_params: Union[InputParams, None, Dict[str, Any]] = None,
|
|
95
98
|
**kwargs,
|
|
96
99
|
) -> Job:
|
|
@@ -103,15 +106,26 @@ class Pasqal(Target):
|
|
|
103
106
|
:type input_data: Any
|
|
104
107
|
:param name: Job name
|
|
105
108
|
:type name: str
|
|
109
|
+
:param shots: Number of shots, defaults to None
|
|
110
|
+
:type shots: int
|
|
106
111
|
:param input_params: Input parameters, see :class:`azure.quantum.target.pasqal.InputParams` for details.
|
|
107
112
|
:type input_params: Union[InputParams, None, Dict[str, Any]]
|
|
108
113
|
:return: Azure Quantum job
|
|
109
114
|
:rtype: Job
|
|
110
115
|
"""
|
|
116
|
+
|
|
111
117
|
if isinstance(input_params, InputParams):
|
|
112
118
|
typed_input_params = input_params
|
|
113
119
|
input_params = {
|
|
114
|
-
|
|
120
|
+
self.__class__._SHOTS_PARAM_NAME: typed_input_params.runs,
|
|
115
121
|
}
|
|
122
|
+
|
|
123
|
+
input_params = input_params or {}
|
|
116
124
|
|
|
117
|
-
return super().submit(
|
|
125
|
+
return super().submit(
|
|
126
|
+
input_data=input_data,
|
|
127
|
+
name=name,
|
|
128
|
+
shots=shots,
|
|
129
|
+
input_params=input_params,
|
|
130
|
+
**kwargs
|
|
131
|
+
)
|
|
@@ -3,8 +3,12 @@
|
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
5
|
from typing import Any, Dict
|
|
6
|
+
from warnings import warn
|
|
6
7
|
|
|
7
|
-
from azure.quantum.target.target import
|
|
8
|
+
from azure.quantum.target.target import (
|
|
9
|
+
Target,
|
|
10
|
+
_determine_shots_or_deprecated_num_shots,
|
|
11
|
+
)
|
|
8
12
|
from azure.quantum.job.job import Job
|
|
9
13
|
from azure.quantum.workspace import Workspace
|
|
10
14
|
from azure.quantum._client.models import CostEstimate, UsageEvent
|
|
@@ -25,6 +29,8 @@ class Quantinuum(Target):
|
|
|
25
29
|
"quantinuum.sim.h2-1e",
|
|
26
30
|
)
|
|
27
31
|
|
|
32
|
+
_SHOTS_PARAM_NAME = "count"
|
|
33
|
+
|
|
28
34
|
def __init__(
|
|
29
35
|
self,
|
|
30
36
|
workspace: Workspace,
|
|
@@ -53,7 +59,7 @@ class Quantinuum(Target):
|
|
|
53
59
|
self,
|
|
54
60
|
circuit: str = None,
|
|
55
61
|
name: str = "quantinuum-job",
|
|
56
|
-
|
|
62
|
+
shots: int = None,
|
|
57
63
|
input_params: Dict[str, Any] = None,
|
|
58
64
|
**kwargs
|
|
59
65
|
) -> Job:
|
|
@@ -63,8 +69,8 @@ class Quantinuum(Target):
|
|
|
63
69
|
:type circuit: str
|
|
64
70
|
:param name: Job name
|
|
65
71
|
:type name: str
|
|
66
|
-
:param
|
|
67
|
-
:type
|
|
72
|
+
:param shots: Number of shots, defaults to None
|
|
73
|
+
:type shots: int
|
|
68
74
|
:param input_params: Optional input params dict
|
|
69
75
|
:type input_params: Dict[str, Any]
|
|
70
76
|
:return: Azure Quantum job
|
|
@@ -77,13 +83,18 @@ class Quantinuum(Target):
|
|
|
77
83
|
)
|
|
78
84
|
if input_params is None:
|
|
79
85
|
input_params = {}
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
|
|
87
|
+
num_shots = kwargs.pop("num_shots", None)
|
|
88
|
+
|
|
89
|
+
shots = _determine_shots_or_deprecated_num_shots(
|
|
90
|
+
shots=shots,
|
|
91
|
+
num_shots=num_shots,
|
|
92
|
+
)
|
|
83
93
|
|
|
84
94
|
return super().submit(
|
|
85
95
|
input_data=input_data,
|
|
86
96
|
name=name,
|
|
97
|
+
shots=shots,
|
|
87
98
|
input_params=input_params,
|
|
88
99
|
**kwargs
|
|
89
100
|
)
|
|
@@ -94,7 +105,8 @@ class Quantinuum(Target):
|
|
|
94
105
|
num_shots: int = None,
|
|
95
106
|
N_1q: int = None,
|
|
96
107
|
N_2q: int = None,
|
|
97
|
-
N_m: int = None
|
|
108
|
+
N_m: int = None,
|
|
109
|
+
shots: int = None,
|
|
98
110
|
) -> CostEstimate:
|
|
99
111
|
"""Estimate the cost in HQC for a given circuit.
|
|
100
112
|
Optionally, you can provide the number of gate and measurement operations
|
|
@@ -119,9 +131,22 @@ class Quantinuum(Target):
|
|
|
119
131
|
:param N_m: Number of measurement operations, if not specified,
|
|
120
132
|
this is estimated from the circuit
|
|
121
133
|
:type N_m: int, optional
|
|
134
|
+
:param shots: Number of shots for which to estimate costs
|
|
135
|
+
:type shots: int, optional
|
|
122
136
|
:raises ImportError: If N_1q, N_2q and N_m are not specified,
|
|
123
137
|
this will require a qiskit installation.
|
|
124
138
|
"""
|
|
139
|
+
|
|
140
|
+
if num_shots is None and shots is None:
|
|
141
|
+
raise ValueError("The 'shots' parameter has to be specified")
|
|
142
|
+
|
|
143
|
+
if num_shots is not None:
|
|
144
|
+
warn(
|
|
145
|
+
"The 'num_shots' parameter will be deprecated. Please, use 'shots' parameter instead.",
|
|
146
|
+
category=DeprecationWarning,
|
|
147
|
+
)
|
|
148
|
+
shots = num_shots
|
|
149
|
+
|
|
125
150
|
if circuit is not None and (N_1q is None or N_2q is None or N_m is None):
|
|
126
151
|
try:
|
|
127
152
|
from qiskit.circuit.quantumcircuit import Qasm
|
|
@@ -160,7 +185,7 @@ class Quantinuum(Target):
|
|
|
160
185
|
if is_syntax_checker_regex.match(self.name):
|
|
161
186
|
HQC = 0.0
|
|
162
187
|
else:
|
|
163
|
-
HQC = 5 +
|
|
188
|
+
HQC = 5 + shots * (N_1q + 10 * N_2q + 5 * N_m) / 5000
|
|
164
189
|
|
|
165
190
|
return CostEstimate(
|
|
166
191
|
events=[
|