diff --git a/BlockTriangular.cc b/BlockTriangular.cc deleted file mode 100644 index ad0dd471..00000000 --- a/BlockTriangular.cc +++ /dev/null @@ -1,1166 +0,0 @@ -/* - * Copyright (C) 2007-2009 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "MinimumFeedbackSet.hh" -#include -#include -#include -#include - -//------------------------------------------------------------------------------ -#include "BlockTriangular.hh" -//------------------------------------------------------------------------------ -using namespace std; -using namespace boost; -using namespace MFS; - -BlockTriangular::BlockTriangular(SymbolTable &symbol_table_arg, NumericalConstants &num_const_arg) - : symbol_table(symbol_table_arg), - //normalization(symbol_table_arg), - incidencematrix(symbol_table_arg), - num_const(num_const_arg) -{ - bt_verbose = 0; - ModelBlock = NULL; - periods = 0; - prologue = epilogue = 0; - Normalized_Equation = new DataTree(symbol_table, num_const); -} - -BlockTriangular::~BlockTriangular() -{ - delete Normalized_Equation; -} - -//------------------------------------------------------------------------------ -// Find the prologue and the epilogue of the model -void -BlockTriangular::Prologue_Epilogue(bool *IM, int &prologue, int &epilogue, int n, vector &Index_Var_IM, vector &Index_Equ_IM, bool *IM0) -{ - bool modifie = 1; - int i, j, k, l = 0; - /*Looking for a prologue */ - prologue = 0; - while (modifie) - { - modifie = 0; - for (i = prologue; i < n; i++) - { - k = 0; - for (j = prologue; j < n; j++) - { - if (IM[i*n + j]) - { - k++; - l = j; - } - } - if ((k == 1) && IM0[Index_Equ_IM[i]*n + Index_Var_IM[l]]) - { - modifie = 1; - incidencematrix.swap_IM_c(IM, prologue, i, l, Index_Var_IM, Index_Equ_IM, n); - prologue++; - } - } - } - epilogue = 0; - modifie = 1; - while (modifie) - { - modifie = 0; - for (i = prologue; i < n - epilogue; i++) - { - k = 0; - for (j = prologue; j < n - epilogue; j++) - { - if (IM[j*n + i]) - { - k++; - l = j; - } - } - if ((k == 1) && IM0[Index_Equ_IM[l]*n + Index_Var_IM[i]]) - { - modifie = 1; - incidencematrix.swap_IM_c(IM, n - (1 + epilogue), l, i, Index_Var_IM, Index_Equ_IM, n); - epilogue++; - } - } - } -} - -//------------------------------------------------------------------------------ -// Find a matching between equations and endogenous variables -bool -BlockTriangular::Compute_Normalization(bool *IM, int equation_number, int prologue, int epilogue, int verbose, bool *IM0, vector &Index_Equ_IM) const -{ - int n = equation_number - prologue - epilogue; - - typedef adjacency_list BipartiteGraph; - - - if(verbose == 2) - cout << "trying to normlized even in singular case\n"; - /* - Vertices 0 to n-1 are for endogenous (using type specific ID) - Vertices n to 2*n-1 are for equations (using equation no.) - */ - BipartiteGraph g(2 * n); - // Fill in the graph - for (int i = 0; i < n; i++) - for (int j = 0; j < n; j++) - if (IM0[(i+prologue) * equation_number+j+prologue]) - { - //printf("equation=%3d variable=%3d\n",i,j); - add_edge(i + n, j, g); - } - - // Compute maximum cardinality matching - typedef vector::vertex_descriptor> mate_map_t; - mate_map_t mate_map(2*n); - - bool check = checked_edmonds_maximum_cardinality_matching(g, &mate_map[0]); - //cout << "check = " << check << "\n"; - if (check) - { - // Check if all variables are normalized - mate_map_t::const_iterator it = find(mate_map.begin(), mate_map.begin() + n, graph_traits::null_vertex()); - if (it != mate_map.begin() + n) - { - if (verbose == 1) - { - cout << "WARNING: Could not normalize dynamic model. Variable " - << symbol_table.getName(symbol_table.getID(eEndogenous, it - mate_map.begin())) - << " is not in the maximum cardinality matching. Trying to find a singular normalization." << endl; - //exit(EXIT_FAILURE); - return false; - } - else if (verbose == 2) - { - cerr << "ERROR: Could not normalize dynamic model (even with a singularity). Variable " - << symbol_table.getName(symbol_table.getID(eEndogenous, it - mate_map.begin())) - << " is not in the maximum cardinality matching." << endl; - exit(EXIT_FAILURE); - } - return false; - } - vector Index_Equ_IM_tmp(Index_Equ_IM); - bool *SIM; - SIM = (bool *) malloc(equation_number*equation_number*sizeof(bool)); - memcpy(SIM, IM, equation_number*equation_number*sizeof(bool)); - for (int i = 0; i < n; i++) - { - //printf("match equation %4d with variable %4d \n", mate_map[i] - n, i); - Index_Equ_IM[i + prologue] = Index_Equ_IM_tmp[mate_map[i] - n + prologue]; - for (int k = 0; k < n; k++) - IM[(i+prologue)*equation_number+k +prologue] = SIM[(mate_map[i]-n+prologue)*equation_number+k +prologue]; - } - free(SIM); - } - return check; -} - - - - -t_vtype -BlockTriangular::Get_Variable_LeadLag_By_Block(vector &components_set, int nb_blck_sim, int prologue, int epilogue, t_vtype &equation_lead_lag) const -{ - int nb_endo = symbol_table.endo_nbr(); - vector variable_blck(nb_endo), equation_blck(nb_endo); - t_vtype Variable_Type(nb_endo); - for (int i = 0; i < nb_endo; i++) - { - if (i < prologue) - { - variable_blck[Index_Var_IM[i]] = i; - equation_blck[Index_Equ_IM[i]] = i; - } - else if (i < (int)components_set.size() + prologue) - { - variable_blck[Index_Var_IM[i]] = components_set[i-prologue] + prologue; - equation_blck[Index_Equ_IM[i]] = components_set[i-prologue] + prologue; - } - else - { - variable_blck[Index_Var_IM[i]] = i- (nb_endo - nb_blck_sim - prologue - epilogue); - equation_blck[Index_Equ_IM[i]] = i- (nb_endo - nb_blck_sim - prologue - epilogue); - } - Variable_Type[i] = make_pair(0, 0); - } - equation_lead_lag = Variable_Type; - for (int k = -incidencematrix.Model_Max_Lag_Endo; k <= incidencematrix.Model_Max_Lead_Endo; k++) - { - bool *Cur_IM = incidencematrix.Get_IM(k, eEndogenous); - if (Cur_IM) - { - for (int i = 0; i < nb_endo; i++) - { - int i_1 = Index_Var_IM[i]; - for (int j = 0; j < nb_endo; j++) - { - int j_l = Index_Equ_IM[ j]; - if (Cur_IM[i_1 + Index_Equ_IM[ j] * nb_endo] and variable_blck[i_1] == equation_blck[j_l]) - { - if (k > Variable_Type[i_1].second) - Variable_Type[i_1] = make_pair(Variable_Type[i_1].first, k); - if (k < -Variable_Type[i_1].first) - Variable_Type[i_1] = make_pair(-k, Variable_Type[i_1].second); - if (k > equation_lead_lag[j_l].second) - equation_lead_lag[j_l] = make_pair(equation_lead_lag[j_l].first, k); - if (k < -equation_lead_lag[j_l].first) - equation_lead_lag[j_l] = make_pair(-k, equation_lead_lag[j_l].second); - } - } - } - } - } - return (Variable_Type); -} - -void -BlockTriangular::Compute_Block_Decomposition_and_Feedback_Variables_For_Each_Block(bool *IM, int nb_var, int prologue, int epilogue, vector &Index_Equ_IM, vector &Index_Var_IM, vector > &blocks, t_etype &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs) const -{ - t_vtype V_Variable_Type; - int n = nb_var - prologue - epilogue; - bool *AMp; - AMp = (bool *) malloc(n*n*sizeof(bool)); - //transforms the incidence matrix of the complet model into an adjancent matrix of the non-recursive part of the model - for (int i = prologue; i < nb_var - epilogue; i++) - for (int j = prologue; j < nb_var - epilogue; j++) - if (j != i) - AMp[(i-prologue)*n+j-prologue] = IM[i*nb_var + j]; - else - AMp[(i-prologue)*n+j-prologue] = 0; - - //In a first step we compute the strong components of the graph representation of the static model. - // This insures that block are dynamically recursives. - GraphvizDigraph G2 = AM_2_GraphvizDigraph(AMp, n); - vector endo2block(num_vertices(G2)), discover_time(num_vertices(G2)); - - int num = strong_components(G2, &endo2block[0]); - - blocks = vector >(num, make_pair(0, 0)); - - - -/*New*/ - // Compute strongly connected components - // Create directed acyclic graph associated to the strongly connected components - typedef adjacency_list DirectedGraph; - DirectedGraph dag(num); - /*graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(G2); ei != ei_end; ++ei) - { - int s = endo2block[source(*ei, G2)]; - int t = endo2block[target(*ei, G2)]; - if (s != t) - add_edge(s, t, dag); - }*/ - for (unsigned int i = 0;i < num_vertices(G2);i++) - { - GraphvizDigraph::out_edge_iterator it_out, out_end; - GraphvizDigraph::vertex_descriptor vi = vertex(i, G2); - for (tie(it_out, out_end) = out_edges(vi, G2); it_out != out_end; ++it_out) - { - int t_b = endo2block[target(*it_out, G2)]; - int s_b = endo2block[source(*it_out, G2)]; - if (s_b != t_b) - add_edge(s_b, t_b, dag); - } - } - // Compute topological sort of DAG (ordered list of unordered SCC) - deque ordered2unordered; - topological_sort(dag, front_inserter(ordered2unordered)); // We use a front inserter because topological_sort returns the inverse order - // Construct mapping from unordered SCC to ordered SCC - vector unordered2ordered(num); - for(int i = 0; i < num; i++) - unordered2ordered[ordered2unordered[i]] = i; -/*EndNew*/ - - - //This vector contains for each block: - // - first set = equations belonging to the block, - // - second set = the feeback variables, - // - third vector = the reordered non-feedback variables. - vector, pair, vector > > > components_set(num); - - for (unsigned int i = 0; i < endo2block.size(); i++) - { - endo2block[i] = unordered2ordered[endo2block[i]]; - blocks[endo2block[i]].first++; - components_set[endo2block[i]].first.insert(i); - } - - - t_vtype equation_lead_lag; - V_Variable_Type = Get_Variable_LeadLag_By_Block(endo2block, num, prologue, epilogue, equation_lead_lag); - - vector tmp_Index_Equ_IM(Index_Equ_IM), tmp_Index_Var_IM(Index_Var_IM); - int order = prologue; - bool *SIM; - SIM = (bool *) malloc(nb_var*nb_var*sizeof(bool)); - memcpy(SIM, IM, nb_var*nb_var*sizeof(bool)); - - //Add a loop on vertices which could not be normalized or vertices related to lead variables => force those vertices to belong to the feedback set - if(select_feedback_variable) - for (int i = 0; i < n; i++) - if (Equation_Type[Index_Equ_IM[i+prologue]].first == E_SOLVE or V_Variable_Type[Index_Var_IM[i+prologue]].second > 0 or V_Variable_Type[Index_Var_IM[i+prologue]].first > 0 - or equation_lead_lag[Index_Equ_IM[i+prologue]].second > 0 or equation_lead_lag[Index_Equ_IM[i+prologue]].first > 0 - or mfs == 0) - add_edge(i, i, G2); - else - for (int i = 0; i < n; i++) - if (Equation_Type[Index_Equ_IM[i+prologue]].first == E_SOLVE or mfs == 0) - add_edge(i, i, G2); - //For each block, the minimum set of feedback variable is computed - // and the non-feedback variables are reordered to get - // a sub-recursive block without feedback variables - for (int i = 0; i < num; i++) - { - AdjacencyList_type G = GraphvizDigraph_2_AdjacencyList(G2, components_set[i].first); - set feed_back_vertices; - //Print(G); - AdjacencyList_type G1 = Minimal_set_of_feedback_vertex(feed_back_vertices, G); - property_map::type v_index = get(vertex_index, G); - components_set[i].second.first = feed_back_vertices; - blocks[i].second = feed_back_vertices.size(); - vector Reordered_Vertice; - Reorder_the_recursive_variables(G, feed_back_vertices, Reordered_Vertice); - //First we have the recursive equations conditional on feedback variables - for (vector::iterator its = Reordered_Vertice.begin(); its != Reordered_Vertice.end(); its++) - { - Index_Equ_IM[order] = tmp_Index_Equ_IM[*its+prologue]; - Index_Var_IM[order] = tmp_Index_Var_IM[*its+prologue]; - order++; - } - components_set[i].second.second = Reordered_Vertice; - //Second we have the equations related to the feedback variables - for (set::iterator its = feed_back_vertices.begin(); its != feed_back_vertices.end(); its++) - { - Index_Equ_IM[order] = tmp_Index_Equ_IM[v_index[vertex(*its, G)]+prologue]; - Index_Var_IM[order] = tmp_Index_Var_IM[v_index[vertex(*its, G)]+prologue]; - order++; - } - - } - free(AMp); - free(SIM); -} - -void -BlockTriangular::Allocate_Block(int size, int *count_Equ, int count_Block, BlockType type, BlockSimulationType SimType, Model_Block *ModelBlock, t_etype &Equation_Type, int recurs_Size, vector &Index_Var_IM, vector &Index_Equ_IM) -{ - int i, j, k, l, ls, m, i_1, Lead, Lag, first_count_equ, i1, li; - int *tmp_size, *tmp_size_other_endo, *tmp_size_exo, *tmp_var, *tmp_endo, *tmp_other_endo, *tmp_exo, tmp_nb_other_endo, tmp_nb_exo, nb_lead_lag_endo; - bool *tmp_variable_evaluated; - bool *Cur_IM; - bool *IM, OK; - int Lag_Endo, Lead_Endo, Lag_Exo, Lead_Exo, Lag_Other_Endo, Lead_Other_Endo; - //cout << "block " << count_Block << " size " << size << " SimType=" << BlockSim(SimType) << "\n"; - - ModelBlock->Periods = periods; - ModelBlock->Block_List[count_Block].is_linear = true; - ModelBlock->Block_List[count_Block].Size = size; - ModelBlock->Block_List[count_Block].Type = type; - ModelBlock->Block_List[count_Block].Nb_Recursives = recurs_Size; - ModelBlock->Block_List[count_Block].Temporary_InUse = new temporary_terms_inuse_type(); - ModelBlock->Block_List[count_Block].Chain_Rule_Derivatives = new chain_rule_derivatives_type(); - ModelBlock->Block_List[count_Block].Temporary_InUse->clear(); - ModelBlock->Block_List[count_Block].Simulation_Type = SimType; - ModelBlock->Block_List[count_Block].Equation = (int *) malloc(ModelBlock->Block_List[count_Block].Size * sizeof(int)); - ModelBlock->Block_List[count_Block].Equation_Type = (EquationType *) malloc(ModelBlock->Block_List[count_Block].Size * sizeof(EquationType)); - ModelBlock->Block_List[count_Block].Equation_Normalized = (NodeID*)malloc(ModelBlock->Block_List[count_Block].Size * sizeof(NodeID)); - ModelBlock->Block_List[count_Block].Variable = (int *) malloc(ModelBlock->Block_List[count_Block].Size * sizeof(int)); - ModelBlock->Block_List[count_Block].Temporary_Terms_in_Equation = (temporary_terms_type **) malloc(ModelBlock->Block_List[count_Block].Size * sizeof(temporary_terms_type)); - ModelBlock->Block_List[count_Block].Own_Derivative = (int *) malloc(ModelBlock->Block_List[count_Block].Size * sizeof(int)); - Lead = Lag = 0; - first_count_equ = *count_Equ; - tmp_var = (int *) malloc(size * sizeof(int)); - tmp_endo = (int *) malloc((incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1) * sizeof(int)); - tmp_other_endo = (int *) malloc((incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1) * sizeof(int)); - tmp_size = (int *) malloc((incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1) * sizeof(int)); - tmp_size_other_endo = (int *) malloc((incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1) * sizeof(int)); - tmp_size_exo = (int *) malloc((incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1) * sizeof(int)); - memset(tmp_size_exo, 0, (incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1)*sizeof(int)); - memset(tmp_size_other_endo, 0, (incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1)*sizeof(int)); - memset(tmp_size, 0, (incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1)*sizeof(int)); - memset(tmp_endo, 0, (incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1)*sizeof(int)); - memset(tmp_other_endo, 0, (incidencematrix.Model_Max_Lead + incidencematrix.Model_Max_Lag + 1)*sizeof(int)); - nb_lead_lag_endo = 0; - Lag_Endo = Lead_Endo = Lag_Other_Endo = Lead_Other_Endo = Lag_Exo = Lead_Exo = 0; - - //Variable by variable looking for all leads and lags its occurence in each equation of the block - tmp_variable_evaluated = (bool *) malloc(symbol_table.endo_nbr()*sizeof(bool)); - memset(tmp_variable_evaluated, 0, symbol_table.endo_nbr()*sizeof(bool)); - for (i = 0; i < size; i++) - { - ModelBlock->Block_List[count_Block].Temporary_Terms_in_Equation[i] = new temporary_terms_type(); - ModelBlock->Block_List[count_Block].Temporary_Terms_in_Equation[i]->clear(); - ModelBlock->Block_List[count_Block].Equation[i] = Index_Equ_IM[*count_Equ]; - ModelBlock->Block_List[count_Block].Variable[i] = Index_Var_IM[*count_Equ]; - ModelBlock->Block_List[count_Block].Equation_Type[i] = Equation_Type[Index_Equ_IM[*count_Equ]].first; - ModelBlock->Block_List[count_Block].Equation_Normalized[i] = Equation_Type[Index_Equ_IM[*count_Equ]].second; - /*if(Equation_Type[Index_Equ_IM[*count_Equ]].second) - { - temporary_terms_type temporary_terms; - cout << "Equation_Type[Index_Equ_IM[*count_Equ]].second->get_op_code()=" << Equation_Type[Index_Equ_IM[*count_Equ]].second->get_op_code() << "\n"; - cout << "ModelBlock->Block_List[" << count_Block << "].Equation_Normalized[" << i << "]->get_op_code()=" << ModelBlock->Block_List[count_Block].Equation_Normalized[i]->get_op_code() << "\n"; - ModelBlock->Block_List[count_Block].Equation_Normalized[i]->writeOutput(cout, oMatlabDynamicModelSparse, temporary_terms); - }*/ - i_1 = Index_Var_IM[*count_Equ]; - for (k = -incidencematrix.Model_Max_Lag_Endo; k <= incidencematrix.Model_Max_Lead_Endo; k++) - { - Cur_IM = incidencematrix.Get_IM(k, eEndogenous); - if (Cur_IM) - { - OK = false; - if (k >= 0) - { - for (j = 0; j < size; j++) - { - if (Cur_IM[i_1 + Index_Equ_IM[first_count_equ + j]*symbol_table.endo_nbr()]) - { - tmp_variable_evaluated[i_1] = true; - tmp_size[incidencematrix.Model_Max_Lag_Endo + k]++; - if (!OK) - { - tmp_endo[incidencematrix.Model_Max_Lag + k]++; - nb_lead_lag_endo++; - OK = true; - } - if (k > Lead) - Lead = k; - } - } - } - else - { - for (j = 0; j < size; j++) - { - if (Cur_IM[i_1 + Index_Equ_IM[first_count_equ + j]*symbol_table.endo_nbr()]) - { - tmp_variable_evaluated[i_1] = true; - tmp_size[incidencematrix.Model_Max_Lag_Endo + k]++; - if (!OK) - { - tmp_variable_evaluated[i_1] = true; - tmp_endo[incidencematrix.Model_Max_Lag + k]++; - nb_lead_lag_endo++; - OK = true; - } - if (-k > Lag) - Lag = -k; - } - } - } - } - } - (*count_Equ)++; - } - Lag_Endo = Lag; - Lead_Endo = Lead; - - tmp_nb_other_endo = 0; - for (i = 0; i < size; i++) - { - for (k = -incidencematrix.Model_Max_Lag_Endo; k <= incidencematrix.Model_Max_Lead_Endo; k++) - { - Cur_IM = incidencematrix.Get_IM(k, eEndogenous); - if (Cur_IM) - { - i_1 = Index_Equ_IM[first_count_equ+i] * symbol_table.endo_nbr(); - for (j = 0; j < symbol_table.endo_nbr(); j++) - if (Cur_IM[i_1 + j]) - { - if (!tmp_variable_evaluated[j]) - { - tmp_other_endo[incidencematrix.Model_Max_Lag + k]++; - tmp_nb_other_endo++; - } - if (k > 0 && k > Lead_Other_Endo) - Lead_Other_Endo = k; - else if (k < 0 && (-k) > Lag_Other_Endo) - Lag_Other_Endo = -k; - if (k > 0 && k > Lead) - Lead = k; - else if (k < 0 && (-k) > Lag) - Lag = -k; - tmp_size_other_endo[k+incidencematrix.Model_Max_Lag_Endo]++; - } - } - } - } - ModelBlock->Block_List[count_Block].nb_other_endo = tmp_nb_other_endo; - ModelBlock->Block_List[count_Block].Other_Endogenous = (int *) malloc(tmp_nb_other_endo * sizeof(int)); - - tmp_exo = (int *) malloc(symbol_table.exo_nbr() * sizeof(int)); - memset(tmp_exo, 0, symbol_table.exo_nbr() * sizeof(int)); - tmp_nb_exo = 0; - for (i = 0; i < size; i++) - { - for (k = -incidencematrix.Model_Max_Lag_Exo; k <= incidencematrix.Model_Max_Lead_Exo; k++) - { - Cur_IM = incidencematrix.Get_IM(k, eExogenous); - if (Cur_IM) - { - i_1 = Index_Equ_IM[first_count_equ+i] * symbol_table.exo_nbr(); - for (j = 0; j < symbol_table.exo_nbr(); j++) - if (Cur_IM[i_1 + j]) - { - if (!tmp_exo[j]) - { - tmp_exo[j] = 1; - tmp_nb_exo++; - } - if (k > 0 && k > Lead_Exo) - Lead_Exo = k; - else if (k < 0 && (-k) > Lag_Exo) - Lag_Exo = -k; - if (k > 0 && k > Lead) - Lead = k; - else if (k < 0 && (-k) > Lag) - Lag = -k; - tmp_size_exo[k+incidencematrix.Model_Max_Lag_Exo]++; - } - } - } - } - - ModelBlock->Block_List[count_Block].nb_exo = tmp_nb_exo; - ModelBlock->Block_List[count_Block].Exogenous = (int *) malloc(tmp_nb_exo * sizeof(int)); - k = 0; - for (j = 0; j < symbol_table.exo_nbr(); j++) - if (tmp_exo[j]) - { - ModelBlock->Block_List[count_Block].Exogenous[k] = j; - k++; - } - - ModelBlock->Block_List[count_Block].nb_exo_det = 0; - - ModelBlock->Block_List[count_Block].Max_Lag = Lag; - ModelBlock->Block_List[count_Block].Max_Lead = Lead; - ModelBlock->Block_List[count_Block].Max_Lag_Endo = Lag_Endo; - ModelBlock->Block_List[count_Block].Max_Lead_Endo = Lead_Endo; - ModelBlock->Block_List[count_Block].Max_Lag_Other_Endo = Lag_Other_Endo; - ModelBlock->Block_List[count_Block].Max_Lead_Other_Endo = Lead_Other_Endo; - ModelBlock->Block_List[count_Block].Max_Lag_Exo = Lag_Exo; - ModelBlock->Block_List[count_Block].Max_Lead_Exo = Lead_Exo; - ModelBlock->Block_List[count_Block].IM_lead_lag = (IM_compact *) malloc((Lead + Lag + 1) * sizeof(IM_compact)); - ls = l = li = size; - i1 = 0; - ModelBlock->Block_List[count_Block].Nb_Lead_Lag_Endo = nb_lead_lag_endo; - for (i = 0; i < Lead + Lag + 1; i++) - { - if (incidencematrix.Model_Max_Lag_Endo-Lag+i >= 0) - { - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size = tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].nb_endo = tmp_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].us = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_Index = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_Index = (int *) malloc(tmp_size[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size_other_endo = tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].nb_other_endo = tmp_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u_other_endo = (int *) malloc(tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_other_endo = (int *) malloc(tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_other_endo = (int *) malloc(tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_Index_other_endo = (int *) malloc(tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_Index_other_endo = (int *) malloc(tmp_size_other_endo[incidencematrix.Model_Max_Lag_Endo - Lag + i] * sizeof(int)); - } - else - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size = 0; - /*if (incidencematrix.Model_Max_Lag_Exo-Lag+i>=0) - { - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size_exo = tmp_size_exo[incidencematrix.Model_Max_Lag_Exo - Lag + i]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Exogenous = (int*)malloc(tmp_size_exo[incidencematrix.Model_Max_Lag_Exo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Exogenous_Index = (int*)malloc(tmp_size_exo[incidencematrix.Model_Max_Lag_Exo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_X = (int*)malloc(tmp_size_exo[incidencematrix.Model_Max_Lag_Exo - Lag + i] * sizeof(int)); - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_X_Index = (int*)malloc(tmp_size_exo[incidencematrix.Model_Max_Lag_Exo - Lag + i] * sizeof(int)); - } - else - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size_exo = 0;*/ - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u_init = l; - memset(tmp_variable_evaluated, 0, symbol_table.endo_nbr()*sizeof(bool)); - IM = incidencematrix.Get_IM(i - Lag, eEndogenous); - if (IM) - { - for (j = first_count_equ; j < size + first_count_equ; j++) - { - i_1 = Index_Var_IM[j]; - m = 0; - for (k = first_count_equ; k < size + first_count_equ; k++) - if (IM[i_1 + Index_Equ_IM[k] * symbol_table.endo_nbr()]) - m++; - if (m > 0) - { - tmp_var[j - first_count_equ] = i1; - i1++; - } - } - m = 0; - for (j = first_count_equ; j < size + first_count_equ; j++) - { - i_1 = Index_Equ_IM[j] * symbol_table.endo_nbr(); - for (k = first_count_equ; k < size + first_count_equ; k++) - if (IM[Index_Var_IM[k] + i_1]) - { - if (i == Lag) - { - ModelBlock->Block_List[count_Block].IM_lead_lag[i].us[m] = ls; - ls++; - } - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u[m] = li; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ[m] = j - first_count_equ; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var[m] = k - first_count_equ; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_Index[m] = Index_Equ_IM[j]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_Index[m] = Index_Var_IM[k]; - tmp_variable_evaluated[Index_Var_IM[k]] = true; - l++; - m++; - li++; - } - } - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u_finish = li - 1; - m = 0; - for (j = first_count_equ; j < size + first_count_equ; j++) - { - i_1 = Index_Equ_IM[j] * symbol_table.endo_nbr(); - for (k = 0; k < symbol_table.endo_nbr(); k++) - if ((!tmp_variable_evaluated[Index_Var_IM[k]]) && IM[Index_Var_IM[k] + i_1]) - { - ModelBlock->Block_List[count_Block].IM_lead_lag[i].u_other_endo[m] = l; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_other_endo[m] = j - first_count_equ; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_other_endo[m] = k; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_Index_other_endo[m] = Index_Equ_IM[j]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Var_Index_other_endo[m] = Index_Var_IM[k]; - l++; - m++; - } - } - ModelBlock->Block_List[count_Block].IM_lead_lag[i].size_other_endo = m; - } - /*IM = incidencematrix.Get_IM(i - Lag, eExogenous); - if (IM) - { - m = 0; - for (j = first_count_equ;j < size + first_count_equ;j++) - { - i_1 = Index_Equ_IM[j] * symbol_table.exo_nbr(); - for (k = 0; kBlock_List[count_Block].Exogenous[k]+i_1]) - { - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Exogenous[m] = k; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Exogenous_Index[m] = ModelBlock->Block_List[count_Block].Exogenous[k]; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_X[m] = j - first_count_equ; - ModelBlock->Block_List[count_Block].IM_lead_lag[i].Equ_X_Index[m] = Index_Equ_IM[j]; - m++; - } - } - } - }*/ - } - free(tmp_size); - free(tmp_size_other_endo); - free(tmp_size_exo); - free(tmp_endo); - free(tmp_other_endo); - free(tmp_exo); - free(tmp_var); - free(tmp_variable_evaluated); -} - -void -BlockTriangular::Free_Block(Model_Block *ModelBlock) const -{ - int blk, i; - for (blk = 0; blk < ModelBlock->Size; blk++) - { - free(ModelBlock->Block_List[blk].Equation); - free(ModelBlock->Block_List[blk].Variable); - free(ModelBlock->Block_List[blk].Exogenous); - free(ModelBlock->Block_List[blk].Own_Derivative); - free(ModelBlock->Block_List[blk].Other_Endogenous); - free(ModelBlock->Block_List[blk].Equation_Type); - free(ModelBlock->Block_List[blk].Equation_Normalized); - for (i = 0; i < ModelBlock->Block_List[blk].Max_Lag + ModelBlock->Block_List[blk].Max_Lead + 1; i++) - { - if (incidencematrix.Model_Max_Lag_Endo-ModelBlock->Block_List[blk].Max_Lag+i >= 0 /*&& ModelBlock->Block_List[blk].IM_lead_lag[i].size*/) - { - free(ModelBlock->Block_List[blk].IM_lead_lag[i].u); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].us); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Var); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ_Index); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Var_Index); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].u_other_endo); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Var_other_endo); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ_other_endo); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Var_Index_other_endo); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ_Index_other_endo); - } - /*if (incidencematrix.Model_Max_Lag_Exo-ModelBlock->Block_List[blk].Max_Lag+i>=0 ) - { - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Exogenous); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Exogenous_Index); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ_X_Index); - free(ModelBlock->Block_List[blk].IM_lead_lag[i].Equ_X); - }*/ - } - free(ModelBlock->Block_List[blk].IM_lead_lag); - for (i = 0; i < ModelBlock->Block_List[blk].Size; i++) - delete ModelBlock->Block_List[blk].Temporary_Terms_in_Equation[i]; - free(ModelBlock->Block_List[blk].Temporary_Terms_in_Equation); - delete (ModelBlock->Block_List[blk].Temporary_InUse); - delete ModelBlock->Block_List[blk].Chain_Rule_Derivatives; - } - free(ModelBlock->Block_List); - free(ModelBlock); -} - -t_etype -BlockTriangular::Equation_Type_determination(vector &equations, map >, NodeID> &first_order_endo_derivatives, vector &Index_Var_IM, vector &Index_Equ_IM, int mfs) -{ - NodeID lhs, rhs; - ostringstream tmp_output; - BinaryOpNode *eq_node; - ostringstream tmp_s; - temporary_terms_type temporary_terms; - EquationType Equation_Simulation_Type; - t_etype V_Equation_Simulation_Type(equations.size()); - for (unsigned int i = 0; i < equations.size(); i++) - { - temporary_terms.clear(); - int eq = Index_Equ_IM[i]; - int var = Index_Var_IM[i]; - eq_node = equations[eq]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - Equation_Simulation_Type = E_SOLVE; - tmp_s.str(""); - tmp_output.str(""); - lhs->writeOutput(tmp_output, oMatlabDynamicModelSparse, temporary_terms); - tmp_s << "y(it_, " << Index_Var_IM[i]+1 << ")"; - map >, NodeID>::iterator derivative = first_order_endo_derivatives.find(make_pair(eq, make_pair(var, 0))); - pair res; - if(derivative != first_order_endo_derivatives.end()) - { - set > result; - derivative->second->collectEndogenous(result); - set >::const_iterator d_endo_variable = result.find(make_pair(var, 0)); - //Determine whether the equation could be evaluated rather than to be solved - ostringstream tt(""); - derivative->second->writeOutput(tt, oMatlabDynamicModelSparse, temporary_terms); - if (tmp_output.str() == tmp_s.str() and tt.str()=="1") - { - Equation_Simulation_Type = E_EVALUATE; - } - else - { - vector > > List_of_Op_RHS; - res = equations[eq]->normalizeEquation(var, List_of_Op_RHS); - if(mfs==2) - { - if(d_endo_variable == result.end() && res.second) - Equation_Simulation_Type = E_EVALUATE_S; - } - else if(mfs==3) - { - if(res.second) // The equation could be solved analytically - Equation_Simulation_Type = E_EVALUATE_S; - } - } - } - V_Equation_Simulation_Type[eq] = make_pair(Equation_Simulation_Type, dynamic_cast(res.second)); - } - return (V_Equation_Simulation_Type); -} - -t_type -BlockTriangular::Reduce_Blocks_and_type_determination(int prologue, int epilogue, vector > &blocks, vector &equations, t_etype &Equation_Type, vector &Index_Var_IM, vector &Index_Equ_IM) -{ - int i = 0; - int count_equ = 0, blck_count_simult = 0; - int Blck_Size, Recurs_Size; - int Lead, Lag; - t_type Type; - bool *Cur_IM; - BlockSimulationType Simulation_Type, prev_Type = UNKNOWN; - int eq = 0; - for (i = 0; i < prologue+(int) blocks.size()+epilogue; i++) - { - int first_count_equ = count_equ; - if (i < prologue) - { - Blck_Size = 1; - Recurs_Size = 0; - } - else if (i < prologue+(int) blocks.size()) - { - Blck_Size = blocks[blck_count_simult].first; - Recurs_Size = Blck_Size - blocks[blck_count_simult].second; - blck_count_simult++; - } - else if (i < prologue+(int) blocks.size()+epilogue) - { - Blck_Size = 1; - Recurs_Size = 0; - } - - Lag = Lead = 0; - for (count_equ = first_count_equ; count_equ < Blck_Size+first_count_equ; count_equ++) - { - int i_1 = Index_Var_IM[count_equ]; - for (int k = -incidencematrix.Model_Max_Lag_Endo; k <= incidencematrix.Model_Max_Lead_Endo; k++) - { - Cur_IM = incidencematrix.Get_IM(k, eEndogenous); - if (Cur_IM) - { - for (int j = 0; j < Blck_Size; j++) - { - if (Cur_IM[i_1 + Index_Equ_IM[first_count_equ + j] * symbol_table.endo_nbr()]) - { - if (k > Lead) - Lead = k; - else if (-k > Lag) - Lag = -k; - } - } - } - } - } - if ((Lag > 0) && (Lead > 0)) - { - if (Blck_Size == 1) - Simulation_Type = SOLVE_TWO_BOUNDARIES_SIMPLE; - else - Simulation_Type = SOLVE_TWO_BOUNDARIES_COMPLETE; - } - else if (Blck_Size > 1) - { - if (Lead > 0) - Simulation_Type = SOLVE_BACKWARD_COMPLETE; - else - Simulation_Type = SOLVE_FORWARD_COMPLETE; - } - else - { - if (Lead > 0) - Simulation_Type = SOLVE_BACKWARD_SIMPLE; - else - Simulation_Type = SOLVE_FORWARD_SIMPLE; - } - if (Blck_Size == 1) - { - if (Equation_Type[Index_Equ_IM[eq]].first == E_EVALUATE /*or Equation_Type[Index_Equ_IM[eq]].first==E_EVALUATE_R*/ or Equation_Type[Index_Equ_IM[eq]].first == E_EVALUATE_S) - { - if (Simulation_Type == SOLVE_BACKWARD_SIMPLE) - Simulation_Type = EVALUATE_BACKWARD; - else if (Simulation_Type == SOLVE_FORWARD_SIMPLE) - Simulation_Type = EVALUATE_FORWARD; - } - if (i > 0) - { - if ((prev_Type == EVALUATE_FORWARD and Simulation_Type == EVALUATE_FORWARD) - or (prev_Type == EVALUATE_BACKWARD and Simulation_Type == EVALUATE_BACKWARD)) - { - BlockSimulationType c_Type = (Type[Type.size()-1]).first; - int c_Size = (Type[Type.size()-1]).second.first; - Type[Type.size()-1] = make_pair(c_Type, make_pair(++c_Size, Type[Type.size()-1].second.second)); - } - else - Type.push_back(make_pair(Simulation_Type, make_pair(Blck_Size, Recurs_Size))); - } - else - Type.push_back(make_pair(Simulation_Type, make_pair(Blck_Size, Recurs_Size))); - } - else - { - Type.push_back(make_pair(Simulation_Type, make_pair(Blck_Size, Recurs_Size))); - } - prev_Type = Simulation_Type; - eq += Blck_Size; - } - return (Type); -} - - -map >, pair >, int> -BlockTriangular::get_Derivatives(Model_Block *ModelBlock, int blck) -{ - map >, pair >, int> Derivatives; - Derivatives.clear(); - int nb_endo = symbol_table.endo_nbr(); - /*ModelBlock.Block_List[Blck].first_order_determinstic_simulation_derivatives = new*/ - for(int lag = -ModelBlock->Block_List[blck].Max_Lag; lag <= ModelBlock->Block_List[blck].Max_Lead; lag++) - { - bool *IM=incidencematrix.Get_IM(lag, eEndogenous); - if(IM) - { - for(int eq = 0; eq < ModelBlock->Block_List[blck].Size; eq++) - { - int eqr = ModelBlock->Block_List[blck].Equation[eq]; - for(int var = 0; var < ModelBlock->Block_List[blck].Size; var++) - { - int varr = ModelBlock->Block_List[blck].Variable[var]; - /*cout << "IM=" << IM << "\n"; - cout << "varr=" << varr << " eqr=" << eqr << " lag=" << lag << "\n";*/ - if(IM[varr+eqr*nb_endo]) - { - bool OK = true; - map >, pair >, int>::const_iterator its = Derivatives.find(make_pair(make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))); - if(its!=Derivatives.end()) - { - if(its->second == 2) - OK=false; - } - - if(OK) - { - if (ModelBlock->Block_List[blck].Equation_Type[eq] == E_EVALUATE_S and eqBlock_List[blck].Nb_Recursives) - //It's a normalized equation, we have to recompute the derivative using chain rule derivative function*/ - Derivatives[make_pair(make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))] = 1; - else - //It's a feedback equation we can use the derivatives - Derivatives[make_pair(make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))] = 0; - } - if(varBlock_List[blck].Nb_Recursives) - { - int eqs = ModelBlock->Block_List[blck].Equation[var]; - for(int vars=ModelBlock->Block_List[blck].Nb_Recursives; varsBlock_List[blck].Size; vars++) - { - int varrs = ModelBlock->Block_List[blck].Variable[vars]; - //A new derivative need to be computed using the chain rule derivative function (a feedback variable appear in a recursive equation) - if(Derivatives.find(make_pair(make_pair(lag, make_pair(var, vars)), make_pair(eqs, varrs)))!=Derivatives.end()) - Derivatives[make_pair(make_pair(lag, make_pair(eq, vars)), make_pair(eqr, varrs))] = 2; - } - } - } - } - } - } - } - return(Derivatives); -} - -void -BlockTriangular::Normalize_and_BlockDecompose(bool *IM, Model_Block *ModelBlock, int n, int &prologue, int &epilogue, vector &Index_Var_IM, vector &Index_Equ_IM, bool *IM_0, jacob_map &j_m, vector &equations, t_etype &V_Equation_Type, map >, NodeID> &first_order_endo_derivatives, bool dynamic, int mfs, double cutoff) -{ - int i, j, Nb_TotalBlocks, Nb_RecursBlocks, Nb_SimulBlocks; - BlockType Btype; - int count_Block, count_Equ; - bool *SIM0, *SIM00; - - - - int counted = 0; - if (prologue+epilogue < n) - { - cout << "Normalizing the model ...\n"; - double *max_val = (double *) malloc(n*sizeof(double)); - memset(max_val, 0, n*sizeof(double)); - for (map< pair< int, int >, double >::iterator iter = j_m.begin(); iter != j_m.end(); iter++) - { - if (fabs(iter->second) > max_val[iter->first.first]) - max_val[iter->first.first] = fabs(iter->second); - } - for (map< pair< int, int >, double >::iterator iter = j_m.begin(); iter != j_m.end(); iter++) - iter->second /= max_val[iter->first.first]; - free(max_val); - bool OK = false; - double bi = 0.99999999; - //double bi=1e-13; - int suppressed = 0; - vector Index_Equ_IM_save(Index_Equ_IM); - while (!OK && bi > 1e-19) - { - int suppress = 0; - Index_Equ_IM = Index_Equ_IM_save; - SIM0 = (bool *) malloc(n * n * sizeof(bool)); - memset(SIM0, 0, n*n*sizeof(bool)); - SIM00 = (bool *) malloc(n * n * sizeof(bool)); - memset(SIM00, 0, n*n*sizeof(bool)); - //cout << "---------------------------------\n"; - for (map< pair< int, int >, double >::iterator iter = j_m.begin(); iter != j_m.end(); iter++) - { - //printf("iter->second=% 1.10f iter->first.first=%3d iter->first.second=%3d bi=%f\n", iter->second, iter->first.first, iter->first.second, bi); - if (fabs(iter->second) > max(bi, cutoff)) - { - SIM0[iter->first.first*n+iter->first.second] = 1; - if (!IM_0[iter->first.first*n+iter->first.second]) - { - cout << "Error nothing at IM_0[" << iter->first.first << ", " << iter->first.second << "]=" << IM_0[iter->first.first*n+iter->first.second] << " " << iter->second << "\n"; - } - } - else - suppress++; - } - for (i = 0; i < n; i++) - for (j = 0; j < n; j++) - { - SIM00[i*n + j] = SIM0[Index_Equ_IM[i] * n + Index_Var_IM[j]]; - } - free(SIM0); - if (suppress != suppressed) - OK = Compute_Normalization(IM, n, prologue, epilogue, 0, SIM00, Index_Equ_IM); - suppressed = suppress; - if (!OK) - //bi/=1.07; - bi /= 2; - counted++; - if (bi > 1e-19) - free(SIM00); - } - if (!OK) - { - Compute_Normalization(IM, n, prologue, epilogue, 1, SIM00, Index_Equ_IM); - Compute_Normalization(IM, n, prologue, epilogue, 2, IM_0, Index_Equ_IM); - } - } - SIM0 = (bool *) malloc(n * n * sizeof(bool)); - memcpy(SIM0, IM_0, n*n*sizeof(bool)); - Prologue_Epilogue(IM, prologue, epilogue, n, Index_Var_IM, Index_Equ_IM, SIM0); - - free(SIM0); - - V_Equation_Type = Equation_Type_determination(equations, first_order_endo_derivatives, Index_Var_IM, Index_Equ_IM, mfs); - - cout << "Finding the optimal block decomposition of the model ...\n"; - vector > blocks; - if (prologue+epilogue < n) - { - if(dynamic) - Compute_Block_Decomposition_and_Feedback_Variables_For_Each_Block(IM, n, prologue, epilogue, Index_Equ_IM, Index_Var_IM, blocks, V_Equation_Type, false, true, mfs); - else - Compute_Block_Decomposition_and_Feedback_Variables_For_Each_Block(IM, n, prologue, epilogue, Index_Equ_IM, Index_Var_IM, blocks, V_Equation_Type, false, false, mfs); - } - - t_type Type = Reduce_Blocks_and_type_determination(prologue, epilogue, blocks, equations, V_Equation_Type, Index_Var_IM, Index_Equ_IM); - - i = 0; - j = 0; - Nb_SimulBlocks = 0; - int Nb_feedback_variable = 0; - for (t_type::const_iterator it = Type.begin(); it != Type.end(); it++) - { - if (it->first == SOLVE_FORWARD_COMPLETE || it->first == SOLVE_BACKWARD_COMPLETE || it->first == SOLVE_TWO_BOUNDARIES_COMPLETE) - { - Nb_SimulBlocks++; - if (it->second.first > j) - { - j = it->second.first; - Nb_feedback_variable = blocks[Nb_SimulBlocks-1].second; - } - } - } - - Nb_TotalBlocks = Type.size(); - Nb_RecursBlocks = Nb_TotalBlocks - Nb_SimulBlocks; - cout << Nb_TotalBlocks << " block(s) found:\n"; - cout << " " << Nb_RecursBlocks << " recursive block(s) and " << blocks.size() << " simultaneous block(s). \n"; - cout << " the largest simultaneous block has " << j << " equation(s)\n" - <<" and " << Nb_feedback_variable << " feedback variable(s).\n"; - - ModelBlock->Size = Nb_TotalBlocks; - ModelBlock->Periods = periods; - ModelBlock->Block_List = (Block *) malloc(sizeof(ModelBlock->Block_List[0]) * Nb_TotalBlocks); - - count_Equ = count_Block = 0; - - - - for (t_type::const_iterator it = Type.begin(); it != Type.end(); it++) - { - if (count_Equ < prologue) - Btype = PROLOGUE; - else if (count_Equ < n-epilogue) - if (it->second.first == 1) - Btype = PROLOGUE; - else - { - Btype = SIMULTANS; - } - else - Btype = EPILOGUE; - Allocate_Block(it->second.first, &count_Equ, count_Block++, Btype, it->first, ModelBlock, V_Equation_Type, it->second.second, Index_Var_IM, Index_Equ_IM); - } -} - -//------------------------------------------------------------------------------ -// normalize each equation of the dynamic model -// and find the optimal block triangular decomposition of the static model -void -BlockTriangular::Normalize_and_BlockDecompose_Static_0_Model(jacob_map &j_m, vector &equations, t_etype &equation_simulation_type, map >, NodeID> &first_order_endo_derivatives, int mfs, double cutoff) -{ - bool *SIM, *SIM_0; - bool *Cur_IM; - int i, k, size; - //First create a static model incidence matrix - size = symbol_table.endo_nbr() * symbol_table.endo_nbr() * sizeof(*SIM); - SIM = (bool *) malloc(size); - for (i = 0; i < symbol_table.endo_nbr() * symbol_table.endo_nbr(); i++) SIM[i] = 0; - for (k = -incidencematrix.Model_Max_Lag_Endo; k <= incidencematrix.Model_Max_Lead_Endo; k++) - { - Cur_IM = incidencematrix.Get_IM(k, eEndogenous); - if (Cur_IM) - { - for (i = 0; i < symbol_table.endo_nbr()*symbol_table.endo_nbr(); i++) - { - SIM[i] = (SIM[i]) || (Cur_IM[i]); - } - } - } - if (bt_verbose) - { - cout << "incidence matrix for the static model (unsorted) \n"; - incidencematrix.Print_SIM(SIM, eEndogenous); - } - Index_Equ_IM = vector(symbol_table.endo_nbr()); - for (i = 0; i < symbol_table.endo_nbr(); i++) - { - Index_Equ_IM[i] = i; - } - Index_Var_IM = vector(symbol_table.endo_nbr()); - for (i = 0; i < symbol_table.endo_nbr(); i++) - { - Index_Var_IM[i] = i; - } - if (ModelBlock != NULL) - Free_Block(ModelBlock); - ModelBlock = (Model_Block *) malloc(sizeof(*ModelBlock)); - Cur_IM = incidencematrix.Get_IM(0, eEndogenous); - SIM_0 = (bool *) malloc(symbol_table.endo_nbr() * symbol_table.endo_nbr() * sizeof(*SIM_0)); - for (i = 0; i < symbol_table.endo_nbr()*symbol_table.endo_nbr(); i++) - SIM_0[i] = Cur_IM[i]; - Normalize_and_BlockDecompose(SIM, ModelBlock, symbol_table.endo_nbr(), prologue, epilogue, Index_Var_IM, Index_Equ_IM, SIM_0, j_m, equations, equation_simulation_type, first_order_endo_derivatives, true, mfs, cutoff); - free(SIM_0); - free(SIM); -} diff --git a/BlockTriangular.hh b/BlockTriangular.hh deleted file mode 100644 index c0ebfb4b..00000000 --- a/BlockTriangular.hh +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (C) 2007-2008 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#ifndef _BLOCKTRIANGULAR_HH -#define _BLOCKTRIANGULAR_HH - -#include -#include "CodeInterpreter.hh" -#include "ExprNode.hh" -#include "SymbolTable.hh" -//#include "ModelNormalization.hh" -//#include "ModelBlocks.hh" -#include "IncidenceMatrix.hh" -#include "ModelTree.hh" - - - -//! Sparse matrix of double to store the values of the Jacobian -typedef map,double> jacob_map; - -typedef vector > > t_type; - -//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a NodeID on the new normalized equation -typedef vector > t_etype; - -//! Vector describing variables: max_lag in the block, max_lead in the block -typedef vector > t_vtype; - -typedef set temporary_terms_inuse_type; - -typedef vector >, pair > > chain_rule_derivatives_type; - -//! For one lead/lag of one block, stores mapping of information between original model and block-decomposed model -struct IM_compact -{ - int size, u_init, u_finish, nb_endo, nb_other_endo, size_exo, size_other_endo; - int *u, *us, *Var, *Equ, *Var_Index, *Equ_Index, *Exogenous, *Exogenous_Index, *Equ_X, *Equ_X_Index; - int *u_other_endo, *Var_other_endo, *Equ_other_endo, *Var_Index_other_endo, *Equ_Index_other_endo; -}; - -//! One block of the model -struct Block -{ - int Size, Sized, nb_exo, nb_exo_det, nb_other_endo, Nb_Recursives; - BlockType Type; - BlockSimulationType Simulation_Type; - int Max_Lead, Max_Lag, Nb_Lead_Lag_Endo; - int Max_Lag_Endo, Max_Lead_Endo; - int Max_Lag_Other_Endo, Max_Lead_Other_Endo; - int Max_Lag_Exo, Max_Lead_Exo; - bool is_linear; - int *Equation, *Own_Derivative; - EquationType *Equation_Type; - NodeID *Equation_Normalized; - int *Variable, *Other_Endogenous, *Exogenous; - temporary_terms_type **Temporary_Terms_in_Equation; - //temporary_terms_type *Temporary_terms; - temporary_terms_inuse_type *Temporary_InUse; - IM_compact *IM_lead_lag; - chain_rule_derivatives_type *Chain_Rule_Derivatives; - int Code_Start, Code_Length; -}; - - - -//! The set of all blocks of the model -struct Model_Block -{ - int Size, Periods; - Block* Block_List; - //int *in_Block_Equ, *in_Block_Var, *in_Equ_of_Block, *in_Var_of_Block; -}; - - -//! Creates the incidence matrix, computes prologue & epilogue, normalizes the model and computes the block decomposition -class BlockTriangular -{ -private: - //! Find equations and endogenous variables belonging to the prologue and epilogue of the model - void Prologue_Epilogue(bool* IM, int &prologue, int &epilogue, int n, vector &Index_Var_IM, vector &Index_Equ_IM, bool* IM0); - //! Allocates and fills the Model structure describing the content of each block - void Allocate_Block(int size, int *count_Equ, int count_Block, BlockType type, BlockSimulationType SimType, Model_Block *ModelBlock, t_etype &Equation_Type, int recurs_Size, vector &Index_Var_IM, vector &Index_Equ_IM); - //! Finds a matching between equations and endogenous variables - bool Compute_Normalization(bool *IM, int equation_number, int prologue, int epilogue, int verbose, bool *IM0, vector &Index_Var_IM) const; - //! Decomposes into recurive blocks the non purely recursive equations and determines for each block the minimum feedback variables - void Compute_Block_Decomposition_and_Feedback_Variables_For_Each_Block(bool *IM, int nb_var, int prologue, int epilogue, vector &Index_Equ_IM, vector &Index_Var_IM, vector > &blocks, t_etype &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs) const; - //! determines the type of each equation of the model (could be evaluated or need to be solved) - t_etype Equation_Type_determination(vector &equations, map >, NodeID> &first_order_endo_derivatives, vector &Index_Var_IM, vector &Index_Equ_IM, int mfs); - //! Tries to merge the consecutive blocks in a single block and determine the type of each block: recursive, simultaneous, ... - t_type Reduce_Blocks_and_type_determination(int prologue, int epilogue, vector > &blocks, vector &equations, t_etype &Equation_Type, vector &Index_Var_IM, vector &Index_Equ_IM); - //! Compute for each variable its maximum lead and lag in its block - t_vtype Get_Variable_LeadLag_By_Block(vector &components_set, int nb_blck_sim, int prologue, int epilogue, t_vtype &equation_lead_lag) const; -public: - SymbolTable &symbol_table; - /*Blocks blocks; - Normalization normalization;*/ - IncidenceMatrix incidencematrix; - NumericalConstants &num_const; - DataTree *Normalized_Equation; - BlockTriangular(SymbolTable &symbol_table_arg, NumericalConstants &num_const_arg); - ~BlockTriangular(); - //! Frees the Model structure describing the content of each block - void Free_Block(Model_Block* ModelBlock) const; - - map >, pair >, int> get_Derivatives(Model_Block *ModelBlock, int Blck); - - - void Normalize_and_BlockDecompose_Static_0_Model(jacob_map &j_m, vector &equations, t_etype &V_Equation_Type, map >, NodeID> &first_order_endo_derivatives, int mfs, double cutoff); - void Normalize_and_BlockDecompose(bool* IM, Model_Block* ModelBlock, int n, int &prologue, int &epilogue, vector &Index_Var_IM, vector &Index_Equ_IM, bool* IM_0 , jacob_map &j_m, vector &equations, t_etype &equation_simulation_type, map >, NodeID> &first_order_endo_derivatives, bool dynamic, int mfs, double cutoff); - vector Index_Equ_IM; - vector Index_Var_IM; - int prologue, epilogue; - bool bt_verbose; - Model_Block* ModelBlock; - int periods; - inline static std::string BlockType0(int type) - { - switch (type) - { - case 0: - return ("SIMULTANEOUS TIME SEPARABLE "); - break; - case 1: - return ("PROLOGUE "); - break; - case 2: - return ("EPILOGUE "); - break; - case 3: - return ("SIMULTANEOUS TIME UNSEPARABLE"); - break; - default: - return ("UNKNOWN "); - break; - } - }; - inline static std::string BlockSim(int type) - { - switch (type) - { - case EVALUATE_FORWARD: - //case EVALUATE_FORWARD_R: - return ("EVALUATE FORWARD "); - break; - case EVALUATE_BACKWARD: - //case EVALUATE_BACKWARD_R: - return ("EVALUATE BACKWARD "); - break; - case SOLVE_FORWARD_SIMPLE: - return ("SOLVE FORWARD SIMPLE "); - break; - case SOLVE_BACKWARD_SIMPLE: - return ("SOLVE BACKWARD SIMPLE "); - break; - case SOLVE_TWO_BOUNDARIES_SIMPLE: - return ("SOLVE TWO BOUNDARIES SIMPLE "); - break; - case SOLVE_FORWARD_COMPLETE: - return ("SOLVE FORWARD COMPLETE "); - break; - case SOLVE_BACKWARD_COMPLETE: - return ("SOLVE BACKWARD COMPLETE "); - break; - case SOLVE_TWO_BOUNDARIES_COMPLETE: - return ("SOLVE TWO BOUNDARIES COMPLETE"); - break; - default: - return ("UNKNOWN "); - break; - } - }; - inline static std::string c_Equation_Type(int type) - { - char c_Equation_Type[4][13]= - { - "E_UNKNOWN ", - "E_EVALUATE ", - "E_EVALUATE_S", - "E_SOLVE " - }; - return(c_Equation_Type[type]); - }; -}; -#endif diff --git a/CodeInterpreter.hh b/CodeInterpreter.hh index abfa44d1..ae925158 100644 --- a/CodeInterpreter.hh +++ b/CodeInterpreter.hh @@ -100,10 +100,10 @@ enum Tags enum BlockType { - SIMULTANS = 0, //!< Simultaneous time separable block - PROLOGUE = 1, //!< Prologue block (one equation at the beginning, later merged) - EPILOGUE = 2, //!< Epilogue block (one equation at the beginning, later merged) - SIMULTAN = 3 //!< Simultaneous time unseparable block + SIMULTANS, //!< Simultaneous time separable block + PROLOGUE, //!< Prologue block (one equation at the beginning, later merged) + EPILOGUE, //!< Epilogue block (one equation at the beginning, later merged) + SIMULTAN //!< Simultaneous time unseparable block }; enum EquationType @@ -126,7 +126,7 @@ enum BlockSimulationType SOLVE_TWO_BOUNDARIES_SIMPLE, //!< Block of one equation, newton solver needed, forward & ackward SOLVE_FORWARD_COMPLETE, //!< Block of several equations, newton solver needed, forward SOLVE_BACKWARD_COMPLETE, //!< Block of several equations, newton solver needed, backward - SOLVE_TWO_BOUNDARIES_COMPLETE,//!< Block of several equations, newton solver needed, forward and backwar + SOLVE_TWO_BOUNDARIES_COMPLETE //!< Block of several equations, newton solver needed, forward and backwar }; //! Enumeration of possible symbol types @@ -475,9 +475,8 @@ private: uint8_t op_code; int size; uint8_t type; - int *variable; - int *equation; - int *own_derivatives; + vector variable; + vector equation; bool is_linear; vector Block_Contain_; int endo_nbr; @@ -485,11 +484,14 @@ private: int Max_Lead; int u_count_int; public: - inline FBEGINBLOCK_(){ op_code = FBEGINBLOCK; size = 0; type = UNKNOWN; variable = NULL; equation = NULL; own_derivatives = NULL; + inline FBEGINBLOCK_(){ op_code = FBEGINBLOCK; size = 0; type = UNKNOWN; /*variable = NULL; equation = NULL;*/ is_linear = false; endo_nbr = 0; Max_Lag = 0; Max_Lead = 0; u_count_int = 0;}; - inline FBEGINBLOCK_(const int size_arg, const BlockSimulationType type_arg, int *variable_arg, int *equation_arg, int *own_derivatives_arg, - bool is_linear_arg, int endo_nbr_arg, int Max_Lag_arg, int Max_Lead_arg, int u_count_int_arg) - { op_code = FBEGINBLOCK; size = size_arg; type = type_arg; variable = variable_arg; equation = equation_arg; own_derivatives = own_derivatives_arg; + inline FBEGINBLOCK_(unsigned int &size_arg, BlockSimulationType &type_arg, int unsigned first_element, int unsigned &block_size, + const vector &variable_arg, const vector &equation_arg, + bool is_linear_arg, int endo_nbr_arg, int Max_Lag_arg, int Max_Lead_arg, int &u_count_int_arg) + { op_code = FBEGINBLOCK; size = size_arg; type = type_arg; + variable = vector(variable_arg.begin()+first_element, variable_arg.begin()+(first_element+block_size)); + equation = vector(equation_arg.begin()+first_element, equation_arg.begin()+(first_element+block_size)); is_linear = is_linear_arg; endo_nbr = endo_nbr_arg; Max_Lag = Max_Lag_arg; Max_Lead = Max_Lead_arg; u_count_int = u_count_int_arg;/*Block_Contain.clear();*/}; inline unsigned int get_size() { return size;}; inline uint8_t get_type() { return type;}; @@ -508,7 +510,6 @@ public: { CompileCode.write(reinterpret_cast(&variable[i]), sizeof(variable[0])); CompileCode.write(reinterpret_cast(&equation[i]), sizeof(equation[0])); - CompileCode.write(reinterpret_cast(&own_derivatives[i]), sizeof(own_derivatives[0])); } if (type==SOLVE_TWO_BOUNDARIES_SIMPLE || type==SOLVE_TWO_BOUNDARIES_COMPLETE || type==SOLVE_BACKWARD_COMPLETE || type==SOLVE_FORWARD_COMPLETE) @@ -532,7 +533,6 @@ public: Block_contain_type bc; memcpy(&bc.Variable, code, sizeof(bc.Variable)); code += sizeof(bc.Variable); memcpy(&bc.Equation, code, sizeof(bc.Equation)); code += sizeof(bc.Equation); - memcpy(&bc.Own_Derivative, code, sizeof(bc.Own_Derivative)); code += sizeof(bc.Own_Derivative); Block_Contain_.push_back(bc); } if (type==SOLVE_TWO_BOUNDARIES_SIMPLE || type==SOLVE_TWO_BOUNDARIES_COMPLETE || diff --git a/ComputingTasks.cc b/ComputingTasks.cc index dc109d5c..949c21f0 100644 --- a/ComputingTasks.cc +++ b/ComputingTasks.cc @@ -876,13 +876,13 @@ PlannerObjectiveStatement::checkPass(ModFileStructure &mod_file_struct) void PlannerObjectiveStatement::computingPass() { - model_tree->computingPass(false, true, false); + model_tree->computingPass(eval_context_type(), false, true, false); } void PlannerObjectiveStatement::writeOutput(ostream &output, const string &basename) const { - model_tree->writeStaticFile(basename + "_objective", false); + model_tree->writeStaticFile(basename + "_objective", false, false); } BVARDensityStatement::BVARDensityStatement(int maxnlags_arg, const OptionsList &options_list_arg) : diff --git a/DynamicModel.cc b/DynamicModel.cc index ce95029d..90f3d229 100644 --- a/DynamicModel.cc +++ b/DynamicModel.cc @@ -23,6 +23,7 @@ #include #include #include +#include #include "DynamicModel.hh" // For mkdir() and chdir() @@ -42,9 +43,9 @@ DynamicModel::DynamicModel(SymbolTable &symbol_table_arg, max_exo_lag(0), max_exo_lead(0), max_exo_det_lag(0), max_exo_det_lead(0), dynJacobianColsNbr(0), + global_temporary_terms(true), cutoff(1e-15), - mfs(0), - block_triangular(symbol_table_arg, num_constants_arg) + mfs(0) { } @@ -57,12 +58,10 @@ DynamicModel::AddVariable(int symb_id, int lag) void DynamicModel::compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const { - //first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symb_id, lag))); first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symbol_table.getID(eEndogenous, symb_id), lag))); if (it != first_derivatives.end()) (it->second)->compile(code_file, false, temporary_terms, map_idx, true, false); else - /*code_file.write(&FLDZ, sizeof(FLDZ));*/ { FLDZ_ fldz; fldz.write(code_file); @@ -81,240 +80,178 @@ DynamicModel::compileChainRuleDerivative(ofstream &code_file, int eqr, int varr, FLDZ_ fldz; fldz.write(code_file); } - //code_file.write(&FLDZ, sizeof(FLDZ)); } void -DynamicModel::BuildIncidenceMatrix() -{ - set > endogenous, exogenous; - for (int eq = 0; eq < (int) equations.size(); eq++) - { - BinaryOpNode *eq_node = equations[eq]; - endogenous.clear(); - NodeID Id = eq_node->get_arg1(); - Id->collectEndogenous(endogenous); - Id = eq_node->get_arg2(); - Id->collectEndogenous(endogenous); - for (set >::iterator it_endogenous=endogenous.begin();it_endogenous!=endogenous.end();it_endogenous++) - { - block_triangular.incidencematrix.fill_IM(eq, it_endogenous->first, it_endogenous->second, eEndogenous); - } - exogenous.clear(); - Id = eq_node->get_arg1(); - Id->collectExogenous(exogenous); - Id = eq_node->get_arg2(); - Id->collectExogenous(exogenous); - for (set >::iterator it_exogenous=exogenous.begin();it_exogenous!=exogenous.end();it_exogenous++) - { - block_triangular.incidencematrix.fill_IM(eq, it_exogenous->first, it_exogenous->second, eExogenous); - } - } -} - -void -DynamicModel::computeTemporaryTermsOrdered(Model_Block *ModelBlock) +DynamicModel::computeTemporaryTermsOrdered() { map > first_occurence; map reference_count; - int i, j, m, eq, var, eqr, varr, lag; - temporary_terms_type vect; - ostringstream tmp_output; BinaryOpNode *eq_node; first_derivatives_type::const_iterator it; first_chain_rule_derivatives_type::const_iterator it_chr; ostringstream tmp_s; - - temporary_terms.clear(); + v_temporary_terms.clear(); map_idx.clear(); - for (j = 0;j < ModelBlock->Size;j++) - { - // Compute the temporary terms reordered - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S && iBlock_List[j].Nb_Recursives && ModelBlock->Block_List[j].Equation_Normalized[i]) - ModelBlock->Block_List[j].Equation_Normalized[i]->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, i, map_idx); - else - { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, i, map_idx); - } - } - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - lag=it.first.first; - int eqr=it.second.first; - int varr=it.second.second; - it_chr=first_chain_rule_derivatives.find(make_pair(eqr, make_pair( varr, lag))); - it_chr->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); - } - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + unsigned int nb_blocks = getNbBlocks(); + v_temporary_terms = vector >(nb_blocks); + v_temporary_terms_inuse = vector (nb_blocks); + temporary_terms.clear(); + + if(!global_temporary_terms) + { + for (unsigned int block = 0; block < nb_blocks; block++) { - lag=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) + reference_count.clear(); + temporary_terms.clear(); + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + v_temporary_terms[block] = vector(block_size); + for (unsigned int i = 0; i < block_size; i++) { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var), lag))); - it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); - } - } - /*for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - lag=it.first.first; - eqr=it.second.first; - varr=it.second.second; - it_chr=first_chain_rule_derivatives.find(make_pair(eqr, make_pair( varr, lag))); - it_chr->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); - }*/ - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - lag=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size_exo;i++) - { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X_Index[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous_Index[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eExogenous, var), lag))); - it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); - } - }*/ - //jacobian_max_exo_col=(variable_table.max_exo_lag+variable_table.max_exo_lead+1)*symbol_table.exo_nbr; - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - lag=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - { - for (i=0;iBlock_List[j].IM_lead_lag[m].size_other_endo;i++) + if (icomputeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + else { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index_other_endo[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index_other_endo[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var), lag))); - it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); } } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + } + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + + set temporary_terms_in_use; + temporary_terms_in_use.clear(); + v_temporary_terms_inuse[block] = temporary_terms_in_use; } } - for (j = 0;j < ModelBlock->Size;j++) + else { - // Collecte the temporary terms reordered - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) + for (unsigned int block = 0; block < nb_blocks; block++) { - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S && iBlock_List[j].Nb_Recursives && ModelBlock->Block_List[j].Equation_Normalized[i]) - ModelBlock->Block_List[j].Equation_Normalized[i]->collectTemporary_terms(temporary_terms, ModelBlock, j); - else + // Compute the temporary terms reordered + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + v_temporary_terms[block] = vector(block_size); + for (unsigned int i = 0; i < block_size; i++) { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - eq_node->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - - /*eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - eq_node->collectTemporary_terms(temporary_terms, ModelBlock, j); - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - if(ModelBlock->Block_List[j].Equation_Normalized[i]) - ModelBlock->Block_List[j].Equation_Normalized[i]->collectTemporary_terms(temporary_terms, ModelBlock, j); - for(temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->begin(); it!= ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->end(); it++) - (*it)->collectTemporary_terms(temporary_terms, ModelBlock, j);*/ - } - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - lag=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var), lag))); - //it=first_derivatives.find(make_pair(eq,variable_table.getID(var, lag))); - //if(it!=first_derivatives.end()) - it->second->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - } - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - lag=it.first.first; - eqr=it.second.first; - varr=it.second.second; - it_chr=first_chain_rule_derivatives.find(make_pair(eqr, make_pair( varr, lag))); - it_chr->second->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - lag=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size_exo;i++) - { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X_Index[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous_Index[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eExogenous, var), lag))); - //it=first_derivatives.find(make_pair(eq,variable_table.getID(var, lag))); - it->second->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - }*/ - //jacobian_max_exo_col=(variable_table.max_exo_lag+variable_table.max_exo_lead+1)*symbol_table.exo_nbr; - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - lag=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - { - for (i=0;iBlock_List[j].IM_lead_lag[m].size_other_endo;i++) + if (icomputeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + else { - eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index_other_endo[i]; - var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index_other_endo[i]; - it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var), lag))); - //it=first_derivatives.find(make_pair(eq,variable_table.getID(var, lag))); - //if(it!=first_derivatives.end()) - it->second->collectTemporary_terms(temporary_terms, ModelBlock, j); + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); } } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + } + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) + it->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); } + for (unsigned int block = 0; block < nb_blocks; block++) + { + // Collect the temporary terms reordered + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + set temporary_terms_in_use; + for (unsigned int i = 0; i < block_size; i++) + { + if (icollectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + else + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + } + } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + } + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) + it->second->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) + it->second->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + v_temporary_terms_inuse[block] = temporary_terms_in_use; + } + // Add a mapping form node ID to temporary terms order + int j=0; + for (temporary_terms_type::const_iterator it = temporary_terms.begin(); + it != temporary_terms.end(); it++) + map_idx[(*it)->idx]=j++; } - // Add a mapping form node ID to temporary terms order - j=0; - for (temporary_terms_type::const_iterator it = temporary_terms.begin(); - it != temporary_terms.end(); it++) - map_idx[(*it)->idx]=j++; } void -DynamicModel::writeModelEquationsOrdered_M( Model_Block *ModelBlock, const string &dynamic_basename) const +DynamicModel::writeModelEquationsOrdered_M(const string &dynamic_basename) const { - int i,j,k,m; string tmp_s, sps; ostringstream tmp_output, tmp1_output, global_output; NodeID lhs=NULL, rhs=NULL; BinaryOpNode *eq_node; ostringstream Uf[symbol_table.endo_nbr()]; map reference_count; - //int prev_Simulation_Type=-1, count_derivates=0; - int jacobian_max_endo_col; + temporary_terms_type local_temporary_terms; ofstream output; - //temporary_terms_type::const_iterator it_temp=temporary_terms.begin(); int nze, nze_exo, nze_other_endo; - //map recursive_variables; vector feedback_variables; + ExprNodeOutputType local_output_type; + + if(global_temporary_terms) + { + local_output_type = oMatlabDynamicModelSparse; + local_temporary_terms = temporary_terms; + } + else + local_output_type = oMatlabDynamicModelSparseLocalTemporaryTerms; + //---------------------------------------------------------------------- //For each block - for (j = 0;j < ModelBlock->Size;j++) + for (unsigned int block = 0; block < getNbBlocks(); block++) { + //recursive_variables.clear(); feedback_variables.clear(); //For a block composed of a single equation determines wether we have to evaluate or to solve the equation - nze = nze_exo = nze_other_endo = 0; - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - nze+=ModelBlock->Block_List[j].IM_lead_lag[m].size; - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead_Exo+ModelBlock->Block_List[j].Max_Lag_Exo;m++) - nze_exo+=ModelBlock->Block_List[j].IM_lead_lag[m].size_exo;*/ - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + nze = derivative_endo[block].size(); + nze_other_endo = derivative_other_endo[block].size(); + nze_exo = derivative_exo[block].size(); + BlockSimulationType simulation_type = getBlockSimulationType(block); + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + unsigned int block_exo_size = exo_block[block].size(); + unsigned int block_exo_det_size = exo_det_block[block].size(); + unsigned int block_other_endo_size = other_endo_block[block].size(); + int block_max_lag=max_leadlag_block[block].first; + if(global_temporary_terms) { - k=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - nze_other_endo+=ModelBlock->Block_List[j].IM_lead_lag[m].size_other_endo; + local_output_type = oMatlabDynamicModelSparse; + local_temporary_terms = temporary_terms; } + else + local_output_type = oMatlabDynamicModelSparseLocalTemporaryTerms; + tmp1_output.str(""); - tmp1_output << dynamic_basename << "_" << j+1 << ".m"; + tmp1_output << dynamic_basename << "_" << block+1 << ".m"; output.open(tmp1_output.str().c_str(), ios::out | ios::binary); output << "%\n"; output << "% " << tmp1_output.str() << " : Computes dynamic model for Dynare\n"; @@ -322,183 +259,196 @@ DynamicModel::writeModelEquationsOrdered_M( Model_Block *ModelBlock, const strin output << "% Warning : this file is generated automatically by Dynare\n"; output << "% from model file (.mod)\n\n"; output << "%/\n"; - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD - ||ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD - /*||ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD_R - ||ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD_R*/) + if (simulation_type ==EVALUATE_BACKWARD || simulation_type ==EVALUATE_FORWARD) { - output << "function [y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << j+1 << "(y, x, params, jacobian_eval, y_kmin, periods)\n"; + output << "function [y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << block+1 << "(y, x, params, jacobian_eval, y_kmin, periods)\n"; } - else if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE) - output << "function [residual, y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << j+1 << "(y, x, params, it_, jacobian_eval)\n"; - else if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_SIMPLE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_SIMPLE) - output << "function [residual, y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << j+1 << "(y, x, params, it_, jacobian_eval)\n"; + else if (simulation_type ==SOLVE_FORWARD_COMPLETE || simulation_type ==SOLVE_BACKWARD_COMPLETE) + output << "function [residual, y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << block+1 << "(y, x, params, it_, jacobian_eval)\n"; + else if (simulation_type ==SOLVE_BACKWARD_SIMPLE || simulation_type ==SOLVE_FORWARD_SIMPLE) + output << "function [residual, y, g1, g2, g3, varargout] = " << dynamic_basename << "_" << block+1 << "(y, x, params, it_, jacobian_eval)\n"; else - output << "function [residual, y, g1, g2, g3, b, varargout] = " << dynamic_basename << "_" << j+1 << "(y, x, params, periods, jacobian_eval, y_kmin, y_size)\n"; + output << "function [residual, y, g1, g2, g3, b, varargout] = " << dynamic_basename << "_" << block+1 << "(y, x, params, periods, jacobian_eval, y_kmin, y_size)\n"; + BlockType block_type; + if(simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE ||simulation_type == SOLVE_TWO_BOUNDARIES_SIMPLE) + block_type = SIMULTAN; + else if(simulation_type == SOLVE_FORWARD_COMPLETE ||simulation_type == SOLVE_BACKWARD_COMPLETE) + block_type = SIMULTANS; + else if((simulation_type == SOLVE_FORWARD_SIMPLE ||simulation_type == SOLVE_BACKWARD_SIMPLE || + simulation_type == EVALUATE_BACKWARD || simulation_type == EVALUATE_FORWARD) + && getBlockFirstEquation(block) < prologue) + block_type = PROLOGUE; + else if((simulation_type == SOLVE_FORWARD_SIMPLE ||simulation_type == SOLVE_BACKWARD_SIMPLE || + simulation_type == EVALUATE_BACKWARD || simulation_type == EVALUATE_FORWARD) + && getBlockFirstEquation(block) >= equations.size() - epilogue) + block_type = EPILOGUE; + else + block_type = SIMULTANS; output << " % ////////////////////////////////////////////////////////////////////////" << endl - << " % //" << string(" Block ").substr(int(log10(j + 1))) << j + 1 << " " << BlockTriangular::BlockType0(ModelBlock->Block_List[j].Type) + << " % //" << string(" Block ").substr(int(log10(block + 1))) << block + 1 << " " << BlockType0(block_type) << " //" << endl << " % // Simulation type " - << BlockTriangular::BlockSim(ModelBlock->Block_List[j].Simulation_Type) << " //" << endl + << BlockSim(simulation_type) << " //" << endl << " % ////////////////////////////////////////////////////////////////////////" << endl; output << " global options_;" << endl; //The Temporary terms - //output << " relax = 1;\n"; - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD - ||ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD) + if (simulation_type ==EVALUATE_BACKWARD || simulation_type ==EVALUATE_FORWARD) { output << " if(jacobian_eval)\n"; - output << " g1 = spalloc(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives - << ", " << (ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives)*(1+ModelBlock->Block_List[j].Max_Lag_Endo+ModelBlock->Block_List[j].Max_Lead_Endo) - << ", " << nze << ");\n"; - output << " g1_x=spalloc(" << ModelBlock->Block_List[j].Size << ", " << (ModelBlock->Block_List[j].nb_exo + ModelBlock->Block_List[j].nb_exo_det)*(1+ModelBlock->Block_List[j].Max_Lag_Exo+ModelBlock->Block_List[j].Max_Lead_Exo) << ", " << nze_exo << ");\n"; - output << " g1_o=spalloc(" << ModelBlock->Block_List[j].Size << ", " << ModelBlock->Block_List[j].nb_other_endo*(1+ModelBlock->Block_List[j].Max_Lag_Other_Endo+ModelBlock->Block_List[j].Max_Lead_Other_Endo) << ", " << nze_other_endo << ");\n"; + output << " g1 = spalloc(" << block_mfs << ", " << block_mfs*(1+getBlockMaxLag(block)+getBlockMaxLead(block)) << ", " << nze << ");\n"; + output << " g1_x=spalloc(" << block_size << ", " << (block_exo_size + block_exo_det_size)* + (1+max(exo_det_max_leadlag_block[block].first, exo_max_leadlag_block[block].first)+max(exo_det_max_leadlag_block[block].second, exo_max_leadlag_block[block].second)) + << ", " << nze_exo << ");\n"; + output << " g1_o=spalloc(" << block_size << ", " << block_other_endo_size* + (1+other_endo_max_leadlag_block[block].first+other_endo_max_leadlag_block[block].second) + << ", " << nze_other_endo << ");\n"; output << " end;\n"; } else { output << " if(jacobian_eval)\n"; - output << " g1 = spalloc(" << ModelBlock->Block_List[j].Size << ", " << ModelBlock->Block_List[j].Size*(1+ModelBlock->Block_List[j].Max_Lag_Endo+ModelBlock->Block_List[j].Max_Lead_Endo) << ", " << nze << ");\n"; - output << " g1_x=spalloc(" << ModelBlock->Block_List[j].Size << ", " << (ModelBlock->Block_List[j].nb_exo + ModelBlock->Block_List[j].nb_exo_det)*(1+ModelBlock->Block_List[j].Max_Lag_Exo+ModelBlock->Block_List[j].Max_Lead_Exo) << ", " << nze_exo << ");\n"; - output << " g1_o=spalloc(" << ModelBlock->Block_List[j].Size << ", " << ModelBlock->Block_List[j].nb_other_endo*(1+ModelBlock->Block_List[j].Max_Lag_Other_Endo+ModelBlock->Block_List[j].Max_Lead_Other_Endo) << ", " << nze_other_endo << ");\n"; + output << " g1 = spalloc(" << block_size << ", " << block_size*(1+getBlockMaxLag(block)+getBlockMaxLead(block)) << ", " << nze << ");\n"; + output << " g1_x=spalloc(" << block_size << ", " << (block_exo_size + block_exo_det_size)* + (1+max(exo_det_max_leadlag_block[block].first, exo_max_leadlag_block[block].first)+max(exo_det_max_leadlag_block[block].second, exo_max_leadlag_block[block].second)) + << ", " << nze_exo << ");\n"; + output << " g1_o=spalloc(" << block_size << ", " << block_other_endo_size* + (1+other_endo_max_leadlag_block[block].first+other_endo_max_leadlag_block[block].second) + << ", " << nze_other_endo << ");\n"; output << " else\n"; - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) { - output << " g1 = spalloc(" << (ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives) << "*options_.periods, " - << (ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives) << "*(options_.periods+" << ModelBlock->Block_List[j].Max_Lag+ModelBlock->Block_List[j].Max_Lead+1 << ")" + output << " g1 = spalloc(" << block_mfs << "*options_.periods, " + << block_mfs << "*(options_.periods+" << max_leadlag_block[block].first+max_leadlag_block[block].second+1 << ")" << ", " << nze << "*options_.periods);\n"; - /*output << " g1_tmp_r = spalloc(" << (ModelBlock->Block_List[j].Nb_Recursives) - << ", " << (ModelBlock->Block_List[j].Size)*(ModelBlock->Block_List[j].Max_Lag+ModelBlock->Block_List[j].Max_Lead+1) - << ", " << nze << ");\n"; - output << " g1_tmp_b = spalloc(" << (ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives) - << ", " << (ModelBlock->Block_List[j].Size)*(ModelBlock->Block_List[j].Max_Lag+ModelBlock->Block_List[j].Max_Lead+1) - << ", " << nze << ");\n";*/ } else { - output << " g1 = spalloc(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives - << ", " << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives << ", " << nze << ");\n"; - output << " g1_tmp_r = spalloc(" << ModelBlock->Block_List[j].Nb_Recursives - << ", " << ModelBlock->Block_List[j].Size << ", " << nze << ");\n"; - output << " g1_tmp_b = spalloc(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives - << ", " << ModelBlock->Block_List[j].Size << ", " << nze << ");\n"; + output << " g1 = spalloc(" << block_mfs + << ", " << block_mfs << ", " << nze << ");\n"; + output << " g1_tmp_r = spalloc(" << block_recursive + << ", " << block_size << ", " << nze << ");\n"; + output << " g1_tmp_b = spalloc(" << block_mfs + << ", " << block_size << ", " << nze << ");\n"; } output << " end;\n"; } output << " g2=0;g3=0;\n"; - if (ModelBlock->Block_List[j].Temporary_InUse->size()) + if (v_temporary_terms_inuse[block].size()) { tmp_output.str(""); - for (temporary_terms_inuse_type::const_iterator it = ModelBlock->Block_List[j].Temporary_InUse->begin(); - it != ModelBlock->Block_List[j].Temporary_InUse->end(); it++) + for (temporary_terms_inuse_type::const_iterator it = v_temporary_terms_inuse[block].begin(); + it != v_temporary_terms_inuse[block].end(); it++) tmp_output << " T" << *it; output << " global" << tmp_output.str() << ";\n"; } - if (ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD && ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) - output << " residual=zeros(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives << ",1);\n"; - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD) + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) + { + temporary_terms_type tt2; + tt2.clear(); + for(int i=0; i< (int) block_size; i++) + { + if (v_temporary_terms[block][i].size() && global_temporary_terms) + { + output << " " << "% //Temporary variables initialization" << endl + << " " << "T_zeros = zeros(y_kmin+periods, 1);" << endl; + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + { + output << " "; + (*it)->writeOutput(output, oMatlabDynamicModel, local_temporary_terms); + output << " = T_zeros;" << endl; + } + } + } + } + if (simulation_type==SOLVE_BACKWARD_SIMPLE || simulation_type==SOLVE_FORWARD_SIMPLE || simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) + output << " residual=zeros(" << block_mfs << ",1);\n"; + else if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) + output << " residual=zeros(" << block_mfs << ",y_kmin+periods);\n"; + if (simulation_type==EVALUATE_BACKWARD) output << " for it_ = (y_kmin+periods):y_kmin+1\n"; - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD) + if (simulation_type==EVALUATE_FORWARD) output << " for it_ = y_kmin+1:(y_kmin+periods)\n"; - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) { - output << " b = zeros(periods*y_size,1);\n"; - output << " for it_ = y_kmin+1:(periods+y_kmin)\n"; - output << " Per_y_=it_*y_size;\n"; - output << " Per_J_=(it_-y_kmin-1)*y_size;\n"; - output << " Per_K_=(it_-1)*y_size;\n"; + output << " b = zeros(periods*y_size,1);" << endl + << " for it_ = y_kmin+1:(periods+y_kmin)" << endl + << " Per_y_=it_*y_size;" << endl + << " Per_J_=(it_-y_kmin-1)*y_size;" << endl + << " Per_K_=(it_-1)*y_size;" << endl; sps=" "; } else - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD || ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD ) + if (simulation_type==EVALUATE_BACKWARD || simulation_type==EVALUATE_FORWARD ) sps = " "; else sps=""; // The equations - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) + for (unsigned int i = 0; i < block_size; i++) { temporary_terms_type tt2; tt2.clear(); - if (ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->size()) - output << " " << sps << "% //Temporary variables" << endl; - for (temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->begin(); - it != ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->end(); it++) + if (v_temporary_terms[block].size()) { - output << " " << sps; - (*it)->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << " = "; - (*it)->writeOutput(output, oMatlabDynamicModelSparse, tt2); - // Insert current node into tt2 - tt2.insert(*it); - output << ";" << endl; + output << " " << "% //Temporary variables" << endl; + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + { + output << " " << sps; + (*it)->writeOutput(output, local_output_type, local_temporary_terms); + output << " = "; + (*it)->writeOutput(output, local_output_type, tt2); + // Insert current node into tt2 + tt2.insert(*it); + output << ";" << endl; + } } - string sModel = symbol_table.getName(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i])) ; - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; + + int variable_ID = getBlockVariableID(block, i); + int equation_ID = getBlockEquationID(block, i); + EquationType equ_type = getBlockEquationType(block, i); + string sModel = symbol_table.getName(symbol_table.getID(eEndogenous, variable_ID)) ; + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block,i); lhs = eq_node->get_arg1(); rhs = eq_node->get_arg2(); tmp_output.str(""); - /*if((ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD or ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) and (iBlock_List[j].Nb_Recursives)) - lhs->writeOutput(tmp_output, oMatlabDynamicModelSparse, temporary_terms); - else*/ - lhs->writeOutput(tmp_output, oMatlabDynamicModelSparse, temporary_terms); - switch (ModelBlock->Block_List[j].Simulation_Type) + lhs->writeOutput(tmp_output, local_output_type, local_temporary_terms); + switch (simulation_type) { case EVALUATE_BACKWARD: case EVALUATE_FORWARD: -evaluation: if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - output << " % equation " << ModelBlock->Block_List[j].Equation[i]+1 << " variable : " << sModel - << " (" << ModelBlock->Block_List[j].Variable[i]+1 << ") " << block_triangular.c_Equation_Type(ModelBlock->Block_List[j].Equation_Type[i]) << endl; +evaluation: if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) + output << " % equation " << getBlockEquationID(block, i)+1 << " variable : " << sModel + << " (" << variable_ID+1 << ") " << c_Equation_Type(equ_type) << endl; output << " "; - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE) + if (equ_type == E_EVALUATE) { output << tmp_output.str(); output << " = "; - /*if(!(ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD or ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD)) - { - lhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "-relax*("; - lhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "-("; - rhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "))"; - } - else*/ - rhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); + rhs->writeOutput(output, local_output_type, local_temporary_terms); } - else if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) + else if (equ_type == E_EVALUATE_S) { output << "%" << tmp_output.str(); output << " = "; - if (ModelBlock->Block_List[j].Equation_Normalized[i]) + if (isBlockEquationRenormalized(block, i)) { - rhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); + rhs->writeOutput(output, local_output_type, local_temporary_terms); output << "\n "; tmp_output.str(""); - eq_node = (BinaryOpNode *)ModelBlock->Block_List[j].Equation_Normalized[i]; + eq_node = (BinaryOpNode *)getBlockEquationRenormalizedNodeID(block, i); lhs = eq_node->get_arg1(); rhs = eq_node->get_arg2(); - lhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); + lhs->writeOutput(output, local_output_type, local_temporary_terms); output << " = "; - /*if(!(ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD or ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD)) - { - lhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "-relax*("; - lhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "-("; - rhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); - output << "))"; - } - else*/ - rhs->writeOutput(output, oMatlabDynamicModelSparse, temporary_terms); + rhs->writeOutput(output, local_output_type, local_temporary_terms); } } else { - cerr << "Type missmatch for equation " << ModelBlock->Block_List[j].Equation[i]+1 << "\n"; + cerr << "Type missmatch for equation " << equation_ID+1 << "\n"; exit(EXIT_FAILURE); } output << ";\n"; @@ -507,342 +457,251 @@ evaluation: if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDAR case SOLVE_FORWARD_SIMPLE: case SOLVE_BACKWARD_COMPLETE: case SOLVE_FORWARD_COMPLETE: - if (iBlock_List[j].Nb_Recursives) - { - /*if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i]), 0)] = ModelBlock->Block_List[j].Equation_Normalized[i]; - else - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i]), 0)] = equations[ModelBlock->Block_List[j].Equation[i]];*/ - goto evaluation; - } - feedback_variables.push_back(ModelBlock->Block_List[j].Variable[i]); - output << " % equation " << ModelBlock->Block_List[j].Equation[i]+1 << " variable : " << sModel - << " (" << ModelBlock->Block_List[j].Variable[i]+1 << ") " << block_triangular.c_Equation_Type(ModelBlock->Block_List[j].Equation_Type[i]) << endl; - output << " " << "residual(" << i+1-ModelBlock->Block_List[j].Nb_Recursives << ") = ("; + if (iBlock_List[j].Nb_Recursives) - { - /*if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i]), 0)] = ModelBlock->Block_List[j].Equation_Normalized[i]; - else - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i]), 0)] = equations[ModelBlock->Block_List[j].Equation[i]];*/ - goto evaluation; - } - feedback_variables.push_back(ModelBlock->Block_List[j].Variable[i]); - output << " % equation " << ModelBlock->Block_List[j].Equation[i]+1 << " variable : " << sModel - << " (" << ModelBlock->Block_List[j].Variable[i]+1 << ") " << block_triangular.c_Equation_Type(ModelBlock->Block_List[j].Equation_Type[i]) << endl; - Uf[ModelBlock->Block_List[j].Equation[i]] << " b(" << i+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_J_) = -residual(" << i+1-ModelBlock->Block_List[j].Nb_Recursives << ", it_)"; - output << " residual(" << i+1-ModelBlock->Block_List[j].Nb_Recursives << ", it_) = ("; + if (iwriteOutput(output, oMatlabDynamicModelSparse, temporary_terms); + rhs->writeOutput(output, local_output_type, local_temporary_terms); output << ");\n"; #ifdef CONDITION - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) output << " condition(" << i+1 << ")=0;\n"; #endif } } // The Jacobian if we have to solve the block - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE) + if (simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE || simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE) output << " " << sps << "% Jacobian " << endl; else - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_SIMPLE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_SIMPLE || - ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE) + if (simulation_type==SOLVE_BACKWARD_SIMPLE || simulation_type==SOLVE_FORWARD_SIMPLE || + simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) output << " % Jacobian " << endl << " if jacobian_eval" << endl; else output << " % Jacobian " << endl << " if jacobian_eval" << endl; - switch (ModelBlock->Block_List[j].Simulation_Type) + switch (simulation_type) { case EVALUATE_BACKWARD: case EVALUATE_FORWARD: - for (m=0;mBlock_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag+1;m++) + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var[i]; - output << " g1(" << eqr+1 << ", " << /*varr+1+(m+variable_table.max_lag-ModelBlock->Block_List[j].Max_Lag)*symbol_table.endo_nbr*/ - varr+1+m*ModelBlock->Block_List[j].Size << ") = "; - writeDerivative(output, eq, symbol_table.getID(eEndogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) - << "(" << k//variable_table.getLag(variable_table.getSymbolID(ModelBlock->Block_List[j].Variable[0])) + int lag = it->first.first; + int eq = it->first.second.first; + int var = it->first.second.second; + int eqr = getBlockInitialEquationID(block, eq); + int varr = getBlockInitialVariableID(block, var); + + NodeID id = it->second; + + output << " g1(" << eqr+1 << ", " << varr+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag << ") " << var+1 << ", equation=" << eq+1 << endl; - } } - //jacobian_max_endo_col=(variable_table.max_endo_lag+variable_table.max_endo_lead+1)*symbol_table.endo_nbr; - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size_exo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous_Index[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous[i]; - output << " g1_x(" << eqr+1 << ", " - << varr+1+(m+max_exo_lag-ModelBlock->Block_List[j].Max_Lag)*symbol_table.exo_nbr() << ") = "; - writeDerivative(output, eq, symbol_table.getID(eExogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(var) - << "(" << k << ") " << var+1 - << ", equation=" << eq+1 << endl; - } - }*/ - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - k=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - { - for (i=0;iBlock_List[j].IM_lead_lag[m].size_other_endo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index_other_endo[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index_other_endo[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_other_endo[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var_other_endo[i]; - output << " g1_o(" << eqr+1 << ", " - << varr+1+(m+max_endo_lag-ModelBlock->Block_List[j].Max_Lag)*symbol_table.endo_nbr() << ") = "; - writeDerivative(output, eq, symbol_table.getID(eEndogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) - << "(" << k << ") " << var+1 - << ", equation=" << eq+1 << endl; - } - } + int lag = it->first.first; + int eq = it->first.second.first; + int var = it->first.second.second; + int eqr = getBlockInitialEquationID(block, eq); + NodeID id = it->second; + + output << " g1_o(" << eqr+1 << ", " << var+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag + << ") " << var+1 + << ", equation=" << eq+1 << endl; } output << " varargout{1}=g1_x;\n"; output << " varargout{2}=g1_o;\n"; output << " end;" << endl; - //output << " ya = y;\n"; output << " end;" << endl; break; case SOLVE_BACKWARD_SIMPLE: case SOLVE_FORWARD_SIMPLE: case SOLVE_BACKWARD_COMPLETE: case SOLVE_FORWARD_COMPLETE: - for (m=0;mBlock_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag+1;m++) + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var[i]; - output << " g1(" << eq+1 << ", " - << var+1 + m*(ModelBlock->Block_List[j].Size) << ") = "; - writeDerivative(output, eqr, symbol_table.getID(eEndogenous, varr), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) - << "(" << k << ") " << varr+1 - << ", equation=" << eqr+1 << endl; - } + int lag = it->first.first; + unsigned int eq = it->first.second.first; + unsigned int var = it->first.second.second; + NodeID id = it->second; + + output << " g1(" << eq+1 << ", " << var+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag + << ") " << var+1 + << ", equation=" << eq+1 << endl; } - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size_exo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous_Index[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous[i]; - output << " g1_x(" << eqr+1 << ", " << varr+1+(m+max_exo_lag-ModelBlock->Block_List[j].Max_Lag)*ModelBlock->Block_List[j].nb_exo << ") = "; - writeDerivative(output, eq, symbol_table.getID(eExogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(var) - << "(" << k << ") " << var+1 - << ", equation=" << eq+1 << endl; - } - }*/ - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - k=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - { - for (i=0;iBlock_List[j].IM_lead_lag[m].size_other_endo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index_other_endo[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index_other_endo[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_other_endo[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var_other_endo[i]; - output << " g1_o(" << eqr+1/*-ModelBlock->Block_List[j].Nb_Recursives*/ << ", " - << varr+1+(m+max_endo_lag-ModelBlock->Block_List[j].Max_Lag)*symbol_table.endo_nbr() << ") = "; - writeDerivative(output, eq, symbol_table.getID(eEndogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) - << "(" << k << ") " << var+1 - << ", equation=" << eq+1 << endl; - } - } + int lag = it->first.first; + unsigned int eq = it->first.second.first; + unsigned int var = it->first.second.second; + NodeID id = it->second; + + output << " g1_o(" << eq+1 << ", " << var+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag + << ") " << var+1 + << ", equation=" << eq+1 << endl; } output << " varargout{1}=g1_x;\n"; output << " varargout{2}=g1_o;\n"; output << " else" << endl; - - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - k=it.first.first; - int eq=it.first.second.first; - int var=it.first.second.second; - int eqr=it.second.first; - int varr=it.second.second; - output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << ", " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << ") = "; - writeChainRuleDerivative(output, eqr, varr, k, oMatlabDynamicModelSparse, temporary_terms); - output << "; %2 variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) - << "(" << k << ") " << varr+1 << ", equation=" << eqr+1 << endl; + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + unsigned int eqr = getBlockEquationID(block, eq); + unsigned int varr = getBlockVariableID(block, var); + NodeID id = it->second.second; + int lag = it->second.first; + output << " g1(" << eq+1 << ", " << var+1-block_recursive << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) + << "(" << lag + << ") " << varr+1 + << ", equation=" << eqr+1 << endl; } output << " end;\n"; break; case SOLVE_TWO_BOUNDARIES_SIMPLE: case SOLVE_TWO_BOUNDARIES_COMPLETE: output << " if ~jacobian_eval" << endl; - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - k=it.first.first; - int eq=it.first.second.first; - int var=it.first.second.second; - int eqr=it.second.first; - int varr=it.second.second; + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + unsigned int eqr = getBlockEquationID(block, eq); + unsigned int varr = getBlockVariableID(block, var); ostringstream tmp_output; - if(eq>=ModelBlock->Block_List[j].Nb_Recursives and var>=ModelBlock->Block_List[j].Nb_Recursives) + NodeID id = it->second.second; + int lag = it->second.first; + if(eq>=block_recursive and var>=block_recursive) { - if (k==0) - Uf[ModelBlock->Block_List[j].Equation[eq]] << "+g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives - << "+Per_J_, " << var+1-ModelBlock->Block_List[j].Nb_Recursives + if (lag==0) + Uf[eqr] << "+g1(" << eq+1-block_recursive + << "+Per_J_, " << var+1-block_recursive << "+Per_K_)*y(it_, " << varr+1 << ")"; - else if (k==1) - Uf[ModelBlock->Block_List[j].Equation[eq]] << "+g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives - << "+Per_J_, " << var+1-ModelBlock->Block_List[j].Nb_Recursives + else if (lag==1) + Uf[eqr] << "+g1(" << eq+1-block_recursive + << "+Per_J_, " << var+1-block_recursive << "+Per_y_)*y(it_+1, " << varr+1 << ")"; - else if (k>0) - Uf[ModelBlock->Block_List[j].Equation[eq]] << "+g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives - << "+Per_J_, " << var+1-ModelBlock->Block_List[j].Nb_Recursives - << "+y_size*(it_+" << k-1 << "))*y(it_+" << k << ", " << varr+1 << ")"; - else if (k<0) - Uf[ModelBlock->Block_List[j].Equation[eq]] << "+g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives - << "+Per_J_, " << var+1-ModelBlock->Block_List[j].Nb_Recursives - << "+y_size*(it_" << k-1 << "))*y(it_" << k << ", " << varr+1 << ")"; - if (k==0) - tmp_output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_J_, " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_K_) = "; - else if (k==1) - tmp_output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_J_, " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_y_) = "; - else if (k>0) - tmp_output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_J_, " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << "+y_size*(it_+" << k-1 << ")) = "; - else if (k<0) - tmp_output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << "+Per_J_, " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << "+y_size*(it_" << k-1 << ")) = "; + else if (lag>0) + Uf[eqr] << "+g1(" << eq+1-block_recursive + << "+Per_J_, " << var+1-block_recursive + << "+y_size*(it_+" << lag-1 << "))*y(it_+" << lag << ", " << varr+1 << ")"; + else if (lag<0) + Uf[eqr] << "+g1(" << eq+1-block_recursive + << "+Per_J_, " << var+1-block_recursive + << "+y_size*(it_" << lag-1 << "))*y(it_" << lag << ", " << varr+1 << ")"; + if (lag==0) + tmp_output << " g1(" << eq+1-block_recursive << "+Per_J_, " + << var+1-block_recursive << "+Per_K_) = "; + else if (lag==1) + tmp_output << " g1(" << eq+1-block_recursive << "+Per_J_, " + << var+1-block_recursive << "+Per_y_) = "; + else if (lag>0) + tmp_output << " g1(" << eq+1-block_recursive << "+Per_J_, " + << var+1-block_recursive << "+y_size*(it_+" << lag-1 << ")) = "; + else if (lag<0) + tmp_output << " g1(" << eq+1-block_recursive << "+Per_J_, " + << var+1-block_recursive << "+y_size*(it_" << lag-1 << ")) = "; output << " " << tmp_output.str(); - - writeChainRuleDerivative(output, eqr, varr, k, oMatlabDynamicModelSparse, temporary_terms); - + id->writeOutput(output, local_output_type, local_temporary_terms); output << ";"; output << " %2 variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) - << "(" << k << ") " << varr+1 + << "(" << lag << ") " << varr+1 << ", equation=" << eqr+1 << " (" << eq+1 << ")" << endl; } + #ifdef CONDITION output << " if (fabs(condition[" << eqr << "])Block_List[j].Size;i++) + for (unsigned int i = 0; i < block_size; i++) { - if (i>=ModelBlock->Block_List[j].Nb_Recursives) - output << " " << Uf[ModelBlock->Block_List[j].Equation[i]].str() << ";\n"; + if (i>=block_recursive) + output << " " << Uf[getBlockEquationID(block, i)].str() << ";\n"; #ifdef CONDITION output << " if (fabs(condition(" << i+1 << "))Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + for (m=0;m<=ModelBlock->Block_List[block].Max_Lead+ModelBlock->Block_List[block].Max_Lag;m++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) + k=m-ModelBlock->Block_List[block].Max_Lag; + for (i=0;iBlock_List[block].IM_lead_lag[m].size;i++) { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - int u=ModelBlock->Block_List[j].IM_lead_lag[m].u[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ[i]; + unsigned int eq=ModelBlock->Block_List[block].IM_lead_lag[m].Equ_Index[i]; + unsigned int var=ModelBlock->Block_List[block].IM_lead_lag[m].Var_Index[i]; + unsigned int u=ModelBlock->Block_List[block].IM_lead_lag[m].u[i]; + unsigned int eqr=ModelBlock->Block_List[block].IM_lead_lag[m].Equ[i]; output << " u(" << u+1 << "+Per_u_) = u(" << u+1 << "+Per_u_) / condition(" << eqr+1 << ");\n"; } } - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) + for (i = 0;i < ModelBlock->Block_List[block].Size;i++) output << " u(" << i+1 << "+Per_u_) = u(" << i+1 << "+Per_u_) / condition(" << i+1 << ");\n"; #endif output << " else" << endl; - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + + for (t_derivative::const_iterator it = derivative_endo[block].begin(); it != derivative_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var[i]; - output << " g1(" << eqr+1 << ", " << varr+1+(m-ModelBlock->Block_List[j].Max_Lag+ModelBlock->Block_List[j].Max_Lag_Endo)*ModelBlock->Block_List[j].Size << ") = "; - writeDerivative(output, eq, symbol_table.getID(eEndogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) - << "(" << k << ") " << var+1 + int lag = it->first.first; + unsigned int eq = it->first.second.first; + unsigned int var = it->first.second.second; + NodeID id = it->second; + output << " g1(" << eq+1 << ", " << var+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag + << ") " << var+1 << ", equation=" << eq+1 << endl; - } } - jacobian_max_endo_col=(ModelBlock->Block_List[j].Max_Lead_Endo+ModelBlock->Block_List[j].Max_Lag_Endo+1)*ModelBlock->Block_List[j].Size; - /*for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) + for (t_derivative::const_iterator it = derivative_other_endo[block].begin(); it != derivative_other_endo[block].end(); it++) { - k=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size_exo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X_Index[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_X[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Exogenous_Index[i]; - output << " g1_x(" << eqr+1 << ", " - << jacobian_max_endo_col+(m-(ModelBlock->Block_List[j].Max_Lag-ModelBlock->Block_List[j].Max_Lag_Exo))*ModelBlock->Block_List[j].nb_exo+varr+1 << ") = "; - writeDerivative(output, eq, symbol_table.getID(eExogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable (exogenous)=" << symbol_table.getName(var) - << "(" << k << ") " << var+1 << " " << varr+1 - << ", equation=" << eq+1 << endl; - } - }*/ - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - k=m-ModelBlock->Block_List[j].Max_Lag; - if (block_triangular.incidencematrix.Model_Max_Lag_Endo - ModelBlock->Block_List[j].Max_Lag +m >=0) - { - for (i=0;iBlock_List[j].IM_lead_lag[m].size_other_endo;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index_other_endo[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index_other_endo[i]; - int eqr=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_other_endo[i]; - int varr=ModelBlock->Block_List[j].IM_lead_lag[m].Var_other_endo[i]; - output << " g1_o(" << eqr+1 << ", " - << varr+1+(m+max_endo_lag-ModelBlock->Block_List[j].Max_Lag)*symbol_table.endo_nbr() << ") = "; - writeDerivative(output, eq, symbol_table.getID(eEndogenous, var), k, oMatlabDynamicModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) - << "(" << k << ") " << var+1 - << ", equation=" << eq+1 << endl; - } - } + int lag = it->first.first; + unsigned int eq = it->first.second.first; + unsigned int var = it->first.second.second; + NodeID id = it->second; + + output << " g1_o(" << eq+1 << ", " << var+1+(lag+block_max_lag)*block_size << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, var)) + << "(" << lag + << ") " << var+1 + << ", equation=" << eq+1 << endl; } output << " varargout{1}=g1_x;\n"; output << " varargout{2}=g1_o;\n"; output << " end;\n"; - //output << " ya = y;\n"; output << " end;\n"; break; default: @@ -853,7 +712,7 @@ end: } void -DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const Model_Block *ModelBlock, const string bin_basename, map_idx_type map_idx) const +DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const { struct Uff_l { @@ -866,7 +725,7 @@ DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const Model Uff_l *Ufl, *Ufl_First; }; - int i,j,k,v; + int i,v; string tmp_s; ostringstream tmp_output; ofstream code_file; @@ -876,6 +735,7 @@ DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const Model map reference_count; vector feedback_variables; bool file_open=false; + string main_name=file_name; main_name+=".cod"; code_file.open(main_name.c_str(), ios::out | ios::binary | ios::ate ); @@ -885,93 +745,61 @@ DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const Model exit(EXIT_FAILURE); } //Temporary variables declaration - /*code_file.write(&FDIMT, sizeof(FDIMT)); - k=temporary_terms.size(); - code_file.write(reinterpret_cast(&k),sizeof(k));*/ + FDIMT_ fdimt(temporary_terms.size()); fdimt.write(code_file); - for (j = 0; j < ModelBlock->Size ;j++) + for (unsigned int block = 0; block < getNbBlocks(); block++) { feedback_variables.clear(); - if (j>0) + if (block>0) { FENDBLOCK_ fendblock; fendblock.write(code_file); - //code_file.write(&FENDBLOCK, sizeof(FENDBLOCK)); } int count_u; int u_count_int=0; - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || - ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE) + BlockSimulationType simulation_type = getBlockSimulationType(block); + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + int block_max_lag=max_leadlag_block[block].first; + + if (simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE || simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || + simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) { - //cout << "ModelBlock->Block_List[j].Nb_Recursives = " << ModelBlock->Block_List[j].Nb_Recursives << "\n"; - Write_Inf_To_Bin_File(file_name, bin_basename, j, u_count_int,file_open, - ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE); - //cout << "u_count_int=" << u_count_int << "\n"; - - - /*code_file.write(reinterpret_cast(&ModelBlock->Block_List[j].is_linear),sizeof(ModelBlock->Block_List[j].is_linear)); - //v=block_triangular.ModelBlock->Block_List[j].IM_lead_lag[block_triangular.ModelBlock->Block_List[j].Max_Lag + block_triangular.ModelBlock->Block_List[j].Max_Lead].u_finish + 1; - v=symbol_table.endo_nbr(); - code_file.write(reinterpret_cast(&v),sizeof(v)); - v=block_triangular.ModelBlock->Block_List[j].Max_Lag; - code_file.write(reinterpret_cast(&v),sizeof(v)); - v=block_triangular.ModelBlock->Block_List[j].Max_Lead; - code_file.write(reinterpret_cast(&v),sizeof(v)); - - v=u_count_int; - code_file.write(reinterpret_cast(&v),sizeof(v));*/ + Write_Inf_To_Bin_File(file_name, bin_basename, block, u_count_int,file_open, + simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE); file_open=true; } - FBEGINBLOCK_ fbeginblock(ModelBlock->Block_List[j].Size - ModelBlock->Block_List[j].Nb_Recursives, - ModelBlock->Block_List[j].Simulation_Type, - ModelBlock->Block_List[j].Variable, - ModelBlock->Block_List[j].Equation, - ModelBlock->Block_List[j].Own_Derivative, - ModelBlock->Block_List[j].is_linear, + FBEGINBLOCK_ fbeginblock(block_mfs, + simulation_type, + getBlockFirstEquation(block), + block_size, + variable_reordered, + equation_reordered, + blocks_linear[block], symbol_table.endo_nbr(), - ModelBlock->Block_List[j].Max_Lag, - ModelBlock->Block_List[j].Max_Lead, + block_max_lag, + block_max_lag, u_count_int ); fbeginblock.write(code_file); - /*code_file.write(&FBEGINBLOCK, sizeof(FBEGINBLOCK)); - v=ModelBlock->Block_List[j].Size - ModelBlock->Block_List[j].Nb_Recursives; - //cout << "v (Size) = " << v << "\n"; - code_file.write(reinterpret_cast(&v),sizeof(v)); - v=ModelBlock->Block_List[j].Simulation_Type; - code_file.write(reinterpret_cast(&v),sizeof(v)); - for (i=ModelBlock->Block_List[j].Nb_Recursives; i < ModelBlock->Block_List[j].Size;i++) + // The equations + for (i = 0;i < (int) block_size;i++) { - code_file.write(reinterpret_cast(&ModelBlock->Block_List[j].Variable[i]),sizeof(ModelBlock->Block_List[j].Variable[i])); - code_file.write(reinterpret_cast(&ModelBlock->Block_List[j].Equation[i]),sizeof(ModelBlock->Block_List[j].Equation[i])); - code_file.write(reinterpret_cast(&ModelBlock->Block_List[j].Own_Derivative[i]),sizeof(ModelBlock->Block_List[j].Own_Derivative[i])); - }*/ - - // The equations - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) + //The Temporary terms + temporary_terms_type tt2; + tt2.clear(); + if (v_temporary_terms[block][i].size()) { - //The Temporary terms - temporary_terms_type tt2; - tt2.clear(); -#ifdef DEBUGC - k=0; -#endif - for (temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->begin(); - it != ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->end(); it++) + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) { (*it)->compile(code_file, false, tt2, map_idx, true, false); - FSTPT_ fstpt((int)(map_idx.find((*it)->idx)->second)); fstpt.write(code_file); - - /*code_file.write(&FSTPT, sizeof(FSTPT)); - map_idx_type::const_iterator ii=map_idx.find((*it)->idx); - v=(int)ii->second; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ - // Insert current node into tt2 tt2.insert(*it); #ifdef DEBUGC @@ -982,204 +810,167 @@ DynamicModel::writeModelEquationsCodeOrdered(const string file_name, const Model #endif } + } #ifdef DEBUGC - for (temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_terms->begin(); - it != ModelBlock->Block_List[j].Temporary_terms->end(); it++) - { - map_idx_type::const_iterator ii=map_idx.find((*it)->idx); - cout << "map_idx[" << (*it)->idx <<"]=" << ii->second << "\n"; - } + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + { + map_idx_type::const_iterator ii=map_idx.find((*it)->idx); + cout << "map_idx[" << (*it)->idx <<"]=" << ii->second << "\n"; + } #endif - switch (ModelBlock->Block_List[j].Simulation_Type) - { + + int variable_ID, equation_ID; + EquationType equ_type; + + + switch (simulation_type) + { evaluation: - case EVALUATE_BACKWARD: - case EVALUATE_FORWARD: - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE) - { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - rhs->compile(code_file, false, temporary_terms, map_idx, true, false); - lhs->compile(code_file, true, temporary_terms, map_idx, true, false); - } - else if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - { - eq_node = (BinaryOpNode*)ModelBlock->Block_List[j].Equation_Normalized[i]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - rhs->compile(code_file, false, temporary_terms, map_idx, true, false); - lhs->compile(code_file, true, temporary_terms, map_idx, true, false); - } - break; - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - case SOLVE_TWO_BOUNDARIES_COMPLETE: - case SOLVE_TWO_BOUNDARIES_SIMPLE: - if (iBlock_List[j].Nb_Recursives) - goto evaluation; - feedback_variables.push_back(ModelBlock->Block_List[j].Variable[i]); - v=ModelBlock->Block_List[j].Equation[i]; - Uf[v].Ufl=NULL; - goto end; - default: -end: - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; + case EVALUATE_BACKWARD: + case EVALUATE_FORWARD: + equ_type = getBlockEquationType(block, i); + if (equ_type == E_EVALUATE) + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block,i); lhs = eq_node->get_arg1(); rhs = eq_node->get_arg2(); - lhs->compile(code_file, false, temporary_terms, map_idx, true, false); rhs->compile(code_file, false, temporary_terms, map_idx, true, false); - - FBINARY_ fbinary(oMinus); - fbinary.write(code_file); - /*code_file.write(&FBINARY, sizeof(FBINARY)); - int v=oMinus; - code_file.write(reinterpret_cast(&v),sizeof(v));*/ - FSTPR_ fstpr(i - ModelBlock->Block_List[j].Nb_Recursives); - fstpr.write(code_file); - /*code_file.write(&FSTPR, sizeof(FSTPR)); - v = i - ModelBlock->Block_List[j].Nb_Recursives; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ + lhs->compile(code_file, true, temporary_terms, map_idx, true, false); } - } - FENDEQU_ fendequ; - fendequ.write(code_file); - //code_file.write(&FENDEQU, sizeof(FENDEQU)); - // The Jacobian if we have to solve the block - if (ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD - && ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) - { - switch (ModelBlock->Block_List[j].Simulation_Type) + else if (equ_type == E_EVALUATE_S) { - case SOLVE_BACKWARD_SIMPLE: - case SOLVE_FORWARD_SIMPLE: - compileDerivative(code_file, ModelBlock->Block_List[j].Equation[0], ModelBlock->Block_List[j].Variable[0], 0, map_idx); - { - FSTPG_ fstpg(0); - fstpg.write(code_file); - } - /*code_file.write(&FSTPG, sizeof(FSTPG)); - v=0; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ - break; - - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - case SOLVE_TWO_BOUNDARIES_COMPLETE: - case SOLVE_TWO_BOUNDARIES_SIMPLE: - //count_u=ModelBlock->Block_List[j].Size - ModelBlock->Block_List[j].Nb_Recursives; - count_u = feedback_variables.size(); - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - k=it.first.first; - int eq=it.first.second.first; - int var=it.first.second.second; - int eqr=it.second.first; - int varr=it.second.second; - //cout << "k=" << k << " eq=" << eq << " (" << eq-ModelBlock->Block_List[j].Nb_Recursives << ") var=" << var << " (" << var-ModelBlock->Block_List[j].Nb_Recursives << ") eqr=" << eqr << " varr=" << varr << " count_u=" << count_u << "\n"; - int v=ModelBlock->Block_List[j].Equation[eq]; - /*m = ModelBlock->Block_List[j].Max_Lag + k; - int u=ModelBlock->Block_List[j].IM_lead_lag[m].u[i];*/ - if(eq>=ModelBlock->Block_List[j].Nb_Recursives and var>=ModelBlock->Block_List[j].Nb_Recursives) - { - if (!Uf[v].Ufl) - { - Uf[v].Ufl=(Uff_l*)malloc(sizeof(Uff_l)); - Uf[v].Ufl_First=Uf[v].Ufl; - } - else - { - Uf[v].Ufl->pNext=(Uff_l*)malloc(sizeof(Uff_l)); - Uf[v].Ufl=Uf[v].Ufl->pNext; - } - Uf[v].Ufl->pNext=NULL; - Uf[v].Ufl->u=count_u; - Uf[v].Ufl->var=varr; - Uf[v].Ufl->lag=k; - compileChainRuleDerivative(code_file, eqr, varr, k, map_idx); - - FSTPU_ fstpu(count_u); - fstpu.write(code_file); - - /*code_file.write(&FSTPU, sizeof(FSTPU)); - code_file.write(reinterpret_cast(&count_u), sizeof(count_u));*/ - count_u++; - } - } - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - if(i>=ModelBlock->Block_List[j].Nb_Recursives) - { - FLDR_ fldr(i-ModelBlock->Block_List[j].Nb_Recursives); - fldr.write(code_file); - /*code_file.write(&FLDR, sizeof(FLDR)); - v = i-ModelBlock->Block_List[j].Nb_Recursives; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ - - FLDZ_ fldz; - fldz.write(code_file); - //code_file.write(&FLDZ, sizeof(FLDZ)); - - v=ModelBlock->Block_List[j].Equation[i]; - for (Uf[v].Ufl=Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl=Uf[v].Ufl->pNext) - { - FLDU_ fldu(Uf[v].Ufl->u); - fldu.write(code_file); - /*code_file.write(&FLDU, sizeof(FLDU)); - code_file.write(reinterpret_cast(&Uf[v].Ufl->u), sizeof(Uf[v].Ufl->u));*/ - FLDV_ fldv(eEndogenous, Uf[v].Ufl->var, Uf[v].Ufl->lag); - fldv.write(code_file); - - /*code_file.write(&FLDV, sizeof(FLDV)); - char vc=eEndogenous; - code_file.write(reinterpret_cast(&vc), sizeof(vc)); - int v1=Uf[v].Ufl->var; - code_file.write(reinterpret_cast(&v1), sizeof(v1)); - v1=Uf[v].Ufl->lag; - code_file.write(reinterpret_cast(&v1), sizeof(v1));*/ - FBINARY_ fbinary(oTimes); - fbinary.write(code_file); - /*code_file.write(&FBINARY, sizeof(FBINARY)); - v1=oTimes; - code_file.write(reinterpret_cast(&v1), sizeof(v1));*/ - - FCUML_ fcuml; - fcuml.write(code_file); - //code_file.write(&FCUML, sizeof(FCUML)); - } - Uf[v].Ufl=Uf[v].Ufl_First; - while (Uf[v].Ufl) - { - Uf[v].Ufl_First=Uf[v].Ufl->pNext; - free(Uf[v].Ufl); - Uf[v].Ufl=Uf[v].Ufl_First; - } - FBINARY_ fbinary(oMinus); - fbinary.write(code_file); - /*code_file.write(&FBINARY, sizeof(FBINARY)); - v=oMinus; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ - - FSTPU_ fstpu(i - ModelBlock->Block_List[j].Nb_Recursives); - fstpu.write(code_file); - /*code_file.write(&FSTPU, sizeof(FSTPU)); - v = i - ModelBlock->Block_List[j].Nb_Recursives; - code_file.write(reinterpret_cast(&v), sizeof(v));*/ - } - } - break; - default: - break; + eq_node = (BinaryOpNode*)getBlockEquationRenormalizedNodeID(block,i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + rhs->compile(code_file, false, temporary_terms, map_idx, true, false); + lhs->compile(code_file, true, temporary_terms, map_idx, true, false); } + break; + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + case SOLVE_TWO_BOUNDARIES_COMPLETE: + case SOLVE_TWO_BOUNDARIES_SIMPLE: + if (i< (int) block_recursive) + goto evaluation; + variable_ID = getBlockVariableID(block, i); + equation_ID = getBlockEquationID(block, i); + feedback_variables.push_back(variable_ID); + Uf[equation_ID].Ufl=NULL; + goto end; + default: +end: + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + lhs->compile(code_file, false, temporary_terms, map_idx, true, false); + rhs->compile(code_file, false, temporary_terms, map_idx, true, false); + + FBINARY_ fbinary(oMinus); + fbinary.write(code_file); + FSTPR_ fstpr(i - block_recursive); + fstpr.write(code_file); } + } + FENDEQU_ fendequ; + fendequ.write(code_file); + // The Jacobian if we have to solve the block + if (simulation_type != EVALUATE_BACKWARD + && simulation_type != EVALUATE_FORWARD) + { + switch (simulation_type) + { + case SOLVE_BACKWARD_SIMPLE: + case SOLVE_FORWARD_SIMPLE: + compileDerivative(code_file, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0, map_idx); + { + FSTPG_ fstpg(0); + fstpg.write(code_file); + } + break; + + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + case SOLVE_TWO_BOUNDARIES_COMPLETE: + case SOLVE_TWO_BOUNDARIES_SIMPLE: + count_u = feedback_variables.size(); + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + unsigned int eqr = getBlockEquationID(block, eq); + unsigned int varr = getBlockVariableID(block, var); + int lag = it->second.first; + if(eq>=block_recursive and var>=block_recursive) + { + if (!Uf[eqr].Ufl) + { + Uf[eqr].Ufl=(Uff_l*)malloc(sizeof(Uff_l)); + Uf[eqr].Ufl_First=Uf[eqr].Ufl; + } + else + { + Uf[eqr].Ufl->pNext=(Uff_l*)malloc(sizeof(Uff_l)); + Uf[eqr].Ufl=Uf[eqr].Ufl->pNext; + } + Uf[eqr].Ufl->pNext=NULL; + Uf[eqr].Ufl->u=count_u; + Uf[eqr].Ufl->var=varr; + Uf[eqr].Ufl->lag=lag; + compileChainRuleDerivative(code_file, eqr, varr, lag, map_idx); + FSTPU_ fstpu(count_u); + fstpu.write(code_file); + count_u++; + } + } + for (i = 0;i < (int) block_size;i++) + { + if(i>= (int) block_recursive) + { + FLDR_ fldr(i-block_recursive); + fldr.write(code_file); + + FLDZ_ fldz; + fldz.write(code_file); + + v=getBlockEquationID(block, i); + for (Uf[v].Ufl=Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl=Uf[v].Ufl->pNext) + { + FLDU_ fldu(Uf[v].Ufl->u); + fldu.write(code_file); + FLDV_ fldv(eEndogenous, Uf[v].Ufl->var, Uf[v].Ufl->lag); + fldv.write(code_file); + + FBINARY_ fbinary(oTimes); + fbinary.write(code_file); + + FCUML_ fcuml; + fcuml.write(code_file); + } + Uf[v].Ufl=Uf[v].Ufl_First; + while (Uf[v].Ufl) + { + Uf[v].Ufl_First=Uf[v].Ufl->pNext; + free(Uf[v].Ufl); + Uf[v].Ufl=Uf[v].Ufl_First; + } + FBINARY_ fbinary(oMinus); + fbinary.write(code_file); + + FSTPU_ fstpu(i - block_recursive); + fstpu.write(code_file); + } + } + break; + default: + break; + } + } } FENDBLOCK_ fendblock; fendblock.write(code_file); - //code_file.write(&FENDBLOCK, sizeof(FENDBLOCK)); FEND_ fend; fend.write(code_file); - //code_file.write(&FEND, sizeof(FEND)); code_file.close(); } @@ -1201,7 +992,7 @@ DynamicModel::writeDynamicMFile(const string &dynamic_basename) const << "%" << endl << "% Warning : this file is generated automatically by Dynare" << endl << "% from model file (.mod)" << endl << endl; - + if (containsSteadyStateOperator()) mDynamicModelFile << "global oo_;" << endl << endl; @@ -1215,7 +1006,7 @@ DynamicModel::writeDynamicCFile(const string &dynamic_basename) const { string filename = dynamic_basename + ".c"; ofstream mDynamicModelFile; - + mDynamicModelFile.open(filename.c_str(), ios::out | ios::binary); if (!mDynamicModelFile.is_open()) { @@ -1336,73 +1127,38 @@ DynamicModel::Write_Inf_To_Bin_File(const string &dynamic_basename, const string exit(EXIT_FAILURE); } u_count_int=0; - int Size = block_triangular.ModelBlock->Block_List[num].Size - block_triangular.ModelBlock->Block_List[num].Nb_Recursives; - for(int i=0; i<(int)block_triangular.ModelBlock->Block_List[num].Chain_Rule_Derivatives->size();i++) - { - //Chain_Rule_Derivatives.insert(make_pair( make_pair(eq, eqr), make_pair(var, make_pair(varr, lag)))); - pair< pair >, pair > it = block_triangular.ModelBlock->Block_List[num].Chain_Rule_Derivatives->at(i); - int k=it.first.first; - int eq=it.first.second.first; - - int var_init=it.first.second.second; - /*int eqr=it.second.first; - int varr=it.second.second;*/ - if(eq>=block_triangular.ModelBlock->Block_List[num].Nb_Recursives and var_init>=block_triangular.ModelBlock->Block_List[num].Nb_Recursives) + unsigned int block_size = getBlockSize(num); + unsigned int block_mfs = getBlockMfs(num); + unsigned int block_recursive = block_size - block_mfs; + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[num].begin(); it != (blocks_derivatives[num]).end(); it++) + { + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + int lag = it->second.first; + if(eq>=block_recursive and var>=block_recursive) { - int v=eq-block_triangular.ModelBlock->Block_List[num].Nb_Recursives; + int v = eq - block_recursive; SaveCode.write(reinterpret_cast(&v), sizeof(v)); - int var=it.first.second.second-block_triangular.ModelBlock->Block_List[num].Nb_Recursives + k * Size; - SaveCode.write(reinterpret_cast(&var), sizeof(var)); - SaveCode.write(reinterpret_cast(&k), sizeof(k)); - int u = u_count_int + Size; + int varr = var - block_recursive + lag * block_mfs; + SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); + SaveCode.write(reinterpret_cast(&lag), sizeof(lag)); + int u = u_count_int + block_mfs; SaveCode.write(reinterpret_cast(&u), sizeof(u)); - //cout << "eq=" << eq << " var=" << var << " k=" << k << " u=" << u << "\n"; u_count_int++; } - } - - - /*for (int m=0;m<=block_triangular.ModelBlock->Block_List[num].Max_Lead+block_triangular.ModelBlock->Block_List[num].Max_Lag;m++) - { - int k1=m-block_triangular.ModelBlock->Block_List[num].Max_Lag; - for (j=0;jBlock_List[num].IM_lead_lag[m].size;j++) - { - int varr=block_triangular.ModelBlock->Block_List[num].IM_lead_lag[m].Var[j]+k1*block_triangular.ModelBlock->Block_List[num].Size; - int u=block_triangular.ModelBlock->Block_List[num].IM_lead_lag[m].u[j]; - int eqr1=block_triangular.ModelBlock->Block_List[num].IM_lead_lag[m].Equ[j]; - SaveCode.write(reinterpret_cast(&eqr1), sizeof(eqr1)); - SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); - SaveCode.write(reinterpret_cast(&k1), sizeof(k1)); - SaveCode.write(reinterpret_cast(&u), sizeof(u)); - u_count_int++; - } - }*/ - if (is_two_boundaries) - { - /*for (j=0;j(&eqr1), sizeof(eqr1)); - SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); - SaveCode.write(reinterpret_cast(&k1), sizeof(k1)); - SaveCode.write(reinterpret_cast(&eqr1), sizeof(eqr1)); - u_count_int++; - }*/ - u_count_int+=Size; } - //cout << "u_count_int=" << u_count_int << "\n"; - for (j=block_triangular.ModelBlock->Block_List[num].Nb_Recursives;jBlock_List[num].Size;j++) + + if (is_two_boundaries) + u_count_int+=block_mfs; + for (j = block_recursive; j < (int) block_size; j++) { - int varr=block_triangular.ModelBlock->Block_List[num].Variable[j]; + unsigned int varr=getBlockVariableID(num, j); SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); } - for (j=block_triangular.ModelBlock->Block_List[num].Nb_Recursives;jBlock_List[num].Size;j++) + for (j = block_recursive; j < (int) block_size; j++) { - int eqr1=block_triangular.ModelBlock->Block_List[num].Equation[j]; - SaveCode.write(reinterpret_cast(&eqr1), sizeof(eqr1)); + unsigned int eqr=getBlockEquationID(num, j); + SaveCode.write(reinterpret_cast(&eqr), sizeof(eqr)); } SaveCode.close(); } @@ -1413,8 +1169,7 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri string sp; ofstream mDynamicModelFile; ostringstream tmp, tmp1, tmp_eq; - int prev_Simulation_Type, tmp_i; - //SymbolicGaussElimination SGE; + int prev_Simulation_Type; bool OK; chdir(basename.c_str()); string filename = dynamic_basename + ".m"; @@ -1431,7 +1186,7 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << "% from model file (.mod)\n\n"; mDynamicModelFile << "%/\n"; - int i, k, Nb_SGE=0; + int Nb_SGE=0; bool skip_head, open_par=false; mDynamicModelFile << "function [varargout] = " << dynamic_basename << "(varargin)\n"; @@ -1464,95 +1219,73 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri 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"; + mDynamicModelFile << " y_kmin=M_.maximum_lag;" << endl + << " y_kmax=M_.maximum_lead;" << endl + << " y_size=M_.endo_nbr;" << endl + << " if(length(varargin)>0)" << endl + << " %it is a simple evaluation of the dynamic model for time _it" << endl + << " params=varargin{3};" << endl + << " it_=varargin{4};" << endl + << " Per_u_=0;" << endl + << " Per_y_=it_*y_size;" << endl + << " y=varargin{1};" << endl + << " ys=y(it_,:);" << endl + << " x=varargin{2};" << endl; prev_Simulation_Type=-1; tmp.str(""); tmp_eq.str(""); - for (int count_call=1, i = 0;i < block_triangular.ModelBlock->Size;i++, count_call++) + unsigned int nb_blocks = getNbBlocks(); + unsigned int block = 0; + for (int count_call=1; block < nb_blocks; block++, count_call++) { - mDynamicModelFile << " %block_triangular.ModelBlock->Block_List[i].Nb_Recursives=" << block_triangular.ModelBlock->Block_List[i].Nb_Recursives << " block_triangular.ModelBlock->Block_List[i].Size=" << block_triangular.ModelBlock->Block_List[i].Size << "\n"; - k=block_triangular.ModelBlock->Block_List[i].Simulation_Type; - if(k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD) + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + BlockSimulationType simulation_type = getBlockSimulationType(block); + + if(simulation_type==EVALUATE_FORWARD || simulation_type==EVALUATE_BACKWARD) { - for (int ik=0 ;ikBlock_List[i].Size;ik++) + for (unsigned int ik=0 ;ikBlock_List[i].Variable[ik]+1; - tmp_eq << " " << block_triangular.ModelBlock->Block_List[i].Equation[ik]+1; + tmp << " " << getBlockVariableID(block, ik)+1; + tmp_eq << " " << getBlockEquationID(block, ik)+1; } } else { - for (int ik=block_triangular.ModelBlock->Block_List[i].Nb_Recursives ;ikBlock_List[i].Size;ik++) + for (unsigned int ik = block_recursive; ik < block_size; ik++) { - tmp << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; - tmp_eq << " " << block_triangular.ModelBlock->Block_List[i].Equation[ik]+1; + tmp << " " << getBlockVariableID(block, ik)+1; + tmp_eq << " " << getBlockEquationID(block, ik)+1; } } mDynamicModelFile << " y_index_eq=[" << tmp_eq.str() << "];\n"; mDynamicModelFile << " y_index=[" << tmp.str() << "];\n"; - switch (k) + switch (simulation_type) { case EVALUATE_FORWARD: case EVALUATE_BACKWARD: - mDynamicModelFile << " [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"; + mDynamicModelFile << " [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 << "_" << block + 1 << "(y, x, params, 1, it_-1, 1);\n"; mDynamicModelFile << " 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 << " [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 << "_" << block + 1 << "(y, x, params, it_, 1);\n"; mDynamicModelFile << " residual(y_index_eq)=r;\n"; 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 << " [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 << "_" << block + 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;jBlock_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;jBlock_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";*/ - //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-block_triangular.ModelBlock->Block_List[i].Nb_Recursives << ");\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 << " [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 << "_" << block + 1 << "(y, x, params, it_-" << max_lag << ", 1, " << max_lag << ", " << block_recursive << ");\n"; mDynamicModelFile << " residual(y_index_eq)=r(:,M_.maximum_lag+1);\n"; break; + default: + break; } tmp_eq.str(""); tmp.str(""); @@ -1562,43 +1295,47 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri 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_.stack_solve_algo==1)\n"; - mDynamicModelFile << " mthd='Sparse LU';\n"; - mDynamicModelFile << " elseif(options_.stack_solve_algo==2)\n"; - mDynamicModelFile << " mthd='GMRES';\n"; - mDynamicModelFile << " elseif(options_.stack_solve_algo==3)\n"; - mDynamicModelFile << " mthd='BICGSTAB';\n"; - mDynamicModelFile << " elseif(options_.stack_solve_algo==4)\n"; - mDynamicModelFile << " mthd='OPTIMPATH';\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"; + mDynamicModelFile << " varargout{1}=residual;" << endl + << " varargout{2}=dr;" << endl + << " return;" << endl + << " end;" << endl + << " %it is the deterministic simulation of the block decomposed dynamic model" << endl + << " if(options_.stack_solve_algo==1)" << endl + << " mthd='Sparse LU';" << endl + << " elseif(options_.stack_solve_algo==2)" << endl + << " mthd='GMRES';" << endl + << " elseif(options_.stack_solve_algo==3)" << endl + << " mthd='BICGSTAB';" << endl + << " elseif(options_.stack_solve_algo==4)" << endl + << " mthd='OPTIMPATH';" << endl + << " else" << endl + << " mthd='UNKNOWN';" << endl + << " end;" << endl + << " disp (['-----------------------------------------------------']) ;" << endl + << " disp (['MODEL SIMULATION: (method=' mthd ')']) ;" << endl + << " fprintf('\\n') ;" << endl + << " periods=options_.periods;" << endl + << " maxit_=options_.maxit_;" << endl + << " solve_tolf=options_.solve_tolf;" << endl + << " y=oo_.endo_simul';" << endl + << " x=oo_.exo_simul;" << endl; prev_Simulation_Type=-1; mDynamicModelFile << " params=M_.params;\n"; mDynamicModelFile << " oo_.deterministic_simulation.status = 0;\n"; - for (i = 0;i < block_triangular.ModelBlock->Size;i++) + for (block = 0;block < nb_blocks; block++) { - k = block_triangular.ModelBlock->Block_List[i].Simulation_Type; - if (BlockTriangular::BlockSim(prev_Simulation_Type)==BlockTriangular::BlockSim(k) && - (k==EVALUATE_FORWARD || k==EVALUATE_BACKWARD /*|| k==EVALUATE_FORWARD_R || k==EVALUATE_BACKWARD_R*/)) + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + BlockSimulationType simulation_type = getBlockSimulationType(block); + + if (BlockSim(prev_Simulation_Type)==BlockSim(simulation_type) && + (simulation_type==EVALUATE_FORWARD || simulation_type==EVALUATE_BACKWARD )) skip_head=true; else skip_head=false; - if ((k == EVALUATE_FORWARD /*|| k == EVALUATE_FORWARD_R*/) && (block_triangular.ModelBlock->Block_List[i].Size)) + if ((simulation_type == EVALUATE_FORWARD ) && (block_size)) { if (!skip_head) { @@ -1618,17 +1355,15 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << " oo_.deterministic_simulation.block(blck_num).error = 0;\n"; mDynamicModelFile << " oo_.deterministic_simulation.block(blck_num).iterations = 0;\n"; mDynamicModelFile << " g1=[];g2=[];g3=[];\n"; - //mDynamicModelFile << " for it_ = y_kmin+1:(periods+y_kmin)\n"; - mDynamicModelFile << " y=" << dynamic_basename << "_" << i + 1 << "(y, x, params, 0, y_kmin, periods);\n"; - mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << i + 1 << ").variable);\n"; + mDynamicModelFile << " y=" << dynamic_basename << "_" << block + 1 << "(y, x, params, 0, y_kmin, periods);\n"; + mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);\n"; mDynamicModelFile << " if(isnan(tmp) | isinf(tmp))\n"; - mDynamicModelFile << " disp(['Inf or Nan value during the evaluation of block " << i <<"']);\n"; + mDynamicModelFile << " disp(['Inf or Nan value during the evaluation of block " << block <<"']);\n"; mDynamicModelFile << " return;\n"; mDynamicModelFile << " end;\n"; } - //open_par=true; } - else if ((k == EVALUATE_BACKWARD /*|| k == EVALUATE_BACKWARD_R*/) && (block_triangular.ModelBlock->Block_List[i].Size)) + else if ((simulation_type == EVALUATE_BACKWARD ) && (block_size)) { if (!skip_head) { @@ -1648,15 +1383,15 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << " oo_.deterministic_simulation.block(blck_num).error = 0;\n"; mDynamicModelFile << " oo_.deterministic_simulation.block(blck_num).iterations = 0;\n"; mDynamicModelFile << " g1=[];g2=[];g3=[];\n"; - mDynamicModelFile << " " << dynamic_basename << "_" << i + 1 << "(y, x, params, 0, y_kmin, periods);\n"; - mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << i + 1 << ").variable);\n"; + mDynamicModelFile << " " << dynamic_basename << "_" << block + 1 << "(y, x, params, 0, y_kmin, periods);\n"; + mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);\n"; mDynamicModelFile << " if(isnan(tmp) | isinf(tmp))\n"; - mDynamicModelFile << " disp(['Inf or Nan value during the evaluation of block " << i <<"']);\n"; + mDynamicModelFile << " disp(['Inf or Nan value during the evaluation of block " << block <<"']);\n"; mDynamicModelFile << " return;\n"; mDynamicModelFile << " end;\n"; } } - else if ((k == SOLVE_FORWARD_COMPLETE || k == SOLVE_FORWARD_SIMPLE) && (block_triangular.ModelBlock->Block_List[i].Size)) + else if ((simulation_type == SOLVE_FORWARD_COMPLETE || simulation_type == SOLVE_FORWARD_SIMPLE) && (block_size)) { if (open_par) mDynamicModelFile << " end\n"; @@ -1664,30 +1399,28 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << " g1=0;\n"; mDynamicModelFile << " r=0;\n"; tmp.str(""); - for (int ik=block_triangular.ModelBlock->Block_List[i].Nb_Recursives ;ikBlock_List[i].Size;ik++) + for (unsigned int ik = block_recursive; ik < block_size; ik++) { - tmp << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; + tmp << " " << getBlockVariableID(block, ik)+1; } mDynamicModelFile << " y_index = [" << tmp.str() << "];\n"; - int nze, m; - for (nze=0,m=0;m<=block_triangular.ModelBlock->Block_List[i].Max_Lead+block_triangular.ModelBlock->Block_List[i].Max_Lag;m++) - nze+=block_triangular.ModelBlock->Block_List[i].IM_lead_lag[m].size; + int nze = blocks_derivatives[block].size(); mDynamicModelFile << " if(isfield(oo_.deterministic_simulation,'block'))\n"; mDynamicModelFile << " blck_num = length(oo_.deterministic_simulation.block)+1;\n"; mDynamicModelFile << " else\n"; mDynamicModelFile << " blck_num = 1;\n"; mDynamicModelFile << " end;\n"; - mDynamicModelFile << " y = solve_one_boundary('" << dynamic_basename << "_" << i + 1 << "'" << + mDynamicModelFile << " y = solve_one_boundary('" << dynamic_basename << "_" << block + 1 << "'" << ", y, x, params, y_index, " << nze << - ", options_.periods, " << block_triangular.ModelBlock->Block_List[i].is_linear << + ", options_.periods, " << blocks_linear[block] << ", blck_num, y_kmin, options_.maxit_, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0);\n"; - mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << i + 1 << ").variable);\n"; + mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);\n"; mDynamicModelFile << " if(isnan(tmp) | isinf(tmp))\n"; - mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << i <<"']);\n"; + mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << block <<"']);\n"; mDynamicModelFile << " return;\n"; mDynamicModelFile << " end;\n"; } - else if ((k == SOLVE_BACKWARD_COMPLETE || k == SOLVE_BACKWARD_SIMPLE) && (block_triangular.ModelBlock->Block_List[i].Size)) + else if ((simulation_type == SOLVE_BACKWARD_COMPLETE || simulation_type == SOLVE_BACKWARD_SIMPLE) && (block_size)) { if (open_par) mDynamicModelFile << " end\n"; @@ -1695,42 +1428,39 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << " g1=0;\n"; mDynamicModelFile << " r=0;\n"; tmp.str(""); - for (int ik=block_triangular.ModelBlock->Block_List[i].Nb_Recursives ;ikBlock_List[i].Size;ik++) + for (unsigned int ik = block_recursive; ik < block_size; ik++) { - tmp << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; + tmp << " " << getBlockVariableID(block, ik)+1; } mDynamicModelFile << " y_index = [" << tmp.str() << "];\n"; - int nze, m; - for (nze=0,m=0;m<=block_triangular.ModelBlock->Block_List[i].Max_Lead+block_triangular.ModelBlock->Block_List[i].Max_Lag;m++) - nze+=block_triangular.ModelBlock->Block_List[i].IM_lead_lag[m].size; + int nze = blocks_derivatives[block].size(); + mDynamicModelFile << " if(isfield(oo_.deterministic_simulation,'block'))\n"; mDynamicModelFile << " blck_num = length(oo_.deterministic_simulation.block)+1;\n"; mDynamicModelFile << " else\n"; mDynamicModelFile << " blck_num = 1;\n"; mDynamicModelFile << " end;\n"; - mDynamicModelFile << " y = solve_one_boundary('" << dynamic_basename << "_" << i + 1 << "'" << + mDynamicModelFile << " y = solve_one_boundary('" << dynamic_basename << "_" << block + 1 << "'" << ", y, x, params, y_index, " << nze << - ", options_.periods, " << block_triangular.ModelBlock->Block_List[i].is_linear << + ", options_.periods, " << blocks_linear[block] << ", blck_num, y_kmin, options_.maxit_, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo, 1, 1, 0);\n"; - mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << i + 1 << ").variable);\n"; + mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);\n"; mDynamicModelFile << " if(isnan(tmp) | isinf(tmp))\n"; - mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << i <<"']);\n"; + mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << block <<"']);\n"; mDynamicModelFile << " return;\n"; mDynamicModelFile << " end;\n"; } - else if ((k == SOLVE_TWO_BOUNDARIES_COMPLETE || k == SOLVE_TWO_BOUNDARIES_SIMPLE) && (block_triangular.ModelBlock->Block_List[i].Size)) + else if ((simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE || simulation_type == SOLVE_TWO_BOUNDARIES_SIMPLE) && (block_size)) { if (open_par) mDynamicModelFile << " end\n"; open_par=false; Nb_SGE++; - int nze, m; - for (nze=0,m=0;m<=block_triangular.ModelBlock->Block_List[i].Max_Lead+block_triangular.ModelBlock->Block_List[i].Max_Lag;m++) - nze+=block_triangular.ModelBlock->Block_List[i].IM_lead_lag[m].size; + int nze = blocks_derivatives[block].size(); mDynamicModelFile << " y_index=["; - for (int ik=block_triangular.ModelBlock->Block_List[i].Nb_Recursives ;ikBlock_List[i].Size;ik++) + for (unsigned int ik = block_recursive; ik < block_size; ik++) { - mDynamicModelFile << " " << block_triangular.ModelBlock->Block_List[i].Variable[ik]+1; + mDynamicModelFile << " " << getBlockVariableID(block, ik)+1; } mDynamicModelFile << " ];\n"; mDynamicModelFile << " if(isfield(oo_.deterministic_simulation,'block'))\n"; @@ -1738,19 +1468,19 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile << " else\n"; mDynamicModelFile << " blck_num = 1;\n"; mDynamicModelFile << " end;\n"; - mDynamicModelFile << " y = solve_two_boundaries('" << dynamic_basename << "_" << i + 1 << "'" << + mDynamicModelFile << " y = solve_two_boundaries('" << dynamic_basename << "_" << block + 1 << "'" << ", y, x, params, y_index, " << nze << - ", options_.periods, " << block_triangular.ModelBlock->Block_List[i].Max_Lag << - ", " << block_triangular.ModelBlock->Block_List[i].Max_Lead << - ", " << block_triangular.ModelBlock->Block_List[i].is_linear << + ", options_.periods, " << max_leadlag_block[block].first << + ", " << max_leadlag_block[block].second << + ", " << blocks_linear[block] << ", blck_num, y_kmin, options_.maxit_, options_.solve_tolf, options_.slowc, " << cutoff << ", options_.stack_solve_algo);\n"; - mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << i + 1 << ").variable);\n"; + mDynamicModelFile << " tmp = y(:,M_.block_structure.block(" << block + 1 << ").variable);\n"; mDynamicModelFile << " if(isnan(tmp) | isinf(tmp))\n"; - mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << i <<"']);\n"; + mDynamicModelFile << " disp(['Inf or Nan value during the resolution of block " << block <<"']);\n"; mDynamicModelFile << " return;\n"; mDynamicModelFile << " end;\n"; } - prev_Simulation_Type=k; + prev_Simulation_Type=simulation_type; } if (open_par) mDynamicModelFile << " end;\n"; @@ -1760,7 +1490,7 @@ DynamicModel::writeSparseDynamicMFile(const string &dynamic_basename, const stri mDynamicModelFile.close(); - writeModelEquationsOrdered_M( block_triangular.ModelBlock, dynamic_basename); + writeModelEquationsOrdered_M(dynamic_basename); chdir(".."); } @@ -1993,7 +1723,7 @@ DynamicModel::writeDynamicModel(ostream &DynamicOutput, bool use_dll) const } void -DynamicModel::writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll) const +DynamicModel::writeOutput(ostream &output, const string &basename, bool block_decomposition, bool byte_code, bool use_dll) const { /* Writing initialisation for M_.lead_lag_incidence matrix M_.lead_lag_incidence is a matrix with as many columns as there are @@ -2035,58 +1765,50 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block, b << equation_tags[i].second.second << "' ;" << endl; output << "};" << endl; - //In case of sparse model, writes the block structure of the model - if (block) + //In case of sparse model, writes the block_decomposition structure of the model + if (block_decomposition) { - //int prev_Simulation_Type=-1; - //bool skip_the_head; - int k=0; int count_lead_lag_incidence = 0; int max_lead, max_lag, max_lag_endo, max_lead_endo, max_lag_exo, max_lead_exo; - for (int j = 0;j < block_triangular.ModelBlock->Size;j++) + unsigned int nb_blocks = getNbBlocks(); + for (unsigned int block = 0; block < nb_blocks; block++) { //For a block composed of a single equation determines wether we have to evaluate or to solve the equation - //skip_the_head=false; - k++; count_lead_lag_incidence = 0; - int Block_size=block_triangular.ModelBlock->Block_List[j].Size; - max_lag =block_triangular.ModelBlock->Block_List[j].Max_Lag ; - max_lead=block_triangular.ModelBlock->Block_List[j].Max_Lead; - max_lag_endo =block_triangular.ModelBlock->Block_List[j].Max_Lag_Endo ; - max_lead_endo=block_triangular.ModelBlock->Block_List[j].Max_Lead_Endo; - max_lag_exo =block_triangular.ModelBlock->Block_List[j].Max_Lag_Exo ; - max_lead_exo=block_triangular.ModelBlock->Block_List[j].Max_Lead_Exo; - bool evaluate=false; - vector exogenous; + BlockSimulationType simulation_type = getBlockSimulationType(block); + int block_size = getBlockSize(block); + max_lag = max_leadlag_block[block].first; + max_lead = max_leadlag_block[block].second; + max_lag_endo = endo_max_leadlag_block[block].first; + max_lead_endo= endo_max_leadlag_block[block].second; + max_lag_exo = max(exo_max_leadlag_block[block].first, exo_det_max_leadlag_block[block].first); + max_lead_exo= max(exo_max_leadlag_block[block].second, exo_det_max_leadlag_block[block].second); + vector exogenous(symbol_table.exo_nbr(), -1); vector::iterator it_exogenous; exogenous.clear(); ostringstream tmp_s, tmp_s_eq; tmp_s.str(""); tmp_s_eq.str(""); - for (int i=0;iBlock_List[j].Size;i++) + for (int i=0;iBlock_List[j].Variable[i]+1; - tmp_s_eq << " " << block_triangular.ModelBlock->Block_List[j].Equation[i]+1; + tmp_s << " " << getBlockVariableID(block, i)+1; + tmp_s_eq << " " << getBlockEquationID(block, i)+1; } - for (int i=0;iBlock_List[j].nb_exo;i++) - { - int ii=block_triangular.ModelBlock->Block_List[j].Exogenous[i]; - for (it_exogenous=exogenous.begin();it_exogenous!=exogenous.end() && *it_exogenous!=ii;it_exogenous++) /*cout << "*it_exogenous=" << *it_exogenous << "\n"*/; - if (it_exogenous==exogenous.end() || exogenous.begin()==exogenous.end()) - exogenous.push_back(ii); - } - output << "M_.block_structure.block(" << k << ").num = " << j+1 << ";\n"; - output << "M_.block_structure.block(" << k << ").Simulation_Type = " << block_triangular.ModelBlock->Block_List[j].Simulation_Type << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_lag = " << max_lag << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_lead = " << max_lead << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_endo_lag = " << max_lag_endo << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_endo_lead = " << max_lead_endo << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_exo_lag = " << max_lag_exo << ";\n"; - output << "M_.block_structure.block(" << k << ").maximum_exo_lead = " << max_lead_exo << ";\n"; - output << "M_.block_structure.block(" << k << ").endo_nbr = " << Block_size << ";\n"; - output << "M_.block_structure.block(" << k << ").equation = [" << tmp_s_eq.str() << "];\n"; - output << "M_.block_structure.block(" << k << ").variable = [" << tmp_s.str() << "];\n"; - output << "M_.block_structure.block(" << k << ").exogenous = ["; + it_exogenous = exogenous.begin(); + for(t_lag_var::const_iterator it = exo_block[block].begin(); it != exo_block[block].end(); it++) + it_exogenous = set_union(it->second.begin(), it->second.end(), exogenous.begin(), exogenous.end(), it_exogenous); + output << "M_.block_structure.block(" << block+1 << ").num = " << block+1 << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").Simulation_Type = " << simulation_type << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_lag = " << max_lag << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_lead = " << max_lead << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_endo_lag = " << max_lag_endo << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_endo_lead = " << max_lead_endo << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_exo_lag = " << max_lag_exo << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").maximum_exo_lead = " << max_lead_exo << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").endo_nbr = " << block_size << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").equation = [" << tmp_s_eq.str() << "];\n"; + output << "M_.block_structure.block(" << block+1 << ").variable = [" << tmp_s.str() << "];\n"; + output << "M_.block_structure.block(" << block+1 << ").exogenous = ["; int i=0; for (it_exogenous=exogenous.begin();it_exogenous!=exogenous.end();it_exogenous++) if (*it_exogenous>=0) @@ -2095,112 +1817,79 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block, b i++; } output << "];\n"; - output << "M_.block_structure.block(" << k << ").exo_nbr = " << i << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").exo_nbr = " << i << ";\n"; - output << "M_.block_structure.block(" << k << ").exo_det_nbr = " << block_triangular.ModelBlock->Block_List[j].nb_exo_det << ";\n"; + output << "M_.block_structure.block(" << block+1 << ").exo_det_nbr = " << exo_det_block.size() << ";\n"; tmp_s.str(""); - - bool done_IM=false; - if (!evaluate) + count_lead_lag_incidence = 0; + dynamic_jacob_map reordered_dynamic_jacobian; + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != blocks_derivatives[block].end(); it++) + reordered_dynamic_jacobian[make_pair(it->second.first, make_pair(it->first.second, it->first.first))] = it->second.second; + output << "M_.block_structure.block(" << block+1 << ").lead_lag_incidence = [];\n"; + int last_var = -1; + for (int lag=-max_lag_endo;lagfirst.first && last_var != it->first.second.first) { - for (int l_var=0;l_varBlock_List[j].Size;l_var++) - { - for (int l_equ=0;l_equBlock_List[j].Size;l_equ++) - if (tmp_IM[block_triangular.ModelBlock->Block_List[j].Equation[l_equ]*symbol_table.endo_nbr()+block_triangular.ModelBlock->Block_List[j].Variable[l_var]]) - { - count_lead_lag_incidence++; - if (tmp_s.str().length()) - tmp_s << " "; - tmp_s << count_lead_lag_incidence; - done_IM=true; - break; - } - if (!done_IM) - tmp_s << " 0"; - done_IM=false; - } - output << "M_.block_structure.block(" << k << ").lead_lag_incidence = [ M_.block_structure.block(" << k << ").lead_lag_incidence; " << tmp_s.str() << "];\n"; - tmp_s.str(""); + count_lead_lag_incidence++; + for( int i = last_var; i < it->first.second.first-1; i++) + tmp_s << " 0"; + if (tmp_s.str().length()) + tmp_s << " "; + tmp_s << count_lead_lag_incidence; + last_var = it->first.second.first; } } - } - else - { - bool done_some_where; - output << "M_.block_structure.block(" << k << ").lead_lag_incidence = [\n"; - for (int l=-max_lag_endo;lBlock_List[ii].Size;l_var++) - { - for (int l_equ=0;l_equBlock_List[ii].Size;l_equ++) - if (tmp_IM[block_triangular.ModelBlock->Block_List[ii].Equation[l_equ]*symbol_table.endo_nbr()+block_triangular.ModelBlock->Block_List[ii].Variable[l_var]]) - { - //if(not_increm && l==-max_lag) - count_lead_lag_incidence++; - not_increm=false; - if (tmp_s.str().length()) - tmp_s << " "; - //tmp_s << count_lead_lag_incidence+(l+max_lag)*Block_size; - tmp_s << count_lead_lag_incidence; - done_IM=true; - break; - } - if (!done_IM) - tmp_s << " 0"; - else - done_some_where = true; - done_IM=false; - } - ii++; - } - output << tmp_s.str() << "\n"; - tmp_s.str(""); - } - } - output << "];\n"; - } - - } - for (int j=-block_triangular.incidencematrix.Model_Max_Lag_Endo;j<=block_triangular.incidencematrix.Model_Max_Lead_Endo;j++) - { - bool* IM = block_triangular.incidencematrix.Get_IM(j, eEndogenous); - if (IM) - { - bool new_entry=true; - output << "M_.block_structure.incidence(" << block_triangular.incidencematrix.Model_Max_Lag_Endo+j+1 << ").lead_lag = " << j << ";\n"; - output << "M_.block_structure.incidence(" << block_triangular.incidencematrix.Model_Max_Lag_Endo+j+1 << ").sparse_IM = ["; - for (int i=0;i >, int> lag_row_incidence; + for (first_derivatives_type::const_iterator it = first_derivatives.begin(); + it != first_derivatives.end(); it++) + { + int deriv_id = it->first.second; + if (getTypeByDerivID(deriv_id) == eEndogenous) + { + int eq = it->first.first; + int symb = getSymbIDByDerivID(deriv_id); + int var = symbol_table.getTypeSpecificID(symb); + int lag = getLagByDerivID(deriv_id); + int eqr = inv_equation_reordered[eq]; + int varr = inv_variable_reordered[var]; + lag_row_incidence[make_pair(lag, make_pair(eqr, varr))] = 1; + } + } + int prev_lag=-1000000; + for(map >, int> ::const_iterator it=lag_row_incidence.begin(); it != lag_row_incidence.end(); it++) + { + if(prev_lag != it->first.first) + { + if(prev_lag != -1000000) + output << "];\n"; + prev_lag = it->first.first; + output << "M_.block_structure.incidence(" << max_endo_lag+it->first.first+1 << ").lead_lag = " << prev_lag << ";\n"; + output << "M_.block_structure.incidence(" << max_endo_lag+it->first.first+1 << ").sparse_IM = ["; + } + output << it->first.second.first << " " << it->first.second.second << ";\n"; + } + output << "];\n"; } // Writing initialization for some other variables output << "M_.exo_names_orig_ord = [1:" << symbol_table.exo_nbr() << "];" << endl @@ -2234,139 +1923,6 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block, b << "M_.NNZDerivatives(3) = " << NNZDerivatives[2] << ";" << endl; } -void -DynamicModel::evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic) -{ - int i=0; - int j=0; - bool *IM=NULL; - int a_variable_lag=-9999; - for (first_derivatives_type::iterator it = first_derivatives.begin(); - it != first_derivatives.end(); it++) - { - //cout << "it->first.second=" << it->first.second << " variable_table.getSymbolID(it->first.second)=" << variable_table.getSymbolID(it->first.second) << " Type=" << variable_table.getType(it->first.second) << " eEndogenous=" << eEndogenous << " eExogenous=" << eExogenous << " variable_table.getLag(it->first.second)=" << variable_table.getLag(it->first.second) << "\n"; - if (getTypeByDerivID(it->first.second) == eEndogenous) - { - NodeID Id = it->second; - double val = 0; - try - { - val = Id->eval(eval_context); - } - catch (ExprNode::EvalException &e) - { - cout << "evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(getSymbIDByDerivID(it->first.second)) << "(" << getLagByDerivID(it->first.second) << ") [" << getSymbIDByDerivID(it->first.second) << "] !" << endl; - Id->writeOutput(cout, oMatlabDynamicModelSparse, temporary_terms); - cout << "\n"; - cerr << "DynamicModel::evaluateJacobian: evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(getSymbIDByDerivID(it->first.second)) << "(" << getLagByDerivID(it->first.second) << ")!" << endl; - } - int eq=it->first.first; - int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(it->first.second));///symbol_table.getID(eEndogenous,it->first.second);//variable_table.getSymbolID(it->first.second); - int k1 = getLagByDerivID(it->first.second); - if (a_variable_lag!=k1) - { - IM=block_triangular.incidencematrix.Get_IM(k1, eEndogenous); - a_variable_lag=k1; - } - if (k1==0 or !dynamic) - { - j++; - (*j_m)[make_pair(eq,var)]+=val; - } - if (IM[eq*symbol_table.endo_nbr()+var] && (fabs(val) < cutoff)) - { - if (block_triangular.bt_verbose) - cout << "the coefficient related to variable " << var << " with lag " << k1 << " in equation " << eq << " is equal to " << val << " and is set to 0 in the incidence matrix (size=" << symbol_table.endo_nbr() << ")\n"; - block_triangular.incidencematrix.unfill_IM(eq, var, k1, eEndogenous); - i++; - } - } - } - //Get ride of the elements of the incidence matrix equal to Zero - IM=block_triangular.incidencematrix.Get_IM(0, eEndogenous); - for (int i=0;i0) - { - cout << i << " elements among " << first_derivatives.size() << " in the incidence matrices are below the cutoff (" << cutoff << ") and are discarded\n"; - cout << "the contemporaneous incidence matrix has " << j << " elements\n"; - } -} - -void -DynamicModel::BlockLinear(Model_Block *ModelBlock) -{ - int i,j,l,m,ll; - for (j = 0;j < ModelBlock->Size;j++) - { - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE || - ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE) - { - ll=ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[ll].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[ll].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[ll].Var_Index[i]; - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,variable_table.getID(var,0))); - first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var),0))); - if (it!= first_derivatives.end()) - { - NodeID Id = it->second; - set > endogenous; - Id->collectEndogenous(endogenous); - if (endogenous.size() > 0) - { - for (l=0;lBlock_List[j].Size;l++) - { - if (endogenous.find(make_pair(ModelBlock->Block_List[j].Variable[l], 0)) != endogenous.end()) - { - ModelBlock->Block_List[j].is_linear=false; - goto follow; - } - } - } - } - } - } - else if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - { - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - int k1=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,variable_table.getID(var,k1))); - first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var),k1))); - NodeID Id = it->second; - if (it!= first_derivatives.end()) - { - set > endogenous; - Id->collectEndogenous(endogenous); - if (endogenous.size() > 0) - { - for (l=0;lBlock_List[j].Size;l++) - { - if (endogenous.find(make_pair(ModelBlock->Block_List[j].Variable[l], k1)) != endogenous.end()) - { - ModelBlock->Block_List[j].is_linear=false; - goto follow; - } - } - } - } - } - } - } -follow: - i=0; - } -} - map >, NodeID> DynamicModel::collect_first_order_derivatives_endogenous() @@ -2380,7 +1936,6 @@ DynamicModel::collect_first_order_derivatives_endogenous() int eq = it2->first.first; int var=symbol_table.getTypeSpecificID(getSymbIDByDerivID(it2->first.second)); int lag=getLagByDerivID(it2->first.second); - //if (lag==0) endo_derivatives[make_pair(eq, make_pair(var, lag))] = it2->second; } } @@ -2439,28 +1994,39 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative if (block) { - BuildIncidenceMatrix(); + jacob_map contemporaneous_jacobian, static_jacobian; - jacob_map j_m; - evaluateJacobian(eval_context, &j_m, true); + // for each block contains pair + vector > blocks; + evaluateAndReduceJacobian(eval_context, contemporaneous_jacobian, static_jacobian, dynamic_jacobian, cutoff, false); + + computePossiblySingularNormalization(contemporaneous_jacobian, cutoff == 0); + + computePrologueAndEpilogue(static_jacobian, equation_reordered, variable_reordered, prologue, epilogue); - if (block_triangular.bt_verbose) - { - cout << "The gross incidence matrix \n"; - block_triangular.incidencematrix.Print_IM(eEndogenous); - } - t_etype equation_simulation_type; map >, NodeID> first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); - block_triangular.Normalize_and_BlockDecompose_Static_0_Model(j_m, equations, equation_simulation_type, first_order_endo_derivatives, mfs, cutoff); + equation_type_and_normalized_equation = equationTypeDetermination(equations, first_order_endo_derivatives, variable_reordered, equation_reordered, mfs); - BlockLinear(block_triangular.ModelBlock); + cout << "Finding the optimal block decomposition of the model ...\n"; - computeChainRuleJacobian(block_triangular.ModelBlock); + if (prologue+epilogue < (unsigned int) equation_number()) + computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, dynamic_jacobian, prologue, epilogue, equation_reordered, variable_reordered, blocks, equation_type_and_normalized_equation, false, true, mfs, inv_equation_reordered, inv_variable_reordered); + block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(dynamic_jacobian, prologue, epilogue, blocks, equations, equation_type_and_normalized_equation, variable_reordered, equation_reordered); + + printBlockDecomposition(blocks); + + computeChainRuleJacobian(blocks_derivatives); + + blocks_linear = BlockLinear(blocks_derivatives, variable_reordered); + + collect_block_first_order_derivatives(); + + global_temporary_terms = true; if (!no_tmp_terms) - computeTemporaryTermsOrdered(block_triangular.ModelBlock); + computeTemporaryTermsOrdered(); } else @@ -2468,17 +2034,253 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative computeTemporaryTerms(!use_dll); } +map >, pair >, int> +DynamicModel::get_Derivatives(int block) +{ + map >, pair >, int> Derivatives; + Derivatives.clear(); + int max_lag = getBlockMaxLag(block); + int max_lead = getBlockMaxLead(block); + int block_size = getBlockSize(block); + int block_nb_recursive = block_size - getBlockMfs(block); + for(int lag = -max_lag; lag <= max_lead; lag++) + { + for(int eq = 0; eq < block_size; eq++) + { + int eqr = getBlockEquationID(block, eq); + for(int var = 0; var < block_size; var++) + { + int varr = getBlockVariableID(block, var); + if(dynamic_jacobian.find(make_pair(lag, make_pair(eqr, varr))) != dynamic_jacobian.end()) + { + bool OK = true; + map >, pair >, int>::const_iterator its = Derivatives.find(make_pair(make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))); + if(its!=Derivatives.end()) + { + if(its->second == 2) + OK=false; + } + + if(OK) + { + if (getBlockEquationType(block, eq) == E_EVALUATE_S and eq recursive_variables; + unsigned int nb_blocks = getNbBlocks(); + blocks_derivatives = t_blocks_derivatives(nb_blocks); + for(unsigned int block = 0; block < nb_blocks; block++) + { + t_block_derivatives_equation_variable_laglead_nodeid tmp_derivatives; + recursive_variables.clear(); + BlockSimulationType simulation_type = getBlockSimulationType(block); + int block_size = getBlockSize(block); + int block_nb_mfs = getBlockMfs(block); + int block_nb_recursives = block_size - block_nb_mfs; + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE or simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) + { + blocks_derivatives.push_back(t_block_derivatives_equation_variable_laglead_nodeid(0)); + for(int i = 0; i < block_nb_recursives; i++) + { + if (getBlockEquationType(block, i) == E_EVALUATE_S) + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block, i)), 0)] = getBlockEquationRenormalizedNodeID(block, i); + else + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block, i)), 0)] = getBlockEquationNodeID(block, i); + } + map >, pair >, int> Derivatives = get_Derivatives(block); + map >, pair >, int>::const_iterator it = Derivatives.begin(); + for(int i=0; i<(int)Derivatives.size(); i++) + { + int Deriv_type = it->second; + pair >, pair > it_l(it->first); + it++; + int lag = it_l.first.first; + int eq = it_l.first.second.first; + int var = it_l.first.second.second; + int eqr = it_l.second.first; + int varr = it_l.second.second; + if(Deriv_type == 0) + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = first_derivatives[make_pair(eqr, getDerivID(symbol_table.getID(eEndogenous, varr), lag))]; + else if (Deriv_type == 1) + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = (equation_type_and_normalized_equation[eqr].second)->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + else if (Deriv_type == 2) + { + if(getBlockEquationType(block, eq) == E_EVALUATE_S && eqgetChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + else + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + } + tmp_derivatives.push_back(make_pair(make_pair(eq, var), make_pair(lag, first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))]) )); + } + } + else if( simulation_type==SOLVE_BACKWARD_SIMPLE or simulation_type==SOLVE_FORWARD_SIMPLE + or simulation_type==SOLVE_BACKWARD_COMPLETE or simulation_type==SOLVE_FORWARD_COMPLETE) + { + blocks_derivatives.push_back(t_block_derivatives_equation_variable_laglead_nodeid(0)); + for(int i = 0; i < block_nb_recursives; i++) + { + if (getBlockEquationType(block, i) == E_EVALUATE_S) + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block,i)), 0)] = getBlockEquationRenormalizedNodeID(block, i); + else + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block,i)), 0)] = getBlockEquationNodeID(block, i); + } + for(int eq = block_nb_recursives; eq < block_size; eq++) + { + int eqr = getBlockEquationID(block, eq); + for(int var = block_nb_recursives; var < block_size; var++) + { + int varr = getBlockVariableID(block, var); + NodeID d1 = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), 0), recursive_variables); + if (d1 == Zero) + continue; + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))] = d1; + tmp_derivatives.push_back( + make_pair(make_pair(eq, var),make_pair(0, first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))]))); + } + } + } + blocks_derivatives[block] = tmp_derivatives; + } +} + +void +DynamicModel::collect_block_first_order_derivatives() +{ + //! vector for an equation or a variable indicates the block number + vector equation_2_block, variable_2_block; + unsigned int nb_blocks = getNbBlocks(); + equation_2_block = vector(equation_reordered.size()); + variable_2_block = vector(variable_reordered.size()); + for(unsigned int block = 0; block < nb_blocks; block++) + { + unsigned int block_size = getBlockSize(block); + for(unsigned int i = 0; i < block_size; i++) + { + equation_2_block[getBlockEquationID(block, i)] = block; + variable_2_block[getBlockVariableID(block, i)] = block; + } + } + other_endo_block = vector(nb_blocks); + exo_block = vector(nb_blocks); + exo_det_block = vector(nb_blocks); + derivative_endo = vector(nb_blocks); + derivative_other_endo = vector(nb_blocks); + derivative_exo = vector(nb_blocks); + derivative_exo_det = vector(nb_blocks); + endo_max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + other_endo_max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + exo_max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + exo_det_max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + for (first_derivatives_type::iterator it2 = first_derivatives.begin(); + it2 != first_derivatives.end(); it2++) + { + int eq = it2->first.first; + int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(it2->first.second)); + int lag = getLagByDerivID(it2->first.second); + int block_eq = equation_2_block[eq]; + int block_var = variable_2_block[var]; + t_derivative tmp_derivative ; + t_lag_var lag_var; + switch(getTypeByDerivID(it2->first.second)) + { + case eEndogenous: + if(block_eq == block_var) + { + if(lag<0 && lag<-endo_max_leadlag_block[block_eq].first) + endo_max_leadlag_block[block_eq] = make_pair(-lag, endo_max_leadlag_block[block_eq].second); + if(lag>0 && lag>endo_max_leadlag_block[block_eq].second) + endo_max_leadlag_block[block_eq] = make_pair(endo_max_leadlag_block[block_eq].first, lag); + tmp_derivative = derivative_endo[block_eq]; + tmp_derivative[make_pair(lag, make_pair(eq, var))] = first_derivatives[make_pair(eq, getDerivID(symbol_table.getID(eEndogenous, var), lag))]; + derivative_endo[block_eq] = tmp_derivative; + } + else + { + if(lag<0 && lag<-other_endo_max_leadlag_block[block_eq].first) + other_endo_max_leadlag_block[block_eq] = make_pair(-lag, other_endo_max_leadlag_block[block_eq].second); + if(lag>0 && lag>other_endo_max_leadlag_block[block_eq].second) + other_endo_max_leadlag_block[block_eq] = make_pair(other_endo_max_leadlag_block[block_eq].first, lag); + tmp_derivative = derivative_other_endo[block_eq]; + tmp_derivative[make_pair(lag, make_pair(eq, var))] = first_derivatives[make_pair(eq, getDerivID(symbol_table.getID(eEndogenous, var), lag))]; + derivative_other_endo[block_eq] = tmp_derivative; + lag_var = other_endo_block[block_eq]; + if(lag_var.find(lag) == lag_var.end()) + lag_var[lag].clear(); + lag_var[lag].insert(var); + other_endo_block[block_eq] = lag_var; + } + break; + case eExogenous: + if(lag<0 && lag<-exo_max_leadlag_block[block_eq].first) + exo_max_leadlag_block[block_eq] = make_pair(-lag, exo_max_leadlag_block[block_eq].second); + if(lag>0 && lag>exo_max_leadlag_block[block_eq].second) + exo_max_leadlag_block[block_eq] = make_pair(exo_max_leadlag_block[block_eq].first, lag); + tmp_derivative = derivative_exo[block_eq]; + tmp_derivative[make_pair(lag, make_pair(eq, var))] = first_derivatives[make_pair(eq, getDerivID(symbol_table.getID(eExogenous, var), lag))]; + derivative_exo[block_eq] = tmp_derivative ; + lag_var = exo_block[block_eq]; + if(lag_var.find(lag) == lag_var.end()) + lag_var[lag].clear(); + lag_var[lag].insert(var); + exo_block[block_eq] = lag_var; + break; + case eExogenousDet: + if(lag<0 && lag<-exo_det_max_leadlag_block[block_eq].first) + exo_det_max_leadlag_block[block_eq] = make_pair(-lag, exo_det_max_leadlag_block[block_eq].second); + if(lag>0 && lag>exo_det_max_leadlag_block[block_eq].second) + exo_det_max_leadlag_block[block_eq] = make_pair(exo_det_max_leadlag_block[block_eq].first, lag); + tmp_derivative = derivative_exo_det[block_eq]; + tmp_derivative[make_pair(lag, make_pair(eq, var))] = first_derivatives[make_pair(eq, getDerivID(symbol_table.getID(eExogenous, var), lag))]; + derivative_exo_det[block_eq] = tmp_derivative ; + lag_var = exo_det_block[block_eq]; + if(lag_var.find(lag) == lag_var.end()) + lag_var[lag].clear(); + lag_var[lag].insert(var); + exo_det_block[block_eq] = lag_var; + break; + default: + break; + } + if (lag<0 && lag<-max_leadlag_block[block_eq].first) + max_leadlag_block[block_eq] = make_pair(-lag, max_leadlag_block[block_eq].second); + if (lag>0 && lag>max_leadlag_block[block_eq].second) + max_leadlag_block[block_eq] = make_pair(max_leadlag_block[block_eq].first, lag); + } + +} + void DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode, bool use_dll) const { int r; if(block && bytecode) - { - writeModelEquationsCodeOrdered(basename + "_dynamic", block_triangular.ModelBlock, basename, map_idx); - block_triangular.Free_Block(block_triangular.ModelBlock); - block_triangular.incidencematrix.Free_IM(); - //block_triangular.Free_IM_X(block_triangular.First_IM_X); - } + writeModelEquationsCodeOrdered(basename + "_dynamic", basename, map_idx); else if(block && !bytecode) { #ifdef _WIN32 @@ -2492,9 +2294,6 @@ DynamicModel::writeDynamicFile(const string &basename, bool block, bool bytecode exit(EXIT_FAILURE); } writeSparseDynamicMFile(basename + "_dynamic", basename); - block_triangular.Free_Block(block_triangular.ModelBlock); - block_triangular.incidencematrix.Free_IM(); - //block_triangular.Free_IM_X(block_triangular.First_IM_X); } else if (use_dll) writeDynamicCFile(basename + "_dynamic"); @@ -2521,20 +2320,6 @@ DynamicModel::toStatic(StaticModel &static_model) const static_model.addAuxEquation((*it)->toStatic(static_model)); } -void -DynamicModel::toStaticDll(StaticDllModel &static_model) const - { - // Convert model local variables (need to be done first) - for (map::const_iterator it = local_variables_table.begin(); - it != local_variables_table.end(); it++) - static_model.AddLocalVariable(symbol_table.getName(it->first), it->second->toStatic(static_model)); - - // Convert equations - for (vector::const_iterator it = equations.begin(); - it != equations.end(); it++) - static_model.addEquation((*it)->toStatic(static_model)); - } - void DynamicModel::computeDerivIDs() { @@ -2693,86 +2478,6 @@ DynamicModel::getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDExcepti } -void -DynamicModel::computeChainRuleJacobian(Model_Block *ModelBlock) -{ - map recursive_variables; - first_chain_rule_derivatives.clear(); - for(int blck = 0; blckSize; blck++) - { - recursive_variables.clear(); - if (ModelBlock->Block_List[blck].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - { - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->clear(); - for(int i = 0; i < ModelBlock->Block_List[blck].Nb_Recursives; i++) - { - if (ModelBlock->Block_List[blck].Equation_Type[i] == E_EVALUATE_S) - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - else - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = equations[ModelBlock->Block_List[blck].Equation[i]]; - } - map >, pair >, int> Derivatives = block_triangular.get_Derivatives(ModelBlock, blck); - - map >, pair >, int>::const_iterator it = Derivatives.begin(); - //#pragma omp parallel for shared(it, blck) - for(int i=0; i<(int)Derivatives.size(); i++) - { - int Deriv_type = it->second; - pair >, pair > it_l(it->first); - it++; - int lag = it_l.first.first; - int eq = it_l.first.second.first; - int var = it_l.first.second.second; - int eqr = it_l.second.first; - int varr = it_l.second.second; - if(Deriv_type == 0) - { - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = first_derivatives[make_pair(eqr, getDerivID(symbol_table.getID(eEndogenous, varr), lag))]; - } - else if (Deriv_type == 1) - { - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = ModelBlock->Block_List[blck].Equation_Normalized[eq]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); - } - else if (Deriv_type == 2) - { - if(ModelBlock->Block_List[blck].Equation_Type[eq] == E_EVALUATE_S && eqBlock_List[blck].Nb_Recursives) - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = ModelBlock->Block_List[blck].Equation_Normalized[eq]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); - else - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); - } - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->push_back(make_pair( make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))); - } - } - else if( ModelBlock->Block_List[blck].Simulation_Type==SOLVE_BACKWARD_SIMPLE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_FORWARD_SIMPLE - or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_BACKWARD_COMPLETE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_FORWARD_COMPLETE) - { - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->clear(); - for(int i = 0; i < ModelBlock->Block_List[blck].Nb_Recursives; i++) - { - if (ModelBlock->Block_List[blck].Equation_Type[i] == E_EVALUATE_S) - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - else - recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = equations[ModelBlock->Block_List[blck].Equation[i]]; - } - for(int eq = ModelBlock->Block_List[blck].Nb_Recursives; eq < ModelBlock->Block_List[blck].Size; eq++) - { - int eqr = ModelBlock->Block_List[blck].Equation[eq]; - for(int var = ModelBlock->Block_List[blck].Nb_Recursives; var < ModelBlock->Block_List[blck].Size; var++) - { - int varr = ModelBlock->Block_List[blck].Variable[var]; - NodeID d1 = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), 0), recursive_variables); - if (d1 == Zero) - continue; - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))] = d1; - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->push_back(make_pair( make_pair(0, make_pair(eq, var)), make_pair(eqr, varr))); - } - } - } - } -} - - - void DynamicModel::computeParamsDerivatives() { diff --git a/DynamicModel.hh b/DynamicModel.hh index 8edd7153..be88b45c 100644 --- a/DynamicModel.hh +++ b/DynamicModel.hh @@ -25,8 +25,6 @@ using namespace std; #include #include "StaticModel.hh" -#include "StaticDllModel.hh" -#include "BlockTriangular.hh" //! Stores a dynamic model class DynamicModel : public ModelTree @@ -76,10 +74,15 @@ private: //! Temporary terms for the file containing parameters dervicatives temporary_terms_type params_derivs_temporary_terms; + //! Temporary terms for block decomposed models + vector< vector > v_temporary_terms; + + vector v_temporary_terms_inuse; + + //! Store the derivatives or the chainrule derivatives:map, NodeID> typedef map< pair< int, pair< int, int> >, NodeID> first_chain_rule_derivatives_type; first_chain_rule_derivatives_type first_chain_rule_derivatives; - //! Writes dynamic model file (Matlab version) void writeDynamicMFile(const string &dynamic_basename) const; //! Writes dynamic model file (C version) @@ -91,37 +94,38 @@ private: /*! \todo add third derivatives handling in C output */ void writeDynamicModel(ostream &DynamicOutput, bool use_dll) const; //! Writes the Block reordred structure of the model in M output - void writeModelEquationsOrdered_M(Model_Block *ModelBlock, const string &dynamic_basename) const; + void writeModelEquationsOrdered_M(const string &dynamic_basename) const; //! Writes the code of the Block reordred structure of the model in virtual machine bytecode - void writeModelEquationsCodeOrdered(const string file_name, const Model_Block *ModelBlock, const string bin_basename, map_idx_type map_idx) const; + void writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const; //! Computes jacobian and prepares for equation normalization /*! Using values from initval/endval blocks and parameter initializations: - computes the jacobian for the model w.r. to contemporaneous variables - removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff) */ - void evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic); - void BlockLinear(Model_Block *ModelBlock); + //void evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic); + + //! return a map on the block jacobian + map >, pair >, int> get_Derivatives(int block); + //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables + void computeChainRuleJacobian(t_blocks_derivatives &blocks_derivatives); + string reform(string name) const; map_idx_type map_idx; - //! Build The incidence matrix form the modeltree - void BuildIncidenceMatrix(); - void computeTemporaryTermsOrdered(Model_Block *ModelBlock); + void computeTemporaryTermsOrdered(); //! Write derivative code of an equation w.r. to a variable void compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const; //! Write chain rule derivative code of an equation w.r. to a variable void compileChainRuleDerivative(ofstream &code_file, int eq, int var, int lag, map_idx_type &map_idx) const; //! Get the type corresponding to a derivation ID - SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException); + virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException); //! Get the lag corresponding to a derivation ID - int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException); + virtual 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); + virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException); //! Compute the column indices of the dynamic Jacobian void computeDynJacobianCols(bool jacobianExo); - //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables - void computeChainRuleJacobian(Model_Block *ModelBlock); //! Computes derivatives of the Jacobian w.r. to parameters void computeParamsDerivatives(); //! Computes temporary terms for the file containing parameters derivatives @@ -145,10 +149,50 @@ private: //! Write chain rule derivative of a recursive equation w.r. to a variable void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; + //! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous + void collect_block_first_order_derivatives(); + + //! Factorized code for substitutions of leads/lags /*! \param[in] type determines which type of variables is concerned */ void substituteLeadLagInternal(aux_var_t type); + +private: + //! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true + bool global_temporary_terms; + + //! vector of block reordered variables and equations + vector equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered; + + //! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a NodeID on the new normalized equation + t_equation_type_and_normalized_equation equation_type_and_normalized_equation; + + //! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > > + t_block_type_firstequation_size_mfs block_type_firstequation_size_mfs; + + //! for all blocks derivatives description + t_blocks_derivatives blocks_derivatives; + + //! The jacobian without the elements below the cutoff + dynamic_jacob_map dynamic_jacobian; + + //! Vector indicating if the block is linear in endogenous variable (true) or not (false) + vector blocks_linear; + + //! Map the derivatives for a block pair + typedef map >, NodeID> t_derivative; + //! Vector of derivative for each blocks + vector derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det; + + //!List for each block and for each lag-leag all the other endogenous variables and exogenous variables + typedef set t_var; + typedef map t_lag_var; + vector other_endo_block, exo_block, exo_det_block; + + //!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous + vector > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block; + public: DynamicModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); //! Adds a variable node @@ -179,8 +223,6 @@ public: //! Writes model initialization and lead/lag incidence matrix to output void writeOutput(ostream &output, const string &basename, bool block, bool byte_code, bool use_dll) const; - //! Complete set to block decompose the model - BlockTriangular block_triangular; //! Adds informations for simulation in a binary file void Write_Inf_To_Bin_File(const string &dynamic_basename, const string &bin_basename, const int &num, int &u_count_int, bool &file_open, bool is_two_boundaries) const; @@ -192,14 +234,12 @@ public: /*! It assumes that the static model given in argument has just been allocated */ void toStatic(StaticModel &static_model) const; - void toStaticDll(StaticDllModel &static_model) const; - //! Writes LaTeX file with the equations of the dynamic model void writeLatexFile(const string &basename) const; virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException); virtual int getDynJacobianCol(int deriv_id) const throw (UnknownDerivIDException); - + //! Returns true indicating that this is a dynamic model virtual bool isDynamic() const { return true; }; @@ -225,6 +265,40 @@ public: //! Fills eval context with values of model local variables and auxiliary variables void fillEvalContext(eval_context_type &eval_context) const; + + + //! Return the number of blocks + virtual unsigned int getNbBlocks() const {return(block_type_firstequation_size_mfs.size());}; + //! Determine the simulation type of each block + virtual BlockSimulationType getBlockSimulationType(int block_number) const {return(block_type_firstequation_size_mfs[block_number].first.first);}; + //! Return the first equation number of a block + virtual unsigned int getBlockFirstEquation(int block_number) const {return(block_type_firstequation_size_mfs[block_number].first.second);}; + //! Return the size of the block block_number + virtual unsigned int getBlockSize(int block_number) const {return(block_type_firstequation_size_mfs[block_number].second.first);}; + //! Return the number of feedback variable of the block block_number + virtual unsigned int getBlockMfs(int block_number) const {return(block_type_firstequation_size_mfs[block_number].second.second);}; + //! Return the maximum lag in a block + virtual unsigned int getBlockMaxLag(int block_number) const {return(block_lag_lead[block_number].first);}; + //! Return the maximum lead in a block + virtual unsigned int getBlockMaxLead(int block_number) const {return(block_lag_lead[block_number].second);}; + //! Return the type of equation (equation_number) belonging to the block block_number + virtual EquationType getBlockEquationType(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);}; + //! Return true if the equation has been normalized + virtual bool isBlockEquationRenormalized(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);}; + //! Return the NodeID of the equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationNodeID(int block_number, int equation_number) const {return( equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);}; + //! Return the NodeID of the renormalized equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationRenormalizedNodeID(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);}; + //! Return the original number of equation equation_number belonging to the block block_number + virtual int getBlockEquationID(int block_number, int equation_number) const {return( equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);}; + //! Return the original number of variable variable_number belonging to the block block_number + virtual int getBlockVariableID(int block_number, int variable_number) const {return( variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);}; + //! Return the position of equation_number in the block number belonging to the block block_number + virtual int getBlockInitialEquationID(int block_number, int equation_number) const {return((int)inv_equation_reordered[equation_number] - (int)block_type_firstequation_size_mfs[block_number].first.second);}; + //! Return the position of variable_number in the block number belonging to the block block_number + virtual int getBlockInitialVariableID(int block_number, int variable_number) const {return((int)inv_variable_reordered[variable_number] - (int)block_type_firstequation_size_mfs[block_number].first.second);}; + + }; #endif diff --git a/ExprNode.cc b/ExprNode.cc index 705254e3..820dc9de 100644 --- a/ExprNode.cc +++ b/ExprNode.cc @@ -32,7 +32,6 @@ using namespace __gnu_cxx; #include "ExprNode.hh" #include "DataTree.hh" -#include "BlockTriangular.hh" #include "ModFile.hh" ExprNode::ExprNode(DataTree &datatree_arg) : datatree(datatree_arg), preparedForDerivation(false) @@ -127,9 +126,8 @@ ExprNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector > &v_temporary_terms, + int equation) const { // Nothing to do for a terminal node } @@ -242,18 +240,17 @@ NumConstNode::computeDerivative(int deriv_id) } void -NumConstNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +NumConstNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); } void NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const { - //cout << "writeOutput constante\n"; temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) if (output_type == oMatlabDynamicModelSparse) @@ -427,13 +424,13 @@ VariableNode::computeDerivative(int deriv_id) } void -VariableNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +VariableNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); if (type== eModelLocalVariable) - datatree.local_variables_table[symb_id]->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); + datatree.local_variables_table[symb_id]->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); } void @@ -486,7 +483,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, case eModelLocalVariable: case eModFileLocalVariable: - if (output_type==oMatlabDynamicModelSparse || output_type==oMatlabStaticModelSparse) + if (output_type==oMatlabDynamicModelSparse || output_type==oMatlabStaticModelSparse || output_type == oMatlabDynamicModelSparseLocalTemporaryTerms) { output << "("; datatree.local_variables_table[symb_id]->writeOutput(output, output_type,temporary_terms); @@ -510,6 +507,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type); break; case oMatlabDynamicModelSparse: + case oMatlabDynamicModelSparseLocalTemporaryTerms: i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type); if (lag > 0) output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type); @@ -535,6 +533,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, { case oMatlabDynamicModel: case oMatlabDynamicModelSparse: + case oMatlabDynamicModelSparseLocalTemporaryTerms: if (lag > 0) output << "x(it_+" << lag << ", " << i << ")"; else if (lag < 0) @@ -572,6 +571,7 @@ VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type, { case oMatlabDynamicModel: case oMatlabDynamicModelSparse: + case oMatlabDynamicModelSparseLocalTemporaryTerms: if (lag > 0) output << "x(it_+" << lag << ", " << i << ")"; else if (lag < 0) @@ -695,12 +695,11 @@ VariableNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector > &v_temporary_terms, + int equation) const { if (type== eModelLocalVariable) - datatree.local_variables_table[symb_id]->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); + datatree.local_variables_table[symb_id]->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); } void @@ -1204,9 +1203,8 @@ UnaryOpNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector< vector > &v_temporary_terms, + int equation) const { NodeID this2 = const_cast(this); map::iterator it = reference_count.find(this2); @@ -1214,7 +1212,7 @@ UnaryOpNode::computeTemporaryTerms(map &reference_count, { reference_count[this2] = 1; first_occurence[this2] = make_pair(Curr_block,equation); - arg->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); + arg->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); } else { @@ -1222,19 +1220,19 @@ UnaryOpNode::computeTemporaryTerms(map &reference_count, if (reference_count[this2] * cost(temporary_terms, false) > MIN_COST_C) { temporary_terms.insert(this2); - ModelBlock->Block_List[first_occurence[this2].first].Temporary_Terms_in_Equation[first_occurence[this2].second]->insert(this2); + v_temporary_terms[first_occurence[this2].first][first_occurence[this2].second].insert(this2); } } } void -UnaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +UnaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); else - arg->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); + arg->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); } void @@ -1326,6 +1324,7 @@ UnaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, cerr << "Steady State Operator not implemented for oCDynamicModel." << endl; exit(EXIT_FAILURE); case oMatlabDynamicModelSparse: + case oMatlabDynamicModelSparseLocalTemporaryTerms: cerr << "Steady State Operator not implemented for oMatlabDynamicModelSparse." << endl; exit(EXIT_FAILURE); default: @@ -1989,9 +1988,8 @@ BinaryOpNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector > &v_temporary_terms, + int equation) const { NodeID this2 = const_cast(this); map::iterator it = reference_count.find(this2); @@ -1999,8 +1997,8 @@ BinaryOpNode::computeTemporaryTerms(map &reference_count, { reference_count[this2] = 1; first_occurence[this2] = make_pair(Curr_block, equation); - arg1->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); - arg2->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); + arg1->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); + arg2->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); } else { @@ -2008,7 +2006,7 @@ BinaryOpNode::computeTemporaryTerms(map &reference_count, if (reference_count[this2] * cost(temporary_terms, false) > MIN_COST_C) { temporary_terms.insert(this2); - ModelBlock->Block_List[first_occurence[this2].first].Temporary_Terms_in_Equation[first_occurence[this2].second]->insert(this2); + v_temporary_terms[first_occurence[this2].first][first_occurence[this2].second].insert(this2); } } } @@ -2092,15 +2090,15 @@ BinaryOpNode::compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_ } void -BinaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +BinaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); else { - arg1->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); - arg2->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); + arg1->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); + arg2->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); } } @@ -2109,7 +2107,6 @@ void BinaryOpNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const { - //cout << "writeOutput binary\n"; // If current node is a temporary term temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) @@ -2897,9 +2894,8 @@ TrinaryOpNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector > &v_temporary_terms, + int equation) const { NodeID this2 = const_cast(this); map::iterator it = reference_count.find(this2); @@ -2907,9 +2903,9 @@ TrinaryOpNode::computeTemporaryTerms(map &reference_count, { reference_count[this2] = 1; first_occurence[this2] = make_pair(Curr_block,equation); - arg1->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); - arg2->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); - arg3->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, ModelBlock, equation, map_idx); + arg1->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); + arg2->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); + arg3->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, Curr_block, v_temporary_terms, equation); } else { @@ -2917,7 +2913,7 @@ TrinaryOpNode::computeTemporaryTerms(map &reference_count, if (reference_count[this2] * cost(temporary_terms, false) > MIN_COST_C) { temporary_terms.insert(this2); - ModelBlock->Block_List[first_occurence[this2].first].Temporary_Terms_in_Equation[first_occurence[this2].second]->insert(this2); + v_temporary_terms[first_occurence[this2].first][first_occurence[this2].second].insert(this2); } } } @@ -2972,16 +2968,16 @@ TrinaryOpNode::compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms } void -TrinaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +TrinaryOpNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); else { - arg1->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); - arg2->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); - arg3->collectTemporary_terms(temporary_terms, ModelBlock, Curr_Block); + arg1->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); + arg2->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); + arg3->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block); } } @@ -3206,9 +3202,8 @@ UnknownFunctionNode::computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const + vector< vector > &v_temporary_terms, + int equation) const { cerr << "UnknownFunctionNode::computeTemporaryTerms: not implemented" << endl; exit(EXIT_FAILURE); @@ -3223,11 +3218,11 @@ UnknownFunctionNode::collectVariables(SymbolType type_arg, set > } void -UnknownFunctionNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const +UnknownFunctionNode::collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const { temporary_terms_type::const_iterator it = temporary_terms.find(const_cast(this)); if (it != temporary_terms.end()) - ModelBlock->Block_List[Curr_Block].Temporary_InUse->insert(idx); + temporary_terms_inuse.insert(idx); else { //arg->collectTemporary_terms(temporary_terms, result); diff --git a/ExprNode.hh b/ExprNode.hh index 6349e39d..358687c1 100644 --- a/ExprNode.hh +++ b/ExprNode.hh @@ -44,6 +44,9 @@ struct ExprNodeLess; /*! They are ordered by index number thanks to ExprNodeLess */ typedef set temporary_terms_type; +//! set of temporary terms used in a block +typedef set temporary_terms_inuse_type; + typedef map map_idx_type; //! Type for evaluation contexts @@ -63,7 +66,8 @@ enum ExprNodeOutputType oLatexDynamicModel, //!< LaTeX code, dynamic model declarations oLatexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model steady state declarations oMatlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model steady state declarations - oMatlabDynamicModelSparseSteadyStateOperator //!< Matlab code, dynamic block decomposed mode steady state declarations + oMatlabDynamicModelSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model steady state declarations + oMatlabDynamicModelSparseLocalTemporaryTerms //!< Matlab code, dynamic block decomposed model local temporary_terms }; #define IS_MATLAB(output_type) ((output_type) == oMatlabStaticModel \ @@ -71,6 +75,7 @@ enum ExprNodeOutputType || (output_type) == oMatlabOutsideModel \ || (output_type) == oMatlabStaticModelSparse \ || (output_type) == oMatlabDynamicModelSparse \ + || (output_type) == oMatlabDynamicModelSparseLocalTemporaryTerms \ || (output_type) == oMatlabDynamicSteadyStateOperator \ || (output_type) == oMatlabDynamicModelSparseSteadyStateOperator) @@ -102,7 +107,7 @@ class ExprNode { friend class DataTree; friend class DynamicModel; - friend class StaticDllModel; + friend class StaticModel; friend class ExprNodeLess; friend class NumConstNode; friend class VariableNode; @@ -200,14 +205,13 @@ public: */ virtual void collectModelLocalVariables(set &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const = 0; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const = 0; virtual void computeTemporaryTerms(map &reference_count, temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; + vector< vector > &v_temporary_terms, + int equation) const; class EvalException @@ -245,7 +249,7 @@ public: typedef map subst_table_t; //! Creates auxiliary endo lead variables corresponding to this expression - /*! + /*! If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This expression is assumed to have maximum endogenous lead >= 2 \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added @@ -255,7 +259,7 @@ public: VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector &neweqs) const; //! Creates auxiliary exo lead variables corresponding to this expression - /*! + /*! If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table. \pre This expression is assumed to have maximum exogenous lead >= 1 \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added @@ -332,7 +336,7 @@ public: virtual void prepareForDerivation(); virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; virtual void collectVariables(SymbolType type_arg, set > &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; virtual NodeID toStatic(DataTree &static_datatree) const; @@ -367,10 +371,9 @@ public: temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + vector< vector > &v_temporary_terms, + int equation) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; virtual NodeID toStatic(DataTree &static_datatree) const; @@ -409,11 +412,10 @@ public: temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; + vector< vector > &v_temporary_terms, + int equation) const; virtual void collectVariables(SymbolType type_arg, set > &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; static double eval_opcode(UnaryOpcode op_code, double v) throw (EvalException); virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; @@ -458,11 +460,10 @@ public: temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; + vector< vector > &v_temporary_terms, + int equation) const; virtual void collectVariables(SymbolType type_arg, set > &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; static double eval_opcode(double v1, BinaryOpcode op_code, double v2) throw (EvalException); virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; @@ -511,11 +512,10 @@ public: temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; + vector< vector > &v_temporary_terms, + int equation) const; virtual void collectVariables(SymbolType type_arg, set > &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) throw (EvalException); virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; @@ -552,11 +552,10 @@ public: temporary_terms_type &temporary_terms, map > &first_occurence, int Curr_block, - Model_Block *ModelBlock, - int equation, - map_idx_type &map_idx) const; + vector< vector > &v_temporary_terms, + int equation) const; virtual void collectVariables(SymbolType type_arg, set > &result) const; - virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, Model_Block *ModelBlock, int Curr_Block) const; + virtual void collectTemporary_terms(const temporary_terms_type &temporary_terms, temporary_terms_inuse_type &temporary_terms_inuse, int Curr_Block) const; virtual double eval(const eval_context_type &eval_context) const throw (EvalException); virtual void compile(ostream &CompileCode, bool lhs_rhs, const temporary_terms_type &temporary_terms, map_idx_type &map_idx, bool dynamic, bool steady_dynamic) const; virtual NodeID toStatic(DataTree &static_datatree) const; diff --git a/IncidenceMatrix.cc b/IncidenceMatrix.cc deleted file mode 100644 index f9ce7757..00000000 --- a/IncidenceMatrix.cc +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2007-2009 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#include -#include -#include - -#include "IncidenceMatrix.hh" - - -IncidenceMatrix::IncidenceMatrix(const SymbolTable &symbol_table_arg) : - symbol_table(symbol_table_arg) -{ - Model_Max_Lead = Model_Max_Lead_Endo = Model_Max_Lead_Exo = 0; - Model_Max_Lag = Model_Max_Lag_Endo = Model_Max_Lag_Exo = 0; -} -//------------------------------------------------------------------------------ -//For a lead or a lag build the Incidence Matrix structures -bool* -IncidenceMatrix::Build_IM(int lead_lag, SymbolType type) -{ - int size; - bool *IM; - if(type==eEndogenous) - { - size = symbol_table.endo_nbr() * symbol_table.endo_nbr() * sizeof(IM[0]); - List_IM[lead_lag] = IM = (bool*)malloc(size); - for(int i = 0; i< symbol_table.endo_nbr() * symbol_table.endo_nbr(); i++) IM[i] = 0; - if(lead_lag > 0) - { - if(lead_lag > Model_Max_Lead_Endo) - { - Model_Max_Lead_Endo = lead_lag; - if(lead_lag > Model_Max_Lead) - Model_Max_Lead = lead_lag; - } - } - else - { - if( -lead_lag > Model_Max_Lag_Endo) - { - Model_Max_Lag_Endo = -lead_lag; - if(-lead_lag > Model_Max_Lag) - Model_Max_Lag = -lead_lag; - } - } - } - else - { //eExogenous - size = symbol_table.endo_nbr() * symbol_table.exo_nbr() * sizeof(IM[0]); - List_IM_X[lead_lag] = IM = (bool*)malloc(size); - for(int i = 0; i< symbol_table.endo_nbr() * symbol_table.exo_nbr(); i++) IM[i] = 0; - if(lead_lag > 0) - { - if(lead_lag > Model_Max_Lead_Exo) - { - Model_Max_Lead_Exo = lead_lag; - if(lead_lag > Model_Max_Lead) - Model_Max_Lead = lead_lag; - } - } - else - { - if( -lead_lag > Model_Max_Lag_Exo) - { - Model_Max_Lag_Exo = -lead_lag; - if(-lead_lag > Model_Max_Lag) - Model_Max_Lag = -lead_lag; - } - } - } - return (IM); -} - - -void -IncidenceMatrix::Free_IM() const -{ - IncidenceList::const_iterator it = List_IM.begin(); - for(it = List_IM.begin(); it != List_IM.end(); it++) - free(it->second); - for(it = List_IM_X.begin(); it != List_IM_X.end(); it++) - free(it->second); -} - -//------------------------------------------------------------------------------ -// Return the incidence matrix related to a lead or a lag -bool* -IncidenceMatrix::Get_IM(int lead_lag, SymbolType type) const -{ - IncidenceList::const_iterator it; - if(type==eEndogenous) - { - it = List_IM.find(lead_lag); - if(it!=List_IM.end()) - return(it->second); - else - return(NULL); - } - else //eExogenous - { - it = List_IM_X.find(lead_lag); - if(it!=List_IM_X.end()) - return(it->second); - else - return(NULL); - } -} - - -//------------------------------------------------------------------------------ -// Fill the incidence matrix related to a lead or a lag -void -IncidenceMatrix::fill_IM(int equation, int variable, int lead_lag, SymbolType type) -{ - bool* Cur_IM; - Cur_IM = Get_IM(lead_lag, type); - if(equation >= symbol_table.endo_nbr()) - { - cout << "Error : The model has more equations (at least " << equation + 1 << ") than declared endogenous variables (" << symbol_table.endo_nbr() << ")\n"; - exit(EXIT_FAILURE); - } - if (!Cur_IM) - Cur_IM = Build_IM(lead_lag, type); - if(type==eEndogenous) - Cur_IM[equation*symbol_table.endo_nbr() + variable] = 1; - else - Cur_IM[equation*symbol_table.exo_nbr() + variable] = 1; -} - -//------------------------------------------------------------------------------ -// unFill the incidence matrix related to a lead or a lag -void -IncidenceMatrix::unfill_IM(int equation, int variable, int lead_lag, SymbolType type) -{ - bool* Cur_IM; - Cur_IM = Get_IM(lead_lag, type); - if (!Cur_IM) - Cur_IM = Build_IM(lead_lag, type); - if(type==eEndogenous) - Cur_IM[equation*symbol_table.endo_nbr() + variable] = 0; - else - Cur_IM[equation*symbol_table.exo_nbr() + variable] = 0; -} - - -//------------------------------------------------------------------------------ -//Print azn incidence matrix -void -IncidenceMatrix::Print_SIM(bool* IM, SymbolType type) const -{ - int i, j, n; - if(type == eEndogenous) - n = symbol_table.endo_nbr(); - else - n = symbol_table.exo_nbr(); - for(i = 0;i < symbol_table.endo_nbr();i++) - { - cout << " "; - for(j = 0;j < n;j++) - cout << IM[i*n + j] << " "; - cout << "\n"; - } -} - -//------------------------------------------------------------------------------ -//Print all incidence matrix -void -IncidenceMatrix::Print_IM(SymbolType type) const -{ - IncidenceList::const_iterator it; - cout << "-------------------------------------------------------------------\n"; - if(type == eEndogenous) - for(int k=-Model_Max_Lag_Endo; k <= Model_Max_Lead_Endo; k++) - { - it = List_IM.find(k); - if(it!=List_IM.end()) - { - cout << "Incidence matrix for lead_lag = " << k << "\n"; - Print_SIM(it->second, type); - } - } - else // eExogenous - for(int k=-Model_Max_Lag_Exo; k <= Model_Max_Lead_Exo; k++) - { - it = List_IM_X.find(k); - if(it!=List_IM_X.end()) - { - cout << "Incidence matrix for lead_lag = " << k << "\n"; - Print_SIM(it->second, type); - } - } -} - - -//------------------------------------------------------------------------------ -// Swap rows and columns of the incidence matrix -void -IncidenceMatrix::swap_IM_c(bool *SIM, int pos1, int pos2, int pos3, vector &Index_Var_IM, vector &Index_Equ_IM, int n) const -{ - int tmp_i, j; - bool tmp_b; - /* We exchange equation (row)...*/ - if(pos1 != pos2) - { - tmp_i = Index_Equ_IM[pos1]; - Index_Equ_IM[pos1] = Index_Equ_IM[pos2]; - Index_Equ_IM[pos2] = tmp_i; - for(j = 0;j < n;j++) - { - tmp_b = SIM[pos1 * n + j]; - SIM[pos1*n + j] = SIM[pos2 * n + j]; - SIM[pos2*n + j] = tmp_b; - } - } - /* ...and variables (column)*/ - if(pos1 != pos3) - { - tmp_i = Index_Var_IM[pos1]; - Index_Var_IM[pos1] = Index_Var_IM[pos3]; - Index_Var_IM[pos3] = tmp_i; - for(j = 0;j < n;j++) - { - tmp_b = SIM[j * n + pos1]; - SIM[j*n + pos1] = SIM[j * n + pos3]; - SIM[j*n + pos3] = tmp_b; - } - } -} diff --git a/IncidenceMatrix.hh b/IncidenceMatrix.hh deleted file mode 100644 index 765dd027..00000000 --- a/IncidenceMatrix.hh +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (C) 2007-2008 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#ifndef _INCIDENCEMATRIX_HH -#define _INCIDENCEMATRIX_HH - - -#include -#include "ExprNode.hh" -#include "SymbolTable.hh" - - - - - -//! List of incidence matrix (one matrix per lead/lag) -typedef bool* pbool; -typedef map IncidenceList; - -//! create and manage the incidence matrix -class IncidenceMatrix -{ -public: - const SymbolTable &symbol_table; - IncidenceMatrix(const SymbolTable &symbol_table_arg); - bool* Build_IM(int lead_lag, SymbolType type); - bool* Get_IM(int lead_lag, SymbolType type) const; - void fill_IM(int equation, int variable_endo, int lead_lag, SymbolType type); - void unfill_IM(int equation, int variable_endo, int lead_lag, SymbolType type); - void Free_IM() const; - void Print_IM(SymbolType type) const; - void Print_SIM(bool* IM, SymbolType type) const; - void swap_IM_c(bool *SIM, int pos1, int pos2, int pos3, vector &Index_Var_IM, vector &Index_Equ_IM, int n) const; - int Model_Max_Lead, Model_Max_Lag; - int Model_Max_Lead_Endo, Model_Max_Lag_Endo, Model_Max_Lead_Exo, Model_Max_Lag_Exo; -private: - IncidenceList List_IM, List_IM_X; -}; - - -#endif diff --git a/Makefile.am b/Makefile.am index 87d601d6..643e9909 100644 --- a/Makefile.am +++ b/Makefile.am @@ -16,8 +16,6 @@ dynare_m_SOURCES = \ ModelTree.hh \ StaticModel.cc \ StaticModel.hh \ - StaticDllModel.cc \ - StaticDllModel.hh \ DynamicModel.cc \ DynamicModel.hh \ NumericalConstants.cc \ @@ -44,10 +42,6 @@ dynare_m_SOURCES = \ ExprNode.hh \ MinimumFeedbackSet.cc \ MinimumFeedbackSet.hh \ - IncidenceMatrix.cc \ - IncidenceMatrix.hh \ - BlockTriangular.cc \ - BlockTriangular.hh \ DynareMain.cc \ DynareMain2.cc \ CodeInterpreter.hh \ diff --git a/ModFile.cc b/ModFile.cc index 42c829b8..badbad11 100644 --- a/ModFile.cc +++ b/ModFile.cc @@ -25,7 +25,6 @@ ModFile::ModFile() : expressions_tree(symbol_table, num_constants), static_model(symbol_table, num_constants), - static_dll_model(symbol_table, num_constants), dynamic_model(symbol_table, num_constants), linear(false), block(false), byte_code(false), use_dll(false) @@ -187,16 +186,8 @@ ModFile::computingPass(bool no_tmp_terms) if (dynamic_model.equation_number() > 0) { // Compute static model and its derivatives - if(byte_code) - { - dynamic_model.toStaticDll(static_dll_model); - static_dll_model.computingPass(global_eval_context, no_tmp_terms, block); - } - else - { - dynamic_model.toStatic(static_model); - static_model.computingPass(block, false, no_tmp_terms); - } + dynamic_model.toStatic(static_model); + static_model.computingPass(global_eval_context, no_tmp_terms, false, block); // Set things to compute for dynamic model if (dynamic_model_needed) { @@ -356,22 +347,14 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all InitValStatement *ivs = dynamic_cast(*it); if (ivs != NULL) { - if (!byte_code) - static_model.writeAuxVarInitval(mOutputFile); - else - static_dll_model.writeAuxVarInitval(mOutputFile); + static_model.writeAuxVarInitval(mOutputFile); ivs->writeOutputPostInit(mOutputFile); } // Special treatment for load params and steady state statement: insert initial values for the auxiliary variables LoadParamsAndSteadyStateStatement *lpass = dynamic_cast(*it); if (lpass) - { - if (!byte_code) - static_model.writeAuxVarInitval(mOutputFile); - else - static_dll_model.writeAuxVarInitval(mOutputFile); - } + static_model.writeAuxVarInitval(mOutputFile); } // Remove path for block option with M-files @@ -387,10 +370,8 @@ ModFile::writeOutputFiles(const string &basename, bool clear_all // Create static and dynamic files if (dynamic_model.equation_number() > 0) { - if(byte_code) - static_dll_model.writeStaticFile(basename, block); - else - static_model.writeStaticFile(basename, block); + static_model.writeStaticFile(basename, block, byte_code); + if(dynamic_model_needed) { dynamic_model.writeDynamicFile(basename, block, byte_code, use_dll); diff --git a/ModFile.hh b/ModFile.hh index e7ba4e8d..bf128690 100644 --- a/ModFile.hh +++ b/ModFile.hh @@ -29,7 +29,6 @@ using namespace std; #include "NumericalConstants.hh" #include "NumericalInitialization.hh" #include "StaticModel.hh" -#include "StaticDllModel.hh" #include "DynamicModel.hh" #include "Statement.hh" @@ -45,10 +44,8 @@ public: NumericalConstants num_constants; //! Expressions outside model block DataTree expressions_tree; - //! Static model - StaticModel static_model; //! Static Dll model - StaticDllModel static_dll_model; + StaticModel static_model; //! Dynamic model DynamicModel dynamic_model; //! Option linear diff --git a/ModelTree.cc b/ModelTree.cc index bf8ecb96..91e20582 100644 --- a/ModelTree.cc +++ b/ModelTree.cc @@ -23,6 +23,812 @@ #include #include "ModelTree.hh" +#include "MinimumFeedbackSet.hh" +#include +#include +#include +#include + +using namespace boost; +using namespace MFS; + +void +ModelTree::computeNormalization(const set > &endo_eqs_incidence) throw (NormalizationException) +{ + const int n = equation_number(); + + assert(n == symbol_table.endo_nbr()); + + typedef adjacency_list BipartiteGraph; + + /* + Vertices 0 to n-1 are for endogenous (using type specific ID) + Vertices n to 2*n-1 are for equations (using equation no.) + */ + BipartiteGraph g(2 * n); + + // Fill in the graph + set > endo; + + for(set >::const_iterator it = endo_eqs_incidence.begin(); it != endo_eqs_incidence.end(); it++) + add_edge(it->first + n, it->second, g); + + // Compute maximum cardinality matching + vector mate_map(2*n); + +#if 1 + bool check = checked_edmonds_maximum_cardinality_matching(g, &mate_map[0]); +#else // Alternative way to compute normalization, by giving an initial matching using natural normalizations + fill(mate_map.begin(), mate_map.end(), graph_traits::null_vertex()); + + multimap natural_endo2eqs; + computeNormalizedEquations(natural_endo2eqs); + + for(int i = 0; i < symbol_table.endo_nbr(); i++) + { + if (natural_endo2eqs.count(i) == 0) + continue; + + int j = natural_endo2eqs.find(i)->second; + + put(&mate_map[0], i, n+j); + put(&mate_map[0], n+j, i); + } + + edmonds_augmenting_path_finder::type> augmentor(g, &mate_map[0], get(vertex_index, g)); + bool not_maximum_yet = true; + while(not_maximum_yet) + { + not_maximum_yet = augmentor.augment_matching(); + } + augmentor.get_current_matching(&mate_map[0]); + + bool check = maximum_cardinality_matching_verifier::type>::verify_matching(g, &mate_map[0], get(vertex_index, g)); +#endif + + assert(check); + +#ifdef DEBUG + for(int i = 0; i < n; i++) + cout << "Endogenous " << symbol_table.getName(symbol_table.getID(eEndogenous, i)) + << " matched with equation " << (mate_map[i]-n+1) << endl; +#endif + + // Create the resulting map, by copying the n first elements of mate_map, and substracting n to them + endo2eq.resize(equation_number()); + transform(mate_map.begin(), mate_map.begin() + n, endo2eq.begin(), bind2nd(minus(), n)); + +#ifdef DEBUG + multimap natural_endo2eqs; + computeNormalizedEquations(natural_endo2eqs); + + int n1 = 0, n2 = 0; + + for(int i = 0; i < symbol_table.endo_nbr(); i++) + { + if (natural_endo2eqs.count(i) == 0) + continue; + + n1++; + + pair::const_iterator, multimap::const_iterator> x = natural_endo2eqs.equal_range(i); + if (find_if(x.first, x.second, compose1(bind2nd(equal_to(), endo2eq[i]), select2nd::value_type>())) == x.second) + cout << "Natural normalization of variable " << symbol_table.getName(symbol_table.getID(eEndogenous, i)) + << " not used." << endl; + else + n2++; + } + + cout << "Used " << n2 << " natural normalizations out of " << n1 << ", for a total of " << n << " equations." << endl; +#endif + + // Check if all variables are normalized + vector::const_iterator it = find(mate_map.begin(), mate_map.begin() + n, graph_traits::null_vertex()); + if (it != mate_map.begin() + n) + throw NormalizationException(symbol_table.getID(eEndogenous, it - mate_map.begin())); +} + + +void +ModelTree::computePossiblySingularNormalization(const jacob_map &contemporaneous_jacobian, bool try_symbolic) +{ + cout << "Normalizing the model..." << endl; + + set > endo_eqs_incidence; + + for(jacob_map::const_iterator it = contemporaneous_jacobian.begin(); + it != contemporaneous_jacobian.end(); it++) + endo_eqs_incidence.insert(make_pair(it->first.first, it->first.second)); + + try + { + computeNormalization(endo_eqs_incidence); + return; + } + catch(NormalizationException &e) + { + if (try_symbolic) + cout << "Normalization failed with cutoff, trying symbolic normalization..." << endl; + else + { + cerr << "ERROR: Could not normalize the model. Variable " + << symbol_table.getName(e.symb_id) + << " is not in the maximum cardinality matching. Try to decrease the cutoff." << endl; + exit(EXIT_FAILURE); + } + } + + // If no non-singular normalization can be found, try to find a normalization even with a potential singularity + if (try_symbolic) + { + endo_eqs_incidence.clear(); + set > endo; + for(int i = 0; i < equation_number(); i++) + { + endo.clear(); + equations[i]->collectEndogenous(endo); + for(set >::const_iterator it = endo.begin(); it != endo.end(); it++) + endo_eqs_incidence.insert(make_pair(i, it->first)); + } + + try + { + computeNormalization(endo_eqs_incidence); + } + catch(NormalizationException &e) + { + cerr << "ERROR: Could not normalize the model even with zero cutoff. Variable " + << symbol_table.getName(e.symb_id) + << " is not in the maximum cardinality matching." << endl; + exit(EXIT_FAILURE); + } + } +} + +void +ModelTree::computeNormalizedEquations(multimap &endo2eqs) const +{ + for(int i = 0; i < equation_number(); i++) + { + VariableNode *lhs = dynamic_cast(equations[i]->get_arg1()); + if (lhs == NULL) + continue; + + int symb_id = lhs->get_symb_id(); + if (symbol_table.getType(symb_id) != eEndogenous) + continue; + + set > endo; + equations[i]->get_arg2()->collectEndogenous(endo); + if (endo.find(make_pair(symbol_table.getTypeSpecificID(symb_id), 0)) != endo.end()) + continue; + + endo2eqs.insert(make_pair(symbol_table.getTypeSpecificID(symb_id), i)); + cout << "Endogenous " << symbol_table.getName(symb_id) << " normalized in equation " << (i+1) << endl; + } +} + + +void +ModelTree::evaluateAndReduceJacobian(const eval_context_type &eval_context, jacob_map &contemporaneous_jacobian, jacob_map &static_jacobian, dynamic_jacob_map &dynamic_jacobian, double cutoff, bool verbose) +{ + int nb_elements_contemparenous_Jacobian = 0; + set > jacobian_elements_to_delete; + for (first_derivatives_type::iterator it = first_derivatives.begin(); + it != first_derivatives.end(); it++) + { + int deriv_id = it->first.second; + if (getTypeByDerivID(deriv_id) == eEndogenous) + { + NodeID Id = it->second; + int eq = it->first.first; + int symb = getSymbIDByDerivID(deriv_id); + int var = symbol_table.getTypeSpecificID(symb); + int lag = getLagByDerivID(deriv_id); + double val = 0; + try + { + val = Id->eval(eval_context); + } + catch (ExprNode::EvalException &e) + { + cerr << "ERROR: evaluation of Jacobian failed for equation " << eq+1 << " and variable " << symbol_table.getName(symb) << "(" << lag << ") [" << symb << "] !" << endl; + Id->writeOutput(cerr, oMatlabDynamicModelSparse, temporary_terms); + cerr << endl; + exit(EXIT_FAILURE); + } + + if (fabs(val) < cutoff) + { + if (verbose) + cout << "the coefficient related to variable " << var << " with lag " << lag << " in equation " << eq << " is equal to " << val << " and is set to 0 in the incidence matrix (size=" << symbol_table.endo_nbr() << ")" << endl; + jacobian_elements_to_delete.insert(make_pair(eq, deriv_id)); + } + else + { + if (lag == 0) + { + nb_elements_contemparenous_Jacobian++; + contemporaneous_jacobian[make_pair(eq,var)] = val; + } + if (static_jacobian.find(make_pair(eq, var)) != static_jacobian.end()) + static_jacobian[make_pair(eq, var)] += val; + else + static_jacobian[make_pair(eq, var)] = val; + dynamic_jacobian[make_pair(lag, make_pair(eq, var))] = Id; + } + } + } + + // Get rid of the elements of the Jacobian matrix below the cutoff + for(set >::const_iterator it = jacobian_elements_to_delete.begin(); it != jacobian_elements_to_delete.end(); it++) + first_derivatives.erase(*it); + + if (jacobian_elements_to_delete.size()>0) + { + cout << jacobian_elements_to_delete.size() << " elements among " << first_derivatives.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; + } +} + +void +ModelTree::computePrologueAndEpilogue(jacob_map &static_jacobian_arg, vector &equation_reordered, vector &variable_reordered, unsigned int &prologue, unsigned int &epilogue) +{ + vector eq2endo(equation_number(),0); + equation_reordered.resize(equation_number()); + variable_reordered.resize(equation_number()); + bool *IM; + int n = equation_number(); + IM = (bool*)calloc(n*n,sizeof(bool)); + int i = 0; + for(vector::const_iterator it=endo2eq.begin(); it != endo2eq.end(); it++, i++) + { + eq2endo[*it] = i; + equation_reordered[i] = i; + variable_reordered[*it] = i; + } + for (jacob_map::const_iterator it = static_jacobian_arg.begin(); it != static_jacobian_arg.end(); it ++) + IM[it->first.first * n + endo2eq[it->first.second]] = true; + bool something_has_been_done = true; + prologue = 0; + int k = 0; + // Find the prologue equations and place first the AR(1) shock equations first + while (something_has_been_done) + { + int tmp_prologue = prologue; + something_has_been_done = false; + for(int i = prologue;i < n; i++) + { + int nze = 0; + for(int j = tmp_prologue; j < n; j++) + if(IM[i * n + j]) + { + nze ++; + k = j; + } + if(nze == 1) + { + for(int j = 0; j < n; j++) + { + bool tmp_bool = IM[tmp_prologue * n + j]; + IM[tmp_prologue * n + j] = IM[i * n + j]; + IM[i * n + j] = tmp_bool; + } + int tmp = equation_reordered[tmp_prologue]; + equation_reordered[tmp_prologue] = equation_reordered[i]; + equation_reordered[i] = tmp; + for(int j = 0; j < n; j++) + { + bool tmp_bool = IM[j * n + tmp_prologue]; + IM[j * n + tmp_prologue] = IM[j * n + k]; + IM[j * n + k] = tmp_bool; + } + tmp = variable_reordered[tmp_prologue]; + variable_reordered[tmp_prologue] = variable_reordered[k]; + variable_reordered[k] = tmp; + tmp_prologue++; + something_has_been_done = true; + } + } + prologue = tmp_prologue; + } + + something_has_been_done = true; + epilogue = 0; + // Find the epilogue equations + while (something_has_been_done) + { + int tmp_epilogue = epilogue; + something_has_been_done = false; + for(int i = prologue;i < n - (int) epilogue; i++) + { + int nze = 0; + for(int j = prologue; j < n - tmp_epilogue; j++) + if(IM[j * n + i]) + { + nze ++; + k = j; + } + if(nze == 1) + { + for(int j = 0; j < n; j++) + { + bool tmp_bool = IM[(n - 1 - tmp_epilogue) * n + j]; + IM[(n - 1 - tmp_epilogue) * n + j] = IM[k * n + j]; + IM[k * n + j] = tmp_bool; + } + int tmp = equation_reordered[n - 1 - tmp_epilogue]; + equation_reordered[n - 1 - tmp_epilogue] = equation_reordered[k]; + equation_reordered[k] = tmp; + for(int j = 0; j < n; j++) + { + bool tmp_bool = IM[j * n + n - 1 - tmp_epilogue]; + IM[j * n + n - 1 - tmp_epilogue] = IM[j * n + i]; + IM[j * n + i] = tmp_bool; + } + tmp = variable_reordered[n - 1 - tmp_epilogue]; + variable_reordered[n - 1 - tmp_epilogue] = variable_reordered[i]; + variable_reordered[i] = tmp; + tmp_epilogue++; + something_has_been_done = true; + } + } + epilogue = tmp_epilogue; + } + free(IM); +} + +t_equation_type_and_normalized_equation +ModelTree::equationTypeDetermination(vector &equations, map >, NodeID> &first_order_endo_derivatives, vector &Index_Var_IM, vector &Index_Equ_IM, int mfs) +{ + NodeID lhs, rhs; + ostringstream tmp_output; + BinaryOpNode *eq_node; + ostringstream tmp_s; + temporary_terms_type temporary_terms; + EquationType Equation_Simulation_Type; + t_equation_type_and_normalized_equation V_Equation_Simulation_Type(equations.size()); + for (unsigned int i = 0; i < equations.size(); i++) + { + temporary_terms.clear(); + int eq = Index_Equ_IM[i]; + int var = Index_Var_IM[i]; + eq_node = equations[eq]; + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + Equation_Simulation_Type = E_SOLVE; + tmp_s.str(""); + tmp_output.str(""); + lhs->writeOutput(tmp_output, oMatlabDynamicModelSparse, temporary_terms); + tmp_s << "y(it_, " << Index_Var_IM[i]+1 << ")"; + map >, NodeID>::iterator derivative = first_order_endo_derivatives.find(make_pair(eq, make_pair(var, 0))); + pair res; + if(derivative != first_order_endo_derivatives.end()) + { + set > result; + derivative->second->collectEndogenous(result); + set >::const_iterator d_endo_variable = result.find(make_pair(var, 0)); + //Determine whether the equation could be evaluated rather than to be solved + ostringstream tt(""); + derivative->second->writeOutput(tt, oMatlabDynamicModelSparse, temporary_terms); + if (tmp_output.str() == tmp_s.str() and tt.str()=="1") + { + Equation_Simulation_Type = E_EVALUATE; + } + else + { + vector > > List_of_Op_RHS; + res = equations[eq]->normalizeEquation(var, List_of_Op_RHS); + if(mfs==2) + { + if(d_endo_variable == result.end() && res.second) + Equation_Simulation_Type = E_EVALUATE_S; + } + else if(mfs==3) + { + if(res.second) // The equation could be solved analytically + Equation_Simulation_Type = E_EVALUATE_S; + } + } + } + V_Equation_Simulation_Type[eq] = make_pair(Equation_Simulation_Type, dynamic_cast(res.second)); + } + return (V_Equation_Simulation_Type); +} + +void +ModelTree::getVariableLeadLagByBlock(dynamic_jacob_map &dynamic_jacobian, vector &components_set, int nb_blck_sim, int prologue, int epilogue, t_lag_lead_vector &equation_lead_lag, t_lag_lead_vector &variable_lead_lag, vector equation_reordered, vector variable_reordered) const +{ + int nb_endo = symbol_table.endo_nbr(); + variable_lead_lag = t_lag_lead_vector(nb_endo , make_pair(0,0)); + equation_lead_lag = t_lag_lead_vector(nb_endo , make_pair(0,0)); + vector variable_blck(nb_endo), equation_blck(nb_endo); + for (int i = 0; i < nb_endo; i++) + { + if (i < prologue) + { + variable_blck[variable_reordered[i]] = i; + equation_blck[equation_reordered[i]] = i; + } + else if (i < (int)components_set.size() + prologue) + { + variable_blck[variable_reordered[i]] = components_set[i-prologue] + prologue; + equation_blck[equation_reordered[i]] = components_set[i-prologue] + prologue; + } + else + { + variable_blck[variable_reordered[i]] = i- (nb_endo - nb_blck_sim - prologue - epilogue); + equation_blck[equation_reordered[i]] = i- (nb_endo - nb_blck_sim - prologue - epilogue); + } + } + for (dynamic_jacob_map::const_iterator it = dynamic_jacobian.begin(); it != dynamic_jacobian.end(); it++) + { + int lag = it->first.first; + int j_1 = it->first.second.second; + int i_1 = it->first.second.second; + if (variable_blck[i_1] == equation_blck[j_1]) + { + if (lag > variable_lead_lag[i_1].second) + variable_lead_lag[i_1] = make_pair(variable_lead_lag[i_1].first, lag); + if (lag < -variable_lead_lag[i_1].first) + variable_lead_lag[i_1] = make_pair(-lag, variable_lead_lag[i_1].second); + if (lag > equation_lead_lag[j_1].second) + equation_lead_lag[j_1] = make_pair(equation_lead_lag[j_1].first, lag); + if (lag < -equation_lead_lag[j_1].first) + equation_lead_lag[j_1] = make_pair(-lag, equation_lead_lag[j_1].second); + } + } +} + + +void +ModelTree::computeBlockDecompositionAndFeedbackVariablesForEachBlock(jacob_map &static_jacobian, dynamic_jacob_map &dynamic_jacobian, int prologue, int epilogue, vector &equation_reordered, vector &variable_reordered, vector > &blocks, t_equation_type_and_normalized_equation &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector &inv_equation_reordered, vector &inv_variable_reordered) const +{ + int nb_var = variable_reordered.size(); + int n = nb_var - prologue - epilogue; + typedef adjacency_list DirectedGraph; + + GraphvizDigraph G2(n); + + vector reverse_equation_reordered(nb_var), reverse_variable_reordered(nb_var); + + for(int i=0; ifirst.first]>=prologue && reverse_equation_reordered[it->first.first]first.second]>=prologue && reverse_variable_reordered[it->first.second]first.first != endo2eq[it->first.second]) + add_edge(reverse_equation_reordered[it->first.first]-prologue, reverse_equation_reordered[endo2eq[it->first.second]]-prologue, G2); + + vector endo2block(num_vertices(G2)), discover_time(num_vertices(G2)); + + // Compute strongly connected components + int num = strong_components(G2, &endo2block[0]); + + blocks = vector >(num, make_pair(0, 0)); + + + // Create directed acyclic graph associated to the strongly connected components + typedef adjacency_list DirectedGraph; + DirectedGraph dag(num); + + + for (unsigned int i = 0;i < num_vertices(G2);i++) + { + GraphvizDigraph::out_edge_iterator it_out, out_end; + GraphvizDigraph::vertex_descriptor vi = vertex(i, G2); + for (tie(it_out, out_end) = out_edges(vi, G2); it_out != out_end; ++it_out) + { + int t_b = endo2block[target(*it_out, G2)]; + int s_b = endo2block[source(*it_out, G2)]; + if (s_b != t_b) + add_edge(s_b, t_b, dag); + } + } + + // Compute topological sort of DAG (ordered list of unordered SCC) + deque ordered2unordered; + topological_sort(dag, front_inserter(ordered2unordered)); // We use a front inserter because topological_sort returns the inverse order + + // Construct mapping from unordered SCC to ordered SCC + vector unordered2ordered(num); + for(int i = 0; i < num; i++) + unordered2ordered[ordered2unordered[i]] = i; + + + //This vector contains for each block: + // - first set = equations belonging to the block, + // - second set = the feeback variables, + // - third vector = the reordered non-feedback variables. + vector, pair, vector > > > components_set(num); + for (unsigned int i = 0; i < endo2block.size(); i++) + { + endo2block[i] = unordered2ordered[endo2block[i]]; + blocks[endo2block[i]].first++; + components_set[endo2block[i]].first.insert(i); + } + + t_lag_lead_vector equation_lag_lead, variable_lag_lead; + + getVariableLeadLagByBlock(dynamic_jacobian, endo2block, num, prologue, epilogue, equation_lag_lead, variable_lag_lead, equation_reordered, variable_reordered); + + vector tmp_equation_reordered(equation_reordered), tmp_variable_reordered(variable_reordered); + int order = prologue; + //Add a loop on vertices which could not be normalized or vertices related to lead variables => force those vertices to belong to the feedback set + if(select_feedback_variable) + { + for (int i = 0; i < n; i++) + if (Equation_Type[equation_reordered[i+prologue]].first == E_SOLVE + or variable_lag_lead[variable_reordered[i+prologue]].second > 0 or variable_lag_lead[variable_reordered[i+prologue]].first > 0 + or equation_lag_lead[equation_reordered[i+prologue]].second > 0 or equation_lag_lead[equation_reordered[i+prologue]].first > 0 + or mfs == 0) + add_edge(i, i, G2); + } + else + { + for (int i = 0; i < n; i++) + if (Equation_Type[equation_reordered[i+prologue]].first == E_SOLVE || mfs == 0) + add_edge(i, i, G2); + } + //For each block, the minimum set of feedback variable is computed + // and the non-feedback variables are reordered to get + // a sub-recursive block without feedback variables + + for (int i = 0; i < num; i++) + { + AdjacencyList_type G = GraphvizDigraph_2_AdjacencyList(G2, components_set[i].first); + set feed_back_vertices; + //Print(G); + AdjacencyList_type G1 = Minimal_set_of_feedback_vertex(feed_back_vertices, G); + property_map::type v_index = get(vertex_index, G); + components_set[i].second.first = feed_back_vertices; + blocks[i].second = feed_back_vertices.size(); + vector Reordered_Vertice; + Reorder_the_recursive_variables(G, feed_back_vertices, Reordered_Vertice); + + //First we have the recursive equations conditional on feedback variables + for (vector::iterator its = Reordered_Vertice.begin(); its != Reordered_Vertice.end(); its++) + { + equation_reordered[order] = tmp_equation_reordered[*its+prologue]; + variable_reordered[order] = tmp_variable_reordered[*its+prologue]; + order++; + } + components_set[i].second.second = Reordered_Vertice; + //Second we have the equations related to the feedback variables + for (set::iterator its = feed_back_vertices.begin(); its != feed_back_vertices.end(); its++) + { + equation_reordered[order] = tmp_equation_reordered[v_index[vertex(*its, G)]+prologue]; + variable_reordered[order] = tmp_variable_reordered[v_index[vertex(*its, G)]+prologue]; + order++; + } + } + inv_equation_reordered = vector(nb_var); + inv_variable_reordered = vector(nb_var); + for(int i = 0; i < nb_var ; i++) + { + inv_variable_reordered[variable_reordered[i]] = i; + inv_equation_reordered[equation_reordered[i]] = i; + } +} + +void ModelTree::printBlockDecomposition(vector > blocks) +{ + int largest_block = 0; + int Nb_SimulBlocks = 0; + int Nb_feedback_variable = 0; + unsigned int Nb_TotalBlocks = getNbBlocks(); + for (unsigned int block = 0; block < Nb_TotalBlocks; block++) + { + BlockSimulationType simulation_type = getBlockSimulationType(block); + if (simulation_type == SOLVE_FORWARD_COMPLETE || simulation_type == SOLVE_BACKWARD_COMPLETE || simulation_type == SOLVE_TWO_BOUNDARIES_COMPLETE) + { + Nb_SimulBlocks++; + int size = getBlockSize(block); + if (size > largest_block) + { + largest_block = size; + Nb_feedback_variable = blocks[Nb_SimulBlocks-1].second; + } + } + } + + + int Nb_RecursBlocks = Nb_TotalBlocks - Nb_SimulBlocks; + cout << Nb_TotalBlocks << " block(s) found:" << endl + << " " << Nb_RecursBlocks << " recursive block(s) and " << Nb_SimulBlocks << " simultaneous block(s)." << endl + << " the largest simultaneous block has " << largest_block << " equation(s)" << endl + << " and " << Nb_feedback_variable << " feedback variable(s)." << endl; +} + + + +t_block_type_firstequation_size_mfs +ModelTree::reduceBlocksAndTypeDetermination(dynamic_jacob_map &dynamic_jacobian, int prologue, int epilogue, vector > &blocks, vector &equations, t_equation_type_and_normalized_equation &Equation_Type, vector &variable_reordered, vector &equation_reordered) +{ + int i = 0; + int count_equ = 0, blck_count_simult = 0; + int Blck_Size, MFS_Size; + int Lead, Lag; + t_block_type_firstequation_size_mfs block_type_size_mfs; + BlockSimulationType Simulation_Type, prev_Type = UNKNOWN; + int eq = 0; + for (i = 0; i < prologue+(int) blocks.size()+epilogue; i++) + { + int first_count_equ = count_equ; + if (i < prologue) + { + Blck_Size = 1; + MFS_Size = 1; + } + else if (i < prologue+(int) blocks.size()) + { + Blck_Size = blocks[blck_count_simult].first; + MFS_Size = blocks[blck_count_simult].second; + blck_count_simult++; + } + else if (i < prologue+(int) blocks.size()+epilogue) + { + Blck_Size = 1; + MFS_Size = 1; + } + + Lag = Lead = 0; + set > endo; + for(count_equ = first_count_equ; count_equ < Blck_Size+first_count_equ; count_equ++) + { + endo.clear(); + equations[equation_reordered[count_equ]]->collectEndogenous(endo); + for (set >::const_iterator it = endo.begin(); it != endo.end(); it++) + { + int curr_variable = it->first; + int curr_lag = it->second; + vector::const_iterator it = find(variable_reordered.begin()+first_count_equ, variable_reordered.begin()+(first_count_equ+Blck_Size), curr_variable); + if(it != variable_reordered.begin()+(first_count_equ+Blck_Size)) + if (dynamic_jacobian.find(make_pair(curr_lag, make_pair(equation_reordered[count_equ], curr_variable))) != dynamic_jacobian.end()) + { + if (curr_lag > Lead) + Lead = curr_lag; + else if (-curr_lag > Lag) + Lag = -curr_lag; + } + } + } + if ((Lag > 0) && (Lead > 0)) + { + if (Blck_Size == 1) + Simulation_Type = SOLVE_TWO_BOUNDARIES_SIMPLE; + else + Simulation_Type = SOLVE_TWO_BOUNDARIES_COMPLETE; + } + else if (Blck_Size > 1) + { + if (Lead > 0) + Simulation_Type = SOLVE_BACKWARD_COMPLETE; + else + Simulation_Type = SOLVE_FORWARD_COMPLETE; + } + else + { + if (Lead > 0) + Simulation_Type = SOLVE_BACKWARD_SIMPLE; + else + Simulation_Type = SOLVE_FORWARD_SIMPLE; + } + if (Blck_Size == 1) + { + if (Equation_Type[equation_reordered[eq]].first == E_EVALUATE or Equation_Type[equation_reordered[eq]].first == E_EVALUATE_S) + { + if (Simulation_Type == SOLVE_BACKWARD_SIMPLE) + Simulation_Type = EVALUATE_BACKWARD; + else if (Simulation_Type == SOLVE_FORWARD_SIMPLE) + Simulation_Type = EVALUATE_FORWARD; + } + if (i > 0) + { + if ((prev_Type == EVALUATE_FORWARD and Simulation_Type == EVALUATE_FORWARD) + or (prev_Type == EVALUATE_BACKWARD and Simulation_Type == EVALUATE_BACKWARD)) + { + //merge the current block with the previous one + BlockSimulationType c_Type = (block_type_size_mfs[block_type_size_mfs.size()-1]).first.first; + int c_Size = (block_type_size_mfs[block_type_size_mfs.size()-1]).second.first; + int first_equation = (block_type_size_mfs[block_type_size_mfs.size()-1]).first.second; + block_type_size_mfs[block_type_size_mfs.size()-1] = make_pair(make_pair(c_Type, first_equation), make_pair(++c_Size, block_type_size_mfs[block_type_size_mfs.size()-1].second.second)); + if(block_lag_lead[block_type_size_mfs.size()-1].first > Lag) + Lag = block_lag_lead[block_type_size_mfs.size()-1].first; + if(block_lag_lead[block_type_size_mfs.size()-1].second > Lead) + Lead = block_lag_lead[block_type_size_mfs.size()-1].second; + block_lag_lead[block_type_size_mfs.size()-1] = make_pair(Lag, Lead); + } + else + { + block_type_size_mfs.push_back(make_pair(make_pair(Simulation_Type, eq), make_pair(Blck_Size, MFS_Size))); + block_lag_lead.push_back(make_pair(Lag, Lead)); + } + } + else + { + block_type_size_mfs.push_back(make_pair(make_pair(Simulation_Type, eq), make_pair(Blck_Size, MFS_Size))); + block_lag_lead.push_back(make_pair(Lag, Lead)); + } + } + else + { + block_type_size_mfs.push_back(make_pair(make_pair(Simulation_Type, eq), make_pair(Blck_Size, MFS_Size))); + block_lag_lead.push_back(make_pair(Lag, Lead)); + } + prev_Type = Simulation_Type; + eq += Blck_Size; + } + return (block_type_size_mfs); +} + + +vector +ModelTree::BlockLinear(t_blocks_derivatives &blocks_derivatives, vector &variable_reordered) +{ + unsigned int nb_blocks = getNbBlocks(); + vector blocks_linear(nb_blocks, true); + for (unsigned int block = 0;block < nb_blocks; block++) + { + BlockSimulationType simulation_type = getBlockSimulationType(block); + int block_size = getBlockSize(block); + t_block_derivatives_equation_variable_laglead_nodeid derivatives_block = blocks_derivatives[block]; + int first_variable_position = getBlockFirstEquation(block); + if (simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) + { + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = derivatives_block.begin(); it != derivatives_block.end(); it++) + { + int lag = it->second.first; + if (lag == 0) + { + NodeID Id = it->second.second; + set > endogenous; + Id->collectEndogenous(endogenous); + if (endogenous.size() > 0) + { + for (int l=0;lsecond.first; + NodeID Id = it->second.second;// + set > endogenous; + Id->collectEndogenous(endogenous); + if (endogenous.size() > 0) + { + for (int l=0;l > t_equation_type_and_normalized_equation; + +//! Vector describing variables: max_lag in the block, max_lead in the block +typedef vector > t_lag_lead_vector; + +//! for each block contains pair< pair, pair < Block_Size, Recursive_part_Size > > +typedef vector , pair > > t_block_type_firstequation_size_mfs; + +//! for a block contains derivatives pair< pair , pair > +typedef vector< pair , pair< int, NodeID > > > t_block_derivatives_equation_variable_laglead_nodeid; + +//! for all blocks derivatives description +typedef vector t_blocks_derivatives; + //! Shared code for static and dynamic models class ModelTree : public DataTree { + friend class DynamicModel; + friend class StaticModel; + protected: //! Stores declared and generated auxiliary equations vector equations; @@ -100,6 +119,96 @@ protected: //! Writes LaTeX model file void writeLatexModelFile(const string &filename, ExprNodeOutputType output_type) const; + //! Sparse matrix of double to store the values of the Jacobian + /*! First index is equation number, second index is endogenous type specific ID */ + typedef map, double> jacob_map; + + //! Sparse matrix of double to store the values of the Jacobian + /*! First index is lag, second index is equation number, third index is endogenous type specific ID */ + typedef map >, NodeID> dynamic_jacob_map; + + //! Normalization of equations + /*! Maps endogenous type specific IDs to equation numbers */ + vector endo2eq; + + //! number of equation in the prologue and in the epilogue + unsigned int epilogue, prologue; + + //! for each block contains pair< max_lag, max_lead> + t_lag_lead_vector block_lag_lead; + + //! Exception thrown when normalization fails + class NormalizationException + { + public: + //! A variable missing from the maximum cardinal matching + int symb_id; + NormalizationException(int symb_id_arg) : symb_id(symb_id_arg) { } + }; + + //! Compute the matching between endogenous and variable using the jacobian contemporaneous_jacobian + /*! \param endo_eqs_incidence A set indicating which endogenous appear in which equation. First element of pairs is equation number, second is type specific endo ID */ + void computeNormalization(const set > &endo_eqs_incidence) throw (NormalizationException); + //! Try to compute the matching between endogenous and variable using a decreasing cutoff + /*! applied to the jacobian contemporaneous_jacobian and stop when a matching is found.*/ + /*! if no matching is found with a cutoff close to zero an error message is printout */ + void computePossiblySingularNormalization(const jacob_map &contemporaneous_jacobian, bool try_symbolic); + //! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS) + void computeNormalizedEquations(multimap &endo2eqs) const; + //! Evaluate the jacobian and suppress all the elements below the cutoff + void evaluateAndReduceJacobian(const eval_context_type &eval_context, jacob_map &contemporaneous_jacobian, jacob_map &static_jacobian, dynamic_jacob_map &dynamic_jacobian, double cutoff, bool verbose); + //! Search the equations and variables belonging to the prologue and the epilogue of the model + void computePrologueAndEpilogue(jacob_map &static_jacobian, vector &equation_reordered, vector &variable_reordered, unsigned int &prologue, unsigned int &epilogue); + //! Determine the type of each equation of model and try to normalized the unnormalized equation using computeNormalizedEquations + t_equation_type_and_normalized_equation equationTypeDetermination(vector &equations, map >, NodeID> &first_order_endo_derivatives, vector &Index_Var_IM, vector &Index_Equ_IM, int mfs); + //! Compute the block decomposition and for a non-recusive block find the minimum feedback set + void computeBlockDecompositionAndFeedbackVariablesForEachBlock(jacob_map &static_jacobian, dynamic_jacob_map &dynamic_jacobian, int prologue, int epilogue, vector &Index_Equ_IM, vector &Index_Var_IM, vector > &blocks, t_equation_type_and_normalized_equation &Equation_Type, bool verbose_, bool select_feedback_variable, int mfs, vector &inv_equation_reordered, vector &inv_variable_reordered) const; + //! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block + t_block_type_firstequation_size_mfs reduceBlocksAndTypeDetermination(dynamic_jacob_map &dynamic_jacobian, int prologue, int epilogue, vector > &blocks, vector &equations, t_equation_type_and_normalized_equation &Equation_Type, vector &Index_Var_IM, vector &Index_Equ_IM); + //! Determine the maximum number of lead and lag for the endogenous variable in a bloc + void getVariableLeadLagByBlock(dynamic_jacob_map &dynamic_jacobian, vector &components_set, int nb_blck_sim, int prologue, int epilogue, t_lag_lead_vector &equation_lead_lag, t_lag_lead_vector &variable_lead_lag, vector equation_reordered, vector variable_reordered) const; + //! Print an abstract of the block structure of the model + void printBlockDecomposition(vector > blocks); + //! Determine for each block if it is linear or not + vector BlockLinear(t_blocks_derivatives &blocks_derivatives, vector &variable_reordered); + + + virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException) = 0; + virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException) = 0; + virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException) = 0; + + //! Determine the simulation type of each block + virtual BlockSimulationType getBlockSimulationType(int block_number) const = 0; + //! Return the number of blocks + virtual unsigned int getNbBlocks() const = 0; + //! Return the first equation number of a block + virtual unsigned int getBlockFirstEquation(int block_number) const = 0; + //! Return the size of the block block_number + virtual unsigned int getBlockSize(int block_number) const = 0; + //! Return the number of feedback variable of the block block_number + virtual unsigned int getBlockMfs(int block_number) const = 0; + //! Return the maximum lag in a block + virtual unsigned int getBlockMaxLag(int block_number) const = 0; + //! Return the maximum lead in a block + virtual unsigned int getBlockMaxLead(int block_number) const = 0; + //! Return the type of equation (equation_number) belonging to the block block_number + virtual EquationType getBlockEquationType(int block_number, int equation_number) const = 0; + //! Return true if the equation has been normalized + virtual bool isBlockEquationRenormalized(int block_number, int equation_number) const = 0; + //! Return the NodeID of the equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationNodeID(int block_number, int equation_number) const = 0; + //! Return the NodeID of the renormalized equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationRenormalizedNodeID(int block_number, int equation_number) const = 0; + //! Return the original number of equation equation_number belonging to the block block_number + virtual int getBlockEquationID(int block_number, int equation_number) const = 0; + //! Return the original number of variable variable_number belonging to the block block_number + virtual int getBlockVariableID(int block_number, int variable_number) const = 0; + //! Return the position of equation_number in the block number belonging to the block block_number + virtual int getBlockInitialEquationID(int block_number, int equation_number) const = 0; + //! Return the position of variable_number in the block number belonging to the block block_number + virtual int getBlockInitialVariableID(int block_number, int variable_number) const = 0; + + public: ModelTree(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); //! Declare a node as an equation of the model @@ -110,6 +219,74 @@ public: void addAuxEquation(NodeID eq); //! Returns the number of equations in the model int equation_number() const; + + inline static std::string c_Equation_Type(int type) + { + char c_Equation_Type[4][13]= + { + "E_UNKNOWN ", + "E_EVALUATE ", + "E_EVALUATE_S", + "E_SOLVE " + }; + return(c_Equation_Type[type]); + }; + + inline static std::string BlockType0(BlockType type) + { + switch (type) + { + case SIMULTANS: + return ("SIMULTANEOUS TIME SEPARABLE "); + break; + case PROLOGUE: + return ("PROLOGUE "); + break; + case EPILOGUE: + return ("EPILOGUE "); + break; + case SIMULTAN: + return ("SIMULTANEOUS TIME UNSEPARABLE"); + break; + default: + return ("UNKNOWN "); + break; + } + }; + + inline static std::string BlockSim(int type) + { + switch (type) + { + case EVALUATE_FORWARD: + return ("EVALUATE FORWARD "); + break; + case EVALUATE_BACKWARD: + return ("EVALUATE BACKWARD "); + break; + case SOLVE_FORWARD_SIMPLE: + return ("SOLVE FORWARD SIMPLE "); + break; + case SOLVE_BACKWARD_SIMPLE: + return ("SOLVE BACKWARD SIMPLE "); + break; + case SOLVE_TWO_BOUNDARIES_SIMPLE: + return ("SOLVE TWO BOUNDARIES SIMPLE "); + break; + case SOLVE_FORWARD_COMPLETE: + return ("SOLVE FORWARD COMPLETE "); + break; + case SOLVE_BACKWARD_COMPLETE: + return ("SOLVE BACKWARD COMPLETE "); + break; + case SOLVE_TWO_BOUNDARIES_COMPLETE: + return ("SOLVE TWO BOUNDARIES COMPLETE"); + break; + default: + return ("UNKNOWN "); + break; + } + }; }; #endif diff --git a/ParsingDriver.cc b/ParsingDriver.cc index 95641aef..72b63650 100644 --- a/ParsingDriver.cc +++ b/ParsingDriver.cc @@ -377,7 +377,7 @@ ParsingDriver::cutoff(string *value) { double val = atof(value->c_str()); mod_file->dynamic_model.cutoff = val; - mod_file->static_dll_model.cutoff = val; + mod_file->static_model.cutoff = val; delete value; } @@ -386,7 +386,7 @@ ParsingDriver::mfs(string *value) { int val = atoi(value->c_str()); mod_file->dynamic_model.mfs = val; - mod_file->static_dll_model.mfs = val; + mod_file->static_model.mfs = val; delete value; } @@ -731,9 +731,6 @@ ParsingDriver::option_num(const string &name_option, const string &opt) if (options_list.num_options.find(name_option) != options_list.num_options.end()) error("option " + name_option + " declared twice"); - if ((name_option == "periods") && mod_file->block) - mod_file->dynamic_model.block_triangular.periods = atoi(opt.c_str()); - options_list.num_options[name_option] = opt; } diff --git a/StaticDllModel.cc b/StaticDllModel.cc deleted file mode 100644 index a07bebc8..00000000 --- a/StaticDllModel.cc +++ /dev/null @@ -1,1050 +0,0 @@ -/* - * Copyright (C) 2003-2009 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#include -#include -#include -#include -#include -#include -#include "StaticDllModel.hh" - -// For mkdir() and chdir() -#ifdef _WIN32 -# include -#else -# include -# include -# include -#endif - -StaticDllModel::StaticDllModel(SymbolTable &symbol_table_arg, - NumericalConstants &num_constants_arg) : - ModelTree(symbol_table_arg, num_constants_arg), - cutoff(1e-15), - mfs(0), - block_triangular(symbol_table_arg, num_constants_arg) -{ -} - -void -StaticDllModel::compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const -{ - //first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symb_id, lag))); - //first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, getDerivID(symbol_table.getID(eEndogenous, symb_id), lag))); - first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, symbol_table.getID(eEndogenous, symb_id))); - if (it != first_derivatives.end()) - (it->second)->compile(code_file, false, temporary_terms, map_idx, false, false); - else - { - FLDZ_ fldz; - fldz.write(code_file); - } -} - - -void -StaticDllModel::compileChainRuleDerivative(ofstream &code_file, int eqr, int varr, int lag, map_idx_type &map_idx) const -{ - map >, NodeID>::const_iterator it = first_chain_rule_derivatives.find(make_pair(eqr, make_pair(varr, lag))); - if (it != first_chain_rule_derivatives.end()) - (it->second)->compile(code_file, false, temporary_terms, map_idx, false, false); - else - { - FLDZ_ fldz; - fldz.write(code_file); - } -} - - -void -StaticDllModel::BuildIncidenceMatrix() -{ - set > endogenous, exogenous; - for (int eq = 0; eq < (int) equations.size(); eq++) - { - BinaryOpNode *eq_node = equations[eq]; - endogenous.clear(); - NodeID Id = eq_node->get_arg1(); - Id->collectEndogenous(endogenous); - Id = eq_node->get_arg2(); - Id->collectEndogenous(endogenous); - for (set >::iterator it_endogenous=endogenous.begin();it_endogenous!=endogenous.end();it_endogenous++) - { - block_triangular.incidencematrix.fill_IM(eq, it_endogenous->first, 0, eEndogenous); - } - exogenous.clear(); - Id = eq_node->get_arg1(); - Id->collectExogenous(exogenous); - Id = eq_node->get_arg2(); - Id->collectExogenous(exogenous); - for (set >::iterator it_exogenous=exogenous.begin();it_exogenous!=exogenous.end();it_exogenous++) - { - block_triangular.incidencematrix.fill_IM(eq, it_exogenous->first, 0, eExogenous); - } - } -} - -void -StaticDllModel::computeTemporaryTermsOrdered(Model_Block *ModelBlock) -{ - map > first_occurence; - map reference_count; - int i, j, eqr, varr, lag; - temporary_terms_type vect; - ostringstream tmp_output; - BinaryOpNode *eq_node; - first_derivatives_type::const_iterator it; - first_chain_rule_derivatives_type::const_iterator it_chr; - ostringstream tmp_s; - - temporary_terms.clear(); - map_idx.clear(); - for (j = 0;j < ModelBlock->Size;j++) - { - // Compute the temporary terms reordered - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S && iBlock_List[j].Nb_Recursives && ModelBlock->Block_List[j].Equation_Normalized[i]) - ModelBlock->Block_List[j].Equation_Normalized[i]->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, i, map_idx); - else - { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, i, map_idx); - } - } - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - lag=it.first.first; - int eqr=it.second.first; - int varr=it.second.second; - it_chr=first_chain_rule_derivatives.find(make_pair(eqr, make_pair( varr, lag))); - it_chr->second->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, j, ModelBlock, ModelBlock->Block_List[j].Size-1, map_idx); - } - - } - for (j = 0;j < ModelBlock->Size;j++) - { - // Collecte the temporary terms reordered - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S && iBlock_List[j].Nb_Recursives && ModelBlock->Block_List[j].Equation_Normalized[i]) - ModelBlock->Block_List[j].Equation_Normalized[i]->collectTemporary_terms(temporary_terms, ModelBlock, j); - else - { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - eq_node->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - - } - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - lag=it.first.first; - eqr=it.second.first; - varr=it.second.second; - it_chr=first_chain_rule_derivatives.find(make_pair(eqr, make_pair( varr, lag))); - it_chr->second->collectTemporary_terms(temporary_terms, ModelBlock, j); - } - } - // Add a mapping form node ID to temporary terms order - j=0; - for (temporary_terms_type::const_iterator it = temporary_terms.begin(); - it != temporary_terms.end(); it++) - map_idx[(*it)->idx]=j++; -} - -void -StaticDllModel::writeModelEquationsOrdered_M( Model_Block *ModelBlock, const string &static_basename) const - { - int i,j,k,m; - string tmp_s, sps; - ostringstream tmp_output, tmp1_output, global_output; - NodeID lhs=NULL, rhs=NULL; - BinaryOpNode *eq_node; - map reference_count; - ofstream output; - int nze, nze_exo, nze_other_endo; - vector feedback_variables; - //For each block - for (j = 0;j < ModelBlock->Size;j++) - { - //recursive_variables.clear(); - feedback_variables.clear(); - //For a block composed of a single equation determines wether we have to evaluate or to solve the equation - nze = nze_exo = nze_other_endo = 0; - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - nze+=ModelBlock->Block_List[j].IM_lead_lag[m].size; - tmp1_output.str(""); - tmp1_output << static_basename << "_" << j+1 << ".m"; - output.open(tmp1_output.str().c_str(), ios::out | ios::binary); - output << "%\n"; - output << "% " << tmp1_output.str() << " : Computes static model for Dynare\n"; - output << "%\n"; - output << "% Warning : this file is generated automatically by Dynare\n"; - output << "% from model file (.mod)\n\n"; - output << "%/\n"; - if (ModelBlock->Block_List[j].Simulation_Type==EVALUATE_BACKWARD - ||ModelBlock->Block_List[j].Simulation_Type==EVALUATE_FORWARD) - output << "function y = " << static_basename << "_" << j+1 << "(y, x, params)\n"; - else if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_SIMPLE - || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_SIMPLE) - output << "function [residual, y, g1] = " << static_basename << "_" << j+1 << "(y, x, params)\n"; - output << " % ////////////////////////////////////////////////////////////////////////" << endl - << " % //" << string(" Block ").substr(int(log10(j + 1))) << j + 1 << " " << BlockTriangular::BlockType0(ModelBlock->Block_List[j].Type) - << " //" << endl - << " % // Simulation type " - << BlockTriangular::BlockSim(ModelBlock->Block_List[j].Simulation_Type) << " //" << endl - << " % ////////////////////////////////////////////////////////////////////////" << endl; - //The Temporary terms - if (ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD - && ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) - output << " g1 = spalloc(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives - << ", " << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives << ", " << nze << ");\n"; - - if (ModelBlock->Block_List[j].Temporary_InUse->size()) - { - tmp_output.str(""); - for (temporary_terms_inuse_type::const_iterator it = ModelBlock->Block_List[j].Temporary_InUse->begin(); - it != ModelBlock->Block_List[j].Temporary_InUse->end(); it++) - tmp_output << " T" << *it; - output << " global" << tmp_output.str() << ";\n"; - } - if (ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD && ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) - output << " residual=zeros(" << ModelBlock->Block_List[j].Size-ModelBlock->Block_List[j].Nb_Recursives << ",1);\n"; - // The equations - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - temporary_terms_type tt2; - tt2.clear(); - if (ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->size()) - output << " " << sps << "% //Temporary variables" << endl; - for (temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->begin(); - it != ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->end(); it++) - { - output << " " << sps; - (*it)->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - output << " = "; - (*it)->writeOutput(output, oMatlabStaticModelSparse, tt2); - // Insert current node into tt2 - tt2.insert(*it); - output << ";" << endl; - } - string sModel = symbol_table.getName(symbol_table.getID(eEndogenous, ModelBlock->Block_List[j].Variable[i])) ; - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - tmp_output.str(""); - /*if((ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD or ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) and (iBlock_List[j].Nb_Recursives)) - lhs->writeOutput(tmp_output, oMatlabStaticModelSparse, temporary_terms); - else*/ - lhs->writeOutput(tmp_output, oMatlabStaticModelSparse, temporary_terms); - switch (ModelBlock->Block_List[j].Simulation_Type) - { - case EVALUATE_BACKWARD: - case EVALUATE_FORWARD: -evaluation: if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - output << " % equation " << ModelBlock->Block_List[j].Equation[i]+1 << " variable : " << sModel - << " (" << ModelBlock->Block_List[j].Variable[i]+1 << ") " << block_triangular.c_Equation_Type(ModelBlock->Block_List[j].Equation_Type[i]) << endl; - output << " "; - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE) - { - output << tmp_output.str(); - output << " = "; - rhs->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - } - else if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - { - output << "%" << tmp_output.str(); - output << " = "; - if (ModelBlock->Block_List[j].Equation_Normalized[i]) - { - rhs->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - output << "\n "; - tmp_output.str(""); - eq_node = (BinaryOpNode *)ModelBlock->Block_List[j].Equation_Normalized[i]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - lhs->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - output << " = "; - rhs->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - } - } - else - { - cerr << "Type missmatch for equation " << ModelBlock->Block_List[j].Equation[i]+1 << "\n"; - exit(EXIT_FAILURE); - } - output << ";\n"; - break; - case SOLVE_BACKWARD_SIMPLE: - case SOLVE_FORWARD_SIMPLE: - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - if (iBlock_List[j].Nb_Recursives) - goto evaluation; - feedback_variables.push_back(ModelBlock->Block_List[j].Variable[i]); - output << " % equation " << ModelBlock->Block_List[j].Equation[i]+1 << " variable : " << sModel - << " (" << ModelBlock->Block_List[j].Variable[i]+1 << ") " << block_triangular.c_Equation_Type(ModelBlock->Block_List[j].Equation_Type[i]) << endl; - output << " " << "residual(" << i+1-ModelBlock->Block_List[j].Nb_Recursives << ") = ("; - goto end; - default: -end: - output << tmp_output.str(); - output << ") - ("; - rhs->writeOutput(output, oMatlabStaticModelSparse, temporary_terms); - output << ");\n"; - } - } - // The Jacobian if we have to solve the block - output << " " << sps << "% Jacobian " << endl; - switch (ModelBlock->Block_List[j].Simulation_Type) - { - case EVALUATE_BACKWARD: - case EVALUATE_FORWARD: - break; - case SOLVE_BACKWARD_SIMPLE: - case SOLVE_FORWARD_SIMPLE: - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - k=it.first.first; - int eq=it.first.second.first; - int var=it.first.second.second; - int eqr=it.second.first; - int varr=it.second.second; - output << " g1(" << eq+1-ModelBlock->Block_List[j].Nb_Recursives << ", " - << var+1-ModelBlock->Block_List[j].Nb_Recursives << ") = "; - writeChainRuleDerivative(output, eqr, varr, k, oMatlabStaticModelSparse, temporary_terms); - output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) - << " " << varr+1 << ", equation=" << eqr+1 << endl; - } - break; - default: - break; - } - output.close(); - } - } - -void -StaticDllModel::writeModelEquationsCodeOrdered(const string file_name, const Model_Block *ModelBlock, const string bin_basename, map_idx_type map_idx) const - { - struct Uff_l - { - int u, var, lag; - Uff_l *pNext; - }; - - struct Uff - { - Uff_l *Ufl, *Ufl_First; - }; - - int i,j,k,v; - string tmp_s; - ostringstream tmp_output; - ofstream code_file; - NodeID lhs=NULL, rhs=NULL; - BinaryOpNode *eq_node; - Uff Uf[symbol_table.endo_nbr()]; - map reference_count; - vector feedback_variables; - bool file_open=false; - string main_name=file_name; - main_name+=".cod"; - code_file.open(main_name.c_str(), ios::out | ios::binary | ios::ate ); - if (!code_file.is_open()) - { - cout << "Error : Can't open file \"" << main_name << "\" for writing\n"; - exit(EXIT_FAILURE); - } - //Temporary variables declaration - FDIMT_ fdimt(temporary_terms.size()); - fdimt.write(code_file); - - for (j = 0; j < ModelBlock->Size ;j++) - { - feedback_variables.clear(); - if (j>0) - { - FENDBLOCK_ fendblock; - fendblock.write(code_file); - } - int count_u; - - int u_count_int=0; - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE) - { - Write_Inf_To_Bin_File(file_name, bin_basename, j, u_count_int,file_open); - file_open=true; - } - - FBEGINBLOCK_ fbeginblock(ModelBlock->Block_List[j].Size - ModelBlock->Block_List[j].Nb_Recursives, - ModelBlock->Block_List[j].Simulation_Type, - ModelBlock->Block_List[j].Variable, - ModelBlock->Block_List[j].Equation, - ModelBlock->Block_List[j].Own_Derivative, - ModelBlock->Block_List[j].is_linear, - symbol_table.endo_nbr(), - 0, - 0, - u_count_int - ); - fbeginblock.write(code_file); - // The equations - //cout << block_triangular.BlockSim(ModelBlock->Block_List[j].Simulation_Type) << " j=" << j << endl; - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - //The Temporary terms - temporary_terms_type tt2; - tt2.clear(); - for (temporary_terms_type::const_iterator it = ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->begin(); - it != ModelBlock->Block_List[j].Temporary_Terms_in_Equation[i]->end(); it++) - { - (*it)->compile(code_file, false, tt2, map_idx, false, false); - FSTPST_ fstpst((int)(map_idx.find((*it)->idx))->second); - fstpst.write(code_file); - // Insert current node into tt2 - tt2.insert(*it); - } - switch (ModelBlock->Block_List[j].Simulation_Type) - { -evaluation: - case EVALUATE_BACKWARD: - case EVALUATE_FORWARD: - if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE) - { - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - rhs->compile(code_file, false, temporary_terms, map_idx, false, false); - lhs->compile(code_file, true, temporary_terms, map_idx, false, false); - } - else if (ModelBlock->Block_List[j].Equation_Type[i] == E_EVALUATE_S) - { - eq_node = (BinaryOpNode*)ModelBlock->Block_List[j].Equation_Normalized[i]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - rhs->compile(code_file, false, temporary_terms, map_idx, false, false); - lhs->compile(code_file, true, temporary_terms, map_idx, false, false); - } - break; - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - if (iBlock_List[j].Nb_Recursives) - goto evaluation; - feedback_variables.push_back(ModelBlock->Block_List[j].Variable[i]); - v=ModelBlock->Block_List[j].Equation[i]; - Uf[v].Ufl=NULL; - goto end; - default: -end: - eq_node = equations[ModelBlock->Block_List[j].Equation[i]]; - lhs = eq_node->get_arg1(); - rhs = eq_node->get_arg2(); - lhs->compile(code_file, false, temporary_terms, map_idx, false, false); - rhs->compile(code_file, false, temporary_terms, map_idx, false, false); - FBINARY_ fbinary(oMinus); - fbinary.write(code_file); - - FSTPR_ fstpr(i - ModelBlock->Block_List[j].Nb_Recursives); - fstpr.write(code_file); - } - } - FENDEQU_ fendequ; - fendequ.write(code_file); - //code_file.write(&FENDEQU, sizeof(FENDEQU)); - // The Jacobian if we have to solve the block - if (ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_BACKWARD - && ModelBlock->Block_List[j].Simulation_Type!=EVALUATE_FORWARD) - { - switch (ModelBlock->Block_List[j].Simulation_Type) - { - case SOLVE_BACKWARD_SIMPLE: - case SOLVE_FORWARD_SIMPLE: - compileDerivative(code_file, ModelBlock->Block_List[j].Equation[0], ModelBlock->Block_List[j].Variable[0], 0, map_idx); - { - FSTPG_ fstpg; - fstpg.write(code_file); - } - break; - - case SOLVE_BACKWARD_COMPLETE: - case SOLVE_FORWARD_COMPLETE: - count_u = feedback_variables.size(); - for(i=0; i<(int)ModelBlock->Block_List[j].Chain_Rule_Derivatives->size();i++) - { - pair< pair >, pair > it = ModelBlock->Block_List[j].Chain_Rule_Derivatives->at(i); - k=it.first.first; - int eq=it.first.second.first; - int var=it.first.second.second; - int eqr=it.second.first; - int varr=it.second.second; - int v=ModelBlock->Block_List[j].Equation[eq]; - if(eq>=ModelBlock->Block_List[j].Nb_Recursives and var>=ModelBlock->Block_List[j].Nb_Recursives) - { - if (!Uf[v].Ufl) - { - Uf[v].Ufl=(Uff_l*)malloc(sizeof(Uff_l)); - Uf[v].Ufl_First=Uf[v].Ufl; - } - else - { - Uf[v].Ufl->pNext=(Uff_l*)malloc(sizeof(Uff_l)); - Uf[v].Ufl=Uf[v].Ufl->pNext; - } - Uf[v].Ufl->pNext=NULL; - Uf[v].Ufl->u=count_u; - Uf[v].Ufl->var=varr; - Uf[v].Ufl->lag=k; - compileChainRuleDerivative(code_file, eqr, varr, k, map_idx); - FSTPSU_ fstpsu(count_u); - fstpsu.write(code_file); - count_u++; - } - } - for (i = 0;i < ModelBlock->Block_List[j].Size;i++) - { - if(i>=ModelBlock->Block_List[j].Nb_Recursives) - { - FLDR_ fldr(i-ModelBlock->Block_List[j].Nb_Recursives); - fldr.write(code_file); - - FLDZ_ fldz; - fldz.write(code_file); - - v=ModelBlock->Block_List[j].Equation[i]; - for (Uf[v].Ufl=Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl=Uf[v].Ufl->pNext) - { - FLDSU_ fldsu(Uf[v].Ufl->u); - fldsu.write(code_file); - FLDSV_ fldsv(eEndogenous, Uf[v].Ufl->var); - fldsv.write(code_file); - - FBINARY_ fbinary(oTimes); - fbinary.write(code_file); - - FCUML_ fcuml; - fcuml.write(code_file); - } - Uf[v].Ufl=Uf[v].Ufl_First; - while (Uf[v].Ufl) - { - Uf[v].Ufl_First=Uf[v].Ufl->pNext; - free(Uf[v].Ufl); - Uf[v].Ufl=Uf[v].Ufl_First; - } - FBINARY_ fbinary(oMinus); - fbinary.write(code_file); - FSTPSU_ fstpsu(i - ModelBlock->Block_List[j].Nb_Recursives); - fstpsu.write(code_file); - } - } - break; - default: - break; - } - } - } - FENDBLOCK_ fendblock; - fendblock.write(code_file); - FEND_ fend; - fend.write(code_file); - code_file.close(); - } - - - -void -StaticDllModel::Write_Inf_To_Bin_File(const string &static_basename, const string &bin_basename, const int &num, - int &u_count_int, bool &file_open) const - { - int j; - std::ofstream SaveCode; - if (file_open) - SaveCode.open((bin_basename + "_static.bin").c_str(), ios::out | ios::in | ios::binary | ios ::ate ); - else - SaveCode.open((bin_basename + "_static.bin").c_str(), ios::out | ios::binary); - if (!SaveCode.is_open()) - { - cout << "Error : Can't open file \"" << bin_basename << "_static.bin\" for writing\n"; - exit(EXIT_FAILURE); - } - u_count_int=0; - int Size = block_triangular.ModelBlock->Block_List[num].Size - block_triangular.ModelBlock->Block_List[num].Nb_Recursives; - for(int i=0; i<(int)block_triangular.ModelBlock->Block_List[num].Chain_Rule_Derivatives->size();i++) - { - //Chain_Rule_Derivatives.insert(make_pair( make_pair(eq, eqr), make_pair(var, make_pair(varr, lag)))); - pair< pair >, pair > it = block_triangular.ModelBlock->Block_List[num].Chain_Rule_Derivatives->at(i); - int k=it.first.first; - int eq=it.first.second.first; - - int var_init=it.first.second.second; - /*int eqr=it.second.first; - int varr=it.second.second;*/ - if(eq>=block_triangular.ModelBlock->Block_List[num].Nb_Recursives and var_init>=block_triangular.ModelBlock->Block_List[num].Nb_Recursives) - { - int v=eq-block_triangular.ModelBlock->Block_List[num].Nb_Recursives; - SaveCode.write(reinterpret_cast(&v), sizeof(v)); - int var=it.first.second.second-block_triangular.ModelBlock->Block_List[num].Nb_Recursives + k * Size; - SaveCode.write(reinterpret_cast(&var), sizeof(var)); - SaveCode.write(reinterpret_cast(&k), sizeof(k)); - int u = u_count_int + Size; - SaveCode.write(reinterpret_cast(&u), sizeof(u)); - //cout << "eq=" << v << ", var=" << var << ", lag=" << k << " u=" << u << "\n"; - u_count_int++; - } - } - /*cout << "u_count_int=" << u_count_int << endl; - cout << "block_triangular.ModelBlock->Block_List[" << num << "].Nb_Recursives=" << block_triangular.ModelBlock->Block_List[num].Nb_Recursives << " block_triangular.ModelBlock->Block_List[" << num << "].Size=" << block_triangular.ModelBlock->Block_List[num].Size << endl;*/ - for (j=block_triangular.ModelBlock->Block_List[num].Nb_Recursives;jBlock_List[num].Size;j++) - { - int varr=block_triangular.ModelBlock->Block_List[num].Variable[j]; - //cout << "j=" << j << " varr=" << varr << "\n"; - SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); - } - for (j=block_triangular.ModelBlock->Block_List[num].Nb_Recursives;jBlock_List[num].Size;j++) - { - int eqr1=block_triangular.ModelBlock->Block_List[num].Equation[j]; - SaveCode.write(reinterpret_cast(&eqr1), sizeof(eqr1)); - } - SaveCode.close(); - } - - -void -StaticDllModel::evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic) -{ - int i=0; - int j=0; - bool *IM=NULL; - int a_variable_lag=-9999; - for (first_derivatives_type::iterator it = first_derivatives.begin(); - it != first_derivatives.end(); it++) - { - //cout << "it->first.second=" << it->first.second << " variable_table.getSymbolID(it->first.second)=" << variable_table.getSymbolID(it->first.second) << " Type=" << variable_table.getType(it->first.second) << " eEndogenous=" << eEndogenous << " eExogenous=" << eExogenous << " variable_table.getLag(it->first.second)=" << variable_table.getLag(it->first.second) << "\n"; - /*if (getTypeByDerivID(it->first.second) == eEndogenous) - {*/ - NodeID Id = it->second; - double val = 0; - try - { - val = Id->eval(eval_context); - } - catch (ExprNode::EvalException &e) - { - //cout << "evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(getSymbIDByDerivID(it->first.second)) << "(" << getLagByDerivID(it->first.second) << ") [" << getSymbIDByDerivID(it->first.second) << "] !" << endl; - cout << "evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(it->first.second) << "(" << 0 << ") [" << it->first.second << "] !" << endl; - Id->writeOutput(cout, oMatlabStaticModelSparse, temporary_terms); - cout << "\n"; - //cerr << "StaticDllModel::evaluateJacobian: evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(getSymbIDByDerivID(it->first.second)) << "(" << getLagByDerivID(it->first.second) << ")!" << endl; - cerr << "StaticDllModel::evaluateJacobian: evaluation of Jacobian failed for equation " << it->first.first+1 << " and variable " << symbol_table.getName(it->first.second) << "(" << 0 << ")!" << endl; - } - int eq=it->first.first; - //int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(it->first.second));///symbol_table.getID(eEndogenous,it->first.second);//variable_table.getSymbolID(it->first.second); - int var = symbol_table.getTypeSpecificID(it->first.second);///symbol_table.getID(eEndogenous,it->first.second);//variable_table.getSymbolID(it->first.second); - int k1 = 0;//getLagByDerivID(it->first.second); - if (a_variable_lag!=k1) - { - IM=block_triangular.incidencematrix.Get_IM(k1, eEndogenous); - a_variable_lag=k1; - } - if (k1==0 or !dynamic) - { - j++; - (*j_m)[make_pair(eq,var)]+=val; - } - /*if (IM[eq*symbol_table.endo_nbr()+var] && (fabs(val) < cutoff)) - { - //if (block_triangular.bt_verbose) - cout << "the coefficient related to variable " << var << " with lag " << k1 << " in equation " << eq << " is equal to " << val << " and is set to 0 in the incidence matrix (size=" << symbol_table.endo_nbr() << ")\n"; - block_triangular.incidencematrix.unfill_IM(eq, var, k1, eEndogenous); - i++; - }*/ - /*}*/ - } - //Get ride of the elements of the incidence matrix equal to Zero - IM=block_triangular.incidencematrix.Get_IM(0, eEndogenous); - /*for (int i=0;i0) - { - cout << i << " elements among " << first_derivatives.size() << " in the incidence matrices are below the cutoff (" << cutoff << ") and are discarded\n"; - cout << "the contemporaneous incidence matrix has " << j << " elements\n"; - } -} - -void -StaticDllModel::BlockLinear(Model_Block *ModelBlock) -{ - int i,j,l,m,ll; - for (j = 0;j < ModelBlock->Size;j++) - { - if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_BACKWARD_COMPLETE || - ModelBlock->Block_List[j].Simulation_Type==SOLVE_FORWARD_COMPLETE) - { - ll=ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[ll].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[ll].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[ll].Var_Index[i]; - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,variable_table.getID(var,0))); - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var),0))); - first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,symbol_table.getID(eEndogenous, var))); - if (it!= first_derivatives.end()) - { - NodeID Id = it->second; - set > endogenous; - Id->collectEndogenous(endogenous); - if (endogenous.size() > 0) - { - for (l=0;lBlock_List[j].Size;l++) - { - if (endogenous.find(make_pair(ModelBlock->Block_List[j].Variable[l], 0)) != endogenous.end()) - { - ModelBlock->Block_List[j].is_linear=false; - goto follow; - } - } - } - } - } - } - else if (ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE || ModelBlock->Block_List[j].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - { - for (m=0;m<=ModelBlock->Block_List[j].Max_Lead+ModelBlock->Block_List[j].Max_Lag;m++) - { - int k1=m-ModelBlock->Block_List[j].Max_Lag; - for (i=0;iBlock_List[j].IM_lead_lag[m].size;i++) - { - int eq=ModelBlock->Block_List[j].IM_lead_lag[m].Equ_Index[i]; - int var=ModelBlock->Block_List[j].IM_lead_lag[m].Var_Index[i]; - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,variable_table.getID(var,k1))); - //first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,getDerivID(symbol_table.getID(eEndogenous, var),k1))); - first_derivatives_type::const_iterator it=first_derivatives.find(make_pair(eq,symbol_table.getID(eEndogenous, var))); - NodeID Id = it->second; - if (it!= first_derivatives.end()) - { - set > endogenous; - Id->collectEndogenous(endogenous); - if (endogenous.size() > 0) - { - for (l=0;lBlock_List[j].Size;l++) - { - if (endogenous.find(make_pair(ModelBlock->Block_List[j].Variable[l], k1)) != endogenous.end()) - { - ModelBlock->Block_List[j].is_linear=false; - goto follow; - } - } - } - } - } - } - } -follow: - i=0; - } -} - - -map >, NodeID> -StaticDllModel::collect_first_order_derivatives_endogenous() -{ - map >, NodeID> endo_derivatives; - for (first_derivatives_type::iterator it2 = first_derivatives.begin(); - it2 != first_derivatives.end(); it2++) - { - //if (getTypeByDerivID(it2->first.second)==eEndogenous) - /*if (it2->first.second)==eEndogenous) - {*/ - int eq = it2->first.first; - //int var=symbol_table.getTypeSpecificID(getSymbIDByDerivID(it2->first.second)); - int var=symbol_table.getTypeSpecificID(it2->first.second); - //int lag=getLagByDerivID(it2->first.second); - int lag = 0; - //if (lag==0) - endo_derivatives[make_pair(eq, make_pair(var, lag))] = it2->second; - //} - } - return endo_derivatives; -} - - - -void -StaticDllModel::computingPass(const eval_context_type &eval_context, bool no_tmp_terms, bool block) -{ - assert(block); - - // Compute derivatives w.r. to all endogenous, and possibly exogenous and exogenous deterministic - set vars; - /*for (deriv_id_table_t::const_iterator it = deriv_id_table.begin(); - it != deriv_id_table.end(); it++) - { - SymbolType type = symbol_table.getType(it->first.first); - if (type == eEndogenous) - vars.insert(it->second); - }*/ - for(int i = 0; i < symbol_table.endo_nbr(); i++) - vars.insert(symbol_table.getID(eEndogenous, i)); - - // Launch computations - cout << "Computing static model derivatives:" << endl - << " - order 1" << endl; - computeJacobian(vars); - //cout << "mode=" << mode << " eSparseDLLMode=" << eSparseDLLMode << " eSparseMode=" << eSparseMode << "\n"; - BuildIncidenceMatrix(); - - - jacob_map j_m; - evaluateJacobian(eval_context, &j_m, true); - - if (block_triangular.bt_verbose) - { - cout << "The gross incidence matrix \n"; - block_triangular.incidencematrix.Print_IM(eEndogenous); - } - t_etype equation_simulation_type; - map >, NodeID> first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); - - block_triangular.Normalize_and_BlockDecompose_Static_0_Model(j_m, equations, equation_simulation_type, first_order_endo_derivatives, mfs, cutoff); - /*for (int j = 0;j < block_triangular.ModelBlock->Size;j++) - { - for (int i = 0;i < block_triangular.ModelBlock->Block_List[j].Size;i++) - { - if (iBlock_List[j].Nb_Recursives ) - cout << "block=" << j << " R i=" << i << " equation=" << block_triangular.ModelBlock->Block_List[j].Equation[i]+1 << " variable=" << block_triangular.ModelBlock->Block_List[j].Variable[i]+1 << endl; - else - cout << "block=" << j << " S i=" << i << " equation=" << block_triangular.ModelBlock->Block_List[j].Equation[i]+1 << " variable=" << block_triangular.ModelBlock->Block_List[j].Variable[i]+1 << endl; - } - }*/ - - BlockLinear(block_triangular.ModelBlock); - - computeChainRuleJacobian(block_triangular.ModelBlock); - - if (!no_tmp_terms) - computeTemporaryTermsOrdered(block_triangular.ModelBlock); - -} - -void -StaticDllModel::writeStaticFile(const string &basename, bool block) const - { - int r; - - assert(block); - -#ifdef _WIN32 - r = mkdir(basename.c_str()); -#else - r = mkdir(basename.c_str(), 0777); -#endif - if (r < 0 && errno != EEXIST) - { - perror("ERROR"); - exit(EXIT_FAILURE); - } - writeModelEquationsCodeOrdered(basename + "_static", block_triangular.ModelBlock, basename, map_idx); - block_triangular.Free_Block(block_triangular.ModelBlock); - block_triangular.incidencematrix.Free_IM(); - } - -SymbolType -StaticDllModel::getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException) -{ - return symbol_table.getType(getSymbIDByDerivID(deriv_id)); -} - -int -StaticDllModel::getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException) -{ - if (deriv_id < 0 || deriv_id >= (int) inv_deriv_id_table.size()) - throw UnknownDerivIDException(); - - return inv_deriv_id_table[deriv_id].second; -} - -int -StaticDllModel::getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException) -{ - if (deriv_id < 0 || deriv_id >= (int) inv_deriv_id_table.size()) - throw UnknownDerivIDException(); - - return inv_deriv_id_table[deriv_id].first; -} - -int -StaticDllModel::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException) -{ - if (symbol_table.getType(symb_id) == eEndogenous) - return symb_id; - else - return -1; -} - -void -StaticDllModel::computeChainRuleJacobian(Model_Block *ModelBlock) -{ - map recursive_variables; - first_chain_rule_derivatives.clear(); - for(int blck = 0; blckSize; blck++) - { - recursive_variables.clear(); - if (ModelBlock->Block_List[blck].Simulation_Type==SOLVE_TWO_BOUNDARIES_COMPLETE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_TWO_BOUNDARIES_SIMPLE) - { - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->clear(); - for(int i = 0; i < ModelBlock->Block_List[blck].Nb_Recursives; i++) - { - if (ModelBlock->Block_List[blck].Equation_Type[i] == E_EVALUATE_S) - //recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - recursive_variables[symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i])] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - else - //recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = equations[ModelBlock->Block_List[blck].Equation[i]]; - recursive_variables[symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i])] = equations[ModelBlock->Block_List[blck].Equation[i]]; - } - map >, pair >, int> Derivatives = block_triangular.get_Derivatives(ModelBlock, blck); - - map >, pair >, int>::const_iterator it = Derivatives.begin(); - //#pragma omp parallel for shared(it, blck) - for(int i=0; i<(int)Derivatives.size(); i++) - { - int Deriv_type = it->second; - pair >, pair > it_l(it->first); - it++; - int lag = it_l.first.first; - int eq = it_l.first.second.first; - int var = it_l.first.second.second; - int eqr = it_l.second.first; - int varr = it_l.second.second; - if(Deriv_type == 0) - { - //first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = first_derivatives[make_pair(eqr, getDerivID(symbol_table.getID(eEndogenous, varr), lag))]; - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = first_derivatives[make_pair(eqr, symbol_table.getID(eEndogenous, varr))]; - } - else if (Deriv_type == 1) - { - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = ModelBlock->Block_List[blck].Equation_Normalized[eq]->getChainRuleDerivative(symbol_table.getID(eEndogenous, varr), recursive_variables); - } - else if (Deriv_type == 2) - { - if(ModelBlock->Block_List[blck].Equation_Type[eq] == E_EVALUATE_S && eqBlock_List[blck].Nb_Recursives) - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = ModelBlock->Block_List[blck].Equation_Normalized[eq]->getChainRuleDerivative(symbol_table.getID(eEndogenous, varr), recursive_variables); - else - //first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = equations[eqr]->getChainRuleDerivative(symbol_table.getID(eEndogenous, varr), recursive_variables); - } - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->push_back(make_pair( make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))); - } - } - else if( ModelBlock->Block_List[blck].Simulation_Type==SOLVE_BACKWARD_SIMPLE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_FORWARD_SIMPLE - or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_BACKWARD_COMPLETE or ModelBlock->Block_List[blck].Simulation_Type==SOLVE_FORWARD_COMPLETE) - { - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->clear(); - for(int i = 0; i < ModelBlock->Block_List[blck].Nb_Recursives; i++) - { - if (ModelBlock->Block_List[blck].Equation_Type[i] == E_EVALUATE_S) - //recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - recursive_variables[symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i])] = ModelBlock->Block_List[blck].Equation_Normalized[i]; - else - //recursive_variables[getDerivID(symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i]), 0)] = equations[ModelBlock->Block_List[blck].Equation[i]]; - recursive_variables[symbol_table.getID(eEndogenous, ModelBlock->Block_List[blck].Variable[i])] = equations[ModelBlock->Block_List[blck].Equation[i]]; - } - for(int eq = ModelBlock->Block_List[blck].Nb_Recursives; eq < ModelBlock->Block_List[blck].Size; eq++) - { - int eqr = ModelBlock->Block_List[blck].Equation[eq]; - for(int var = ModelBlock->Block_List[blck].Nb_Recursives; var < ModelBlock->Block_List[blck].Size; var++) - { - int varr = ModelBlock->Block_List[blck].Variable[var]; - //NodeID d1 = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), 0), recursive_variables); - NodeID d1 = equations[eqr]->getChainRuleDerivative(symbol_table.getID(eEndogenous, varr), recursive_variables); - if (d1 == Zero) - continue; - first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))] = d1; - ModelBlock->Block_List[blck].Chain_Rule_Derivatives->push_back(make_pair( make_pair(0, make_pair(eq, var)), make_pair(eqr, varr))); - } - } - } - } -} - -void -StaticDllModel::writeChainRuleDerivative(ostream &output, int eqr, int varr, int lag, - ExprNodeOutputType output_type, - const temporary_terms_type &temporary_terms) const -{ - map >, NodeID>::const_iterator it = first_chain_rule_derivatives.find(make_pair(eqr, make_pair(varr, lag))); - if (it != first_chain_rule_derivatives.end()) - (it->second)->writeOutput(output, output_type, temporary_terms); - else - output << 0; -} - - -void -StaticDllModel::writeLatexFile(const string &basename) const - { - writeLatexModelFile(basename + "_static.tex", oLatexStaticModel); - } - -void -StaticDllModel::jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const -{ - output << LEFT_ARRAY_SUBSCRIPT(output_type); - if (IS_MATLAB(output_type)) - output << eq_nb + 1 << ", " << col_nb + 1; - else - output << eq_nb + col_nb * equations.size(); - output << RIGHT_ARRAY_SUBSCRIPT(output_type); -} - -void -StaticDllModel::hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const -{ - output << LEFT_ARRAY_SUBSCRIPT(output_type); - if (IS_MATLAB(output_type)) - output << row_nb + 1 << ", " << col_nb + 1; - else - output << row_nb + col_nb * NNZDerivatives[1]; - output << RIGHT_ARRAY_SUBSCRIPT(output_type); -} - -void -StaticDllModel::writeAuxVarInitval(ostream &output) const -{ - for(int i = 0; i < (int) aux_equations.size(); i++) - { - dynamic_cast(aux_equations[i])->writeOutput(output); - output << ";" << endl; - } -} diff --git a/StaticDllModel.hh b/StaticDllModel.hh deleted file mode 100644 index 8bfc4330..00000000 --- a/StaticDllModel.hh +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (C) 2003-2009 Dynare Team - * - * This file is part of Dynare. - * - * Dynare is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Dynare is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Dynare. If not, see . - */ - -#ifndef _STATICDLLMODEL_HH -#define _STATICDLLMODEL_HH - -using namespace std; - -#include - -#include "StaticModel.hh" -#include "BlockTriangular.hh" - -//! Stores a static model -class StaticDllModel : public ModelTree -{ -private: - typedef map, int> deriv_id_table_t; - //! Maps a pair (symbol_id, lag) to a deriv ID - deriv_id_table_t deriv_id_table; - //! Maps a deriv ID to a pair (symbol_id, lag) - vector > inv_deriv_id_table; - - //! Temporary terms for the file containing parameters dervicatives - temporary_terms_type params_derivs_temporary_terms; - - typedef map< pair< int, pair< int, int> >, NodeID> first_chain_rule_derivatives_type; - first_chain_rule_derivatives_type first_chain_rule_derivatives; - - - //! Writes static model file (Matlab version) - void writeStaticMFile(const string &static_basename) const; - //! Writes static model file (C version) - /*! \todo add third derivatives handling */ - void writeStaticCFile(const string &static_basename) const; - //! Writes the Block reordred structure of the model in M output - void writeModelEquationsOrdered_M(Model_Block *ModelBlock, const string &static_basename) const; - //! Writes the code of the Block reordred structure of the model in virtual machine bytecode - void writeModelEquationsCodeOrdered(const string file_name, const Model_Block *ModelBlock, const string bin_basename, map_idx_type map_idx) const; - //! Computes jacobian and prepares for equation normalization - /*! Using values from initval/endval blocks and parameter initializations: - - computes the jacobian for the model w.r. to contemporaneous variables - - removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff) - */ - void evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic); - void BlockLinear(Model_Block *ModelBlock); - map_idx_type map_idx; - //! Build The incidence matrix form the modeltree - void BuildIncidenceMatrix(); - - 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, map_idx_type &map_idx) const; - //! Write chain rule derivative code of an equation w.r. to a variable - void compileChainRuleDerivative(ofstream &code_file, int eq, int var, int lag, map_idx_type &map_idx) const; - - //! Get the type corresponding to a derivation ID - 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 static Jacobian - void computeStatJacobianCols(); - //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables - void computeChainRuleJacobian(Model_Block *ModelBlock); - //! Collect only the first derivatives - map >, NodeID> collect_first_order_derivatives_endogenous(); - - //! Helper for writing the Jacobian elements in MATLAB and C - /*! Writes either (i+1,j+1) or [i+j*no_eq] */ - void jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const; - - //! Helper for writing the sparse Hessian elements in MATLAB and C - /*! Writes either (i+1,j+1) or [i+j*NNZDerivatives[1]] */ - void hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const; - - //! Write chain rule derivative of a recursive equation w.r. to a variable - void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; - - -public: - StaticDllModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); - //! Absolute value under which a number is considered to be zero - double cutoff; - //! Compute the minimum feedback set in the static model: - /*! 0 : all endogenous variables are considered as feedback variables - 1 : the variables belonging to a non linear equation are considered as feedback variables - 2 : the variables belonging to a non normalizable non linear equation are considered as feedback variables - default value = 0 */ - int mfs; - //! the file containing the model and the derivatives code - ofstream code_file; - //! Execute computations (variable sorting + derivation) - /*! - \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 paramsDerivatives whether 2nd derivatives w.r. to a pair (endo/exo/exo_det, parameter) 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 static files - */ - void computingPass(const eval_context_type &eval_context, bool no_tmp_terms, bool block); - //! Complete set to block decompose the model - BlockTriangular block_triangular; - //! Adds informations for simulation in a binary file - void Write_Inf_To_Bin_File(const string &static_basename, const string &bin_basename, - const int &num, int &u_count_int, bool &file_open) const; - //! Writes static model file - void writeStaticFile(const string &basename, bool block) const; - - //! Writes LaTeX file with the equations of the static model - void writeLatexFile(const string &basename) const; - - //! Writes initializations in oo_.steady_state for the auxiliary variables - void writeAuxVarInitval(ostream &output) const; - - virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException); -}; - -#endif diff --git a/StaticModel.cc b/StaticModel.cc index 6a559544..941f5279 100644 --- a/StaticModel.cc +++ b/StaticModel.cc @@ -17,43 +17,770 @@ * along with Dynare. If not, see . */ +#include +#include #include #include - -#include +#include +#include #include -#include -#include +#include "StaticModel.hh" -#ifdef DEBUG -// For select2nd() -# ifdef __GNUC__ -# include -using namespace __gnu_cxx; -# endif +// For mkdir() and chdir() +#ifdef _WIN32 +# include +#else +# include +# include +# include #endif -#include -#include -#include -#include - -#include "StaticModel.hh" -#include "MinimumFeedbackSet.hh" - -using namespace boost; - StaticModel::StaticModel(SymbolTable &symbol_table_arg, - NumericalConstants &num_constants_arg) : - ModelTree(symbol_table_arg, num_constants_arg) + NumericalConstants &num_constants_arg) : + ModelTree(symbol_table_arg, num_constants_arg), + global_temporary_terms(true), + cutoff(1e-15), + mfs(0) { } void -StaticModel::writeStaticMFile(ostream &output, const string &func_name) const +StaticModel::compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const +{ + first_derivatives_type::const_iterator it = first_derivatives.find(make_pair(eq, symbol_table.getID(eEndogenous, symb_id))); + if (it != first_derivatives.end()) + (it->second)->compile(code_file, false, temporary_terms, map_idx, false, false); + else + { + FLDZ_ fldz; + fldz.write(code_file); + } +} + + +void +StaticModel::compileChainRuleDerivative(ofstream &code_file, int eqr, int varr, int lag, map_idx_type &map_idx) const +{ + map >, NodeID>::const_iterator it = first_chain_rule_derivatives.find(make_pair(eqr, make_pair(varr, lag))); + if (it != first_chain_rule_derivatives.end()) + (it->second)->compile(code_file, false, temporary_terms, map_idx, false, false); + else + { + FLDZ_ fldz; + fldz.write(code_file); + } +} + +void +StaticModel::computeTemporaryTermsOrdered() +{ + map > first_occurence; + map reference_count; + BinaryOpNode *eq_node; + first_derivatives_type::const_iterator it; + first_chain_rule_derivatives_type::const_iterator it_chr; + ostringstream tmp_s; + v_temporary_terms.clear(); + map_idx.clear(); + + unsigned int nb_blocks = getNbBlocks(); + v_temporary_terms = vector< vector >(nb_blocks); + + v_temporary_terms_inuse = vector (nb_blocks); + + temporary_terms.clear(); + if(!global_temporary_terms) + { + for (unsigned int block = 0; block < nb_blocks; block++) + { + + reference_count.clear(); + temporary_terms.clear(); + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + v_temporary_terms[block] = vector(block_size); + for (unsigned int i = 0; i < block_size; i++) + { + if (icomputeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + else + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + } + } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + } + set temporary_terms_in_use; + temporary_terms_in_use.clear(); + v_temporary_terms_inuse[block] = temporary_terms_in_use; + } + } + else + { + for (unsigned int block = 0; block < nb_blocks; block++) + { + // Compute the temporary terms reordered + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + v_temporary_terms[block] = vector(block_size); + for (unsigned int i = 0; i < block_size; i++) + { + if (icomputeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + else + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, i); + } + } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->computeTemporaryTerms(reference_count, temporary_terms, first_occurence, block, v_temporary_terms, block_size-1); + } + + } + for (unsigned int block = 0; block < nb_blocks; block++) + { + // Collecte the temporary terms reordered + unsigned int block_size = getBlockSize(block); + unsigned int block_nb_mfs = getBlockMfs(block); + unsigned int block_nb_recursives = block_size - block_nb_mfs; + set temporary_terms_in_use; + for (unsigned int i = 0; i < block_size; i++) + { + if (icollectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + else + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + eq_node->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + } + } + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + NodeID id=it->second.second; + id->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + } + for(int i = 0; i < (int) getBlockSize(block); i++) + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + (*it)->collectTemporary_terms(temporary_terms, temporary_terms_in_use, block); + v_temporary_terms_inuse[block] = temporary_terms_in_use; + } + } + // Add a mapping form node ID to temporary terms order + int j=0; + for (temporary_terms_type::const_iterator it = temporary_terms.begin(); + it != temporary_terms.end(); it++) + map_idx[(*it)->idx]=j++; +} + + +void +StaticModel::writeModelEquationsOrdered_M(const string &static_basename) const + { + string tmp_s, sps; + ostringstream tmp_output, tmp1_output, global_output; + NodeID lhs=NULL, rhs=NULL; + BinaryOpNode *eq_node; + map reference_count; + temporary_terms_type local_temporary_terms; + ofstream output; + int nze; + vector feedback_variables; + ExprNodeOutputType local_output_type; + + if(global_temporary_terms) + { + local_output_type = oMatlabStaticModelSparse; + local_temporary_terms = temporary_terms; + } + else + local_output_type = oMatlabDynamicModelSparseLocalTemporaryTerms; + + //---------------------------------------------------------------------- + //For each block + for (unsigned int block = 0; block < getNbBlocks(); block++) + { + //recursive_variables.clear(); + feedback_variables.clear(); + //For a block composed of a single equation determines wether we have to evaluate or to solve the equation + nze = derivative_endo[block].size(); + BlockSimulationType simulation_type = getBlockSimulationType(block); + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + + tmp1_output.str(""); + tmp1_output << static_basename << "_" << block+1 << ".m"; + output.open(tmp1_output.str().c_str(), ios::out | ios::binary); + output << "%\n"; + output << "% " << tmp1_output.str() << " : Computes static model for Dynare\n"; + output << "%\n"; + output << "% Warning : this file is generated automatically by Dynare\n"; + output << "% from model file (.mod)\n\n"; + output << "%/\n"; + if (simulation_type == EVALUATE_BACKWARD || simulation_type ==EVALUATE_FORWARD) + output << "function y = " << static_basename << "_" << block+1 << "(y, x, params)\n"; + else + output << "function [residual, y, g1] = " << static_basename << "_" << block+1 << "(y, x, params)\n"; + + BlockType block_type; + if(simulation_type == SOLVE_FORWARD_COMPLETE ||simulation_type == SOLVE_BACKWARD_COMPLETE) + block_type = SIMULTANS; + else if((simulation_type == SOLVE_FORWARD_SIMPLE ||simulation_type == SOLVE_BACKWARD_SIMPLE || + simulation_type == EVALUATE_BACKWARD || simulation_type == EVALUATE_FORWARD) + && getBlockFirstEquation(block) < prologue) + block_type = PROLOGUE; + else if((simulation_type == SOLVE_FORWARD_SIMPLE ||simulation_type == SOLVE_BACKWARD_SIMPLE || + simulation_type == EVALUATE_BACKWARD || simulation_type == EVALUATE_FORWARD) + && getBlockFirstEquation(block) >= equations.size() - epilogue) + block_type = EPILOGUE; + else + block_type = SIMULTANS; + output << " % ////////////////////////////////////////////////////////////////////////" << endl + << " % //" << string(" Block ").substr(int(log10(block + 1))) << block + 1 << " " << BlockType0(block_type) + << " //" << endl + << " % // Simulation type " + << BlockSim(simulation_type) << " //" << endl + << " % ////////////////////////////////////////////////////////////////////////" << endl; + output << " global options_;" << endl; + //The Temporary terms + if (simulation_type != EVALUATE_BACKWARD && simulation_type != EVALUATE_FORWARD) + output << " g1 = zeros(" << block_mfs << ", " << block_mfs << ");" << endl; + + + if (v_temporary_terms_inuse[block].size()) + { + tmp_output.str(""); + for (temporary_terms_inuse_type::const_iterator it = v_temporary_terms_inuse[block].begin(); + it != v_temporary_terms_inuse[block].end(); it++) + tmp_output << " T" << *it; + output << " global" << tmp_output.str() << ";\n"; + } + + if (simulation_type!=EVALUATE_BACKWARD && simulation_type!=EVALUATE_FORWARD) + output << " residual=zeros(" << block_mfs << ",1);\n"; + + + // The equations + for (unsigned int i = 0; i < block_size; i++) + { + if(!global_temporary_terms) + local_temporary_terms = v_temporary_terms[block][i]; + temporary_terms_type tt2; + tt2.clear(); + if (v_temporary_terms[block].size()) + { + output << " " << "% //Temporary variables" << endl; + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + { + output << " " << sps; + (*it)->writeOutput(output, local_output_type, local_temporary_terms); + output << " = "; + (*it)->writeOutput(output, local_output_type, tt2); + // Insert current node into tt2 + tt2.insert(*it); + output << ";" << endl; + } + } + + int variable_ID = getBlockVariableID(block, i); + int equation_ID = getBlockEquationID(block, i); + EquationType equ_type = getBlockEquationType(block, i); + string sModel = symbol_table.getName(symbol_table.getID(eEndogenous, variable_ID)) ; + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block,i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + tmp_output.str(""); + lhs->writeOutput(tmp_output, local_output_type, local_temporary_terms); + switch (simulation_type) + { + case EVALUATE_BACKWARD: + case EVALUATE_FORWARD: +evaluation: + output << " % equation " << getBlockEquationID(block, i)+1 << " variable : " << sModel + << " (" << variable_ID+1 << ") " << c_Equation_Type(equ_type) << endl; + output << " "; + if (equ_type == E_EVALUATE) + { + output << tmp_output.str(); + output << " = "; + rhs->writeOutput(output, local_output_type, local_temporary_terms); + } + else if (equ_type == E_EVALUATE_S) + { + output << "%" << tmp_output.str(); + output << " = "; + if (isBlockEquationRenormalized(block, i)) + { + rhs->writeOutput(output, local_output_type, local_temporary_terms); + output << "\n "; + tmp_output.str(""); + eq_node = (BinaryOpNode *)getBlockEquationRenormalizedNodeID(block, i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + lhs->writeOutput(output, local_output_type, local_temporary_terms); + output << " = "; + rhs->writeOutput(output, local_output_type, local_temporary_terms); + } + } + else + { + cerr << "Type missmatch for equation " << equation_ID+1 << "\n"; + exit(EXIT_FAILURE); + } + output << ";\n"; + break; + case SOLVE_BACKWARD_SIMPLE: + case SOLVE_FORWARD_SIMPLE: + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + if (iwriteOutput(output, local_output_type, local_temporary_terms); + output << ");\n"; + } + } + // The Jacobian if we have to solve the block + if (simulation_type==SOLVE_BACKWARD_SIMPLE || simulation_type==SOLVE_FORWARD_SIMPLE || + simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) + output << " " << sps << "% Jacobian " << endl; + switch (simulation_type) + { + case SOLVE_BACKWARD_SIMPLE: + case SOLVE_FORWARD_SIMPLE: + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + unsigned int eqr = getBlockEquationID(block, eq); + unsigned int varr = getBlockVariableID(block, var); + NodeID id = it->second.second; + output << " g1(" << eq+1-block_recursive << ", " << var+1-block_recursive << ") = "; + id->writeOutput(output, local_output_type, local_temporary_terms); + output << "; % variable=" << symbol_table.getName(symbol_table.getID(eEndogenous, varr)) + << "(" << 0 + << ") " << varr+1 + << ", equation=" << eqr+1 << endl; + } + break; + default: + break; + } + output.close(); + } + } + +void +StaticModel::writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const + { + struct Uff_l + { + int u, var, lag; + Uff_l *pNext; + }; + + struct Uff + { + Uff_l *Ufl, *Ufl_First; + }; + + int i,v; + string tmp_s; + ostringstream tmp_output; + ofstream code_file; + NodeID lhs=NULL, rhs=NULL; + BinaryOpNode *eq_node; + Uff Uf[symbol_table.endo_nbr()]; + map reference_count; + vector feedback_variables; + bool file_open=false; + + string main_name=file_name; + main_name+=".cod"; + code_file.open(main_name.c_str(), ios::out | ios::binary | ios::ate ); + if (!code_file.is_open()) + { + cout << "Error : Can't open file \"" << main_name << "\" for writing\n"; + exit(EXIT_FAILURE); + } + //Temporary variables declaration + + FDIMT_ fdimt(temporary_terms.size()); + fdimt.write(code_file); + + for (unsigned int block = 0; block < getNbBlocks(); block++) + { + feedback_variables.clear(); + if (block>0) + { + FENDBLOCK_ fendblock; + fendblock.write(code_file); + } + int count_u; + int u_count_int=0; + BlockSimulationType simulation_type = getBlockSimulationType(block); + unsigned int block_size = getBlockSize(block); + unsigned int block_mfs = getBlockMfs(block); + unsigned int block_recursive = block_size - block_mfs; + + if (simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE || simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE || + simulation_type==SOLVE_BACKWARD_COMPLETE || simulation_type==SOLVE_FORWARD_COMPLETE) + { + Write_Inf_To_Bin_File(file_name, bin_basename, block, u_count_int,file_open); + file_open=true; + } + + FBEGINBLOCK_ fbeginblock(block_mfs, + simulation_type, + getBlockFirstEquation(block), + block_size, + variable_reordered, + equation_reordered, + blocks_linear[block], + symbol_table.endo_nbr(), + 0, + 0, + u_count_int + ); + fbeginblock.write(code_file); + + // The equations + for (i = 0;i < (int) block_size;i++) + { + //The Temporary terms + temporary_terms_type tt2; + tt2.clear(); + if (v_temporary_terms[block].size()) + { + for (temporary_terms_type::const_iterator it = v_temporary_terms[block][i].begin(); + it != v_temporary_terms[block][i].end(); it++) + { + (*it)->compile(code_file, false, tt2, map_idx, false, false); + FSTPST_ fstpst((int)(map_idx.find((*it)->idx)->second)); + fstpst.write(code_file); + // Insert current node into tt2 + tt2.insert(*it); + } + } + + int variable_ID, equation_ID; + EquationType equ_type; + switch (simulation_type) + { +evaluation: + case EVALUATE_BACKWARD: + case EVALUATE_FORWARD: + equ_type = getBlockEquationType(block, i); + if (equ_type == E_EVALUATE) + { + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block,i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + rhs->compile(code_file, false, temporary_terms, map_idx, false, false); + lhs->compile(code_file, true, temporary_terms, map_idx, false, false); + } + else if (equ_type == E_EVALUATE_S) + { + eq_node = (BinaryOpNode*)getBlockEquationRenormalizedNodeID(block,i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + rhs->compile(code_file, false, temporary_terms, map_idx, false, false); + lhs->compile(code_file, true, temporary_terms, map_idx, false, false); + } + break; + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + if (i< (int) block_recursive) + goto evaluation; + variable_ID = getBlockVariableID(block, i); + equation_ID = getBlockEquationID(block, i); + feedback_variables.push_back(variable_ID); + Uf[equation_ID].Ufl=NULL; + goto end; + default: +end: + eq_node = (BinaryOpNode*)getBlockEquationNodeID(block, i); + lhs = eq_node->get_arg1(); + rhs = eq_node->get_arg2(); + lhs->compile(code_file, false, temporary_terms, map_idx, false, false); + rhs->compile(code_file, false, temporary_terms, map_idx, false, false); + + FBINARY_ fbinary(oMinus); + fbinary.write(code_file); + + FSTPR_ fstpr(i - block_recursive); + fstpr.write(code_file); + } + } + FENDEQU_ fendequ; + fendequ.write(code_file); + // The Jacobian if we have to solve the block + if (simulation_type != EVALUATE_BACKWARD + && simulation_type != EVALUATE_FORWARD) + { + switch (simulation_type) + { + case SOLVE_BACKWARD_SIMPLE: + case SOLVE_FORWARD_SIMPLE: + compileDerivative(code_file, getBlockEquationID(block, 0), getBlockVariableID(block, 0), 0, map_idx); + { + FSTPG_ fstpg(0); + fstpg.write(code_file); + } + break; + + case SOLVE_BACKWARD_COMPLETE: + case SOLVE_FORWARD_COMPLETE: + count_u = feedback_variables.size(); + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[block].begin(); it != (blocks_derivatives[block]).end(); it++) + { + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + unsigned int eqr = getBlockEquationID(block, eq); + unsigned int varr = getBlockVariableID(block, var); + if(eq>=block_recursive and var>=block_recursive) + { + if (!Uf[eqr].Ufl) + { + Uf[eqr].Ufl=(Uff_l*)malloc(sizeof(Uff_l)); + Uf[eqr].Ufl_First=Uf[eqr].Ufl; + } + else + { + Uf[eqr].Ufl->pNext=(Uff_l*)malloc(sizeof(Uff_l)); + Uf[eqr].Ufl=Uf[eqr].Ufl->pNext; + } + Uf[eqr].Ufl->pNext=NULL; + Uf[eqr].Ufl->u=count_u; + Uf[eqr].Ufl->var=varr; + compileChainRuleDerivative(code_file, eqr, varr, 0, map_idx); + FSTPSU_ fstpsu(count_u); + fstpsu.write(code_file); + count_u++; + } + } + for (i = 0;i < (int) block_size;i++) + { + if(i>= (int) block_recursive) + { + FLDR_ fldr(i-block_recursive); + fldr.write(code_file); + + FLDZ_ fldz; + fldz.write(code_file); + + v=getBlockEquationID(block, i); + for (Uf[v].Ufl=Uf[v].Ufl_First; Uf[v].Ufl; Uf[v].Ufl=Uf[v].Ufl->pNext) + { + FLDSU_ fldsu(Uf[v].Ufl->u); + fldsu.write(code_file); + FLDSV_ fldsv(eEndogenous, Uf[v].Ufl->var); + fldsv.write(code_file); + + FBINARY_ fbinary(oTimes); + fbinary.write(code_file); + + FCUML_ fcuml; + fcuml.write(code_file); + } + Uf[v].Ufl=Uf[v].Ufl_First; + while (Uf[v].Ufl) + { + Uf[v].Ufl_First=Uf[v].Ufl->pNext; + free(Uf[v].Ufl); + Uf[v].Ufl=Uf[v].Ufl_First; + } + FBINARY_ fbinary(oMinus); + fbinary.write(code_file); + + FSTPSU_ fstpsu(i - block_recursive); + fstpsu.write(code_file); + + } + } + break; + default: + break; + } + } + } + FENDBLOCK_ fendblock; + fendblock.write(code_file); + FEND_ fend; + fend.write(code_file); + code_file.close(); + } + + +void +StaticModel::Write_Inf_To_Bin_File(const string &static_basename, const string &bin_basename, const int &num, + int &u_count_int, bool &file_open) const + { + int j; + std::ofstream SaveCode; + if (file_open) + SaveCode.open((bin_basename + "_static.bin").c_str(), ios::out | ios::in | ios::binary | ios ::ate ); + else + SaveCode.open((bin_basename + "_static.bin").c_str(), ios::out | ios::binary); + if (!SaveCode.is_open()) + { + cout << "Error : Can't open file \"" << bin_basename << "_static.bin\" for writing\n"; + exit(EXIT_FAILURE); + } + u_count_int=0; + unsigned int block_size = getBlockSize(num); + unsigned int block_mfs = getBlockMfs(num); + unsigned int block_recursive = block_size - block_mfs; + for (t_block_derivatives_equation_variable_laglead_nodeid::const_iterator it = blocks_derivatives[num].begin(); it != (blocks_derivatives[num]).end(); it++) + { + unsigned int eq = it->first.first; + unsigned int var = it->first.second; + int lag = 0; + if(eq>=block_recursive and var>=block_recursive) + { + int v = eq - block_recursive; + SaveCode.write(reinterpret_cast(&v), sizeof(v)); + int varr = var - block_recursive; + SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); + SaveCode.write(reinterpret_cast(&lag), sizeof(lag)); + int u = u_count_int + block_mfs; + SaveCode.write(reinterpret_cast(&u), sizeof(u)); + u_count_int++; + } + } + + for (j = block_recursive; j < (int) block_size; j++) + { + unsigned int varr=getBlockVariableID(num, j); + SaveCode.write(reinterpret_cast(&varr), sizeof(varr)); + } + for (j = block_recursive; j < (int) block_size; j++) + { + unsigned int eqr=getBlockEquationID(num, j); + SaveCode.write(reinterpret_cast(&eqr), sizeof(eqr)); + } + SaveCode.close(); + } + +map >, NodeID> +StaticModel::collect_first_order_derivatives_endogenous() +{ + map >, NodeID> endo_derivatives; + for (first_derivatives_type::iterator it2 = first_derivatives.begin(); + it2 != first_derivatives.end(); it2++) + { + if (getTypeByDerivID(it2->first.second)==eEndogenous) + { + int eq = it2->first.first; + int var=symbol_table.getTypeSpecificID(it2->first.second); + int lag = 0; + endo_derivatives[make_pair(eq, make_pair(var, lag))] = it2->second; + } + } + return endo_derivatives; +} + +void +StaticModel::computingPass(const eval_context_type &eval_context, bool no_tmp_terms, bool hessian, bool block) +{ + // Compute derivatives w.r. to all endogenous, and possibly exogenous and exogenous deterministic + set vars; + + for(int i = 0; i < symbol_table.endo_nbr(); i++) + vars.insert(symbol_table.getID(eEndogenous, i)); + + // Launch computations + cout << "Computing static model derivatives:" << endl + << " - order 1" << endl; + first_derivatives.clear(); + + computeJacobian(vars); + + if (hessian) + { + cout << " - order 2" << endl; + computeHessian(vars); + } + + + if (block) + { + jacob_map contemporaneous_jacobian, static_jacobian; + + // for each block contains pair + vector > blocks; + + evaluateAndReduceJacobian(eval_context, contemporaneous_jacobian, static_jacobian, dynamic_jacobian, cutoff, false); + + computePossiblySingularNormalization(contemporaneous_jacobian, cutoff == 0); + + computePrologueAndEpilogue(static_jacobian, equation_reordered, variable_reordered, prologue, epilogue); + + map >, NodeID> first_order_endo_derivatives = collect_first_order_derivatives_endogenous(); + + equation_type_and_normalized_equation = equationTypeDetermination(equations, first_order_endo_derivatives, variable_reordered, equation_reordered, mfs); + + cout << "Finding the optimal block decomposition of the model ...\n"; + + if (prologue+epilogue < (unsigned int) equation_number()) + computeBlockDecompositionAndFeedbackVariablesForEachBlock(static_jacobian, dynamic_jacobian, prologue, epilogue, equation_reordered, variable_reordered, blocks, equation_type_and_normalized_equation, false, false, mfs, inv_equation_reordered, inv_variable_reordered); + + block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination(dynamic_jacobian, prologue, epilogue, blocks, equations, equation_type_and_normalized_equation, variable_reordered, equation_reordered); + + printBlockDecomposition(blocks); + + computeChainRuleJacobian(blocks_derivatives); + + blocks_linear = BlockLinear(blocks_derivatives, variable_reordered); + + collect_block_first_order_derivatives(); + + global_temporary_terms = true; + if (!no_tmp_terms) + computeTemporaryTermsOrdered(); + + } + else + if (!no_tmp_terms) + computeTemporaryTerms(true); +} + +void +StaticModel::writeStaticMFile(const string &func_name) const { // Writing comments and function definition command - output << "function [residual, g1, g2] = " << func_name << "(y, x, params)" << endl + string filename = func_name + "_static.m"; + + ofstream output; + output.open(filename.c_str(), ios::out | ios::binary); + if (!output.is_open()) + { + cerr << "ERROR: Can't open file " << filename << " for writing" << endl; + exit(EXIT_FAILURE); + } + + output << "function [residual, g1, g2] = " << func_name + "_static(y, x, params)" << endl << "%" << endl << "% Status : Computes static model for Dynare" << endl << "%" << endl @@ -152,12 +879,45 @@ StaticModel::writeStaticMFile(ostream &output, const string &func_name) const output << " g2 = sparse([],[],[]," << equations.size() << "," << g2ncols << ");" << endl; output << "end;" << endl; // Close the if nargout >= 3 statement + output.close(); } + + void -StaticModel::writeStaticFile(const string &basename, bool block) const +StaticModel::writeStaticFile(const string &basename, bool block, bool bytecode) const + { + int r; + + //assert(block); + +#ifdef _WIN32 + r = mkdir(basename.c_str()); +#else + r = mkdir(basename.c_str(), 0777); +#endif + if (r < 0 && errno != EEXIST) + { + perror("ERROR"); + exit(EXIT_FAILURE); + } + if(block && bytecode) + writeModelEquationsCodeOrdered(basename + "_static", basename, map_idx); + else if(block && !bytecode) + { + chdir(basename.c_str()); + writeModelEquationsOrdered_M(basename + "_static"); + chdir(".."); + writeStaticBlockMFSFile(basename); + } + else + writeStaticMFile(basename); + } + +void +StaticModel::writeStaticBlockMFSFile(const string &basename) const { - string filename = basename + "_static.m"; + string filename = basename + "_static.m"; ofstream output; output.open(filename.c_str(), ios::out | ios::binary); @@ -167,45 +927,79 @@ StaticModel::writeStaticFile(const string &basename, bool block) const exit(EXIT_FAILURE); } - if (block) - writeStaticBlockMFSFile(output, basename + "_static"); - else - writeStaticMFile(output, basename + "_static"); + string func_name = basename + "_static"; + output << "function [residual, g1, y] = " << func_name << "(nblock, y, x, params)" << endl + << " residual = [];" << endl + << " g1 = [];" << endl + << " switch nblock" << endl; + + unsigned int nb_blocks = getNbBlocks(); + + + for(int b = 0; b < (int) nb_blocks; b++) + { + + set local_var; + + output << " case " << b+1 << endl; + + BlockSimulationType simulation_type = getBlockSimulationType(b); + + if (simulation_type == EVALUATE_BACKWARD || simulation_type ==EVALUATE_FORWARD) + output << " y = " << func_name << "_" << b+1 << "(y, x, params);\n"; + else + output << " [residual, y, g1] = " << func_name << "_" << b+1 << "(y, x, params);\n"; + } + output << " end" << endl + << "end" << endl; output.close(); + } + + void -StaticModel::computingPass(bool block, bool hessian, bool no_tmp_terms) +StaticModel::writeOutput(ostream &output, bool block) const { + if (!block) + return; - - // Compute derivatives w.r. to all endogenous - set vars; - for(int i = 0; i < symbol_table.endo_nbr(); i++) - vars.insert(symbol_table.getID(eEndogenous, i)); - - // Launch computations - cout << "Computing static model derivatives:" << endl - << " - order 1" << endl; - computeJacobian(vars); - - if (hessian) + unsigned int nb_blocks = getNbBlocks(); + output << "M_.blocksMFS = cell(" << nb_blocks << ", 1);" << endl; + for(int b = 0; b < (int) nb_blocks; b++) { - cout << " - order 2" << endl; - computeHessian(vars); - } + output << "M_.blocksMFS{" << b+1 << "} = [ "; + unsigned int block_size = getBlockSize(b); + unsigned int block_mfs = getBlockMfs(b); + unsigned int block_recursive = block_size - block_mfs; + BlockSimulationType simulation_type = getBlockSimulationType(b); - if (block) - { - computeNormalization(); - computeSortedBlockDecomposition(); - computeMFS(); - computeSortedRecursive(); - computeBlockMFSJacobian(); + if (simulation_type != EVALUATE_BACKWARD && simulation_type != EVALUATE_FORWARD) + for(int i= block_recursive; i< (int) block_size; i++) + output << getBlockVariableID(b, i)+1 << "; "; + + output << "];" << endl; } - else if (!no_tmp_terms) - computeTemporaryTerms(true); +} + + +SymbolType +StaticModel::getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException) +{ + return symbol_table.getType(getSymbIDByDerivID(deriv_id)); +} + +int +StaticModel::getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException) +{ + return 0; +} + +int +StaticModel::getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException) +{ + return deriv_id; } int @@ -217,440 +1011,222 @@ StaticModel::getDerivID(int symb_id, int lag) const throw (UnknownDerivIDExcepti return -1; } -void -StaticModel::computeNormalization() + +map >, pair >, int> +StaticModel::get_Derivatives(int block) { - const int n = equation_number(); - - assert(n == symbol_table.endo_nbr()); - - typedef adjacency_list BipartiteGraph; - - /* - Vertices 0 to n-1 are for endogenous (using type specific ID) - Vertices n to 2*n-1 are for equations (using equation no.) - */ - BipartiteGraph g(2 * n); - - // Fill in the graph - set > endo; - for(int i = 0; i < n; i++) + map >, pair >, int> Derivatives; + Derivatives.clear(); + int block_size = getBlockSize(block); + int block_nb_recursive = block_size - getBlockMfs(block); + int lag = 0; + for(int eq = 0; eq < block_size; eq++) { - endo.clear(); - equations[i]->collectEndogenous(endo); - for(set >::const_iterator it = endo.begin(); - it != endo.end(); it++) - add_edge(i + n, it->first, g); + int eqr = getBlockEquationID(block, eq); + for(int var = 0; var < block_size; var++) + { + int varr = getBlockVariableID(block, var); + if(dynamic_jacobian.find(make_pair(lag, make_pair(eqr, varr))) != dynamic_jacobian.end()) + { + bool OK = true; + map >, pair >, int>::const_iterator its = Derivatives.find(make_pair(make_pair(lag, make_pair(eq, var)), make_pair(eqr, varr))); + if(its!=Derivatives.end()) + { + if(its->second == 2) + OK=false; + } + + if(OK) + { + if (getBlockEquationType(block, eq) == E_EVALUATE_S and eq mate_map(2*n); + return(Derivatives); +} -#if 1 - bool check = checked_edmonds_maximum_cardinality_matching(g, &mate_map[0]); -#else // Alternative way to compute normalization, by giving an initial matching using natural normalizations - fill(mate_map.begin(), mate_map.end(), graph_traits::null_vertex()); - multimap natural_endo2eqs; - computeNormalizedEquations(natural_endo2eqs); - - for(int i = 0; i < symbol_table.endo_nbr(); i++) +void +StaticModel::computeChainRuleJacobian(t_blocks_derivatives &blocks_derivatives) +{ + map recursive_variables; + unsigned int nb_blocks = getNbBlocks(); + blocks_derivatives = t_blocks_derivatives(nb_blocks); + for(unsigned int block = 0; block < nb_blocks; block++) { - if (natural_endo2eqs.count(i) == 0) - continue; - - int j = natural_endo2eqs.find(i)->second; - - put(&mate_map[0], i, n+j); - put(&mate_map[0], n+j, i); + t_block_derivatives_equation_variable_laglead_nodeid tmp_derivatives; + recursive_variables.clear(); + BlockSimulationType simulation_type = getBlockSimulationType(block); + int block_size = getBlockSize(block); + int block_nb_mfs = getBlockMfs(block); + int block_nb_recursives = block_size - block_nb_mfs; + if (simulation_type==SOLVE_TWO_BOUNDARIES_COMPLETE or simulation_type==SOLVE_TWO_BOUNDARIES_SIMPLE) + { + blocks_derivatives.push_back(t_block_derivatives_equation_variable_laglead_nodeid(0)); + for(int i = 0; i < block_nb_recursives; i++) + { + if (getBlockEquationType(block, i) == E_EVALUATE_S) + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block, i)), 0)] = getBlockEquationRenormalizedNodeID(block, i); + else + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block, i)), 0)] = getBlockEquationNodeID(block, i); + } + map >, pair >, int> Derivatives = get_Derivatives(block); + map >, pair >, int>::const_iterator it = Derivatives.begin(); + for(int i=0; i<(int)Derivatives.size(); i++) + { + int Deriv_type = it->second; + pair >, pair > it_l(it->first); + it++; + int lag = it_l.first.first; + int eq = it_l.first.second.first; + int var = it_l.first.second.second; + int eqr = it_l.second.first; + int varr = it_l.second.second; + if(Deriv_type == 0) + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = first_derivatives[make_pair(eqr, getDerivID(symbol_table.getID(eEndogenous, varr), lag))]; + else if (Deriv_type == 1) + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = (equation_type_and_normalized_equation[eqr].second)->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + else if (Deriv_type == 2) + { + if(getBlockEquationType(block, eq) == E_EVALUATE_S && eqgetChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + else + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))] = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), lag), recursive_variables); + } + tmp_derivatives.push_back(make_pair(make_pair(eq, var), make_pair(lag, first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, lag))]) )); + } + } + else if( simulation_type==SOLVE_BACKWARD_SIMPLE or simulation_type==SOLVE_FORWARD_SIMPLE + or simulation_type==SOLVE_BACKWARD_COMPLETE or simulation_type==SOLVE_FORWARD_COMPLETE) + { + blocks_derivatives.push_back(t_block_derivatives_equation_variable_laglead_nodeid(0)); + for(int i = 0; i < block_nb_recursives; i++) + { + if (getBlockEquationType(block, i) == E_EVALUATE_S) + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block,i)), 0)] = getBlockEquationRenormalizedNodeID(block, i); + else + recursive_variables[getDerivID(symbol_table.getID(eEndogenous, getBlockVariableID(block,i)), 0)] = getBlockEquationNodeID(block, i); + } + for(int eq = block_nb_recursives; eq < block_size; eq++) + { + int eqr = getBlockEquationID(block, eq); + for(int var = block_nb_recursives; var < block_size; var++) + { + int varr = getBlockVariableID(block, var); + NodeID d1 = equations[eqr]->getChainRuleDerivative(getDerivID(symbol_table.getID(eEndogenous, varr), 0), recursive_variables); + if (d1 == Zero) + continue; + first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))] = d1; + tmp_derivatives.push_back( + make_pair(make_pair(eq, var),make_pair(0, first_chain_rule_derivatives[make_pair(eqr, make_pair(varr, 0))]))); + } + } + } + blocks_derivatives[block] = tmp_derivatives; } +} - edmonds_augmenting_path_finder::type> augmentor(g, &mate_map[0], get(vertex_index, g)); - bool not_maximum_yet = true; - while(not_maximum_yet) + +void +StaticModel::collect_block_first_order_derivatives() +{ + //! vector for an equation or a variable indicates the block number + vector equation_2_block, variable_2_block; + unsigned int nb_blocks = getNbBlocks(); + equation_2_block = vector(equation_reordered.size()); + variable_2_block = vector(variable_reordered.size()); + for(unsigned int block = 0; block < nb_blocks; block++) { - not_maximum_yet = augmentor.augment_matching(); + unsigned int block_size = getBlockSize(block); + for(unsigned int i = 0; i < block_size; i++) + { + equation_2_block[getBlockEquationID(block, i)] = block; + variable_2_block[getBlockVariableID(block, i)] = block; + } } - augmentor.get_current_matching(&mate_map[0]); - - bool check = maximum_cardinality_matching_verifier::type>::verify_matching(g, &mate_map[0], get(vertex_index, g)); -#endif - - assert(check); - - // Check if all variables are normalized - vector::const_iterator it = find(mate_map.begin(), mate_map.begin() + n, graph_traits::null_vertex()); - if (it != mate_map.begin() + n) + derivative_endo = vector(nb_blocks); + endo_max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + max_leadlag_block = vector >(nb_blocks, make_pair( 0, 0)); + for (first_derivatives_type::iterator it2 = first_derivatives.begin(); + it2 != first_derivatives.end(); it2++) { - cerr << "ERROR: Could not normalize static model. Variable " - << symbol_table.getName(symbol_table.getID(eEndogenous, it - mate_map.begin())) - << " is not in the maximum cardinality matching." << endl; - exit(EXIT_FAILURE); + int eq = it2->first.first; + int var = symbol_table.getTypeSpecificID(getSymbIDByDerivID(it2->first.second)); + int lag = 0; + int block_eq = equation_2_block[eq]; + int block_var = variable_2_block[var]; + max_leadlag_block[block_eq] = make_pair(0, 0); + max_leadlag_block[block_eq] = make_pair(0, 0); + endo_max_leadlag_block[block_eq] = make_pair(0, 0); + endo_max_leadlag_block[block_eq] = make_pair(0, 0); + t_derivative tmp_derivative ; + t_lag_var lag_var; + if (getTypeByDerivID(it2->first.second) == eEndogenous && block_eq == block_var) + { + tmp_derivative = derivative_endo[block_eq]; + tmp_derivative[make_pair(lag, make_pair(eq, var))] = first_derivatives[make_pair(eq, getDerivID(symbol_table.getID(eEndogenous, var), lag))]; + derivative_endo[block_eq] = tmp_derivative; + } } - -#ifdef DEBUG - for(int i = 0; i < n; i++) - cout << "Endogenous " << symbol_table.getName(symbol_table.getID(eEndogenous, i)) - << " matched with equation " << (mate_map[i]-n+1) << endl; -#endif - - // Create the resulting map, by copying the n first elements of mate_map, and substracting n to them - endo2eq.resize(equation_number()); - transform(mate_map.begin(), mate_map.begin() + n, endo2eq.begin(), bind2nd(minus(), n)); - -#ifdef DEBUG - multimap natural_endo2eqs; - computeNormalizedEquations(natural_endo2eqs); - - int n1 = 0, n2 = 0; - - for(int i = 0; i < symbol_table.endo_nbr(); i++) - { - if (natural_endo2eqs.count(i) == 0) - continue; - - n1++; - - pair::const_iterator, multimap::const_iterator> x = natural_endo2eqs.equal_range(i); - if (find_if(x.first, x.second, compose1(bind2nd(equal_to(), endo2eq[i]), select2nd::value_type>())) == x.second) - cout << "Natural normalization of variable " << symbol_table.getName(symbol_table.getID(eEndogenous, i)) - << " not used." << endl; - else - n2++; - } - - cout << "Used " << n2 << " natural normalizations out of " << n1 << ", for a total of " << n << " equations." << endl; -#endif } void -StaticModel::computeNormalizedEquations(multimap &endo2eqs) const +StaticModel::writeChainRuleDerivative(ostream &output, int eqr, int varr, int lag, + ExprNodeOutputType output_type, + const temporary_terms_type &temporary_terms) const { - for(int i = 0; i < equation_number(); i++) - { - VariableNode *lhs = dynamic_cast(equations[i]->get_arg1()); - if (lhs == NULL) - continue; - - int symb_id = lhs->get_symb_id(); - if (symbol_table.getType(symb_id) != eEndogenous) - continue; - - set > endo; - equations[i]->get_arg2()->collectEndogenous(endo); - if (endo.find(make_pair(symbol_table.getTypeSpecificID(symb_id), 0)) != endo.end()) - continue; - - endo2eqs.insert(make_pair(symbol_table.getTypeSpecificID(symb_id), i)); - cout << "Endogenous " << symbol_table.getName(symb_id) << " normalized in equation " << (i+1) << endl; - } + map >, NodeID>::const_iterator it = first_chain_rule_derivatives.find(make_pair(eqr, make_pair(varr, lag))); + if (it != first_chain_rule_derivatives.end()) + (it->second)->writeOutput(output, output_type, temporary_terms); + else + output << 0; } + void StaticModel::writeLatexFile(const string &basename) const + { + writeLatexModelFile(basename + "_static.tex", oLatexStaticModel); + } + +void +StaticModel::jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const { - writeLatexModelFile(basename + "_static.tex", oLatexStaticModel); + output << LEFT_ARRAY_SUBSCRIPT(output_type); + if (IS_MATLAB(output_type)) + output << eq_nb + 1 << ", " << col_nb + 1; + else + output << eq_nb + col_nb * equations.size(); + output << RIGHT_ARRAY_SUBSCRIPT(output_type); } void -StaticModel::computeSortedBlockDecomposition() +StaticModel::hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const { - const int n = equation_number(); - - assert((int) endo2eq.size() == n); - - // Compute graph representation of static model - typedef adjacency_list DirectedGraph; - DirectedGraph g(n); - - set > endo; - for(int i = 0; i < n; i++) - { - endo.clear(); - equations[endo2eq[i]]->collectEndogenous(endo); - for(set >::const_iterator it = endo.begin(); - it != endo.end(); it++) - add_edge(it->first, i, g); - } - - // Compute strongly connected components - vector endo2block(n); - int m = strong_components(g, &endo2block[0]); - - // Create directed acyclic graph associated to the strongly connected components - DirectedGraph dag(m); - graph_traits::edge_iterator ei, ei_end; - for(tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) - { - int s = endo2block[source(*ei, g)]; - int t = endo2block[target(*ei, g)]; - if (s != t) - add_edge(s, t, dag); - } - - // Compute topological sort of DAG (ordered list of unordered SCC) - deque ordered2unordered; - topological_sort(dag, front_inserter(ordered2unordered)); // We use a front inserter because topological_sort returns the inverse order - // Construct mapping from unordered SCC to ordered SCC - vector unordered2ordered(m); - for(int i = 0; i < m; i++) - unordered2ordered[ordered2unordered[i]] = i; - - // Fill in data structure representing blocks - blocks.clear(); - blocks.resize(m); - for(int i = 0; i < n; i++) - blocks[unordered2ordered[endo2block[i]]].insert(i); - -#ifdef DEBUG - cout << "Found " << m << " blocks" << endl; - for(int i = 0; i < m; i++) - cout << " Block " << i << " of size " << blocks[i].size() << endl; -#endif -} - -void -StaticModel::computeMFS() -{ - const int n = equation_number(); - assert((int) endo2eq.size() == n); - - const int nblocks = blocks.size(); - blocksMFS.clear(); - blocksMFS.resize(nblocks); - - // Iterate over blocks - for(int b = 0; b < nblocks; b++) - { - // Construct subgraph for MFS computation, where vertex number is position in the block - int p = blocks[b].size(); - MFS::AdjacencyList_type g(p); - - // Construct v_index and v_index1 properties, and a mapping between type specific IDs and vertex descriptors - property_map::type v_index = get(vertex_index, g); - property_map::type v_index1 = get(vertex_index1, g); - map::vertex_descriptor> tsid2vertex; - int j = 0; - for(set::const_iterator it = blocks[b].begin(); it != blocks[b].end(); ++it) - { - tsid2vertex[*it] = vertex(j, g); - put(v_index, vertex(j, g), *it); - put(v_index1, vertex(j, g), *it); - j++; - } - - // Add edges, loop over endogenous in the block - set > endo; - for(set::const_iterator it = blocks[b].begin(); it != blocks[b].end(); ++it) - { - endo.clear(); - - // Test if associated equation is in normalized form, and compute set of endogenous appearing in it - ExprNode *lhs = equations[endo2eq[*it]]->get_arg1(); - VariableNode *lhs_var = dynamic_cast(lhs); - if (lhs_var == NULL || lhs_var->get_symb_id() != symbol_table.getID(eEndogenous, *it)) - lhs->collectEndogenous(endo); // Only collect endogenous of LHS if not normalized form - ExprNode *rhs = equations[endo2eq[*it]]->get_arg2(); - rhs->collectEndogenous(endo); - - for(set >::const_iterator it2 = endo.begin(); - it2 != endo.end(); ++it2) - if (blocks[b].find(it2->first) != blocks[b].end()) // Add edge only if vertex member of this block - add_edge(tsid2vertex[it2->first], tsid2vertex[*it], g); - } - - // Compute minimum feedback set - MFS::Minimal_set_of_feedback_vertex(blocksMFS[b], g); - -#ifdef DEBUG - cout << "Block " << b << ": " << blocksMFS[b].size() << "/" << blocks[b].size() << " in MFS" << endl; -#endif - } -} - -void -StaticModel::computeSortedRecursive() -{ - const int nblocks = blocks.size(); - blocksRecursive.clear(); - blocksRecursive.resize(nblocks); - - for(int b = 0; b < nblocks; b++) - { - // Construct the set of recursive vars - // The index in this vector will be the vertex descriptor in the graph - vector recurs_vars; - set_difference(blocks[b].begin(), blocks[b].end(), - blocksMFS[b].begin(), blocksMFS[b].end(), - back_inserter(recurs_vars)); - - // Construct graph representation of recursive vars - typedef adjacency_list DirectedGraph; - DirectedGraph dag(recurs_vars.size()); - set > endo; - for(int i = 0; i < (int) recurs_vars.size(); i++) - { - endo.clear(); - equations[endo2eq[recurs_vars[i]]]->get_arg2()->collectEndogenous(endo); - for(set >::const_iterator it = endo.begin(); - it != endo.end(); it++) - { - vector::const_iterator it2 = find(recurs_vars.begin(), recurs_vars.end(), it->first); - if (it2 != recurs_vars.end()) - { - int source_vertex = it2 - recurs_vars.begin(); - add_edge(source_vertex, i, dag); - } - } - } - // Compute topological sort - deque ordered_recurs_vertices; - topological_sort(dag, front_inserter(ordered_recurs_vertices)); // We use a front inserter because topological_sort returns the inverse order - - // Construct the final order - for(deque::const_iterator it = ordered_recurs_vertices.begin(); - it != ordered_recurs_vertices.end(); it++) - blocksRecursive[b].push_back(recurs_vars[*it]); - } -} - -void -StaticModel::computeBlockMFSJacobian() -{ - blocksMFSJacobian.clear(); - for(int b = 0; b < (int) blocks.size(); b++) - { - // Create the map of recursive vars to their normalized equation - map recursive2eq; - for(vector::const_iterator it = blocksRecursive[b].begin(); - it != blocksRecursive[b].end(); it++) - recursive2eq[symbol_table.getID(eEndogenous, *it)] = equations[endo2eq[*it]]; - - for(set::const_iterator it = blocksMFS[b].begin(); - it != blocksMFS[b].end(); it++) - { - int eq_no = endo2eq[*it]; - for(set::const_iterator it2 = blocksMFS[b].begin(); - it2 != blocksMFS[b].end(); it2++) - { - int deriv_id = symbol_table.getID(eEndogenous, *it2); - NodeID d = equations[eq_no]->getChainRuleDerivative(deriv_id, recursive2eq); - if (d != Zero) - blocksMFSJacobian[make_pair(eq_no, *it2)] = d; - } - } - } -} - -void -StaticModel::writeOutput(ostream &output, bool block) const -{ - if (!block) - return; - - output << "M_.blocksMFS = cell(" << blocksMFS.size() << ", 1);" << endl; - for(int b = 0; b < (int) blocks.size(); b++) - { - output << "M_.blocksMFS{" << b+1 << "} = [ "; - transform(blocksMFS[b].begin(), blocksMFS[b].end(), ostream_iterator(output, "; "), bind2nd(plus(), 1)); - output << "];" << endl; - } -} - -void -StaticModel::writeLocalVars(ostream &output, NodeID expr, set &local_var_written) const -{ - set expr_local_var; - expr->collectModelLocalVariables(expr_local_var); - vector new_local_var; - set_difference(expr_local_var.begin(), expr_local_var.end(), - local_var_written.begin(), local_var_written.end(), - back_inserter(new_local_var)); - - for(vector::const_iterator it = new_local_var.begin(); - it != new_local_var.end(); it++) - { - output << symbol_table.getName(*it) << " = "; - map::const_iterator it2 = local_variables_table.find(*it); - it2->second->writeOutput(output, oMatlabStaticModel, temporary_terms_type()); - output << ";" << endl; - local_var_written.insert(*it); - } -} - -void -StaticModel::writeStaticBlockMFSFile(ostream &output, const string &func_name) const -{ - output << "function [residual, g1, y] = " << func_name << "(nblock, y, x, params)" << endl - << " switch nblock" << endl; - - for(int b = 0; b < (int) blocks.size(); b++) - { - set local_var; - - output << " case " << b+1 << endl - << " % Variables not in minimum feedback set" << endl; - for(vector::const_iterator it = blocksRecursive[b].begin(); - it != blocksRecursive[b].end(); it++) - { - NodeID eq = equations[endo2eq[*it]]; - - writeLocalVars(output, eq, local_var); - - eq->writeOutput(output, oMatlabStaticModel, temporary_terms_type()); - output << ";" << endl; - } - - output << " % Model residuals" << endl - << "residual = zeros(" << blocksMFS[b].size() << ",1);" << endl; - - int i = 1; - for (set::const_iterator it = blocksMFS[b].begin(); - it != blocksMFS[b].end(); it++) - { - BinaryOpNode *eq = equations[endo2eq[*it]]; - - writeLocalVars(output, eq, local_var); - - output << "residual(" << i << ")=("; - - NodeID lhs = eq->get_arg1(); - lhs->writeOutput(output, oMatlabStaticModel, temporary_terms_type()); - output << ")-("; - - NodeID rhs = eq->get_arg2(); - rhs->writeOutput(output, oMatlabStaticModel, temporary_terms_type()); - output << ");" << endl; - - i++; - } - - output << " % Jacobian matrix" << endl - << "g1 = zeros(" << blocksMFS[b].size() << ", " << blocksMFS[b].size() << ");" << endl; - i = 1; - for (set::const_iterator it = blocksMFS[b].begin(); - it != blocksMFS[b].end(); it++) - { - int eq_no = endo2eq[*it]; - int j = 1; - for (set::const_iterator it2 = blocksMFS[b].begin(); - it2 != blocksMFS[b].end(); it2++) - { - map, NodeID>::const_iterator itd = blocksMFSJacobian.find(make_pair(eq_no, *it2)); - if (itd != blocksMFSJacobian.end()) - { - output << "g1(" << i << "," << j << ")="; - itd->second->writeOutput(output, oMatlabStaticModel, temporary_terms_type()); - output << ";" << endl; - } - j++; - } - i++; - } - } - - output << " end" << endl - << "end" << endl; + output << LEFT_ARRAY_SUBSCRIPT(output_type); + if (IS_MATLAB(output_type)) + output << row_nb + 1 << ", " << col_nb + 1; + else + output << row_nb + col_nb * NNZDerivatives[1]; + output << RIGHT_ARRAY_SUBSCRIPT(output_type); } void diff --git a/StaticModel.hh b/StaticModel.hh index a55e8cad..ae2da074 100644 --- a/StaticModel.hh +++ b/StaticModel.hh @@ -17,86 +17,166 @@ * along with Dynare. If not, see . */ -#ifndef _STATICMODEL_HH -#define _STATICMODEL_HH +#ifndef _STATIC_MODEL_HH +#define _STATIC_MODEL_HH + +using namespace std; + +#include #include "ModelTree.hh" //! Stores a static model -/*! Derivation IDs are allocated only for endogenous, and are equal to symbol ID in that case */ class StaticModel : public ModelTree { private: - //! Normalization of equations - /*! Maps endogenous type specific IDs to equation numbers */ - vector endo2eq; + typedef map, int> deriv_id_table_t; + //! Maps a pair (symbol_id, lag) to a deriv ID + deriv_id_table_t deriv_id_table; + //! Maps a deriv ID to a pair (symbol_id, lag) + vector > inv_deriv_id_table; - //! Block decomposition of the model - /*! List of blocks in topological order. Lists the set of endogenous type specific IDs for each block. */ - vector > blocks; + //! Temporary terms for the file containing parameters dervicatives + temporary_terms_type params_derivs_temporary_terms; - //! Minimum feedback set for each block - /*! Elements of blocksMFS are subset of elements of blocks */ - vector > blocksMFS; + //! Temporary terms for block decomposed models + vector > v_temporary_terms; - //! Variables not in minimum feedback set for each block, sorted in topological order - /*! This is the set difference blocks - blocksMFS. The variables are sorted in topological order. */ - vector > blocksRecursive; + vector v_temporary_terms_inuse; - //! Jacobian for matrix restricted to MFS - /*! Maps a pair (equation ID, endogenous type specific ID) to the derivative expression. Stores only non-null derivatives. */ - map, NodeID> blocksMFSJacobian; + + typedef map< pair< int, pair< int, int> >, NodeID> first_chain_rule_derivatives_type; + first_chain_rule_derivatives_type first_chain_rule_derivatives; //! Writes static model file (standard Matlab version) - void writeStaticMFile(ostream &output, const string &func_name) const; + void writeStaticMFile(const string &static_basename) const; - //! Writes static model file (block+MFS version) - void writeStaticBlockMFSFile(ostream &output, const string &func_name) const; + //! Writes the static function calling the block to solve (Matlab version) + void writeStaticBlockMFSFile(const string &basename) const; - //! Computes normalization of the static model - void computeNormalization(); - //! Computes blocks of the static model, sorted in topological order - /*! Must be called after computeNormalization() */ - void computeSortedBlockDecomposition(); + //! Writes static model file (C version) + /*! \todo add third derivatives handling */ + void writeStaticCFile(const string &static_basename) const; - //! For each block of the static model, computes minimum feedback set (MFS) - /*! Must be called after computeSortedBlockDecomposition() */ - void computeMFS(); + //! Writes the Block reordred structure of the model in M output + void writeModelEquationsOrdered_M(const string &dynamic_basename) const; - //! For each block of the static model, computes resursive variables (those not in minimum feedback set), and sort them in topological order - /*! Must be called after computeMFS() */ - void computeSortedRecursive(); + //! Writes the code of the Block reordred structure of the model in virtual machine bytecode + void writeModelEquationsCodeOrdered(const string file_name, const string bin_basename, map_idx_type map_idx) const; - //! Computes derivatives of each MFS - /*! Must be called after computeSortedRecursive() */ - void computeBlockMFSJacobian(); - - //! Computes the list of equations which are already in normalized form - /*! Returns a multimap mapping endogenous which are normalized (represented by their type specific ID) to the equation(s) which define it */ - void computeNormalizedEquations(multimap &endo2eqs) const; - - //! Helper for writing model local variables in block+MFS mode - /*! - Write the definition of model local variables which are used in expr, except those in local_var_written. - Add these variables to local_var_written at the end. + //! Computes jacobian and prepares for equation normalization + /*! Using values from initval/endval blocks and parameter initializations: + - computes the jacobian for the model w.r. to contemporaneous variables + - removes edges of the incidence matrix when derivative w.r. to the corresponding variable is too close to zero (below the cutoff) */ - void writeLocalVars(ostream &output, NodeID expr, set &local_var_written) const; + void evaluateJacobian(const eval_context_type &eval_context, jacob_map *j_m, bool dynamic); + + map_idx_type map_idx; + + void computeTemporaryTermsOrdered(); + //! Write derivative code of an equation w.r. to a variable + void compileDerivative(ofstream &code_file, int eq, int symb_id, int lag, map_idx_type &map_idx) const; + //! Write chain rule derivative code of an equation w.r. to a variable + void compileChainRuleDerivative(ofstream &code_file, int eq, int var, int lag, map_idx_type &map_idx) const; + + //! Get the type corresponding to a derivation ID + virtual SymbolType getTypeByDerivID(int deriv_id) const throw (UnknownDerivIDException); + //! Get the lag corresponding to a derivation ID + virtual int getLagByDerivID(int deriv_id) const throw (UnknownDerivIDException); + //! Get the symbol ID corresponding to a derivation ID + virtual int getSymbIDByDerivID(int deriv_id) const throw (UnknownDerivIDException); + //! Compute the column indices of the static Jacobian + void computeStatJacobianCols(); + //! return a map on the block jacobian + map >, pair >, int> get_Derivatives(int block); + //! Computes chain rule derivatives of the Jacobian w.r. to endogenous variables + void computeChainRuleJacobian(t_blocks_derivatives &blocks_derivatives); + //! Collect only the first derivatives + map >, NodeID> collect_first_order_derivatives_endogenous(); + + //! Helper for writing the Jacobian elements in MATLAB and C + /*! Writes either (i+1,j+1) or [i+j*no_eq] */ + void jacobianHelper(ostream &output, int eq_nb, int col_nb, ExprNodeOutputType output_type) const; + + //! Helper for writing the sparse Hessian elements in MATLAB and C + /*! Writes either (i+1,j+1) or [i+j*NNZDerivatives[1]] */ + void hessianHelper(ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const; + + //! Write chain rule derivative of a recursive equation w.r. to a variable + void writeChainRuleDerivative(ostream &output, int eq, int var, int lag, ExprNodeOutputType output_type, const temporary_terms_type &temporary_terms) const; + + //! Collecte the derivatives w.r. to endogenous of the block, to endogenous of previouys blocks and to exogenous + void collect_block_first_order_derivatives(); + +protected: + //! Indicate if the temporary terms are computed for the overall model (true) or not (false). Default value true + bool global_temporary_terms; + + //! vector of block reordered variables and equations + vector equation_reordered, variable_reordered, inv_equation_reordered, inv_variable_reordered; + + //! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a NodeID on the new normalized equation + t_equation_type_and_normalized_equation equation_type_and_normalized_equation; + + //! for each block contains pair< Simulation_Type, pair < Block_Size, Recursive_part_Size > > + t_block_type_firstequation_size_mfs block_type_firstequation_size_mfs; + + //! for all blocks derivatives description + t_blocks_derivatives blocks_derivatives; + + //! The jacobian without the elements below the cutoff + dynamic_jacob_map dynamic_jacobian; + + //! Vector indicating if the block is linear in endogenous variable (true) or not (false) + vector blocks_linear; + + //! Map the derivatives for a block pair + typedef map >, NodeID> t_derivative; + //! Vector of derivative for each blocks + vector derivative_endo, derivative_other_endo, derivative_exo, derivative_exo_det; + + //!List for each block and for each lag-leag all the other endogenous variables and exogenous variables + typedef set t_var; + typedef map t_lag_var; + vector other_endo_block, exo_block, exo_det_block; + + //!Maximum lead and lag for each block on endogenous of the block, endogenous of the previous blocks, exogenous and deterministic exogenous + vector > endo_max_leadlag_block, other_endo_max_leadlag_block, exo_max_leadlag_block, exo_det_max_leadlag_block, max_leadlag_block; public: StaticModel(SymbolTable &symbol_table_arg, NumericalConstants &num_constants); - //! Execute computations (derivation) - /*! - \param block whether block decomposition and minimum feedback set should be computed - \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 block, bool hessian, bool no_tmp_terms); //! Writes information on block decomposition when relevant void writeOutput(ostream &output, bool block) const; + //! Absolute value under which a number is considered to be zero + double cutoff; + //! Compute the minimum feedback set in the static model: + /*! 0 : all endogenous variables are considered as feedback variables + 1 : the variables belonging to a non linear equation are considered as feedback variables + 2 : the variables belonging to a non normalizable non linear equation are considered as feedback variables + default value = 0 */ + int mfs; + //! the file containing the model and the derivatives code + ofstream code_file; + //! Execute computations (variable sorting + derivation) + /*! + \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 paramsDerivatives whether 2nd derivatives w.r. to a pair (endo/exo/exo_det, parameter) 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 static files + */ + void computingPass(const eval_context_type &eval_context, bool no_tmp_terms, bool hessian, bool block); + + //! Adds informations for simulation in a binary file + void Write_Inf_To_Bin_File(const string &static_basename, const string &bin_basename, const int &num, + int &u_count_int, bool &file_open) const; + //! Writes static model file - void writeStaticFile(const string &basename, bool block) const; + void writeStaticFile(const string &basename, bool block, bool bytecode) const; //! Writes LaTeX file with the equations of the static model void writeLatexFile(const string &basename) const; @@ -105,6 +185,39 @@ public: void writeAuxVarInitval(ostream &output) const; virtual int getDerivID(int symb_id, int lag) const throw (UnknownDerivIDException); + + //! Return the number of blocks + virtual unsigned int getNbBlocks() const {return(block_type_firstequation_size_mfs.size());}; + //! Determine the simulation type of each block + virtual BlockSimulationType getBlockSimulationType(int block_number) const {return(block_type_firstequation_size_mfs[block_number].first.first);}; + //! Return the first equation number of a block + virtual unsigned int getBlockFirstEquation(int block_number) const {return(block_type_firstequation_size_mfs[block_number].first.second);}; + //! Return the size of the block block_number + virtual unsigned int getBlockSize(int block_number) const {return(block_type_firstequation_size_mfs[block_number].second.first);}; + //! Return the number of feedback variable of the block block_number + virtual unsigned int getBlockMfs(int block_number) const {return(block_type_firstequation_size_mfs[block_number].second.second);}; + //! Return the maximum lag in a block + virtual unsigned int getBlockMaxLag(int block_number) const {return(block_lag_lead[block_number].first);}; + //! Return the maximum lead in a block + virtual unsigned int getBlockMaxLead(int block_number) const {return(block_lag_lead[block_number].second);}; + //! Return the type of equation (equation_number) belonging to the block block_number + virtual EquationType getBlockEquationType(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first);}; + //! Return true if the equation has been normalized + virtual bool isBlockEquationRenormalized(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].first == E_EVALUATE_S);}; + //! Return the NodeID of the equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationNodeID(int block_number, int equation_number) const {return( equations[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]]);}; + //! Return the NodeID of the renormalized equation equation_number belonging to the block block_number + virtual NodeID getBlockEquationRenormalizedNodeID(int block_number, int equation_number) const {return( equation_type_and_normalized_equation[equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]].second);}; + //! Return the original number of equation equation_number belonging to the block block_number + virtual int getBlockEquationID(int block_number, int equation_number) const {return( equation_reordered[block_type_firstequation_size_mfs[block_number].first.second+equation_number]);}; + //! Return the original number of variable variable_number belonging to the block block_number + virtual int getBlockVariableID(int block_number, int variable_number) const {return( variable_reordered[block_type_firstequation_size_mfs[block_number].first.second+variable_number]);}; + //! Return the position of equation_number in the block number belonging to the block block_number + virtual int getBlockInitialEquationID(int block_number, int equation_number) const {return((int)inv_equation_reordered[equation_number] - (int)block_type_firstequation_size_mfs[block_number].first.second);}; + //! Return the position of variable_number in the block number belonging to the block block_number + virtual int getBlockInitialVariableID(int block_number, int variable_number) const {return((int)inv_variable_reordered[variable_number] - (int)block_type_firstequation_size_mfs[block_number].first.second);}; + + }; #endif