diff --git a/src/qibotn/backends/__init__.py b/src/qibotn/backends/__init__.py index 4e0d026..624ed62 100644 --- a/src/qibotn/backends/__init__.py +++ b/src/qibotn/backends/__init__.py @@ -2,10 +2,10 @@ from typing import Union from qibo.config import raise_error -from qibotn.backends.cutensornet import CuTensorNet # pylint: disable=E0401 -from qibotn.backends.quimb import QuimbBackend # pylint: disable=E0401 -from qibotn.backends.qmatchatea import QMatchaTeaBackend # pylint: disable=E0401 from qibotn.backends.abstract import QibotnBackend +from qibotn.backends.cutensornet import CuTensorNet # pylint: disable=E0401 +from qibotn.backends.qmatchatea import QMatchaTeaBackend # pylint: disable=E0401 +from qibotn.backends.quimb import QuimbBackend # pylint: disable=E0401 QibotnBackend = Union[CuTensorNet, QuimbBackend, QMatchaTeaBackend] diff --git a/src/qibotn/backends/abstract.py b/src/qibotn/backends/abstract.py index 6e8088d..f7d2df2 100644 --- a/src/qibotn/backends/abstract.py +++ b/src/qibotn/backends/abstract.py @@ -1,11 +1,11 @@ from abc import abstractmethod + from qibo.backends.numpy import NumpyBackend from qibo.config import raise_error - DEFAULT_CONFIGURATION = { - "MPI_enabled": False, # TODO: cutensornet specific, TBRemoved - "NCCL_enabled": False, # TODO: cutensornet specific, TBRemoved + "MPI_enabled": False, # TODO: cutensornet specific, TBRemoved + "NCCL_enabled": False, # TODO: cutensornet specific, TBRemoved "expectation_enabled": False, "pauli_string_pattern": None, "MPS_enabled": False, @@ -14,10 +14,9 @@ DEFAULT_CONFIGURATION = { } - class QibotnBackend(NumpyBackend): - def __init__(self, runcard:dict = DEFAULT_CONFIGURATION): + def __init__(self, runcard: dict = DEFAULT_CONFIGURATION): super().__init__() def apply_gate(self, gate, state, nqubits): # pragma: no cover @@ -32,10 +31,8 @@ class QibotnBackend(NumpyBackend): def set_precision(self, precision): if precision != self.precision: super().set_precision(precision) - + @abstractmethod def configure_tn_simulation(self, **config): """Configure the TN simulation that will be performed.""" pass - - diff --git a/src/qibotn/backends/cutensornet.py b/src/qibotn/backends/cutensornet.py index d4f1bcc..d02fdd5 100644 --- a/src/qibotn/backends/cutensornet.py +++ b/src/qibotn/backends/cutensornet.py @@ -82,7 +82,6 @@ class CuTensorNet(QibotnBackend): # pragma: no cover if hasattr(self, "cutn"): self.cutn.destroy(self.handle) - def cuda_type(self, dtype="complex64"): """Get CUDA Type. diff --git a/src/qibotn/backends/qmatchatea.py b/src/qibotn/backends/qmatchatea.py index ba40475..2af64ee 100644 --- a/src/qibotn/backends/qmatchatea.py +++ b/src/qibotn/backends/qmatchatea.py @@ -1,103 +1,108 @@ -"""Implementation of Quantum Matcha Tea backend""" +"""Implementation of Quantum Matcha Tea backend.""" from dataclasses import dataclass + +from qibo.config import raise_error from qiskit import QuantumCircuit from qibotn.backends.abstract import QibotnBackend -from qibo.config import raise_error + @dataclass class QMatchaTeaBackend(QibotnBackend): - - def __init__(self): + + def __init__(self): super().__init__() + import qiskit # pylint: disable=import-error import qmatchatea # pylint: disable=import-error - import qiskit # pylint: disable=import-error - import qtealeaves # pylint: disable=import-error + import qtealeaves # pylint: disable=import-error self.qmatchatea = qmatchatea self.qiskit = qiskit self.qtleaves = qtealeaves - # Set default configurations self.configure_tn_simulation() # TODO: update this function whenever ``set_device`` and ``set_precision`` # are set (?) self._setup_qmatchatea_backend() - def execute_circuit( - self, circuit, initial_state=None, nshots=None, return_array=False + self, circuit, initial_state=None, nshots=None, return_array=False ): - + # TODO: verify if the QCIO mechanism of matcha is supported by Fortran only - # as written in the docstrings or by Python too (see ``io_info`` argument of + # as written in the docstrings or by Python too (see ``io_info`` argument of # ``qmatchatea.interface.run_simulation`` function) if initial_state is not None: raise_error( NotImplementedError, - f"Backend {self.name}-{self.platform} currently does not support initial state." + f"Backend {self.name}-{self.platform} currently does not support initial state.", ) - # TODO: do we want to keep it like this or we aim to implement a different - # idea of "shots" here? + # TODO: do we want to keep it like this or we aim to implement a different + # idea of "shots" here? nshots = None - + circuit = self._qibocirc_to_qiskitcirc(circuit) run_qk_params = self.qmatchatea.preprocessing.qk_transpilation_params(False) results = self.qmatchatea.run_simulation( - circ = circuit, - convergence_parameters = self.convergence_params, - transpilation_parameters = run_qk_params, - backend = self.qmatchatea_backend, + circ=circuit, + convergence_parameters=self.convergence_params, + transpilation_parameters=run_qk_params, + backend=self.qmatchatea_backend, ) # TODO: construct a proper TNResult object? # It does not make sense to reconstruct QuantumState here! return results.measure_probabilities - def configure_tn_simulation( - self, - convergence_params = None, - ansatz: str = "MPS", - ): - """ - Configure TN simulation given Quantum Matcha Tea interface. - + self, + convergence_params=None, + ansatz: str = "MPS", + ): + """Configure TN simulation given Quantum Matcha Tea interface. + Args: ansatz (str): tensor network ansatz. It can be tree tensor network "TTN" or Matrix Product States "MPS" (default). - convergence_params (qmatchatea.utils.QCConvergenceParameters): - convergence parameters class adapted to the quantum computing + convergence_params (qmatchatea.utils.QCConvergenceParameters): + convergence parameters class adapted to the quantum computing execution. See https://baltig.infn.it/quantum_matcha_tea/py_api_quantum_matcha_tea/-/blob/master/qmatchatea/utils/utils.py?ref_type=heads#L540 - for more instructions. If not passed, the default values proposed + for more instructions. If not passed, the default values proposed by Quantum Matcha Tea's authors are set. """ # Set configurationsor defaults - self.convergence_params = convergence_params or self.qmatchatea.QCConvergenceParameters() + self.convergence_params = ( + convergence_params or self.qmatchatea.QCConvergenceParameters() + ) self.ansatz = ansatz - # Initializing the TNObservables according to qmatchatea + # Initializing the TNObservables according to qmatchatea self.observables = self.qtleaves.observables.TNObservables() - def _setup_qmatchatea_backend(self): """Configure qmatchatea QCBackend object.""" - self.qmatchatea_device = "cpu" if "CPU" in self.device else "gpu" if "GPU" in self.device else None - self.qmatchatea_precision = "C" if self.precision == "single" else "Z" if self.precision == "double" else "A" + self.qmatchatea_device = ( + "cpu" if "CPU" in self.device else "gpu" if "GPU" in self.device else None + ) + self.qmatchatea_precision = ( + "C" + if self.precision == "single" + else "Z" if self.precision == "double" else "A" + ) # TODO: once MPI is available for Python, integrate it here self.qmatchatea_backend = self.qmatchatea.QCBackend( - backend = "PY", # The only alternative is Fortran, but we use Python here - precision = self.qmatchatea_precision, - device = self.qmatchatea_device, - ansatz = self.ansatz, + backend="PY", # The only alternative is Fortran, but we use Python here + precision=self.qmatchatea_precision, + device=self.qmatchatea_device, + ansatz=self.ansatz, ) def _qibocirc_to_qiskitcirc(self, qibo_circuit) -> QuantumCircuit: @@ -106,11 +111,11 @@ class QMatchaTeaBackend(QibotnBackend): qasm_circuit = qibo_circuit.to_qasm() qiskit_circuit = QuantumCircuit.from_qasm_str(qasm_circuit) - # Transpile the circuit to adapt it to the linear structure of the MPS, + # Transpile the circuit to adapt it to the linear structure of the MPS, # with the constraint of having only the gates basis_gates qiskit_circuit = self.qmatchatea.preprocessing.preprocess( - qiskit_circuit, - qk_params=self.qmatchatea.preprocessing.qk_transpilation_params() + qiskit_circuit, + qk_params=self.qmatchatea.preprocessing.qk_transpilation_params(), ) - return qiskit_circuit \ No newline at end of file + return qiskit_circuit diff --git a/src/qibotn/backends/quimb.py b/src/qibotn/backends/quimb.py index 20223b3..30ef888 100644 --- a/src/qibotn/backends/quimb.py +++ b/src/qibotn/backends/quimb.py @@ -1,4 +1,3 @@ -from qibo.backends.numpy import NumpyBackend from qibo.config import raise_error from qibo.result import QuantumState @@ -38,7 +37,6 @@ class QuimbBackend(QibotnBackend): self.platform = "QuimbBackend" self.versions["quimb"] = self.quimb.__version__ - def execute_circuit( self, circuit, initial_state=None, nshots=None, return_array=False ): # pragma: no cover