NuriKit v0.1.0b2
Loading...
Searching...
No Matches
optim.h
Go to the documentation of this file.
1//
2// Project NuriKit - Copyright 2024 SNU Compbio Lab.
3// SPDX-License-Identifier: Apache-2.0
4//
5
6#ifndef NURI_ALGO_OPTIM_H_
7#define NURI_ALGO_OPTIM_H_
8
10#include <algorithm>
11#include <cmath>
12#include <cstdint>
13#include <functional>
14#include <utility>
15
16#include <absl/log/absl_check.h>
17#include <Eigen/Dense>
19
20#include "nuri/eigen_config.h"
22#include "nuri/utils.h"
23
24namespace nuri {
31
34 int niter;
35 double fx;
36 ArrayXd gx;
37};
38
39namespace internal {
40 constexpr double kEpsMach = 2.220446049250313e-16;
41 constexpr double kSqrtEpsMach =
42 1.4901161193847655978721599999999997530663236602513281125266e-8;
43
44 enum class DcsrchStatus : std::uint8_t {
45 kFound,
46 kConverged,
47 kContinue,
48 };
49
50 class Dcsrch {
51 public:
52 constexpr static double kStepMin = 0, kStepMax = 1e+10;
53
54 Dcsrch(double f0, double g0, double step0, double stepmin = kStepMin,
55 double stepmax = kStepMax, double ftol = 1e-3, double gtol = 0.9,
56 double xtol = 0.1) noexcept;
57
58 DcsrchStatus operator()(double f, double g);
59
60 double step() const { return step_; }
61
62 double finit() const { return finit_; }
63
64 double ginit() const { return ginit_; }
65
66 private:
67 constexpr static double kXTrapL = 1.1, kXTrapU = 4;
68
69 double finit_, ginit_;
70 double stepmin_, stepmax_;
71 double gtest_, gtol_, xtol_;
72
73 double step_;
74
75 // The variables stx, fx, gx contain the values of the step, function,
76 // and derivative at the best step.
77 // The variables sty, fy, gy contain the value of the step, function,
78 // and derivative at sty.
79 // The variables stp, f, g contain the values of the step, function,
80 // and derivative at stp.
81 double stx_ = 0, fx_, gx_;
82 double sty_ = 0, fy_, gy_;
83 double stmin_ = 0, stmax_;
84 double width_, width1_;
85
86 bool brackt_ = false, bisect_ = false;
87 };
88
89 class LBfgsBase {
90 public:
91 LBfgsBase(MutRef<ArrayXd> x, int m);
92
93 /* State modifiers, only for implementations */
94
95 int n() const { return static_cast<int>(x_.size()); }
96
97 int m() const { return static_cast<int>(ws_.cols()); }
98
99 auto &x() { return x_; }
100
101 const auto &x() const { return x_; }
102
103 auto wnt() { return wnt_.topLeftCorner(2 * col_, 2 * col_); }
104 auto &wnt_raw() { return wnt_; }
105
106 auto ws() { return ws_.leftCols(col_); }
107
108 auto wy() { return wy_.leftCols(col_); }
109
110 auto ss() { return ss_.topLeftCorner(col_, col_); }
111
112 auto sy() { return sy_.topLeftCorner(col_, col_); }
113
114 auto wtt() { return wtt_.topLeftCorner(col_, col_); }
115
116 auto p() { return p_.head(2 * col_); }
117
118 auto v() { return v_.head(2 * col_); }
119
120 auto c() { return c_.head(2 * col_); }
121
122 auto wbp() { return wbp_.head(2 * col_); }
123
124 auto smul() { return smul_.head(nonnegative(col_ - 1)); }
125
126 auto &z() { return z_; }
127 auto &xcp() { return z_; }
128
129 auto &r() { return r_; }
130
131 auto &t() { return t_; }
132 auto &xp() { return t_; }
133
134 auto &d() { return d_; }
135
136 double d_dot(const ArrayXd &gx) const {
137 return gx.matrix().dot(d_.matrix());
138 }
139
140 double theta() const { return theta_; }
141
142 int col() const { return col_; }
143
144 int prev_col() const { return prev_col_; }
145
146 bool updated() const { return updated_; }
147
148 /* Test utils; normally not used */
149
150 void update_col(int col) { col_ = col; }
151
152 void update_theta(double theta) { theta_ = theta; }
153
154 protected:
155 bool prepare_next_iter(double gd, double ginit, double step, double dtd);
156
157 void reset_memory() {
158 theta_ = 1.0;
159 col_ = prev_col_ = 0;
160 updated_ = false;
161 }
162
163 private:
164 /* System, size n */
165 MutRef<ArrayXd> x_;
166
167 /* (2m, 2m) */
168 MatrixXd wnt_;
169 /* (n, m) */
170 MatrixXd ws_, wy_;
171 /* (m, m) */
172 MatrixXd ss_, sy_, wtt_;
173 /* 2*m */
174 VectorXd p_, v_, c_, wbp_;
175 /* n */
176 ArrayXd z_, r_, t_, d_;
177 /* m-1 */
178 ArrayXd smul_;
179
180 double theta_;
181 int col_, prev_col_;
182 bool updated_;
183 };
184
185 extern bool lbfgs_bmv(MutVecBlock<VectorXd> p, MutVecBlock<ArrayXd> smul,
186 ConstRef<VectorXd> v, ConstRef<MatrixXd> sy,
187 ConstRef<MatrixXd> wtt);
188} // namespace internal
189
242template <class Impl>
243class LBfgs: public internal::LBfgsBase {
244public:
253 LBfgs(MutRef<ArrayXd> x, Impl &&impl, const int m = 10)
254 : internal::LBfgsBase(x, m), impl_(std::move(impl)) { }
255
271 template <class FuncGrad>
272 LbfgsResult minimize(FuncGrad fg, double factr = 1e+7, double pgtol = 1e-5,
273 int maxiter = 15000, int maxls = 20);
274
276 Impl &impl() { return impl_; }
277
278private:
279 Impl impl_;
280};
281
282template <class Impl>
283template <class FuncGrad>
284LbfgsResult LBfgs<Impl>::minimize(FuncGrad fg, const double factr,
285 const double pgtol, const int maxiter,
286 const int maxls) {
287 const double tol = factr * internal::kEpsMach;
288
289 ArrayXd gx(n());
290 double fx = fg(gx, x());
291
292 internal::AllowEigenMallocScoped<false> ems;
293
294 double sbgnrm = impl_.projgr(x(), gx);
295 if (sbgnrm <= pgtol)
296 return { OptimResultCode::kSuccess, 0, fx, std::move(gx) };
297
298 impl_.reset();
299 reset_memory();
300
301 int iter = 0;
302 for (; iter < maxiter; ++iter) {
303 if (!impl_.prepare_lnsrch(*this, gx, sbgnrm, iter)) {
304 reset_memory();
305 continue;
306 }
307
308 d() = z() - x();
309
310 double gd = d_dot(gx);
311 if (gd >= 0) {
312 if (col() == 0)
313 return { OptimResultCode::kAbnormalTerm, iter + 1, fx, std::move(gx) };
314
315 reset_memory();
316 continue;
317 }
318
319 t() = x();
320 r() = gx;
321
322 auto lnsrl = impl_.lnsrch(x(), t(), z(), d(), fx, gd, iter);
323 bool converged = false;
324 for (int i = 0; !converged && i < maxls; ++i) {
325 NURI_EIGEN_ALLOW_MALLOC(true);
326 fx = fg(gx, x());
327 NURI_EIGEN_ALLOW_MALLOC(false);
328
329 gd = d_dot(gx);
330 converged = lnsrl.search(fx, gd);
331 }
332
333 if (!converged) {
334 x() = t();
335 fx = lnsrl.finit();
336 gx = r();
337
338 if (col() == 0)
339 return { OptimResultCode::kAbnormalTerm, iter + 1, fx, std::move(gx) };
340
341 reset_memory();
342 continue;
343 }
344
345 sbgnrm = impl_.projgr(x(), gx);
346 if (sbgnrm <= pgtol)
347 return { OptimResultCode::kSuccess, iter + 1, fx, std::move(gx) };
348
349 double ddum = std::max({ std::abs(lnsrl.finit()), std::abs(fx), 1.0 });
350 if (lnsrl.finit() - fx <= tol * ddum)
351 return { OptimResultCode::kSuccess, iter + 1, fx, std::move(gx) };
352
353 r() = gx - r();
354 if (!prepare_next_iter(gd, lnsrl.ginit(), lnsrl.step(), lnsrl.dtd()))
355 reset_memory();
356 }
357
358 return { OptimResultCode::kMaxIterReached, maxiter, fx, std::move(gx) };
359}
360
361namespace internal {
367 class LbfgsbBounds {
368 public:
369 LbfgsbBounds(const ArrayXi &nbd, const Array2Xd &bounds)
370 : nbd_(&nbd), bds_(&bounds) {
371 check_sizes();
372 }
373
374 LbfgsbBounds(ArrayXi &&nbd, Array2Xd &&bounds) = delete;
375
376 bool has_bound(int i) const { return nbd()[i] != 0; }
377
378 bool has_lb(int i) const { return (nbd()[i] & 0x1) != 0; }
379
380 bool has_ub(int i) const { return (nbd()[i] & 0x2) != 0; }
381
382 bool has_both(int i) const { return nbd()[i] == (0x1 | 0x2); }
383
384 int raw_nbd(int i) const { return nbd()[i]; }
385
386 double lb(int i) const {
387 ABSL_DCHECK(has_lb(i));
388 return bds()(0, i);
389 }
390
391 double ub(int i) const {
392 ABSL_DCHECK(has_ub(i));
393 return bds()(1, i);
394 }
395
396 private:
397 const ArrayXi &nbd() const { return *nbd_; }
398
399 const Array2Xd &bds() const { return *bds_; }
400
401 void check_sizes() const {
402 ABSL_DCHECK(nbd().size() == bds().cols());
403 ABSL_DCHECK(((nbd() >= 0) && (nbd() <= 3)).all());
404 ABSL_DCHECK(
405 ((nbd() != 3).transpose() || bds().row(0) <= bds().row(1)).all());
406 }
407
408 const ArrayXi *nbd_;
409 const Array2Xd *bds_;
410 };
411
412 class LbfgsbLnsrch {
413 public:
414 LbfgsbLnsrch(MutRef<ArrayXd> &x, const ArrayXd &t, const ArrayXd &z,
415 const ArrayXd &d, const LbfgsbBounds &bounds, double f0,
416 double g0, int iter, bool constrained, bool boxed,
417 double ftol = 1e-3, double gtol = 0.9,
418 double xtol = 0.1) noexcept;
419
420 bool search(double f, double g);
421
422 double dtd() const { return dtd_; }
423
424 double step() const { return dcsrch_.step(); }
425
426 double xstep() const { return step() * dnorm_; }
427
428 double finit() const { return dcsrch_.finit(); }
429
430 double ginit() const { return dcsrch_.ginit(); }
431
432 private:
433 MutRef<ArrayXd> &x() { return *x_; }
434
435 const ArrayXd &t() const { return *t_; }
436
437 const ArrayXd &z() const { return *z_; }
438
439 const ArrayXd &d() const { return *d_; }
440
441 const LbfgsbBounds &bounds() const { return *bounds_; }
442
443 void step_x();
444
445 MutRef<ArrayXd> *x_;
446 const ArrayXd *t_, *z_, *d_;
447 const LbfgsbBounds *bounds_;
448 double dtd_, dnorm_;
449
450 Dcsrch dcsrch_;
451 };
452
453 struct CauchyBrkpt {
454 int ibp;
455 double tj;
456 };
457
458 inline bool operator>(CauchyBrkpt lhs, CauchyBrkpt rhs) {
459 return lhs.tj > rhs.tj;
460 }
461
462 class LBfgsBImpl {
463 public:
464 LBfgsBImpl(MutRef<ArrayXd> x, LbfgsbBounds bounds, int m);
465
466 LbfgsbLnsrch lnsrch(MutRef<ArrayXd> &x, const ArrayXd &t, const ArrayXd &z,
467 const ArrayXd &d, double f0, double g0, int iter,
468 double ftol = 1e-3, double gtol = 0.9,
469 double xtol = 0.1) const noexcept;
470
471 void reset();
472
473 bool prepare_lnsrch(LBfgsBase &lbfgsb, const ArrayXd &gx, double sbgnrm,
474 int iter);
475
476 double projgr(ConstRef<ArrayXd> x, const ArrayXd &gx);
477
478 // For internal use only
479
480 MatrixXd &wn1() { return wn1_; }
481
482 int n() const { return static_cast<int>(iwhere_.size()); }
483
484 const LbfgsbBounds &bounds() const { return bounds_; }
485
486 int nfree() const { return nfree_; }
487
488 bool constrained() const { return constrained_; }
489
490 bool boxed() const { return boxed_; }
491
492 auto &iwhere() { return iwhere_; }
493
494 auto free() const { return free_bound_.head(nfree_); }
495
496 auto bound() const { return free_bound_.tail(n() - nfree_); }
497
498 auto enter() const { return enter_leave_.head(nenter_); }
499
500 auto leave() const { return enter_leave_.tail(nleave_); }
501
502 auto &brks() { return brks_; }
503
504 ArrayXi &free_bound() { return free_bound_; }
505
506 void update_nfree(int nfree) { nfree_ = nfree; }
507
508 private:
509 bool freev(int iter);
510
511 /* (2m, 2m) */
512 MatrixXd wn1_;
513
514 /* Bound constraints */
515 LbfgsbBounds bounds_;
516
517 /* n */
518 ArrayXi iwhere_, free_bound_, enter_leave_;
519
520 ClearablePQ<CauchyBrkpt, std::greater<>> brks_;
521
522 int nfree_, nenter_, nleave_;
523 bool constrained_, boxed_;
524 };
525
526 extern bool lbfgsb_errclb(const ArrayXd &x, const ArrayXi &nbd,
527 const Array2Xd &bounds, int m, double factr);
528
529 extern bool lbfgsb_cauchy(LBfgsBase &lbfgsb, LBfgsBImpl &impl,
530 const ArrayXd &gx, double sbgnrm);
531
532 extern bool lbfgsb_subsm(LBfgsBase &lbfgsb, LBfgsBImpl &impl,
533 const ArrayXd &gg);
534} // namespace internal
535
609template <class FuncGrad>
610LbfgsResult l_bfgs_b(FuncGrad &&fg, MutRef<ArrayXd> x, const ArrayXi &nbd,
611 const Array2Xd &bounds, const int m = 10,
612 const double factr = 1e+7, const double pgtol = 1e-5,
613 const int maxiter = 15000, const int maxls = 20) {
614 bool args_ok = internal::lbfgsb_errclb(x, nbd, bounds, m, factr);
615 if (!args_ok)
616 return { OptimResultCode::kInvalidInput, 0, 0, {} };
617
619 x, internal::LBfgsBImpl(x, { nbd, bounds }, m), m);
620 return lbfgsb.minimize(std::forward<FuncGrad>(fg), factr, pgtol, maxiter,
621 maxls);
622}
623
624namespace internal {
625 class LbfgsLnsrch {
626 public:
627 LbfgsLnsrch(MutRef<ArrayXd> &x, const ArrayXd &t, const ArrayXd &z,
628 const ArrayXd &d, double f0, double g0, int iter,
629 double ftol = 1e-3, double gtol = 0.9,
630 double xtol = 0.1) noexcept;
631
632 bool search(double f, double g);
633
634 double dtd() const { return dtd_; }
635
636 double step() const { return dcsrch_.step(); }
637
638 double xstep() const { return step() * dnorm_; }
639
640 double finit() const { return dcsrch_.finit(); }
641
642 double ginit() const { return dcsrch_.ginit(); }
643
644 private:
645 MutRef<ArrayXd> &x() { return *x_; }
646
647 const ArrayXd &t() const { return *t_; }
648
649 const ArrayXd &z() const { return *z_; }
650
651 const ArrayXd &d() const { return *d_; }
652
653 void step_x();
654
655 MutRef<ArrayXd> *x_;
656 const ArrayXd *t_, *z_, *d_;
657 double dtd_, dnorm_;
658
659 Dcsrch dcsrch_;
660 };
661
662 class LBfgsImpl {
663 public:
664 LBfgsImpl(): LBfgsImpl(10) { }
665
666 explicit LBfgsImpl(int m);
667
668 static LbfgsLnsrch lnsrch(MutRef<ArrayXd> &x, const ArrayXd &t,
669 const ArrayXd &z, const ArrayXd &d, double f0,
670 double g0, int iter, double ftol = 1e-3,
671 double gtol = 0.9, double xtol = 0.1) noexcept;
672
673 static void reset() { }
674
675 bool prepare_lnsrch(LBfgsBase &lbfgs, const ArrayXd &gx, double sbgnrm,
676 int iter);
677
678 static double projgr(ConstRef<ArrayXd> x, const ArrayXd &gx);
679
680 MatrixXd &wn1() { return wn1_; }
681
682 private:
683 /* (2m, m) */
684 MatrixXd wn1_;
685 };
686
687 extern bool lbfgs_errclb(const ArrayXd &x, int m, double factr);
688} // namespace internal
689
759template <class FuncGrad>
760LbfgsResult l_bfgs(FuncGrad &&fg, MutRef<ArrayXd> x, const int m = 10,
761 const double factr = 1e+7, const double pgtol = 1e-5,
762 const int maxiter = 15000, const int maxls = 20) {
763 bool args_ok = internal::lbfgs_errclb(x, m, factr);
764 if (!args_ok)
765 return { OptimResultCode::kInvalidInput, 0, 0, {} };
766
767 LBfgs<internal::LBfgsImpl> lbfgsb(x, internal::LBfgsImpl(m), m);
768 return lbfgsb.minimize(std::forward<FuncGrad>(fg), factr, pgtol, maxiter,
769 maxls);
770}
771
774 int niter;
775 double fx;
776 ArrayXd gx;
777};
778
826class Bfgs {
827public:
833 Bfgs(MutRef<ArrayXd> x);
834
853 template <class FuncGrad>
854 BfgsResult minimize(FuncGrad fg, const double pgtol = 1e-5,
855 const double xrtol = 0, int maxiter = -1,
856 const int maxls = 100, const double ftol = 1e-4,
857 const double gtol = 0.9, const double xtol = 1e-14) {
858 using internal::Dcsrch;
859 using internal::DcsrchStatus;
860
861 if (maxiter < 0)
862 maxiter = 200 * static_cast<int>(x().size());
863
864 Hk_.setIdentity();
865
866 ArrayXd gfk(x().size());
867
868 const double f0 = fg(gfk, x());
869 double gnorm = gfk.abs().maxCoeff();
870 if (gnorm <= pgtol)
871 return { OptimResultCode::kSuccess, 0, f0, std::move(gfk) };
872
873 int k = 0;
874 double fk = f0, fkm1 = fk + gfk.matrix().norm() * 0.5;
875 for (; k < maxiter; ++k) {
876 Dcsrch dcsrch = prepare_lnsrch(gfk, fk, fkm1, ftol, gtol, xtol);
877 fkm1 = fk;
878
879 bool success = false;
880 for (int iter = 0; iter < maxls; ++iter) {
881 xk() = x() + dcsrch.step() * pk().array();
882 fk = fg(gfkp1(), xk());
883
884 auto status = dcsrch(fk, gfkp1().matrix().dot(pk()));
885 if (status == DcsrchStatus::kContinue)
886 continue;
887
888 success = true;
889 break;
890 }
891 if (!success)
892 return { OptimResultCode::kAbnormalTerm, k + 1, fk, std::move(gfk) };
893
894 bool converged = prepare_next_iter(gfk, dcsrch.step(), pgtol, xrtol);
895 if (converged)
896 return { OptimResultCode::kSuccess, k + 1, fk, std::move(gfk) };
897 }
898
899 return { OptimResultCode::kMaxIterReached, maxiter, fk, std::move(gfk) };
900 }
901
902private:
903 internal::Dcsrch prepare_lnsrch(const ArrayXd &gfk, double fk, double fkm1,
904 double ftol, double gtol, double xtol);
905
906 bool prepare_next_iter(ArrayXd &gfk, double step, double pgtol, double xrtol);
907
908 MutRef<ArrayXd> &x() { return x_; }
909
910 // NOLINTNEXTLINE(readability-identifier-naming)
911 Eigen::SelfAdjointView<MatrixXd, Eigen::Upper> Hk() {
912 return Hk_.selfadjointView<Eigen::Upper>();
913 }
914
915 VectorXd &pk() { return pk_; }
916
917 ArrayXd &xk() { return xk_; }
918 Eigen::MatrixWrapper<ArrayXd> sk() { return xk_.matrix(); }
919
920 VectorXd &yk() { return yk_; }
921
922 ArrayXd &gfkp1() { return gfkp1_; }
923 // NOLINTNEXTLINE(readability-identifier-naming)
924 Eigen::MatrixWrapper<ArrayXd> Hk_yk() { return gfkp1_.matrix(); }
925
926 MutRef<ArrayXd> x_;
927 ArrayXd xk_, gfkp1_;
928
929 MatrixXd Hk_;
930 VectorXd pk_, yk_;
931};
932
998template <class FuncGrad>
999inline BfgsResult bfgs(FuncGrad &&fg, MutRef<ArrayXd> x,
1000 const double pgtol = 1e-5, const double xrtol = 0,
1001 int maxiter = -1, const int maxls = 100,
1002 const double ftol = 1e-4, const double gtol = 0.9,
1003 const double xtol = 1e-14) {
1004 Bfgs bfgs(x);
1005 return bfgs.minimize(std::forward<FuncGrad>(fg), pgtol, xrtol, maxiter, maxls,
1006 ftol, gtol, xtol);
1007}
1008
1013
1026public:
1035 explicit NelderMead(MutRef<ArrayXXd> data);
1036
1037 auto n() const { return data_.cols() - 1; }
1038
1039 constexpr static int argmin() { return 0; }
1040 int argmax() const { return static_cast<int>(n()); }
1041
1042 auto min() const { return data_.col(argmin()); }
1043 double minf() const { return min()[n()]; }
1044
1045 auto max() { return data_.col(argmax()); }
1046 auto max() const { return data_.col(argmax()); }
1047 double maxf() const { return max()[n()]; }
1048
1049 double max2f() const { return data_(n(), n() - 1); }
1050
1070 template <class Func>
1071 NMResult minimize(Func f, int maxiter = -1, const double ftol = 1e-6,
1072 const double alpha = 1, const double gamma = 2,
1073 const double rho = 0.5, const double sigma = 0.5) {
1074 // NOLINTNEXTLINE(readability-identifier-naming)
1075 const auto N = n();
1076 if (maxiter <= 0)
1077 maxiter = static_cast<int>(N) * 200;
1078
1079 auto eval_update = [&](auto &&simplexf) -> double {
1080 return simplexf[N] = f(simplexf.head(N));
1081 };
1082
1083 for (int i = 0; i < data_.cols(); ++i)
1084 eval_update(data_.col(i));
1085
1086 for (int iter = 0; iter < maxiter; ++iter) {
1087 partiton_min1_max2();
1088 if (maxf() - minf() < ftol)
1089 return { OptimResultCode::kSuccess, argmin() };
1090
1091 centroid();
1092 eval_update(c_);
1093
1094 reflection(alpha);
1095 double fr = eval_update(r_);
1096
1097 if (fr < minf()) {
1098 expansion(ets_, gamma);
1099 const double fe = eval_update(ets_);
1100
1101 max() = (fr < fe) ? r_ : ets_;
1102 continue;
1103 }
1104
1105 if (fr < max2f()) {
1106 max() = r_;
1107 continue;
1108 }
1109
1110 if (maxf() < fr) {
1111 r_ = max();
1112 fr = maxf();
1113 }
1114 contraction(ets_, rho);
1115 const double ft = eval_update(ets_);
1116
1117 if (ft < fr) {
1118 max() = ets_;
1119 continue;
1120 }
1121
1122 shrink(sigma);
1123 for (int i = 1; i < data_.cols(); ++i)
1124 eval_update(data_.col(i));
1125 }
1126
1128 }
1129
1130private:
1131 void partiton_min1_max2();
1132
1133 void centroid();
1134
1135 void reflection(double alpha);
1136
1137 void expansion(ArrayXd &e, double gamma) const;
1138
1139 void contraction(ArrayXd &t, double rho) const;
1140
1141 void shrink(double sigma);
1142
1143 /* (N + 1, N + 1) */
1144 MutRef<ArrayXXd> data_;
1145 /* (N + 1) */
1146 ArrayXd c_, r_, ets_;
1147};
1148
1149namespace internal {
1150 extern bool nm_check_input(ConstRef<ArrayXXd> data, double alpha,
1151 double gamma, double rho, double sigma);
1152}
1153
1186template <class Func>
1187inline NMResult nelder_mead(Func &&f, MutRef<ArrayXXd> data, int maxiter = -1,
1188 const double ftol = 1e-6, const double alpha = 1,
1189 const double gamma = 2, const double rho = 0.5,
1190 const double sigma = 0.5) {
1191 if (!internal::nm_check_input(data, alpha, gamma, rho, sigma))
1192 return { OptimResultCode::kInvalidInput, -1 };
1193
1194 NelderMead nm(data);
1195 return nm.minimize(std::forward<Func>(f), maxiter, ftol, alpha, gamma, rho,
1196 sigma);
1197}
1198
1213extern ArrayXXd nm_prepare_simplex(ConstRef<ArrayXd> x0, double eps = 1e-6);
1214} // namespace nuri
1215
1216#endif /* NURI_ALGO_OPTIM_H_ */
BFGS minimizer.
Definition optim.h:826
Bfgs(MutRef< ArrayXd > x)
Prepare BFGS minimization algorithm.
BfgsResult minimize(FuncGrad fg, const double pgtol=1e-5, const double xrtol=0, int maxiter=-1, const int maxls=100, const double ftol=1e-4, const double gtol=0.9, const double xtol=1e-14)
Minimize a function using BFGS algorithm.
Definition optim.h:854
L-BFGS(-B) minimizer.
Definition optim.h:243
LbfgsResult minimize(FuncGrad fg, double factr=1e+7, double pgtol=1e-5, int maxiter=15000, int maxls=20)
Minimize a function using L-BFGS(-B) algorithm.
Definition optim.h:284
LBfgs(MutRef< ArrayXd > x, Impl &&impl, const int m=10)
Prepare L-BFGS(-B) minimization algorithm.
Definition optim.h:253
Nelder-Mead simplex algorithm for function minimization.
Definition optim.h:1025
static constexpr int argmin()
Definition optim.h:1039
auto max()
Definition optim.h:1045
NelderMead(MutRef< ArrayXXd > data)
Prepare Nelder-Mead simplex algorithm.
NMResult minimize(Func f, int maxiter=-1, const double ftol=1e-6, const double alpha=1, const double gamma=2, const double rho=0.5, const double sigma=0.5)
Minimize a function using Nelder-Mead simplex algorithm.
Definition optim.h:1071
auto min() const
Definition optim.h:1042
double maxf() const
Definition optim.h:1047
int argmax() const
Definition optim.h:1040
auto n() const
Definition optim.h:1037
double minf() const
Definition optim.h:1043
double max2f() const
Definition optim.h:1049
auto max() const
Definition optim.h:1046
Definition crdgen.h:16
ArrayXXd nm_prepare_simplex(ConstRef< ArrayXd > x0, double eps=1e-6)
Prepare the initial simplex for Nelder-Mead algorithm.
BfgsResult bfgs(FuncGrad &&fg, MutRef< ArrayXd > x, const double pgtol=1e-5, const double xrtol=0, int maxiter=-1, const int maxls=100, const double ftol=1e-4, const double gtol=0.9, const double xtol=1e-14)
Minimize a function using BFGS algorithm.
Definition optim.h:999
OptimResultCode
Definition optim.h:25
@ kMaxIterReached
Definition optim.h:27
@ kInvalidInput
Definition optim.h:28
@ kAbnormalTerm
Definition optim.h:29
@ kSuccess
Definition optim.h:26
LbfgsResult l_bfgs_b(FuncGrad &&fg, MutRef< ArrayXd > x, const ArrayXi &nbd, const Array2Xd &bounds, const int m=10, const double factr=1e+7, const double pgtol=1e-5, const int maxiter=15000, const int maxls=20)
Minimize a function using L-BFGS-B algorithm.
Definition optim.h:610
NMResult nelder_mead(Func &&f, MutRef< ArrayXXd > data, int maxiter=-1, const double ftol=1e-6, const double alpha=1, const double gamma=2, const double rho=0.5, const double sigma=0.5)
Minimize a function using Nelder-Mead simplex algorithm.
Definition optim.h:1187
LbfgsResult l_bfgs(FuncGrad &&fg, MutRef< ArrayXd > x, const int m=10, const double factr=1e+7, const double pgtol=1e-5, const int maxiter=15000, const int maxls=20)
Minimize a function using L-BFGS algorithm.
Definition optim.h:760
Definition optim.h:772
double fx
Definition optim.h:775
OptimResultCode code
Definition optim.h:773
int niter
Definition optim.h:774
ArrayXd gx
Definition optim.h:776
Definition optim.h:32
ArrayXd gx
Definition optim.h:36
int niter
Definition optim.h:34
OptimResultCode code
Definition optim.h:33
double fx
Definition optim.h:35
Definition optim.h:1009
int argmin
Definition optim.h:1011
OptimResultCode code
Definition optim.h:1010