1 /*
2 * Copyright © 2003-2019 Dynare Team
3 *
4 * This file is part of Dynare.
5 *
6 * Dynare is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * Dynare is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with Dynare. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include <algorithm>
21 #include <sstream>
22 #include <iostream>
23 #include <cassert>
24 #pragma GCC diagnostic push
25 #pragma GCC diagnostic ignored "-Wold-style-cast"
26 #include <boost/algorithm/string/replace.hpp>
27 #pragma GCC diagnostic pop
28 #include <utility>
29
30 #include "SymbolTable.hh"
31
AuxVarInfo(int symb_id_arg,AuxVarType type_arg,int orig_symb_id_arg,int orig_lead_lag_arg,int equation_number_for_multiplier_arg,int information_set_arg,expr_t expr_node_arg,string unary_op_arg)32 AuxVarInfo::AuxVarInfo(int symb_id_arg, AuxVarType type_arg, int orig_symb_id_arg, int orig_lead_lag_arg,
33 int equation_number_for_multiplier_arg, int information_set_arg,
34 expr_t expr_node_arg, string unary_op_arg) :
35 symb_id{symb_id_arg},
36 type{type_arg},
37 orig_symb_id{orig_symb_id_arg},
38 orig_lead_lag{orig_lead_lag_arg},
39 equation_number_for_multiplier{equation_number_for_multiplier_arg},
40 information_set{information_set_arg},
41 expr_node{expr_node_arg},
42 unary_op{move(unary_op_arg)}
43 {
44 }
45
46 int
addSymbol(const string & name,SymbolType type,const string & tex_name,const vector<pair<string,string>> & partition_value)47 SymbolTable::addSymbol(const string &name, SymbolType type, const string &tex_name, const vector<pair<string, string>> &partition_value) noexcept(false)
48 {
49 if (frozen)
50 throw FrozenException();
51
52 if (exists(name))
53 {
54 if (type_table[getID(name)] == type)
55 throw AlreadyDeclaredException(name, true);
56 else
57 throw AlreadyDeclaredException(name, false);
58 }
59
60 string final_tex_name = tex_name;
61 if (final_tex_name.empty())
62 {
63 final_tex_name = name;
64 size_t pos = 0;
65 while ((pos = final_tex_name.find('_', pos)) != string::npos)
66 {
67 final_tex_name.insert(pos, R"(\)");
68 pos += 2;
69 }
70 }
71
72 string final_long_name = name;
73 bool non_long_name_partition_exists = false;
74 for (const auto &it : partition_value)
75 if (it.first == "long_name")
76 final_long_name = it.second;
77 else
78 non_long_name_partition_exists = true;
79
80 int id = symbol_table.size();
81
82 symbol_table[name] = id;
83 type_table.push_back(type);
84 name_table.push_back(name);
85 tex_name_table.push_back(final_tex_name);
86 long_name_table.push_back(final_long_name);
87 if (non_long_name_partition_exists)
88 {
89 map<string, string> pmv;
90 for (const auto &it : partition_value)
91 pmv[it.first] = it.second;
92 partition_value_map[id] = pmv;
93 }
94 return id;
95 }
96
97 int
addSymbol(const string & name,SymbolType type)98 SymbolTable::addSymbol(const string &name, SymbolType type) noexcept(false)
99 {
100 return addSymbol(name, type, "", {});
101 }
102
103 void
freeze()104 SymbolTable::freeze() noexcept(false)
105 {
106 if (frozen)
107 throw FrozenException();
108
109 frozen = true;
110
111 for (int i = 0; i < static_cast<int>(symbol_table.size()); i++)
112 {
113 int tsi;
114 switch (getType(i))
115 {
116 case SymbolType::endogenous:
117 tsi = endo_ids.size();
118 endo_ids.push_back(i);
119 break;
120 case SymbolType::exogenous:
121 tsi = exo_ids.size();
122 exo_ids.push_back(i);
123 break;
124 case SymbolType::exogenousDet:
125 tsi = exo_det_ids.size();
126 exo_det_ids.push_back(i);
127 break;
128 case SymbolType::parameter:
129 tsi = param_ids.size();
130 param_ids.push_back(i);
131 break;
132 default:
133 tsi = -1;
134 break;
135 }
136 type_specific_ids.push_back(tsi);
137 }
138 }
139
140 void
unfreeze()141 SymbolTable::unfreeze()
142 {
143 frozen = false;
144 endo_ids.clear();
145 exo_ids.clear();
146 exo_det_ids.clear();
147 param_ids.clear();
148 type_specific_ids.clear();
149 }
150
151 void
changeType(int id,SymbolType newtype)152 SymbolTable::changeType(int id, SymbolType newtype) noexcept(false)
153 {
154 if (frozen)
155 throw FrozenException();
156
157 validateSymbID(id);
158
159 type_table[id] = newtype;
160 }
161
162 int
getID(SymbolType type,int tsid) const163 SymbolTable::getID(SymbolType type, int tsid) const noexcept(false)
164 {
165 if (!frozen)
166 throw NotYetFrozenException();
167
168 switch (type)
169 {
170 case SymbolType::endogenous:
171 if (tsid < 0 || tsid >= static_cast<int>(endo_ids.size()))
172 throw UnknownTypeSpecificIDException(tsid, type);
173 else
174 return endo_ids[tsid];
175 case SymbolType::exogenous:
176 if (tsid < 0 || tsid >= static_cast<int>(exo_ids.size()))
177 throw UnknownTypeSpecificIDException(tsid, type);
178 else
179 return exo_ids[tsid];
180 case SymbolType::exogenousDet:
181 if (tsid < 0 || tsid >= static_cast<int>(exo_det_ids.size()))
182 throw UnknownTypeSpecificIDException(tsid, type);
183 else
184 return exo_det_ids[tsid];
185 case SymbolType::parameter:
186 if (tsid < 0 || tsid >= static_cast<int>(param_ids.size()))
187 throw UnknownTypeSpecificIDException(tsid, type);
188 else
189 return param_ids[tsid];
190 default:
191 throw UnknownTypeSpecificIDException(tsid, type);
192 }
193 }
194
195 map<string, map<int, string>>
getPartitionsForType(SymbolType st) const196 SymbolTable::getPartitionsForType(SymbolType st) const noexcept(false)
197 {
198 map<string, map<int, string>> partitions;
199 for (const auto &it : partition_value_map)
200 if (getType(it.first) == st)
201 for (const auto &it1 : it.second)
202 {
203 if (partitions.find(it1.first) == partitions.end())
204 partitions[it1.first] = {};
205 partitions[it1.first][it.first] = it1.second;
206 }
207 return partitions;
208 }
209
210 void
writeOutput(ostream & output) const211 SymbolTable::writeOutput(ostream &output) const noexcept(false)
212 {
213 if (!frozen)
214 throw NotYetFrozenException();
215
216 if (exo_nbr() > 0)
217 {
218 output << "M_.exo_names = cell(" << exo_nbr() << ",1);" << endl;
219 output << "M_.exo_names_tex = cell(" << exo_nbr() << ",1);" << endl;
220 output << "M_.exo_names_long = cell(" << exo_nbr() << ",1);" << endl;
221 for (int id = 0; id < exo_nbr(); id++)
222 output << "M_.exo_names(" << id+1 << ") = {'" << getName(exo_ids[id]) << "'};" << endl
223 << "M_.exo_names_tex(" << id+1 << ") = {'" << getTeXName(exo_ids[id]) << "'};" << endl
224 << "M_.exo_names_long(" << id+1 << ") = {'" << getLongName(exo_ids[id]) << "'};" << endl;
225 map<string, map<int, string>> partitions = getPartitionsForType(SymbolType::exogenous);
226 for (auto &partition : partitions)
227 if (partition.first != "long_name")
228 {
229 output << "M_.exo_partitions." << partition.first << " = { ";
230 for (int id = 0; id < exo_nbr(); id++)
231 {
232 output << "'";
233 if (auto it1 = partition.second.find(exo_ids[id]);
234 it1 != partition.second.end())
235 output << it1->second;
236 output << "' ";
237 }
238 output << "};" << endl;
239 if (partition.first == "status")
240 output << "M_ = set_observed_exogenous_variables(M_);" << endl;
241 if (partition.first == "used")
242 output << "M_ = set_exogenous_variables_for_simulation(M_);" << endl;
243 }
244 }
245 else
246 {
247 output << "M_.exo_names = {};" << endl;
248 output << "M_.exo_names_tex = {};" << endl;
249 output << "M_.exo_names_long = {};" << endl;
250 }
251
252 if (exo_det_nbr() > 0)
253 {
254 output << "M_.exo_det_names = cell(" << exo_det_nbr() << ",1);" << endl;
255 output << "M_.exo_det_names_tex = cell(" << exo_det_nbr() << ",1);" << endl;
256 output << "M_.exo_det_names_long = cell(" << exo_det_nbr() << ",1);" << endl;
257 for (int id = 0; id < exo_det_nbr(); id++)
258 output << "M_.exo_det_names(" << id+1 << ") = {'" << getName(exo_det_ids[id]) << "'};" << endl
259 << "M_.exo_det_names_tex(" << id+1 << ") = {'" << getTeXName(exo_det_ids[id]) << "'};" << endl
260 << "M_.exo_det_names_long(" << id+1 << ") = {'" << getLongName(exo_det_ids[id]) << "'};" << endl;
261 output << "M_.exo_det_partitions = struct();" << endl;
262 map<string, map<int, string>> partitions = getPartitionsForType(SymbolType::exogenousDet);
263 for (auto &partition : partitions)
264 if (partition.first != "long_name")
265 {
266 output << "M_.exo_det_partitions." << partition.first << " = { ";
267 for (int id = 0; id < exo_det_nbr(); id++)
268 {
269 output << "'";
270 if (auto it1 = partition.second.find(exo_det_ids[id]);
271 it1 != partition.second.end())
272 output << it1->second;
273 output << "' ";
274 }
275 output << "};" << endl;
276 }
277 }
278
279 if (endo_nbr() > 0)
280 {
281 output << "M_.endo_names = cell(" << endo_nbr() << ",1);" << endl;
282 output << "M_.endo_names_tex = cell(" << endo_nbr() << ",1);" << endl;
283 output << "M_.endo_names_long = cell(" << endo_nbr() << ",1);" << endl;
284 for (int id = 0; id < endo_nbr(); id++)
285 output << "M_.endo_names(" << id+1 << ") = {'" << getName(endo_ids[id]) << "'};" << endl
286 << "M_.endo_names_tex(" << id+1 << ") = {'" << getTeXName(endo_ids[id]) << "'};" << endl
287 << "M_.endo_names_long(" << id+1 << ") = {'" << getLongName(endo_ids[id]) << "'};" << endl;
288 output << "M_.endo_partitions = struct();" << endl;
289 map<string, map<int, string>> partitions = getPartitionsForType(SymbolType::endogenous);
290 for (auto &partition : partitions)
291 if (partition.first != "long_name")
292 {
293 output << "M_.endo_partitions." << partition.first << " = { ";
294 for (int id = 0; id < endo_nbr(); id++)
295 {
296 output << "'";
297 if (auto it1 = partition.second.find(endo_ids[id]);
298 it1 != partition.second.end())
299 output << it1->second;
300 output << "' ";
301 }
302 output << "};" << endl;
303 }
304 }
305
306 if (param_nbr() > 0)
307 {
308 output << "M_.param_names = cell(" << param_nbr() << ",1);" << endl;
309 output << "M_.param_names_tex = cell(" << param_nbr() << ",1);" << endl;
310 output << "M_.param_names_long = cell(" << param_nbr() << ",1);" << endl;
311 for (int id = 0; id < param_nbr(); id++)
312 {
313 output << "M_.param_names(" << id+1 << ") = {'" << getName(param_ids[id]) << "'};" << endl
314 << "M_.param_names_tex(" << id+1 << ") = {'" << getTeXName(param_ids[id]) << "'};" << endl
315 << "M_.param_names_long(" << id+1 << ") = {'" << getLongName(param_ids[id]) << "'};" << endl;
316 if (getName(param_ids[id]) == "dsge_prior_weight")
317 output << "options_.dsge_var = 1;" << endl;
318 }
319 output << "M_.param_partitions = struct();" << endl;
320 map<string, map<int, string>> partitions = getPartitionsForType(SymbolType::parameter);
321 for (auto &partition : partitions)
322 if (partition.first != "long_name")
323 {
324 output << "M_.param_partitions." << partition.first << " = { ";
325 for (int id = 0; id < param_nbr(); id++)
326 {
327 output << "'";
328 if (auto it1 = partition.second.find(param_ids[id]);
329 it1 != partition.second.end())
330 output << it1->second;
331 output << "' ";
332 }
333 output << "};" << endl;
334 }
335 }
336 else
337 {
338 output << "M_.param_names = {};" << endl;
339 output << "M_.param_names_tex = {};" << endl;
340 output << "M_.param_names_long = {};" << endl;
341 }
342
343 output << "M_.exo_det_nbr = " << exo_det_nbr() << ";" << endl
344 << "M_.exo_nbr = " << exo_nbr() << ";" << endl
345 << "M_.endo_nbr = " << endo_nbr() << ";" << endl
346 << "M_.param_nbr = " << param_nbr() << ";" << endl;
347
348 // Write the auxiliary variable table
349 output << "M_.orig_endo_nbr = " << orig_endo_nbr() << ";" << endl;
350 if (aux_vars.size() == 0)
351 output << "M_.aux_vars = [];" << endl;
352 else
353 for (int i = 0; i < static_cast<int>(aux_vars.size()); i++)
354 {
355 output << "M_.aux_vars(" << i+1 << ").endo_index = " << getTypeSpecificID(aux_vars[i].get_symb_id())+1 << ";" << endl
356 << "M_.aux_vars(" << i+1 << ").type = " << aux_vars[i].get_type_id() << ";" << endl;
357 switch (aux_vars[i].get_type())
358 {
359 case AuxVarType::endoLead:
360 case AuxVarType::exoLead:
361 break;
362 case AuxVarType::endoLag:
363 case AuxVarType::exoLag:
364 case AuxVarType::varModel:
365 output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl
366 << "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
367 break;
368 case AuxVarType::unaryOp:
369 if (aux_vars[i].get_orig_symb_id() >= 0)
370 output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl
371 << "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
372 output << "M_.aux_vars(" << i+1 << ").unary_op = '" << aux_vars[i].get_unary_op() << "';" << endl;
373 break;
374 case AuxVarType::multiplier:
375 output << "M_.aux_vars(" << i+1 << ").eq_nbr = " << aux_vars[i].get_equation_number_for_multiplier() + 1 << ";" << endl;
376 break;
377 case AuxVarType::diffForward:
378 output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl;
379 break;
380 case AuxVarType::expectation:
381 break;
382 case AuxVarType::diff:
383 case AuxVarType::diffLag:
384 case AuxVarType::diffLead:
385 if (aux_vars[i].get_orig_symb_id() >= 0)
386 output << "M_.aux_vars(" << i+1 << ").orig_index = " << getTypeSpecificID(aux_vars[i].get_orig_symb_id())+1 << ";" << endl
387 << "M_.aux_vars(" << i+1 << ").orig_lead_lag = " << aux_vars[i].get_orig_lead_lag() << ";" << endl;
388 break;
389 }
390
391 if (expr_t orig_expr = aux_vars[i].get_expr_node();
392 orig_expr)
393 {
394 output << "M_.aux_vars(" << i+1 << ").orig_expr = '";
395 orig_expr->writeJsonOutput(output, {}, {});
396 output << "';" << endl;
397 }
398 }
399
400 if (predeterminedNbr() > 0)
401 {
402 output << "M_.predetermined_variables = [ ";
403 for (int predetermined_variable : predetermined_variables)
404 output << getTypeSpecificID(predetermined_variable)+1 << " ";
405 output << "];" << endl;
406 }
407
408 if (observedVariablesNbr() > 0)
409 {
410 int ic = 1;
411 output << "options_.varobs = cell(" << observedVariablesNbr() << ", 1);" << endl;
412 for (auto it = varobs.begin(); it != varobs.end(); ++it, ic++)
413 output << "options_.varobs(" << ic << ") = {'" << getName(*it) << "'};" << endl;
414
415 output << "options_.varobs_id = [ ";
416 for (int varob : varobs)
417 output << getTypeSpecificID(varob)+1 << " ";
418 output << " ];" << endl;
419 }
420
421 if (observedExogenousVariablesNbr() > 0)
422 {
423 int ic = 1;
424 output << "options_.varexobs = cell(1);" << endl;
425 for (auto it = varexobs.begin(); it != varexobs.end(); ++it, ic++)
426 output << "options_.varexobs(" << ic << ") = {'" << getName(*it) << "'};" << endl;
427
428 output << "options_.varexobs_id = [ ";
429 for (int varexob : varexobs)
430 output << getTypeSpecificID(varexob)+1 << " ";
431 output << " ];" << endl;
432 }
433 }
434
435 int
addLeadAuxiliaryVarInternal(bool endo,int index,expr_t expr_arg)436 SymbolTable::addLeadAuxiliaryVarInternal(bool endo, int index, expr_t expr_arg) noexcept(false)
437 {
438 ostringstream varname;
439 if (endo)
440 varname << "AUX_ENDO_LEAD_";
441 else
442 varname << "AUX_EXO_LEAD_";
443 varname << index;
444 int symb_id;
445 try
446 {
447 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
448 }
449 catch (AlreadyDeclaredException &e)
450 {
451 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
452 exit(EXIT_FAILURE);
453 }
454
455 aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLead : AuxVarType::exoLead), 0, 0, 0, 0, expr_arg, "");
456
457 return symb_id;
458 }
459
460 int
addLagAuxiliaryVarInternal(bool endo,int orig_symb_id,int orig_lead_lag,expr_t expr_arg)461 SymbolTable::addLagAuxiliaryVarInternal(bool endo, int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
462 {
463 ostringstream varname;
464 if (endo)
465 varname << "AUX_ENDO_LAG_";
466 else
467 varname << "AUX_EXO_LAG_";
468 varname << orig_symb_id << "_" << -orig_lead_lag;
469
470 int symb_id;
471 try
472 {
473 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
474 }
475 catch (AlreadyDeclaredException &e)
476 {
477 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
478 exit(EXIT_FAILURE);
479 }
480
481 aux_vars.emplace_back(symb_id, (endo ? AuxVarType::endoLag : AuxVarType::exoLag), orig_symb_id, orig_lead_lag, 0, 0, expr_arg, "");
482
483 return symb_id;
484 }
485
486 int
addEndoLeadAuxiliaryVar(int index,expr_t expr_arg)487 SymbolTable::addEndoLeadAuxiliaryVar(int index, expr_t expr_arg) noexcept(false)
488 {
489 return addLeadAuxiliaryVarInternal(true, index, expr_arg);
490 }
491
492 int
addEndoLagAuxiliaryVar(int orig_symb_id,int orig_lead_lag,expr_t expr_arg)493 SymbolTable::addEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
494 {
495 return addLagAuxiliaryVarInternal(true, orig_symb_id, orig_lead_lag, expr_arg);
496 }
497
498 int
addExoLeadAuxiliaryVar(int index,expr_t expr_arg)499 SymbolTable::addExoLeadAuxiliaryVar(int index, expr_t expr_arg) noexcept(false)
500 {
501 return addLeadAuxiliaryVarInternal(false, index, expr_arg);
502 }
503
504 int
addExoLagAuxiliaryVar(int orig_symb_id,int orig_lead_lag,expr_t expr_arg)505 SymbolTable::addExoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
506 {
507 return addLagAuxiliaryVarInternal(false, orig_symb_id, orig_lead_lag, expr_arg);
508 }
509
510 int
addExpectationAuxiliaryVar(int information_set,int index,expr_t expr_arg)511 SymbolTable::addExpectationAuxiliaryVar(int information_set, int index, expr_t expr_arg) noexcept(false)
512 {
513 ostringstream varname;
514 int symb_id;
515
516 varname << "AUX_EXPECT_" << (information_set < 0 ? "LAG" : "LEAD") << "_"
517 << abs(information_set) << "_" << index;
518
519 try
520 {
521 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
522 }
523 catch (AlreadyDeclaredException &e)
524 {
525 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
526 exit(EXIT_FAILURE);
527 }
528
529 aux_vars.emplace_back(symb_id, AuxVarType::expectation, 0, 0, 0, information_set, expr_arg, "");
530
531 return symb_id;
532 }
533
534 int
addDiffLagAuxiliaryVar(int index,expr_t expr_arg,int orig_symb_id,int orig_lag)535 SymbolTable::addDiffLagAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false)
536 {
537 ostringstream varname;
538 int symb_id;
539
540 varname << "AUX_DIFF_LAG_" << index;
541
542 try
543 {
544 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
545 }
546 catch (AlreadyDeclaredException &e)
547 {
548 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
549 exit(EXIT_FAILURE);
550 }
551
552 aux_vars.emplace_back(symb_id, AuxVarType::diffLag, orig_symb_id, orig_lag, 0, 0, expr_arg, "");
553
554 return symb_id;
555 }
556
557 int
addDiffLeadAuxiliaryVar(int index,expr_t expr_arg,int orig_symb_id,int orig_lead)558 SymbolTable::addDiffLeadAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lead) noexcept(false)
559 {
560 ostringstream varname;
561 int symb_id;
562
563 varname << "AUX_DIFF_LEAD_" << index;
564
565 try
566 {
567 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
568 }
569 catch (AlreadyDeclaredException &e)
570 {
571 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
572 exit(EXIT_FAILURE);
573 }
574
575 aux_vars.emplace_back(symb_id, AuxVarType::diffLead, orig_symb_id, orig_lead, 0, 0, expr_arg, "");
576
577 return symb_id;
578 }
579
580 int
addDiffAuxiliaryVar(int index,expr_t expr_arg,int orig_symb_id,int orig_lag)581 SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg, int orig_symb_id, int orig_lag) noexcept(false)
582 {
583 ostringstream varname;
584 int symb_id;
585
586 varname << "AUX_DIFF_" << index;
587
588 try
589 {
590 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
591 }
592 catch (AlreadyDeclaredException &e)
593 {
594 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
595 exit(EXIT_FAILURE);
596 }
597
598 aux_vars.emplace_back(symb_id, AuxVarType::diff, orig_symb_id, orig_lag, 0, 0, expr_arg, "");
599
600 return symb_id;
601 }
602
603 int
addDiffAuxiliaryVar(int index,expr_t expr_arg)604 SymbolTable::addDiffAuxiliaryVar(int index, expr_t expr_arg) noexcept(false)
605 {
606 return addDiffAuxiliaryVar(index, expr_arg, -1, 0);
607 }
608
609 int
addUnaryOpAuxiliaryVar(int index,expr_t expr_arg,string unary_op,int orig_symb_id,int orig_lag)610 SymbolTable::addUnaryOpAuxiliaryVar(int index, expr_t expr_arg, string unary_op, int orig_symb_id, int orig_lag) noexcept(false)
611 {
612 ostringstream varname;
613 int symb_id;
614
615 varname << "AUX_UOP_" << index;
616 try
617 {
618 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
619 }
620 catch (AlreadyDeclaredException &e)
621 {
622 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
623 exit(EXIT_FAILURE);
624 }
625
626 aux_vars.emplace_back(symb_id, AuxVarType::unaryOp, orig_symb_id, orig_lag, 0, 0, expr_arg, unary_op);
627
628 return symb_id;
629 }
630
631 int
addVarModelEndoLagAuxiliaryVar(int orig_symb_id,int orig_lead_lag,expr_t expr_arg)632 SymbolTable::addVarModelEndoLagAuxiliaryVar(int orig_symb_id, int orig_lead_lag, expr_t expr_arg) noexcept(false)
633 {
634 int symb_id;
635 ostringstream varname;
636 varname << "AUX_VARMODEL_" << orig_symb_id << "_" << -orig_lead_lag;
637
638 try
639 {
640 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
641 }
642 catch (AlreadyDeclaredException &e)
643 {
644 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
645 exit(EXIT_FAILURE);
646 }
647
648 aux_vars.emplace_back(symb_id, AuxVarType::varModel, orig_symb_id, orig_lead_lag, 0, 0, expr_arg, "");
649
650 return symb_id;
651 }
652
653 int
addMultiplierAuxiliaryVar(int index)654 SymbolTable::addMultiplierAuxiliaryVar(int index) noexcept(false)
655 {
656 ostringstream varname;
657 int symb_id;
658 varname << "MULT_" << index+1;
659
660 try
661 {
662 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
663 }
664 catch (AlreadyDeclaredException &e)
665 {
666 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
667 exit(EXIT_FAILURE);
668 }
669
670 aux_vars.emplace_back(symb_id, AuxVarType::multiplier, 0, 0, index, 0, nullptr, "");
671 return symb_id;
672 }
673
674 int
addDiffForwardAuxiliaryVar(int orig_symb_id,expr_t expr_arg)675 SymbolTable::addDiffForwardAuxiliaryVar(int orig_symb_id, expr_t expr_arg) noexcept(false)
676 {
677 ostringstream varname;
678 int symb_id;
679 varname << "AUX_DIFF_FWRD_" << orig_symb_id+1;
680
681 try
682 {
683 symb_id = addSymbol(varname.str(), SymbolType::endogenous);
684 }
685 catch (AlreadyDeclaredException &e)
686 {
687 cerr << "ERROR: you should rename your variable called " << varname.str() << ", this name is internally used by Dynare" << endl;
688 exit(EXIT_FAILURE);
689 }
690
691 aux_vars.emplace_back(symb_id, AuxVarType::diffForward, orig_symb_id, 0, 0, 0, expr_arg, "");
692 return symb_id;
693 }
694
695 int
searchAuxiliaryVars(int orig_symb_id,int orig_lead_lag) const696 SymbolTable::searchAuxiliaryVars(int orig_symb_id, int orig_lead_lag) const noexcept(false)
697 {
698 for (const auto &aux_var : aux_vars)
699 if ((aux_var.get_type() == AuxVarType::endoLag || aux_var.get_type() == AuxVarType::exoLag)
700 && aux_var.get_orig_symb_id() == orig_symb_id && aux_var.get_orig_lead_lag() == orig_lead_lag)
701 return aux_var.get_symb_id();
702 throw SearchFailedException(orig_symb_id, orig_lead_lag);
703 }
704
705 int
getOrigSymbIdForAuxVar(int aux_var_symb_id) const706 SymbolTable::getOrigSymbIdForAuxVar(int aux_var_symb_id) const noexcept(false)
707 {
708 for (const auto &aux_var : aux_vars)
709 if ((aux_var.get_type() == AuxVarType::endoLag
710 || aux_var.get_type() == AuxVarType::exoLag
711 || aux_var.get_type() == AuxVarType::diff
712 || aux_var.get_type() == AuxVarType::diffLag
713 || aux_var.get_type() == AuxVarType::diffLead)
714 && aux_var.get_symb_id() == aux_var_symb_id)
715 return aux_var.get_orig_symb_id();
716 throw UnknownSymbolIDException(aux_var_symb_id);
717 }
718
719 int
getOrigLeadLagForDiffAuxVar(int diff_aux_var_symb_id) const720 SymbolTable::getOrigLeadLagForDiffAuxVar(int diff_aux_var_symb_id) const noexcept(false)
721 {
722 int lag = 0;
723 for (const auto &aux_var : aux_vars)
724 if ((aux_var.get_type() == AuxVarType::diffLag || aux_var.get_type() == AuxVarType::diffLead)
725 && aux_var.get_symb_id() == diff_aux_var_symb_id)
726 lag += 1 + getOrigLeadLagForDiffAuxVar(aux_var.get_orig_symb_id());
727 return lag;
728 }
729
730 int
getOrigSymbIdForDiffAuxVar(int diff_aux_var_symb_id) const731 SymbolTable::getOrigSymbIdForDiffAuxVar(int diff_aux_var_symb_id) const noexcept(false)
732 {
733 int orig_symb_id = -1;
734 for (const auto &aux_var : aux_vars)
735 if (aux_var.get_symb_id() == diff_aux_var_symb_id)
736 if (aux_var.get_type() == AuxVarType::diff)
737 orig_symb_id = diff_aux_var_symb_id;
738 else if (aux_var.get_type() == AuxVarType::diffLag || aux_var.get_type() == AuxVarType::diffLead)
739 orig_symb_id = getOrigSymbIdForDiffAuxVar(aux_var.get_orig_symb_id());
740 return orig_symb_id;
741 }
742
743 expr_t
getAuxiliaryVarsExprNode(int symb_id) const744 SymbolTable::getAuxiliaryVarsExprNode(int symb_id) const noexcept(false)
745 // throw exception if it is a Lagrange multiplier
746 {
747 for (const auto &aux_var : aux_vars)
748 if (aux_var.get_symb_id() == symb_id)
749 if (expr_t expr_node = aux_var.get_expr_node();
750 expr_node)
751 return expr_node;
752 else
753 throw SearchFailedException(symb_id);
754 throw SearchFailedException(symb_id);
755 }
756
757 void
markPredetermined(int symb_id)758 SymbolTable::markPredetermined(int symb_id) noexcept(false)
759 {
760 validateSymbID(symb_id);
761
762 if (frozen)
763 throw FrozenException();
764
765 assert(getType(symb_id) == SymbolType::endogenous);
766
767 predetermined_variables.insert(symb_id);
768 }
769
770 bool
isPredetermined(int symb_id) const771 SymbolTable::isPredetermined(int symb_id) const noexcept(false)
772 {
773 validateSymbID(symb_id);
774 return (predetermined_variables.find(symb_id) != predetermined_variables.end());
775 }
776
777 int
predeterminedNbr() const778 SymbolTable::predeterminedNbr() const
779 {
780 return (predetermined_variables.size());
781 }
782
783 void
addObservedVariable(int symb_id)784 SymbolTable::addObservedVariable(int symb_id) noexcept(false)
785 {
786 validateSymbID(symb_id);
787 assert(getType(symb_id) == SymbolType::endogenous);
788 varobs.push_back(symb_id);
789 }
790
791 int
observedVariablesNbr() const792 SymbolTable::observedVariablesNbr() const
793 {
794 return static_cast<int>(varobs.size());
795 }
796
797 bool
isObservedVariable(int symb_id) const798 SymbolTable::isObservedVariable(int symb_id) const
799 {
800 return find(varobs.begin(), varobs.end(), symb_id) != varobs.end();
801 }
802
803 int
getObservedVariableIndex(int symb_id) const804 SymbolTable::getObservedVariableIndex(int symb_id) const
805 {
806 auto it = find(varobs.begin(), varobs.end(), symb_id);
807 assert(it != varobs.end());
808 return static_cast<int>(it - varobs.begin());
809 }
810
811 void
addObservedExogenousVariable(int symb_id)812 SymbolTable::addObservedExogenousVariable(int symb_id) noexcept(false)
813 {
814 validateSymbID(symb_id);
815 assert(getType(symb_id) != SymbolType::endogenous);
816 varexobs.push_back(symb_id);
817 }
818
819 int
observedExogenousVariablesNbr() const820 SymbolTable::observedExogenousVariablesNbr() const
821 {
822 return static_cast<int>(varexobs.size());
823 }
824
825 bool
isObservedExogenousVariable(int symb_id) const826 SymbolTable::isObservedExogenousVariable(int symb_id) const
827 {
828 return find(varexobs.begin(), varexobs.end(), symb_id) != varexobs.end();
829 }
830
831 int
getObservedExogenousVariableIndex(int symb_id) const832 SymbolTable::getObservedExogenousVariableIndex(int symb_id) const
833 {
834 auto it = find(varexobs.begin(), varexobs.end(), symb_id);
835 assert(it != varexobs.end());
836 return static_cast<int>(it - varexobs.begin());
837 }
838
839 vector <int>
getTrendVarIds() const840 SymbolTable::getTrendVarIds() const
841 {
842 vector <int> trendVars;
843 for (const auto &it : symbol_table)
844 if (getType(it.second) == SymbolType::trend || getType(it.second) == SymbolType::logTrend)
845 trendVars.push_back(it.second);
846 return trendVars;
847 }
848
849 set<int>
getExogenous() const850 SymbolTable::getExogenous() const
851 {
852 set <int> exogs;
853 for (const auto &it : symbol_table)
854 if (getType(it.second) == SymbolType::exogenous)
855 exogs.insert(it.second);
856 return exogs;
857 }
858
859 set<int>
getObservedExogenous() const860 SymbolTable::getObservedExogenous() const
861 {
862 set <int> oexogs;
863 for (const auto &it : symbol_table)
864 if (getType(it.second) == SymbolType::exogenous)
865 if (isObservedExogenousVariable(it.second))
866 oexogs.insert(it.second);
867 return oexogs;
868 }
869
870 set<int>
getEndogenous() const871 SymbolTable::getEndogenous() const
872 {
873 set <int> endogs;
874 for (const auto &it : symbol_table)
875 if (getType(it.second) == SymbolType::endogenous)
876 endogs.insert(it.second);
877 return endogs;
878 }
879
880 bool
isAuxiliaryVariable(int symb_id) const881 SymbolTable::isAuxiliaryVariable(int symb_id) const
882 {
883 for (const auto &aux_var : aux_vars)
884 if (aux_var.get_symb_id() == symb_id)
885 return true;
886 return false;
887 }
888
889 bool
isAuxiliaryVariableButNotMultiplier(int symb_id) const890 SymbolTable::isAuxiliaryVariableButNotMultiplier(int symb_id) const
891 {
892 for (const auto &aux_var : aux_vars)
893 if (aux_var.get_symb_id() == symb_id && aux_var.get_type() != AuxVarType::multiplier)
894 return true;
895 return false;
896 }
897
898 bool
isDiffAuxiliaryVariable(int symb_id) const899 SymbolTable::isDiffAuxiliaryVariable(int symb_id) const
900 {
901 for (const auto &aux_var : aux_vars)
902 if (aux_var.get_symb_id() == symb_id
903 && (aux_var.get_type() == AuxVarType::diff
904 || aux_var.get_type() == AuxVarType::diffLag
905 || aux_var.get_type() == AuxVarType::diffLead))
906 return true;
907 return false;
908 }
909
910 set<int>
getOrigEndogenous() const911 SymbolTable::getOrigEndogenous() const
912 {
913 set <int> origendogs;
914 for (const auto &it : symbol_table)
915 if (getType(it.second) == SymbolType::endogenous && !isAuxiliaryVariable(it.second))
916 origendogs.insert(it.second);
917 return origendogs;
918 }
919
920 void
writeJuliaOutput(ostream & output) const921 SymbolTable::writeJuliaOutput(ostream &output) const noexcept(false)
922 {
923 if (!frozen)
924 throw NotYetFrozenException();
925
926 output << "# Endogenous Variables" << endl
927 << "model_.endo = [" << endl;
928 if (endo_nbr() > 0)
929 for (int id = 0; id < endo_nbr(); id++)
930 output << R"( DynareModel.Endo(")"
931 << getName(endo_ids[id]) << R"(", raw")"
932 << getTeXName(endo_ids[id]) << R"(", ")"
933 << getLongName(endo_ids[id]) << R"("))" << endl;
934 output << " ]" << endl;
935 output << "model_.endo_nbr = " << endo_nbr() << ";" << endl;
936
937 output << "# Exogenous Variables" << endl
938 << "model_.exo = [" << endl;
939 if (exo_nbr() > 0)
940 for (int id = 0; id < exo_nbr(); id++)
941 output << R"( DynareModel.Exo(")"
942 << getName(exo_ids[id]) << R"(", raw")"
943 << getTeXName(exo_ids[id]) << R"(", ")"
944 << getLongName(exo_ids[id]) << R"("))" << endl;
945 output << " ]" << endl;
946 output << "model_.exo_nbr = " << exo_nbr() << ";" << endl;
947
948 if (exo_det_nbr() > 0)
949 {
950 output << "# Exogenous Deterministic Variables" << endl
951 << "model_.exo_det = [" << endl;
952 if (exo_det_nbr() > 0)
953 for (int id = 0; id < exo_det_nbr(); id++)
954 output << R"( DynareModel.ExoDet(")"
955 << getName(exo_det_ids[id]) << R"(", raw")"
956 << getTeXName(exo_det_ids[id]) << R"(", ")"
957 << getLongName(exo_det_ids[id]) << R"("))" << endl;
958 output << " ]" << endl;
959 output << "model_.exo_det_nbr = " << exo_det_nbr() << ";" << endl;
960 }
961
962 output << "# Parameters" << endl
963 << "model_.param = [" << endl;
964 if (param_nbr() > 0)
965 for (int id = 0; id < param_nbr(); id++)
966 output << R"( DynareModel.Param(")"
967 << getName(param_ids[id]) << R"(", raw")"
968 << getTeXName(param_ids[id]) << R"(", ")"
969 << getLongName(param_ids[id]) << R"("))" << endl;
970 output << " ]" << endl;
971 output << "model_.param_nbr = " << param_nbr() << ";" << endl;
972
973 output << "model_.orig_endo_nbr = " << orig_endo_nbr() << endl;
974
975 if (aux_vars.size() > 0)
976 {
977 output << "# Auxiliary Variables" << endl
978 << "model_.aux_vars = [" << endl;
979 for (const auto &aux_var : aux_vars)
980 {
981 output << " DynareModel.AuxVars("
982 << getTypeSpecificID(aux_var.get_symb_id()) + 1 << ", "
983 << aux_var.get_type_id() << ", ";
984 switch (aux_var.get_type())
985 {
986 case AuxVarType::endoLead:
987 case AuxVarType::exoLead:
988 case AuxVarType::endoLag:
989 case AuxVarType::exoLag:
990 case AuxVarType::varModel:
991 output << getTypeSpecificID(aux_var.get_orig_symb_id()) + 1 << ", "
992 << aux_var.get_orig_lead_lag() << ", typemin(Int), string(), string()";
993 break;
994 case AuxVarType::unaryOp:
995 if (aux_var.get_orig_symb_id() >= 0)
996 output << getTypeSpecificID(aux_var.get_orig_symb_id()) + 1 << ", " << aux_var.get_orig_lead_lag();
997 else
998 output << "typemin(Int), typemin(Int)";
999 output << ", typemin(Int), string(), "
1000 << R"(")" << aux_var.get_unary_op() << R"(")" << endl;
1001 break;
1002 case AuxVarType::diff:
1003 case AuxVarType::diffLag:
1004 case AuxVarType::diffLead:
1005 if (aux_var.get_orig_symb_id() >= 0)
1006 output << getTypeSpecificID(aux_var.get_orig_symb_id()) + 1 << ", "
1007 << aux_var.get_orig_lead_lag() << ", typemin(Int), string(), string()";
1008 break;
1009 case AuxVarType::multiplier:
1010 output << "typemin(Int), typemin(Int), " << aux_var.get_equation_number_for_multiplier() + 1
1011 << ", string(), string()";
1012 break;
1013 case AuxVarType::diffForward:
1014 output << getTypeSpecificID(aux_var.get_orig_symb_id())+1 << ", typemin(Int), typemin(Int), string(), string()";
1015 break;
1016 case AuxVarType::expectation:
1017 output << R"(typemin(Int), typemin(Int), typemin(Int), "\mathbb{E}_{t)"
1018 << (aux_var.get_information_set() < 0 ? "" : "+")
1019 << aux_var.get_information_set() << "}(";
1020 aux_var.get_expr_node()->writeOutput(output, ExprNodeOutputType::latexDynamicModel);
1021 output << R"lit()")lit";
1022 break;
1023 default:
1024 output << " typemin(Int), typemin(Int), typemin(Int), string(), string()";
1025 }
1026 output << ")" << endl;
1027 }
1028 output << "]" << endl;
1029 }
1030
1031 if (predeterminedNbr() > 0)
1032 {
1033 output << "# Predetermined Variables" << endl
1034 << "model_.pred_vars = [ " << endl;
1035 for (int predetermined_variable : predetermined_variables)
1036 output << " DynareModel.PredVars("
1037 << getTypeSpecificID(predetermined_variable)+1 << ")" << endl;
1038 output << " ]" << endl;
1039 }
1040
1041 if (observedVariablesNbr() > 0)
1042 {
1043 output << "# Observed Variables" << endl
1044 << "options_.obs_vars = [" << endl;
1045 for (int varob : varobs)
1046 output << " DynareModel.ObsVars("
1047 << getTypeSpecificID(varob)+1 << ")" << endl;
1048 output << " ]" << endl;
1049 }
1050 }
1051
1052 void
writeJsonOutput(ostream & output) const1053 SymbolTable::writeJsonOutput(ostream &output) const
1054 {
1055 output << R"("endogenous": )";
1056 writeJsonVarVector(output, endo_ids);
1057
1058 output << R"(, "exogenous":)";
1059 writeJsonVarVector(output, exo_ids);
1060
1061 output << R"(, "exogenous_deterministic": )";
1062 writeJsonVarVector(output, exo_det_ids);
1063
1064 output << R"(, "parameters": )";
1065 writeJsonVarVector(output, param_ids);
1066 }
1067
1068 void
writeJsonVarVector(ostream & output,const vector<int> & varvec) const1069 SymbolTable::writeJsonVarVector(ostream &output, const vector<int> &varvec) const
1070 {
1071 output << "[";
1072 for (size_t i = 0; i < varvec.size(); i++)
1073 {
1074 if (i != 0)
1075 output << ", ";
1076 output << "{"
1077 << R"("name":")" << getName(varvec[i]) << R"(", )"
1078 << R"("texName":")" << boost::replace_all_copy(getTeXName(varvec[i]), R"(\)", R"(\\)") << R"(", )"
1079 << R"("longName":")" << boost::replace_all_copy(getLongName(varvec[i]), R"(\)", R"(\\)") << R"("})"
1080 << endl;
1081 }
1082 output << "]" << endl;
1083 }
1084
1085 int
getUltimateOrigSymbID(int symb_id) const1086 SymbolTable::getUltimateOrigSymbID(int symb_id) const
1087 {
1088 while (isAuxiliaryVariable(symb_id))
1089 try
1090 {
1091 symb_id = getOrigSymbIdForAuxVar(symb_id);
1092 }
1093 catch (UnknownSymbolIDException &)
1094 {
1095 break;
1096 }
1097 return symb_id;
1098 }
1099
1100 int
getEquationNumberForMultiplier(int symb_id) const1101 SymbolTable::getEquationNumberForMultiplier(int symb_id) const
1102 {
1103 for (const auto &aux_var : aux_vars)
1104 if (aux_var.get_symb_id() == symb_id && aux_var.get_type() == AuxVarType::multiplier)
1105 return aux_var.get_equation_number_for_multiplier();
1106 return -1;
1107 }
1108