ComputingTasks.cc 163 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2018 Dynare Team
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 <cassert>
21
22
23
24
25
26
27
28
#include <iostream>
#include <sstream>

using namespace std;

#include "ComputingTasks.hh"
#include "Statement.hh"

29
30
31
#include <boost/algorithm/string/trim.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/tokenizer.hpp>
32
#include <utility>
33

34
35
SteadyStatement::SteadyStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
36
37
38
{
}

39
void
40
SteadyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
41
{
42
  mod_file_struct.steady_present = true;
43
44
}

45
void
46
SteadyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
47
48
{
  options_list.writeOutput(output);
49
  output << "steady;" << endl;
50
51
}

52
53
54
55
56
57
58
59
60
61
62
63
void
SteadyStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"steady\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

64
65
CheckStatement::CheckStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
66
67
68
69
{
}

void
70
CheckStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
71
72
{
  options_list.writeOutput(output);
73
  output << "oo_.dr.eigval = check(M_,options_,oo_);" << endl;
74
75
76
}

void
77
CheckStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
78
79
80
81
{
  mod_file_struct.check_present = true;
}

82
83
84
85
86
87
88
89
90
91
92
93
void
CheckStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"check\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

94
95
ModelInfoStatement::ModelInfoStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
96
97
98
{
}

99
void
100
ModelInfoStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
101
{
ferhat's avatar
ferhat committed
102
  //mod_file_struct.model_info_present = true;
103
104
}

105
void
106
ModelInfoStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
107
108
{
  options_list.writeOutput(output);
109
  output << "model_info();" << endl;
110
111
}

112
113
114
115
116
117
118
119
120
121
122
123
void
ModelInfoStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"model_info\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

124
125
SimulStatement::SimulStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
126
127
128
129
{
}

void
130
SimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
131
{
132
  mod_file_struct.perfect_foresight_solver_present = true;
133
134
135
}

void
136
SimulStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
137
138
{
  options_list.writeOutput(output);
139
140
141
142
  output << "perfect_foresight_setup;" << endl
         << "perfect_foresight_solver;" << endl;
}

143
144
145
146
147
148
149
150
151
152
153
154
void
SimulStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"simul\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

155
156
PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
157
158
159
160
{
}

void
161
PerfectForesightSetupStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
162
163
164
165
166
{
  options_list.writeOutput(output);
  output << "perfect_foresight_setup;" << endl;
}

167
168
169
170
171
172
173
174
175
176
177
178
void
PerfectForesightSetupStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"perfect_foresight_setup\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

179
180
PerfectForesightSolverStatement::PerfectForesightSolverStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
181
182
183
184
185
186
187
{
}

void
PerfectForesightSolverStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
  mod_file_struct.perfect_foresight_solver_present = true;
188
  // Fill in option_occbin of mod_file_struct
Houtan Bastani's avatar
Houtan Bastani committed
189
  if (options_list.num_options.find("occbin") != options_list.num_options.end())
190
    mod_file_struct.occbin_option = true;
191
192
193
}

void
194
PerfectForesightSolverStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
195
196
197
{
  options_list.writeOutput(output);
  output << "perfect_foresight_solver;" << endl;
198
199
}

200
201
202
203
204
205
206
207
208
209
210
211
void
PerfectForesightSolverStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"perfect_foresight_solver\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

212
PriorPosteriorFunctionStatement::PriorPosteriorFunctionStatement(const bool prior_func_arg,
213
                                                                 OptionsList options_list_arg) :
214
  prior_func(prior_func_arg),
215
  options_list(move(options_list_arg))
216
217
218
219
220
221
{
}

void
PriorPosteriorFunctionStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
222
  auto it2 = options_list.string_options.find("function");
223
  if (it2 == options_list.string_options.end() || it2->second.empty())
224
225
226
227
228
    {
      cerr << "ERROR: both the prior_function and posterior_function commands require the 'function' argument"
           << endl;
      exit(EXIT_FAILURE);
    }
229
230
231
232
233
}

void
PriorPosteriorFunctionStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
234
  options_list.writeOutput(output);
235
  string type = "posterior";
236
  if (prior_func)
237
    type = "prior";
238
239

  output << "oo_ = execute_prior_posterior_function("
240
         << "'" << options_list.string_options.find("function")->second << "', "
241
242
243
244
         << "M_, options_, oo_, estim_params_, bayestopt_, dataset_, dataset_info, "
         << "'" << type << "');" << endl;
}

245
246
247
248
249
void
PriorPosteriorFunctionStatement::writeJsonOutput(ostream &output) const
{
  string type = "posterior";
  if (prior_func)
Stéphane Adjemian's avatar
Stéphane Adjemian committed
250
    type = "prior";
251
252
253
254
255
256
257
258
259
  output << "{\"statementName\": \"prior_posterior_function\", \"type\": \"" << type << "\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

260
PacModelStatement::PacModelStatement(string name_arg,
261
                                     string aux_model_name_arg,
262
263
                                     string discount_arg,
                                     string growth_arg,
Houtan Bastani's avatar
Houtan Bastani committed
264
                                     const SymbolTable &symbol_table_arg) :
265
  name{move(name_arg)},
266
  aux_model_name{move(aux_model_name_arg)},
267
268
269
  discount{move(discount_arg)},
  growth{move(growth_arg)},
  symbol_table{symbol_table_arg}
Houtan Bastani's avatar
Houtan Bastani committed
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
{
}

void
PacModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
  mod_file_struct.pac_params.insert(symbol_table.getID(discount));
  if (!growth.empty())
    mod_file_struct.pac_params.insert(symbol_table.getID(growth));
}

void
PacModelStatement::fillUndiffedLHS(vector<int> &lhs_arg)
{
  lhs = lhs_arg;
}

void
PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
290
  output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
291
292
293
294
295
296
297
298
         << "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;

  if (!growth.empty())
    {
      output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(growth) + 1 << ";" << endl
             << "M_.pac." << name << ".growth_type = ";
      switch(symbol_table.getType(growth))
        {
299
        case SymbolType::endogenous:
Houtan Bastani's avatar
Houtan Bastani committed
300
301
          output << "'endogenous';" << endl;
          break;
302
        case SymbolType::exogenous:
Houtan Bastani's avatar
Houtan Bastani committed
303
304
          output << "'exogenous';" << endl;
          break;
305
        case SymbolType::parameter:
Houtan Bastani's avatar
Houtan Bastani committed
306
307
308
309
310
311
312
313
314
          output << "'parameter';" << endl;
          break;
        default:
          cerr << "pac_model: error encountered in growth type" << endl;
          exit(EXIT_FAILURE);
        }
    }

  output << "M_.pac." << name << ".lhs = [";
315
  for (auto it = lhs.begin(); it !=lhs.end(); it++)
Houtan Bastani's avatar
Houtan Bastani committed
316
317
318
319
320
    {
      if (it != lhs.begin())
        output << " ";
      output << *it + 1;
    }
321
322
  output << "];" << endl;
  /*
Houtan Bastani's avatar
Houtan Bastani committed
323
         << "M_.pac." << name << ".undiff_eqtags = {";
324
  for (auto it = undiff.begin(); it != undiff.end(); it++)
Houtan Bastani's avatar
Houtan Bastani committed
325
326
327
328
329
330
331
    {
      if (it != undiff.begin())
        output << "; ";
      output << "'" << it->first << "'";
    }
  output << "};" << endl
         << "M_.pac." << name << ".undiff_num = [";
332
  for (auto it = undiff.begin(); it != undiff.end(); it++)
Houtan Bastani's avatar
Houtan Bastani committed
333
334
335
336
337
    {
      if (it != undiff.begin())
        output << " ";
      output << it->second;
    }
Houtan Bastani's avatar
Houtan Bastani committed
338
  output << "];" << endl;
339
  */
Houtan Bastani's avatar
Houtan Bastani committed
340
341
342
343
344
345
346
}

void
PacModelStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"pac_model\","
         << "\"model_name\": \"" << name << "\","
347
         << "\"auxiliary_model_name\": \"" << aux_model_name << "\","
Houtan Bastani's avatar
Houtan Bastani committed
348
349
350
351
352
353
354
355
356
         << "\"discount_index\": " << symbol_table.getTypeSpecificID(discount) + 1;

  if (!growth.empty())
    {
      output << ","
             << "\"growth_index\": " << symbol_table.getTypeSpecificID(growth) + 1 << ","
             << "\"growth_type\": ";
      switch(symbol_table.getType(growth))
        {
357
        case SymbolType::endogenous:
Houtan Bastani's avatar
Houtan Bastani committed
358
359
          output << "\"endogenous\"" << endl;
          break;
360
        case SymbolType::exogenous:
Houtan Bastani's avatar
Houtan Bastani committed
361
362
          output << "\"exogenous\"" << endl;
          break;
363
        case SymbolType::parameter:
Houtan Bastani's avatar
Houtan Bastani committed
364
365
366
367
368
369
370
371
372
373
          output << "\"parameter\"" << endl;
          break;
        default:
          cerr << "pac_model: error encountered in growth type" << endl;
          exit(EXIT_FAILURE);
        }
    }
  output << "}";
}

374
375
tuple<string, string, int>
PacModelStatement::getPacModelInfoForPacExpectation() const
Houtan Bastani's avatar
Houtan Bastani committed
376
377
378
379
{
  int growth_symb_id = -1;
  if (!growth.empty())
    growth_symb_id = symbol_table.getID(growth);
380
  return { name, aux_model_name, growth_symb_id };
Houtan Bastani's avatar
Houtan Bastani committed
381
382
}

383
384
VarEstimationStatement::VarEstimationStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
385
386
387
{
}

388
389
390
void
VarEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
391
  auto it = options_list.string_options.find("var_estimation.model_name");
392
393
394
395
396
397
398
  if (it == options_list.string_options.end())
    {
      cerr << "ERROR: You must provide the model name to the var_estimation statement." << endl;
      exit(EXIT_FAILURE);
    }
}

399
400
401
void
VarEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
402
403
  options_list.writeOutput(output);
  output << "oo_ = var_estimation(M_, options_, oo_);" << endl;
404
405
}

406
407
VarRestrictionsStatement::VarRestrictionsStatement(string var_model_name_arg,
                                                   map<string, vector<string>> var_map_arg,
408
                                                   map<int, map<int, SymbolList>> exclusion_restrictions_arg,
409
410
411
                                                   equation_restrictions_t equation_restrictions_arg,
                                                   crossequation_restrictions_t crossequation_restrictions_arg,
                                                   map<pair<int, int>, double> covariance_number_restriction_arg,
412
                                                   map<pair<int, int>, pair<int, int>> covariance_pair_restriction_arg,
413
                                                   const SymbolTable &symbol_table_arg) :
414
415
  var_model_name{move(var_model_name_arg)},
  var_map{move(var_map_arg)},
416
417
418
419
420
  exclusion_restrictions(move(exclusion_restrictions_arg)),
  equation_restrictions(move(equation_restrictions_arg)),
  crossequation_restrictions(move(crossequation_restrictions_arg)),
  covariance_number_restriction(move(covariance_number_restriction_arg)),
  covariance_pair_restriction(move(covariance_pair_restriction_arg)),
421
  symbol_table(symbol_table_arg)
422
423
424
{
}

425
426
427
428
429
int
VarRestrictionsStatement::findIdxInVector(const vector<string> &vecvars, const string &var) const
{
  int idx = 0;
  bool setflag = false;
430
  for (auto itvs = vecvars.begin();
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
       itvs != vecvars.end(); itvs++, idx++)
    if (*itvs == var)
      {
        setflag = true;
        break;
      }

  if (!setflag)
    {
      cerr << "ERROR: you are imposing an exclusion restriction on an equation or variable "
           << var << " that is not contained in VAR " << var_model_name;
      exit(EXIT_FAILURE);
    }
  return idx;
}

447
448
449
void
VarRestrictionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
450
  auto itvs = var_map.find(var_model_name);
451
452
453
454
455
456
457
458
  if (itvs == var_map.end())
    {
      cerr << "ERROR: you are imposing restrictions on a VAR named " << var_model_name
           << " but this VAR has not been declared via thevar_model statement." << endl;
      exit(EXIT_FAILURE);
    }
  vector<string> vars = itvs->second;

459
  string Mstr("M_.var." + var_model_name + ".restrictions.");
460
  int nrestrictions = 0;
461
462
463

  // Exclusion Restrictions
  int idx = 1;
464
  for (auto it = exclusion_restrictions.begin();
465
466
       it != exclusion_restrictions.end(); it++, idx++)
    {
Houtan Bastani's avatar
Houtan Bastani committed
467
      output << Mstr << "exclusion_restrictions{" << idx<< "}.lag = "
468
             << it->first << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
469
             << Mstr << "exclusion_restrictions{" << idx << "}.restrictions = [";
470
      for (auto it1 = it->second.begin();
471
472
473
474
           it1 != it->second.end(); it1++)
        {
          if (it1 != it->second.begin())
            output << " ";
475
476
477
478
479
480
481
482

          output << "struct('eq', " << findIdxInVector(vars, symbol_table.getName(it1->first)) + 1
                 << ", 'vars', [";
          vector<string> excvars = it1->second.getSymbols();
          for (vector<string>::const_iterator itvs1 = excvars.begin();
               itvs1 != excvars.end(); itvs1++)
            output << findIdxInVector(vars, *itvs1) + 1 << " ";
          output << "])";
483
          nrestrictions += it1->second.getSize();
484
485
486
487
488
489
        }
      output << "];" << endl;
    }

  // Equation Restrictions
  idx = 1;
490
  for (auto it = equation_restrictions.begin();
491
       it != equation_restrictions.end(); it++, idx++, nrestrictions++)
492
    {
493
494
      output << Mstr << "equation_restriction{" << idx << "}.eq = '"
             << symbol_table.getName(it->first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
495
             << Mstr << "equation_restriction{" << idx << "}.val = "
496
497
498
             << it->second.second << ";" << endl;

      var_restriction_eq_crosseq_t ls = it->second.first.first;
499
500
      output << Mstr << "equation_restriction{" << idx << "}.ls = '"
             << symbol_table.getName(ls.first.first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
501
             << Mstr << "equation_restriction{" << idx << "}.lslag = "
502
             << ls.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
503
             << Mstr << "equation_restriction{" << idx << "}.lscoeff = ";
504
505
506
507
508
509
      ls.second->writeOutput(output);
      output << ";" << endl;

      var_restriction_eq_crosseq_t rs = it->second.first.second;
      if (rs.first.first >= 0)
        {
510
511
          output << Mstr << "equation_restriction{" << idx << "}.rs = '"
                 << symbol_table.getName(rs.first.first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
512
                 << Mstr << "equation_restriction{" << idx << "}.rslag = "
513
                 << rs.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
514
                 << Mstr << "equation_restriction{" << idx << "}.rscoeff = ";
515
516
517
518
519
520
521
          rs.second->writeOutput(output);
          output << ";" << endl;
        }
    }

  // Cross Equation Restrictions
  idx = 1;
522
  for (auto it = crossequation_restrictions.begin();
523
       it != crossequation_restrictions.end(); it++, idx++, nrestrictions++)
524
    {
525
526
      output << Mstr << "crossequation_restriction{" << idx << "}.val = "
             << it->second << ";" << endl;
527

528
      var_restriction_eq_crosseq_t ls = it->first.first;
529
530
531
532
      output << Mstr << "crossequation_restriction{" << idx << "}.lseq = "
             << findIdxInVector(vars, symbol_table.getName(ls.first.first)) + 1 << ";" << endl
             << Mstr << "crossequation_restriction{" << idx << "}.lsvar = "
             << findIdxInVector(vars, symbol_table.getName(ls.first.second.first)) + 1 << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
533
             << Mstr << "crossequation_restriction{" << idx << "}.lslag = "
534
             << ls.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
535
             << Mstr << "crossequation_restriction{" << idx << "}.lscoeff = ";
536
537
538
      ls.second->writeOutput(output);
      output << ";" << endl;

539
      var_restriction_eq_crosseq_t rs = it->first.second;
540
541
      if (rs.first.first >= 0)
        {
542
543
544
545
          output << Mstr << "crossequation_restriction{" << idx << "}.rseq = "
                 << findIdxInVector(vars, symbol_table.getName(rs.first.first)) + 1 << ";" << endl
                 << Mstr << "crossequation_restriction{" << idx << "}.rsvar = "
                 << findIdxInVector(vars, symbol_table.getName(rs.first.second.first)) + 1 << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
546
                 << Mstr << "crossequation_restriction{" << idx << "}.rslag = "
547
                 << rs.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
548
                 << Mstr << "crossequation_restriction{" << idx << "}.rscoeff = ";
549
550
551
552
553
554
555
          rs.second->writeOutput(output);
          output << ";" << endl;
        }
    }

  // Covariance Const Restrictions
  idx = 1;
556
  for (auto it = covariance_number_restriction.begin();
557
       it != covariance_number_restriction.end(); it++, idx++)
558
559
560
561
    output << Mstr << "covariance_const_restriction{" << idx << "}.var1 = '"
           << symbol_table.getName(it->first.first) << "';" << endl
           << Mstr << "covariance_const_restriction{" << idx << "}.var2 = '"
           << symbol_table.getName(it->first.second) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
562
           << Mstr << "covariance_const_restriction{" << idx << "}.val = "
563
564
565
566
           << it->second << ";" << endl;

  // Covariance Pair Restrictions
  idx = 1;
567
  for (auto it = covariance_pair_restriction.begin();
568
       it != covariance_pair_restriction.end(); it++, idx++)
569
570
571
572
573
574
575
576
577
578
    output << Mstr << "covariance_pair_restriction{" << idx << "}.var11 = '"
           << symbol_table.getName(it->first.first) << "';" << endl
           << Mstr << "covariance_pair_restriction{" << idx << "}.var12 = '"
           << symbol_table.getName(it->first.second) << "';" << endl
           << Mstr << "covariance_pair_restriction{" << idx << "}.var21 = '"
           << symbol_table.getName(it->second.first) << "';" << endl
           << Mstr << "covariance_pair_restriction{" << idx << "}.var22 = '"
           << symbol_table.getName(it->second.second) << "';" << endl;

  output << Mstr << "N = " << nrestrictions << ";" << endl;
579
580
}

581
582
583
584
StochSimulStatement::StochSimulStatement(SymbolList symbol_list_arg,
                                         OptionsList options_list_arg) :
  symbol_list(move(symbol_list_arg)),
  options_list(move(options_list_arg))
585
586
587
588
{
}

void
589
StochSimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
590
{
sebastien's avatar
sebastien committed
591
  mod_file_struct.stoch_simul_present = true;
592
593

  // Fill in option_order of mod_file_struct
594
  auto it = options_list.num_options.find("order");
595
  if (it != options_list.num_options.end())
596
    mod_file_struct.order_option = max(mod_file_struct.order_option, stoi(it->second));
sebastien's avatar
trunk:    
sebastien committed
597

598
599
600
601
  // Fill in mod_file_struct.partial_information
  it = options_list.num_options.find("partial_information");
  if (it != options_list.num_options.end() && it->second == "1")
    mod_file_struct.partial_information = true;
sebastien's avatar
sebastien committed
602
603
604
605
606
607

  // Option k_order_solver (implicit when order >= 3)
  it = options_list.num_options.find("k_order_solver");
  if ((it != options_list.num_options.end() && it->second == "1")
      || mod_file_struct.order_option >= 3)
    mod_file_struct.k_order_solver = true;
608

609
  it = options_list.num_options.find("hp_filter");
610
611
  auto it1 = options_list.num_options.find("bandpass.indicator");
  auto it2 = options_list.num_options.find("one_sided_hp_filter");
612
613
614
615
616
617
618
619
  if ((it != options_list.num_options.end() && it1 != options_list.num_options.end())
      || (it != options_list.num_options.end() && it2 != options_list.num_options.end())
      || (it1 != options_list.num_options.end() && it2 != options_list.num_options.end()))
    {
      cerr << "ERROR: stoch_simul: can only use one of hp, one-sided hp, and bandpass filters"
           << endl;
      exit(EXIT_FAILURE);
    }
620
621
622
}

void
623
StochSimulStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
624
{
625
  // Ensure that order 3 implies k_order (#844)
626
627
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
628
  if ((it1 != options_list.num_options.end() && it1->second == "1")
629
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
630
631
    output << "options_.k_order_solver = 1;" << endl;

632
  options_list.writeOutput(output);
sebastien's avatar
sebastien committed
633
  symbol_list.writeOutput("var_list_", output);
634
  output << "info = stoch_simul(var_list_);" << endl;
635
636
}

637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
void
StochSimulStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"stoch_simul\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  if (!symbol_list.empty())
    {
      output << ", ";
      symbol_list.writeJsonOutput(output);
    }
  output << "}";
}

654
655
656
657
ForecastStatement::ForecastStatement(SymbolList symbol_list_arg,
                                     OptionsList options_list_arg) :
  symbol_list(move(symbol_list_arg)),
  options_list(move(options_list_arg))
658
659
660
661
{
}

void
662
ForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
663
664
665
{
  options_list.writeOutput(output);
  symbol_list.writeOutput("var_list_", output);
666
  output << "[oo_.forecast,info] = dyn_forecast(var_list_,M_,options_,oo_,'simul');" << endl;
667
668
}

669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
void
ForecastStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"forecast\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  if (!symbol_list.empty())
    {
      output << ", ";
      symbol_list.writeJsonOutput(output);
    }
  output << "}";
}

686
687
RamseyModelStatement::RamseyModelStatement(OptionsList options_list_arg) :
  options_list(move(options_list_arg))
688
689
690
691
692
693
694
695
696
697
698
{
}

void
RamseyModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
  mod_file_struct.ramsey_model_present = true;

  /* Fill in option_order of mod_file_struct
     Since ramsey model needs one further order of derivation (for example, for 1st order
     approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
699
  auto it = options_list.num_options.find("order");
700
701
  if (it != options_list.num_options.end())
    {
702
      int order = stoi(it->second);
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
      if (order > 2)
        {
          cerr << "ERROR: ramsey_model: order > 2 is not  implemented" << endl;
          exit(EXIT_FAILURE);
        }
      mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
    }

  // Fill in mod_file_struct.partial_information
  it = options_list.num_options.find("partial_information");
  if (it != options_list.num_options.end() && it->second == "1")
    mod_file_struct.partial_information = true;

  // Option k_order_solver (implicit when order >= 3)
  it = options_list.num_options.find("k_order_solver");
  if ((it != options_list.num_options.end() && it->second == "1")
      || mod_file_struct.order_option >= 3)
    mod_file_struct.k_order_solver = true;
}

void
724
RamseyModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
725
{
726
727
728
  // options_.ramsey_policy indicates that a Ramsey model is present in the *.mod file
  // this affects the computation of the steady state that uses a special algorithm
  // It should probably rather be a M_ field, but we leave it in options_ for historical reason
729

730
  // Ensure that order 3 implies k_order (#844)
731
732
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
733
  if ((it1 != options_list.num_options.end() && it1->second == "1")
734
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
735
736
    output << "options_.k_order_solver = 1;" << endl;

737
  output << "options_.ramsey_policy = 1;" << endl;
738
  options_list.writeOutput(output);
739
740
}

741
742
743
744
745
746
747
748
749
750
751
752
void
RamseyModelStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"ramsey_model\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

753
RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg) :
754
  symbol_table(symbol_table_arg),
755
  constraints(move(constraints_arg))
756
757
758
759
760
761
{
}

void
RamseyConstraintsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
762
  if ((mod_file_struct.ramsey_model_present != true) || (mod_file_struct.ramsey_policy_present != true))
763
764
765
766
767
768
769
    cerr << "ramsey_constraints: can only be used with ramsey_model or ramsey_policy" << endl;
}

void
RamseyConstraintsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
  output << "M_.ramsey_model_constraints = {" << endl;
770
  for (auto it = constraints.begin(); it != constraints.end(); ++it)
771
772
    {
      if (it != constraints.begin())
773
        output << ", ";
774
      output << "{" << it->endo + 1 << ", '";
775
776
      switch (it->code)
        {
777
        case BinaryOpcode::less:
778
779
          output << '<';
          break;
780
        case BinaryOpcode::greater:
781
782
          output << '>';
          break;
783
        case BinaryOpcode::lessEqual:
784
785
          output << "<=";
          break;
786
        case BinaryOpcode::greaterEqual:
787
788
789
790
791
792
          output << ">=";
          break;
        default:
          cerr << "Ramsey constraints: this shouldn't happen." << endl;
          exit(EXIT_FAILURE);
        }
793
794
795
796
797
798
799
      output << "', '";
      it->expression->writeOutput(output);
      output << "'}" << endl;
    }
  output << "};" << endl;
}

800
801
802
803
804
void
RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"ramsey_constraints\""
         << ", \"ramsey_model_constraints\": [" << endl;
805
  for (auto it = constraints.begin(); it != constraints.end(); ++it)
806
807
    {
      if (it != constraints.begin())
Stéphane Adjemian's avatar
Stéphane Adjemian committed
808
        output << ", ";
809
      output << "{\"constraint\": \"" << symbol_table.getName(it->endo) << " ";
Stéphane Adjemian's avatar
Stéphane Adjemian committed
810
811
      switch (it->code)
        {
812
        case BinaryOpcode::less:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
813
814
          output << '<';
          break;
815
        case BinaryOpcode::greater:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
816
817
          output << '>';
          break;
818
        case BinaryOpcode::lessEqual:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
819
820
          output << "<=";
          break;
821
        case BinaryOpcode::greaterEqual:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
822
823
824
825
826
827
          output << ">=";
          break;
        default:
          cerr << "Ramsey constraints: this shouldn't happen." << endl;
          exit(1);
        }
828
      output << " ";
829
      it->expression->writeJsonOutput(output, {}, {});
830
831
832
833
834
835
      output << "\"}" << endl;
    }
  output << "]" << endl;
  output << "}";
}

836
RamseyPolicyStatement::RamseyPolicyStatement(const SymbolTable &symbol_table_arg,
837
838
                                             vector<string> ramsey_policy_list_arg,
                                             OptionsList options_list_arg) :
839
  symbol_table(symbol_table_arg),
840
841
  ramsey_policy_list(move(ramsey_policy_list_arg)),
  options_list(move(options_list_arg))
842
843
844
845
{
}

void
846
RamseyPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
847
{
848
849
  // ramsey_model_present indicates that the model is augmented with the FOC of the planner problem
  mod_file_struct.ramsey_model_present = true;
850
  // ramsey_policy_present indicates that ramsey_policy instruction for computation of first order approximation
851
  // of  a stochastic Ramsey problem if present in the *.mod file
sebastien's avatar
sebastien committed
852
  mod_file_struct.ramsey_policy_present = true;
853
854
855
856

  /* Fill in option_order of mod_file_struct
     Since ramsey policy needs one further order of derivation (for example, for 1st order
     approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
857
  auto it = options_list.num_options.find("order");
858
  if (it != options_list.num_options.end())
859
    {
860
      int order = stoi(it->second);
861
      if (order > 2)
862
        {
863
          cerr << "ERROR: ramsey_policy: order > 2 is not  implemented" << endl;
864
865
866
867
          exit(EXIT_FAILURE);
        }
      mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
    }
sebastien's avatar
trunk:    
sebastien committed
868

869
870
871
872
  // Fill in mod_file_struct.partial_information
  it = options_list.num_options.find("partial_information");
  if (it != options_list.num_options.end() && it->second == "1")
    mod_file_struct.partial_information = true;
sebastien's avatar
sebastien committed
873
874
875
876
877
878

  // Option k_order_solver (implicit when order >= 3)
  it = options_list.num_options.find("k_order_solver");
  if ((it != options_list.num_options.end() && it->second == "1")
      || mod_file_struct.order_option >= 3)
    mod_file_struct.k_order_solver = true;
879
880
}

881
882
883
void
RamseyPolicyStatement::checkRamseyPolicyList()
{
884
  for (const auto & it : ramsey_policy_list)
885
    {
886
      if (!symbol_table.exists(it))
887
        {
888
          cerr << "ERROR: ramsey_policy: " << it << " was not declared." << endl;
889
890
          exit(EXIT_FAILURE);
        }
891
      if (symbol_table.getType(it) != SymbolType::endogenous)
892
        {
893
          cerr << "ERROR: ramsey_policy: " << it << " is not endogenous." << endl;
894
895
896
897
898
          exit(EXIT_FAILURE);
        }
    }
}

899
void
900
RamseyPolicyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
901
{
902
  // Ensure that order 3 implies k_order (#844)
903
904
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
905
  if ((it1 != options_list.num_options.end() && it1->second == "1")
906
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
907
908
    output << "options_.k_order_solver = 1;" << endl;

909
  options_list.writeOutput(output);
910
  output << "var_list_ = {";
911
  for (auto it = ramsey_policy_list.begin();
912
913
914
       it != ramsey_policy_list.end(); ++it)
    {
      if (it != ramsey_policy_list.begin())
915
        output << ";";
916
917
      output << "'" << *it << "'";
    }
918
  output << "};" << endl
919
         << "ramsey_policy(var_list_);" << endl;
920
921
}

922
923
924
925
926
927
928
929
930
void
RamseyPolicyStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"ramsey_policy\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
931
  output << ", \"ramsey_policy_list\": [";
932
  for (auto it = ramsey_policy_list.begin();
933
934
935
936
937
938
939
940
941
942
       it != ramsey_policy_list.end(); ++it)
    {
      if (it != ramsey_policy_list.begin())
        output << ",";
      output << "\"" << *it << "\"";
    }
  output << "]"
         << "}";
}

943
944
945
946
DiscretionaryPolicyStatement::DiscretionaryPolicyStatement(SymbolList symbol_list_arg,
                                                           OptionsList options_list_arg) :
  symbol_list(move(symbol_list_arg)),
  options_list(move(options_list_arg))
947
948
949
950
{
}

void
951
DiscretionaryPolicyStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
952
953
954
{
  mod_file_struct.discretionary_policy_present = true;

955
956
957
958
959
960
  if (options_list.symbol_list_options.find("instruments") == options_list.symbol_list_options.end())
    {
      cerr << "ERROR: discretionary_policy: the instruments option is required." << endl;
      exit(EXIT_FAILURE);
    }

961
962
963
  /* Fill in option_order of mod_file_struct
     Since discretionary policy needs one further order of derivation (for example, for 1st order
     approximation, it needs 2nd derivatives), we add 1 to the order declared by user */
964
  auto it = options_list.num_options.find("order");
965
966
  if (it != options_list.num_options.end())
    {
967
      int order = stoi(it->second);
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
      if (order > 1)
        {
          cerr << "ERROR: discretionary_policy: order > 1 is not yet implemented" << endl;
          exit(EXIT_FAILURE);
        }
      mod_file_struct.order_option = max(mod_file_struct.order_option, order + 1);
    }

  // Fill in mod_file_struct.partial_information
  it = options_list.num_options.find("partial_information");
  if (it != options_list.num_options.end() && it->second == "1")
    mod_file_struct.partial_information = true;

  // Option k_order_solver (implicit when order >= 3)
  it = options_list.num_options.find("k_order_solver");
  if ((it != options_list.num_options.end() && it->second == "1")
      || mod_file_struct.order_option >= 3)
    mod_file_struct.k_order_solver = true;
}

void
989
DiscretionaryPolicyStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
990
{
991
  // Ensure that order 3 implies k_order (#844)
992
993
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
994
  if ((it1 != options_list.num_options.end() && it1->second == "1")
995
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
996
997
    output << "options_.k_order_solver = 1;" << endl;

998
999
  options_list.writeOutput(output);
  symbol_list.writeOutput("var_list_", output);
1000
  output << "discretionary_policy(var_list_);" << endl;