2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* Copyright © 2006 Ondra Kamenik
|
|
|
|
|
* Copyright © 2019 Dynare Team
|
|
|
|
|
*
|
|
|
|
|
* This file is part of Dynare.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is free software: you can redistribute it and/or modify
|
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
|
* (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* Dynare is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
2021-06-09 17:33:48 +02:00
|
|
|
|
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
|
2019-06-19 14:34:30 +02:00
|
|
|
|
*/
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
|
|
|
|
#ifndef OGU_NLSOLVE_H
|
|
|
|
|
#define OGU_NLSOLVE_H
|
|
|
|
|
|
2019-01-08 16:09:25 +01:00
|
|
|
|
#include "twod_matrix.hh"
|
2019-01-04 16:29:57 +01:00
|
|
|
|
#include "journal.hh"
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2019-04-23 18:57:52 +02:00
|
|
|
|
#include <cmath>
|
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
namespace ogu
|
|
|
|
|
{
|
|
|
|
|
class OneDFunction
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-04-23 18:57:52 +02:00
|
|
|
|
virtual ~OneDFunction() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
virtual double eval(double) = 0;
|
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class GoldenSectionSearch
|
|
|
|
|
{
|
|
|
|
|
protected:
|
2019-04-23 18:57:52 +02:00
|
|
|
|
constexpr static double tol = 1.e-4;
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* This is equal to the golden section ratio. */
|
2019-05-08 15:13:28 +02:00
|
|
|
|
static double golden;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
public:
|
|
|
|
|
static double search(OneDFunction &f, double x1, double x2);
|
|
|
|
|
protected:
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* This initializes a bracket by moving x2 and b (as a golden section of
|
|
|
|
|
x1,x2) so that f(x1)>f(b) && f(b)<f(x2). The point x1 is not moved,
|
|
|
|
|
since it is considered as reliable and f(x1) is supposed to be finite.
|
|
|
|
|
If initialization of a bracket succeeded, then [x1,b,x2] is the bracket
|
|
|
|
|
and true is returned. Otherwise, b is the minimum found and false is
|
|
|
|
|
returned. */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
static bool init_bracket(OneDFunction &f, double x1, double &x2, double &b);
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* This supposes that f(x1) is finite and it moves x2 toward x1 until x2
|
|
|
|
|
and b (as a golden section of x1,x2) are finite. If succeeded, the
|
|
|
|
|
routine returns true and x2, and b. Otherwise, it returns false. */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
static bool search_for_finite(OneDFunction &f, double x1, double &x2, double &b);
|
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class VectorFunction
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-04-23 18:57:52 +02:00
|
|
|
|
VectorFunction() = default;
|
|
|
|
|
virtual ~VectorFunction() = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
virtual int inDim() const = 0;
|
|
|
|
|
virtual int outDim() const = 0;
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* Check dimensions of eval parameters. */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
void check_for_eval(const ConstVector &in, Vector &out) const;
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* Evaluate the vector function. */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
virtual void eval(const ConstVector &in, Vector &out) = 0;
|
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class Jacobian : public TwoDMatrix
|
|
|
|
|
{
|
|
|
|
|
public:
|
2019-04-23 18:57:52 +02:00
|
|
|
|
Jacobian(int n) : TwoDMatrix(n, n)
|
2017-05-16 16:30:27 +02:00
|
|
|
|
{
|
|
|
|
|
}
|
2019-04-23 18:57:52 +02:00
|
|
|
|
~Jacobian() override = default;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
virtual void eval(const Vector &in) = 0;
|
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
|
2017-05-16 16:30:27 +02:00
|
|
|
|
class NLSolver : public OneDFunction
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
Journal &journal;
|
|
|
|
|
VectorFunction &func;
|
|
|
|
|
Jacobian &jacob;
|
|
|
|
|
const int max_iter;
|
|
|
|
|
const double tol;
|
|
|
|
|
private:
|
|
|
|
|
Vector xnewton;
|
|
|
|
|
Vector xcauchy;
|
|
|
|
|
Vector x;
|
|
|
|
|
public:
|
|
|
|
|
NLSolver(VectorFunction &f, Jacobian &j, int maxit, double tl, Journal &jr)
|
|
|
|
|
: journal(jr), func(f), jacob(j), max_iter(maxit), tol(tl),
|
|
|
|
|
xnewton(f.inDim()), xcauchy(f.inDim()), x(f.inDim())
|
|
|
|
|
{
|
|
|
|
|
xnewton.zeros(); xcauchy.zeros(); x.zeros();
|
|
|
|
|
}
|
2019-04-23 18:57:52 +02:00
|
|
|
|
~NLSolver() override = default;
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* Returns true if the problem has converged. xx as input is the starting
|
|
|
|
|
value, as output it is a solution. */
|
2017-05-16 16:30:27 +02:00
|
|
|
|
bool solve(Vector &xx, int &iter);
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* To implement OneDFunction interface. It returns func(xx)ᵀ·func(xx),
|
|
|
|
|
where xx=x+lambda·xcauchy+(1−lambda)·xnewton. It is non-const only
|
|
|
|
|
because it calls func, x, xnewton, xcauchy is not changed. */
|
2019-01-09 16:26:42 +01:00
|
|
|
|
double eval(double lambda) override;
|
2017-05-16 16:30:27 +02:00
|
|
|
|
};
|
2009-09-08 15:55:19 +02:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif
|