diff --git a/src/DynamicModel.cc b/src/DynamicModel.cc index 097b8a736d753b7840e83552421a0852b2946da5..6a7b5dd6841cc5c6a5b1b2e3654f01b6696a4d94 100644 --- a/src/DynamicModel.cc +++ b/src/DynamicModel.cc @@ -4822,27 +4822,25 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); is_equation_linear = equationLinear(first_order_endo_derivatives); - evaluateAndReduceJacobian(eval_context, contemporaneous_jacobian, static_jacobian, dynamic_jacobian, cutoff, false); + tie(contemporaneous_jacobian, static_jacobian) = evaluateAndReduceJacobian(eval_context, cutoff, false); if (!computeNaturalNormalization()) - computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian, dynamic_jacobian); + computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian); lag_lead_vector_t equation_lag_lead, variable_lag_lead; - blocks = select_non_linear_equations_and_variables(is_equation_linear, dynamic_jacobian, equation_reordered, variable_reordered, - inv_equation_reordered, inv_variable_reordered, - equation_lag_lead, variable_lag_lead, - n_static, n_forward, n_backward, n_mixed); + tie(blocks, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) + = select_non_linear_equations_and_variables(is_equation_linear); - equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, variable_reordered, equation_reordered, 0); + equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, 0); prologue = 0; epilogue = 0; - block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(dynamic_jacobian, blocks, equation_type_and_normalized_equation, variable_reordered, equation_reordered, n_static, n_forward, n_backward, n_mixed, block_col_type, linear_decomposition); + block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(blocks, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, linear_decomposition); - computeChainRuleJacobian(blocks_derivatives); + computeChainRuleJacobian(); - blocks_linear = BlockLinear(blocks_derivatives, variable_reordered); + blocks_linear = BlockLinear(); collect_block_first_order_derivatives(); @@ -4855,29 +4853,29 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO if (block) { - evaluateAndReduceJacobian(eval_context, contemporaneous_jacobian, static_jacobian, dynamic_jacobian, cutoff, false); + tie(contemporaneous_jacobian, static_jacobian) = evaluateAndReduceJacobian(eval_context, cutoff, false); - computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian, dynamic_jacobian); + computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian); - computePrologueAndEpilogue(static_jacobian, equation_reordered, variable_reordered); + computePrologueAndEpilogue(static_jacobian); first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); - equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, variable_reordered, equation_reordered, mfs); + equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, mfs); cout << "Finding the optimal block decomposition of the model ..." << endl; lag_lead_vector_t equation_lag_lead, variable_lag_lead; - computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, dynamic_jacobian, equation_reordered, variable_reordered, blocks, equation_type_and_normalized_equation, false, true, mfs, inv_equation_reordered, inv_variable_reordered, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed); + tie(blocks, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed) = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false, true); - block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(dynamic_jacobian, blocks, equation_type_and_normalized_equation, variable_reordered, equation_reordered, n_static, n_forward, n_backward, n_mixed, block_col_type, linear_decomposition); + block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(blocks, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, linear_decomposition); printBlockDecomposition(blocks); - computeChainRuleJacobian(blocks_derivatives); + computeChainRuleJacobian(); - blocks_linear = BlockLinear(blocks_derivatives, variable_reordered); + blocks_linear = BlockLinear(); collect_block_first_order_derivatives(); @@ -4888,7 +4886,8 @@ DynamicModel::computingPass(bool jacobianExo, int derivsOrder, int paramsDerivsO computeTemporaryTermsOrdered(); int k = 0; equation_block.resize(equations.size()); - variable_block_lead_lag = vector<tuple<int, int, int>>(equations.size()); + variable_block_lead_lag.clear(); + variable_block_lead_lag.resize(equations.size()); for (unsigned int i = 0; i < getNbBlocks(); i++) { for (unsigned int j = 0; j < getBlockSize(i); j++) @@ -5072,11 +5071,11 @@ DynamicModel::get_Derivatives(int block) } void -DynamicModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_endo_derivatives) +DynamicModel::computeChainRuleJacobian() { map<int, expr_t> recursive_variables; unsigned int nb_blocks = getNbBlocks(); - blocks_endo_derivatives = blocks_derivatives_t(nb_blocks); + blocks_derivatives.resize(nb_blocks); for (unsigned int block = 0; block < nb_blocks; block++) { block_derivatives_equation_variable_laglead_nodeid_t tmp_derivatives; @@ -5084,7 +5083,6 @@ DynamicModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_endo_derivat int block_size = getBlockSize(block); int block_nb_mfs = getBlockMfs(block); int block_nb_recursives = block_size - block_nb_mfs; - blocks_endo_derivatives.push_back(block_derivatives_equation_variable_laglead_nodeid_t(0)); for (int i = 0; i < block_nb_recursives; i++) { if (getBlockEquationType(block, i) == E_EVALUATE_S) @@ -5110,7 +5108,7 @@ DynamicModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_endo_derivat } tmp_derivatives.emplace_back(eq, var, lag, first_chain_rule_derivatives[{ eqr, varr, lag }]); } - blocks_endo_derivatives[block] = tmp_derivatives; + blocks_derivatives[block] = tmp_derivatives; } } diff --git a/src/DynamicModel.hh b/src/DynamicModel.hh index 4dacd05852385afd8ff76d47cfe6cd9c75fb49df..6033ab7817c0757040c04d10404fb01c06e5e547 100644 --- a/src/DynamicModel.hh +++ b/src/DynamicModel.hh @@ -138,7 +138,7 @@ private: //! return a map on the block jacobian map<tuple<int, int, int, int, int>, int> get_Derivatives(int block); //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables - void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives); + void computeChainRuleJacobian(); string reform(const string &name) const; diff --git a/src/ModelTree.cc b/src/ModelTree.cc index ca721cf96ed4b9f649d7581379f41d9c1726e9de..71b8550d104a08c7a70d533fbf76346fc6a25441 100644 --- a/src/ModelTree.cc +++ b/src/ModelTree.cc @@ -349,7 +349,7 @@ ModelTree::computeNormalization(const jacob_map_t &contemporaneous_jacobian, boo } void -ModelTree::computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian) +ModelTree::computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian) { bool check = false; @@ -466,9 +466,10 @@ ModelTree::computeNormalizedEquations() const return endo2eqs; } -void -ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_map_t &contemporaneous_jacobian, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian, double cutoff, bool verbose) +pair<ModelTree::jacob_map_t, ModelTree::jacob_map_t> +ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, double cutoff, bool verbose) { + jacob_map_t contemporaneous_jacobian, static_jacobian; int nb_elements_contemparenous_Jacobian = 0; set<vector<int>> jacobian_elements_to_delete; for (const auto &[indices, d1] : derivatives[1]) @@ -527,22 +528,20 @@ ModelTree::evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_m cout << jacobian_elements_to_delete.size() << " elements among " << derivatives[1].size() << " in the incidence matrices are below the cutoff (" << cutoff << ") and are discarded" << endl << "The contemporaneous incidence matrix has " << nb_elements_contemparenous_Jacobian << " elements" << endl; } + + return { contemporaneous_jacobian, static_jacobian }; } -vector<pair<int, int>> -ModelTree::select_non_linear_equations_and_variables(vector<bool> is_equation_linear, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, - vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, - lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead, - vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed) +tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t, + vector<unsigned int>, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>> +ModelTree::select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear) { vector<int> eq2endo(equations.size(), 0); - /*equation_reordered.resize(equations.size()); - variable_reordered.resize(equations.size());*/ unsigned int num = 0; for (auto it : endo2eq) if (!is_equation_linear[it]) num++; - vector<int> endo2block = vector<int>(endo2eq.size(), 1); + vector<int> endo2block(endo2eq.size(), 1); vector<pair<set<int>, pair<set<int>, vector<int>>>> components_set(num); int i = 0, j = 0; for (auto it : endo2eq) @@ -555,11 +554,9 @@ ModelTree::select_non_linear_equations_and_variables(vector<bool> is_equation_li i++; j++; } - getVariableLeadLagByBlock(dynamic_jacobian, endo2block, endo2block.size(), equation_lag_lead, variable_lag_lead, equation_reordered, variable_reordered); - n_static = vector<unsigned int>(endo2eq.size(), 0); - n_forward = vector<unsigned int>(endo2eq.size(), 0); - n_backward = vector<unsigned int>(endo2eq.size(), 0); - n_mixed = vector<unsigned int>(endo2eq.size(), 0); + auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2block, endo2block.size()); + vector<unsigned int> n_static(endo2eq.size(), 0), n_forward(endo2eq.size(), 0), + n_backward(endo2eq.size(), 0), n_mixed(endo2eq.size(), 0); for (unsigned int i = 0; i < endo2eq.size(); i++) { if (variable_lag_lead[variable_reordered[i]].first != 0 && variable_lag_lead[variable_reordered[i]].second != 0) @@ -581,7 +578,8 @@ ModelTree::select_non_linear_equations_and_variables(vector<bool> is_equation_li inv_variable_reordered[variable_reordered[i]] = i; inv_equation_reordered[equation_reordered[i]] = i; } - return blocks; + return { blocks, equation_lag_lead, variable_lag_lead, + n_static, n_forward, n_backward, n_mixed }; } bool @@ -613,7 +611,7 @@ ModelTree::computeNaturalNormalization() } void -ModelTree::computePrologueAndEpilogue(const jacob_map_t &static_jacobian_arg, vector<int> &equation_reordered, vector<int> &variable_reordered) +ModelTree::computePrologueAndEpilogue(const jacob_map_t &static_jacobian_arg) { vector<int> eq2endo(equations.size(), 0); equation_reordered.resize(equations.size()); @@ -731,7 +729,7 @@ ModelTree::computePrologueAndEpilogue(const jacob_map_t &static_jacobian_arg, ve } equation_type_and_normalized_equation_t -ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, const vector<int> &Index_Var_IM, const vector<int> &Index_Equ_IM, int mfs) const +ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, int mfs) const { expr_t lhs; BinaryOpNode *eq_node; @@ -739,20 +737,20 @@ ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &fi equation_type_and_normalized_equation_t V_Equation_Simulation_Type(equations.size()); for (unsigned int i = 0; i < equations.size(); i++) { - int eq = Index_Equ_IM[i]; - int var = Index_Var_IM[i]; + int eq = equation_reordered[i]; + int var = variable_reordered[i]; eq_node = equations[eq]; lhs = eq_node->arg1; Equation_Simulation_Type = E_SOLVE; - auto derivative = first_order_endo_derivatives.find({ eq, var, 0 }); pair<bool, expr_t> res; - if (derivative != first_order_endo_derivatives.end()) + if (auto derivative = first_order_endo_derivatives.find({ eq, var, 0 }); + derivative != first_order_endo_derivatives.end()) { set<pair<int, int>> result; derivative->second->collectEndogenous(result); auto d_endo_variable = result.find({ var, 0 }); //Determine whether the equation could be evaluated rather than to be solved - if (lhs->isVariableNodeEqualTo(SymbolType::endogenous, Index_Var_IM[i], 0) && derivative->second->isNumConstNodeEqualTo(1)) + if (lhs->isVariableNodeEqualTo(SymbolType::endogenous, variable_reordered[i], 0) && derivative->second->isNumConstNodeEqualTo(1)) Equation_Simulation_Type = E_EVALUATE; else { @@ -775,12 +773,11 @@ ModelTree::equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &fi return V_Equation_Simulation_Type; } -void -ModelTree::getVariableLeadLagByBlock(const dynamic_jacob_map_t &dynamic_jacobian, const vector<int> &components_set, int nb_blck_sim, lag_lead_vector_t &equation_lead_lag, lag_lead_vector_t &variable_lead_lag, const vector<int> &equation_reordered, const vector<int> &variable_reordered) const +pair<lag_lead_vector_t, lag_lead_vector_t> +ModelTree::getVariableLeadLagByBlock(const vector<int> &components_set, int nb_blck_sim) const { int nb_endo = symbol_table.endo_nbr(); - variable_lead_lag = lag_lead_vector_t(nb_endo, { 0, 0 }); - equation_lead_lag = lag_lead_vector_t(nb_endo, { 0, 0 }); + lag_lead_vector_t variable_lead_lag(nb_endo, { 0, 0 }), equation_lead_lag(nb_endo, { 0, 0 }); vector<int> variable_blck(nb_endo), equation_blck(nb_endo); for (int i = 0; i < nb_endo; i++) { @@ -815,10 +812,12 @@ ModelTree::getVariableLeadLagByBlock(const dynamic_jacob_map_t &dynamic_jacobian equation_lead_lag[j_1] = { -lag, equation_lead_lag[j_1].second }; } } + return { equation_lead_lag, variable_lead_lag }; } -void -ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed) const +tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t, + vector<unsigned int>, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>> +ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable) { int nb_var = variable_reordered.size(); int n = nb_var - prologue - epilogue; @@ -865,7 +864,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob // Compute strongly connected components int num = strong_components(G2, endo2block_map); - blocks = vector<pair<int, int>>(num, { 0, 0 }); + vector<pair<int, int>> blocks(num, { 0, 0 }); // Create directed acyclic graph associated to the strongly connected components using DirectedGraph = boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS>; @@ -905,7 +904,7 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob get<0>(components_set[endo2block[i]]).insert(i); } - getVariableLeadLagByBlock(dynamic_jacobian, endo2block, num, equation_lag_lead, variable_lag_lead, equation_reordered, variable_reordered); + auto [equation_lag_lead, variable_lag_lead] = getVariableLeadLagByBlock(endo2block, num); vector<int> tmp_equation_reordered(equation_reordered), tmp_variable_reordered(variable_reordered); int order = prologue; @@ -927,10 +926,8 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob add_edge(vertex(i, G2), vertex(i, G2), G2); //Determines the dynamic structure of each equation - n_static = vector<unsigned int>(prologue+num+epilogue, 0); - n_forward = vector<unsigned int>(prologue+num+epilogue, 0); - n_backward = vector<unsigned int>(prologue+num+epilogue, 0); - n_mixed = vector<unsigned int>(prologue+num+epilogue, 0); + vector<unsigned int> n_static(prologue+num+epilogue, 0), n_forward(prologue+num+epilogue, 0), + n_backward(prologue+num+epilogue, 0), n_mixed(prologue+num+epilogue, 0); for (int i = 0; i < static_cast<int>(prologue); i++) if (variable_lag_lead[tmp_variable_reordered[i]].first != 0 && variable_lag_lead[tmp_variable_reordered[i]].second != 0) @@ -1042,6 +1039,8 @@ ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob inv_variable_reordered[variable_reordered[i]] = i; inv_equation_reordered[equation_reordered[i]] = i; } + + return { blocks, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed }; } void @@ -1074,7 +1073,7 @@ ModelTree::printBlockDecomposition(const vector<pair<int, int>> &blocks) const } block_type_firstequation_size_mfs_t -ModelTree::reduceBlocksAndTypeDetermination(const dynamic_jacob_map_t &dynamic_jacobian, vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &variable_reordered, const vector<int> &equation_reordered, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed, vector<tuple<int, int, int, int>> &block_col_type, bool linear_decomposition) +ModelTree::reduceBlocksAndTypeDetermination(const vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<unsigned int> &n_static, const vector<unsigned int> &n_forward, const vector<unsigned int> &n_backward, const vector<unsigned int> &n_mixed, bool linear_decomposition) { int i = 0; int count_equ = 0, blck_count_simult = 0; @@ -1232,7 +1231,7 @@ ModelTree::reduceBlocksAndTypeDetermination(const dynamic_jacob_map_t &dynamic_j } vector<bool> -ModelTree::equationLinear(map<tuple<int, int, int>, expr_t> first_order_endo_derivatives) const +ModelTree::equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives) const { vector<bool> is_linear(symbol_table.endo_nbr(), true); for (const auto &it : first_order_endo_derivatives) @@ -1250,7 +1249,7 @@ ModelTree::equationLinear(map<tuple<int, int, int>, expr_t> first_order_endo_der } vector<bool> -ModelTree::BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const +ModelTree::BlockLinear() const { unsigned int nb_blocks = getNbBlocks(); vector<bool> blocks_linear(nb_blocks, true); diff --git a/src/ModelTree.hh b/src/ModelTree.hh index 90c896480083fd30fa44d1d4add6c2c1b7e46484..a9a32e99ec20c98220bed499ecb5a98eb82e281f 100644 --- a/src/ModelTree.hh +++ b/src/ModelTree.hh @@ -53,7 +53,7 @@ vectorToTuple(const vector<T> &v) using equation_type_and_normalized_equation_t = vector<pair<EquationType, expr_t>>; //! Vector describing variables: max_lag in the block, max_lead in the block -using lag_lead_vector_t = vector<pair< int, int>>; +using lag_lead_vector_t = vector<pair<int, int>>; //! for each block contains tuple<Simulation_Type, first_equation, Block_Size, Recursive_part_Size> using block_type_firstequation_size_mfs_t = vector<tuple<BlockSimulationType, int, int, int>>; @@ -279,34 +279,38 @@ protected: If no matching is found using a strictly positive cutoff, then a zero cutoff is applied (i.e. use a symbolic normalization); in that case, the method adds zeros in the jacobian matrices to reflect all the edges in the symbolic incidence matrix. If no matching is found with a zero cutoff close to zero an error message is printout. */ - void computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian); + void computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian, double cutoff, jacob_map_t &static_jacobian); //! Try to find a natural normalization if all equations are matched to an endogenous variable on the LHS bool computeNaturalNormalization(); //! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS) multimap<int, int> computeNormalizedEquations() const; //! Evaluate the jacobian and suppress all the elements below the cutoff - void evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_map_t &contemporaneous_jacobian, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian, double cutoff, bool verbose); + /*! Returns a pair (contemporaneous_jacobian, static_jacobian). Also fills + dynamic_jacobian. */ + pair<jacob_map_t, jacob_map_t> evaluateAndReduceJacobian(const eval_context_t &eval_context, double cutoff, bool verbose); //! Select and reorder the non linear equations of the model - vector<pair<int, int>> select_non_linear_equations_and_variables(vector<bool> is_equation_linear, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, - vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, - lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead, - vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed); + /*! Returns a tuple (blocks, equation_lag_lead, variable_lag_lead, n_static, + n_forward, n_backward, n_mixed) */ + tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>> select_non_linear_equations_and_variables(const vector<bool> &is_equation_linear); //! Search the equations and variables belonging to the prologue and the epilogue of the model - void computePrologueAndEpilogue(const jacob_map_t &static_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered); + void computePrologueAndEpilogue(const jacob_map_t &static_jacobian); //! Determine the type of each equation of model and try to normalized the unnormalized equation using computeNormalizedEquations - equation_type_and_normalized_equation_t equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, const vector<int> &Index_Var_IM, const vector<int> &Index_Equ_IM, int mfs) const; + equation_type_and_normalized_equation_t equationTypeDetermination(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives, int mfs) const; //! Compute the block decomposition and for a non-recusive block find the minimum feedback set - void computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const dynamic_jacob_map_t &dynamic_jacobian, vector<int> &equation_reordered, vector<int> &variable_reordered, vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector<int> &inv_equation_reordered, vector<int> &inv_variable_reordered, lag_lead_vector_t &equation_lag_lead, lag_lead_vector_t &variable_lag_lead_t, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed) const; + /*! Returns a tuple (blocks, equation_lag_lead, variable_lag_lead, n_static, + n_forward, n_backward, n_mixed) */ + tuple<vector<pair<int, int>>, lag_lead_vector_t, lag_lead_vector_t, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>, vector<unsigned int>> computeBlockDecompositionAndFeedbackVariablesForEachBlock(const jacob_map_t &static_jacobian, const equation_type_and_normalized_equation_t &Equation_Type, bool verbose_, bool select_feedback_variable); //! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block - block_type_firstequation_size_mfs_t reduceBlocksAndTypeDetermination(const dynamic_jacob_map_t &dynamic_jacobian, vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<int> &variable_reordered, const vector<int> &equation_reordered, vector<unsigned int> &n_static, vector<unsigned int> &n_forward, vector<unsigned int> &n_backward, vector<unsigned int> &n_mixed, vector<tuple<int, int, int, int>> &block_col_type, bool linear_decomposition); + block_type_firstequation_size_mfs_t reduceBlocksAndTypeDetermination(const vector<pair<int, int>> &blocks, const equation_type_and_normalized_equation_t &Equation_Type, const vector<unsigned int> &n_static, const vector<unsigned int> &n_forward, const vector<unsigned int> &n_backward, const vector<unsigned int> &n_mixed, bool linear_decomposition); //! Determine the maximum number of lead and lag for the endogenous variable in a bloc - void getVariableLeadLagByBlock(const dynamic_jacob_map_t &dynamic_jacobian, const vector<int> &components_set, int nb_blck_sim, lag_lead_vector_t &equation_lead_lag, lag_lead_vector_t &variable_lead_lag, const vector<int> &equation_reordered, const vector<int> &variable_reordered) const; + /*! Returns a pair { equation_lead,lag, variable_lead_lag } */ + pair<lag_lead_vector_t, lag_lead_vector_t> getVariableLeadLagByBlock(const vector<int> &components_set, int nb_blck_sim) const; //! For each equation determine if it is linear or not - vector<bool> equationLinear(map<tuple<int, int, int>, expr_t> first_order_endo_derivatives) const; + vector<bool> equationLinear(const map<tuple<int, int, int>, expr_t> &first_order_endo_derivatives) const; //! Print an abstract of the block structure of the model void printBlockDecomposition(const vector<pair<int, int>> &blocks) const; //! Determine for each block if it is linear or not - vector<bool> BlockLinear(const blocks_derivatives_t &blocks_derivatives, const vector<int> &variable_reordered) const; + vector<bool> BlockLinear() const; //! Remove equations specified by exclude_eqs vector<int> includeExcludeEquations(set<pair<string, string>> &eqs, bool exclude_eqs, vector<BinaryOpNode *> &equations, vector<int> &equations_lineno, diff --git a/src/StaticModel.cc b/src/StaticModel.cc index 6feb67291ca41cc25e8d49a2e6c9ac58f8a9ba12..eec56f50292d7f9ac2605840eb883dc7cbfc4d07 100644 --- a/src/StaticModel.cc +++ b/src/StaticModel.cc @@ -1144,35 +1144,27 @@ StaticModel::computingPass(int derivsOrder, int paramsDerivsOrder, const eval_co if (block) { - jacob_map_t contemporaneous_jacobian, static_jacobian; - vector<unsigned int> n_static, n_forward, n_backward, n_mixed; + auto [contemporaneous_jacobian, static_jacobian] = evaluateAndReduceJacobian(eval_context, cutoff, false); - // for each block contains pair<Size, Feddback_variable> - vector<pair<int, int>> blocks; + computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian); - evaluateAndReduceJacobian(eval_context, contemporaneous_jacobian, static_jacobian, dynamic_jacobian, cutoff, false); + computePrologueAndEpilogue(static_jacobian); - computeNonSingularNormalization(contemporaneous_jacobian, cutoff, static_jacobian, dynamic_jacobian); + auto first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); - computePrologueAndEpilogue(static_jacobian, equation_reordered, variable_reordered); - - map<tuple<int, int, int>, expr_t> first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); - - equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, variable_reordered, equation_reordered, mfs); + equation_type_and_normalized_equation = equationTypeDetermination(first_order_endo_derivatives, mfs); cout << "Finding the optimal block decomposition of the model ..." << endl; - lag_lead_vector_t equation_lag_lead, variable_lag_lead; - - computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, dynamic_jacobian, equation_reordered, variable_reordered, blocks, equation_type_and_normalized_equation, false, false, mfs, inv_equation_reordered, inv_variable_reordered, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed); + auto [blocks, equation_lag_lead, variable_lag_lead, n_static, n_forward, n_backward, n_mixed] = computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, equation_type_and_normalized_equation, false, false); - block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(dynamic_jacobian, blocks, equation_type_and_normalized_equation, variable_reordered, equation_reordered, n_static, n_forward, n_backward, n_mixed, block_col_type, false); + block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(blocks, equation_type_and_normalized_equation, n_static, n_forward, n_backward, n_mixed, false); printBlockDecomposition(blocks); - computeChainRuleJacobian(blocks_derivatives); + computeChainRuleJacobian(); - blocks_linear = BlockLinear(blocks_derivatives, variable_reordered); + blocks_linear = BlockLinear(); collect_block_first_order_derivatives(); @@ -2176,11 +2168,11 @@ StaticModel::get_Derivatives(int block) } void -StaticModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives) +StaticModel::computeChainRuleJacobian() { map<int, expr_t> recursive_variables; unsigned int nb_blocks = getNbBlocks(); - blocks_derivatives = blocks_derivatives_t(nb_blocks); + blocks_derivatives.resize(nb_blocks); for (unsigned int block = 0; block < nb_blocks; block++) { block_derivatives_equation_variable_laglead_nodeid_t tmp_derivatives; @@ -2191,7 +2183,6 @@ StaticModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives) int block_nb_recursives = block_size - block_nb_mfs; if (simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type == SOLVE_TWO_BOUNDARIES_SIMPLE) { - blocks_derivatives.push_back(block_derivatives_equation_variable_laglead_nodeid_t(0)); for (int i = 0; i < block_nb_recursives; i++) { if (getBlockEquationType(block, i) == E_EVALUATE_S) @@ -2220,7 +2211,6 @@ StaticModel::computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives) } else { - blocks_derivatives.push_back(block_derivatives_equation_variable_laglead_nodeid_t(0)); for (int i = 0; i < block_nb_recursives; i++) { if (getBlockEquationType(block, i) == E_EVALUATE_S) diff --git a/src/StaticModel.hh b/src/StaticModel.hh index b62d84bc2f8b6f53f773755bd98da58b8659d126..ed3c6227c800cc7aa379a83923dd0bb0ed40635d 100644 --- a/src/StaticModel.hh +++ b/src/StaticModel.hh @@ -90,7 +90,7 @@ private: //! return a map on the block jacobian map<tuple<int, int, int, int, int>, int> get_Derivatives(int block); //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables - void computeChainRuleJacobian(blocks_derivatives_t &blocks_derivatives); + void computeChainRuleJacobian(); //! Collect only the first derivatives map<tuple<int, int, int>, expr_t> collect_first_order_derivatives_endogenous();