From c07d9bf6c9931e84b6a4f7bebcd22a84b78ff3f6 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 11:01:24 +0100 Subject: [PATCH 1/6] Drop previous parser --- src/qibotn/qasm_quimb.py | 139 +++---------------------------- tests/test_qasm_quimb_backend.py | 26 +++--- 2 files changed, 26 insertions(+), 139 deletions(-) diff --git a/src/qibotn/qasm_quimb.py b/src/qibotn/qasm_quimb.py index a552ad0..f7546eb 100644 --- a/src/qibotn/qasm_quimb.py +++ b/src/qibotn/qasm_quimb.py @@ -5,127 +5,6 @@ import quimb.tensor as qtn import numpy as np -def get_gate_params(operation): - if "h " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "H") - elif "x " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "X") - elif "y " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "Y") - elif "z " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "Z") - elif "s " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "S") - elif "t " in operation: - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no.insert(0, "T") - elif "cu1" in operation: - lambda_ = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no[0:0] = ["CU1", lambda_] - elif "cu2" in operation: - angles = re.findall(r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0]) - phi = float(".".join(angles[0:2])) - lambda_ = float(".".join(angles[2:])) - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no[0:0] = ["CU2", phi, lambda_] - elif "cu3" in operation: - angles = re.findall(r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0]) - theta = float(".".join(angles[0:2])) - phi = float(".".join(angles[2:4])) - lambda_ = float(".".join(angles[4:])) - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no[0:0] = ["CU3", theta, phi, lambda_] - elif " cx " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CX") - elif " cy " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CY") - elif " cz " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CZ") - elif " ccx " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CCX") - elif " ccy " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CCY") - elif " ccz " in operation: - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no.insert(0, "CCZ") - elif " rx " in operation: - theta = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no[0:0] = ["RX", theta] - elif "^ry " in operation: - theta = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no[0:0] = ["RY", theta] - elif "^rz " in operation: - theta = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no[0:0] = ["RZ", theta] - elif "^rzz " in operation: - theta = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = re.findall(r"\d+", operation.split(" ")[1]) - qbit_no = [int(x) for x in qbit_no] - qbit_no[0:0] = ["RZZ", theta] - elif "^u1 " in operation: - lambda_ = float( - ".".join(re.findall( - r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0])) - ) - qbit_no = [int(re.findall(r"\d+", operation)[0])] - qbit_no[0:0] = ["U1", lambda_] - elif "^u2 " in operation: - angles = re.findall(r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0]) - phi = float(".".join(angles[0:2])) - lambda_ = float(".".join(angles[2:])) - qbit_no = int(re.findall(r"\d+", operation)[0]) - qbit_no[0:0] = ["U2", phi, lambda_] # pylint: disable=E1137 - elif "^u3 " in operation: - angles = re.findall(r"\b\d+(?:[Ee][+-]?\d+)?", operation.split(" ")[0]) - theta = float(".".join(angles[0:2])) - phi = float(".".join(angles[2:4])) - lambda_ = float(".".join(angles[4:])) - qbit_no = int(re.findall(r"\d+", operation)[0]) - qbit_no[0:0] = ["U3", theta, phi, lambda_] # pylint: disable=E1137 - else: - assert "Unsupported gate" - - return qbit_no - - def get_gate_functions(qasm_str, start_idx): func_list = [] result = [] @@ -179,7 +58,8 @@ def init_state_tn(nqubits, init_state_sv, tn_lib="quimb"): if tn_lib == "quimb": init_state_MPS = qtn.tensor_1d.MatrixProductState.from_dense( - init_state_sv, dims) + init_state_sv, dims + ) else: # TODO: Add cuquantum later assert False, "Unsupported tensor network backend in initilization" @@ -187,8 +67,9 @@ def init_state_tn(nqubits, init_state_sv, tn_lib="quimb"): return init_state_MPS -def tn_circ_eval(nqubits, qasm_circ, init_state, swaps=True, tn_lib="quimb", - backend='numpy'): +def tn_circ_eval( + nqubits, qasm_circ, init_state, swaps=True, tn_lib="quimb", backend="numpy" +): if tn_lib == "quimb": circ_quimb = qasm_QFT(nqubits, qasm_circ, swaps, psi0=init_state) @@ -205,7 +86,11 @@ def eval_QI_qft(nqubits, qasm_circ, init_state, backend="numpy", swaps=True): # Quimb circuit init_state_mps = init_state_tn(nqubits=nqubits, init_state_sv=init_state) - amplitudes = tn_circ_eval(nqubits=nqubits, qasm_circ=qasm_circ, - init_state=init_state_mps, swaps=swaps, - tn_lib="quimb") + amplitudes = tn_circ_eval( + nqubits=nqubits, + qasm_circ=qasm_circ, + init_state=init_state_mps, + swaps=swaps, + tn_lib="quimb", + ) return amplitudes diff --git a/tests/test_qasm_quimb_backend.py b/tests/test_qasm_quimb_backend.py index 450104b..edb99a2 100644 --- a/tests/test_qasm_quimb_backend.py +++ b/tests/test_qasm_quimb_backend.py @@ -11,8 +11,7 @@ import config def init_state_sv(nqubits): - init_state = np.random.random(2**nqubits) + \ - 1j * np.random.random(2**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 init_state_for_tn = copy.deepcopy(init_state) @@ -33,25 +32,28 @@ def test_eval(nqubits: int): init_state_qibo, init_state_for_tn = init_state_sv(nqubits=nqubits) # Test qibo - qibo.set_backend(backend=config.qibo['backend'], - platform=config.qibo['platform']) + qibo.set_backend(backend=config.qibo["backend"], platform=config.qibo["platform"]) start_time = timer() - qibo_circ, result_sv = qibo_qft(nqubits, init_state=init_state_qibo, - swaps=config.qibo['swaps']) + qibo_circ, result_sv = qibo_qft( + nqubits, init_state=init_state_qibo, swaps=config.qibo["swaps"] + ) end_time = timer() qibo_time = end_time - start_time # 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=init_state_for_tn, - backend=config.quimb['backend'], - swaps=config.quimb['swaps']) + result_tn = qasm_quimb.eval_QI_qft( + nqubits=nqubits, + qasm_circ=qasm_circ, + init_state=init_state_for_tn, + backend=config.quimb["backend"], + swaps=config.quimb["swaps"], + ) end_time = timer() quimb_time = end_time - start_time - assert np.allclose(result_sv, result_tn), \ - "Resulting dense vectors do not match" + assert np.allclose(result_sv, result_tn), "Resulting dense vectors do not match" From 250c41bf4dbe72508ec32eafe2cd231942188d8c Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 12:37:50 +0100 Subject: [PATCH 2/6] Start reworking qasm parser --- src/qibotn/{qasm_quimb.py => quimb.py} | 48 +++++++------------------- tests/test_qasm_quimb_backend.py | 11 +++--- 2 files changed, 17 insertions(+), 42 deletions(-) rename src/qibotn/{qasm_quimb.py => quimb.py} (55%) diff --git a/src/qibotn/qasm_quimb.py b/src/qibotn/quimb.py similarity index 55% rename from src/qibotn/qasm_quimb.py rename to src/qibotn/quimb.py index f7546eb..93457f4 100644 --- a/src/qibotn/qasm_quimb.py +++ b/src/qibotn/quimb.py @@ -1,6 +1,6 @@ import re -import quimb as qu +import qibo 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 qasm_QFT(nqubits: int, qasm_str: str, with_swaps: bool = True, psi0=None): +def convert(nqubits: int, qasm_str: str, with_swaps: bool = True, psi0=None): circ = qtn.Circuit(nqubits, psi0=psi0) qasm_str = qasm_str.split("\n") @@ -53,44 +53,22 @@ def qasm_QFT(nqubits: int, qasm_str: str, with_swaps: bool = True, psi0=None): return circ -def init_state_tn(nqubits, init_state_sv, tn_lib="quimb"): +def init_state_tn(nqubits, init_state_sv): dims = tuple(2 * np.ones(nqubits, dtype=int)) - if tn_lib == "quimb": - init_state_MPS = qtn.tensor_1d.MatrixProductState.from_dense( - init_state_sv, dims - ) - else: - # TODO: Add cuquantum later - assert False, "Unsupported tensor network backend in initilization" - - return init_state_MPS + return qtn.tensor_1d.MatrixProductState.from_dense(init_state_sv, dims) -def tn_circ_eval( - nqubits, qasm_circ, init_state, swaps=True, tn_lib="quimb", backend="numpy" -): - if tn_lib == "quimb": +def eval(qasm: str, init_state, backend="numpy", swaps=True): + """Evaluate QASM with Quimb - circ_quimb = qasm_QFT(nqubits, qasm_circ, swaps, psi0=init_state) - interim = circ_quimb.psi.full_simplify(seq="DRC") - result = interim.to_dense(backend=backend).flatten() - return result - else: - # TODO: Change assert or value. Add cuquantum later - assert False, "Unsupported tensor network library" + backend (quimb): numpy, cupy, jax. Passed to ``opt_einsum``. + """ + circuit = qibo.models.Circuit.from_qasm(qasm) + init_state_mps = init_state_tn(circuit.nqubits, init_state) + circ_quimb = convert(circuit, swaps=swaps, psi0=init_state_mps) + interim = circ_quimb.psi.full_simplify(seq="DRC") + amplitudes = interim.to_dense(backend=backend).flatten() -def eval_QI_qft(nqubits, qasm_circ, init_state, backend="numpy", swaps=True): - # backend (quimb): numpy, cupy, jax. Passed to ``opt_einsum``. - - # Quimb circuit - init_state_mps = init_state_tn(nqubits=nqubits, init_state_sv=init_state) - amplitudes = tn_circ_eval( - nqubits=nqubits, - qasm_circ=qasm_circ, - init_state=init_state_mps, - swaps=swaps, - tn_lib="quimb", - ) return amplitudes diff --git a/tests/test_qasm_quimb_backend.py b/tests/test_qasm_quimb_backend.py index edb99a2..9f4c854 100644 --- a/tests/test_qasm_quimb_backend.py +++ b/tests/test_qasm_quimb_backend.py @@ -14,8 +14,7 @@ def init_state_sv(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 - init_state_for_tn = copy.deepcopy(init_state) - return init_state, init_state_for_tn + return init_state def qibo_qft(nqubits, init_state, swaps): @@ -29,14 +28,12 @@ def test_eval(nqubits: int): os.environ["QUIMB_NUM_PROCS"] = str(os.cpu_count()) from qibotn import qasm_quimb - init_state_qibo, init_state_for_tn = init_state_sv(nqubits=nqubits) + init_state = init_state_sv(nqubits=nqubits) # 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=init_state_qibo, swaps=config.qibo["swaps"] - ) + qibo_circ, result_sv = qibo_qft(nqubits, init_state, swaps=config.qibo["swaps"]) end_time = timer() qibo_time = end_time - start_time @@ -49,7 +46,7 @@ def test_eval(nqubits: int): result_tn = qasm_quimb.eval_QI_qft( nqubits=nqubits, qasm_circ=qasm_circ, - init_state=init_state_for_tn, + init_state=copy.deepcopy(init_state), backend=config.quimb["backend"], swaps=config.quimb["swaps"], ) From bdecea17edd18905600a8bb8db90c2c8a6368054 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 13:13:10 +0100 Subject: [PATCH 3/6] Clean up tests --- src/qibotn/quimb.py | 8 +++--- tests/config.py | 21 ++++++++------- tests/test_qasm_quimb_backend.py | 46 +++++++++++++++++++------------- 3 files changed, 43 insertions(+), 32 deletions(-) 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" From 458ad3cfc53817e37b5c57232342d982cd9fedfe Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 13:34:32 +0100 Subject: [PATCH 4/6] Add pre-commit --- .pre-commit-config.yaml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..177c408 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,25 @@ +# See https://pre-commit.com for more information +# See https://pre-commit.com/hooks.html for more hooks +repos: + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v4.4.0 + hooks: + - id: trailing-whitespace + - id: end-of-file-fixer + - id: check-yaml + - id: check-toml + - id: check-merge-conflict + - id: debug-statements + - repo: https://github.com/psf/black + rev: 23.1.0 + hooks: + - id: black + - repo: https://github.com/pycqa/isort + rev: 5.12.0 + hooks: + - id: isort + args: ["--profile", "black"] + - repo: https://github.com/asottile/pyupgrade + rev: v3.3.1 + hooks: + - id: pyupgrade From 0af53d1ab0ad4256c73fedfd551ef02577ccced5 Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 13:35:00 +0100 Subject: [PATCH 5/6] Drop gate definition parser --- src/qibotn/quimb.py | 56 ++++++++------------------------------------- 1 file changed, 10 insertions(+), 46 deletions(-) diff --git a/src/qibotn/quimb.py b/src/qibotn/quimb.py index 4f7244f..46a527c 100644 --- a/src/qibotn/quimb.py +++ b/src/qibotn/quimb.py @@ -1,56 +1,20 @@ -import re - -from qibo.models import Circuit as QiboCircuit -import quimb.tensor as qtn import numpy as np +import quimb.tensor as qtn +from qibo.models import Circuit as QiboCircuit -def get_gate_functions(qasm_str, start_idx): - func_list = [] - result = [] - idx_inc = 0 - for line in qasm_str[start_idx:]: - if "gate " in line: - result = re.findall("[^,\s()]+", line) - elif result and "{" not in line and "}" not in line: - params = get_gate_params(line) - func_list.append(*params) - elif "}" in line: - print("Returning the list") - print(func_list) - return func_list, idx_inc - idx_inc += 1 +def from_qibo(circuit: QiboCircuit, swaps: bool = True, psi0=None): + nqubits = circuit.nqubits + tncirc = qtn.Circuit(nqubits, psi0=psi0) + for gate in circuit.queue: + tncirc.apply_gate(gate.name) -def from_qibo(circuit: QiboCircuit, with_swaps: bool = True, psi0=None): - circ = qtn.Circuit(nqubits, psi0=psi0) - - qasm_str = qasm_str.split("\n") - for idx, line in enumerate(qasm_str): - command = line.split(" ")[0] - if re.search("include|//|OPENQASM", command): - continue - elif "qreg" in command: - nbits = int(re.findall(r"\d+", line)[0]) - assert nbits == nqubits - elif "swap" in command: - break - elif "gate" in command: # TODO: Complete gate handling - gate_func, increment = get_gate_functions(qasm_str, idx) - pass - elif "barrier" in command: # TODO: Complete barrier handling - pass - elif "measure" in command: # TODO: Complete measure handling - pass - else: - params = get_gate_params(line) - circ.apply_gate(*params) - - if with_swaps: + if swaps: for i in range(nqubits // 2): # TODO: Ignore the barrier indices? - circ.apply_gate("SWAP", i, nqubits - i - 1) + tncirc.apply_gate("SWAP", i, nqubits - i - 1) - return circ + return tncirc def init_state_tn(nqubits, init_state_sv): From 662adfe1585c7eebede9006a76dfd379ff13734c Mon Sep 17 00:00:00 2001 From: Alessandro Candido Date: Wed, 15 Feb 2023 16:36:42 +0100 Subject: [PATCH 6/6] Drop circuit-specific dedicated handling for swaps --- src/qibotn/quimb.py | 17 +++++++++-------- tests/config.py | 1 - tests/test_qasm_quimb_backend.py | 18 +++++++----------- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/qibotn/quimb.py b/src/qibotn/quimb.py index 46a527c..8414540 100644 --- a/src/qibotn/quimb.py +++ b/src/qibotn/quimb.py @@ -3,16 +3,17 @@ import quimb.tensor as qtn from qibo.models import Circuit as QiboCircuit -def from_qibo(circuit: QiboCircuit, swaps: bool = True, psi0=None): +def from_qibo(circuit: QiboCircuit, psi0=None): nqubits = circuit.nqubits tncirc = qtn.Circuit(nqubits, psi0=psi0) for gate in circuit.queue: - tncirc.apply_gate(gate.name) - - if swaps: - for i in range(nqubits // 2): # TODO: Ignore the barrier indices? - tncirc.apply_gate("SWAP", i, nqubits - i - 1) + tncirc.apply_gate( + gate.name, + *gate.parameters, + *gate.qubits, + parametrize=len(gate.parameters) > 0 + ) return tncirc @@ -23,7 +24,7 @@ def init_state_tn(nqubits, init_state_sv): return qtn.tensor_1d.MatrixProductState.from_dense(init_state_sv, dims) -def eval(qasm: str, init_state, backend="numpy", swaps=True): +def eval(qasm: str, init_state, backend="numpy"): """Evaluate QASM with Quimb backend (quimb): numpy, cupy, jax. Passed to ``opt_einsum``. @@ -31,7 +32,7 @@ def eval(qasm: str, init_state, backend="numpy", swaps=True): """ circuit = QiboCircuit.from_qasm(qasm) init_state_mps = init_state_tn(circuit.nqubits, init_state) - circ_quimb = from_qibo(circuit, swaps=swaps, psi0=init_state_mps) + circ_quimb = from_qibo(circuit, 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 7570e30..7403673 100644 --- a/tests/config.py +++ b/tests/config.py @@ -6,7 +6,6 @@ from typing import Optional class Executor: backend: str platform: Optional[str] = None - swaps: bool = True qibo = Executor(backend="qibojit", platform="numpy") diff --git a/tests/test_qasm_quimb_backend.py b/tests/test_qasm_quimb_backend.py index db1ad27..e962018 100644 --- a/tests/test_qasm_quimb_backend.py +++ b/tests/test_qasm_quimb_backend.py @@ -1,13 +1,12 @@ -import os - -import pytest -import qibo -from qibo.models import QFT -import numpy as np import copy +import os from timeit import default_timer as timer import config +import numpy as np +import pytest +import qibo +from qibo.models import QFT def create_init_state(nqubits): @@ -44,7 +43,7 @@ def test_eval(nqubits: int): # Test qibo 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) + lambda: qibo_qft(nqubits, init_state, swaps=True) ) # Convert to qasm for other backends @@ -53,10 +52,7 @@ def test_eval(nqubits: int): # Test quimb quimb_time, result_tn = time( lambda: qibotn.quimb.eval( - qasm_circ, - init_state_tn, - backend=config.quimb.backend, - swaps=config.quimb.swaps, + qasm_circ, init_state_tn, backend=config.quimb.backend ) )