From 4ac7f0f1b6bfe4eb7e52ecc70510418b977adcde Mon Sep 17 00:00:00 2001 From: Eugene Rublenko <16805621+stand-by@users.noreply.github.com> Date: Tue, 30 Jul 2024 19:40:54 -0400 Subject: [PATCH] Tests for c++ objects against python implementations --- tests/{equivalence => approvals}/__init__.py | 0 tests/approvals/test_pauli_string.py | 69 ++++++++++++++++++++ 2 files changed, 69 insertions(+) rename tests/{equivalence => approvals}/__init__.py (100%) create mode 100644 tests/approvals/test_pauli_string.py diff --git a/tests/equivalence/__init__.py b/tests/approvals/__init__.py similarity index 100% rename from tests/equivalence/__init__.py rename to tests/approvals/__init__.py diff --git a/tests/approvals/test_pauli_string.py b/tests/approvals/test_pauli_string.py new file mode 100644 index 0000000..9564485 --- /dev/null +++ b/tests/approvals/test_pauli_string.py @@ -0,0 +1,69 @@ +"""Test pauli c++ objects against python implementations.""" + +import itertools as it + +import numpy as np +import pytest + +import fast_pauli._fast_pauli as fp +import fast_pauli.pypauli.operations as pp + + +@pytest.fixture +def sample_strings() -> list[str]: + """Provide sample strings for testing.""" + strings = it.chain( + ["I", "X", "Y", "Z"], + it.permutations("IXYZ", 2), + it.permutations("IXYZ", 3), + ["ZIZI", "YZYZ", "XYZXYZ", "ZZZIII", "XYIZXYZ", "XXIYYIZZ", "ZIXIZYXX"], + ) + return list(map("".join, strings)) + + +def test_pauli_object(paulis: dict) -> None: + """Test that C++ Pauli object is numerically equivalent to Python Pauli object.""" + # ideally, here we want to test against corresponding Pauli struct + # from python land, but currently we don't have one + for c in ["I", "X", "Y", "Z"]: + p = fp.Pauli(c) + np.testing.assert_array_equal( + np.array(p.to_tensor()), + paulis[c], + ) + np.testing.assert_string_equal(str(p), c) + + +def test_pauli_string_representations(sample_strings: list[str]) -> None: + """Test that C++ PauliString is numerically equivalent to Python PauliString.""" + for s in sample_strings: + pcpp = fp.PauliString(s) + ppy = pp.PauliString(s) + + np.testing.assert_allclose( + pcpp.to_tensor(), + ppy.dense(), + atol=1e-15, + ) + np.testing.assert_string_equal(str(pcpp), str(ppy)) + assert pcpp.dims == ppy.dim + assert pcpp.weight == ppy.weight + + +def test_pauli_string_apply_batch(sample_strings: list[str]) -> None: + """Test that C++ PauliString is numerically equivalent to Python PauliString.""" + rng = np.random.default_rng(321) + + for s in sample_strings: + n = 2 ** len(s) + psis = rng.random((n, 42)) + + np.testing.assert_allclose( + np.array(fp.PauliString(s).apply_batch(psis.tolist())), + pp.PauliString(s).multiply(psis), + atol=1e-15, + ) + + +if __name__ == "__main__": + pytest.main([__file__])