azure-quantum 0.30.0__tar.gz → 1.0.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-0.30.0 → azure-quantum-1.0.0}/PKG-INFO +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_version.py +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/service.py +7 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/quantinuum.py +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/job.py +15 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/backend.py +130 -35
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/ionq.py +65 -5
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/qci.py +35 -2
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/quantinuum.py +25 -4
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/rigetti.py +8 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/job.py +7 -16
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/provider.py +18 -2
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/ionq.py +37 -12
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/target.py +13 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/target.py +36 -9
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/params.py +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/target.py +16 -2
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/quantinuum.py +34 -9
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/target.py +15 -2
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/solvers.py +7 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/target.py +82 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/target_factory.py +0 -2
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/version.py +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/workspace.py +11 -8
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/PKG-INFO +1 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/SOURCES.txt +0 -28
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/requires.txt +2 -4
- azure-quantum-1.0.0/requirements-qsharp.txt +1 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements.txt +0 -2
- azure-quantum-0.30.0/azure/quantum/_client/aio/__init__.py +0 -23
- azure-quantum-0.30.0/azure/quantum/_client/aio/_client.py +0 -124
- azure-quantum-0.30.0/azure/quantum/_client/aio/_configuration.py +0 -89
- azure-quantum-0.30.0/azure/quantum/_client/aio/operations/_operations.py +0 -1291
- azure-quantum-0.30.0/azure/quantum/_client/models/_patch.py +0 -20
- azure-quantum-0.30.0/azure/quantum/_client/operations/__init__.py +0 -29
- azure-quantum-0.30.0/azure/quantum/_client/operations/_patch.py +0 -20
- azure-quantum-0.30.0/azure/quantum/aio/__init__.py +0 -14
- azure-quantum-0.30.0/azure/quantum/aio/_authentication/__init__.py +0 -9
- azure-quantum-0.30.0/azure/quantum/aio/_authentication/_chained.py +0 -94
- azure-quantum-0.30.0/azure/quantum/aio/_authentication/_default.py +0 -212
- azure-quantum-0.30.0/azure/quantum/aio/_authentication/_token.py +0 -81
- azure-quantum-0.30.0/azure/quantum/aio/job/__init__.py +0 -1
- azure-quantum-0.30.0/azure/quantum/aio/job/base_job.py +0 -326
- azure-quantum-0.30.0/azure/quantum/aio/job/job.py +0 -104
- azure-quantum-0.30.0/azure/quantum/aio/optimization/__init__.py +0 -11
- azure-quantum-0.30.0/azure/quantum/aio/optimization/online_problem.py +0 -17
- azure-quantum-0.30.0/azure/quantum/aio/optimization/problem.py +0 -102
- azure-quantum-0.30.0/azure/quantum/aio/optimization/streaming_problem.py +0 -280
- azure-quantum-0.30.0/azure/quantum/aio/storage.py +0 -390
- azure-quantum-0.30.0/azure/quantum/aio/target/__init__.py +0 -19
- azure-quantum-0.30.0/azure/quantum/aio/target/ionq.py +0 -47
- azure-quantum-0.30.0/azure/quantum/aio/target/quantinuum.py +0 -47
- azure-quantum-0.30.0/azure/quantum/aio/target/solvers.py +0 -96
- azure-quantum-0.30.0/azure/quantum/aio/target/target.py +0 -68
- azure-quantum-0.30.0/azure/quantum/aio/target/target_factory.py +0 -72
- azure-quantum-0.30.0/azure/quantum/aio/target/toshiba.py +0 -6
- azure-quantum-0.30.0/azure/quantum/aio/workspace.py +0 -337
- azure-quantum-0.30.0/requirements-qsharp.txt +0 -1
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/README.md +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_chained.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_default.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_token.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_client.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_configuration.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_patch.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_serialization.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_vendor.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/_enums.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/_models.py +0 -0
- {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client/models}/_patch.py +0 -0
- {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client}/operations/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/operations/_operations.py +0 -0
- {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client}/operations/_patch.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/argument_types/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/argument_types/types.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/chemistry/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/job.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/ionq.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/target.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/base_job.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/filtered_job.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/job_failed_with_results_error.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/session.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/workspace_item.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/workspace_item_factory.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/online_problem.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/problem.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/solvers.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/streaming_problem.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/term.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/toshiba/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/toshiba/solvers.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/microsoft.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/results/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/results/resource_estimator.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/storage.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/job.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/job.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/result.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/result.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/result.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/toshiba/__init__.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/toshiba/solvers.py +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/dependency_links.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/top_level.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-cirq.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-dev.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-qiskit.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-quil.txt +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/setup.cfg +0 -0
- {azure-quantum-0.30.0 → azure-quantum-1.0.0}/setup.py +0 -0
|
@@ -43,6 +43,13 @@ class AzureQuantumService:
|
|
|
43
43
|
:param default_target: Default target name, defaults to None
|
|
44
44
|
:type default_target: Optional[str], optional
|
|
45
45
|
"""
|
|
46
|
+
if kwargs is not None and len(kwargs) > 0:
|
|
47
|
+
from warnings import warn
|
|
48
|
+
warn(f"""Consider passing \"workspace\" argument explicitly.
|
|
49
|
+
The ability to initialize AzureQuantumService with arguments {', '.join(f'"{argName}"' for argName in kwargs)} is going to be deprecated in future versions.""",
|
|
50
|
+
DeprecationWarning,
|
|
51
|
+
stacklevel=2)
|
|
52
|
+
|
|
46
53
|
if workspace is None:
|
|
47
54
|
workspace = Workspace(**kwargs)
|
|
48
55
|
|
|
@@ -133,7 +133,21 @@ class Job(BaseJob, FilteredJob):
|
|
|
133
133
|
payload = self.download_data(self.details.output_data_uri)
|
|
134
134
|
try:
|
|
135
135
|
payload = payload.decode("utf8")
|
|
136
|
-
|
|
136
|
+
results = json.loads(payload)
|
|
137
|
+
|
|
138
|
+
if self.details.output_data_format == "microsoft.quantum-results.v1":
|
|
139
|
+
if "Histogram" not in results:
|
|
140
|
+
raise f"\"Histogram\" array was expected to be in the Job results for \"{self.details.output_data_format}\" output format."
|
|
141
|
+
|
|
142
|
+
histogram_values = results["Histogram"]
|
|
143
|
+
|
|
144
|
+
if len(histogram_values) % 2 == 0:
|
|
145
|
+
# Re-mapping {'Histogram': ['[0]', 0.50, '[1]', 0.50] } to {'[0]': 0.50, '[1]': 0.50}
|
|
146
|
+
return {histogram_values[i]: histogram_values[i + 1] for i in range(0, len(histogram_values), 2)}
|
|
147
|
+
else:
|
|
148
|
+
raise f"\"Histogram\" array has invalid format. Even number of items is expected."
|
|
149
|
+
|
|
150
|
+
return results
|
|
137
151
|
except:
|
|
138
152
|
# If errors decoding the data, return the raw payload:
|
|
139
153
|
return payload
|
|
@@ -10,7 +10,7 @@ import warnings
|
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
-
from typing import Any, Dict, Tuple, Union, List
|
|
13
|
+
from typing import Any, Dict, Tuple, Union, List, Optional
|
|
14
14
|
from azure.quantum.version import __version__
|
|
15
15
|
from azure.quantum.qiskit.job import (
|
|
16
16
|
MICROSOFT_OUTPUT_DATA_FORMAT,
|
|
@@ -38,6 +38,11 @@ To install run: pip install azure-quantum[qiskit]"
|
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
class AzureBackendBase(Backend, SessionHost):
|
|
41
|
+
|
|
42
|
+
# Name of the provider's input parameter which specifies number of shots for a submitted job.
|
|
43
|
+
# If None, backend will not pass this input parameter.
|
|
44
|
+
_SHOTS_PARAM_NAME = None
|
|
45
|
+
|
|
41
46
|
@abstractmethod
|
|
42
47
|
def __init__(
|
|
43
48
|
self,
|
|
@@ -46,6 +51,41 @@ class AzureBackendBase(Backend, SessionHost):
|
|
|
46
51
|
**fields
|
|
47
52
|
):
|
|
48
53
|
super().__init__(configuration, provider, **fields)
|
|
54
|
+
|
|
55
|
+
@abstractmethod
|
|
56
|
+
def run(
|
|
57
|
+
self,
|
|
58
|
+
run_input: Union[QuantumCircuit, List[QuantumCircuit]] = [],
|
|
59
|
+
shots: int = None,
|
|
60
|
+
**options,
|
|
61
|
+
) -> AzureQuantumJob:
|
|
62
|
+
"""Run on the backend.
|
|
63
|
+
|
|
64
|
+
This method returns a
|
|
65
|
+
:class:`~azure.quantum.qiskit.job.AzureQuantumJob` object
|
|
66
|
+
that runs circuits.
|
|
67
|
+
|
|
68
|
+
Args:
|
|
69
|
+
run_input (QuantumCircuit or List[QuantumCircuit]): An individual or a
|
|
70
|
+
list of :class:`~qiskit.circuits.QuantumCircuit` to run on the backend.
|
|
71
|
+
shots (int, optional): Number of shots, defaults to None.
|
|
72
|
+
options: Any kwarg options to pass to the backend for running the
|
|
73
|
+
config. If a key is also present in the options
|
|
74
|
+
attribute/object then the expectation is that the value
|
|
75
|
+
specified will be used instead of what's set in the options
|
|
76
|
+
object.
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
Job: The job object for the run
|
|
80
|
+
"""
|
|
81
|
+
pass
|
|
82
|
+
|
|
83
|
+
@classmethod
|
|
84
|
+
def _can_send_shots_input_param(cls) -> bool:
|
|
85
|
+
"""
|
|
86
|
+
Tells if provider's backend class is able to specify shots number for its jobs.
|
|
87
|
+
"""
|
|
88
|
+
return cls._SHOTS_PARAM_NAME is not None
|
|
49
89
|
|
|
50
90
|
@classmethod
|
|
51
91
|
@abstractmethod
|
|
@@ -80,30 +120,47 @@ class AzureBackendBase(Backend, SessionHost):
|
|
|
80
120
|
output_data_format = options.pop("output_data_format", azure_defined_override)
|
|
81
121
|
|
|
82
122
|
return output_data_format
|
|
83
|
-
|
|
84
|
-
def _get_input_params(self, options) -> Dict[str, Any]:
|
|
123
|
+
|
|
124
|
+
def _get_input_params(self, options, shots: int = None) -> Dict[str, Any]:
|
|
85
125
|
# Backend options are mapped to input_params.
|
|
86
126
|
input_params: Dict[str, Any] = vars(self.options).copy()
|
|
87
127
|
|
|
88
|
-
#
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
128
|
+
# Determine shots number, if needed.
|
|
129
|
+
if self._can_send_shots_input_param():
|
|
130
|
+
options_shots = options.pop(self.__class__._SHOTS_PARAM_NAME, None)
|
|
131
|
+
|
|
132
|
+
# First we check for the explicitly specified 'shots' parameter, then for a provider-specific
|
|
133
|
+
# field in options, then for a backend's default value.
|
|
134
|
+
|
|
135
|
+
# Warn abount options conflict, default to 'shots'.
|
|
136
|
+
if shots is not None and options_shots is not None:
|
|
137
|
+
warnings.warn(
|
|
138
|
+
f"Parameter 'shots' conflicts with the '{self.__class__._SHOTS_PARAM_NAME}' parameter. "
|
|
139
|
+
"Please, provide only one option for setting shots. Defaulting to 'shots' parameter."
|
|
140
|
+
)
|
|
141
|
+
final_shots = shots
|
|
142
|
+
|
|
143
|
+
elif shots is not None:
|
|
144
|
+
final_shots = shots
|
|
145
|
+
else:
|
|
146
|
+
warnings.warn(
|
|
147
|
+
f"Parameter '{self.__class__._SHOTS_PARAM_NAME}' is subject to change in future versions. "
|
|
148
|
+
"Please, use 'shots' parameter instead."
|
|
149
|
+
)
|
|
150
|
+
final_shots = options_shots
|
|
151
|
+
|
|
152
|
+
# If nothing is found, try to get from default values.
|
|
153
|
+
if final_shots is None:
|
|
154
|
+
final_shots = input_params.get(self.__class__._SHOTS_PARAM_NAME)
|
|
155
|
+
|
|
156
|
+
# Also add all possible shots options into input_params to make sure
|
|
157
|
+
# that all backends covered.
|
|
158
|
+
# TODO: Double check all backends for shots options in order to remove this extra check.
|
|
159
|
+
input_params["shots"] = final_shots
|
|
160
|
+
input_params["count"] = final_shots
|
|
102
161
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
options.pop("shots", None)
|
|
106
|
-
options.pop("count", None)
|
|
162
|
+
input_params[self.__class__._SHOTS_PARAM_NAME] = final_shots
|
|
163
|
+
|
|
107
164
|
|
|
108
165
|
if "items" in options:
|
|
109
166
|
input_params["items"] = options.pop("items")
|
|
@@ -114,9 +171,6 @@ class AzureBackendBase(Backend, SessionHost):
|
|
|
114
171
|
if opt in input_params:
|
|
115
172
|
input_params[opt] = options.pop(opt)
|
|
116
173
|
|
|
117
|
-
input_params["count"] = shots_count
|
|
118
|
-
input_params["shots"] = shots_count
|
|
119
|
-
|
|
120
174
|
return input_params
|
|
121
175
|
|
|
122
176
|
def _run(self, job_name, input_data, input_params, metadata, **options):
|
|
@@ -223,18 +277,21 @@ class AzureQirBackend(AzureBackendBase):
|
|
|
223
277
|
}
|
|
224
278
|
|
|
225
279
|
def run(
|
|
226
|
-
self,
|
|
280
|
+
self,
|
|
281
|
+
run_input: Union[QuantumCircuit, List[QuantumCircuit]] = [],
|
|
282
|
+
shots: int = None,
|
|
283
|
+
**options,
|
|
227
284
|
) -> AzureQuantumJob:
|
|
228
285
|
"""Run on the backend.
|
|
229
286
|
|
|
230
287
|
This method returns a
|
|
231
288
|
:class:`~azure.quantum.qiskit.job.AzureQuantumJob` object
|
|
232
|
-
that runs circuits.
|
|
289
|
+
that runs circuits.
|
|
233
290
|
|
|
234
291
|
Args:
|
|
235
292
|
run_input (QuantumCircuit or List[QuantumCircuit]): An individual or a
|
|
236
293
|
list of :class:`~qiskit.circuits.QuantumCircuit` to run on the backend.
|
|
237
|
-
|
|
294
|
+
shots (int, optional): Number of shots, defaults to None.
|
|
238
295
|
options: Any kwarg options to pass to the backend for running the
|
|
239
296
|
config. If a key is also present in the options
|
|
240
297
|
attribute/object then the expectation is that the value
|
|
@@ -261,13 +318,18 @@ class AzureQirBackend(AzureBackendBase):
|
|
|
261
318
|
)
|
|
262
319
|
|
|
263
320
|
# config normalization
|
|
264
|
-
input_params = self._get_input_params(options)
|
|
321
|
+
input_params = self._get_input_params(options, shots=shots)
|
|
322
|
+
|
|
323
|
+
shots_count = None
|
|
265
324
|
|
|
266
|
-
|
|
325
|
+
if self._can_send_shots_input_param():
|
|
326
|
+
shots_count = input_params.get(self.__class__._SHOTS_PARAM_NAME)
|
|
267
327
|
|
|
268
328
|
job_name = ""
|
|
269
329
|
if len(circuits) > 1:
|
|
270
|
-
job_name = f"batch-{len(circuits)}
|
|
330
|
+
job_name = f"batch-{len(circuits)}"
|
|
331
|
+
if shots_count is not None:
|
|
332
|
+
job_name = f"{job_name}-{shots_count}"
|
|
271
333
|
else:
|
|
272
334
|
job_name = circuits[0].name
|
|
273
335
|
job_name = options.pop("job_name", job_name)
|
|
@@ -386,9 +448,13 @@ class AzureBackend(AzureBackendBase):
|
|
|
386
448
|
def _translate_input(self, circuit):
|
|
387
449
|
pass
|
|
388
450
|
|
|
389
|
-
def run(
|
|
390
|
-
|
|
391
|
-
|
|
451
|
+
def run(
|
|
452
|
+
self,
|
|
453
|
+
run_input: Union[QuantumCircuit, List[QuantumCircuit]] = [],
|
|
454
|
+
shots: int = None,
|
|
455
|
+
**options,
|
|
456
|
+
):
|
|
457
|
+
"""Submits the given circuit to run on an Azure Quantum backend."""
|
|
392
458
|
circuit = self._normalize_run_input_params(run_input, **options)
|
|
393
459
|
options.pop("run_input", None)
|
|
394
460
|
options.pop("circuit", None)
|
|
@@ -417,16 +483,45 @@ class AzureBackend(AzureBackendBase):
|
|
|
417
483
|
job_name = options.pop("job_name", circuit.name)
|
|
418
484
|
metadata = options.pop("metadata", self._prepare_job_metadata(circuit))
|
|
419
485
|
|
|
420
|
-
input_params = self._get_input_params(options)
|
|
486
|
+
input_params = self._get_input_params(options, shots=shots)
|
|
421
487
|
|
|
422
488
|
input_data = self._translate_input(circuit)
|
|
423
489
|
|
|
424
490
|
job = super()._run(job_name, input_data, input_params, metadata, **options)
|
|
425
491
|
|
|
426
|
-
shots_count =
|
|
492
|
+
shots_count = None
|
|
493
|
+
if self._can_send_shots_input_param():
|
|
494
|
+
shots_count = input_params.get(self.__class__._SHOTS_PARAM_NAME)
|
|
495
|
+
|
|
427
496
|
logger.info(
|
|
428
497
|
f"Submitted job with id '{job.id()}' for circuit '{circuit.name}' with shot count of {shots_count}:"
|
|
429
498
|
)
|
|
430
499
|
logger.info(input_data)
|
|
431
500
|
|
|
432
501
|
return job
|
|
502
|
+
|
|
503
|
+
def _get_shots_or_deprecated_count_input_param(
|
|
504
|
+
param_name: str,
|
|
505
|
+
shots: int = None,
|
|
506
|
+
count: int = None,
|
|
507
|
+
) -> Optional[int]:
|
|
508
|
+
"""
|
|
509
|
+
This helper function checks if the deprecated 'count' option is specified.
|
|
510
|
+
In earlier versions it was possible to pass this option to specify shots number for a job,
|
|
511
|
+
but now we only check for it for compatibility reasons.
|
|
512
|
+
"""
|
|
513
|
+
|
|
514
|
+
final_shots = None
|
|
515
|
+
|
|
516
|
+
if shots is not None:
|
|
517
|
+
final_shots = shots
|
|
518
|
+
|
|
519
|
+
elif count is not None:
|
|
520
|
+
final_shots = count
|
|
521
|
+
warnings.warn(
|
|
522
|
+
"The 'count' parameter will be deprecated. "
|
|
523
|
+
f"Please, use '{param_name}' parameter instead.",
|
|
524
|
+
category=DeprecationWarning,
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
return final_shots
|
|
@@ -2,12 +2,19 @@
|
|
|
2
2
|
# Copyright (c) Microsoft Corporation.
|
|
3
3
|
# Licensed under the MIT License.
|
|
4
4
|
##
|
|
5
|
-
from typing import TYPE_CHECKING, Dict
|
|
5
|
+
from typing import TYPE_CHECKING, Dict, List, Union
|
|
6
6
|
from azure.quantum import __version__
|
|
7
|
+
from azure.quantum.qiskit.job import AzureQuantumJob
|
|
7
8
|
from azure.quantum.target.ionq import IonQ
|
|
8
9
|
from abc import abstractmethod
|
|
9
10
|
|
|
10
|
-
from
|
|
11
|
+
from qiskit import QuantumCircuit
|
|
12
|
+
|
|
13
|
+
from .backend import (
|
|
14
|
+
AzureBackend,
|
|
15
|
+
AzureQirBackend,
|
|
16
|
+
_get_shots_or_deprecated_count_input_param
|
|
17
|
+
)
|
|
11
18
|
|
|
12
19
|
from qiskit.providers.models import BackendConfiguration
|
|
13
20
|
from qiskit.providers import Options, Provider
|
|
@@ -42,10 +49,14 @@ __all__ = [
|
|
|
42
49
|
"IonQForteNativeBackend",
|
|
43
50
|
]
|
|
44
51
|
|
|
52
|
+
_IONQ_SHOTS_INPUT_PARAM_NAME = "shots"
|
|
53
|
+
_DEFAULT_SHOTS_COUNT = 500
|
|
45
54
|
|
|
46
55
|
class IonQQirBackendBase(AzureQirBackend):
|
|
47
56
|
"""Base class for interfacing with an IonQ QIR backend"""
|
|
48
57
|
|
|
58
|
+
_SHOTS_PARAM_NAME = _IONQ_SHOTS_INPUT_PARAM_NAME
|
|
59
|
+
|
|
49
60
|
@abstractmethod
|
|
50
61
|
def __init__(
|
|
51
62
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
@@ -54,7 +65,12 @@ class IonQQirBackendBase(AzureQirBackend):
|
|
|
54
65
|
|
|
55
66
|
@classmethod
|
|
56
67
|
def _default_options(cls) -> Options:
|
|
57
|
-
return Options(
|
|
68
|
+
return Options(
|
|
69
|
+
**{
|
|
70
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
71
|
+
},
|
|
72
|
+
targetCapability="BasicExecution",
|
|
73
|
+
)
|
|
58
74
|
|
|
59
75
|
def _azure_config(self) -> Dict[str, str]:
|
|
60
76
|
config = super()._azure_config()
|
|
@@ -64,6 +80,25 @@ class IonQQirBackendBase(AzureQirBackend):
|
|
|
64
80
|
}
|
|
65
81
|
)
|
|
66
82
|
return config
|
|
83
|
+
|
|
84
|
+
def run(
|
|
85
|
+
self,
|
|
86
|
+
run_input: Union[QuantumCircuit, List[QuantumCircuit]] = [],
|
|
87
|
+
shots: int = None,
|
|
88
|
+
**options,
|
|
89
|
+
) -> AzureQuantumJob:
|
|
90
|
+
|
|
91
|
+
# In earlier versions, backends for all providers accepted the 'count' option,
|
|
92
|
+
# but now we accept it only for a compatibility reasons and do not recommend using it.
|
|
93
|
+
count = options.pop("count", None)
|
|
94
|
+
|
|
95
|
+
final_shots = _get_shots_or_deprecated_count_input_param(
|
|
96
|
+
param_name=self.__class__._SHOTS_PARAM_NAME,
|
|
97
|
+
shots=shots,
|
|
98
|
+
count=count,
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return super().run(run_input, shots=final_shots, **options)
|
|
67
102
|
|
|
68
103
|
|
|
69
104
|
class IonQSimulatorQirBackend(IonQQirBackendBase):
|
|
@@ -199,15 +234,40 @@ class IonQBackend(AzureBackend):
|
|
|
199
234
|
|
|
200
235
|
backend_name = None
|
|
201
236
|
|
|
237
|
+
_SHOTS_PARAM_NAME = _IONQ_SHOTS_INPUT_PARAM_NAME
|
|
238
|
+
|
|
202
239
|
@abstractmethod
|
|
203
240
|
def __init__(
|
|
204
241
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
205
242
|
):
|
|
206
243
|
super().__init__(configuration, provider, **fields)
|
|
207
244
|
|
|
245
|
+
def run(
|
|
246
|
+
self,
|
|
247
|
+
run_input=None,
|
|
248
|
+
shots: int = None,
|
|
249
|
+
**options,
|
|
250
|
+
) -> AzureQuantumJob:
|
|
251
|
+
|
|
252
|
+
# In earlier versions, backends for all providers accepted the 'count' option,
|
|
253
|
+
# but now we accept it only for a compatibility reasons and do not recommend using it.
|
|
254
|
+
count = options.pop("count", None)
|
|
255
|
+
|
|
256
|
+
final_shots = _get_shots_or_deprecated_count_input_param(
|
|
257
|
+
param_name=self.__class__._SHOTS_PARAM_NAME,
|
|
258
|
+
shots=shots,
|
|
259
|
+
count=count,
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
return super().run(run_input, shots=final_shots, **options)
|
|
263
|
+
|
|
208
264
|
@classmethod
|
|
209
265
|
def _default_options(cls):
|
|
210
|
-
return Options(
|
|
266
|
+
return Options(
|
|
267
|
+
**{
|
|
268
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
269
|
+
},
|
|
270
|
+
)
|
|
211
271
|
|
|
212
272
|
def _azure_config(self) -> Dict[str, str]:
|
|
213
273
|
return {
|
|
@@ -249,7 +309,7 @@ class IonQBackend(AzureBackend):
|
|
|
249
309
|
}
|
|
250
310
|
workspace = self.provider().get_workspace()
|
|
251
311
|
target = workspace.get_targets(self.name())
|
|
252
|
-
return target.estimate_cost(input_data,
|
|
312
|
+
return target.estimate_cost(input_data, shots=shots)
|
|
253
313
|
|
|
254
314
|
|
|
255
315
|
class IonQSimulatorBackend(IonQBackend):
|
|
@@ -5,8 +5,12 @@
|
|
|
5
5
|
|
|
6
6
|
from typing import TYPE_CHECKING, Dict
|
|
7
7
|
from azure.quantum.version import __version__
|
|
8
|
+
from azure.quantum.qiskit.job import AzureQuantumJob
|
|
8
9
|
from abc import abstractmethod
|
|
9
|
-
from .backend import
|
|
10
|
+
from .backend import (
|
|
11
|
+
AzureQirBackend,
|
|
12
|
+
_get_shots_or_deprecated_count_input_param,
|
|
13
|
+
)
|
|
10
14
|
|
|
11
15
|
from qiskit.providers.models import BackendConfiguration
|
|
12
16
|
from qiskit.providers import Options, Provider
|
|
@@ -43,7 +47,12 @@ logger = logging.getLogger(__name__)
|
|
|
43
47
|
__all__ = ["QCISimulatorBackend" "QCIQPUBackend"]
|
|
44
48
|
|
|
45
49
|
|
|
50
|
+
_DEFAULT_SHOTS_COUNT = 500
|
|
51
|
+
|
|
46
52
|
class QCIBackend(AzureQirBackend):
|
|
53
|
+
|
|
54
|
+
_SHOTS_PARAM_NAME = "shots"
|
|
55
|
+
|
|
47
56
|
@abstractmethod
|
|
48
57
|
def __init__(
|
|
49
58
|
self, configuration: BackendConfiguration, provider: Provider = None, **fields
|
|
@@ -52,7 +61,12 @@ class QCIBackend(AzureQirBackend):
|
|
|
52
61
|
|
|
53
62
|
@classmethod
|
|
54
63
|
def _default_options(cls) -> Options:
|
|
55
|
-
return Options(
|
|
64
|
+
return Options(
|
|
65
|
+
**{
|
|
66
|
+
cls._SHOTS_PARAM_NAME: _DEFAULT_SHOTS_COUNT,
|
|
67
|
+
},
|
|
68
|
+
targetCapability="AdaptiveExecution",
|
|
69
|
+
)
|
|
56
70
|
|
|
57
71
|
def _azure_config(self) -> Dict[str, str]:
|
|
58
72
|
config = super()._azure_config()
|
|
@@ -62,6 +76,25 @@ class QCIBackend(AzureQirBackend):
|
|
|
62
76
|
}
|
|
63
77
|
)
|
|
64
78
|
return config
|
|
79
|
+
|
|
80
|
+
def run(
|
|
81
|
+
self,
|
|
82
|
+
run_input=None,
|
|
83
|
+
shots: int = None,
|
|
84
|
+
**options,
|
|
85
|
+
) -> AzureQuantumJob:
|
|
86
|
+
|
|
87
|
+
# In earlier versions, backends for all providers accepted the 'count' option,
|
|
88
|
+
# but now we accept it only for a compatibility reasons and do not recommend using it.
|
|
89
|
+
count = options.pop("count", None)
|
|
90
|
+
|
|
91
|
+
final_shots = _get_shots_or_deprecated_count_input_param(
|
|
92
|
+
param_name=self.__class__._SHOTS_PARAM_NAME,
|
|
93
|
+
shots=shots,
|
|
94
|
+
count=count,
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
return super().run(run_input, shots=final_shots, **options)
|
|
65
98
|
|
|
66
99
|
|
|
67
100
|
class QCISimulatorBackend(QCIBackend):
|
|
@@ -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()
|
|
@@ -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)
|
|
@@ -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.
|