qiboteam / qibo

A full-stack framework for quantum computing.
https://qibo.science
Apache License 2.0
297 stars 61 forks source link

Import loops #1490

Open alecandido opened 1 month ago

alecandido commented 1 month ago

During #1440 many import required to be scoped within functions in order to avoid circular dependencies. This is only a temporary patch, and just a symptom of bad design.

Part of the solution will come with qibo-core backends migration[*], but while waiting for it, reconsidering the internal Qibo structure would be also worth. Even because some loops may survive the backend mechanism replacement (especially those related to the _Global, which won't be necessarily handled by qibo-core).

[*]: it doesn't mean the backends will be migrated to qibo-core, which in fact is attempting to stay backend-free, but rather that the imports will change in any case

alecandido commented 1 month ago

The loop is roughly structured like this: many modules in qibo.__init__.py import the backends at the top of their files. (Because of _check_backend() and get_backend()) If we import the transpiler at the top of backends.__init__.py, it causes a circular import because many transpiler modules rely on qibo.models.Circuit, which depends on the backend.

Untitled Diagram drawio (1)

_Originally posted by @csookim in https://github.com/qiboteam/qibo/pull/1440#discussion_r1800991580_

stavros11 commented 1 month ago

Came here from the related discussion from #1440. If I understand correctly, the suggestion is to break the loop where the Circuit depends on the _Global backend. This may be problematic if we want to keep the usual qibo execution style:

result = circuit(nshots=1000)

because this will always have to invoke a (global) backend.

Qibo-core may address the problem. The core circuit will be (and should be) backend independent, however if we want to maintain the same execution interface we will still need a higher level qibo circuit that depends on the global backend. If the transpilers only depend on the core circuit though, the cyclic problem should be solved. But then we are breaking the loop in a different place.

alecandido commented 1 month ago

Yes, the current Circuit loop can only be broken either by giving up some features (namely, execution as a method) or separating the concerns.

Indeed, the qibo.Circuit is both the UI and the primitive of Qibo, and this is what is generating loops. qibo-core will take away the primitive task, and the native qibo.Circuit will just remain as UI.

In principle, we could do the same even without qibo-core. But since it's half-done, it's not worth to reinvent the wheel once more.

Still, I feel like there may be further loops, e.g. involving the transpiler or the measurements. So, at some point (maybe even after qibo-core introduction) it may be worth to audit the whole content of src looking for scoped (non-top-level) import statements.