2019-06-19 14:34:30 +02:00
|
|
|
|
/*
|
|
|
|
|
* 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
|
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
|
|
|
|
*/
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
#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. */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
ParameterSignal::ParameterSignal(int n)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
: data(n, true)
|
2019-01-04 17:27:23 +01:00
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
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). */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
ParameterSignal::signalAfter(int l)
|
|
|
|
|
{
|
2019-04-23 12:58:38 +02:00
|
|
|
|
for (size_t i = 0; i < std::min(static_cast<size_t>(l), data.size()); i++)
|
2019-01-04 17:27:23 +01:00
|
|
|
|
data[i] = false;
|
2019-01-14 16:09:49 +01:00
|
|
|
|
for (size_t i = l; i < data.size(); i++)
|
2019-01-04 17:27:23 +01:00
|
|
|
|
data[i] = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* This constructs a function set hardcopying also the first. */
|
|
|
|
|
VectorFunctionSet::VectorFunctionSet(const VectorFunction &f, int n)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
: funcs(n)
|
2019-01-04 17:27:23 +01:00
|
|
|
|
{
|
|
|
|
|
for (int i = 0; i < n; i++)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
{
|
|
|
|
|
func_copies.push_back(f.clone());
|
|
|
|
|
funcs[i] = func_copies.back().get();
|
|
|
|
|
}
|
2019-01-04 17:27:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
2019-06-19 17:33:01 +02:00
|
|
|
|
/* This constructs a function set with shallow copy in the first and hard
|
|
|
|
|
copies in others. */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
VectorFunctionSet::VectorFunctionSet(VectorFunction &f, int n)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
: funcs(n)
|
2019-01-04 17:27:23 +01:00
|
|
|
|
{
|
|
|
|
|
if (n > 0)
|
|
|
|
|
funcs[0] = &f;
|
|
|
|
|
for (int i = 1; i < n; i++)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
{
|
|
|
|
|
func_copies.push_back(f.clone());
|
|
|
|
|
funcs[i] = func_copies.back().get();
|
|
|
|
|
}
|
2019-01-04 17:27:23 +01:00
|
|
|
|
}
|
|
|
|
|
|
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ᵀ. */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
GaussConverterFunction::GaussConverterFunction(VectorFunction &f, const GeneralMatrix &vcov)
|
2019-04-16 12:40:50 +02:00
|
|
|
|
: VectorFunction(f), func(&f), A(vcov.nrows(), vcov.nrows()),
|
2019-01-04 17:27:23 +01:00
|
|
|
|
multiplier(calcMultiplier())
|
|
|
|
|
{
|
2019-06-19 17:33:01 +02:00
|
|
|
|
// TODO: raise if A.nrows() ≠ indim()
|
2019-01-04 17:27:23 +01:00
|
|
|
|
calcCholeskyFactor(vcov);
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-14 16:09:49 +01:00
|
|
|
|
GaussConverterFunction::GaussConverterFunction(std::unique_ptr<VectorFunction> f, const GeneralMatrix &vcov)
|
2019-04-16 12:40:50 +02:00
|
|
|
|
: VectorFunction(*f), func_storage{move(f)}, func{func_storage.get()}, A(vcov.nrows(), vcov.nrows()),
|
2019-01-04 17:27:23 +01:00
|
|
|
|
multiplier(calcMultiplier())
|
|
|
|
|
{
|
2019-06-19 17:33:01 +02:00
|
|
|
|
// TODO: raise if A.nrows() ≠ indim()
|
2019-01-04 17:27:23 +01:00
|
|
|
|
calcCholeskyFactor(vcov);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
GaussConverterFunction::GaussConverterFunction(const GaussConverterFunction &f)
|
2019-01-14 16:09:49 +01:00
|
|
|
|
: VectorFunction(f), func_storage{f.func->clone()}, func{func_storage.get()}, A(f.A),
|
2019-01-04 17:27:23 +01:00
|
|
|
|
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. */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
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/√(πⁿ). */
|
2019-01-04 17:27:23 +01:00
|
|
|
|
|
|
|
|
|
double
|
|
|
|
|
GaussConverterFunction::calcMultiplier() const
|
|
|
|
|
{
|
|
|
|
|
return sqrt(pow(M_PI, -1*indim()));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
GaussConverterFunction::calcCholeskyFactor(const GeneralMatrix &vcov)
|
|
|
|
|
{
|
|
|
|
|
A = vcov;
|
|
|
|
|
|
2019-04-16 12:40:50 +02:00
|
|
|
|
lapack_int rows = A.nrows(), lda = A.getLD();
|
2019-01-04 17:27:23 +01:00
|
|
|
|
for (int i = 0; i < rows; i++)
|
|
|
|
|
for (int j = i+1; j < rows; j++)
|
|
|
|
|
A.get(i, j) = 0.0;
|
|
|
|
|
|
|
|
|
|
lapack_int info;
|
2019-01-24 13:08:05 +01:00
|
|
|
|
dpotrf("L", &rows, A.base(), &lda, &info);
|
2019-06-19 17:33:01 +02:00
|
|
|
|
// TODO: raise if info≠1
|
2019-01-04 17:27:23 +01:00
|
|
|
|
}
|