diff --git a/src/qibotn/quimb.py b/src/qibotn/quimb.py index 93457f4..4f7244f 100644 --- a/src/qibotn/quimb.py +++ b/src/qibotn/quimb.py @@ -1,6 +1,6 @@ import re -import qibo +from qibo.models import Circuit as QiboCircuit import quimb.tensor as qtn import numpy as np @@ -22,7 +22,7 @@ def get_gate_functions(qasm_str, start_idx): idx_inc += 1 -def convert(nqubits: int, qasm_str: str, with_swaps: bool = True, psi0=None): +def from_qibo(circuit: QiboCircuit, with_swaps: bool = True, psi0=None): circ = qtn.Circuit(nqubits, psi0=psi0) qasm_str = qasm_str.split("\n") @@ -65,9 +65,9 @@ def eval(qasm: str, init_state, backend="numpy", swaps=True): backend (quimb): numpy, cupy, jax. Passed to ``opt_einsum``. """ - circuit = qibo.models.Circuit.from_qasm(qasm) + circuit = QiboCircuit.from_qasm(qasm) init_state_mps = init_state_tn(circuit.nqubits, init_state) - circ_quimb = convert(circuit, swaps=swaps, psi0=init_state_mps) + circ_quimb = from_qibo(circuit, swaps=swaps, psi0=init_state_mps) interim = circ_quimb.psi.full_simplify(seq="DRC") amplitudes = interim.to_dense(backend=backend).flatten() diff --git a/tests/config.py b/tests/config.py index 96621a2..7570e30 100644 --- a/tests/config.py +++ b/tests/config.py @@ -1,10 +1,13 @@ -qibo = dict( - backend = 'qibojit', - platform = 'numpy', - swaps = True -) +from dataclasses import dataclass +from typing import Optional -quimb = dict( - backend = 'numpy', - swaps = True -) + +@dataclass +class Executor: + backend: str + platform: Optional[str] = None + swaps: bool = True + + +qibo = Executor(backend="qibojit", platform="numpy") +quimb = Executor(backend="numpy") diff --git a/tests/test_qasm_quimb_backend.py b/tests/test_qasm_quimb_backend.py index 9f4c854..db1ad27 100644 --- a/tests/test_qasm_quimb_backend.py +++ b/tests/test_qasm_quimb_backend.py @@ -10,10 +10,9 @@ from timeit import default_timer as timer import config -def init_state_sv(nqubits): +def create_init_state(nqubits): init_state = np.random.random(2**nqubits) + 1j * np.random.random(2**nqubits) init_state = init_state / np.sqrt((np.abs(init_state) ** 2).sum()) - # An unmodified init_state has to be converted to tn format return init_state @@ -23,34 +22,43 @@ def qibo_qft(nqubits, init_state, swaps): return circ_qibo, state_vec +def time(func): + start = timer() + res = func() + end = timer() + time = end - start + return time, res + + @pytest.mark.parametrize("nqubits", [1, 2, 5, 10]) def test_eval(nqubits: int): + # hack quimb to use the correct number of processes + # TODO: remove completely, or at least delegate to the backend + # implementation os.environ["QUIMB_NUM_PROCS"] = str(os.cpu_count()) - from qibotn import qasm_quimb + import qibotn.quimb - init_state = init_state_sv(nqubits=nqubits) + init_state = create_init_state(nqubits=nqubits) + init_state_tn = copy.deepcopy(init_state) # Test qibo - qibo.set_backend(backend=config.qibo["backend"], platform=config.qibo["platform"]) - start_time = timer() - qibo_circ, result_sv = qibo_qft(nqubits, init_state, swaps=config.qibo["swaps"]) - end_time = timer() - qibo_time = end_time - start_time + qibo.set_backend(backend=config.qibo.backend, platform=config.qibo.platform) + qibo_time, (qibo_circ, result_sv) = time( + lambda: qibo_qft(nqubits, init_state, swaps=config.qibo.swaps) + ) # Convert to qasm for other backends qasm_circ = qibo_circ.to_qasm() - __import__("pdb").set_trace() # Test quimb - start_time = timer() - result_tn = qasm_quimb.eval_QI_qft( - nqubits=nqubits, - qasm_circ=qasm_circ, - init_state=copy.deepcopy(init_state), - backend=config.quimb["backend"], - swaps=config.quimb["swaps"], + quimb_time, result_tn = time( + lambda: qibotn.quimb.eval( + qasm_circ, + init_state_tn, + backend=config.quimb.backend, + swaps=config.quimb.swaps, + ) ) - end_time = timer() - quimb_time = end_time - start_time + assert 1e-2 * qibo_time < quimb_time < 1e2 * qibo_time assert np.allclose(result_sv, result_tn), "Resulting dense vectors do not match"