SymbolTable.cc 11.3 KB
Newer Older
sebastien's avatar
sebastien committed
1
/*
sebastien's avatar
sebastien committed
2
 * Copyright (C) 2003-2009 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
  output << "M_.Sigma_e = zeros(" << exo_nbr() << ", " << exo_nbr() << ");" << endl;
sebastien's avatar
sebastien committed
213
214

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

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

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

270
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLead : avExoLead), 0, 0, ""));
sebastien's avatar
sebastien committed
271
272
273
274
275

  return symb_id;
}

int
sebastien's avatar
sebastien committed
276
SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag) throw (FrozenException)
sebastien's avatar
sebastien committed
277
278
{
  ostringstream varname;
sebastien's avatar
sebastien committed
279
280
281
282
  if (endo)
    varname << "AUX_ENDO_LAG_";
  else
    varname << "AUX_EXO_LAG_";
sebastien's avatar
sebastien committed
283
  varname << orig_symb_id << "_" << -orig_lead_lag;
284

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

296
  aux_vars.push_back(AuxVarInfo(symb_id, (endo ? avEndoLag : avExoLag), orig_symb_id, orig_lead_lag, ""));
sebastien's avatar
sebastien committed
297
298

  return symb_id;
299
}
300

sebastien's avatar
sebastien committed
301
302
303
304
305
306
int
SymbolTable::addEndoLeadAuxiliaryVar(int index) throw (FrozenException)
{
  return addLeadAuxiliaryVarInternal(true, index);
}

307
int
sebastien's avatar
sebastien committed
308
SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag) throw (FrozenException)
309
{
sebastien's avatar
sebastien committed
310
  return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag);
311
312
313
}

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

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

int
326
SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, const string &information_set_name) throw (FrozenException)
327
328
329
{
  ostringstream varname;
  int symb_id;
330
331
332
333
334
335
336

  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;

337
338
339
340
  try
    {
      symb_id = addSymbol(varname.str(), eEndogenous);
    }
341
  catch (AlreadyDeclaredException &e)
342
343
344
345
346
    {
      cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
      exit(EXIT_FAILURE);
    }

347
  aux_vars.push_back(AuxVarInfo(symb_id, (information_set_name.empty() ? avExpectation : avExpectationRIS), 0, 0, information_set_name));
348
349
350

  return symb_id;
}
sebastien's avatar
sebastien committed
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370

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

371
  return (predetermined_variables.find(symb_id) != predetermined_variables.end());
sebastien's avatar
sebastien committed
372
373
374
375
376
}

int
SymbolTable::predeterminedNbr() const
{
377
  return (predetermined_variables.size());
sebastien's avatar
sebastien committed
378
}