numerical-collection-cpp 0.10.0
A collection of algorithms in numerical analysis implemented in C++
Loading...
Searching...
No Matches
tv_admm.h
Go to the documentation of this file.
1/*
2 * Copyright 2024 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 */
20#pragma once
21
22#include <algorithm>
23#include <limits>
24#include <utility>
25
38#include "num_collect/regularization/impl/weak_coeff_param.h" // IWYU pragma: keep
40
42
44constexpr auto tv_admm_tag =
45 logging::log_tag_view("num_collect::regularization::tv_admm");
46
71template <typename Coeff, typename DerivativeMatrix,
78 tv_admm<Coeff, DerivativeMatrix, Data>, Data> {
79public:
82
85
86 using typename base_type::data_type;
87 using typename base_type::scalar_type;
88
90 using coeff_type = Coeff;
91
93 using derivative_matrix_type = DerivativeMatrix;
94
101
113 void compute(const Coeff& coeff, const DerivativeMatrix& derivative_matrix,
114 const Data& data) {
115 coeff_ = &coeff;
116 derivative_matrix_ = &derivative_matrix;
117 data_ = &data;
118 // Sizes will be checked in init.
119 }
120
122 void init(const scalar_type& param, data_type& solution) {
123 (void)param;
124
125 NUM_COLLECT_PRECONDITION(coeff_->rows() == data_->rows(),
126 this->logger(),
127 "Coefficient matrix and data vector must have the same number of "
128 "rows.");
129 NUM_COLLECT_PRECONDITION(coeff_->cols() == solution.rows(),
130 this->logger(),
131 "The number of columns in the coefficient matrix must match the "
132 "number of rows in solution vector.");
133 NUM_COLLECT_PRECONDITION(data_->cols() == solution.cols(),
134 this->logger(),
135 "Data and solution must have the same number of columns.");
136 NUM_COLLECT_PRECONDITION(derivative_matrix_->cols() == solution.rows(),
137 this->logger(),
138 "The number of columns in the derivative matrix must match the "
139 "number of rows in solution vector.");
140
141 iterations_ = 0;
142 derivative_ = (*derivative_matrix_) * solution;
143 lagrange_multiplier_ = data_type::Zero(derivative_matrix_->rows());
144 temp_solution_ = solution;
145 temp_data_ = data_type::Zero(data_->rows());
146 temp_derivative_ = data_type::Zero(derivative_matrix_->rows());
147 residual_ = (*coeff_) * solution - (*data_);
148 update_rate_ = std::numeric_limits<scalar_type>::infinity();
149
150 const scalar_type conjugate_gradient_tolerance_rate =
152 conjugate_gradient_.tolerance_rate(conjugate_gradient_tolerance_rate);
153 }
154
156 void iterate(const scalar_type& param, data_type& solution) {
157 // Update solution.
158 temp_solution_.noalias() =
159 static_cast<scalar_type>(2) * (*coeff_).transpose() * (*data_);
160 temp_solution_.noalias() -=
161 (*derivative_matrix_).transpose() * lagrange_multiplier_;
163 (*derivative_matrix_).transpose() * derivative_;
164 previous_solution_ = solution;
166 [this](const data_type& target, data_type& result) {
167 temp_data_.noalias() = (*coeff_) * target;
168 result.noalias() = static_cast<scalar_type>(2) *
169 (*coeff_).transpose() * temp_data_;
170 temp_derivative_.noalias() = (*derivative_matrix_) * target;
171 result.noalias() += derivative_constraint_coeff_ *
172 (*derivative_matrix_).transpose() * temp_derivative_;
173 },
174 temp_solution_, solution);
175 update_rate_ = (solution - previous_solution_).norm() /
176 (solution.norm() + std::numeric_limits<scalar_type>::epsilon());
177 residual_.noalias() = (*coeff_) * solution;
178 residual_ -= (*data_);
179
180 // Update derivative.
182 derivative_.noalias() = (*derivative_matrix_) * solution;
184 const scalar_type derivative_shrinkage_threshold =
187 derivative_, derivative_shrinkage_threshold);
189 (derivative_.norm() + std::numeric_limits<scalar_type>::epsilon());
190
191 // Update lagrange multiplier.
193 derivative_constraint_coeff_ * (*derivative_matrix_) * solution;
198 (lagrange_multiplier_.norm() +
199 std::numeric_limits<scalar_type>::epsilon());
200
201 ++iterations_;
202 }
203
205 [[nodiscard]] auto is_stop_criteria_satisfied(
206 const data_type& solution) const -> bool {
207 (void)solution;
208 return (iterations() > max_iterations()) ||
210 }
211
215 const {
216 iteration_logger.template append<index_type>(
217 "Iter.", &this_type::iterations);
218 iteration_logger.template append<scalar_type>(
219 "UpdateRate", &this_type::update_rate);
220 iteration_logger.template append<scalar_type>(
221 "Res.Rate", &this_type::residual_norm_rate);
222 }
223
225 [[nodiscard]] auto residual_norm(const data_type& solution) const
226 -> scalar_type {
227 return ((*coeff_) * solution - (*data_)).squaredNorm();
228 }
229
231 [[nodiscard]] auto regularization_term(const data_type& solution) const
232 -> scalar_type {
233 return (*derivative_matrix_ * solution).template lpNorm<1>();
234 }
235
237 void change_data(const data_type& data) { data_ = &data; }
238
240 void calculate_data_for(const data_type& solution, data_type& data) const {
241 data = (*coeff_) * solution;
242 }
243
245 [[nodiscard]] auto data_size() const -> index_type { return data_->size(); }
246
248 [[nodiscard]] auto param_search_region() const
249 -> std::pair<scalar_type, scalar_type> {
250 const data_type approx_order_of_solution = coeff_->transpose() *
252 const scalar_type approx_order_of_param =
253 (*derivative_matrix_ * approx_order_of_solution)
254 .cwiseAbs()
255 .maxCoeff();
257 this->logger(), "approx_order_of_param={}", approx_order_of_param);
258 constexpr auto tol_update_coeff_multiplier =
259 static_cast<scalar_type>(10);
260 return {approx_order_of_param *
262 tol_update_coeff_multiplier * tol_update_rate_),
263 approx_order_of_param * impl::weak_coeff_max_param<scalar_type>};
264 }
265
271 [[nodiscard]] auto iterations() const noexcept -> index_type {
272 return iterations_;
273 }
274
281 [[nodiscard]] auto update_rate() const noexcept -> scalar_type {
282 return update_rate_;
283 }
284
290 [[nodiscard]] auto residual_norm_rate() const -> scalar_type {
291 return residual_.squaredNorm() / data_->squaredNorm();
292 }
293
299 [[nodiscard]] auto max_iterations() const -> index_type {
300 return max_iterations_;
301 }
302
310 NUM_COLLECT_PRECONDITION(value > 0, this->logger(),
311 "Maximum number of iterations must be a positive integer.");
312 max_iterations_ = value;
313 return *this;
314 }
315
321 [[nodiscard]] auto tol_update_rate() const -> scalar_type {
322 return tol_update_rate_;
323 }
324
332 NUM_COLLECT_PRECONDITION(value > 0, this->logger(),
333 "Tolerance of update rate of the solution must be a positive "
334 "value.");
335 tol_update_rate_ = value;
336 return *this;
337 }
338
339private:
341 const coeff_type* coeff_{nullptr};
342
345
347 const data_type* data_{nullptr};
348
351
354
357
360
363
366
369
372
375
378
381
384
387 static_cast<scalar_type>(1);
388
392
394 static constexpr index_type default_max_iterations = 10000;
395
398
400 static constexpr auto default_tol_update_rate =
401 static_cast<scalar_type>(1e-4);
402
405
408 static_cast<scalar_type>(1e-2);
409
413};
414
415} // namespace num_collect::regularization
Definition of apply_shrinkage_operator function.
Definition of max_eigen_aat function.
Class to perform conjugate gradient (CG) method golub2013 for linear operators.
Class of tags of logs without memory management.
void configure_child_algorithm_logger_if_exists(Child &child)
Configure a logger of a child algorithm if exists.
auto logger() const noexcept -> const num_collect::logging::logger &
Access to the logger.
typename Eigen::NumTraits< typename data_type::Scalar >::Real scalar_type
Type of scalars.
scalar_type tol_update_rate_
Tolerance of update rate of the solution.
Definition tv_admm.h:404
auto param_search_region() const -> std::pair< scalar_type, scalar_type >
Get the default region to search for the optimal regularization parameter.
Definition tv_admm.h:248
index_type iterations_
Number of iterations.
Definition tv_admm.h:350
void iterate(const scalar_type &param, data_type &solution)
Iterate the algorithm once.
Definition tv_admm.h:156
const data_type * data_
Data vector.
Definition tv_admm.h:347
static constexpr index_type default_max_iterations
Default maximum number of iterations.
Definition tv_admm.h:394
static constexpr auto default_derivative_constraint_coeff
Default coefficient of the constraint for the derivative.
Definition tv_admm.h:386
data_type derivative_
Derivative.
Definition tv_admm.h:353
data_type temp_derivative_
Temporary vector with the size of the derivative.
Definition tv_admm.h:365
scalar_type update_rate_
Rate of norm of the update of the solution in the last iteration.
Definition tv_admm.h:380
auto update_rate() const noexcept -> scalar_type
Get the rate of the norm of the update of the solution in the last iteration.
Definition tv_admm.h:281
const coeff_type * coeff_
Coefficient matrix to compute data vector.
Definition tv_admm.h:341
data_type previous_derivative_
Previous derivative.
Definition tv_admm.h:371
data_type temp_data_
Temporary vector with the size of data.
Definition tv_admm.h:362
auto residual_norm_rate() const -> scalar_type
Get the rate of the last residual norm.
Definition tv_admm.h:290
auto residual_norm(const data_type &solution) const -> scalar_type
Calculate the squared norm of the residual.
Definition tv_admm.h:225
data_type lagrange_multiplier_
Lagrange multiplier.
Definition tv_admm.h:356
const derivative_matrix_type * derivative_matrix_
Matrix to compute derivative.
Definition tv_admm.h:344
iterative_regularized_solver_base< this_type, Data > base_type
Type of the base class.
Definition tv_admm.h:84
auto data_size() const -> index_type
Get the size of data.
Definition tv_admm.h:245
tv_admm< Coeff, DerivativeMatrix, Data > this_type
This type.
Definition tv_admm.h:81
data_type previous_solution_
Previous solution.
Definition tv_admm.h:368
auto max_iterations() const -> index_type
Get the maximum number of iterations.
Definition tv_admm.h:299
data_type residual_
Residual vector.
Definition tv_admm.h:377
Coeff coeff_type
Type of coefficient matrices.
Definition tv_admm.h:90
void calculate_data_for(const data_type &solution, data_type &data) const
Calculate data for a solution.
Definition tv_admm.h:240
static constexpr auto default_tol_update_rate
Default tolerance of update rate of the solution.
Definition tv_admm.h:400
auto tol_update_rate(scalar_type value) -> tv_admm &
Set the tolerance of update rate of the solution.
Definition tv_admm.h:331
static constexpr auto default_rate_of_cg_tol_rate_to_tol_update_rate
Default value of the ratio of the rate of tolerance in CG method to the tolerance of update rate of t...
Definition tv_admm.h:407
auto iterations() const noexcept -> index_type
Get the number of iterations.
Definition tv_admm.h:271
auto tol_update_rate() const -> scalar_type
Get the tolerance of update rate of the solution.
Definition tv_admm.h:321
auto max_iterations(index_type value) -> tv_admm &
Set the maximum number of iterations.
Definition tv_admm.h:309
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
Definition tv_admm.h:213
data_type lagrange_multiplier_update_
Update of lagrange multiplier.
Definition tv_admm.h:374
linear::impl::operator_conjugate_gradient< data_type > conjugate_gradient_
Conjugate gradient solver.
Definition tv_admm.h:383
DerivativeMatrix derivative_matrix_type
Type of matrices to compute derivatives.
Definition tv_admm.h:93
data_type temp_solution_
Temporary vector for the update of the solution.
Definition tv_admm.h:359
void compute(const Coeff &coeff, const DerivativeMatrix &derivative_matrix, const Data &data)
Compute internal parameters.
Definition tv_admm.h:113
scalar_type rate_of_cg_tol_rate_to_tol_update_rate_
Rate of the ratio of the rate of tolerance in CG method to the tolerance of update rate of the soluti...
Definition tv_admm.h:411
void init(const scalar_type &param, data_type &solution)
Initialize.
Definition tv_admm.h:122
auto is_stop_criteria_satisfied(const data_type &solution) const -> bool
Determine if stopping criteria of the algorithm are satisfied.
Definition tv_admm.h:205
scalar_type derivative_constraint_coeff_
Coefficient of the constraint for the derivative.
Definition tv_admm.h:390
index_type max_iterations_
Maximum number of iterations.
Definition tv_admm.h:397
auto regularization_term(const data_type &solution) const -> scalar_type
Calculate the regularization term.
Definition tv_admm.h:231
void change_data(const data_type &data)
Change data.
Definition tv_admm.h:237
Concept of Eigen's dense matrices.
Concept of Eigen's dense vectors.
Definition of dense_matrix concept.
Definition of dense_vector concept.
Definition of exceptions.
Definition of index_type type.
Definition of iteration_logger class.
Definition of iterative_regularized_solver_base class.
Definition of log_tag_view class.
Definition of macros for logging.
#define NUM_COLLECT_LOG_TRACE(LOGGER,...)
Write a trace log.
std::ptrdiff_t index_type
Type of indices in this library.
Definition index_type.h:33
auto norm(const Matrix &matrix)
Calculate norm of a matrix.
Definition norm.h:39
constexpr auto weak_coeff_min_param
Coefficient (minimum parameter to be searched) / (maximum singular value or eigen value).
auto approximate_max_eigen_aat(const Matrix &matrix) -> typename Matrix::Scalar
Approximate the maximum eigenvalue of for a matrix .
void apply_shrinkage_operator(Vector &target, typename Vector::Scalar threshold)
Apply shrinkage operator to a vector.
constexpr auto weak_coeff_max_param
Coefficient (maximum parameter to be searched) / (maximum singular value or eigen value).
Namespace of regularization algorithms.
constexpr auto tv_admm_tag
Tag of tv_admm.
Definition tv_admm.h:44
STL namespace.
Definition of operator_conjugate_gradient class.
Definition of NUM_COLLECT_PRECONDITION macro.
#define NUM_COLLECT_PRECONDITION(CONDITION,...)
Check whether a precondition is satisfied and throw an exception if not.
Definition of sparse_matrix concept.
Definition of coefficients for regularization parameters.