Skip to content
This repository was archived by the owner on Jul 28, 2023. It is now read-only.

Commit 06e557b

Browse files
authored
Runtime service (#926)
* runtime service * add directory * use env var for file names * add interim queue * interim result * add runtime options * add circuits to encoder * move encoder to utils * reformat doc * add whether parameter is required * use real url * get single program * always use interim queue * use dill * use real url * fix urls * add logging * use real coders * add user messenger * fix import * fix setup * add program backend * add to_json in encoder * interim results * move json coder * clarify docstring * return program max_execution_time * make max_execution_time required * get runtime url from server * update ws * add job cancel * add doc and tests * fix lint * fix doc * fix doc * add more tests * fix mypy * fix serializable class * add release notes * fix program name * fix tests * add metadata * add result decoder * add metadata * add pagination * use qobj * remove unused code * fix typo * remove qobj * add ws tests * change program output format * fix test job status * remove update program * fix run_circuits parameters * doc update * fix lint * minor doc update * more minor doc update * fix doc link
1 parent c90f17c commit 06e557b

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+4123
-61
lines changed

.github/workflows/main.yml

-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ jobs:
7878
run: |
7979
python -m pip install --upgrade pip
8080
pip install -U -c constraints.txt -r requirements-dev.txt
81-
pip install -U git+https://github.com/Qiskit/qiskit-aer.git
8281
pip install -c constraints.txt -e .
8382
- name: Run Tests
8483
run: make test

docs/apidocs/ibmq-provider.rst

+1
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ Qiskit IBM Quantum Provider API Reference
1414
ibmq_utils
1515
ibmq_random
1616
ibmq_experiment
17+
ibmq_runtime

docs/apidocs/ibmq_runtime.rst

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.. _qiskit-providers-ibmq-runtime:
2+
3+
.. automodule:: qiskit.providers.ibmq.runtime
4+
:no-members:
5+
:no-inherited-members:
6+
:no-special-members:

qiskit/providers/ibmq/accountprovider.py

+147-11
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,18 @@
1313
"""Provider for a single IBM Quantum Experience account."""
1414

1515
import logging
16-
from typing import Dict, List, Optional, Any, Callable
16+
from typing import Dict, List, Optional, Any, Callable, Union
1717
from collections import OrderedDict
1818
import traceback
1919

2020
from qiskit.providers import ProviderV1 as Provider # type: ignore[attr-defined]
2121
from qiskit.providers.models import (QasmBackendConfiguration,
2222
PulseBackendConfiguration)
23+
from qiskit.circuit import QuantumCircuit
24+
from qiskit.providers.backend import BackendV1 as Backend
25+
from qiskit.providers.basebackend import BaseBackend
26+
from qiskit.transpiler import Layout
27+
from qiskit.providers.ibmq.runtime import runtime_job # pylint: disable=unused-import
2328

2429
from .api.clients import AccountClient
2530
from .ibmqbackend import IBMQBackend, IBMQSimulator
@@ -28,6 +33,7 @@
2833
from .utils.json_decoder import decode_backend_configuration
2934
from .random.ibmqrandomservice import IBMQRandomService
3035
from .experiment.experimentservice import ExperimentService
36+
from .runtime.ibm_runtime_service import IBMRuntimeService
3137
from .exceptions import IBMQNotAuthorizedError, IBMQInputValueError
3238

3339
logger = logging.getLogger(__name__)
@@ -89,18 +95,16 @@ class AccountProvider(Provider):
8995
in Jupyter Notebook and the Python interpreter.
9096
"""
9197

92-
def __init__(self, credentials: Credentials, access_token: str) -> None:
98+
def __init__(self, credentials: Credentials) -> None:
9399
"""AccountProvider constructor.
94100
95101
Args:
96102
credentials: IBM Quantum Experience credentials.
97-
access_token: IBM Quantum Experience access token.
98103
"""
99104
super().__init__()
100105

101106
self.credentials = credentials
102-
self._api_client = AccountClient(access_token,
103-
credentials,
107+
self._api_client = AccountClient(credentials,
104108
**credentials.connection_parameters())
105109

106110
# Initialize the internal list of backends.
@@ -109,14 +113,15 @@ def __init__(self, credentials: Credentials, access_token: str) -> None:
109113
self.backends = IBMQDeprecatedBackendService(self.backend) # type: ignore[assignment]
110114

111115
# Initialize other services.
112-
self._random = IBMQRandomService(self, access_token) \
113-
if credentials.extractor_url else None
114-
self._experiment = ExperimentService(self, access_token) \
115-
if credentials.experiment_url else None
116+
self._random = IBMQRandomService(self) if credentials.extractor_url else None
117+
self._experiment = ExperimentService(self) if credentials.experiment_url else None
118+
self._runtime = IBMRuntimeService(self) \
119+
if credentials.runtime_url else None
116120

117121
self._services = {'backend': self._backend,
118122
'random': self._random,
119-
'experiment': self._experiment}
123+
'experiment': self._experiment,
124+
'runtime': self._runtime}
120125

121126
def backends(
122127
self,
@@ -188,6 +193,102 @@ def _discover_remote_backends(self, timeout: Optional[float] = None) -> Dict[str
188193

189194
return ret
190195

196+
def run_circuits(
197+
self,
198+
circuits: Union[QuantumCircuit, List[QuantumCircuit]],
199+
backend: Union[Backend, BaseBackend],
200+
shots: Optional[int] = None,
201+
initial_layout: Optional[Union[Layout, Dict, List]] = None,
202+
layout_method: Optional[str] = None,
203+
routing_method: Optional[str] = None,
204+
translation_method: Optional[str] = None,
205+
seed_transpiler: Optional[int] = None,
206+
optimization_level: Optional[int] = None,
207+
init_qubits: Optional[bool] = True,
208+
rep_delay: Optional[float] = None,
209+
transpiler_options: Optional[dict] = None,
210+
measurement_error_mitigation: Optional[bool] = False,
211+
**run_config: Dict
212+
) -> 'runtime_job.RuntimeJob':
213+
"""Execute the input circuit(s) on a backend using the runtime service.
214+
215+
Note:
216+
This method uses the IBM Quantum runtime service which is not
217+
available to all accounts.
218+
219+
Note:
220+
This method returns a :class:``~qiskit.provider.ibmq.runtime.RuntimeJob``.
221+
To get the job result, you'll need to use the
222+
``qiskit_runtime.circuit_runner.RunnerResult`` class
223+
as the ``decoder``, e.g.::
224+
225+
result = provider.run_circuits(...).result(decoder=RunnerResult)
226+
227+
You can find more about the ``RunnerResult`` class in the
228+
`qiskit-runtime repository <https://github.com/Qiskit-Partners/qiskit-runtime>`_.
229+
230+
Args:
231+
circuits: Circuit(s) to execute.
232+
233+
backend: Backend to execute circuits on.
234+
Transpiler options are automatically grabbed from backend configuration
235+
and properties unless otherwise specified.
236+
237+
initial_layout: Initial position of virtual qubits on physical qubits.
238+
239+
layout_method: Name of layout selection pass ('trivial', 'dense',
240+
'noise_adaptive', 'sabre').
241+
Sometimes a perfect layout can be available in which case the layout_method
242+
may not run.
243+
244+
routing_method: Name of routing pass ('basic', 'lookahead', 'stochastic', 'sabre')
245+
246+
translation_method: Name of translation pass ('unroller', 'translator', 'synthesis')
247+
248+
seed_transpiler: Sets random seed for the stochastic parts of the transpiler.
249+
250+
optimization_level: How much optimization to perform on the circuits.
251+
Higher levels generate more optimized circuits, at the expense of longer
252+
transpilation time.
253+
If None, level 1 will be chosen as default.
254+
255+
shots: Number of repetitions of each circuit, for sampling. Default: 1024.
256+
257+
rep_delay: Delay between programs in seconds. Only supported on certain
258+
backends (``backend.configuration().dynamic_reprate_enabled`` ). If supported,
259+
``rep_delay`` will be used instead of ``rep_time`` and must be from the
260+
range supplied by the backend (``backend.configuration().rep_delay_range``).
261+
Default is given by ``backend.configuration().default_rep_delay``.
262+
263+
init_qubits: Whether to reset the qubits to the ground state for each shot.
264+
265+
transpiler_options: Additional transpiler options.
266+
267+
measurement_error_mitigation: Whether to apply measurement error mitigation.
268+
269+
**run_config: Extra arguments used to configure the circuit execution.
270+
271+
Returns:
272+
Runtime job.
273+
"""
274+
inputs = {
275+
'circuits': circuits,
276+
'initial_layout': initial_layout,
277+
'seed_transpiler': seed_transpiler,
278+
'optimization_level': optimization_level,
279+
'layout_method': layout_method,
280+
'shots': shots,
281+
'routing_method': routing_method,
282+
'translation_method': translation_method,
283+
'rep_delay': rep_delay,
284+
'init_qubits': init_qubits,
285+
'transpiler_options': transpiler_options,
286+
'measurement_error_mitigation': measurement_error_mitigation
287+
}
288+
inputs.update(run_config)
289+
options = {'backend_name': backend.name()}
290+
return self.runtime.run('circuit-runner', options=options, inputs=inputs)
291+
191292
def service(self, name: str) -> Any:
192293
"""Return the specified service.
193294
@@ -218,6 +319,26 @@ def services(self) -> Dict:
218319
"""
219320
return {key: val for key, val in self._services.items() if val is not None}
220321

322+
def has_service(self, name: str) -> bool:
323+
"""Check if this provider has access to the service.
324+
325+
Args:
326+
name: Name of the service.
327+
328+
Returns:
329+
Whether the provider has access to the service.
330+
331+
Raises:
332+
IBMQInputValueError: If an unknown service name is specified.
333+
"""
334+
if name not in self._services:
335+
raise IBMQInputValueError(f"Unknown service {name} specified.")
336+
337+
if self._services[name] is None:
338+
return False
339+
340+
return True
341+
221342
@property
222343
def backend(self) -> IBMQBackendService:
223344
"""Return the backend service.
@@ -257,7 +378,22 @@ def random(self) -> IBMQRandomService:
257378
if self._random:
258379
return self._random
259380
else:
260-
raise IBMQNotAuthorizedError("You are not authorized to use the random number service.")
381+
raise IBMQNotAuthorizedError("You are not authorized to use the service.")
382+
383+
@property
384+
def runtime(self) -> IBMRuntimeService:
385+
"""Return the runtime service.
386+
387+
Returns:
388+
The runtime service instance.
389+
390+
Raises:
391+
IBMQNotAuthorizedError: If the account is not authorized to use the service.
392+
"""
393+
if self._runtime:
394+
return self._runtime
395+
else:
396+
raise IBMQNotAuthorizedError("You are not authorized to use the runtime service.")
261397

262398
def __eq__(
263399
self,

qiskit/providers/ibmq/api/clients/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -17,3 +17,5 @@
1717
from .auth import AuthClient
1818
from .version import VersionClient
1919
from .websocket import WebsocketClient
20+
from .runtime import RuntimeClient
21+
from .runtime_ws import RuntimeWebsocketClient

qiskit/providers/ibmq/api/clients/account.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -41,24 +41,23 @@ class AccountClient(BaseClient):
4141

4242
def __init__(
4343
self,
44-
access_token: str,
4544
credentials: Credentials,
4645
**request_kwargs: Any
4746
) -> None:
4847
"""AccountClient constructor.
4948
5049
Args:
51-
access_token: IBM Quantum Experience access token.
5250
credentials: Account credentials.
5351
**request_kwargs: Arguments for the request ``Session``.
5452
"""
55-
self._session = RetrySession(credentials.base_url, access_token, **request_kwargs)
53+
self._session = RetrySession(
54+
credentials.base_url, credentials.access_token, **request_kwargs)
5655
# base_api is used to handle endpoints that don't include h/g/p.
5756
# account_api is for h/g/p.
5857
self.base_api = Api(self._session)
5958
self.account_api = Account(session=self._session, hub=credentials.hub,
6059
group=credentials.group, project=credentials.project)
61-
self.client_ws = WebsocketClient(credentials.websockets_url, access_token)
60+
self.client_ws = WebsocketClient(credentials.websockets_url, credentials.access_token)
6261
self._use_websockets = (not credentials.proxies)
6362

6463
# Backend-related public functions.

qiskit/providers/ibmq/api/clients/experiment.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,14 @@ class ExperimentClient(BaseClient):
2929

3030
def __init__(
3131
self,
32-
access_token: str,
3332
credentials: Credentials
3433
) -> None:
3534
"""ExperimentClient constructor.
3635
3736
Args:
38-
access_token: IBM Quantum Experience access token.
3937
credentials: Account credentials.
4038
"""
41-
self._session = RetrySession(credentials.experiment_url, access_token,
39+
self._session = RetrySession(credentials.experiment_url, credentials.access_token,
4240
**credentials.connection_parameters())
4341
self.base_api = Api(self._session)
4442

qiskit/providers/ibmq/api/clients/random.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -28,16 +28,14 @@ class RandomClient:
2828

2929
def __init__(
3030
self,
31-
access_token: str,
3231
credentials: Credentials,
3332
) -> None:
3433
"""RandomClient constructor.
3534
3635
Args:
37-
access_token: IBM Quantum Experience access token.
3836
credentials: Account credentials.
3937
"""
40-
self._session = RetrySession(credentials.extractor_url, access_token,
38+
self._session = RetrySession(credentials.extractor_url, credentials.access_token,
4139
**credentials.connection_parameters())
4240
self.random_api = Random(self._session)
4341

@@ -47,7 +45,6 @@ def list_services(self) -> List[Dict[str, Any]]:
4745
Returns:
4846
RNG services available for this provider.
4947
"""
50-
# return [{'name': 'cqc', 'extractors': ['ext1', 'ext2']}]
5148
return self.random_api.list_services()
5249

5350
def extract(

0 commit comments

Comments
 (0)