Skip to content

Commit

Permalink
Merge pull request #95 from UST-QuAntiL/feature/qiskit-executor
Browse files Browse the repository at this point in the history
Feature: Qiskit Executor Plugin
  • Loading branch information
infacc authored Oct 31, 2023
2 parents 43483db + d3a28b4 commit 24e02ea
Show file tree
Hide file tree
Showing 10 changed files with 1,079 additions and 3 deletions.
60 changes: 60 additions & 0 deletions plugins/qiskit_executor/__init__.py
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
75 changes: 75 additions & 0 deletions plugins/qiskit_executor/backend/qiskit_backends.py
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}")
Loading

0 comments on commit 24e02ea

Please sign in to comment.