Rewrite test functions into higher level

This commit is contained in:
tankya2
2025-08-22 15:42:04 +08:00
parent 410a742cc3
commit 77c9cd9cd6

View File

@@ -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)