/builds/MusicScience37Projects/numerical-analysis/numerical-collection-cpp/include/num_collect/opt/adaptive_diagonal_curves.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2021 MusicScience37 (Kenta Kabashima) |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | /*! |
17 | | * \file |
18 | | * \brief Definition of dividing_rectangles class. |
19 | | */ |
20 | | #pragma once |
21 | | |
22 | | #include <algorithm> |
23 | | #include <cmath> |
24 | | #include <cstddef> |
25 | | #include <cstdint> |
26 | | #include <iterator> |
27 | | #include <limits> |
28 | | #include <string_view> |
29 | | #include <utility> |
30 | | #include <vector> |
31 | | |
32 | | #include "num_collect/base/exception.h" |
33 | | #include "num_collect/base/index_type.h" |
34 | | #include "num_collect/base/precondition.h" |
35 | | #include "num_collect/logging/iterations/iteration_logger.h" |
36 | | #include "num_collect/logging/log_tag_view.h" |
37 | | #include "num_collect/logging/logging_macros.h" |
38 | | #include "num_collect/opt/concepts/multi_variate_objective_function.h" |
39 | | #include "num_collect/opt/impl/adc_group.h" |
40 | | #include "num_collect/opt/impl/adc_sample_dict.h" |
41 | | #include "num_collect/opt/optimizer_base.h" |
42 | | #include "num_collect/util/assert.h" |
43 | | #include "num_collect/util/safe_cast.h" |
44 | | |
45 | | namespace num_collect::opt { |
46 | | |
47 | | //! Tag of adaptive_diagonal_curves. |
48 | | constexpr auto adaptive_diagonal_curves_tag = |
49 | | logging::log_tag_view("num_collect::opt::adaptive_diagonal_curves"); |
50 | | |
51 | | /*! |
52 | | * \brief Class of adaptive diagonal curves (ADC) method \cite Sergeyev2006 for |
53 | | * optimization. |
54 | | * |
55 | | * \tparam ObjectiveFunction Type of the objective function. |
56 | | * \tparam MaxDigits Maximum number of ternary digits per dimension at compile |
57 | | * time. |
58 | | */ |
59 | | template <concepts::multi_variate_objective_function ObjectiveFunction, |
60 | | index_type MaxDigits = 8> // NOLINT(*-magic-numbers) |
61 | | class adaptive_diagonal_curves |
62 | | : public optimizer_base< |
63 | | adaptive_diagonal_curves<ObjectiveFunction, MaxDigits>> { |
64 | | public: |
65 | | //! This class. |
66 | | using this_type = adaptive_diagonal_curves<ObjectiveFunction, MaxDigits>; |
67 | | |
68 | | //! Type of the objective function. |
69 | | using objective_function_type = ObjectiveFunction; |
70 | | |
71 | | //! Type of variables. |
72 | | using variable_type = typename objective_function_type::variable_type; |
73 | | |
74 | | //! Type of function values. |
75 | | using value_type = typename objective_function_type::value_type; |
76 | | |
77 | | /*! |
78 | | * \brief Enumeration of states in ADC method. |
79 | | */ |
80 | | enum class state_type : std::uint8_t { |
81 | | none, //!< No operation. |
82 | | local, //!< Local phase (not last iteration). |
83 | | local_last, //!< Last iteration in local phase. |
84 | | global, //!< Global phase (not last iteration). |
85 | | global_last, //!< Last iteration in global phase. |
86 | | non_dividable //!< No rectangle can be divided. |
87 | | }; |
88 | | |
89 | | /*! |
90 | | * \brief Convert a state to string. |
91 | | * |
92 | | * \param[in] state State. |
93 | | * \return Name of state. |
94 | | */ |
95 | 57 | [[nodiscard]] static auto state_name(state_type state) -> std::string_view { |
96 | 57 | switch (state) { |
97 | 3 | case state_type::none: |
98 | 3 | return "none"; |
99 | 5 | case state_type::local: |
100 | 5 | return "local"; |
101 | 4 | case state_type::local_last: |
102 | 4 | return "local (last)"; |
103 | 42 | case state_type::global: |
104 | 42 | return "global"; |
105 | 2 | case state_type::global_last: |
106 | 2 | return "global (last)"; |
107 | 1 | case state_type::non_dividable: |
108 | 1 | return "non dividable"; |
109 | 0 | default: |
110 | 0 | return "invalid process"; |
111 | 57 | } |
112 | 57 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE10state_nameENS5_10state_typeE Line | Count | Source | 95 | 54 | [[nodiscard]] static auto state_name(state_type state) -> std::string_view { | 96 | 54 | switch (state) { | 97 | 2 | case state_type::none: | 98 | 2 | return "none"; | 99 | 4 | case state_type::local: | 100 | 4 | return "local"; | 101 | 4 | case state_type::local_last: | 102 | 4 | return "local (last)"; | 103 | 42 | case state_type::global: | 104 | 42 | return "global"; | 105 | 2 | case state_type::global_last: | 106 | 2 | return "global (last)"; | 107 | 0 | case state_type::non_dividable: | 108 | 0 | return "non dividable"; | 109 | 0 | default: | 110 | 0 | return "invalid process"; | 111 | 54 | } | 112 | 54 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE10state_nameENS5_10state_typeE Line | Count | Source | 95 | 3 | [[nodiscard]] static auto state_name(state_type state) -> std::string_view { | 96 | 3 | switch (state) { | 97 | 1 | case state_type::none: | 98 | 1 | return "none"; | 99 | 1 | case state_type::local: | 100 | 1 | return "local"; | 101 | 0 | case state_type::local_last: | 102 | 0 | return "local (last)"; | 103 | 0 | case state_type::global: | 104 | 0 | return "global"; | 105 | 0 | case state_type::global_last: | 106 | 0 | return "global (last)"; | 107 | 1 | case state_type::non_dividable: | 108 | 1 | return "non dividable"; | 109 | 0 | default: | 110 | 0 | return "invalid process"; | 111 | 3 | } | 112 | 3 | } |
|
113 | | |
114 | | /*! |
115 | | * \brief Constructor. |
116 | | * |
117 | | * \param[in] obj_fun Objective function. |
118 | | */ |
119 | | explicit adaptive_diagonal_curves( |
120 | | const objective_function_type& obj_fun = objective_function_type()) |
121 | 5 | : optimizer_base<this_type>(adaptive_diagonal_curves_tag), |
122 | 5 | value_dict_(obj_fun) {} _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EEC2ERKS4_ Line | Count | Source | 121 | 4 | : optimizer_base<this_type>(adaptive_diagonal_curves_tag), | 122 | 4 | value_dict_(obj_fun) {} |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EEC2ERKS4_ Line | Count | Source | 121 | 1 | : optimizer_base<this_type>(adaptive_diagonal_curves_tag), | 122 | 1 | value_dict_(obj_fun) {} |
|
123 | | |
124 | | /*! |
125 | | * \brief Change the objective function. |
126 | | * |
127 | | * \param[in] obj_fun Objective function. |
128 | | */ |
129 | | void change_objective_function(const objective_function_type& obj_fun) { |
130 | | value_dict_.change_objective_function(obj_fun); |
131 | | } |
132 | | |
133 | | /*! |
134 | | * \brief Initialize the algorithm. |
135 | | * |
136 | | * \param[in] lower Lower limit. |
137 | | * \param[in] upper Upper limit. |
138 | | */ |
139 | 5 | void init(const variable_type& lower, const variable_type& upper) { |
140 | 5 | value_dict_.init(lower, upper); |
141 | 5 | groups_.clear(); |
142 | 5 | iterations_ = 0; |
143 | 5 | state_ = state_type::none; |
144 | | |
145 | | // Initialize groups_, optimal_value_, optimal_group_index_. |
146 | 5 | create_first_rectangle(); |
147 | | |
148 | | // prec_optimal_value_, prec_optimal_group_index, and |
149 | | // iterations_in_current_phase_ are initialized in switch_state(). |
150 | | |
151 | 5 | value_dict_.reserve(max_evaluations_); |
152 | 5 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE4initERKN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEESA_ Line | Count | Source | 139 | 4 | void init(const variable_type& lower, const variable_type& upper) { | 140 | 4 | value_dict_.init(lower, upper); | 141 | 4 | groups_.clear(); | 142 | 4 | iterations_ = 0; | 143 | 4 | state_ = state_type::none; | 144 | | | 145 | | // Initialize groups_, optimal_value_, optimal_group_index_. | 146 | 4 | create_first_rectangle(); | 147 | | | 148 | | // prec_optimal_value_, prec_optimal_group_index, and | 149 | | // iterations_in_current_phase_ are initialized in switch_state(). | 150 | | | 151 | 4 | value_dict_.reserve(max_evaluations_); | 152 | 4 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE4initERKN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEESA_ Line | Count | Source | 139 | 1 | void init(const variable_type& lower, const variable_type& upper) { | 140 | 1 | value_dict_.init(lower, upper); | 141 | 1 | groups_.clear(); | 142 | 1 | iterations_ = 0; | 143 | 1 | state_ = state_type::none; | 144 | | | 145 | | // Initialize groups_, optimal_value_, optimal_group_index_. | 146 | 1 | create_first_rectangle(); | 147 | | | 148 | | // prec_optimal_value_, prec_optimal_group_index, and | 149 | | // iterations_in_current_phase_ are initialized in switch_state(). | 150 | | | 151 | 1 | value_dict_.reserve(max_evaluations_); | 152 | 1 | } |
|
153 | | |
154 | | /*! |
155 | | * \copydoc num_collect::opt::optimizer_base::iterate |
156 | | */ |
157 | 526 | void iterate() { |
158 | 526 | switch_state(); |
159 | | |
160 | 526 | switch (state_) { |
161 | 79 | case state_type::local: |
162 | 79 | iterate_locally(); |
163 | 79 | break; |
164 | 26 | case state_type::local_last: |
165 | 26 | iterate_locally_last(); |
166 | 26 | break; |
167 | 397 | case state_type::global: |
168 | 397 | iterate_globally(); |
169 | 397 | break; |
170 | 23 | case state_type::global_last: |
171 | 23 | iterate_globally_last(); |
172 | 23 | break; |
173 | 1 | case state_type::non_dividable: |
174 | | // Nothing can be done. |
175 | 1 | break; |
176 | 0 | default: |
177 | 0 | NUM_COLLECT_LOG_AND_THROW(algorithm_failure, |
178 | 526 | "invalid state (bug in adaptive_diagonal_curve class)"); |
179 | 526 | } |
180 | | |
181 | 526 | ++iterations_; |
182 | 526 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE7iterateEv Line | Count | Source | 157 | 511 | void iterate() { | 158 | 511 | switch_state(); | 159 | | | 160 | 511 | switch (state_) { | 161 | 70 | case state_type::local: | 162 | 70 | iterate_locally(); | 163 | 70 | break; | 164 | 23 | case state_type::local_last: | 165 | 23 | iterate_locally_last(); | 166 | 23 | break; | 167 | 395 | case state_type::global: | 168 | 395 | iterate_globally(); | 169 | 395 | break; | 170 | 23 | case state_type::global_last: | 171 | 23 | iterate_globally_last(); | 172 | 23 | break; | 173 | 0 | case state_type::non_dividable: | 174 | | // Nothing can be done. | 175 | 0 | break; | 176 | 0 | default: | 177 | 0 | NUM_COLLECT_LOG_AND_THROW(algorithm_failure, | 178 | 511 | "invalid state (bug in adaptive_diagonal_curve class)"); | 179 | 511 | } | 180 | | | 181 | 511 | ++iterations_; | 182 | 511 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE7iterateEv Line | Count | Source | 157 | 15 | void iterate() { | 158 | 15 | switch_state(); | 159 | | | 160 | 15 | switch (state_) { | 161 | 9 | case state_type::local: | 162 | 9 | iterate_locally(); | 163 | 9 | break; | 164 | 3 | case state_type::local_last: | 165 | 3 | iterate_locally_last(); | 166 | 3 | break; | 167 | 2 | case state_type::global: | 168 | 2 | iterate_globally(); | 169 | 2 | break; | 170 | 0 | case state_type::global_last: | 171 | 0 | iterate_globally_last(); | 172 | 0 | break; | 173 | 1 | case state_type::non_dividable: | 174 | | // Nothing can be done. | 175 | 1 | break; | 176 | 0 | default: | 177 | 0 | NUM_COLLECT_LOG_AND_THROW(algorithm_failure, | 178 | 15 | "invalid state (bug in adaptive_diagonal_curve class)"); | 179 | 15 | } | 180 | | | 181 | 15 | ++iterations_; | 182 | 15 | } |
|
183 | | |
184 | | /*! |
185 | | * \copydoc num_collect::base::iterative_solver_base::is_stop_criteria_satisfied |
186 | | */ |
187 | 527 | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { |
188 | 527 | return evaluations() >= max_evaluations_ || |
189 | 527 | state_ == state_type::non_dividable; |
190 | 527 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE26is_stop_criteria_satisfiedEv Line | Count | Source | 187 | 512 | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { | 188 | 512 | return evaluations() >= max_evaluations_ || | 189 | 512 | state_ == state_type::non_dividable; | 190 | 512 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE26is_stop_criteria_satisfiedEv Line | Count | Source | 187 | 15 | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { | 188 | 15 | return evaluations() >= max_evaluations_ || | 189 | 15 | state_ == state_type::non_dividable; | 190 | 15 | } |
|
191 | | |
192 | | /*! |
193 | | * \copydoc num_collect::base::iterative_solver_base::configure_iteration_logger |
194 | | */ |
195 | | void configure_iteration_logger( |
196 | | logging::iterations::iteration_logger<this_type>& iteration_logger) |
197 | 3 | const { |
198 | 3 | iteration_logger.template append<index_type>( |
199 | 3 | "Iter.", &this_type::iterations); |
200 | 3 | iteration_logger.template append<index_type>( |
201 | 3 | "Eval.", &this_type::evaluations); |
202 | 3 | iteration_logger.template append<value_type>( |
203 | 3 | "Value", &this_type::opt_value); |
204 | 3 | constexpr index_type state_width = 15; |
205 | 3 | iteration_logger |
206 | 3 | .template append<std::string_view>( |
207 | 3 | "State", &this_type::last_state_name) |
208 | 3 | ->width(state_width); |
209 | 3 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE26configure_iteration_loggerERNS_7logging10iterations16iteration_loggerIS5_EE Line | Count | Source | 197 | 2 | const { | 198 | 2 | iteration_logger.template append<index_type>( | 199 | 2 | "Iter.", &this_type::iterations); | 200 | 2 | iteration_logger.template append<index_type>( | 201 | 2 | "Eval.", &this_type::evaluations); | 202 | 2 | iteration_logger.template append<value_type>( | 203 | 2 | "Value", &this_type::opt_value); | 204 | 2 | constexpr index_type state_width = 15; | 205 | 2 | iteration_logger | 206 | 2 | .template append<std::string_view>( | 207 | 2 | "State", &this_type::last_state_name) | 208 | 2 | ->width(state_width); | 209 | 2 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE26configure_iteration_loggerERNS_7logging10iterations16iteration_loggerIS5_EE Line | Count | Source | 197 | 1 | const { | 198 | 1 | iteration_logger.template append<index_type>( | 199 | 1 | "Iter.", &this_type::iterations); | 200 | 1 | iteration_logger.template append<index_type>( | 201 | 1 | "Eval.", &this_type::evaluations); | 202 | 1 | iteration_logger.template append<value_type>( | 203 | 1 | "Value", &this_type::opt_value); | 204 | 1 | constexpr index_type state_width = 15; | 205 | 1 | iteration_logger | 206 | 1 | .template append<std::string_view>( | 207 | 1 | "State", &this_type::last_state_name) | 208 | 1 | ->width(state_width); | 209 | 1 | } |
|
210 | | |
211 | | /*! |
212 | | * \copydoc num_collect::opt::optimizer_base::opt_variable |
213 | | */ |
214 | 3 | [[nodiscard]] auto opt_variable() const -> const variable_type& { |
215 | 3 | return value_dict_.opt_variable(); |
216 | 3 | } |
217 | | |
218 | | /*! |
219 | | * \copydoc num_collect::opt::optimizer_base::opt_value |
220 | | */ |
221 | 61 | [[nodiscard]] auto opt_value() const -> const value_type& { |
222 | 61 | return value_dict_.opt_value(); |
223 | 61 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE9opt_valueEv Line | Count | Source | 221 | 58 | [[nodiscard]] auto opt_value() const -> const value_type& { | 222 | 58 | return value_dict_.opt_value(); | 223 | 58 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE9opt_valueEv Line | Count | Source | 221 | 3 | [[nodiscard]] auto opt_value() const -> const value_type& { | 222 | 3 | return value_dict_.opt_value(); | 223 | 3 | } |
|
224 | | |
225 | | /*! |
226 | | * \copydoc num_collect::opt::optimizer_base::iterations |
227 | | */ |
228 | 59 | [[nodiscard]] auto iterations() const noexcept -> index_type { |
229 | 59 | return iterations_; |
230 | 59 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE10iterationsEv Line | Count | Source | 228 | 56 | [[nodiscard]] auto iterations() const noexcept -> index_type { | 229 | 56 | return iterations_; | 230 | 56 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE10iterationsEv Line | Count | Source | 228 | 3 | [[nodiscard]] auto iterations() const noexcept -> index_type { | 229 | 3 | return iterations_; | 230 | 3 | } |
|
231 | | |
232 | | /*! |
233 | | * \copydoc num_collect::opt::optimizer_base::evaluations |
234 | | */ |
235 | 586 | [[nodiscard]] auto evaluations() const noexcept -> index_type { |
236 | 586 | return value_dict_.evaluations(); |
237 | 586 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE11evaluationsEv Line | Count | Source | 235 | 568 | [[nodiscard]] auto evaluations() const noexcept -> index_type { | 236 | 568 | return value_dict_.evaluations(); | 237 | 568 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE11evaluationsEv Line | Count | Source | 235 | 18 | [[nodiscard]] auto evaluations() const noexcept -> index_type { | 236 | 18 | return value_dict_.evaluations(); | 237 | 18 | } |
|
238 | | |
239 | | /*! |
240 | | * \brief Get the last state. |
241 | | * |
242 | | * \return Last state. |
243 | | */ |
244 | 59 | [[nodiscard]] auto last_state() const noexcept -> state_type { |
245 | 59 | return state_; |
246 | 59 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE10last_stateEv Line | Count | Source | 244 | 54 | [[nodiscard]] auto last_state() const noexcept -> state_type { | 245 | 54 | return state_; | 246 | 54 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE10last_stateEv Line | Count | Source | 244 | 5 | [[nodiscard]] auto last_state() const noexcept -> state_type { | 245 | 5 | return state_; | 246 | 5 | } |
|
247 | | |
248 | | /*! |
249 | | * \brief Get the name of the last state. |
250 | | * |
251 | | * \return Last state. |
252 | | */ |
253 | 57 | [[nodiscard]] auto last_state_name() const noexcept -> std::string_view { |
254 | 57 | return state_name(last_state()); |
255 | 57 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE15last_state_nameEv Line | Count | Source | 253 | 54 | [[nodiscard]] auto last_state_name() const noexcept -> std::string_view { | 254 | 54 | return state_name(last_state()); | 255 | 54 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE15last_state_nameEv Line | Count | Source | 253 | 3 | [[nodiscard]] auto last_state_name() const noexcept -> std::string_view { | 254 | 3 | return state_name(last_state()); | 255 | 3 | } |
|
256 | | |
257 | | /*! |
258 | | * \brief Set the maximum number of function evaluations. |
259 | | * |
260 | | * \param[in] value Value. |
261 | | * \return This object. |
262 | | */ |
263 | 3 | auto max_evaluations(index_type value) -> adaptive_diagonal_curves& { |
264 | 3 | NUM_COLLECT_PRECONDITION(value > 0, this->logger(), |
265 | 3 | "Maximum number of function evaluations must be a positive " |
266 | 3 | "integer."); |
267 | | |
268 | 3 | max_evaluations_ = value; |
269 | 3 | return *this; |
270 | 3 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE15max_evaluationsEl Line | Count | Source | 263 | 2 | auto max_evaluations(index_type value) -> adaptive_diagonal_curves& { | 264 | 2 | NUM_COLLECT_PRECONDITION(value > 0, this->logger(), | 265 | 2 | "Maximum number of function evaluations must be a positive " | 266 | 2 | "integer."); | 267 | | | 268 | 2 | max_evaluations_ = value; | 269 | 2 | return *this; | 270 | 2 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE15max_evaluationsEl Line | Count | Source | 263 | 1 | auto max_evaluations(index_type value) -> adaptive_diagonal_curves& { | 264 | 1 | NUM_COLLECT_PRECONDITION(value > 0, this->logger(), | 265 | 1 | "Maximum number of function evaluations must be a positive " | 266 | 1 | "integer."); | 267 | | | 268 | 1 | max_evaluations_ = value; | 269 | 1 | return *this; | 270 | 1 | } |
|
271 | | |
272 | | /*! |
273 | | * \brief Set the minimum rate of improvement in the function value required |
274 | | * for potentially optimal rectangles. |
275 | | * |
276 | | * \param[in] value Value. |
277 | | * \return This object. |
278 | | */ |
279 | | auto min_rate_imp(value_type value) -> adaptive_diagonal_curves& { |
280 | | NUM_COLLECT_PRECONDITION(value > static_cast<value_type>(0), |
281 | | this->logger(), |
282 | | "Minimum rate of improvement in the function value required for " |
283 | | "potentially optimal rectangles must be a positive value."); |
284 | | min_rate_imp_ = value; |
285 | | return *this; |
286 | | } |
287 | | |
288 | | /*! |
289 | | * \brief Set the rate of function value used to check whether the function |
290 | | * value decreased in the current phase. |
291 | | * |
292 | | * \param[in] value Value. |
293 | | * \return This object. |
294 | | */ |
295 | 1 | auto decrease_rate_bound(value_type value) -> adaptive_diagonal_curves& { |
296 | 1 | NUM_COLLECT_PRECONDITION(value > static_cast<value_type>(0), |
297 | 1 | this->logger(), |
298 | 1 | "Rate of function value used to check whether the function value " |
299 | 1 | "decreased in the current phase must be a positive value."); |
300 | 1 | decrease_rate_bound_ = value; |
301 | 1 | return *this; |
302 | 1 | } |
303 | | |
304 | | private: |
305 | | //! Type of dictionaries of sample points. |
306 | | using dict_type = impl::adc_sample_dict<objective_function_type, MaxDigits>; |
307 | | |
308 | | //! Type of ternary vectors. |
309 | | using ternary_vector_type = typename dict_type::ternary_vector_type; |
310 | | |
311 | | //! Type of groups of hyper-rectangles. |
312 | | using group_type = impl::adc_group<value_type, ternary_vector_type>; |
313 | | |
314 | | //! Type of hyper-rectangles. |
315 | | using rectangle_type = typename group_type::rectangle_type; |
316 | | |
317 | | /*! |
318 | | * \brief Create the first hyper-rectangle. |
319 | | */ |
320 | 5 | void create_first_rectangle() { |
321 | 5 | const index_type dim = value_dict_.dim(); |
322 | 5 | auto point = ternary_vector_type{dim}; |
323 | 20 | for (index_type i = 0; i < dim; ++i) { |
324 | 15 | point.push_back(0); |
325 | 15 | } |
326 | | |
327 | 5 | const auto [lower_vertex, upper_vertex] = |
328 | 5 | rectangle_type::determine_sample_points(point); |
329 | 5 | const auto lower_vertex_value = value_dict_(lower_vertex); |
330 | 5 | const auto upper_vertex_value = value_dict_(upper_vertex); |
331 | 5 | const auto ave_value = half * (lower_vertex_value + upper_vertex_value); |
332 | 5 | const auto rect = rectangle_type(point, ave_value); |
333 | | |
334 | 5 | groups_.emplace_back(rect.dist()); |
335 | 5 | groups_.front().push(rect); |
336 | 5 | using std::min; |
337 | 5 | optimal_value_ = min(lower_vertex_value, upper_vertex_value); |
338 | 5 | optimal_group_index_ = 0; |
339 | 5 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE22create_first_rectangleEv Line | Count | Source | 320 | 4 | void create_first_rectangle() { | 321 | 4 | const index_type dim = value_dict_.dim(); | 322 | 4 | auto point = ternary_vector_type{dim}; | 323 | 16 | for (index_type i = 0; i < dim; ++i) { | 324 | 12 | point.push_back(0); | 325 | 12 | } | 326 | | | 327 | 4 | const auto [lower_vertex, upper_vertex] = | 328 | 4 | rectangle_type::determine_sample_points(point); | 329 | 4 | const auto lower_vertex_value = value_dict_(lower_vertex); | 330 | 4 | const auto upper_vertex_value = value_dict_(upper_vertex); | 331 | 4 | const auto ave_value = half * (lower_vertex_value + upper_vertex_value); | 332 | 4 | const auto rect = rectangle_type(point, ave_value); | 333 | | | 334 | 4 | groups_.emplace_back(rect.dist()); | 335 | 4 | groups_.front().push(rect); | 336 | 4 | using std::min; | 337 | 4 | optimal_value_ = min(lower_vertex_value, upper_vertex_value); | 338 | 4 | optimal_group_index_ = 0; | 339 | 4 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE22create_first_rectangleEv Line | Count | Source | 320 | 1 | void create_first_rectangle() { | 321 | 1 | const index_type dim = value_dict_.dim(); | 322 | 1 | auto point = ternary_vector_type{dim}; | 323 | 4 | for (index_type i = 0; i < dim; ++i) { | 324 | 3 | point.push_back(0); | 325 | 3 | } | 326 | | | 327 | 1 | const auto [lower_vertex, upper_vertex] = | 328 | 1 | rectangle_type::determine_sample_points(point); | 329 | 1 | const auto lower_vertex_value = value_dict_(lower_vertex); | 330 | 1 | const auto upper_vertex_value = value_dict_(upper_vertex); | 331 | 1 | const auto ave_value = half * (lower_vertex_value + upper_vertex_value); | 332 | 1 | const auto rect = rectangle_type(point, ave_value); | 333 | | | 334 | 1 | groups_.emplace_back(rect.dist()); | 335 | 1 | groups_.front().push(rect); | 336 | 1 | using std::min; | 337 | 1 | optimal_value_ = min(lower_vertex_value, upper_vertex_value); | 338 | 1 | optimal_group_index_ = 0; | 339 | 1 | } |
|
340 | | |
341 | | /*! |
342 | | * \brief Switch to the next state if necessary. |
343 | | * |
344 | | * Step 2.1, 2.4, 3, 4.4, 4.5, 4.7 in \cite Sergeyev2006. |
345 | | */ |
346 | 526 | void switch_state() { |
347 | 526 | using std::abs; |
348 | 526 | switch (state_) { |
349 | 78 | case state_type::local: |
350 | 78 | ++iterations_in_current_phase_; |
351 | 78 | if (iterations_in_current_phase_ > value_dict_.dim()) { |
352 | 26 | state_ = state_type::local_last; |
353 | 26 | } |
354 | 78 | return; |
355 | 26 | case state_type::local_last: |
356 | 26 | switch_state_on_local_last(); |
357 | 26 | return; |
358 | 394 | case state_type::global: |
359 | 394 | if (optimal_value_ <= prec_optimal_value_ - |
360 | 394 | decrease_rate_bound_ * abs(prec_optimal_value_)) { |
361 | 0 | state_ = state_type::local; |
362 | 0 | prec_optimal_value_ = optimal_value_; |
363 | 0 | iterations_in_current_phase_ = 1; |
364 | 0 | prec_optimal_group_index_ = optimal_group_index_; |
365 | 0 | return; |
366 | 0 | } |
367 | 394 | ++iterations_in_current_phase_; |
368 | 394 | if (iterations_in_current_phase_ > |
369 | 394 | util::safe_cast<index_type>((static_cast<std::size_t>(2) |
370 | 394 | << util::safe_cast<std::size_t>(value_dict_.dim())))) { |
371 | 23 | state_ = state_type::global_last; |
372 | 23 | return; |
373 | 23 | } |
374 | 371 | return; |
375 | 371 | case state_type::global_last: |
376 | 23 | if (optimal_value_ <= prec_optimal_value_ - |
377 | 23 | decrease_rate_bound_ * abs(prec_optimal_value_)) { |
378 | 0 | state_ = state_type::local; |
379 | 0 | prec_optimal_value_ = optimal_value_; |
380 | 0 | iterations_in_current_phase_ = 1; |
381 | 0 | prec_optimal_group_index_ = optimal_group_index_; |
382 | 0 | return; |
383 | 0 | } |
384 | 23 | state_ = state_type::global; |
385 | 23 | iterations_in_current_phase_ = 1; |
386 | 23 | prec_optimal_group_index_ = optimal_group_index_; |
387 | 23 | return; |
388 | 1 | case state_type::non_dividable: |
389 | | // Nothing can be done. |
390 | 1 | return; |
391 | 4 | default: |
392 | 4 | state_ = state_type::local; |
393 | 4 | prec_optimal_value_ = optimal_value_; |
394 | 4 | iterations_in_current_phase_ = 1; |
395 | 4 | prec_optimal_group_index_ = optimal_group_index_; |
396 | 526 | } |
397 | 526 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE12switch_stateEv Line | Count | Source | 346 | 511 | void switch_state() { | 347 | 511 | using std::abs; | 348 | 511 | switch (state_) { | 349 | 69 | case state_type::local: | 350 | 69 | ++iterations_in_current_phase_; | 351 | 69 | if (iterations_in_current_phase_ > value_dict_.dim()) { | 352 | 23 | state_ = state_type::local_last; | 353 | 23 | } | 354 | 69 | return; | 355 | 23 | case state_type::local_last: | 356 | 23 | switch_state_on_local_last(); | 357 | 23 | return; | 358 | 393 | case state_type::global: | 359 | 393 | if (optimal_value_ <= prec_optimal_value_ - | 360 | 393 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 361 | 0 | state_ = state_type::local; | 362 | 0 | prec_optimal_value_ = optimal_value_; | 363 | 0 | iterations_in_current_phase_ = 1; | 364 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 365 | 0 | return; | 366 | 0 | } | 367 | 393 | ++iterations_in_current_phase_; | 368 | 393 | if (iterations_in_current_phase_ > | 369 | 393 | util::safe_cast<index_type>((static_cast<std::size_t>(2) | 370 | 393 | << util::safe_cast<std::size_t>(value_dict_.dim())))) { | 371 | 23 | state_ = state_type::global_last; | 372 | 23 | return; | 373 | 23 | } | 374 | 370 | return; | 375 | 370 | case state_type::global_last: | 376 | 23 | if (optimal_value_ <= prec_optimal_value_ - | 377 | 23 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 378 | 0 | state_ = state_type::local; | 379 | 0 | prec_optimal_value_ = optimal_value_; | 380 | 0 | iterations_in_current_phase_ = 1; | 381 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 382 | 0 | return; | 383 | 0 | } | 384 | 23 | state_ = state_type::global; | 385 | 23 | iterations_in_current_phase_ = 1; | 386 | 23 | prec_optimal_group_index_ = optimal_group_index_; | 387 | 23 | return; | 388 | 0 | case state_type::non_dividable: | 389 | | // Nothing can be done. | 390 | 0 | return; | 391 | 3 | default: | 392 | 3 | state_ = state_type::local; | 393 | 3 | prec_optimal_value_ = optimal_value_; | 394 | 3 | iterations_in_current_phase_ = 1; | 395 | 3 | prec_optimal_group_index_ = optimal_group_index_; | 396 | 511 | } | 397 | 511 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE12switch_stateEv Line | Count | Source | 346 | 15 | void switch_state() { | 347 | 15 | using std::abs; | 348 | 15 | switch (state_) { | 349 | 9 | case state_type::local: | 350 | 9 | ++iterations_in_current_phase_; | 351 | 9 | if (iterations_in_current_phase_ > value_dict_.dim()) { | 352 | 3 | state_ = state_type::local_last; | 353 | 3 | } | 354 | 9 | return; | 355 | 3 | case state_type::local_last: | 356 | 3 | switch_state_on_local_last(); | 357 | 3 | return; | 358 | 1 | case state_type::global: | 359 | 1 | if (optimal_value_ <= prec_optimal_value_ - | 360 | 1 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 361 | 0 | state_ = state_type::local; | 362 | 0 | prec_optimal_value_ = optimal_value_; | 363 | 0 | iterations_in_current_phase_ = 1; | 364 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 365 | 0 | return; | 366 | 0 | } | 367 | 1 | ++iterations_in_current_phase_; | 368 | 1 | if (iterations_in_current_phase_ > | 369 | 1 | util::safe_cast<index_type>((static_cast<std::size_t>(2) | 370 | 1 | << util::safe_cast<std::size_t>(value_dict_.dim())))) { | 371 | 0 | state_ = state_type::global_last; | 372 | 0 | return; | 373 | 0 | } | 374 | 1 | return; | 375 | 1 | case state_type::global_last: | 376 | 0 | if (optimal_value_ <= prec_optimal_value_ - | 377 | 0 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 378 | 0 | state_ = state_type::local; | 379 | 0 | prec_optimal_value_ = optimal_value_; | 380 | 0 | iterations_in_current_phase_ = 1; | 381 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 382 | 0 | return; | 383 | 0 | } | 384 | 0 | state_ = state_type::global; | 385 | 0 | iterations_in_current_phase_ = 1; | 386 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 387 | 0 | return; | 388 | 1 | case state_type::non_dividable: | 389 | | // Nothing can be done. | 390 | 1 | return; | 391 | 1 | default: | 392 | 1 | state_ = state_type::local; | 393 | 1 | prec_optimal_value_ = optimal_value_; | 394 | 1 | iterations_in_current_phase_ = 1; | 395 | 1 | prec_optimal_group_index_ = optimal_group_index_; | 396 | 15 | } | 397 | 15 | } |
|
398 | | |
399 | | /*! |
400 | | * \brief Switch to the next state if necessary in local_last state. |
401 | | */ |
402 | 26 | void switch_state_on_local_last() { |
403 | 26 | using std::abs; |
404 | 26 | if (optimal_value_ <= prec_optimal_value_ - |
405 | 26 | decrease_rate_bound_ * abs(prec_optimal_value_)) { |
406 | 22 | state_ = state_type::local; |
407 | 22 | prec_optimal_value_ = optimal_value_; |
408 | 22 | iterations_in_current_phase_ = 1; |
409 | 22 | prec_optimal_group_index_ = optimal_group_index_; |
410 | 22 | return; |
411 | 22 | } |
412 | | |
413 | 4 | const bool is_optimal_smallest = |
414 | 4 | (optimal_group_index_ == groups_.size() - 1); |
415 | 4 | const bool is_all_smallest = |
416 | 4 | std::all_of(std::begin(groups_), std::end(groups_) - 1, |
417 | 13 | [](const group_type& group) { return group.empty(); }); _ZZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE26switch_state_on_local_lastEvENKUlRKNS0_4impl9adc_groupIdNS6_18adc_ternary_vectorIN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEELl8EEEEEE_clESF_ Line | Count | Source | 417 | 10 | [](const group_type& group) { return group.empty(); }); |
_ZZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE26switch_state_on_local_lastEvENKUlRKNS0_4impl9adc_groupIdNS6_18adc_ternary_vectorIN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEELl2EEEEEE_clESF_ Line | Count | Source | 417 | 3 | [](const group_type& group) { return group.empty(); }); |
|
418 | 4 | if ((!is_optimal_smallest) || is_all_smallest) { |
419 | 1 | state_ = state_type::local; |
420 | 1 | iterations_in_current_phase_ = 1; |
421 | 1 | prec_optimal_group_index_ = optimal_group_index_; |
422 | 1 | return; |
423 | 1 | } |
424 | | |
425 | 3 | state_ = state_type::global; |
426 | 3 | prec_optimal_value_ = optimal_value_; |
427 | 3 | iterations_in_current_phase_ = 1; |
428 | 3 | prec_optimal_group_index_ = optimal_group_index_; |
429 | 3 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE26switch_state_on_local_lastEv Line | Count | Source | 402 | 23 | void switch_state_on_local_last() { | 403 | 23 | using std::abs; | 404 | 23 | if (optimal_value_ <= prec_optimal_value_ - | 405 | 23 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 406 | 20 | state_ = state_type::local; | 407 | 20 | prec_optimal_value_ = optimal_value_; | 408 | 20 | iterations_in_current_phase_ = 1; | 409 | 20 | prec_optimal_group_index_ = optimal_group_index_; | 410 | 20 | return; | 411 | 20 | } | 412 | | | 413 | 3 | const bool is_optimal_smallest = | 414 | 3 | (optimal_group_index_ == groups_.size() - 1); | 415 | 3 | const bool is_all_smallest = | 416 | 3 | std::all_of(std::begin(groups_), std::end(groups_) - 1, | 417 | 3 | [](const group_type& group) { return group.empty(); }); | 418 | 3 | if ((!is_optimal_smallest) || is_all_smallest) { | 419 | 1 | state_ = state_type::local; | 420 | 1 | iterations_in_current_phase_ = 1; | 421 | 1 | prec_optimal_group_index_ = optimal_group_index_; | 422 | 1 | return; | 423 | 1 | } | 424 | | | 425 | 2 | state_ = state_type::global; | 426 | 2 | prec_optimal_value_ = optimal_value_; | 427 | 2 | iterations_in_current_phase_ = 1; | 428 | 2 | prec_optimal_group_index_ = optimal_group_index_; | 429 | 2 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE26switch_state_on_local_lastEv Line | Count | Source | 402 | 3 | void switch_state_on_local_last() { | 403 | 3 | using std::abs; | 404 | 3 | if (optimal_value_ <= prec_optimal_value_ - | 405 | 3 | decrease_rate_bound_ * abs(prec_optimal_value_)) { | 406 | 2 | state_ = state_type::local; | 407 | 2 | prec_optimal_value_ = optimal_value_; | 408 | 2 | iterations_in_current_phase_ = 1; | 409 | 2 | prec_optimal_group_index_ = optimal_group_index_; | 410 | 2 | return; | 411 | 2 | } | 412 | | | 413 | 1 | const bool is_optimal_smallest = | 414 | 1 | (optimal_group_index_ == groups_.size() - 1); | 415 | 1 | const bool is_all_smallest = | 416 | 1 | std::all_of(std::begin(groups_), std::end(groups_) - 1, | 417 | 1 | [](const group_type& group) { return group.empty(); }); | 418 | 1 | if ((!is_optimal_smallest) || is_all_smallest) { | 419 | 0 | state_ = state_type::local; | 420 | 0 | iterations_in_current_phase_ = 1; | 421 | 0 | prec_optimal_group_index_ = optimal_group_index_; | 422 | 0 | return; | 423 | 0 | } | 424 | | | 425 | 1 | state_ = state_type::global; | 426 | 1 | prec_optimal_value_ = optimal_value_; | 427 | 1 | iterations_in_current_phase_ = 1; | 428 | 1 | prec_optimal_group_index_ = optimal_group_index_; | 429 | 1 | } |
|
430 | | |
431 | | /*! |
432 | | * \brief Iterate once in the local phase (not last iteration). |
433 | | */ |
434 | 79 | void iterate_locally() { |
435 | 79 | const std::size_t max_group_index = std::max<std::size_t>( |
436 | 79 | std::max<std::size_t>(prec_optimal_group_index_, 1) - 1, |
437 | 79 | min_nonempty_group_index()); |
438 | 79 | divide_nondominated_rectangles( |
439 | 79 | min_nonempty_group_index(), max_group_index); |
440 | 79 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE15iterate_locallyEv Line | Count | Source | 434 | 70 | void iterate_locally() { | 435 | 70 | const std::size_t max_group_index = std::max<std::size_t>( | 436 | 70 | std::max<std::size_t>(prec_optimal_group_index_, 1) - 1, | 437 | 70 | min_nonempty_group_index()); | 438 | 70 | divide_nondominated_rectangles( | 439 | 70 | min_nonempty_group_index(), max_group_index); | 440 | 70 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE15iterate_locallyEv Line | Count | Source | 434 | 9 | void iterate_locally() { | 435 | 9 | const std::size_t max_group_index = std::max<std::size_t>( | 436 | 9 | std::max<std::size_t>(prec_optimal_group_index_, 1) - 1, | 437 | 9 | min_nonempty_group_index()); | 438 | 9 | divide_nondominated_rectangles( | 439 | 9 | min_nonempty_group_index(), max_group_index); | 440 | 9 | } |
|
441 | | |
442 | | /*! |
443 | | * \brief Iterate once at the last of the local phase. |
444 | | */ |
445 | 49 | void iterate_locally_last() { |
446 | 49 | const std::size_t max_group_index = std::max<std::size_t>( |
447 | 49 | prec_optimal_group_index_, min_nonempty_group_index()); |
448 | 49 | divide_nondominated_rectangles( |
449 | 49 | min_nonempty_group_index(), max_group_index); |
450 | 49 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE20iterate_locally_lastEv Line | Count | Source | 445 | 46 | void iterate_locally_last() { | 446 | 46 | const std::size_t max_group_index = std::max<std::size_t>( | 447 | 46 | prec_optimal_group_index_, min_nonempty_group_index()); | 448 | 46 | divide_nondominated_rectangles( | 449 | 46 | min_nonempty_group_index(), max_group_index); | 450 | 46 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE20iterate_locally_lastEv Line | Count | Source | 445 | 3 | void iterate_locally_last() { | 446 | 3 | const std::size_t max_group_index = std::max<std::size_t>( | 447 | 3 | prec_optimal_group_index_, min_nonempty_group_index()); | 448 | 3 | divide_nondominated_rectangles( | 449 | 3 | min_nonempty_group_index(), max_group_index); | 450 | 3 | } |
|
451 | | |
452 | | /*! |
453 | | * \brief Iterate once in the global phase (not last iteration). |
454 | | */ |
455 | 397 | void iterate_globally() { |
456 | 397 | const std::size_t max_group_index = |
457 | 397 | (std::max<std::size_t>( |
458 | 397 | prec_optimal_group_index_, min_nonempty_group_index()) + |
459 | 397 | min_nonempty_group_index() + 1) / |
460 | 397 | 2; |
461 | 397 | divide_nondominated_rectangles( |
462 | 397 | min_nonempty_group_index(), max_group_index); |
463 | 397 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE16iterate_globallyEv Line | Count | Source | 455 | 395 | void iterate_globally() { | 456 | 395 | const std::size_t max_group_index = | 457 | 395 | (std::max<std::size_t>( | 458 | 395 | prec_optimal_group_index_, min_nonempty_group_index()) + | 459 | 395 | min_nonempty_group_index() + 1) / | 460 | 395 | 2; | 461 | 395 | divide_nondominated_rectangles( | 462 | 395 | min_nonempty_group_index(), max_group_index); | 463 | 395 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE16iterate_globallyEv Line | Count | Source | 455 | 2 | void iterate_globally() { | 456 | 2 | const std::size_t max_group_index = | 457 | 2 | (std::max<std::size_t>( | 458 | 2 | prec_optimal_group_index_, min_nonempty_group_index()) + | 459 | 2 | min_nonempty_group_index() + 1) / | 460 | 2 | 2; | 461 | 2 | divide_nondominated_rectangles( | 462 | 2 | min_nonempty_group_index(), max_group_index); | 463 | 2 | } |
|
464 | | |
465 | | /*! |
466 | | * \brief Iterate once at teh last of the global phase. |
467 | | */ |
468 | 23 | void iterate_globally_last() { iterate_locally_last(); } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE21iterate_globally_lastEv Line | Count | Source | 468 | 23 | void iterate_globally_last() { iterate_locally_last(); } |
Unexecuted instantiation: _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE21iterate_globally_lastEv |
469 | | |
470 | | /*! |
471 | | * \brief Get the minimum index of non-empty groups. |
472 | | * |
473 | | * \return Minimum index of groups. |
474 | | */ |
475 | 1.44k | [[nodiscard]] auto min_nonempty_group_index() const -> std::size_t { |
476 | 7.94k | for (std::size_t i = 0; i < groups_.size(); ++i) { |
477 | 7.94k | if (!groups_[i].empty()) { |
478 | 1.44k | return i; |
479 | 1.44k | } |
480 | 7.94k | } |
481 | 0 | NUM_COLLECT_LOG_AND_THROW(precondition_not_satisfied, |
482 | 0 | "adaptive_diagonal_curves::init is not called."); |
483 | 0 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE24min_nonempty_group_indexEv Line | Count | Source | 475 | 1.41k | [[nodiscard]] auto min_nonempty_group_index() const -> std::size_t { | 476 | 7.85k | for (std::size_t i = 0; i < groups_.size(); ++i) { | 477 | 7.85k | if (!groups_[i].empty()) { | 478 | 1.41k | return i; | 479 | 1.41k | } | 480 | 7.85k | } | 481 | 0 | NUM_COLLECT_LOG_AND_THROW(precondition_not_satisfied, | 482 | 0 | "adaptive_diagonal_curves::init is not called."); | 483 | 0 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE24min_nonempty_group_indexEv Line | Count | Source | 475 | 30 | [[nodiscard]] auto min_nonempty_group_index() const -> std::size_t { | 476 | 83 | for (std::size_t i = 0; i < groups_.size(); ++i) { | 477 | 83 | if (!groups_[i].empty()) { | 478 | 30 | return i; | 479 | 30 | } | 480 | 83 | } | 481 | 0 | NUM_COLLECT_LOG_AND_THROW(precondition_not_satisfied, | 482 | 0 | "adaptive_diagonal_curves::init is not called."); | 483 | 0 | } |
|
484 | | |
485 | | /*! |
486 | | * \brief Divide nondominated hyper-rectangles. |
487 | | * |
488 | | * \param[in] min_group Minimum index of groups to search in. |
489 | | * \param[in] max_group Maximum index of groups to search in. |
490 | | */ |
491 | | void divide_nondominated_rectangles( |
492 | 525 | std::size_t min_group, std::size_t max_group) { |
493 | 525 | const auto search_rect = |
494 | 525 | determine_nondominated_rectangles(min_group, max_group); |
495 | 525 | bool divided_rectangle = false; |
496 | 525 | for (auto iter = std::rbegin(search_rect); |
497 | 3.24k | iter != std::rend(search_rect); ++iter) { |
498 | 2.71k | if (divide_rectangle(iter->first)) { |
499 | 2.71k | divided_rectangle = true; |
500 | 2.71k | } |
501 | 2.71k | } |
502 | 525 | if (!divided_rectangle) { |
503 | 1 | state_ = state_type::non_dividable; |
504 | 1 | this->logger().warning()( |
505 | 1 | "No rectangle can be divided. " |
506 | 1 | "Stop the iteration or tune the parameter MaxDigits."); |
507 | 1 | } |
508 | 525 | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE30divide_nondominated_rectanglesEmm Line | Count | Source | 492 | 511 | std::size_t min_group, std::size_t max_group) { | 493 | 511 | const auto search_rect = | 494 | 511 | determine_nondominated_rectangles(min_group, max_group); | 495 | 511 | bool divided_rectangle = false; | 496 | 511 | for (auto iter = std::rbegin(search_rect); | 497 | 3.21k | iter != std::rend(search_rect); ++iter) { | 498 | 2.70k | if (divide_rectangle(iter->first)) { | 499 | 2.69k | divided_rectangle = true; | 500 | 2.69k | } | 501 | 2.70k | } | 502 | 511 | if (!divided_rectangle) { | 503 | 0 | state_ = state_type::non_dividable; | 504 | 0 | this->logger().warning()( | 505 | 0 | "No rectangle can be divided. " | 506 | 0 | "Stop the iteration or tune the parameter MaxDigits."); | 507 | 0 | } | 508 | 511 | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE30divide_nondominated_rectanglesEmm Line | Count | Source | 492 | 14 | std::size_t min_group, std::size_t max_group) { | 493 | 14 | const auto search_rect = | 494 | 14 | determine_nondominated_rectangles(min_group, max_group); | 495 | 14 | bool divided_rectangle = false; | 496 | 14 | for (auto iter = std::rbegin(search_rect); | 497 | 30 | iter != std::rend(search_rect); ++iter) { | 498 | 16 | if (divide_rectangle(iter->first)) { | 499 | 13 | divided_rectangle = true; | 500 | 13 | } | 501 | 16 | } | 502 | 14 | if (!divided_rectangle) { | 503 | 1 | state_ = state_type::non_dividable; | 504 | 1 | this->logger().warning()( | 505 | 1 | "No rectangle can be divided. " | 506 | 1 | "Stop the iteration or tune the parameter MaxDigits."); | 507 | 1 | } | 508 | 14 | } |
|
509 | | |
510 | | /*! |
511 | | * \brief Determine nondominated hyper-rectangles. |
512 | | * |
513 | | * \param[in] min_group Minimum index of groups to search in. |
514 | | * \param[in] max_group Maximum index of groups to search in. |
515 | | * \return List of (index of group, slope). |
516 | | */ |
517 | | [[nodiscard]] auto determine_nondominated_rectangles( |
518 | | std::size_t min_group, std::size_t max_group) const |
519 | 525 | -> std::vector<std::pair<std::size_t, value_type>> { |
520 | 525 | NUM_COLLECT_DEBUG_ASSERT(min_group <= max_group); |
521 | 525 | NUM_COLLECT_DEBUG_ASSERT(max_group < groups_.size()); |
522 | 525 | NUM_COLLECT_DEBUG_ASSERT(!groups_[min_group].empty()); |
523 | | |
524 | 525 | std::vector<std::pair<std::size_t, value_type>> search_rects; |
525 | 525 | search_rects.emplace_back( |
526 | 525 | min_group, std::numeric_limits<value_type>::max()); |
527 | | |
528 | | // convex full scan |
529 | 3.23k | for (std::size_t i = min_group + 1; i <= max_group; ++i) { |
530 | 2.71k | if (groups_[i].empty()) { |
531 | 3 | continue; |
532 | 3 | } |
533 | 3.22k | while (true) { |
534 | 3.22k | const auto& [last_i, last_slope] = search_rects.back(); |
535 | 3.22k | const auto slope = calculate_slope(last_i, i); |
536 | 3.22k | if (slope <= last_slope) { |
537 | 2.70k | search_rects.emplace_back(i, slope); |
538 | 2.70k | break; |
539 | 2.70k | } |
540 | 515 | search_rects.pop_back(); |
541 | 515 | } |
542 | 2.70k | } |
543 | | |
544 | | // remove rectangles which won't update optimal value |
545 | 525 | using std::abs; |
546 | 525 | const auto value_bound = |
547 | 525 | optimal_value_ - min_rate_imp_ * abs(optimal_value_); |
548 | 3.24k | for (auto iter = search_rects.begin(); iter != search_rects.end();) { |
549 | 2.71k | const auto& [ind, slope] = *iter; |
550 | 2.71k | if (groups_[ind].min_rect().ave_value() - |
551 | 2.71k | slope * groups_[ind].dist() <= |
552 | 2.71k | value_bound) { |
553 | 2.71k | ++iter; |
554 | 2.71k | } else { |
555 | 0 | iter = search_rects.erase(iter); |
556 | 0 | } |
557 | 2.71k | } |
558 | | |
559 | 525 | return search_rects; |
560 | 525 | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE33determine_nondominated_rectanglesEmm Line | Count | Source | 519 | 511 | -> std::vector<std::pair<std::size_t, value_type>> { | 520 | 511 | NUM_COLLECT_DEBUG_ASSERT(min_group <= max_group); | 521 | 511 | NUM_COLLECT_DEBUG_ASSERT(max_group < groups_.size()); | 522 | 511 | NUM_COLLECT_DEBUG_ASSERT(!groups_[min_group].empty()); | 523 | | | 524 | 511 | std::vector<std::pair<std::size_t, value_type>> search_rects; | 525 | 511 | search_rects.emplace_back( | 526 | 511 | min_group, std::numeric_limits<value_type>::max()); | 527 | | | 528 | | // convex full scan | 529 | 3.22k | for (std::size_t i = min_group + 1; i <= max_group; ++i) { | 530 | 2.71k | if (groups_[i].empty()) { | 531 | 3 | continue; | 532 | 3 | } | 533 | 3.22k | while (true) { | 534 | 3.22k | const auto& [last_i, last_slope] = search_rects.back(); | 535 | 3.22k | const auto slope = calculate_slope(last_i, i); | 536 | 3.22k | if (slope <= last_slope) { | 537 | 2.70k | search_rects.emplace_back(i, slope); | 538 | 2.70k | break; | 539 | 2.70k | } | 540 | 515 | search_rects.pop_back(); | 541 | 515 | } | 542 | 2.70k | } | 543 | | | 544 | | // remove rectangles which won't update optimal value | 545 | 511 | using std::abs; | 546 | 511 | const auto value_bound = | 547 | 511 | optimal_value_ - min_rate_imp_ * abs(optimal_value_); | 548 | 3.21k | for (auto iter = search_rects.begin(); iter != search_rects.end();) { | 549 | 2.70k | const auto& [ind, slope] = *iter; | 550 | 2.70k | if (groups_[ind].min_rect().ave_value() - | 551 | 2.70k | slope * groups_[ind].dist() <= | 552 | 2.70k | value_bound) { | 553 | 2.70k | ++iter; | 554 | 2.70k | } else { | 555 | 0 | iter = search_rects.erase(iter); | 556 | 0 | } | 557 | 2.70k | } | 558 | | | 559 | 511 | return search_rects; | 560 | 511 | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE33determine_nondominated_rectanglesEmm Line | Count | Source | 519 | 14 | -> std::vector<std::pair<std::size_t, value_type>> { | 520 | 14 | NUM_COLLECT_DEBUG_ASSERT(min_group <= max_group); | 521 | 14 | NUM_COLLECT_DEBUG_ASSERT(max_group < groups_.size()); | 522 | 14 | NUM_COLLECT_DEBUG_ASSERT(!groups_[min_group].empty()); | 523 | | | 524 | 14 | std::vector<std::pair<std::size_t, value_type>> search_rects; | 525 | 14 | search_rects.emplace_back( | 526 | 14 | min_group, std::numeric_limits<value_type>::max()); | 527 | | | 528 | | // convex full scan | 529 | 16 | for (std::size_t i = min_group + 1; i <= max_group; ++i) { | 530 | 2 | if (groups_[i].empty()) { | 531 | 0 | continue; | 532 | 0 | } | 533 | 2 | while (true) { | 534 | 2 | const auto& [last_i, last_slope] = search_rects.back(); | 535 | 2 | const auto slope = calculate_slope(last_i, i); | 536 | 2 | if (slope <= last_slope) { | 537 | 2 | search_rects.emplace_back(i, slope); | 538 | 2 | break; | 539 | 2 | } | 540 | 0 | search_rects.pop_back(); | 541 | 0 | } | 542 | 2 | } | 543 | | | 544 | | // remove rectangles which won't update optimal value | 545 | 14 | using std::abs; | 546 | 14 | const auto value_bound = | 547 | 14 | optimal_value_ - min_rate_imp_ * abs(optimal_value_); | 548 | 30 | for (auto iter = search_rects.begin(); iter != search_rects.end();) { | 549 | 16 | const auto& [ind, slope] = *iter; | 550 | 16 | if (groups_[ind].min_rect().ave_value() - | 551 | 16 | slope * groups_[ind].dist() <= | 552 | 16 | value_bound) { | 553 | 16 | ++iter; | 554 | 16 | } else { | 555 | 0 | iter = search_rects.erase(iter); | 556 | 0 | } | 557 | 16 | } | 558 | | | 559 | 14 | return search_rects; | 560 | 14 | } |
|
561 | | |
562 | | /*! |
563 | | * \brief Calculate slope. |
564 | | * |
565 | | * \param[in] group_ind1 Index of group. |
566 | | * \param[in] group_ind2 Index of group. |
567 | | * \return Slope. |
568 | | */ |
569 | | [[nodiscard]] auto calculate_slope( |
570 | 3.22k | std::size_t group_ind1, std::size_t group_ind2) const -> value_type { |
571 | 3.22k | return (groups_[group_ind1].min_rect().ave_value() - |
572 | 3.22k | groups_[group_ind2].min_rect().ave_value()) / |
573 | 3.22k | (groups_[group_ind1].dist() - groups_[group_ind2].dist()); |
574 | 3.22k | } _ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE15calculate_slopeEmm Line | Count | Source | 570 | 3.22k | std::size_t group_ind1, std::size_t group_ind2) const -> value_type { | 571 | 3.22k | return (groups_[group_ind1].min_rect().ave_value() - | 572 | 3.22k | groups_[group_ind2].min_rect().ave_value()) / | 573 | 3.22k | (groups_[group_ind1].dist() - groups_[group_ind2].dist()); | 574 | 3.22k | } |
_ZNK11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE15calculate_slopeEmm Line | Count | Source | 570 | 2 | std::size_t group_ind1, std::size_t group_ind2) const -> value_type { | 571 | 2 | return (groups_[group_ind1].min_rect().ave_value() - | 572 | 2 | groups_[group_ind2].min_rect().ave_value()) / | 573 | 2 | (groups_[group_ind1].dist() - groups_[group_ind2].dist()); | 574 | 2 | } |
|
575 | | |
576 | | /*! |
577 | | * \brief Divide a hyper-rectangle. |
578 | | * |
579 | | * \param[in] group_ind Index of group. |
580 | | * \retval true The hyper-rectangle is divided. |
581 | | * \retval false The hyper-rectangle is not divided. |
582 | | */ |
583 | 2.71k | [[nodiscard]] auto divide_rectangle(std::size_t group_ind) -> bool { |
584 | 2.71k | if (!groups_[group_ind].is_dividable()) { |
585 | 9 | return false; |
586 | 9 | } |
587 | | |
588 | 2.71k | impl::adc_ternary_vector vertex = |
589 | 2.71k | std::move(groups_[group_ind].pop().vertex()); |
590 | | |
591 | 2.71k | const auto [dim, digit] = vertex.push_back(0); |
592 | 2.71k | const auto rect0 = create_rect(vertex, group_ind + 1); |
593 | 2.71k | vertex(dim, digit) = 1; |
594 | 2.71k | const auto rect1 = create_rect(vertex, group_ind + 1); |
595 | 2.71k | vertex(dim, digit) = 2; |
596 | 2.71k | const auto rect2 = create_rect(vertex, group_ind + 1); |
597 | | |
598 | 2.71k | if (groups_.size() == group_ind + 1) { |
599 | 46 | groups_.emplace_back(rect0.dist()); |
600 | 46 | } |
601 | 2.71k | groups_[group_ind + 1].push(rect0); |
602 | 2.71k | groups_[group_ind + 1].push(rect1); |
603 | 2.71k | groups_[group_ind + 1].push(rect2); |
604 | | |
605 | 2.71k | return true; |
606 | 2.71k | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE16divide_rectangleEm Line | Count | Source | 583 | 2.70k | [[nodiscard]] auto divide_rectangle(std::size_t group_ind) -> bool { | 584 | 2.70k | if (!groups_[group_ind].is_dividable()) { | 585 | 6 | return false; | 586 | 6 | } | 587 | | | 588 | 2.69k | impl::adc_ternary_vector vertex = | 589 | 2.69k | std::move(groups_[group_ind].pop().vertex()); | 590 | | | 591 | 2.69k | const auto [dim, digit] = vertex.push_back(0); | 592 | 2.69k | const auto rect0 = create_rect(vertex, group_ind + 1); | 593 | 2.69k | vertex(dim, digit) = 1; | 594 | 2.69k | const auto rect1 = create_rect(vertex, group_ind + 1); | 595 | 2.69k | vertex(dim, digit) = 2; | 596 | 2.69k | const auto rect2 = create_rect(vertex, group_ind + 1); | 597 | | | 598 | 2.69k | if (groups_.size() == group_ind + 1) { | 599 | 43 | groups_.emplace_back(rect0.dist()); | 600 | 43 | } | 601 | 2.69k | groups_[group_ind + 1].push(rect0); | 602 | 2.69k | groups_[group_ind + 1].push(rect1); | 603 | 2.69k | groups_[group_ind + 1].push(rect2); | 604 | | | 605 | 2.69k | return true; | 606 | 2.70k | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE16divide_rectangleEm Line | Count | Source | 583 | 16 | [[nodiscard]] auto divide_rectangle(std::size_t group_ind) -> bool { | 584 | 16 | if (!groups_[group_ind].is_dividable()) { | 585 | 3 | return false; | 586 | 3 | } | 587 | | | 588 | 13 | impl::adc_ternary_vector vertex = | 589 | 13 | std::move(groups_[group_ind].pop().vertex()); | 590 | | | 591 | 13 | const auto [dim, digit] = vertex.push_back(0); | 592 | 13 | const auto rect0 = create_rect(vertex, group_ind + 1); | 593 | 13 | vertex(dim, digit) = 1; | 594 | 13 | const auto rect1 = create_rect(vertex, group_ind + 1); | 595 | 13 | vertex(dim, digit) = 2; | 596 | 13 | const auto rect2 = create_rect(vertex, group_ind + 1); | 597 | | | 598 | 13 | if (groups_.size() == group_ind + 1) { | 599 | 3 | groups_.emplace_back(rect0.dist()); | 600 | 3 | } | 601 | 13 | groups_[group_ind + 1].push(rect0); | 602 | 13 | groups_[group_ind + 1].push(rect1); | 603 | 13 | groups_[group_ind + 1].push(rect2); | 604 | | | 605 | 13 | return true; | 606 | 16 | } |
|
607 | | |
608 | | /*! |
609 | | * \brief Create a hyper-rectangle. |
610 | | * |
611 | | * \param[in] vertex Vertex with lower first component. |
612 | | * \param[in] group_ind Group index. |
613 | | * \return Hyper-rectangle. |
614 | | */ |
615 | | [[nodiscard]] auto create_rect(const ternary_vector_type& vertex, |
616 | 8.13k | std::size_t group_ind) -> rectangle_type { |
617 | 8.13k | const auto [vertex1, vertex2] = |
618 | 8.13k | rectangle_type::determine_sample_points(vertex); |
619 | 8.13k | const auto value1 = value_dict_(vertex1); |
620 | 8.13k | const auto value2 = value_dict_(vertex2); |
621 | 8.13k | const auto ave_value = half * (value1 + value2); |
622 | 8.13k | if (value1 < optimal_value_) { |
623 | 38 | optimal_value_ = value1; |
624 | 38 | optimal_group_index_ = group_ind; |
625 | 8.09k | } else if (value1 <= optimal_value_ && |
626 | 8.09k | group_ind > optimal_group_index_) { |
627 | 22 | optimal_group_index_ = group_ind; |
628 | 22 | } |
629 | 8.13k | if (value2 < optimal_value_) { |
630 | 30 | optimal_value_ = value2; |
631 | 30 | optimal_group_index_ = group_ind; |
632 | 8.10k | } else if (value2 <= optimal_value_ && |
633 | 8.10k | group_ind > optimal_group_index_) { |
634 | 0 | optimal_group_index_ = group_ind; |
635 | 0 | } |
636 | 8.13k | return rectangle_type(vertex, ave_value); |
637 | 8.13k | } _ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl8EE11create_rectERKNS0_4impl18adc_ternary_vectorIN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEELl8EEEm Line | Count | Source | 616 | 8.09k | std::size_t group_ind) -> rectangle_type { | 617 | 8.09k | const auto [vertex1, vertex2] = | 618 | 8.09k | rectangle_type::determine_sample_points(vertex); | 619 | 8.09k | const auto value1 = value_dict_(vertex1); | 620 | 8.09k | const auto value2 = value_dict_(vertex2); | 621 | 8.09k | const auto ave_value = half * (value1 + value2); | 622 | 8.09k | if (value1 < optimal_value_) { | 623 | 36 | optimal_value_ = value1; | 624 | 36 | optimal_group_index_ = group_ind; | 625 | 8.05k | } else if (value1 <= optimal_value_ && | 626 | 8.05k | group_ind > optimal_group_index_) { | 627 | 19 | optimal_group_index_ = group_ind; | 628 | 19 | } | 629 | 8.09k | if (value2 < optimal_value_) { | 630 | 27 | optimal_value_ = value2; | 631 | 27 | optimal_group_index_ = group_ind; | 632 | 8.06k | } else if (value2 <= optimal_value_ && | 633 | 8.06k | group_ind > optimal_group_index_) { | 634 | 0 | optimal_group_index_ = group_ind; | 635 | 0 | } | 636 | 8.09k | return rectangle_type(vertex, ave_value); | 637 | 8.09k | } |
_ZN11num_collect3opt24adaptive_diagonal_curvesIN16num_prob_collect3opt24multi_quadratic_functionELl2EE11create_rectERKNS0_4impl18adc_ternary_vectorIN5Eigen6MatrixIdLin1ELi1ELi0ELin1ELi1EEELl2EEEm Line | Count | Source | 616 | 39 | std::size_t group_ind) -> rectangle_type { | 617 | 39 | const auto [vertex1, vertex2] = | 618 | 39 | rectangle_type::determine_sample_points(vertex); | 619 | 39 | const auto value1 = value_dict_(vertex1); | 620 | 39 | const auto value2 = value_dict_(vertex2); | 621 | 39 | const auto ave_value = half * (value1 + value2); | 622 | 39 | if (value1 < optimal_value_) { | 623 | 2 | optimal_value_ = value1; | 624 | 2 | optimal_group_index_ = group_ind; | 625 | 37 | } else if (value1 <= optimal_value_ && | 626 | 37 | group_ind > optimal_group_index_) { | 627 | 3 | optimal_group_index_ = group_ind; | 628 | 3 | } | 629 | 39 | if (value2 < optimal_value_) { | 630 | 3 | optimal_value_ = value2; | 631 | 3 | optimal_group_index_ = group_ind; | 632 | 36 | } else if (value2 <= optimal_value_ && | 633 | 36 | group_ind > optimal_group_index_) { | 634 | 0 | optimal_group_index_ = group_ind; | 635 | 0 | } | 636 | 39 | return rectangle_type(vertex, ave_value); | 637 | 39 | } |
|
638 | | |
639 | | //! Half. |
640 | | static inline const auto half = static_cast<value_type>(0.5); |
641 | | |
642 | | //! Dictionary of sampled points. |
643 | | dict_type value_dict_; |
644 | | |
645 | | //! Groups of hyper-rectangles. |
646 | | std::vector<group_type> groups_{}; |
647 | | |
648 | | //! Number of iterations. |
649 | | index_type iterations_{0}; |
650 | | |
651 | | //! State. |
652 | | state_type state_{state_type::none}; |
653 | | |
654 | | /*! |
655 | | * \brief Current optimal value. |
656 | | * |
657 | | * This value is used for updating \ref optimal_group_index_. |
658 | | */ |
659 | | value_type optimal_value_{}; |
660 | | |
661 | | //! Index of the group in which the optimal solution exists. |
662 | | std::size_t optimal_group_index_{0}; |
663 | | |
664 | | //! Old optimal value at the start of the current phase. |
665 | | value_type prec_optimal_value_{}; |
666 | | |
667 | | /*! |
668 | | * \brief Index of the group in which the old optimal solution at the start |
669 | | * of the current phase exists. |
670 | | */ |
671 | | std::size_t prec_optimal_group_index_{0}; |
672 | | |
673 | | /*! |
674 | | * \brief Number of iterations in the current phase. |
675 | | * |
676 | | * This is initialized at the start of the local or global phases. |
677 | | */ |
678 | | index_type iterations_in_current_phase_{0}; |
679 | | |
680 | | //! Default maximum number of function evaluations. |
681 | | static constexpr index_type default_max_evaluations = 10000; |
682 | | |
683 | | //! Maximum number of function evaluations. |
684 | | index_type max_evaluations_{default_max_evaluations}; |
685 | | |
686 | | /*! |
687 | | * \brief Default minimum rate of improvement in the function value required |
688 | | * for potentially optimal rectangles. |
689 | | */ |
690 | | static inline const auto default_min_rate_imp = |
691 | | static_cast<value_type>(1e-4); |
692 | | |
693 | | /*! |
694 | | * \brief Minimum rate of improvement in the function value required for |
695 | | * potentially optimal rectangles. |
696 | | */ |
697 | | value_type min_rate_imp_{default_min_rate_imp}; |
698 | | |
699 | | /*! |
700 | | * \brief Default rate of function value used to check whether the function |
701 | | * value decreased in the current phase. |
702 | | */ |
703 | | static inline const auto default_decrease_rate_bound = |
704 | | static_cast<value_type>(0.01); |
705 | | |
706 | | /*! |
707 | | * \brief Rate of function value used to check whether the function value |
708 | | * decreased in the current phase. |
709 | | */ |
710 | | value_type decrease_rate_bound_{default_decrease_rate_bound}; |
711 | | }; |
712 | | |
713 | | } // namespace num_collect::opt |