ExprNode.hh 110 KB
Newer Older
1
/*
2
 * Copyright (C) 2007-2019 Dynare Team
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
 *
 * This file is part of Dynare.
 *
 * Dynare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Dynare is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Dynare.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _EXPR_NODE_HH
#define _EXPR_NODE_HH

#include <set>
#include <map>
#include <vector>
26
#include <ostream>
27
#include <functional>
28

29
30
using namespace std;

31
32
#include "SymbolTable.hh"
#include "CodeInterpreter.hh"
33
#include "ExternalFunctionsTable.hh"
34
#include "SymbolList.hh"
35
36

class DataTree;
37
class NumConstNode;
sebastien's avatar
sebastien committed
38
class VariableNode;
39
class UnaryOpNode;
sebastien's avatar
sebastien committed
40
class BinaryOpNode;
41
class PacExpectationNode;
42

43
using expr_t = class ExprNode *;
44
45
46
47

struct ExprNodeLess;

//! Type for set of temporary terms
48
49
/*! The ExprNodeLess ordering is important for the temporary terms algorithm,
    see the definition of ExprNodeLess */
50
using temporary_terms_t = set<expr_t, ExprNodeLess>;
Houtan Bastani's avatar
Houtan Bastani committed
51
/*! Keeps track of array indices of temporary_terms for writing */
52
using temporary_terms_idxs_t = map<expr_t, int>;
53

54
//! set of temporary terms used in a block
55
using temporary_terms_inuse_t = set<int>;
56

57
using map_idx_t = map<int, int>;
58

59
60
//! Type for evaluation contexts
/*! The key is a symbol id. Lags are assumed to be null */
61
using eval_context_t = map<int, double>;
62

63
//! Type for tracking first/second derivative functions that have already been written as temporary terms
64
using deriv_node_temp_terms_t = map<pair<int, vector<expr_t>>, int>;
65

66
//! Type for the substitution map used in the process of substitutitng diff expressions
67
//! diff_table[static_expr_t][lag] -> [dynamic_expr_t]
68
using diff_table_t = map<expr_t, map<int, expr_t>>;
69

70
//! Possible types of output when writing ExprNode(s)
71
enum class ExprNodeOutputType
72
  {
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
    matlabStaticModel,                           //!< Matlab code, static model
    matlabDynamicModel,                          //!< Matlab code, dynamic model
    matlabStaticModelSparse,                     //!< Matlab code, static block decomposed model
    matlabDynamicModelSparse,                    //!< Matlab code, dynamic block decomposed model
    CDynamicModel,                               //!< C code, dynamic model
    CStaticModel,                                //!< C code, static model
    juliaStaticModel,                            //!< Julia code, static model
    juliaDynamicModel,                           //!< Julia code, dynamic model
    matlabOutsideModel,                          //!< Matlab code, outside model block (for example in initval)
    latexStaticModel,                            //!< LaTeX code, static model
    latexDynamicModel,                           //!< LaTeX code, dynamic model
    latexDynamicSteadyStateOperator,             //!< LaTeX code, dynamic model, inside a steady state operator
    matlabDynamicSteadyStateOperator,            //!< Matlab code, dynamic model, inside a steady state operator
    matlabDynamicSparseSteadyStateOperator,      //!< Matlab code, dynamic block decomposed model, inside a steady state operator
    CDynamicSteadyStateOperator,                 //!< C code, dynamic model, inside a steady state operator
    juliaDynamicSteadyStateOperator,             //!< Julia code, dynamic model, inside a steady state operator
    steadyStateFile,                             //!< Matlab code, in the generated steady state file
    juliaSteadyStateFile,                        //!< Julia code, in the generated steady state file
    matlabDseries,                               //!< Matlab code for dseries
    epilogueFile                                 //!< Matlab code, in the generated epilogue file
93
94
  };

95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
inline bool
isMatlabOutput(ExprNodeOutputType output_type)
{
  return output_type == ExprNodeOutputType::matlabStaticModel
    || output_type == ExprNodeOutputType::matlabDynamicModel
    || output_type == ExprNodeOutputType::matlabOutsideModel
    || output_type == ExprNodeOutputType::matlabStaticModelSparse
    || output_type == ExprNodeOutputType::matlabDynamicModelSparse
    || output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator
    || output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
    || output_type == ExprNodeOutputType::steadyStateFile
    || output_type == ExprNodeOutputType::matlabDseries
    || output_type == ExprNodeOutputType::epilogueFile;
}

inline bool
isJuliaOutput(ExprNodeOutputType output_type)
{
  return output_type == ExprNodeOutputType::juliaStaticModel
    || output_type == ExprNodeOutputType::juliaDynamicModel
    || output_type == ExprNodeOutputType::juliaDynamicSteadyStateOperator
    || output_type == ExprNodeOutputType::juliaSteadyStateFile;
}

inline bool
isCOutput(ExprNodeOutputType output_type)
{
  return output_type == ExprNodeOutputType::CDynamicModel
    || output_type == ExprNodeOutputType::CStaticModel
    || output_type == ExprNodeOutputType::CDynamicSteadyStateOperator;
}

inline bool
isLatexOutput(ExprNodeOutputType output_type)
{
  return output_type == ExprNodeOutputType::latexStaticModel
    || output_type == ExprNodeOutputType::latexDynamicModel
    || output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator;
}
134

Houtan Bastani's avatar
Houtan Bastani committed
135
136
/* Equal to 1 for Matlab langage or Julia, or to 0 for C language. Not defined for LaTeX.
   In Matlab and Julia, array indexes begin at 1, while they begin at 0 in C */
137
#define ARRAY_SUBSCRIPT_OFFSET(output_type) ((int) (isMatlabOutput(output_type) || isJuliaOutput(output_type)))
138

139
// Left and right array subscript delimiters: '(' and ')' for Matlab, '[' and ']' for C
140
141
#define LEFT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? '(' : '[')
#define RIGHT_ARRAY_SUBSCRIPT(output_type) (isMatlabOutput(output_type) ? ')' : ']')
142

143
// Left and right parentheses
144
145
#define LEFT_PAR(output_type) (isLatexOutput(output_type) ? "\\left(" : "(")
#define RIGHT_PAR(output_type) (isLatexOutput(output_type) ? "\\right)" : ")")
146
147

//! Base class for expression nodes
148
class ExprNode
149
150
151
152
153
154
155
156
157
158
159
160
161
    {
      friend class DataTree;
      friend class DynamicModel;
      friend class StaticModel;
      friend class ModelTree;
      friend struct ExprNodeLess;
      friend class NumConstNode;
      friend class VariableNode;
      friend class UnaryOpNode;
      friend class BinaryOpNode;
      friend class TrinaryOpNode;
      friend class AbstractExternalFunctionNode;
      friend class VarExpectationNode;
162
      friend class PacExpectationNode;
163
164
165
166
167
168
169
170
171
172
    private:
      //! Computes derivative w.r. to a derivation ID (but doesn't store it in derivatives map)
      /*! You shoud use getDerivative() to get the benefit of symbolic a priori and of caching */
      virtual expr_t computeDerivative(int deriv_id) = 0;

    protected:
      //! Reference to the enclosing DataTree
      DataTree &datatree;

      //! Index number
173
      const int idx;
174
175

      //! Is the data member non_null_derivatives initialized ?
176
      bool preparedForDerivation{false};
177
178
179
180
181
182
183

      //! Set of derivation IDs with respect to which the derivative is potentially non-null
      set<int> non_null_derivatives;

      //! Used for caching of first order derivatives (when non-null)
      map<int, expr_t> derivatives;

184
185
186
187
      const static int min_cost_matlab{40*90};
      const static int min_cost_c{40*4};
      inline static int min_cost(bool is_matlab) { return(is_matlab ? min_cost_matlab : min_cost_c); };

188
189
190
191
      //! Cost of computing current node
      /*! Nodes included in temporary_terms are considered having a null cost */
      virtual int cost(int cost, bool is_matlab) const;
      virtual int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const;
192
      virtual int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const;
193
194
195
196

      //! For creating equation cross references
      struct EquationInfo
      {
197
198
199
200
        set<pair<int, int>> param;
        set<pair<int, int>> endo;
        set<pair<int, int>> exo;
        set<pair<int, int>> exo_det;
201
202
      };

203
204
205
206
207
208
      //! If this node is a temporary term, writes its temporary term representation
      /*! Returns true if node is a temporary term and has therefore been
          written to output*/
      bool checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
                                         const temporary_terms_t &temporary_terms,
                                         const temporary_terms_idxs_t &temporary_terms_idxs) const;
209
210
211
212

      // Internal helper for matchVariableTimesConstantTimesParam()
      virtual void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const;

213
    public:
214
      ExprNode(DataTree &datatree_arg, int idx_arg);
215
      virtual ~ExprNode() = default;
216

217
218
219
220
221
      ExprNode(const ExprNode &) = delete;
      ExprNode(ExprNode &&) = delete;
      ExprNode & operator=(const ExprNode &) = delete;
      ExprNode & operator=(ExprNode &&) = delete;

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
      //! Initializes data member non_null_derivatives
      virtual void prepareForDerivation() = 0;

      //! Returns derivative w.r. to derivation ID
      /*! Uses a symbolic a priori to pre-detect null derivatives, and caches the result for other derivatives (to avoid computing it several times)
        For an equal node, returns the derivative of lhs minus rhs */
      expr_t getDerivative(int deriv_id);

      //! Computes derivatives by applying the chain rule for some variables
      /*!
        \param deriv_id The derivation ID with respect to which we are derivating
        \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
      */
      virtual expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) = 0;

      //! Returns precedence of node
      /*! Equals 100 for constants, variables, unary ops, and temporary terms */
      virtual int precedence(ExprNodeOutputType output_t, const temporary_terms_t &temporary_terms) const;

241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
      //! Compute temporary terms in this expression
      /*!
        \param[in] derivOrder the derivation order (first w.r.t. endo/exo,
                   second w.r.t. params)
        \param[out] temp_terms_map the computed temporary terms, associated
                    with their derivation order
        \param[out] reference_count a temporary structure, used to count
                    references to each node (integer in outer pair is the
                    reference count, the inner pair is the derivation order)
        \param[in] is_matlab whether we are in a MATLAB context, since that
                    affects the cost of each operator

        A node will be marked as a temporary term if it is referenced at least
        two times (i.e. has at least two parents), and has a computing cost
        (multiplied by reference count) greater to datatree.min_cost
      */
      virtual void computeTemporaryTerms(const pair<int, int> &derivOrder,
                                         map<pair<int, int>, temporary_terms_t> &temp_terms_map,
                                         map<expr_t, pair<int, pair<int, int>>> &reference_count,
                                         bool is_matlab) const;
261
262
263
264
265
266

      //! Writes output of node, using a Txxx notation for nodes in temporary_terms, and specifiying the set of already written external functions
      /*!
        \param[in] output the output stream
        \param[in] output_type the type of output (MATLAB, C, LaTeX...)
        \param[in] temporary_terms the nodes that are marked as temporary terms
267
        \param[in] a map from temporary_terms to integers indexes (in the
268
269
                   MATLAB, C or Julia vector of temporary terms); can be empty
                   when writing MATLAB with block decomposition)
270
        \param[in] tef_terms the set of already written external function nodes
271
      */
272
      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;
273
274
275
276
277
278
279
280
281
282
283

      //! returns true if the expr node contains an external function
      virtual bool containsExternalFunction() const = 0;

      //! Writes output of node (with no temporary terms and with "outside model" output type)
      void writeOutput(ostream &output) const;

      //! Writes output of node (with no temporary terms)
      void writeOutput(ostream &output, ExprNodeOutputType output_type) const;

      //! Writes output of node, using a Txxx notation for nodes in temporary_terms
Houtan Bastani's avatar
Houtan Bastani committed
284
      void writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const;
285

Stéphane Adjemian's avatar
Stéphane Adjemian committed
286
      //! Writes output of node in JSON syntax
287
      virtual void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic = true) const = 0;
Stéphane Adjemian's avatar
Stéphane Adjemian committed
288

Houtan Bastani's avatar
Houtan Bastani committed
289
290
291
      //! Writes the Abstract Syntax Tree in JSON
      virtual void writeJsonAST(ostream &output) const = 0;

Stéphane Adjemian's avatar
Stéphane Adjemian committed
292
293
      virtual int precedenceJson(const temporary_terms_t &temporary_terms) const;

294
295
296
      //! Writes the output for an external function, ensuring that the external function is called as few times as possible using temporary terms
      virtual void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
                                               const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
297
                                               const temporary_terms_idxs_t &temporary_terms_idxs,
298
299
                                               deriv_node_temp_terms_t &tef_terms) const;

Stéphane Adjemian's avatar
Stéphane Adjemian committed
300
301
302
303
      //! Write the JSON output of an external function in a string vector
      //! Allows the insertion of commas if necessary
      virtual void writeJsonExternalFunctionOutput(vector<string> &efout,
                                                   const temporary_terms_t &temporary_terms,
304
305
                                                   deriv_node_temp_terms_t &tef_terms,
                                                   const bool isdynamic = true) const;
Stéphane Adjemian's avatar
Stéphane Adjemian committed
306

307
308
309
310
311
312
313
314
315
316
317
318
      virtual void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
                                                 bool lhs_rhs, const temporary_terms_t &temporary_terms,
                                                 const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
                                                 deriv_node_temp_terms_t &tef_terms) const;

      //! Computes the set of all variables of a given symbol type in the expression (with information on lags)
      /*!
        Variables are stored as integer pairs of the form (symb_id, lag).
        They are added to the set given in argument.
        Note that model local variables are substituted by their expression in the computation
        (and added if type_arg = ModelLocalVariable).
      */
319
      virtual void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const = 0;
320

321
322
323
      //! Find lowest lag for VAR
      virtual int VarMinLag() const = 0;

324
      //! Find the maximum lag in a VAR: handles case where LHS is diff
Houtan Bastani's avatar
Houtan Bastani committed
325
      virtual int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const = 0;
326
327
328
329

      //! Finds LHS variable in a VAR equation
      virtual void collectVARLHSVariable(set<expr_t> &result) const = 0;

330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
      //! Computes the set of all variables of a given symbol type in the expression (without information on lags)
      /*!
        Variables are stored as symb_id.
        They are added to the set given in argument.
        Note that model local variables are substituted by their expression in the computation
        (and added if type_arg = ModelLocalVariable).
      */
      void collectVariables(SymbolType type_arg, set<int> &result) const;

      //! Computes the set of endogenous variables in the expression
      /*!
        Endogenous are stored as integer pairs of the form (type_specific_id, lag).
        They are added to the set given in argument.
        Note that model local variables are substituted by their expression in the computation.
      */
345
      virtual void collectEndogenous(set<pair<int, int>> &result) const;
346
347
348
349
350
351
352

      //! Computes the set of exogenous variables in the expression
      /*!
        Exogenous are stored as integer pairs of the form (type_specific_id, lag).
        They are added to the set given in argument.
        Note that model local variables are substituted by their expression in the computation.
      */
353
      virtual void collectExogenous(set<pair<int, int>> &result) const;
354
355
356
357
358

      virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const = 0;

      virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
                                         temporary_terms_t &temporary_terms,
359
                                         map<expr_t, pair<int, int>> &first_occurence,
360
                                         int Curr_block,
361
                                         vector< vector<temporary_terms_t>> &v_temporary_terms,
362
363
364
365
366
367
368
369
370
371
372
373
                                         int equation) const;

      class EvalException

      {
      };

      class EvalExternalFunctionException : public EvalException

      {
      };

374
      virtual double eval(const eval_context_t &eval_context) const noexcept(false) = 0;
375
      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;
376
377
378
379
380
381
382
383
384
385
386
387
388
389
      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;
      //! Creates a static version of this node
      /*!
        This method duplicates the current node by creating a similar node from which all leads/lags have been stripped,
        adds the result in the static_datatree argument (and not in the original datatree), and returns it.
      */
      virtual expr_t toStatic(DataTree &static_datatree) const = 0;

      /*!
        Compute cross references for equations
      */
      //  virtual void computeXrefs(set<int> &param, set<int> &endo, set<int> &exo, set<int> &exo_det) const = 0;
      virtual void computeXrefs(EquationInfo &ei) const = 0;
      //! Try to normalize an equation linear in its endogenous variable
390
      virtual pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const = 0;
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407

      //! Returns the maximum lead of endogenous in this expression
      /*! Always returns a non-negative value */
      virtual int maxEndoLead() const = 0;

      //! Returns the maximum lead of exogenous in this expression
      /*! Always returns a non-negative value */
      virtual int maxExoLead() const = 0;

      //! Returns the maximum lag of endogenous in this expression
      /*! Always returns a non-negative value */
      virtual int maxEndoLag() const = 0;

      //! Returns the maximum lag of exogenous in this expression
      /*! Always returns a non-negative value */
      virtual int maxExoLag() const = 0;

408
409
410
      //! Returns the maximum lead of endo/exo/exodet in this expression
      /*! A negative value means that the expression contains only lagged
          variables. */
411
412
      virtual int maxLead() const = 0;

413
414
415
      //! Returns the maximum lag of endo/exo/exodet in this expression
      /*! A negative value means that the expression contains only leaded
          variables. */
416
417
      virtual int maxLag() const = 0;

418
419
420
421
422
423
      //! Returns the maximum lag of endo/exo/exodet, as if diffs were expanded
      /*! This function behaves as maxLag(), except that it treats diff()
          differently. For e.g., on diff(diff(x(-1))), maxLag() returns 1 while
          maxLagWithDiffsExpanded() returns 3. */
      virtual int maxLagWithDiffsExpanded() const = 0;

Houtan Bastani's avatar
Houtan Bastani committed
424
425
      //! Get Max lag of var associated with Pac model
      //! Takes account of undiffed LHS variables in calculating the max lag
426
      virtual int PacMaxLag(int lhs_symb_id) const = 0;
Houtan Bastani's avatar
Houtan Bastani committed
427

Houtan Bastani's avatar
Houtan Bastani committed
428
429
      virtual expr_t undiff() const = 0;

430
431
432
433
434
435
436
437
      //! Returns a new expression where all the leads/lags have been shifted backwards by the same amount
      /*!
        Only acts on endogenous, exogenous, exogenous det
        \param[in] n The number of lags by which to shift
        \return The same expression except that leads/lags have been shifted backwards
      */
      virtual expr_t decreaseLeadsLags(int n) const = 0;

438
      //! Type for the substitution map used in the process of creating auxiliary vars
439
      using subst_table_t = map<const ExprNode *, const VariableNode *>;
440

441
      //! Type for the substitution map used in the process of substituting adl expressions
442
      using subst_table_adl_t = map<const ExprNode *, const expr_t>;
443

444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
      //! Creates auxiliary endo lead variables corresponding to this expression
      /*!
        If maximum endogenous lead >= 3, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
        \pre This expression is assumed to have maximum endogenous lead >= 2
        \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
        \return The new variable node corresponding to the current expression
      */
      VariableNode *createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;

      //! Creates auxiliary exo lead variables corresponding to this expression
      /*!
        If maximum exogenous lead >= 2, this method will also create intermediary auxiliary var, and will add the equations of the form aux1 = aux2(+1) to the substitution table.
        \pre This expression is assumed to have maximum exogenous lead >= 1
        \param[in,out] subst_table The table to which new auxiliary variables and their correspondance will be added
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
        \return The new variable node corresponding to the current expression
      */
      VariableNode *createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;

      //! Constructs a new expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
      /*!
        \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.
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.

        If the method detects a sub-expr which needs to be substituted, two cases are possible:
        - if this expr is in the table, then it will use the corresponding variable and return the substituted expression
        - 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

        \return A new equivalent expression where sub-expressions with max endo lead >= 2 have been replaced by auxiliary variables
      */
      virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;

      //! Constructs a new expression where endo variables with max endo lag >= 2 have been replaced by auxiliary variables
      /*!
        \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.
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
      */
      virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;

      //! Constructs a new expression where exogenous variables with a lead have been replaced by auxiliary variables
      /*!
        \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.
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
      */
      virtual expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const = 0;
      //! Constructs a new expression where exogenous variables with a lag have been replaced by auxiliary variables
      /*!
        \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.
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
      */
      virtual expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;

      //! Constructs a new expression where the expectation operator has been replaced by auxiliary variables
      /*!
        \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.
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
        \param[in] partial_information_model Are we substituting in a partial information model?
      */
      virtual expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const = 0;

      virtual expr_t decreaseLeadsLagsPredeterminedVariables() const = 0;

      //! 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
      /*!
        \param[in] subset variables to which to limit the transformation; transform
        all fwrd vars if empty
        \param[in,out] subst_table Map used to store mapping between a given
        forward variable and the aux var that contains its differentiate
        \param[out] neweqs Equations to be added to the model to match the creation of auxiliary variables.
      */
      virtual expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;

      //! Return true if the nodeID is a numerical constant equal to value and false otherwise
      /*!
        \param[in] value of the numerical constante
        \param[out] the boolean equal to true if NodeId is a constant equal to value
      */
      virtual bool isNumConstNodeEqualTo(double value) const = 0;

      //! Returns true if the expression contains one or several endogenous variable
525
      virtual bool containsEndogenous() const = 0;
526
527
528
529

      //! Returns true if the expression contains one or several exogenous variable
      virtual bool containsExogenous() const = 0;

530
      //! Returns the maximum number of nested diffs in the expression
531
      virtual int countDiffs() const = 0;
532

533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
      //! 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
      /*!
        \param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
        \param[out] the boolean equal to true if NodeId is the variable
      */
      virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const = 0;

      //! Replaces the Trend var with datatree.One
      virtual expr_t replaceTrendVar() const = 0;

      //! Constructs a new expression where the variable indicated by symb_id has been detrended
      /*!
        \param[in] symb_id indicating the variable to be detrended
        \param[in] log_trend indicates if the trend is in log
        \param[in] trend indicating the trend
        \return the new binary op pointing to a detrended variable
      */
      virtual expr_t detrend(int symb_id, bool log_trend, expr_t trend) const = 0;

552
553
554
      //! Substitute adl operator
      virtual expr_t substituteAdl() const = 0;

555
556
557
      //! Substitute VarExpectation nodes
      virtual expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const = 0;

558
      //! Substitute diff operator
559
      virtual void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const = 0;
560
      virtual void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const = 0;
561
      virtual int findTargetVariable(int lhs_symb_id) const = 0;
Houtan Bastani's avatar
Houtan Bastani committed
562
      virtual expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
563
      virtual expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const = 0;
564

565
      //! Substitute pac_expectation operator
566
      virtual expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) = 0;
567

568
      //! Add ExprNodes to the provided datatree
569
      virtual expr_t clone(DataTree &datatree) const = 0;
570
571
572
573
574
575
576
577
578
579
580
581
582

      //! Move a trend variable with lag/lead to time t by dividing/multiplying by its growth factor
      virtual expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const = 0;

      //! Returns true if the expression is in static form (no lead, no lag, no expectation, no STEADY_STATE)
      virtual bool isInStaticForm() const = 0;

      //! Substitute auxiliary variables by their expression in static model
      virtual expr_t substituteStaticAuxiliaryVariable() const = 0;

      //! Returns true if model_info_name is referenced by a VarExpectationNode
      virtual bool isVarModelReferenced(const string &model_info_name) const = 0;

583
584
      //! Fills parameter information rerhs_symblated to PAC equation
      virtual void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
585
586
                                        set<pair<int, pair<int, int>>> &params_and_vars) const = 0;

587
      //! Matches a linear combination of variables, where scalars can be constant*parameter
588
589
      /*! Returns a list of (variable_id, lag, param_id, constant)
          corresponding to the terms in the expression. When there is no
590
591
592
          parameter in a term, param_id == -1.
          Can throw a MatchFailureException. */
      vector<tuple<int, int, int, double>> matchLinearCombinationOfVariables() const;
593
594
595
596
597
598
599
600
601
602
      //! Returns true if expression is of the form:
      //! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
      virtual bool isParamTimesEndogExpr() const = 0;

      //! Finds the share of optimizing agents in the PAC equation,
      //! the expr node associated with it,
      //! and the expr node associated with the non-optimizing part
      virtual void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
                                                     expr_t &optim_part,
                                                     expr_t &non_optim_part) const = 0;
603
      //! Adds PAC equation param info to pac_expectation
604
      virtual void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) = 0;
605

606
      //! Fills var_model info for pac_expectation node
607
      virtual void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) = 0;
608

Houtan Bastani's avatar
Houtan Bastani committed
609
      //! Fills the AR matrix structure
610
      virtual void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const = 0;
Houtan Bastani's avatar
Houtan Bastani committed
611

612
      //! Fills the EC matrix structure
613
614
      virtual void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs,
                                          map<tuple<int, int, int>, expr_t> &EC) const = 0;
615

616
      //! Finds equations where a variable is equal to a constant
617
      virtual void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const = 0;
618
619

      //! Replaces variables found in findConstantEquations() with their constant values
620
      virtual expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const = 0;
621

622
      //! Returns true if PacExpectationNode encountered
623
      virtual bool containsPacExpectation(const string &pac_model_name = "") const = 0;
624

625
626
      //! Fills map
      virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0;
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653

      //! Decompose an expression into its additive terms
      /*! Returns a list of terms, with their sign (either 1 or -1, depending
        on whether the terms appears with a plus or a minus).
        The current_sign argument should normally be left to 1.
        If current_sign == -1, then all signs are inverted */
      virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign = 1) const;

      // Matches an expression of the form variable*constant*parameter
      /* Returns a tuple (variable_id, lag, param_id, constant).
         The variable must be an exogenous or an endogenous.
         The constant is optional (in which case 1 is returned); there can be
         several multiplicative constants; constants can also appear at the
         denominator (i.e. after a divide sign).
         The parameter is optional (in which case param_id == -1).
         If the expression is not of the expected form, throws a
         MatchFailureException */
      tuple<int, int, int, double> matchVariableTimesConstantTimesParam() const;

      //! Exception thrown by matchVariableTimesConstantTimesParam when matching fails
      class MatchFailureException
      {
      public:
        const string message;
        MatchFailureException(string message_arg) : message{move(message_arg)} {};
      };
};
654
655

//! Object used to compare two nodes (using their indexes)
656
657
658
/*! Note that in this ordering, a subexpression is always less than the
    expression from which it is extracted. This property is used extensively in
    the temporary terms computations. */
659
660
struct ExprNodeLess
{
661
  bool
662
  operator()(expr_t arg1, expr_t arg2) const
663
664
665
666
667
668
669
670
671
  {
    return arg1->idx < arg2->idx;
  }
};

//! Numerical constant node
/*! The constant is necessarily non-negative (this is enforced at the NumericalConstants class level) */
class NumConstNode : public ExprNode
{
672
public:
673
674
  //! Id from numerical constants table
  const int id;
675
private:
676
  expr_t computeDerivative(int deriv_id) override;
677
678
protected:
  void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
679
public:
680
  NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg);
681
682
  void prepareForDerivation() override;
  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;
Houtan Bastani's avatar
Houtan Bastani committed
683
  void writeJsonAST(ostream &output) const override;
684
685
686
  void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
  bool containsExternalFunction() const override;
  void collectVARLHSVariable(set<expr_t> &result) const override;
687
  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
688
689
690
691
692
  void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
  double eval(const eval_context_t &eval_context) const noexcept(false) override;
  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;
  expr_t toStatic(DataTree &static_datatree) const override;
  void computeXrefs(EquationInfo &ei) const override;
693
  pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>>  &List_of_Op_RHS) const override;
694
695
696
697
698
699
700
  expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
  int maxEndoLead() const override;
  int maxExoLead() const override;
  int maxEndoLag() const override;
  int maxExoLag() const override;
  int maxLead() const override;
  int maxLag() const override;
701
  int maxLagWithDiffsExpanded() const override;
702
  int VarMinLag() const override;
Houtan Bastani's avatar
Houtan Bastani committed
703
  int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
704
  int PacMaxLag(int lhs_symb_id) const override;
705
706
707
708
709
710
711
712
  expr_t undiff() const override;
  expr_t decreaseLeadsLags(int n) const override;
  expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
  expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
  expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
  expr_t substituteAdl() const override;
713
  expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
714
715
  void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override;
  void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override;
716
  int findTargetVariable(int lhs_symb_id) const override;
717
718
719
720
721
722
723
724
725
726
727
728
  expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override;
  expr_t decreaseLeadsLagsPredeterminedVariables() const override;
  expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  bool isNumConstNodeEqualTo(double value) const override;
  bool containsEndogenous() const override;
  bool containsExogenous() const override;
  int countDiffs() const override;
  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
  expr_t replaceTrendVar() const override;
  expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
729
  expr_t clone(DataTree &datatree) const override;
730
731
  expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
  bool isInStaticForm() const override;
732
  void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
733
  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
734
  void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
735
  void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
736
737
  void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
738
  bool containsPacExpectation(const string &pac_model_name = "") const override;
739
  void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
740
741
742
743
744
                            set<pair<int, pair<int, int>>> &params_and_vars) const override;
  void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
                                         expr_t &optim_part,
                                         expr_t &non_optim_part) const override;
  bool isParamTimesEndogExpr() const override;
745
746
747
  bool isVarModelReferenced(const string &model_info_name) const override;
  void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
  expr_t substituteStaticAuxiliaryVariable() const override;
748
749
750
751
752
};

//! Symbol or variable node
class VariableNode : public ExprNode
{
753
  friend class UnaryOpNode;
754
public:
755
756
  //! Id from the symbol table
  const int symb_id;
757
  //! A positive value is a lead, a negative is a lag
758
  const int lag;
759
private:
760
  expr_t computeDerivative(int deriv_id) override;
761
762
protected:
  void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
763
public:
764
  VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg);
765
766
  void prepareForDerivation() override;
  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;
Houtan Bastani's avatar
Houtan Bastani committed
767
  void writeJsonAST(ostream &output) const override;
768
769
770
  void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
  bool containsExternalFunction() const override;
  void collectVARLHSVariable(set<expr_t> &result) const override;
771
  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
772
  void computeTemporaryTerms(map<expr_t, int > &reference_count,
773
                                     temporary_terms_t &temporary_terms,
774
                                     map<expr_t, pair<int, int>> &first_occurence,
775
                                     int Curr_block,
776
                                     vector< vector<temporary_terms_t>> &v_temporary_terms,
777
778
779
780
781
782
                                     int equation) const override;
  void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
  double eval(const eval_context_t &eval_context) const noexcept(false) override;
  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;
  expr_t toStatic(DataTree &static_datatree) const override;
  void computeXrefs(EquationInfo &ei) const override;
783
  SymbolType get_type() const;
784
  pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>>  &List_of_Op_RHS) const override;
785
786
787
788
789
790
791
  expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
  int maxEndoLead() const override;
  int maxExoLead() const override;
  int maxEndoLag() const override;
  int maxExoLag() const override;
  int maxLead() const override;
  int maxLag() const override;
792
  int maxLagWithDiffsExpanded() const override;
793
  int VarMinLag() const override;
Houtan Bastani's avatar
Houtan Bastani committed
794
  int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
795
  int PacMaxLag(int lhs_symb_id) const override;
796
797
798
799
800
801
802
803
  expr_t undiff() const override;
  expr_t decreaseLeadsLags(int n) const override;
  expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
  expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
  expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
  expr_t substituteAdl() const override;
804
  expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
805
806
  void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override;
  void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override;
807
  int findTargetVariable(int lhs_symb_id) const override;
808
809
810
811
812
813
814
815
816
817
818
819
  expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override;
  expr_t decreaseLeadsLagsPredeterminedVariables() const override;
  expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  bool isNumConstNodeEqualTo(double value) const override;
  bool containsEndogenous() const override;
  bool containsExogenous() const override;
  int countDiffs() const override;
  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
  expr_t replaceTrendVar() const override;
  expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
820
  expr_t clone(DataTree &datatree) const override;
821
822
  expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
  bool isInStaticForm() const override;
823
  void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
824
  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
825
  void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
826
  void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
827
828
  void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
829
  bool containsPacExpectation(const string &pac_model_name = "") const override;
830
  void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
831
832
833
834
835
                            set<pair<int, pair<int, int>>> &params_and_vars) const override;
  void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
                                         expr_t &optim_part,
                                         expr_t &non_optim_part) const override;
  bool isParamTimesEndogExpr() const override;
836
837
  bool isVarModelReferenced(const string &model_info_name) const override;
  void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
838
  //! Substitute auxiliary variables by their expression in static model
839
  expr_t substituteStaticAuxiliaryVariable() const override;
840
841
842
843
844
};

//! Unary operator node
class UnaryOpNode : public ExprNode
{
845
846
protected:
  void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
847
public:
848
  const expr_t arg;
sebastien's avatar
sebastien committed
849
850
  //! Stores the information set. Only used for expectation operator
  const int expectation_information_set;
851
  //! Only used for UnaryOpcode::steadyStateParamDeriv and UnaryOpcode::steadyStateParam2ndDeriv
852
  const int param1_symb_id, param2_symb_id;
853
  const UnaryOpcode op_code;
854
  const string adl_param_name;
855
  const vector<int> adl_lags;
856
private:
857
858
859
  expr_t computeDerivative(int deriv_id) override;
  int cost(int cost, bool is_matlab) const override;
  int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
860
  int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
861
  //! Returns the derivative of this node if darg is the derivative of the argument
862
  expr_t composeDerivatives(expr_t darg, int deriv_id);
863
public:
864
  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);
865
  void prepareForDerivation() override;
866
867
868
869
  void computeTemporaryTerms(const pair<int, int> &derivOrder,
                             map<pair<int, int>, temporary_terms_t> &temp_terms_map,
                             map<expr_t, pair<int, pair<int, int>>> &reference_count,
                             bool is_matlab) const override;
870
  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;
Houtan Bastani's avatar
Houtan Bastani committed
871
  void writeJsonAST(ostream &output) const override;
872
873
874
  void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
  bool containsExternalFunction() const override;
  void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
875
                                           const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
876
                                           const temporary_terms_idxs_t &temporary_terms_idxs,
877
878
                                           deriv_node_temp_terms_t &tef_terms) const override;
  void writeJsonExternalFunctionOutput(vector<string> &efout,
879
                                               const temporary_terms_t &temporary_terms,
880
                                               deriv_node_temp_terms_t &tef_terms,
881
882
                                               const bool isdynamic) const override;
  void compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
883
884
                                             bool lhs_rhs, const temporary_terms_t &temporary_terms,
                                             const map_idx_t &map_idx, bool dynamic, bool steady_dynamic,
885
886
                                             deriv_node_temp_terms_t &tef_terms) const override;
  void computeTemporaryTerms(map<expr_t, int> &reference_count,
887
                                     temporary_terms_t &temporary_terms,
888
                                     map<expr_t, pair<int, int>> &first_occurence,
889
                                     int Curr_block,
890
                                     vector< vector<temporary_terms_t>> &v_temporary_terms,
891
892
                                     int equation) const override;
  void collectVARLHSVariable(set<expr_t> &result) const override;
893
  void collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const override;
894
  void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const override;
895
  static double eval_opcode(UnaryOpcode op_code, double v) noexcept(false);
896
897
898
899
  double eval(const eval_context_t &eval_context) const noexcept(false) override;
  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;
  expr_t toStatic(DataTree &static_datatree) const override;
  void computeXrefs(EquationInfo &ei) const override;
900
  pair<int, expr_t> normalizeEquation(int symb_id_endo, vector<tuple<int, expr_t, expr_t>>  &List_of_Op_RHS) const override;
901
902
903
904
905
906
907
  expr_t getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables) override;
  int maxEndoLead() const override;
  int maxExoLead() const override;
  int maxEndoLag() const override;
  int maxExoLag() const override;
  int maxLead() const override;
  int maxLag() const override;
908
  int maxLagWithDiffsExpanded() const override;
909
  int VarMinLag() const override;
Houtan Bastani's avatar
Houtan Bastani committed
910
  int VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const override;
911
  int PacMaxLag(int lhs_symb_id) const override;
912
913
914
  expr_t undiff() const override;
  expr_t decreaseLeadsLags(int n) const override;
  expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
sebastien's avatar
sebastien committed
915
  //! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
916
  expr_t buildSimilarUnaryOpNode(expr_t alt_arg, DataTree &alt_datatree) const;
917
918
919
920
921
  expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const override;
  expr_t substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const override;
  expr_t substituteAdl() const override;
922
  expr_t substituteVarExpectation(const map<string, expr_t> &subst_table) const override;
923
  void findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const override;
924
  bool createAuxVarForUnaryOpNode() const;
925
  void findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const override;
926
  int findTargetVariable(int lhs_symb_id) const override;
927
928
929
930
931
932
933
934
935
936
937
938
  expr_t substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  expr_t substitutePacExpectation(map<const PacExpectationNode *, const BinaryOpNode *> &subst_table) override;
  expr_t decreaseLeadsLagsPredeterminedVariables() const override;
  expr_t differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const override;
  bool isNumConstNodeEqualTo(double value) const override;
  bool containsEndogenous() const override;
  bool containsExogenous() const override;
  int countDiffs() const override;
  bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const override;
  expr_t replaceTrendVar() const override;
  expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
939
  expr_t clone(DataTree &datatree) const override;
940
941
  expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
  bool isInStaticForm() const override;
942
  void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
943
  void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int growth_lag, int equation_number_arg) override;
944
  void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
945
  void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
946
947
  void findConstantEquations(map<VariableNode *, NumConstNode *> &table) const override;
  expr_t replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const override;
948
  bool containsPacExpectation(const string &pac_model_name = "") const override;
949
  void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
950
951
952
953
954
                            set<pair<int, pair<int, int>>> &params_and_vars) const override;
  void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
                                         expr_t &optim_part,
                                         expr_t &non_optim_part) const override;
  bool isParamTimesEndogExpr() const override;
955
956
  bool isVarModelReferenced(const string &model_info_name) const override;
  void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
957
  //! Substitute auxiliary variables by their expression in static model
958
  expr_t substituteStaticAuxiliaryVariable() const override;
959
  void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign) const override;
960
961
962
963
964
};

//! Binary operator node
class BinaryOpNode : public ExprNode
{
965
966
protected:
  void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
967
public:
968
  const expr_t arg1, arg2;
969
  const BinaryOpcode op_code;
970
971
972
  const int powerDerivOrder;
  const string adlparam;
private:
973
974
975
  expr_t computeDerivative(int deriv_id) override;
  int cost(int cost, bool is_matlab) const override;
  int cost(const temporary_terms_t &temporary_terms, bool is_matlab) const override;
976
  int cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const override;
977
  //! Returns the derivative of this node if darg1 and darg2 are the derivatives of the arguments
978
  expr_t composeDerivatives(expr_t darg1, expr_t darg2);
979
public:
980
  BinaryOpNode(DataTree &datatree_arg, int idx_arg, const expr_t arg1_arg,
981
               BinaryOpcode op_code_arg, const expr_t arg2_arg, int powerDerivOrder);
982
983
984
  void prepareForDerivation() override;
  int precedenceJson(const temporary_terms_t &temporary_terms) const override;
  int precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const override;
985
986
987
988
  void computeTemporaryTerms(const pair<int, int> &derivOrder,
                             map<pair<int, int>, temporary_terms_t> &temp_terms_map,
                             map<expr_t, pair<int, pair<int, int>>> &reference_count,
                             bool is_matlab) const override;
989
  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;
Houtan Bastani's avatar
Houtan Bastani committed
990
  void writeJsonAST(ostream &output) const override;
991
992
993
  void writeJsonOutput(ostream &output, const temporary_terms_t &temporary_terms, const deriv_node_temp_terms_t &tef_terms, const bool isdynamic) const override;
  bool containsExternalFunction() const override;
  void writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
994
                                           const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
995
                                           const temporary_terms_idxs_t &temporary_terms_idxs,
996
997
                                           deriv_node_temp_terms_t &tef_terms) const override;
  void writeJsonExternalFunctionOutput(vector<string> &efout,
998
                                               const temporary_terms_t &temporary_terms,
999
                                               deriv_node_temp_terms_t &tef_terms,
1000
                                               const bool isdynamic) const override;