-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #95 from UST-QuAntiL/feature/qiskit-executor
Feature: Qiskit Executor Plugin
- Loading branch information
Showing
10 changed files
with
1,079 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
# Copyright 2023 QHAna plugin runner contributors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from typing import Optional | ||
|
||
from flask import Flask | ||
|
||
from qhana_plugin_runner.api.util import SecurityBlueprint | ||
from qhana_plugin_runner.util.plugins import plugin_identifier, QHAnaPluginBase | ||
|
||
_plugin_name = "qiskit-executor" | ||
__version__ = "v0.1.0" | ||
_identifier = plugin_identifier(_plugin_name, __version__) | ||
|
||
|
||
QISKIT_EXECUTOR_BLP = SecurityBlueprint( | ||
_identifier, # blueprint name | ||
__name__, # module import name! | ||
description="Qiskit Quantum Circuit Executor", | ||
) | ||
|
||
|
||
qiskit_version = "0.43" | ||
|
||
|
||
class QiskitExecutor(QHAnaPluginBase): | ||
name = _plugin_name | ||
version = __version__ | ||
description = "Allows execution of quantum circuits using IBM Quantum backends." | ||
tags = ["circuit-executor", "qc-executor", "qiskit", "qasm", "qasm-2"] | ||
|
||
def __init__(self, app: Optional[Flask]) -> None: | ||
super().__init__(app) | ||
|
||
def get_api_blueprint(self): | ||
return QISKIT_EXECUTOR_BLP | ||
|
||
def get_requirements(self) -> str: | ||
return f"qiskit~={qiskit_version}" | ||
|
||
|
||
try: | ||
# It is important to import the routes **after** COSTUME_LOADER_BLP and CostumeLoader are defined, because they are | ||
# accessed as soon as the routes are imported. | ||
from . import routes | ||
except ImportError: | ||
# When running `poetry run flask install`, importing the routes will fail, because the dependencies are not | ||
# installed yet. | ||
pass |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# Copyright 2023 QHAna plugin runner contributors. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from typing import Optional | ||
from celery.utils.log import get_task_logger | ||
from qiskit import IBMQ | ||
|
||
from qiskit.providers.exceptions import QiskitBackendNotFoundError | ||
from qiskit.providers.ibmq.exceptions import IBMQAccountError | ||
from qiskit.providers.ibmq.accountprovider import AccountProvider | ||
from qiskit.providers.ibmq.ibmqbackend import IBMQBackend, IBMQSimulator | ||
from qiskit.providers.ibmq.api.exceptions import RequestsApiError | ||
|
||
|
||
TASK_LOGGER = get_task_logger(__name__) | ||
|
||
|
||
def get_provider(ibmq_token: str) -> Optional[AccountProvider]: | ||
"""Get the IBMQ provider from the token. If no provider is found (e.g. invalid token), return None. | ||
Args: | ||
ibmq_token: The IBMQ token to use. | ||
""" | ||
try: | ||
provider = IBMQ.enable_account(ibmq_token) | ||
except IBMQAccountError as e: | ||
# Try to get provider from existing accounts | ||
providers = (p for p in IBMQ.providers() if p.credentials.token == ibmq_token) | ||
provider = next(iter(providers), None) | ||
if not provider: | ||
TASK_LOGGER.info("No IBMQ provider found!") | ||
except RequestsApiError: | ||
TASK_LOGGER.info("Login failed!") | ||
return None | ||
return provider | ||
|
||
|
||
def get_backends(ibmq_token: str) -> Optional[list[IBMQBackend | IBMQSimulator]]: | ||
"""Get the list of available backends for the given IBMQ token. If no provider is found (e.g. invalid token), return None.""" | ||
provider = get_provider(ibmq_token) | ||
if provider is None: | ||
return None | ||
return provider.backends() | ||
|
||
|
||
def get_backend_names(ibmq_token: str) -> Optional[list[str]]: | ||
"""Get the list of available backend names for the given IBMQ token. If no provider is found (e.g. invalid token), return None.""" | ||
backends = get_backends(ibmq_token) | ||
if backends is None: | ||
return None | ||
return [backend.name() for backend in backends] | ||
|
||
|
||
def get_qiskit_backend( | ||
backend: str, ibmq_token: str | ||
) -> Optional[IBMQBackend | IBMQSimulator]: | ||
"""Get the backend with the given name from the IBMQ provider. If no provider is found (e.g. invalid token), return None.""" | ||
provider = get_provider(ibmq_token) | ||
if provider is None: | ||
return None | ||
try: | ||
return provider.get_backend(backend) | ||
except QiskitBackendNotFoundError: | ||
TASK_LOGGER.info(f"Unknown qiskit backend specified: {backend}") |
Oops, something went wrong.