SymbolTable.cc 12.4 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
213
  output << "M_.orig_endo_nbr = " << orig_endo_nbr() << ";" << endl;
sebastien's avatar
sebastien committed
214
215
216
  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

  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;
253
254
255
256
257
258

      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
259
    }
sebastien's avatar
sebastien committed
260
261
262
}

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

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

  return symb_id;
}

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

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

308
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, ""));
sebastien's avatar
sebastien committed
309
310

  return symb_id;
311
}
312

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

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

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

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

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

  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;

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

359
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name));
360
361
362

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

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

383
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
384
385
386
387
388
}

int
SymbolTable::predeterminedNbr() const
{
389
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
390
}
Sébastien Villemot's avatar
Sébastien Villemot committed
391
392
393
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

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