SymbolTable.cc 14.1 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
2
 * Copyright (C) 2003-2011 Dynare Team
sebastien's avatar
sebastien committed
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
 *
 * 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/>.
 */

20
#include <algorithm>
21
#include <sstream>
sebastien's avatar
sebastien committed
22
#include <iostream>
sebastien's avatar
sebastien committed
23
#include <cassert>
24

25
#include "SymbolTable.hh"
26

27
28
AuxVarInfo::AuxVarInfo(int symb_id_arg, aux_var_t type_arg, int orig_symb_id_arg, int orig_lead_lag_arg,
                       string expectation_information_set_name_arg, int equation_number_for_multiplier_arg) :
29
30
31
32
  symb_id(symb_id_arg),
  type(type_arg),
  orig_symb_id(orig_symb_id_arg),
  orig_lead_lag(orig_lead_lag_arg),
33
34
  expectation_information_set_name(expectation_information_set_name_arg),
  equation_number_for_multiplier(equation_number_for_multiplier_arg)
35
36
37
{
}

sebastien's avatar
sebastien committed
38
SymbolTable::SymbolTable() : frozen(false), size(0)
39
40
41
{
}

sebastien's avatar
sebastien committed
42
int
sebastien's avatar
sebastien committed
43
SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_name) throw (AlreadyDeclaredException, FrozenException)
44
{
sebastien's avatar
sebastien committed
45
46
47
  if (frozen)
    throw FrozenException();

sebastien's avatar
sebastien committed
48
  if (exists(name))
49
    {
sebastien's avatar
sebastien committed
50
      if (type_table[getID(name)] == type)
51
52
53
54
        throw AlreadyDeclaredException(name, true);
      else
        throw AlreadyDeclaredException(name, false);
    }
sebastien's avatar
sebastien committed
55

sebastien's avatar
sebastien committed
56
57
58
59
60
61
  int id = size++;

  symbol_table[name] = id;
  type_table.push_back(type);
  name_table.push_back(name);
  tex_name_table.push_back(tex_name);
sebastien's avatar
sebastien committed
62
63

  return id;
sebastien's avatar
sebastien committed
64
65
}

sebastien's avatar
sebastien committed
66
int
67
68
69
70
71
SymbolTable::addSymbol(const string &name, SymbolType type) throw (AlreadyDeclaredException, FrozenException)
{
  // Construct "tex_name" by prepending an antislash to all underscores in "name"
  string tex_name = name;
  size_t pos = 0;
72
  while ((pos = tex_name.find('_', pos)) != string::npos)
73
74
75
76
    {
      tex_name.insert(pos, "\\");
      pos += 2;
    }
sebastien's avatar
sebastien committed
77
  return addSymbol(name, type, tex_name);
78
79
}

sebastien's avatar
sebastien committed
80
81
82
83
84
void
SymbolTable::freeze() throw (FrozenException)
{
  if (frozen)
    throw FrozenException();
85

sebastien's avatar
sebastien committed
86
87
  frozen = true;

88
  for (int i = 0; i < size; i++)
89
    {
sebastien's avatar
sebastien committed
90
      int tsi;
91
      switch (getType(i))
sebastien's avatar
sebastien committed
92
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
134
        {
        case eEndogenous:
          tsi = endo_ids.size();
          endo_ids.push_back(i);
          break;
        case eExogenous:
          tsi = exo_ids.size();
          exo_ids.push_back(i);
          break;
        case eExogenousDet:
          tsi = exo_det_ids.size();
          exo_det_ids.push_back(i);
          break;
        case eParameter:
          tsi = param_ids.size();
          param_ids.push_back(i);
          break;
        default:
          tsi = -1;
          break;
        }
      type_specific_ids.push_back(tsi);
    }
}

void
SymbolTable::changeType(int id, SymbolType newtype) throw (UnknownSymbolIDException, FrozenException)
{
  if (frozen)
    throw FrozenException();

  if (id < 0 || id >= size)
    throw UnknownSymbolIDException(id);

  type_table[id] = newtype;
}

int
SymbolTable::getID(SymbolType type, int tsid) const throw (UnknownTypeSpecificIDException, NotYetFrozenException)
{
  if (!frozen)
    throw NotYetFrozenException();

135
  switch (type)
sebastien's avatar
sebastien committed
136
137
138
139
140
141
    {
    case eEndogenous:
      if (tsid < 0 || tsid >= (int) endo_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return endo_ids[tsid];
142
    case eExogenous:
sebastien's avatar
sebastien committed
143
144
145
146
      if (tsid < 0 || tsid >= (int) exo_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return exo_ids[tsid];
147
    case eExogenousDet:
sebastien's avatar
sebastien committed
148
149
150
151
      if (tsid < 0 || tsid >= (int) exo_det_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return exo_det_ids[tsid];
152
    case eParameter:
sebastien's avatar
sebastien committed
153
154
155
156
157
158
      if (tsid < 0 || tsid >= (int) param_ids.size())
        throw UnknownTypeSpecificIDException(tsid, type);
      else
        return param_ids[tsid];
    default:
      throw UnknownTypeSpecificIDException(tsid, type);
159
160
161
    }
}

sebastien's avatar
sebastien committed
162
void
sebastien's avatar
sebastien committed
163
SymbolTable::writeOutput(ostream &output) const throw (NotYetFrozenException)
164
{
sebastien's avatar
sebastien committed
165
166
167
168
  if (!frozen)
    throw NotYetFrozenException();

  if (exo_nbr() > 0)
169
    {
sebastien's avatar
sebastien committed
170
171
172
      output << "M_.exo_names = '" << getName(exo_ids[0]) << "';" << endl;
      output << "M_.exo_names_tex = '" << getTeXName(exo_ids[0]) << "';" << endl;
      for (int id = 1; id < exo_nbr(); id++)
173
        {
174
175
          output << "M_.exo_names = char(M_.exo_names, '" << getName(exo_ids[id]) << "');" << endl
                 << "M_.exo_names_tex = char(M_.exo_names_tex, '" << getTeXName(exo_ids[id]) << "');" << endl;
176
177
        }
    }
sebastien's avatar
sebastien committed
178
  if (exo_det_nbr() > 0)
179
    {
sebastien's avatar
sebastien committed
180
181
182
      output << "M_.exo_det_names = '" << getName(exo_det_ids[0]) << "';" << endl;
      output << "M_.exo_det_names_tex = '" << getTeXName(exo_det_ids[0]) << "';" << endl;
      for (int id = 1; id < exo_det_nbr(); id++)
183
        {
184
185
          output << "M_.exo_det_names = char(M_.exo_det_names, '" << getName(exo_det_ids[id]) << "');" << endl
                 << "M_.exo_det_names_tex = char(M_.exo_det_names_tex, '" << getTeXName(exo_det_ids[id]) << "');" << endl;
186
187
        }
    }
sebastien's avatar
sebastien committed
188
  if (endo_nbr() > 0)
189
    {
sebastien's avatar
sebastien committed
190
191
192
      output << "M_.endo_names = '" << getName(endo_ids[0]) << "';" << endl;
      output << "M_.endo_names_tex = '" << getTeXName(endo_ids[0]) << "';" << endl;
      for (int id = 1; id < endo_nbr(); id++)
193
        {
194
195
          output << "M_.endo_names = char(M_.endo_names, '" << getName(endo_ids[id]) << "');" << endl
                 << "M_.endo_names_tex = char(M_.endo_names_tex, '" << getTeXName(endo_ids[id]) << "');" << endl;
196
197
        }
    }
sebastien's avatar
sebastien committed
198
  if (param_nbr() > 0)
199
    {
sebastien's avatar
sebastien committed
200
201
202
      output << "M_.param_names = '" << getName(param_ids[0]) << "';" << endl;
      output << "M_.param_names_tex = '" << getTeXName(param_ids[0]) << "';" << endl;
      for (int id = 1; id < param_nbr(); id++)
203
        {
204
205
          output << "M_.param_names = char(M_.param_names, '" << getName(param_ids[id]) << "');" << endl
                 << "M_.param_names_tex = char(M_.param_names_tex, '" << getTeXName(param_ids[id]) << "');" << endl;
206
207
208

          if (getName(param_ids[id]) == "dsge_prior_weight")
            output << "options_.dsge_var = 1;" << endl;
209
210
211
        }
    }

sebastien's avatar
sebastien committed
212
213
214
215
  output << "M_.exo_det_nbr = " << exo_det_nbr() << ";" << endl
         << "M_.exo_nbr = " << exo_nbr() << ";" << endl
         << "M_.endo_nbr = " << endo_nbr() << ";" << endl
         << "M_.param_nbr = " << param_nbr() << ";" << endl;
sebastien's avatar
sebastien committed
216

sebastien's avatar
sebastien committed
217
  // Write the auxiliary variable table
218
  output << "M_.orig_endo_nbr = " << orig_endo_nbr() << ";" << endl;
sebastien's avatar
sebastien committed
219
220
221
  if (aux_vars.size() == 0)
    output << "M_.aux_vars = [];" << endl;
  else
222
    for (int i = 0; i < (int) aux_vars.size(); i++)
sebastien's avatar
sebastien committed
223
      {
224
225
226
        output << "M_.aux_vars(" << i+1 << ").endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id())+1 << ";" << endl
               << "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].get_type() << ";" << endl;
        switch (aux_vars[i].get_type())
sebastien's avatar
sebastien committed
227
228
229
230
231
          {
          case avEndoLead:
          case avExoLead:
          case avExpectation:
            break;
232
233
234
          case avExpectationRIS:
            output << "M_.aux_vars(" << i+1 << ").expectation_information_set_name = '" << aux_vars[i].get_expectation_information_set_name() << "';" << endl;
            break;
sebastien's avatar
sebastien committed
235
236
          case avEndoLag:
          case avExoLag:
237
238
            output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl
                   << "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
sebastien's avatar
sebastien committed
239
            break;
240
241
242
          case avMultiplier:
            output << "M_.aux_vars(" << i+1 << ").eq_nbr = '" << aux_vars[i].get_equation_number_for_multiplier() << "';" << endl;
            break;
sebastien's avatar
sebastien committed
243
244
          }
      }
sebastien's avatar
sebastien committed
245
246
247
248

  if (predeterminedNbr() > 0)
    {
      output << "M_.predetermined_variables = [ ";
249
250
      for (set<int>::const_iterator it = predetermined_variables.begin();
           it != predetermined_variables.end(); it++)
251
        output << getTypeSpecificID(*it)+1 << " ";
sebastien's avatar
sebastien committed
252
253
      output << "];" << endl;
    }
Sébastien Villemot's avatar
Sébastien Villemot committed
254
255
256
257
258
259

  if (observedVariablesNbr() > 0)
    {
      output << "options_.varobs = [];" << endl;
      for (vector<int>::const_iterator it = varobs.begin();
           it != varobs.end(); it++)
260
261
262
263
        if (it == varobs.begin())
          output << "options_.varobs = '" << getName(*it) << "';" << endl;
        else
          output << "options_.varobs = char(options_.varobs, '" << getName(*it) << "');" << endl;
264
265
266
267
268
269

      output << "options_.varobs_id = [ ";
      for (vector<int>::const_iterator it = varobs.begin();
           it != varobs.end(); it++)
        output << getTypeSpecificID(*it)+1 << " ";
      output << " ];"  << endl;
Sébastien Villemot's avatar
Sébastien Villemot committed
270
    }
sebastien's avatar
sebastien committed
271
272
273
}

int
sebastien's avatar
sebastien committed
274
SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index) throw (FrozenException)
sebastien's avatar
sebastien committed
275
276
{
  ostringstream varname;
sebastien's avatar
sebastien committed
277
278
279
280
281
  if (endo)
    varname << "AUX_ENDO_LEAD_";
  else
    varname << "AUX_EXO_LEAD_";
  varname << index;
sebastien's avatar
sebastien committed
282
283
284
285
286
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
287
  catch (AlreadyDeclaredException &e)
sebastien's avatar
sebastien committed
288
289
290
291
292
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

293
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLead : avExoLead), 0, 0, "", 0));
sebastien's avatar
sebastien committed
294
295
296
297
298

  return symb_id;
}

int
sebastien's avatar
sebastien committed
299
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag) throw (FrozenException)
sebastien's avatar
sebastien committed
300
301
{
  ostringstream varname;
sebastien's avatar
sebastien committed
302
303
304
305
  if (endo)
    varname << "AUX_ENDO_LAG_";
  else
    varname << "AUX_EXO_LAG_";
306
  varname << orig_symb_id << "_" << -orig_lead_lag;
307

sebastien's avatar
sebastien committed
308
309
310
311
312
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
313
  catch (AlreadyDeclaredException &e)
sebastien's avatar
sebastien committed
314
315
316
317
318
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

319
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, "", 0));
sebastien's avatar
sebastien committed
320
321

  return symb_id;
322
}
323

sebastien's avatar
sebastien committed
324
325
326
327
328
329
int
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
{
  return addLeadAuxiliaryVarInternal(true, index);
}

330
int
sebastien's avatar
sebastien committed
331
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
332
{
sebastien's avatar
sebastien committed
333
  return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag);
334
335
336
}

int
sebastien's avatar
sebastien committed
337
SymbolTable::addExoLeadAuxiliaryVar(int index) throw (FrozenException)
338
{
sebastien's avatar
sebastien committed
339
  return addLeadAuxiliaryVarInternal(false, index);
340
341
342
}

int
sebastien's avatar
sebastien committed
343
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
344
{
sebastien's avatar
sebastien committed
345
  return addLagAuxiliaryVarInternal(false, orig_symb_id, orig_lead_lag);
346
}
347
348

int
349
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException)
350
351
352
{
  ostringstream varname;
  int symb_id;
353
354
355
356
357
358
359

  if (information_set_name.empty())
    varname << "AUX_EXPECT_" << (information_set < 0 ? "LAG" : "LEAD") << "_"
            << abs(information_set) << "_" << index;
  else
    varname << "AUX_EXPECT_" << information_set_name << "_" << index;

360
361
362
363
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
364
  catch (AlreadyDeclaredException &e)
365
366
367
368
369
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name, 0));

  return symb_id;
}

int
SymbolTable::addMultiplierAuxiliaryVar(int index) throw (FrozenException)
{
  ostringstream varname;
  int symb_id;
  varname << "MULT_" << index;

  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
  catch (AlreadyDeclaredException &e)
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }
391

392
  aux_vars.push_back(AuxVarInfo(symb_id, avMultiplier, 0, 0, "", index));
393
394
  return symb_id;
}
sebastien's avatar
sebastien committed
395

396
int
Sébastien Villemot's avatar
Sébastien Villemot committed
397
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException)
398
{
Sébastien Villemot's avatar
Sébastien Villemot committed
399
  for (size_t i = 0; i < aux_vars.size(); i++)
400
401
    if ((aux_vars[i].get_type() == avEndoLag || aux_vars[i].get_type() == avExoLag)
        && aux_vars[i].get_orig_symb_id() == orig_symb_id && aux_vars[i].get_orig_lead_lag() == orig_lead_lag)
402
      return aux_vars[i].get_symb_id();
Sébastien Villemot's avatar
Sébastien Villemot committed
403
  throw SearchFailedException(orig_symb_id, orig_lead_lag);
404
405
}

sebastien's avatar
sebastien committed
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
void
SymbolTable::markPredetermined(int symb_id) throw (UnknownSymbolIDException, FrozenException)
{
  if (symb_id < 0 || symb_id >= size)
    throw UnknownSymbolIDException(symb_id);
  if (frozen)
    throw FrozenException();

  assert(getType(symb_id) == eEndogenous);

  predetermined_variables.insert(symb_id);
}

bool
SymbolTable::isPredetermined(int symb_id) const throw (UnknownSymbolIDException)
{
  if (symb_id < 0 || symb_id >= size)
    throw UnknownSymbolIDException(symb_id);

425
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
426
427
428
429
430
}

int
SymbolTable::predeterminedNbr() const
{
431
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
432
}
Sébastien Villemot's avatar
Sébastien Villemot committed
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462

void
SymbolTable::addObservedVariable(int symb_id) throw (UnknownSymbolIDException)
{
  if (symb_id < 0 || symb_id >= size)
    throw UnknownSymbolIDException(symb_id);

  assert(getType(symb_id) == eEndogenous);
  varobs.push_back(symb_id);
}

int
SymbolTable::observedVariablesNbr() const
{
  return (int) varobs.size();
}

bool
SymbolTable::isObservedVariable(int symb_id) const
{
  return (find(varobs.begin(), varobs.end(), symb_id) != varobs.end());
}

int
SymbolTable::getObservedVariableIndex(int symb_id) const
{
  vector<int>::const_iterator it = find(varobs.begin(), varobs.end(), symb_id);
  assert(it != varobs.end());
  return (int) (it - varobs.begin());
}
463
464
465
466
467
468
469
470
471
472
473

vector <int>
SymbolTable::getTrendVarIds() const
{
  vector <int> trendVars;
  for (symbol_table_type::const_iterator it = symbol_table.begin();
       it != symbol_table.end(); it++)
    if (getType(it->second) == eTrend)
      trendVars.push_back(it->second);
  return trendVars;
}