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

Define a general agreement on what a Backend should be able to do #1474

Open
BrunoLiegiBastonLiegi opened this issue Oct 4, 2024 · 2 comments

Comments

@BrunoLiegiBastonLiegi
Copy link
Contributor

Right now we support several backends, some inside qibo and others outside of it: qibojit, qibo-cloud, qiboml, qibolab ...
However it is nowhere defined what exactly each backend should provide to be compatible with the rest of the qibo API, for instance the quantum_info module.
At the moment we rely on the self.np or backend.np trick to trigger the "engine" of each separate backend. However this is neither consistent across the backends, PyTorchBackend has self.np = torch whereas TensorflowBackend has self.tf = tf and self.np = tf.experimental.numpy or CupyBackend has self.np = numpy and self.cp = cupy, nor is enough to cover all the needed cases. A quick search with git grep "if backend"shows several situations in which we need to explicitely check which backend is used and act accordingly:

git grep "if backend"
src/qibo/backends/__init__.py:        if backend == "numpy":
src/qibo/backends/__init__.py:        elif backend == "tensorflow":
src/qibo/backends/__init__.py:        elif backend == "pytorch":
src/qibo/backends/__init__.py:        elif backend == "clifford":
src/qibo/backends/__init__.py:        elif backend == "qulacs":
src/qibo/backends/__init__.py:        if backend:  # pragma: no cover
src/qibo/backends/__init__.py:    if backend is None:
src/qibo/backends/__init__.py:    if backend in QIBO_NATIVE_BACKENDS + ("clifford",):
src/qibo/backends/__init__.py:        if backend.__class__.__name__ in [
src/qibo/backends/clifford.py:    return backend.platform if backend.platform is not None else backend.name
src/qibo/models/error_mitigation.py:    if backend.name == "pytorch":
src/qibo/models/error_mitigation.py:    if backend.name == "pytorch":
src/qibo/models/error_mitigation.py:    if backend.name == "pytorch":
src/qibo/models/error_mitigation.py:    if backend is None:  # pragma: no cover
src/qibo/models/error_mitigation.py:    elif backend.name == "qibolab":  # pragma: no cover
src/qibo/optimizers.py:    if backend.name == "tensorflow":
src/qibo/optimizers.py:    if backend.name == "pytorch":
src/qibo/quantum_info/metrics.py:                if backend.np.real(eig) > PRECISION_TOL:
src/qibo/quantum_info/quantum_networks.py:        if backend is None:  # pragma: no cover
src/qibo/quantum_info/quantum_networks.py:        if backend is None:  # pragma: no cover
src/qibo/quantum_info/quantum_networks.py:    if backend is None:  # pragma: no cover
src/qibo/quantum_info/random_ensembles.py:    if backend.name == "tensorflow":
src/qibo/quantum_info/superoperator_transformations.py:            if backend.np.abs(eig) > precision_tol:
src/qibo/quantum_info/utils.py:        if backend.np.abs(backend.np.sum(prob_dist_p) - 1.0) > PRECISION_TOL:
src/qibo/quantum_info/utils.py:        if backend.np.abs(backend.np.sum(prob_dist_q) - 1.0) > PRECISION_TOL:
src/qibo/quantum_info/utils.py:        if backend.np.abs(backend.np.sum(prob_dist_p) - 1.0) > PRECISION_TOL:
src/qibo/quantum_info/utils.py:        if backend.np.abs(backend.np.sum(prob_dist_q) - 1.0) > PRECISION_TOL:
src/qibo/tomography/gate_set_tomography.py:    if backend.name == "qibolab" and transpiler is None:  # pragma: no cover
src/qibo/transpiler/unitary_decompositions.py:    if backend.__class__.__name__ in [
src/qibo/transpiler/unitary_decompositions.py:    if backend.__class__.__name__ != "PyTorchBackend":
src/qibo/transpiler/unitary_decompositions.py:    if backend.__class__.__name__ == "TensorflowBackend":
src/qibo/transpiler/unitary_decompositions.py:    if backend.__class__.__name__ == "TensorflowBackend":
tests/test_backends_clifford.py:        GlobalBackend().name if backend.name == "numpy" else GlobalBackend().platform
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:    if backend.name == "pytorch":
tests/test_hamiltonians.py:    if backend.name == "tensorflow" and sparse_type is not None:
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:        if backend.name == "tensorflow":
tests/test_hamiltonians.py:        elif backend.name == "pytorch":
tests/test_hamiltonians.py:            if backend.name == "tensorflow":
tests/test_hamiltonians.py:            elif backend.name == "pytorch":
tests/test_measurements_collapse.py:        if backend.name == "tensorflow":
tests/test_models_circuit_features.py:    if backend.__class__.__name__ == "TensorflowBackend":
tests/test_models_circuit_features.py:    elif backend.__class__.__name__ == "PyTorchBackend":
tests/test_models_error_mitigation.py:    if backend.name == "tensorflow":
tests/test_models_error_mitigation.py:    if backend.name == "tensorflow":
tests/test_models_error_mitigation.py:    if backend.name == "tensorflow":
tests/test_models_error_mitigation.py:    if backend.name == "tensorflow":
tests/test_models_error_mitigation.py:    if backend.name == "tensorflow":
tests/test_models_evolution.py:        if backend.name != "tensorflow":
tests/test_models_qft.py:    if backend is not None:
tests/test_models_variational.py:    if backend.name == "pytorch":
tests/test_models_variational.py:    if backend.name == "pytorch":
tests/test_quantum_info_clifford.py:    if backend.__class__.__name__ == "TensorflowBackend":
tests/test_quantum_info_clifford.py:    elif backend.__class__.__name__ == "PyTorchBackend":
tests/test_quantum_info_entropies.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_quantum_info_entropies.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_quantum_info_entropies.py:    if backend.__class__.__name__ == "CupyBackend":
tests/test_quantum_info_random.py:        if backend.name == "pytorch"
tests/test_transpiler_decompositions.py:        if backend.np.allclose(
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/test_transpiler_unitary_decompositions.py:    if backend.__class__.__name__ in ["CupyBackend", "CuQuantumBackend"]:
tests/utils.py:    if backend.name == "tensorflow":

which is not a sustainable strategy with the inclusion of more and more backends. Especially, an external backend provider should be able to know which operations the backend has to support to have a reasonable "guarantee" of being compatible with qibo.

I think, therefore, that we should compile a list of necessary functionalities, i.e. backend methods, that every backend has to expose to grant compatibility.

@alecandido
Copy link
Member

qiboteam/qibo-core#11

@BrunoLiegiBastonLiegi
Copy link
Contributor Author

Just to complement on this, I would like to summarize here the list of methods that are called through the self.np.method or backend.np.method pattern and that, therefore, are candidate to be converted to explicit methods of the Backend.

git grep "self.np\."
self.np.eye
self.np.zeros
self.np.ones
self.np.copy
self.np.random.choice
self.np.vstack
self.np.cos
self.np.sin
self.np.array
self.np.exp
self.np.conj
self.np.__version__
self.np.reshape
self.np.transpose
self.np.einsum
self.np.concatenate
self.np.expand_dims
self.np.sqrt
self.np.tensordot
self.np.real
self.np.sum
self.np.abs
self.np.unique
self.np.random.seed
self.np.linalg.norm
self.np.trace
self.np.matmul
self.np.diag
self.np.linalg.svd
self.np.as_tensor
self.np.stack
self.np.device
self.np.linalg.det
self.np.permute
self.np.Tensor
self.np.clone
self.np.pow
self.np.mod
self.np.remainder
self.np.unsqueeze
self.np.right_shift
self.np.bitwise_right_shift
self.np.sign
self.np.sgn
self.np.flatnonzero
self.np.nonzero
self.np.tensor
self.np.manual_seed
self.np.multinomial
self.np.linalg.eigvalsh
self.np.linalg.eigvals
self.np.linalg.eigh
self.np.linalg.eig
self.np.linalg.matrix_exp
self.np.imag
self.np.autograd.functional.jacobian
self.np.finfo
self.np.identity
git grep "backend.np\."
backend.np.random.default_rng
backend.np.less
backend.np.outer
backend.np.count_nonzero
backend.np.flip
backend.np.diagonal
backend.np.mean
backend.np.optim.LBFGS
backend.np.any
backend.np.std
backend.np.float64
backend.np.where
backend.np.log2
backend.np.tensordot
backend.np.absolute
backend.np.arccos
backend.np.linalg.qr
backend.np.kron
backend.np.squeeze
backend.np.swapaxes
backend.np.arctan2
backend.np.angle
backend.np.multiply
backend.np.allclose
backend.np.prod
backend.np.optim.Adam
backend.np.rand
backend.np.optim.SGD
backend.np.norm
backend.np.complex128
backend.np.int64
backend.np.sort
backend.np.log
backend.np.inverse

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

No branches or pull requests

2 participants