adding 3rd order derivatives to Static Model for evaluation of Ramsey

policy computed at order = 2
issue#70
Michel Juillard 2013-11-22 21:09:04 +01:00
parent 1d7646a6e5
commit 9dfcf897f7
4 changed files with 101 additions and 7 deletions

View File

@ -179,9 +179,9 @@ RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConso
if (it != options_list.num_options.end()) if (it != options_list.num_options.end())
{ {
int order = atoi(it->second.c_str()); int order = atoi(it->second.c_str());
if (order > 1) if (order > 2)
{ {
cerr << "ERROR: ramsey_policy: order > 1 is not yet implemented" << endl; cerr << "ERROR: ramsey_policy: order > 2 is not implemented" << endl;
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1); mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
@ -968,7 +968,7 @@ PlannerObjectiveStatement::getPlannerObjective() const
void void
PlannerObjectiveStatement::computingPass() PlannerObjectiveStatement::computingPass()
{ {
model_tree->computingPass(eval_context_t(), false, true, false, false, false); model_tree->computingPass(eval_context_t(), false, true, true, false, false, false);
} }
void void

View File

@ -470,7 +470,7 @@ ModFile::computingPass(bool no_tmp_terms)
const bool paramsDerivatives = mod_file_struct.identification_present const bool paramsDerivatives = mod_file_struct.identification_present
|| mod_file_struct.estimation_analytic_derivation; || mod_file_struct.estimation_analytic_derivation;
static_model.computingPass(global_eval_context, no_tmp_terms, static_hessian, static_model.computingPass(global_eval_context, no_tmp_terms, static_hessian,
paramsDerivatives, block, byte_code); false, paramsDerivatives, block, byte_code);
} }
// Set things to compute for dynamic model // Set things to compute for dynamic model
if (mod_file_struct.simul_present || mod_file_struct.check_present if (mod_file_struct.simul_present || mod_file_struct.check_present

View File

@ -1047,7 +1047,7 @@ StaticModel::collect_first_order_derivatives_endogenous()
} }
void void
StaticModel::computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian, bool paramsDerivatives, bool block, bool bytecode) StaticModel::computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian, bool thirdDerivatives, bool paramsDerivatives, bool block, bool bytecode)
{ {
initializeVariablesAndEquations(); initializeVariablesAndEquations();
@ -1070,6 +1070,12 @@ StaticModel::computingPass(const eval_context_t &eval_context, bool no_tmp_terms
computeHessian(vars); computeHessian(vars);
} }
if (thirdDerivatives)
{
cout << " - order 3" << endl;
computeThirdDerivatives(vars);
}
if (paramsDerivatives) if (paramsDerivatives)
{ {
cout << " - derivatives of Jacobian/Hessian w.r. to parameters" << endl; cout << " - derivatives of Jacobian/Hessian w.r. to parameters" << endl;
@ -1142,7 +1148,7 @@ StaticModel::writeStaticMFile(const string &func_name) const
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
output << "function [residual, g1, g2] = " << func_name + "_static(y, x, params)" << endl output << "function [residual, g1, g2, g3] = " << func_name + "_static(y, x, params)" << endl
<< "%" << endl << "%" << endl
<< "% Status : Computes static model for Dynare" << endl << "% Status : Computes static model for Dynare" << endl
<< "%" << endl << "%" << endl
@ -1160,6 +1166,9 @@ StaticModel::writeStaticMFile(const string &func_name) const
<< "% g2 [M_.endo_nbr by (M_.endo_nbr)^2] double Hessian matrix of the static model equations;" << endl << "% g2 [M_.endo_nbr by (M_.endo_nbr)^2] double Hessian matrix of the static model equations;" << endl
<< "% columns: equations in order of declaration" << endl << "% columns: equations in order of declaration" << endl
<< "% rows: variables in declaration order" << endl << "% rows: variables in declaration order" << endl
<< "% g3 [M_.endo_nbr by (M_.endo_nbr)^3] double Third derivatives matrix of the static model equations;" << endl
<< "% columns: variables in declaration order" << endl
<< "% rows: equations in order of declaration" << endl
<< "%" << endl << "%" << endl
<< "%" << endl << "%" << endl
<< "% Warning : this file is generated automatically by Dynare" << endl << "% Warning : this file is generated automatically by Dynare" << endl
@ -1176,6 +1185,7 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll) const
ostringstream model_output; // Used for storing model equations ostringstream model_output; // Used for storing model equations
ostringstream jacobian_output; // Used for storing jacobian equations ostringstream jacobian_output; // Used for storing jacobian equations
ostringstream hessian_output; // Used for storing Hessian equations ostringstream hessian_output; // Used for storing Hessian equations
ostringstream third_derivatives_output; // Used for storing third order derivatives equations
ExprNodeOutputType output_type = (use_dll ? oCStaticModel : oMatlabStaticModel); ExprNodeOutputType output_type = (use_dll ? oCStaticModel : oMatlabStaticModel);
deriv_node_temp_terms_t tef_terms; deriv_node_temp_terms_t tef_terms;
@ -1185,6 +1195,10 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll) const
writeModelEquations(model_output, output_type); writeModelEquations(model_output, output_type);
int nrows = equations.size();
int JacobianColsNbr = symbol_table.endo_nbr();
int hessianColsNbr = JacobianColsNbr*JacobianColsNbr;
// Write Jacobian w.r. to endogenous only // Write Jacobian w.r. to endogenous only
for (first_derivatives_t::const_iterator it = first_derivatives.begin(); for (first_derivatives_t::const_iterator it = first_derivatives.begin();
it != first_derivatives.end(); it++) it != first_derivatives.end(); it++)
@ -1247,6 +1261,64 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll) const
} }
} }
// Writing third derivatives
k = 0; // Keep the line of a 3rd derivative in v3
for (third_derivatives_t::const_iterator it = third_derivatives.begin();
it != third_derivatives.end(); it++)
{
int eq = it->first.first;
int var1 = it->first.second.first;
int var2 = it->first.second.second.first;
int var3 = it->first.second.second.second;
expr_t d3 = it->second;
int id1 = getSymbIDByDerivID(var1);
int id2 = getSymbIDByDerivID(var2);
int id3 = getSymbIDByDerivID(var3);
// Reference column number for the g3 matrix
int ref_col = id1 * hessianColsNbr + id2 * JacobianColsNbr + id3;
sparseHelper(3, third_derivatives_output, k, 0, output_type);
third_derivatives_output << "=" << eq + 1 << ";" << endl;
sparseHelper(3, third_derivatives_output, k, 1, output_type);
third_derivatives_output << "=" << ref_col + 1 << ";" << endl;
sparseHelper(3, third_derivatives_output, k, 2, output_type);
third_derivatives_output << "=";
d3->writeOutput(third_derivatives_output, output_type, temporary_terms, tef_terms);
third_derivatives_output << ";" << endl;
// Compute the column numbers for the 5 other permutations of (id1,id2,id3) and store them in a set (to avoid duplicates if two indexes are equal)
set<int> cols;
cols.insert(id1 * hessianColsNbr + id3 * JacobianColsNbr + id2);
cols.insert(id2 * hessianColsNbr + id1 * JacobianColsNbr + id3);
cols.insert(id2 * hessianColsNbr + id3 * JacobianColsNbr + id1);
cols.insert(id3 * hessianColsNbr + id1 * JacobianColsNbr + id2);
cols.insert(id3 * hessianColsNbr + id2 * JacobianColsNbr + id1);
int k2 = 1; // Keeps the offset of the permutation relative to k
for (set<int>::iterator it2 = cols.begin(); it2 != cols.end(); it2++)
if (*it2 != ref_col)
{
sparseHelper(3, third_derivatives_output, k+k2, 0, output_type);
third_derivatives_output << "=" << eq + 1 << ";" << endl;
sparseHelper(3, third_derivatives_output, k+k2, 1, output_type);
third_derivatives_output << "=" << *it2 + 1 << ";" << endl;
sparseHelper(3, third_derivatives_output, k+k2, 2, output_type);
third_derivatives_output << "=";
sparseHelper(3, third_derivatives_output, k, 2, output_type);
third_derivatives_output << ";" << endl;
k2++;
}
k += k2;
}
if (!use_dll) if (!use_dll)
{ {
StaticOutput << "residual = zeros( " << equations.size() << ", 1);" << endl << endl StaticOutput << "residual = zeros( " << equations.size() << ", 1);" << endl << endl
@ -1280,6 +1352,20 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll) const
else else
StaticOutput << " g2 = sparse([],[],[]," << equations.size() << "," << g2ncols << ");" << endl; StaticOutput << " g2 = sparse([],[],[]," << equations.size() << "," << g2ncols << ");" << endl;
StaticOutput << "end" << endl; StaticOutput << "end" << endl;
// Initialize g3 matrix
StaticOutput << "if nargout >= 4," << endl
<< " %" << endl
<< " % Third order derivatives" << endl
<< " %" << endl
<< endl;
int ncols = hessianColsNbr * JacobianColsNbr;
if (third_derivatives.size())
StaticOutput << " v3 = zeros(" << NNZDerivatives[2] << ",3);" << endl
<< third_derivatives_output.str()
<< " g3 = sparse(v3(:,1),v3(:,2),v3(:,3)," << nrows << "," << ncols << ");" << endl;
else // Either 3rd derivatives is all zero, or we didn't compute it
StaticOutput << " g3 = sparse([],[],[]," << nrows << "," << ncols << ");" << endl;
} }
else else
{ {
@ -1305,6 +1391,14 @@ StaticModel::writeStaticModel(ostream &StaticOutput, bool use_dll) const
<< " {" << endl << " {" << endl
<< hessian_output.str() << hessian_output.str()
<< " }" << endl; << " }" << endl;
if (third_derivatives.size())
StaticOutput << " /* Third derivatives for endogenous and exogenous variables */" << endl
<< " if (v3 == NULL)" << endl
<< " return;" << endl
<< " else" << endl
<< " {" << endl
<< third_derivatives_output.str()
<< " }" << endl;
} }
} }

View File

@ -161,7 +161,7 @@ public:
\param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed \param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed
\param paramsDerivatives whether 2nd derivatives w.r. to a pair (endo/exo/exo_det, parameter) should be computed \param paramsDerivatives whether 2nd derivatives w.r. to a pair (endo/exo/exo_det, parameter) should be computed
*/ */
void computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian,bool paramsDerivatives, bool block, bool bytecode); void computingPass(const eval_context_t &eval_context, bool no_tmp_terms, bool hessian, bool thirdDerivatices, bool paramsDerivatives, bool block, bool bytecode);
//! Adds informations for simulation in a binary file for a block decomposed model //! Adds informations for simulation in a binary file for a block decomposed model
void Write_Inf_To_Bin_File_Block(const string &static_basename, const string &bin_basename, const int &num, void Write_Inf_To_Bin_File_Block(const string &static_basename, const string &bin_basename, const int &num,