57template <concepts::
objective_function ObjectiveFunction>
66template <concepts::multi_variate_
objective_function ObjectiveFunction>
68 :
public optimizer_base<annealing_downhill_simplex<ObjectiveFunction>> {
85 using value_type =
typename objective_function_type::value_type;
94 reflection_and_expansion,
106 -> std::string_view {
108 case process_type::none:
110 case process_type::reflection:
112 case process_type::reflection_and_expansion:
113 return "reflection and expansion";
114 case process_type::contraction:
115 return "contraction";
116 case process_type::multiple_contraction:
117 return "multiple contraction";
119 return "invalid process";
151 dim_ = init_var.size();
154 iterations_in_current_trial_ = 0;
155 temperature_ = highest_temperature_;
156 opt_value_ = std::numeric_limits<value_type>::max();
161 points_.push_back(var);
162 values_.push_back(evaluate_on(var));
166 points_.push_back(var);
167 values_.push_back(evaluate_on(var));
172 for (std::size_t i = 0; i < util::safe_cast<std::size_t>(dim_ + 1);
174 value_order_.push_back(i);
185 const auto min_ind = value_order_.front();
186 const auto second_max_ind =
188 const auto max_ind = value_order_.back();
190 reflect(face_center);
191 if (fluctuated_values_[max_ind] < fluctuated_values_[min_ind]) {
193 }
else if (fluctuated_values_[max_ind] >=
194 fluctuated_values_[second_max_ind]) {
195 contract(face_center);
196 if (fluctuated_values_[max_ind] >=
197 fluctuated_values_[second_max_ind]) {
206 ++iterations_in_current_trial_;
207 if (iterations_in_current_trial_ >= max_iterations_per_trial_) {
208 iterations_in_current_trial_ = 0;
211 temperature_ = highest_temperature_ *
213 static_cast<value_type>(iterations_in_current_trial_) /
214 static_cast<value_type>(max_iterations_per_trial_),
222 return iterations() >= max_iterations_;
231 iteration_logger.template append<index_type>(
232 "Iter.", &this_type::iterations);
233 iteration_logger.template append<index_type>(
234 "Eval.", &this_type::evaluations);
235 iteration_logger.template append<value_type>(
236 "Value", &this_type::opt_value);
237 iteration_logger.template append<variable_scalar_type>(
238 "SimplexSize", &this_type::simplex_size);
239 iteration_logger.template append<variable_scalar_type>(
240 "Temperature", &this_type::temperature);
243 .template append<std::string_view>(
244 "Process", &this_type::last_process_name)
245 ->width(process_width);
252 return opt_variable_;
291 return process_name(last_process());
300 return (points_[value_order_.front()] - points_[value_order_.back()])
319 auto seed(random_number_generator_type::result_type value)
321 random_number_generator_.seed(value);
333 this->logger(),
"Highest temperature must be a positive number.");
334 highest_temperature_ = value;
347 "Maximum number of iterations in each trial must be a positive "
349 max_iterations_per_trial_ = value;
361 "Maximum number of iterations must be a positive number.");
362 max_iterations_ = value;
367 static inline const auto default_width =
378 obj_fun_.evaluate_on(variable);
380 const auto& value = obj_fun_.value();
381 if (value < opt_value_) {
383 opt_variable_ = variable;
392 for (std::size_t i = 0; i < values_.size(); ++i) {
393 fluctuated_values_[i] = values_[i] + generate_fluctuation();
395 std::sort(std::begin(value_order_), std::end(value_order_),
396 [
this](std::size_t i, std::size_t j) {
397 return fluctuated_values_[i] < fluctuated_values_[j];
409 for (std::size_t i = 0; i < util::safe_cast<std::size_t>(dim_); ++i) {
410 face_center += points_[value_order_[i]];
429 const std::size_t ind_move = value_order_.back();
430 points_[ind_move] = twice * face_center - points_[ind_move];
431 values_[ind_move] = evaluate_on(points_[ind_move]);
432 fluctuated_values_[ind_move] =
433 values_[ind_move] - generate_fluctuation();
434 process_ = process_type::reflection;
444 const std::size_t ind_move = value_order_.back();
445 points_[ind_move] = twice * points_[ind_move] - face_center;
446 values_[ind_move] = evaluate_on(points_[ind_move]);
447 fluctuated_values_[ind_move] =
448 values_[ind_move] - generate_fluctuation();
449 process_ = process_type::reflection_and_expansion;
459 const std::size_t ind_move = value_order_.back();
460 points_[ind_move] = half * (points_[ind_move] + face_center);
461 values_[ind_move] = evaluate_on(points_[ind_move]);
462 fluctuated_values_[ind_move] =
463 values_[ind_move] - generate_fluctuation();
464 process_ = process_type::contraction;
472 const auto& min_point = points_[value_order_.front()];
473 for (std::size_t i = 1; i <= util::safe_cast<std::size_t>(dim_); ++i) {
474 const std::size_t ind_move = value_order_[i];
475 points_[ind_move] = half * (points_[ind_move] + min_point);
476 values_[ind_move] = evaluate_on(points_[ind_move]);
477 fluctuated_values_[ind_move] =
478 values_[ind_move] - generate_fluctuation();
480 process_ = process_type::multiple_contraction;
490 return temperature_ *
491 log(
static_cast<value_type>(random_number_generator_type::max()) /
492 (
static_cast<value_type>(random_number_generator_()) +
503 std::vector<variable_type, Eigen::aligned_allocator<variable_type>>
507 std::vector<value_type> values_{};
510 std::vector<value_type> fluctuated_values_{};
513 std::vector<std::size_t> value_order_{};
535 std::random_device()()};
541 static inline const auto default_highest_temperature =
545 value_type highest_temperature_{default_highest_temperature};
548 static constexpr index_type default_max_iterations_per_trial = 100;
551 index_type max_iterations_per_trial_{default_max_iterations_per_trial};
Class to write logs of iterations.
Class of tags of logs without memory management.
Class of downhill simplex method with simulated annealing press2007.
auto iterations() const noexcept -> index_type
Get the number of iterations.
auto is_stop_criteria_satisfied() const -> bool
Determine if stopping criteria of the algorithm are satisfied.
auto max_iterations_per_trial(index_type value) -> annealing_downhill_simplex &
Set the maximum number of iterations in each trial.
process_type
Type of processes.
void change_objective_function(const objective_function_type &obj_fun)
Change the objective function.
void reorder()
Reorder function values.
void contract(const variable_type &face_center)
Contract the highest point to the opposite face.
auto highest_temperature(value_type value) -> annealing_downhill_simplex &
Set the highest temperature.
auto simplex_size() const -> variable_scalar_type
Get the size of simplex.
objective_function_type obj_fun_
Objective function.
auto evaluations() const noexcept -> index_type
Get the number of function evaluations.
annealing_downhill_simplex(const objective_function_type &obj_fun=objective_function_type())
Constructor.
typename objective_function_type::value_type value_type
Type of function values.
auto calc_face_center() const -> variable_type
Calculate center of the face composed from points other than highest point.
std::mt19937 random_number_generator_type
Type of the random number generator.
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
auto last_process_name() const noexcept -> std::string_view
Get the name of the last process.
auto opt_variable() const -> const variable_type &
Get current optimal variable.
void expand(const variable_type &face_center)
Expand the simplex.
void iterate()
Iterate the algorithm once.
auto opt_value() const -> const value_type &
Get current optimal value.
auto max_iterations(index_type value) -> annealing_downhill_simplex &
Set the maximum number of iterations.
auto last_process() const noexcept -> process_type
Get last process.
typename variable_type::Scalar variable_scalar_type
Type of scalars in variables.
void init(const variable_type &init_var, const variable_scalar_type &width=default_width)
Initialize the algorithm.
static auto process_name(process_type process) -> std::string_view
Convert type of process to string.
void reflect(const variable_type &face_center)
Reflect the highest point.
ObjectiveFunction objective_function_type
Type of the objective function.
void multi_contract()
Contract all points other than the lowest point toward the lowest point.
auto seed(random_number_generator_type::result_type value) -> annealing_downhill_simplex &
Change the seed of the random number generator.
auto evaluate_on(const variable_type &variable)
Evaluate function value.
typename objective_function_type::variable_type variable_type
Type of variables.
auto generate_fluctuation() -> value_type
Generate a thermal fluctuation.
auto temperature() const noexcept -> value_type
Get the current temperature.
Class of downhill simplex method with simulated annealing press2007.
Base class of implementations of optimization algorithms.
Definition of exceptions.
Definition of index_type type.
Definition of iteration_logger class.
Definition of log_tag_view class.
Definition of macros for logging.
Definition of multi_variate_objective_function concept.
std::ptrdiff_t index_type
Type of indices in this library.
Namespace of optimization algorithms.
constexpr auto annealing_downhill_simplex_tag
Tag of annealing_downhill_simplex.
auto safe_cast(const From &value) -> To
Cast safely.
Definition of objective_function concept.
Definition of optimizer_base class.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of safe_cast function.