Skip to content
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

introduce abstract base class for backends #84

Merged
merged 15 commits into from
Oct 4, 2017

Conversation

ewinston
Copy link
Contributor

introduce abstract base class for backends

Description

With this change, backend modules should inherent from BaseBackend
and will need to implement a small set of methods for them to be
registered as working backends. Also, the runnable backend modules are put
into the namespace so e.g. they get included in the sphinx docs.

Motivation and Context

This change encourages a common structure for backend modules.

How Has This Been Tested?

make test
make doc

Screenshots (if appropriate):

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)

Checklist:

  • My code follows the code style of this project.
  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have read the CONTRIBUTING document.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

With this change, backend modules should inherent from BaseBackend
and will need to implement a small set of methods for them to be
registered as working backends. Also, the runnable backend modules are put
into the namespace so e.g. they get included in the sphinx docs.
@ewinston ewinston changed the title ABC backend introduce abstract base class for backends Sep 26, 2017
Copy link
Member

@diego-plan9 diego-plan9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm really glad to see this PR, @ewinston! I feel it provides a much more consistent and robust way of defining local backends, making it more friendly for developers.

As hinted during the documentation PR, I feel this would be a really good time to tackle the way the backends are discovered. I understand the motivation on that comment, but going case by case and making hopefully reasonable assumptions:

  • if a user uses qiskit as a library and wants to implement their own simulator, currently the autodiscover mechanism will only pick up their simulator if it is placed on the PYTHON_LIBRARY_PATH/qiskit/backend/, which is unlikely to be there if installed via pip.
  • if a QISKit developer is implementing a custom simulator that might not be part of the SDK, it seems safe to assume he would be comfortable declaring it elsewhere or modifying another file on the library to make it work.
  • if we implement a simulator in the future for being available in the SDK, it will end up being discovered every time - making the autodiscovery a bit redundant.

I might be missing some use cases and would welcome some input, but for these three cases we are mostly trading quite a bit of "niceties" (clarity, the ability for the users to discover the backends using their development tools, documentation, etc) compared to using the standard import mechanism. Would it be worth discussing a bit the available options and try to address it on this PR?

@configuration.setter
@abstractmethod
def configuration(self, configuration):
"""Set backend configuration"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it likely that any local backend will do something different than return self._configuration and self._configuration = configuration on these two functions?

All of the existing simulators seem to be have exactly the same implementation for these two methods, and it might be worth just moving the implementation for these two functions to BaseBackend directly (and not making them @abstractmethods) to avoid duplication - if in the end a future simulator needs to do something different it can just override them anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did this in case a user wanted to do some kind of module specific validation of configuration but since I don't currently have a clear picture of this perhaps it would be ok to implement it in BaseBackend.

self._configuration = None # IMPLEMENT for your backend

@abstractmethod
def run(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With the recent changes, would it be a good idea to define run_circuit(...) as an @abstractmethod, this enforcing the simulators to provide and implement it? Currently, it seems it is never called directly outside each module (ie. it is always called from FooSimulator.run()), but I'm not sure if the goal is to eventually use run_circuit() directly elsewhere.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we have changed to using qobj for communicating tasks the simulator, and perhaps the online backends, don't need to run circuits individually. For instance a c simulator can take in the whole qobj. The run_circuit() method is sort of a non-essential fix to get the python simulators to work with qobj without making too many changes. It seems like a good method to have for python simulators but some simulators might want to do optimizations on batches of circuits which don't need running individual ones. At least this way we make it optional.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds sensible, thanks for the clarification - I was mostly not sure how "universal" the run_circuit() was meant to be, and keeping it just on the simulator that needs it sounds fine to me!

FileNotFoundError if backend executable is not available.
"""
self._qobj = qobj
self._configuration = None # IMPLEMENT for your backend
Copy link
Member

@diego-plan9 diego-plan9 Sep 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we also at least document the format of the configuration somewhere on the docstrings of this file, to make as clear as possible for users interested in subclassing it? Going a bit further, we might want to make some configuration values class methods, for example name (so they are available as MySimulator.name) to further enforce them (I'm picking name as an example as it is the identifier that is later used to refer to the simulator by the user).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the nice thing about the discovery is that the backend developer does not have to put import statements in any qiskit file for the backend to be used. They only need to know the name of the backend they put into the configuration of their own backend module. Even for the number of backends we have this keeps the core code cleaner.

I think you could be right about the user putting the module in the backends folder if they've installed with pip. Perhaps if they are developing backends they are more likely to use a git repo and would be comfortable with putting modules there. Still, maybe it's strange to have "local" modules mixed with qiskit ones. Perhaps we can have a ".qiskit/backends" folder in their home directory, or other locations, which are also checked.

Another nice thing about the discovery mechanics is that if, for instance wants to make several versions of a compiled simulator (e.g. different optimizations) it would be easier to implement.

We could also use the discovery function to "discover" online backends and make them subclass BaseBackend. This would make us less dependent on changes to the set of available online backends.

I'm a little unclear about what niceties we are giving up. In the previous discovery I intentionally hid backends and just made LocalSimulator the only one that was visible. With this PR I import all the backend modules into the namespace as you suggested so you should see no difference from doing a normal import (that was the goal anyway). For instance documentation and tab completion seems to be available now.

ewinston and others added 7 commits October 2, 2017 17:02
Add "qiskit.backends._backendutils.register_backend()" as the main
function for registering a local backend, including in turn:
* revise the autodiscovery function "discover_sdk_backends()", making
  use of "register_backend()" and dropping compatibility with old-style
  definition of backends (ie. using a "__configuration" module
  variable".
* merge the module-level variables "_backend_classes" and
  "_backend_configurations" into a single "_REGISTERED_BACKENDS" dict
  that uses namedtuples, for consistency.
* update "local_backends()" and "remote_backends()" to make use of the
  new merged variable.
* reorganize the "qiskit.backend.__init__" imports to expose only the
  methods needed by the user.
* update the tests and add tests for "register_backend()".
Change "BaseBackend.configuration" to a non-abstract property, dropping
the setter, as all the current backends share the same implementation,
in order to avoid code duplication. Custom backends can still override
the method directly if needed.
Copy link
Member

@diego-plan9 diego-plan9 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the latest changes! As a summary of the conversations, the backends are now registered via a new public register_backend() function, which is used during the autodiscovery and can be used by users to register backends outside the SDK.

There is still some work to do once we tackle the bigger issue of better integrating the online backends, but looks ready to merge to me - maybe except the _qelocal.py file?

@diego-plan9 diego-plan9 merged commit 949fe46 into Qiskit:master Oct 4, 2017
@ewinston ewinston deleted the abc-backend branch June 9, 2020 19:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants