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

Runtime service #926

Merged
merged 61 commits into from
May 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
61 commits
Select commit Hold shift + click to select a range
70b9bb7
runtime service
jyu00 Mar 2, 2021
c574e0f
add directory
jyu00 Mar 2, 2021
ff71d41
use env var for file names
jyu00 Mar 2, 2021
2c71ce8
add interim queue
jyu00 Mar 2, 2021
f2c801a
interim result
jyu00 Mar 3, 2021
d153155
add runtime options
jyu00 Mar 17, 2021
4a659e2
add circuits to encoder
jyu00 Mar 18, 2021
f760eb7
move encoder to utils
jyu00 Mar 18, 2021
c30f06e
reformat doc
jyu00 Mar 19, 2021
bfdf8c7
add whether parameter is required
jyu00 Mar 19, 2021
8b55c3d
use real url
jyu00 Mar 23, 2021
5247968
get single program
jyu00 Mar 23, 2021
7d73603
always use interim queue
jyu00 Mar 25, 2021
14afe53
use dill
jyu00 Mar 25, 2021
a4b24a1
use real url
jyu00 Mar 23, 2021
6138f03
fix urls
jyu00 Mar 26, 2021
3e860a4
add logging
jyu00 Mar 26, 2021
06bb63f
use real coders
jyu00 Mar 26, 2021
c26dce6
add user messenger
jyu00 Mar 26, 2021
1190457
fix import
jyu00 Mar 26, 2021
5973b5d
fix setup
jyu00 Mar 26, 2021
0ba3590
add program backend
jyu00 Mar 26, 2021
4eba7ff
add to_json in encoder
jyu00 Mar 31, 2021
0ebd5a7
interim results
jyu00 Apr 7, 2021
2c62d6f
move json coder
jyu00 Apr 9, 2021
a2f6c9a
clarify docstring
jyu00 Apr 9, 2021
d0c2f23
return program max_execution_time
jyu00 Apr 9, 2021
caf8f95
make max_execution_time required
jyu00 Apr 12, 2021
2f93605
get runtime url from server
jyu00 Apr 13, 2021
efbf958
update ws
jyu00 Apr 14, 2021
2ac3916
add job cancel
jyu00 Apr 14, 2021
00c6882
add doc and tests
jyu00 Apr 26, 2021
7060915
fix lint
jyu00 Apr 26, 2021
40f29bc
fix doc
jyu00 Apr 26, 2021
89ea5b4
fix doc
jyu00 Apr 26, 2021
addb11d
add more tests
jyu00 Apr 27, 2021
72cdf15
fix mypy
jyu00 Apr 27, 2021
487f6ce
fix serializable class
jyu00 Apr 27, 2021
22d63e6
add release notes
jyu00 Apr 28, 2021
bff6a59
Merge remote-tracking branch 'upstream/master' into runtime-real
jyu00 Apr 28, 2021
43272f6
fix program name
jyu00 Apr 28, 2021
9353918
fix tests
jyu00 Apr 28, 2021
0d350e4
add metadata
jyu00 Apr 29, 2021
8bdcc15
add result decoder
jyu00 Apr 29, 2021
8fb76ba
add metadata
jyu00 May 4, 2021
20a9bb9
add pagination
jyu00 May 5, 2021
6ed5394
use qobj
jyu00 May 5, 2021
c9a5035
remove unused code
jyu00 May 5, 2021
e6150a8
fix typo
jyu00 May 5, 2021
aa4a194
remove qobj
jyu00 May 5, 2021
9616b25
add ws tests
jyu00 May 6, 2021
6415f89
change program output format
jyu00 May 6, 2021
ef76418
Merge remote-tracking branch 'upstream/master' into runtime-real
jyu00 May 6, 2021
d5b77cc
fix test job status
jyu00 May 6, 2021
7e97927
remove update program
jyu00 May 6, 2021
68f32a6
fix run_circuits parameters
jyu00 May 7, 2021
49e957e
doc update
jyu00 May 7, 2021
b26a785
fix lint
jyu00 May 7, 2021
0d8b9be
minor doc update
jyu00 May 7, 2021
227fdc6
more minor doc update
jyu00 May 7, 2021
b500e98
fix doc link
jyu00 May 7, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ jobs:
run: |
python -m pip install --upgrade pip
pip install -U -c constraints.txt -r requirements-dev.txt
pip install -U git+https://github.com/Qiskit/qiskit-aer.git
pip install -c constraints.txt -e .
- name: Run Tests
run: make test
1 change: 1 addition & 0 deletions docs/apidocs/ibmq-provider.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ Qiskit IBM Quantum Provider API Reference
ibmq_utils
ibmq_random
ibmq_experiment
ibmq_runtime
6 changes: 6 additions & 0 deletions docs/apidocs/ibmq_runtime.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
.. _qiskit-providers-ibmq-runtime:

.. automodule:: qiskit.providers.ibmq.runtime
:no-members:
:no-inherited-members:
:no-special-members:
158 changes: 147 additions & 11 deletions qiskit/providers/ibmq/accountprovider.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,18 @@
"""Provider for a single IBM Quantum Experience account."""

import logging
from typing import Dict, List, Optional, Any, Callable
from typing import Dict, List, Optional, Any, Callable, Union
from collections import OrderedDict
import traceback

from qiskit.providers import ProviderV1 as Provider # type: ignore[attr-defined]
from qiskit.providers.models import (QasmBackendConfiguration,
PulseBackendConfiguration)
from qiskit.circuit import QuantumCircuit
from qiskit.providers.backend import BackendV1 as Backend
from qiskit.providers.basebackend import BaseBackend
from qiskit.transpiler import Layout
from qiskit.providers.ibmq.runtime import runtime_job # pylint: disable=unused-import

from .api.clients import AccountClient
from .ibmqbackend import IBMQBackend, IBMQSimulator
Expand All @@ -28,6 +33,7 @@
from .utils.json_decoder import decode_backend_configuration
from .random.ibmqrandomservice import IBMQRandomService
from .experiment.experimentservice import ExperimentService
from .runtime.ibm_runtime_service import IBMRuntimeService
from .exceptions import IBMQNotAuthorizedError, IBMQInputValueError

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

def __init__(self, credentials: Credentials, access_token: str) -> None:
def __init__(self, credentials: Credentials) -> None:
"""AccountProvider constructor.

Args:
credentials: IBM Quantum Experience credentials.
access_token: IBM Quantum Experience access token.
"""
super().__init__()

self.credentials = credentials
self._api_client = AccountClient(access_token,
credentials,
self._api_client = AccountClient(credentials,
**credentials.connection_parameters())

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

# Initialize other services.
self._random = IBMQRandomService(self, access_token) \
if credentials.extractor_url else None
self._experiment = ExperimentService(self, access_token) \
if credentials.experiment_url else None
self._random = IBMQRandomService(self) if credentials.extractor_url else None
self._experiment = ExperimentService(self) if credentials.experiment_url else None
self._runtime = IBMRuntimeService(self) \
if credentials.runtime_url else None

self._services = {'backend': self._backend,
'random': self._random,
'experiment': self._experiment}
'experiment': self._experiment,
'runtime': self._runtime}

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

return ret

def run_circuits(
self,
circuits: Union[QuantumCircuit, List[QuantumCircuit]],
backend: Union[Backend, BaseBackend],
shots: Optional[int] = None,
initial_layout: Optional[Union[Layout, Dict, List]] = None,
layout_method: Optional[str] = None,
routing_method: Optional[str] = None,
translation_method: Optional[str] = None,
seed_transpiler: Optional[int] = None,
optimization_level: Optional[int] = None,
init_qubits: Optional[bool] = True,
rep_delay: Optional[float] = None,
transpiler_options: Optional[dict] = None,
measurement_error_mitigation: Optional[bool] = False,
**run_config: Dict
) -> 'runtime_job.RuntimeJob':
"""Execute the input circuit(s) on a backend using the runtime service.

Note:
This method uses the IBM Quantum runtime service which is not
available to all accounts.

Note:
This method returns a :class:``~qiskit.provider.ibmq.runtime.RuntimeJob``.
To get the job result, you'll need to use the
``qiskit_runtime.circuit_runner.RunnerResult`` class
as the ``decoder``, e.g.::

result = provider.run_circuits(...).result(decoder=RunnerResult)

You can find more about the ``RunnerResult`` class in the
`qiskit-runtime repository <https://github.com/Qiskit-Partners/qiskit-runtime>`_.

Args:
circuits: Circuit(s) to execute.

backend: Backend to execute circuits on.
Transpiler options are automatically grabbed from backend configuration
and properties unless otherwise specified.

initial_layout: Initial position of virtual qubits on physical qubits.

layout_method: Name of layout selection pass ('trivial', 'dense',
'noise_adaptive', 'sabre').
Sometimes a perfect layout can be available in which case the layout_method
may not run.

routing_method: Name of routing pass ('basic', 'lookahead', 'stochastic', 'sabre')

translation_method: Name of translation pass ('unroller', 'translator', 'synthesis')

seed_transpiler: Sets random seed for the stochastic parts of the transpiler.

optimization_level: How much optimization to perform on the circuits.
Higher levels generate more optimized circuits, at the expense of longer
transpilation time.
If None, level 1 will be chosen as default.

shots: Number of repetitions of each circuit, for sampling. Default: 1024.

rep_delay: Delay between programs in seconds. Only supported on certain
backends (``backend.configuration().dynamic_reprate_enabled`` ). If supported,
``rep_delay`` will be used instead of ``rep_time`` and must be from the
range supplied by the backend (``backend.configuration().rep_delay_range``).
Default is given by ``backend.configuration().default_rep_delay``.

init_qubits: Whether to reset the qubits to the ground state for each shot.

transpiler_options: Additional transpiler options.

measurement_error_mitigation: Whether to apply measurement error mitigation.

**run_config: Extra arguments used to configure the circuit execution.

Returns:
Runtime job.
"""
inputs = {
'circuits': circuits,
'initial_layout': initial_layout,
'seed_transpiler': seed_transpiler,
'optimization_level': optimization_level,
'layout_method': layout_method,
'shots': shots,
'routing_method': routing_method,
'translation_method': translation_method,
'rep_delay': rep_delay,
'init_qubits': init_qubits,
'transpiler_options': transpiler_options,
'measurement_error_mitigation': measurement_error_mitigation
}
inputs.update(run_config)
options = {'backend_name': backend.name()}
return self.runtime.run('circuit-runner', options=options, inputs=inputs)

def service(self, name: str) -> Any:
"""Return the specified service.

Expand Down Expand Up @@ -218,6 +319,26 @@ def services(self) -> Dict:
"""
return {key: val for key, val in self._services.items() if val is not None}

def has_service(self, name: str) -> bool:
"""Check if this provider has access to the service.

Args:
name: Name of the service.

Returns:
Whether the provider has access to the service.

Raises:
IBMQInputValueError: If an unknown service name is specified.
"""
if name not in self._services:
raise IBMQInputValueError(f"Unknown service {name} specified.")

if self._services[name] is None:
return False

return True

@property
def backend(self) -> IBMQBackendService:
"""Return the backend service.
Expand Down Expand Up @@ -257,7 +378,22 @@ def random(self) -> IBMQRandomService:
if self._random:
return self._random
else:
raise IBMQNotAuthorizedError("You are not authorized to use the random number service.")
raise IBMQNotAuthorizedError("You are not authorized to use the service.")

@property
def runtime(self) -> IBMRuntimeService:
"""Return the runtime service.

Returns:
The runtime service instance.

Raises:
IBMQNotAuthorizedError: If the account is not authorized to use the service.
"""
if self._runtime:
return self._runtime
else:
raise IBMQNotAuthorizedError("You are not authorized to use the runtime service.")

def __eq__(
self,
Expand Down
2 changes: 2 additions & 0 deletions qiskit/providers/ibmq/api/clients/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@
from .auth import AuthClient
from .version import VersionClient
from .websocket import WebsocketClient
from .runtime import RuntimeClient
from .runtime_ws import RuntimeWebsocketClient
7 changes: 3 additions & 4 deletions qiskit/providers/ibmq/api/clients/account.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,23 @@ class AccountClient(BaseClient):

def __init__(
self,
access_token: str,
credentials: Credentials,
**request_kwargs: Any
) -> None:
"""AccountClient constructor.

Args:
access_token: IBM Quantum Experience access token.
credentials: Account credentials.
**request_kwargs: Arguments for the request ``Session``.
"""
self._session = RetrySession(credentials.base_url, access_token, **request_kwargs)
self._session = RetrySession(
credentials.base_url, credentials.access_token, **request_kwargs)
# base_api is used to handle endpoints that don't include h/g/p.
# account_api is for h/g/p.
self.base_api = Api(self._session)
self.account_api = Account(session=self._session, hub=credentials.hub,
group=credentials.group, project=credentials.project)
self.client_ws = WebsocketClient(credentials.websockets_url, access_token)
self.client_ws = WebsocketClient(credentials.websockets_url, credentials.access_token)
self._use_websockets = (not credentials.proxies)

# Backend-related public functions.
Expand Down
4 changes: 1 addition & 3 deletions qiskit/providers/ibmq/api/clients/experiment.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,14 @@ class ExperimentClient(BaseClient):

def __init__(
self,
access_token: str,
credentials: Credentials
) -> None:
"""ExperimentClient constructor.

Args:
access_token: IBM Quantum Experience access token.
credentials: Account credentials.
"""
self._session = RetrySession(credentials.experiment_url, access_token,
self._session = RetrySession(credentials.experiment_url, credentials.access_token,
**credentials.connection_parameters())
self.base_api = Api(self._session)

Expand Down
5 changes: 1 addition & 4 deletions qiskit/providers/ibmq/api/clients/random.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,14 @@ class RandomClient:

def __init__(
self,
access_token: str,
credentials: Credentials,
) -> None:
"""RandomClient constructor.

Args:
access_token: IBM Quantum Experience access token.
credentials: Account credentials.
"""
self._session = RetrySession(credentials.extractor_url, access_token,
self._session = RetrySession(credentials.extractor_url, credentials.access_token,
**credentials.connection_parameters())
self.random_api = Random(self._session)

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

def extract(
Expand Down
Loading