Unverified Commit 3d27672c authored by Normann Rion's avatar Normann Rion Committed by Sébastien Villemot
Browse files

kth-order approximation of conditional welfare

Partially addresses issue #1680:
- unconditional welfare resorts to dynare++ simulation tools, which shall be updated very soon
TO DO:
- implement a function computing kth-order approximation of simulated moments of y
parent edeb7911
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -240,11 +240,14 @@ void
Approximation::saveRuleDerivs(const FGSContainer &g)
{
rule_ders = std::make_unique<FGSContainer>(g);
rule_ders_s = std::make_unique<FGSContainer>(4);
rule_ders_ss = std::make_unique<FGSContainer>(4);
for (auto &run : *rule_ders)
{
auto ten = std::make_unique<FGSTensor>(ypart.nstat+ypart.npred, ypart.nyss(), *(run.second));
rule_ders_ss->insert(std::move(ten));
auto ten_s = std::make_unique<FGSTensor>(ypart.nstat, ypart.nys(), *(run.second));
rule_ders_s->insert(std::move(ten_s));
auto ten_ss = std::make_unique<FGSTensor>(ypart.nstat+ypart.npred, ypart.nyss(), *(run.second));
rule_ders_ss->insert(std::move(ten_ss));
}
}
......
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -122,6 +122,7 @@ class Approximation
DynamicModel &model;
Journal &journal;
std::unique_ptr<FGSContainer> rule_ders;
std::unique_ptr<FGSContainer> rule_ders_s;
std::unique_ptr<FGSContainer> rule_ders_ss;
std::unique_ptr<FoldDecisionRule> fdr;
std::unique_ptr<UnfoldDecisionRule> udr;
......@@ -156,6 +157,11 @@ public:
return *rule_ders;
}
const FGSContainer &
get_rule_ders_s() const
{
return *rule_ders_s;
}
const FGSContainer &
get_rule_ders_ss() const
{
return *rule_ders_ss;
......
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -126,6 +126,7 @@ class DecisionRuleImpl : public ctraits<t>::Tpol, public DecisionRule
protected:
using _Tpol = typename ctraits<t>::Tpol;
using _Tg = typename ctraits<t>::Tg;
using _TW = typename ctraits<t>::TW;
using _Ttensor = typename ctraits<t>::Ttensor;
using _Ttensym = typename ctraits<t>::Ttensym;
const Vector ysteady;
......@@ -149,6 +150,12 @@ public:
{
fillTensors(g, sigma);
}
DecisionRuleImpl(const _TW &W, int nys, int nuu,
const ConstVector &ys)
: ctraits<t>::Tpol(1, nys+nuu), ysteady(ys), nu(nuu)
{
fillTensors(W, nys);
}
DecisionRuleImpl(const DecisionRuleImpl<t> &dr, const ConstVector &fixpoint)
: ctraits<t>::Tpol(dr.ypart.ny(), dr.ypart.nys()+dr.nu),
ysteady(fixpoint), ypart(dr.ypart), nu(dr.nu)
......@@ -179,6 +186,7 @@ public:
}
protected:
void fillTensors(const _Tg &g, double sigma);
void fillTensors(const _TW &W, int nys);
void centralize(const DecisionRuleImpl &dr);
public:
void eval(emethod em, Vector &out, const ConstVector &v) const override;
......@@ -265,6 +273,50 @@ DecisionRuleImpl<t>::fillTensors(const _Tg &g, double sigma)
}
}
template<Storage t>
void
DecisionRuleImpl<t>::fillTensors(const _TW &W, int nys)
{
IntSequence tns{nys, nu};
int dfact = 1;
for (int d = 0; d <= W.getMaxDim(); d++, dfact *= d)
{
auto W_yud = std::make_unique<_Ttensym>(1, nys+nu, d);
W_yud->zeros();
// fill tensor of ‘g_yud’ of dimension ‘d’
/* Here we have to fill the tensor [g_(yu)ᵈ]. So we go through all pairs
(i,j) such that i+j=d, and through all k from zero up to maximal
dimension minus d. In this way we go through all symmetries of
[g_yⁱuʲσᵏ] which will be added to [g_(yu)ᵈ].
Note that at the beginning, ‘dfact’ is a factorial of ‘d’. We
calculate ‘kfact’ is equal to k!. As indicated in
DecisionRuleImpl::fillTensors(), the added tensor is thus multiplied
with 1/(d!k!)·σᵏ. */
for (int i = 0; i <= d; i++)
{
int j = d-i;
int kfact = 1;
_Ttensor tmp(1, TensorDimens(Symmetry{i, j}, tns));
tmp.zeros();
for (int k = 0; k+d <= W.getMaxDim(); k++, kfact *= k)
{
Symmetry sym{i, j, 0, k};
if (W.check(sym))
{
double mult = 1.0/dfact/kfact;
tmp.add(mult, W.get(sym));
}
}
W_yud->addSubTensor(tmp);
}
this->insert(std::move(W_yud));
}
}
/* The centralization is straightforward. We suppose here that the object’s
steady state is the fix point ỹ. It is clear that the new derivatives
[g~_(yu)ⁱ] will be equal to the derivatives of the original decision rule
......@@ -457,6 +509,11 @@ public:
: DecisionRuleImpl<Storage::fold>(g, yp, nuu, ys, sigma)
{
}
FoldDecisionRule(const ctraits<Storage::fold>::TW &W, int nys, int nuu,
const ConstVector &ys)
: DecisionRuleImpl<Storage::fold>(W, nys, nuu, ys)
{
}
FoldDecisionRule(const DecisionRuleImpl<Storage::fold> &dr, const ConstVector &fixpoint)
: DecisionRuleImpl<Storage::fold>(dr, fixpoint)
{
......
/*
* Copyright © 2004 Ondra Kamenik
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -82,7 +82,11 @@ public:
using Tgs = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using Tgss = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using TG = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using TU = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using TW = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using TWrond = std::conditional_t<type == Storage::fold, FGSContainer, UGSContainer>;
using TZstack = std::conditional_t<type == Storage::fold, FoldedZContainer, UnfoldedZContainer>;
using TXstack = std::conditional_t<type == Storage::fold, FoldedXContainer, UnfoldedXContainer>;
using TGstack = std::conditional_t<type == Storage::fold, FoldedGContainer, UnfoldedGContainer>;
using Tm = std::conditional_t<type == Storage::fold, FNormalMoments, UNormalMoments>;
using Tpol = std::conditional_t<type == Storage::fold, FTensorPolynomial, UTensorPolynomial>;
......@@ -113,6 +117,7 @@ struct PartitionY
const int npred;
const int nboth;
const int nforw;
PartitionY() : PartitionY(0,0,0,0) {}
PartitionY(int num_stat, int num_pred,
int num_both, int num_forw)
: nstat(num_stat), npred(num_pred),
......@@ -322,6 +327,11 @@ public:
{
return _ug;
}
const FGSContainer &
getFoldDersS() const
{
return _fgs;
}
static bool
is_even(int i)
{
......
/*
* Copyright © 2005 Ondra Kamenik
* Copyright © 2019 Dynare Team
* Copyright © 2019-2021 Dynare Team
*
* This file is part of Dynare.
*
......@@ -458,6 +458,11 @@ public:
{
return _ug;
}
const FGSContainer &
getFoldDersS() const
{
return _fgs;
}
protected:
template<Storage t>
std::unique_ptr<typename ctraits<t>::Ttensor> faaDiBrunoZ(const Symmetry &sym) const;
......
......@@ -337,6 +337,65 @@ protected:
UGSTensor &out, std::mutex &mut) const;
};
/* Here is the specialization of the StackContainer. We implement
here the x needed in DSGE context for welfare assessment. We implement getType() and define a constructor feeding the data and sizes.
It depends on four variables U(y,u,u',σ), the variable u' being introduced to enable additions with 4-variable tensors*/
template<class _Ttype>
class XContainer : public StackContainer<_Ttype>
{
public:
using _Tparent = StackContainer<_Ttype>;
using _Stype = StackContainerInterface<_Ttype>;
using _Ctype = typename _Tparent::_Ctype;
using itype = typename _Tparent::itype;
XContainer(const _Ctype *g, int ng)
: _Tparent(1, 1)
{
_Tparent::stack_sizes = { ng };
_Tparent::conts[0] = g;
_Tparent::calculateOffsets();
}
/* Here we say, what happens if we derive z. recall the top of the
file, how z looks, and code is clear. */
itype
getType(int i, const Symmetry &s) const override
{
if (i==0)
if (s[2] > 0)
return itype::zero;
else
return itype::matrix;
TL_RAISE("Wrong stack index in XContainer::getType");
}
};
class FoldedXContainer : public XContainer<FGSTensor>,
public FoldedStackContainer
{
public:
using _Ctype = TensorContainer<FGSTensor>;
FoldedXContainer(const _Ctype *g, int ng)
: XContainer<FGSTensor>(g, ng)
{
}
};
class UnfoldedXContainer : public XContainer<UGSTensor>,
public UnfoldedStackContainer
{
public:
using _Ctype = TensorContainer<UGSTensor>;
UnfoldedXContainer(const _Ctype *g, int ng)
: XContainer<UGSTensor>(g, ng)
{
}
};
/* Here is the specialization of the StackContainer. We implement
here the z needed in DSGE context. We implement getType() and define
a constructor feeding the data and sizes.
......
......@@ -169,8 +169,8 @@ if options_.ramsey_policy
planner_objective_value(2) = W;
else
%Order k code will go here!
fprintf('\nevaluate_planner_objective: order>2 not yet supported\n')
planner_objective_value(1) = NaN;
fprintf('\nevaluate_planner_objective: order>2 unconditional welfare calculation not yet supported\n')
planner_objective_value(1) = k_order_welfare(dr, M_, options_);
planner_objective_value(2) = NaN;
return
end
......
% [unc_welfare, U_dynpp_derivs, W_dynpp_derivs, U_dyn_derivs, W_dyn_derivs] = k_order_welfare(dr, DynareModel, DynareOptions)
% computes a k-th order approximation of welfare
%
% INPUTS
% dr: struct describing the reduced form solution of the model.
% DynareModel: struct jobs's parameters
% DynareOptions: struct job's options
%
% OUTPUTS
%
% unc_welfare double approximation of conditional welfare from the non-stochastic steady state and allowing stochastic shocks
%
% U_dynpp_derivs struct Derivatives of the felicity function in Dynare++ format.
% The tensors are folded and the Taylor coefficients (1/n!) are
% included.
% Fieldnames are U_0, U_1, U_2, …
% W_dynpp_derivs struct Derivatives of the welfare function in Dynare++ format.
% The tensors are folded and the Taylor coefficients (1/n!) are
% included.
% Fieldnames are W_0, W_1, W_2, …
% U_dyn_derivs struct Derivatives of the felicity function in Dynare format, up to third order.
% Matrices are dense and unfolded. The Taylor coefficients (1/2
% and 1/6) aren't included.
% The derivatives w.r.t. different categories of variables
% are separated.
% Fieldnames are:
% + Uy, Uu
% + if order ≥ 2: Uyy, Uyu, Uuu, Uss
% + if order ≥ 3: Uyyy, Uyyu, Uyuu, Uuuu, Uyss, Uuss
%
% W_dyn_derivs struct Derivatives of the welfare function in Dynare format, up to third order.
% Matrices are dense and unfolded. The Taylor coefficients (1/2
% and 1/6) aren't included.
% The derivatives w.r.t. different categories of variables
% are separated.
% Fieldnames are:
% + Wy, Wu
% + if order ≥ 2: Wyy, Wyu, Wuu, Wss
% + if order ≥ 3: Wyyy, Wyyu, Wyuu, Wuuu, Wyss, Wuss
%
% k_order_welfare is a compiled MEX function. Its source code is in
% dynare/mex/sources/k_order_welfare/k_order_welfare.cc and it uses code provided by
% dynare++
% Copyright (C) 2021 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/>.
......@@ -7,13 +7,9 @@ k_order_perturbation_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/../../../dynare++
k_order_perturbation_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
k_order_perturbation_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
k_order_perturbation_LDADD = ../libdynare++/libdynare++.a $(LIBADD_DLOPEN) $(LIBADD_MATIO)
k_order_perturbation_LDADD = ../libdynare++/libdynare++.a ../libkorder/libkorder.a $(LIBADD_DLOPEN) $(LIBADD_MATIO)
nodist_k_order_perturbation_SOURCES = \
k_order_perturbation.cc \
k_ord_dynare.cc \
dynamic_dll.cc \
dynamic_m.cc
nodist_k_order_perturbation_SOURCES = k_order_perturbation.cc
BUILT_SOURCES = $(nodist_k_order_perturbation_SOURCES)
CLEANFILES = $(nodist_k_order_perturbation_SOURCES)
......
mex_PROGRAMS = k_order_welfare
TOPDIR = $(top_srcdir)/../../sources/k_order_welfare
k_order_welfare_CPPFLAGS = $(AM_CPPFLAGS) -I$(TOPDIR) -I$(TOPDIR)/../k_order_perturbation -I$(top_srcdir)/../../../dynare++/tl/cc -I$(top_srcdir)/../../../dynare++/kord -I$(top_srcdir)/../../../dynare++/src -I$(top_srcdir)/../../../dynare++/sylv/cc -I$(top_srcdir)/../../../dynare++/utils/cc $(CPPFLAGS_MATIO)
k_order_welfare_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
k_order_welfare_LDFLAGS = $(AM_LDFLAGS) $(LDFLAGS_MATIO)
k_order_welfare_LDADD = ../libdynare++/libdynare++.a ../libkorder/libkorder.a $(LIBADD_DLOPEN) $(LIBADD_MATIO)
nodist_k_order_welfare_SOURCES = \
k_order_welfare.cc \
approximation_welfare.cc \
k_ord_objective.cc \
objective_m.cc
BUILT_SOURCES = $(nodist_k_order_welfare_SOURCES)
CLEANFILES = $(nodist_k_order_welfare_SOURCES)
%.cc: $(TOPDIR)/%.cc
$(LN_S) -f $< $@
noinst_LIBRARIES = libkorder.a
TOPDIR = $(top_srcdir)/../../sources/k_order_perturbation
libkorder_a_CPPFLAGS = $(AM_CPPFLAGS) -I$(TOPDIR) -I$(top_srcdir)/../../../dynare++/tl/cc -I$(top_srcdir)/../../../dynare++/sylv/cc -I$(top_srcdir)/../../../dynare++/src -I$(top_srcdir)/../../../dynare++/kord -I$(top_srcdir)/../../../dynare++/utils/cc $(CPPFLAGS_MATIO)
libkorder_a_CXXFLAGS = $(AM_CXXFLAGS) $(THREAD_CXXFLAGS)
nodist_libkorder_a_SOURCES = \
k_ord_dynare.cc \
dynamic_dll.cc \
dynamic_m.cc
BUILT_SOURCES = $(nodist_libkorder_a_SOURCES)
CLEANFILES = $(nodist_libkorder_a_SOURCES)
%.cc: $(TOPDIR)/%.cc
$(LN_S) -f $< $@
......@@ -4,7 +4,7 @@ SUBDIRS = mjdgges kronecker bytecode block_kalman_filter sobol perfect_foresight
# libdynare++ must come before gensylv, k_order_perturbation, dynare_simul_
if ENABLE_MEX_DYNAREPLUSPLUS
SUBDIRS += libdynare++ gensylv k_order_perturbation dynare_simul_ local_state_space_iterations
SUBDIRS += libdynare++ gensylv libkorder dynare_simul_ k_order_perturbation k_order_welfare local_state_space_iterations
endif
if ENABLE_MEX_MS_SBVAR
......
......@@ -153,7 +153,9 @@ AC_CONFIG_FILES([Makefile
bytecode/Makefile
libdynare++/Makefile
gensylv/Makefile
libkorder/Makefile
k_order_perturbation/Makefile
k_order_welfare/Makefile
dynare_simul_/Makefile
kalman_steady_state/Makefile
ms_sbvar/Makefile
......
include ../mex.am
include ../../k_order_welfare.am
include ../mex.am
include ../../libkorder.am
......@@ -4,7 +4,7 @@ SUBDIRS = mjdgges kronecker bytecode block_kalman_filter sobol perfect_foresight
# libdynare++ must come before gensylv, k_order_perturbation, dynare_simul_
if ENABLE_MEX_DYNAREPLUSPLUS
SUBDIRS += libdynare++ gensylv k_order_perturbation dynare_simul_ local_state_space_iterations
SUBDIRS += libdynare++ gensylv libkorder dynare_simul_ k_order_perturbation k_order_welfare local_state_space_iterations
endif
if ENABLE_MEX_MS_SBVAR
......
......@@ -135,7 +135,9 @@ AC_CONFIG_FILES([Makefile
bytecode/Makefile
libdynare++/Makefile
gensylv/Makefile
libkorder/Makefile
k_order_perturbation/Makefile
k_order_welfare/Makefile
dynare_simul_/Makefile
kalman_steady_state/Makefile
ms_sbvar/Makefile
......
EXEEXT = .mex
include ../mex.am
include ../../k_order_welfare.am
EXEEXT = .mex
include ../mex.am
include ../../libkorder.am
......@@ -10,6 +10,7 @@ EXTRA_DIST = \
kronecker \
bytecode \
k_order_perturbation \
k_order_welfare \
kalman_steady_state \
ms-sbvar \
block_kalman_filter \
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment