17#include "../utility/variable.hpp"
18#include "../utility/min_polynomial.hpp"
27template <
typename RandType>
32 const typename RandType::result_type seed)
33 : model(model), seed(seed), random_number_engine(seed) {
38 this->state_.reserve(num_variables);
39 const auto &bounds = this->model.
GetBounds();
40 for (std::int64_t i = 0; i < num_variables; ++i) {
42 x.SetRandomValue(this->random_number_engine);
43 this->state_.push_back(x);
45 this->energy_ = this->CalculateEnergy(this->state_);
49 const std::size_t num_terms = key_value_list.size();
50 this->zero_count_.resize(num_terms, 0);
51 this->term_prod_.resize(num_terms, 1.0);
53 for (std::size_t i = 0; i < num_terms; ++i) {
56 for (
const auto &[index, degree] : key_value_list[i].first) {
57 auto x = this->state_[index].value;
61 prod *= std::pow(x, degree);
64 this->zero_count_[i] = count;
65 this->term_prod_[i] = prod;
69 this->base_energy_difference_.resize(num_variables);
70 for (std::size_t i = 0; i < num_terms; ++i) {
71 const double value = key_value_list[i].second;
72 for (
const auto &[index, degree] : key_value_list[i].first) {
73 const auto x = this->state_[index].value;
75 if (this->zero_count_[i] == 1) {
76 this->base_energy_difference_[index][degree] +=
77 value * this->term_prod_[i];
80 if (this->zero_count_[i] == 0) {
81 this->base_energy_difference_[index][degree] +=
82 value * this->term_prod_[i] / std::pow(x, degree);
91 double energy = this->model.GetConstant();
92 const auto &key_value_list = this->model.GetKeyValueList();
93 for (
const auto &term : key_value_list) {
95 for (
const auto &[index, degree] : term.first) {
96 prod *= std::pow(state[index].value, degree);
98 energy += term.second * prod;
104 return this->state_[index].GenerateCandidateValue(
105 this->random_number_engine);
110 const auto current_value = this->state_[index].value;
111 for (
const auto &[degree, value] : this->base_energy_difference_[index]) {
113 (std::pow(new_value, degree) - std::pow(current_value, degree));
118 void SetValue(std::int64_t index, std::int64_t new_value) {
119 const auto current_value = this->state_[index].value;
120 if (current_value == new_value) {
124 this->energy_ += this->GetEnergyDifference(index, new_value);
125 this->state_[index].SetValue(new_value);
127 const auto &interactions = this->model.GetIndexToInteractions().at(index);
128 const auto &key_value_list = this->model.GetKeyValueList();
130 if (current_value != 0 && new_value != 0) {
131 for (
const auto &[cons_ind, degree] : interactions) {
133 std::pow(
static_cast<double>(new_value) / current_value, degree);
134 const double ddE = (a - 1) * key_value_list[cons_ind].second *
135 this->term_prod_[cons_ind];
136 this->term_prod_[cons_ind] *= a;
137 const int total_count = this->zero_count_[cons_ind];
138 for (
const auto &[i, d] : key_value_list[cons_ind].first) {
140 if (this->state_[i].value == 0 && total_count == 1) {
141 this->base_energy_difference_[i][d] += ddE;
142 }
else if (this->state_[i].value != 0 && total_count == 0) {
143 this->base_energy_difference_[i][d] +=
144 ddE / std::pow(this->state_[i].value, d);
149 }
else if (current_value == 0 && new_value != 0) {
150 for (
const auto &[cons_ind, degree] : interactions) {
151 this->zero_count_[cons_ind]--;
152 const int total_count = this->zero_count_[cons_ind];
153 const double b = std::pow(new_value, degree);
155 b * key_value_list[cons_ind].second * this->term_prod_[cons_ind];
156 this->term_prod_[cons_ind] *= b;
157 for (
const auto &[i, d] : key_value_list[cons_ind].first) {
159 if (this->state_[i].value == 0 && total_count == 1) {
160 this->base_energy_difference_[i][d] += ddE;
161 }
else if (this->state_[i].value != 0 && total_count == 0) {
162 this->base_energy_difference_[i][d] +=
163 ddE / std::pow(this->state_[i].value, d);
169 for (
const auto &[cons_ind, degree] : interactions) {
170 const int total_count = this->zero_count_[cons_ind];
171 this->zero_count_[cons_ind]++;
173 -key_value_list[cons_ind].second * this->term_prod_[cons_ind];
174 this->term_prod_[cons_ind] /= std::pow(current_value, degree);
175 for (
const auto &[i, d] : key_value_list[cons_ind].first) {
177 if (this->state_[i].value == 0 && total_count == 1) {
178 this->base_energy_difference_[i][d] += ddE;
179 }
else if (this->state_[i].value != 0 && total_count == 0) {
180 this->base_energy_difference_[i][d] +=
181 ddE / std::pow(this->state_[i].value, d);
190 const auto &x = this->state_[index];
191 const std::int64_t dxl = x.lower_bound - x.value;
192 const std::int64_t dxu = x.upper_bound - x.value;
194 if (this->UnderQuadraticCoeff(index)) {
195 auto it_a = this->base_energy_difference_[index].find(2);
196 const double a = (it_a != this->base_energy_difference_[index].end())
199 auto it_b = this->base_energy_difference_[index].find(1);
200 const double b = (it_b != this->base_energy_difference_[index].end())
205 const double bb = b + 2 * x.value * a;
209 else if (this->IsCubicCoeff(index)) {
210 auto it_a = this->base_energy_difference_[index].find(3);
211 const double a = (it_a != this->base_energy_difference_[index].end())
214 auto it_b = this->base_energy_difference_[index].find(2);
215 const double b = (it_b != this->base_energy_difference_[index].end())
218 auto it_c = this->base_energy_difference_[index].find(1);
219 const double c = (it_c != this->base_energy_difference_[index].end())
224 const double bb = 3 * a * x.value + b;
225 const double cc = 3 * a * x.value * x.value + 2 * b * x.value + c;
228 }
else if (this->IsQuarticCoeff(index)) {
229 auto it_a = this->base_energy_difference_[index].find(4);
230 const double a = (it_a != this->base_energy_difference_[index].end())
233 auto it_b = this->base_energy_difference_[index].find(3);
234 const double b = (it_b != this->base_energy_difference_[index].end())
237 auto it_c = this->base_energy_difference_[index].find(2);
238 const double c = (it_c != this->base_energy_difference_[index].end())
241 auto it_d = this->base_energy_difference_[index].find(1);
242 const double d = (it_d != this->base_energy_difference_[index].end())
247 const double bb = 4 * a * x.value + b;
248 const double cc = 6 * a * x.value * x.value + 3 * b * x.value + c;
249 const double dd = 4 * a * x.value * x.value * x.value +
250 3 * b * x.value * x.value + 2 * c * x.value + d;
254 double min_dE = std::numeric_limits<double>::infinity();
255 std::int64_t min_value = -1;
257 for (std::int64_t val = this->state_[index].lower_bound;
258 val <= this->state_[index].upper_bound; ++val) {
259 double dE = this->GetEnergyDifference(index, val);
265 if (min_value == -1) {
266 throw std::runtime_error(
"No valid state number found.");
268 return {min_value, min_dE};
273 auto it1 = this->base_energy_difference_[index].find(1);
275 (it1 != this->base_energy_difference_[index].end()) ? it1->second : 0.0;
277 auto it2 = this->base_energy_difference_[index].find(2);
279 (it2 != this->base_energy_difference_[index].end()) ? it2->second : 0.0;
281 return c1 + 2 * this->state_[index].value * c2;
284 const std::vector<utility::IntegerVariable> &
GetState()
const {
291 return this->model.GetEachVariableDegreeAt(index) == 1;
295 return (this->model.GetEachVariableDegreeAt(index) == 2) || (this->model.GetEachVariableDegreeAt(index) == 1);
299 return this->model.GetEachVariableDegreeAt(index) == 3;
303 return this->model.GetEachVariableDegreeAt(index) == 4;
307 return this->UnderQuadraticCoeff(index) || this->IsCubicCoeff(index) || this->IsQuarticCoeff(index);
312 const typename RandType::result_type
seed;
316 std::vector<utility::IntegerVariable>
state_;
Definition integer_polynomial_model.hpp:20
const std::vector< std::pair< std::int64_t, std::int64_t > > & GetBounds() const
Definition integer_polynomial_model.hpp:162
std::int64_t GetNumVariables() const
Definition integer_polynomial_model.hpp:161
const std::vector< std::pair< std::vector< std::pair< std::int64_t, std::int64_t > >, double > > & GetKeyValueList() const
Definition integer_polynomial_model.hpp:168
double CalculateEnergy(const std::vector< utility::IntegerVariable > &state) const
Definition integer_polynomial_sa_system.hpp:90
RandType random_number_engine
Definition integer_polynomial_sa_system.hpp:313
const RandType::result_type seed
Definition integer_polynomial_sa_system.hpp:312
double GetEnergy() const
Definition integer_polynomial_sa_system.hpp:288
bool UnderQuadraticCoeff(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:294
double GetEnergyDifference(std::int64_t index, std::int64_t new_value) const
Definition integer_polynomial_sa_system.hpp:108
IntegerSASystem(const graph::IntegerPolynomialModel &model, const typename RandType::result_type seed)
Definition integer_polynomial_sa_system.hpp:31
void SetValue(std::int64_t index, std::int64_t new_value)
Definition integer_polynomial_sa_system.hpp:118
bool IsCubicCoeff(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:298
const graph::IntegerPolynomialModel & model
Definition integer_polynomial_sa_system.hpp:311
std::vector< utility::IntegerVariable > state_
Definition integer_polynomial_sa_system.hpp:316
bool CanOptMove(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:306
std::vector< double > term_prod_
Definition integer_polynomial_sa_system.hpp:319
std::int64_t GenerateCandidateValue(std::int64_t index)
Definition integer_polynomial_sa_system.hpp:103
const std::vector< utility::IntegerVariable > & GetState() const
Definition integer_polynomial_sa_system.hpp:284
std::vector< int > zero_count_
Definition integer_polynomial_sa_system.hpp:318
std::pair< int, double > GetMinEnergyDifference(std::int64_t index)
Definition integer_polynomial_sa_system.hpp:189
std::vector< std::unordered_map< std::int64_t, double > > base_energy_difference_
Definition integer_polynomial_sa_system.hpp:320
double GetLinearCoeff(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:272
double energy_
Definition integer_polynomial_sa_system.hpp:317
bool IsLinearCoeff(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:290
bool IsQuarticCoeff(std::int64_t index) const
Definition integer_polynomial_sa_system.hpp:302
Definition sa_system.hpp:24
std::pair< std::int64_t, double > FindMinimumIntegerQuartic(const double a, const double b, const double c, const double d, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:104
std::pair< std::int64_t, double > FindMinimumIntegerQuadratic(const double a, const double b, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:15
std::pair< std::int64_t, double > FindMinimumIntegerCubic(const double a, const double b, const double c, const std::int64_t l, const std::int64_t u, const std::int64_t x, RandomNumberEngine &random_number_engine)
Definition min_polynomial.hpp:45
Definition algorithm.hpp:24
Definition variable.hpp:20