From 0ccc82300c3046d159554c24027ded09a93b687e Mon Sep 17 00:00:00 2001 From: Houtan Bastani Date: Mon, 6 Mar 2017 16:34:08 +0100 Subject: [PATCH] preprocessor: write equation cross references in JSON. #1387 --- preprocessor/DynamicModel.cc | 122 +++++++++++++++++++++++++++++++++++ preprocessor/DynamicModel.hh | 17 ++++- preprocessor/ExprNode.cc | 81 +++++++++++++++++++++++ preprocessor/ExprNode.hh | 18 ++++++ preprocessor/ModFile.cc | 3 + 5 files changed, 240 insertions(+), 1 deletion(-) diff --git a/preprocessor/DynamicModel.cc b/preprocessor/DynamicModel.cc index 10db3a8b9..c05529c48 100644 --- a/preprocessor/DynamicModel.cc +++ b/preprocessor/DynamicModel.cc @@ -5342,6 +5342,127 @@ void DynamicModel::writeJsonOutput(ostream &output) const { writeJsonModelEquations(output, false); + output << ", "; + writeJsonXrefs(output); +} + +void +DynamicModel::writeJsonXrefs(ostream &output) const +{ + output << "\"xrefs\": {" + << "\"parameters\": ["; + for (map, set >::const_iterator it = json_xref_param.begin(); + it != json_xref_param.end(); it++) + { + if (it != json_xref_param.begin()) + output << ", "; + output << "{\"parameter\": \"" << symbol_table.getName(it->first.first) << "\"" + << ", \"equations\": ["; + for (set::const_iterator it1 = it->second.begin(); + it1 != it->second.end(); it1++) + { + if (it1 != it->second.begin()) + output << ", "; + output << *it1 + 1; + } + output << "]}"; + } + output << "]" + << ", \"endogenous\": ["; + for (map, set >::const_iterator it = json_xref_endo.begin(); + it != json_xref_endo.end(); it++) + { + if (it != json_xref_endo.begin()) + output << ", "; + output << "{\"endogenous\": \"" << symbol_table.getName(it->first.first) << "\"" + << ", \"shift\": " << it->first.second + << ", \"equations\": ["; + for (set::const_iterator it1 = it->second.begin(); + it1 != it->second.end(); it1++) + { + if (it1 != it->second.begin()) + output << ", "; + output << *it1 + 1; + } + output << "]}"; + } + output << "]" + << ", \"exogenous\": ["; + for (map, set >::const_iterator it = json_xref_exo.begin(); + it != json_xref_exo.end(); it++) + { + if (it != json_xref_exo.begin()) + output << ", "; + output << "{\"exogenous\": \"" << symbol_table.getName(it->first.first) << "\"" + << ", \"shift\": " << it->first.second + << ", \"equations\": ["; + for (set::const_iterator it1 = it->second.begin(); + it1 != it->second.end(); it1++) + { + if (it1 != it->second.begin()) + output << ", "; + output << *it1 + 1; + } + output << "]}"; + } + output << "]" + << ", \"exogenous_deterministic\": ["; + for (map, set >::const_iterator it = json_xref_exo_det.begin(); + it != json_xref_exo_det.end(); it++) + { + if (it != json_xref_exo_det.begin()) + output << ", "; + output << "{\"exogenous_det\": \"" << symbol_table.getName(it->first.first) << "\"" + << ", \"shift\": " << it->first.second + << ", \"equations\": ["; + for (set::const_iterator it1 = it->second.begin(); + it1 != it->second.end(); it1++) + { + if (it1 != it->second.begin()) + output << ", "; + output << *it1 + 1; + } + output << "]}"; + } + output << "]}" << endl; +} + +void +DynamicModel::computeJsonXrefs() +{ + map xrefs; + int i = 0; + for (vector::iterator it = equations.begin(); + it != equations.end(); it++) + { + ExprNode::JsonEquationInfo ei; + (*it)->computeJsonXrefs(ei); + xrefs[i++] = ei; + } + + i = 0; + for (map::const_iterator it = xrefs.begin(); + it != xrefs.end(); it++, i++) + { + computeJsonRevXref(json_xref_param, it->second.param, i); + computeJsonRevXref(json_xref_endo, it->second.endo, i); + computeJsonRevXref(json_xref_exo, it->second.exo, i); + computeJsonRevXref(json_xref_exo_det, it->second.exo_det, i); + } +} + +void +DynamicModel::computeJsonRevXref(map, set > &xrefset, const set > &eiref, int eqn) +{ + for (set >::const_iterator it = eiref.begin(); + it != eiref.end(); it++) + { + set eq; + if (xrefset.find(*it) != xrefset.end()) + eq = xrefset[*it]; + eq.insert(eqn); + xrefset[*it] = eq; + } } void @@ -5721,3 +5842,4 @@ DynamicModel::writeJsonParamsDerivativesFile(ostream &output, bool writeDetails) << ", " << third_derivs1_output.str() << "}"; } + diff --git a/preprocessor/DynamicModel.hh b/preprocessor/DynamicModel.hh index b0828a2b2..cec66d97e 100644 --- a/preprocessor/DynamicModel.hh +++ b/preprocessor/DynamicModel.hh @@ -62,6 +62,12 @@ private: /*! Set by computeDerivIDs() */ int max_exo_det_lag, max_exo_det_lead; + //! Cross references WITH lags (for #1387, potentially combine with cross references above upon decision by @michel) + map, set > json_xref_param; + map, set > json_xref_endo; + map, set > json_xref_exo; + map, set > json_xref_exo_det; + //! Number of columns of dynamic jacobian /*! Set by computeDerivID()s and computeDynJacobianCols() */ int dynJacobianColsNbr; @@ -189,6 +195,9 @@ private: /*! pair< pair, pair > */ vector, pair > > block_col_type; + //! Related to public function computeJsonXref + void computeJsonRevXref(map, set > &xrefset, const set > &eiref, int eqn); + //! List for each variable its block number and its maximum lag and lead inside the block vector > > variable_block_lead_lag; //! List for each equation its block number @@ -202,7 +211,10 @@ public: //! Adds a variable node /*! This implementation allows for non-zero lag */ virtual VariableNode *AddVariable(int symb_id, int lag = 0); - + + //! For computing cross references for json output (i.e. that contains lag information) #1387 + void computeJsonXrefs(); + //! 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) @@ -220,6 +232,9 @@ public: //! Write JSON Output void writeJsonOutput(ostream &output) const; + //! Write cross reference output if the xref maps have been filed + void writeJsonXrefs(ostream &output) const; + //! Write JSON Output representation of dynamic model after computing pass void writeJsonComputingPassOutput(ostream &output, bool writeDetails) const; diff --git a/preprocessor/ExprNode.cc b/preprocessor/ExprNode.cc index 5cc0298bd..dfb66d3df 100644 --- a/preprocessor/ExprNode.cc +++ b/preprocessor/ExprNode.cc @@ -396,6 +396,11 @@ NumConstNode::computeXrefs(EquationInfo &ei) const { } +void +NumConstNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ +} + expr_t NumConstNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -1131,6 +1136,34 @@ VariableNode::computeXrefs(EquationInfo &ei) const } } +void +VariableNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + switch (type) + { + case eEndogenous: + ei.endo.insert(make_pair(symb_id, lag)); + break; + case eExogenous: + ei.exo.insert(make_pair(symb_id, lag)); + break; + case eExogenousDet: + ei.exo_det.insert(make_pair(symb_id, lag)); + break; + case eParameter: + ei.param.insert(make_pair(symb_id, 0)); + break; + case eTrend: + case eLogTrend: + case eModelLocalVariable: + case eModFileLocalVariable: + case eStatementDeclaredVariable: + case eUnusedEndogenous: + case eExternalFunction: + break; + } +} + expr_t VariableNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -2558,6 +2591,12 @@ UnaryOpNode::computeXrefs(EquationInfo &ei) const arg->computeXrefs(ei); } +void +UnaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + arg->computeJsonXrefs(ei); +} + expr_t UnaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -3994,6 +4033,13 @@ BinaryOpNode::computeXrefs(EquationInfo &ei) const arg2->computeXrefs(ei); } +void +BinaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + arg1->computeJsonXrefs(ei); + arg2->computeJsonXrefs(ei); +} + expr_t BinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -4761,6 +4807,14 @@ TrinaryOpNode::computeXrefs(EquationInfo &ei) const arg3->computeXrefs(ei); } +void +TrinaryOpNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + arg1->computeJsonXrefs(ei); + arg2->computeJsonXrefs(ei); + arg3->computeJsonXrefs(ei); +} + expr_t TrinaryOpNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -5644,6 +5698,15 @@ ExternalFunctionNode::computeXrefs(EquationInfo &ei) const (*it)->computeXrefs(ei); } +void +ExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeJsonXrefs(ei); +} + expr_t ExternalFunctionNode::cloneDynamic(DataTree &dynamic_datatree) const { @@ -6044,6 +6107,15 @@ FirstDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const (*it)->computeXrefs(ei); } +void +FirstDerivExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeJsonXrefs(ei); +} + SecondDerivExternalFunctionNode::SecondDerivExternalFunctionNode(DataTree &datatree_arg, int top_level_symb_id_arg, const vector &arguments_arg, @@ -6359,6 +6431,15 @@ SecondDerivExternalFunctionNode::computeXrefs(EquationInfo &ei) const (*it)->computeXrefs(ei); } +void +SecondDerivExternalFunctionNode::computeJsonXrefs(JsonEquationInfo &ei) const +{ + vector dynamic_arguments; + for (vector::const_iterator it = arguments.begin(); + it != arguments.end(); it++) + (*it)->computeJsonXrefs(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 e4e5d9bcd..c6dca0352 100644 --- a/preprocessor/ExprNode.hh +++ b/preprocessor/ExprNode.hh @@ -171,6 +171,14 @@ protected: set exo_det; }; + struct JsonEquationInfo + { + set > param; + set > endo; + set > exo; + set > exo_det; + }; + public: ExprNode(DataTree &datatree_arg); virtual ~ExprNode(); @@ -310,6 +318,7 @@ public: */ // virtual void computeXrefs(set ¶m, set &endo, set &exo, set &exo_det) const = 0; virtual void computeXrefs(EquationInfo &ei) const = 0; + virtual void computeJsonXrefs(JsonEquationInfo &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; @@ -497,6 +506,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; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &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; @@ -553,6 +563,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; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &ei) const; SymbolType get_type() const { @@ -652,6 +663,7 @@ public: }; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &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; @@ -756,6 +768,7 @@ public: } virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &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; @@ -841,6 +854,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; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &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; @@ -928,6 +942,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 void computeJsonXrefs(JsonEquationInfo &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; @@ -989,6 +1004,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; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &ei) const; virtual expr_t buildSimilarExternalFunctionNode(vector &alt_args, DataTree &alt_datatree) const; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const; }; @@ -1030,6 +1046,7 @@ public: deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &ei) const; virtual expr_t buildSimilarExternalFunctionNode(vector &alt_args, DataTree &alt_datatree) const; virtual expr_t cloneDynamic(DataTree &dynamic_datatree) const; }; @@ -1073,6 +1090,7 @@ public: deriv_node_temp_terms_t &tef_terms) const; virtual expr_t toStatic(DataTree &static_datatree) const; virtual void computeXrefs(EquationInfo &ei) const; + virtual void computeJsonXrefs(JsonEquationInfo &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/ModFile.cc b/preprocessor/ModFile.cc index 7ee204ad4..ea9cf4e37 100644 --- a/preprocessor/ModFile.cc +++ b/preprocessor/ModFile.cc @@ -414,6 +414,9 @@ ModFile::transformPass(bool nostrict) // Freeze the symbol table symbol_table.freeze(); + //! Need access to this info after transform pass so calculate it here + dynamic_model.computeJsonXrefs(); + /* Enforce the same number of equations and endogenous, except in three cases: - ramsey_model, ramsey_policy or discretionary_policy is used