dynare/dynare++/integ/cc/vector_function.cc

148 lines
3.9 KiB
C++
Raw Normal View History

/*
* 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/>.
*/
#include "vector_function.hh"
#include <dynlapack.h>
#include <cmath>
#include <algorithm>
2019-06-19 17:33:01 +02:00
/* Just an easy constructor of sequence of booleans defaulting to change
everywhere. */
ParameterSignal::ParameterSignal(int n)
: data(n, true)
{
}
2019-06-19 17:33:01 +02:00
/* This sets false (no change) before a given parameter, and true (change)
after the given parameter (including). */
void
ParameterSignal::signalAfter(int l)
{
for (size_t i = 0; i < std::min(static_cast<size_t>(l), data.size()); i++)
data[i] = false;
for (size_t i = l; i < data.size(); i++)
data[i] = true;
}
/* This constructs a function set hardcopying also the first. */
VectorFunctionSet::VectorFunctionSet(const VectorFunction &f, int n)
: funcs(n)
{
for (int i = 0; i < n; i++)
{
func_copies.push_back(f.clone());
funcs[i] = func_copies.back().get();
}
}
2019-06-19 17:33:01 +02:00
/* This constructs a function set with shallow copy in the first and hard
copies in others. */
VectorFunctionSet::VectorFunctionSet(VectorFunction &f, int n)
: funcs(n)
{
if (n > 0)
funcs[0] = &f;
for (int i = 1; i < n; i++)
{
func_copies.push_back(f.clone());
funcs[i] = func_copies.back().get();
}
}
2019-06-19 17:33:01 +02:00
/* Here we construct the object from the given function f and given
variance-covariance matrix Σ=vcov. The matrix A is calculated as lower
triangular and yields Σ=AA. */
GaussConverterFunction::GaussConverterFunction(VectorFunction &f, const GeneralMatrix &vcov)
: VectorFunction(f), func(&f), A(vcov.nrows(), vcov.nrows()),
multiplier(calcMultiplier())
{
2019-06-19 17:33:01 +02:00
// TODO: raise if A.nrows() ≠ indim()
calcCholeskyFactor(vcov);
}
GaussConverterFunction::GaussConverterFunction(std::unique_ptr<VectorFunction> f, const GeneralMatrix &vcov)
: VectorFunction(*f), func_storage{move(f)}, func{func_storage.get()}, A(vcov.nrows(), vcov.nrows()),
multiplier(calcMultiplier())
{
2019-06-19 17:33:01 +02:00
// TODO: raise if A.nrows() ≠ indim()
calcCholeskyFactor(vcov);
}
GaussConverterFunction::GaussConverterFunction(const GaussConverterFunction &f)
: VectorFunction(f), func_storage{f.func->clone()}, func{func_storage.get()}, A(f.A),
multiplier(f.multiplier)
{
}
/* Here we evaluate the function
2019-06-19 17:33:01 +02:00
g(y) = 1/(π) f(2·Ay).
Since the matrix A is lower triangular, the change signal for the function f
will look like (0,,0,1,,1) where the first 1 is in the same position as
the first change in the given signal sig of the input y=point. */
void
GaussConverterFunction::eval(const Vector &point, const ParameterSignal &sig, Vector &out)
{
ParameterSignal s(sig);
int i = 0;
while (i < indim() && !sig[i])
i++;
s.signalAfter(i);
Vector x(indim());
x.zeros();
A.multaVec(x, point);
x.mult(sqrt(2.0));
func->eval(x, s, out);
out.mult(multiplier);
}
2019-06-19 17:33:01 +02:00
/* This returns 1/√(πⁿ). */
double
GaussConverterFunction::calcMultiplier() const
{
return sqrt(pow(M_PI, -1*indim()));
}
void
GaussConverterFunction::calcCholeskyFactor(const GeneralMatrix &vcov)
{
A = vcov;
lapack_int rows = A.nrows(), lda = A.getLD();
for (int i = 0; i < rows; i++)
for (int j = i+1; j < rows; j++)
A.get(i, j) = 0.0;
lapack_int info;
dpotrf("L", &rows, A.base(), &lda, &info);
2019-06-19 17:33:01 +02:00
// TODO: raise if info≠1
}