From e9b5f239df4cc0b7c250a85f6211d469ae726f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Fri, 16 Nov 2018 18:13:34 +0100 Subject: [PATCH] Properly deal with model local variables in params derivatives file Closes #13 --- src/DynamicModel.cc | 35 +++++++++++++++++------------------ src/ModelTree.cc | 8 ++++++-- src/ModelTree.hh | 4 ++++ src/StaticModel.cc | 33 ++++++++++++++++----------------- 4 files changed, 43 insertions(+), 37 deletions(-) diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 376dfbba..31663c14 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -2508,7 +2508,7 @@ DynamicModel::writeDynamicModel(const string &basename, ostream &DynamicOutput, deriv_node_temp_terms_t tef_terms; temporary_terms_t temp_term_union; - writeModelLocalVariableTemporaryTerms(temp_term_union, + writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_idxs, model_tt_output, output_type, tef_terms); writeTemporaryTerms(temporary_terms_derivatives[0], @@ -4400,9 +4400,6 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative if (!nopreprocessoroutput) cout << " - derivatives of Jacobian/Hessian w.r. to parameters" << endl; computeParamsDerivatives(paramsDerivsOrder); - - if (!no_tmp_terms) - computeParamsDerivativesTemporaryTerms(); } if (thirdDerivatives) @@ -4509,6 +4506,11 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative computeTemporaryTerms(!use_dll, no_tmp_terms); if (bytecode && !no_tmp_terms) computeTemporaryTermsMapping(); + + /* Must be called after computeTemporaryTerms(), because it depends on + temporary_terms_mlv to be filled */ + if (paramsDerivsOrder > 0 && !no_tmp_terms) + computeParamsDerivativesTemporaryTerms(); } } @@ -5375,8 +5377,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con return; ExprNodeOutputType output_type = (julia ? ExprNodeOutputType::juliaDynamicModel : ExprNodeOutputType::matlabDynamicModel); - ostringstream model_local_vars_output; // Used for storing model local vars - ostringstream model_output; // Used for storing model temp vars and equations + ostringstream tt_output; // Used for storing model temp vars and equations ostringstream jacobian_output; // Used for storing jacobian equations ostringstream hessian_output; // Used for storing Hessian equations ostringstream hessian1_output; // Used for storing Hessian equations @@ -5386,7 +5387,8 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con temporary_terms_t temp_term_union; deriv_node_temp_terms_t tef_terms; - writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, model_output, output_type, tef_terms); + writeModelLocalVariableTemporaryTerms(temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms); + writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms); for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second) { @@ -5398,7 +5400,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con jacobian_output << "rp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d1->writeOutput(jacobian_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d1->writeOutput(jacobian_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); jacobian_output << ";" << endl; } @@ -5413,7 +5415,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con hessian_output << "gp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << var_col << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d2->writeOutput(hessian_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(hessian_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); hessian_output << ";" << endl; } @@ -5435,7 +5437,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(hessian1_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(hessian1_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); hessian1_output << ";" << endl; i++; @@ -5462,7 +5464,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(third_derivs_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(third_derivs_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); third_derivs_output << ";" << endl; i++; @@ -5489,7 +5491,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param_col << ";" << endl << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(third_derivs1_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(third_derivs1_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); third_derivs1_output << ";" << endl; i++; @@ -5509,8 +5511,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con // Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201 map tmp_paren_vars; bool message_printed = false; - fixNestedParenthesis(model_output, tmp_paren_vars, message_printed); - fixNestedParenthesis(model_local_vars_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(tt_output, tmp_paren_vars, message_printed); fixNestedParenthesis(jacobian_output, tmp_paren_vars, message_printed); fixNestedParenthesis(hessian_output, tmp_paren_vars, message_printed); fixNestedParenthesis(hessian1_output, tmp_paren_vars, message_printed); @@ -5561,8 +5562,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl << "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl - << model_local_vars_output.str() - << model_output.str() + << tt_output.str() << "rp = zeros(" << equations.size() << ", " << symbol_table.param_nbr() << ");" << endl << jacobian_output.str() @@ -5589,8 +5589,7 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con << "export params_derivs" << endl << endl << "function params_derivs(y, x, paramssteady_state, it_, " << "ss_param_deriv, ss_param_2nd_deriv)" << endl - << model_local_vars_output.str() - << model_output.str() + << tt_output.str() << "rp = zeros(" << equations.size() << ", " << symbol_table.param_nbr() << ");" << endl << jacobian_output.str() diff --git a/src/ModelTree.cc b/src/ModelTree.cc index 111c046c..22741cc8 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -1432,6 +1432,7 @@ ModelTree::computeTemporaryTerms(bool is_matlab, bool no_tmp_terms) void ModelTree::writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union, + const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const { @@ -1444,9 +1445,9 @@ ModelTree::writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_un if (isJuliaOutput(output_type)) output << " @inbounds const "; - it.first->writeOutput(output, output_type, tto, temporary_terms_idxs, tef_terms); + it.first->writeOutput(output, output_type, tto, tt_idxs, tef_terms); output << " = "; - it.second->writeOutput(output, output_type, temp_term_union, temporary_terms_idxs, tef_terms); + it.second->writeOutput(output, output_type, temp_term_union, tt_idxs, tef_terms); if (isCOutput(output_type) || isMatlabOutput(output_type)) output << ";"; @@ -2184,6 +2185,9 @@ ModelTree::computeParamsDerivativesTemporaryTerms() params_derivs_temporary_terms_split[{ 2, 1 }] = temp_terms_map[NodeTreeReference::hessianParamsDeriv]; int idx = 0; + for (auto &it : temporary_terms_mlv) + params_derivs_temporary_terms_idxs[it.first] = idx++; + for (auto tt : params_derivs_temporary_terms_split[{ 0, 1 }]) params_derivs_temporary_terms_idxs[tt] = idx++; diff --git a/src/ModelTree.hh b/src/ModelTree.hh index 33e0b79f..0560f473 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -121,6 +121,9 @@ protected: temporary_terms_idxs_t temporary_terms_idxs; //! Temporary terms for the file containing parameters derivatives + /*! However does not contain the TT related to model local variables. + TODO: this variable should probably be removed, it is essentially the + same information as in params_derivs_temporary_terms_split */ temporary_terms_t params_derivs_temporary_terms; //! Temporary terms for parameter derivatives, under a disaggregated form @@ -176,6 +179,7 @@ protected: //! Tests if string contains more than 32 nested parens, Issue #1201 bool testNestedParenthesis(const string &str) const; void writeModelLocalVariableTemporaryTerms(temporary_terms_t &temp_term_union, + const temporary_terms_idxs_t &tt_idxs, ostream &output, ExprNodeOutputType output_type, deriv_node_temp_terms_t &tef_terms) const; //! Writes model equations diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 20ab6982..4d621f3d 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -1269,9 +1269,6 @@ StaticModel::computingPass(const eval_context_t &eval_context, bool no_tmp_terms if (!nopreprocessoroutput) cout << " - derivatives of Jacobian/Hessian w.r. to parameters" << endl; computeParamsDerivatives(paramsDerivsOrder); - - if (!no_tmp_terms) - computeParamsDerivativesTemporaryTerms(); } if (block) @@ -1318,6 +1315,11 @@ StaticModel::computingPass(const eval_context_t &eval_context, bool no_tmp_terms computeTemporaryTerms(true, no_tmp_terms); if (bytecode && !no_tmp_terms) computeTemporaryTermsMapping(temporary_terms, map_idx); + + /* Must be called after computeTemporaryTerms(), because it depends on + temporary_terms_mlv to be filled */ + if (paramsDerivsOrder > 0 && !no_tmp_terms) + computeParamsDerivativesTemporaryTerms(); } } @@ -1519,7 +1521,7 @@ StaticModel::writeStaticModel(const string &basename, deriv_node_temp_terms_t tef_terms; temporary_terms_t temp_term_union; - writeModelLocalVariableTemporaryTerms(temp_term_union, + writeModelLocalVariableTemporaryTerms(temp_term_union, temporary_terms_idxs, model_tt_output, output_type, tef_terms); writeTemporaryTerms(temporary_terms_derivatives[0], @@ -2640,8 +2642,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons ExprNodeOutputType output_type = (julia ? ExprNodeOutputType::juliaStaticModel : ExprNodeOutputType::matlabStaticModel); - ostringstream model_local_vars_output; // Used for storing model local vars - ostringstream model_output; // Used for storing model + ostringstream tt_output; // Used for storing temporary terms ostringstream jacobian_output; // Used for storing jacobian equations ostringstream hessian_output; // Used for storing Hessian equations ostringstream hessian1_output; // Used for storing Hessian equations @@ -2651,6 +2652,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons temporary_terms_t temp_term_union; deriv_node_temp_terms_t tef_terms; + writeModelLocalVariableTemporaryTerms(temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms); writeTemporaryTerms(params_derivs_temporary_terms, temp_term_union, params_derivs_temporary_terms_idxs, tt_output, output_type, tef_terms); for (const auto & residuals_params_derivative : params_derivatives.find({ 0, 1 })->second) @@ -2664,7 +2666,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons jacobian_output << "rp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d1->writeOutput(jacobian_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d1->writeOutput(jacobian_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); jacobian_output << ";" << endl; } @@ -2680,7 +2682,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons hessian_output << "gp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << var_col << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d2->writeOutput(hessian_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(hessian_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); hessian_output << ";" << endl; } @@ -2702,7 +2704,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(hessian1_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(hessian1_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); hessian1_output << ";" << endl; i++; @@ -2729,7 +2731,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(third_derivs_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(third_derivs_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); third_derivs_output << ";" << endl; i++; @@ -2756,7 +2758,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param_col << ";" << endl << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(third_derivs1_output, output_type, params_derivs_temporary_terms, params_derivs_temporary_terms_idxs, tef_terms); + d2->writeOutput(third_derivs1_output, output_type, temp_term_union, params_derivs_temporary_terms_idxs, tef_terms); third_derivs1_output << ";" << endl; i++; @@ -2776,8 +2778,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons // Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201 map tmp_paren_vars; bool message_printed = false; - fixNestedParenthesis(model_output, tmp_paren_vars, message_printed); - fixNestedParenthesis(model_local_vars_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(tt_output, tmp_paren_vars, message_printed); fixNestedParenthesis(jacobian_output, tmp_paren_vars, message_printed); fixNestedParenthesis(hessian_output, tmp_paren_vars, message_printed); fixNestedParenthesis(hessian1_output, tmp_paren_vars, message_printed); @@ -2817,8 +2818,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl << "T = NaN(" << params_derivs_temporary_terms_idxs.size() << ",1);" << endl - << model_local_vars_output.str() - << model_output.str() + << tt_output.str() << "rp = zeros(" << equations.size() << ", " << symbol_table.param_nbr() << ");" << endl << jacobian_output.str() @@ -2845,8 +2845,7 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons << "#" << endl << "export params_derivs" << endl << endl << "function params_derivs(y, x, params)" << endl - << model_local_vars_output.str() - << model_output.str() + << tt_output.str() << "rp = zeros(" << equations.size() << ", " << symbol_table.param_nbr() << ");" << endl << jacobian_output.str()