ExprNode.cc 320 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
 *
 * 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/>.
 */

#include <iostream>
#include <iterator>
#include <algorithm>

24
#include <cassert>
25
#include <cmath>
26

27
#include <utility>
28

29
30
#include "ExprNode.hh"
#include "DataTree.hh"
31
#include "ModFile.hh"
32

33
ExprNode::ExprNode(DataTree &datatree_arg, int idx_arg) : datatree{datatree_arg}, idx{idx_arg}
34
35
36
{
}

37
expr_t
38
ExprNode::getDerivative(int deriv_id)
39
{
sebastien's avatar
sebastien committed
40
41
  if (!preparedForDerivation)
    prepareForDerivation();
42

43
  // Return zero if derivative is necessarily null (using symbolic a priori)
44
  auto it = non_null_derivatives.find(deriv_id);
45
46
  if (it == non_null_derivatives.end())
    return datatree.Zero;
47

48
  // If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
49
  map<int, expr_t>::const_iterator it2 = derivatives.find(deriv_id);
50
51
52
53
  if (it2 != derivatives.end())
    return it2->second;
  else
    {
54
      expr_t d = computeDerivative(deriv_id);
55
      derivatives[deriv_id] = d;
56
57
58
59
      return d;
    }
}

ferhat's avatar
ferhat committed
60
int
61
ExprNode::precedence(ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms) const
62
63
64
65
{
  // For a constant, a variable, or a unary op, the precedence is maximal
  return 100;
}
ferhat's avatar
ferhat committed
66

67
68
69
70
71
72
73
int
ExprNode::precedenceJson(const temporary_terms_t &temporary_terms) const
{
  // For a constant, a variable, or a unary op, the precedence is maximal
  return 100;
}

74
int
75
76
77
78
79
80
81
82
83
84
85
86
87
88
ExprNode::cost(int cost, bool is_matlab) const
{
  // For a terminal node, the cost is null
  return 0;
}

int
ExprNode::cost(const temporary_terms_t &temp_terms_map, bool is_matlab) const
{
  // For a terminal node, the cost is null
  return 0;
}

int
89
ExprNode::cost(const map<pair<int, int>, temporary_terms_t> &temp_terms_map, bool is_matlab) const
90
91
92
93
{
  // For a terminal node, the cost is null
  return 0;
}
94

95
96
97
98
99
100
101
102
103
bool
ExprNode::checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
                                        const temporary_terms_t &temporary_terms,
                                        const temporary_terms_idxs_t &temporary_terms_idxs) const
{
  auto it = temporary_terms.find(const_cast<ExprNode *>(this));
  if (it == temporary_terms.end())
    return false;

104
  if (output_type == ExprNodeOutputType::matlabDynamicModelSparse)
105
106
    output << "T" << idx << "(it_)";
  else
107
    if (output_type == ExprNodeOutputType::matlabStaticModelSparse)
108
109
110
111
112
113
114
      output << "T" << idx;
    else
      {
        auto it2 = temporary_terms_idxs.find(const_cast<ExprNode *>(this));
        // It is the responsibility of the caller to ensure that all temporary terms have their index
        assert(it2 != temporary_terms_idxs.end());
        output << "T" << LEFT_ARRAY_SUBSCRIPT(output_type)
115
               << it2->second + ARRAY_SUBSCRIPT_OFFSET(output_type)
116
117
118
119
120
               << RIGHT_ARRAY_SUBSCRIPT(output_type);
      }
  return true;
}

121
122
123
void
ExprNode::collectVariables(SymbolType type, set<int> &result) const
{
124
  set<pair<int, int>> symbs_lags;
125
126
  collectDynamicVariables(type, symbs_lags);
  transform(symbs_lags.begin(), symbs_lags.end(), inserter(result, result.begin()),
127
            [](auto x) { return x.first; });
128
129
}

sebastien's avatar
sebastien committed
130
void
131
ExprNode::collectEndogenous(set<pair<int, int>> &result) const
sebastien's avatar
sebastien committed
132
{
133
  set<pair<int, int>> symb_ids;
134
  collectDynamicVariables(SymbolType::endogenous, symb_ids);
135
  for (const auto & symb_id : symb_ids)
136
    result.emplace(datatree.symbol_table.getTypeSpecificID(symb_id.first), symb_id.second);
sebastien's avatar
sebastien committed
137
138
139
}

void
140
ExprNode::collectExogenous(set<pair<int, int>> &result) const
sebastien's avatar
sebastien committed
141
{
142
  set<pair<int, int>> symb_ids;
143
  collectDynamicVariables(SymbolType::exogenous, symb_ids);
144
  for (const auto & symb_id : symb_ids)
145
    result.emplace(datatree.symbol_table.getTypeSpecificID(symb_id.first), symb_id.second);
sebastien's avatar
sebastien committed
146
147
}

148
void
149
150
151
152
ExprNode::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
153
154
155
{
  // Nothing to do for a terminal node
}
156
157

void
158
ExprNode::computeTemporaryTerms(map<expr_t, int> &reference_count,
159
                                temporary_terms_t &temporary_terms,
160
                                map<expr_t, pair<int, int>> &first_occurence,
161
                                int Curr_block,
162
                                vector<vector<temporary_terms_t>> &v_temporary_terms,
163
                                int equation) const
164
165
166
{
  // Nothing to do for a terminal node
}
167

168
169
pair<int, expr_t>
ExprNode::normalizeEquation(int var_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const
170
{
171
  /* nothing to do */
172
  return { 0, nullptr };
173
}
174

175
void
176
ExprNode::writeOutput(ostream &output) const
177
{
178
  writeOutput(output, ExprNodeOutputType::matlabOutsideModel, {}, {});
179
180
}

181
182
183
void
ExprNode::writeOutput(ostream &output, ExprNodeOutputType output_type) const
{
184
  writeOutput(output, output_type, {}, {});
185
186
}

187
void
Houtan Bastani's avatar
Houtan Bastani committed
188
ExprNode::writeOutput(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, const temporary_terms_idxs_t &temporary_terms_idxs) const
189
{
190
  writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, {});
191
192
}

193
194
void
ExprNode::compile(ostream &CompileCode, unsigned int &instruction_number,
195
196
                  bool lhs_rhs, const temporary_terms_t &temporary_terms,
                  const map_idx_t &map_idx, bool dynamic, bool steady_dynamic) const
197
{
198
  compile(CompileCode, instruction_number, lhs_rhs, temporary_terms, map_idx, dynamic, steady_dynamic, {});
199
200
}

201
202
void
ExprNode::writeExternalFunctionOutput(ostream &output, ExprNodeOutputType output_type,
203
                                      const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
204
                                      const temporary_terms_idxs_t &temporary_terms_idxs,
205
                                      deriv_node_temp_terms_t &tef_terms) const
206
207
208
209
{
  // Nothing to do
}

210
211
212
void
ExprNode::writeJsonExternalFunctionOutput(vector<string> &efout,
                                          const temporary_terms_t &temporary_terms,
213
214
                                          deriv_node_temp_terms_t &tef_terms,
                                          const bool isdynamic) const
215
216
217
218
{
  // Nothing to do
}

219
220
void
ExprNode::compileExternalFunctionOutput(ostream &CompileCode, unsigned int &instruction_number,
221
222
223
                                        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
224
225
226
227
{
  // Nothing to do
}

sebastien's avatar
sebastien committed
228
VariableNode *
229
ExprNode::createEndoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
sebastien's avatar
sebastien committed
230
231
232
233
234
235
236
237
{
  int n = maxEndoLead();
  assert(n >= 2);

  subst_table_t::const_iterator it = subst_table.find(this);
  if (it != subst_table.end())
    return const_cast<VariableNode *>(it->second);

238
  expr_t substexpr = decreaseLeadsLags(n-1);
sebastien's avatar
sebastien committed
239
240
241
242
  int lag = n-2;

  // Each iteration tries to create an auxvar such that auxvar(+1)=expr(-lag)
  // At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to expr(-lag-1) (resp. expr(-lag))
243
  while (lag >= 0)
sebastien's avatar
sebastien committed
244
    {
245
      expr_t orig_expr = decreaseLeadsLags(lag);
sebastien's avatar
sebastien committed
246
247
248
      it = subst_table.find(orig_expr);
      if (it == subst_table.end())
        {
249
          int symb_id = datatree.symbol_table.addEndoLeadAuxiliaryVar(orig_expr->idx, substexpr);
sebastien's avatar
sebastien committed
250
251
          neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr)));
          substexpr = datatree.AddVariable(symb_id, +1);
252
          assert(dynamic_cast<VariableNode *>(substexpr) != nullptr);
sebastien's avatar
sebastien committed
253
254
255
256
257
258
259
260
261
262
263
          subst_table[orig_expr] = dynamic_cast<VariableNode *>(substexpr);
        }
      else
        substexpr = const_cast<VariableNode *>(it->second);

      lag--;
    }

  return dynamic_cast<VariableNode *>(substexpr);
}

sebastien's avatar
sebastien committed
264
265
266
267
268
269
270
271
272
273
VariableNode *
ExprNode::createExoLeadAuxiliaryVarForMyself(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
  int n = maxExoLead();
  assert(n >= 1);

  subst_table_t::const_iterator it = subst_table.find(this);
  if (it != subst_table.end())
    return const_cast<VariableNode *>(it->second);

274
  expr_t substexpr = decreaseLeadsLags(n);
sebastien's avatar
sebastien committed
275
276
277
278
  int lag = n-1;

  // Each iteration tries to create an auxvar such that auxvar(+1)=expr(-lag)
  // At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to expr(-lag-1) (resp. expr(-lag))
279
  while (lag >= 0)
sebastien's avatar
sebastien committed
280
    {
281
      expr_t orig_expr = decreaseLeadsLags(lag);
sebastien's avatar
sebastien committed
282
283
284
      it = subst_table.find(orig_expr);
      if (it == subst_table.end())
        {
285
          int symb_id = datatree.symbol_table.addExoLeadAuxiliaryVar(orig_expr->idx, substexpr);
sebastien's avatar
sebastien committed
286
287
          neweqs.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(datatree.AddVariable(symb_id, 0), substexpr)));
          substexpr = datatree.AddVariable(symb_id, +1);
288
          assert(dynamic_cast<VariableNode *>(substexpr) != nullptr);
sebastien's avatar
sebastien committed
289
290
291
292
293
294
295
296
297
298
299
          subst_table[orig_expr] = dynamic_cast<VariableNode *>(substexpr);
        }
      else
        substexpr = const_cast<VariableNode *>(it->second);

      lag--;
    }

  return dynamic_cast<VariableNode *>(substexpr);
}

300
301
302
303
304
305
306
307
308
309
310
311
bool
ExprNode::isNumConstNodeEqualTo(double value) const
{
  return false;
}

bool
ExprNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
{
  return false;
}

312
313
314
315
316
void
ExprNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const
{
}

317
NumConstNode::NumConstNode(DataTree &datatree_arg, int idx_arg, int id_arg) :
318
319
  ExprNode{datatree_arg, idx_arg},
  id{id_arg}
320
{
sebastien's avatar
sebastien committed
321
}
322

323
324
int
NumConstNode::countDiffs() const
325
{
326
  return 0;
327
328
}

sebastien's avatar
sebastien committed
329
330
331
332
void
NumConstNode::prepareForDerivation()
{
  preparedForDerivation = true;
333
334
335
  // All derivatives are null, so non_null_derivatives is left empty
}

336
expr_t
337
NumConstNode::computeDerivative(int deriv_id)
338
339
340
341
{
  return datatree.Zero;
}

342
void
343
NumConstNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const
344
{
345
  auto it = temporary_terms.find(const_cast<NumConstNode *>(this));
346
347
348
  if (it != temporary_terms.end())
    temporary_terms_inuse.insert(idx);
}
349

350
351
void
NumConstNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
352
                          const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
353
                          const temporary_terms_idxs_t &temporary_terms_idxs,
354
                          const deriv_node_temp_terms_t &tef_terms) const
355
{
356
  if (!checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
357
358
    output << datatree.num_constants.get(id);
}
359

Houtan Bastani's avatar
Houtan Bastani committed
360
361
362
void
NumConstNode::writeJsonAST(ostream &output) const
{
363
364
365
366
367
  output << "{\"node_type\" : \"NumConstNode\", \"value\" : ";
  double testval = datatree.num_constants.getDouble(id);
  if (testval < 1.0 && testval > -1.0 && testval != 0.0)
    output << "0";
  output << datatree.num_constants.get(id) << "}";
Houtan Bastani's avatar
Houtan Bastani committed
368
369
}

370
void
371
NumConstNode::writeJsonOutput(ostream &output,
372
                              const temporary_terms_t &temporary_terms,
373
                              const deriv_node_temp_terms_t &tef_terms,
374
                              const bool isdynamic) const
375
376
377
378
{
  output << datatree.num_constants.get(id);
}

379
380
381
382
383
384
bool
NumConstNode::containsExternalFunction() const
{
  return false;
}

385
double
386
NumConstNode::eval(const eval_context_t &eval_context) const noexcept(false)
387
{
388
  return (datatree.num_constants.getDouble(id));
389
390
391
}

void
392
393
394
NumConstNode::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,
395
                      const deriv_node_temp_terms_t &tef_terms) const
396
397
{
  FLDC_ fldc(datatree.num_constants.getDouble(id));
398
  fldc.write(CompileCode, instruction_number);
399
}
400

401
402
403
void
NumConstNode::collectVARLHSVariable(set<expr_t> &result) const
{
404
405
  cerr << "ERROR: you can only have variables or unary ops on LHS of VAR" << endl;
  exit(EXIT_FAILURE);
406
407
}

408
void
409
NumConstNode::collectDynamicVariables(SymbolType type_arg, set<pair<int, int>> &result) const
410
411
412
{
}

413
414
pair<int, expr_t>
NumConstNode::normalizeEquation(int var_endo, vector<tuple<int, expr_t, expr_t>> &List_of_Op_RHS) const
415
{
416
  /* return the numercial constant */
417
  return { 0, datatree.AddNonNegativeConstant(datatree.num_constants.get(id)) };
418
}
ferhat's avatar
ferhat committed
419

420
421
expr_t
NumConstNode::getChainRuleDerivative(int deriv_id, const map<int, expr_t> &recursive_variables)
ferhat's avatar
ferhat committed
422
{
ferhat's avatar
ferhat committed
423
  return datatree.Zero;
ferhat's avatar
ferhat committed
424
425
}

426
expr_t
sebastien's avatar
sebastien committed
427
NumConstNode::toStatic(DataTree &static_datatree) const
428
{
429
  return static_datatree.AddNonNegativeConstant(datatree.num_constants.get(id));
430
}
sebastien's avatar
sebastien committed
431

432
433
434
435
436
void
NumConstNode::computeXrefs(EquationInfo &ei) const
{
}

437
expr_t
438
NumConstNode::clone(DataTree &datatree) const
439
{
440
  return datatree.AddNonNegativeConstant(datatree.num_constants.get(id));
441
442
}

sebastien's avatar
sebastien committed
443
444
445
446
447
int
NumConstNode::maxEndoLead() const
{
  return 0;
}
ferhat's avatar
ferhat committed
448

sebastien's avatar
sebastien committed
449
450
451
452
453
454
int
NumConstNode::maxExoLead() const
{
  return 0;
}

455
456
457
458
459
460
461
462
463
464
465
466
int
NumConstNode::maxEndoLag() const
{
  return 0;
}

int
NumConstNode::maxExoLag() const
{
  return 0;
}

467
468
469
470
471
472
int
NumConstNode::maxLead() const
{
  return 0;
}

473
474
475
476
477
478
int
NumConstNode::maxLag() const
{
  return 0;
}

479
480
481
482
483
484
int
NumConstNode::maxLagWithDiffsExpanded() const
{
  return 0;
}

Houtan Bastani's avatar
Houtan Bastani committed
485
486
487
488
489
490
expr_t
NumConstNode::undiff() const
{
  return const_cast<NumConstNode *>(this);
}

491
492
493
494
495
496
int
NumConstNode::VarMinLag() const
{
  return 1;
}

Houtan Bastani's avatar
Houtan Bastani committed
497
498
int
NumConstNode::VarMaxLag(DataTree &static_datatree, set<expr_t> &static_lhs) const
499
{
Houtan Bastani's avatar
Houtan Bastani committed
500
  return 0;
501
502
}

Houtan Bastani's avatar
Houtan Bastani committed
503
int
504
NumConstNode::PacMaxLag(int lhs_symb_id) const
Houtan Bastani's avatar
Houtan Bastani committed
505
506
507
508
{
  return 0;
}

509
510
511
512
513
514
int
NumConstNode::getPacTargetSymbId(int lhs_symb_id, int undiff_lhs_symb_id) const
{
  return -1;
}

515
expr_t
sebastien's avatar
sebastien committed
516
517
518
519
520
NumConstNode::decreaseLeadsLags(int n) const
{
  return const_cast<NumConstNode *>(this);
}

521
expr_t
sebastien's avatar
sebastien committed
522
NumConstNode::decreaseLeadsLagsPredeterminedVariables() const
523
{
sebastien's avatar
sebastien committed
524
  return const_cast<NumConstNode *>(this);
525
526
}

527
expr_t
528
NumConstNode::substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
sebastien's avatar
sebastien committed
529
530
531
532
{
  return const_cast<NumConstNode *>(this);
}

533
expr_t
534
535
536
537
538
NumConstNode::substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
  return const_cast<NumConstNode *>(this);
}

539
expr_t
540
NumConstNode::substituteExoLead(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const
sebastien's avatar
sebastien committed
541
542
543
544
{
  return const_cast<NumConstNode *>(this);
}

545
expr_t
sebastien's avatar
sebastien committed
546
NumConstNode::substituteExoLag(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
sebastien's avatar
sebastien committed
547
548
549
550
{
  return const_cast<NumConstNode *>(this);
}

551
expr_t
552
553
554
555
556
NumConstNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool partial_information_model) const
{
  return const_cast<NumConstNode *>(this);
}

557
expr_t
558
559
560
561
562
NumConstNode::substituteAdl() const
{
  return const_cast<NumConstNode *>(this);
}

563
564
565
566
567
568
expr_t
NumConstNode::substituteVarExpectation(const map<string, expr_t> &subst_table) const
{
  return const_cast<NumConstNode *>(this);
}

569
570
571
572
573
void
NumConstNode::findDiffNodes(DataTree &static_datatree, diff_table_t &diff_table) const
{
}

574
575
576
577
578
void
NumConstNode::findUnaryOpNodesForAuxVarCreation(DataTree &static_datatree, diff_table_t &nodes) const
{
}

579
int
580
NumConstNode::findTargetVariable(int lhs_symb_id) const
581
582
583
584
{
  return -1;
}

585
expr_t
Houtan Bastani's avatar
Houtan Bastani committed
586
NumConstNode::substituteDiff(DataTree &static_datatree, diff_table_t &diff_table, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
587
588
589
590
{
  return const_cast<NumConstNode *>(this);
}

591
592
593
594
595
596
expr_t
NumConstNode::substituteUnaryOpNodes(DataTree &static_datatree, diff_table_t &nodes, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
{
  return const_cast<NumConstNode *>(this);
}

597
expr_t
598
NumConstNode::substitutePacExpectation(const string & name, expr_t subexpr)
599
600
601
602
{
  return const_cast<NumConstNode *>(this);
}

603
expr_t
604
NumConstNode::differentiateForwardVars(const vector<string> &subset, subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const
605
606
607
608
{
  return const_cast<NumConstNode *>(this);
}

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
bool
NumConstNode::isNumConstNodeEqualTo(double value) const
{
  if (datatree.num_constants.getDouble(id) == value)
    return true;
  else
    return false;
}

bool
NumConstNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const
{
  return false;
}

624
625
626
627
628
void
NumConstNode::getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const
{
}

629
bool
630
NumConstNode::containsPacExpectation(const string &pac_model_name) const
631
632
633
634
{
  return false;
}

635
bool
636
NumConstNode::containsEndogenous() const
637
638
639
640
{
  return false;
}

641
642
643
644
645
646
bool
NumConstNode::containsExogenous() const
{
  return false;
}

647
648
649
650
651
652
653
expr_t
NumConstNode::replaceTrendVar() const
{
  return const_cast<NumConstNode *>(this);
}

expr_t
654
NumConstNode::detrend(int symb_id, bool log_trend, expr_t trend) const
655
656
657
658
659
660
661
662
663
664
{
  return const_cast<NumConstNode *>(this);
}

expr_t
NumConstNode::removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const
{
  return const_cast<NumConstNode *>(this);
}

665
666
667
668
669
670
bool
NumConstNode::isInStaticForm() const
{
  return true;
}

671
672
673
674
675
676
bool
NumConstNode::isParamTimesEndogExpr() const
{
  return false;
}

677
678
679
680
681
682
bool
NumConstNode::isVarModelReferenced(const string &model_info_name) const
{
  return false;
}

683
684
685
686
687
688
expr_t
NumConstNode::substituteStaticAuxiliaryVariable() const
{
  return const_cast<NumConstNode *>(this);
}

Houtan Bastani's avatar
Houtan Bastani committed
689
void
690
NumConstNode::fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const
Houtan Bastani's avatar
Houtan Bastani committed
691
692
693
{
}

694
void
695
NumConstNode::fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &A0, map<tuple<int, int, int>, expr_t> &A0star) const
696
697
698
{
}

699
void
700
NumConstNode::findConstantEquations(map<VariableNode *, NumConstNode *> &table) const
701
702
703
704
705
{
  return;
}

expr_t
706
NumConstNode::replaceVarsInEquation(map<VariableNode *, NumConstNode *> &table) const
707
708
709
710
{
  return const_cast<NumConstNode *>(this);
}

711
VariableNode::VariableNode(DataTree &datatree_arg, int idx_arg, int symb_id_arg, int lag_arg) :
712
713
714
  ExprNode{datatree_arg, idx_arg},
  symb_id{symb_id_arg},
  lag{lag_arg}
Houtan Bastani's avatar
Houtan Bastani committed
715
716
{
  // It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
717
718
  assert(get_type() != SymbolType::externalFunction
         && (lag == 0 || (get_type() != SymbolType::modelLocalVariable && get_type() != SymbolType::modFileLocalVariable)));
Houtan Bastani's avatar
Houtan Bastani committed
719
720
}

sebastien's avatar
sebastien committed
721
722
723
724
725
void
VariableNode::prepareForDerivation()
{
  if (preparedForDerivation)
    return;
726

sebastien's avatar
sebastien committed
727
  preparedForDerivation = true;
sebastien's avatar
sebastien committed
728

729
  // Fill in non_null_derivatives
730
  switch (get_type())
731
    {
732
733
734
735
736
737
    case SymbolType::endogenous:
    case SymbolType::exogenous:
    case SymbolType::exogenousDet:
    case SymbolType::parameter:
    case SymbolType::trend:
    case SymbolType::logTrend:
sebastien's avatar
sebastien committed
738
      // For a variable or a parameter, the only non-null derivative is with respect to itself
739
      non_null_derivatives.insert(datatree.getDerivID(symb_id, lag));
740
      break;
741
    case SymbolType::modelLocalVariable:
742
      datatree.getLocalVariable(symb_id)->prepareForDerivation();
743
      // Non null derivatives are those of the value of the local parameter
744
      non_null_derivatives = datatree.getLocalVariable(symb_id)->non_null_derivatives;
745
      break;
746
747
748
    case SymbolType::modFileLocalVariable:
    case SymbolType::statementDeclaredVariable:
    case SymbolType::unusedEndogenous:
749
750
      // Such a variable is never derived
      break;
751
752
    case SymbolType::externalFunction:
    case SymbolType::endogenousVAR:
753
    case SymbolType::epilogue:
sebastien's avatar
sebastien committed
754
      cerr << "VariableNode::prepareForDerivation: impossible case" << endl;
755
      exit(EXIT_FAILURE);
756
757
758
    }
}

759
expr_t
sebastien's avatar
sebastien committed
760
VariableNode::computeDerivative(int deriv_id)
761
{
762
  switch (get_type())
763
    {
764
765
766
767
768
769
    case SymbolType::endogenous:
    case SymbolType::exogenous:
    case SymbolType::exogenousDet:
    case SymbolType::parameter:
    case SymbolType::trend:
    case SymbolType::logTrend:
sebastien's avatar
sebastien committed
770
      if (deriv_id == datatree.getDerivID(symb_id, lag))
771
772
773
        return datatree.One;
      else
        return datatree.Zero;
774
    case SymbolType::modelLocalVariable:
775
      return datatree.getLocalVariable(symb_id)->getDerivative(deriv_id);
776
    case SymbolType::modFileLocalVariable:
777
      cerr << "ModFileLocalVariable is not derivable" << endl;
778
      exit(EXIT_FAILURE);
779
    case SymbolType::statementDeclaredVariable:
780
781
      cerr << "eStatementDeclaredVariable is not derivable" << endl;
      exit(EXIT_FAILURE);
782
    case SymbolType::unusedEndogenous:
783
784
      cerr << "eUnusedEndogenous is not derivable" << endl;
      exit(EXIT_FAILURE);
785
786
    case SymbolType::externalFunction:
    case SymbolType::endogenousVAR:
787
    case SymbolType::epilogue:
Houtan Bastani's avatar
Houtan Bastani committed
788
      cerr << "VariableNode::computeDerivative: Impossible case!" << endl;
789
      exit(EXIT_FAILURE);
790
    }
sebastien's avatar
sebastien committed
791
  // Suppress GCC warning
792
  exit(EXIT_FAILURE);
793
794
}

795
void
796
VariableNode::collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const
797
{
798
  auto it = temporary_terms.find(const_cast<VariableNode *>(this));
799
800
  if (it != temporary_terms.end())
    temporary_terms_inuse.insert(idx);
801
  if (get_type() == SymbolType::modelLocalVariable)
802
    datatree.getLocalVariable(symb_id)->collectTemporary_terms(temporary_terms, temporary_terms_inuse, Curr_Block);
803
}
804

805
806
807
808
809
810
bool
VariableNode::containsExternalFunction() const
{
  return false;
}

Houtan Bastani's avatar
Houtan Bastani committed
811
812
813
814
815
void
VariableNode::writeJsonAST(ostream &output) const
{
  output << "{\"node_type\" : \"VariableNode\", "
         << "\"name\" : \"" << datatree.symbol_table.getName(symb_id) << "\", \"type\" : \"";
816
  switch (get_type())
Houtan Bastani's avatar
Houtan Bastani committed
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
    {
    case SymbolType::endogenous:
      output << "endogenous";
      break;
    case SymbolType::exogenous:
      output << "exogenous";
      break;
    case SymbolType::exogenousDet:
      output << "exogenousDet";
      break;
    case SymbolType::parameter:
      output << "parameter";
      break;
    case SymbolType::modelLocalVariable:
      output << "modelLocalVariable";
      break;
    case SymbolType::modFileLocalVariable:
      output << "modFileLocalVariable";
      break;
    case SymbolType::externalFunction:
      output << "externalFunction";
      break;
    case SymbolType::trend:
      output << "trend";
      break;
    case SymbolType::statementDeclaredVariable:
      output << "statementDeclaredVariable";
      break;
    case SymbolType::logTrend:
      output << "logTrend:";
      break;
    case SymbolType::unusedEndogenous:
      output << "unusedEndogenous";
      break;
    case SymbolType::endogenousVAR:
      output << "endogenousVAR";
      break;
854
855
856
    case SymbolType::epilogue:
      output << "epilogue";
      break;
Houtan Bastani's avatar
Houtan Bastani committed
857
858
859
860
    }
  output << "\", \"lag\" : " << lag << "}";
}

861
void
862
VariableNode::writeJsonOutput(ostream &output,
863
                              const temporary_terms_t &temporary_terms,
864
                              const deriv_node_temp_terms_t &tef_terms,
865
                              const bool isdynamic) const
866
{
867
  auto it = temporary_terms.find(const_cast<VariableNode *>(this));
868
869
870
871
872
873
  if (it != temporary_terms.end())
    {
      output << "T" << idx;
      return;
    }

874
  output << datatree.symbol_table.getName(symb_id);
875
  if (isdynamic && lag != 0)
876
877
878
    output << "(" << lag << ")";
}

879
880
void
VariableNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
881
                          const temporary_terms_t &temporary_terms,
Houtan Bastani's avatar
Houtan Bastani committed
882
                          const temporary_terms_idxs_t &temporary_terms_idxs,
883
                          const deriv_node_temp_terms_t &tef_terms) const
884
{
885
  auto type = get_type();
886
887
  if (checkIfTemporaryTermThenWrite(output, output_type, temporary_terms, temporary_terms_idxs))
    return;
888

889
  if (isLatexOutput(output_type))
890
    {
891
      if (output_type == ExprNodeOutputType::latexDynamicSteadyStateOperator)
892
893
        output << "\\bar";
      output << "{" << datatree.symbol_table.getTeXName(symb_id);
894
      if (output_type == ExprNodeOutputType::latexDynamicModel
895
          && (type == SymbolType::endogenous || type == SymbolType::exogenous || type == SymbolType::exogenousDet || type == SymbolType::modelLocalVariable || type == SymbolType::trend || type == SymbolType::logTrend))
896
897
898
899
900
901
902
903
        {
          output << "_{t";
          if (lag != 0)
            {
              if (lag > 0)
                output << "+";
              output << lag;
            }
904
          output << "}";
905
        }
906
      output << "}";
907
908
      return;
    }
909

910
911
912
913
  int i;
  int tsid = datatree.symbol_table.getTypeSpecificID(symb_id);
  switch (type)
    {
914
    case SymbolType::parameter:
915
      if (output_type == ExprNodeOutputType::matlabOutsideModel)
916
917
918
919
        output << "M_.params" << "(" << tsid + 1 << ")";
      else
        output << "params" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + ARRAY_SUBSCRIPT_OFFSET(output_type) << RIGHT_ARRAY_SUBSCRIPT(output_type);
      break;
ferhat's avatar
ferhat committed
920

921
    case SymbolType::modelLocalVariable:
922
923
924
      if (output_type == ExprNodeOutputType::matlabDynamicModelSparse || output_type == ExprNodeOutputType::matlabStaticModelSparse
          || output_type == ExprNodeOutputType::matlabDynamicSteadyStateOperator || output_type == ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator
          || output_type == ExprNodeOutputType::CDynamicSteadyStateOperator)
925
926
        {
          output << "(";
927
          datatree.getLocalVariable(symb_id)->writeOutput(output, output_type, temporary_terms, temporary_terms_idxs, tef_terms);
928
929
930
          output << ")";
        }
      else
Sébastien Villemot's avatar
Sébastien Villemot committed
931
932
        /* We append underscores to avoid name clashes with "g1" or "oo_".
           But we probably never arrive here because MLV are temporary terms… */
933
        output << datatree.symbol_table.getName(symb_id) << "__";
934
      break;
ferhat's avatar
ferhat committed
935

936
    case SymbolType::modFileLocalVariable:
937
938
939
      output << datatree.symbol_table.getName(symb_id);
      break;

940
    case SymbolType::endogenous:
941
942
      switch (output_type)
        {
943
944
945
        case ExprNodeOutputType::juliaDynamicModel:
        case ExprNodeOutputType::matlabDynamicModel:
        case ExprNodeOutputType::CDynamicModel:
946
947
948
          i = datatree.getDynJacobianCol(datatree.getDerivID(symb_id, lag)) + ARRAY_SUBSCRIPT_OFFSET(output_type);
          output <<  "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
949
950
951
952
        case ExprNodeOutputType::CStaticModel:
        case ExprNodeOutputType::juliaStaticModel:
        case ExprNodeOutputType::matlabStaticModel:
        case ExprNodeOutputType::matlabStaticModelSparse:
953
954
955
          i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
          output <<  "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
956
        case ExprNodeOutputType::matlabDynamicModelSparse:
957
958
959
960
961
962
963
964
          i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
          if (lag > 0)
            output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          else if (lag < 0)
            output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_" << lag << ", " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          else
            output << "y" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_, " << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
965
        case ExprNodeOutputType::matlabOutsideModel:
966
967
          output << "oo_.steady_state(" << tsid + 1 << ")";
          break;
968
969
970
        case ExprNodeOutputType::juliaDynamicSteadyStateOperator:
        case ExprNodeOutputType::matlabDynamicSteadyStateOperator:
        case ExprNodeOutputType::matlabDynamicSparseSteadyStateOperator:
Houtan Bastani's avatar
Houtan Bastani committed
971
          output << "steady_state" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + 1 << RIGHT_ARRAY_SUBSCRIPT(output_type);
972
          break;
973
        case ExprNodeOutputType::CDynamicSteadyStateOperator:
974
975
          output << "steady_state[" << tsid << "]";
          break;
976
977
        case ExprNodeOutputType::juliaSteadyStateFile:
        case ExprNodeOutputType::steadyStateFile:
Houtan Bastani's avatar
Houtan Bastani committed
978
          output << "ys_" << LEFT_ARRAY_SUBSCRIPT(output_type) << tsid + 1 << RIGHT_ARRAY_SUBSCRIPT(output_type);
979
          break;
980
        case ExprNodeOutputType::matlabDseries:
981
982
983
984
          output << "ds." << datatree.symbol_table.getName(symb_id);
          if (lag != 0)
            output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
985
        case ExprNodeOutputType::epilogueFile:
Houtan Bastani's avatar
Houtan Bastani committed
986
          output << "dseries__." << datatree.symbol_table.getName(symb_id);
987
988
989
990
          output << LEFT_ARRAY_SUBSCRIPT(output_type) << "t";
          if (lag != 0)
            output << lag;
          output << RIGHT_ARRAY_SUBSCRIPT(output_type);
Houtan Bastani's avatar
Houtan Bastani committed
991
          break;
992
        default:
993
994
          cerr << "VariableNode::writeOutput: should not reach this point" << endl;
          exit(EXIT_FAILURE);
995
996
        }
      break;
ferhat's avatar
ferhat committed
997

998
    case SymbolType::exogenous:
999
1000
1001
      i = tsid + ARRAY_SUBSCRIPT_OFFSET(output_type);
      switch (output_type)
        {
1002
1003
1004
        case ExprNodeOutputType::juliaDynamicModel:
        case ExprNodeOutputType::matlabDynamicModel:
        case ExprNodeOutputType::matlabDynamicModelSparse:
1005
          if (lag > 0)
Houtan Bastani's avatar
Houtan Bastani committed
1006
1007
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1008
          else if (lag < 0)
Houtan Bastani's avatar
Houtan Bastani committed
1009
1010
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_" << lag << ", " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1011
          else
Houtan Bastani's avatar
Houtan Bastani committed
1012
1013
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_, " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1014
          break;
1015
        case ExprNodeOutputType::CDynamicModel:
1016
1017
1018
1019
1020
1021
1022
          if (lag == 0)
            output <<  "x[it_+" << i << "*nb_row_x]";
          else if (lag > 0)
            output <<  "x[it_+" << lag << "+" << i << "*nb_row_x]";
          else
            output <<  "x[it_" << lag << "+" << i << "*nb_row_x]";
          break;
1023
1024
1025
1026
        case ExprNodeOutputType::CStaticModel:
        case ExprNodeOutputType::juliaStaticModel:
        case ExprNodeOutputType::matlabStaticModel:
        case ExprNodeOutputType::matlabStaticModelSparse:
1027
1028
          output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
1029
        case ExprNodeOutputType::matlabOutsideModel:
1030
          assert(lag == 0);
1031
          output <<  "oo_.exo_steady_state(" << i << ")";
1032
          break;
1033
        case ExprNodeOutputType::matlabDynamicSteadyStateOperator:
1034
          output <<  "oo_.exo_steady_state(" << i << ")";
1035
          break;
1036
1037
        case ExprNodeOutputType::juliaSteadyStateFile:
        case ExprNodeOutputType::steadyStateFile:
Houtan Bastani's avatar
Houtan Bastani committed
1038
          output << "exo_" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
1039
          break;
1040
        case ExprNodeOutputType::matlabDseries:
1041
1042
1043
1044
          output << "ds." << datatree.symbol_table.getName(symb_id);
          if (lag != 0)
            output << LEFT_ARRAY_SUBSCRIPT(output_type) << lag << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
1045
        case ExprNodeOutputType::epilogueFile:
Houtan Bastani's avatar
Houtan Bastani committed
1046
          output << "dseries__." << datatree.symbol_table.getName(symb_id);
1047
          output << LEFT_ARRAY_SUBSCRIPT(output_type) << "t";
Houtan Bastani's avatar
Houtan Bastani committed
1048
          if (lag != 0)
1049
1050
            output << lag;
          output << RIGHT_ARRAY_SUBSCRIPT(output_type);
Houtan Bastani's avatar
Houtan Bastani committed
1051
          break;
1052
        default:
1053
1054
          cerr << "VariableNode::writeOutput: should not reach this point" << endl;
          exit(EXIT_FAILURE);
1055
1056
        }
      break;
ferhat's avatar
ferhat committed
1057

1058
    case SymbolType::exogenousDet:
1059
1060
1061
      i = tsid + datatree.symbol_table.exo_nbr() + ARRAY_SUBSCRIPT_OFFSET(output_type);
      switch (output_type)
        {
1062
1063
1064
        case ExprNodeOutputType::juliaDynamicModel:
        case ExprNodeOutputType::matlabDynamicModel:
        case ExprNodeOutputType::matlabDynamicModelSparse:
1065
          if (lag > 0)
Houtan Bastani's avatar
Houtan Bastani committed
1066
1067
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_+" << lag << ", " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1068
          else if (lag < 0)
Houtan Bastani's avatar
Houtan Bastani committed
1069
1070
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_" << lag << ", " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1071
          else
Houtan Bastani's avatar
Houtan Bastani committed
1072
1073
            output <<  "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << "it_, " << i
                   << RIGHT_ARRAY_SUBSCRIPT(output_type);
1074
          break;
1075
        case ExprNodeOutputType::CDynamicModel:
1076
          if (lag == 0)
1077
            output <<  "x[it_+" << i << "*nb_row_x]";
1078
          else if (lag > 0)
1079
            output <<  "x[it_+" << lag << "+" << i << "*nb_row_x]";
1080
          else
1081
            output <<  "x[it_" << lag << "+" << i << "*nb_row_x]";
1082
          break;
1083
1084
1085
1086
        case ExprNodeOutputType::CStaticModel:
        case ExprNodeOutputType::juliaStaticModel:
        case ExprNodeOutputType::matlabStaticModel:
        case ExprNodeOutputType::matlabStaticModelSparse:
1087
1088
          output << "x" << LEFT_ARRAY_SUBSCRIPT(output_type) << i << RIGHT_ARRAY_SUBSCRIPT(output_type);
          break;
1089
        case ExprNodeOutputType::matlabOutsideModel:
1090
1091
1092
          assert(lag == 0);
          output <<  "oo_.exo_det_steady_state(" << tsid + 1 << ")";
          break;
1093
        case ExprNodeOutputType::matl