-
Notifications
You must be signed in to change notification settings - Fork 2.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add unregister() via DefaultQISKitProvider changes #584
Changes from 4 commits
bfd4ea9
e3d3e26
e05068e
a5fbf93
1fbb1a4
85e6395
cec2fdf
d62d938
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,9 +8,8 @@ | |
"""Helper module for simplified QISKit usage.""" | ||
|
||
import warnings | ||
|
||
import qiskit._compiler | ||
from qiskit import QISKitError | ||
from qiskit.backends.ibmq.ibmqprovider import IBMQProvider | ||
from qiskit.wrapper.defaultqiskitprovider import DefaultQISKitProvider | ||
from ._circuittoolkit import circuit_from_qasm_file, circuit_from_qasm_string | ||
|
||
|
@@ -22,7 +21,7 @@ | |
|
||
def register(token, url='https://quantumexperience.ng.bluemix.net/api', | ||
hub=None, group=None, project=None, proxies=None, verify=True, | ||
provider_name='ibmq'): | ||
provider_name=None): | ||
""" | ||
Authenticate against an online backend provider. | ||
|
||
|
@@ -37,17 +36,34 @@ def register(token, url='https://quantumexperience.ng.bluemix.net/api', | |
proxies (dict): Proxy configuration for the API, as a dict with | ||
'urls' and credential keys. | ||
verify (bool): If False, ignores SSL certificates errors. | ||
provider_name (str): the unique name for the online backend | ||
provider (for example, 'ibmq' for the IBM Quantum Experience). | ||
provider_name (str): the user-provided name for the registered | ||
provider. | ||
Raises: | ||
QISKitError: if the provider name is not recognized. | ||
""" | ||
if provider_name == 'ibmq': | ||
provider = IBMQProvider(token, url, | ||
hub, group, project, proxies, verify) | ||
_DEFAULT_PROVIDER.add_provider(provider) | ||
else: | ||
raise QISKitError('provider name %s is not recognized' % provider_name) | ||
# Convert the credentials to a dict. | ||
credentials = { | ||
'token': token, 'url': url, 'hub': hub, 'group': group, | ||
'project': project, 'proxies': proxies, 'verify': verify | ||
} | ||
_DEFAULT_PROVIDER.add_ibmq_provider(credentials, provider_name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to the comment at #584 (comment) - I went for being conservative when exposing the providers to the user in the wrapper, but happy to reevaluate eventually. |
||
|
||
|
||
def unregister(provider_name): | ||
""" | ||
Removes a provider of list of registered providers. | ||
|
||
Args: | ||
provider_name (str): The unique name for the online provider. | ||
Raises: | ||
QISKitError: if the provider name is not valid. | ||
""" | ||
_DEFAULT_PROVIDER.remove_provider(provider_name) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If modifying There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm, I'm unsure if it would play nicely with the philosophy of not having the end-user-oriented wrapper functions expose the providers directly (and in this particular case, would return a "not longer in use provider"). It's a good point, though - perhaps we can reevaluate in the parent PR? |
||
|
||
|
||
def registered_providers(): | ||
"""Return the names of the currently registered providers.""" | ||
return list(_DEFAULT_PROVIDER.providers.keys()) | ||
|
||
|
||
# Functions for inspecting and retrieving backends. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,9 +7,11 @@ | |
|
||
"""Meta-provider that aggregates several providers.""" | ||
import logging | ||
|
||
from itertools import combinations | ||
|
||
from qiskit import QISKitError | ||
from qiskit.backends.baseprovider import BaseProvider | ||
from qiskit.backends.ibmq import IBMQProvider | ||
from qiskit.backends.local.localprovider import LocalProvider | ||
|
||
logger = logging.getLogger(__name__) | ||
|
@@ -22,12 +24,12 @@ class DefaultQISKitProvider(BaseProvider): | |
def __init__(self): | ||
super().__init__() | ||
|
||
# List of providers. | ||
self.providers = [LocalProvider()] | ||
# Dict of providers. | ||
self.providers = {'local': LocalProvider()} | ||
|
||
def get_backend(self, name): | ||
name = self.resolve_backend_name(name) | ||
for provider in self.providers: | ||
for provider in self.providers.values(): | ||
try: | ||
return provider.get_backend(name) | ||
except KeyError: | ||
|
@@ -45,7 +47,7 @@ def available_backends(self, filters=None): | |
""" | ||
# pylint: disable=arguments-differ | ||
backends = [] | ||
for provider in self.providers: | ||
for provider in self.providers.values(): | ||
backends.extend(provider.available_backends(filters)) | ||
return backends | ||
|
||
|
@@ -60,7 +62,7 @@ def aliased_backend_names(self): | |
ValueError: if a backend is mapped to multiple aliases | ||
""" | ||
aliases = {} | ||
for provider in self.providers: | ||
for provider in self.providers.values(): | ||
aliases = {**aliases, **provider.aliased_backend_names()} | ||
for pair in combinations(aliases.values(), r=2): | ||
if not set.isdisjoint(set(pair[0]), set(pair[1])): | ||
|
@@ -76,19 +78,85 @@ def deprecated_backend_names(self): | |
dict[str: list[str]]: aggregated alias dictionary | ||
""" | ||
deprecates = {} | ||
for provider in self.providers: | ||
for provider in self.providers.values(): | ||
deprecates = {**deprecates, **provider.deprecated_backend_names()} | ||
|
||
return deprecates | ||
|
||
def add_provider(self, provider): | ||
def add_provider(self, provider, provider_name): | ||
""" | ||
Add a new provider to the list of known providers. | ||
|
||
Args: | ||
provider (BaseProvider): Provider instance. | ||
provider_name (str): User-provided name for the provider. | ||
|
||
Returns: | ||
BaseProvider: the provider instance. | ||
|
||
Raises: | ||
QISKitError: if a provider with the same name is already in the | ||
list. | ||
""" | ||
if provider_name in self.providers.keys(): | ||
raise QISKitError( | ||
'A provider with name "%s" is already registered.' | ||
% provider_name) | ||
|
||
self.providers[provider_name] = provider | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Non-blocking: should we return the provider to keep it consistent with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sure, makes sense! |
||
|
||
return provider | ||
|
||
def add_ibmq_provider(self, credentials_dict, provider_name=None): | ||
""" | ||
Add a new IBMQProvider to the list of known providers. | ||
|
||
Args: | ||
credentials_dict (dict): dictionary of credentials for a provider. | ||
provider_name (str): User-provided name for the provider. A name | ||
will automatically be assigned if possible. | ||
Raises: | ||
QISKitError: if a provider with the same name is already in the | ||
list; or if a provider name could not be assigned. | ||
Returns: | ||
IBMQProvider: the new IBMQProvider instance. | ||
""" | ||
# Automatically assign a name if not specified. | ||
if not provider_name: | ||
if 'quantumexperience' in credentials_dict['url']: | ||
provider_name = 'ibmq' | ||
elif 'q-console' in credentials_dict['url']: | ||
provider_name = 'qnet' | ||
else: | ||
raise QISKitError( | ||
'Cannot parse provider name from credentials.') | ||
|
||
if provider_name in self.providers.keys(): | ||
raise QISKitError( | ||
'A provider with name "%s" is already registered.' | ||
% provider_name) | ||
|
||
ibmq_provider = IBMQProvider(**credentials_dict) | ||
self.providers[provider_name] = ibmq_provider | ||
|
||
return ibmq_provider | ||
|
||
def remove_provider(self, provider_name): | ||
""" | ||
Remove a provider from the list of known providers. | ||
|
||
Args: | ||
provider_name (str): name of the provider to be removed. | ||
|
||
Raises: | ||
QISKitError: if the provider name is not valid. | ||
""" | ||
self.providers.append(provider) | ||
if provider_name == 'local': | ||
raise QISKitError("Cannot unregister 'local' provider.") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you elaborate a bit about why you can not register nor unregister the However, there would be no problem in unregistering the local = DEFAULT_PROVIDER.remove_provider('local')
DEFAULT_PROVIDER.add_provider(my_provider, 'local')
DEFAULT_PROVIDER.add_provider(local, 'qiskit_local') The above is optional and non-blocking. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, it's very much up for debate - it was mostly based on https://github.com/QISKit/qiskit-core/pull/547/files/1ca64661029eba38d25edcc5c1f0ba61388c9581#diff-c8057d22bae58d0abb388944221cc41d. I'd be happy to re-discuss it when the other PR is addressed, as I don't have a strong opinion either way! |
||
try: | ||
self.providers.pop(provider_name) | ||
except KeyError: | ||
raise QISKitError("'%s' provider is not registered.") | ||
|
||
def resolve_backend_name(self, name): | ||
"""Resolve backend name from a possible short alias or a deprecated name. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If changing the signatures or
register()
andunregister()
for them to return the provider instances, consider adding that here too.