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.
Files changed (126) hide show
  1. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/PKG-INFO +1 -1
  2. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_version.py +1 -1
  3. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/service.py +7 -0
  4. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/quantinuum.py +1 -1
  5. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/job.py +15 -1
  6. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/backend.py +130 -35
  7. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/ionq.py +65 -5
  8. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/qci.py +35 -2
  9. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/quantinuum.py +25 -4
  10. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/rigetti.py +8 -1
  11. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/job.py +7 -16
  12. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/provider.py +18 -2
  13. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/ionq.py +37 -12
  14. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/target.py +13 -1
  15. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/target.py +36 -9
  16. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/params.py +1 -1
  17. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/target.py +16 -2
  18. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/quantinuum.py +34 -9
  19. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/target.py +15 -2
  20. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/solvers.py +7 -1
  21. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/target.py +82 -0
  22. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/target_factory.py +0 -2
  23. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/version.py +1 -1
  24. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/workspace.py +11 -8
  25. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/PKG-INFO +1 -1
  26. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/SOURCES.txt +0 -28
  27. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/requires.txt +2 -4
  28. azure-quantum-1.0.0/requirements-qsharp.txt +1 -0
  29. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements.txt +0 -2
  30. azure-quantum-0.30.0/azure/quantum/_client/aio/__init__.py +0 -23
  31. azure-quantum-0.30.0/azure/quantum/_client/aio/_client.py +0 -124
  32. azure-quantum-0.30.0/azure/quantum/_client/aio/_configuration.py +0 -89
  33. azure-quantum-0.30.0/azure/quantum/_client/aio/operations/_operations.py +0 -1291
  34. azure-quantum-0.30.0/azure/quantum/_client/models/_patch.py +0 -20
  35. azure-quantum-0.30.0/azure/quantum/_client/operations/__init__.py +0 -29
  36. azure-quantum-0.30.0/azure/quantum/_client/operations/_patch.py +0 -20
  37. azure-quantum-0.30.0/azure/quantum/aio/__init__.py +0 -14
  38. azure-quantum-0.30.0/azure/quantum/aio/_authentication/__init__.py +0 -9
  39. azure-quantum-0.30.0/azure/quantum/aio/_authentication/_chained.py +0 -94
  40. azure-quantum-0.30.0/azure/quantum/aio/_authentication/_default.py +0 -212
  41. azure-quantum-0.30.0/azure/quantum/aio/_authentication/_token.py +0 -81
  42. azure-quantum-0.30.0/azure/quantum/aio/job/__init__.py +0 -1
  43. azure-quantum-0.30.0/azure/quantum/aio/job/base_job.py +0 -326
  44. azure-quantum-0.30.0/azure/quantum/aio/job/job.py +0 -104
  45. azure-quantum-0.30.0/azure/quantum/aio/optimization/__init__.py +0 -11
  46. azure-quantum-0.30.0/azure/quantum/aio/optimization/online_problem.py +0 -17
  47. azure-quantum-0.30.0/azure/quantum/aio/optimization/problem.py +0 -102
  48. azure-quantum-0.30.0/azure/quantum/aio/optimization/streaming_problem.py +0 -280
  49. azure-quantum-0.30.0/azure/quantum/aio/storage.py +0 -390
  50. azure-quantum-0.30.0/azure/quantum/aio/target/__init__.py +0 -19
  51. azure-quantum-0.30.0/azure/quantum/aio/target/ionq.py +0 -47
  52. azure-quantum-0.30.0/azure/quantum/aio/target/quantinuum.py +0 -47
  53. azure-quantum-0.30.0/azure/quantum/aio/target/solvers.py +0 -96
  54. azure-quantum-0.30.0/azure/quantum/aio/target/target.py +0 -68
  55. azure-quantum-0.30.0/azure/quantum/aio/target/target_factory.py +0 -72
  56. azure-quantum-0.30.0/azure/quantum/aio/target/toshiba.py +0 -6
  57. azure-quantum-0.30.0/azure/quantum/aio/workspace.py +0 -337
  58. azure-quantum-0.30.0/requirements-qsharp.txt +0 -1
  59. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/README.md +0 -0
  60. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/__init__.py +0 -0
  61. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/__init__.py +0 -0
  62. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_chained.py +0 -0
  63. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_default.py +0 -0
  64. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_authentication/_token.py +0 -0
  65. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/__init__.py +0 -0
  66. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_client.py +0 -0
  67. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_configuration.py +0 -0
  68. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_patch.py +0 -0
  69. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_serialization.py +0 -0
  70. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/_vendor.py +0 -0
  71. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/__init__.py +0 -0
  72. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/_enums.py +0 -0
  73. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/models/_models.py +0 -0
  74. {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client/models}/_patch.py +0 -0
  75. {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client}/operations/__init__.py +0 -0
  76. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/_client/operations/_operations.py +0 -0
  77. {azure-quantum-0.30.0/azure/quantum/_client/aio → azure-quantum-1.0.0/azure/quantum/_client}/operations/_patch.py +0 -0
  78. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/argument_types/__init__.py +0 -0
  79. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/argument_types/types.py +0 -0
  80. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/chemistry/__init__.py +0 -0
  81. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/__init__.py +0 -0
  82. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/job.py +0 -0
  83. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/__init__.py +0 -0
  84. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/ionq.py +0 -0
  85. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/cirq/targets/target.py +0 -0
  86. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/__init__.py +0 -0
  87. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/base_job.py +0 -0
  88. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/filtered_job.py +0 -0
  89. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/job_failed_with_results_error.py +0 -0
  90. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/session.py +0 -0
  91. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/workspace_item.py +0 -0
  92. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/job/workspace_item_factory.py +0 -0
  93. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/__init__.py +0 -0
  94. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/online_problem.py +0 -0
  95. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/problem.py +0 -0
  96. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/solvers.py +0 -0
  97. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/streaming_problem.py +0 -0
  98. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/term.py +0 -0
  99. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/toshiba/__init__.py +0 -0
  100. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/optimization/toshiba/solvers.py +0 -0
  101. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/__init__.py +0 -0
  102. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/__init__.py +0 -0
  103. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/backends/microsoft.py +0 -0
  104. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/results/__init__.py +0 -0
  105. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/qiskit/results/resource_estimator.py +0 -0
  106. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/storage.py +0 -0
  107. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/__init__.py +0 -0
  108. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/__init__.py +0 -0
  109. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/__init__.py +0 -0
  110. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/elements/dft/job.py +0 -0
  111. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/job.py +0 -0
  112. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/microsoft/result.py +0 -0
  113. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/__init__.py +0 -0
  114. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/pasqal/result.py +0 -0
  115. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/__init__.py +0 -0
  116. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/rigetti/result.py +0 -0
  117. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/toshiba/__init__.py +0 -0
  118. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure/quantum/target/toshiba/solvers.py +0 -0
  119. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/dependency_links.txt +0 -0
  120. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/azure_quantum.egg-info/top_level.txt +0 -0
  121. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-cirq.txt +0 -0
  122. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-dev.txt +0 -0
  123. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-qiskit.txt +0 -0
  124. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/requirements-quil.txt +0 -0
  125. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/setup.cfg +0 -0
  126. {azure-quantum-0.30.0 → azure-quantum-1.0.0}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: azure-quantum
3
- Version: 0.30.0
3
+ Version: 1.0.0
4
4
  Summary: Python client for Azure Quantum
5
5
  Home-page: https://github.com/microsoft/azure-quantum-python
6
6
  Author: Microsoft
@@ -6,4 +6,4 @@
6
6
  # Changes may cause incorrect behavior and will be lost if the code is regenerated.
7
7
  # --------------------------------------------------------------------------
8
8
 
9
- VERSION = "0.30.0"
9
+ VERSION = "1.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
 
@@ -91,7 +91,7 @@ class QuantinuumTarget(Quantinuum, CirqTarget):
91
91
  serialized_program = self._translate_circuit(program)
92
92
  return super().estimate_cost(
93
93
  circuit=serialized_program,
94
- num_shots=repetitions
94
+ shots=repetitions
95
95
  )
96
96
 
97
97
  def submit(
@@ -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
- return json.loads(payload)
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
- # The shots/count number can be specified in different ways for different providers,
89
- # so let's get it first. Values in 'kwargs' take precedence over options, and to keep
90
- # the convention, 'count' takes precedence over 'shots' afterwards.
91
- shots_count = (
92
- options["count"]
93
- if "count" in options
94
- else options["shots"]
95
- if "shots" in options
96
- else input_params["count"]
97
- if "count" in input_params
98
- else input_params["shots"]
99
- if "shots" in input_params
100
- else None
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
- # Let's clear the options of both properties regardless of which one was used to prevent
104
- # double specification of the value.
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, run_input: Union[QuantumCircuit, List[QuantumCircuit]] = [], **options
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. This is an async call.
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
- shots_count = input_params["count"]
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)}-{shots_count}"
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(self, run_input=None, **kwargs):
390
- """Submits the given circuit to run on an Azure Quantum backend."""
391
- options = kwargs
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 = input_params["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 .backend import AzureBackend, AzureQirBackend
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(shots=500, targetCapability="BasicExecution")
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(shots=500)
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, num_shots=shots)
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 AzureQirBackend
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(shots=500, targetCapability="AdaptiveExecution")
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(shots=500, targetCapability="BasicExecution")
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(count=500)
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, num_shots=shots)
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
- return Options(count=500, targetCapability="BasicExecution")
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
- az_result = self._azure_job.get_results()
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
- # The Histogram serialization is odd entries are key and even entries values
242
- # Make sure we have even entries
243
- if (len(histogram) % 2) == 0:
244
- items = range(0, len(histogram), 2)
245
- for i in items:
246
- bitstring = AzureQuantumJob._qir_to_qiskit_bitstring(histogram[i])
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
- def __init__(self, workspace=None, **kwargs):
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.