SymbolTable.hh 17.7 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2018 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 38 39
//! Types of auxiliary variables
enum aux_var_t
  {
40 41 42 43 44 45 46 47 48 49 50
    avEndoLead = 0,    //!< Substitute for endo leads >= 2
    avEndoLag = 1,     //!< Substitute for endo lags >= 2
    avExoLead = 2,     //!< Substitute for exo leads >= 1
    avExoLag = 3,      //!< Substitute for exo lags >= 1
    avExpectation = 4, //!< Substitute for Expectation Operator
    avDiffForward = 5, //!< Substitute for the differentiate of a forward variable
    avMultiplier = 6,  //!< Multipliers for FOC of Ramsey Problem
    avVarModel = 7,    //!< Variable for var_model with order > abs(min_lag()) present in model
    avDiff = 8,        //!< Variable for Diff operator
    avDiffLag = 9,     //!< Variable for timing between Diff operators
    avUnaryOp = 10     //!< Variable for allowing the undiff operator to work when diff was taken of unary op, eg diff(log(x))
sebastien's avatar
sebastien committed
51 52 53
  };

//! Information on some auxiliary variables
54
class AuxVarInfo
sebastien's avatar
sebastien committed
55
{
56
private:
sebastien's avatar
sebastien committed
57 58
  int symb_id; //!< Symbol ID of the auxiliary variable
  aux_var_t type; //!< Its type
Sébastien Villemot's avatar
Sébastien Villemot committed
59 60
  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.
61
  int equation_number_for_multiplier; //!< Stores the original constraint equation number associated with this aux var. Only used for avMultiplier.
62
  int information_set; //! Argument of expectation operator. Only used for avExpectation.
63
  expr_t expr_node; //! Auxiliary variable definition
64
public:
65
  AuxVarInfo(int symb_id_arg, aux_var_t 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);
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
  int
  get_symb_id() const
  {
    return symb_id;
  };
  aux_var_t
  get_type() const
  {
    return type;
  };
  int
  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;
  };
sebastien's avatar
sebastien committed
101 102
};

103 104
//! Stores the symbol table
/*!
sebastien's avatar
sebastien committed
105
  A symbol is given by its name, and is internally represented by a unique integer.
106

sebastien's avatar
sebastien committed
107 108 109
  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".
110

111
  Also manages a TeX name for each symbol, which by default is an empty string.
112 113 114 115
*/
class SymbolTable
{
private:
sebastien's avatar
sebastien committed
116
  //! Has method freeze() been called?
117
  bool frozen{false};
sebastien's avatar
sebastien committed
118 119 120

  typedef map<string, int> symbol_table_type;
  //! Maps strings to symbol IDs
121 122
  symbol_table_type symbol_table;

sebastien's avatar
sebastien committed
123 124 125 126
  //! Maps IDs to names
  vector<string> name_table;
  //! Maps IDs to TeX names
  vector<string> tex_name_table;
127 128
  //! Maps IDs to string names of variables
  vector<string> long_name_table;
129
  //! Maps IDs to a pair containing the partition and the partition value
130
  map<int, map<string, string> > partition_value_map;
sebastien's avatar
sebastien committed
131 132 133 134 135 136 137 138 139 140 141 142 143 144
  //! 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
145 146
  //! Information about auxiliary variables
  vector<AuxVarInfo> aux_vars;
147

sebastien's avatar
sebastien committed
148 149 150
  //! Stores the predetermined variables (by symbol IDs)
  set<int> predetermined_variables;

Sébastien Villemot's avatar
Sébastien Villemot committed
151 152 153
  //! Stores the list of observed variables
  vector<int> varobs;

154 155 156
  //! Stores the list of observed exogenous variables
  vector<int> varexobs;

157 158 159 160 161 162 163 164
public:
  SymbolTable();
  //! Thrown when trying to access an unknown symbol (by name)
  class UnknownSymbolNameException
  {
  public:
    //! Symbol name
    string name;
165
    UnknownSymbolNameException(string name_arg) : name(move(name_arg))
166 167
    {
    }
168
  };
sebastien's avatar
sebastien committed
169
  //! Thrown when trying to access an unknown symbol (by id)
170 171 172 173 174
  class UnknownSymbolIDException
  {
  public:
    //! Symbol ID
    int id;
175 176 177
    UnknownSymbolIDException(int id_arg) : id(id_arg)
    {
    }
sebastien's avatar
sebastien committed
178 179 180 181 182 183 184
  };
  //! Thrown when trying to access an unknown type specific ID
  class UnknownTypeSpecificIDException
  {
  public:
    int tsid;
    SymbolType type;
185 186 187
    UnknownTypeSpecificIDException(int tsid_arg, SymbolType type_arg) : tsid(tsid_arg), type(type_arg)
    {
    }
188 189 190 191 192 193 194 195 196
  };
  //! 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;
197
    AlreadyDeclaredException(string name_arg, bool same_type_arg) : name(move(name_arg)), same_type(same_type_arg)
198 199
    {
    }
200
  };
sebastien's avatar
sebastien committed
201 202 203 204 205 206 207 208
  //! 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
209 210 211 212
  //! Thrown when searchAuxiliaryVars() failed
  class SearchFailedException
  {
  public:
213
    int orig_symb_id, orig_lead_lag, symb_id;
Sébastien Villemot's avatar
Sébastien Villemot committed
214 215 216 217
    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)
    {
    }
218 219 220
    SearchFailedException(int symb_id_arg) : symb_id(symb_id_arg)
    {
    }
Sébastien Villemot's avatar
Sébastien Villemot committed
221
  };
222 223

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

397
inline void
398
SymbolTable::validateSymbID(int symb_id) const noexcept(false)
399
{
400
  if (symb_id < 0 || symb_id > (int) symbol_table.size())
401 402 403
    throw UnknownSymbolIDException(symb_id);
}

404 405 406
inline bool
SymbolTable::exists(const string &name) const
{
407
  auto iter = symbol_table.find(name);
408 409 410 411
  return (iter != symbol_table.end());
}

inline string
412
SymbolTable::getName(int id) const noexcept(false)
413
{
414 415
  validateSymbID(id);
  return name_table[id];
416 417 418
}

inline string
419
SymbolTable::getTeXName(int id) const noexcept(false)
420
{
421 422
  validateSymbID(id);
  return tex_name_table[id];
423 424
}

425
inline string
426
SymbolTable::getLongName(int id) const noexcept(false)
427
{
428 429
  validateSymbID(id);
  return long_name_table[id];
430 431
}

432
inline SymbolType
433
SymbolTable::getType(int id) const noexcept(false)
434
{
435 436
  validateSymbID(id);
  return type_table[id];
sebastien's avatar
sebastien committed
437 438 439
}

inline SymbolType
440
SymbolTable::getType(const string &name) const noexcept(false)
sebastien's avatar
sebastien committed
441 442
{
  return getType(getID(name));
443 444 445
}

inline int
446
SymbolTable::getID(const string &name) const noexcept(false)
447
{
448
  auto iter = symbol_table.find(name);
449
  if (iter != symbol_table.end())
sebastien's avatar
sebastien committed
450
    return iter->second;
451 452 453 454
  else
    throw UnknownSymbolNameException(name);
}

sebastien's avatar
sebastien committed
455
inline int
456
SymbolTable::getTypeSpecificID(int id) const noexcept(false)
sebastien's avatar
sebastien committed
457 458 459 460
{
  if (!frozen)
    throw NotYetFrozenException();

461
  validateSymbID(id);
sebastien's avatar
sebastien committed
462 463 464 465 466

  return type_specific_ids[id];
}

inline int
467
SymbolTable::getTypeSpecificID(const string &name) const noexcept(false)
sebastien's avatar
sebastien committed
468 469 470 471 472
{
  return getTypeSpecificID(getID(name));
}

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

  return endo_ids.size();
}

inline int
482
SymbolTable::exo_nbr() const noexcept(false)
sebastien's avatar
sebastien committed
483 484 485 486 487 488 489 490
{
  if (!frozen)
    throw NotYetFrozenException();

  return exo_ids.size();
}

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

  return exo_det_ids.size();
}

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

  return param_ids.size();
}

inline int
SymbolTable::maxID()
{
511
  return symbol_table.size() - 1;
sebastien's avatar
sebastien committed
512 513
}

514
inline int
515
SymbolTable::orig_endo_nbr() const noexcept(false)
516 517 518 519
{
  return (endo_nbr() - aux_vars.size());
}

520
#endif