Optimist  0.0.0
A C++ library for optimization
Loading...
Searching...
No Matches
SolverBase.hh
Go to the documentation of this file.
1/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
2 * Copyright (c) 2025, Davide Stocco, Mattia Piazza and Enrico Bertolazzi. *
3 * *
4 * The Optimist project is distributed under the BSD 2-Clause License. *
5 * *
6 * Davide Stocco Mattia Piazza Enrico Bertolazzi *
7 * University of Trento University of Trento University of Trento *
8 * davide.stocco@unitn.it mattia.piazza@unitn.it enrico.bertolazzi@unitn.it *
9\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
10
11#pragma once
12
13#ifndef OPTIMIST_SOLVER_HH
14#define OPTIMIST_SOLVER_HH
15
16#include "Optimist.hh"
17#include "Optimist/Function.hh"
18
19namespace Optimist
20{
21
22 /*\
23 | ____ _ ____
24 | / ___| ___ | |_ _____ _ __| __ ) __ _ ___ ___
25 | \___ \ / _ \| \ \ / / _ \ '__| _ \ / _` / __|/ _ \
26 | ___) | (_) | |\ V / __/ | | |_) | (_| \__ \ __/
27 | |____/ \___/|_| \_/ \___|_| |____/ \__,_|___/\___|
28 |
29 \*/
30
42 template <typename Real, Integer SolInDim, Integer SolOutDim, typename DerivedSolver, bool ForceEigen = false>
44 {
45 public:
46 // Fancy static assertions (just for fun, don't take it too seriously)
47 static_assert(SolInDim > static_cast<Integer>(0) && SolOutDim > static_cast<Integer>(0),
48 "Negative-dimensional optimization problem? Are you serious?");
49
51
52 protected:
53 // I/O types
54 using InputType = typename std::conditional_t<ForceEigen || (SolInDim > 1), Eigen::Vector<Real, SolInDim>, Real>;
55 using OutputType = typename std::conditional_t<ForceEigen || (SolOutDim > 1), Eigen::Vector<Real, SolOutDim>, Real>;
56
57 // Trace types
58 using TraceType = typename std::vector<InputType>;
59
60 // Derivative types
61 using FirstDerivativeType = std::conditional_t<ForceEigen || (SolInDim > 1) || (SolOutDim > 1), Eigen::Matrix<Real, SolOutDim, SolInDim>, Real>;
62 using SecondDerivativeType = std::conditional_t<ForceEigen || (SolInDim > 1) || (SolOutDim > 1),
63 std::conditional_t<SolInDim == 1 || SolOutDim == 1, Eigen::Matrix<Real, SolInDim, SolInDim>,
64 std::vector<Eigen::Matrix<Real, SolInDim, SolInDim>>>, Real>;
65
66 // Function types
67 using FunctionWrapper = typename std::function<void(const InputType &, OutputType &)>;
68 using FirstDerivativeWrapper = typename std::function<void(const InputType &, FirstDerivativeType &)>;
69 using SecondDerivativeWrapper = typename std::function<void(const InputType &, SecondDerivativeType &)>;
70
71 // Bounds (may not be used)
74
75 // Evaluations
79
80 // Maximum allowed evaluations
84
85 // Iterations and relaxations
88 Real m_alpha{0.8};
91
92 // Settings
93 Real m_tolerance{EPSILON_LOW};
94 bool m_verbose{false};
95 bool m_damped{true};
96 std::ostream * m_ostream{&std::cout};
97
98 // Convergence output flag and trace
99 std::string m_task{"Undefined"};
100 bool m_converged{false};
102
103 public:
108 if constexpr (ForceEigen || SolInDim > 1) {
109 this->m_lower_bound.setConstant(-INFTY);
110 this->m_upper_bound.setConstant(INFTY);
111 } else {
112 this->m_lower_bound = -INFTY;
113 this->m_upper_bound = INFTY;
114 }
115 this->m_trace.reserve(this->m_max_iterations * this->m_max_relaxations);
116 }
117
124 SolverBase(FunctionWrapper function, const InputType & x_ini, InputType & x_sol) : SolverBase() {
125 static_cast<const DerivedSolver *>(this)->solve_impl(function, x_ini, x_sol);
126 }
127
135 SolverBase(FunctionWrapper function, FirstDerivativeWrapper first_derivative, const InputType & x_ini,
136 InputType & x_sol) : SolverBase()
137 {
138 static_cast<const DerivedSolver *>(this)->solve_impl(function, first_derivative, x_ini, x_sol);
139 }
140
150 second_derivative, const InputType & x_ini, InputType & x_sol) : SolverBase()
151 {
152 static_cast<const DerivedSolver *>(this)->solve_impl(function, first_derivative, second_derivative, x_ini, x_sol);
153 }
154
159 const InputType & lower_bound() const {return this->m_lower_bound;}
160
165 void lower_bound(const InputType & t_lower_bound) {
166 #define CMD "Optimist::Solver::bounds(...): "
167
168 if constexpr (ForceEigen || SolInDim > 1) {
169 OPTIMIST_ASSERT((this->m_upper_bound - t_lower_bound).minCoeff() <= 0.0,
170 CMD "invalid or degenarate bounds detected.");
171 } else {
172 OPTIMIST_ASSERT(this->m_upper_bound > t_lower_bound,
173 CMD "invalid or degenarate bounds detected.");
174 }
175 this->m_lower_bound = t_lower_bound;
176
177 #undef CMD
178 }
179
184 const InputType & upper_bound() const {return this->m_upper_bound;}
185
190 void upper_bound(const InputType & t_upper_bound) {
191 #define CMD "Optimist::Solver::bounds(...): "
192
193 if constexpr (ForceEigen || SolInDim > 1) {
194 OPTIMIST_ASSERT((t_upper_bound - this->m_lower_bound).minCoeff() <= 0.0,
195 CMD "invalid or degenarate bounds detected.");
196 } else {
197 OPTIMIST_ASSERT(t_upper_bound > this->m_lower_bound,
198 CMD "invalid or degenarate bounds detected.");
199 }
200 this->m_upper_bound = t_upper_bound;
201
202 #undef CMD
203 }
204
210 void bounds(const InputType & t_lower_bound, const InputType & t_upper_bound)
211 {
212 #define CMD "Optimist::Solver::bounds(...): "
213
214 if constexpr (ForceEigen || SolInDim > 1) {
215 OPTIMIST_ASSERT((t_upper_bound - t_lower_bound).minCoeff() <= 0.0,
216 CMD "invalid or degenarate bounds detected.");
217 } else {
218 OPTIMIST_ASSERT(t_upper_bound > t_lower_bound,
219 CMD "invalid or degenarate bounds detected.");
220 }
221 this->m_lower_bound = t_lower_bound;
222 this->m_upper_bound = t_upper_bound;
223
224 #undef CMD
225 }
226
231 constexpr Integer input_dimension() const {return SolInDim;}
232
237 constexpr Integer output_dimension() const {return SolOutDim;}
238
243 Integer function_evaluations() const {return this->m_function_evaluations;}
244
249 void max_function_evaluations(Integer t_max_function_evaluations)
250 {
251 OPTIMIST_ASSERT(!std::isnan(t_max_function_evaluations) && std::isfinite(t_max_function_evaluations),
252 "Optimist::Solver::max_function_evaluations(...): invalid input detected.");
253 this->m_max_function_evaluations = t_max_function_evaluations;
254 }
255
260 Integer max_function_evaluations() const {return this->m_max_function_evaluations;}
261
262 protected:
267 Integer first_derivative_evaluations() const {return this->m_first_derivative_evaluations;}
268
273 Integer max_first_derivative_evaluations() const {return this->m_max_first_derivative_evaluations;}
274
280 {
282 !std::isnan(first_derivative_evaluations) && std::isfinite(first_derivative_evaluations),
283 "Optimist::Solver::max_first_derivative_evaluations(...): invalid input detected.");
284 this->m_max_first_derivative_evaluations = first_derivative_evaluations;
285 }
286
291 Integer second_derivative_evaluations() const {return this->m_second_derivative_evaluations;}
292
297 Integer max_second_derivative_evaluations() const {return this->m_max_second_derivative_evaluations;}
298
304 {
307 "Optimist::Solver::max_second_derivative_evaluations(...): invalid input detected.");
308 this->m_max_second_derivative_evaluations = second_derivative_evaluations;
309 }
310
311 public:
315 Integer iterations() const {return this->m_iterations;}
316
321 Integer max_iterations() const {return this->max_iterations;}
322
327 void max_iterations(Integer t_max_iterations) {
328 OPTIMIST_ASSERT(!std::isnan(t_max_iterations) && std::isfinite(t_max_iterations),
329 "Optimist::Solver::max_iterations(...): invalid input detected.");
330 this->m_max_iterations = t_max_iterations;
331 }
332
337 Real alpha() const {return this->m_alpha;}
338
343 void alpha(Real t_alpha)
344 {
346 !std::isnan(t_alpha) && std::isfinite(t_alpha) && 0.0 <= t_alpha && t_alpha <= 1.0,
347 "Optimist::Solver::alpha(...): invalid input detected.");
348 this->m_alpha = t_alpha;
349 }
350
355 Integer relaxations() const {return this->m_relaxations;}
356
362
367 void max_relaxations(Integer t_max_relaxations)
368 {
369 OPTIMIST_ASSERT(!std::isnan(t_max_relaxations) && std::isfinite(t_max_relaxations),
370 "Optimist::Solver::max_relaxations(...): invalid input detected.");
371 this->m_max_relaxations = t_max_relaxations;
372 }
373
378 Real tolerance() const {return this->m_tolerance;}
379
385 void tolerance(Real t_tolerance) {
387 !std::isnan(t_tolerance) && std::isfinite(t_tolerance) && t_tolerance > 0.0,
388 "Optimist::Solver::tolerance(...): invalid input detected.");
389 this->m_tolerance = t_tolerance;
390 }
391
396 void verbose_mode(bool t_verbose) {this->m_verbose = t_verbose;}
397
402 bool verbose_mode() const {return this->m_verbose;}
403
407 void enable_verbose_mode() {this->m_verbose = true;}
408
412 void disable_verbose_mode() {this->m_verbose = false;}
413
418 void damped_mode(bool t_damped) {this->m_damped = t_damped;}
419
424 bool damped_mode() const {return this->m_damped;}
425
429 void enable_damped_mode() {this->m_damped = true;}
430
434 void disable_damped_mode() {this->m_damped = false;}
435
440 std::string task() const {return this->m_task;}
441
446 void task(std::string t_task) {this->m_task = t_task;}
447
452 bool converged() const {return this->m_converged;}
453
458 const TraceType & trace() const {return this->m_trace;}
459
464 std::ostream & ostream() const {return *this->m_ostream;}
465
470 void ostream(std::ostream & t_ostream) {this->m_ostream = &t_ostream;}
471
479 bool solve(FunctionWrapper function, const InputType & x_ini, InputType & x_sol)
480 {
481 #define CMD "Optimist::Solver::solve(...): "
482
483 static_assert(DerivedSolver::requires_function,
484 CMD "the solver requires a function.");
485 return static_cast<DerivedSolver *>(this)->solve(function, nullptr, nullptr, x_ini, x_sol);
486
487 #undef CMD
488 }
489
498 bool solve(FunctionWrapper function, FirstDerivativeWrapper first_derivative, const InputType & x_ini,
499 InputType & x_sol)
500 {
501 #define CMD "Optimist::Solver::solve(...): "
502
503 static_assert(DerivedSolver::requires_function,
504 CMD "the solver requires a function.");
505 static_assert(DerivedSolver::requires_first_derivative,
506 CMD "the solver requires the first derivative.");
507 return static_cast<DerivedSolver *>(this)->solve(function, first_derivative, nullptr, x_ini, x_sol);
508
509 #undef CMD
510 }
511
522 second_derivative, const InputType & x_ini, InputType & x_sol)
523 {
524 #define CMD "Optimist::Solver::solve(...): "
525
526 static_assert(DerivedSolver::requires_function,
527 CMD "the solver requires the function.");
528 static_assert(DerivedSolver::requires_first_derivative,
529 CMD "the solver requires the first derivative.");
530 static_assert(DerivedSolver::requires_second_derivative,
531 CMD "the solver requires the second derivative.");
532 return static_cast<DerivedSolver *>(this)->solve(function, first_derivative, second_derivative,
533 x_ini, x_sol);
534
535 #undef CMD
536 }
537
548 template <Integer FunInDim, Integer FunOutDim, typename DerivedFunction>
550 const InputType & x_ini, InputType & x_sol)
551 {
552 #define CMD "Optimist::Solver::rootfind(...): "
553
554 static_assert(SolInDim == FunInDim,
555 CMD "solver input dimension must be equal to the function input dimension.");
556 static_assert(SolOutDim == FunOutDim || SolOutDim == 1,
557 CMD "solver output dimension must be equal to the function output dimension or 1.");
558 static_assert(!(SolInDim == 1 && DerivedSolver::is_optimizer),
559 CMD "one-dimensional optimizers do not support root-finding problems.");
560 return this->solve(function, x_ini, x_sol, SolOutDim != FunOutDim || (SolInDim > 1 && SolOutDim == 1));
561
562 #undef CMD
563 }
564
575 template <Integer FunInDim, Integer FunOutDim, typename DerivedFunction>
577 const InputType & x_ini, InputType & x_sol)
578 {
579 #define CMD "Optimist::Solver::optimize(...): "
580
581 static_assert(SolInDim == FunInDim,
582 CMD "solver input dimension must be equal to the function input dimension.");
583 static_assert(SolOutDim == 1,
584 CMD "solver output dimension must be equal to the function output dimension or 1.");
585 static_assert(!(SolInDim == 1 && DerivedSolver::is_rootfinder),
586 CMD "one-dimensional root-finders do not support optimization problems.");
587 return this->solve(function, x_ini, x_sol, true);
588
589 #undef CMD
590 }
591
596 std::string name() const {return static_cast<const DerivedSolver *>(this)->name_impl();};
597
598 protected:
610 template <Integer FunInDim, Integer FunOutDim, typename DerivedFunction>
612 const InputType & x_ini, InputType & x_sol, bool is_optimization)
613 {
614 #define CMD "Optimist::Solver::solve(...): "
615
617
618 static_assert(SolInDim == FunInDim,
619 CMD "solver input dimension must be equal to the function input dimension.");
620 static_assert(SolOutDim == FunOutDim || SolOutDim == 1,
621 CMD "solver output dimension must be equal to the function output dimension or 1.");
622
623 // Lambda generators for function and derivatives
624 auto function_wrapper = [&function, is_optimization](const InputType & x, OutputType & out)
625 {
626 typename FunctionType::OutputType f;
627 function.evaluate(x, f);
628 if (is_optimization) {
629 if constexpr (FunOutDim == 1) {out = 0.5*f*f;}
630 else if constexpr (SolOutDim != FunOutDim) {out = 0.5*f.squaredNorm();}
631 else {OPTIMIST_ERROR(CMD "optimization problem with inconsistent output in function.");}
632 } else {
633 if constexpr (SolOutDim == FunOutDim) {
634 out = f;
635 }
636 else {OPTIMIST_ERROR(CMD "root-finding problem with inconsistent output in function.");}
637 }
638 };
639
640 auto first_derivative_wrapper = [&function, is_optimization, this](const InputType & x, FirstDerivativeType & out)
641 {
642 typename FunctionType::FirstDerivativeType J; function.first_derivative(x, J);
643
644 if (is_optimization) {
645 typename FunctionType::OutputType f; function.evaluate(x, f);
646 this->m_function_evaluations++;
647 if constexpr (FunInDim == 1 && FunOutDim == 1) {out = J*f;}
648 else if constexpr (SolOutDim != FunOutDim) {out = J.transpose()*f;}
649 else {OPTIMIST_ERROR(CMD "optimization problem inconsistent output in first derivative.");}
650 } else {
651 if constexpr (SolOutDim == FunOutDim) {
652 out = J;
653 }
654 else {OPTIMIST_ERROR(CMD "root-finding problem with inconsistent output in first derivative.");}
655 }
656 };
657
658 auto second_derivative_wrapper = [&function, is_optimization, this](const InputType & x, SecondDerivativeType & out)
659 {
660 typename FunctionType::SecondDerivativeType H; function.second_derivative(x, H);
661
662 if (is_optimization) {
663 typename FunctionType::OutputType f; function.evaluate(x, f);
664 typename FunctionType::FirstDerivativeType J; function.first_derivative(x, J);
665 this->m_function_evaluations++; this->m_first_derivative_evaluations++;
666 if constexpr (FunInDim == 1 && FunOutDim == 1) {out = J*J + f*H;}
667 else if constexpr (SolOutDim != FunOutDim) {
668 out = J.transpose()*J;
669 for (Integer i = 0; i < static_cast<Integer>(H.size()); ++i) {out += f(i)*H[i];}
670 }
671 else {OPTIMIST_ERROR(CMD "optimization problem with inconsistent output in second derivative.");}
672 } else {
673 if constexpr (SolOutDim == FunOutDim) {out = H;}
674 else {OPTIMIST_ERROR(CMD "root-finding problem with inconsistent output in second derivative.");}
675 }
676 };
677
678 // Select solver method based on derivative requirements
679 if constexpr (DerivedSolver::requires_function && !DerivedSolver::requires_first_derivative &&
680 !DerivedSolver::requires_second_derivative) {
681 return static_cast<DerivedSolver *>(this)->solve(function_wrapper, x_ini, x_sol);
682 } else if constexpr (DerivedSolver::requires_function && DerivedSolver::requires_first_derivative &&
683 !DerivedSolver::requires_second_derivative) {
684 return static_cast<DerivedSolver *>(this)->solve(function_wrapper, first_derivative_wrapper,
685 x_ini, x_sol);
686 } else if constexpr (DerivedSolver::requires_function && DerivedSolver::requires_first_derivative &&
687 DerivedSolver::requires_second_derivative) {
688 return static_cast<DerivedSolver *>(this)->solve(function_wrapper, first_derivative_wrapper,
689 second_derivative_wrapper, x_ini, x_sol);
690 } else {
691 OPTIMIST_ERROR(CMD "no matching function signature found for the solver.");
692 }
693
694 #undef CMD
695 }
696
700 void reset()
701 {
702 this->m_function_evaluations = static_cast<Integer>(0);
703 this->m_first_derivative_evaluations = static_cast<Integer>(0);
704 this->m_second_derivative_evaluations = static_cast<Integer>(0);
705 this->m_iterations = static_cast<Integer>(0);
706 this->m_relaxations = static_cast<Integer>(0);
707 this->m_converged = false;
708 this->m_trace.clear();
709 }
710
717 void evaluate_function(FunctionWrapper function, const InputType & x, OutputType & out)
718 {
719 OPTIMIST_ASSERT(this->m_function_evaluations < this->m_max_function_evaluations,
720 "Optimist::" << this-> name() << "::evaluate_function(...): maximum allowed function evaluations reached.");
721 ++this->m_function_evaluations;
722 function(x, out);
723 }
724
732 {
733 OPTIMIST_ASSERT(this->m_first_derivative_evaluations < this->m_max_first_derivative_evaluations,
734 "Optimist::" << this-> name() << "::evaluate_first_derivative(...): maximum allowed first derivative evaluations reached.");
735 ++this->m_first_derivative_evaluations;
736 function(x, out);
737 }
738
746 {
747 OPTIMIST_ASSERT(this->m_second_derivative_evaluations < this->m_max_second_derivative_evaluations,
748 "Optimist::" << this-> name() << "::evaluate_second_derivative(...): maximum allowed second derivative evaluations reached.");
749 ++this->m_second_derivative_evaluations;
750 function(x, out);
751 }
752
757 void store_trace(const InputType & x) {this->m_trace.push_back(x);}
758
770 bool damp(FunctionWrapper function, InputType const & x_old, InputType const & function_old,
771 InputType const & step_old, InputType & x_new, InputType & function_new, InputType & step_new)
772 {
773 Real step_norm_old, step_norm_new, residuals_old, residuals_new, tau{1.0};
774 for (this->m_relaxations = static_cast<Integer>(0); this->m_relaxations < this->m_max_relaxations; ++this->m_relaxations)
775 {
776 // Update point
777 step_new = tau * step_old;
778 x_new = x_old + step_new;
779 this->evaluate_function(function, x_new, function_new);
780
781 // Check relaxation
782 if constexpr (ForceEigen || (SolInDim > 1 && SolOutDim > 1)) {
783 residuals_old = function_old.norm();
784 residuals_new = function_new.norm();
785 step_norm_old = step_old.norm();
786 step_norm_new = step_new.norm();
787 } else {
788 residuals_old = std::abs(function_old);
789 residuals_new = std::abs(function_new);
790 step_norm_old = std::abs(step_old);
791 step_norm_new = std::abs(step_new);
792 }
793 if (residuals_new < residuals_old || step_norm_new < (Real(1.0)-tau/Real(2.0))*step_norm_old) {
794 return true;
795 } else {
796 tau *= this->m_alpha;
797 }
798 }
799 return false;
800 }
801
806 void header()
807 {
808 std::string c_tl{table_top_left_corner()};
809 std::string c_tr{table_top_right_corner()};
810 std::string h_7{table_horizontal_line<7>()};
811 std::string h_14{table_horizontal_line<14>()};
812 std::string h_23{table_horizontal_line<23>()};
813 std::string h_78{table_horizontal_line<78>()};
814 std::string v_ll{table_vertical_line() + " "};
815 std::string v_rr{" " + table_vertical_line()};
816 std::string v_lc{" " + table_vertical_line() + " "};
817 std::string j_tt{table_top_junction()};
818 std::string j_cc{table_center_cross()};
819 std::string j_ll{table_left_junction()};
820 std::string j_rr{table_right_junction()};
821
822 *this->m_ostream
823 << c_tl << h_78 << c_tr << std::endl
824 << v_ll << "Solver:" << std::setw(69) << this->name() << v_rr << std::endl
825 << v_ll << "Task: " << std::setw(69) << this->task() << v_rr << std::endl
826 << j_ll << h_7 << j_tt << h_7 << j_tt << h_7 << j_tt << h_7 << j_tt << h_7 << j_tt << h_14 << j_tt << h_23 << j_rr << std::endl
827 << v_ll << "#Iter" << v_lc << " #f" << v_lc << " #Df" << v_lc << " #DDf" << v_lc << " #Rlx" << v_lc
828 << " ║f(x)║₂ " << v_lc << "Additional notes" << std::setw(9) << v_rr << std::endl
829 << j_ll << h_7 << j_cc << h_7 << j_cc << h_7 << j_cc << h_7 << j_cc << h_7 << j_cc << h_14 << j_cc << h_23 << j_rr << std::endl;
830 }
831
836 void bottom()
837 {
838 std::string c_bl{table_bottom_left_corner()};
839 std::string c_br{table_bottom_right_corner()};
840 std::string h_7{table_horizontal_line<7>()};
841 std::string h_14{table_horizontal_line<14>()};
842 std::string h_23{table_horizontal_line<23>()};
843 std::string h_78{table_horizontal_line<78>()};
844 std::string v_ll{table_vertical_line() + " "};
845 std::string v_rr{" " + table_vertical_line()};
846 std::string j_ll{table_left_junction()};
847 std::string j_rr{table_right_junction()};
848 std::string j_bb{table_bottom_junction()};
849
850 *this->m_ostream
851 << j_ll << h_7 << j_bb << h_7 << j_bb << h_7 << j_bb << h_7 << j_bb << h_7 << j_bb << h_14 << j_bb << h_23 << j_rr << std::endl
852 << v_ll << std::setw(40) << (this->m_converged ? "CONVERGED" : "NOT CONVERGED") << std::setw(40) << v_rr << std::endl
853 << c_bl << h_78 << c_br << std::endl;
854 }
855
860 void info(Real residuals, std::string const & notes = "-")
861 {
862 std::string v_rr{" " + table_vertical_line()};
863 std::string v_ll{table_vertical_line() + " "};
864 std::string v_lc{" " + table_vertical_line() + " "};
865
866 *this->m_ostream << v_ll
867 << std::setw(5) << this->m_iterations << v_lc
868 << std::setw(5) << this->m_function_evaluations << v_lc
869 << std::setw(5) << this->m_first_derivative_evaluations << v_lc
870 << std::setw(5) << this->m_second_derivative_evaluations << v_lc
871 << std::setw(5) << this->m_relaxations << v_lc
872 << std::setw(12) << std::scientific << std::setprecision(6) << residuals << v_lc
873 << notes << std::setw(25-notes.length()) << v_rr << std::endl;
874 }
875
876 }; // class Solver
877
878} // namespace Optimist
879
880#endif // OPTIMIST_SOLVER_HH
#define OPTIMIST_ERROR(MSG)
Definition Optimist.hh:33
#define OPTIMIST_BASIC_CONSTANTS(Real)
Definition Optimist.hh:70
#define OPTIMIST_ASSERT(COND, MSG)
Definition Optimist.hh:43
#define CMD
Class container for the generic function.
Definition Function.hh:43
void second_derivative(const InputType &x, SecondDerivativeType &out) const
Definition Function.hh:102
void first_derivative(const InputType &x, FirstDerivativeType &out) const
Definition Function.hh:92
void evaluate(const InputType &x, OutputType &out) const
Definition Function.hh:82
std::conditional_t< ForceEigen||(SolInDim > 1)||(SolOutDim > 1), Eigen::Matrix< Real, SolOutDim, SolInDim >, Real > FirstDerivativeType
Definition SolverBase.hh:61
Integer max_iterations() const
Definition SolverBase.hh:321
typename std::vector< InputType > TraceType
Definition SolverBase.hh:58
bool m_damped
Definition SolverBase.hh:95
void max_second_derivative_evaluations(Integer second_derivative_evaluations)
Definition SolverBase.hh:303
void ostream(std::ostream &t_ostream)
Definition SolverBase.hh:470
bool converged() const
Definition SolverBase.hh:452
bool rootfind(FunctionBase< Real, FunInDim, FunOutDim, DerivedFunction, ForceEigen &&FunOutDim==1 > const &function, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:549
const InputType & upper_bound() const
Definition SolverBase.hh:184
void alpha(Real t_alpha)
Definition SolverBase.hh:343
Integer max_first_derivative_evaluations() const
Definition SolverBase.hh:273
void max_iterations(Integer t_max_iterations)
Definition SolverBase.hh:327
void info(Real residuals, std::string const &notes="-")
Definition SolverBase.hh:860
void lower_bound(const InputType &t_lower_bound)
Definition SolverBase.hh:165
constexpr Integer output_dimension() const
Definition SolverBase.hh:237
const TraceType & trace() const
Definition SolverBase.hh:458
Integer m_iterations
Definition SolverBase.hh:86
void bounds(const InputType &t_lower_bound, const InputType &t_upper_bound)
Definition SolverBase.hh:210
Integer max_relaxations() const
Definition SolverBase.hh:361
Real alpha() const
Definition SolverBase.hh:337
bool solve(FunctionWrapper function, FirstDerivativeWrapper first_derivative, SecondDerivativeWrapper second_derivative, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:521
SolverBase(FunctionWrapper function, FirstDerivativeWrapper first_derivative, SecondDerivativeWrapper second_derivative, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:149
Integer m_max_iterations
Definition SolverBase.hh:87
std::string task() const
Definition SolverBase.hh:440
SolverBase(FunctionWrapper function, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:124
void enable_damped_mode()
Definition SolverBase.hh:429
void upper_bound(const InputType &t_upper_bound)
Definition SolverBase.hh:190
Integer relaxations() const
Definition SolverBase.hh:355
typename std::function< void(const InputType &, SecondDerivativeType &)> SecondDerivativeWrapper
Definition SolverBase.hh:69
void verbose_mode(bool t_verbose)
Definition SolverBase.hh:396
SolverBase(FunctionWrapper function, FirstDerivativeWrapper first_derivative, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:135
std::string name() const
Definition SolverBase.hh:596
void header()
Definition SolverBase.hh:806
Integer max_second_derivative_evaluations() const
Definition SolverBase.hh:297
bool solve(FunctionWrapper function, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:479
bool optimize(FunctionBase< Real, FunInDim, FunOutDim, DerivedFunction, ForceEigen &&FunOutDim==1 > const &function, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:576
Integer function_evaluations() const
Definition SolverBase.hh:243
Real tolerance() const
Definition SolverBase.hh:378
Integer iterations() const
Definition SolverBase.hh:315
typename std::conditional_t< ForceEigen||(SolInDim > 1), Eigen::Vector< Real, SolInDim >, Real > InputType
Definition SolverBase.hh:54
void reset()
Definition SolverBase.hh:700
void max_relaxations(Integer t_max_relaxations)
Definition SolverBase.hh:367
std::ostream & ostream() const
Definition SolverBase.hh:464
void damped_mode(bool t_damped)
Definition SolverBase.hh:418
Integer m_max_first_derivative_evaluations
Definition SolverBase.hh:82
void evaluate_second_derivative(SecondDerivativeWrapper function, const InputType &x, SecondDerivativeType &out)
Definition SolverBase.hh:745
bool m_verbose
Definition SolverBase.hh:94
typename std::function< void(const InputType &, OutputType &)> FunctionWrapper
Definition SolverBase.hh:67
Integer m_max_second_derivative_evaluations
Definition SolverBase.hh:83
void evaluate_first_derivative(FirstDerivativeWrapper function, const InputType &x, FirstDerivativeType &out)
Definition SolverBase.hh:731
bool m_converged
Definition SolverBase.hh:100
Real m_alpha
Definition SolverBase.hh:88
InputType m_upper_bound
Definition SolverBase.hh:73
void enable_verbose_mode()
Definition SolverBase.hh:407
void disable_damped_mode()
Definition SolverBase.hh:434
constexpr Integer input_dimension() const
Definition SolverBase.hh:231
Integer max_function_evaluations() const
Definition SolverBase.hh:260
typename std::conditional_t< ForceEigen||(SolOutDim > 1), Eigen::Vector< Real, SolOutDim >, Real > OutputType
Definition SolverBase.hh:55
TraceType m_trace
Definition SolverBase.hh:101
bool verbose_mode() const
Definition SolverBase.hh:402
const InputType & lower_bound() const
Definition SolverBase.hh:159
bool damp(FunctionWrapper function, InputType const &x_old, InputType const &function_old, InputType const &step_old, InputType &x_new, InputType &function_new, InputType &step_new)
Definition SolverBase.hh:770
Integer second_derivative_evaluations() const
Definition SolverBase.hh:291
void store_trace(const InputType &x)
Definition SolverBase.hh:757
void bottom()
Definition SolverBase.hh:836
SolverBase()
Definition SolverBase.hh:107
std::ostream * m_ostream
Definition SolverBase.hh:96
Integer m_function_evaluations
Definition SolverBase.hh:76
bool solve(FunctionBase< Real, FunInDim, FunOutDim, DerivedFunction, ForceEigen &&FunOutDim==1 > const &function, const InputType &x_ini, InputType &x_sol, bool is_optimization)
Definition SolverBase.hh:611
std::conditional_t< ForceEigen||(SolInDim > 1)||(SolOutDim > 1), std::conditional_t< SolInDim==1||SolOutDim==1, Eigen::Matrix< Real, SolInDim, SolInDim >, std::vector< Eigen::Matrix< Real, SolInDim, SolInDim > > >, Real > SecondDerivativeType
Definition SolverBase.hh:62
Integer m_first_derivative_evaluations
Definition SolverBase.hh:77
Integer m_relaxations
Definition SolverBase.hh:89
void max_first_derivative_evaluations(Integer first_derivative_evaluations)
Definition SolverBase.hh:279
Real m_tolerance
Definition SolverBase.hh:93
bool solve(FunctionWrapper function, FirstDerivativeWrapper first_derivative, const InputType &x_ini, InputType &x_sol)
Definition SolverBase.hh:498
std::string m_task
Definition SolverBase.hh:99
bool damped_mode() const
Definition SolverBase.hh:424
Integer m_second_derivative_evaluations
Definition SolverBase.hh:78
Integer m_max_relaxations
Definition SolverBase.hh:90
Integer first_derivative_evaluations() const
Definition SolverBase.hh:267
void disable_verbose_mode()
Definition SolverBase.hh:412
void evaluate_function(FunctionWrapper function, const InputType &x, OutputType &out)
Definition SolverBase.hh:717
void tolerance(Real t_tolerance)
Definition SolverBase.hh:385
Integer m_max_function_evaluations
Definition SolverBase.hh:81
void max_function_evaluations(Integer t_max_function_evaluations)
Definition SolverBase.hh:249
void task(std::string t_task)
Definition SolverBase.hh:446
typename std::function< void(const InputType &, FirstDerivativeType &)> FirstDerivativeWrapper
Definition SolverBase.hh:68
InputType m_lower_bound
Definition SolverBase.hh:72
Namespace for the Optimist library.
Definition Optimist.hh:87
static std::string table_vertical_line()
Retrieve the Unicode character for the vertical line of a table.
Definition Optimist.hh:173
static std::string table_bottom_right_corner()
Retrieve the Unicode character for the bottom-right corner of a table.
Definition Optimist.hh:119
static std::string table_top_left_corner()
Retrieve the Unicode character for the top-left corner of a table.
Definition Optimist.hh:101
static std::string table_bottom_left_corner()
Retrieve the Unicode character for the bottom-left corner of a table.
Definition Optimist.hh:113
OPTIMIST_DEFAULT_INTEGER_TYPE Integer
The Integer type as used for the API.
Definition Optimist.hh:95
static std::string table_center_cross()
Retrieve the Unicode character for the center cross of a table.
Definition Optimist.hh:149
static std::string table_bottom_junction()
Retrieve the Unicode character for the bottom junction of a table.
Definition Optimist.hh:143
static std::string table_top_junction()
Retrieve the Unicode character for the top junction of a table.
Definition Optimist.hh:137
static std::string table_top_right_corner()
Retrieve the Unicode character for the top-right corner of a table.
Definition Optimist.hh:107
static std::string table_horizontal_line()
Retrieve the Unicode character for the horizontal line of a table.
Definition Optimist.hh:155
static std::string table_right_junction()
Retrieve the Unicode character for the right junction of a table.
Definition Optimist.hh:131
static std::string table_left_junction()
Retrieve the Unicode character for the left junction of a table.
Definition Optimist.hh:125