/builds/MusicScience37Projects/numerical-analysis/numerical-collection-cpp/include/num_collect/roots/newton_raphson.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 newton_raphson class. |
19 | | */ |
20 | | #pragma once |
21 | | |
22 | | #include <cmath> |
23 | | #include <limits> |
24 | | #include <type_traits> |
25 | | |
26 | | #include <Eigen/LU> |
27 | | |
28 | | #include "num_collect/base/exception.h" |
29 | | #include "num_collect/base/index_type.h" |
30 | | #include "num_collect/base/precondition.h" |
31 | | #include "num_collect/logging/iterations/iteration_logger.h" |
32 | | #include "num_collect/logging/log_tag_view.h" |
33 | | #include "num_collect/logging/logging_macros.h" |
34 | | #include "num_collect/roots/concepts/differentiable_function.h" |
35 | | #include "num_collect/roots/concepts/multi_variate_differentiable_function.h" |
36 | | #include "num_collect/roots/concepts/single_variate_differentiable_function.h" |
37 | | #include "num_collect/roots/function_root_finder_base.h" |
38 | | |
39 | | namespace num_collect::roots { |
40 | | |
41 | | //! Tag of newton_raphson. |
42 | | constexpr auto newton_raphson_tag = |
43 | | logging::log_tag_view("num_collect::roots::newton_raphson"); |
44 | | |
45 | | /*! |
46 | | * \brief Class of Newton-Raphson method. |
47 | | * |
48 | | * \tparam Function Type of the function of equation. |
49 | | */ |
50 | | template <concepts::differentiable_function Function> |
51 | | class newton_raphson; |
52 | | |
53 | | /*! |
54 | | * \brief Class of Newton-Raphson method. |
55 | | * |
56 | | * This version is used when variable type is a floating-point number type. |
57 | | * |
58 | | * \tparam Function Type of the function of equation. |
59 | | */ |
60 | | template <concepts::single_variate_differentiable_function Function> |
61 | | class newton_raphson<Function> |
62 | | : public function_root_finder_base<newton_raphson<Function>, Function> { |
63 | | public: |
64 | | //! Type of this object. |
65 | | using this_type = newton_raphson<Function>; |
66 | | |
67 | | //! Type of base class. |
68 | | using base_type = |
69 | | function_root_finder_base<newton_raphson<Function>, Function>; |
70 | | |
71 | | using typename base_type::function_type; |
72 | | using typename base_type::variable_type; |
73 | | |
74 | | static_assert( |
75 | | std::is_same_v<variable_type, typename function_type::jacobian_type>); |
76 | | |
77 | | /*! |
78 | | * \brief Constructor. |
79 | | * |
80 | | * \param[in] function Function of equation. |
81 | | */ |
82 | | explicit newton_raphson(const function_type& function = function_type()) |
83 | 83 | : base_type(newton_raphson_tag, function) {} _ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEEC2ERKS5_ Line | Count | Source | 83 | 46 | : base_type(newton_raphson_tag, function) {} |
_ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEEC2ERKS5_ Line | Count | Source | 83 | 34 | : base_type(newton_raphson_tag, function) {} |
_ZN11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEEC2ERKS4_ Line | Count | Source | 83 | 3 | : base_type(newton_raphson_tag, function) {} |
|
84 | | |
85 | | /*! |
86 | | * \brief Initialize. |
87 | | * |
88 | | * \param[in] variable Initial variable. |
89 | | */ |
90 | 587 | void init(const variable_type& variable) { |
91 | 587 | variable_ = variable; |
92 | 587 | last_change_ = std::numeric_limits<variable_type>::infinity(); |
93 | 587 | iterations_ = 0; |
94 | 587 | evaluations_ = 0; |
95 | | |
96 | 587 | function().evaluate_on(variable_); |
97 | 587 | ++evaluations_; |
98 | 587 | using std::abs; |
99 | 587 | value_norm_ = abs(function().value()); |
100 | 587 | } _ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE4initERKd Line | Count | Source | 90 | 304 | void init(const variable_type& variable) { | 91 | 304 | variable_ = variable; | 92 | 304 | last_change_ = std::numeric_limits<variable_type>::infinity(); | 93 | 304 | iterations_ = 0; | 94 | 304 | evaluations_ = 0; | 95 | | | 96 | 304 | function().evaluate_on(variable_); | 97 | 304 | ++evaluations_; | 98 | 304 | using std::abs; | 99 | 304 | value_norm_ = abs(function().value()); | 100 | 304 | } |
_ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE4initERKf Line | Count | Source | 90 | 280 | void init(const variable_type& variable) { | 91 | 280 | variable_ = variable; | 92 | 280 | last_change_ = std::numeric_limits<variable_type>::infinity(); | 93 | 280 | iterations_ = 0; | 94 | 280 | evaluations_ = 0; | 95 | | | 96 | 280 | function().evaluate_on(variable_); | 97 | 280 | ++evaluations_; | 98 | 280 | using std::abs; | 99 | 280 | value_norm_ = abs(function().value()); | 100 | 280 | } |
_ZN11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE4initERKd Line | Count | Source | 90 | 3 | void init(const variable_type& variable) { | 91 | 3 | variable_ = variable; | 92 | 3 | last_change_ = std::numeric_limits<variable_type>::infinity(); | 93 | 3 | iterations_ = 0; | 94 | 3 | evaluations_ = 0; | 95 | | | 96 | 3 | function().evaluate_on(variable_); | 97 | 3 | ++evaluations_; | 98 | 3 | using std::abs; | 99 | 3 | value_norm_ = abs(function().value()); | 100 | 3 | } |
|
101 | | |
102 | | //! \copydoc function_root_finder_base::iterate |
103 | 1.10k | void iterate() { |
104 | 1.10k | change_ = -function().value() / function().jacobian(); |
105 | 1.10k | variable_ += change_; |
106 | | |
107 | 1.10k | function().evaluate_on(variable_); |
108 | 1.10k | ++evaluations_; |
109 | 1.10k | ++iterations_; |
110 | 1.10k | using std::abs; |
111 | 1.10k | last_change_ = abs(change_); |
112 | 1.10k | value_norm_ = abs(function().value()); |
113 | 1.10k | } _ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE7iterateEv Line | Count | Source | 103 | 766 | void iterate() { | 104 | 766 | change_ = -function().value() / function().jacobian(); | 105 | 766 | variable_ += change_; | 106 | | | 107 | 766 | function().evaluate_on(variable_); | 108 | 766 | ++evaluations_; | 109 | 766 | ++iterations_; | 110 | 766 | using std::abs; | 111 | 766 | last_change_ = abs(change_); | 112 | 766 | value_norm_ = abs(function().value()); | 113 | 766 | } |
_ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE7iterateEv Line | Count | Source | 103 | 332 | void iterate() { | 104 | 332 | change_ = -function().value() / function().jacobian(); | 105 | 332 | variable_ += change_; | 106 | | | 107 | 332 | function().evaluate_on(variable_); | 108 | 332 | ++evaluations_; | 109 | 332 | ++iterations_; | 110 | 332 | using std::abs; | 111 | 332 | last_change_ = abs(change_); | 112 | 332 | value_norm_ = abs(function().value()); | 113 | 332 | } |
_ZN11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE7iterateEv Line | Count | Source | 103 | 5 | void iterate() { | 104 | 5 | change_ = -function().value() / function().jacobian(); | 105 | 5 | variable_ += change_; | 106 | | | 107 | 5 | function().evaluate_on(variable_); | 108 | 5 | ++evaluations_; | 109 | 5 | ++iterations_; | 110 | 5 | using std::abs; | 111 | 5 | last_change_ = abs(change_); | 112 | 5 | value_norm_ = abs(function().value()); | 113 | 5 | } |
|
114 | | |
115 | | //! \copydoc num_collect::base::iterative_solver_base::is_stop_criteria_satisfied |
116 | 1.68k | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { |
117 | 1.68k | return (iterations() > max_iterations_) || |
118 | 1.68k | (last_change() < tol_last_change_) || |
119 | 1.68k | (value_norm() < tol_value_norm_); |
120 | 1.68k | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE26is_stop_criteria_satisfiedEv Line | Count | Source | 116 | 1.07k | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { | 117 | 1.07k | return (iterations() > max_iterations_) || | 118 | 1.07k | (last_change() < tol_last_change_) || | 119 | 1.07k | (value_norm() < tol_value_norm_); | 120 | 1.07k | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE26is_stop_criteria_satisfiedEv Line | Count | Source | 116 | 612 | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { | 117 | 612 | return (iterations() > max_iterations_) || | 118 | 612 | (last_change() < tol_last_change_) || | 119 | 612 | (value_norm() < tol_value_norm_); | 120 | 612 | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE26is_stop_criteria_satisfiedEv Line | Count | Source | 116 | 5 | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { | 117 | 5 | return (iterations() > max_iterations_) || | 118 | 5 | (last_change() < tol_last_change_) || | 119 | 5 | (value_norm() < tol_value_norm_); | 120 | 5 | } |
|
121 | | |
122 | | //! \copydoc num_collect::base::iterative_solver_base::configure_iteration_logger |
123 | | void configure_iteration_logger( |
124 | | logging::iterations::iteration_logger<this_type>& iteration_logger) |
125 | 77 | const { |
126 | 77 | iteration_logger.template append<index_type>( |
127 | 77 | "Iter.", &this_type::iterations); |
128 | 77 | iteration_logger.template append<index_type>( |
129 | 77 | "Eval.", &this_type::evaluations); |
130 | 77 | iteration_logger.template append<variable_type>( |
131 | 77 | "Value", &this_type::value_norm); |
132 | 77 | iteration_logger.template append<variable_type>( |
133 | 77 | "Change", &this_type::last_change); |
134 | 77 | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE26configure_iteration_loggerERNS_7logging10iterations16iteration_loggerIS6_EE Line | Count | Source | 125 | 44 | const { | 126 | 44 | iteration_logger.template append<index_type>( | 127 | 44 | "Iter.", &this_type::iterations); | 128 | 44 | iteration_logger.template append<index_type>( | 129 | 44 | "Eval.", &this_type::evaluations); | 130 | 44 | iteration_logger.template append<variable_type>( | 131 | 44 | "Value", &this_type::value_norm); | 132 | 44 | iteration_logger.template append<variable_type>( | 133 | 44 | "Change", &this_type::last_change); | 134 | 44 | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE26configure_iteration_loggerERNS_7logging10iterations16iteration_loggerIS6_EE Line | Count | Source | 125 | 32 | const { | 126 | 32 | iteration_logger.template append<index_type>( | 127 | 32 | "Iter.", &this_type::iterations); | 128 | 32 | iteration_logger.template append<index_type>( | 129 | 32 | "Eval.", &this_type::evaluations); | 130 | 32 | iteration_logger.template append<variable_type>( | 131 | 32 | "Value", &this_type::value_norm); | 132 | 32 | iteration_logger.template append<variable_type>( | 133 | 32 | "Change", &this_type::last_change); | 134 | 32 | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE26configure_iteration_loggerERNS_7logging10iterations16iteration_loggerIS5_EE Line | Count | Source | 125 | 1 | const { | 126 | 1 | iteration_logger.template append<index_type>( | 127 | 1 | "Iter.", &this_type::iterations); | 128 | 1 | iteration_logger.template append<index_type>( | 129 | 1 | "Eval.", &this_type::evaluations); | 130 | 1 | iteration_logger.template append<variable_type>( | 131 | 1 | "Value", &this_type::value_norm); | 132 | 1 | iteration_logger.template append<variable_type>( | 133 | 1 | "Change", &this_type::last_change); | 134 | 1 | } |
|
135 | | |
136 | | using base_type::function; |
137 | | |
138 | | /*! |
139 | | * \brief Get current variable. |
140 | | * |
141 | | * \return Current variable. |
142 | | */ |
143 | 587 | [[nodiscard]] auto variable() const -> const variable_type& { |
144 | 587 | return variable_; |
145 | 587 | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE8variableEv Line | Count | Source | 143 | 304 | [[nodiscard]] auto variable() const -> const variable_type& { | 144 | 304 | return variable_; | 145 | 304 | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE8variableEv Line | Count | Source | 143 | 280 | [[nodiscard]] auto variable() const -> const variable_type& { | 144 | 280 | return variable_; | 145 | 280 | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE8variableEv Line | Count | Source | 143 | 3 | [[nodiscard]] auto variable() const -> const variable_type& { | 144 | 3 | return variable_; | 145 | 3 | } |
|
146 | | |
147 | | /*! |
148 | | * \brief Get current value. |
149 | | * |
150 | | * \return Current value. |
151 | | */ |
152 | | [[nodiscard]] auto value() const |
153 | | -> std::invoke_result_t<decltype(&function_type::value), |
154 | 1 | const function_type> { |
155 | 1 | return function().value(); |
156 | 1 | } |
157 | | |
158 | | /*! |
159 | | * \brief Get Jacobian matrix. |
160 | | * |
161 | | * \return Jacobian matrix. |
162 | | */ |
163 | | [[nodiscard]] auto jacobian() const |
164 | | -> std::invoke_result_t<decltype(&function_type::jacobian), |
165 | 1 | const function_type> { |
166 | 1 | return function().jacobian(); |
167 | 1 | } |
168 | | |
169 | | /*! |
170 | | * \brief Get the number of iterations. |
171 | | * |
172 | | * \return Number of iterations. |
173 | | */ |
174 | 2.86k | [[nodiscard]] auto iterations() const noexcept -> index_type { |
175 | 2.86k | return iterations_; |
176 | 2.86k | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE10iterationsEv Line | Count | Source | 174 | 1.67k | [[nodiscard]] auto iterations() const noexcept -> index_type { | 175 | 1.67k | return iterations_; | 176 | 1.67k | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE10iterationsEv Line | Count | Source | 174 | 1.17k | [[nodiscard]] auto iterations() const noexcept -> index_type { | 175 | 1.17k | return iterations_; | 176 | 1.17k | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE10iterationsEv Line | Count | Source | 174 | 10 | [[nodiscard]] auto iterations() const noexcept -> index_type { | 175 | 10 | return iterations_; | 176 | 10 | } |
|
177 | | |
178 | | /*! |
179 | | * \brief Get the number of function evaluations. |
180 | | * |
181 | | * \return Number of function evaluations. |
182 | | */ |
183 | 1.17k | [[nodiscard]] auto evaluations() const noexcept -> index_type { |
184 | 1.17k | return evaluations_; |
185 | 1.17k | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE11evaluationsEv Line | Count | Source | 183 | 608 | [[nodiscard]] auto evaluations() const noexcept -> index_type { | 184 | 608 | return evaluations_; | 185 | 608 | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE11evaluationsEv Line | Count | Source | 183 | 560 | [[nodiscard]] auto evaluations() const noexcept -> index_type { | 184 | 560 | return evaluations_; | 185 | 560 | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE11evaluationsEv Line | Count | Source | 183 | 4 | [[nodiscard]] auto evaluations() const noexcept -> index_type { | 184 | 4 | return evaluations_; | 185 | 4 | } |
|
186 | | |
187 | | /*! |
188 | | * \brief Get the last change of the variable. |
189 | | * |
190 | | * \return Last change of the variable. |
191 | | */ |
192 | 2.85k | [[nodiscard]] auto last_change() const noexcept -> variable_type { |
193 | 2.85k | return last_change_; |
194 | 2.85k | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE11last_changeEv Line | Count | Source | 192 | 1.67k | [[nodiscard]] auto last_change() const noexcept -> variable_type { | 193 | 1.67k | return last_change_; | 194 | 1.67k | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE11last_changeEv Line | Count | Source | 192 | 1.17k | [[nodiscard]] auto last_change() const noexcept -> variable_type { | 193 | 1.17k | return last_change_; | 194 | 1.17k | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE11last_changeEv Line | Count | Source | 192 | 9 | [[nodiscard]] auto last_change() const noexcept -> variable_type { | 193 | 9 | return last_change_; | 194 | 9 | } |
|
195 | | |
196 | | /*! |
197 | | * \brief Get the norm of function value. |
198 | | * |
199 | | * \return Norm of function value. |
200 | | */ |
201 | 2.76k | [[nodiscard]] auto value_norm() const noexcept -> variable_type { |
202 | 2.76k | return value_norm_; |
203 | 2.76k | } _ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE10value_normEv Line | Count | Source | 201 | 1.64k | [[nodiscard]] auto value_norm() const noexcept -> variable_type { | 202 | 1.64k | return value_norm_; | 203 | 1.64k | } |
_ZNK11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE10value_normEv Line | Count | Source | 201 | 1.11k | [[nodiscard]] auto value_norm() const noexcept -> variable_type { | 202 | 1.11k | return value_norm_; | 203 | 1.11k | } |
_ZNK11num_collect5roots14newton_raphsonIN16num_prob_collect5roots24cubic_root_test_functionEE10value_normEv Line | Count | Source | 201 | 8 | [[nodiscard]] auto value_norm() const noexcept -> variable_type { | 202 | 8 | return value_norm_; | 203 | 8 | } |
|
204 | | |
205 | | /*! |
206 | | * \brief Set maximum number of iterations. |
207 | | * |
208 | | * \param[in] val Value. |
209 | | * \return This. |
210 | | */ |
211 | | auto max_iterations(index_type val) -> this_type& { |
212 | | NUM_COLLECT_PRECONDITION(val > 0, this->logger(), |
213 | | "Maximum number of iterations must be a positive integer."); |
214 | | max_iterations_ = val; |
215 | | return *this; |
216 | | } |
217 | | |
218 | | /*! |
219 | | * \brief Set tolerance of last change of the variable. |
220 | | * |
221 | | * \param[in] val Value. |
222 | | * \return This. |
223 | | */ |
224 | 80 | auto tol_last_change(const variable_type& val) -> this_type& { |
225 | 80 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), |
226 | 80 | this->logger(), |
227 | 80 | "Tolerance of last change of the variable must be a " |
228 | 80 | "non-negative value."); |
229 | 80 | tol_last_change_ = val; |
230 | 80 | return *this; |
231 | 80 | } _ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE15tol_last_changeERKd Line | Count | Source | 224 | 46 | auto tol_last_change(const variable_type& val) -> this_type& { | 225 | 46 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), | 226 | 46 | this->logger(), | 227 | 46 | "Tolerance of last change of the variable must be a " | 228 | 46 | "non-negative value."); | 229 | 46 | tol_last_change_ = val; | 230 | 46 | return *this; | 231 | 46 | } |
_ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE15tol_last_changeERKf Line | Count | Source | 224 | 34 | auto tol_last_change(const variable_type& val) -> this_type& { | 225 | 34 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), | 226 | 34 | this->logger(), | 227 | 34 | "Tolerance of last change of the variable must be a " | 228 | 34 | "non-negative value."); | 229 | 34 | tol_last_change_ = val; | 230 | 34 | return *this; | 231 | 34 | } |
|
232 | | |
233 | | /*! |
234 | | * \brief Set tolerance of the norm of function value. |
235 | | * |
236 | | * \param[in] val Value. |
237 | | * \return This. |
238 | | */ |
239 | 80 | auto tol_value_norm(const variable_type& val) -> this_type& { |
240 | 80 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), |
241 | 80 | this->logger(), |
242 | 80 | "Tolerance of the norm of function value must be a " |
243 | 80 | "non-negative value."); |
244 | 80 | tol_value_norm_ = val; |
245 | 80 | return *this; |
246 | 80 | } _ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIdEEE14tol_value_normERKd Line | Count | Source | 239 | 46 | auto tol_value_norm(const variable_type& val) -> this_type& { | 240 | 46 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), | 241 | 46 | this->logger(), | 242 | 46 | "Tolerance of the norm of function value must be a " | 243 | 46 | "non-negative value."); | 244 | 46 | tol_value_norm_ = val; | 245 | 46 | return *this; | 246 | 46 | } |
_ZN11num_collect5roots14newton_raphsonINS_9functions4impl19legendre_for_newtonIfEEE14tol_value_normERKf Line | Count | Source | 239 | 34 | auto tol_value_norm(const variable_type& val) -> this_type& { | 240 | 34 | NUM_COLLECT_PRECONDITION(val >= static_cast<variable_type>(0), | 241 | 34 | this->logger(), | 242 | 34 | "Tolerance of the norm of function value must be a " | 243 | 34 | "non-negative value."); | 244 | 34 | tol_value_norm_ = val; | 245 | 34 | return *this; | 246 | 34 | } |
|
247 | | |
248 | | private: |
249 | | //! Variable. |
250 | | variable_type variable_{}; |
251 | | |
252 | | //! Change. |
253 | | variable_type change_{}; |
254 | | |
255 | | //! Number of iterations. |
256 | | index_type iterations_{}; |
257 | | |
258 | | //! Number of function evaluations. |
259 | | index_type evaluations_{}; |
260 | | |
261 | | //! Last change of the variable. |
262 | | variable_type last_change_{}; |
263 | | |
264 | | //! Norm of function value. |
265 | | variable_type value_norm_{}; |
266 | | |
267 | | //! Default maximum iterations. |
268 | | static constexpr index_type default_max_iterations = 1000; |
269 | | |
270 | | //! Maximum iterations. |
271 | | index_type max_iterations_{default_max_iterations}; |
272 | | |
273 | | //! Default tolerance of last change of the variable. |
274 | | static constexpr auto default_tol_last_change = |
275 | | static_cast<variable_type>(1e-6); |
276 | | |
277 | | //! Threshold of last change of the variable. |
278 | | variable_type tol_last_change_{default_tol_last_change}; |
279 | | |
280 | | //! Default tolerance of the norm of function value. |
281 | | static constexpr auto default_tol_value_norm = |
282 | | static_cast<variable_type>(1e-6); |
283 | | |
284 | | //! Threshold of the norm of function value. |
285 | | variable_type tol_value_norm_{default_tol_value_norm}; |
286 | | }; |
287 | | |
288 | | /*! |
289 | | * \brief Class of Newton-Raphson method. |
290 | | * |
291 | | * This version is used when variable type is Eigen's vector. |
292 | | * |
293 | | * \tparam Function Type of the function of equation. |
294 | | */ |
295 | | template <concepts::multi_variate_differentiable_function Function> |
296 | | class newton_raphson<Function> |
297 | | : public function_root_finder_base<newton_raphson<Function>, Function> { |
298 | | public: |
299 | | //! Type of this object. |
300 | | using this_type = newton_raphson<Function>; |
301 | | |
302 | | //! Type of base class. |
303 | | using base_type = |
304 | | function_root_finder_base<newton_raphson<Function>, Function>; |
305 | | |
306 | | using typename base_type::function_type; |
307 | | using typename base_type::variable_type; |
308 | | |
309 | | //! Type of scalars in variables. |
310 | | using scalar_type = typename variable_type::Scalar; |
311 | | |
312 | | //! Type of Jacobian matrices. |
313 | | using jacobian_type = typename function_type::jacobian_type; |
314 | | |
315 | | //! Type of solvers of Jacobian matrices. |
316 | | using jacobian_solver_type = |
317 | | Eigen::PartialPivLU<typename Function::jacobian_type>; |
318 | | |
319 | | /*! |
320 | | * \brief Constructor. |
321 | | * |
322 | | * \param[in] function Function of equation. |
323 | | */ |
324 | | explicit newton_raphson(const function_type& function = function_type()) |
325 | 3 | : base_type(newton_raphson_tag, function) {} |
326 | | |
327 | | /*! |
328 | | * \brief Initialize. |
329 | | * |
330 | | * \param[in] variable Initial variable. |
331 | | */ |
332 | 3 | void init(const variable_type& variable) { |
333 | 3 | variable_ = variable; |
334 | 3 | last_change_ = std::numeric_limits<scalar_type>::infinity(); |
335 | 3 | iterations_ = 0; |
336 | 3 | evaluations_ = 0; |
337 | | |
338 | 3 | function().evaluate_on(variable_); |
339 | 3 | ++evaluations_; |
340 | 3 | value_norm_ = function().value().norm(); |
341 | 3 | } |
342 | | |
343 | | //! \copydoc function_root_finder_base::iterate |
344 | 1.00k | void iterate() { |
345 | 1.00k | jacobian_solver_.compute(function().jacobian()); |
346 | 1.00k | change_ = -jacobian_solver_.solve(function().value()); |
347 | 1.00k | variable_ += change_; |
348 | | |
349 | 1.00k | function().evaluate_on(variable_); |
350 | 1.00k | ++evaluations_; |
351 | 1.00k | ++iterations_; |
352 | 1.00k | last_change_ = change_.norm(); |
353 | 1.00k | value_norm_ = function().value().norm(); |
354 | 1.00k | } |
355 | | |
356 | | //! \copydoc function_root_finder_base::is_stop_criteria_satisfied |
357 | 1.00k | [[nodiscard]] auto is_stop_criteria_satisfied() const -> bool { |
358 | 1.00k | return (iterations() > max_iterations_) || |
359 | 1.00k | (last_change() < tol_last_change_) || |
360 | 1.00k | (value_norm() < tol_value_norm_); |
361 | 1.00k | } |
362 | | |
363 | | //! \copydoc num_collect::base::iterative_solver_base::configure_iteration_logger |
364 | | void configure_iteration_logger( |
365 | | logging::iterations::iteration_logger<this_type>& iteration_logger) |
366 | 1 | const { |
367 | 1 | iteration_logger.template append<index_type>( |
368 | 1 | "Iter.", &this_type::iterations); |
369 | 1 | iteration_logger.template append<index_type>( |
370 | 1 | "Eval.", &this_type::evaluations); |
371 | 1 | iteration_logger.template append<scalar_type>( |
372 | 1 | "Value", &this_type::value_norm); |
373 | 1 | iteration_logger.template append<scalar_type>( |
374 | 1 | "Change", &this_type::last_change); |
375 | 1 | } |
376 | | |
377 | | using base_type::function; |
378 | | |
379 | | /*! |
380 | | * \brief Get current variable. |
381 | | * |
382 | | * \return Current variable. |
383 | | */ |
384 | 4 | [[nodiscard]] auto variable() const -> const variable_type& { |
385 | 4 | return variable_; |
386 | 4 | } |
387 | | |
388 | | /*! |
389 | | * \brief Get current value. |
390 | | * |
391 | | * \return Current value. |
392 | | */ |
393 | | [[nodiscard]] auto value() const |
394 | | -> std::invoke_result_t<decltype(&function_type::value), |
395 | 1 | const function_type> { |
396 | 1 | return function().value(); |
397 | 1 | } |
398 | | |
399 | | /*! |
400 | | * \brief Get Jacobian matrix. |
401 | | * |
402 | | * \return Jacobian matrix. |
403 | | */ |
404 | | [[nodiscard]] auto jacobian() const |
405 | | -> std::invoke_result_t<decltype(&function_type::jacobian), |
406 | 1 | const function_type> { |
407 | 1 | return function().jacobian(); |
408 | 1 | } |
409 | | |
410 | | /*! |
411 | | * \brief Get the number of iterations. |
412 | | * |
413 | | * \return Number of iterations. |
414 | | */ |
415 | 1.10k | [[nodiscard]] auto iterations() const noexcept -> index_type { |
416 | 1.10k | return iterations_; |
417 | 1.10k | } |
418 | | |
419 | | /*! |
420 | | * \brief Get the number of function evaluations. |
421 | | * |
422 | | * \return Number of function evaluations. |
423 | | */ |
424 | 104 | [[nodiscard]] auto evaluations() const noexcept -> index_type { |
425 | 104 | return evaluations_; |
426 | 104 | } |
427 | | |
428 | | /*! |
429 | | * \brief Get the last change of the variable. |
430 | | * |
431 | | * \return Last change of the variable. |
432 | | */ |
433 | 1.10k | [[nodiscard]] auto last_change() const noexcept -> scalar_type { |
434 | 1.10k | return last_change_; |
435 | 1.10k | } |
436 | | |
437 | | /*! |
438 | | * \brief Get the norm of function value. |
439 | | * |
440 | | * \return Norm of function value. |
441 | | */ |
442 | 1.10k | [[nodiscard]] auto value_norm() const noexcept -> scalar_type { |
443 | 1.10k | return value_norm_; |
444 | 1.10k | } |
445 | | |
446 | | /*! |
447 | | * \brief Set maximum number of iterations. |
448 | | * |
449 | | * \param[in] val Value. |
450 | | * \return This. |
451 | | */ |
452 | | auto max_iterations(index_type val) -> this_type& { |
453 | | NUM_COLLECT_PRECONDITION(val > 0, this->logger(), |
454 | | "Maximum number of iterations must be a positive integer."); |
455 | | max_iterations_ = val; |
456 | | return *this; |
457 | | } |
458 | | |
459 | | /*! |
460 | | * \brief Set tolerance of last change of the variable. |
461 | | * |
462 | | * \param[in] val Value. |
463 | | * \return This. |
464 | | */ |
465 | | auto tol_last_change(const scalar_type& val) -> this_type& { |
466 | | NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0), |
467 | | this->logger(), |
468 | | "Tolerance of last change of the variable must be a " |
469 | | "non-negative value."); |
470 | | tol_last_change_ = val; |
471 | | return *this; |
472 | | } |
473 | | |
474 | | /*! |
475 | | * \brief Set tolerance of the norm of function value. |
476 | | * |
477 | | * \param[in] val Value. |
478 | | * \return This. |
479 | | */ |
480 | | auto tol_value_norm(const scalar_type& val) -> this_type& { |
481 | | NUM_COLLECT_PRECONDITION(val >= static_cast<scalar_type>(0), |
482 | | this->logger(), |
483 | | "Tolerance of the norm of function value must be a " |
484 | | "non-negative value."); |
485 | | tol_value_norm_ = val; |
486 | | return *this; |
487 | | } |
488 | | |
489 | | private: |
490 | | //! Variable. |
491 | | variable_type variable_{}; |
492 | | |
493 | | //! Change. |
494 | | variable_type change_{}; |
495 | | |
496 | | //! Solver of Jacobian matrices. |
497 | | jacobian_solver_type jacobian_solver_{}; |
498 | | |
499 | | //! Number of iterations. |
500 | | index_type iterations_{}; |
501 | | |
502 | | //! Number of function evaluations. |
503 | | index_type evaluations_{}; |
504 | | |
505 | | //! Last change of the variable. |
506 | | scalar_type last_change_{}; |
507 | | |
508 | | //! Norm of function value. |
509 | | scalar_type value_norm_{}; |
510 | | |
511 | | //! Default maximum iterations. |
512 | | static constexpr index_type default_max_iterations = 1000; |
513 | | |
514 | | //! Maximum iterations. |
515 | | index_type max_iterations_{default_max_iterations}; |
516 | | |
517 | | //! Default tolerance of last change of the variable. |
518 | | static constexpr auto default_tol_last_change = |
519 | | static_cast<scalar_type>(1e-6); |
520 | | |
521 | | //! Threshold of last change of the variable. |
522 | | scalar_type tol_last_change_{default_tol_last_change}; |
523 | | |
524 | | //! Default tolerance of the norm of function value. |
525 | | static constexpr auto default_tol_value_norm = |
526 | | static_cast<scalar_type>(1e-6); |
527 | | |
528 | | //! Threshold of the norm of function value. |
529 | | scalar_type tol_value_norm_{default_tol_value_norm}; |
530 | | }; |
531 | | |
532 | | } // namespace num_collect::roots |