From 39adc5c55f042e7f817cf41d903ffe2b0df31859 Mon Sep 17 00:00:00 2001 From: kenya-sk <30319295+kenya-sk@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:18:07 +0900 Subject: [PATCH] (add): test for feature map (#130) --- tests/feature_maps/pennylane/test_ising.py | 83 +++++++++++++++++++ tests/feature_maps/pennylane/test_npqc.py | 43 ++++++++++ tests/feature_maps/pennylane/test_rotation.py | 78 +++++++++++++++++ tests/feature_maps/pennylane/test_yzcx.py | 40 +++++++++ 4 files changed, 244 insertions(+) create mode 100644 tests/feature_maps/pennylane/test_ising.py create mode 100644 tests/feature_maps/pennylane/test_npqc.py create mode 100644 tests/feature_maps/pennylane/test_rotation.py create mode 100644 tests/feature_maps/pennylane/test_yzcx.py diff --git a/tests/feature_maps/pennylane/test_ising.py b/tests/feature_maps/pennylane/test_ising.py new file mode 100644 index 00000000..447eaa98 --- /dev/null +++ b/tests/feature_maps/pennylane/test_ising.py @@ -0,0 +1,83 @@ +import numpy as np +import pennylane as qml +import pytest +from pennylane.measurements import StateMP + +from qxmt.feature_maps.pennylane.ising import XXFeatureMap, YYFeatureMap, ZZFeatureMap + +N_QUBITS = 2 + + +class TestIsingFeatureMap: + @pytest.fixture(scope="function") + def xx_feature_map(self) -> XXFeatureMap: + # create XX Feature Map instance + feature_map = XXFeatureMap(n_qubits=N_QUBITS, reps=2) + return feature_map + + @pytest.fixture(scope="function") + def yy_feature_map(self) -> YYFeatureMap: + # create YY Feature Map instance + feature_map = YYFeatureMap(n_qubits=N_QUBITS, reps=2) + return feature_map + + @pytest.fixture(scope="function") + def zz_feature_map(self) -> ZZFeatureMap: + # create ZZ Feature Map instance + feature_map = ZZFeatureMap(n_qubits=N_QUBITS, reps=2) + return feature_map + + @pytest.mark.parametrize( + "feature_map_name, expected_n_qubits, expected_reps", + [ + pytest.param("xx_feature_map", N_QUBITS, 2, id="Valid XXFeatureMap"), + pytest.param("yy_feature_map", N_QUBITS, 2, id="Valid YYFeatureMap"), + pytest.param("zz_feature_map", N_QUBITS, 2, id="Valid ZZFeatureMap"), + ], + ) + def test_init( + self, + request: pytest.FixtureRequest, + feature_map_name: str, + expected_n_qubits: int, + expected_reps: int, + ) -> None: + feature_map = request.getfixturevalue(feature_map_name) + assert feature_map.n_qubits == expected_n_qubits + assert feature_map.reps == expected_reps + + @pytest.mark.parametrize( + "feature_map_name, input_data, expected_gates", + [ + pytest.param("xx_feature_map", np.array([0.5, 0.3]), ["RX", "IsingXX"], id="Valid XXFeatureMap"), + pytest.param( + "yy_feature_map", np.array([0.5, 0.3]), ["Hadamard", "RY", "IsingYY"], id="Valid YYFeatureMap" + ), + pytest.param( + "zz_feature_map", np.array([0.5, 0.3]), ["Hadamard", "RZ", "IsingZZ"], id="Valid ZZFeatureMap" + ), + ], + ) + def test_feature_map( + self, + request: pytest.FixtureRequest, + feature_map_name: str, + input_data: np.ndarray, + expected_gates: list[str], + ) -> None: + feature_map = request.getfixturevalue(feature_map_name) + + # create a quantum device and circuit + dev = qml.device("default.qubit", wires=N_QUBITS) + + @qml.qnode(dev) + def circuit() -> StateMP: + feature_map(input_data) + return qml.state() + + circuit() + + # check if the expected gates are in the circuit + ops = [op.name for op in circuit.tape.operations] + for expected_gate in expected_gates: + assert any(expected_gate in op for op in ops) diff --git a/tests/feature_maps/pennylane/test_npqc.py b/tests/feature_maps/pennylane/test_npqc.py new file mode 100644 index 00000000..c90ab1be --- /dev/null +++ b/tests/feature_maps/pennylane/test_npqc.py @@ -0,0 +1,43 @@ +import numpy as np +import pennylane as qml +import pytest +from pennylane.measurements import StateMP + +from qxmt.feature_maps.pennylane.npqc import NPQCFeatureMap + +DEFAULT_N_QUBITS = 2 + + +class TestNPQCFeatureMap: + @pytest.fixture(scope="function") + def npqc_feature_map(self) -> NPQCFeatureMap: + # create NPQC Feature Map instance + feature_map = NPQCFeatureMap(n_qubits=DEFAULT_N_QUBITS, reps=2, c=1.0) + return feature_map + + def test_init(self, npqc_feature_map: NPQCFeatureMap) -> None: + assert npqc_feature_map.n_qubits == DEFAULT_N_QUBITS + assert npqc_feature_map.reps == 2 + assert npqc_feature_map.c == 1.0 + + def test_validation(self) -> None: + with pytest.raises(ValueError, match="NPQC feature map requires an even number of qubits. but got 3"): + NPQCFeatureMap(n_qubits=3, reps=2, c=1.0) + + def test_feature_map(self, npqc_feature_map: NPQCFeatureMap) -> None: + # create a quantum device and circuit + input_data = np.array([0.5, 0.3, 0.8, 0.2]) + dev = qml.device("default.qubit", wires=DEFAULT_N_QUBITS) + + @qml.qnode(dev) + def circuit() -> StateMP: + npqc_feature_map.feature_map(input_data) + return qml.state() + + circuit() + + # check if the expected gates are in the circuit + ops = [op.name for op in circuit.tape.operations] + expected_gates = ["RY", "RZ", "CZ"] + for expected_gate in expected_gates: + assert any(expected_gate in op for op in ops) diff --git a/tests/feature_maps/pennylane/test_rotation.py b/tests/feature_maps/pennylane/test_rotation.py new file mode 100644 index 00000000..99842419 --- /dev/null +++ b/tests/feature_maps/pennylane/test_rotation.py @@ -0,0 +1,78 @@ +import numpy as np +import pennylane as qml +import pytest +from pennylane.measurements import StateMP + +from qxmt.feature_maps.pennylane.rotation import HRotationFeatureMap, RotationFeatureMap + +N_QUBITS = 2 + + +class TestRotationFeatureMap: + @pytest.fixture(scope="function") + def rotation_feature_map(self) -> RotationFeatureMap: + feature_map = RotationFeatureMap(n_qubits=N_QUBITS, reps=1, rotation_axis=["X"]) + return feature_map + + @pytest.fixture(scope="function") + def h_rotation_feature_map(self) -> HRotationFeatureMap: + feature_map = HRotationFeatureMap(n_qubits=N_QUBITS, reps=1, rotation_axis=["X"]) + return feature_map + + @pytest.mark.parametrize( + "feature_map_name, expected_n_qubits, expected_reps, expected_rotation_axis", + [ + pytest.param("rotation_feature_map", N_QUBITS, 1, ["X"], id="Valid RotationFeatureMap"), + pytest.param("h_rotation_feature_map", N_QUBITS, 1, ["X"], id="Valid HRotationFeatureMap"), + ], + ) + def test_init( + self, + request: pytest.FixtureRequest, + feature_map_name: str, + expected_n_qubits: int, + expected_reps: int, + expected_rotation_axis: list[str], + ) -> None: + feature_map = request.getfixturevalue(feature_map_name) + assert feature_map.n_qubits == expected_n_qubits + assert feature_map.reps == expected_reps + assert feature_map.rotation_axis == expected_rotation_axis + + @pytest.mark.parametrize( + "feature_map_name, input_data, expected_gates", + [ + pytest.param( + "rotation_feature_map", np.array([0.5, 0.3]), ["AngleEmbedding"], id="Valid RotationFeatureMap" + ), + pytest.param( + "h_rotation_feature_map", + np.array([0.5, 0.3]), + ["Hadamard", "AngleEmbedding"], + id="Valid HRotationFeatureMap", + ), + ], + ) + def test_feature_map( + self, + request: pytest.FixtureRequest, + feature_map_name: str, + input_data: np.ndarray, + expected_gates: list[str], + ) -> None: + feature_map = request.getfixturevalue(feature_map_name) + + # create a quantum device and circuit + dev = qml.device("default.qubit", wires=N_QUBITS) + + @qml.qnode(dev) + def circuit() -> StateMP: + feature_map.feature_map(input_data) + return qml.state() + + circuit() + + # check if the expected gates are in the circuit + ops = [op.name for op in circuit.tape.operations] + for expected_gate in expected_gates: + assert any(expected_gate in op for op in ops) diff --git a/tests/feature_maps/pennylane/test_yzcx.py b/tests/feature_maps/pennylane/test_yzcx.py new file mode 100644 index 00000000..1adc1a4b --- /dev/null +++ b/tests/feature_maps/pennylane/test_yzcx.py @@ -0,0 +1,40 @@ +import numpy as np +import pennylane as qml +import pytest +from pennylane.measurements import StateMP + +from qxmt.feature_maps.pennylane.yzcx import YZCXFeatureMap + +N_QUBITS = 2 + + +class TestYZCXFeatureMap: + @pytest.fixture(scope="function") + def yzcx_feature_map(self) -> YZCXFeatureMap: + # create YZCX Feature Map instance + feature_map = YZCXFeatureMap(n_qubits=N_QUBITS, reps=2, c=1.0, seed=42) + return feature_map + + def test_init(self, yzcx_feature_map: YZCXFeatureMap) -> None: + assert yzcx_feature_map.n_qubits == N_QUBITS + assert yzcx_feature_map.reps == 2 + assert yzcx_feature_map.c == 1.0 + assert yzcx_feature_map.seed == 42 + + def test_feature_map(self, yzcx_feature_map: YZCXFeatureMap) -> None: + # create a quantum device and circuit + input_data = np.array([0.5, 0.3, 0.8, 0.2]) + dev = qml.device("default.qubit", wires=N_QUBITS) + + @qml.qnode(dev) + def circuit() -> StateMP: + yzcx_feature_map.feature_map(input_data) + return qml.state() + + circuit() + + # check if the expected gates are in the circuit + ops = [op.name for op in circuit.tape.operations] + expected_gates = ["RY", "RZ", "CNOT"] + for expected_gate in expected_gates: + assert any(expected_gate in op for op in ops)