diff --git a/matlab/global_initialization.m b/matlab/global_initialization.m index dd3cf7176..c927b2ab2 100644 --- a/matlab/global_initialization.m +++ b/matlab/global_initialization.m @@ -510,6 +510,11 @@ M_.Correlation_matrix = []; M_.Correlation_matrix_ME = []; M_.parameter_used_with_lead_lag = false; +M_.xref1.params = {}; +M_.xref1.endo = {}; +M_.xref1.exo = {}; +M_.xref1.exo_det = {}; + % homotopy for steady state options_.homotopy_mode = 0; options_.homotopy_steps = 1; diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index d7e744960..2d4943ccc 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -3049,6 +3049,8 @@ DynamicModel::writeOutput(ostream &output, const string &basename, bool block_de output << modstruct << "params = " << (julia ? "fill(NaN, " : "NaN(") << symbol_table.param_nbr() << ", 1);" << endl; + writeXrefs(output); + // Write number of non-zero derivatives // Use -1 if the derivatives have not been computed output << modstruct << (julia ? "nnzderivatives" : "NNZDerivatives") @@ -3200,6 +3202,8 @@ DynamicModel::computingPass(bool jacobianExo, bool hessian, bool thirdDerivative if (bytecode) computeTemporaryTermsMapping(); } + + computeXrefs(); } map >, pair >, int> diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc index 9fd0c0ebd..8e60eea1d 100644 --- a/preprocessor/ExprNode.cc +++ b/preprocessor/ExprNode.cc @@ -354,6 +354,11 @@ NumConstNode::toStatic(DataTree &static_datatree) const return static_datatree.AddNonNegativeConstant(datatree.num_constants.get(id)); } +void +NumConstNode::computeXrefs(EquationInfo &ei) const +{ +} + expr_t NumConstNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -1015,6 +1020,34 @@ VariableNode::toStatic(DataTree &static_datatree) const return static_datatree.AddVariable(symb_id); } +void +VariableNode::computeXrefs(EquationInfo &ei) const +{ + switch (type) + { + case eEndogenous: + ei.endo.insert(symb_id); + break; + case eExogenous: + ei.exo.insert(symb_id); + break; + case eExogenousDet: + ei.exo_det.insert(symb_id); + break; + case eParameter: + ei.param.insert(symb_id); + break; + case eTrend: + case eLogTrend: + case eModelLocalVariable: + case eModFileLocalVariable: + case eStatementDeclaredVariable: + case eUnusedEndogenous: + case eExternalFunction: + break; + } +} + expr_t VariableNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -2269,6 +2302,12 @@ UnaryOpNode::toStatic(DataTree &static_datatree) const return buildSimilarUnaryOpNode(sarg, static_datatree); } +void +UnaryOpNode::computeXrefs(EquationInfo &ei) const +{ + arg->computeXrefs(ei); +} + expr_t UnaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -3496,6 +3535,13 @@ BinaryOpNode::toStatic(DataTree &static_datatree) const return buildSimilarBinaryOpNode(sarg1, sarg2, static_datatree); } +void +BinaryOpNode::computeXrefs(EquationInfo &ei) const +{ + arg1->computeXrefs(ei); + arg2->computeXrefs(ei); +} + expr_t BinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -4172,6 +4218,14 @@ TrinaryOpNode::toStatic(DataTree &static_datatree) const return buildSimilarTrinaryOpNode(sarg1, sarg2, sarg3, static_datatree); } +void +TrinaryOpNode::computeXrefs(EquationInfo &ei) const +{ + arg1->computeXrefs(ei); + arg2->computeXrefs(ei); + arg3->computeXrefs(ei); +} + expr_t TrinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -4944,6 +4998,15 @@ ExternalFunctionNode::toStatic(DataTree &static_datatree) const return static_datatree.AddExternalFunction(symb_id, static_arguments); } +void +ExternalFunctionNode::computeXrefs(EquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeXrefs(ei); +} + expr_t ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -5266,6 +5329,15 @@ FirstDerivExternalFunctionNode::toStatic(DataTree &static_datatree) const inputIndex); } +void +FirstDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeXrefs(ei); +} + SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg, int top_level_symb_id_arg, const vector &arguments_arg, @@ -5501,6 +5573,15 @@ SecondDerivExternalFunctionNode::toStatic(DataTree &static_datatree) const inputIndex1, inputIndex2); } +void +SecondDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeXrefs(ei); +} + void SecondDerivExternalFunctionNode::compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, diff --git a/preprocessor/ExprNode.hh b/preprocessor/ExprNode.hh index 526e98427..98f59800f 100644 --- a/preprocessor/ExprNode.hh +++ b/preprocessor/ExprNode.hh @@ -159,6 +159,15 @@ protected: /*! Nodes included in temporary_terms are considered having a null cost */ virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const; + //! For creating equation cross references + struct EquationInfo + { + set param; + set endo; + set exo; + set exo_det; + }; + public: ExprNode(DataTree &datatree_arg); virtual ~ExprNode(); @@ -279,6 +288,12 @@ public: adds the result in the static_datatree argument (and not in the original datatree), and returns it. */ virtual expr_t toStatic(DataTree &static_datatree) const = 0; + + /*! + Compute cross references for equations + */ + // virtual void computeXrefs(set ¶m, set &endo, set &exo, set &exo_det) const = 0; + virtual void computeXrefs(EquationInfo &ei) const = 0; //! Try to normalize an equation linear in its endogenous variable virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const = 0; @@ -458,6 +473,7 @@ public: virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException); virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const; virtual expr_t getChainRuleDerivative(int deriv_id, const map &recursive_variables); virtual int maxEndoLead() const; @@ -510,6 +526,7 @@ public: virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException); virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; SymbolType get_type() const { @@ -597,6 +614,7 @@ public: return (op_code); }; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const; virtual expr_t getChainRuleDerivative(int deriv_id, const map &recursive_variables); virtual int maxEndoLead() const; @@ -688,6 +706,7 @@ public: return powerDerivOrder; } virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const; virtual expr_t getChainRuleDerivative(int deriv_id, const map &recursive_variables); virtual int maxEndoLead() const; @@ -759,6 +778,7 @@ public: virtual double eval(const eval_context_t &eval_context) const throw (EvalException, EvalExternalFunctionException); virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const; virtual expr_t getChainRuleDerivative(int deriv_id, const map &recursive_variables); virtual int maxEndoLead() const; @@ -835,6 +855,7 @@ public: virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const = 0; virtual expr_t toStatic(DataTree &static_datatree) const = 0; + virtual void computeXrefs(EquationInfo &ei) const = 0; virtual pair normalizeEquation(int symb_id_endo, vector > > &List_of_Op_RHS) const; virtual expr_t getChainRuleDerivative(int deriv_id, const map &recursive_variables); virtual int maxEndoLead() const; @@ -886,6 +907,7 @@ public: int equation) const; virtual void compile(ostream &CompileCode, unsigned int &instruction_number, bool lhs_rhs, const temporary_terms_t &temporary_terms, const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual expr_t buildSimilarExternalFunctionNode(vector &alt_args, DataTree &alt_datatree) const; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const; }; @@ -920,6 +942,7 @@ public: const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual expr_t buildSimilarExternalFunctionNode(vector &alt_args, DataTree &alt_datatree) const; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const; }; @@ -956,6 +979,7 @@ public: const map_idx_t &map_idx, bool dynamic, bool steady_dynamic, deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; + virtual void computeXrefs(EquationInfo &ei) const; virtual expr_t buildSimilarExternalFunctionNode(vector &alt_args, DataTree &alt_datatree) const; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const; }; diff --git a/preprocessor/ModelTree.cc b/preprocessor/ModelTree.cc index 21c2d509e..3f2bcbcc6 100644 --- a/preprocessor/ModelTree.cc +++ b/preprocessor/ModelTree.cc @@ -229,6 +229,51 @@ ModelTree::computeNonSingularNormalization(jacob_map_t &contemporaneous_jacobian } } +void +ModelTree::computeXrefs() +{ + int i = 0; + for (vector::iterator it = equations.begin(); + it != equations.end(); it++) + { + ExprNode::EquationInfo ei; + (*it)->computeXrefs(ei); + xrefs[i++] = ei; + } +} + +void +ModelTree::writeXrefs(ostream &output) const +{ + for (map::const_iterator it = xrefs.begin(); + it != xrefs.end(); it++) + { + output << "M_.xref1.params{end+1} = [ "; + for (set::const_iterator it1 = it->second.param.begin(); + it1 != it->second.param.end(); it1++) + output << symbol_table.getTypeSpecificID(*it1) + 1 << " "; + output << "];" << endl; + + output << "M_.xref1.endo{end+1} = [ "; + for (set::const_iterator it1 = it->second.endo.begin(); + it1 != it->second.endo.end(); it1++) + output << symbol_table.getTypeSpecificID(*it1) + 1 << " "; + output << "];" << endl; + + output << "M_.xref1.exo{end+1} = [ "; + for (set::const_iterator it1 = it->second.exo.begin(); + it1 != it->second.exo.end(); it1++) + output << symbol_table.getTypeSpecificID(*it1) + 1 << " "; + output << "];" << endl; + + output << "M_.xref1.exo_det{end+1} = [ "; + for (set::const_iterator it1 = it->second.exo_det.begin(); + it1 != it->second.exo_det.end(); it1++) + output << symbol_table.getTypeSpecificID(*it1) + 1 << " "; + output << "];" << endl; + } +} + void ModelTree::computeNormalizedEquations(multimap &endo2eqs) const { diff --git a/preprocessor/ModelTree.hh b/preprocessor/ModelTree.hh index ea799585c..bb6ffb3fe 100644 --- a/preprocessor/ModelTree.hh +++ b/preprocessor/ModelTree.hh @@ -99,6 +99,8 @@ protected: */ first_derivatives_t residuals_params_derivatives; + map xrefs; + //! Second derivatives of the residuals w.r. to parameters /*! First index is equation number, second and third indeces are parameters. Only non-null derivatives are stored in the map. @@ -220,6 +222,10 @@ protected: //! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS) void computeNormalizedEquations(multimap &endo2eqs) const; + //! Compute cross references + void computeXrefs(); + //! Write cross references + void writeXrefs(ostream &output) const; //! Evaluate the jacobian and suppress all the elements below the cutoff void evaluateAndReduceJacobian(const eval_context_t &eval_context, jacob_map_t &contemporaneous_jacobian, jacob_map_t &static_jacobian, dynamic_jacob_map_t &dynamic_jacobian, double cutoff, bool verbose); //! Search the equations and variables belonging to the prologue and the epilogue of the model @@ -319,7 +325,6 @@ public: /*! If order=2, writes either v2(i+1,j+1) or v2[i+j*NNZDerivatives[1]] If order=3, writes either v3(i+1,j+1) or v3[i+j*NNZDerivatives[2]] */ void sparseHelper(int order, ostream &output, int row_nb, int col_nb, ExprNodeOutputType output_type) const; - inline static std::string c_Equation_Type(int type) {