From 7fb7dd7ccc8ec0afd87e836f1dad40afd3058aa4 Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Thu, 5 Jan 2017 17:31:48 +0100 Subject: [PATCH] fix nested parens for params derivatives. closes #1201 --- preprocessor/DynamicModel.cc | 301 +++++++++++++++++++---------------- preprocessor/StaticModel.cc | 282 +++++++++++++++++--------------- 2 files changed, 315 insertions(+), 268 deletions(-) diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index fc5164ef3..08dd2bc45 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -4016,81 +4016,20 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con && !hessian_params_derivatives.size()) return; - string filename = julia ? basename + "DynamicParamsDerivs.jl" : basename + "_params_derivs.m"; - ofstream paramsDerivsFile; - paramsDerivsFile.open(filename.c_str(), ios::out | ios::binary); - if (!paramsDerivsFile.is_open()) - { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; - exit(EXIT_FAILURE); - } - ExprNodeOutputType output_type = (julia ? oJuliaDynamicModel : oMatlabDynamicModel); - - if (!julia) - paramsDerivsFile << "function [rp, gp, rpp, gpp, hp] = " << basename << "_params_derivs(y, x, params, steady_state, it_, ss_param_deriv, ss_param_2nd_deriv)" << endl - << "%" << endl - << "% Compute the derivatives of the dynamic model with respect to the parameters" << endl - << "% Inputs :" << endl - << "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << endl - << "% in M_.lead_lag_incidence; see the Manual" << endl - << "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order)" << endl - << "% for all simulation periods" << endl - << "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl - << "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << endl - << "% it_ scalar double time period for exogenous variables for which to evaluate the model" << endl - << "% ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady states values with respect to the parameters" << endl - << "% ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the steady states values with respect to the parameters" << endl - << "%" << endl - << "% Outputs:" << endl - << "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " << endl - << "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl - << "% gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of the Jacobian matrix of the dynamic model equations with respect to the parameters" << endl - << "% rows: equations in order of declaration" << endl - << "% columns: variables in order stored in M_.lead_lag_incidence" << endl - << "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl - << "% rows: respective derivative term" << endl - << "% 1st column: equation number of the term appearing" << endl - << "% 2nd column: number of the first parameter in derivative" << endl - << "% 3rd column: number of the second parameter in derivative" << endl - << "% 4th column: value of the Hessian term" << endl - << "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters;" << endl - << "% rows: respective derivative term" << endl - << "% 1st column: equation number of the term appearing" << endl - << "% 2nd column: column number of variable in Jacobian of the dynamic model" << endl - << "% 3rd column: number of the first parameter in derivative" << endl - << "% 4th column: number of the second parameter in derivative" << endl - << "% 5th column: value of the Hessian term" << endl - << "% hp [#first_order_Hessian_terms by 5] double Jacobian matrix of derivatives of the dynamic Hessian with respect to the parameters;" << endl - << "% rows: respective derivative term" << endl - << "% 1st column: equation number of the term appearing" << endl - << "% 2nd column: column number of first variable in Hessian of the dynamic model" << endl - << "% 3rd column: column number of second variable in Hessian of the dynamic model" << endl - << "% 4th column: number of the parameter in derivative" << endl - << "% 5th column: value of the Hessian term" << endl - << "%" << endl - << "%" << endl - << "% Warning : this file is generated automatically by Dynare" << endl - << "% from model file (.mod)" << endl << endl; - else - paramsDerivsFile << "module " << basename << "DynamicParamsDerivs" << endl - << "#" << endl - << "# NB: this file was automatically generated by Dynare" << endl - << "# from " << basename << ".mod" << endl - << "#" << endl - << "export params_derivs" << endl << endl - << "function params_derivs(y, x, paramssteady_state, it_, " - << "ss_param_deriv, ss_param_2nd_deriv)" << endl; + ostringstream model_local_vars_output; // Used for storing model local vars + ostringstream model_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 + ostringstream third_derivs_output; // Used for storing third order derivatives equations + ostringstream third_derivs1_output; // Used for storing third order derivatives equations deriv_node_temp_terms_t tef_terms; - writeModelLocalVariables(paramsDerivsFile, output_type, tef_terms); + writeModelLocalVariables(model_local_vars_output, output_type, tef_terms); temporary_terms_t temp_terms_empty; - writeTemporaryTerms(params_derivs_temporary_terms, temp_terms_empty, paramsDerivsFile, output_type, tef_terms); - - // Write parameter derivative - paramsDerivsFile << "rp = zeros(" << equation_number() << ", " - << symbol_table.param_nbr() << ");" << endl; + writeTemporaryTerms(params_derivs_temporary_terms, temp_terms_empty, model_output, output_type, tef_terms); for (first_derivatives_t::const_iterator it = residuals_params_derivatives.begin(); it != residuals_params_derivatives.end(); it++) @@ -4101,16 +4040,12 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "rp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << param_col - << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d1->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + 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, tef_terms); + jacobian_output << ";" << endl; } - // Write jacobian derivatives - paramsDerivsFile << "gp = zeros(" << equation_number() << ", " << dynJacobianColsNbr << ", " - << symbol_table.param_nbr() << ");" << endl; - for (second_derivatives_t::const_iterator it = jacobian_params_derivatives.begin(); it != jacobian_params_derivatives.end(); it++) { @@ -4122,20 +4057,12 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con int var_col = getDynJacobianCol(var) + 1; int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "gp" << LEFT_ARRAY_SUBSCRIPT(output_type) << eq+1 << ", " << var_col - << ", " << param_col << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + 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, tef_terms); + hessian_output << ";" << endl; } - if (!julia) - // If nargout >= 3... - paramsDerivsFile << "if nargout >= 3" << endl; - - // Write parameter second derivatives (only if nargout >= 3) - paramsDerivsFile << "rpp = zeros(" << residuals_params_second_derivatives.size() - << ",4);" << endl; - int i = 1; for (second_derivatives_t::const_iterator it = residuals_params_second_derivatives.begin(); it != residuals_params_second_derivatives.end(); ++it, i++) @@ -4148,22 +4075,18 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1; int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1; - paramsDerivsFile << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + hessian1_output << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl + << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << 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, tef_terms); + hessian1_output << ";" << endl; } - // Write jacobian second derivatives (only if nargout >= 3) - paramsDerivsFile << "gpp = zeros(" << jacobian_params_second_derivatives.size() - << ",5);" << endl; - i = 1; for (third_derivatives_t::const_iterator it = jacobian_params_second_derivatives.begin(); it != jacobian_params_second_derivatives.end(); ++it, i++) @@ -4178,28 +4101,20 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1; int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1; - paramsDerivsFile << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + third_derivs_output << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var_col << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" + << 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, tef_terms); + third_derivs_output << ";" << endl; } - if (!julia) - // If nargout >= 5... - paramsDerivsFile << "end" << endl - << "if nargout >= 5" << endl; - - // Write hessian derivatives (only if nargout >= 5) - paramsDerivsFile << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl; - i = 1; for (third_derivatives_t::const_iterator it = hessian_params_derivatives.begin(); it != hessian_params_derivatives.end(); ++it, i++) @@ -4214,24 +4129,130 @@ DynamicModel::writeParamsDerivativesFile(const string &basename, bool julia) con int var2_col = getDynJacobianCol(var2) + 1; int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var1_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var2_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + third_derivs1_output << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var1_col << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var2_col << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" + << 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, tef_terms); + third_derivs1_output << ";" << endl; } - if (julia) - paramsDerivsFile << "(rp, gp, rpp, gpp, hp)" << endl; - paramsDerivsFile << "end" << endl - << "end" << endl; + string filename = julia ? basename + "DynamicParamsDerivs.jl" : basename + "_params_derivs.m"; + ofstream paramsDerivsFile; + paramsDerivsFile.open(filename.c_str(), ios::out | ios::binary); + if (!paramsDerivsFile.is_open()) + { + cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + if (!julia) + { + // 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(jacobian_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(hessian_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(hessian1_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(third_derivs_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(third_derivs1_output, tmp_paren_vars, message_printed); + paramsDerivsFile << "function [rp, gp, rpp, gpp, hp] = " << basename << "_params_derivs(y, x, params, steady_state, it_, ss_param_deriv, ss_param_2nd_deriv)" << endl + << "%" << endl + << "% Compute the derivatives of the dynamic model with respect to the parameters" << endl + << "% Inputs :" << endl + << "% y [#dynamic variables by 1] double vector of endogenous variables in the order stored" << endl + << "% in M_.lead_lag_incidence; see the Manual" << endl + << "% x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order)" << endl + << "% for all simulation periods" << endl + << "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl + << "% steady_state [M_.endo_nbr by 1] double vector of steady state values" << endl + << "% it_ scalar double time period for exogenous variables for which to evaluate the model" << endl + << "% ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady states values with respect to the parameters" << endl + << "% ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the steady states values with respect to the parameters" << endl + << "%" << endl + << "% Outputs:" << endl + << "% rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " << endl + << "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl + << "% gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of the Jacobian matrix of the dynamic model equations with respect to the parameters" << endl + << "% rows: equations in order of declaration" << endl + << "% columns: variables in order stored in M_.lead_lag_incidence" << endl + << "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl + << "% rows: respective derivative term" << endl + << "% 1st column: equation number of the term appearing" << endl + << "% 2nd column: number of the first parameter in derivative" << endl + << "% 3rd column: number of the second parameter in derivative" << endl + << "% 4th column: value of the Hessian term" << endl + << "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters;" << endl + << "% rows: respective derivative term" << endl + << "% 1st column: equation number of the term appearing" << endl + << "% 2nd column: column number of variable in Jacobian of the dynamic model" << endl + << "% 3rd column: number of the first parameter in derivative" << endl + << "% 4th column: number of the second parameter in derivative" << endl + << "% 5th column: value of the Hessian term" << endl + << "% hp [#first_order_Hessian_terms by 5] double Jacobian matrix of derivatives of the dynamic Hessian with respect to the parameters;" << endl + << "% rows: respective derivative term" << endl + << "% 1st column: equation number of the term appearing" << endl + << "% 2nd column: column number of first variable in Hessian of the dynamic model" << endl + << "% 3rd column: column number of second variable in Hessian of the dynamic model" << endl + << "% 4th column: number of the parameter in derivative" << endl + << "% 5th column: value of the Hessian term" << endl + << "%" << endl + << "%" << endl + << "% Warning : this file is generated automatically by Dynare" << endl + << "% from model file (.mod)" << endl << endl + << model_local_vars_output.str() + << model_output.str() + << "rp = zeros(" << equation_number() << ", " + << symbol_table.param_nbr() << ");" << endl + << jacobian_output.str() + << "gp = zeros(" << equation_number() << ", " << dynJacobianColsNbr << ", " << symbol_table.param_nbr() << ");" << endl + << hessian_output.str() + << "if nargout >= 3" << endl + << "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl + << hessian1_output.str() + << "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl + << third_derivs_output.str() + << "end" << endl + << "if nargout >= 5" << endl + << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl + << third_derivs1_output.str() + << "end" << endl + << "end" << endl; + } + else + paramsDerivsFile << "module " << basename << "DynamicParamsDerivs" << endl + << "#" << endl + << "# NB: this file was automatically generated by Dynare" << endl + << "# from " << basename << ".mod" << endl + << "#" << endl + << "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() + << "rp = zeros(" << equation_number() << ", " + << symbol_table.param_nbr() << ");" << endl + << jacobian_output.str() + << "gp = zeros(" << equation_number() << ", " << dynJacobianColsNbr << ", " << symbol_table.param_nbr() << ");" << endl + << hessian_output.str() + << "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl + << hessian1_output.str() + << "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl + << third_derivs_output.str() + << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl + << third_derivs1_output.str() + << "(rp, gp, rpp, gpp, hp)" << endl + << "end" << endl + << "end" << endl; + paramsDerivsFile.close(); } diff --git a/preprocessor/StaticModel.cc b/preprocessor/StaticModel.cc index f02ef83cc..a7652f9b8 100644 --- a/preprocessor/StaticModel.cc +++ b/preprocessor/StaticModel.cc @@ -2181,68 +2181,21 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons && !hessian_params_derivatives.size()) return; - string filename = julia ? basename + "StaticParamsDerivs.jl" : basename + "_static_params_derivs.m"; - ofstream paramsDerivsFile; - paramsDerivsFile.open(filename.c_str(), ios::out | ios::binary); - if (!paramsDerivsFile.is_open()) - { - cerr << "ERROR: Can't open file " << filename << " for writing" << endl; - exit(EXIT_FAILURE); - } - ExprNodeOutputType output_type = (julia ? oJuliaStaticModel : oMatlabStaticModel); - if (!julia) - paramsDerivsFile << "function [rp, gp, rpp, gpp, hp] = " << basename << "_static_params_derivs(y, x, params)" << endl - << "%" << endl - << "% Status : Computes derivatives of the static model with respect to the parameters" << endl - << "%" << endl - << "% Inputs : " << endl - << "% y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order" << endl - << "% x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order" << endl - << "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl - << "%" << endl - << "% Outputs:" << endl - << "% rp [M_.eq_nbr by #params] double Jacobian matrix of static model equations with respect to parameters " << endl - << "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl - << "% gp [M_.endo_nbr by M_.endo_nbr by #params] double Derivative of the Jacobian matrix of the static model equations with respect to the parameters" << endl - << "% rows: variables in declaration order" << endl - << "% rows: equations in order of declaration" << endl - << "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl - << "% rows: respective derivative term" << endl - << "% 1st column: equation number of the term appearing" << endl - << "% 2nd column: number of the first parameter in derivative" << endl - << "% 3rd column: number of the second parameter in derivative" << endl - << "% 4th column: value of the Hessian term" << endl - << "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters;" << endl - << "% rows: respective derivative term" << endl - << "% 1st column: equation number of the term appearing" << endl - << "% 2nd column: column number of variable in Jacobian of the static model" << endl - << "% 3rd column: number of the first parameter in derivative" << endl - << "% 4th column: number of the second parameter in derivative" << endl - << "% 5th column: value of the Hessian term" << endl - << "%" << endl - << "%" << endl - << "% Warning : this file is generated automatically by Dynare" << endl - << "% from model file (.mod)" << endl << endl; - else - paramsDerivsFile << "module " << basename << "StaticParamsDerivs" << endl - << "#" << endl - << "# NB: this file was automatically generated by Dynare" << endl - << "# from " << basename << ".mod" << endl - << "#" << endl - << "export params_derivs" << endl << endl - << "function params_derivs(y, x, params)" << endl; + ostringstream model_local_vars_output; // Used for storing model local vars + ostringstream model_output; // Used for storing model + ostringstream jacobian_output; // Used for storing jacobian equations + ostringstream hessian_output; // Used for storing Hessian equations + ostringstream hessian1_output; // Used for storing Hessian equations + ostringstream third_derivs_output; // Used for storing third order derivatives equations + ostringstream third_derivs1_output; // Used for storing third order derivatives equations deriv_node_temp_terms_t tef_terms; - writeModelLocalVariables(paramsDerivsFile, output_type, tef_terms); + writeModelLocalVariables(model_local_vars_output, output_type, tef_terms); temporary_terms_t temp_terms_empty; - writeTemporaryTerms(params_derivs_temporary_terms, temp_terms_empty, paramsDerivsFile, output_type, tef_terms); - - // Write parameter derivative - paramsDerivsFile << "rp = zeros(" << equation_number() << ", " - << symbol_table.param_nbr() << ");" << endl; + writeTemporaryTerms(params_derivs_temporary_terms, temp_terms_empty, model_output, output_type, tef_terms); for (first_derivatives_t::const_iterator it = residuals_params_derivatives.begin(); it != residuals_params_derivatives.end(); it++) @@ -2253,17 +2206,13 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "rp" << LEFT_ARRAY_SUBSCRIPT(output_type) - << eq+1 << ", " << param_col - << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d1->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + 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, tef_terms); + jacobian_output << ";" << endl; } - // Write jacobian derivatives - paramsDerivsFile << "gp = zeros(" << equation_number() << ", " << symbol_table.endo_nbr() << ", " - << symbol_table.param_nbr() << ");" << endl; - for (second_derivatives_t::const_iterator it = jacobian_params_derivatives.begin(); it != jacobian_params_derivatives.end(); it++) { @@ -2275,21 +2224,13 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons int var_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var)) + 1; int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "gp" << LEFT_ARRAY_SUBSCRIPT(output_type) - << eq+1 << ", " << var_col << ", " << param_col - << RIGHT_ARRAY_SUBSCRIPT(output_type) << " = "; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + 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, tef_terms); + hessian_output << ";" << endl; } - if (!julia) - // If nargout >= 3... - paramsDerivsFile << "if nargout >= 3" << endl; - - // Write parameter second derivatives (only if nargout >= 3) - paramsDerivsFile << "rpp = zeros(" << residuals_params_second_derivatives.size() - << ",4);" << endl; - int i = 1; for (second_derivatives_t::const_iterator it = residuals_params_second_derivatives.begin(); it != residuals_params_second_derivatives.end(); ++it, i++) @@ -2302,22 +2243,18 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1; int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1; - paramsDerivsFile << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl - << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + hessian1_output << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl + << "rpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << 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, tef_terms); + hessian1_output << ";" << endl; } - // Write jacobian second derivatives (only if nargout >= 3) - paramsDerivsFile << "gpp = zeros(" << jacobian_params_second_derivatives.size() - << ",5);" << endl; - i = 1; for (third_derivatives_t::const_iterator it = jacobian_params_second_derivatives.begin(); it != jacobian_params_second_derivatives.end(); ++it, i++) @@ -2332,28 +2269,20 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons int param1_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param1)) + 1; int param2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param2)) + 1; - paramsDerivsFile << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param2_col << ";" << endl - << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + third_derivs_output << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var_col << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param1_col << ";" << endl + << "gpp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" + << 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, tef_terms); + third_derivs_output << ";" << endl; } - if (!julia) - // If nargout >= 5... - paramsDerivsFile << "end" << endl - << "if nargout >= 5" << endl; - - // Write hessian derivatives (only if nargout >= 5) - paramsDerivsFile << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl; - i = 1; for (third_derivatives_t::const_iterator it = hessian_params_derivatives.begin(); it != hessian_params_derivatives.end(); ++it, i++) @@ -2368,23 +2297,120 @@ StaticModel::writeParamsDerivativesFile(const string &basename, bool julia) cons int var2_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(var2)) + 1; int param_col = symbol_table.getTypeSpecificID(getSymbIDByDerivID(param)) + 1; - paramsDerivsFile << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var1_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var2_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << param_col << ";" << endl - << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",5" - << RIGHT_ARRAY_SUBSCRIPT(output_type) << "="; - d2->writeOutput(paramsDerivsFile, output_type, params_derivs_temporary_terms, tef_terms); - paramsDerivsFile << ";" << endl; + third_derivs1_output << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",1" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << eq+1 << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",2" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var1_col << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",3" + << RIGHT_ARRAY_SUBSCRIPT(output_type) << "=" << var2_col << ";" << endl + << "hp" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << ",4" + << 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, tef_terms); + third_derivs1_output << ";" << endl; } - if (julia) - paramsDerivsFile << "(rp, gp, rpp, gpp, hp)" << endl; - paramsDerivsFile << "end" << endl - << "end" << endl; + + ofstream paramsDerivsFile; + string filename = julia ? basename + "StaticParamsDerivs.jl" : basename + "_static_params_derivs.m"; + paramsDerivsFile.open(filename.c_str(), ios::out | ios::binary); + if (!paramsDerivsFile.is_open()) + { + cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + if (!julia) + { + // 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(jacobian_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(hessian_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(hessian1_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(third_derivs_output, tmp_paren_vars, message_printed); + fixNestedParenthesis(third_derivs1_output, tmp_paren_vars, message_printed); + + paramsDerivsFile << "function [rp, gp, rpp, gpp, hp] = " << basename << "_static_params_derivs(y, x, params)" << endl + << "%" << endl + << "% Status : Computes derivatives of the static model with respect to the parameters" << endl + << "%" << endl + << "% Inputs : " << endl + << "% y [M_.endo_nbr by 1] double vector of endogenous variables in declaration order" << endl + << "% x [M_.exo_nbr by 1] double vector of exogenous variables in declaration order" << endl + << "% params [M_.param_nbr by 1] double vector of parameter values in declaration order" << endl + << "%" << endl + << "% Outputs:" << endl + << "% rp [M_.eq_nbr by #params] double Jacobian matrix of static model equations with respect to parameters " << endl + << "% Dynare may prepend or append auxiliary equations, see M_.aux_vars" << endl + << "% gp [M_.endo_nbr by M_.endo_nbr by #params] double Derivative of the Jacobian matrix of the static model equations with respect to the parameters" << endl + << "% rows: variables in declaration order" << endl + << "% rows: equations in order of declaration" << endl + << "% rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters;" << endl + << "% rows: respective derivative term" << endl + << "% 1st column: equation number of the term appearing" << endl + << "% 2nd column: number of the first parameter in derivative" << endl + << "% 3rd column: number of the second parameter in derivative" << endl + << "% 4th column: value of the Hessian term" << endl + << "% gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters;" << endl + << "% rows: respective derivative term" << endl + << "% 1st column: equation number of the term appearing" << endl + << "% 2nd column: column number of variable in Jacobian of the static model" << endl + << "% 3rd column: number of the first parameter in derivative" << endl + << "% 4th column: number of the second parameter in derivative" << endl + << "% 5th column: value of the Hessian term" << endl + << "%" << endl + << "%" << endl + << "% Warning : this file is generated automatically by Dynare" << endl + << "% from model file (.mod)" << endl << endl + << model_local_vars_output.str() + << model_output.str() + << "rp = zeros(" << equation_number() << ", " + << symbol_table.param_nbr() << ");" << endl + << jacobian_output.str() + << "gp = zeros(" << equation_number() << ", " << symbol_table.endo_nbr() << ", " + << symbol_table.param_nbr() << ");" << endl + << hessian_output.str() + << "if nargout >= 3" << endl + << "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl + << hessian1_output.str() + << "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl + << third_derivs_output.str() + << "end" << endl + << "if nargout >= 5" << endl + << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl + << third_derivs1_output.str() + << "end" << endl + << "end" << endl; + } + else + paramsDerivsFile << "module " << basename << "StaticParamsDerivs" << endl + << "#" << endl + << "# NB: this file was automatically generated by Dynare" << endl + << "# from " << basename << ".mod" << endl + << "#" << endl + << "export params_derivs" << endl << endl + << "function params_derivs(y, x, params)" << endl + << model_local_vars_output.str() + << model_output.str() + << "rp = zeros(" << equation_number() << ", " + << symbol_table.param_nbr() << ");" << endl + << jacobian_output.str() + << "gp = zeros(" << equation_number() << ", " << symbol_table.endo_nbr() << ", " + << symbol_table.param_nbr() << ");" << endl + << hessian_output.str() + << "rpp = zeros(" << residuals_params_second_derivatives.size() << ",4);" << endl + << hessian1_output.str() + << "gpp = zeros(" << jacobian_params_second_derivatives.size() << ",5);" << endl + << third_derivs_output.str() + << "hp = zeros(" << hessian_params_derivatives.size() << ",5);" << endl + << third_derivs1_output.str() + << "(rp, gp, rpp, gpp, hp)" << endl + << "end" << endl + << "end" << endl; + paramsDerivsFile.close(); }