23#include <nlohmann/json.hpp>
39template <
typename FloatType>
64 const cimod::Vartype init_vartype)
65 : num_variables(poly_graph.size()), variables(init_variables),
66 vartype(init_vartype) {
67 cimod::CheckVariables(variables, vartype);
68 SetInteractions(poly_graph);
74 std::abs(FindMaxInteraction().second * utility::THRESHOLD<FloatType>);
75 min_effective_dE_ = std::abs(FindMinInteraction(thres_hold).second);
87 const std::string init_vartype)
88 : num_variables(poly_graph.size()), variables(init_variables),
89 vartype(ConvertVartype(init_vartype)) {
90 cimod::CheckVariables(variables, vartype);
91 SetInteractions(poly_graph);
97 std::abs(FindMaxInteraction().second * utility::THRESHOLD<FloatType>);
98 min_effective_dE_ = std::abs(FindMinInteraction(thres_hold).second);
106 const nlohmann::json &j)
107 : num_variables(init_variables.size()), variables(init_variables),
108 vartype(j.at(
"vartype") ==
"SPIN" ? cimod::Vartype::SPIN
109 : cimod::Vartype::BINARY) {
110 cimod::CheckVariables(variables, vartype);
112 const auto &poly_key_list = std::get<0>(v_k_v);
113 const auto &poly_value_list = std::get<1>(v_k_v);
115 if (poly_key_list.size() != poly_value_list.size()) {
116 throw std::runtime_error(
117 "The sizes of key_list and value_list must match each other");
119 if (poly_key_list.size() == 0) {
120 throw std::runtime_error(
"The interaction is empty.");
122 if (num_variables == 0) {
123 throw std::runtime_error(
"The number of variables is zero.");
126 num_interactions_ =
static_cast<int64_t
>(poly_key_list.size());
128 poly_key_list_.resize(num_interactions_);
129 poly_value_list_.resize(num_interactions_);
131#pragma omp parallel for
132 for (int64_t i = 0; i < num_interactions_; ++i) {
133 poly_key_list_[i] = poly_key_list[i];
134 poly_value_list_[i] = poly_value_list[i];
137 active_variables_.resize(num_variables);
138 std::iota(active_variables_.begin(), active_variables_.end(), 0);
145 std::abs(FindMaxInteraction().second * utility::THRESHOLD<FloatType>);
146 min_effective_dE_ = std::abs(FindMinInteraction(thres_hold).second);
154 if (init_variables.size() != variables.size()) {
155 throw std::runtime_error(
156 "The size of initial spins/binaries does not equal to system size");
158 cimod::CheckVariables(init_variables, vartype);
159 if (vartype == cimod::Vartype::SPIN) {
160 for (
const auto &index_variable : active_variables_) {
161 if (variables[index_variable] != init_variables[index_variable]) {
162 update_spin_system(index_variable);
164 if (variables[index_variable] != init_variables[index_variable]) {
165 std::stringstream ss;
166 ss <<
"Unknown error detected in " << __func__;
167 throw std::runtime_error(ss.str());
170 }
else if (vartype == cimod::Vartype::BINARY) {
171 for (
const auto &index_variable : active_variables_) {
172 if (variables[index_variable] != init_variables[index_variable]) {
173 update_binary_system(index_variable);
175 if (variables[index_variable] != init_variables[index_variable]) {
176 std::stringstream ss;
177 ss <<
"Unknown error detected in " << __func__;
178 throw std::runtime_error(ss.str());
182 throw std::runtime_error(
"Unknown vartype detected");
190 dE_.resize(num_variables);
192 if (vartype == cimod::Vartype::SPIN) {
194 max_effective_dE_ = 2.0 * std::abs(poly_value_list_.front());
195 for (
const auto &index_binary : active_variables_) {
199 for (
const auto &index_key : adj_[index_binary]) {
200 val += poly_value_list_[index_key] * sign_key_[index_key];
201 abs_val += std::abs(poly_value_list_[index_key]);
204 dE_[index_binary] = -2 * val;
205 if (flag && max_effective_dE_ < 2 * abs_val) {
206 max_effective_dE_ = 2 * abs_val;
209 }
else if (vartype == cimod::Vartype::BINARY) {
211 max_effective_dE_ = std::abs(poly_value_list_.front());
212 for (
const auto &index_binary : active_variables_) {
217 for (
const auto &index_key : adj_[index_binary]) {
218 if (zero_count_[index_key] + binary == 1) {
219 val += poly_value_list_[index_key];
222 abs_val += std::abs(poly_value_list_[index_key]);
224 dE_[index_binary] = (-2 * binary + 1) * val;
226 if (flag && max_effective_dE_ < abs_val) {
227 max_effective_dE_ = abs_val;
231 throw std::runtime_error(
"Unknown vartype detected");
239 for (
const auto &index_key : adj_[index_update_spin]) {
240 const FloatType val = 4.0 * poly_value_list_[index_key];
241 const int8_t sign = sign_key_[index_key];
242 for (
const auto &index_spin : poly_key_list_[index_key]) {
243 if (index_spin != index_update_spin) {
244 dE_[index_spin] += val * sign;
247 sign_key_[index_key] *= -1;
249 dE_[index_update_spin] *= -1;
250 variables[index_update_spin] *= -1;
257 const graph::Binary update_binary = variables[index_update_binary];
258 const int coeef = -2 * update_binary + 1;
259 const int count = +2 * update_binary - 1;
260 for (
const auto &index_key : adj_[index_update_binary]) {
261 const FloatType val = poly_value_list_[index_key];
262 for (
const auto &index_binary : poly_key_list_[index_key]) {
264 if (zero_count_[index_key] + update_binary + binary == 2 &&
265 index_binary != index_update_binary) {
266 dE_[index_binary] += coeef * (-2 * binary + 1) * val;
269 zero_count_[index_key] += count;
271 dE_[index_update_binary] *= -1;
272 variables[index_update_binary] = 1 - variables[index_update_binary];
279 return dE_[index_variable];
286 return active_variables_;
292 const cimod::PolynomialValueList<FloatType> &
get_values()
const {
293 return poly_value_list_;
299 const cimod::PolynomialKeyList<graph::Index> &
get_keys()
const {
300 return poly_key_list_;
306 const std::vector<std::vector<graph::Index>> &
get_adj()
const {
return adj_; }
319 if (vartype == cimod::Vartype::SPIN) {
321 }
else if (vartype == cimod::Vartype::BINARY) {
324 throw std::runtime_error(
"Unknown vartype detected");
333 std::vector<FloatType>
dE_;
345 std::vector<std::vector<graph::Index>>
adj_;
367 adj_.resize(num_variables);
368 for (int64_t i = 0; i < num_interactions_; ++i) {
369 for (
const auto &index : poly_key_list_[i]) {
370 adj_[index].push_back(i);
378 const auto &poly_key_list = poly_graph.
get_keys();
379 const auto &poly_value_list = poly_graph.
get_values();
381 if (poly_key_list.size() != poly_value_list.size()) {
382 throw std::runtime_error(
383 "The sizes of key_list and value_list must match each other");
386 if (poly_key_list.size() == 0) {
387 throw std::runtime_error(
"The interaction is empty.");
390 std::unordered_set<graph::Index> active_variable_set;
392 poly_key_list_.clear();
393 poly_value_list_.clear();
395 for (std::size_t i = 0; i < poly_key_list.size(); ++i) {
396 if (poly_value_list[i] != 0.0) {
397 poly_key_list_.push_back(poly_key_list[i]);
398 poly_value_list_.push_back(poly_value_list[i]);
399 for (
const auto &it : poly_key_list[i]) {
400 active_variable_set.emplace(it);
404 num_interactions_ =
static_cast<int64_t
>(poly_key_list_.size());
405 active_variables_ = std::vector<graph::Index>(active_variable_set.begin(),
406 active_variable_set.end());
407 std::sort(active_variables_.begin(), active_variables_.end());
412 if (vartype != cimod::Vartype::BINARY) {
415 zero_count_.resize(num_interactions_);
416#pragma omp parallel for
417 for (int64_t i = 0; i < num_interactions_; ++i) {
418 int64_t zero_count = 0;
419 for (
const auto &index : poly_key_list_[i]) {
420 if (variables[index] == 0) {
424 zero_count_[i] = zero_count;
430 if (vartype != cimod::Vartype::SPIN) {
433 sign_key_.resize(num_interactions_);
434#pragma omp parallel for
435 for (int64_t i = 0; i < num_interactions_; ++i) {
437 for (
const auto &index : poly_key_list_[i]) {
438 sign_key *= variables[index];
440 sign_key_[i] = sign_key;
447 if (vartype ==
"SPIN") {
448 return cimod::Vartype::SPIN;
449 }
else if (vartype ==
"BINARY") {
450 return cimod::Vartype::BINARY;
452 throw std::runtime_error(
"Unknown vartype detected");
460 if (poly_key_list_.size() == 0) {
461 throw std::runtime_error(
"Interactions are empty.");
464 std::vector<graph::Index> max_key = {};
465 for (std::size_t i = 0; i < poly_key_list_.size(); ++i) {
466 if (std::abs(max_val) < std::abs(poly_value_list_[i])) {
467 max_val = poly_value_list_[i];
468 max_key = poly_key_list_[i];
471 return std::pair<std::vector<graph::Index>,
FloatType>(max_key, max_val);
477 std::pair<std::vector<graph::Index>,
FloatType>
479 if (poly_key_list_.size() == 0) {
480 throw std::runtime_error(
"Interactions are empty.");
483 std::vector<graph::Index> min_key;
486 bool flag_success_initialize =
false;
487 for (std::size_t i = 0; i < poly_key_list_.size(); ++i) {
488 if (std::abs(threshold) < std::abs(poly_value_list_[i])) {
489 min_val = poly_value_list_[i];
490 min_key = poly_key_list_[i];
491 flag_success_initialize =
true;
495 if (!flag_success_initialize) {
496 std::stringstream ss;
497 ss <<
"No interactions larger than threshold=" << std::abs(threshold)
499 throw std::runtime_error(ss.str());
502 for (std::size_t i = 0; i < poly_key_list_.size(); ++i) {
503 if (std::abs(threshold) < std::abs(poly_value_list_[i]) &&
504 std::abs(poly_value_list_[i]) < std::abs(min_val)) {
505 min_val = poly_value_list_[i];
506 min_key = poly_key_list_[i];
510 if (std::abs(min_val) <= std::abs(threshold)) {
511 std::stringstream ss;
512 ss <<
"Unknown error in " << __func__ << std::endl;
513 throw std::runtime_error(ss.str());
515 return std::pair<std::vector<graph::Index>,
FloatType>(min_key, min_val);
527template <
typename GraphType>
529 const GraphType &poly_graph,
530 const cimod::Vartype init_vartype) {
542template <
typename GraphType>
544 const GraphType &poly_graph,
545 const std::string init_vartype) {
547 init_variables, poly_graph, init_vartype);
556 const nlohmann::json &init_obj) {
Polynomial graph class, which can treat many-body interactions.
Definition polynomial.hpp:47
const cimod::PolynomialKeyList< Index > & get_keys() const
Get the PolynomialKeyList object (all the keys of polynomial interactions).
Definition polynomial.hpp:180
const cimod::PolynomialValueList< FloatType > & get_values() const
Get the PolynomialValueList object (all the values of polynomial interactions).
Definition polynomial.hpp:187
FloatType get_min_effective_dE() const
Get "min_effective_dE", which is a rough lower bound of energy gap.
Definition classical_ising_polynomial.hpp:314
void SetAdj()
Set adjacency list.
Definition classical_ising_polynomial.hpp:365
graph::Spins variables
Spin/binary configurations.
Definition classical_ising_polynomial.hpp:50
std::pair< std::vector< graph::Index >, FloatType > FindMaxInteraction() const
Return the key and value of the absolute maximum interaction.
Definition classical_ising_polynomial.hpp:459
ClassicalIsingPolynomial(const graph::Spins &init_variables, const graph::Polynomial< FloatType > &poly_graph, const cimod::Vartype init_vartype)
Constructor of ClassicalIsingPolynomial.
Definition classical_ising_polynomial.hpp:62
const cimod::PolynomialValueList< FloatType > & get_values() const
Get the PolynomialValueList object, which is the list of the values of the polynomial interactions as...
Definition classical_ising_polynomial.hpp:292
void update_spin_system(const graph::Index index_update_spin)
Flip specified spin by single spin flip.
Definition classical_ising_polynomial.hpp:238
void reset_dE()
Reset energy differences (dE), which is used to determine whether to flip the spin/binary or not.
Definition classical_ising_polynomial.hpp:188
cimod::PolynomialKeyList< graph::Index > poly_key_list_
The list of the indices of the polynomial interactions as std::vector<std::vector<graph::Index>>.
Definition classical_ising_polynomial.hpp:349
cimod::PolynomialValueList< FloatType > poly_value_list_
The list of the values of the polynomial interactions as std::vector<FloatType>.
Definition classical_ising_polynomial.hpp:353
FloatType get_max_effective_dE() const
Get "max_effective_dE", which is a upper bound of energy gap.
Definition classical_ising_polynomial.hpp:310
void ResetSignKey()
Set sign_key_.
Definition classical_ising_polynomial.hpp:429
void ResetZeroCount()
Set zero_count_.
Definition classical_ising_polynomial.hpp:411
ClassicalIsingPolynomial(const graph::Spins &init_variables, const nlohmann::json &j)
Constructor of ClassicalIsingPolynomial.
Definition classical_ising_polynomial.hpp:105
const std::vector< graph::Index > & get_active_variables() const
Get "active_binaries_", which is the list of the binaries connected by at least one interaction.
Definition classical_ising_polynomial.hpp:285
cimod::Vartype ConvertVartype(const std::string vartype) const
Convert vartype from std::string to cimod::Vartype.
Definition classical_ising_polynomial.hpp:446
std::pair< std::vector< graph::Index >, FloatType > FindMinInteraction(const FloatType threshold=0.0) const
Return the key and value of the absolute minimum interaction.
Definition classical_ising_polynomial.hpp:478
void SetInteractions(const graph::Polynomial< FloatType > &poly_graph)
Set interactions from Polynomial graph.
Definition classical_ising_polynomial.hpp:377
std::vector< graph::Index > active_variables_
The list of the binaries connected by at least one interaction.
Definition classical_ising_polynomial.hpp:356
FloatType dE(const graph::Index index_variable) const
Return the energy difference of single spin flip update.
Definition classical_ising_polynomial.hpp:278
void reset_variables(const graph::Spins &init_variables)
Reset ClassicalIsingPolynomial system with new spin/binary configurations.
Definition classical_ising_polynomial.hpp:153
std::vector< std::vector< graph::Index > > adj_
Adjacency list, which is the list of the indices of polynomial interactions including specific spin/b...
Definition classical_ising_polynomial.hpp:345
const cimod::Vartype vartype
The model's type. SPIN or BINARY.
Definition classical_ising_polynomial.hpp:53
FloatType min_effective_dE_
Rough lower bound of energy gap.
Definition classical_ising_polynomial.hpp:362
ClassicalIsingPolynomial(const graph::Spins &init_variables, const graph::Polynomial< FloatType > &poly_graph, const std::string init_vartype)
Constructor of ClassicalIsingPolynomial.
Definition classical_ising_polynomial.hpp:85
const std::vector< std::vector< graph::Index > > & get_adj() const
Get the adjacency list, which is the list of the indices of polynomial interactions including specifi...
Definition classical_ising_polynomial.hpp:306
const cimod::PolynomialKeyList< graph::Index > & get_keys() const
Get the PolynomialKeyList object, which is the list of the indices of the polynomial interactions as ...
Definition classical_ising_polynomial.hpp:299
std::string get_vartype_string() const
Get the vartype as std::string.
Definition classical_ising_polynomial.hpp:318
int64_t num_interactions_
The number of the interactions.
Definition classical_ising_polynomial.hpp:330
std::vector< FloatType > dE_
The energy differences when flipping a spin/binary.
Definition classical_ising_polynomial.hpp:333
void update_binary_system(const graph::Index index_update_binary)
Flip specified binary by single spin flip.
Definition classical_ising_polynomial.hpp:256
const int64_t num_variables
The number of spins/binaries.
Definition classical_ising_polynomial.hpp:47
std::vector< int8_t > sign_key_
The sign of product of spin variables in each interaction.
Definition classical_ising_polynomial.hpp:341
FloatType max_effective_dE_
Upper bound of energy gap.
Definition classical_ising_polynomial.hpp:359
std::vector< int64_t > zero_count_
The number of variables taking the zero in each interaction.
Definition classical_ising_polynomial.hpp:337
ClassicalIsingPolynomial class, which is a system to solve higher order unconstrained binary optimiza...
Definition classical_ising_polynomial.hpp:36
auto json_parse(const json &obj, bool relabel=true)
parse json object from bqm.to_serializable
Definition parse.hpp:50
int Binary
Definition graph.hpp:28
std::vector< Spin > Spins
Definition graph.hpp:27
std::size_t Index
Definition graph.hpp:30
auto make_classical_ising_polynomial(const graph::Spins &init_variables, const GraphType &poly_graph, const cimod::Vartype init_vartype)
Helper function for ClassicalIsingPolynomial constructor.
Definition classical_ising_polynomial.hpp:528
Definition algorithm.hpp:24
double FloatType
Note:
Definition compile_config.hpp:37
classical monte carlo system (using beta (inverse temperature) for annealing parameter)
Definition system.hpp:31