dynare/dynare++/kord/global_check.hh

172 lines
6.0 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

/*
* Copyright © 2005 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
* along with Dynare. If not, see <https://www.gnu.org/licenses/>.
*/
// Global check
/* The purpose of this file is to provide classes for checking error of
approximation. If yₜ=g(y*ₜ₋₁,u) is an approximate solution, then we check
for the error of residuals of the system equations. Let
F(y*,u,u)=f(g**(g*(y*,u),u),g(y*,u),y*,u), then we calculate the integral:
𝔼ₜ[F(y*,u,u)]
which we want to be zero for all y* and u.
There are a few possibilities how and where the integral is evaluated.
Currently we offer the following ones:
— Along shocks. The y* is set to the steady state, and u is set to zero but
one element is going from minus through plus shocks in few steps. The user
gives the scaling factor, for instance the interval [3σ,3σ] (where σ is
one standard error of the shock), and a number of steps. This is repeated
for each shock (element of the u vector).
— Along simulation. Some random simulation is run, and for each realization
of y* and u along the path we evaluate the residual.
— On ellipse. Let V=AAᵀ be a covariance matrix of the predetermined
variables y* based on linear approximation, then we calculate integral for
points on the ellipse { Ax | ‖x‖₂=1 }. The points are selected by means of
low discrepancy method and polar transformation. The shock u are zeros.
— Unconditional distribution.
*/
#ifndef GLOBAL_CHECK_H
#define GLOBAL_CHECK_H
#include <matio.h>
#include <memory>
#include "vector_function.hh"
#include "quadrature.hh"
#include "dynamic_model.hh"
#include "journal.hh"
#include "approximation.hh"
/* This is a class for implementing the VectorFunction interface evaluating the
residual of equations, this is F(y*,u,u)=f(g**(g*(y*,u),u),y*,u) is
written as a function of u.
When the object is constructed, one has to specify (y*,u), this is done by
the setYU() method. The object has basically two states. One is after
construction and before the call to setYU(). The second is after the call to
setYU(). We distinguish between the two states, an object in the second
state contains yplus, ystar, u, and hss.
The vector yplus is g*(y*,u). ystar is y*, and polynomial hss is
partially evaluated g**(yplus, u).
The pointer to DynamicModel is important, since the DynamicModel evaluates
the function f. When copying the object, we have to make also a copy of
DynamicModel. */
class ResidFunction : public VectorFunction
{
protected:
const Approximation &approx;
std::unique_ptr<DynamicModel> model;
std::unique_ptr<Vector> yplus, ystar, u;
std::unique_ptr<FTensorPolynomial> hss;
public:
ResidFunction(const Approximation &app);
ResidFunction(const ResidFunction &rf);
std::unique_ptr<VectorFunction>
clone() const override
{
return std::make_unique<ResidFunction>(*this);
}
void eval(const Vector &point, const ParameterSignal &sig, Vector &out) override;
void setYU(const ConstVector &ys, const ConstVector &xx);
};
/* This is a ResidFunction wrapped with GaussConverterFunction. */
class GResidFunction : public GaussConverterFunction
{
public:
GResidFunction(const Approximation &app)
: GaussConverterFunction(std::make_unique<ResidFunction>(app), app.getModel().getVcov())
{
}
std::unique_ptr<VectorFunction>
clone() const override
{
return std::make_unique<GResidFunction>(*this);
}
void
setYU(const ConstVector &ys, const ConstVector &xx)
{
dynamic_cast<ResidFunction *>(func)->setYU(ys, xx);
}
};
/* This is a class encapsulating checking algorithms. Its core routine is
check(), which calculates integral 𝔼[F(y*,u,u) | y*,u] for given
realizations of y* and u. The both are given in matrices. The methods
checking along shocks, on ellipse and anlong a simulation path, just fill
the matrices and call the core check().
The method checkUnconditionalAndSave() evaluates unconditional 𝔼[F(y,u,u)].
The object also maintains a set of GResidFunction functions vfs in order
to save (possibly expensive) copying of DynamicModels. */
class GlobalChecker
{
const Approximation &approx;
const DynamicModel &model;
Journal &journal;
GResidFunction rf;
VectorFunctionSet vfs;
public:
GlobalChecker(const Approximation &app, int n, Journal &jr)
: approx(app), model(approx.getModel()), journal(jr),
rf(approx), vfs(rf, n)
{
}
void check(int max_evals, const ConstTwoDMatrix &y,
const ConstTwoDMatrix &x, TwoDMatrix &out);
void checkAlongShocksAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals);
void checkOnEllipseAndSave(mat_t *fd, const std::string &prefix,
int m, double mult, int max_evals);
void checkAlongSimulationAndSave(mat_t *fd, const std::string &prefix,
int m, int max_evals);
void checkUnconditionalAndSave(mat_t *fd, const std::string &prefix,
int m, int max_evals);
protected:
void check(const Quadrature &quad, int level,
const ConstVector &y, const ConstVector &x, Vector &out);
};
/* Signalled resid function. Not implemented yet. todo: */
class ResidFunctionSig : public ResidFunction
{
public:
ResidFunctionSig(const Approximation &app, const Vector &ys, const Vector &xx);
};
#endif