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
56template <typename Coeff, typename DerivativeMatrix,
63 tv_admm<Coeff, DerivativeMatrix, Data>, Data> {
64public:
67
70
71 using typename base_type::data_type;
72 using typename base_type::scalar_type;
73
75 using coeff_type = Coeff;
76
78 using derivative_matrix_type = DerivativeMatrix;
79
86
98 void compute(const Coeff& coeff, const DerivativeMatrix& derivative_matrix,
99 const Data& data) {
100 coeff_ = &coeff;
101 derivative_matrix_ = &derivative_matrix;
102 data_ = &data;
103 }
104
106 void init(const scalar_type& param, data_type& solution) {
107 (void)param;
108
109 NUM_COLLECT_PRECONDITION(coeff_->rows() == data_->rows(),
110 this->logger(),
111 "Coefficient matrix and data vector must have the same number of "
112 "rows.");
113 NUM_COLLECT_PRECONDITION(coeff_->cols() == solution.rows(),
114 this->logger(),
115 "The number of columns in the coefficient matrix must match the "
116 "number of rows in solution vector.");
117 NUM_COLLECT_PRECONDITION(data_->cols() == solution.cols(),
118 this->logger(),
119 "Data and solution must have the same number of columns.");
120 NUM_COLLECT_PRECONDITION(derivative_matrix_->cols() == solution.rows(),
121 this->logger(),
122 "The number of columns in the derivative matrix must match the "
123 "number of rows in solution vector.");
124
125 iterations_ = 0;
126 derivative_ = (*derivative_matrix_) * solution;
127 lagrange_multiplier_ = data_type::Zero(derivative_matrix_->rows());
128 temp_solution_ = solution;
129 residual_ = (*coeff_) * solution - (*data_);
130 update_rate_ = std::numeric_limits<scalar_type>::infinity();
131
132 const scalar_type conjugate_gradient_tolerance_rate =
134 conjugate_gradient_.tolerance_rate(conjugate_gradient_tolerance_rate);
135 }
136
138 void iterate(const scalar_type& param, data_type& solution) {
139 // Update solution.
141 static_cast<scalar_type>(2) * (*coeff_).transpose() * (*data_) -
142 (*derivative_matrix_).transpose() * lagrange_multiplier_ +
143 derivative_constraint_coeff_ * (*derivative_matrix_).transpose() *
145 previous_solution_ = solution;
147 [this](const data_type& target, data_type& result) {
148 result = static_cast<scalar_type>(2) * (*coeff_).transpose() *
149 (*coeff_) * target;
151 (*derivative_matrix_).transpose() * (*derivative_matrix_) *
152 target;
153 },
154 temp_solution_, solution);
155 update_rate_ = (solution - previous_solution_).norm() /
156 (solution.norm() + std::numeric_limits<scalar_type>::epsilon());
157 residual_ = (*coeff_) * solution - (*data_);
158
159 // Update derivative.
161 derivative_ = (*derivative_matrix_) * solution +
163 const scalar_type derivative_shrinkage_threshold =
166 derivative_, derivative_shrinkage_threshold);
168 (derivative_.norm() + std::numeric_limits<scalar_type>::epsilon());
169
170 // Update lagrange multiplier.
172 ((*derivative_matrix_) * solution - derivative_);
175 (lagrange_multiplier_.norm() +
176 std::numeric_limits<scalar_type>::epsilon());
177
178 ++iterations_;
179 }
180
182 [[nodiscard]] auto is_stop_criteria_satisfied(
183 const data_type& solution) const -> bool {
184 (void)solution;
185 return (iterations() > max_iterations()) ||
187 }
188
192 const {
193 iteration_logger.template append<index_type>(
194 "Iter.", &this_type::iterations);
195 iteration_logger.template append<scalar_type>(
196 "UpdateRate", &this_type::update_rate);
197 iteration_logger.template append<scalar_type>(
198 "Res.Rate", &this_type::residual_norm_rate);
199 }
200
202 [[nodiscard]] auto residual_norm(const data_type& solution) const
203 -> scalar_type {
204 return ((*coeff_) * solution - (*data_)).squaredNorm();
205 }
206
208 [[nodiscard]] auto regularization_term(const data_type& solution) const
209 -> scalar_type {
210 return (*derivative_matrix_ * solution).template lpNorm<1>();
211 }
212
214 void change_data(const data_type& data) { data_ = &data; }
215
217 void calculate_data_for(const data_type& solution, data_type& data) const {
218 data = (*coeff_) * solution;
219 }
220
222 [[nodiscard]] auto data_size() const -> index_type { return data_->size(); }
223
225 [[nodiscard]] auto param_search_region() const
226 -> std::pair<scalar_type, scalar_type> {
227 const data_type approx_order_of_solution = coeff_->transpose() *
229 const scalar_type approx_order_of_param =
230 (*derivative_matrix_ * approx_order_of_solution)
231 .cwiseAbs()
232 .maxCoeff();
234 this->logger(), "approx_order_of_param={}", approx_order_of_param);
235 constexpr auto tol_update_coeff_multiplier =
236 static_cast<scalar_type>(10);
237 return {approx_order_of_param *
239 tol_update_coeff_multiplier * tol_update_rate_),
240 approx_order_of_param * impl::weak_coeff_max_param<scalar_type>};
241 }
242
248 [[nodiscard]] auto iterations() const noexcept -> index_type {
249 return iterations_;
250 }
251
258 [[nodiscard]] auto update_rate() const noexcept -> scalar_type {
259 return update_rate_;
260 }
261
267 [[nodiscard]] auto residual_norm_rate() const -> scalar_type {
268 return residual_.squaredNorm() / data_->squaredNorm();
269 }
270
276 [[nodiscard]] auto max_iterations() const -> index_type {
277 return max_iterations_;
278 }
279
287 NUM_COLLECT_PRECONDITION(value > 0, this->logger(),
288 "Maximum number of iterations must be a positive integer.");
289 max_iterations_ = value;
290 return *this;
291 }
292
298 [[nodiscard]] auto tol_update_rate() const -> scalar_type {
299 return tol_update_rate_;
300 }
301
309 NUM_COLLECT_PRECONDITION(value > 0, this->logger(),
310 "Tolerance of update rate of the solution must be a positive "
311 "value.");
312 tol_update_rate_ = value;
313 return *this;
314 }
315
316private:
318 const coeff_type* coeff_{nullptr};
319
322
324 const data_type* data_{nullptr};
325
328
331
334
337
340
343
346
349
352
355
358 static_cast<scalar_type>(1);
359
363
365 static constexpr index_type default_max_iterations = 1000;
366
369
371 static constexpr auto default_tol_update_rate =
372 static_cast<scalar_type>(1e-4);
373
376
379 static_cast<scalar_type>(1e-2);
380
384};
385
386} // 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:375
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:225
index_type iterations_
Number of iterations.
Definition tv_admm.h:327
void iterate(const scalar_type &param, data_type &solution)
Iterate the algorithm once.
Definition tv_admm.h:138
const data_type * data_
Data vector.
Definition tv_admm.h:324
static constexpr index_type default_max_iterations
Default maximum number of iterations.
Definition tv_admm.h:365
static constexpr auto default_derivative_constraint_coeff
Default coefficient of the constraint for the derivative.
Definition tv_admm.h:357
data_type derivative_
Derivative.
Definition tv_admm.h:330
scalar_type update_rate_
Rate of norm of the update of the solution in the last iteration.
Definition tv_admm.h:351
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:258
const coeff_type * coeff_
Coefficient matrix to compute data vector.
Definition tv_admm.h:318
data_type previous_derivative_
Previous derivative.
Definition tv_admm.h:342
auto residual_norm_rate() const -> scalar_type
Get the rate of the last residual norm.
Definition tv_admm.h:267
auto residual_norm(const data_type &solution) const -> scalar_type
Calculate the squared norm of the residual.
Definition tv_admm.h:202
data_type lagrange_multiplier_
Lagrange multiplier.
Definition tv_admm.h:333
const derivative_matrix_type * derivative_matrix_
Matrix to compute derivative.
Definition tv_admm.h:321
iterative_regularized_solver_base< this_type, Data > base_type
Type of the base class.
Definition tv_admm.h:69
auto data_size() const -> index_type
Get the size of data.
Definition tv_admm.h:222
tv_admm< Coeff, DerivativeMatrix, Data > this_type
This type.
Definition tv_admm.h:66
data_type previous_solution_
Previous solution.
Definition tv_admm.h:339
auto max_iterations() const -> index_type
Get the maximum number of iterations.
Definition tv_admm.h:276
data_type residual_
Residual vector.
Definition tv_admm.h:348
Coeff coeff_type
Type of coefficient matrices.
Definition tv_admm.h:75
void calculate_data_for(const data_type &solution, data_type &data) const
Calculate data for a solution.
Definition tv_admm.h:217
static constexpr auto default_tol_update_rate
Default tolerance of update rate of the solution.
Definition tv_admm.h:371
auto tol_update_rate(scalar_type value) -> tv_admm &
Set the tolerance of update rate of the solution.
Definition tv_admm.h:308
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:378
auto iterations() const noexcept -> index_type
Get the number of iterations.
Definition tv_admm.h:248
auto tol_update_rate() const -> scalar_type
Get the tolerance of update rate of the solution.
Definition tv_admm.h:298
auto max_iterations(index_type value) -> tv_admm &
Set the maximum number of iterations.
Definition tv_admm.h:286
void configure_iteration_logger(logging::iterations::iteration_logger< this_type > &iteration_logger) const
Configure an iteration logger.
Definition tv_admm.h:190
data_type lagrange_multiplier_update_
Update of lagrange multiplier.
Definition tv_admm.h:345
linear::impl::operator_conjugate_gradient< data_type > conjugate_gradient_
Conjugate gradient solver.
Definition tv_admm.h:354
DerivativeMatrix derivative_matrix_type
Type of matrices to compute derivatives.
Definition tv_admm.h:78
data_type temp_solution_
Temporary vector for the update of the solution.
Definition tv_admm.h:336
void compute(const Coeff &coeff, const DerivativeMatrix &derivative_matrix, const Data &data)
Compute internal parameters.
Definition tv_admm.h:98
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:382
void init(const scalar_type &param, data_type &solution)
Initialize.
Definition tv_admm.h:106
auto is_stop_criteria_satisfied(const data_type &solution) const -> bool
Determine if stopping criteria of the algorithm are satisfied.
Definition tv_admm.h:182
scalar_type derivative_constraint_coeff_
Coefficient of the constraint for the derivative.
Definition tv_admm.h:361
index_type max_iterations_
Maximum number of iterations.
Definition tv_admm.h:368
auto regularization_term(const data_type &solution) const -> scalar_type
Calculate the regularization term.
Definition tv_admm.h:208
void change_data(const data_type &data)
Change data.
Definition tv_admm.h:214
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.