SymbolTable.cc 13.3 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
29
30
31
32
33
34
35
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) :
  symb_id(symb_id_arg),
  type(type_arg),
  orig_symb_id(orig_symb_id_arg),
  orig_lead_lag(orig_lead_lag_arg),
  expectation_information_set_name(expectation_information_set_name_arg)
{
}

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

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

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

sebastien's avatar
sebastien committed
54
55
56
57
58
59
  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
60
61

  return id;
sebastien's avatar
sebastien committed
62
63
}

sebastien's avatar
sebastien committed
64
int
65
66
67
68
69
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;
70
  while ((pos = tex_name.find('_', pos)) != string::npos)
71
72
73
74
    {
      tex_name.insert(pos, "\\");
      pos += 2;
    }
sebastien's avatar
sebastien committed
75
  return addSymbol(name, type, tex_name);
76
77
}

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

sebastien's avatar
sebastien committed
84
85
  frozen = true;

86
  for (int i = 0; i < size; i++)
87
    {
sebastien's avatar
sebastien committed
88
      int tsi;
89
      switch (getType(i))
sebastien's avatar
sebastien committed
90
91
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
        {
        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();

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

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

  if (exo_nbr() > 0)
167
    {
sebastien's avatar
sebastien committed
168
169
170
      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++)
171
        {
172
173
          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;
174
175
        }
    }
sebastien's avatar
sebastien committed
176
  if (exo_det_nbr() > 0)
177
    {
sebastien's avatar
sebastien committed
178
179
180
      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++)
181
        {
182
183
          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;
184
185
        }
    }
sebastien's avatar
sebastien committed
186
  if (endo_nbr() > 0)
187
    {
sebastien's avatar
sebastien committed
188
189
190
      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++)
191
        {
192
193
          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;
194
195
        }
    }
sebastien's avatar
sebastien committed
196
  if (param_nbr() > 0)
197
    {
sebastien's avatar
sebastien committed
198
199
200
      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++)
201
        {
202
203
          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;
204
205
206

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

sebastien's avatar
sebastien committed
210
211
212
213
  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
214

sebastien's avatar
sebastien committed
215
  // Write the auxiliary variable table
216
  output << "M_.orig_endo_nbr = " << orig_endo_nbr() << ";" << endl;
sebastien's avatar
sebastien committed
217
218
219
  if (aux_vars.size() == 0)
    output << "M_.aux_vars = [];" << endl;
  else
220
    for (int i = 0; i < (int) aux_vars.size(); i++)
sebastien's avatar
sebastien committed
221
      {
222
223
224
        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
225
226
227
228
229
          {
          case avEndoLead:
          case avExoLead:
          case avExpectation:
            break;
230
231
232
          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
233
234
          case avEndoLag:
          case avExoLag:
235
236
            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
237
238
239
            break;
          }
      }
sebastien's avatar
sebastien committed
240
241
242
243

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

  if (observedVariablesNbr() > 0)
    {
      output << "options_.varobs = [];" << endl;
      for (vector<int>::const_iterator it = varobs.begin();
           it != varobs.end(); it++)
255
256
257
258
        if (it == varobs.begin())
          output << "options_.varobs = '" << getName(*it) << "';" << endl;
        else
          output << "options_.varobs = char(options_.varobs, '" << getName(*it) << "');" << endl;
259
260
261
262
263
264

      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
265
    }
sebastien's avatar
sebastien committed
266
267
268
}

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

288
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLead : avExoLead), 0, 0, ""));
sebastien's avatar
sebastien committed
289
290
291
292
293

  return symb_id;
}

int
sebastien's avatar
sebastien committed
294
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag) throw (FrozenException)
sebastien's avatar
sebastien committed
295
296
{
  ostringstream varname;
sebastien's avatar
sebastien committed
297
298
299
300
  if (endo)
    varname << "AUX_ENDO_LAG_";
  else
    varname << "AUX_EXO_LAG_";
301
  varname << orig_symb_id << "_" << -orig_lead_lag;
302

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

314
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, ""));
sebastien's avatar
sebastien committed
315
316

  return symb_id;
317
}
318

sebastien's avatar
sebastien committed
319
320
321
322
323
324
int
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
{
  return addLeadAuxiliaryVarInternal(true, index);
}

325
int
sebastien's avatar
sebastien committed
326
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
327
{
sebastien's avatar
sebastien committed
328
  return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag);
329
330
331
}

int
sebastien's avatar
sebastien committed
332
SymbolTable::addExoLeadAuxiliaryVar(int index) throw (FrozenException)
333
{
sebastien's avatar
sebastien committed
334
  return addLeadAuxiliaryVarInternal(false, index);
335
336
337
}

int
sebastien's avatar
sebastien committed
338
SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
339
{
sebastien's avatar
sebastien committed
340
  return addLagAuxiliaryVarInternal(false, orig_symb_id, orig_lead_lag);
341
}
342
343

int
344
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException)
345
346
347
{
  ostringstream varname;
  int symb_id;
348
349
350
351
352
353
354

  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;

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

365
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name));
366
367
368

  return symb_id;
}
sebastien's avatar
sebastien committed
369

370
int
Sébastien Villemot's avatar
Sébastien Villemot committed
371
SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const throw (SearchFailedException)
372
{
Sébastien Villemot's avatar
Sébastien Villemot committed
373
  for (size_t i = 0; i < aux_vars.size(); i++)
374
375
    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)
376
      return aux_vars[i].get_symb_id();
Sébastien Villemot's avatar
Sébastien Villemot committed
377
  throw SearchFailedException(orig_symb_id, orig_lead_lag);
378
379
}

sebastien's avatar
sebastien committed
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
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);

399
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
400
401
402
403
404
}

int
SymbolTable::predeterminedNbr() const
{
405
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
406
}
Sébastien Villemot's avatar
Sébastien Villemot committed
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436

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());
}
437
438
439
440
441
442
443
444
445
446
447

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;
}