diff --git a/openjij/main.cpp b/openjij/main.cpp index e90435fc9..07c809edd 100644 --- a/openjij/main.cpp +++ b/openjij/main.cpp @@ -126,15 +126,21 @@ PYBIND11_MODULE(cxxjij, m){ py::class_(m_method, "ClassicalIsing") .def(py::init&>(), "other"_a) .def(py::init&>(), "other"_a) + .def(py::init&, graph::Spins&>(), "other"_a, "init_state"_a) .def("simulated_annealing", &method::ClassicalIsing::simulated_annealing, "beta_min"_a, "beta_max"_a, "step_length"_a, "step_num"_a, "algo"_a="") - .def("get_spins", &method::ClassicalIsing::get_spins); + .def("get_spins", &method::ClassicalIsing::get_spins) + .def("initialize_spins", &method::ClassicalIsing::initialize_spins) + .def("set_spins", &method::ClassicalIsing::set_spins, "initial_state"_a); //QuantumIsing py::class_(m_method, "QuantumIsing") .def(py::init&, size_t>(), "other"_a, "num_trotter_slices"_a) .def(py::init&, size_t>(), "other"_a, "num_trotter_slices"_a) + .def(py::init&, size_t, graph::Spins&>(), "other"_a, "num_trotter_slices"_a, "init_state"_a) .def("simulated_quantum_annealing", &method::QuantumIsing::simulated_quantum_annealing, "beta"_a, "gamma_min"_a, "gamma_max"_a, "step_length"_a, "step_num"_a, "algo"_a="") - .def("get_spins", &method::QuantumIsing::get_spins); + .def("get_spins", &method::QuantumIsing::get_spins) + .def("initialize_spins", &method::QuantumIsing::initialize_spins) + .def("set_spins", &method::QuantumIsing::set_spins, "initial_state"_a); #ifdef USE_CUDA py::class_(m_method, "ChimeraGPUQuantum") diff --git a/src/method/classical_ising.cpp b/src/method/classical_ising.cpp index 604f667eb..3eac8fc59 100644 --- a/src/method/classical_ising.cpp +++ b/src/method/classical_ising.cpp @@ -14,6 +14,21 @@ namespace openjij { uid = std::uniform_int_distribution<>{0,(int)spins.size()-1}; } + ClassicalIsing::ClassicalIsing(const graph::Dense& interaction, graph::Spins& spins) + : spins(spins), interaction(interaction), urd{0.0, 1.0}{ + //random number generator + std::random_device rd; + mt = std::mt19937(rd()); + uid = std::uniform_int_distribution<>{0,(int)spins.size()-1}; + } + + void ClassicalIsing::initialize_spins(){ + spins = interaction.gen_spin(); + } + void ClassicalIsing::set_spins(graph::Spins& initial_spins){ + spins = initial_spins; + } + double ClassicalIsing::update(double beta, const std::string& algo){ double totaldE = 0; size_t num_spins = spins.size(); diff --git a/src/method/classical_ising.h b/src/method/classical_ising.h index ffd685feb..40360dd24 100644 --- a/src/method/classical_ising.h +++ b/src/method/classical_ising.h @@ -21,6 +21,10 @@ namespace openjij { public: ClassicalIsing(const graph::Dense& interaction); + ClassicalIsing(const graph::Dense& interaction, graph::Spins& spins); + + void initialize_spins(); + void set_spins(graph::Spins& initial_spins); virtual double update(double beta, const std::string& algo = "") override; diff --git a/src/method/quantum_ising.cpp b/src/method/quantum_ising.cpp index 614371650..9f43025a4 100644 --- a/src/method/quantum_ising.cpp +++ b/src/method/quantum_ising.cpp @@ -12,6 +12,35 @@ namespace openjij { return (a+spins.size())%spins.size(); } + void QuantumIsing::initialize_spins(){ + for (auto& elem : spins){ + elem = interaction.gen_spin(); + } + } + + void QuantumIsing::set_spins(graph::Spins& initial_spin){ + if(spins[0].size() != initial_spin.size()){ + throw "Exception : spin size not match."; + } + for (auto& elem : spins){ + elem = initial_spin; + } + } + + QuantumIsing::QuantumIsing(const graph::Dense& interaction, size_t num_trotter_slices, graph::Spins& classical_spins) + :spins(num_trotter_slices), interaction(interaction), urd{0.0, 1.0}{ + for(auto& elem : spins){ + elem = classical_spins; + + //random number generators + std::random_device rd; + mt = std::mt19937(rd()); + uid = std::uniform_int_distribution<>{0, (int)elem.size()-1}; + uid_trotter = std::uniform_int_distribution<>{0, (int)num_trotter_slices-1}; + } + assert(spins.size() != 0 and spins[0].size() != 0); + } + QuantumIsing::QuantumIsing(const graph::Dense& interaction, size_t num_trotter_slices) :spins(num_trotter_slices), interaction(interaction), urd{0.0, 1.0}{ //TODO: add exception diff --git a/src/method/quantum_ising.h b/src/method/quantum_ising.h index 296fe5148..9f18a155f 100644 --- a/src/method/quantum_ising.h +++ b/src/method/quantum_ising.h @@ -27,6 +27,10 @@ namespace openjij { public: QuantumIsing(const graph::Dense& interaction, size_t num_trotter_slices); + QuantumIsing(const graph::Dense& interaction, size_t num_trotter_slices, graph::Spins& classical_spins); + + void initialize_spins(); + void set_spins(graph::Spins& initial_spin); virtual double update(double beta, double gamma, const std::string& algo = "") override; diff --git a/tests/cxxtest.cpp b/tests/cxxtest.cpp index 5cb1b00be..cd18009d8 100644 --- a/tests/cxxtest.cpp +++ b/tests/cxxtest.cpp @@ -43,24 +43,58 @@ TEST(OpenJijTest, spin_matrix){ // EXPECT_ANY_THROW({int_mat(4, 0) = 1.0;}); } -// TEST(OpenJijTest, energy){ -// int N = 3; -// openjij::Spins spins(N, 1); -// openjij::SquareMatrix int_mat{N, 0.0}; -// // H = -s0 * s1 - s1 * s2 - s0 - s2 -// int_mat(0, 0) = -1.0; -// int_mat(0, 1) = -1.0; -// int_mat(1, 0) = -1.0; -// int_mat(1, 2) = -1.0; -// int_mat(2, 1) = -1.0; -// int_mat(2, 2) = -1.0; - -// openjij::sampler::Sampler samp(int_mat); -// double energy = samp.calc_energy(spins); -// ASSERT_EQ(energy, -4.0); +TEST(OpenJijTest, classicalIsing_initialize){ + size_t N=10; + openjij::graph::Dense dense(N); + openjij::method::ClassicalIsing cising(dense); + openjij::graph::Spins spins = cising.get_spins(); + + cising.initialize_spins(); + + openjij::graph::Spins new_spins = cising.get_spins(); + + EXPECT_NE(spins, new_spins); + + // input initial state + openjij::graph::Spins init_spins(N, 1); + openjij::method::ClassicalIsing input_cising(dense, init_spins); + spins = input_cising.get_spins(); + EXPECT_EQ(init_spins, spins); +} + +TEST(OpenJijTest, quantumIsing_initialize){ + size_t N=10; + size_t trotter = 5; + openjij::graph::Dense dense(N); + openjij::method::QuantumIsing qising(dense, trotter); + openjij::method::TrotterSpins spins = qising.get_spins(); + + qising.initialize_spins(); + + openjij::method::TrotterSpins new_spins = qising.get_spins(); + + for(int i=0; i < spins.size(); i++){ + EXPECT_NE(spins[i], new_spins[i]); + } + + // input initial state + openjij::graph::Spins init_classical_spins(N, 1); + openjij::method::QuantumIsing input_qising(dense, trotter, init_classical_spins); + spins = input_qising.get_spins(); + for(openjij::graph::Spins c_spin : spins){ + EXPECT_EQ(init_classical_spins, c_spin); + } + + openjij::graph::Spins c_spin(N, 1); + qising.set_spins(c_spin); + for(openjij::graph::Spins cc_spins : qising.get_spins()){ + EXPECT_EQ(cc_spins, c_spin); + } + + openjij::graph::Spins small_state(5, 1); + ASSERT_ANY_THROW(qising.set_spins(small_state)); +} -// } -// //--------------------------------------------- // // ---------- Updater Test ------------------------- // class UpdaterTest: public ::testing::Test{ diff --git a/tests/test.py b/tests/test.py index 98d345cd5..ff9f52f59 100644 --- a/tests/test.py +++ b/tests/test.py @@ -2,6 +2,7 @@ import numpy as np import openjij as oj +import cxxjij as cj # class UtilsTest(unittest.TestCase): @@ -85,6 +86,24 @@ def test_gpu_sqa(self): chimera = gpu_sampler._chimera_graph(model, chimera_L=10) +class CXXTest(unittest.TestCase): + def test_system(self): + N = 10 + graph = cj.graph.Dense(N) + q_ising = cj.method.QuantumIsing(graph, 3) + spins = q_ising.get_spins() + q_ising.initialize_spins() + new_spins = q_ising.get_spins() + for spin, n_spin in zip(spins, new_spins): + not_eq = spins == new_spins + self.assertFalse(not_eq) + + initial_state = [1] * N + q_ising.set_spins(initial_state) + for spin in q_ising.get_spins(): + self.assertEqual(initial_state, spin) + + if __name__ == '__main__': # test is currently disabled. TODO: write test! unittest.main()