SymbolTable.cc 12.5 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
Sébastien Villemot's avatar
Sébastien Villemot committed
2
 * Copyright (C) 2003-2010 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
        {
sebastien's avatar
sebastien committed
172
173
          output << "M_.exo_names = strvcat(M_.exo_names, '" << getName(exo_ids[id]) << "');" << endl
                 << "M_.exo_names_tex = strvcat(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
        {
sebastien's avatar
sebastien committed
182
183
          output << "M_.exo_det_names = strvcat(M_.exo_det_names, '" << getName(exo_det_ids[id]) << "');" << endl
                 << "M_.exo_det_names_tex = strvcat(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
        {
sebastien's avatar
sebastien committed
192
193
          output << "M_.endo_names = strvcat(M_.endo_names, '" << getName(endo_ids[id]) << "');" << endl
                 << "M_.endo_names_tex = strvcat(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
        {
sebastien's avatar
sebastien committed
202
203
          output << "M_.param_names = strvcat(M_.param_names, '" << getName(param_ids[id]) << "');" << endl
                 << "M_.param_names_tex = strvcat(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
255

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

      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
262
    }
sebastien's avatar
sebastien committed
263
264
265
}

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

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

  return symb_id;
}

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

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

311
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, ""));
sebastien's avatar
sebastien committed
312
313

  return symb_id;
314
}
315

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

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

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

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

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

  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;

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

362
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name));
363
364
365

  return symb_id;
}
sebastien's avatar
sebastien committed
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385

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

386
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
387
388
389
390
391
}

int
SymbolTable::predeterminedNbr() const
{
392
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
393
}
Sébastien Villemot's avatar
Sébastien Villemot committed
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423

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