From 317162e3ef1299aa26ad2e8a14ee05ec599c3c04 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 30 Dec 2024 16:57:59 +0100 Subject: [PATCH 1/7] shadows avoid tomography comparison and combine observables for measuring only once --- .../qadence/test_measurements/test_shadows.py | 61 ++++++------------- 1 file changed, 19 insertions(+), 42 deletions(-) diff --git a/tests/qadence/test_measurements/test_shadows.py b/tests/qadence/test_measurements/test_shadows.py index 32a262008..826f00c27 100644 --- a/tests/qadence/test_measurements/test_shadows.py +++ b/tests/qadence/test_measurements/test_shadows.py @@ -2,6 +2,7 @@ import json import os +from typing import Callable import pytest import torch @@ -125,7 +126,7 @@ def test_estimations_comparison_exact( ], ) @pytest.mark.parametrize("observable", [Z(0) ^ 2, X(1)]) -def test_estimations_comparison_tomo_forward_pass( +def test_estimations_shadow_forward_pass( circuit: QuantumCircuit, values: dict, diff_mode: DiffMode, @@ -140,54 +141,30 @@ def test_estimations_comparison_tomo_forward_pass( backend=BackendName.PYQTORCH, diff_mode=DiffMode.GPSR, ) - options = {"n_shots": 100000} - estimated_exp_tomo = model.expectation( - values=values, - measurement=Measurements(protocol=Measurements.TOMOGRAPHY, options=options), - ) - new_options = {"accuracy": 0.1, "confidence": 0.1} + options = {"accuracy": 0.1, "confidence": 0.1} estimated_exp_shadow = model.expectation( values=values, - measurement=Measurements(protocol=Measurements.SHADOW, options=new_options), - ) # N = 54400. - assert torch.allclose(estimated_exp_tomo, pyq_exp_exact, atol=1.0e-2) - assert torch.allclose(estimated_exp_shadow, pyq_exp_exact, atol=0.1) + measurement=Measurements(protocol=Measurements.SHADOW, options=options), + ) assert torch.allclose(estimated_exp_shadow, pyq_exp_exact, atol=0.1) @pytest.mark.flaky(max_runs=5) -def test_chemistry_hamiltonian_1() -> None: +@pytest.mark.parametrize( + "ham_generator, tolerance", + [ + ("./tests/test_files/chem_ham.json", 0.3), + (ising_hamiltonian, 0.2), + ], +) +def test_chemistry_hamiltonian_1(ham_generator: str | Callable, tolerance: float) -> None: from qadence import load circuit = load("./tests/test_files/chem_circ.json") assert isinstance(circuit, QuantumCircuit) - hamiltonian = load("./tests/test_files/chem_ham.json") - assert isinstance(hamiltonian, AbstractBlock) - # Restrict shadow size for faster tests. - kwargs = {"accuracy": 0.1, "confidence": 0.1, "shadow_size": 1000} - param_values = {"theta_0": torch.tensor([1.0])} - - model = QuantumModel( - circuit=circuit, - observable=hamiltonian, - backend=BackendName.PYQTORCH, - diff_mode=DiffMode.GPSR, + hamiltonian = ( + load(ham_generator) if isinstance(ham_generator, str) else ham_generator(circuit.n_qubits) ) - exact = model.expectation(values=param_values) - estim = model.expectation( - values=param_values, - measurement=Measurements(protocol=Measurements.SHADOW, options=kwargs), - ) - assert torch.allclose(estim, exact, atol=0.3) - - -@pytest.mark.flaky(max_runs=5) -def test_chemistry_hamiltonian_2() -> None: - from qadence import load - - circuit = load("./tests/test_files/chem_circ.json") - assert isinstance(circuit, QuantumCircuit) - hamiltonian = ising_hamiltonian(2) assert isinstance(hamiltonian, AbstractBlock) # Restrict shadow size for faster tests. kwargs = {"accuracy": 0.1, "confidence": 0.1, "shadow_size": 1000} @@ -197,14 +174,14 @@ def test_chemistry_hamiltonian_2() -> None: circuit=circuit, observable=hamiltonian, backend=BackendName.PYQTORCH, - diff_mode=DiffMode.GPSR, + diff_mode=DiffMode.AD, ) exact = model.expectation(values=param_values) estim = model.expectation( values=param_values, measurement=Measurements(protocol=Measurements.SHADOW, options=kwargs), ) - assert torch.allclose(estim, exact, atol=0.2) + assert torch.allclose(estim, exact, atol=tolerance) def open_chem_obs() -> AbstractBlock: @@ -215,7 +192,7 @@ def open_chem_obs() -> AbstractBlock: @pytest.mark.flaky(max_runs=5) -def test_chemistry_hamiltonian_3() -> None: +def test_chemistry_hamiltonian_2() -> None: circuit = QuantumCircuit(4, kron(Z(0), H(1), Z(2), X(3))) hamiltonian = open_chem_obs() param_values: dict = dict() @@ -226,7 +203,7 @@ def test_chemistry_hamiltonian_3() -> None: circuit=circuit, observable=hamiltonian, backend=BackendName.PYQTORCH, - diff_mode=DiffMode.GPSR, + diff_mode=DiffMode.AD, ) exact = model.expectation(values=param_values) estim = model.expectation( From d8634264d2f68803f6b2dbbf8603b05ff79c2fd4 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 30 Dec 2024 17:06:51 +0100 Subject: [PATCH 2/7] combine two observables in list for chemistry ham --- .../qadence/test_measurements/test_shadows.py | 30 +++++++------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/tests/qadence/test_measurements/test_shadows.py b/tests/qadence/test_measurements/test_shadows.py index 826f00c27..88a0340bd 100644 --- a/tests/qadence/test_measurements/test_shadows.py +++ b/tests/qadence/test_measurements/test_shadows.py @@ -2,7 +2,6 @@ import json import os -from typing import Callable import pytest import torch @@ -125,14 +124,12 @@ def test_estimations_comparison_exact( (QuantumCircuit(2, blocks), values2, DiffMode.GPSR), ], ) -@pytest.mark.parametrize("observable", [Z(0) ^ 2, X(1)]) def test_estimations_shadow_forward_pass( - circuit: QuantumCircuit, - values: dict, - diff_mode: DiffMode, - observable: AbstractBlock, + circuit: QuantumCircuit, values: dict, diff_mode: DiffMode ) -> None: pyq_backend = backend_factory(BackendName.PYQTORCH, diff_mode=diff_mode) + # combine observables to avoid repeating measurements + observable = [Z(0) ^ 2, X(1)] (conv_circ, conv_obs, embed, params) = pyq_backend.convert(circuit, observable) pyq_exp_exact = pyq_backend.expectation(conv_circ, conv_obs, embed(params, values)) model = QuantumModel( @@ -150,29 +147,22 @@ def test_estimations_shadow_forward_pass( @pytest.mark.flaky(max_runs=5) -@pytest.mark.parametrize( - "ham_generator, tolerance", - [ - ("./tests/test_files/chem_ham.json", 0.3), - (ising_hamiltonian, 0.2), - ], -) -def test_chemistry_hamiltonian_1(ham_generator: str | Callable, tolerance: float) -> None: +def test_chemistry_hamiltonian_1() -> None: from qadence import load circuit = load("./tests/test_files/chem_circ.json") assert isinstance(circuit, QuantumCircuit) - hamiltonian = ( - load(ham_generator) if isinstance(ham_generator, str) else ham_generator(circuit.n_qubits) - ) - assert isinstance(hamiltonian, AbstractBlock) + # combine observables to avoid repeating measurements + hamiltonians = [load("./tests/test_files/chem_ham.json"), ising_hamiltonian(circuit.n_qubits)] + for hamiltonian in hamiltonians: + assert isinstance(hamiltonian, AbstractBlock) # Restrict shadow size for faster tests. kwargs = {"accuracy": 0.1, "confidence": 0.1, "shadow_size": 1000} param_values = {"theta_0": torch.tensor([1.0])} model = QuantumModel( circuit=circuit, - observable=hamiltonian, + observable=hamiltonians, # type: ignore[arg-type] backend=BackendName.PYQTORCH, diff_mode=DiffMode.AD, ) @@ -181,7 +171,7 @@ def test_chemistry_hamiltonian_1(ham_generator: str | Callable, tolerance: float values=param_values, measurement=Measurements(protocol=Measurements.SHADOW, options=kwargs), ) - assert torch.allclose(estim, exact, atol=tolerance) + assert torch.allclose(estim, exact, atol=0.3) def open_chem_obs() -> AbstractBlock: From 79e6f7f8b7484f4ee572e74e3191493009d95e25 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 30 Dec 2024 17:09:46 +0100 Subject: [PATCH 3/7] reduce shadow size for chem 2 test --- tests/qadence/test_measurements/test_shadows.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qadence/test_measurements/test_shadows.py b/tests/qadence/test_measurements/test_shadows.py index 88a0340bd..1d72f0292 100644 --- a/tests/qadence/test_measurements/test_shadows.py +++ b/tests/qadence/test_measurements/test_shadows.py @@ -187,7 +187,7 @@ def test_chemistry_hamiltonian_2() -> None: hamiltonian = open_chem_obs() param_values: dict = dict() - kwargs = {"accuracy": 0.1, "confidence": 0.1, "shadow_size": 5000} + kwargs = {"accuracy": 0.1, "confidence": 0.1, "shadow_size": 1000} model = QuantumModel( circuit=circuit, From 41d0be3ebfe45627aefb31556919890d2b329947 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 30 Dec 2024 18:43:56 +0100 Subject: [PATCH 4/7] disabling long tomo tests --- .../test_measurements/test_tomography.py | 32 ++++++++++--------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/tests/qadence/test_measurements/test_tomography.py b/tests/qadence/test_measurements/test_tomography.py index a30e15a70..009b4e177 100644 --- a/tests/qadence/test_measurements/test_tomography.py +++ b/tests/qadence/test_measurements/test_tomography.py @@ -457,7 +457,7 @@ def test_basic_tomography_for_parametric_circuit_forward_pass( "observable, acceptance", [ (total_magnetization(4), MIDDLE_ACCEPTANCE), - (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), + # (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy # (ising_hamiltonian(4), MIDDLE_ACCEPTANCE), ( add( @@ -482,7 +482,6 @@ def test_forward_and_backward_passes_with_qnn(observable: AbstractBlock, accepta batch_size = 5 kwargs = {"n_shots": 1000000} - # fm = fourier_feature_map(n_qubits) fm = feature_map(n_qubits, fm_type=BasisSet.CHEBYSHEV) ansatz = hea(n_qubits, depth=2) circuit = QuantumCircuit(n_qubits, fm, ansatz) @@ -571,12 +570,13 @@ def test_partial_derivatives_with_qnn(observable: AbstractBlock, acceptance: flo ones_like(dexpval_tomo_phi), create_graph=True, )[0] - d2expval_tomo_phi2theta = autograd.grad( - d2expval_tomo_phi2, - list(params.values()), - ones_like(d2expval_tomo_phi2), - create_graph=True, - )[0] + ##### this derivative is very long, disabling for CI + # d2expval_tomo_phi2theta = autograd.grad( + # d2expval_tomo_phi2, + # list(params.values()), + # ones_like(d2expval_tomo_phi2), + # create_graph=True, + # )[0] expectation_exact = model_with_psr.expectation(values=values) dexpval_exact_phi = autograd.grad( expectation_exact, @@ -590,6 +590,7 @@ def test_partial_derivatives_with_qnn(observable: AbstractBlock, acceptance: flo ones_like(expectation_exact), create_graph=True, )[0] + dexpval_exact_phitheta = autograd.grad( dexpval_exact_phi, list(params.values()), @@ -602,18 +603,19 @@ def test_partial_derivatives_with_qnn(observable: AbstractBlock, acceptance: flo ones_like(dexpval_exact_phi), create_graph=True, )[0] - d2expval_exact_phi2theta = autograd.grad( - d2expval_exact_phi2, - list(params.values()), - ones_like(d2expval_exact_phi2), - create_graph=True, - )[0] + ##### this derivative is very long, disabling for CI + # d2expval_exact_phi2theta = autograd.grad( + # d2expval_exact_phi2, + # list(params.values()), + # ones_like(d2expval_exact_phi2), + # create_graph=True, + # )[0] assert allclose(expectation_tomo, expectation_exact, atol=acceptance) assert allclose(dexpval_tomo_phi, dexpval_exact_phi, atol=acceptance) assert allclose(dexpval_tomo_theta, dexpval_exact_theta, atol=acceptance) assert allclose(dexpval_tomo_phitheta, dexpval_exact_phitheta, atol=acceptance) assert allclose(d2expval_tomo_phi2, d2expval_exact_phi2, atol=HIGH_ACCEPTANCE) - assert allclose(d2expval_tomo_phi2theta, d2expval_exact_phi2theta, atol=HIGH_ACCEPTANCE) + # assert allclose(d2expval_tomo_phi2theta, d2expval_exact_phi2theta, atol=HIGH_ACCEPTANCE) @pytest.mark.skip( From b52136e591a558cc4288c47c9c3feef49330b10e Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 6 Jan 2025 13:50:09 +0100 Subject: [PATCH 5/7] reduce zz_hamiltonian to 3 qubits --- tests/qadence/test_measurements/test_tomography.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qadence/test_measurements/test_tomography.py b/tests/qadence/test_measurements/test_tomography.py index 009b4e177..af395d81e 100644 --- a/tests/qadence/test_measurements/test_tomography.py +++ b/tests/qadence/test_measurements/test_tomography.py @@ -457,7 +457,7 @@ def test_basic_tomography_for_parametric_circuit_forward_pass( "observable, acceptance", [ (total_magnetization(4), MIDDLE_ACCEPTANCE), - # (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy + (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy # (ising_hamiltonian(4), MIDDLE_ACCEPTANCE), ( add( From 22d12d65aa5d0aba3568d3de27582ba4c917f6c9 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 6 Jan 2025 13:52:18 +0100 Subject: [PATCH 6/7] fix lint --- tests/qadence/test_measurements/test_tomography.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qadence/test_measurements/test_tomography.py b/tests/qadence/test_measurements/test_tomography.py index af395d81e..3d4de613b 100644 --- a/tests/qadence/test_measurements/test_tomography.py +++ b/tests/qadence/test_measurements/test_tomography.py @@ -457,7 +457,7 @@ def test_basic_tomography_for_parametric_circuit_forward_pass( "observable, acceptance", [ (total_magnetization(4), MIDDLE_ACCEPTANCE), - (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy + (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy # (ising_hamiltonian(4), MIDDLE_ACCEPTANCE), ( add( From 27d31bb235a8b5a6b02ec6c6389377fc33b10cd2 Mon Sep 17 00:00:00 2001 From: Charles MOUSSA Date: Mon, 6 Jan 2025 14:30:10 +0100 Subject: [PATCH 7/7] comment zz hamiltonian as it requires 1 min --- tests/qadence/test_measurements/test_tomography.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/qadence/test_measurements/test_tomography.py b/tests/qadence/test_measurements/test_tomography.py index 3d4de613b..0ed185f7c 100644 --- a/tests/qadence/test_measurements/test_tomography.py +++ b/tests/qadence/test_measurements/test_tomography.py @@ -457,7 +457,7 @@ def test_basic_tomography_for_parametric_circuit_forward_pass( "observable, acceptance", [ (total_magnetization(4), MIDDLE_ACCEPTANCE), - (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy + # (zz_hamiltonian(4), MIDDLE_ACCEPTANCE), # skiping zz as it is very heavy # (ising_hamiltonian(4), MIDDLE_ACCEPTANCE), ( add(