SymbolTable.cc 12.2 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
        }
    }

sebastien's avatar
sebastien committed
207
208
209
210
  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
211

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

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

  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;
    }
sebastien's avatar
sebastien committed
254
255
256
}

int
sebastien's avatar
sebastien committed
257
SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index) throw (FrozenException)
sebastien's avatar
sebastien committed
258
259
{
  ostringstream varname;
sebastien's avatar
sebastien committed
260
261
262
263
264
  if (endo)
    varname << "AUX_ENDO_LEAD_";
  else
    varname << "AUX_EXO_LEAD_";
  varname << index;
sebastien's avatar
sebastien committed
265
266
267
268
269
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
270
  catch (AlreadyDeclaredException &e)
sebastien's avatar
sebastien committed
271
272
273
274
275
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

276
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLead : avExoLead), 0, 0, ""));
sebastien's avatar
sebastien committed
277
278
279
280
281

  return symb_id;
}

int
sebastien's avatar
sebastien committed
282
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag) throw (FrozenException)
sebastien's avatar
sebastien committed
283
284
{
  ostringstream varname;
sebastien's avatar
sebastien committed
285
286
287
288
  if (endo)
    varname << "AUX_ENDO_LAG_";
  else
    varname << "AUX_EXO_LAG_";
sebastien's avatar
sebastien committed
289
  varname << orig_symb_id << "_" << -orig_lead_lag;
290

sebastien's avatar
sebastien committed
291
292
293
294
295
  int symb_id;
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
296
  catch (AlreadyDeclaredException &e)
sebastien's avatar
sebastien committed
297
298
299
300
301
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

302
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, ""));
sebastien's avatar
sebastien committed
303
304

  return symb_id;
305
}
306

sebastien's avatar
sebastien committed
307
308
309
310
311
312
int
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
{
  return addLeadAuxiliaryVarInternal(true, index);
}

313
int
sebastien's avatar
sebastien committed
314
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
315
{
sebastien's avatar
sebastien committed
316
  return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag);
317
318
319
}

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

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

int
332
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException)
333
334
335
{
  ostringstream varname;
  int symb_id;
336
337
338
339
340
341
342

  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;

343
344
345
346
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
347
  catch (AlreadyDeclaredException &e)
348
349
350
351
352
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

353
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name));
354
355
356

  return symb_id;
}
sebastien's avatar
sebastien committed
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376

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

377
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
378
379
380
381
382
}

int
SymbolTable::predeterminedNbr() const
{
383
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
384
}
Sébastien Villemot's avatar
Sébastien Villemot committed
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414

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