From ca0fd1fd4b9a6b9f8b04f24b9f0a4afdc22b9403 Mon Sep 17 00:00:00 2001 From: celvira <clement.elvira@centralesupelec.fr> Date: Mon, 6 Sep 2021 17:16:23 +0200 Subject: [PATCH] Adding some unit-test --- run_tests.sh | 1 + tests/__init__.py | 1 + tests/test_generalized_screening.py | 58 +++++++++++++++++ tests/test_solver.py | 42 +++++++++++++ tests/test_utils.py | 96 +++++++++++++++++++++++++++++ 5 files changed, 198 insertions(+) create mode 100755 run_tests.sh create mode 100755 tests/__init__.py create mode 100644 tests/test_generalized_screening.py create mode 100644 tests/test_solver.py create mode 100644 tests/test_utils.py diff --git a/run_tests.sh b/run_tests.sh new file mode 100755 index 0000000..ebc4a76 --- /dev/null +++ b/run_tests.sh @@ -0,0 +1 @@ +python -m unittest \ No newline at end of file diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100755 index 0000000..7c68785 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +# -*- coding: utf-8 -*- \ No newline at end of file diff --git a/tests/test_generalized_screening.py b/tests/test_generalized_screening.py new file mode 100644 index 0000000..c497b08 --- /dev/null +++ b/tests/test_generalized_screening.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +import unittest +import numpy as np + +from src.dictionaries import generate_dic +from src.solver.slope import primal_func, dual_func, slope_gp +from src.solver.parameters import SlopeParameters +from src.screening.singletest import GapSphereSingleTest +from src.screening.gap_ptest import GAP_Ptest +import src.utils as utils + +class TestSolver(unittest.TestCase): + + def test_gp_cost_decrease(self): + """ Run a non accelerated proximal gradient algorithm + assess that the cost function decreaes + """ + + # 1. Create problem + m = 20 + n = 50 + matA = generate_dic("gaussian", m, n, True) + vecy = np.random.randn(m) + vec_gammas = np.linspace(.5, 1, n)[::-1] + + # 2. Compute lambda_max + lbd_max = utils.get_lambda_max(vecy, matA, vec_gammas) + lbd = .6 * lbd_max + + # 3. Eval solution of slope problem + algParameters = SlopeParameters() + algParameters.gap_stopping = 1e-12 + algParameters.max_it = 100000 + algParameters.accelerated = False + out = slope_gp(vecy, matA, .5*lbd_max, vec_gammas, algParameters) + + vecu = vecy - matA @ out["sol"] + beta_dual = np.sort(np.abs(matA.T @ vecu))[::-1] + beta_dual = np.cumsum(beta_dual) / np.cumsum(lbd * vec_gammas) + vecu /= np.max(beta_dual) + Atu = matA.T @ vecu + + pval = primal_func(vecy, matA @ out["sol"], out["sol"], lbd, vec_gammas) + dval = dual_func(vecy, np.linalg.norm(vecy, 2)**2, vecu) + gap = np.abs(pval - dval) + + # 4. Start screening test + test1 = GapSphereSingleTest() + test2 = GAP_Ptest(np.cumsum(vec_gammas)) + + out1 = test1.apply_test(Atu, gap, lbd, vec_gammas) + out2 = test2.apply_test(Atu, gap, lbd, vec_gammas) + + # 1e-15 due to machine precision error + self.assertTrue( (out2 >= out1).all() ) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_solver.py b/tests/test_solver.py new file mode 100644 index 0000000..1bea217 --- /dev/null +++ b/tests/test_solver.py @@ -0,0 +1,42 @@ +# -*- coding: utf-8 -*- +import unittest +import numpy as np + +import src.utils as utils +from src.dictionaries import generate_dic +from src.solver.slope import slope_gp +from src.solver.parameters import SlopeParameters + + +class TestSolver(unittest.TestCase): + + def test_gp_cost_decrease(self): + """ Run a non accelerated proximal gradient algorithm + assess that the cost function decreaes + """ + + # 1. Create problem + m = 20 + n = 50 + matA = generate_dic("gaussian", m, n, True) + vecy = np.random.randn(m) + vec_gammas = np.linspace(0, 1, n)[::-1] + + # 2. Compute lambda_max + lbd_max = utils.get_lambda_max(vecy, matA, vec_gammas) + + # 3. Eval solution of slope problem + algParameters = SlopeParameters() + algParameters.max_it = 1000 + algParameters.accelerated = False + out = slope_gp(vecy, matA, .5*lbd_max, vec_gammas, algParameters) + + # 4. Assert that the zero vector is solution + vec_cost = out["cost_function"] + vec_diff = (vec_cost[1:] - vec_cost[:-1]) + + # 1e-15 due to machine precision error + self.assertTrue( (vec_diff <= 1e-14).all() ) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/tests/test_utils.py b/tests/test_utils.py new file mode 100644 index 0000000..4017a3c --- /dev/null +++ b/tests/test_utils.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +import unittest +import numpy as np + +import src.utils as utils +from src.dictionaries import generate_dic +from src.solver.slope import slope_gp + +class TestUtilsModule(unittest.TestCase): + + def test_coherence(self): + """ Compute the coherence manually and compare it + to the value output by the module + """ + + # 1. Create dictionary + m = 20 + n = 50 + matA = generate_dic("gaussian", m, n, True) + + # 2. Compute coherence with module + mu = utils.compute_coherence(matA) + + # 3. Compute coherence with brute force + mu_prime = np.max(np.abs((matA.T @ matA) - np.eye(n))) + + # 4. Test + self.assertAlmostEqual(mu, mu_prime, 14) + + + def test_cound_coherence_function(self): + """ Compute the coherence manually and compare it + to the value output by the module + """ + + # 1. Create dictionary + m = 20 + n = 50 + matA = generate_dic("gaussian", m, n, True) + + # 2. Compute coherence with module + mu = utils.compute_coherence(matA) + coherence_func = utils.compute_coherence_function(matA) + + # 3. Test + self.assertAlmostEqual(mu, coherence_func[1], 14) + self.assertTrue( (coherence_func <= mu * np.arange(n)).all() ) + + + def test_coherences_pulse(self): + """ + test on analytic dictionary defined in tropp's paper "greed is good" + (unnormalzied dictionary) + """ + + # 1. Create dictionary + m = 50 + n = 30 + matA = np.zeros((m, n)) + + beta = .5 + for j in range(n): + for i in range(j, m): + matA[i, j] = np.sqrt(1 - beta**2) * beta**(i-j) + + # 2. Compute coherence with module + mu = utils.compute_coherence(matA) + mu_star = matA[:, 0] @ matA[:, 1] + + # 3. Test + self.assertAlmostEqual(mu, mu_star, 14) + + + def test_get_lambda_max(self): + """ + """ + + # 1. Create problem + m = 20 + n = 50 + matA = generate_dic("gaussian", m, n, True) + vecy = np.random.randn(m) + vec_gammas = np.linspace(0, 1, n)[::-1] + + # 2. Compute lambda_max + lbd_max = utils.get_lambda_max(vecy, matA, vec_gammas) + + # 3. Eval solution of slope problem + out = slope_gp(vecy, matA, lbd_max, vec_gammas) + + # 4. Assert that the zero vector is solution + self.assertTrue( (out["sol"] == np.zeros(n)).all() ) + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file -- GitLab