Rewrite test functions into higher level
This commit is contained in:
@@ -1,11 +1,8 @@
|
|||||||
import math
|
import math
|
||||||
from timeit import default_timer as timer
|
|
||||||
|
|
||||||
import cupy as cp
|
import cupy as cp
|
||||||
import numpy as np
|
|
||||||
import pytest
|
import pytest
|
||||||
import qibo
|
import qibo
|
||||||
from qibo import Circuit, construct_backend, gates, hamiltonians
|
from qibo import construct_backend, hamiltonians
|
||||||
from qibo.models import QFT
|
from qibo.models import QFT
|
||||||
from qibo.symbols import X, Z
|
from qibo.symbols import X, Z
|
||||||
|
|
||||||
@@ -16,14 +13,6 @@ def qibo_qft(nqubits, swaps):
|
|||||||
return circ_qibo, state_vec
|
return circ_qibo, state_vec
|
||||||
|
|
||||||
|
|
||||||
def time(func):
|
|
||||||
start = timer()
|
|
||||||
res = func()
|
|
||||||
end = timer()
|
|
||||||
time = end - start
|
|
||||||
return time, res
|
|
||||||
|
|
||||||
|
|
||||||
def build_observable(nqubits):
|
def build_observable(nqubits):
|
||||||
"""Helper function to construct a target observable."""
|
"""Helper function to construct a target observable."""
|
||||||
hamiltonian_form = 0
|
hamiltonian_form = 0
|
||||||
@@ -34,35 +23,64 @@ def build_observable(nqubits):
|
|||||||
return hamiltonian, hamiltonian_form
|
return hamiltonian, hamiltonian_form
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gpu
|
def build_observable_dict(nqubits):
|
||||||
|
"""Construct a target observable as a dictionary representation.
|
||||||
|
|
||||||
|
Returns a dictionary suitable for `create_hamiltonian_from_dict`.
|
||||||
|
"""
|
||||||
|
terms = []
|
||||||
|
|
||||||
|
for i in range(nqubits):
|
||||||
|
term = {
|
||||||
|
"coefficient": 0.5,
|
||||||
|
"operators": [("X", i % nqubits), ("Z", (i + 1) % nqubits)],
|
||||||
|
}
|
||||||
|
terms.append(term)
|
||||||
|
|
||||||
|
return {"terms": terms}
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize("nqubits", [1, 2, 5, 10])
|
@pytest.mark.parametrize("nqubits", [1, 2, 5, 10])
|
||||||
def test_eval(nqubits: int, dtype="complex128"):
|
def test_eval(nqubits: int, dtype="complex128"):
|
||||||
"""Evaluate QASM with cuQuantum.
|
"""
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
nqubits (int): Total number of qubits in the system.
|
nqubits (int): Total number of qubits in the system.
|
||||||
dtype (str): The data type for precision, 'complex64' for single,
|
dtype (str): The data type for precision, 'complex64' for single,
|
||||||
'complex128' for double.
|
'complex128' for double.
|
||||||
"""
|
"""
|
||||||
import qibotn.eval
|
|
||||||
|
|
||||||
# Test qibo
|
# Test qibo
|
||||||
# qibo.set_backend(backend=config.qibo.backend, platform=config.qibo.platform)
|
|
||||||
qibo.set_backend(backend="numpy")
|
qibo.set_backend(backend="numpy")
|
||||||
qibo_time, (qibo_circ, result_sv) = time(lambda: qibo_qft(nqubits, swaps=True))
|
qibo_circ, result_sv = qibo_qft(nqubits, swaps=True)
|
||||||
result_sv_cp = cp.asarray(result_sv)
|
result_sv_cp = cp.asarray(result_sv)
|
||||||
|
|
||||||
# Test Cuquantum
|
# Test cutensornet
|
||||||
cutn_time, result_tn = time(
|
backend = construct_backend(backend="qibotn", platform="cutensornet")
|
||||||
lambda: qibotn.eval.dense_vector_tn(qibo_circ, dtype).flatten()
|
# Test 1: no computation settings specified. Use default.
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
print(
|
||||||
|
f"State vector difference: {abs(result_tn.statevector.flatten() - result_sv_cp).max():0.3e}"
|
||||||
)
|
)
|
||||||
|
assert cp.allclose(
|
||||||
|
result_sv_cp, result_tn.statevector.flatten()
|
||||||
|
), "Resulting dense vectors do not match"
|
||||||
|
|
||||||
print(f"State vector difference: {abs(result_tn - result_sv_cp).max():0.3e}")
|
# Test 2: Explicit computation settings specified (same as default).
|
||||||
|
computation_settings = {
|
||||||
assert cp.allclose(result_sv_cp, result_tn), "Resulting dense vectors do not match"
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": False,
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": False,
|
||||||
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings)
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
print(
|
||||||
|
f"State vector difference: {abs(result_tn.statevector.flatten() - result_sv_cp).max():0.3e}"
|
||||||
|
)
|
||||||
|
assert cp.allclose(
|
||||||
|
result_sv_cp, result_tn.statevector.flatten()
|
||||||
|
), "Resulting dense vectors do not match"
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gpu
|
|
||||||
@pytest.mark.parametrize("nqubits", [2, 5, 10])
|
@pytest.mark.parametrize("nqubits", [2, 5, 10])
|
||||||
def test_mps(nqubits: int, dtype="complex128"):
|
def test_mps(nqubits: int, dtype="complex128"):
|
||||||
"""Evaluate MPS with cuQuantum.
|
"""Evaluate MPS with cuQuantum.
|
||||||
@@ -72,41 +90,59 @@ def test_mps(nqubits: int, dtype="complex128"):
|
|||||||
dtype (str): The data type for precision, 'complex64' for single,
|
dtype (str): The data type for precision, 'complex64' for single,
|
||||||
'complex128' for double.
|
'complex128' for double.
|
||||||
"""
|
"""
|
||||||
import qibotn.eval
|
|
||||||
|
|
||||||
# Test qibo
|
# Test qibo
|
||||||
qibo.set_backend(backend="numpy")
|
qibo.set_backend(backend="numpy")
|
||||||
|
qibo_circ, result_sv = qibo_qft(nqubits, swaps=True)
|
||||||
qibo_time, (circ_qibo, result_sv) = time(lambda: qibo_qft(nqubits, swaps=True))
|
|
||||||
|
|
||||||
result_sv_cp = cp.asarray(result_sv)
|
result_sv_cp = cp.asarray(result_sv)
|
||||||
|
|
||||||
# Test of MPS
|
# Test cutensornet
|
||||||
gate_algo = {
|
backend = construct_backend(backend="qibotn", platform="cutensornet")
|
||||||
|
# Test 1: No MPS computation settings specified. Use default.
|
||||||
|
computation_settings_1 = {
|
||||||
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": True,
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": False,
|
||||||
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings_1)
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
print(
|
||||||
|
f"State vector difference: {abs(result_tn.statevector.flatten() - result_sv_cp).max():0.3e}"
|
||||||
|
)
|
||||||
|
assert cp.allclose(
|
||||||
|
result_tn.statevector.flatten(), result_sv_cp
|
||||||
|
), "Resulting dense vectors do not match"
|
||||||
|
|
||||||
|
# Test 2: Explicit MPS computation settings specified (same as default).
|
||||||
|
computation_settings_2 = {
|
||||||
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": {
|
||||||
"qr_method": False,
|
"qr_method": False,
|
||||||
"svd_method": {
|
"svd_method": {
|
||||||
"partition": "UV",
|
"partition": "UV",
|
||||||
"abs_cutoff": 1e-12,
|
"abs_cutoff": 1e-12,
|
||||||
},
|
},
|
||||||
|
},
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": False,
|
||||||
}
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings_2)
|
||||||
cutn_time, result_tn = time(
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
lambda: qibotn.eval.dense_vector_mps(circ_qibo, gate_algo, dtype).flatten()
|
print(
|
||||||
|
f"State vector difference: {abs(result_tn.statevector.flatten() - result_sv_cp).max():0.3e}"
|
||||||
)
|
)
|
||||||
|
assert cp.allclose(
|
||||||
print(f"State vector difference: {abs(result_tn - result_sv_cp).max():0.3e}")
|
result_tn.statevector.flatten(), result_sv_cp
|
||||||
|
), "Resulting dense vectors do not match"
|
||||||
assert cp.allclose(result_tn, result_sv_cp), "Resulting dense vectors do not match"
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.gpu
|
|
||||||
@pytest.mark.parametrize("nqubits", [2, 5, 10])
|
@pytest.mark.parametrize("nqubits", [2, 5, 10])
|
||||||
def test_expectation(nqubits: int, dtype="complex128"):
|
def test_expectation(nqubits: int, dtype="complex128"):
|
||||||
import qibotn.eval
|
|
||||||
|
|
||||||
circ_qibo, state_vec_qibo = qibo_qft(nqubits, swaps=True)
|
# Test qibo
|
||||||
|
qibo_circ, state_vec_qibo = qibo_qft(nqubits, swaps=True)
|
||||||
ham, ham_form = build_observable(nqubits)
|
ham, ham_form = build_observable(nqubits)
|
||||||
|
|
||||||
numpy_backend = construct_backend("numpy")
|
numpy_backend = construct_backend("numpy")
|
||||||
exact_expval = numpy_backend.calculate_expectation_state(
|
exact_expval = numpy_backend.calculate_expectation_state(
|
||||||
hamiltonian=ham,
|
hamiltonian=ham,
|
||||||
@@ -114,6 +150,39 @@ def test_expectation(nqubits: int, dtype="complex128"):
|
|||||||
normalize=False,
|
normalize=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
tn_expval = qibotn.eval.expectation_tn(circ_qibo, dtype, ham).flatten()
|
# Test cutensornet
|
||||||
|
backend = construct_backend(backend="qibotn", platform="cutensornet")
|
||||||
|
|
||||||
assert math.isclose(exact_expval.item(), tn_expval.real.get().item(), abs_tol=1e-7)
|
# Test 1: No Hamilitonian computation settings specified. Use default.
|
||||||
|
computation_settings_1 = {
|
||||||
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": False,
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": True,
|
||||||
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings_1)
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
assert math.isclose(exact_expval.item(), result_tn.real.get().item(), abs_tol=1e-7)
|
||||||
|
|
||||||
|
# Test 2: hamiltonians.SymbolicHamiltonian object in computation settings specified.
|
||||||
|
computation_settings_2 = {
|
||||||
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": False,
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": ham,
|
||||||
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings_2)
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
assert math.isclose(exact_expval.item(), result_tn.real.get().item(), abs_tol=1e-7)
|
||||||
|
|
||||||
|
# Test 3: Dictionary object form of hamiltonian in computation settings specified.
|
||||||
|
ham_dict = build_observable_dict(nqubits)
|
||||||
|
computation_settings_3 = {
|
||||||
|
"MPI_enabled": False,
|
||||||
|
"MPS_enabled": False,
|
||||||
|
"NCCL_enabled": False,
|
||||||
|
"expectation_enabled": ham_dict,
|
||||||
|
}
|
||||||
|
backend.configure_tn_simulation(computation_settings_3)
|
||||||
|
result_tn = backend.execute_circuit(circuit=qibo_circ)
|
||||||
|
assert math.isclose(exact_expval.item(), result_tn.real.get().item(), abs_tol=1e-7)
|
||||||
|
|||||||
Reference in New Issue
Block a user