34#include <hash_tables/maps/multi_open_address_map_st.h>
64template <concepts::
objective_function ObjectiveFunction>
73template <concepts::multi_variate_
objective_function ObjectiveFunction>
83 using value_type =
typename objective_function_type::value_type;
93 constexpr std::size_t initial_space = 10000;
94 value_dict_.reserve_approx(initial_space);
114 "Element-wise limits must have the same size.");
116 "Element-wise limits must satisfy lower < upper for each element.");
119 width_ = upper - lower;
133 return value_dict_.get_or_create_with_factory(
134 point, [
this, &point] {
return evaluate_on(point); });
148 return opt_variable_;
172 return static_cast<index_type>(value_dict_.size());
189 width_(i) * point.elem_as<
typename variable_type::Scalar>(i);
191 obj_fun_.evaluate_on(var);
193 if (value_dict_.empty() || obj_fun_.value() < opt_value_) {
196 opt_value_ = obj_fun_.value();
199 return obj_fun_.value();
235template <base::concepts::real_scalar Value>
285 auto squared_sum =
static_cast<value_type>(0);
292 const auto half =
static_cast<value_type>(0.5);
293 return half * sqrt(squared_sum);
304 -> std::pair<ternary_vector, ternary_vector> {
305 auto res = std::make_pair(lowest_vertex, lowest_vertex);
306 const auto dim = lowest_vertex.dim();
308 const auto digits = lowest_vertex.digits(i);
310 std::uint_fast32_t one_count = 0;
318 static_cast<std::int_fast32_t
>(lowest_vertex(i, digits - 1));
320 constexpr std::uint_fast32_t odd_mask = 1;
321 if ((one_count & odd_mask) == odd_mask) {
322 res.first(i, digits - 1) =
325 res.second(i, digits - 1) =
345 std::int_fast32_t temp =
368template <base::concepts::real_scalar Value>
394 rects_.push(std::move(rect));
413 [[nodiscard]]
auto empty() const ->
bool {
return rects_.empty(); }
449 return left->ave_value() > right->ave_value();
455 std::vector<rectangle_pointer_type>,
greater>;
472template <concepts::
objective_function ObjectiveFunction>
474 :
public optimizer_base<adaptive_diagonal_curves<ObjectiveFunction>> {
486 using value_type =
typename objective_function_type::value_type;
512 return "local (last)";
516 return "global (last)";
518 return "invalid process";
582 "invalid state (bug in adaptive_diagonal_curve class)");
601 iteration_logger.template append<index_type>(
603 iteration_logger.template append<index_type>(
605 iteration_logger.template append<value_type>(
609 .template append<std::string_view>(
611 ->width(state_width);
668 "Maximum number of function evaluations must be a positive "
685 "Minimum rate of improvement in the function value required for "
686 "potentially optimal rectangles must be a positive value.");
701 "Rate of function value used to check whether the function value "
702 "decreased in the current phase must be a positive value.");
724 point.push_back(i, 0);
727 const auto [lower_vertex, upper_vertex] =
728 rectangle_type::determine_sample_points(point);
729 const auto lower_vertex_value =
value_dict_(lower_vertex);
730 const auto upper_vertex_value =
value_dict_(upper_vertex);
731 const auto ave_value =
half * (lower_vertex_value + upper_vertex_value);
732 const auto rect = std::make_shared<rectangle_type>(point, ave_value);
734 groups_.emplace_back(rect->dist());
810 const bool is_optimal_smallest =
812 const bool is_all_smallest =
815 if ((!is_optimal_smallest) || is_all_smallest) {
832 const std::size_t max_group_index = std::max<std::size_t>(
843 const std::size_t max_group_index = std::max<std::size_t>(
853 const std::size_t max_group_index =
854 (std::max<std::size_t>(
873 for (std::size_t i = 0; i <
groups_.size(); ++i) {
879 "adaptive_diagonal_curves::init is not called.");
889 std::size_t min_group, std::size_t max_group) {
890 const auto search_rect =
892 for (
auto iter = std::rbegin(search_rect);
893 iter != std::rend(search_rect); ++iter) {
906 std::size_t min_group, std::size_t max_group)
const
907 -> std::vector<std::pair<std::size_t, value_type>> {
912 std::vector<std::pair<std::size_t, value_type>> search_rects;
913 search_rects.emplace_back(
914 min_group, std::numeric_limits<value_type>::max());
917 for (std::size_t i = min_group + 1; i <= max_group; ++i) {
922 const auto& [last_i, last_slope] = search_rects.back();
924 if (slope <= last_slope) {
925 search_rects.emplace_back(i, slope);
928 search_rects.pop_back();
934 const auto value_bound =
936 for (
auto iter = search_rects.begin(); iter != search_rects.end();) {
937 const auto& [ind, slope] = *iter;
938 if (
groups_[ind].min_rect()->ave_value() -
943 iter = search_rects.erase(iter);
958 std::size_t group_ind1, std::size_t group_ind2)
const ->
value_type {
959 return (
groups_[group_ind1].min_rect()->ave_value() -
960 groups_[group_ind2].min_rect()->ave_value()) /
972 for (; divided_dim < vertex.
dim(); ++divided_dim) {
977 if (divided_dim == vertex.
dim()) {
982 const auto rect0 =
create_rect(vertex, group_ind + 1);
983 vertex(divided_dim, vertex.
digits(divided_dim) - 1) = 1;
984 const auto rect1 =
create_rect(vertex, group_ind + 1);
985 vertex(divided_dim, vertex.
digits(divided_dim) - 1) = 2;
986 const auto rect2 =
create_rect(vertex, group_ind + 1);
988 if (
groups_.size() == group_ind + 1) {
989 groups_.emplace_back(rect0->dist());
991 groups_[group_ind + 1].push(rect0);
992 groups_[group_ind + 1].push(rect1);
993 groups_[group_ind + 1].push(rect2);
1004 std::size_t group_ind) -> std::shared_ptr<rectangle_type> {
1005 const auto [vertex1, vertex2] =
1006 rectangle_type::determine_sample_points(vertex);
1009 const auto ave_value =
half * (value1 + value2);
1024 return std::make_shared<rectangle_type>(vertex, ave_value);
Definition of assertion macros.
#define NUM_COLLECT_DEBUG_ASSERT(CONDITION)
Macro to check whether a condition is satisfied in debug build only.
Class of exception on failure in algorithm.
Class of exception on not satisfying a precondition.
Class to write logs of iterations.
Class of tags of logs without memory management.
auto logger() const noexcept -> const num_collect::logging::logger &
Access to the logger.
Class of adaptive diagonal curves (ADC) method sergeyev2006 for optimization.
auto calculate_slope(std::size_t group_ind1, std::size_t group_ind2) const -> value_type
Calculate slope.
value_type decrease_rate_bound_
Rate of function value used to check whether the function value decreased in the current phase.
std::size_t optimal_group_index_
Index of the group in which the optimal solution exists.
std::size_t prec_optimal_group_index_
Index of the group in which the old optimal solution at the start of the current phase exists.
static const auto half
Half.
void iterate_locally()
Iterate once in the local phase (not last iteration).
void create_first_rectangle()
Create the first hyper-rectangle.
std::vector< group_type > groups_
Groups of hyper-rectangles.
value_type min_rate_imp_
Minimum rate of improvement in the function value required for potentially optimal rectangles.
index_type max_evaluations_
Maximum number of function evaluations.
auto max_evaluations(index_type value) -> adaptive_diagonal_curves &
Set the maximum number of function evaluations.
auto min_rate_imp(value_type value) -> adaptive_diagonal_curves &
Set the minimum rate of improvement in the function value required for potentially optimal rectangles...
void divide_rectangle(std::size_t group_ind)
Divide a hyper-rectangle.
dict_type value_dict_
Dictionary of sampled points.
void init(const variable_type &lower, const variable_type &upper)
Initialize the algorithm.
auto last_state() const noexcept -> state_type
Get the last state.
static const auto default_min_rate_imp
Default minimum rate of improvement in the function value required for potentially optimal rectangles...
auto is_stop_criteria_satisfied() const -> bool
Determine if stopping criteria of the algorithm are satisfied.
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
void switch_state()
Switch to the next state if necessary.
auto iterations() const noexcept -> index_type
Get the number of iterations.
void switch_state_on_local_last()
Switch to the next state if necessary in local_last state.
typename objective_function_type::variable_type variable_type
Type of variables.
auto evaluations() const noexcept -> index_type
Get the number of function evaluations.
adaptive_diagonal_curves(const objective_function_type &obj_fun=objective_function_type())
Constructor.
auto opt_value() const -> const value_type &
Get current optimal value.
void change_objective_function(const objective_function_type &obj_fun)
Change the objective function.
void iterate_globally()
Iterate once in the global phase (not last iteration).
void iterate()
Iterate the algorithm once.
static const auto default_decrease_rate_bound
Default rate of function value used to check whether the function value decreased in the current phas...
static auto state_name(state_type state) -> std::string_view
Convert a state to string.
static constexpr index_type default_max_evaluations
Default maximum number of function evaluations.
auto determine_nondominated_rectangles(std::size_t min_group, std::size_t max_group) const -> std::vector< std::pair< std::size_t, value_type > >
Determine nondominated hyper-rectangles.
auto create_rect(const impl::ternary_vector &vertex, std::size_t group_ind) -> std::shared_ptr< rectangle_type >
Create a hyper-rectangle.
void divide_nondominated_rectangles(std::size_t min_group, std::size_t max_group)
Divide nondominated hyper-rectangles.
typename group_type::rectangle_type rectangle_type
Type of hyper-rectangles.
auto decrease_rate_bound(value_type value) -> adaptive_diagonal_curves &
Set the rate of function value used to check whether the function value decreased in the current phas...
auto opt_variable() const -> const variable_type &
Get current optimal variable.
void iterate_globally_last()
Iterate once at teh last of the global phase.
value_type prec_optimal_value_
Old optimal value at the start of the current phase.
void iterate_locally_last()
Iterate once at the last of the local phase.
index_type iterations_in_current_phase_
Number of iterations in the current phase.
ObjectiveFunction objective_function_type
Type of the objective function.
auto min_nonempty_group_index() const -> std::size_t
Get the minimum index of non-empty groups.
value_type optimal_value_
Current optimal value.
state_type
Enumeration of states in ADC method.
@ global_last
Last iteration in global phase.
@ global
Global phase (not last iteration).
@ local_last
Last iteration in local phase.
@ local
Local phase (not last iteration).
typename objective_function_type::value_type value_type
Type of function values.
index_type iterations_
Number of iterations.
auto last_state_name() const noexcept -> std::string_view
Get the name of the last state.
Class of groups in sergeyev2006 for num_collect::opt::adaptive_diagonal_curves.
auto dist() const -> const value_type &
Get the distance between center point and vertex.
value_type dist_
Distance between center point and vertex.
auto pop() -> rectangle_pointer_type
Pick out the hyper-rectangle with the smallest average of function values at diagonal vertices.
queue_type rects_
Rectangles.
Value value_type
Type of function values.
std::shared_ptr< rectangle_type > rectangle_pointer_type
Type of pointers of hyper-rectangles.
adc_rectangle< value_type > rectangle_type
Type of hyper-rectangles.
void push(rectangle_pointer_type rect)
Add a hyper-rectangle to this group.
adc_group(value_type dist)
Constructor.
auto empty() const -> bool
Check whether this group is empty.
auto min_rect() const -> const rectangle_pointer_type &
Access the hyper-rectangle with the smallest average of function values at diagonal vertices.
std::priority_queue< rectangle_pointer_type, std::vector< rectangle_pointer_type >, greater > queue_type
Type of queues of rectangles.
Class of rectangles as proposed in sergeyev2000 for num_collect::opt::adaptive_diagonal_curves.
auto ave_value() const -> const value_type &
Get the average function value.
auto sample_points() const -> std::pair< ternary_vector, ternary_vector >
Determine sampling points.
Value value_type
Type of function values.
auto dist() const -> value_type
Get the distance between center point and vertex.
adc_rectangle(const impl::ternary_vector &vertex, const value_type &ave_value)
Constructor.
static void normalize_point(ternary_vector &point)
Normalize point.
impl::ternary_vector vertex_
A vertex with lower first component.
auto vertex() const -> const impl::ternary_vector &
Get the vertex with lower first component.
value_type ave_value_
Average function value.
static auto determine_sample_points(const ternary_vector &lowest_vertex) -> std::pair< ternary_vector, ternary_vector >
Determine sampling points.
auto opt_variable() const -> const variable_type &
Get current optimal variable.
auto evaluate_on(const ternary_vector &point) -> value_type
Evaluate function value.
ObjectiveFunction objective_function_type
Type of the objective function.
auto opt_value() const -> const value_type &
Get current optimal value.
typename objective_function_type::variable_type variable_type
Type of variables.
auto evaluations() const noexcept -> index_type
Get the number of function evaluations.
adc_sample_dict(const objective_function_type &obj_fun=objective_function_type())
Constructor.
void change_objective_function(const objective_function_type &obj_fun)
Change the objective function.
void init(const variable_type &lower, const variable_type &upper)
Initialize this object.
auto opt_point() const -> const ternary_vector &
Get the point in the unit hyper-cube for the current optimal variable.
auto operator()(const ternary_vector &point) -> value_type
Evaluate or get function value.
objective_function_type obj_fun_
Objective function.
auto dim() const -> index_type
Get the number of dimension.
typename objective_function_type::value_type value_type
Type of function values.
Class of dictionaries of sampling points in num_collect::opt::adaptive_diagonal_curves.
Class of vectors of ternary floating-point numbers.
auto digits(index_type dim) const -> index_type
Get the number of digits of a dimension.
std::int8_t digit_type
Type of a digit.
void push_back(index_type dim, digit_type digit)
Add a digit to a dimension.
auto dim() const -> index_type
Get the number of dimensions.
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.
#define NUM_COLLECT_LOG_AND_THROW(EXCEPTION_TYPE,...)
Write an error log and throw an exception for an error.
Definition of multi_variate_objective_function concept.
std::ptrdiff_t index_type
Type of indices in this library.
Namespace of optimization algorithms.
constexpr auto adaptive_diagonal_curves_tag
Tag of adaptive_diagonal_curves.
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 real_scalar concept.
Definition of safe_cast function.
Class to compare rectangles.
auto operator()(const rectangle_pointer_type &left, const rectangle_pointer_type &right) const -> bool
Compare rectangles.
Definition of ternary_vector class.