suanPan
🧮 An Open Source, Parallel and Heterogeneous Finite Element Analysis Framework
Loading...
Searching...
No Matches
LBFGS.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2026 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
41#ifndef LBFGS_HPP
42#define LBFGS_HPP
43
44#include <deque>
45#include <suanPan.h>
46
47class LBFGS final {
48 std::deque<vec> hist_ninja, hist_residual;
49 std::deque<double> hist_factor;
50 std::vector<double> alpha;
51
52 const unsigned max_hist;
53 const unsigned max_iteration;
54 const double abs_tol;
55 const double rel_tol;
56
57public:
58 explicit LBFGS(const unsigned MH = 10, const unsigned MI = 500, const double AT = datum::eps, const double RT = datum::eps)
59 : max_hist(MH)
60 , max_iteration(MI)
61 , abs_tol(AT)
62 , rel_tol(RT) {}
63
64 template<typename F> requires requires(F t, const vec& x) {
65 { t.evaluate_residual(x) } -> std::same_as<vec>;
66 { t.evaluate_jacobian(x) } -> std::same_as<mat>;
67 } int optimize(F& func, vec& x) {
68 // clear container
69 hist_ninja.clear();
70 hist_residual.clear();
71 hist_factor.clear();
72
73 vec ninja;
74 const auto ref_magnitude = norm(x);
75
76 // iteration counter
77 auto counter = 0u;
78 while(true) {
79 const auto residual = func.evaluate_residual(x);
80
81 if(0u == counter) ninja = solve(func.evaluate_jacobian(x), residual);
82 else {
83 // clear temporary factor container
84 alpha.clear();
85 alpha.reserve(hist_ninja.size());
86 // commit current residual
87 hist_residual.back() += residual;
88 // commit current factor after obtaining ninja and residual
89 hist_factor.emplace_back(dot(hist_ninja.back(), hist_residual.back()));
90 // copy current residual to ninja
91 ninja = residual;
92 // perform two-step recursive loop
93 // right side loop
94 // compute and commit alpha and update ninja
95 for(auto J = static_cast<int>(hist_factor.size()) - 1; J >= 0; --J) ninja -= alpha.emplace_back(dot(hist_ninja[J], ninja)) / hist_factor[J] * hist_residual[J];
96 // apply the Hessian from the factorization in the first iteration
97 ninja *= dot(hist_residual.back(), hist_ninja.back()) / dot(hist_residual.back(), hist_residual.back());
98 // left side loop
99 for(size_t I = 0, J = hist_factor.size() - 1; I < hist_factor.size(); ++I, --J) ninja += (alpha[J] - dot(hist_residual[I], ninja)) / hist_factor[I] * hist_ninja[I];
100 }
101
102 // commit current displacement increment
103 hist_ninja.emplace_back(-ninja);
104 hist_residual.emplace_back(-residual);
105
106 const auto error = norm(ninja);
107 const auto ref_error = error / ref_magnitude;
108 suanpan_debug("Local iteration error: {:.5E}.\n", ref_error);
109 if(error <= abs_tol && ref_error <= rel_tol) return SUANPAN_SUCCESS;
110 if(++counter > max_iteration) return SUANPAN_FAIL;
111
112 // check if the maximum record number is hit (LBFGS)
113 if(counter > max_hist) {
114 hist_ninja.pop_front();
115 hist_residual.pop_front();
116 hist_factor.pop_front();
117 }
118
119 x -= ninja;
120 }
121 }
122};
123
124#endif
125
The LBFGS class defines a solver using LBFGS iteration method.
Definition LBFGS.hpp:47
LBFGS(const unsigned MH=10, const unsigned MI=500, const double AT=datum::eps, const double RT=datum::eps)
Definition LBFGS.hpp:58
int optimize(F &func, vec &x)
Definition LBFGS.hpp:67
#define suanpan_debug(...)
Definition suanPan.h:347
constexpr auto SUANPAN_SUCCESS
Definition suanPan.h:166
constexpr auto SUANPAN_FAIL
Definition suanPan.h:167