diff --git a/preprocessor/ComputingTasks.cc b/preprocessor/ComputingTasks.cc index 2954c023810dc6d62cd36675371054ef81ebe97f..ce800ac8da04b8dc6cf7cf5b78e53f95d7ef0318 100644 --- a/preprocessor/ComputingTasks.cc +++ b/preprocessor/ComputingTasks.cc @@ -907,8 +907,7 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct) void PlannerObjectiveStatement::computingPass() { - model_tree->computeStaticHessian = true; - model_tree->computingPass(false); + model_tree->computingPass(true, false); } void diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index a6d334dcfd0785262aeb2805dfcf4e8382f6aae8..a04e0ef106ffe58efd2ae31f80d30e236ccf3820 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -34,17 +34,13 @@ DynamicModel::DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg) : ModelTree(symbol_table_arg, num_constants_arg), - var_endo_nbr(0), max_lag(0), max_lead(0), max_endo_lag(0), max_endo_lead(0), max_exo_lag(0), max_exo_lead(0), max_exo_det_lag(0), max_exo_det_lead(0), + dynJacobianColsNbr(0), cutoff(1e-15), markowitz(0.7), - computeJacobian(false), - computeJacobianExo(false), - computeHessian(false), - computeThirdDerivatives(false), block_triangular(symbol_table_arg) { } @@ -94,7 +90,7 @@ DynamicModel::BuildIncidenceMatrix() } void -DynamicModel::computeTemporaryTermsOrdered(int order, Model_Block *ModelBlock) +DynamicModel::computeTemporaryTermsOrdered(Model_Block *ModelBlock) { map<NodeID, pair<int, int> > first_occurence; map<NodeID, int> reference_count; @@ -1157,7 +1153,7 @@ DynamicModel::writeDynamicCFile(const string &dynamic_basename) const << " {" << endl << " /* Set the output pointer to the output matrix g1. */" << endl - << " plhs[1] = mxCreateDoubleMatrix(" << equations.size() << ", " << getDynJacobianColsNbr() << ", mxREAL);" << endl + << " plhs[1] = mxCreateDoubleMatrix(" << equations.size() << ", " << dynJacobianColsNbr << ", mxREAL);" << endl << " /* Create a C pointer to a copy of the output matrix g1. */" << endl << " g1 = mxGetPr(plhs[1]);" << endl << " }" << endl @@ -1166,7 +1162,7 @@ DynamicModel::writeDynamicCFile(const string &dynamic_basename) const << " if (nlhs >= 3)" << endl << " {" << endl << " /* Set the output pointer to the output matrix g2. */" << endl - << " plhs[2] = mxCreateDoubleMatrix(" << equations.size() << ", " << getDynJacobianColsNbr()*getDynJacobianColsNbr() + << " plhs[2] = mxCreateDoubleMatrix(" << equations.size() << ", " << dynJacobianColsNbr*dynJacobianColsNbr << ", mxREAL);" << endl << " /* Create a C pointer to a copy of the output matrix g1. */" << endl << " g2 = mxGetPr(plhs[2]);" << endl @@ -1282,62 +1278,77 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri int i, k, Nb_SGE=0; bool skip_head, open_par=false; - if (computeJacobian || computeJacobianExo || computeHessian) + + mDynamicModelFile << "function [varargout] = " << dynamic_basename << "(varargin)\n"; + mDynamicModelFile << " global oo_ options_ M_ ;\n"; + mDynamicModelFile << " g2=[];g3=[];\n"; + //Temporary variables declaration + OK=true; + ostringstream tmp_output; + for (temporary_terms_type::const_iterator it = temporary_terms.begin(); + it != temporary_terms.end(); it++) + { + if (OK) + OK=false; + else + tmp_output << " "; + (*it)->writeOutput(tmp_output, oMatlabStaticModelSparse, temporary_terms); + } + if (tmp_output.str().length()>0) + mDynamicModelFile << " global " << tmp_output.str() << " M_ ;\n"; + + mDynamicModelFile << " T_init=zeros(1,options_.periods+M_.maximum_lag+M_.maximum_lead);\n"; + tmp_output.str(""); + for (temporary_terms_type::const_iterator it = temporary_terms.begin(); + it != temporary_terms.end(); it++) + { + tmp_output << " "; + (*it)->writeOutput(tmp_output, oMatlabDynamicModel, temporary_terms); + tmp_output << "=T_init;\n"; + } + if (tmp_output.str().length()>0) + mDynamicModelFile << tmp_output.str(); + + mDynamicModelFile << " y_kmin=M_.maximum_lag;\n"; + mDynamicModelFile << " y_kmax=M_.maximum_lead;\n"; + mDynamicModelFile << " y_size=M_.endo_nbr;\n"; + mDynamicModelFile << " if(length(varargin)>0)\n"; + mDynamicModelFile << " %it is a simple evaluation of the dynamic model for time _it\n"; + mDynamicModelFile << " params=varargin{3};\n"; + mDynamicModelFile << " it_=varargin{4};\n"; + /*i = symbol_table.endo_nbr*(variable_table.max_endo_lag+variable_table.max_endo_lead+1)+ + symbol_table.exo_nbr*(variable_table.max_exo_lag+variable_table.max_exo_lead+1); + mDynamicModelFile << " g1=spalloc(" << symbol_table.endo_nbr << ", " << i << ", " << i*symbol_table.endo_nbr << ");\n";*/ + mDynamicModelFile << " Per_u_=0;\n"; + mDynamicModelFile << " Per_y_=it_*y_size;\n"; + mDynamicModelFile << " y=varargin{1};\n"; + mDynamicModelFile << " ys=y(it_,:);\n"; + mDynamicModelFile << " x=varargin{2};\n"; + prev_Simulation_Type=-1; + tmp.str(""); + tmp_eq.str(""); + for (int count_call=1, i = 0;i < block_triangular.ModelBlock->Size;i++, count_call++) { - mDynamicModelFile << "function [varargout] = " << dynamic_basename << "(varargin)\n"; - mDynamicModelFile << " global oo_ options_ M_ ;\n"; - mDynamicModelFile << " g2=[];g3=[];\n"; - //Temporary variables declaration - OK=true; - ostringstream tmp_output; - for (temporary_terms_type::const_iterator it = temporary_terms.begin(); - it != temporary_terms.end(); it++) + k=block_triangular.ModelBlock->Block_List[i].Simulation_Type; + if ((BlockTriangular::BlockSim(prev_Simulation_Type)!=BlockTriangular::BlockSim(k)) && + ((prev_Simulation_Type==EVALUATE_FORWARD || prev_Simulation_Type==EVALUATE_BACKWARD || prev_Simulation_Type==EVALUATE_FORWARD_R || prev_Simulation_Type==EVALUATE_BACKWARD_R) + || (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R))) { - if (OK) - OK=false; - else - tmp_output << " "; - (*it)->writeOutput(tmp_output, oMatlabStaticModelSparse, temporary_terms); + mDynamicModelFile << " y_index_eq=[" << tmp_eq.str() << "];\n"; + tmp_eq.str(""); + mDynamicModelFile << " y_index=[" << tmp.str() << "];\n"; + tmp.str(""); + mDynamicModelFile << tmp1.str(); + tmp1.str(""); } - if (tmp_output.str().length()>0) - mDynamicModelFile << " global " << tmp_output.str() << " M_ ;\n"; - - mDynamicModelFile << " T_init=zeros(1,options_.periods+M_.maximum_lag+M_.maximum_lead);\n"; - tmp_output.str(""); - for (temporary_terms_type::const_iterator it = temporary_terms.begin(); - it != temporary_terms.end(); it++) + for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].Size;ik++) { - tmp_output << " "; - (*it)->writeOutput(tmp_output, oMatlabDynamicModel, temporary_terms); - tmp_output << "=T_init;\n"; + tmp << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; + tmp_eq << " " << block_triangular.ModelBlock->Block_List[i].Equation[ik]+1; } - if (tmp_output.str().length()>0) - mDynamicModelFile << tmp_output.str(); - - mDynamicModelFile << " y_kmin=M_.maximum_lag;\n"; - mDynamicModelFile << " y_kmax=M_.maximum_lead;\n"; - mDynamicModelFile << " y_size=M_.endo_nbr;\n"; - mDynamicModelFile << " if(length(varargin)>0)\n"; - mDynamicModelFile << " %it is a simple evaluation of the dynamic model for time _it\n"; - mDynamicModelFile << " params=varargin{3};\n"; - mDynamicModelFile << " it_=varargin{4};\n"; - /*i = symbol_table.endo_nbr*(variable_table.max_endo_lag+variable_table.max_endo_lead+1)+ - symbol_table.exo_nbr*(variable_table.max_exo_lag+variable_table.max_exo_lead+1); - mDynamicModelFile << " g1=spalloc(" << symbol_table.endo_nbr << ", " << i << ", " << i*symbol_table.endo_nbr << ");\n";*/ - mDynamicModelFile << " Per_u_=0;\n"; - mDynamicModelFile << " Per_y_=it_*y_size;\n"; - mDynamicModelFile << " y=varargin{1};\n"; - mDynamicModelFile << " ys=y(it_,:);\n"; - mDynamicModelFile << " x=varargin{2};\n"; - prev_Simulation_Type=-1; - tmp.str(""); - tmp_eq.str(""); - for (int count_call=1, i = 0;i < block_triangular.ModelBlock->Size;i++, count_call++) + if (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R) { - k=block_triangular.ModelBlock->Block_List[i].Simulation_Type; - if ((BlockTriangular::BlockSim(prev_Simulation_Type)!=BlockTriangular::BlockSim(k)) && - ((prev_Simulation_Type==EVALUATE_FORWARD || prev_Simulation_Type==EVALUATE_BACKWARD || prev_Simulation_Type==EVALUATE_FORWARD_R || prev_Simulation_Type==EVALUATE_BACKWARD_R) - || (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R))) + if (i==block_triangular.ModelBlock->Size-1) { mDynamicModelFile << " y_index_eq=[" << tmp_eq.str() << "];\n"; tmp_eq.str(""); @@ -1346,116 +1357,100 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << tmp1.str(); tmp1.str(""); } - for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].Size;ik++) - { - tmp << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; - tmp_eq << " " << block_triangular.ModelBlock->Block_List[i].Equation[ik]+1; - } - if (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R) - { - if (i==block_triangular.ModelBlock->Size-1) - { - mDynamicModelFile << " y_index_eq=[" << tmp_eq.str() << "];\n"; - tmp_eq.str(""); - mDynamicModelFile << " y_index=[" << tmp.str() << "];\n"; - tmp.str(""); - mDynamicModelFile << tmp1.str(); - tmp1.str(""); - } - } - if (BlockTriangular::BlockSim(prev_Simulation_Type)==BlockTriangular::BlockSim(k) && - (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R)) - skip_head=true; - else - skip_head=false; - switch (k) - { - case EVALUATE_FORWARD: - case EVALUATE_BACKWARD: - case EVALUATE_FORWARD_R: - case EVALUATE_BACKWARD_R: - if (!skip_head) - { - tmp1 << " [y, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, 1, it_-1, 1);\n"; - tmp1 << " residual(y_index_eq)=ys(y_index)-y(it_, y_index);\n"; - } - break; - case SOLVE_FORWARD_SIMPLE: - case SOLVE_BACKWARD_SIMPLE: - mDynamicModelFile << " y_index_eq = " << block_triangular.ModelBlock->Block_List[i].Equation[0]+1 << ";\n"; - mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_, 1);\n"; - mDynamicModelFile << " residual(y_index_eq)=r;\n"; - tmp_eq.str(""); - tmp.str(""); - break; - case SOLVE_FORWARD_COMPLETE: - case SOLVE_BACKWARD_COMPLETE: - mDynamicModelFile << " y_index_eq = [" << tmp_eq.str() << "];\n"; - mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_, 1);\n"; - mDynamicModelFile << " residual(y_index_eq)=r;\n"; - break; - case SOLVE_TWO_BOUNDARIES_COMPLETE: - case SOLVE_TWO_BOUNDARIES_SIMPLE: - int j; - mDynamicModelFile << " y_index_eq = [" << tmp_eq.str() << "];\n"; - tmp_i=block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1; - mDynamicModelFile << " y_index = ["; - for (j=0;j<tmp_i;j++) - for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].Size;ik++) - { - mDynamicModelFile << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1+j*symbol_table.endo_nbr(); - } - int tmp_ix=block_triangular.ModelBlock->Block_List[i].Max_Lag_Exo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Exo+1; - for (j=0;j<tmp_ix;j++) - for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].nb_exo;ik++) - mDynamicModelFile << " " << block_triangular.ModelBlock->Block_List[i].Exogenous[ik]+1+j*symbol_table.exo_nbr()+symbol_table.endo_nbr()*tmp_i; - mDynamicModelFile << " ];\n"; - tmp.str(""); - tmp_eq.str(""); - //mDynamicModelFile << " ga = [];\n"; - j = block_triangular.ModelBlock->Block_List[i].Size*(block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1) - + block_triangular.ModelBlock->Block_List[i].nb_exo*(block_triangular.ModelBlock->Block_List[i].Max_Lag_Exo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Exo+1); - /*mDynamicModelFile << " ga=spalloc(" << block_triangular.ModelBlock->Block_List[i].Size << ", " << j << ", " << - block_triangular.ModelBlock->Block_List[i].Size*j << ");\n";*/ - tmp_i=block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1; - mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, b, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_-" << max_lag << ", 1, " << max_lag << ", " << block_triangular.ModelBlock->Block_List[i].Size << ");\n"; - /*if(block_triangular.ModelBlock->Block_List[i].Max_Lag==variable_table.max_lag && block_triangular.ModelBlock->Block_List[i].Max_Lead==variable_table.max_lead) - mDynamicModelFile << " g1(y_index_eq,y_index) = ga;\n"; - else - mDynamicModelFile << " g1(y_index_eq,y_index) = ga(:," << 1+(variable_table.max_lag-block_triangular.ModelBlock->Block_List[i].Max_Lag)*block_triangular.ModelBlock->Block_List[i].Size << ":" << (variable_table.max_lag+1+block_triangular.ModelBlock->Block_List[i].Max_Lead)*block_triangular.ModelBlock->Block_List[i].Size << ");\n";*/ - mDynamicModelFile << " residual(y_index_eq)=r(:,M_.maximum_lag+1);\n"; - break; - } - prev_Simulation_Type=k; } - if (tmp1.str().length()) + if (BlockTriangular::BlockSim(prev_Simulation_Type)==BlockTriangular::BlockSim(k) && + (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD || k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R)) + skip_head=true; + else + skip_head=false; + switch (k) { - mDynamicModelFile << tmp1.str(); - tmp1.str(""); + case EVALUATE_FORWARD: + case EVALUATE_BACKWARD: + case EVALUATE_FORWARD_R: + case EVALUATE_BACKWARD_R: + if (!skip_head) + { + tmp1 << " [y, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, 1, it_-1, 1);\n"; + tmp1 << " residual(y_index_eq)=ys(y_index)-y(it_, y_index);\n"; + } + break; + case SOLVE_FORWARD_SIMPLE: + case SOLVE_BACKWARD_SIMPLE: + mDynamicModelFile << " y_index_eq = " << block_triangular.ModelBlock->Block_List[i].Equation[0]+1 << ";\n"; + mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_, 1);\n"; + mDynamicModelFile << " residual(y_index_eq)=r;\n"; + tmp_eq.str(""); + tmp.str(""); + break; + case SOLVE_FORWARD_COMPLETE: + case SOLVE_BACKWARD_COMPLETE: + mDynamicModelFile << " y_index_eq = [" << tmp_eq.str() << "];\n"; + mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_, 1);\n"; + mDynamicModelFile << " residual(y_index_eq)=r;\n"; + break; + case SOLVE_TWO_BOUNDARIES_COMPLETE: + case SOLVE_TWO_BOUNDARIES_SIMPLE: + int j; + mDynamicModelFile << " y_index_eq = [" << tmp_eq.str() << "];\n"; + tmp_i=block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1; + mDynamicModelFile << " y_index = ["; + for (j=0;j<tmp_i;j++) + for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].Size;ik++) + { + mDynamicModelFile << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1+j*symbol_table.endo_nbr(); + } + int tmp_ix=block_triangular.ModelBlock->Block_List[i].Max_Lag_Exo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Exo+1; + for (j=0;j<tmp_ix;j++) + for (int ik=0;ik<block_triangular.ModelBlock->Block_List[i].nb_exo;ik++) + mDynamicModelFile << " " << block_triangular.ModelBlock->Block_List[i].Exogenous[ik]+1+j*symbol_table.exo_nbr()+symbol_table.endo_nbr()*tmp_i; + mDynamicModelFile << " ];\n"; + tmp.str(""); + tmp_eq.str(""); + //mDynamicModelFile << " ga = [];\n"; + j = block_triangular.ModelBlock->Block_List[i].Size*(block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1) + + block_triangular.ModelBlock->Block_List[i].nb_exo*(block_triangular.ModelBlock->Block_List[i].Max_Lag_Exo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Exo+1); + /*mDynamicModelFile << " ga=spalloc(" << block_triangular.ModelBlock->Block_List[i].Size << ", " << j << ", " << + block_triangular.ModelBlock->Block_List[i].Size*j << ");\n";*/ + tmp_i=block_triangular.ModelBlock->Block_List[i].Max_Lag_Endo+block_triangular.ModelBlock->Block_List[i].Max_Lead_Endo+1; + mDynamicModelFile << " [r, dr(" << count_call << ").g1, dr(" << count_call << ").g2, dr(" << count_call << ").g3, b, dr(" << count_call << ").g1_x, dr(" << count_call << ").g1_o]=" << dynamic_basename << "_" << i + 1 << "(y, x, params, it_-" << max_lag << ", 1, " << max_lag << ", " << block_triangular.ModelBlock->Block_List[i].Size << ");\n"; + /*if(block_triangular.ModelBlock->Block_List[i].Max_Lag==variable_table.max_lag && block_triangular.ModelBlock->Block_List[i].Max_Lead==variable_table.max_lead) + mDynamicModelFile << " g1(y_index_eq,y_index) = ga;\n"; + else + mDynamicModelFile << " g1(y_index_eq,y_index) = ga(:," << 1+(variable_table.max_lag-block_triangular.ModelBlock->Block_List[i].Max_Lag)*block_triangular.ModelBlock->Block_List[i].Size << ":" << (variable_table.max_lag+1+block_triangular.ModelBlock->Block_List[i].Max_Lead)*block_triangular.ModelBlock->Block_List[i].Size << ");\n";*/ + mDynamicModelFile << " residual(y_index_eq)=r(:,M_.maximum_lag+1);\n"; + break; } - mDynamicModelFile << " varargout{1}=residual;\n"; - mDynamicModelFile << " varargout{2}=dr;\n"; - mDynamicModelFile << " return;\n"; - mDynamicModelFile << " end;\n"; - mDynamicModelFile << " %it is the deterministic simulation of the block decomposed dynamic model\n"; - mDynamicModelFile << " if(options_.simulation_method==0)\n"; - mDynamicModelFile << " mthd='Sparse LU';\n"; - mDynamicModelFile << " elseif(options_.simulation_method==2)\n"; - mDynamicModelFile << " mthd='GMRES';\n"; - mDynamicModelFile << " elseif(options_.simulation_method==3)\n"; - mDynamicModelFile << " mthd='BICGSTAB';\n"; - mDynamicModelFile << " else\n"; - mDynamicModelFile << " mthd='UNKNOWN';\n"; - mDynamicModelFile << " end;\n"; - mDynamicModelFile << " disp (['-----------------------------------------------------']) ;\n"; - mDynamicModelFile << " disp (['MODEL SIMULATION: (method=' mthd ')']) ;\n"; - mDynamicModelFile << " fprintf('\\n') ;\n"; - mDynamicModelFile << " periods=options_.periods;\n"; - mDynamicModelFile << " maxit_=options_.maxit_;\n"; - mDynamicModelFile << " solve_tolf=options_.solve_tolf;\n"; - mDynamicModelFile << " y=oo_.endo_simul';\n"; - mDynamicModelFile << " x=oo_.exo_simul;\n"; + prev_Simulation_Type=k; + } + if (tmp1.str().length()) + { + mDynamicModelFile << tmp1.str(); + tmp1.str(""); } + mDynamicModelFile << " varargout{1}=residual;\n"; + mDynamicModelFile << " varargout{2}=dr;\n"; + mDynamicModelFile << " return;\n"; + mDynamicModelFile << " end;\n"; + mDynamicModelFile << " %it is the deterministic simulation of the block decomposed dynamic model\n"; + mDynamicModelFile << " if(options_.simulation_method==0)\n"; + mDynamicModelFile << " mthd='Sparse LU';\n"; + mDynamicModelFile << " elseif(options_.simulation_method==2)\n"; + mDynamicModelFile << " mthd='GMRES';\n"; + mDynamicModelFile << " elseif(options_.simulation_method==3)\n"; + mDynamicModelFile << " mthd='BICGSTAB';\n"; + mDynamicModelFile << " else\n"; + mDynamicModelFile << " mthd='UNKNOWN';\n"; + mDynamicModelFile << " end;\n"; + mDynamicModelFile << " disp (['-----------------------------------------------------']) ;\n"; + mDynamicModelFile << " disp (['MODEL SIMULATION: (method=' mthd ')']) ;\n"; + mDynamicModelFile << " fprintf('\\n') ;\n"; + mDynamicModelFile << " periods=options_.periods;\n"; + mDynamicModelFile << " maxit_=options_.maxit_;\n"; + mDynamicModelFile << " solve_tolf=options_.solve_tolf;\n"; + mDynamicModelFile << " y=oo_.endo_simul';\n"; + mDynamicModelFile << " x=oo_.exo_simul;\n"; + prev_Simulation_Type=-1; mDynamicModelFile << " params=M_.params;\n"; mDynamicModelFile << " oo_.deterministic_simulation.status = 0;\n"; @@ -1629,105 +1624,98 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput) const writeModelEquations(model_output, output_type); int nrows = equations.size(); - int nvars = getDynJacobianColsNbr(); - int nvars_sq = nvars * nvars; + int hessianColsNbr = dynJacobianColsNbr * dynJacobianColsNbr; // Writing Jacobian - if (computeJacobian || computeJacobianExo) - for (first_derivatives_type::const_iterator it = first_derivatives.begin(); - it != first_derivatives.end(); it++) - { - int eq = it->first.first; - int var = it->first.second; - NodeID d1 = it->second; - - if (computeJacobianExo || getTypeByDerivID(var) == eEndogenous) - { - ostringstream g1; - g1 << " g1"; - matrixHelper(g1, eq, getDynJacobianCol(var), output_type); + for (first_derivatives_type::const_iterator it = first_derivatives.begin(); + it != first_derivatives.end(); it++) + { + int eq = it->first.first; + int var = it->first.second; + NodeID d1 = it->second; - jacobian_output << g1.str() << "=" << g1.str() << "+"; - d1->writeOutput(jacobian_output, output_type, temporary_terms); - jacobian_output << ";" << endl; - } - } + ostringstream g1; + g1 << " g1"; + matrixHelper(g1, eq, getDynJacobianCol(var), output_type); + + jacobian_output << g1.str() << "=" << g1.str() << "+"; + d1->writeOutput(jacobian_output, output_type, temporary_terms); + jacobian_output << ";" << endl; + } // Writing Hessian - if (computeHessian) - for (second_derivatives_type::const_iterator it = second_derivatives.begin(); - it != second_derivatives.end(); it++) - { - int eq = it->first.first; - int var1 = it->first.second.first; - int var2 = it->first.second.second; - NodeID d2 = it->second; - - int id1 = getDynJacobianCol(var1); - int id2 = getDynJacobianCol(var2); - - int col_nb = id1*nvars+id2; - int col_nb_sym = id2*nvars+id1; - - hessian_output << " g2"; - matrixHelper(hessian_output, eq, col_nb, output_type); - hessian_output << " = "; - d2->writeOutput(hessian_output, output_type, temporary_terms); - hessian_output << ";" << endl; - - // Treating symetric elements - if (id1 != id2) - { - lsymetric << " g2"; - matrixHelper(lsymetric, eq, col_nb_sym, output_type); - lsymetric << " = " << "g2"; - matrixHelper(lsymetric, eq, col_nb, output_type); - lsymetric << ";" << endl; - } - } + for (second_derivatives_type::const_iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) + { + int eq = it->first.first; + int var1 = it->first.second.first; + int var2 = it->first.second.second; + NodeID d2 = it->second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + + int col_nb = id1 * dynJacobianColsNbr + id2; + int col_nb_sym = id2 * dynJacobianColsNbr + id1; + + hessian_output << " g2"; + matrixHelper(hessian_output, eq, col_nb, output_type); + hessian_output << " = "; + d2->writeOutput(hessian_output, output_type, temporary_terms); + hessian_output << ";" << endl; + + // Treating symetric elements + if (id1 != id2) + { + lsymetric << " g2"; + matrixHelper(lsymetric, eq, col_nb_sym, output_type); + lsymetric << " = " << "g2"; + matrixHelper(lsymetric, eq, col_nb, output_type); + lsymetric << ";" << endl; + } + } // Writing third derivatives - if (computeThirdDerivatives) - for (third_derivatives_type::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; - NodeID d3 = it->second; - - int id1 = getDynJacobianCol(var1); - int id2 = getDynJacobianCol(var2); - int id3 = getDynJacobianCol(var3); - - // Reference column number for the g3 matrix - int ref_col = id1 * nvars_sq + id2 * nvars + id3; - - third_derivatives_output << " g3"; - matrixHelper(third_derivatives_output, eq, ref_col, output_type); - third_derivatives_output << " = "; - d3->writeOutput(third_derivatives_output, output_type, temporary_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 * nvars_sq + id3 * nvars + id2); - cols.insert(id2 * nvars_sq + id1 * nvars + id3); - cols.insert(id2 * nvars_sq + id3 * nvars + id1); - cols.insert(id3 * nvars_sq + id1 * nvars + id2); - cols.insert(id3 * nvars_sq + id2 * nvars + id1); - - for (set<int>::iterator it2 = cols.begin(); it2 != cols.end(); it2++) - if (*it2 != ref_col) - { - third_derivatives_output << " g3"; - matrixHelper(third_derivatives_output, eq, *it2, output_type); - third_derivatives_output << " = " << "g3"; - matrixHelper(third_derivatives_output, eq, ref_col, output_type); - third_derivatives_output << ";" << endl; - } - } + for (third_derivatives_type::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; + NodeID d3 = it->second; + + int id1 = getDynJacobianCol(var1); + int id2 = getDynJacobianCol(var2); + int id3 = getDynJacobianCol(var3); + + // Reference column number for the g3 matrix + int ref_col = id1 * hessianColsNbr + id2 * dynJacobianColsNbr + id3; + + third_derivatives_output << " g3"; + matrixHelper(third_derivatives_output, eq, ref_col, output_type); + third_derivatives_output << " = "; + d3->writeOutput(third_derivatives_output, output_type, temporary_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 * dynJacobianColsNbr + id2); + cols.insert(id2 * hessianColsNbr + id1 * dynJacobianColsNbr + id3); + cols.insert(id2 * hessianColsNbr + id3 * dynJacobianColsNbr + id1); + cols.insert(id3 * hessianColsNbr + id1 * dynJacobianColsNbr + id2); + cols.insert(id3 * hessianColsNbr + id2 * dynJacobianColsNbr + id1); + + for (set<int>::iterator it2 = cols.begin(); it2 != cols.end(); it2++) + if (*it2 != ref_col) + { + third_derivatives_output << " g3"; + matrixHelper(third_derivatives_output, eq, *it2, output_type); + third_derivatives_output << " = " << "g3"; + matrixHelper(third_derivatives_output, eq, ref_col, output_type); + third_derivatives_output << ";" << endl; + } + } if (mode == eStandardMode) { @@ -1736,27 +1724,23 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput) const << "%" << endl << endl << "residual = zeros(" << nrows << ", 1);" << endl - << model_output.str(); - - if (computeJacobian || computeJacobianExo) - { - // Writing initialization instruction for matrix g1 - DynamicOutput << "if nargout >= 2," << endl - << " g1 = zeros(" << nrows << ", " << nvars << ");" << endl - << endl - << "%" << endl - << "% Jacobian matrix" << endl - << "%" << endl - << endl - << jacobian_output.str() - << "end" << endl; - } - if (computeHessian) + << model_output.str() + // Writing initialization instruction for matrix g1 + << "if nargout >= 2," << endl + << " g1 = zeros(" << nrows << ", " << dynJacobianColsNbr << ");" << endl + << endl + << "%" << endl + << "% Jacobian matrix" << endl + << "%" << endl + << endl + << jacobian_output.str() + << "end" << endl; + + if (second_derivatives.size()) { // Writing initialization instruction for matrix g2 - int ncols = nvars_sq; DynamicOutput << "if nargout >= 3," << endl - << " g2 = sparse([],[],[], " << nrows << ", " << ncols << ", " << 5*ncols << ");" << endl + << " g2 = sparse([],[],[], " << nrows << ", " << hessianColsNbr << ", " << 5*hessianColsNbr << ");" << endl << endl << "%" << endl << "% Hessian matrix" << endl @@ -1766,9 +1750,9 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput) const << lsymetric.str() << "end;" << endl; } - if (computeThirdDerivatives) + if (third_derivatives.size()) { - int ncols = nvars_sq * nvars; + int ncols = hessianColsNbr * dynJacobianColsNbr; DynamicOutput << "if nargout >= 4," << endl << " g3 = sparse([],[],[], " << nrows << ", " << ncols << ", " << 5*ncols << ");" << endl << endl @@ -1787,19 +1771,16 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput) const << " double lhs, rhs;" << endl << endl << " /* Residual equations */" << endl - << model_output.str(); - - if (computeJacobian || computeJacobianExo) - { - DynamicOutput << " /* Jacobian */" << endl - << " if (g1 == NULL)" << endl - << " return;" << endl - << " else" << endl - << " {" << endl - << jacobian_output.str() - << " }" << endl; - } - if (computeHessian) + << model_output.str() + << " /* Jacobian */" << endl + << " if (g1 == NULL)" << endl + << " return;" << endl + << " else" << endl + << " {" << endl + << jacobian_output.str() + << " }" << endl; + + if (second_derivatives.size()) { DynamicOutput << " /* Hessian for endogenous and exogenous variables */" << endl << " if (g2 == NULL)" << endl @@ -2169,22 +2150,43 @@ DynamicModel::BlockLinear(Model_Block *ModelBlock) } void -DynamicModel::computingPass(const eval_context_type &eval_context, bool no_tmp_terms) +DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, + const eval_context_type &eval_context, bool no_tmp_terms) { + if (!jacobianExo && (hessian || thirdDerivatives)) + { + cerr << "DynamicModel::computingPass: computing 2nd or 3rd order derivatives imply computing 1st derivatives w.r. to exogenous" << endl; + exit(EXIT_FAILURE); + } + // Computes dynamic jacobian columns - computeDynJacobianCols(); + computeDynJacobianCols(jacobianExo); - // Determine derivation order - int order = 1; - if (computeThirdDerivatives) - order = 3; - else if (computeHessian) - order = 2; + // Compute derivatives w.r. to all endogenous, and possibly exogenous and exogenous deterministic + set<int> vars; + for(int i = 0; i < getDerivIDNbr(); i++) + { + SymbolType type = getTypeByDerivID(i); + if (type == eEndogenous || (jacobianExo && (type == eExogenous || type == eExogenousDet))) + vars.insert(i); + } // Launch computations - cout << "Computing dynamic model derivatives at order " << order << "..."; - derive(order); - cout << " done" << endl; + cout << "Computing dynamic model derivatives:" << endl + << " - order 1" << endl; + computeJacobian(vars); + + if (hessian) + { + cout << " - order 2" << endl; + computeHessian(vars); + } + + if (thirdDerivatives) + { + cout << " - order 3" << endl; + computeThirdDerivatives(vars); + } if (mode == eSparseDLLMode || mode == eSparseMode) { @@ -2203,11 +2205,11 @@ DynamicModel::computingPass(const eval_context_type &eval_context, bool no_tmp_t block_triangular.Normalize_and_BlockDecompose_Static_0_Model(j_m, equations); BlockLinear(block_triangular.ModelBlock); if (!no_tmp_terms) - computeTemporaryTermsOrdered(order, block_triangular.ModelBlock); + computeTemporaryTermsOrdered(block_triangular.ModelBlock); } else if (!no_tmp_terms) - computeTemporaryTerms(order); + computeTemporaryTerms(); } void @@ -2261,10 +2263,6 @@ DynamicModel::toStatic(StaticModel &static_model) const int DynamicModel::computeDerivID(int symb_id, int lag) { - /* NOTE: we can't use computeJacobianExo here to decide - which variables to include, since this boolean is not - yet set at this point. */ - // Setting maximum and minimum lags if (max_lead < lag) max_lead = lag; @@ -2310,12 +2308,12 @@ DynamicModel::computeDerivID(int symb_id, int lag) inv_deriv_id_table.push_back(key); if (type == eEndogenous) - var_endo_nbr++; + dynJacobianColsNbr++; return deriv_id; } -int +SymbolType DynamicModel::getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException) { return symbol_table.getType(getSymbIDByDerivID(deriv_id)); @@ -2356,7 +2354,7 @@ DynamicModel::getDerivIDNbr() const } void -DynamicModel::computeDynJacobianCols() +DynamicModel::computeDynJacobianCols(bool jacobianExo) { /* Sort the dynamic endogenous variables by lexicographic order over (lag, type_specific_symbol_id) and fill the dynamic columns for exogenous and exogenous deterministic */ @@ -2377,10 +2375,14 @@ DynamicModel::computeDynJacobianCols() ordered_dyn_endo[make_pair(lag, tsid)] = deriv_id; break; case eExogenous: - dyn_jacobian_cols_table[deriv_id] = var_endo_nbr + tsid; + // At this point, dynJacobianColsNbr contains the number of dynamic endogenous + if (jacobianExo) + dyn_jacobian_cols_table[deriv_id] = dynJacobianColsNbr + tsid; break; case eExogenousDet: - dyn_jacobian_cols_table[deriv_id] = var_endo_nbr + symbol_table.exo_nbr() + tsid; + // At this point, dynJacobianColsNbr contains the number of dynamic endogenous + if (jacobianExo) + dyn_jacobian_cols_table[deriv_id] = dynJacobianColsNbr + symbol_table.exo_nbr() + tsid; break; default: // Shut up GCC @@ -2393,6 +2395,10 @@ DynamicModel::computeDynJacobianCols() for(map<pair<int, int>, int>::const_iterator it = ordered_dyn_endo.begin(); it != ordered_dyn_endo.end(); it++) dyn_jacobian_cols_table[it->second] = sorted_id++; + + // Set final value for dynJacobianColsNbr + if (jacobianExo) + dynJacobianColsNbr += symbol_table.exo_nbr() + symbol_table.exo_det_nbr(); } int @@ -2405,11 +2411,3 @@ DynamicModel::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDExcepti return it->second; } -int -DynamicModel::getDynJacobianColsNbr() const -{ - if (computeJacobianExo) - return var_endo_nbr + symbol_table.exo_nbr() + symbol_table.exo_det_nbr(); - else - return var_endo_nbr; -} diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh index c246c0e9bbdcb0f26d5450835cd2ab63120222a8..871909a8b8e61b85e2e5b39fcc094a3b4bc25efe 100644 --- a/preprocessor/DynamicModel.hh +++ b/preprocessor/DynamicModel.hh @@ -39,10 +39,6 @@ private: /*! Contains only endogenous, exogenous and exogenous deterministic */ map<int, int> dyn_jacobian_cols_table; - //! Number of dynamic endogenous variables inside the model block - /*! Set by computeDerivID() */ - int var_endo_nbr; - //! Maximum lag and lead over all types of variables (positive values) /*! Set by computeDerivID() */ int max_lag, max_lead; @@ -56,6 +52,10 @@ private: /*! Set by computeDerivID() */ int max_exo_det_lag, max_exo_det_lead; + //! Number of columns of dynamic jacobian + /*! Set by computeDerivID() and computeDynJacobianCols() */ + int dynJacobianColsNbr; + //! Writes dynamic model file (Matlab version) void writeDynamicMFile(const string &dynamic_basename) const; //! Writes dynamic model file (C version) @@ -82,21 +82,19 @@ private: //! Build The incidence matrix form the modeltree void BuildIncidenceMatrix(); - void computeTemporaryTermsOrdered(int order, Model_Block *ModelBlock); + void computeTemporaryTermsOrdered(Model_Block *ModelBlock); //! Write derivative code of an equation w.r. to a variable void compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, ExprNodeOutputType output_type, map_idx_type &map_idx) const; virtual int computeDerivID(int symb_id, int lag); - //! Get the number of columns of dynamic jacobian - int getDynJacobianColsNbr() const; //! Get the type corresponding to a derivation ID - int getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException); + SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException); //! Get the lag corresponding to a derivation ID int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException); //! Get the symbol ID corresponding to a derivation ID int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException); //! Compute the column indices of the dynamic Jacobian - void computeDynJacobianCols(); + void computeDynJacobianCols(bool jacobianExo); public: DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); @@ -109,18 +107,16 @@ public: double markowitz; //! the file containing the model and the derivatives code ofstream code_file; - //! Whether dynamic Jacobian (w.r. to endogenous) should be written - bool computeJacobian; - //! Whether dynamic Jacobian (w.r. to endogenous and exogenous) should be written - bool computeJacobianExo; - //! Whether dynamic Hessian (w.r. to endogenous and exogenous) should be written - bool computeHessian; - //! Whether dynamic third order derivatives (w.r. to endogenous and exogenous) should be written - bool computeThirdDerivatives; //! Execute computations (variable sorting + derivation) - /*! You must set computeJacobian, computeJacobianExo, computeHessian and computeThirdDerivatives to correct values before calling this function - \param no_tmp_terms if true, no temporary terms will be computed in the dynamic files */ - void computingPass(const eval_context_type &eval_context, bool no_tmp_terms); + /*! + \param jacobianExo whether derivatives w.r. to exo and exo_det should be in the Jacobian (derivatives w.r. to endo are always computed) + \param hessian whether 2nd derivatives w.r. to exo, exo_det and endo should be computed (implies jacobianExo = true) + \param thirdDerivatives whether 3rd derivatives w.r. to endo/exo/exo_det should be computed (implies jacobianExo = true) + \param eval_context evaluation context for normalization + \param no_tmp_terms if true, no temporary terms will be computed in the dynamic files + */ + void computingPass(bool jacobianExo, bool hessian, bool thirdDerivatives, + const eval_context_type &eval_context, bool no_tmp_terms); //! Writes model initialization and lead/lag incidence matrix to output void writeOutput(ostream &output) const; //! Complete set to block decompose the model diff --git a/preprocessor/ModFile.cc b/preprocessor/ModFile.cc index b3ae75732c16c7b591cc744cced6351e9af843ae..7d1d75fc3644d0067ad6293730d4753cf7e2ca74 100644 --- a/preprocessor/ModFile.cc +++ b/preprocessor/ModFile.cc @@ -144,11 +144,12 @@ ModFile::computingPass(bool no_tmp_terms) { // Compute static model and its derivatives dynamic_model.toStatic(static_model); - static_model.computingPass(no_tmp_terms); + static_model.computingPass(false, no_tmp_terms); // Set things to compute for dynamic model + if (mod_file_struct.simul_present) - dynamic_model.computeJacobian = true; + dynamic_model.computingPass(false, false, false, global_eval_context, no_tmp_terms); else { if (mod_file_struct.order_option < 1 || mod_file_struct.order_option > 3) @@ -156,14 +157,12 @@ ModFile::computingPass(bool no_tmp_terms) cerr << "Incorrect order option..." << endl; exit(EXIT_FAILURE); } - dynamic_model.computeJacobianExo = true; - if (mod_file_struct.order_option >= 2) - dynamic_model.computeHessian = true; - if (mod_file_struct.order_option == 3) - dynamic_model.computeThirdDerivatives = true; + bool hessian = mod_file_struct.order_option >= 2; + bool thirdDerivatives = mod_file_struct.order_option == 3; + dynamic_model.computingPass(true, hessian, thirdDerivatives, global_eval_context, no_tmp_terms); } - dynamic_model.computingPass(global_eval_context, no_tmp_terms); } + for(vector<Statement *>::iterator it = statements.begin(); it != statements.end(); it++) (*it)->computingPass(); diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc index 1e2f392e14029952cc9a3b5256c8090d174f1970..75919b1cbabe81eafe98db23915ffbb6cdf5a102 100644 --- a/preprocessor/ModelTree.cc +++ b/preprocessor/ModelTree.cc @@ -48,65 +48,77 @@ ModelTree::writeDerivative(ostream &output, int eq, int symb_id, int lag, } void -ModelTree::derive(int order) +ModelTree::computeJacobian(const set<int> &vars) { - - for (int var = 0; var < getDerivIDNbr(); var++) + for(set<int>::const_iterator it = vars.begin(); + it != vars.end(); it++) for (int eq = 0; eq < (int) equations.size(); eq++) { - NodeID d1 = equations[eq]->getDerivative(var); + NodeID d1 = equations[eq]->getDerivative(*it); if (d1 == Zero) continue; - first_derivatives[make_pair(eq, var)] = d1; + first_derivatives[make_pair(eq, *it)] = d1; } +} - if (order >= 2) +void +ModelTree::computeHessian(const set<int> &vars) +{ + for (first_derivatives_type::const_iterator it = first_derivatives.begin(); + it != first_derivatives.end(); it++) { - for (first_derivatives_type::const_iterator it = first_derivatives.begin(); - it != first_derivatives.end(); it++) + int eq = it->first.first; + int var1 = it->first.second; + NodeID d1 = it->second; + + // Store only second derivatives with var2 <= var1 + for(set<int>::const_iterator it2 = vars.begin(); + it2 != vars.end(); it2++) { - int eq = it->first.first; - int var1 = it->first.second; - NodeID d1 = it->second; - - // Store only second derivatives with var2 <= var1 - for (int var2 = 0; var2 <= var1; var2++) - { - NodeID d2 = d1->getDerivative(var2); - if (d2 == Zero) - continue; - second_derivatives[make_pair(eq, make_pair(var1, var2))] = d2; - } + int var2 = *it2; + if (var2 > var1) + continue; + + NodeID d2 = d1->getDerivative(var2); + if (d2 == Zero) + continue; + second_derivatives[make_pair(eq, make_pair(var1, var2))] = d2; } } +} - if (order >= 3) +void +ModelTree::computeThirdDerivatives(const set<int> &vars) +{ + for (second_derivatives_type::const_iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) { - for (second_derivatives_type::const_iterator it = second_derivatives.begin(); - it != second_derivatives.end(); it++) + int eq = it->first.first; + + int var1 = it->first.second.first; + int var2 = it->first.second.second; + // By construction, var2 <= var1 + + NodeID d2 = it->second; + + // Store only third derivatives such that var3 <= var2 <= var1 + for(set<int>::const_iterator it2 = vars.begin(); + it2 != vars.end(); it2++) { - int eq = it->first.first; - - int var1 = it->first.second.first; - int var2 = it->first.second.second; - // By construction, var2 <= var1 - - NodeID d2 = it->second; - - // Store only third derivatives such that var3 <= var2 <= var1 - for (int var3 = 0; var3 <= var2; var3++) - { - NodeID d3 = d2->getDerivative(var3); - if (d3 == Zero) - continue; - third_derivatives[make_pair(eq, make_pair(var1, make_pair(var2, var3)))] = d3; - } + int var3 = *it2; + if (var3 > var2) + continue; + + NodeID d3 = d2->getDerivative(var3); + if (d3 == Zero) + continue; + third_derivatives[make_pair(eq, make_pair(var1, make_pair(var2, var3)))] = d3; } } } void -ModelTree::computeTemporaryTerms(int order) +ModelTree::computeTemporaryTerms() { map<NodeID, int> reference_count; temporary_terms.clear(); @@ -121,15 +133,13 @@ ModelTree::computeTemporaryTerms(int order) it != first_derivatives.end(); it++) it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab); - if (order >= 2) - for (second_derivatives_type::iterator it = second_derivatives.begin(); - it != second_derivatives.end(); it++) - it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab); + for (second_derivatives_type::iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab); - if (order >= 3) - for (third_derivatives_type::iterator it = third_derivatives.begin(); - it != third_derivatives.end(); it++) - it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab); + for (third_derivatives_type::iterator it = third_derivatives.begin(); + it != third_derivatives.end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, is_matlab); } void diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh index 6e6cb44b58147562598ecd6ca467002c0fe2e5dd..278623ec2ca01e5d21674a3e30371999df412b11 100644 --- a/preprocessor/ModelTree.hh +++ b/preprocessor/ModelTree.hh @@ -74,12 +74,20 @@ protected: //! Temporary terms (those which will be noted Txxxx) temporary_terms_type temporary_terms; - //! Computes derivatives of ModelTree - void derive(int order); + //! Computes 1st derivatives + /*! \param vars the derivation IDs w.r. to which compute the derivatives */ + void computeJacobian(const set<int> &vars); + //! Computes 2nd derivatives + /*! \param vars the derivation IDs w.r. to which derive the 1st derivatives */ + void computeHessian(const set<int> &vars); + //! Computes 3rd derivatives + /*! \param vars the derivation IDs w.r. to which derive the 2nd derivatives */ + void computeThirdDerivatives(const set<int> &vars); + //! Write derivative of an equation w.r. to a variable void writeDerivative(ostream &output, int eq, int symb_id, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; - //! Computes temporary terms - void computeTemporaryTerms(int order); + //! Computes temporary terms (for all equations and derivatives) + void computeTemporaryTerms(); //! Writes temporary terms void writeTemporaryTerms(ostream &output, ExprNodeOutputType output_type) const; //! Writes model local variables diff --git a/preprocessor/StaticModel.cc b/preprocessor/StaticModel.cc index 8cc372575726881891eb5be5c1e47db03984b6c5..90aa477532e68ae65a9c9c88a0a80b8125ef0685 100644 --- a/preprocessor/StaticModel.cc +++ b/preprocessor/StaticModel.cc @@ -23,8 +23,7 @@ StaticModel::StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants_arg) : - ModelTree(symbol_table_arg, num_constants_arg), - computeStaticHessian(false) + ModelTree(symbol_table_arg, num_constants_arg) { } @@ -151,38 +150,37 @@ StaticModel::writeStaticModel(ostream &StaticOutput) const jacobian_output << ";" << endl; } - // Write Hessian w.r. to endogenous only - if (computeStaticHessian) - for (second_derivatives_type::const_iterator it = second_derivatives.begin(); - it != second_derivatives.end(); it++) - { - int eq = it->first.first; - int symb_id1 = inv_deriv_id_table[it->first.second.first]; - int symb_id2 = inv_deriv_id_table[it->first.second.second]; - NodeID d2 = it->second; - - int tsid1 = symbol_table.getTypeSpecificID(symb_id1); - int tsid2 = symbol_table.getTypeSpecificID(symb_id2); - - int col_nb = tsid1*symbol_table.endo_nbr()+tsid2; - int col_nb_sym = tsid2*symbol_table.endo_nbr()+tsid1; - - hessian_output << " g2"; - matrixHelper(hessian_output, eq, col_nb, output_type); - hessian_output << " = "; - d2->writeOutput(hessian_output, output_type, temporary_terms); - hessian_output << ";" << endl; - - // Treating symetric elements - if (symb_id1 != symb_id2) - { - lsymetric << " g2"; - matrixHelper(lsymetric, eq, col_nb_sym, output_type); - lsymetric << " = " << "g2"; - matrixHelper(lsymetric, eq, col_nb, output_type); - lsymetric << ";" << endl; - } - } + // Write Hessian w.r. to endogenous only (only if 2nd order derivatives have been computed) + for (second_derivatives_type::const_iterator it = second_derivatives.begin(); + it != second_derivatives.end(); it++) + { + int eq = it->first.first; + int symb_id1 = inv_deriv_id_table[it->first.second.first]; + int symb_id2 = inv_deriv_id_table[it->first.second.second]; + NodeID d2 = it->second; + + int tsid1 = symbol_table.getTypeSpecificID(symb_id1); + int tsid2 = symbol_table.getTypeSpecificID(symb_id2); + + int col_nb = tsid1*symbol_table.endo_nbr()+tsid2; + int col_nb_sym = tsid2*symbol_table.endo_nbr()+tsid1; + + hessian_output << " g2"; + matrixHelper(hessian_output, eq, col_nb, output_type); + hessian_output << " = "; + d2->writeOutput(hessian_output, output_type, temporary_terms); + hessian_output << ";" << endl; + + // Treating symetric elements + if (symb_id1 != symb_id2) + { + lsymetric << " g2"; + matrixHelper(lsymetric, eq, col_nb_sym, output_type); + lsymetric << " = " << "g2"; + matrixHelper(lsymetric, eq, col_nb, output_type); + lsymetric << ";" << endl; + } + } // Writing ouputs if (mode != eDLLMode) @@ -208,9 +206,11 @@ StaticModel::writeStaticModel(ostream &StaticOutput) const << " g1 = real(g1)+2*imag(g1);" << endl << " end" << endl << "end" << endl; - if (computeStaticHessian) + + // If 2nd order derivatives have been computed + if (second_derivatives.size()) { - StaticOutput << "if nargout >= 3,\n"; + StaticOutput << "if nargout >= 3," << endl; // Writing initialization instruction for matrix g2 int ncols = symbol_table.endo_nbr() * symbol_table.endo_nbr(); StaticOutput << " g2 = sparse([],[],[], " << equations.size() << ", " << ncols << ", " << 5*ncols << ");" << endl @@ -266,20 +266,26 @@ StaticModel::writeStaticFile(const string &basename) const } void -StaticModel::computingPass(bool no_tmp_terms) +StaticModel::computingPass(bool hessian, bool no_tmp_terms) { - // Determine derivation order - int order = 1; - if (computeStaticHessian) - order = 2; + // Compute derivatives w.r. to all derivation IDs (i.e. all endogenous) + set<int> vars; + for(int i = 0; i < getDerivIDNbr(); i++) + vars.insert(i); // Launch computations - cout << "Computing static model derivatives at order " << order << "..."; - derive(order); - cout << " done" << endl; + cout << "Computing static model derivatives:" << endl + << " - order 1" << endl; + computeJacobian(vars); + + if (hessian) + { + cout << " - order 2" << endl; + computeHessian(vars); + } if (!no_tmp_terms) - computeTemporaryTerms(order); + computeTemporaryTerms(); } int diff --git a/preprocessor/StaticModel.hh b/preprocessor/StaticModel.hh index 407e3b53243ceb1f7e7b25c2bfab979e776c480f..50882b941cc9cf0105cca8d90ec6f0f2be53f089 100644 --- a/preprocessor/StaticModel.hh +++ b/preprocessor/StaticModel.hh @@ -46,12 +46,11 @@ private: public: StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); - //! Whether static Hessian (w.r. to endogenous only) should be written - bool computeStaticHessian; //! Execute computations (derivation) /*! You must set computeStaticHessian before calling this function + \param hessian whether Hessian (w.r. to endogenous only) should be computed \param no_tmp_terms if true, no temporary terms will be computed in the static and dynamic files */ - void computingPass(bool no_tmp_terms); + void computingPass(bool hessian, bool no_tmp_terms); //! Writes static model file void writeStaticFile(const string &basename) const;