diff --git a/sqaodpy/tests/__init__.py b/sqaodpy/tests/__init__.py index 67c46a7..3080961 100644 --- a/sqaodpy/tests/__init__.py +++ b/sqaodpy/tests/__init__.py @@ -5,3 +5,7 @@ from .test_dense_graph_bf_searcher import * from .test_dense_graph_formulas import * from .test_wrong_type import * +from .test_symmetrize import * +from .test_symmetrize_solvers import * +from .test_symmetrize_formulas import * + diff --git a/sqaodpy/tests/example_problems.py b/sqaodpy/tests/example_problems.py index 69d5222..e67e54c 100644 --- a/sqaodpy/tests/example_problems.py +++ b/sqaodpy/tests/example_problems.py @@ -27,3 +27,13 @@ def bipartite_graph_random(N0, N1, dtype = np.float64) : b1 = np.random.random((N1)) - 0.5 W = np.random.random((N1, N0)) - 0.5 return _quantize(b0, dtype), _quantize(b1, dtype), _quantize(W, dtype) + +def upper_triangular_random_matrix(N, dtype = np.float64) : + W = np.random.random((N, N)) - 0.5 + W = np.asarray(W, dtype) + return np.triu(W) + +def lower_triangular_random_matrix(N, dtype = np.float64) : + W = np.random.random((N, N)) - 0.5 + W = np.asarray(W, dtype) + return np.tril(W) diff --git a/sqaodpy/tests/test_dense_graph_annealer.py b/sqaodpy/tests/test_dense_graph_annealer.py index 7c433d5..3d31048 100644 --- a/sqaodpy/tests/test_dense_graph_annealer.py +++ b/sqaodpy/tests/test_dense_graph_annealer.py @@ -4,7 +4,7 @@ import numpy as np import sqaod as sq import sqaod.common as common -from .example_problems import * +from tests.example_problems import * from math import log from math import exp diff --git a/sqaodpy/tests/test_symmetrize.py b/sqaodpy/tests/test_symmetrize.py new file mode 100644 index 0000000..377618a --- /dev/null +++ b/sqaodpy/tests/test_symmetrize.py @@ -0,0 +1,68 @@ +import numpy as np +import sqaod as sq +from tests import example_problems +import unittest + + +class Base : + def __init__(self) : + assert False, "Not intended to be called." + + class TestSymmetrize(unittest.TestCase) : + + N = 1024 + + def test_is_triangular_triu(self) : + W = example_problems.dense_graph_random(self.N, self.dtype) + self.assertTrue(sq.common.is_triangular(np.triu(W))) + + def test_is_triangular_tril(self) : + W = example_problems.dense_graph_random(self.N, self.dtype) + self.assertTrue(sq.common.is_triangular(np.tril(W))) + + def test_is_not_triangular(self) : + W = np.ones((self.N, self.N), self.dtype) + self.assertFalse(sq.common.is_triangular(W)) + + def test_symmetrize_triu(self) : + W = example_problems.upper_triangular_random_matrix(self.N, self.dtype) + self.assertFalse(sq.common.is_symmetric(W)) + Wsym = sq.common.symmetrize(W) + self.assertTrue(sq.common.is_symmetric(Wsym)) + self.assertTrue(np.allclose(W, np.triu(Wsym))) + self.assertNotEqual(id(W), id(Wsym)) + + def test_symmetrize_tril(self) : + W = example_problems.lower_triangular_random_matrix(self.N, self.dtype) + self.assertFalse(sq.common.is_symmetric(W)) + Wsym = sq.common.symmetrize(W) + self.assertTrue(sq.common.is_symmetric(Wsym)) + self.assertTrue(np.allclose(W, np.tril(Wsym))) + self.assertNotEqual(id(W), id(Wsym)) + + def test_symmetrize_symmetric(self) : + W = example_problems.dense_graph_random(self.N, self.dtype) + self.assertTrue(sq.common.is_symmetric(W)) + Wsym = sq.common.symmetrize(W) + self.assertTrue(sq.common.is_symmetric(Wsym)) + self.assertTrue(np.allclose(W, Wsym)) + self.assertEqual(id(W), id(Wsym)) + + def test_symmetrize_invalid(self) : + W = np.asarray(np.random.random((self.N, self.N)), self.dtype) + with self.assertRaises(RuntimeError) : + sq.common.symmetrize(W) + + + +class TestSymmetrize64(Base.TestSymmetrize) : + dtype = np.float64 + +class TestSymmetrize32(Base.TestSymmetrize) : + dtype = np.float32 + + + +if __name__ == '__main__': + np.random.seed(0) + unittest.main() diff --git a/sqaodpy/tests/test_symmetrize_formulas.py b/sqaodpy/tests/test_symmetrize_formulas.py new file mode 100644 index 0000000..5bba563 --- /dev/null +++ b/sqaodpy/tests/test_symmetrize_formulas.py @@ -0,0 +1,129 @@ +import numpy as np +import sqaod as sq +from tests import example_problems +import unittest + +class Base : + def __init__(self) : + assert False, 'Namescope to hide unittest base class' + + class TestDGFormulas(unittest.TestCase) : + + def test_calculate_hamiltonian(self) : + Wsym = example_problems.dense_graph_random(self.N, self.dtype) + hsym, Jsym, csym = self.pkg.formulas.dense_graph_calculate_hamiltonian(Wsym, Wsym.dtype) + + Wu = np.triu(Wsym) + hu, Ju, cu = self.pkg.formulas.dense_graph_calculate_hamiltonian(Wu, Wu.dtype) + + self.assertTrue(np.allclose(hsym, hu)) + self.assertTrue(np.allclose(Jsym, Ju)) + self.assertTrue(np.allclose(csym, cu)) + + Wl = np.tril(Wsym) + hl, Jl, cl = self.pkg.formulas.dense_graph_calculate_hamiltonian(Wl, Wl.dtype) + + self.assertTrue(np.allclose(hsym, hl)) + self.assertTrue(np.allclose(Jsym, Jl)) + self.assertTrue(np.allclose(csym, cl)) + + + def test_calculate_E(self) : + Wsym = example_problems.dense_graph_random(self.N, self.dtype) + x = np.empty((self.N, ), dtype=np.int8) + sq.randomize_spin(x) + x = sq.bit_from_spin(x) + + Esym = self.pkg.formulas.dense_graph_calculate_E(Wsym, x, Wsym.dtype) + + Wu = np.triu(Wsym) + Eu = self.pkg.formulas.dense_graph_calculate_E(Wu, x, Wu.dtype) + self.assertTrue(np.allclose(Esym, Eu)) + + Wl = np.tril(Wsym) + El = self.pkg.formulas.dense_graph_calculate_E(Wl, x, Wl.dtype) + self.assertTrue(np.allclose(Esym, El)) + + + def test_batch_calculate_E(self) : + Wsym = example_problems.dense_graph_random(self.N, self.dtype) + x = np.empty((self.N, self.N), dtype=np.int8) + sq.randomize_spin(x) + x = sq.bit_from_spin(x) + + Esym = self.pkg.formulas.dense_graph_batch_calculate_E(Wsym, x, Wsym.dtype) + + Wu = np.triu(Wsym) + Eu = self.pkg.formulas.dense_graph_batch_calculate_E(Wu, x, Wu.dtype) + self.assertTrue(np.allclose(Esym, Eu)) + + Wl = np.tril(Wsym) + El = self.pkg.formulas.dense_graph_batch_calculate_E(Wl, x, Wl.dtype) + self.assertTrue(np.allclose(Esym, El)) + + def test_calculate_E_from_spin(self) : + Wsym = example_problems.dense_graph_random(self.N, self.dtype) + + h, Jsym, c = self.pkg.formulas.dense_graph_calculate_hamiltonian(Wsym, Wsym.dtype) + q = np.empty((self.N, ), dtype=np.int8) + sq.randomize_spin(q) + + Esym = self.pkg.formulas.dense_graph_calculate_E_from_spin(h, Jsym, c, q, Jsym.dtype) + + Ju = np.triu(Jsym) + Eu = self.pkg.formulas.dense_graph_calculate_E_from_spin(h, Ju, c, q, Ju.dtype) + self.assertTrue(np.allclose(Esym, Eu)) + + Jl = np.tril(Jsym) + El = self.pkg.formulas.dense_graph_calculate_E_from_spin(h, Jl, c, q, Jl.dtype) + self.assertTrue(np.allclose(Esym, El)) + + + def test_batch_calculate_E_from_spin(self) : + Wsym = example_problems.dense_graph_random(self.N, self.dtype) + + h, Jsym, c = self.pkg.formulas.dense_graph_calculate_hamiltonian(Wsym, Wsym.dtype) + q = np.empty((self.N, self.N), dtype=np.int8) + sq.randomize_spin(q) + + Esym = self.pkg.formulas.dense_graph_batch_calculate_E_from_spin(h, Jsym, c, q, Jsym.dtype) + + Ju = np.triu(Jsym) + Eu = self.pkg.formulas.dense_graph_batch_calculate_E_from_spin(h, Ju, c, q, Ju.dtype) + self.assertTrue(np.allclose(Esym, Eu)) + + Jl = np.tril(Jsym) + El = self.pkg.formulas.dense_graph_batch_calculate_E_from_spin(h, Jl, c, q, Jl.dtype) + self.assertTrue(np.allclose(Esym, El)) + + +class TestDGFormulasPy(Base.TestDGFormulas) : + N = 512 + dtype = np.float64 + pkg = sq.py + +class TestDGFormulasCPU64(Base.TestDGFormulas) : + N = 512 + dtype = np.float64 + pkg = sq.cpu + +class TestDGFormulasCPU32(Base.TestDGFormulas) : + N = 512 + dtype = np.float32 + pkg = sq.cpu + +if sq.is_cuda_available() : + class TestDGFormulasCUDA64(Base.TestDGFormulas) : + N = 512 + dtype = np.float64 + pkg = sq.cuda + + class TestDGFormulasCUDA32(Base.TestDGFormulas) : + N = 512 + dtype = np.float32 + pkg = sq.cuda + + +if __name__ == '__main__': + np.random.seed(0) + unittest.main() diff --git a/sqaodpy/tests/test_symmetrize_solvers.py b/sqaodpy/tests/test_symmetrize_solvers.py new file mode 100644 index 0000000..5200687 --- /dev/null +++ b/sqaodpy/tests/test_symmetrize_solvers.py @@ -0,0 +1,148 @@ +import numpy as np +import sqaod as sq +from tests import example_problems +import unittest + +class TestSymmetrizeBase : + def __init__(self) : + assert False, 'Namescope to hide unittest base class' + + + class TestDGAnnealer(unittest.TestCase) : + + def test_symmetrize_triu(self) : + sol = self.pkg.dense_graph_annealer(dtype = self.dtype) + W = example_problems.dense_graph_random(self.N, self.dtype) + sol.set_qubo(W) + h0, J0, c0 = sol.get_hamiltonian() + + Wtriu = np.triu(W) + sol.set_qubo(Wtriu) + h1, J1, c1 = sol.get_hamiltonian() + + self.assertTrue(np.allclose(J0, J1)) + + def test_symmetrize_tril(self) : + sol = self.pkg.dense_graph_annealer(dtype = self.dtype) + W = example_problems.dense_graph_random(self.N, self.dtype) + sol.set_qubo(W) + h0, J0, c0 = sol.get_hamiltonian() + + Wtril = np.tril(W) + sol.set_qubo(Wtril) + h1, J1, c1 = sol.get_hamiltonian() + + self.assertTrue(np.allclose(J0, J1)) + + def test_symmetrize_triu_hamiltonian(self) : + sol = self.pkg.dense_graph_annealer(dtype = self.dtype) + W = example_problems.dense_graph_random(self.N, self.dtype) + sol.set_qubo(W) + h0, J0, c0 = self.pkg.formulas.dense_graph_calculate_hamiltonian(W, W.dtype) + + J0u = np.triu(J0) + sol.set_hamiltonian(h0, J0u, c0) + h1, J1, c1 = sol.get_hamiltonian() + + self.assertTrue(np.allclose(J0, J1)) + + def test_symmetrize_tril_hamiltonian(self) : + sol = self.pkg.dense_graph_annealer(dtype = self.dtype) + W = example_problems.dense_graph_random(self.N, self.dtype) + sol.set_qubo(W) + h0, J0, c0 = self.pkg.formulas.dense_graph_calculate_hamiltonian(W, W.dtype) + + J0l = np.tril(J0) + sol.set_hamiltonian(h0, J0l, c0) + h1, J1, c1 = sol.get_hamiltonian() + + self.assertTrue(np.allclose(J0, J1)) + + + class Test_DGBFSearcher(unittest.TestCase) : + + def test_symmetrize_triu(self) : + sol = self.pkg.dense_graph_bf_searcher(dtype = self.dtype) + W = example_problems.dense_graph_random(self.N, self.dtype) + sol.set_qubo(W) + sol.search() + x = sol.get_x() + E = sol.get_E() + + Wu = np.triu(W) + sol.set_qubo(Wu) + sol.search() + xu = sol.get_x() + Eu = sol.get_E() + + self.assertTrue(np.allclose(E, Eu)) + self.assertTrue(np.allclose(x, xu)) + + Wl = np.tril(W) + sol.set_qubo(Wl) + sol.search() + xl = sol.get_x() + El = sol.get_E() + + self.assertTrue(np.allclose(E, El)) + self.assertTrue(np.allclose(x, xl)) + + +class TestSymmetrize_DGAnnealerPy(TestSymmetrizeBase.TestDGAnnealer) : + N = 512 + dtype = np.float64 + pkg = sq.py + +class TestSymmetrize_DGAnnealerCPU64(TestSymmetrizeBase.TestDGAnnealer) : + N = 512 + dtype = np.float64 + pkg = sq.cpu + +class TestSymmetrize_DGAnnealerCPU32(TestSymmetrizeBase.TestDGAnnealer) : + N = 512 + dtype = np.float32 + pkg = sq.cpu + +if sq.is_cuda_available() : + class TestSymmetrize_DGAnnealerCUDA64(TestSymmetrizeBase.TestDGAnnealer) : + N = 512 + dtype = np.float64 + pkg = sq.cuda + + class TestSymmetrize_DGAnnealerCUDA32(TestSymmetrizeBase.TestDGAnnealer) : + N = 512 + dtype = np.float32 + pkg = sq.cuda + + +class TestSymmetrize_DGBFSearcherPy(TestSymmetrizeBase.Test_DGBFSearcher) : + N = 8 + dtype = np.float64 + pkg = sq.py + + +class TestSymmetrize_DGBFSearcherCPU64(TestSymmetrizeBase.Test_DGBFSearcher) : + N = 16 + dtype = np.float64 + pkg = sq.cpu + +class TestSymmetrize_DGBFSearcherCPU32(TestSymmetrizeBase.Test_DGBFSearcher) : + N = 16 + dtype = np.float32 + pkg = sq.cpu + +if sq.is_cuda_available() : + class TestSymmetrize_DGBFSearcherCUDA64(TestSymmetrizeBase.Test_DGBFSearcher) : + N = 16 + dtype = np.float64 + pkg = sq.cuda + + class TestSymmetrize_DGBFSearcherCUDA32(TestSymmetrizeBase.Test_DGBFSearcher) : + N = 16 + dtype = np.float32 + pkg = sq.cuda + + +if __name__ == '__main__': + np.random.seed(0) + unittest.main()