2008-02-03 11:28:36 +01:00
/*
2021-01-06 14:19:33 +01:00
* Copyright © 2006 - 2021 Dynare Team
2008-02-03 11:28:36 +01:00
*
* 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
2021-06-09 16:52:20 +02:00
* along with Dynare . If not , see < https : //www.gnu.org/licenses/>.
2008-02-03 11:28:36 +01:00
*/
2008-06-28 13:20:45 +02:00
# include <cstdlib>
2008-02-03 11:28:36 +01:00
# include <iostream>
# include <fstream>
2008-12-19 11:24:31 +01:00
# include <typeinfo>
2011-03-21 18:40:57 +01:00
# include <cassert>
2019-04-04 17:01:37 +02:00
# include <random>
2018-06-27 15:01:31 +02:00
2019-04-04 17:01:37 +02:00
# include <filesystem>
2012-05-08 16:02:22 +02:00
2008-02-03 11:28:36 +01:00
# include "ModFile.hh"
2010-10-25 18:20:58 +02:00
# include "ConfigFile.hh"
2011-03-21 18:40:57 +01:00
# include "ComputingTasks.hh"
2018-11-07 15:24:57 +01:00
# include "Shocks.hh"
2008-02-03 11:28:36 +01:00
2013-02-26 16:50:05 +01:00
ModFile : : ModFile ( WarningConsolidation & warnings_arg )
2018-10-04 17:18:27 +02:00
: var_model_table { symbol_table } ,
trend_component_model_table { symbol_table } ,
expressions_tree { symbol_table , num_constants , external_functions_table } ,
original_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
trend_dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
ramsey_FOC_equations_dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
orig_ramsey_dynamic_model { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
epilogue { symbol_table , num_constants , external_functions_table ,
trend_component_model_table , var_model_table } ,
static_model { symbol_table , num_constants , external_functions_table } ,
steady_state_model { symbol_table , num_constants , external_functions_table , static_model } ,
warnings { warnings_arg }
2008-02-03 11:28:36 +01:00
{
}
2008-12-19 11:24:31 +01:00
void
2018-12-20 17:04:28 +01:00
ModFile : : evalAllExpressions ( bool warn_uninit )
2008-12-19 11:24:31 +01:00
{
2018-12-20 17:04:28 +01:00
cout < < " Evaluating expressions... " ;
2008-12-31 20:29:17 +01:00
2009-02-27 13:19:25 +01:00
// Loop over all statements, and fill global eval context if relevant
2018-09-05 15:17:21 +02:00
for ( auto & st : statements )
2008-12-19 11:24:31 +01:00
{
2019-10-28 11:09:36 +01:00
if ( auto ips = dynamic_cast < InitParamStatement * > ( st . get ( ) ) ; ips )
2009-02-27 13:19:25 +01:00
ips - > fillEvalContext ( global_eval_context ) ;
2019-10-28 11:09:36 +01:00
if ( auto ies = dynamic_cast < InitOrEndValStatement * > ( st . get ( ) ) ; ies )
2009-02-27 13:19:25 +01:00
ies - > fillEvalContext ( global_eval_context ) ;
2019-10-28 11:09:36 +01:00
if ( auto lpass = dynamic_cast < LoadParamsAndSteadyStateStatement * > ( st . get ( ) ) ; lpass )
2009-02-27 13:19:25 +01:00
lpass - > fillEvalContext ( global_eval_context ) ;
2008-12-19 11:24:31 +01:00
}
2009-02-27 13:19:25 +01:00
// Evaluate model local variables
2009-04-14 16:39:53 +02:00
dynamic_model . fillEvalContext ( global_eval_context ) ;
2009-02-27 13:19:25 +01:00
2018-12-20 17:04:28 +01:00
cout < < " done " < < endl ;
2009-02-27 13:19:25 +01:00
// Check if some symbols are not initialized, and give them a zero value then
2009-12-16 18:13:23 +01:00
for ( int id = 0 ; id < = symbol_table . maxID ( ) ; id + + )
2019-10-28 11:09:36 +01:00
if ( auto type = symbol_table . getType ( id ) ;
( type = = SymbolType : : endogenous | | type = = SymbolType : : exogenous | | type = = SymbolType : : exogenousDet
| | type = = SymbolType : : parameter | | type = = SymbolType : : modelLocalVariable )
& & global_eval_context . find ( id ) = = global_eval_context . end ( ) )
{
if ( warn_uninit )
warnings < < " WARNING: Can't find a numeric initial value for "
< < symbol_table . getName ( id ) < < " , using zero " < < endl ;
global_eval_context [ id ] = 0 ;
}
2008-12-19 11:24:31 +01:00
}
2008-02-03 11:28:36 +01:00
void
2018-09-05 15:17:21 +02:00
ModFile : : addStatement ( unique_ptr < Statement > st )
2008-02-03 11:28:36 +01:00
{
2018-09-05 15:17:21 +02:00
statements . push_back ( move ( st ) ) ;
2008-02-03 11:28:36 +01:00
}
2010-06-24 15:07:15 +02:00
void
2018-09-05 15:17:21 +02:00
ModFile : : addStatementAtFront ( unique_ptr < Statement > st )
2010-06-24 15:07:15 +02:00
{
2018-09-05 15:17:21 +02:00
statements . insert ( statements . begin ( ) , move ( st ) ) ;
2010-06-24 15:07:15 +02:00
}
2008-02-03 11:28:36 +01:00
void
2017-08-31 10:19:43 +02:00
ModFile : : checkPass ( bool nostrict , bool stochastic )
2008-02-03 11:28:36 +01:00
{
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2018-06-04 12:26:16 +02:00
statement - > checkPass ( mod_file_struct , warnings ) ;
2008-02-03 11:28:36 +01:00
2010-05-31 17:43:17 +02:00
// Check the steady state block
2017-08-30 15:46:17 +02:00
steady_state_model . checkPass ( mod_file_struct , warnings ) ;
2018-09-03 17:16:28 +02:00
// Check epilogue block
2019-12-20 11:10:32 +01:00
epilogue . checkPass ( mod_file_struct , warnings ) ;
2018-09-03 17:16:28 +02:00
2019-12-20 16:59:30 +01:00
if ( mod_file_struct . write_latex_steady_state_model_present
& & ! mod_file_struct . steady_state_model_present )
2017-08-30 15:46:17 +02:00
{
cerr < < " ERROR: You cannot have a write_latex_steady_state_model statement without a steady_state_model block. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2010-05-31 17:43:17 +02:00
2008-04-24 12:55:26 +02:00
// If order option has not been set, default to 2
if ( ! mod_file_struct . order_option )
mod_file_struct . order_option = 2 ;
2015-07-30 14:40:03 +02:00
param_used_with_lead_lag = dynamic_model . ParamUsedWithLeadLag ( ) ;
if ( param_used_with_lead_lag )
warnings < < " WARNING: A parameter was used with a lead or a lag in the model block " < < endl ;
2008-09-29 12:16:13 +02:00
bool stochastic_statement_present = mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present
| | mod_file_struct . osr_present
2011-03-17 15:15:13 +01:00
| | mod_file_struct . ramsey_policy_present
2013-10-28 14:22:23 +01:00
| | mod_file_struct . discretionary_policy_present
2017-08-31 10:19:43 +02:00
| | mod_file_struct . calib_smoother_present
2019-01-09 14:48:25 +01:00
| | mod_file_struct . identification_present
2020-07-08 18:42:14 +02:00
| | mod_file_struct . mom_estimation_present
2019-01-09 14:48:25 +01:00
| | mod_file_struct . sensitivity_present
2017-08-31 10:19:43 +02:00
| | stochastic ;
2008-09-29 12:16:13 +02:00
2008-02-03 11:28:36 +01:00
// Allow empty model only when doing a standalone BVAR estimation
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) = = 0
2008-02-03 11:28:36 +01:00
& & ( mod_file_struct . check_present
2014-04-09 17:57:17 +02:00
| | mod_file_struct . perfect_foresight_solver_present
2008-09-29 12:16:13 +02:00
| | stochastic_statement_present ) )
{
cerr < < " ERROR: At least one model equation must be declared! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-09-29 12:16:13 +02:00
}
2015-09-03 17:04:34 +02:00
if ( ( mod_file_struct . ramsey_model_present | | mod_file_struct . ramsey_policy_present )
& & mod_file_struct . discretionary_policy_present )
{
2017-04-06 08:41:12 +02:00
cerr < < " ERROR: You cannot use the discretionary_policy command when you use either ramsey_model or ramsey_policy and vice versa " < < endl ;
2015-09-03 17:04:34 +02:00
exit ( EXIT_FAILURE ) ;
}
2017-06-01 19:58:32 +02:00
if ( ( ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present )
2011-03-17 15:15:13 +01:00
& & ! mod_file_struct . planner_objective_present )
2014-03-09 09:52:44 +01:00
| | ( ! ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present )
2017-06-01 19:58:32 +02:00
& & mod_file_struct . planner_objective_present ) )
2011-03-03 16:03:21 +01:00
{
2014-03-09 09:52:44 +01:00
cerr < < " ERROR: A planner_objective statement must be used with a ramsey_model, a ramsey_policy or a discretionary_policy statement and vice versa. " < < endl ;
2011-03-03 16:03:21 +01:00
exit ( EXIT_FAILURE ) ;
}
2011-03-03 16:30:53 +01:00
if ( ( mod_file_struct . osr_present & & ( ! mod_file_struct . osr_params_present | | ! mod_file_struct . optim_weights_present ) )
| | ( ( ! mod_file_struct . osr_present | | ! mod_file_struct . osr_params_present ) & & mod_file_struct . optim_weights_present )
| | ( ( ! mod_file_struct . osr_present | | ! mod_file_struct . optim_weights_present ) & & mod_file_struct . osr_params_present ) )
{
cerr < < " ERROR: The osr statement must be used with osr_params and optim_weights. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2014-04-09 17:57:17 +02:00
if ( mod_file_struct . perfect_foresight_solver_present & & stochastic_statement_present )
2008-02-03 11:28:36 +01:00
{
2014-04-09 17:57:17 +02:00
cerr < < " ERROR: A .mod file cannot contain both one of {perfect_foresight_solver,simul} and one of {stoch_simul, estimation, osr, ramsey_policy, discretionary_policy}. This is not possible: one cannot mix perfect foresight context with stochastic context in the same file. " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2020-05-20 11:39:59 +02:00
if ( mod_file_struct . k_order_solver & & bytecode )
2009-12-09 12:50:58 +01:00
{
2010-12-17 18:34:23 +01:00
cerr < < " ERROR: 'k_order_solver' (which is implicit if order >= 3), is not yet compatible with 'bytecode'. " < < endl ;
2009-12-09 12:50:58 +01:00
exit ( EXIT_FAILURE ) ;
}
2020-06-23 15:13:04 +02:00
if ( use_dll & & bytecode )
2018-09-21 17:13:19 +02:00
{
2020-06-23 15:13:04 +02:00
cerr < < " ERROR: In 'model' block, 'use_dll' option is not compatible with 'bytecode' " < < endl ;
2018-09-21 17:13:19 +02:00
exit ( EXIT_FAILURE ) ;
}
2009-09-02 15:36:56 +02:00
2011-02-04 16:25:38 +01:00
if ( ( stochastic_statement_present | | mod_file_struct . check_present | | mod_file_struct . steady_present ) & & no_static )
2010-01-08 12:06:25 +01:00
{
2011-03-17 15:15:13 +01:00
cerr < < " ERROR: no_static option is incompatible with stoch_simul, estimation, osr, ramsey_policy, discretionary_policy, steady and check commands " < < endl ;
2010-01-08 12:06:25 +01:00
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
2019-12-16 19:42:59 +01:00
if ( mod_file_struct . dsge_var_estimated & & ! mod_file_struct . dsge_prior_weight_in_estimated_params )
{
cerr < < " ERROR: When estimating a DSGE-VAR model and estimating the weight of the prior, dsge_prior_weight must "
< < " be referenced in the estimated_params block. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2010-06-11 21:19:30 +02:00
2010-06-21 18:40:36 +02:00
if ( symbol_table . exists ( " dsge_prior_weight " ) )
{
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( " dsge_prior_weight " ) ! = SymbolType : : parameter )
2010-06-21 18:40:36 +02:00
{
cerr < < " ERROR: dsge_prior_weight may only be used as a parameter. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
2012-01-23 16:52:27 +01:00
warnings < < " WARNING: When estimating a DSGE-Var, declaring dsge_prior_weight as a "
< < " parameter is deprecated. The preferred method is to do this via "
< < " the dsge_var option in the estimation statement. " < < endl ;
2010-06-21 18:40:36 +02:00
if ( mod_file_struct . dsge_var_estimated | | ! mod_file_struct . dsge_var_calibrated . empty ( ) )
{
cerr < < " ERROR: dsge_prior_weight can either be declared as a parameter (deprecated) or via the dsge_var option "
< < " to the estimation statement (preferred), but not both. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( ! mod_file_struct . dsge_prior_weight_initialized & & ! mod_file_struct . dsge_prior_weight_in_estimated_params )
{
cerr < < " ERROR: If dsge_prior_weight is declared as a parameter, it must either be initialized or placed in the "
< < " estimated_params block. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( mod_file_struct . dsge_prior_weight_initialized & & mod_file_struct . dsge_prior_weight_in_estimated_params )
{
2017-06-28 15:06:54 +02:00
cerr < < " ERROR: dsge_prior_weight cannot be both initialized and estimated. " < < endl ;
2010-06-21 18:40:36 +02:00
exit ( EXIT_FAILURE ) ;
}
}
2010-06-11 21:19:30 +02:00
if ( mod_file_struct . dsge_prior_weight_in_estimated_params )
2010-06-21 18:40:36 +02:00
if ( ! mod_file_struct . dsge_var_estimated & & ! mod_file_struct . dsge_var_calibrated . empty ( ) )
2010-06-11 21:19:30 +02:00
{
2010-06-21 18:40:36 +02:00
cerr < < " ERROR: If dsge_prior_weight is in the estimated_params block, the prior weight cannot be calibrated "
2010-06-11 21:19:30 +02:00
< < " via the dsge_var option in the estimation statement. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2010-06-21 18:40:36 +02:00
else if ( ! mod_file_struct . dsge_var_estimated & & ! symbol_table . exists ( " dsge_prior_weight " ) )
{
cerr < < " ERROR: If dsge_prior_weight is in the estimated_params block, it must either be declared as a parameter "
< < " (deprecated) or the dsge_var option must be passed to the estimation statement (preferred). " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2013-04-11 17:07:39 +02:00
if ( dynamic_model . staticOnlyEquationsNbr ( ) ! = dynamic_model . dynamicOnlyEquationsNbr ( ) )
{
cerr < < " ERROR: the number of equations marked [static] must be equal to the number of equations marked [dynamic] " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-06-01 19:58:32 +02:00
if ( dynamic_model . staticOnlyEquationsNbr ( ) > 0
& & ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present ) )
2013-04-11 17:07:39 +02:00
{
2014-03-09 09:52:44 +01:00
cerr < < " ERROR: marking equations as [static] or [dynamic] is not possible with ramsey_model, ramsey_policy or discretionary_policy " < < endl ;
2013-04-11 17:07:39 +02:00
exit ( EXIT_FAILURE ) ;
}
2013-05-17 14:14:15 +02:00
2017-06-01 19:58:32 +02:00
if ( stochastic_statement_present
2018-07-18 16:18:26 +02:00
& & ( dynamic_model . isUnaryOpUsed ( UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsed ( UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsed ( BinaryOpcode : : different ) ) )
2019-04-03 16:32:52 +02:00
warnings < < R " (WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about " Expressions " , for more details.) " < < endl ;
2013-11-29 14:50:58 +01:00
2017-06-01 19:58:32 +02:00
if ( linear
2019-09-10 12:37:11 +02:00
& & ( dynamic_model . isUnaryOpUsedOnType ( SymbolType : : endogenous , UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsedOnType ( SymbolType : : endogenous , UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : endogenous , BinaryOpcode : : different ) ) )
{
cerr < < " ERROR: you have declared your model 'linear' but you are using a function "
< < " (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
< < " endogenous variable. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( linear
& & ! mod_file_struct . perfect_foresight_solver_present
& & ( dynamic_model . isUnaryOpUsedOnType ( SymbolType : : exogenous , UnaryOpcode : : sign )
| | dynamic_model . isUnaryOpUsedOnType ( SymbolType : : exogenous , UnaryOpcode : : abs )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : max )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : min )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : greater )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : less )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : greaterEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : lessEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : equalEqual )
| | dynamic_model . isBinaryOpUsedOnType ( SymbolType : : exogenous , BinaryOpcode : : different ) ) )
{
cerr < < " ERROR: you have declared your model 'linear' but you are using a function "
< < " (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
< < " exogenous variable in a non-perfect-foresight context. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-04-05 11:07:34 +02:00
2013-11-29 14:50:58 +01:00
// Test if some estimated parameters are used within the values of shocks
// statements (see issue #469)
set < int > parameters_intersect ;
set_intersection ( mod_file_struct . parameters_within_shocks_values . begin ( ) ,
mod_file_struct . parameters_within_shocks_values . end ( ) ,
mod_file_struct . estimated_parameters . begin ( ) ,
mod_file_struct . estimated_parameters . end ( ) ,
inserter ( parameters_intersect , parameters_intersect . begin ( ) ) ) ;
if ( parameters_intersect . size ( ) > 0 )
{
cerr < < " ERROR: some estimated parameters ( " ;
2018-06-04 15:03:26 +02:00
for ( auto it = parameters_intersect . begin ( ) ;
2017-06-01 19:58:32 +02:00
it ! = parameters_intersect . end ( ) ; )
2013-11-29 14:50:58 +01:00
{
cerr < < symbol_table . getName ( * it ) ;
if ( + + it ! = parameters_intersect . end ( ) )
cerr < < " , " ;
}
cerr < < " ) also appear in the expressions defining the variance/covariance matrix of shocks; this is not allowed. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2013-11-29 16:03:15 +01:00
2015-08-24 12:54:05 +02:00
// Check if some exogenous is not used in the model block, Issue #841
2018-03-28 18:46:15 +02:00
set < int > unusedExo0 = dynamic_model . findUnusedExogenous ( ) ;
set < int > unusedExo ;
set_difference ( unusedExo0 . begin ( ) , unusedExo0 . end ( ) ,
mod_file_struct . pac_params . begin ( ) , mod_file_struct . pac_params . end ( ) ,
inserter ( unusedExo , unusedExo . begin ( ) ) ) ;
2015-03-06 09:49:11 +01:00
if ( unusedExo . size ( ) > 0 )
2013-11-29 16:03:15 +01:00
{
2015-08-24 12:54:05 +02:00
ostringstream unused_exos ;
2018-06-04 12:26:16 +02:00
for ( int it : unusedExo )
unused_exos < < symbol_table . getName ( it ) < < " " ;
2015-08-24 12:54:05 +02:00
if ( nostrict )
warnings < < " WARNING: " < < unused_exos . str ( )
< < " not used in model block, removed by nostrict command-line option " < < endl ;
else
2013-11-29 16:03:15 +01:00
{
2015-08-24 12:54:05 +02:00
cerr < < " ERROR: " < < unused_exos . str ( ) < < " not used in model block. To bypass this error, use the `nostrict` option. This may lead to crashes or unexpected behavior. " < < endl ;
exit ( EXIT_FAILURE ) ;
2013-11-29 16:03:15 +01:00
}
}
2021-05-04 17:10:36 +02:00
2021-05-04 17:21:47 +02:00
// See dynare#1726
2021-05-04 17:10:36 +02:00
if ( ( stochastic_statement_present | | mod_file_struct . check_present ) & & dynamic_model . mfs > 0 )
{
cerr < < " ERROR: mfs > 0 is incompatible with check, stoch_simul, estimation, osr, ramsey_policy, discretionary_policy, calib_smoother, identification, methods_of_moments and sensitivity commands " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-09-30 17:10:31 +02:00
}
void
2019-12-16 19:42:59 +01:00
ModFile : : transformPass ( bool nostrict , bool stochastic , bool compute_xrefs , bool transform_unary_ops ,
2019-11-18 17:13:49 +01:00
const string & exclude_eqs , const string & include_eqs )
2009-09-30 17:10:31 +02:00
{
2019-08-20 12:50:41 +02:00
/* Save the original model (must be done before any model transformations by preprocessor)
— except substituting out variables which we know are constant ( they
appear in an equation of the form : X = constant )
— except adl operators which we always want expanded
2020-03-02 17:09:09 +01:00
— except predetermined variables ( which must be handled before the call to
setLeadsLagsOrig ( ) , see preprocessor # 47 )
2019-08-20 12:50:41 +02:00
— except diff operators with a lead which have been expanded by
DataTree : AddDiff ( )
*/
2019-11-18 17:13:49 +01:00
dynamic_model . includeExcludeEquations ( exclude_eqs , true ) ;
dynamic_model . includeExcludeEquations ( include_eqs , false ) ;
2019-01-28 17:53:04 +01:00
dynamic_model . simplifyEquations ( ) ;
2018-01-30 10:06:56 +01:00
dynamic_model . substituteAdl ( ) ;
2020-03-02 17:09:09 +01:00
if ( symbol_table . predeterminedNbr ( ) > 0 )
dynamic_model . transformPredeterminedVariables ( ) ;
2017-07-27 23:14:50 +02:00
dynamic_model . setLeadsLagsOrig ( ) ;
2018-10-09 18:27:19 +02:00
original_model = dynamic_model ;
2019-10-16 17:34:27 +02:00
dynamic_model . expandEqTags ( ) ;
2015-02-16 08:31:30 +01:00
2020-11-10 18:04:05 +01:00
// Replace all model-local variables by their expression
dynamic_model . substituteModelLocalVariables ( ) ;
2019-09-25 12:00:40 +02:00
// Check that all declared endogenous are used in equations
2019-09-05 11:24:36 +02:00
set < int > unusedEndogs = dynamic_model . findUnusedEndogenous ( ) ;
bool unusedEndogsIsErr = ! nostrict & & ! mod_file_struct . bvar_present & & unusedEndogs . size ( ) ;
for ( int unusedEndog : unusedEndogs )
if ( nostrict )
{
symbol_table . changeType ( unusedEndog , SymbolType : : unusedEndogenous ) ;
warnings < < " WARNING: ' " < < symbol_table . getName ( unusedEndog )
< < " ' not used in model block, removed by nostrict command-line option " < < endl ;
}
else if ( unusedEndogsIsErr )
cerr < < " Error: " < < symbol_table . getName ( unusedEndog ) < < " not used in the model block " < < endl ;
if ( unusedEndogsIsErr )
exit ( EXIT_FAILURE ) ;
2013-09-13 20:37:31 +02:00
2019-09-25 12:00:40 +02:00
// Declare endogenous used for PAC model-consistent expectations
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2019-10-28 11:09:36 +01:00
if ( auto pms = dynamic_cast < PacModelStatement * > ( statement . get ( ) ) ;
2019-12-16 19:42:59 +01:00
pms )
2019-10-28 11:09:36 +01:00
{
2019-12-16 19:42:59 +01:00
if ( pms - > growth )
2019-10-28 11:09:36 +01:00
pac_growth . push_back ( pms - > growth ) ;
2019-12-16 19:42:59 +01:00
if ( pms - > aux_model_name . empty ( ) )
2019-10-28 11:09:36 +01:00
dynamic_model . declarePacModelConsistentExpectationEndogs ( pms - > name ) ;
}
2019-09-25 12:00:40 +02:00
2019-02-19 12:51:05 +01:00
// Get all equation tags associated with VARs and Trend Component Models
2018-06-05 16:38:37 +02:00
set < string > eqtags ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : trend_component_model_table . getEqTags ( ) )
for ( auto & it1 : it . second )
2018-08-14 14:23:21 +02:00
eqtags . insert ( it1 ) ;
2018-06-05 16:38:37 +02:00
2019-12-20 16:59:30 +01:00
for ( const auto & it : var_model_table . getEqTags ( ) )
for ( auto & it1 : it . second )
2018-08-21 11:46:59 +02:00
eqtags . insert ( it1 ) ;
2019-10-22 14:56:28 +02:00
// Create auxiliary variables and equations for unary ops
lag_equivalence_table_t unary_ops_nodes ;
2018-11-29 16:01:49 +01:00
ExprNode : : subst_table_t unary_ops_subst_table ;
2018-05-30 16:48:08 +02:00
if ( transform_unary_ops )
2019-10-22 14:56:28 +02:00
tie ( unary_ops_nodes , unary_ops_subst_table ) = dynamic_model . substituteUnaryOps ( ) ;
2018-06-07 12:53:00 +02:00
else
2018-08-21 11:46:59 +02:00
// substitute only those unary ops that appear in auxiliary model equations
2019-10-22 14:56:28 +02:00
tie ( unary_ops_nodes , unary_ops_subst_table ) = dynamic_model . substituteUnaryOps ( eqtags ) ;
2018-05-30 16:48:08 +02:00
2019-02-19 16:36:10 +01:00
// Create auxiliary variable and equations for Diff operators
2019-10-22 14:56:28 +02:00
auto [ diff_nodes , diff_subst_table ] = dynamic_model . substituteDiff ( pac_growth ) ;
2018-02-08 13:07:15 +01:00
2018-08-14 14:23:21 +02:00
// Fill Trend Component Model Table
dynamic_model . fillTrendComponentModelTable ( ) ;
2019-10-22 16:04:24 +02:00
original_model . fillTrendComponentModelTableFromOrigModel ( ) ;
2018-09-12 17:56:30 +02:00
dynamic_model . fillTrendComponentmodelTableAREC ( diff_subst_table ) ;
2018-08-21 11:46:59 +02:00
dynamic_model . fillVarModelTable ( ) ;
2019-10-22 16:04:24 +02:00
original_model . fillVarModelTableFromOrigModel ( ) ;
2018-08-14 14:23:21 +02:00
2018-08-21 11:46:59 +02:00
// Pac Model
2019-02-28 19:22:34 +01:00
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2019-12-16 19:42:59 +01:00
if ( auto pms = dynamic_cast < PacModelStatement * > ( statement . get ( ) ) ; pms )
2019-10-28 11:09:36 +01:00
{
2019-12-16 19:42:59 +01:00
if ( pms - > growth )
2019-10-28 11:09:36 +01:00
pms - > overwriteGrowth ( pac_growth . at ( i + + ) ) ;
int max_lag ;
vector < int > lhs ;
vector < bool > nonstationary ;
string aux_model_type ;
if ( trend_component_model_table . isExistingTrendComponentModelName ( pms - > aux_model_name ) )
{
aux_model_type = " trend_component " ;
max_lag = trend_component_model_table . getMaxLag ( pms - > aux_model_name ) + 1 ;
lhs = dynamic_model . getUndiffLHSForPac ( pms - > aux_model_name , diff_subst_table ) ;
// All lhs variables in a trend component model are nonstationary
nonstationary . insert ( nonstationary . end ( ) , trend_component_model_table . getDiff ( pms - > aux_model_name ) . size ( ) , true ) ;
}
else if ( var_model_table . isExistingVarModelName ( pms - > aux_model_name ) )
{
aux_model_type = " var " ;
max_lag = var_model_table . getMaxLag ( pms - > aux_model_name ) ;
lhs = var_model_table . getLhs ( pms - > aux_model_name ) ;
// nonstationary variables in a VAR are those that are in diff
nonstationary = var_model_table . getDiff ( pms - > aux_model_name ) ;
}
2019-12-16 19:42:59 +01:00
else if ( pms - > aux_model_name . empty ( ) )
2019-10-28 11:09:36 +01:00
max_lag = 0 ;
else
{
cerr < < " Error: aux_model_name not recognized as VAR model or Trend Component model " < < endl ;
exit ( EXIT_FAILURE ) ;
}
auto eqtag_and_lag = dynamic_model . walkPacParameters ( pms - > name ) ;
2019-12-16 19:42:59 +01:00
if ( pms - > aux_model_name . empty ( ) )
2019-10-28 11:09:36 +01:00
dynamic_model . addPacModelConsistentExpectationEquation ( pms - > name , symbol_table . getID ( pms - > discount ) ,
eqtag_and_lag , diff_subst_table ) ;
else
dynamic_model . fillPacModelInfo ( pms - > name , lhs , max_lag , aux_model_type ,
eqtag_and_lag , nonstationary , pms - > growth ) ;
dynamic_model . substitutePacExpectation ( pms - > name ) ;
}
2020-09-10 14:24:20 +02:00
dynamic_model . checkNoRemainingPacExpectation ( ) ;
2018-08-21 11:46:59 +02:00
dynamic_model . addEquationsForVar ( ) ;
2011-03-21 18:36:38 +01:00
// Create auxiliary vars for Expectation operator
2018-12-20 17:04:28 +01:00
dynamic_model . substituteExpectation ( mod_file_struct . partial_information ) ;
2011-03-21 18:36:38 +01:00
2010-10-15 19:05:16 +02:00
if ( nonstationary_variables )
{
dynamic_model . detrendEquations ( ) ;
2018-10-09 18:27:19 +02:00
trend_dynamic_model = dynamic_model ;
2010-10-15 19:05:16 +02:00
dynamic_model . removeTrendVariableFromEquations ( ) ;
2019-12-20 16:59:30 +01:00
const auto & trend_symbols = dynamic_model . getTrendSymbolsMap ( ) ;
const auto & nonstationary_symbols = dynamic_model . getNonstationarySymbolsMap ( ) ;
2019-12-04 15:48:33 +01:00
epilogue . detrend ( trend_symbols , nonstationary_symbols ) ;
2010-10-15 19:05:16 +02:00
}
2019-12-11 15:49:29 +01:00
epilogue . toStatic ( ) ;
2016-03-14 07:56:16 +01:00
mod_file_struct . orig_eq_nbr = dynamic_model . equation_number ( ) ;
2014-03-09 09:52:44 +01:00
if ( mod_file_struct . ramsey_model_present )
2011-03-21 18:40:57 +01:00
{
2018-07-31 12:42:08 +02:00
PlannerObjectiveStatement * pos = nullptr ;
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2019-12-16 19:42:59 +01:00
if ( auto pos2 = dynamic_cast < PlannerObjectiveStatement * > ( statement . get ( ) ) ; pos2 )
if ( pos )
2019-10-28 11:09:36 +01:00
{
cerr < < " ERROR: there can only be one planner_objective statement " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
pos = pos2 ;
2019-12-16 19:42:59 +01:00
assert ( pos ) ;
2018-07-31 12:42:08 +02:00
const StaticModel & planner_objective = pos - > getPlannerObjective ( ) ;
2011-03-21 18:40:57 +01:00
/*
clone the model then clone the new equations back to the original because
we have to call computeDerivIDs ( in computeRamseyPolicyFOCs and computingPass )
2017-06-01 19:58:32 +02:00
*/
2016-11-29 14:20:53 +01:00
if ( linear )
2018-10-09 18:27:19 +02:00
orig_ramsey_dynamic_model = dynamic_model ;
ramsey_FOC_equations_dynamic_model = dynamic_model ;
2018-12-20 17:04:28 +01:00
ramsey_FOC_equations_dynamic_model . computeRamseyPolicyFOCs ( planner_objective ) ;
2011-03-21 18:40:57 +01:00
ramsey_FOC_equations_dynamic_model . replaceMyEquations ( dynamic_model ) ;
2016-03-14 07:56:16 +01:00
mod_file_struct . ramsey_eq_nbr = dynamic_model . equation_number ( ) - mod_file_struct . orig_eq_nbr ;
2011-03-21 18:40:57 +01:00
}
2018-08-01 19:41:44 +02:00
/* Handle var_expectation_model statements: collect information about them,
create the new corresponding parameters , and the expressions to replace
the var_expectation statements .
TODO : move information collection to checkPass ( ) , within a new
VarModelTable class * /
map < string , expr_t > var_expectation_subst_table ;
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2018-08-01 19:41:44 +02:00
{
2018-09-05 15:17:21 +02:00
auto vems = dynamic_cast < VarExpectationModelStatement * > ( statement . get ( ) ) ;
2018-08-01 19:41:44 +02:00
if ( ! vems )
continue ;
2018-08-22 16:50:01 +02:00
int max_lag ;
vector < int > lhs ;
2018-08-01 19:41:44 +02:00
auto & model_name = vems - > model_name ;
2018-08-22 16:57:36 +02:00
if ( var_model_table . isExistingVarModelName ( vems - > aux_model_name ) )
2018-08-22 16:50:01 +02:00
{
2018-08-22 16:57:36 +02:00
max_lag = var_model_table . getMaxLag ( vems - > aux_model_name ) ;
lhs = var_model_table . getLhs ( vems - > aux_model_name ) ;
2018-08-22 16:50:01 +02:00
}
2018-08-22 16:57:36 +02:00
else if ( trend_component_model_table . isExistingTrendComponentModelName ( vems - > aux_model_name ) )
2018-08-22 16:50:01 +02:00
{
2018-08-27 14:51:54 +02:00
max_lag = trend_component_model_table . getMaxLag ( vems - > aux_model_name ) + 1 ;
2018-10-12 15:19:36 +02:00
lhs = dynamic_model . getUndiffLHSForPac ( vems - > aux_model_name , diff_subst_table ) ;
2018-08-22 16:50:01 +02:00
}
else
2018-08-01 19:41:44 +02:00
{
2018-08-21 11:46:59 +02:00
cerr < < " ERROR: var_expectation_model " < < model_name
2018-08-22 16:57:36 +02:00
< < " refers to nonexistent auxiliary model " < < vems - > aux_model_name < < endl ;
2018-08-01 19:41:44 +02:00
exit ( EXIT_FAILURE ) ;
}
2018-11-29 16:01:49 +01:00
/* Substitute unary and diff operators in the 'expression' option, then
match the linear combination in the expression option */
2019-10-22 14:56:28 +02:00
vems - > substituteUnaryOpNodes ( unary_ops_nodes , unary_ops_subst_table ) ;
vems - > substituteDiff ( diff_nodes , diff_subst_table ) ;
2018-11-29 16:01:49 +01:00
vems - > matchExpression ( ) ;
2018-08-22 16:50:01 +02:00
/* Create auxiliary parameters and the expression to be substituted into
2018-08-01 19:41:44 +02:00
the var_expectations statement */
auto subst_expr = dynamic_model . Zero ;
2018-08-06 21:36:52 +02:00
for ( int lag = 0 ; lag < max_lag ; lag + + )
2018-08-01 19:41:44 +02:00
for ( auto variable : lhs )
{
string param_name = " var_expectation_model_ " + model_name + ' _ ' + symbol_table . getName ( variable ) + ' _ ' + to_string ( lag ) ;
int new_param_id = symbol_table . addSymbol ( param_name , SymbolType : : parameter ) ;
vems - > aux_params_ids . push_back ( new_param_id ) ;
subst_expr = dynamic_model . AddPlus ( subst_expr ,
dynamic_model . AddTimes ( dynamic_model . AddVariable ( new_param_id ) ,
dynamic_model . AddVariable ( variable , - lag ) ) ) ;
}
if ( var_expectation_subst_table . find ( model_name ) ! = var_expectation_subst_table . end ( ) )
{
cerr < < " ERROR: model name ' " < < model_name < < " ' is used by several var_expectation_model statements " < < endl ;
exit ( EXIT_FAILURE ) ;
}
var_expectation_subst_table [ model_name ] = subst_expr ;
}
// And finally perform the substitutions
dynamic_model . substituteVarExpectation ( var_expectation_subst_table ) ;
2020-12-09 17:32:08 +01:00
dynamic_model . createVariableMapping ( mod_file_struct . orig_eq_nbr +
( mod_file_struct . ramsey_model_present ?
mod_file_struct . ramsey_eq_nbr : 0 ) ) ;
2018-08-01 19:41:44 +02:00
2020-11-09 16:28:32 +01:00
/* Create auxiliary vars for leads and lags greater than 2, on both endos and
exos . The transformation is not exactly the same on stochastic and
deterministic models , because there is no need to take into account the
Jensen inequality on the latter . */
bool deterministic_model = ! ( mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present
| | mod_file_struct . osr_present
| | mod_file_struct . ramsey_policy_present
| | mod_file_struct . discretionary_policy_present
| | mod_file_struct . calib_smoother_present
| | mod_file_struct . identification_present
| | mod_file_struct . mom_estimation_present
| | mod_file_struct . sensitivity_present
| | stochastic ) ;
dynamic_model . substituteEndoLeadGreaterThanTwo ( deterministic_model ) ;
dynamic_model . substituteExoLead ( deterministic_model ) ;
dynamic_model . substituteEndoLagGreaterThanTwo ( deterministic_model ) ;
dynamic_model . substituteExoLag ( deterministic_model ) ;
2009-09-02 15:36:56 +02:00
2018-09-03 15:05:30 +02:00
dynamic_model . updateVarAndTrendModel ( ) ;
2018-08-21 11:46:59 +02:00
2013-04-25 18:09:31 +02:00
if ( differentiate_forward_vars )
2018-12-20 17:04:28 +01:00
dynamic_model . differentiateForwardVars ( differentiate_forward_vars_subset ) ;
2013-04-25 18:09:31 +02:00
2010-06-21 18:40:36 +02:00
if ( mod_file_struct . dsge_var_estimated | | ! mod_file_struct . dsge_var_calibrated . empty ( ) )
2010-06-11 21:19:30 +02:00
try
{
2018-07-17 18:34:07 +02:00
int sid = symbol_table . addSymbol ( " dsge_prior_weight " , SymbolType : : parameter ) ;
2010-06-21 18:40:36 +02:00
if ( ! mod_file_struct . dsge_var_calibrated . empty ( ) )
2018-09-05 15:17:21 +02:00
addStatementAtFront ( make_unique < InitParamStatement > ( sid ,
expressions_tree . AddNonNegativeConstant ( mod_file_struct . dsge_var_calibrated ) ,
symbol_table ) ) ;
2010-06-11 21:19:30 +02:00
}
catch ( SymbolTable : : AlreadyDeclaredException & e )
{
cerr < < " ERROR: dsge_prior_weight should not be declared as a model variable / parameter "
< < " when the dsge_var option is passed to the estimation statement. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-12-03 14:19:32 +01:00
dynamic_model . reorderAuxiliaryEquations ( ) ;
2009-02-27 13:19:25 +01:00
// Freeze the symbol table
symbol_table . freeze ( ) ;
2017-03-06 16:34:08 +01:00
if ( compute_xrefs )
dynamic_model . computeXrefs ( ) ;
2008-10-17 14:52:08 +02:00
/*
2013-09-13 20:37:31 +02:00
Enforce the same number of equations and endogenous , except in three cases :
2014-03-09 09:52:44 +01:00
- ramsey_model , ramsey_policy or discretionary_policy is used
2008-10-17 14:52:08 +02:00
- a BVAR command is used and there is no equation ( standalone BVAR estimation )
2013-09-13 20:37:31 +02:00
- nostrict option is passed and there are more endogs than equations ( dealt with before freeze )
2008-10-17 14:52:08 +02:00
*/
2014-03-09 09:52:44 +01:00
if ( ! ( mod_file_struct . ramsey_model_present | | mod_file_struct . discretionary_policy_present )
2009-11-26 18:25:04 +01:00
& & ! ( mod_file_struct . bvar_present & & dynamic_model . equation_number ( ) = = 0 )
2009-04-14 16:39:53 +02:00
& & ( dynamic_model . equation_number ( ) ! = symbol_table . endo_nbr ( ) ) )
2008-02-03 11:28:36 +01:00
{
2009-04-14 16:39:53 +02:00
cerr < < " ERROR: There are " < < dynamic_model . equation_number ( ) < < " equations but " < < symbol_table . endo_nbr ( ) < < " endogenous variables! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2011-03-21 18:40:57 +01:00
2014-04-09 17:57:17 +02:00
if ( symbol_table . exo_det_nbr ( ) > 0 & & mod_file_struct . perfect_foresight_solver_present )
2011-03-18 12:47:06 +01:00
{
2017-01-31 17:10:39 +01:00
cerr < < " ERROR: A .mod file cannot contain both one of {perfect_foresight_solver, simul} and varexo_det declaration (all exogenous variables are deterministic in this case) " < < endl ;
2011-03-18 12:47:06 +01:00
exit ( EXIT_FAILURE ) ;
}
2011-03-21 18:40:57 +01:00
2013-02-07 11:52:59 +01:00
if ( mod_file_struct . ramsey_policy_present & & symbol_table . exo_det_nbr ( ) > 0 )
{
cerr < < " ERROR: ramsey_policy is incompatible with deterministic exogenous variables " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2014-07-30 17:28:45 +02:00
if ( mod_file_struct . identification_present & & symbol_table . exo_det_nbr ( ) > 0 )
{
cerr < < " ERROR: identification is incompatible with deterministic exogenous variables " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2021-02-22 18:26:21 +01:00
if ( occbin & & ! dynamic_model . hasOccbinTags ( ) )
{
cerr < < " ERROR: the 'occbin' option is present, but there is no equation with the associated tags (bind/relax/pswitch/pcrit) " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( occbin
2021-05-28 12:01:19 +02:00
& & ( mod_file_struct . osr_present | | mod_file_struct . mom_estimation_present
2021-02-22 18:26:21 +01:00
| | mod_file_struct . ramsey_model_present | | mod_file_struct . ramsey_policy_present
| | mod_file_struct . discretionary_policy_present | | mod_file_struct . extended_path_present
2021-05-28 12:01:19 +02:00
| | mod_file_struct . identification_present | | mod_file_struct . sensitivity_present ) )
2021-02-22 18:26:21 +01:00
{
2021-05-28 12:01:19 +02:00
cerr < < " ERROR: the 'occbin' option is not compatible with commands other than 'estimation', 'stoch_simul', and 'calib_smoother'. " < < endl ;
2021-02-22 18:26:21 +01:00
exit ( EXIT_FAILURE ) ;
}
2018-12-20 17:04:28 +01:00
if ( ! mod_file_struct . ramsey_model_present )
cout < < " Found " < < dynamic_model . equation_number ( ) < < " equation(s). " < < endl ;
else
{
cout < < " Found " < < mod_file_struct . orig_eq_nbr < < " equation(s). " < < endl ;
cout < < " Found " < < dynamic_model . equation_number ( ) < < " FOC equation(s) for Ramsey Problem. " < < endl ;
}
2010-06-11 21:19:30 +02:00
2010-06-21 18:40:36 +02:00
if ( symbol_table . exists ( " dsge_prior_weight " ) )
2010-06-11 21:19:30 +02:00
if ( mod_file_struct . bayesian_irf_present )
{
if ( symbol_table . exo_nbr ( ) ! = symbol_table . observedVariablesNbr ( ) )
{
2010-06-21 18:40:36 +02:00
cerr < < " ERROR: When estimating a DSGE-Var and the bayesian_irf option is passed to the estimation "
< < " statement, the number of shocks must equal the number of observed variables. " < < endl ;
2010-06-11 21:19:30 +02:00
exit ( EXIT_FAILURE ) ;
}
}
else
if ( symbol_table . exo_nbr ( ) < symbol_table . observedVariablesNbr ( ) )
{
2010-06-21 18:40:36 +02:00
cerr < < " ERROR: When estimating a DSGE-Var, the number of shocks must be "
< < " greater than or equal to the number of observed variables. " < < endl ;
2010-06-11 21:19:30 +02:00
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
}
void
2021-01-08 14:55:15 +01:00
ModFile : : computingPass ( bool no_tmp_terms , OutputType output , int params_derivs_order )
2008-02-03 11:28:36 +01:00
{
// Mod file may have no equation (for example in a standalone BVAR estimation)
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2008-02-03 11:28:36 +01:00
{
2013-10-29 11:46:54 +01:00
if ( nonstationary_variables )
trend_dynamic_model . runTrendTest ( global_eval_context ) ;
2010-10-15 19:05:16 +02:00
2009-04-14 16:39:53 +02:00
// Compute static model and its derivatives
2018-10-10 17:08:54 +02:00
static_model = static_cast < StaticModel > ( dynamic_model ) ;
2011-02-04 16:25:38 +01:00
if ( ! no_static )
2017-06-01 19:58:32 +02:00
{
if ( mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
| | mod_file_struct . ramsey_model_present | | mod_file_struct . identification_present
2020-07-08 18:42:14 +02:00
| | mod_file_struct . calib_smoother_present | | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
static_model . set_cutoff_to_zero ( ) ;
2018-11-22 14:32:40 +01:00
int derivsOrder = 1 ;
2016-05-18 12:26:19 +02:00
int paramsDerivsOrder = 0 ;
if ( mod_file_struct . identification_present | | mod_file_struct . estimation_analytic_derivation )
2020-12-11 13:27:23 +01:00
derivsOrder = 2 ;
if ( mod_file_struct . identification_present
| | mod_file_struct . estimation_analytic_derivation
2021-01-08 15:04:13 +01:00
| | ( mod_file_struct . GMM_present & & ( mod_file_struct . analytic_standard_errors_present | | mod_file_struct . analytic_jacobian_present ) ) )
2020-12-11 13:27:23 +01:00
paramsDerivsOrder = params_derivs_order ;
2020-05-20 11:39:59 +02:00
static_model . computingPass ( derivsOrder , paramsDerivsOrder , global_eval_context , no_tmp_terms , block , bytecode ) ;
2017-06-01 19:58:32 +02:00
}
2009-04-14 16:39:53 +02:00
// Set things to compute for dynamic model
2014-04-09 17:57:17 +02:00
if ( mod_file_struct . perfect_foresight_solver_present | | mod_file_struct . check_present
2017-06-01 19:58:32 +02:00
| | mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
| | mod_file_struct . ramsey_model_present | | mod_file_struct . identification_present
2020-07-08 18:42:14 +02:00
| | mod_file_struct . calib_smoother_present | | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
{
if ( mod_file_struct . perfect_foresight_solver_present )
2021-01-08 14:55:15 +01:00
{
int derivsOrder = 1 ;
if ( output = = OutputType : : second )
derivsOrder = 2 ;
else if ( output = = OutputType : : third )
derivsOrder = 3 ;
2021-01-25 18:03:37 +01:00
dynamic_model . computingPass ( true , derivsOrder , 0 , global_eval_context , no_tmp_terms , block , use_dll , bytecode ) ;
2021-01-08 14:55:15 +01:00
}
2017-06-01 19:58:32 +02:00
else
{
if ( mod_file_struct . stoch_simul_present
| | mod_file_struct . estimation_present | | mod_file_struct . osr_present
| | mod_file_struct . ramsey_model_present | | mod_file_struct . identification_present
2020-07-08 18:42:14 +02:00
| | mod_file_struct . calib_smoother_present | | mod_file_struct . mom_estimation_present )
2017-06-01 19:58:32 +02:00
dynamic_model . set_cutoff_to_zero ( ) ;
2019-04-12 15:41:52 +02:00
if ( mod_file_struct . order_option < 1 )
2017-06-01 19:58:32 +02:00
{
cerr < < " ERROR: Incorrect order option... " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2020-12-11 13:27:23 +01:00
int derivsOrder = max ( mod_file_struct . order_option , mod_file_struct . identification_order + 1 ) ; // See preprocessor#40
2021-01-08 15:04:13 +01:00
if ( mod_file_struct . GMM_present
& & ( mod_file_struct . analytic_standard_errors_present | | mod_file_struct . analytic_jacobian_present ) ) //analytic_standard_errors or analytic_jacobian require one order more
2020-12-11 13:27:23 +01:00
derivsOrder = max ( mod_file_struct . order_option ,
max ( mod_file_struct . identification_order , mod_file_struct . mom_order ) + 1 ) ; // See preprocessor#40
2021-01-08 14:55:15 +01:00
if ( mod_file_struct . sensitivity_present | | linear | | output = = OutputType : : second )
2018-11-22 14:32:40 +01:00
derivsOrder = max ( derivsOrder , 2 ) ;
2021-01-08 14:55:15 +01:00
if ( mod_file_struct . estimation_analytic_derivation | | output = = OutputType : : third )
2018-11-22 14:32:40 +01:00
derivsOrder = max ( derivsOrder , 3 ) ;
2017-06-01 19:58:32 +02:00
int paramsDerivsOrder = 0 ;
2020-12-11 13:27:23 +01:00
if ( mod_file_struct . identification_present
| | mod_file_struct . estimation_analytic_derivation
2021-01-08 15:04:13 +01:00
| | ( mod_file_struct . GMM_present & & ( mod_file_struct . analytic_standard_errors_present | | mod_file_struct . analytic_jacobian_present ) ) )
2017-06-01 19:58:32 +02:00
paramsDerivsOrder = params_derivs_order ;
2021-01-25 18:03:37 +01:00
dynamic_model . computingPass ( true , derivsOrder , paramsDerivsOrder , global_eval_context , no_tmp_terms , block , use_dll , bytecode ) ;
2017-06-01 19:58:32 +02:00
if ( linear & & mod_file_struct . ramsey_model_present )
2021-01-25 18:03:37 +01:00
orig_ramsey_dynamic_model . computingPass ( true , 2 , paramsDerivsOrder , global_eval_context , no_tmp_terms , block , use_dll , bytecode ) ;
2017-06-01 19:58:32 +02:00
}
}
else // No computing task requested, compute derivatives up to 2nd order by default
2021-01-25 18:03:37 +01:00
dynamic_model . computingPass ( true , 2 , 0 , global_eval_context , no_tmp_terms , block , use_dll , bytecode ) ;
2017-06-01 19:58:32 +02:00
2019-12-13 17:15:03 +01:00
/* Check that the model is linear.
FIXME : this check always passes if derivsOrder = 1 , i . e . for a perfect
foresight model , because the Hessian is not computed in that case . */
if ( linear )
2018-01-11 12:55:36 +01:00
{
2019-12-13 17:15:03 +01:00
set < int > eqs ;
if ( mod_file_struct . ramsey_model_present )
eqs = orig_ramsey_dynamic_model . getNonZeroHessianEquations ( ) ;
else
eqs = dynamic_model . getNonZeroHessianEquations ( ) ;
if ( ! eqs . empty ( ) )
2016-07-27 21:01:54 +02:00
{
2019-12-13 17:15:03 +01:00
cerr < < " ERROR: If the model is declared linear the second derivatives must be equal to zero. " < < endl
< < " The following equations have non-zero second derivatives: " < < endl ;
for ( const auto & it : eqs )
{
cerr < < " * Eq # " < < it + 1 ;
auto tags = dynamic_model . getEquationTags ( it ) ;
if ( auto it2 = tags . find ( " name " ) ; it2 ! = tags . end ( ) )
cerr < < " [ " < < it2 - > second < < " ] " ;
cerr < < endl ;
}
exit ( EXIT_FAILURE ) ;
2016-07-27 21:01:54 +02:00
}
2016-07-25 19:43:34 +02:00
}
2008-02-03 11:28:36 +01:00
}
2009-04-20 12:48:54 +02:00
2019-12-20 16:59:30 +01:00
for ( auto & statement : statements )
2021-06-04 16:20:29 +02:00
statement - > computingPass ( mod_file_struct ) ;
2018-09-03 17:16:28 +02:00
2018-12-20 17:04:28 +01:00
// Compute epilogue derivatives (but silence standard output)
streambuf * oldcout = cout . rdbuf ( ) ;
cout . rdbuf ( nullptr ) ;
2021-01-25 18:03:37 +01:00
epilogue . computingPass ( true , 2 , 0 , global_eval_context , true , false , false , false ) ;
2018-12-20 17:04:28 +01:00
cout . rdbuf ( oldcout ) ;
2008-02-03 11:28:36 +01:00
}
void
2021-01-08 14:55:15 +01:00
ModFile : : writeMOutput ( const string & basename , bool clear_all , bool clear_global , bool no_warn ,
bool console , bool nograph , bool nointeractive , const ConfigFile & config_file ,
bool check_model_changes , bool minimal_workspace , bool compute_xrefs ,
const string & mexext ,
const filesystem : : path & matlabroot ,
const filesystem : : path & dynareroot , bool onlymodel , bool gui , bool notime ) const
2008-02-03 11:28:36 +01:00
{
2019-10-07 11:29:11 +02:00
bool hasModelChanged = ! dynamic_model . isChecksumMatching ( basename , block ) | | ! check_model_changes ;
2018-06-27 15:01:31 +02:00
if ( hasModelChanged )
{
// Erase possible remnants of previous runs
2018-07-09 18:18:26 +02:00
/* Under MATLAB+Windows (but not under Octave nor under GNU/Linux or
macOS ) , if we directly remove the " + " subdirectory , then the
preprocessor is not able to recreate it afterwards ( presumably because
MATLAB maintains some sort of lock on it ) . The workaround is to rename
2019-09-11 17:03:37 +02:00
it before deleting it ( the renaming must occur in the same directory ,
otherwise it may file if the destination is not on the same
filesystem ) . */
2019-12-06 15:19:23 +01:00
if ( filesystem : : path plusfolder { " + " + basename } ; filesystem : : exists ( plusfolder ) )
2019-12-20 16:59:30 +01:00
{
2019-12-06 15:19:23 +01:00
if ( filesystem : : exists ( plusfolder / " +objective " ) )
{
// Do it recursively for the +objective folder, created by ramsey_policy
auto tmp2 = unique_path ( ) ;
filesystem : : rename ( plusfolder / " +objective " , tmp2 ) ;
filesystem : : remove_all ( tmp2 ) ;
}
2019-12-20 16:59:30 +01:00
auto tmp = unique_path ( ) ;
filesystem : : rename ( plusfolder , tmp ) ;
filesystem : : remove_all ( tmp ) ;
}
2019-04-04 17:01:37 +02:00
filesystem : : remove_all ( basename + " /model/src " ) ;
filesystem : : remove_all ( basename + " /model/bytecode " ) ;
2018-06-27 15:01:31 +02:00
}
2008-02-03 11:28:36 +01:00
ofstream mOutputFile ;
2009-10-06 10:56:02 +02:00
2008-02-03 11:28:36 +01:00
if ( basename . size ( ) )
{
2019-04-04 17:01:37 +02:00
filesystem : : create_directory ( " + " + basename ) ;
2018-06-27 15:01:31 +02:00
string fname = " + " + basename + " /driver.m " ;
2018-06-27 15:12:12 +02:00
mOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2008-02-03 11:28:36 +01:00
if ( ! mOutputFile . is_open ( ) )
{
2015-06-30 12:12:49 +02:00
cerr < < " ERROR: Can't open file " < < fname < < " for writing " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
}
else
{
2008-09-29 12:16:13 +02:00
cerr < < " ERROR: Missing file name " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2008-06-16 18:33:28 +02:00
mOutputFile < < " % " < < endl
2015-06-30 12:12:49 +02:00
< < " % Status : main Dynare file " < < endl
2008-06-16 18:33:28 +02:00
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl ;
2008-02-03 11:28:36 +01:00
2013-02-26 16:50:05 +01:00
if ( no_warn )
mOutputFile < < " warning off " < < endl ; // This will be executed *after* function warning_config()
2008-02-03 11:28:36 +01:00
if ( clear_all )
2015-09-30 22:52:48 +02:00
mOutputFile < < " if isoctave || matlab_ver_less_than('8.6') " < < endl
< < " clear all " < < endl
2017-06-01 19:58:32 +02:00
< < " else " < < endl
< < " clearvars -global " < < endl
< < " clear_persistent_variables(fileparts(which('dynare')), false) " < < endl
< < " end " < < endl ;
2014-12-30 21:51:33 +01:00
else if ( clear_global )
2015-04-04 19:22:49 +02:00
mOutputFile < < " clear M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info ys0_ ex0_; " < < endl ;
2009-04-30 15:05:21 +02:00
2020-04-06 09:29:57 +02:00
if ( ! notime )
mOutputFile < < " tic0 = tic; " < < endl ;
mOutputFile < < " % Define global variables. " < < endl
2015-04-04 19:22:49 +02:00
< < " global M_ options_ oo_ estim_params_ bayestopt_ dataset_ dataset_info estimation_info ys0_ ex0_ " < < endl
2009-04-30 15:05:21 +02:00
< < " options_ = []; " < < endl
< < " M_.fname = ' " < < basename < < " '; " < < endl
2015-04-30 12:35:33 +02:00
< < " M_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
< < " oo_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
< < " options_.dynare_version = ' " < < PACKAGE_VERSION < < " '; " < < endl
2009-04-30 15:05:21 +02:00
< < " % " < < endl
< < " % Some global variables initialization " < < endl
2012-06-06 16:07:59 +02:00
< < " % " < < endl ;
2018-11-07 15:24:57 +01:00
if ( ! onlymodel )
config_file . writeHooks ( mOutputFile ) ;
2021-01-06 14:19:33 +01:00
mOutputFile < < " global_initialization; " < < endl ;
2009-04-30 15:05:21 +02:00
2015-05-28 11:42:12 +02:00
if ( minimal_workspace )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.minimal_workspace = true; " < < endl ;
2015-05-28 11:42:12 +02:00
2010-10-28 11:19:11 +02:00
if ( console )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.console_mode = true; " < < endl
< < " options_.nodisplay = true; " < < endl ;
2013-07-10 11:03:48 +02:00
if ( nograph )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.nograph = true; " < < endl ;
2013-07-10 12:02:12 +02:00
if ( nointeractive )
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.nointeractive = true; " < < endl ;
2015-07-30 14:40:03 +02:00
if ( param_used_with_lead_lag )
mOutputFile < < " M_.parameter_used_with_lead_lag = true; " < < endl ;
2018-12-20 17:04:28 +01:00
cout < < " Processing outputs ... " < < endl ;
2008-02-03 11:28:36 +01:00
symbol_table . writeOutput ( mOutputFile ) ;
2020-09-25 23:23:38 +02:00
// Fill the fields related to solve_algo={12,14} if possible.
mOutputFile < < " M_ = setup_solvers(M_); " < < endl ;
2018-09-06 17:53:07 +02:00
var_model_table . writeOutput ( basename , mOutputFile ) ;
2018-09-07 10:56:40 +02:00
trend_component_model_table . writeOutput ( basename , mOutputFile ) ;
2018-08-14 14:23:21 +02:00
2013-10-28 15:29:41 +01:00
// Initialize M_.Sigma_e, M_.Correlation_matrix, M_.H, and M_.Correlation_matrix_ME
2010-04-14 15:03:41 +02:00
mOutputFile < < " M_.Sigma_e = zeros( " < < symbol_table . exo_nbr ( ) < < " , "
2013-10-28 15:29:41 +01:00
< < symbol_table . exo_nbr ( ) < < " ); " < < endl
< < " M_.Correlation_matrix = eye( " < < symbol_table . exo_nbr ( ) < < " , "
2010-04-14 15:03:41 +02:00
< < symbol_table . exo_nbr ( ) < < " ); " < < endl ;
if ( mod_file_struct . calibrated_measurement_errors )
mOutputFile < < " M_.H = zeros( " < < symbol_table . observedVariablesNbr ( ) < < " , "
2013-10-28 15:29:41 +01:00
< < symbol_table . observedVariablesNbr ( ) < < " ); " < < endl
< < " M_.Correlation_matrix_ME = eye( " < < symbol_table . observedVariablesNbr ( ) < < " , "
2010-04-14 15:03:41 +02:00
< < symbol_table . observedVariablesNbr ( ) < < " ); " < < endl ;
else
2013-10-28 15:29:41 +01:00
mOutputFile < < " M_.H = 0; " < < endl
< < " M_.Correlation_matrix_ME = 1; " < < endl ;
2010-04-14 15:03:41 +02:00
2014-04-10 11:43:26 +02:00
// May be later modified by a shocks block
2019-03-19 14:05:41 +01:00
mOutputFile < < " M_.sigma_e_is_diagonal = true; " < < endl ;
2014-04-10 11:43:26 +02:00
2014-04-09 18:33:24 +02:00
// Initialize M_.det_shocks
mOutputFile < < " M_.det_shocks = []; " < < endl ;
2019-03-19 14:05:41 +01:00
auto to_matlab_logical = [ ] ( bool m ) { return m ? " true " : " false " ; } ;
2008-02-03 11:28:36 +01:00
2019-03-19 14:05:41 +01:00
mOutputFile < < " options_.linear = " < < to_matlab_logical ( linear ) < < " ; " < < endl
< < " options_.block = " < < to_matlab_logical ( block ) < < " ; " < < endl
2020-05-20 11:39:59 +02:00
< < " options_.bytecode = " < < to_matlab_logical ( bytecode ) < < " ; " < < endl
2021-01-25 18:03:37 +01:00
< < " options_.use_dll = " < < to_matlab_logical ( use_dll ) < < " ; " < < endl ;
2009-09-02 15:36:56 +02:00
2013-05-31 14:47:28 +02:00
if ( parallel_local_files . size ( ) > 0 )
{
mOutputFile < < " options_.parallel_info.local_files = { " < < endl ;
2019-12-20 16:59:30 +01:00
for ( const auto & parallel_local_file : parallel_local_files )
2013-05-31 14:47:28 +02:00
{
2019-04-03 16:32:52 +02:00
size_t j = parallel_local_file . find_last_of ( R " (/ \ ) " ) ;
2013-05-31 14:47:28 +02:00
if ( j = = string : : npos )
2018-06-04 12:26:16 +02:00
mOutputFile < < " '', ' " < < parallel_local_file < < " '; " < < endl ;
2013-05-31 14:47:28 +02:00
else
2018-06-04 12:26:16 +02:00
mOutputFile < < " ' " < < parallel_local_file . substr ( 0 , j + 1 ) < < " ', ' "
< < parallel_local_file . substr ( j + 1 , string : : npos ) < < " '; " < < endl ;
2013-05-31 14:47:28 +02:00
}
mOutputFile < < " }; " < < endl ;
}
2019-12-13 17:15:03 +01:00
if ( dynamic_model . isHessianComputed ( ) )
{
mOutputFile < < " M_.nonzero_hessian_eqs = " ;
dynamic_model . printNonZeroHessianEquations ( mOutputFile ) ;
mOutputFile < < " ; " < < endl
< < " M_.hessian_eq_zero = isempty(M_.nonzero_hessian_eqs); " < < endl ;
}
2016-11-14 12:30:52 +01:00
2018-11-07 15:24:57 +01:00
if ( ! onlymodel )
config_file . writeCluster ( mOutputFile ) ;
2010-10-25 18:20:58 +02:00
2020-05-20 11:39:59 +02:00
if ( bytecode )
2009-09-03 18:34:15 +02:00
mOutputFile < < " if exist('bytecode') ~= 3 " < < endl
< < " error('DYNARE: Can''t find bytecode DLL. Please compile it or remove the ''bytecode'' option.') " < < endl
< < " end " < < endl ;
2016-03-14 07:56:16 +01:00
mOutputFile < < " M_.orig_eq_nbr = " < < mod_file_struct . orig_eq_nbr < < " ; " < < endl
2014-10-13 17:25:08 +02:00
< < " M_.eq_nbr = " < < dynamic_model . equation_number ( ) < < " ; " < < endl
2017-08-29 10:58:39 +02:00
< < " M_.ramsey_eq_nbr = " < < mod_file_struct . ramsey_eq_nbr < < " ; " < < endl
2018-06-27 15:01:31 +02:00
< < " M_.set_auxiliary_variables = exist(['./+' M_.fname '/set_auxiliary_variables.m'], 'file') == 2; " < < endl ;
2011-03-21 18:40:57 +01:00
2019-12-11 12:20:13 +01:00
epilogue . writeOutput ( mOutputFile ) ;
2009-04-14 16:39:53 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2008-02-03 11:28:36 +01:00
{
2021-02-22 18:26:21 +01:00
dynamic_model . writeDriverOutput ( mOutputFile , basename , block , use_dll , occbin , mod_file_struct . estimation_present , compute_xrefs ) ;
2010-09-17 11:23:00 +02:00
if ( ! no_static )
2020-05-20 11:44:40 +02:00
static_model . writeDriverOutput ( mOutputFile , block ) ;
2008-02-03 11:28:36 +01:00
}
2021-02-22 18:26:21 +01:00
if ( occbin )
2021-05-28 12:01:19 +02:00
mOutputFile < < " options_ = occbin.set_default_options(options_, M_); " < < endl
< < " M_ = occbin.get_info(M_); " < < endl ;
2021-02-22 18:26:21 +01:00
2020-02-06 15:25:14 +01:00
if ( onlymodel | | gui )
2020-02-06 15:26:12 +01:00
for ( const auto & statement : statements )
2018-11-07 15:24:57 +01:00
{
2018-12-27 12:06:39 +01:00
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
2019-12-16 19:42:59 +01:00
if ( auto ivs = dynamic_cast < InitValStatement * > ( statement . get ( ) ) ; ivs )
2018-12-27 12:06:39 +01:00
{
ivs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
ivs - > writeOutputPostInit ( mOutputFile ) ;
}
// Special treatment for endval block: insert initial values for the auxiliary variables
2019-12-16 19:42:59 +01:00
if ( auto evs = dynamic_cast < EndValStatement * > ( statement . get ( ) ) ; evs )
2018-12-27 12:06:39 +01:00
{
evs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
}
2019-12-16 19:42:59 +01:00
if ( auto ips = dynamic_cast < InitParamStatement * > ( statement . get ( ) ) ; ips )
2018-11-07 15:24:57 +01:00
ips - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2009-09-30 17:10:31 +02:00
2019-12-16 19:42:59 +01:00
if ( auto ss = dynamic_cast < ShocksStatement * > ( statement . get ( ) ) ; ss )
2018-11-07 15:24:57 +01:00
ss - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2018-12-27 19:07:51 +01:00
2019-12-16 19:42:59 +01:00
if ( auto eps = dynamic_cast < EstimatedParamsStatement * > ( statement . get ( ) ) ; eps )
2018-12-27 19:07:51 +01:00
eps - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2019-07-22 23:18:01 +02:00
2019-12-16 19:42:59 +01:00
if ( auto sgs = dynamic_cast < ShockGroupsStatement * > ( statement . get ( ) ) ; sgs )
2019-07-22 23:18:01 +02:00
sgs - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2020-02-06 15:25:14 +01:00
if ( gui )
if ( auto it = dynamic_cast < NativeStatement * > ( statement . get ( ) ) ; it )
it - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
2018-11-07 15:24:57 +01:00
}
else
{
2020-02-06 15:26:12 +01:00
for ( const auto & statement : statements )
2009-09-30 17:10:31 +02:00
{
2018-11-07 15:24:57 +01:00
statement - > writeOutput ( mOutputFile , basename , minimal_workspace ) ;
/* Special treatment for initval block: insert initial values for the
auxiliary variables and initialize exo det */
2019-12-16 19:42:59 +01:00
if ( auto ivs = dynamic_cast < InitValStatement * > ( statement . get ( ) ) ; ivs )
2018-11-07 15:24:57 +01:00
{
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
ivs - > writeOutputPostInit ( mOutputFile ) ;
}
2009-09-30 17:10:31 +02:00
2018-11-07 15:24:57 +01:00
// Special treatment for endval block: insert initial values for the auxiliary variables
2019-12-16 19:42:59 +01:00
if ( auto evs = dynamic_cast < EndValStatement * > ( statement . get ( ) ) ; evs )
2018-11-07 15:24:57 +01:00
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
2013-04-22 17:29:59 +02:00
2018-11-07 15:24:57 +01:00
// Special treatment for load params and steady state statement: insert initial values for the auxiliary variables
2019-10-28 11:09:36 +01:00
if ( auto lpass = dynamic_cast < LoadParamsAndSteadyStateStatement * > ( statement . get ( ) ) ; lpass & & ! no_static )
2018-11-07 15:24:57 +01:00
static_model . writeAuxVarInitval ( mOutputFile , ExprNodeOutputType : : matlabOutsideModel ) ;
}
2008-02-03 11:28:36 +01:00
2021-02-04 10:48:59 +01:00
if ( ! notime )
mOutputFile < < endl < < endl
< < " oo_.time = toc(tic0); " < < endl
< < " disp(['Total computing time : ' dynsec2hms(oo_.time) ]); " < < endl ;
2018-11-07 15:24:57 +01:00
mOutputFile < < " save(' " < < basename < < " _results.mat', 'oo_', 'M_', 'options_'); " < < endl
< < " if exist('estim_params_', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'estim_params_', '-append'); " < < endl < < " end " < < endl
< < " if exist('bayestopt_', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'bayestopt_', '-append'); " < < endl < < " end " < < endl
< < " if exist('dataset_', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'dataset_', '-append'); " < < endl < < " end " < < endl
< < " if exist('estimation_info', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'estimation_info', '-append'); " < < endl < < " end " < < endl
< < " if exist('dataset_info', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'dataset_info', '-append'); " < < endl < < " end " < < endl
< < " if exist('oo_recursive_', 'var') == 1 " < < endl
< < " save(' " < < basename < < " _results.mat', 'oo_recursive_', '-append'); " < < endl < < " end " < < endl ;
config_file . writeEndParallel ( mOutputFile ) ;
2020-04-06 09:29:57 +02:00
2018-11-07 15:24:57 +01:00
if ( ! no_warn )
{
if ( warnings . countWarnings ( ) > 0 )
mOutputFile < < " disp('Note: " < < warnings . countWarnings ( ) < < " warning(s) encountered in the preprocessor') " < < endl ;
2013-03-05 12:53:37 +01:00
2018-11-07 15:24:57 +01:00
mOutputFile < < " if ~isempty(lastwarn) " < < endl
< < " disp('Note: warning(s) encountered in MATLAB/Octave code') " < < endl
< < " end " < < endl ;
}
2013-02-26 16:50:05 +01:00
}
2012-01-23 16:52:27 +01:00
2008-02-03 11:28:36 +01:00
mOutputFile . close ( ) ;
2009-04-30 15:05:21 +02:00
2015-05-10 18:16:11 +02:00
if ( hasModelChanged )
2009-07-07 16:20:48 +02:00
{
2015-05-10 18:16:11 +02:00
// Create static and dynamic files
if ( dynamic_model . equation_number ( ) > 0 )
2017-06-01 19:58:32 +02:00
{
if ( ! no_static )
{
2020-05-20 11:39:59 +02:00
static_model . writeStaticFile ( basename , block , bytecode , use_dll , mexext , matlabroot , dynareroot , false ) ;
2017-06-01 19:58:32 +02:00
static_model . writeParamsDerivativesFile ( basename , false ) ;
}
2009-12-16 14:21:31 +01:00
2021-01-25 18:03:37 +01:00
dynamic_model . writeDynamicFile ( basename , block , bytecode , use_dll , mexext , matlabroot , dynareroot , false ) ;
2018-09-21 17:13:19 +02:00
2017-06-01 19:58:32 +02:00
dynamic_model . writeParamsDerivativesFile ( basename , false ) ;
2019-05-03 19:24:55 +02:00
dynamic_model . writeDynamicJacobianNonZeroElts ( basename ) ;
2017-06-01 19:58:32 +02:00
}
2010-04-23 18:39:07 +02:00
2015-05-10 18:16:11 +02:00
// Create steady state file
2015-07-28 17:27:56 +02:00
steady_state_model . writeSteadyStateFile ( basename , mod_file_struct . ramsey_model_present , false ) ;
2018-09-03 17:16:28 +02:00
// Create epilogue file
epilogue . writeEpilogueFile ( basename ) ;
2015-05-10 18:16:11 +02:00
}
2015-07-21 17:47:56 +02:00
2018-12-20 17:04:28 +01:00
cout < < " done " < < endl ;
2008-02-03 11:28:36 +01:00
}
2015-07-21 17:26:08 +02:00
void
2021-01-08 14:55:15 +01:00
ModFile : : writeJuliaOutput ( const string & basename ) const
2015-07-21 17:47:56 +02:00
{
2015-07-27 15:33:38 +02:00
if ( dynamic_model . equation_number ( ) > 0 )
2015-07-27 17:02:51 +02:00
{
if ( ! no_static )
2015-07-28 12:29:42 +02:00
{
2018-10-26 11:44:26 +02:00
static_model . writeStaticFile ( basename , false , false , false , " " , { } , { } , true ) ;
2015-07-28 12:29:42 +02:00
static_model . writeParamsDerivativesFile ( basename , true ) ;
}
2021-01-25 18:03:37 +01:00
dynamic_model . writeDynamicFile ( basename , block , bytecode , use_dll , " " , { } , { } , true ) ;
2015-07-28 14:59:55 +02:00
dynamic_model . writeParamsDerivativesFile ( basename , true ) ;
2015-07-27 17:02:51 +02:00
}
2015-07-28 17:27:56 +02:00
steady_state_model . writeSteadyStateFile ( basename , mod_file_struct . ramsey_model_present , true ) ;
2015-07-21 17:47:56 +02:00
}
2017-02-02 15:09:43 +01:00
void
2018-12-20 17:04:28 +01:00
ModFile : : writeJsonOutput ( const string & basename , JsonOutputPointType json , JsonFileOutputType json_output_mode , bool onlyjson , bool jsonderivsimple )
2017-02-20 12:18:11 +01:00
{
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : nojson )
2017-02-20 12:18:11 +01:00
return ;
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : parsing | | json = = JsonOutputPointType : : checkpass )
2017-02-20 12:18:11 +01:00
symbol_table . freeze ( ) ;
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-06-29 13:18:59 +02:00
cout < < " //-- BEGIN JSON --// " < < endl
< < " { " < < endl ;
2017-06-29 13:15:32 +02:00
2018-07-18 17:28:05 +02:00
writeJsonOutputParsingCheck ( basename , json_output_mode , json = = JsonOutputPointType : : transformpass , json = = JsonOutputPointType : : computingpass ) ;
2017-02-20 12:18:11 +01:00
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : parsing | | json = = JsonOutputPointType : : checkpass )
2017-02-20 12:18:11 +01:00
symbol_table . unfreeze ( ) ;
2018-07-18 17:28:05 +02:00
if ( json = = JsonOutputPointType : : computingpass )
2017-06-29 12:42:28 +02:00
writeJsonComputingPassOutput ( basename , json_output_mode , jsonderivsimple ) ;
2017-02-20 12:18:11 +01:00
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-06-29 13:18:59 +02:00
cout < < " } " < < endl
< < " //-- END JSON --// " < < endl ;
2017-02-20 12:18:11 +01:00
2018-12-20 17:04:28 +01:00
switch ( json )
{
case JsonOutputPointType : : parsing :
cout < < " JSON written after Parsing step. " < < endl ;
break ;
case JsonOutputPointType : : checkpass :
cout < < " JSON written after Check step. " < < endl ;
break ;
case JsonOutputPointType : : transformpass :
cout < < " JSON written after Transform step. " < < endl ;
break ;
case JsonOutputPointType : : computingpass :
cout < < " JSON written after Computing step. " < < endl ;
break ;
case JsonOutputPointType : : nojson :
cerr < < " ModFile::writeJsonOutput: should not arrive here. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-02-28 14:34:22 +01:00
if ( onlyjson )
exit ( EXIT_SUCCESS ) ;
2017-02-20 12:18:11 +01:00
}
void
2017-06-28 17:11:24 +02:00
ModFile : : writeJsonOutputParsingCheck ( const string & basename , JsonFileOutputType json_output_mode , bool transformpass , bool computingpass ) const
2017-02-02 15:09:43 +01:00
{
ostringstream output ;
output < < " { " < < endl ;
symbol_table . writeJsonOutput ( output ) ;
2017-02-27 15:40:34 +01:00
output < < " , " ;
2017-02-02 15:09:43 +01:00
dynamic_model . writeJsonOutput ( output ) ;
2018-08-22 09:15:00 +02:00
if ( ! statements . empty ( )
2018-08-21 11:46:59 +02:00
| | ! var_model_table . empty ( )
2018-08-22 09:15:00 +02:00
| | ! trend_component_model_table . empty ( ) )
2017-02-02 15:09:43 +01:00
{
2019-04-03 16:32:52 +02:00
output < < R " (, " statements " : [) " ;
2018-08-21 11:46:59 +02:00
if ( ! var_model_table . empty ( ) )
{
var_model_table . writeJsonOutput ( output ) ;
2019-12-20 16:59:30 +01:00
output < < " , " ;
2018-08-21 11:46:59 +02:00
}
2018-08-22 09:15:00 +02:00
if ( ! trend_component_model_table . empty ( ) )
{
trend_component_model_table . writeJsonOutput ( output ) ;
output < < " , " ;
}
2019-12-16 19:42:59 +01:00
for ( auto it = statements . begin ( ) ; it ! = statements . end ( ) ; + + it )
2017-02-02 15:09:43 +01:00
{
2017-02-08 18:29:57 +01:00
if ( it ! = statements . begin ( ) )
output < < " , " < < endl ;
2017-02-02 15:09:43 +01:00
( * it ) - > writeJsonOutput ( output ) ;
}
output < < " ] " < < endl ;
}
2017-06-28 17:11:24 +02:00
if ( computingpass )
{
output < < " , " ;
dynamic_model . writeJsonDynamicModelInfo ( output ) ;
}
2017-02-02 15:09:43 +01:00
output < < " } " < < endl ;
2017-06-28 12:04:04 +02:00
ostringstream original_model_output ;
original_model_output < < " " ;
2017-06-29 13:15:32 +02:00
if ( transformpass | | computingpass )
2017-06-28 12:04:04 +02:00
{
original_model_output < < " { " ;
original_model . writeJsonOriginalModelOutput ( original_model_output ) ;
2019-03-06 11:43:23 +01:00
if ( ! statements . empty ( ) | | ! var_model_table . empty ( ) | | ! trend_component_model_table . empty ( ) )
{
2019-04-03 16:32:52 +02:00
original_model_output < < endl < < R " (, " statements " : [) " ;
2019-03-06 11:43:23 +01:00
if ( ! var_model_table . empty ( ) )
{
var_model_table . writeJsonOutput ( original_model_output ) ;
original_model_output < < " , " ;
}
if ( ! trend_component_model_table . empty ( ) )
{
trend_component_model_table . writeJsonOutput ( original_model_output ) ;
original_model_output < < " , " ;
}
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : statements )
2019-03-06 11:43:23 +01:00
{
original_model_output < < ( i + + > 0 ? " , " : " " ) < < endl ;
it - > writeJsonOutput ( original_model_output ) ;
}
original_model_output < < " ] " < < endl ;
}
2017-06-28 12:04:04 +02:00
original_model_output < < " } " < < endl ;
}
2017-10-16 17:24:55 +02:00
ostringstream steady_state_model_output ;
steady_state_model_output < < " " ;
if ( dynamic_model . equation_number ( ) > 0 )
steady_state_model . writeJsonSteadyStateFile ( steady_state_model_output ,
transformpass | | computingpass ) ;
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-06-28 12:04:04 +02:00
{
2017-06-29 13:15:32 +02:00
if ( transformpass | | computingpass )
2019-04-03 16:32:52 +02:00
cout < < R " ( " transformed_modfile " : ) " ;
2017-06-29 13:15:32 +02:00
else
2019-04-03 16:32:52 +02:00
cout < < R " ( " modfile " : ) " ;
2017-06-28 12:04:04 +02:00
cout < < output . str ( ) ;
if ( ! original_model_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " original_model " : ) " < < original_model_output . str ( ) ;
2017-10-16 17:24:55 +02:00
if ( ! steady_state_model_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " steady_state_model " : ) " < < steady_state_model_output . str ( ) ;
2017-06-28 12:04:04 +02:00
}
2017-02-02 15:09:43 +01:00
else
{
ofstream jsonOutputFile ;
if ( basename . size ( ) )
{
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/json " ) ;
2018-06-27 16:08:31 +02:00
string fname { basename + " /model/json/modfile.json " } ;
2018-06-27 15:12:12 +02:00
jsonOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2017-02-02 15:09:43 +01:00
if ( ! jsonOutputFile . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < fname < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2017-06-14 07:01:31 +02:00
else
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2017-02-02 15:09:43 +01:00
jsonOutputFile < < output . str ( ) ;
jsonOutputFile . close ( ) ;
2017-06-28 12:04:04 +02:00
if ( ! original_model_output . str ( ) . empty ( ) )
{
if ( basename . size ( ) )
{
2018-06-27 16:08:31 +02:00
string fname { basename + " /model/json/modfile-original.json " } ;
2018-06-27 15:12:12 +02:00
jsonOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2017-06-28 12:04:04 +02:00
if ( ! jsonOutputFile . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < fname < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
else
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
jsonOutputFile < < original_model_output . str ( ) ;
jsonOutputFile . close ( ) ;
}
2017-10-16 17:24:55 +02:00
if ( ! steady_state_model_output . str ( ) . empty ( ) )
{
if ( basename . size ( ) )
{
2018-06-27 16:08:31 +02:00
string fname { basename + " /model/json/steady_state_model.json " } ;
2018-06-27 15:12:12 +02:00
jsonOutputFile . open ( fname , ios : : out | ios : : binary ) ;
2017-10-16 17:24:55 +02:00
if ( ! jsonOutputFile . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < fname < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
else
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
jsonOutputFile < < steady_state_model_output . str ( ) ;
jsonOutputFile . close ( ) ;
}
2017-02-02 15:09:43 +01:00
}
}
2017-02-20 12:18:11 +01:00
void
2017-06-29 12:42:28 +02:00
ModFile : : writeJsonComputingPassOutput ( const string & basename , JsonFileOutputType json_output_mode , bool jsonderivsimple ) const
2017-02-20 12:18:11 +01:00
{
2018-07-18 17:28:05 +02:00
if ( basename . empty ( ) & & json_output_mode ! = JsonFileOutputType : : standardout )
2017-06-29 15:03:31 +02:00
{
cerr < < " ERROR: Missing file name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
ostringstream tmp_out , static_output , dynamic_output , static_paramsd_output , dynamic_paramsd_output ;
2017-02-20 12:18:11 +01:00
static_output < < " { " ;
2017-06-29 15:03:31 +02:00
static_model . writeJsonComputingPassOutput ( static_output , ! jsonderivsimple ) ;
static_output < < " } " ;
2017-02-20 12:18:11 +01:00
dynamic_output < < " { " ;
2017-06-29 15:03:31 +02:00
dynamic_model . writeJsonComputingPassOutput ( dynamic_output , ! jsonderivsimple ) ;
dynamic_output < < " } " ;
2017-02-20 12:18:11 +01:00
2017-06-29 15:03:31 +02:00
static_model . writeJsonParamsDerivativesFile ( tmp_out , ! jsonderivsimple ) ;
2017-02-20 12:18:11 +01:00
if ( ! tmp_out . str ( ) . empty ( ) )
static_paramsd_output < < " { " < < tmp_out . str ( ) < < " } " < < endl ;
2017-06-29 15:03:31 +02:00
tmp_out . str ( " " ) ;
dynamic_model . writeJsonParamsDerivativesFile ( tmp_out , ! jsonderivsimple ) ;
if ( ! tmp_out . str ( ) . empty ( ) )
dynamic_paramsd_output < < " { " < < tmp_out . str ( ) < < " } " < < endl ;
2017-03-02 18:34:18 +01:00
2018-07-18 17:28:05 +02:00
if ( json_output_mode = = JsonFileOutputType : : standardout )
2017-02-20 12:18:11 +01:00
{
2019-04-03 16:32:52 +02:00
cout < < R " (, " static_model " : ) " < < static_output . str ( ) < < endl
< < R " (, " dynamic_model " : ) " < < dynamic_output . str ( ) < < endl ;
2017-03-02 18:34:18 +01:00
2017-02-20 12:18:11 +01:00
if ( ! static_paramsd_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " static_params_deriv " : ) " < < static_paramsd_output . str ( ) < < endl ;
2017-03-02 18:34:18 +01:00
if ( ! dynamic_paramsd_output . str ( ) . empty ( ) )
2019-04-03 16:32:52 +02:00
cout < < R " (, " dynamic_params_deriv " : ) " < < dynamic_paramsd_output . str ( ) < < endl ;
2017-02-20 12:18:11 +01:00
}
else
{
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/json " ) ;
2017-02-20 12:18:11 +01:00
2018-06-27 16:08:31 +02:00
writeJsonFileHelper ( basename + " /model/json/static.json " , static_output ) ;
writeJsonFileHelper ( basename + " /model/json/dynamic.json " , dynamic_output ) ;
2017-02-20 12:18:11 +01:00
if ( ! static_paramsd_output . str ( ) . empty ( ) )
2018-06-27 16:08:31 +02:00
writeJsonFileHelper ( basename + " /model/json/static_params_derivs.json " , static_paramsd_output ) ;
2017-02-20 12:18:11 +01:00
if ( ! dynamic_paramsd_output . str ( ) . empty ( ) )
2018-06-27 16:08:31 +02:00
writeJsonFileHelper ( basename + " /model/json/params_derivs.json " , dynamic_paramsd_output ) ;
2017-02-20 12:18:11 +01:00
}
}
2017-03-02 18:34:18 +01:00
void
2018-06-27 16:08:31 +02:00
ModFile : : writeJsonFileHelper ( const string & fname , ostringstream & output ) const
2017-03-02 18:34:18 +01:00
{
ofstream jsonOutput ;
2018-06-27 15:12:12 +02:00
jsonOutput . open ( fname , ios : : out | ios : : binary ) ;
2017-03-02 18:34:18 +01:00
if ( ! jsonOutput . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < fname < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
jsonOutput < < output . str ( ) ;
jsonOutput . close ( ) ;
}
2019-04-04 17:01:37 +02:00
filesystem : : path
ModFile : : unique_path ( )
{
filesystem : : path path ;
string possible_characters = " 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " ;
random_device rd ;
mt19937 generator ( rd ( ) ) ;
uniform_int_distribution < int > distribution { 0 , static_cast < int > ( possible_characters . size ( ) ) - 1 } ;
do
{
constexpr int rand_length = 10 ;
string rand_str ( rand_length , ' \0 ' ) ;
for ( auto & dis : rand_str )
dis = possible_characters [ distribution ( generator ) ] ;
2019-09-11 17:03:37 +02:00
path = rand_str ;
2019-04-04 17:01:37 +02:00
}
while ( filesystem : : exists ( path ) ) ;
return path ;
}