SymbolTable.hh 18.4 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-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
26
 *
 * 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 _SYMBOLTABLE_HH
#define _SYMBOLTABLE_HH

using namespace std;

#include <map>
#include <string>
27
#include <utility>
28
#include <vector>
sebastien's avatar
sebastien committed
29
#include <set>
30
#include <ostream>
sebastien's avatar
sebastien committed
31

32
#include "CodeInterpreter.hh"
33
34
#include "ExprNode.hh"

35
using expr_t = class ExprNode *;
36

sebastien's avatar
sebastien committed
37
//! Types of auxiliary variables
38
enum class AuxVarType
sebastien's avatar
sebastien committed
39
  {
40
41
42
43
44
45
46
47
48
49
    endoLead = 0,    //!< Substitute for endo leads >= 2
    endoLag = 1,     //!< Substitute for endo lags >= 2
    exoLead = 2,     //!< Substitute for exo leads >= 1
    exoLag = 3,      //!< Substitute for exo lags >= 1
    expectation = 4, //!< Substitute for Expectation Operator
    diffForward = 5, //!< Substitute for the differentiate of a forward variable
    multiplier = 6,  //!< Multipliers for FOC of Ramsey Problem
    varModel = 7,    //!< Variable for var_model with order > abs(min_lag()) present in model
    diff = 8,        //!< Variable for Diff operator
    diffLag = 9,     //!< Variable for timing between Diff operators
50
51
    unaryOp = 10,    //!< Variable for allowing the undiff operator to work when diff was taken of unary op, eg diff(log(x))
    diffLead = 11    //!< Variable for timing between Diff operators
sebastien's avatar
sebastien committed
52
53
54
  };

//! Information on some auxiliary variables
55
class AuxVarInfo
sebastien's avatar
sebastien committed
56
{
57
private:
sebastien's avatar
sebastien committed
58
  int symb_id; //!< Symbol ID of the auxiliary variable
59
  AuxVarType type; //!< Its type
Sébastien Villemot's avatar
Sébastien Villemot committed
60
61
  int orig_symb_id; //!< Symbol ID of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
  int orig_lead_lag; //!< Lead/lag of the endo of the original model represented by this aux var. Only used for avEndoLag and avExoLag.
62
  int equation_number_for_multiplier; //!< Stores the original constraint equation number associated with this aux var. Only used for avMultiplier.
63
  int information_set; //! Argument of expectation operator. Only used for avExpectation.
64
  expr_t expr_node; //! Auxiliary variable definition
65
  string unary_op; //! Used with AuxUnaryOp
66
public:
67
  AuxVarInfo(int symb_id_arg, AuxVarType type_arg, int orig_symb_id, int orig_lead_lag, int equation_number_for_multiplier_arg, int information_set_arg, expr_t expr_node_arg, string unary_op_arg);
68
69
70
71
72
  int
  get_symb_id() const
  {
    return symb_id;
  };
73
  AuxVarType
74
75
76
77
78
  get_type() const
  {
    return type;
  };
  int
79
80
81
82
83
  get_type_id() const
  {
    return static_cast<int>(type);
  }
  int
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
  get_orig_symb_id() const
  {
    return orig_symb_id;
  };
  int
  get_orig_lead_lag() const
  {
    return orig_lead_lag;
  };
  int
  get_equation_number_for_multiplier() const
  {
    return equation_number_for_multiplier;
  };
  int
  get_information_set() const
  {
    return information_set;
  };
  expr_t
  get_expr_node() const
  {
    return expr_node;
  };
108
109
110
111
112
  string
  get_unary_op() const
  {
    return unary_op;
  };
sebastien's avatar
sebastien committed
113
114
};

115
116
//! Stores the symbol table
/*!
sebastien's avatar
sebastien committed
117
  A symbol is given by its name, and is internally represented by a unique integer.
118

sebastien's avatar
sebastien committed
119
120
121
  When method freeze() is called, computes a distinct sequence of IDs for some types
  (endogenous, exogenous, parameters), which are used by the Matlab/Octave functions.
  We call these "type specific IDs".
122

123
  Also manages a TeX name for each symbol, which by default is an empty string.
124
125
126
127
*/
class SymbolTable
{
private:
sebastien's avatar
sebastien committed
128
  //! Has method freeze() been called?
129
  bool frozen{false};
sebastien's avatar
sebastien committed
130

131
  using symbol_table_type = map<string, int>;
sebastien's avatar
sebastien committed
132
  //! Maps strings to symbol IDs
133
134
  symbol_table_type symbol_table;

sebastien's avatar
sebastien committed
135
136
137
138
  //! Maps IDs to names
  vector<string> name_table;
  //! Maps IDs to TeX names
  vector<string> tex_name_table;
139
140
  //! Maps IDs to string names of variables
  vector<string> long_name_table;
141
  //! Maps IDs to a pair containing the partition and the partition value
142
  map<int, map<string, string>> partition_value_map;
sebastien's avatar
sebastien committed
143
144
145
146
147
148
149
150
151
152
153
154
155
156
  //! Maps IDs to types
  vector<SymbolType> type_table;

  //! Maps symbol IDs to type specific IDs
  vector<int> type_specific_ids;

  //! Maps type specific IDs of endogenous to symbol IDs
  vector<int> endo_ids;
  //! Maps type specific IDs of exogenous to symbol IDs
  vector<int> exo_ids;
  //! Maps type specific IDs of exogenous deterministic to symbol IDs
  vector<int> exo_det_ids;
  //! Maps type specific IDs of parameters to symbol IDs
  vector<int> param_ids;
sebastien's avatar
sebastien committed
157
158
  //! Information about auxiliary variables
  vector<AuxVarInfo> aux_vars;
159

sebastien's avatar
sebastien committed
160
161
162
  //! Stores the predetermined variables (by symbol IDs)
  set<int> predetermined_variables;

Sébastien Villemot's avatar
Sébastien Villemot committed
163
164
165
  //! Stores the list of observed variables
  vector<int> varobs;

166
167
168
  //! Stores the list of observed exogenous variables
  vector<int> varexobs;

169
170
171
172
173
174
175
176
public:
  SymbolTable();
  //! Thrown when trying to access an unknown symbol (by name)
  class UnknownSymbolNameException
  {
  public:
    //! Symbol name
    string name;
177
    explicit UnknownSymbolNameException(string name_arg) : name{move(name_arg)}
178
179
    {
    }
180
  };
sebastien's avatar
sebastien committed
181
  //! Thrown when trying to access an unknown symbol (by id)
182
183
184
185
186
  class UnknownSymbolIDException
  {
  public:
    //! Symbol ID
    int id;
187
    explicit UnknownSymbolIDException(int id_arg) : id{id_arg}
188
189
    {
    }
sebastien's avatar
sebastien committed
190
191
192
193
194
195
196
  };
  //! Thrown when trying to access an unknown type specific ID
  class UnknownTypeSpecificIDException
  {
  public:
    int tsid;
    SymbolType type;
197
    UnknownTypeSpecificIDException(int tsid_arg, SymbolType type_arg) : tsid{tsid_arg}, type{type_arg}
198
199
    {
    }
200
201
202
203
204
205
206
207
208
  };
  //! Thrown when trying to declare a symbol twice
  class AlreadyDeclaredException
  {
  public:
    //! Symbol name
    string name;
    //! Was the previous declaration done with the same symbol type ?
    bool same_type;
209
    AlreadyDeclaredException(string name_arg, bool same_type_arg) : name{move(name_arg)}, same_type{same_type_arg}
210
211
    {
    }
212
  };
sebastien's avatar
sebastien committed
213
214
215
216
217
218
219
220
  //! Thrown when table is frozen and trying to modify it
  class FrozenException
  {
  };
  //! Thrown when trying to use the result of freeze() while this method has not yet been called
  class NotYetFrozenException
  {
  };
Sébastien Villemot's avatar
Sébastien Villemot committed
221
222
223
224
  //! Thrown when searchAuxiliaryVars() failed
  class SearchFailedException
  {
  public:
225
    int orig_symb_id, orig_lead_lag, symb_id;
226
227
    SearchFailedException(int orig_symb_id_arg, int orig_lead_lag_arg) : orig_symb_id{orig_symb_id_arg},
                                                                         orig_lead_lag{orig_lead_lag_arg}
Sébastien Villemot's avatar
Sébastien Villemot committed
228
229
    {
    }
230
    explicit SearchFailedException(int symb_id_arg) : symb_id{symb_id_arg}
231
232
    {
    }
Sébastien Villemot's avatar
Sébastien Villemot committed
233
  };
234
235

private:
sebastien's avatar
sebastien committed
236
  //! Factorized code for adding aux lag variables
237
  int addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
sebastien's avatar
sebastien committed
238
  //! Factorized code for adding aux lead variables
239
  int addLeadAuxiliaryVarInternal(bool endo, int index, expr_t arg) noexcept(false);
240
241
  //! Factorized code for Json writing
  void writeJsonVarVector(ostream &output, const vector<int> &varvec) const;
242
  //! Factorized code for asserting that 0 <= symb_id <= symbol_table.size()
243
  inline void validateSymbID(int symb_id) const noexcept(false);
244
public:
245
  //! Add a symbol
sebastien's avatar
sebastien committed
246
  /*! Returns the symbol ID */
247
  int addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value) noexcept(false);
248
  //! Add a symbol without its TeX name (will be equal to its name)
sebastien's avatar
sebastien committed
249
  /*! Returns the symbol ID */
250
  int addSymbol(const string &name, SymbolType type) noexcept(false);
251
252
253
254
  //! Adds an auxiliary variable for endogenous with lead >= 2
  /*!
    \param[in] index Used to construct the variable name
    \return the symbol ID of the new symbol */
255
  int addEndoLeadAuxiliaryVar(int index, expr_t arg) noexcept(false);
256
257
258
  //! Adds an auxiliary variable for endogenous with lag >= 2
  /*!
    \param[in] orig_symb_id symbol ID of the endogenous declared by the user that this new variable will represent
sebastien's avatar
sebastien committed
259
    \param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
260
    \return the symbol ID of the new symbol */
261
  int addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
262
263
  //! Adds an auxiliary variable for endogenous with lead >= 1
  /*!
sebastien's avatar
sebastien committed
264
    \param[in] index Used to construct the variable name
265
    \return the symbol ID of the new symbol */
266
  int addExoLeadAuxiliaryVar(int index, expr_t arg) noexcept(false);
267
268
269
  //! Adds an auxiliary variable for exogenous with lag >= 1
  /*!
    \param[in] orig_symb_id symbol ID of the exogenous declared by the user that this new variable will represent
sebastien's avatar
sebastien committed
270
    \param[in] orig_lead_lag lag value such that this new variable will be equivalent to orig_symb_id(orig_lead_lag)
271
    \return the symbol ID of the new symbol */
272
  int addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t arg) noexcept(false);
sebastien's avatar
sebastien committed
273
  //! Adds an auxiliary variable for the expectation operator
274
  /*!
sebastien's avatar
sebastien committed
275
276
277
278
    \param[in] information_set information set (possibly negative) of the expectation operator
    \param[in] index Used to construct the variable name
    \return the symbol ID of the new symbol
  */
279
  int addExpectationAuxiliaryVar(int information_set, int index, expr_t arg) noexcept(false);
280
281
282
283
284
  //! Adds an auxiliary variable for the multiplier for the FOCs of the Ramsey Problem
  /*!
    \param[in] index Used to construct the variable name
    \return the symbol ID of the new symbol
  */
285
  int addMultiplierAuxiliaryVar(int index) noexcept(false);
286
287
288
289
290
  //! Adds an auxiliary variable for the (time) differentiate of a forward var
  /*!
    \param[in] orig_symb_id The symb_id of the forward variable
    \return the symbol ID of the new symbol
  */
291
  int addDiffForwardAuxiliaryVar(int orig_symb_id, expr_t arg) noexcept(false);
Sébastien Villemot's avatar
Sébastien Villemot committed
292
  //! Searches auxiliary variables which are substitutes for a given symbol_id and lead/lag
293
  /*!
Sébastien Villemot's avatar
Sébastien Villemot committed
294
295
296
    The search is only performed among auxiliary variables of endo/exo lag.
    \return the symbol ID of the auxiliary variable
    Throws an exception if match not found.
297
  */
298
  int searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const noexcept(false);
299
  //! Serches aux_vars for the aux var represented by aux_var_symb_id and returns its associated orig_symb_id
300
  int getOrigSymbIdForAuxVar(int aux_var_symb_id) const noexcept(false);
301
302
303
304
  //! Searches for diff aux var and finds the original lag associated with this variable
  int getOrigLeadLagForDiffAuxVar(int diff_aux_var_symb_id) const noexcept(false);
  //! Searches for diff aux var and finds the symb id associated with this variable
  int getOrigSymbIdForDiffAuxVar(int diff_aux_var_symb_id) const noexcept(false);
305
306
  //! Adds an auxiliary variable when var_model is used with an order that is greater in absolute value
  //! than the largest lag present in the model.
307
  int addVarModelEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false);
308
  //! Adds an auxiliary variable when the diff operator is encountered
309
310
  int addDiffAuxiliaryVar(int index, expr_t expr_arg) noexcept(false);
  int addDiffAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false);
311
  //! Takes care of timing between diff statements
312
  int addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false);
313
314
  //! Takes care of timing between diff statements
  int addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lead) noexcept(false);
315
  //! An Auxiliary variable for a unary op
316
  int addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, int orig_symb_id = -1, int orig_lag = 0) noexcept(false);
317
  //! Returns the number of auxiliary variables
318
319
320
321
322
  int
  AuxVarsSize() const
  {
    return aux_vars.size();
  };
323
  //! Retruns expr_node for an auxiliary variable
324
  expr_t getAuxiliaryVarsExprNode(int symb_id) const noexcept(false);
325
326
  //! Tests if symbol already exists
  inline bool exists(const string &name) const;
sebastien's avatar
sebastien committed
327
  //! Get symbol name (by ID)
328
  inline string getName(int id) const noexcept(false);
sebastien's avatar
sebastien committed
329
  //! Get TeX name
330
  inline string getTeXName(int id) const noexcept(false);
331
  //! Get long name
332
  inline string getLongName(int id) const noexcept(false);
333
  //! Returns true if the partition name is the first encountered for the type of variable represented by id
334
  bool isFirstOfPartitionForType(int id) const noexcept(false);
335
  //! Returns a list of partitions and symbols that belong to that partition
336
  map<string, map<int, string>> getPartitionsForType(SymbolType st) const noexcept(false);
sebastien's avatar
sebastien committed
337
  //! Get type (by ID)
338
  inline SymbolType getType(int id) const noexcept(false);
sebastien's avatar
sebastien committed
339
  //! Get type (by name)
340
  inline SymbolType getType(const string &name) const noexcept(false);
sebastien's avatar
sebastien committed
341
  //! Get ID (by name)
342
  inline int getID(const string &name) const noexcept(false);
sebastien's avatar
sebastien committed
343
  //! Get ID (by type specific ID)
344
  int getID(SymbolType type, int tsid) const noexcept(false);
sebastien's avatar
sebastien committed
345
  //! Freeze symbol table
346
  void freeze() noexcept(false);
347
348
349
  //! unreeze symbol table
  //! Used after having written JSON files
  void unfreeze();
sebastien's avatar
sebastien committed
350
  //! Change the type of a symbol
351
  void changeType(int id, SymbolType newtype) noexcept(false);
sebastien's avatar
sebastien committed
352
  //! Get type specific ID (by symbol ID)
353
  inline int getTypeSpecificID(int id) const noexcept(false);
sebastien's avatar
sebastien committed
354
  //! Get type specific ID (by symbol name)
355
  inline int getTypeSpecificID(const string &name) const noexcept(false);
sebastien's avatar
sebastien committed
356
  //! Get number of endogenous variables
357
  inline int endo_nbr() const noexcept(false);
sebastien's avatar
sebastien committed
358
  //! Get number of exogenous variables
359
  inline int exo_nbr() const noexcept(false);
sebastien's avatar
sebastien committed
360
  //! Get number of exogenous deterministic variables
361
  inline int exo_det_nbr() const noexcept(false);
sebastien's avatar
sebastien committed
362
  //! Get number of parameters
363
  inline int param_nbr() const noexcept(false);
sebastien's avatar
sebastien committed
364
365
  //! Returns the greatest symbol ID (the smallest is zero)
  inline int maxID();
366
  //! Get number of user-declared endogenous variables (without the auxiliary variables)
367
  inline int orig_endo_nbr() const noexcept(false);
368
  //! Write output of this class
369
  void writeOutput(ostream &output) const noexcept(false);
370
371
  //! Write JSON Output
  void writeJsonOutput(ostream &output) const;
372
  //! Write Julia output of this class
373
  void writeJuliaOutput(ostream &output) const noexcept(false);
374
  //! Write C output of this class
375
  void writeCOutput(ostream &output) const noexcept(false);
376
  //! Write CC output of this class
377
  void writeCCOutput(ostream &output) const noexcept(false);
sebastien's avatar
sebastien committed
378
  //! Mark a symbol as predetermined variable
379
  void markPredetermined(int symb_id) noexcept(false);
sebastien's avatar
sebastien committed
380
  //! Test if a given symbol is a predetermined variable
381
  bool isPredetermined(int symb_id) const noexcept(false);
sebastien's avatar
sebastien committed
382
383
  //! Return the number of predetermined variables
  int predeterminedNbr() const;
Sébastien Villemot's avatar
Sébastien Villemot committed
384
  //! Add an observed variable
385
  void addObservedVariable(int symb_id) noexcept(false);
Sébastien Villemot's avatar
Sébastien Villemot committed
386
387
388
389
390
391
  //! Return the number of observed variables
  int observedVariablesNbr() const;
  //! Is a given symbol in the set of observed variables
  bool isObservedVariable(int symb_id) const;
  //! Return the index of a given observed variable in the vector of all observed variables
  int getObservedVariableIndex(int symb_id) const;
392
  //! Add an observed exogenous variable
393
  void addObservedExogenousVariable(int symb_id) noexcept(false);
394
395
396
397
398
399
  //! Return the number of observed exogenous variables
  int observedExogenousVariablesNbr() const;
  //! Is a given symbol in the set of observed exogenous variables
  bool isObservedExogenousVariable(int symb_id) const;
  //! Return the index of a given observed exogenous variable in the vector of all observed variables
  int getObservedExogenousVariableIndex(int symb_id) const;
400
  vector <int> getTrendVarIds() const;
401
402
  //! Get list of exogenous variables
  set <int> getExogenous() const;
403
404
  //! Get list of exogenous variables
  set <int> getObservedExogenous() const;
405
406
  //! Get list of endogenous variables
  set <int> getEndogenous() const;
407
408
  //! Is a given symbol an auxiliary variable
  bool isAuxiliaryVariable(int symb_id) const;
409
410
  //! Is a given symbol an auxiliary variable but not a Lagrange multiplier
  bool isAuxiliaryVariableButNotMultiplier(int symb_id) const;
411
412
  //! Get list of endogenous variables without aux vars
  set <int> getOrigEndogenous() const;
413
414
};

415
inline void
416
SymbolTable::validateSymbID(int symb_id) const noexcept(false)
417
{
418
  if (symb_id < 0 || symb_id > (int) symbol_table.size())
419
420
421
    throw UnknownSymbolIDException(symb_id);
}

422
423
424
inline bool
SymbolTable::exists(const string &name) const
{
425
  auto iter = symbol_table.find(name);
426
427
428
429
  return (iter != symbol_table.end());
}

inline string
430
SymbolTable::getName(int id) const noexcept(false)
431
{
432
433
  validateSymbID(id);
  return name_table[id];
434
435
436
}

inline string
437
SymbolTable::getTeXName(int id) const noexcept(false)
438
{
439
440
  validateSymbID(id);
  return tex_name_table[id];
441
442
}

443
inline string
444
SymbolTable::getLongName(int id) const noexcept(false)
445
{
446
447
  validateSymbID(id);
  return long_name_table[id];
448
449
}

450
inline SymbolType
451
SymbolTable::getType(int id) const noexcept(false)
452
{
453
454
  validateSymbID(id);
  return type_table[id];
sebastien's avatar
sebastien committed
455
456
457
}

inline SymbolType
458
SymbolTable::getType(const string &name) const noexcept(false)
sebastien's avatar
sebastien committed
459
460
{
  return getType(getID(name));
461
462
463
}

inline int
464
SymbolTable::getID(const string &name) const noexcept(false)
465
{
466
  auto iter = symbol_table.find(name);
467
  if (iter != symbol_table.end())
sebastien's avatar
sebastien committed
468
    return iter->second;
469
470
471
472
  else
    throw UnknownSymbolNameException(name);
}

sebastien's avatar
sebastien committed
473
inline int
474
SymbolTable::getTypeSpecificID(int id) const noexcept(false)
sebastien's avatar
sebastien committed
475
476
477
478
{
  if (!frozen)
    throw NotYetFrozenException();

479
  validateSymbID(id);
sebastien's avatar
sebastien committed
480
481
482
483
484

  return type_specific_ids[id];
}

inline int
485
SymbolTable::getTypeSpecificID(const string &name) const noexcept(false)
sebastien's avatar
sebastien committed
486
487
488
489
490
{
  return getTypeSpecificID(getID(name));
}

inline int
491
SymbolTable::endo_nbr() const noexcept(false)
sebastien's avatar
sebastien committed
492
493
494
495
496
497
498
499
{
  if (!frozen)
    throw NotYetFrozenException();

  return endo_ids.size();
}

inline int
500
SymbolTable::exo_nbr() const noexcept(false)
sebastien's avatar
sebastien committed
501
502
503
504
505
506
507
508
{
  if (!frozen)
    throw NotYetFrozenException();

  return exo_ids.size();
}

inline int
509
SymbolTable::exo_det_nbr() const noexcept(false)
sebastien's avatar
sebastien committed
510
511
512
513
514
515
516
517
{
  if (!frozen)
    throw NotYetFrozenException();

  return exo_det_ids.size();
}

inline int
518
SymbolTable::param_nbr() const noexcept(false)
sebastien's avatar
sebastien committed
519
520
521
522
523
524
525
526
527
528
{
  if (!frozen)
    throw NotYetFrozenException();

  return param_ids.size();
}

inline int
SymbolTable::maxID()
{
529
  return symbol_table.size() - 1;
sebastien's avatar
sebastien committed
530
531
}

532
inline int
533
SymbolTable::orig_endo_nbr() const noexcept(false)
534
535
536
537
{
  return (endo_nbr() - aux_vars.size());
}

538
#endif