ComputingTasks.cc 172 KB
Newer Older
1
/*
2
 * Copyright (C) 2003-2019 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
SteadyStatement::SteadyStatement(OptionsList options_list_arg) :
35
  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
CheckStatement::CheckStatement(OptionsList options_list_arg) :
65
  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
ModelInfoStatement::ModelInfoStatement(OptionsList options_list_arg) :
95
  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
SimulStatement::SimulStatement(OptionsList options_list_arg) :
125
  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
PerfectForesightSetupStatement::PerfectForesightSetupStatement(OptionsList options_list_arg) :
156
  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 215
  prior_func{prior_func_arg},
  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
                                     string discount_arg,
263
                                     expr_t growth_arg,
264 265
                                     double steady_state_growth_rate_number_arg,
                                     int steady_state_growth_rate_symb_id_arg,
Houtan Bastani's avatar
Houtan Bastani committed
266
                                     const SymbolTable &symbol_table_arg) :
267
  name{move(name_arg)},
268
  aux_model_name{move(aux_model_name_arg)},
269
  discount{move(discount_arg)},
270
  growth{growth_arg},
271
  original_growth{growth_arg},
272 273
  steady_state_growth_rate_number{steady_state_growth_rate_number_arg},
  steady_state_growth_rate_symb_id{steady_state_growth_rate_symb_id_arg},
274 275 276
  symbol_table{symbol_table_arg},
  growth_symb_id{-1},
  growth_lag{0}
Houtan Bastani's avatar
Houtan Bastani committed
277 278 279 280 281 282
{
}

void
PacModelStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
283 284 285 286 287
  if (growth == nullptr)
    return;

  VariableNode *vn = dynamic_cast<VariableNode *>(growth);
  if (vn != nullptr)
288
    {
289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
      mod_file_struct.pac_params.insert(vn->symb_id);
      mod_file_struct.pac_params.insert(vn->lag);
    }

  UnaryOpNode *uon = dynamic_cast<UnaryOpNode *>(growth);
  if (uon != nullptr)
    if (uon->op_code == UnaryOpcode::diff)
      {
        VariableNode *uonvn = dynamic_cast<VariableNode *>(uon->arg);
        UnaryOpNode *uon1 = dynamic_cast<UnaryOpNode *>(uon->arg);
        while (uonvn == nullptr && uon1 != nullptr)
          {
            uonvn = dynamic_cast<VariableNode *>(uon1->arg);
            uon1 = dynamic_cast<UnaryOpNode *>(uon1->arg);
          }
        if (uonvn == nullptr)
305
          {
306
            cerr << "Pac growth parameter must be either a variable or a diff unary op of a variable" << endl;
307 308
            exit(EXIT_FAILURE);
          }
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
         mod_file_struct.pac_params.insert(uonvn->symb_id);
         mod_file_struct.pac_params.insert(uonvn->lag);
      }

  if (vn == nullptr && uon == nullptr)
    {
      cerr << "Pac growth parameter must be either a variable or a diff unary op of a variable" << endl;
      exit(EXIT_FAILURE);
    }
}

void
PacModelStatement::overwriteGrowth(expr_t new_growth)
{
  if (new_growth == nullptr || growth == nullptr)
    return;

  growth = new_growth;
  VariableNode *vn = dynamic_cast<VariableNode *>(growth);
  if (vn == nullptr)
    {
      cerr << "PacModelStatement::overwriteGrowth: Internal Dynare error: should not arrive here" << endl;
331
    }
332 333
  growth_symb_id = vn->symb_id;
  growth_lag = vn->lag;
Houtan Bastani's avatar
Houtan Bastani committed
334 335 336 337 338
}

void
PacModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
339
  output << "M_.pac." << name << ".auxiliary_model_name = '" << aux_model_name << "';" << endl
340 341 342 343 344 345 346
         << "M_.pac." << name << ".discount_index = " << symbol_table.getTypeSpecificID(discount) + 1 << ";" << endl;
  if (steady_state_growth_rate_symb_id < 0 && steady_state_growth_rate_number > 0)
    output << "M_.pac." << name << ".steady_state_growth_rate = "
           << steady_state_growth_rate_number << ";" << endl;
  else if (steady_state_growth_rate_symb_id >= 0)
    output << "M_.pac." << name << ".steady_state_growth_rate = "
           << symbol_table.getTypeSpecificID(steady_state_growth_rate_symb_id) + 1 << ";" << endl;
Houtan Bastani's avatar
Houtan Bastani committed
347

348
  if (growth_symb_id >= 0)
Houtan Bastani's avatar
Houtan Bastani committed
349
    {
350 351
      string growth_type;
      switch (symbol_table.getType(growth_symb_id))
Houtan Bastani's avatar
Houtan Bastani committed
352
        {
353
        case SymbolType::endogenous:
354
          growth_type = "endogenous";
Houtan Bastani's avatar
Houtan Bastani committed
355
          break;
356
        case SymbolType::exogenous:
357
          growth_type = "exogenous";
Houtan Bastani's avatar
Houtan Bastani committed
358
          break;
359
        case SymbolType::parameter:
360
          growth_type = "parameter";
Houtan Bastani's avatar
Houtan Bastani committed
361 362
          break;
        default:
363 364
          {
          }
Houtan Bastani's avatar
Houtan Bastani committed
365 366
        }

367 368 369 370 371 372
      try
        {
          // case when this is not the highest lag of the growth variable
          int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, growth_lag);
          output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
                 << "M_.pac." << name << ".growth_lag = 0;" << endl
373 374 375 376
                 << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl
                 << "M_.pac." << name << ".growth_str = '";
          original_growth->writeJsonOutput(output, {}, {}, true);
          output << "';" << endl;
377 378 379 380 381 382 383 384 385 386
        }
      catch (...)
        {
          try
            {
              // case when this is the highest lag of the growth variable
              int tmp_growth_lag = growth_lag + 1;
              int aux_symb_id = symbol_table.searchAuxiliaryVars(growth_symb_id, tmp_growth_lag);
              output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(aux_symb_id) + 1 << ";" << endl
                     << "M_.pac." << name << ".growth_lag = -1;" << endl
387 388 389 390
                     << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl
                     << "M_.pac." << name << ".growth_str = '";
              original_growth->writeJsonOutput(output, {}, {}, true);
              output << "';" << endl;
391 392 393 394 395 396
            }
          catch (...)
            {
              // case when there is no aux var for the variable
              output << "M_.pac." << name << ".growth_index = " << symbol_table.getTypeSpecificID(growth_symb_id) + 1 << ";" << endl
                     << "M_.pac." << name << ".growth_lag = " << growth_lag << ";" << endl
397 398 399 400
                     << "M_.pac." << name << ".growth_type = '" << growth_type << "';" << endl
                     << "M_.pac." << name << ".growth_str = '";
              original_growth->writeJsonOutput(output, {}, {}, true);
              output << "';" << endl;
401 402 403
            }
        }
    }
Houtan Bastani's avatar
Houtan Bastani committed
404 405 406 407 408 409 410
}

void
PacModelStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"pac_model\","
         << "\"model_name\": \"" << name << "\","
411
         << "\"auxiliary_model_name\": \"" << aux_model_name << "\","
Houtan Bastani's avatar
Houtan Bastani committed
412 413
         << "\"discount_index\": " << symbol_table.getTypeSpecificID(discount) + 1;

414
  if (growth_symb_id >= 0)
Houtan Bastani's avatar
Houtan Bastani committed
415
    {
416 417
      string growth_type;
      switch (symbol_table.getType(growth_symb_id))
Houtan Bastani's avatar
Houtan Bastani committed
418
        {
419
        case SymbolType::endogenous:
420
          growth_type = "endogenous";
Houtan Bastani's avatar
Houtan Bastani committed
421
          break;
422
        case SymbolType::exogenous:
423
          growth_type = "exogenous";
Houtan Bastani's avatar
Houtan Bastani committed
424
          break;
425
        case SymbolType::parameter:
426
          growth_type = "parameter";
Houtan Bastani's avatar
Houtan Bastani committed
427 428
          break;
        default:
429 430
          {
          }
Houtan Bastani's avatar
Houtan Bastani committed
431
        }
432 433 434
      output << ","
             << "\"growth_index\": " << symbol_table.getTypeSpecificID(growth_symb_id) + 1 << ","
             << "\"growth_lag\": " << growth_lag << ","
435 436 437 438
             << "\"growth_type\": \"" << growth_type << "\"," << endl
             << "\"growth_str\": \"";
      original_growth->writeJsonOutput(output, {}, {}, true);
      output << "\"" << endl;
Houtan Bastani's avatar
Houtan Bastani committed
439 440 441 442
    }
  output << "}";
}

443
VarEstimationStatement::VarEstimationStatement(OptionsList options_list_arg) :
444
  options_list{move(options_list_arg)}
445 446 447
{
}

448 449 450
void
VarEstimationStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
451
  auto it = options_list.string_options.find("var_estimation.model_name");
452 453 454 455 456 457 458
  if (it == options_list.string_options.end())
    {
      cerr << "ERROR: You must provide the model name to the var_estimation statement." << endl;
      exit(EXIT_FAILURE);
    }
}

459 460 461
void
VarEstimationStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
462 463
  options_list.writeOutput(output);
  output << "oo_ = var_estimation(M_, options_, oo_);" << endl;
464 465
}

466 467
VarRestrictionsStatement::VarRestrictionsStatement(string var_model_name_arg,
                                                   map<string, vector<string>> var_map_arg,
468
                                                   map<int, map<int, SymbolList>> exclusion_restrictions_arg,
469 470 471
                                                   equation_restrictions_t equation_restrictions_arg,
                                                   crossequation_restrictions_t crossequation_restrictions_arg,
                                                   map<pair<int, int>, double> covariance_number_restriction_arg,
472
                                                   map<pair<int, int>, pair<int, int>> covariance_pair_restriction_arg,
473
                                                   const SymbolTable &symbol_table_arg) :
474 475
  var_model_name{move(var_model_name_arg)},
  var_map{move(var_map_arg)},
476 477 478 479 480 481
  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)},
  symbol_table{symbol_table_arg}
482 483 484
{
}

485 486 487 488 489
int
VarRestrictionsStatement::findIdxInVector(const vector<string> &vecvars, const string &var) const
{
  int idx = 0;
  bool setflag = false;
490
  for (auto itvs = vecvars.begin();
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
       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;
}

507 508 509
void
VarRestrictionsStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
510
  auto itvs = var_map.find(var_model_name);
511 512 513 514 515 516 517 518
  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;

519
  string Mstr("M_.var." + var_model_name + ".restrictions.");
520
  int nrestrictions = 0;
521 522 523

  // Exclusion Restrictions
  int idx = 1;
524
  for (auto it = exclusion_restrictions.begin();
525 526
       it != exclusion_restrictions.end(); it++, idx++)
    {
Houtan Bastani's avatar
Houtan Bastani committed
527
      output << Mstr << "exclusion_restrictions{" << idx<< "}.lag = "
528
             << it->first << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
529
             << Mstr << "exclusion_restrictions{" << idx << "}.restrictions = [";
530
      for (auto it1 = it->second.begin();
531 532 533 534
           it1 != it->second.end(); it1++)
        {
          if (it1 != it->second.begin())
            output << " ";
535 536 537 538 539 540 541 542

          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 << "])";
543
          nrestrictions += it1->second.getSize();
544 545 546 547 548 549
        }
      output << "];" << endl;
    }

  // Equation Restrictions
  idx = 1;
550
  for (auto it = equation_restrictions.begin();
551
       it != equation_restrictions.end(); it++, idx++, nrestrictions++)
552
    {
553 554
      output << Mstr << "equation_restriction{" << idx << "}.eq = '"
             << symbol_table.getName(it->first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
555
             << Mstr << "equation_restriction{" << idx << "}.val = "
556 557 558
             << it->second.second << ";" << endl;

      var_restriction_eq_crosseq_t ls = it->second.first.first;
559 560
      output << Mstr << "equation_restriction{" << idx << "}.ls = '"
             << symbol_table.getName(ls.first.first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
561
             << Mstr << "equation_restriction{" << idx << "}.lslag = "
562
             << ls.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
563
             << Mstr << "equation_restriction{" << idx << "}.lscoeff = ";
564 565 566 567 568 569
      ls.second->writeOutput(output);
      output << ";" << endl;

      var_restriction_eq_crosseq_t rs = it->second.first.second;
      if (rs.first.first >= 0)
        {
570 571
          output << Mstr << "equation_restriction{" << idx << "}.rs = '"
                 << symbol_table.getName(rs.first.first) << "';" << endl
Houtan Bastani's avatar
Houtan Bastani committed
572
                 << Mstr << "equation_restriction{" << idx << "}.rslag = "
573
                 << rs.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
574
                 << Mstr << "equation_restriction{" << idx << "}.rscoeff = ";
575 576 577 578 579 580 581
          rs.second->writeOutput(output);
          output << ";" << endl;
        }
    }

  // Cross Equation Restrictions
  idx = 1;
582
  for (auto it = crossequation_restrictions.begin();
583
       it != crossequation_restrictions.end(); it++, idx++, nrestrictions++)
584
    {
585 586
      output << Mstr << "crossequation_restriction{" << idx << "}.val = "
             << it->second << ";" << endl;
587

588
      var_restriction_eq_crosseq_t ls = it->first.first;
589 590 591 592
      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
593
             << Mstr << "crossequation_restriction{" << idx << "}.lslag = "
594
             << ls.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
595
             << Mstr << "crossequation_restriction{" << idx << "}.lscoeff = ";
596 597 598
      ls.second->writeOutput(output);
      output << ";" << endl;

599
      var_restriction_eq_crosseq_t rs = it->first.second;
600 601
      if (rs.first.first >= 0)
        {
602 603 604 605
          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
606
                 << Mstr << "crossequation_restriction{" << idx << "}.rslag = "
607
                 << rs.first.second.second << ";" << endl
Houtan Bastani's avatar
Houtan Bastani committed
608
                 << Mstr << "crossequation_restriction{" << idx << "}.rscoeff = ";
609 610 611 612 613 614 615
          rs.second->writeOutput(output);
          output << ";" << endl;
        }
    }

  // Covariance Const Restrictions
  idx = 1;
616
  for (auto it = covariance_number_restriction.begin();
617
       it != covariance_number_restriction.end(); it++, idx++)
618 619 620 621
    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
622
           << Mstr << "covariance_const_restriction{" << idx << "}.val = "
623 624 625 626
           << it->second << ";" << endl;

  // Covariance Pair Restrictions
  idx = 1;
627
  for (auto it = covariance_pair_restriction.begin();
628
       it != covariance_pair_restriction.end(); it++, idx++)
629 630 631 632 633 634 635 636 637 638
    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;
639 640
}

641 642
StochSimulStatement::StochSimulStatement(SymbolList symbol_list_arg,
                                         OptionsList options_list_arg) :
643 644
  symbol_list{move(symbol_list_arg)},
  options_list{move(options_list_arg)}
645 646 647 648
{
}

void
649
StochSimulStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
650
{
sebastien's avatar
sebastien committed
651
  mod_file_struct.stoch_simul_present = true;
652 653

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

658 659
  // Fill in mod_file_struct.partial_information
  it = options_list.num_options.find("partial_information");
660
  if (it != options_list.num_options.end() && it->second == "true")
661
    mod_file_struct.partial_information = true;
sebastien's avatar
sebastien committed
662 663 664

  // Option k_order_solver (implicit when order >= 3)
  it = options_list.num_options.find("k_order_solver");
665
  if ((it != options_list.num_options.end() && it->second == "true")
sebastien's avatar
sebastien committed
666 667
      || mod_file_struct.order_option >= 3)
    mod_file_struct.k_order_solver = true;
668

669
  it = options_list.num_options.find("hp_filter");
670 671
  auto it1 = options_list.num_options.find("bandpass.indicator");
  auto it2 = options_list.num_options.find("one_sided_hp_filter");
672 673 674 675 676 677 678 679
  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);
    }
680 681 682
}

void
683
StochSimulStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
684
{
685
  // Ensure that order 3 implies k_order (#844)
686 687
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
688
  if ((it1 != options_list.num_options.end() && it1->second == "true")
689
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
690
    output << "options_.k_order_solver = true;" << endl;
691

692
  options_list.writeOutput(output);
sebastien's avatar
sebastien committed
693
  symbol_list.writeOutput("var_list_", output);
694
  output << "info = stoch_simul(var_list_);" << endl;
695 696
}

697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713
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 << "}";
}

714 715
ForecastStatement::ForecastStatement(SymbolList symbol_list_arg,
                                     OptionsList options_list_arg) :
716 717
  symbol_list{move(symbol_list_arg)},
  options_list{move(options_list_arg)}
718 719 720 721
{
}

void
722
ForecastStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
723 724 725
{
  options_list.writeOutput(output);
  symbol_list.writeOutput("var_list_", output);
726
  output << "[oo_.forecast,info] = dyn_forecast(var_list_,M_,options_,oo_,'simul');" << endl;
727 728
}

729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745
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 << "}";
}

746
DetCondForecast::DetCondForecast(SymbolList symbol_list_arg,
747
                                 OptionsList options_list_arg,
748
                                 const bool linear_decomposition_arg) :
749
  options_list{move(options_list_arg)},
750
  symbol_list{move(symbol_list_arg)},
751
  linear_decomposition{linear_decomposition_arg}
752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771
{

}

void
DetCondForecast::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
{
  options_list.writeOutput(output);
  if (linear_decomposition)
    {
      output << "first_order_solution_to_compute = 1;" << endl;
      output << "if exist('oo_')" << endl;
      output << "  if isfield(oo_, 'dr')" << endl;
      output << "    if isfield(oo_.dr, 'ghx') && isfield(oo_.dr, 'ghu') && isfield(oo_.dr, 'state_var') && isfield(oo_.dr, 'order_var')" << endl;
      output << "      first_order_solution_to_compute = 0;" << endl;
      output << "    end;" << endl;
      output << "  end;" << endl;
      output << "end;" << endl;
      output << "if first_order_solution_to_compute" << endl;
      output << " fprintf('%s','Computing the first order solution ...');" << endl;
772
      output << " options_.nograph = true;" << endl;
773
      output << " options_.order = 1;" << endl;
774 775 776 777 778
      output << " options_.noprint = true;" << endl;
      output << " options_.nocorr = true;" << endl;
      output << " options_.nomoments = true;" << endl;
      output << " options_.nodecomposition = true;" << endl;
      output << " options_.nofunctions = true;" << endl;
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
      output << " options_.irf = 0;" << endl;
      output << " tmp_periods = options_.periods;" << endl;
      output << " options_.periods = 0;" << endl;
      output << " var_list_ = char();" << endl;
      output << " info = stoch_simul(var_list_);" << endl;
      output << " fprintf('%s\\n','done');" << endl;
      output << " options_.periods = tmp_periods;" << endl;
      output << "end;" << endl;
    }
  vector<string> symbols = symbol_list.get_symbols();
  if (symbols.size() > 0)
    output << symbols[1] << " = det_cond_forecast(" ;
  for (unsigned int i = 0; i < symbols.size() - 1; i++)
    output << symbols[i] << ", ";
  if (symbols.size() > 0)
    output << symbols[symbols.size() - 1];
  output << ");" << endl;
}

798
RamseyModelStatement::RamseyModelStatement(OptionsList options_list_arg) :
799
  options_list{move(options_list_arg)}
800 801 802 803 804 805 806 807 808 809 810
{
}

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 */
811
  auto it = options_list.num_options.find("order");
812 813
  if (it != options_list.num_options.end())
    {
814
      int order = stoi(it->second);
815 816 817 818 819 820 821 822 823 824
      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");
825
  if (it != options_list.num_options.end() && it->second == "true")
826 827 828 829
    mod_file_struct.partial_information = true;

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

void
836
RamseyModelStatement::writeOutput(ostream &output, const string &basename, bool minimal_workspace) const
837
{
838 839 840
  // 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
841

842
  // Ensure that order 3 implies k_order (#844)
843 844
  auto it = options_list.num_options.find("order");
  auto it1 = options_list.num_options.find("k_order_solver");
845
  if ((it1 != options_list.num_options.end() && it1->second == "true")
846
      || (it != options_list.num_options.end() && stoi(it->second) >= 3))
847
    output << "options_.k_order_solver = true;" << endl;
848

849
  output << "options_.ramsey_policy = true;" << endl;
850
  options_list.writeOutput(output);
851 852
}

853 854 855 856 857 858 859 860 861 862 863 864
void
RamseyModelStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"ramsey_model\"";
  if (options_list.getNumberOfOptions())
    {
      output << ", ";
      options_list.writeJsonOutput(output);
    }
  output << "}";
}

865
RamseyConstraintsStatement::RamseyConstraintsStatement(const SymbolTable &symbol_table_arg, constraints_t constraints_arg) :
866 867
  symbol_table{symbol_table_arg},
  constraints{move(constraints_arg)}
868 869 870 871 872 873
{
}

void
RamseyConstraintsStatement::checkPass(ModFileStructure &mod_file_struct, WarningConsolidation &warnings)
{
874
  if ((mod_file_struct.ramsey_model_present != true) || (mod_file_struct.ramsey_policy_present != true))
875 876 877 878 879 880 881
    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;
882
  for (auto it = constraints.begin(); it != constraints.end(); ++it)
883 884
    {
      if (it != constraints.begin())
885
        output << ", ";
886
      output << "{" << it->endo + 1 << ", '";
887 888
      switch (it->code)
        {
889
        case BinaryOpcode::less:
890 891
          output << '<';
          break;
892
        case BinaryOpcode::greater:
893 894
          output << '>';
          break;
895
        case BinaryOpcode::lessEqual:
896 897
          output << "<=";
          break;
898
        case BinaryOpcode::greaterEqual:
899 900 901 902 903 904
          output << ">=";
          break;
        default:
          cerr << "Ramsey constraints: this shouldn't happen." << endl;
          exit(EXIT_FAILURE);
        }
905 906 907 908 909 910 911
      output << "', '";
      it->expression->writeOutput(output);
      output << "'}" << endl;
    }
  output << "};" << endl;
}

912 913 914 915 916
void
RamseyConstraintsStatement::writeJsonOutput(ostream &output) const
{
  output << "{\"statementName\": \"ramsey_constraints\""
         << ", \"ramsey_model_constraints\": [" << endl;
917
  for (auto it = constraints.begin(); it != constraints.end(); ++it)
918 919
    {
      if (it != constraints.begin())
Stéphane Adjemian's avatar
Stéphane Adjemian committed
920
        output << ", ";
921
      output << "{\"constraint\": \"" << symbol_table.getName(it->endo) << " ";
Stéphane Adjemian's avatar
Stéphane Adjemian committed
922 923
      switch (it->code)
        {
924
        case BinaryOpcode::less:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
925 926
          output << '<';
          break;
927
        case BinaryOpcode::greater:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
928 929
          output << '>';
          break;
930
        case BinaryOpcode::lessEqual:
Stéphane Adjemian's avatar
Stéphane Adjemian committed
931 932
          output << "<=";
          break;
933
        case BinaryOpcode::greaterEqual: