1 /*
2  * Copyright © 2007-2019 Dynare Team
3  *
4  * This file is part of Dynare.
5  *
6  * Dynare is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * Dynare is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef _EXPR_NODE_HH
21 #define _EXPR_NODE_HH
22 
23 #include <set>
24 #include <map>
25 #include <vector>
26 #include <ostream>
27 #include <functional>
28 
29 using namespace std;
30 
31 #include "CodeInterpreter.hh"
32 #include "ExternalFunctionsTable.hh"
33 
34 class DataTree;
35 class NumConstNode;
36 class VariableNode;
37 class UnaryOpNode;
38 class BinaryOpNode;
39 class PacExpectationNode;
40 
41 using expr_t = class ExprNode *;
42 
43 struct ExprNodeLess;
44 
45 //! Type for set of temporary terms
46 /*! The ExprNodeLess ordering is important for the temporary terms algorithm,
47   see the definition of ExprNodeLess */
48 using temporary_terms_t = set<expr_t, ExprNodeLess>;
49 /*! Keeps track of array indices of temporary_terms for writing */
50 using temporary_terms_idxs_t = map<expr_t, int>;
51 
52 //! set of temporary terms used in a block
53 using temporary_terms_inuse_t = set<int>;
54 
55 using map_idx_t = map<int, int>;
56 
57 //! Type for evaluation contexts
58 /*! The key is a symbol id. Lags are assumed to be null */
59 using eval_context_t = map<int, double>;
60 
61 //! Type for tracking first/second derivative functions that have already been written as temporary terms
62 using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
63 
64 //! Type for the substitution map used for creating aux. vars for diff and unary_ops
65 /*! Let ≅ be the equivalence relationship such that two expressions e₁ and e₂
66     are equivalent iff e₁ can be obtained from e₂ by shifting all leads/lags by
67     the same number of periods (e.g. x₋₁+y₂≅x₁+y₄).
68 
69     For each equivalence class, we select a representative element, which is
70     the class member which has no lead and a variable appearing at current
71     period (in the previous example, it would be x₋₃+y). (Obviously, if there
72     is no variable in the expression, then there is only one element in the
73     class, and that one is the representative)
74 
75     Each member of an equivalence class is represented by an integer,
76     corresponding to its distance to the representative element (e.g. x₋₁+y₂
77     has index 2 and x₁+y₄ has index 4). The representative element has index 0
78     by definition.
79 
80     The keys in the std::map are the representative elements of the various
81     equivalence classes. The values are themselves std::map that describe the
82     equivalence class: they associate indices of class members to the
83     expressions with which they should be substituted. */
84 using lag_equivalence_table_t = map<expr_t, map<int, expr_t>>;
85 
86 //! Possible types of output when writing ExprNode(s)
87 enum class ExprNodeOutputType
88   {
89    matlabStaticModel, //!< Matlab code, static model
90    matlabDynamicModel, //!< Matlab code, dynamic model
91    matlabStaticModelSparse, //!< Matlab code, static block decomposed model
92    matlabDynamicModelSparse, //!< Matlab code, dynamic block decomposed model
93    CDynamicModel, //!< C code, dynamic model
94    CStaticModel, //!< C code, static model
95    juliaStaticModel, //!< Julia code, static model
96    juliaDynamicModel, //!< Julia code, dynamic model
97    matlabOutsideModel, //!< Matlab code, outside model block (for example in initval)
98    latexStaticModel, //!< LaTeX code, static model
99    latexDynamicModel, //!< LaTeX code, dynamic model
100    latexDynamicSteadyStateOperator, //!< LaTeX code, dynamic model, inside a steady state operator
101    matlabDynamicSteadyStateOperator, //!< Matlab code, dynamic model, inside a steady state operator
102    matlabDynamicSparseSteadyStateOperator, //!< Matlab code, dynamic block decomposed model, inside a steady state operator
103    CDynamicSteadyStateOperator, //!< C code, dynamic model, inside a steady state operator
104    juliaDynamicSteadyStateOperator, //!< Julia code, dynamic model, inside a steady state operator
105    steadyStateFile, //!< Matlab code, in the generated steady state file
106    juliaSteadyStateFile, //!< Julia code, in the generated steady state file
107    matlabDseries, //!< Matlab code for dseries
108    epilogueFile //!< Matlab code, in the generated epilogue file
109   };
110 
111 inline bool
isMatlabOutput(ExprNodeOutputType output_type)112 isMatlabOutput(ExprNodeOutputType output_type)
113 {
114   return output_type == ExprNodeOutputType::matlabStaticModel
115     || output_type == ExprNodeOutputType::matlabDynamicModel
116     || output_type == ExprNodeOutputType::matlabOutsideModel
117     || output_type == ExprNodeOutputType::matlabStaticModelSparse
118     || output_type == ExprNodeOutputType::matlabDynamicModelSparse
119     || output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
120     || output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
121     || output_type == ExprNodeOutputType::steadyStateFile
122     || output_type == ExprNodeOutputType::matlabDseries
123     || output_type == ExprNodeOutputType::epilogueFile;
124 }
125 
126 inline bool
isJuliaOutput(ExprNodeOutputType output_type)127 isJuliaOutput(ExprNodeOutputType output_type)
128 {
129   return output_type == ExprNodeOutputType::juliaStaticModel
130     || output_type == ExprNodeOutputType::juliaDynamicModel
131     || output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
132     || output_type == ExprNodeOutputType::juliaSteadyStateFile;
133 }
134 
135 inline bool
isCOutput(ExprNodeOutputType output_type)136 isCOutput(ExprNodeOutputType output_type)
137 {
138   return output_type == ExprNodeOutputType::CDynamicModel
139     || output_type == ExprNodeOutputType::CStaticModel
140     || output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
141 }
142 
143 inline bool
isLatexOutput(ExprNodeOutputType output_type)144 isLatexOutput(ExprNodeOutputType output_type)
145 {
146   return output_type == ExprNodeOutputType::latexStaticModel
147     || output_type == ExprNodeOutputType::latexDynamicModel
148     || output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator;
149 }
150 
151 /* Equal to 1 for Matlab langage or Julia, or to 0 for C language. Not defined for LaTeX.
152    In Matlab and Julia, array indexes begin at 1, while they begin at 0 in C */
153 inline int
ARRAY_SUBSCRIPT_OFFSET(ExprNodeOutputType output_type)154 ARRAY_SUBSCRIPT_OFFSET(ExprNodeOutputType output_type)
155 {
156   return static_cast<int>(isMatlabOutput(output_type) || isJuliaOutput(output_type));
157 }
158 
159 // Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
160 inline char
LEFT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)161 LEFT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
162 {
163   return isMatlabOutput(output_type) ? '(' : '[';
164 }
165 
166 inline char
RIGHT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)167 RIGHT_ARRAY_SUBSCRIPT(ExprNodeOutputType output_type)
168 {
169   return isMatlabOutput(output_type) ? ')' : ']';
170 }
171 
172 // Left and right parentheses
173 inline string
LEFT_PAR(ExprNodeOutputType output_type)174 LEFT_PAR(ExprNodeOutputType output_type)
175 {
176   return isLatexOutput(output_type) ? "\\left(" : "(";
177 }
178 
179 inline string
RIGHT_PAR(ExprNodeOutputType output_type)180 RIGHT_PAR(ExprNodeOutputType output_type)
181 {
182   return isLatexOutput(output_type) ? "\\right)" : ")";
183 }
184 
185 //! Base class for expression nodes
186 class ExprNode
187 {
188   friend class DataTree;
189   friend class DynamicModel;
190   friend class StaticModel;
191   friend class ModelTree;
192   friend struct ExprNodeLess;
193   friend class NumConstNode;
194   friend class VariableNode;
195   friend class UnaryOpNode;
196   friend class BinaryOpNode;
197   friend class TrinaryOpNode;
198   friend class AbstractExternalFunctionNode;
199   friend class VarExpectationNode;
200   friend class PacExpectationNode;
201 private:
202   //! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
203   /*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
204   virtual expr_t computeDerivative(int deriv_id) = 0;
205 
206 protected:
207   //! Reference to the enclosing DataTree
208   DataTree &datatree;
209 
210   //! Index number
211   const int idx;
212 
213   //! Is the data member non_null_derivatives initialized ?
214   bool preparedForDerivation{false};
215 
216   //! Set of derivation IDs with respect to which the derivative is potentially non-null
217   set<int> non_null_derivatives;
218 
219   //! Used for caching of first order derivatives (when non-null)
220   map<int, expr_t> derivatives;
221 
222   constexpr static int min_cost_matlab{40*90};
223   constexpr static int min_cost_c{40*4};
224   inline static int
min_cost(bool is_matlab)225   min_cost(bool is_matlab)
226   {
227     return (is_matlab ? min_cost_matlab : min_cost_c);
228   };
229 
230   //! Cost of computing current node
231   /*! Nodes included in temporary_terms are considered having a null cost */
232   virtual int cost(int cost, bool is_matlab) const;
233   virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const;
234   virtual int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const;
235 
236   //! For creating equation cross references
237   struct EquationInfo
238   {
239     set<pair<int, int>> param;
240     set<pair<int, int>> endo;
241     set<pair<int, int>> exo;
242     set<pair<int, int>> exo_det;
243   };
244 
245   //! If this node is a temporary term, writes its temporary term representation
246   /*! Returns true if node is a temporary term and has therefore been
247     written to output*/
248   bool checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
249                                      const temporary_terms_t &temporary_terms,
250                                      const temporary_terms_idxs_t &temporary_terms_idxs) const;
251 
252   // Internal helper for matchVariableTimesConstantTimesParam()
253   virtual void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const;
254 
255   /* Computes the representative element and the index under the
256      lag-equivalence relationship. See the comment above
257      lag_equivalence_table_t for an explanation of these concepts. */
258   pair<expr_t, int> getLagEquivalenceClass() const;
259 
260 public:
261   ExprNode(DataTree &datatree_arg, int idx_arg);
262   virtual ~ExprNode() = default;
263 
264   ExprNode(const ExprNode &) = delete;
265   ExprNode(ExprNode &&) = delete;
266   ExprNode &operator=(const ExprNode &) = delete;
267   ExprNode &operator=(ExprNode &&) = delete;
268 
269   //! Initializes data member non_null_derivatives
270   virtual void prepareForDerivation() = 0;
271 
272   //! Returns derivative w.r. to derivation ID
273   /*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other derivatives (to avoid computing it several times)
274     For an equal node, returns the derivative of lhs minus rhs */
275   expr_t getDerivative(int deriv_id);
276 
277   //! Computes derivatives by applying the chain rule for some variables
278   /*!
279     \param deriv_id The derivation ID with respect to which we are derivating
280     \param recursive_variables Contains the derivation ID for which chain rules must be applied. Keys are derivation IDs, values are equations of the form x=f(y) where x is the key variable and x doesn't appear in y
281   */
282   virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) = 0;
283 
284   //! Returns precedence of node
285   /*! Equals 100 for constants, variables, unary ops, and temporary terms */
286   virtual int precedence(ExprNodeOutputType output_t, const temporary_terms_t &temporary_terms) const;
287 
288   //! Compute temporary terms in this expression
289   /*!
290     \param[in] derivOrder the derivation order (first w.r.t. endo/exo,
291     second w.r.t. params)
292     \param[out] temp_terms_map the computed temporary terms, associated
293     with their derivation order
294     \param[out] reference_count a temporary structure, used to count
295     references to each node (integer in outer pair is the
296     reference count, the inner pair is the derivation order)
297     \param[in] is_matlab whether we are in a MATLAB context, since that
298     affects the cost of each operator
299 
300     A node will be marked as a temporary term if it is referenced at least
301     two times (i.e. has at least two parents), and has a computing cost
302     (multiplied by reference count) greater to datatree.min_cost
303   */
304   virtual void computeTemporaryTerms(const pair<int, int> &derivOrder,
305                                      map<pair<int, int>, temporary_terms_t> &temp_terms_map,
306                                      map<expr_t, pair<int, pair<int, int>>> &reference_count,
307                                      bool is_matlab) const;
308 
309   //! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions
310   /*!
311     \param[in] output the output stream
312     \param[in] output_type the type of output (MATLAB, C, LaTeX...)
313     \param[in] temporary_terms the nodes that are marked as temporary terms
314     \param[in] a map from temporary_terms to integers indexes (in the
315     MATLAB, C or Julia vector of temporary terms); can be empty
316     when writing MATLAB with block decomposition)
317     \param[in] tef_terms the set of already written external function nodes
318   */
319   virtual void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const = 0;
320 
321   //! returns true if the expr node contains an external function
322   virtual bool containsExternalFunction() const = 0;
323 
324   //! Writes output of node (with no temporary terms and with "outside model" output type)
325   void writeOutput(ostream &output) const;
326 
327   //! Writes output of node (with no temporary terms)
328   void writeOutput(ostream &output, ExprNodeOutputType output_type) const;
329 
330   //! Writes output of node, using a Txxx notation for nodes in temporary_terms
331   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const;
332 
333   //! Writes output of node in JSON syntax
334   virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic = true) const = 0;
335 
336   //! Writes the Abstract Syntax Tree in JSON
337   virtual void writeJsonAST(ostream &output) const = 0;
338 
339   virtual int precedenceJson(const temporary_terms_t &temporary_terms) const;
340 
341   //! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
342   virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
343                                            const temporary_terms_t &temporary_terms,
344                                            const temporary_terms_idxs_t &temporary_terms_idxs,
345                                            deriv_node_temp_terms_t &tef_terms) const;
346 
347   //! Write the JSON output of an external function in a string vector
348   //! Allows the insertion of commas if necessary
349   virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
350                                                const temporary_terms_t &temporary_terms,
351                                                deriv_node_temp_terms_t &tef_terms,
352                                                bool isdynamic = true) const;
353 
354   virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
355                                              bool lhs_rhs, const temporary_terms_t &temporary_terms,
356                                              const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
357                                              deriv_node_temp_terms_t &tef_terms) const;
358 
359   //! Computes the set of all variables of a given symbol type in the expression (with information on lags)
360   /*!
361     Variables are stored as integer pairs of the form (symb_id, lag).
362     They are added to the set given in argument.
363     Note that model local variables are substituted by their expression in the computation
364     (and added if type_arg = ModelLocalVariable).
365   */
366   virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const = 0;
367 
368   //! Find lowest lag for VAR
369   virtual int VarMinLag() const = 0;
370 
371   //! Find the maximum lag in a VAR: handles case where LHS is diff
372   virtual int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const = 0;
373 
374   //! Finds LHS variable in a VAR equation
375   virtual void collectVARLHSVariable(set<expr_t> &result) const = 0;
376 
377   //! Computes the set of all variables of a given symbol type in the expression (without information on lags)
378   /*!
379     Variables are stored as symb_id.
380     They are added to the set given in argument.
381     Note that model local variables are substituted by their expression in the computation
382     (and added if type_arg = ModelLocalVariable).
383   */
384   void collectVariables(SymbolType type_arg, set<int> &result) const;
385 
386   //! Computes the set of endogenous variables in the expression
387   /*!
388     Endogenous are stored as integer pairs of the form (type_specific_id, lag).
389     They are added to the set given in argument.
390     Note that model local variables are substituted by their expression in the computation.
391   */
392   virtual void collectEndogenous(set<pair<int, int>> &result) const;
393 
394   //! Computes the set of exogenous variables in the expression
395   /*!
396     Exogenous are stored as integer pairs of the form (type_specific_id, lag).
397     They are added to the set given in argument.
398     Note that model local variables are substituted by their expression in the computation.
399   */
400   virtual void collectExogenous(set<pair<int, int>> &result) const;
401 
402   virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const = 0;
403 
404   virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
405                                      temporary_terms_t &temporary_terms,
406                                      map<expr_t, pair<int, int>> &first_occurence,
407                                      int Curr_block,
408                                      vector< vector<temporary_terms_t>> &v_temporary_terms,
409                                      int equation) const;
410 
411   class EvalException
412   {
413   };
414 
415   class EvalExternalFunctionException : public EvalException
416   {
417   };
418 
419   virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0;
420   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, const deriv_node_temp_terms_t &tef_terms) const = 0;
421   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) const;
422   //! Creates a static version of this node
423   /*!
424     This method duplicates the current node by creating a similar node from which all leads/lags have been stripped,
425     adds the result in the static_datatree argument (and not in the original datatree), and returns it.
426   */
427   virtual expr_t toStatic(DataTree &static_datatree) const = 0;
428 
429   /*!
430     Compute cross references for equations
431   */
432   //  virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det) const = 0;
433   virtual void computeXrefs(EquationInfo &ei) const = 0;
434   //! Try to normalize an equation linear in its endogenous variable
435   virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const = 0;
436 
437   //! Returns the maximum lead of endogenous in this expression
438   /*! Always returns a non-negative value */
439   virtual int maxEndoLead() const = 0;
440 
441   //! Returns the maximum lead of exogenous in this expression
442   /*! Always returns a non-negative value */
443   virtual int maxExoLead() const = 0;
444 
445   //! Returns the maximum lag of endogenous in this expression
446   /*! Always returns a non-negative value */
447   virtual int maxEndoLag() const = 0;
448 
449   //! Returns the maximum lag of exogenous in this expression
450   /*! Always returns a non-negative value */
451   virtual int maxExoLag() const = 0;
452 
453   //! Returns the maximum lead of endo/exo/exodet in this expression
454   /*! A negative value means that the expression contains only lagged
455     variables. A value of numeric_limits<int>::min() means that there is
456     no variable. */
457   virtual int maxLead() const = 0;
458 
459   //! Returns the maximum lag of endo/exo/exodet in this expression
460   /*! A negative value means that the expression contains only leaded
461     variables. A value of numeric_limits<int>::min() means that there is
462     no variable. */
463   virtual int maxLag() const = 0;
464 
465   //! Returns the maximum lag of endo/exo/exodet, as if diffs were expanded
466   /*! This function behaves as maxLag(), except that it treats diff()
467     differently. For e.g., on diff(diff(x(-1))), maxLag() returns 1 while
468     maxLagWithDiffsExpanded() returns 3. */
469   virtual int maxLagWithDiffsExpanded() const = 0;
470 
471   //! Get Max lag of var associated with Pac model
472   //! Takes account of undiffed LHS variables in calculating the max lag
473   virtual int PacMaxLag(int lhs_symb_id) const = 0;
474 
475   //! Get the target variable of the PAC model
476   virtual int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const = 0;
477 
478   virtual expr_t undiff() const = 0;
479 
480   //! Returns a new expression where all the leads/lags have been shifted backwards by the same amount
481   /*!
482     Only acts on endogenous, exogenous, exogenous det
483     \param[in] n The number of lags by which to shift
484     \return The same expression except that leads/lags have been shifted backwards
485   */
486   virtual expr_t decreaseLeadsLags(int n) const = 0;
487 
488   //! Type for the substitution map used in the process of creating auxiliary vars
489   using subst_table_t = map<const ExprNode *, const VariableNode *>;
490 
491   //! Type for the substitution map used in the process of substituting adl expressions
492   using subst_table_adl_t = map<const ExprNode *, const expr_t>;
493 
494   //! Creates auxiliary endo lead variables corresponding to this expression
495   /*!
496     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.
497     \pre This expression is assumed to have maximum endogenous lead >= 2
498     \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
499     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
500     \return The new variable node corresponding to the current expression
501   */
502   VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
503 
504   //! Creates auxiliary exo lead variables corresponding to this expression
505   /*!
506     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.
507     \pre This expression is assumed to have maximum exogenous lead >= 1
508     \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
509     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
510     \return The new variable node corresponding to the current expression
511   */
512   VariableNode *createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
513 
514   //! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
515   /*!
516     \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
517     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
518 
519     If the method detects a sub-expr which needs to be substituted, two cases are possible:
520     - if this expr is in the table, then it will use the corresponding variable and return the substituted expression
521     - if this expr is not in the table, then it will create an auxiliary endogenous variable, add the substitution in the table and return the substituted expression
522 
523     \return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
524   */
525   virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;
526 
527   //! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables
528   /*!
529     \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
530     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
531   */
532   virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
533 
534   //! Constructs a new expression where exogenous variables with a lead have been replaced by auxiliary variables
535   /*!
536     \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
537     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
538   */
539   virtual expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;
540   //! Constructs a new expression where exogenous variables with a lag have been replaced by auxiliary variables
541   /*!
542     \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
543     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
544   */
545   virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
546 
547   //! Constructs a new expression where the expectation operator has been replaced by auxiliary variables
548   /*!
549     \param[in,out] subst_table Map used to store expressions that have already be substituted and their corresponding variable, in order to avoid creating two auxiliary variables for the same sub-expr.
550     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
551     \param[in] partial_information_model Are we substituting in a partial information model?
552   */
553   virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const = 0;
554 
555   virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;
556 
557   //! Constructs a new expression where forward variables (supposed to be at most in t+1) have been replaced by themselves at t, plus a new aux var representing their (time) differentiate
558   /*!
559     \param[in] subset variables to which to limit the transformation; transform
560     all fwrd vars if empty
561     \param[in,out] subst_table Map used to store mapping between a given
562     forward variable and the aux var that contains its differentiate
563     \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
564   */
565   virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
566 
567   //! Return true if the nodeID is a numerical constant equal to value and false otherwise
568   /*!
569     \param[in] value of the numerical constante
570     \param[out] the boolean equal to true if NodeId is a constant equal to value
571   */
572   virtual bool isNumConstNodeEqualTo(double value) const = 0;
573 
574   //! Returns true if the expression contains one or several endogenous variable
575   virtual bool containsEndogenous() const = 0;
576 
577   //! Returns true if the expression contains one or several exogenous variable
578   virtual bool containsExogenous() const = 0;
579 
580   //! Returns the maximum number of nested diffs in the expression
581   virtual int countDiffs() const = 0;
582 
583   //! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id aqual to varfiable_id and a lag equal to lag_arg and false otherwise
584   /*!
585     \param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
586     \param[out] the boolean equal to true if NodeId is the variable
587   */
588   virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0;
589 
590   //! Replaces the Trend var with datatree.One
591   virtual expr_t replaceTrendVar() const = 0;
592 
593   //! Constructs a new expression where the variable indicated by symb_id has been detrended
594   /*!
595     \param[in] symb_id indicating the variable to be detrended
596     \param[in] log_trend indicates if the trend is in log
597     \param[in] trend indicating the trend
598     \return the new binary op pointing to a detrended variable
599   */
600   virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;
601 
602   //! Substitute adl operator
603   virtual expr_t substituteAdl() const = 0;
604 
605   //! Substitute VarExpectation nodes
606   virtual expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const = 0;
607 
608   //! Mark diff nodes to be substituted
609   /*! The various nodes that are equivalent up to a shift of leads/lags are
610     grouped together in the “nodes” table. See the comment above
611     lag_equivalence_table_t for more details. */
612   virtual void findDiffNodes(lag_equivalence_table_t &nodes) const = 0;
613   //! Substitute diff operator
614   virtual expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
615 
616   //! Mark unary ops nodes to be substituted
617   /*! The various nodes that are equivalent up to a shift of leads/lags are
618     grouped together in the “nodes” table. See the comment above
619     lag_equivalence_table_t for more details. */
620   virtual void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const = 0;
621   //! Substitute unary ops nodes
622   virtual expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
623 
624   //! Substitute pac_expectation operator
625   virtual expr_t substitutePacExpectation(const string &name, expr_t subexpr) = 0;
626 
627   virtual int findTargetVariable(int lhs_symb_id) const = 0;
628 
629   //! Add ExprNodes to the provided datatree
630   virtual expr_t clone(DataTree &datatree) const = 0;
631 
632   //! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
633   virtual expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const = 0;
634 
635   //! Returns true if the expression is in static form (no lead, no lag, no expectation, no STEADY_STATE)
636   virtual bool isInStaticForm() const = 0;
637 
638   //! Substitute auxiliary variables by their expression in static model
639   virtual expr_t substituteStaticAuxiliaryVariable() const = 0;
640 
641   //! Returns true if model_info_name is referenced by a VarExpectationNode
642   virtual bool isVarModelReferenced(const string &model_info_name) const = 0;
643 
644   //! Matches a linear combination of variables, where scalars can be constant*parameter
645   /*! Returns a list of (variable_id, lag, param_id, constant)
646     corresponding to the terms in the expression. When there is no
647     parameter in a term, param_id == -1.
648     Can throw a MatchFailureException.
649     if `variable_obligatory_in_each_term` is true, then every part of the linear combination must contain a variable;
650     otherwise, if `variable_obligatory_in_each_term`, then any linear combination of constant/variable/param is matched
651   */
652   vector<tuple<int, int, int, double>> matchLinearCombinationOfVariables(bool variable_obligatory_in_each_term = true) const;
653 
654   pair<int, vector<tuple<int, int, int, double>>> matchParamTimesLinearCombinationOfVariables() const;
655 
656   //! Returns true if expression is of the form:
657   //! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
658   virtual bool isParamTimesEndogExpr() const = 0;
659 
660   //! Fills the EC matrix structure
661   void fillErrorCorrectionRow(int eqn, const vector<int> &nontarget_lhs, const vector<int> &target_lhs,
662                               map<tuple<int, int, int>, expr_t> &A0,
663                               map<tuple<int, int, int>, expr_t> &A0star) const;
664 
665   //! Finds equations where a variable is equal to a constant
666   virtual void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const = 0;
667 
668   //! Replaces variables found in findConstantEquations() with their constant values
669   virtual expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const = 0;
670 
671   //! Returns true if PacExpectationNode encountered
672   virtual bool containsPacExpectation(const string &pac_model_name = "") const = 0;
673 
674   //! Fills map
675   virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0;
676 
677   //! Decompose an expression into its additive terms
678   /*! Returns a list of terms, with their sign (either 1 or -1, depending
679     on whether the terms appears with a plus or a minus).
680     The current_sign argument should normally be left to 1.
681     If current_sign == -1, then all signs are inverted */
682   virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign = 1) const;
683 
684   // Matches an expression of the form variable*constant*parameter
685   /* Returns a tuple (variable_id, lag, param_id, constant).
686      The variable must be an exogenous or an endogenous.
687      The constant is optional (in which case 1 is returned); there can be
688      several multiplicative constants; constants can also appear at the
689      denominator (i.e. after a divide sign).
690      The parameter is optional (in which case param_id == -1).
691      If the expression is not of the expected form, throws a
692      MatchFailureException
693      if `variable_obligatory` is true, then the linear combination must contain a variable;
694      otherwise, if `variable_obligatory`, then an expression is matched that has any mix of constant/variable/param
695   */
696   tuple<int, int, int, double> matchVariableTimesConstantTimesParam(bool variable_obligatory = true) const;
697 
698   //! Exception thrown by matchVariableTimesConstantTimesParam when matching fails
699   class MatchFailureException
700   {
701   public:
702     const string message;
MatchFailureException(string message_arg)703     MatchFailureException(string message_arg) : message{move(message_arg)}
704     {
705     };
706   };
707 };
708 
709 //! Object used to compare two nodes (using their indexes)
710 /*! Note that in this ordering, a subexpression is always less than the
711   expression from which it is extracted. This property is used extensively in
712   the temporary terms computations. */
713 struct ExprNodeLess
714 {
715   bool
operator ()ExprNodeLess716   operator()(expr_t arg1, expr_t arg2) const
717   {
718     return arg1->idx < arg2->idx;
719   }
720 };
721 
722 //! Numerical constant node
723 /*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */
724 class NumConstNode : public ExprNode
725 {
726 public:
727   //! Id from numerical constants table
728   const int id;
729 private:
730   expr_t computeDerivative(int deriv_id) override;
731 protected:
732   void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
733 public:
734   NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg);
735   void prepareForDerivation() override;
736   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
737   void writeJsonAST(ostream &output) const override;
738   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
739   bool containsExternalFunction() const override;
740   void collectVARLHSVariable(set<expr_t> &result) const override;
741   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
742   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
743   double eval(const eval_context_t &eval_context) const noexcept(false) override;
744   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, const deriv_node_temp_terms_t &tef_terms) const override;
745   expr_t toStatic(DataTree &static_datatree) const override;
746   void computeXrefs(EquationInfo &ei) const override;
747   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
748   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
749   int maxEndoLead() const override;
750   int maxExoLead() const override;
751   int maxEndoLag() const override;
752   int maxExoLag() const override;
753   int maxLead() const override;
754   int maxLag() const override;
755   int maxLagWithDiffsExpanded() const override;
756   int VarMinLag() const override;
757   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
758   int PacMaxLag(int lhs_symb_id) const override;
759   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
760   expr_t undiff() const override;
761   expr_t decreaseLeadsLags(int n) const override;
762   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
763   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
764   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
765   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
766   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
767   expr_t substituteAdl() const override;
768   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
769   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
770   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
771   int findTargetVariable(int lhs_symb_id) const override;
772   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
773   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
774   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
775   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
776   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
777   bool isNumConstNodeEqualTo(double value) const override;
778   bool containsEndogenous() const override;
779   bool containsExogenous() const override;
780   int countDiffs() const override;
781   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
782   expr_t replaceTrendVar() const override;
783   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
784   expr_t clone(DataTree &datatree) const override;
785   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
786   bool isInStaticForm() const override;
787   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
788   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
789   bool containsPacExpectation(const string &pac_model_name = "") const override;
790   bool isParamTimesEndogExpr() const override;
791   bool isVarModelReferenced(const string &model_info_name) const override;
792   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
793   expr_t substituteStaticAuxiliaryVariable() const override;
794 };
795 
796 //! Symbol or variable node
797 class VariableNode : public ExprNode
798 {
799   friend class UnaryOpNode;
800 public:
801   //! Id from the symbol table
802   const int symb_id;
803   //! A positive value is a lead, a negative is a lag
804   const int lag;
805 private:
806   expr_t computeDerivative(int deriv_id) override;
807 protected:
808   void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
809 public:
810   VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
811   void prepareForDerivation() override;
812   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
813   void writeJsonAST(ostream &output) const override;
814   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
815   bool containsExternalFunction() const override;
816   void collectVARLHSVariable(set<expr_t> &result) const override;
817   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
818   void computeTemporaryTerms(map<expr_t, int > &reference_count,
819                              temporary_terms_t &temporary_terms,
820                              map<expr_t, pair<int, int>> &first_occurence,
821                              int Curr_block,
822                              vector< vector<temporary_terms_t>> &v_temporary_terms,
823                              int equation) const override;
824   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
825   double eval(const eval_context_t &eval_context) const noexcept(false) override;
826   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, const deriv_node_temp_terms_t &tef_terms) const override;
827   expr_t toStatic(DataTree &static_datatree) const override;
828   void computeXrefs(EquationInfo &ei) const override;
829   SymbolType get_type() const;
830   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
831   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
832   int maxEndoLead() const override;
833   int maxExoLead() const override;
834   int maxEndoLag() const override;
835   int maxExoLag() const override;
836   int maxLead() const override;
837   int maxLag() const override;
838   int maxLagWithDiffsExpanded() const override;
839   int VarMinLag() const override;
840   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
841   int PacMaxLag(int lhs_symb_id) const override;
842   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
843   expr_t undiff() const override;
844   expr_t decreaseLeadsLags(int n) const override;
845   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
846   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
847   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
848   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
849   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
850   expr_t substituteAdl() const override;
851   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
852   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
853   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
854   int findTargetVariable(int lhs_symb_id) const override;
855   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
856   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
857   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
858   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
859   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
860   bool isNumConstNodeEqualTo(double value) const override;
861   bool containsEndogenous() const override;
862   bool containsExogenous() const override;
863   int countDiffs() const override;
864   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
865   expr_t replaceTrendVar() const override;
866   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
867   expr_t clone(DataTree &datatree) const override;
868   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
869   bool isInStaticForm() const override;
870   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
871   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
872   bool containsPacExpectation(const string &pac_model_name = "") const override;
873   bool isParamTimesEndogExpr() const override;
874   bool isVarModelReferenced(const string &model_info_name) const override;
875   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
876   //! Substitute auxiliary variables by their expression in static model
877   expr_t substituteStaticAuxiliaryVariable() const override;
878 };
879 
880 //! Unary operator node
881 class UnaryOpNode : public ExprNode
882 {
883 protected:
884   void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
885 public:
886   const expr_t arg;
887   //! Stores the information set. Only used for expectation operator
888   const int expectation_information_set;
889   //! Only used for UnaryOpcode::steadyStateParamDeriv and UnaryOpcode::steadyStateParam2ndDeriv
890   const int param1_symb_id, param2_symb_id;
891   const UnaryOpcode op_code;
892   const string adl_param_name;
893   const vector<int> adl_lags;
894 private:
895   expr_t computeDerivative(int deriv_id) override;
896   int cost(int cost, bool is_matlab) const override;
897   int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
898   int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
899   //! Returns the derivative of this node if darg is the derivative of the argument
900   expr_t composeDerivatives(expr_t darg, int deriv_id);
901 public:
902   UnaryOpNode(DataTree &datatree_arg, int idx_arg, UnaryOpcode op_code_arg, const expr_t arg_arg, int expectation_information_set_arg, int param1_symb_id_arg, int param2_symb_id_arg, string adl_param_name_arg, vector<int> adl_lags_arg);
903   void prepareForDerivation() override;
904   void computeTemporaryTerms(const pair<int, int> &derivOrder,
905                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
906                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
907                              bool is_matlab) const override;
908   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
909   void writeJsonAST(ostream &output) const override;
910   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
911   bool containsExternalFunction() const override;
912   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
913                                    const temporary_terms_t &temporary_terms,
914                                    const temporary_terms_idxs_t &temporary_terms_idxs,
915                                    deriv_node_temp_terms_t &tef_terms) const override;
916   void writeJsonExternalFunctionOutput(vector<string> &efout,
917                                        const temporary_terms_t &temporary_terms,
918                                        deriv_node_temp_terms_t &tef_terms,
919                                        bool isdynamic) const override;
920   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
921                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
922                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
923                                      deriv_node_temp_terms_t &tef_terms) const override;
924   void computeTemporaryTerms(map<expr_t, int> &reference_count,
925                              temporary_terms_t &temporary_terms,
926                              map<expr_t, pair<int, int>> &first_occurence,
927                              int Curr_block,
928                              vector< vector<temporary_terms_t>> &v_temporary_terms,
929                              int equation) const override;
930   void collectVARLHSVariable(set<expr_t> &result) const override;
931   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
932   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
933   static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
934   double eval(const eval_context_t &eval_context) const noexcept(false) override;
935   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, const deriv_node_temp_terms_t &tef_terms) const override;
936   expr_t toStatic(DataTree &static_datatree) const override;
937   void computeXrefs(EquationInfo &ei) const override;
938   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
939   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
940   int maxEndoLead() const override;
941   int maxExoLead() const override;
942   int maxEndoLag() const override;
943   int maxExoLag() const override;
944   int maxLead() const override;
945   int maxLag() const override;
946   int maxLagWithDiffsExpanded() const override;
947   int VarMinLag() const override;
948   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
949   int PacMaxLag(int lhs_symb_id) const override;
950   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
951   expr_t undiff() const override;
952   expr_t decreaseLeadsLags(int n) const override;
953   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
954   //! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
955   expr_t buildSimilarUnaryOpNode(expr_t alt_arg, DataTree &alt_datatree) const;
956   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
957   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
958   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
959   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
960   expr_t substituteAdl() const override;
961   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
962   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
963   bool createAuxVarForUnaryOpNode() const;
964   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
965   int findTargetVariable(int lhs_symb_id) const override;
966   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
967   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
968   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
969   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
970   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
971   bool isNumConstNodeEqualTo(double value) const override;
972   bool containsEndogenous() const override;
973   bool containsExogenous() const override;
974   int countDiffs() const override;
975   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
976   expr_t replaceTrendVar() const override;
977   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
978   expr_t clone(DataTree &datatree) const override;
979   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
980   bool isInStaticForm() const override;
981   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
982   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
983   bool containsPacExpectation(const string &pac_model_name = "") const override;
984   bool isParamTimesEndogExpr() const override;
985   bool isVarModelReferenced(const string &model_info_name) const override;
986   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
987   //! Substitute auxiliary variables by their expression in static model
988   expr_t substituteStaticAuxiliaryVariable() const override;
989   void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign) const override;
990 };
991 
992 //! Binary operator node
993 class BinaryOpNode : public ExprNode
994 {
995 protected:
996   void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
997 public:
998   const expr_t arg1, arg2;
999   const BinaryOpcode op_code;
1000   const int powerDerivOrder;
1001   const string adlparam;
1002 private:
1003   expr_t computeDerivative(int deriv_id) override;
1004   int cost(int cost, bool is_matlab) const override;
1005   int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
1006   int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
1007   //! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
1008   expr_t composeDerivatives(expr_t darg1, expr_t darg2);
1009 public:
1010   BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
1011                BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder);
1012   void prepareForDerivation() override;
1013   int precedenceJson(const temporary_terms_t &temporary_terms) const override;
1014   int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
1015   void computeTemporaryTerms(const pair<int, int> &derivOrder,
1016                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
1017                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
1018                              bool is_matlab) const override;
1019   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1020   void writeJsonAST(ostream &output) const override;
1021   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1022   bool containsExternalFunction() const override;
1023   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1024                                    const temporary_terms_t &temporary_terms,
1025                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1026                                    deriv_node_temp_terms_t &tef_terms) const override;
1027   void writeJsonExternalFunctionOutput(vector<string> &efout,
1028                                        const temporary_terms_t &temporary_terms,
1029                                        deriv_node_temp_terms_t &tef_terms,
1030                                        bool isdynamic) const override;
1031   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1032                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1033                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1034                                      deriv_node_temp_terms_t &tef_terms) const override;
1035   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1036                              temporary_terms_t &temporary_terms,
1037                              map<expr_t, pair<int, int>> &first_occurence,
1038                              int Curr_block,
1039                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1040                              int equation) const override;
1041   void collectVARLHSVariable(set<expr_t> &result) const override;
1042   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
1043   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
1044   static double eval_opcode(double v1, BinaryOpcode op_code, double v2, int derivOrder) noexcept(false);
1045   double eval(const eval_context_t &eval_context) const noexcept(false) override;
1046   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, const deriv_node_temp_terms_t &tef_terms) const override;
1047   expr_t Compute_RHS(expr_t arg1, expr_t arg2, int op, int op_type) const;
1048   expr_t toStatic(DataTree &static_datatree) const override;
1049   void computeXrefs(EquationInfo &ei) const override;
1050   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
1051   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
1052   int maxEndoLead() const override;
1053   int maxExoLead() const override;
1054   int maxEndoLag() const override;
1055   int maxExoLag() const override;
1056   int maxLead() const override;
1057   int maxLag() const override;
1058   int maxLagWithDiffsExpanded() const override;
1059   int VarMinLag() const override;
1060   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
1061   int PacMaxLag(int lhs_symb_id) const override;
1062   int getPacTargetSymbIdHelper(int lhs_symb_id, int undiff_lhs_symb_id, const set<pair<int, int>> &endogs) const;
1063   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
1064   expr_t undiff() const override;
1065   expr_t decreaseLeadsLags(int n) const override;
1066   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1067   //! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments
1068   expr_t buildSimilarBinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, DataTree &alt_datatree) const;
1069   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1070   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1071   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1072   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
1073   expr_t substituteAdl() const override;
1074   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
1075   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
1076   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
1077   bool findTargetVariableHelper1(int lhs_symb_id, int rhs_symb_id) const;
1078   int findTargetVariableHelper(const expr_t arg1, const expr_t arg2, int lhs_symb_id) const;
1079   int findTargetVariable(int lhs_symb_id) const override;
1080   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1081   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1082   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
1083   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
1084   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1085   bool isNumConstNodeEqualTo(double value) const override;
1086   bool containsEndogenous() const override;
1087   bool containsExogenous() const override;
1088   int countDiffs() const override;
1089   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
1090   expr_t replaceTrendVar() const override;
1091   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
1092   expr_t clone(DataTree &datatree) const override;
1093   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
1094   //! Function to write out the oPowerNode in expr_t terms as opposed to writing out the function itself
1095   expr_t unpackPowerDeriv() const;
1096   //! Returns MULT_i*(lhs-rhs) = 0, creating multiplier MULT_i
1097   expr_t addMultipliersToConstraints(int i);
1098   //! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero)
1099   expr_t getNonZeroPartofEquation() const;
1100   bool isInStaticForm() const override;
1101   void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const;
1102   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
1103   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
1104   bool containsPacExpectation(const string &pac_model_name = "") const override;
1105   pair<int, vector<tuple<int, bool, int>>> getPacEC(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const;
1106   void getPacAREC(int lhs_symb_id, int lhs_orig_symb_id,
1107                   pair<int, vector<tuple<int, bool, int>>> &ec_params_and_vars,
1108                   set<pair<int, pair<int, int>>> &ar_params_and_vars,
1109                   vector<tuple<int, int, int, double>> &additive_vars_params_and_constants) const;
1110 
1111   //! Finds the share of optimizing agents in the PAC equation,
1112   //! the expr node associated with it,
1113   //! and the expr node associated with the non-optimizing part
1114   tuple<int, expr_t, expr_t, expr_t> getPacOptimizingShareAndExprNodes(int lhs_symb_id, int lhs_orig_symb_id) const;
1115   pair<int, expr_t> getPacOptimizingShareAndExprNodesHelper(BinaryOpNode *bopn, int lhs_symb_id, int lhs_orig_symb_id) const;
1116   expr_t getPacNonOptimizingPart(BinaryOpNode *bopn, int optim_share) const;
1117   bool getPacNonOptimizingPartHelper(BinaryOpNode *bopn, int optim_share) const;
1118   bool isParamTimesEndogExpr() const override;
1119   bool isVarModelReferenced(const string &model_info_name) const override;
1120   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
1121   //! Substitute auxiliary variables by their expression in static model
1122   expr_t substituteStaticAuxiliaryVariable() const override;
1123   //! Substitute auxiliary variables by their expression in static model auxiliary variable definition
1124   expr_t substituteStaticAuxiliaryDefinition() const;
1125   void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign) const override;
1126 };
1127 
1128 //! Trinary operator node
1129 class TrinaryOpNode : public ExprNode
1130 {
1131   friend class ModelTree;
1132 public:
1133   const expr_t arg1, arg2, arg3;
1134   const TrinaryOpcode op_code;
1135 private:
1136   expr_t computeDerivative(int deriv_id) override;
1137   int cost(int cost, bool is_matlab) const override;
1138   int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
1139   int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
1140   //! Returns the derivative of this node if darg1, darg2 and darg3 are the derivatives of the arguments
1141   expr_t composeDerivatives(expr_t darg1, expr_t darg2, expr_t darg3);
1142 public:
1143   TrinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
1144                 TrinaryOpcode op_code_arg, const expr_t arg2_arg, const expr_t arg3_arg);
1145   void prepareForDerivation() override;
1146   int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
1147   void computeTemporaryTerms(const pair<int, int> &derivOrder,
1148                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
1149                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
1150                              bool is_matlab) const override;
1151   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1152   void writeJsonAST(ostream &output) const override;
1153   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1154   bool containsExternalFunction() const override;
1155   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1156                                    const temporary_terms_t &temporary_terms,
1157                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1158                                    deriv_node_temp_terms_t &tef_terms) const override;
1159   void writeJsonExternalFunctionOutput(vector<string> &efout,
1160                                        const temporary_terms_t &temporary_terms,
1161                                        deriv_node_temp_terms_t &tef_terms,
1162                                        bool isdynamic) const override;
1163   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1164                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1165                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1166                                      deriv_node_temp_terms_t &tef_terms) const override;
1167   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1168                              temporary_terms_t &temporary_terms,
1169                              map<expr_t, pair<int, int>> &first_occurence,
1170                              int Curr_block,
1171                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1172                              int equation) const override;
1173   void collectVARLHSVariable(set<expr_t> &result) const override;
1174   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
1175   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
1176   static double eval_opcode(double v1, TrinaryOpcode op_code, double v2, double v3) noexcept(false);
1177   double eval(const eval_context_t &eval_context) const noexcept(false) override;
1178   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, const deriv_node_temp_terms_t &tef_terms) const override;
1179   expr_t toStatic(DataTree &static_datatree) const override;
1180   void computeXrefs(EquationInfo &ei) const override;
1181   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
1182   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
1183   int maxEndoLead() const override;
1184   int maxExoLead() const override;
1185   int maxEndoLag() const override;
1186   int maxExoLag() const override;
1187   int maxLead() const override;
1188   int maxLag() const override;
1189   int maxLagWithDiffsExpanded() const override;
1190   int VarMinLag() const override;
1191   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
1192   int PacMaxLag(int lhs_symb_id) const override;
1193   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
1194   expr_t undiff() const override;
1195   expr_t decreaseLeadsLags(int n) const override;
1196   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1197   //! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments
1198   expr_t buildSimilarTrinaryOpNode(expr_t alt_arg1, expr_t alt_arg2, expr_t alt_arg3, DataTree &alt_datatree) const;
1199   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1200   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1201   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1202   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
1203   expr_t substituteAdl() const override;
1204   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
1205   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
1206   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
1207   int findTargetVariable(int lhs_symb_id) const override;
1208   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1209   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1210   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
1211   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
1212   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1213   bool isNumConstNodeEqualTo(double value) const override;
1214   bool containsEndogenous() const override;
1215   bool containsExogenous() const override;
1216   int countDiffs() const override;
1217   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
1218   expr_t replaceTrendVar() const override;
1219   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
1220   expr_t clone(DataTree &datatree) const override;
1221   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
1222   bool isInStaticForm() const override;
1223   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
1224   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
1225   bool containsPacExpectation(const string &pac_model_name = "") const override;
1226   bool isParamTimesEndogExpr() const override;
1227   bool isVarModelReferenced(const string &model_info_name) const override;
1228   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
1229   //! Substitute auxiliary variables by their expression in static model
1230   expr_t substituteStaticAuxiliaryVariable() const override;
1231 };
1232 
1233 //! External function node
1234 class AbstractExternalFunctionNode : public ExprNode
1235 {
1236 public:
1237   const int symb_id;
1238   const vector<expr_t> arguments;
1239 private:
1240   expr_t computeDerivative(int deriv_id) override;
1241   virtual expr_t composeDerivatives(const vector<expr_t> &dargs) = 0;
1242 protected:
1243   //! Thrown when trying to access an unknown entry in external_function_node_map
1244   class UnknownFunctionNameAndArgs
1245   {
1246   };
1247   //! Returns true if the given external function has been written as a temporary term
1248   bool alreadyWrittenAsTefTerm(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const;
1249   //! Returns the index in the tef_terms map of this external function
1250   int getIndxInTefTerms(int the_symb_id, const deriv_node_temp_terms_t &tef_terms) const noexcept(false);
1251   //! Helper function to write output arguments of any given external function
1252   void writeExternalFunctionArguments(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const;
1253   void writeJsonASTExternalFunctionArguments(ostream &output) const;
1254   void writeJsonExternalFunctionArguments(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const;
1255   /*! Returns a predicate that tests whether an other ExprNode is an external
1256     function which is computed by the same external function call (i.e. it has
1257     the same so-called "Tef" index) */
1258   virtual function<bool (expr_t)> sameTefTermPredicate() const = 0;
1259 public:
1260   AbstractExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
1261                                vector<expr_t> arguments_arg);
1262   void prepareForDerivation() override;
1263   void computeTemporaryTerms(const pair<int, int> &derivOrder,
1264                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
1265                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
1266                              bool is_matlab) const override;
1267   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override = 0;
1268   void writeJsonAST(ostream &output) const override = 0;
1269   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic = true) const override = 0;
1270   bool containsExternalFunction() const override;
1271   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1272                                    const temporary_terms_t &temporary_terms,
1273                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1274                                    deriv_node_temp_terms_t &tef_terms) const override = 0;
1275   void writeJsonExternalFunctionOutput(vector<string> &efout,
1276                                        const temporary_terms_t &temporary_terms,
1277                                        deriv_node_temp_terms_t &tef_terms,
1278                                        bool isdynamic = true) const override = 0;
1279   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1280                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1281                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1282                                      deriv_node_temp_terms_t &tef_terms) const override = 0;
1283   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1284                              temporary_terms_t &temporary_terms,
1285                              map<expr_t, pair<int, int>> &first_occurence,
1286                              int Curr_block,
1287                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1288                              int equation) const override = 0;
1289   void collectVARLHSVariable(set<expr_t> &result) const override;
1290   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
1291   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
1292   double eval(const eval_context_t &eval_context) const noexcept(false) override;
1293   unsigned int compileExternalFunctionArguments(ostream &CompileCode, unsigned int &instruction_number,
1294                                                 bool lhs_rhs, const temporary_terms_t &temporary_terms,
1295                                                 const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1296                                                 const deriv_node_temp_terms_t &tef_terms) const;
1297 
1298   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, const deriv_node_temp_terms_t &tef_terms) const override = 0;
1299   expr_t toStatic(DataTree &static_datatree) const override = 0;
1300   void computeXrefs(EquationInfo &ei) const override = 0;
1301   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
1302   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
1303   int maxEndoLead() const override;
1304   int maxExoLead() const override;
1305   int maxEndoLag() const override;
1306   int maxExoLag() const override;
1307   int maxLead() const override;
1308   int maxLag() const override;
1309   int maxLagWithDiffsExpanded() const override;
1310   int VarMinLag() const override;
1311   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
1312   int PacMaxLag(int lhs_symb_id) const override;
1313   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
1314   expr_t undiff() const override;
1315   expr_t decreaseLeadsLags(int n) const override;
1316   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1317   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1318   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1319   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1320   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
1321   expr_t substituteAdl() const override;
1322   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
1323   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
1324   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
1325   int findTargetVariable(int lhs_symb_id) const override;
1326   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1327   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1328   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
1329   virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const = 0;
1330   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
1331   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1332   bool isNumConstNodeEqualTo(double value) const override;
1333   bool containsEndogenous() const override;
1334   bool containsExogenous() const override;
1335   int countDiffs() const override;
1336   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
1337   void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms, const string &ending) const;
1338   expr_t replaceTrendVar() const override;
1339   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
1340   expr_t clone(DataTree &datatree) const override = 0;
1341   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
1342   bool isInStaticForm() const override;
1343   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
1344   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
1345   bool containsPacExpectation(const string &pac_model_name = "") const override;
1346   bool isParamTimesEndogExpr() const override;
1347   bool isVarModelReferenced(const string &model_info_name) const override;
1348   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
1349   //! Substitute auxiliary variables by their expression in static model
1350   expr_t substituteStaticAuxiliaryVariable() const override;
1351 };
1352 
1353 class ExternalFunctionNode : public AbstractExternalFunctionNode
1354 {
1355   friend class FirstDerivExternalFunctionNode;
1356   friend class SecondDerivExternalFunctionNode;
1357 private:
1358   expr_t composeDerivatives(const vector<expr_t> &dargs) override;
1359 protected:
1360   function<bool (expr_t)> sameTefTermPredicate() const override;
1361 public:
1362   ExternalFunctionNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg,
1363                        const vector<expr_t> &arguments_arg);
1364   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1365   void writeJsonAST(ostream &output) const override;
1366   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1367   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1368                                    const temporary_terms_t &temporary_terms,
1369                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1370                                    deriv_node_temp_terms_t &tef_terms) const override;
1371   void writeJsonExternalFunctionOutput(vector<string> &efout,
1372                                        const temporary_terms_t &temporary_terms,
1373                                        deriv_node_temp_terms_t &tef_terms,
1374                                        bool isdynamic) const override;
1375   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1376                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1377                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1378                                      deriv_node_temp_terms_t &tef_terms) const override;
1379   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1380                              temporary_terms_t &temporary_terms,
1381                              map<expr_t, pair<int, int>> &first_occurence,
1382                              int Curr_block,
1383                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1384                              int equation) const override;
1385   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, const deriv_node_temp_terms_t &tef_terms) const override;
1386   expr_t toStatic(DataTree &static_datatree) const override;
1387   void computeXrefs(EquationInfo &ei) const override;
1388   expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
1389   expr_t clone(DataTree &datatree) const override;
1390 };
1391 
1392 class FirstDerivExternalFunctionNode : public AbstractExternalFunctionNode
1393 {
1394 public:
1395   const int inputIndex;
1396 private:
1397   expr_t composeDerivatives(const vector<expr_t> &dargs) override;
1398 protected:
1399   function<bool (expr_t)> sameTefTermPredicate() const override;
1400 public:
1401   FirstDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
1402                                  int top_level_symb_id_arg,
1403                                  const vector<expr_t> &arguments_arg,
1404                                  int inputIndex_arg);
1405   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1406                              temporary_terms_t &temporary_terms,
1407                              map<expr_t, pair<int, int>> &first_occurence,
1408                              int Curr_block,
1409                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1410                              int equation) const override;
1411   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1412   void writeJsonAST(ostream &output) const override;
1413   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1414   void compile(ostream &CompileCode, unsigned int &instruction_number,
1415                bool lhs_rhs, const temporary_terms_t &temporary_terms,
1416                const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1417                const deriv_node_temp_terms_t &tef_terms) const override;
1418   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1419                                    const temporary_terms_t &temporary_terms,
1420                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1421                                    deriv_node_temp_terms_t &tef_terms) const override;
1422   void writeJsonExternalFunctionOutput(vector<string> &efout,
1423                                        const temporary_terms_t &temporary_terms,
1424                                        deriv_node_temp_terms_t &tef_terms,
1425                                        bool isdynamic) const override;
1426   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1427                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1428                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1429                                      deriv_node_temp_terms_t &tef_terms) const override;
1430   expr_t toStatic(DataTree &static_datatree) const override;
1431   void computeXrefs(EquationInfo &ei) const override;
1432   expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
1433   expr_t clone(DataTree &datatree) const override;
1434 };
1435 
1436 class SecondDerivExternalFunctionNode : public AbstractExternalFunctionNode
1437 {
1438 public:
1439   const int inputIndex1;
1440   const int inputIndex2;
1441 private:
1442   expr_t composeDerivatives(const vector<expr_t> &dargs) override;
1443 protected:
1444   function<bool (expr_t)> sameTefTermPredicate() const override;
1445 public:
1446   SecondDerivExternalFunctionNode(DataTree &datatree_arg, int idx_arg,
1447                                   int top_level_symb_id_arg,
1448                                   const vector<expr_t> &arguments_arg,
1449                                   int inputIndex1_arg,
1450                                   int inputIndex2_arg);
1451   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1452                              temporary_terms_t &temporary_terms,
1453                              map<expr_t, pair<int, int>> &first_occurence,
1454                              int Curr_block,
1455                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1456                              int equation) const override;
1457   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1458   void writeJsonAST(ostream &output) const override;
1459   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1460   void compile(ostream &CompileCode, unsigned int &instruction_number,
1461                bool lhs_rhs, const temporary_terms_t &temporary_terms,
1462                const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1463                const deriv_node_temp_terms_t &tef_terms) const override;
1464   void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
1465                                    const temporary_terms_t &temporary_terms,
1466                                    const temporary_terms_idxs_t &temporary_terms_idxs,
1467                                    deriv_node_temp_terms_t &tef_terms) const override;
1468   void writeJsonExternalFunctionOutput(vector<string> &efout,
1469                                        const temporary_terms_t &temporary_terms,
1470                                        deriv_node_temp_terms_t &tef_terms,
1471                                        bool isdynamic) const override;
1472   void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
1473                                      bool lhs_rhs, const temporary_terms_t &temporary_terms,
1474                                      const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1475                                      deriv_node_temp_terms_t &tef_terms) const override;
1476   expr_t toStatic(DataTree &static_datatree) const override;
1477   void computeXrefs(EquationInfo &ei) const override;
1478   expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const override;
1479   expr_t clone(DataTree &datatree) const override;
1480 };
1481 
1482 class VarExpectationNode : public ExprNode
1483 {
1484 public:
1485   const string model_name;
1486   VarExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name_arg);
1487   void computeTemporaryTerms(const pair<int, int> &derivOrder,
1488                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
1489                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
1490                              bool is_matlab) const override;
1491   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1492   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1493                              temporary_terms_t &temporary_terms,
1494                              map<expr_t, pair<int, int>> &first_occurence,
1495                              int Curr_block,
1496                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1497                              int equation) const override;
1498   expr_t toStatic(DataTree &static_datatree) const override;
1499   expr_t clone(DataTree &datatree) const override;
1500   int maxEndoLead() const override;
1501   int maxExoLead() const override;
1502   int maxEndoLag() const override;
1503   int maxExoLag() const override;
1504   int maxLead() const override;
1505   int maxLag() const override;
1506   int maxLagWithDiffsExpanded() const override;
1507   int VarMinLag() const override;
1508   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
1509   int PacMaxLag(int lhs_symb_id) const override;
1510   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
1511   expr_t undiff() const override;
1512   expr_t decreaseLeadsLags(int n) const override;
1513   void prepareForDerivation() override;
1514   expr_t computeDerivative(int deriv_id) override;
1515   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
1516   bool containsExternalFunction() const override;
1517   double eval(const eval_context_t &eval_context) const noexcept(false) override;
1518   void computeXrefs(EquationInfo &ei) const override;
1519   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1520   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1521   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1522   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1523   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
1524   expr_t substituteAdl() const override;
1525   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
1526   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
1527   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
1528   int findTargetVariable(int lhs_symb_id) const override;
1529   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1530   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1531   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
1532   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
1533   void compile(ostream &CompileCode, unsigned int &instruction_number,
1534                bool lhs_rhs, const temporary_terms_t &temporary_terms,
1535                const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1536                const deriv_node_temp_terms_t &tef_terms) const override;
1537   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
1538   void collectVARLHSVariable(set<expr_t> &result) const override;
1539   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
1540   bool containsEndogenous() const override;
1541   bool containsExogenous() const override;
1542   int countDiffs() const override;
1543   bool isNumConstNodeEqualTo(double value) const override;
1544   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1545   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
1546   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
1547   expr_t replaceTrendVar() const override;
1548   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
1549   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
1550   bool isInStaticForm() const override;
1551   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
1552   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
1553   bool containsPacExpectation(const string &pac_model_name = "") const override;
1554   bool isParamTimesEndogExpr() const override;
1555   bool isVarModelReferenced(const string &model_info_name) const override;
1556   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
1557   expr_t substituteStaticAuxiliaryVariable() const override;
1558   void writeJsonAST(ostream &output) const override;
1559   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1560 };
1561 
1562 class PacExpectationNode : public ExprNode
1563 {
1564 public:
1565   const string model_name;
1566 public:
1567   PacExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name);
1568   void computeTemporaryTerms(const pair<int, int> &derivOrder,
1569                              map<pair<int, int>, temporary_terms_t> &temp_terms_map,
1570                              map<expr_t, pair<int, pair<int, int>>> &reference_count,
1571                              bool is_matlab) const override;
1572   void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs, const deriv_node_temp_terms_t &tef_terms) const override;
1573   void computeTemporaryTerms(map<expr_t, int> &reference_count,
1574                              temporary_terms_t &temporary_terms,
1575                              map<expr_t, pair<int, int>> &first_occurence,
1576                              int Curr_block,
1577                              vector< vector<temporary_terms_t>> &v_temporary_terms,
1578                              int equation) const override;
1579   expr_t toStatic(DataTree &static_datatree) const override;
1580   expr_t clone(DataTree &datatree) const override;
1581   int maxEndoLead() const override;
1582   int maxExoLead() const override;
1583   int maxEndoLag() const override;
1584   int maxExoLag() const override;
1585   int maxLead() const override;
1586   int maxLag() const override;
1587   int maxLagWithDiffsExpanded() const override;
1588   int VarMinLag() const override;
1589   int VarMaxLag(const set<expr_t> &lhs_lag_equiv) const override;
1590   int PacMaxLag(int lhs_symb_id) const override;
1591   int getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const override;
1592   expr_t undiff() const override;
1593   expr_t decreaseLeadsLags(int n) const override;
1594   void prepareForDerivation() override;
1595   expr_t computeDerivative(int deriv_id) override;
1596   expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
1597   bool containsExternalFunction() const override;
1598   double eval(const eval_context_t &eval_context) const noexcept(false) override;
1599   void computeXrefs(EquationInfo &ei) const override;
1600   expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1601   expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1602   expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
1603   expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1604   expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
1605   expr_t substituteAdl() const override;
1606   expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
1607   void findDiffNodes(lag_equivalence_table_t &nodes) const override;
1608   void findUnaryOpNodesForAuxVarCreation(lag_equivalence_table_t &nodes) const override;
1609   int findTargetVariable(int lhs_symb_id) const override;
1610   expr_t substituteDiff(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1611   expr_t substituteUnaryOpNodes(const lag_equivalence_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1612   expr_t substitutePacExpectation(const string &name, expr_t subexpr) override;
1613   pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const override;
1614   void compile(ostream &CompileCode, unsigned int &instruction_number,
1615                bool lhs_rhs, const temporary_terms_t &temporary_terms,
1616                const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
1617                const deriv_node_temp_terms_t &tef_terms) const override;
1618   void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
1619   void collectVARLHSVariable(set<expr_t> &result) const override;
1620   void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
1621   bool containsEndogenous() const override;
1622   bool containsExogenous() const override;
1623   int countDiffs() const override;
1624   bool isNumConstNodeEqualTo(double value) const override;
1625   expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
1626   expr_t decreaseLeadsLagsPredeterminedVariables() const override;
1627   bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
1628   expr_t replaceTrendVar() const override;
1629   expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
1630   expr_t removeTrendLeadLag(const map<int, expr_t> &trend_symbols_map) const override;
1631   bool isInStaticForm() const override;
1632   void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
1633   expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
1634   bool containsPacExpectation(const string &pac_model_name = "") const override;
1635   bool isParamTimesEndogExpr() const override;
1636   bool isVarModelReferenced(const string &model_info_name) const override;
1637   void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
1638   expr_t substituteStaticAuxiliaryVariable() const override;
1639   void writeJsonAST(ostream &output) const override;
1640   void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, bool isdynamic) const override;
1641 };
1642 
1643 #endif
1644