openjij
Framework for the Ising model and QUBO.
Loading...
Searching...
No Matches
declare.hpp
Go to the documentation of this file.
1// Copyright 2023 Jij Inc.
2
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6
7// http://www.apache.org/licenses/LICENSE-2.0
8
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#pragma once
16
17#include <pybind11/pybind11.h>
18#include <pybind11/stl.h>
19#include <pybind11/functional.h>
20#include <pybind11/eigen.h>
21
22#include <pybind11_json/pybind11_json.hpp>
23
24#include <nlohmann/json.hpp>
25
27#include <openjij/graph/all.hpp>
32
33namespace py = pybind11;
34
35using namespace py::literals;
36
37namespace openjij {
38
39// NOTE: please add `py::module_local()` when defining `py::class_`
40
41// graph
42inline void declare_Graph(py::module &m) {
43 py::class_<graph::Graph>(m, "Graph", py::module_local())
44 .def(py::init<std::size_t>(), "num_spins"_a)
45 .def(
46 "gen_spin",
47 [](const graph::Graph &self, std::size_t seed) {
48 RandomEngine rng(seed);
49 return self.gen_spin(rng);
50 },
51 "seed"_a)
52 .def("gen_spin",
53 [](const graph::Graph &self) {
54 RandomEngine rng(std::random_device{}());
55 return self.gen_spin(rng);
56 })
57 .def(
58 "gen_binary",
59 [](const graph::Graph &self, std::size_t seed) {
60 RandomEngine rng(seed);
61 return self.gen_binary(rng);
62 },
63 "seed"_a)
64 .def("gen_binary",
65 [](const graph::Graph &self) {
66 RandomEngine rng(std::random_device{}());
67 return self.gen_binary(rng);
68 })
69 .def("size", &graph::Graph::size);
70}
71
72// dense
73template <typename FloatType>
74inline void declare_Dense(py::module &m, const std::string &suffix) {
75
76 using json = nlohmann::json;
77
78 auto str = std::string("Dense") + suffix;
79 py::class_<graph::Dense<FloatType>, graph::Graph>(m, str.c_str(),
80 py::module_local())
81 .def(py::init<std::size_t>(), "num_spins"_a)
82 .def(py::init([](py::object obj) {
83 return std::unique_ptr<graph::Dense<FloatType>>(
84 new graph::Dense<FloatType>(static_cast<json>(obj)));
85 }),
86 "obj"_a)
87 .def(py::init<const graph::Dense<FloatType> &>(), "other"_a)
88 .def("set_interaction_matrix",
90 .def(
91 "calc_energy",
92 [](const graph::Dense<FloatType> &self,
93 const Eigen::Matrix<FloatType, Eigen::Dynamic, 1, Eigen::ColMajor>
94 &spins) { return self.calc_energy(spins); },
95 "spins"_a)
96 .def(
97 "calc_energy",
98 [](const graph::Dense<FloatType> &self, const graph::Spins &spins) {
99 return self.calc_energy(spins);
100 },
101 "spins"_a)
102 .def(
103 "__setitem__",
105 const std::pair<std::size_t, std::size_t> &key,
106 FloatType val) { self.J(key.first, key.second) = val; },
107 "key"_a, "val"_a)
108 .def(
109 "__getitem__",
110 [](const graph::Dense<FloatType> &self,
111 const std::pair<std::size_t, std::size_t> &key) {
112 return self.J(key.first, key.second);
113 },
114 "key"_a)
115 .def(
116 "__setitem__",
117 [](graph::Dense<FloatType> &self, std::size_t key, FloatType val) {
118 self.h(key) = val;
119 },
120 "key"_a, "val"_a)
121 .def(
122 "__getitem__",
123 [](const graph::Dense<FloatType> &self, std::size_t key) {
124 return self.h(key);
125 },
126 "key"_a)
127 .def("get_interactions", &graph::Dense<FloatType>::get_interactions);
128}
129
130// sparse
131template <typename FloatType>
132inline void declare_Sparse(py::module &m, const std::string &suffix) {
133
134 using json = nlohmann::json;
135
136 auto str = std::string("Sparse") + suffix;
137 py::class_<graph::Sparse<FloatType>, graph::Graph>(m, str.c_str(),
138 py::module_local())
139 .def(py::init<std::size_t, std::size_t>(), "num_spins"_a, "num_edges"_a)
140 .def(py::init<std::size_t>(), "num_spins"_a)
141 .def(py::init([](py::object obj, std::size_t num_edges) {
142 return std::unique_ptr<graph::Sparse<FloatType>>(
143 new graph::Sparse<FloatType>(static_cast<json>(obj),
144 num_edges));
145 }),
146 "obj"_a, "num_edges"_a)
147 .def(py::init([](py::object obj) {
148 return std::unique_ptr<graph::Sparse<FloatType>>(
149 new graph::Sparse<FloatType>(static_cast<json>(obj)));
150 }),
151 "obj"_a)
152 .def(py::init<const graph::Sparse<FloatType> &>(), "other"_a)
153 .def("adj_nodes", &graph::Sparse<FloatType>::adj_nodes)
154 .def("get_num_edges", &graph::Sparse<FloatType>::get_num_edges)
155 .def(
156 "calc_energy",
157 [](const graph::Sparse<FloatType> &self,
158 const Eigen::Matrix<FloatType, Eigen::Dynamic, 1, Eigen::ColMajor>
159 &spins) { return self.calc_energy(spins); },
160 "spins"_a)
161 .def(
162 "calc_energy",
163 [](const graph::Sparse<FloatType> &self, const graph::Spins &spins) {
164 return self.calc_energy(spins);
165 },
166 "spins"_a)
167 .def(
168 "__setitem__",
170 const std::pair<std::size_t, std::size_t> &key,
171 FloatType val) { self.J(key.first, key.second) = val; },
172 "key"_a, "val"_a)
173 .def(
174 "__getitem__",
175 [](const graph::Sparse<FloatType> &self,
176 const std::pair<std::size_t, std::size_t> &key) {
177 return self.J(key.first, key.second);
178 },
179 "key"_a)
180 .def(
181 "__setitem__",
182 [](graph::Sparse<FloatType> &self, std::size_t key, FloatType val) {
183 self.h(key) = val;
184 },
185 "key"_a, "val"_a)
186 .def(
187 "__getitem__",
188 [](const graph::Sparse<FloatType> &self, std::size_t key) {
189 return self.h(key);
190 },
191 "key"_a);
192}
193
194// csr sparse
195template <typename FloatType>
196inline void declare_CSRSparse(py::module &m, const std::string &suffix) {
197
198 auto str = std::string("CSRSparse") + suffix;
199 py::class_<graph::CSRSparse<FloatType>, graph::Graph>(m, str.c_str(),
200 py::module_local())
201 .def(py::init<const Eigen::SparseMatrix<FloatType, Eigen::RowMajor> &>(), "interaction"_a)
202 .def(py::init<const graph::CSRSparse<FloatType> &>(), "other"_a)
203 .def(
204 "calc_energy",
205 [](const graph::CSRSparse<FloatType> &self,
206 const Eigen::Matrix<FloatType, Eigen::Dynamic, 1, Eigen::ColMajor>
207 &spins) { return self.calc_energy(spins); },
208 "spins"_a)
209 .def(
210 "calc_energy",
211 [](const graph::CSRSparse<FloatType> &self, const graph::Spins &spins) {
212 return self.calc_energy(spins);
213 },
214 "spins"_a)
215 .def("get_interactions", &graph::CSRSparse<FloatType>::get_interactions);
216}
217
218// Polynomial
219template <typename FloatType>
220inline void declare_Polynomial(py::module &m, const std::string &suffix) {
221
222 using json = nlohmann::json;
223 using Poly = graph::Polynomial<FloatType>;
224 auto str = std::string("Polynomial") + suffix;
225
226 py::class_<Poly, graph::Graph>(m, str.c_str(), py::module_local())
227 .def(py::init<const std::size_t>(), "num_variables"_a)
228 .def(py::init([](const py::object &obj) {
229 return std::unique_ptr<graph::Polynomial<FloatType>>(
230 new graph::Polynomial<FloatType>(static_cast<json>(obj)));
231 }),
232 "obj"_a)
233 .def("get_num_interactions", &Poly::get_num_interactions)
234 .def("calc_energy", &Poly::calc_energy, "spins"_a, "omp_flag"_a = true)
235 .def("energy", &Poly::energy, "spins"_a, "omp_flag"_a = true)
236 .def(
237 "__setitem__",
238 [](Poly &self, graph::Index key, FloatType val) {
239 self.J(key) = val;
240 },
241 "key"_a, "val"_a)
242 .def(
243 "__setitem__",
244 [](Poly &self, std::vector<graph::Index> &key, FloatType val) {
245 self.J(key) = val;
246 },
247 "key"_a, "val"_a)
248 .def(
249 "__getitem__",
250 [](const Poly &self, std::vector<graph::Index> &key) {
251 return self.J(key);
252 },
253 "key"_a)
254 .def(
255 "__getitem__",
256 [](const Poly &self, graph::Index key) { return self.J(key); },
257 "key"_a)
258 .def("get_polynomial", [](const Poly &self) {
259 py::dict py_polynomial;
260 for (std::size_t i = 0; i < self.get_keys().size(); ++i) {
261 py::tuple temp;
262 for (const auto &it : self.get_keys()[i]) {
263 temp = temp + py::make_tuple(it);
264 }
265 py_polynomial[temp] = self.get_values()[i];
266 }
267 return py_polynomial;
268 });
269}
270
271// enum class Dir
272inline void declare_Dir(py::module &m) {
273 py::enum_<graph::Dir>(m, "Dir", py::module_local())
274 .value("PLUS_R", graph::Dir::PLUS_R)
275 .value("MINUS_R", graph::Dir::MINUS_R)
276 .value("PLUS_C", graph::Dir::PLUS_C)
277 .value("MINUS_C", graph::Dir::MINUS_C);
278}
279
280// square
281template <typename FloatType>
282inline void declare_Square(py::module &m, const std::string &suffix) {
283
284 using json = nlohmann::json;
285
286 auto str = std::string("Square") + suffix;
287 py::class_<graph::Square<FloatType>, graph::Sparse<FloatType>>(
288 m, str.c_str(), py::module_local())
289 .def(py::init<std::size_t, std::size_t, FloatType>(), "num_row"_a,
290 "num_column"_a, "init_val"_a = 0)
291 .def(py::init<const graph::Square<FloatType> &>(), "other"_a)
292 .def(py::init([](py::object obj, std::size_t num_row,
293 std::size_t num_column, FloatType init_val) {
294 return std::unique_ptr<graph::Square<FloatType>>(
295 new graph::Square<FloatType>(static_cast<json>(obj), num_row,
296 num_column, init_val));
297 }),
298 "obj"_a, "num_row"_a, "num_column"_a, "init_val"_a = 0)
299 .def("to_ind", &graph::Square<FloatType>::to_ind)
300 .def("to_rc", &graph::Square<FloatType>::to_rc)
301 .def("get_num_row", &graph::Square<FloatType>::get_num_row)
302 .def("get_num_column", &graph::Square<FloatType>::get_num_column)
303 .def(
304 "__setitem__",
306 const std::tuple<std::size_t, std::size_t, graph::Dir> &key,
307 FloatType val) {
308 self.J(std::get<0>(key), std::get<1>(key), std::get<2>(key)) = val;
309 },
310 "key"_a, "val"_a)
311 .def(
312 "__getitem__",
313 [](const graph::Square<FloatType> &self,
314 const std::tuple<std::size_t, std::size_t, graph::Dir> &key) {
315 return self.J(std::get<0>(key), std::get<1>(key), std::get<2>(key));
316 },
317 "key"_a)
318 .def(
319 "__setitem__",
321 const std::pair<std::size_t, std::size_t> &key,
322 FloatType val) { self.h(key.first, key.second) = val; },
323 "key"_a, "val"_a)
324 .def(
325 "__getitem__",
326 [](const graph::Square<FloatType> &self,
327 const std::pair<std::size_t, std::size_t> &key) {
328 return self.h(key.first, key.second);
329 },
330 "key"_a);
331}
332
333// enum class ChimeraDir
334inline void declare_ChimeraDir(py::module &m) {
335 py::enum_<graph::ChimeraDir>(m, "ChimeraDir")
336 .value("PLUS_R", graph::ChimeraDir::PLUS_R)
337 .value("MINUS_R", graph::ChimeraDir::MINUS_R)
338 .value("PLUS_C", graph::ChimeraDir::PLUS_C)
339 .value("MINUS_C", graph::ChimeraDir::MINUS_C)
340 .value("IN_0or4", graph::ChimeraDir::IN_0or4)
341 .value("IN_1or5", graph::ChimeraDir::IN_1or5)
342 .value("IN_2or6", graph::ChimeraDir::IN_2or6)
343 .value("IN_3or7", graph::ChimeraDir::IN_3or7);
344}
345
346// chimera
347template <typename FloatType>
348inline void declare_Chimera(py::module &m, const std::string &suffix) {
349
350 using json = nlohmann::json;
351
352 auto str = std::string("Chimera") + suffix;
353 py::class_<graph::Chimera<FloatType>, graph::Sparse<FloatType>>(
354 m, str.c_str(), py::module_local())
355 .def(py::init<std::size_t, std::size_t, FloatType>(), "num_row"_a,
356 "num_column"_a, "init_val"_a = 0)
357 .def(py::init<const graph::Chimera<FloatType> &>(), "other"_a)
358 .def(py::init([](py::object obj, std::size_t num_row,
359 std::size_t num_column, FloatType init_val) {
360 return std::unique_ptr<graph::Chimera<FloatType>>(
361 new graph::Chimera<FloatType>(static_cast<json>(obj), num_row,
362 num_column, init_val));
363 }),
364 "obj"_a, "num_row"_a, "num_column"_a, "init_val"_a = 0)
365 .def("to_ind", &graph::Chimera<FloatType>::to_ind)
366 .def("to_rci", &graph::Chimera<FloatType>::to_rci)
367 .def("get_num_row", &graph::Chimera<FloatType>::get_num_row)
368 .def("get_num_column", &graph::Chimera<FloatType>::get_num_column)
369 .def("get_num_in_chimera", &graph::Chimera<FloatType>::get_num_in_chimera)
370 .def(
371 "__setitem__",
373 const std::tuple<std::size_t, std::size_t, std::size_t,
374 graph::ChimeraDir> &key,
375 FloatType val) {
376 self.J(std::get<0>(key), std::get<1>(key), std::get<2>(key),
377 std::get<3>(key)) = val;
378 },
379 "key"_a, "val"_a)
380 .def(
381 "__getitem__",
382 [](const graph::Chimera<FloatType> &self,
383 const std::tuple<std::size_t, std::size_t, std::size_t,
384 graph::ChimeraDir> &key) {
385 return self.J(std::get<0>(key), std::get<1>(key), std::get<2>(key),
386 std::get<3>(key));
387 },
388 "key"_a)
389 .def(
390 "__setitem__",
392 const std::tuple<std::size_t, std::size_t, std::size_t> &key,
393 FloatType val) {
394 self.h(std::get<0>(key), std::get<1>(key), std::get<2>(key)) = val;
395 },
396 "key"_a, "val"_a)
397 .def(
398 "__getitem__",
399 [](const graph::Chimera<FloatType> &self,
400 const std::tuple<std::size_t, std::size_t, std::size_t> &key) {
401 return self.h(std::get<0>(key), std::get<1>(key), std::get<2>(key));
402 },
403 "key"_a);
404}
405
406// system
407
408// ClassicalIsing
409template <typename GraphType>
410inline void declare_ClassicalIsing(py::module &m,
411 const std::string &gtype_str) {
412 // ClassicalIsing
413 using ClassicalIsing = system::ClassicalIsing<GraphType>;
414
415 auto str = std::string("ClassicalIsing") + gtype_str;
416 py::class_<ClassicalIsing>(m, str.c_str(), py::module_local())
417 .def(py::init<const graph::Spins &, const GraphType &>(), "init_spin"_a,
418 "init_interaction"_a)
419 .def(
420 "reset_spins",
421 [](ClassicalIsing &self, const graph::Spins &init_spin) {
422 self.reset_spins(init_spin);
423 },
424 "init_spin"_a)
425 .def_readwrite("spin", &ClassicalIsing::spin)
426 .def_readonly("interaction", &ClassicalIsing::interaction)
427 .def_readonly("num_spins", &ClassicalIsing::num_spins);
428
429 // make_classical_ising
430 auto mkci_str = std::string("make_classical_ising");
431 m.def(
432 mkci_str.c_str(),
433 [](const graph::Spins &init_spin, const GraphType &init_interaction) {
434 return system::make_classical_ising(init_spin, init_interaction);
435 },
436 "init_spin"_a, "init_interaction"_a);
437}
438
439// ClassicalIsingPolynomial
440template <typename GraphType>
441inline void declare_ClassicalIsingPolynomial(py::module &m,
442 const std::string &gtype_str) {
443
445 auto str = std::string("ClassicalIsing") + gtype_str;
446
447 py::class_<CIP>(m, str.c_str(), py::module_local())
448 .def(py::init<const graph::Spins &, const GraphType &,
449 const cimod::Vartype>(),
450 "init_variables"_a, "init_interaction"_a, "vartype"_a)
451 .def(py::init<const graph::Spins &, const GraphType &,
452 const std::string>(),
453 "init_variables"_a, "init_interaction"_a, "vartype"_a)
454 .def(py::init([](const graph::Spins &init_spins, const py::object &obj) {
455 return std::unique_ptr<CIP>(
456 new CIP(init_spins, static_cast<nlohmann::json>(obj)));
457 }),
458 "init_spin"_a, "obj"_a)
459 .def_readonly("variables", &CIP::variables)
460 .def_readonly("num_variables", &CIP::num_variables)
461 .def("reset_variables", &CIP::reset_variables, "init_variables"_a)
462 .def("reset_spins", &CIP::reset_variables, "init_spins"_a)
463 .def("get_values", &CIP::get_values)
464 .def("get_keys", &CIP::get_keys)
465 .def("get_adj", &CIP::get_adj)
466 .def("get_vartype_to_string", &CIP::get_vartype_string)
467 .def("get_max_effective_dE", &CIP::get_max_effective_dE)
468 .def("get_min_effective_dE", &CIP::get_min_effective_dE);
469
470 // make_classical_ising_polynomial
471 auto mkcip_str = std::string("make_classical_ising_polynomial");
472 m.def(
473 mkcip_str.c_str(),
474 [](const graph::Spins &init_spin, const GraphType &init_interaction,
475 const cimod::Vartype vartype) {
476 return system::make_classical_ising_polynomial(
477 init_spin, init_interaction, vartype);
478 },
479 "init_spin"_a, "init_interaction"_a, "vartype"_a);
480
481 // make_classical_ising_polynomial
482 m.def(
483 mkcip_str.c_str(),
484 [](const graph::Spins &init_spin, const GraphType &init_interaction,
485 const std::string vartype) {
486 return system::make_classical_ising_polynomial(
487 init_spin, init_interaction, vartype);
488 },
489 "init_spin"_a, "init_interaction"_a, "vartype"_a);
490
491 // make_classical_ising_polynomial
492 m.def(
493 mkcip_str.c_str(),
494 [](const graph::Spins &init_spin, const py::object &obj) {
495 return system::make_classical_ising_polynomial(
496 init_spin, static_cast<nlohmann::json>(obj));
497 },
498 "init_spin"_a, "obj"_a);
499}
500
501template <typename GraphType>
502inline void declare_KLocalPolynomial(py::module &m,
503 const std::string &gtype_str) {
504
506 auto str = std::string("KLocal") + gtype_str;
507
508 py::class_<KLP>(m, str.c_str(), py::module_local())
509 .def(py::init<const graph::Binaries &, const GraphType &>(),
510 "init_spin"_a, "init_interaction"_a)
511 .def(py::init(
512 [](const graph::Binaries &init_binaries, const py::object &obj) {
513 return std::unique_ptr<KLP>(
514 new KLP(init_binaries, static_cast<nlohmann::json>(obj)));
515 }),
516 "init_binaries"_a, "obj"_a)
517 .def_readonly("binaries", &KLP::binaries)
518 .def_readonly("num_binaries", &KLP::num_binaries)
519 .def_readonly("count_call_updater", &KLP::count_call_updater)
520 .def_property_readonly("num_interactions", &KLP::GetNumInteractions)
521 .def_readwrite("rate_call_k_local", &KLP::rate_call_k_local)
522 .def("reset_binaries", &KLP::reset_binaries, "init_binaries"_a)
523 .def("reset_spins", &KLP::reset_binaries, "init_spins"_a)
524 .def("reset_dE", &KLP::reset_dE)
525 .def("get_active_binaries", &KLP::get_active_binaries)
526 .def("get_max_effective_dE", &KLP::get_max_effective_dE)
527 .def("get_min_effective_dE", &KLP::get_min_effective_dE)
528 .def("get_keys", &KLP::get_keys)
529 .def("get_values", &KLP::get_values)
530 .def("get_vartype_to_string", &KLP::get_vartype_string)
531 .def("get_polynomial",
532 [](const KLP &self) {
533 py::dict py_polynomial;
534 const auto &poly_key_list = self.get_keys();
535 const auto &poly_value_list = self.get_values();
536 for (std::size_t i = 0; i < poly_key_list.size(); ++i) {
537 py::tuple tuple;
538 for (const auto &index : poly_key_list[i]) {
539 tuple = tuple + py::make_tuple(index);
540 }
541 py_polynomial[tuple] = poly_value_list[i];
542 }
543 return py_polynomial;
544 })
545 .def("get_adj", [](const KLP &self) {
546 const auto &adj = self.get_adj();
547 const auto &poly_key_list = self.get_keys();
548 const auto &poly_value_list = self.get_values();
549 py::dict py_adj;
550 for (int64_t i = 0; i < self.num_binaries; ++i) {
551 py::dict dict;
552 for (const auto &index_key : adj[i]) {
553 py::tuple tuple;
554 for (const auto &index_binary : poly_key_list[index_key]) {
555 tuple = tuple + py::make_tuple(index_binary);
556 }
557 dict[tuple] = poly_value_list[index_key];
558 }
559 py_adj[py::int_(i)] = dict;
560 }
561 return py_adj;
562 });
563
564 // make_classical_ising_polynomial
565 auto mkcip_str = std::string("make_k_local_polynomial");
566 m.def(
567 mkcip_str.c_str(),
568 [](const graph::Spins &init_spin, const GraphType &init_interaction) {
569 return system::make_k_local_polynomial(init_spin, init_interaction);
570 },
571 "init_spin"_a, "init_interaction"_a);
572
573 // make_classical_ising_polynomial
574 auto mkcip_json_str = std::string("make_k_local_polynomial");
575 m.def(
576 mkcip_json_str.c_str(),
577 [](const graph::Spins &init_spin, const py::object &obj) {
578 return system::make_k_local_polynomial(
579 init_spin, static_cast<nlohmann::json>(obj));
580 },
581 "init_spin"_a, "obj"_a);
582}
583
584// TransverseIsing
585template <typename GraphType>
586inline void declare_TransverseIsing(py::module &m,
587 const std::string &gtype_str) {
588 // TransverseIsing
589 using TransverseIsing = system::TransverseIsing<GraphType>;
590 using FloatType = typename GraphType::value_type;
591
592 auto str = std::string("TransverseIsing") + gtype_str;
593 py::class_<TransverseIsing>(m, str.c_str(), py::module_local())
594 .def(py::init<const system::TrotterSpins &, const GraphType &,
595 FloatType>(),
596 "init_spin"_a, "init_interaction"_a, "gamma"_a)
597 .def(py::init<const graph::Spins &, const GraphType &, FloatType,
598 size_t>(),
599 "init_classical_spins"_a, "init_interaction"_a, "gamma"_a,
600 "num_trotter_slices"_a)
601 .def(
602 "reset_spins",
603 [](TransverseIsing &self,
604 const system::TrotterSpins &init_trotter_spins) {
605 self.reset_spins(init_trotter_spins);
606 },
607 "init_trotter_spins"_a)
608 .def(
609 "reset_spins",
610 [](TransverseIsing &self, const graph::Spins &classical_spins) {
611 self.reset_spins(classical_spins);
612 },
613 "classical_spins"_a)
614 .def_readwrite("trotter_spins", &TransverseIsing::trotter_spins)
615 .def_readonly("interaction", &TransverseIsing::interaction)
616 .def_readonly("num_classical_spins",
617 &TransverseIsing::num_classical_spins)
618 .def_readwrite("gamma", &TransverseIsing::gamma);
619
620 // make_transverse_ising
621 auto mkci_str = std::string("make_transverse_ising");
622 m.def(
623 mkci_str.c_str(),
624 [](const system::TrotterSpins &init_trotter_spins,
625 const GraphType &init_interaction, double gamma) {
626 return system::make_transverse_ising(init_trotter_spins,
627 init_interaction, gamma);
628 },
629 "init_trotter_spins"_a, "init_interaction"_a, "gamma"_a);
630
631 m.def(
632 mkci_str.c_str(),
633 [](const graph::Spins &classical_spins, const GraphType &init_interaction,
634 double gamma, std::size_t num_trotter_slices) {
635 return system::make_transverse_ising(classical_spins, init_interaction,
636 gamma, num_trotter_slices);
637 },
638 "classical_spins"_a, "init_interaction"_a, "gamma"_a,
639 "num_trotter_slices"_a);
640}
641
642// Continuous Time Transverse Ising
643template <typename GraphType>
644inline void declare_ContinuousTimeIsing(py::module &m,
645 const std::string &gtype_str) {
646 // TransverseIsing
647 using TransverseIsing = system::ContinuousTimeIsing<GraphType>;
648 using FloatType = typename GraphType::value_type;
649 using SpinConfiguration = typename TransverseIsing::SpinConfiguration;
650
651 auto str = std::string("ContinuousTimeIsing") + gtype_str;
652 py::class_<TransverseIsing>(m, str.c_str(), py::module_local())
653 .def(py::init<const SpinConfiguration &, const GraphType &, FloatType>(),
654 "init_spin_config"_a, "init_interaction"_a, "gamma"_a)
655 .def(py::init<const graph::Spins &, const GraphType &, FloatType>(),
656 "init_spins"_a, "init_interaction"_a, "gamma"_a)
657 .def(
658 "reset_spins",
659 [](TransverseIsing &self, const SpinConfiguration &init_spin_config) {
660 self.reset_spins(init_spin_config);
661 },
662 "init_spin_config"_a)
663 .def(
664 "reset_spins",
665 [](TransverseIsing &self, const graph::Spins &classical_spins) {
666 self.reset_spins(classical_spins);
667 },
668 "classical_spins"_a)
669 .def_readwrite("spin_config", &TransverseIsing::spin_config)
670 .def_readonly("interaction", &TransverseIsing::interaction)
671 .def_readonly("num_spins", &TransverseIsing::num_spins)
672 .def_readonly("gamma", &TransverseIsing::gamma);
673
674 // make_continuous_ising
675 auto mkci_str = std::string("make_continuous_time_ising");
676 m.def(
677 mkci_str.c_str(),
678 [](const graph::Spins &classical_spins, const GraphType &init_interaction,
679 double gamma) {
680 return system::make_continuous_time_ising(classical_spins,
681 init_interaction, gamma);
682 },
683 "classical_spins"_a, "init_interaction"_a, "gamma"_a);
684}
685
686// Algorithm
687template <template <typename> class Updater, typename System,
688 typename RandomNumberEngine>
689inline void declare_Algorithm_run(py::module &m,
690 const std::string &updater_str) {
691 auto str = std::string("Algorithm_") + updater_str + std::string("_run");
692 using SystemType = typename system::get_system_type<System>::type;
693 // with seed
694 m.def(
695 str.c_str(),
696 [](System &system, std::size_t seed,
697 const utility::ScheduleList<SystemType> &schedule_list,
698 const std::function<void(
699 const System &,
701 &callback) {
702 py::gil_scoped_release release;
703
704 using Callback = std::function<void(
705 const System &, const utility::UpdaterParameter<SystemType> &)>;
706 RandomNumberEngine rng(seed);
707 algorithm::Algorithm<Updater>::run(
708 system, rng, schedule_list,
709 callback ? [=](const System &system,
710 const utility::UpdaterParameter<SystemType>
711 &param) { callback(system, param.get_tuple()); }
712 : Callback(nullptr));
713
714 py::gil_scoped_acquire acquire;
715 },
716 "system"_a, "seed"_a, "schedule_list"_a, "callback"_a = nullptr);
717
718 // without seed
719 m.def(
720 str.c_str(),
721 [](System &system, const utility::ScheduleList<SystemType> &schedule_list,
722 const std::function<void(
723 const System &,
724 const typename utility::UpdaterParameter<SystemType>::Tuple &)>
725 &callback) {
726 py::gil_scoped_release release;
727
728 using Callback = std::function<void(
729 const System &, const utility::UpdaterParameter<SystemType> &)>;
730 RandomNumberEngine rng(std::random_device{}());
732 system, rng, schedule_list,
733 callback ? [=](const System &system,
734 const utility::UpdaterParameter<SystemType>
735 &param) { callback(system, param.get_tuple()); }
736 : Callback(nullptr));
737
738 py::gil_scoped_acquire acquire;
739 },
740 "system"_a, "schedule_list"_a, "callback"_a = nullptr);
741
742 // schedule_list can be a list of tuples
743 using TupleList = std::vector<std::pair<
744 typename utility::UpdaterParameter<SystemType>::Tuple, std::size_t>>;
745
746 // with seed
747 m.def(
748 str.c_str(),
749 [](System &system, std::size_t seed, const TupleList &tuplelist,
750 const std::function<void(
751 const System &,
752 const typename utility::UpdaterParameter<SystemType>::Tuple &)>
753 &callback) {
754 py::gil_scoped_release release;
755
756 using Callback = std::function<void(
757 const System &, const utility::UpdaterParameter<SystemType> &)>;
758 RandomNumberEngine rng(seed);
760 system, rng, utility::make_schedule_list<SystemType>(tuplelist),
761 callback ? [=](const System &system,
762 const utility::UpdaterParameter<SystemType>
763 &param) { callback(system, param.get_tuple()); }
764 : Callback(nullptr));
765
766 py::gil_scoped_acquire acquire;
767 },
768 "system"_a, "seed"_a, "tuplelist"_a, "callback"_a = nullptr);
769
770 // without seed
771 m.def(
772 str.c_str(),
773 [](System &system, const TupleList &tuplelist,
774 const std::function<void(
775 const System &,
776 const typename utility::UpdaterParameter<SystemType>::Tuple &)>
777 &callback) {
778 py::gil_scoped_release release;
779 using Callback = std::function<void(
780 const System &, const utility::UpdaterParameter<SystemType> &)>;
781 RandomNumberEngine rng(std::random_device{}());
783 system, rng, utility::make_schedule_list<SystemType>(tuplelist),
784 callback ? [=](const System &system,
785 const utility::UpdaterParameter<SystemType>
786 &param) { callback(system, param.get_tuple()); }
787 : Callback(nullptr));
788
789 py::gil_scoped_acquire acquire;
790 },
791 "system"_a, "tuplelist"_a, "callback"_a = nullptr);
792}
793
794// utility
795template <typename SystemType>
797
798template <>
799inline std::string
801 return "(beta: " + std::to_string(obj.beta) + ")";
802}
803
804template <>
805inline std::string repr_impl(
807 return "(beta: " + std::to_string(obj.beta) +
808 ", lambda: " + std::to_string(obj.lambda) + ")";
809}
810
811template <>
812inline std::string repr_impl(
814 return "(beta: " + std::to_string(obj.beta) +
815 ", s: " + std::to_string(obj.s) + ")";
816}
817
818inline void declare_ClassicalUpdaterParameter(py::module &m) {
819 py::class_<utility::ClassicalUpdaterParameter>(m, "ClassicalUpdaterParameter",
820 py::module_local())
821 .def(py::init<>())
822 .def(py::init<double>(), "beta"_a)
823 .def_readwrite("beta", &utility::ClassicalUpdaterParameter::beta)
824 .def("__repr__", [](const utility::ClassicalUpdaterParameter &self) {
825 return repr_impl(self);
826 });
827}
828
830 py::class_<utility::ClassicalConstraintUpdaterParameter>(
831 m, "ClassicalConstraintUpdaterParameter", py::module_local())
832 .def(py::init<>())
833 .def(py::init<double, double>(), "beta"_a, "lambda"_a)
834 .def(py::init<const std::pair<double, double> &>(), "obj"_a)
835 .def_readwrite("beta",
836 &utility::ClassicalConstraintUpdaterParameter::beta)
837 .def_readwrite("lambda",
838 &utility::ClassicalConstraintUpdaterParameter::lambda)
839 .def("__repr__",
841 return repr_impl(self);
842 });
843}
844
845inline void declare_TransverseFieldUpdaterParameter(py::module &m) {
846 py::class_<utility::TransverseFieldUpdaterParameter>(
847 m, "TransverseFieldUpdaterParameter", py::module_local())
848 .def(py::init<>())
849 .def(py::init<double, double>(), "beta"_a, "s"_a)
850 .def(py::init<const std::pair<double, double> &>(), "obj"_a)
851 .def_readwrite("beta", &utility::TransverseFieldUpdaterParameter::beta)
852 .def_readwrite("s", &utility::TransverseFieldUpdaterParameter::s)
853 .def("__repr__",
855 return repr_impl(self);
856 });
857}
858
859template <typename SystemType>
860inline void declare_Schedule(py::module &m, const std::string &systemtype_str) {
861 auto str = systemtype_str + "Schedule";
862 py::class_<utility::Schedule<SystemType>>(m, str.c_str(), py::module_local())
863 .def(py::init<>())
864 .def(py::init<const std::pair<
865 const utility::UpdaterParameter<SystemType> &, std::size_t> &>(),
866 "obj"_a)
867 .def_readwrite("one_mc_step", &utility::Schedule<SystemType>::one_mc_step)
868 .def_readwrite("updater_parameter",
870 .def("__repr__", [](const utility::Schedule<SystemType> &self) {
871 return "(" + repr_impl(self.updater_parameter) +
872 " mcs: " + std::to_string(self.one_mc_step) + ")";
873 });
874
875 // define make_schedule_list
876 m.def("make_schedule_list", &utility::make_schedule_list<SystemType>,
877 "tuplelist"_a);
878}
879
880// result
881// get_solution
882template <typename System> inline void declare_get_solution(py::module &m) {
883 m.def(
884 "get_solution",
885 [](const System &system) { return result::get_solution(system); },
886 "system"_a);
887}
888
889
890template<typename FloatType>
891void declare_BinaryPolynomialModel(py::module &m) {
893
894 std::string name = std::string("BinaryPolynomialModel");
895 auto py_class = py::class_<BPM>(m, name.c_str(), py::module_local());
896
897 py_class.def(py::init<const std::vector<std::vector<typename BPM::IndexType>>&,
898 const std::vector<FloatType>&>(),
899 "key_list"_a, "value_list"_a);
900
901 py_class.def("get_degree", &BPM::GetDegree);
902 py_class.def("get_system_size", &BPM::GetSystemSize);
903 py_class.def("get_index_list", &BPM::GetIndexList);
904 py_class.def("get_index_map", &BPM::GetIndexMap);
905 py_class.def("get_key_value_list", &BPM::GetKeyValueList);
906 py_class.def("get_adjacency_list", &BPM::GetAdjacencyList);
907 py_class.def("get_estimated_min_energy_difference", &BPM::GetEstimatedMinEnergyDifference);
908 py_class.def("get_estimated_max_energy_difference", &BPM::GetEstimatedMaxEnergyDifference);
909 py_class.def("calculate_energy", &BPM::CalculateEnergy);
910}
911
912template<typename FloatType>
913void declare_IsingPolynomialModel(py::module &m) {
915
916 std::string name = std::string("IsingPolynomialModel");
917 auto py_class = py::class_<IPM>(m, name.c_str(), py::module_local());
918
919 py_class.def(py::init<std::vector<std::vector<typename IPM::IndexType>>&,
920 std::vector<FloatType>&>(),
921 "key_list"_a, "value_list"_a);
922
923 py_class.def("get_degree", &IPM::GetDegree);
924 py_class.def("get_system_size", &IPM::GetSystemSize);
925 py_class.def("get_index_list", &IPM::GetIndexList);
926 py_class.def("get_index_map", &IPM::GetIndexMap);
927 py_class.def("get_key_value_list", &IPM::GetKeyValueList);
928 py_class.def("get_adjacency_list", &IPM::GetAdjacencyList);
929 py_class.def("get_estimated_min_energy_difference", &IPM::GetEstimatedMinEnergyDifference);
930 py_class.def("get_estimated_max_energy_difference", &IPM::GetEstimatedMaxEnergyDifference);
931 py_class.def("calculate_energy", &IPM::CalculateEnergy);
932}
933
934
935template<class ModelType>
936void declare_SASampler(py::module &m, const std::string &post_name = "") {
938
939 std::string name = std::string("SASampler") + post_name;
940
941 auto py_class = py::class_<SAS>(m, name.c_str(), py::module_local());
942
943 py_class.def(py::init<const ModelType&>(), "model"_a);
944
945 py_class.def("set_num_sweeps", &SAS::SetNumSweeps, "num_sweeps"_a);
946 py_class.def("set_num_reads", &SAS::SetNumReads, "num_reads"_a);
947 py_class.def("set_num_threads", &SAS::SetNumThreads, "num_threads"_a);
948 py_class.def("set_beta_min", &SAS::SetBetaMin, "beta_min"_a);
949 py_class.def("set_beta_max", &SAS::SetBetaMax, "beta_max"_a);
950 py_class.def("set_beta_min_auto", &SAS::SetBetaMinAuto);
951 py_class.def("set_beta_max_auto", &SAS::SetBetaMaxAuto);
952 py_class.def("set_update_method", &SAS::SetUpdateMethod, "update_method"_a);
953 py_class.def("set_random_number_engine", &SAS::SetRandomNumberEngine, "random_number_engine"_a);
954 py_class.def("set_temperature_schedule", &SAS::SetTemperatureSchedule, "temperature_schedule"_a);
955 py_class.def("get_model", &SAS::GetModel);
956 py_class.def("get_num_sweeps", &SAS::GetNumSweeps);
957 py_class.def("get_num_reads", &SAS::GetNumReads);
958 py_class.def("get_num_threads", &SAS::GetNumThreads);
959 py_class.def("get_beta_min", &SAS::GetBetaMin);
960 py_class.def("get_beta_max", &SAS::GetBetaMax);
961 py_class.def("get_update_method", &SAS::GetUpdateMethod);
962 py_class.def("get_random_number_engine", &SAS::GetRandomNumberEngine);
963 py_class.def("get_temperature_schedule", &SAS::GetTemperatureSchedule);
964 py_class.def("get_seed", &SAS::GetSeed);
965 py_class.def("get_index_list", &SAS::GetIndexList);
966 py_class.def("get_samples", &SAS::GetSamples);
967 py_class.def("calculate_energies", &SAS::CalculateEnergies);
968 py_class.def("sample", py::overload_cast<>(&SAS::Sample));
969 py_class.def("sample", py::overload_cast<const std::uint64_t>(&SAS::Sample), "seed"_a);
970
971 m.def("make_sa_sampler", [](const ModelType &model) {
972 return sampler::make_sa_sampler(model);
973 }, "model"_a);
974
975}
976
977void declare_UpdateMethod(py::module &m) {
978 py::enum_<algorithm::UpdateMethod>(m, "UpdateMethod")
979 .value("METROPOLIS", algorithm::UpdateMethod::METROPOLIS)
980 .value("HEAT_BATH", algorithm::UpdateMethod::HEAT_BATH);
981}
982
983void declare_RandomNumberEngine(py::module &m) {
984 py::enum_<algorithm::RandomNumberEngine>(m, "RandomNumberEngine")
985 .value("MT", algorithm::RandomNumberEngine::MT)
986 .value("MT_64", algorithm::RandomNumberEngine::MT_64)
987 .value("XORSHIFT", algorithm::RandomNumberEngine::XORSHIFT);
988}
989
990void declare_TemperatureSchedule(py::module &m) {
991 py::enum_<utility::TemperatureSchedule>(m, "TemperatureSchedule")
992 .value("LINEAR", utility::TemperatureSchedule::LINEAR)
993 .value("GEOMETRIC", utility::TemperatureSchedule::GEOMETRIC);
994}
995
996
997} // namespace openjij
Definition binary_polynomial_model.hpp:27
CSRSparse graph: just store CSR Sparse Matrix (Eigen::Sparse) The Hamiltonian is like.
Definition csr_sparse.hpp:42
FloatType calc_energy(const Spins &spins) const
calculate total energy
Definition csr_sparse.hpp:123
chimera lattice graph
Definition chimera.hpp:95
FloatType & h(std::size_t r, std::size_t c, std::size_t i)
access h(row, colum, in-chimera) (local field)
Definition chimera.hpp:458
FloatType & J(std::size_t r, std::size_t c, std::size_t i, ChimeraDir dir)
access J(row, colum, in-chimera, direction)
Definition chimera.hpp:354
two-body all-to-all interactions The Hamiltonian is like
Definition dense.hpp:44
FloatType & J(Index i, Index j)
access J_{ij}
Definition dense.hpp:211
FloatType calc_energy(const Spins &spins) const
calculate total energy
Definition dense.hpp:160
FloatType & h(Index i)
access h_{i} (local field)
Definition dense.hpp:246
Abstract graph class.
Definition graph.hpp:37
const Spins gen_spin(RandomNumberEngine &random_numder_engine) const
generate spins randomly.
Definition graph.hpp:55
const Binaries gen_binary(RandomNumberEngine &random_numder_engine) const
generate spins randomly.
Definition graph.hpp:73
std::size_t size() const noexcept
get number of spins
Definition graph.hpp:96
Definition ising_polynomial_model.hpp:23
Polynomial graph class, which can treat many-body interactions.
Definition polynomial.hpp:47
Sparse graph: two-body intereactions with O(1) connectivity The Hamiltonian is like.
Definition sparse.hpp:40
FloatType calc_energy(const Spins &spins) const
calculate total energy
Definition sparse.hpp:218
FloatType & h(Index i)
access h_{i} (local field)
Definition sparse.hpp:300
FloatType & J(Index i, Index j)
access J_{ij}
Definition sparse.hpp:269
square lattice graph
Definition square.hpp:64
FloatType & h(std::size_t r, std::size_t c)
access h(row, colum) (local field)
Definition square.hpp:337
FloatType & J(std::size_t r, std::size_t c, Dir dir)
access J(row, colum, direction)
Definition square.hpp:276
Class for executing simulated annealing.
Definition sa_sampler.hpp:27
ClassicalIsingPolynomial class, which is a system to solve higher order unconstrained binary optimiza...
Definition classical_ising_polynomial.hpp:36
KLocalPolynomial class, which is a system to solve higher order unconstrained binary optimization (HU...
Definition k_local_polynomial.hpp:32
xorshift random generator for c++11 random
Definition random.hpp:39
RandomNumberEngine
Definition algorithm.hpp:73
std::vector< Binary > Binaries
Definition graph.hpp:29
auto json_parse(const json &obj, bool relabel=true)
parse json object from bqm.to_serializable
Definition parse.hpp:50
ChimeraDir
direction in chimera graph
Definition chimera.hpp:46
@ MINUS_C
minus-column direction: (r, c, ind) -> (r, c-1, ind)
@ IN_0or4
inside-chimera 0or4 direction: (r, c, ind) -> (r, c, 0or4)
@ IN_2or6
inside-chimera 2or6 direction: (r, c, ind) -> (r, c, 2or6)
@ MINUS_R
minus-row direction: (r, c, ind) -> (r-1, c, ind)
@ IN_1or5
inside-chimera 1or5 direction: (r, c, ind) -> (r, c, 1or5)
@ IN_3or7
inside-chimera 3or7 direction: (r, c, ind) -> (r, c, 3or7)
@ PLUS_C
plus-column direction: (r, c, ind) -> (r, c+1, ind)
@ PLUS_R
plus-row direction: (r, c, ind) -> (r+1, c, ind)
std::vector< Spin > Spins
Definition graph.hpp:27
@ MINUS_C
minux-column direction: (r, c) -> (r, c-1)
@ MINUS_R
minus-row direction: (r, c) -> (r-1, c)
@ PLUS_C
plus-column direction: (r, c) -> (r, c+1)
@ PLUS_R
plus-row direction: (r, c) -> (r+1, c)
std::size_t Index
Definition graph.hpp:30
std::vector< graph::Spins > TrotterSpins
trotterized spin (std::vector<Spins>) trotter_spins[i][j] -> jth spin in ith trotter slice.
Definition transverse_ising.hpp:32
std::vector< Schedule< SystemType > > ScheduleList
schedule list alias
Definition schedule_list.hpp:135
Definition algorithm.hpp:24
void declare_Dir(py::module &m)
Definition declare.hpp:272
void declare_Chimera(py::module &m, const std::string &suffix)
Definition declare.hpp:348
void declare_IsingPolynomialModel(py::module &m)
Definition declare.hpp:913
void declare_ClassicalConstraintUpdaterParameter(py::module &m)
Definition declare.hpp:829
void declare_ClassicalIsingPolynomial(py::module &m, const std::string &gtype_str)
Definition declare.hpp:441
void declare_TransverseFieldUpdaterParameter(py::module &m)
Definition declare.hpp:845
void declare_KLocalPolynomial(py::module &m, const std::string &gtype_str)
Definition declare.hpp:502
void declare_Schedule(py::module &m, const std::string &systemtype_str)
Definition declare.hpp:860
void declare_Dense(py::module &m, const std::string &suffix)
Definition declare.hpp:74
void declare_CSRSparse(py::module &m, const std::string &suffix)
Definition declare.hpp:196
void declare_TemperatureSchedule(py::module &m)
Definition declare.hpp:990
void declare_Algorithm_run(py::module &m, const std::string &updater_str)
Definition declare.hpp:689
void declare_ContinuousTimeIsing(py::module &m, const std::string &gtype_str)
Definition declare.hpp:644
void declare_ClassicalIsing(py::module &m, const std::string &gtype_str)
Definition declare.hpp:410
void declare_TransverseIsing(py::module &m, const std::string &gtype_str)
Definition declare.hpp:586
void declare_RandomNumberEngine(py::module &m)
Definition declare.hpp:983
void declare_BinaryPolynomialModel(py::module &m)
Definition declare.hpp:891
void declare_get_solution(py::module &m)
Definition declare.hpp:882
void declare_ClassicalUpdaterParameter(py::module &m)
Definition declare.hpp:818
void declare_ChimeraDir(py::module &m)
Definition declare.hpp:334
void declare_Square(py::module &m, const std::string &suffix)
Definition declare.hpp:282
void declare_Graph(py::module &m)
Definition declare.hpp:42
void declare_UpdateMethod(py::module &m)
Definition declare.hpp:977
double FloatType
Note:
Definition compile_config.hpp:37
void declare_Polynomial(py::module &m, const std::string &suffix)
Definition declare.hpp:220
void declare_Sparse(py::module &m, const std::string &suffix)
Definition declare.hpp:132
std::string repr_impl(const utility::UpdaterParameter< SystemType > &)
void declare_SASampler(py::module &m, const std::string &post_name="")
Definition declare.hpp:936
static void run(System &system, RandomNumberEngine &random_number_engine, const utility::ScheduleList< typename system::get_system_type< System >::type > &schedule_list, const std::function< void(const System &, const utility::UpdaterParameter< typename system::get_system_type< System >::type > &)> &callback=nullptr)
Definition algorithm.hpp:29
ClassicalIsing structure (system for classical Ising model)
Definition classical_ising.hpp:38
Continuous Time Quantum Ising system.
Definition continuous_time_ising.hpp:34
TransverseIsing structure with discrete-time trotter spins.
Definition transverse_ising.hpp:39
typename System::system_type type
Definition system.hpp:77
schedule struct
Definition schedule_list.hpp:121
std::size_t one_mc_step
Definition schedule_list.hpp:126
UpdaterParameter< SystemType > updater_parameter
Definition schedule_list.hpp:125
updater paramter for classical ising model with a single constraint
Definition schedule_list.hpp:52
updater parameter for classical ising system
Definition schedule_list.hpp:37
updater paramter for transverse ising model
Definition schedule_list.hpp:74
updater parameter for monte carlo simulation
Definition schedule_list.hpp:32