2018-08-14 14:23:21 +02:00
/*
2021-07-01 16:16:04 +02:00
* Copyright © 2018 - 2021 Dynare Team
2018-08-14 14:23:21 +02: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/>.
2018-08-14 14:23:21 +02:00
*/
# include <algorithm>
# include "SubModel.hh"
2021-10-27 16:26:52 +02:00
# include "DynamicModel.hh"
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : TrendComponentModelTable ( SymbolTable & symbol_table_arg ) :
2018-10-04 17:18:27 +02:00
symbol_table { symbol_table_arg }
2018-08-14 14:23:21 +02:00
{
}
void
TrendComponentModelTable : : addTrendComponentModel ( string name_arg ,
vector < string > eqtags_arg ,
2018-09-13 12:21:23 +02:00
vector < string > target_eqtags_arg )
2018-08-14 14:23:21 +02:00
{
if ( isExistingTrendComponentModelName ( name_arg ) )
{
cerr < < " Error: a trend component model already exists with the name " < < name_arg < < endl ;
exit ( EXIT_FAILURE ) ;
}
eqtags [ name_arg ] = move ( eqtags_arg ) ;
2018-09-13 12:21:23 +02:00
target_eqtags [ name_arg ] = move ( target_eqtags_arg ) ;
2018-08-14 14:23:21 +02:00
names . insert ( move ( name_arg ) ) ;
}
void
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : setVals ( map < string , vector < int > > eqnums_arg , map < string , vector < int > > target_eqnums_arg ,
2018-10-24 15:57:07 +02:00
map < string , vector < int > > lhs_arg , map < string , vector < expr_t > > lhs_expr_t_arg )
2018-08-14 14:23:21 +02:00
{
eqnums = move ( eqnums_arg ) ;
2018-09-13 12:21:23 +02:00
target_eqnums = move ( target_eqnums_arg ) ;
2018-09-12 11:56:04 +02:00
lhs = move ( lhs_arg ) ;
lhs_expr_t = move ( lhs_expr_t_arg ) ;
2018-08-14 14:23:21 +02:00
for ( const auto & it : eqnums )
{
vector < int > nontrend_vec ;
for ( auto eq : it . second )
2018-09-13 12:21:23 +02:00
if ( find ( target_eqnums [ it . first ] . begin ( ) , target_eqnums [ it . first ] . end ( ) , eq ) = = target_eqnums [ it . first ] . end ( ) )
2018-08-14 14:23:21 +02:00
nontrend_vec . push_back ( eq ) ;
2018-09-13 12:21:23 +02:00
nontarget_eqnums [ it . first ] = nontrend_vec ;
2018-08-14 14:23:21 +02:00
}
2018-09-12 11:56:04 +02:00
for ( const auto & name : names )
{
2018-09-13 12:21:23 +02:00
vector < int > nontarget_lhs_vec , target_lhs_vec ;
2018-09-12 11:56:04 +02:00
vector < int > lhsv = getLhs ( name ) ;
vector < int > eqnumsv = getEqNums ( name ) ;
2018-09-13 12:21:23 +02:00
for ( int nontrend_it : getNonTargetEqNums ( name ) )
nontarget_lhs_vec . push_back ( lhsv . at ( distance ( eqnumsv . begin ( ) , find ( eqnumsv . begin ( ) , eqnumsv . end ( ) , nontrend_it ) ) ) ) ;
nontarget_lhs [ name ] = nontarget_lhs_vec ;
2018-08-31 12:35:51 +02:00
2018-09-13 12:21:23 +02:00
for ( int trend_it : getTargetEqNums ( name ) )
target_lhs_vec . push_back ( lhsv . at ( distance ( eqnumsv . begin ( ) , find ( eqnumsv . begin ( ) , eqnumsv . end ( ) , trend_it ) ) ) ) ;
target_lhs [ name ] = target_lhs_vec ;
2018-09-12 11:56:04 +02:00
}
2018-08-14 14:23:21 +02:00
}
void
TrendComponentModelTable : : setRhs ( map < string , vector < set < pair < int , int > > > > rhs_arg )
{
rhs = move ( rhs_arg ) ;
}
void
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : setTargetVar ( map < string , vector < int > > target_vars_arg )
2018-08-14 14:23:21 +02:00
{
2018-09-13 12:21:23 +02:00
target_vars = move ( target_vars_arg ) ;
2018-08-14 14:23:21 +02:00
}
void
TrendComponentModelTable : : setMaxLags ( map < string , vector < int > > max_lags_arg )
{
max_lags = move ( max_lags_arg ) ;
}
void
TrendComponentModelTable : : setDiff ( map < string , vector < bool > > diff_arg )
{
diff = move ( diff_arg ) ;
}
void
TrendComponentModelTable : : setOrigDiffVar ( map < string , vector < int > > orig_diff_var_arg )
{
orig_diff_var = move ( orig_diff_var_arg ) ;
}
2018-09-07 10:56:40 +02:00
void
TrendComponentModelTable : : setAR ( map < string , map < tuple < int , int , int > , expr_t > > AR_arg )
{
AR = move ( AR_arg ) ;
}
2018-09-10 17:13:51 +02:00
void
2019-02-19 12:08:00 +01:00
TrendComponentModelTable : : setA0 ( map < string , map < tuple < int , int , int > , expr_t > > A0_arg ,
map < string , map < tuple < int , int , int > , expr_t > > A0star_arg )
2018-09-10 17:13:51 +02:00
{
2019-02-19 12:08:00 +01:00
A0 = move ( A0_arg ) ;
A0star = move ( A0star_arg ) ;
2018-09-10 17:13:51 +02:00
}
2021-07-01 16:16:04 +02:00
const map < string , vector < string > > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getEqTags ( ) const
{
return eqtags ;
}
2021-07-01 16:16:04 +02:00
const vector < string > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getEqTags ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return eqtags . find ( name_arg ) - > second ;
}
void
TrendComponentModelTable : : checkModelName ( const string & name_arg ) const
{
if ( ! isExistingTrendComponentModelName ( name_arg ) )
{
cerr < < name_arg
< < " is not a recognized equation tag of a trend component model equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2019-02-14 11:44:06 +01:00
TrendComponentModelTable : : getNonTargetLhs ( const string & name_arg ) const
2018-09-12 11:56:04 +02:00
{
checkModelName ( name_arg ) ;
2018-09-13 12:21:23 +02:00
return nontarget_lhs . find ( name_arg ) - > second ;
2018-09-12 11:56:04 +02:00
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getTargetLhs ( const string & name_arg ) const
2018-09-12 11:56:04 +02:00
{
checkModelName ( name_arg ) ;
2018-09-13 12:21:23 +02:00
return target_lhs . find ( name_arg ) - > second ;
2018-09-12 11:56:04 +02:00
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getLhs ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return lhs . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < expr_t > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getLhsExprT ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return lhs_expr_t . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const map < string , vector < string > > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getTargetEqTags ( ) const
2018-08-14 14:23:21 +02:00
{
2018-09-13 12:21:23 +02:00
return target_eqtags ;
2018-08-14 14:23:21 +02:00
}
2021-07-01 16:16:04 +02:00
const map < string , vector < int > > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getEqNums ( ) const
{
return eqnums ;
}
2021-07-01 16:16:04 +02:00
const map < string , vector < int > > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getTargetEqNums ( ) const
2018-09-03 15:05:30 +02:00
{
2018-09-13 12:21:23 +02:00
return target_eqnums ;
2018-09-03 15:05:30 +02:00
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getTargetEqNums ( const string & name_arg ) const
2018-09-10 17:13:51 +02:00
{
checkModelName ( name_arg ) ;
2018-09-13 12:21:23 +02:00
return target_eqnums . find ( name_arg ) - > second ;
2018-09-10 17:13:51 +02:00
}
2021-07-01 16:16:04 +02:00
const map < string , vector < int > > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getNonTargetEqNums ( ) const
2018-09-10 17:13:51 +02:00
{
2018-09-13 12:21:23 +02:00
return nontarget_eqnums ;
2018-09-10 17:13:51 +02:00
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-09-13 12:21:23 +02:00
TrendComponentModelTable : : getNonTargetEqNums ( const string & name_arg ) const
2018-08-14 14:23:21 +02:00
{
checkModelName ( name_arg ) ;
2018-09-13 12:21:23 +02:00
return nontarget_eqnums . find ( name_arg ) - > second ;
2018-08-14 14:23:21 +02:00
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getEqNums ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return eqnums . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getMaxLags ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return max_lags . find ( name_arg ) - > second ;
}
int
TrendComponentModelTable : : getMaxLag ( const string & name_arg ) const
{
int max_lag_int = 0 ;
for ( auto it : getMaxLags ( name_arg ) )
max_lag_int = max ( max_lag_int , it ) ;
return max_lag_int ;
}
2021-07-01 16:16:04 +02:00
const vector < bool > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getDiff ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return diff . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-14 14:23:21 +02:00
TrendComponentModelTable : : getOrigDiffVar ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return orig_diff_var . find ( name_arg ) - > second ;
}
void
2018-09-07 10:56:40 +02:00
TrendComponentModelTable : : writeOutput ( const string & basename , ostream & output ) const
2018-08-14 14:23:21 +02:00
{
2018-09-25 12:17:34 +02:00
if ( names . empty ( ) )
return ;
2019-02-19 12:08:00 +01:00
string filename = " + " + basename + " /trend_component_ar_a0.m " ;
2018-09-10 17:13:51 +02:00
ofstream ar_ec_output ;
ar_ec_output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! ar_ec_output . is_open ( ) )
2018-09-07 10:56:40 +02:00
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-19 12:08:00 +01:00
ar_ec_output < < " function [AR, A0, A0star] = trend_component_ar_a0(model_name, params) " < < endl
2019-12-20 16:59:30 +01:00
< < " %function [AR, A0, A0star] = trend_component_ar_a0(model_name, params) " < < endl
< < " % File automatically generated by the Dynare preprocessor " < < endl < < endl ;
2018-09-07 10:56:40 +02:00
2018-08-14 14:23:21 +02:00
for ( const auto & name : names )
{
2018-08-20 10:50:28 +02:00
output < < " M_.trend_component. " < < name < < " .model_name = ' " < < name < < " '; " < < endl
2018-08-14 14:23:21 +02:00
< < " M_.trend_component. " < < name < < " .eqtags = { " ;
for ( const auto & it : eqtags . at ( name ) )
output < < " ' " < < it < < " '; " ;
output < < " }; " < < endl
< < " M_.trend_component. " < < name < < " .eqn = [ " ;
for ( auto it : eqnums . at ( name ) )
output < < it + 1 < < " " ;
output < < " ]; " < < endl
2018-09-13 12:21:23 +02:00
< < " M_.trend_component. " < < name < < " .targets = [ " ;
2018-08-14 14:23:21 +02:00
for ( auto it : eqnums . at ( name ) )
2018-09-13 12:21:23 +02:00
if ( find ( target_eqnums . at ( name ) . begin ( ) , target_eqnums . at ( name ) . end ( ) , it )
= = target_eqnums . at ( name ) . end ( ) )
2018-08-14 14:23:21 +02:00
output < < " false " ;
else
output < < " true " ;
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .lhs = [ " ;
for ( auto it : lhs . at ( name ) )
output < < symbol_table . getTypeSpecificID ( it ) + 1 < < " " ;
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .max_lag = [ " ;
for ( auto it : max_lags . at ( name ) )
output < < it < < " " ;
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .diff = [ " ;
for ( const auto & it : diff . at ( name ) )
output < < ( it ? " true " : " false " ) < < " " ;
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .orig_diff_var = [ " ;
for ( auto it : orig_diff_var . at ( name ) )
output < < ( it > = 0 ? symbol_table . getTypeSpecificID ( it ) + 1 : - 1 ) < < " " ;
2018-08-22 14:29:07 +02:00
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .nonstationary = [ " ;
2018-10-24 15:57:07 +02:00
for ( size_t i = 0 ; i < diff . at ( name ) . size ( ) ; i + + )
output < < " true " ;
2018-08-14 14:23:21 +02:00
output < < " ]; " < < endl ;
int i = 1 ;
for ( const auto & it : rhs . at ( name ) )
{
output < < " M_.trend_component. " < < name < < " .rhs.vars_at_eq{ " < < i < < " }.var = [ " ;
2021-07-01 16:16:04 +02:00
for ( auto [ var , lag ] : it )
output < < symbol_table . getTypeSpecificID ( var ) + 1 < < " " ;
2018-08-14 14:23:21 +02:00
output < < " ]; " < < endl
< < " M_.trend_component. " < < name < < " .rhs.vars_at_eq{ " < < i < < " }.lag = [ " ;
2021-07-01 16:16:04 +02:00
for ( auto [ var , lag ] : it )
output < < lag < < " " ;
2018-08-14 14:23:21 +02:00
output < < " ]; " < < endl ;
i + + ;
}
2018-09-13 12:21:23 +02:00
output < < " M_.trend_component. " < < name < < " .target_vars = [ " ;
for ( auto it : target_vars . at ( name ) )
2018-08-31 12:35:51 +02:00
output < < ( it > = 0 ? symbol_table . getTypeSpecificID ( it ) + 1 : - 1 ) < < " " ;
output < < " ]; " < < endl ;
2018-09-07 10:56:40 +02:00
2019-02-21 09:47:13 +01:00
vector < string > target_eqtags_vec = target_eqtags . at ( name ) ;
output < < " M_.trend_component. " < < name < < " .target_eqtags = { " ;
for ( auto it : target_eqtags_vec )
output < < " ' " < < it < < " '; " ;
output < < " }; " < < endl ;
vector < string > eqtags_vec = eqtags . at ( name ) ;
output < < " M_.trend_component. " < < name < < " .target_eqn = [ " ;
for ( auto it : target_eqtags_vec )
{
int i = 0 ;
for ( auto it1 : eqtags_vec )
{
i + + ;
if ( it = = it1 )
{
output < < i < < " " ;
break ;
}
}
}
output < < " ]; " < < endl ;
2018-09-13 12:21:23 +02:00
vector < int > target_lhs_vec = getTargetLhs ( name ) ;
2019-02-14 11:44:06 +01:00
vector < int > nontarget_lhs_vec = getNonTargetLhs ( name ) ;
2018-09-10 17:13:51 +02:00
ar_ec_output < < " if strcmp(model_name, ' " < < name < < " ') " < < endl
2019-12-20 16:59:30 +01:00
< < " % AR " < < endl
< < " AR = zeros( " < < nontarget_lhs_vec . size ( ) < < " , " < < nontarget_lhs_vec . size ( ) < < " , " < < getMaxLag ( name ) < < " ); " < < endl ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : AR . at ( name ) )
2018-09-07 10:56:40 +02:00
{
2021-07-01 16:16:04 +02:00
auto [ eqn , lag , lhs_symb_id ] = key ;
2019-04-23 11:07:32 +02:00
int colidx = static_cast < int > ( distance ( nontarget_lhs_vec . begin ( ) , find ( nontarget_lhs_vec . begin ( ) , nontarget_lhs_vec . end ( ) , lhs_symb_id ) ) ) ;
2019-02-19 12:08:00 +01:00
ar_ec_output < < " AR( " < < eqn + 1 < < " , " < < colidx + 1 < < " , " < < lag < < " ) = " ;
2021-07-01 16:16:04 +02:00
expr - > writeOutput ( ar_ec_output , ExprNodeOutputType : : matlabDynamicModel ) ;
2018-09-10 17:13:51 +02:00
ar_ec_output < < " ; " < < endl ;
}
2019-02-15 11:12:07 +01:00
2019-02-19 12:08:00 +01:00
int a0_lag = 0 ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : A0 . at ( name ) )
a0_lag = max ( a0_lag , get < 1 > ( key ) ) ;
2018-09-10 17:13:51 +02:00
ar_ec_output < < endl
2019-02-19 12:08:00 +01:00
< < " % A0 " < < endl
< < " A0 = zeros( " < < nontarget_lhs_vec . size ( ) < < " , " < < nontarget_lhs_vec . size ( ) < < " , " < < a0_lag < < " ); " < < endl ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : A0 . at ( name ) )
2018-09-10 17:13:51 +02:00
{
2021-07-01 16:16:04 +02:00
auto [ eqn , lag , colidx ] = key ;
2019-02-19 12:08:00 +01:00
ar_ec_output < < " A0( " < < eqn + 1 < < " , " < < colidx + 1 < < " , " < < lag < < " ) = " ;
2021-07-01 16:16:04 +02:00
expr - > writeOutput ( ar_ec_output , ExprNodeOutputType : : matlabDynamicModel ) ;
2018-09-10 17:13:51 +02:00
ar_ec_output < < " ; " < < endl ;
2018-09-07 10:56:40 +02:00
}
2019-02-19 12:08:00 +01:00
int a0star_lag = 0 ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : A0star . at ( name ) )
a0star_lag = max ( a0star_lag , get < 1 > ( key ) ) ;
2019-02-19 12:08:00 +01:00
ar_ec_output < < endl
< < " % A0star " < < endl
< < " A0star = zeros( " < < nontarget_lhs_vec . size ( ) < < " , " < < target_lhs_vec . size ( ) < < " , " < < a0star_lag < < " ); " < < endl ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : A0star . at ( name ) )
2019-02-19 12:08:00 +01:00
{
2021-07-01 16:16:04 +02:00
auto [ eqn , lag , colidx ] = key ;
2019-02-19 12:08:00 +01:00
ar_ec_output < < " A0star( " < < eqn + 1 < < " , " < < colidx + 1 < < " , " < < lag < < " ) = " ;
2021-07-01 16:16:04 +02:00
expr - > writeOutput ( ar_ec_output , ExprNodeOutputType : : matlabDynamicModel ) ;
2019-02-19 12:08:00 +01:00
ar_ec_output < < " ; " < < endl ;
}
2018-09-10 17:13:51 +02:00
ar_ec_output < < " return " < < endl
2019-12-20 16:59:30 +01:00
< < " end " < < endl < < endl ;
2018-08-14 14:23:21 +02:00
}
2018-09-10 17:13:51 +02:00
ar_ec_output < < " error([model_name ' is not a valid trend_component_model name']) " < < endl
2019-12-20 16:59:30 +01:00
< < " end " < < endl ;
2018-09-10 17:13:51 +02:00
ar_ec_output . close ( ) ;
2018-08-14 14:23:21 +02:00
}
void
TrendComponentModelTable : : writeJsonOutput ( ostream & output ) const
{
for ( const auto & name : names )
{
2019-12-16 19:42:59 +01:00
if ( name ! = * names . begin ( ) )
2018-08-14 14:23:21 +02:00
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ({ " statementName " : " trend_component_model " ,) "
< < R " ( " model_name " : " ) " << name << R " ( " ,) "
< < R " ( " eqtags " : [) " ;
2018-08-22 09:15:00 +02:00
for ( const auto & it : eqtags . at ( name ) )
{
2019-04-03 16:32:52 +02:00
output < < R " ( " ) " << it << R " ( " ) " ;
2018-08-22 09:15:00 +02:00
if ( & it ! = & eqtags . at ( name ) . back ( ) )
output < < " , " ;
}
2019-04-03 16:32:52 +02:00
output < < R " (], " target_eqtags " : [) " ;
2018-09-13 12:21:23 +02:00
for ( const auto & it : target_eqtags . at ( name ) )
2018-08-22 09:15:00 +02:00
{
2019-04-03 16:32:52 +02:00
output < < R " ( " ) " << it << R " ( " ) " ;
2018-09-13 12:21:23 +02:00
if ( & it ! = & target_eqtags . at ( name ) . back ( ) )
2018-08-22 09:15:00 +02:00
output < < " , " ;
}
output < < " ]} " ;
2018-08-14 14:23:21 +02:00
}
}
2018-08-21 11:46:59 +02:00
VarModelTable : : VarModelTable ( SymbolTable & symbol_table_arg ) :
2018-10-04 17:18:27 +02:00
symbol_table { symbol_table_arg }
2018-08-21 11:46:59 +02:00
{
}
void
2021-07-07 10:54:04 +02:00
VarModelTable : : addVarModel ( string name_arg , bool structural_arg , vector < string > eqtags_arg )
2018-08-21 11:46:59 +02:00
{
if ( isExistingVarModelName ( name_arg ) )
{
cerr < < " Error: a VAR model already exists with the name " < < name_arg < < endl ;
exit ( EXIT_FAILURE ) ;
}
2021-07-07 10:54:04 +02:00
structural [ name_arg ] = structural_arg ;
2018-08-21 11:46:59 +02:00
eqtags [ name_arg ] = move ( eqtags_arg ) ;
names . insert ( move ( name_arg ) ) ;
}
void
2018-09-06 17:53:07 +02:00
VarModelTable : : writeOutput ( const string & basename , ostream & output ) const
2018-08-21 11:46:59 +02:00
{
2018-09-25 12:17:34 +02:00
if ( names . empty ( ) )
return ;
2021-07-16 08:33:26 +02:00
string filename = " + " + basename + " /varmatrices.m " ;
2018-09-06 17:53:07 +02:00
ofstream ar_output ;
ar_output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! ar_output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2021-07-16 15:12:37 +02:00
ar_output < < " function [ar, a0, constants] = varmatrices(model_name, params, reducedform) " < < endl
2021-07-16 08:33:26 +02:00
< < " % File automatically generated by the Dynare preprocessor " < < endl < < endl
< < " if nargin<3 " < < endl
< < " reducedform = false; " < < endl
< < " end " < < endl < < endl ;
2018-09-06 17:53:07 +02:00
2018-08-21 11:46:59 +02:00
for ( const auto & name : names )
{
2021-07-07 10:54:04 +02:00
output < < " M_.var. " < < name < < " .model_name = ' " < < name < < " '; " < < endl
< < " M_.var. " < < name < < " .structural = " < < ( structural . at ( name ) ? " true " : " false " ) < < " ; " < < endl
< < " M_.var. " < < name < < " .eqtags = { " ;
2018-08-21 11:46:59 +02:00
for ( const auto & it : eqtags . at ( name ) )
output < < " ' " < < it < < " '; " ;
output < < " }; " < < endl
< < " M_.var. " < < name < < " .eqn = [ " ;
for ( auto it : eqnums . at ( name ) )
output < < it + 1 < < " " ;
output < < " ]; " < < endl
< < " M_.var. " < < name < < " .lhs = [ " ;
for ( auto it : lhs . at ( name ) )
output < < symbol_table . getTypeSpecificID ( it ) + 1 < < " " ;
output < < " ]; " < < endl
< < " M_.var. " < < name < < " .max_lag = [ " ;
for ( auto it : max_lags . at ( name ) )
output < < it < < " " ;
output < < " ]; " < < endl
< < " M_.var. " < < name < < " .diff = [ " ;
for ( const auto & it : diff . at ( name ) )
output < < ( it ? " true " : " false " ) < < " " ;
output < < " ]; " < < endl
2018-10-24 15:57:07 +02:00
< < " M_.var. " < < name < < " .nonstationary = M_.var. " < < name < < " .diff; " < < endl
2018-08-21 11:46:59 +02:00
< < " M_.var. " < < name < < " .orig_diff_var = [ " ;
for ( auto it : orig_diff_var . at ( name ) )
output < < ( it > = 0 ? symbol_table . getTypeSpecificID ( it ) + 1 : - 1 ) < < " " ;
output < < " ]; " < < endl ;
int i = 1 ;
for ( const auto & it : rhs . at ( name ) )
{
output < < " M_.var. " < < name < < " .rhs.vars_at_eq{ " < < i < < " }.var = [ " ;
2021-07-01 16:16:04 +02:00
for ( auto [ var , lag ] : it )
output < < symbol_table . getTypeSpecificID ( var ) + 1 < < " " ;
2018-08-21 11:46:59 +02:00
output < < " ]; " < < endl
< < " M_.var. " < < name < < " .rhs.vars_at_eq{ " < < i < < " }.lag = [ " ;
2021-07-01 16:16:04 +02:00
for ( auto [ var , lag ] : it )
output < < lag < < " " ;
2018-08-21 11:46:59 +02:00
output < < " ]; " < < endl ;
i + + ;
}
2018-09-06 17:53:07 +02:00
2019-03-14 17:20:45 +01:00
vector < int > lhs = getLhsOrigIds ( name ) ;
2018-09-06 17:53:07 +02:00
ar_output < < " if strcmp(model_name, ' " < < name < < " ') " < < endl
< < " ar = zeros( " < < lhs . size ( ) < < " , " < < lhs . size ( ) < < " , " < < getMaxLag ( name ) < < " ); " < < endl ;
2021-07-01 16:16:04 +02:00
for ( const auto & [ key , expr ] : AR . at ( name ) )
2018-09-06 17:53:07 +02:00
{
2021-07-01 16:16:04 +02:00
auto [ eqn , lag , lhs_symb_id ] = key ;
2019-04-23 11:07:32 +02:00
int colidx = static_cast < int > ( distance ( lhs . begin ( ) , find ( lhs . begin ( ) , lhs . end ( ) , lhs_symb_id ) ) ) ;
2021-07-16 08:33:26 +02:00
ar_output < < " ar( " < < eqn + 1 < < " , " < < colidx + 1 < < " , " < < lag < < " ) = " ;
2021-07-01 16:16:04 +02:00
expr - > writeOutput ( ar_output , ExprNodeOutputType : : matlabDynamicModel ) ;
2018-09-12 18:21:34 +02:00
ar_output < < " ; " < < endl ;
2018-09-06 17:53:07 +02:00
}
2021-07-16 08:33:26 +02:00
ar_output < < " if nargout>1 " < < endl
< < " a0 = eye( " < < lhs . size ( ) < < " ); " < < endl ;
2021-07-07 10:54:04 +02:00
for ( const auto & [ key , expr ] : A0 . at ( name ) )
{
auto [ eqn , lhs_symb_id ] = key ;
int colidx = static_cast < int > ( distance ( lhs . begin ( ) , find ( lhs . begin ( ) , lhs . end ( ) , lhs_symb_id ) ) ) ;
2021-07-16 08:33:26 +02:00
if ( eqn ! = colidx )
{
ar_output < < " a0( " < < eqn + 1 < < " , " < < colidx + 1 < < " ) = " ;
expr - > writeOutput ( ar_output , ExprNodeOutputType : : matlabDynamicModel ) ;
ar_output < < " ; " < < endl ;
}
2021-07-07 10:54:04 +02:00
}
2021-07-16 08:33:26 +02:00
ar_output < < " if reducedform " < < endl
< < " for i=1: " < < getMaxLag ( name ) < < endl
< < " ar(:,:,i) = a0 \\ ar(:,:,i); " < < endl
< < " end " < < endl
2021-07-16 22:39:00 +02:00
< < " if nargout<3 " < < endl
< < " a0 = eye( " < < lhs . size ( ) < < " ); " < < endl
< < " end " < < endl
2021-07-16 08:33:26 +02:00
< < " end " < < endl
2021-07-16 15:12:37 +02:00
< < " if nargout>2 " < < endl
2021-07-16 19:50:02 +02:00
< < " constants = zeros( " < < lhs . size ( ) < < " ,1); " < < endl ;
2021-07-16 15:12:37 +02:00
for ( auto [ eqn , expr ] : constants . at ( name ) )
{
ar_output < < " constants( " < < eqn + 1 < < " ) = " ;
expr - > writeOutput ( ar_output , ExprNodeOutputType : : matlabDynamicModel ) ;
ar_output < < " ; " < < endl ;
}
ar_output < < " end " < < endl
2021-07-16 22:39:00 +02:00
< < " if reducedform " < < endl
< < " constants = a0 \\ constants; " < < endl
< < " a0 = eye( " < < lhs . size ( ) < < " ); " < < endl
< < " end " < < endl
2021-07-16 08:33:26 +02:00
< < " end " < < endl
2021-07-07 10:54:04 +02:00
< < " return " < < endl
2018-09-06 17:53:07 +02:00
< < " end " < < endl < < endl ;
2018-08-21 11:46:59 +02:00
}
2021-07-16 08:33:26 +02:00
ar_output < < " error('%s is not a valid var_model name', model_name) " < < endl ;
2018-09-06 17:53:07 +02:00
ar_output . close ( ) ;
2018-08-21 11:46:59 +02:00
}
void
VarModelTable : : writeJsonOutput ( ostream & output ) const
{
for ( const auto & name : names )
{
2019-12-16 19:42:59 +01:00
if ( name ! = * names . begin ( ) )
2018-08-21 11:46:59 +02:00
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ({ " statementName " : " var_model " ,) "
2021-07-07 15:08:17 +02:00
< < R " ( " model_name " : " ) " << name << R " ( " ,) "
< < R " ( " eqtags " : [) " ;
for ( const auto & it : eqtags . at ( name ) )
2018-08-21 11:46:59 +02:00
{
2021-07-07 15:08:17 +02:00
output < < R " ( " ) " << it << R " ( " ) " ;
if ( & it ! = & eqtags . at ( name ) . back ( ) )
output < < " , " ;
2018-08-21 11:46:59 +02:00
}
2021-07-07 15:08:17 +02:00
output < < " ]} " ;
2018-08-21 11:46:59 +02:00
}
}
2021-07-07 10:54:04 +02:00
const map < string , bool > &
VarModelTable : : getStructural ( ) const
{
return structural ;
}
2021-07-01 16:16:04 +02:00
const map < string , vector < string > > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getEqTags ( ) const
{
return eqtags ;
}
2021-07-01 16:16:04 +02:00
const vector < string > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getEqTags ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return eqtags . find ( name_arg ) - > second ;
}
void
VarModelTable : : checkModelName ( const string & name_arg ) const
{
if ( ! isExistingVarModelName ( name_arg ) )
{
cerr < < name_arg
< < " is not a recognized equation tag of a VAR model equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
void
VarModelTable : : setEqNums ( map < string , vector < int > > eqnums_arg )
{
eqnums = move ( eqnums_arg ) ;
}
void
VarModelTable : : setLhs ( map < string , vector < int > > lhs_arg )
{
lhs = move ( lhs_arg ) ;
2019-03-14 17:20:45 +01:00
for ( auto it : lhs )
{
vector < int > lhsvec ;
for ( auto ids : it . second )
{
int lhs_last_orig_symb_id = ids ;
int lhs_orig_symb_id = ids ;
if ( symbol_table . isAuxiliaryVariable ( lhs_orig_symb_id ) )
try
2019-12-20 16:59:30 +01:00
{
lhs_last_orig_symb_id = lhs_orig_symb_id ;
lhs_orig_symb_id = symbol_table . getOrigSymbIdForAuxVar ( lhs_orig_symb_id ) ;
}
2019-03-14 17:20:45 +01:00
catch ( . . . )
{
}
lhsvec . emplace_back ( lhs_last_orig_symb_id ) ;
}
lhs_orig_symb_ids [ it . first ] = lhsvec ;
}
2018-08-21 11:46:59 +02:00
}
void
VarModelTable : : setRhs ( map < string , vector < set < pair < int , int > > > > rhs_arg )
{
rhs = move ( rhs_arg ) ;
}
void
VarModelTable : : setLhsExprT ( map < string , vector < expr_t > > lhs_expr_t_arg )
{
lhs_expr_t = move ( lhs_expr_t_arg ) ;
}
2021-07-01 16:16:04 +02:00
const map < string , vector < int > > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getEqNums ( ) const
{
return eqnums ;
}
2021-07-01 16:16:04 +02:00
const vector < bool > &
2018-10-24 15:57:07 +02:00
VarModelTable : : getDiff ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return diff . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getEqNums ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return eqnums . find ( name_arg ) - > second ;
}
void
VarModelTable : : setMaxLags ( map < string , vector < int > > max_lags_arg )
{
max_lags = move ( max_lags_arg ) ;
}
void
VarModelTable : : setDiff ( map < string , vector < bool > > diff_arg )
{
diff = move ( diff_arg ) ;
}
void
VarModelTable : : setOrigDiffVar ( map < string , vector < int > > orig_diff_var_arg )
{
orig_diff_var = move ( orig_diff_var_arg ) ;
}
2018-09-06 17:53:07 +02:00
void
2018-09-07 10:14:18 +02:00
VarModelTable : : setAR ( map < string , map < tuple < int , int , int > , expr_t > > AR_arg )
2018-09-06 17:53:07 +02:00
{
AR = move ( AR_arg ) ;
}
2021-07-07 10:54:04 +02:00
void
VarModelTable : : setA0 ( map < string , map < tuple < int , int > , expr_t > > A0_arg )
{
A0 = move ( A0_arg ) ;
}
2021-07-16 15:12:37 +02:00
void
VarModelTable : : setConstants ( map < string , map < int , expr_t > > constants_arg )
{
constants = move ( constants_arg ) ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getMaxLags ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return max_lags . find ( name_arg ) - > second ;
}
int
VarModelTable : : getMaxLag ( const string & name_arg ) const
{
int max_lag_int = 0 ;
for ( auto it : getMaxLags ( name_arg ) )
max_lag_int = max ( max_lag_int , it ) ;
return max_lag_int ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getLhs ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return lhs . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < int > &
2019-03-14 17:20:45 +01:00
VarModelTable : : getLhsOrigIds ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return lhs_orig_symb_ids . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < set < pair < int , int > > > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getRhs ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return rhs . find ( name_arg ) - > second ;
}
2021-07-01 16:16:04 +02:00
const vector < expr_t > &
2018-08-21 11:46:59 +02:00
VarModelTable : : getLhsExprT ( const string & name_arg ) const
{
checkModelName ( name_arg ) ;
return lhs_expr_t . find ( name_arg ) - > second ;
}
2021-10-27 16:26:52 +02:00
PacModelTable : : PacModelTable ( SymbolTable & symbol_table_arg ) :
symbol_table { symbol_table_arg }
{
}
void
PacModelTable : : addPacModel ( string name_arg , string aux_model_name_arg , string discount_arg , expr_t growth_arg )
{
if ( isExistingPacModelName ( name_arg ) )
{
cerr < < " Error: a PAC model already exists with the name " < < name_arg < < endl ;
exit ( EXIT_FAILURE ) ;
}
aux_model_name [ name_arg ] = move ( aux_model_name_arg ) ;
discount [ name_arg ] = move ( discount_arg ) ;
growth [ name_arg ] = growth_arg ;
original_growth [ name_arg ] = growth_arg ;
names . insert ( move ( name_arg ) ) ;
}
bool
PacModelTable : : isExistingPacModelName ( const string & name_arg ) const
{
return names . find ( name_arg ) ! = names . end ( ) ;
}
bool
PacModelTable : : empty ( ) const
{
return names . empty ( ) ;
}
void
PacModelTable : : checkPass ( ModFileStructure & mod_file_struct , WarningConsolidation & warnings )
{
for ( auto & [ name , gv ] : growth )
if ( gv )
gv - > collectVariables ( SymbolType : : exogenous , mod_file_struct . pac_params ) ;
}
void
PacModelTable : : findDiffNodesInGrowth ( lag_equivalence_table_t & diff_nodes ) const
{
for ( auto & [ name , gv ] : growth )
if ( gv )
gv - > findDiffNodes ( diff_nodes ) ;
}
void
PacModelTable : : substituteDiffNodesInGrowth ( const lag_equivalence_table_t & diff_nodes , ExprNode : : subst_table_t & diff_subst_table , vector < BinaryOpNode * > & neweqs )
{
for ( auto & [ name , gv ] : growth )
if ( gv )
gv = gv - > substituteDiff ( diff_nodes , diff_subst_table , neweqs ) ;
}
void
PacModelTable : : transformPass ( ExprNode : : subst_table_t & diff_subst_table ,
DynamicModel & dynamic_model , const VarModelTable & var_model_table ,
const TrendComponentModelTable & trend_component_model_table )
{
2021-10-28 14:42:56 +02:00
// model name → expression for pac_expectation
map < string , expr_t > pac_expectation_substitution ;
2021-10-27 18:17:14 +02:00
2021-10-27 16:26:52 +02:00
for ( const auto & name : names )
{
/* Fill the growth_info structure.
Cannot be done in an earlier pass since growth terms can be
transformed by DynamicModel : : substituteDiff ( ) . */
if ( growth [ name ] )
try
{
growth_info [ name ] = growth [ name ] - > matchLinearCombinationOfVariables ( false ) ;
}
catch ( ExprNode : : MatchFailureException & e )
{
auto gv = dynamic_cast < const VariableNode * > ( growth [ name ] ) ;
if ( gv )
growth_info [ name ] . emplace_back ( gv - > symb_id , gv - > lag , - 1 , 1 ) ;
else
{
cerr < < " Pac growth must be a linear combination of variables " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2021-10-27 18:17:14 +02:00
// Collect some information about PAC models
2021-10-27 16:26:52 +02:00
int max_lag ;
vector < bool > nonstationary ;
if ( trend_component_model_table . isExistingTrendComponentModelName ( aux_model_name [ name ] ) )
{
2021-10-27 18:17:14 +02:00
aux_model_type [ name ] = " trend_component " ;
2021-10-27 16:26:52 +02:00
max_lag = trend_component_model_table . getMaxLag ( aux_model_name [ name ] ) + 1 ;
2021-10-27 18:17:14 +02:00
lhs [ name ] = dynamic_model . getUndiffLHSForPac ( aux_model_name [ name ] , diff_subst_table ) ;
2021-10-27 16:26:52 +02:00
// All lhs variables in a trend component model are nonstationary
nonstationary . insert ( nonstationary . end ( ) , trend_component_model_table . getDiff ( aux_model_name [ name ] ) . size ( ) , true ) ;
}
else if ( var_model_table . isExistingVarModelName ( aux_model_name [ name ] ) )
{
2021-10-27 18:17:14 +02:00
aux_model_type [ name ] = " var " ;
2021-10-27 16:26:52 +02:00
max_lag = var_model_table . getMaxLag ( aux_model_name [ name ] ) ;
2021-10-27 18:17:14 +02:00
lhs [ name ] = var_model_table . getLhs ( aux_model_name [ name ] ) ;
2021-10-27 16:26:52 +02:00
// nonstationary variables in a VAR are those that are in diff
nonstationary = var_model_table . getDiff ( aux_model_name [ name ] ) ;
}
else if ( aux_model_name [ name ] . empty ( ) )
max_lag = 0 ;
else
{
cerr < < " Error: aux_model_name not recognized as VAR model or Trend Component model " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2021-10-28 14:42:56 +02:00
dynamic_model . analyzePacEquationStructure ( name , eq_name , equation_info ) ;
2021-10-27 18:17:14 +02:00
// Declare parameter for growth neutrality correction
if ( growth [ name ] )
{
string param_name = name + " _pac_growth_neutrality_correction " ;
try
{
int param_idx = symbol_table . addSymbol ( param_name , SymbolType : : parameter ) ;
growth_neutrality_params [ name ] = param_idx ;
}
catch ( SymbolTable : : AlreadyDeclaredException )
{
cerr < < " The variable/parameter ' " < < param_name < < " ' conflicts with the auxiliary parameter that will be generated for the growth neutrality correction of the ' " < < name < < " ' PAC model. Please rename that parameter. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2021-10-27 16:26:52 +02:00
2021-10-27 18:17:14 +02:00
// Compute the expressions that will be substituted for the pac_expectation operators
2021-10-28 14:42:56 +02:00
expr_t growth_correction_term = dynamic_model . Zero ;
if ( growth [ name ] )
growth_correction_term = dynamic_model . AddTimes ( growth [ name ] , dynamic_model . AddVariable ( growth_neutrality_params [ name ] ) ) ;
2021-10-27 18:17:14 +02:00
if ( aux_model_name [ name ] . empty ( ) )
2021-10-28 14:42:56 +02:00
dynamic_model . computePacModelConsistentExpectationSubstitution ( name ,
2021-11-16 17:58:20 +01:00
symbol_table . getID ( discount [ name ] ) ,
pacEquationMaxLag ( name ) ,
2021-10-28 14:42:56 +02:00
growth_correction_term ,
2021-11-16 17:58:20 +01:00
diff_subst_table ,
aux_var_symb_ids ,
mce_alpha_symb_ids ,
2021-10-27 18:17:14 +02:00
pac_expectation_substitution ) ;
else
dynamic_model . computePacBackwardExpectationSubstitution ( name , lhs [ name ] , max_lag ,
aux_model_type [ name ] ,
2021-10-28 14:42:56 +02:00
nonstationary ,
growth_correction_term ,
2021-11-16 17:58:20 +01:00
aux_var_symb_ids ,
2021-10-27 18:17:14 +02:00
h0_indices , h1_indices ,
pac_expectation_substitution ) ;
2021-10-27 16:26:52 +02:00
}
2021-10-27 18:17:14 +02:00
// Actually perform the substitution of pac_expectation
2021-10-28 14:42:56 +02:00
dynamic_model . substitutePacExpectation ( pac_expectation_substitution , eq_name ) ;
2021-10-27 16:26:52 +02:00
dynamic_model . checkNoRemainingPacExpectation ( ) ;
}
void
PacModelTable : : writeOutput ( const string & basename , ostream & output ) const
{
for ( const auto & name : names )
{
output < < " M_.pac. " < < name < < " .auxiliary_model_name = ' " < < aux_model_name . at ( name ) < < " '; " < < endl
< < " M_.pac. " < < name < < " .discount_index = " < < symbol_table . getTypeSpecificID ( discount . at ( name ) ) + 1 < < " ; " < < endl ;
if ( growth . at ( name ) )
{
output < < " M_.pac. " < < name < < " .growth_str = ' " ;
original_growth . at ( name ) - > writeJsonOutput ( output , { } , { } , true ) ;
output < < " '; " < < endl ;
int i = 0 ;
for ( auto [ growth_symb_id , growth_lag , param_id , constant ] : growth_info . at ( name ) )
{
string structname = " M_.pac. " + name + " .growth_linear_comb( " + to_string ( + + i ) + " ). " ;
if ( growth_symb_id > = 0 )
{
string var_field = " endo_id " ;
if ( symbol_table . getType ( growth_symb_id ) = = SymbolType : : exogenous )
{
var_field = " exo_id " ;
output < < structname < < " endo_id = 0; " < < endl ;
}
else
output < < structname < < " exo_id = 0; " < < endl ;
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 < < structname < < var_field < < " = " < < symbol_table . getTypeSpecificID ( aux_symb_id ) + 1 < < " ; " < < endl
< < structname < < " lag = 0; " < < endl ;
}
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 < < structname < < var_field < < " = " < < symbol_table . getTypeSpecificID ( aux_symb_id ) + 1 < < " ; " < < endl
< < structname < < " lag = -1; " < < endl ;
}
catch ( . . . )
{
// case when there is no aux var for the variable
output < < structname < < var_field < < " = " < < symbol_table . getTypeSpecificID ( growth_symb_id ) + 1 < < " ; " < < endl
< < structname < < " lag = " < < growth_lag < < " ; " < < endl ;
}
}
}
else
output < < structname < < " endo_id = 0; " < < endl
< < structname < < " exo_id = 0; " < < endl
< < structname < < " lag = 0; " < < endl ;
output < < structname < < " param_id = "
< < ( param_id = = - 1 ? 0 : symbol_table . getTypeSpecificID ( param_id ) + 1 ) < < " ; " < < endl
< < structname < < " constant = " < < constant < < " ; " < < endl ;
}
}
}
2021-10-27 18:17:14 +02:00
// Write PAC Model Consistent Expectation parameter info
2021-10-28 14:42:56 +02:00
for ( auto & [ name , ids ] : mce_alpha_symb_ids )
2021-10-27 18:17:14 +02:00
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .mce.alpha = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto id : ids )
output < < symbol_table . getTypeSpecificID ( id ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2021-11-16 17:58:20 +01:00
// Write the auxiliary variable IDs created for the pac_expectation operator
for ( auto & [ name , id ] : aux_var_symb_ids )
output < < " M_.pac. " < < name < < " . " < < ( aux_model_name . at ( name ) . empty ( ) ? " mce.z1 " : " aux_id " )
< < " = " < < symbol_table . getTypeSpecificID ( id ) + 1 < < " ; " < < endl ;
2021-10-27 18:17:14 +02:00
2021-10-28 14:42:56 +02:00
// Write PAC equation name info
for ( auto & [ name , eq ] : eq_name )
output < < " M_.pac. " < < name < < " .eq_name = ' " < < eq < < " '; " < < endl ;
2021-10-27 18:17:14 +02:00
for ( auto & [ model , growth_neutrality_param_index ] : growth_neutrality_params )
output < < " M_.pac. " < < model < < " .growth_neutrality_param_index = "
< < symbol_table . getTypeSpecificID ( growth_neutrality_param_index ) + 1 < < " ; " < < endl ;
for ( auto & [ model , lhs ] : lhs )
{
output < < " M_.pac. " < < model < < " .lhs = [ " ;
for ( auto id : lhs )
output < < id + 1 < < " " ;
output < < " ]; " < < endl ;
}
for ( auto & [ model , type ] : aux_model_type )
output < < " M_.pac. " < < model < < " .auxiliary_model_type = ' " < < type < < " '; " < < endl ;
2021-10-28 14:42:56 +02:00
for ( auto & [ name , val ] : equation_info )
2021-10-27 18:17:14 +02:00
{
auto [ lhs_pac_var , optim_share_index , ar_params_and_vars , ec_params_and_vars , non_optim_vars_params_and_constants , additive_vars_params_and_constants , optim_additive_vars_params_and_constants ] = val ;
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .lhs_var = "
2021-10-27 18:17:14 +02:00
< < symbol_table . getTypeSpecificID ( lhs_pac_var . first ) + 1 < < " ; " < < endl ;
if ( optim_share_index > = 0 )
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .share_of_optimizing_agents_index = "
2021-10-27 18:17:14 +02:00
< < symbol_table . getTypeSpecificID ( optim_share_index ) + 1 < < " ; " < < endl ;
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .ec.params = "
2021-10-27 18:17:14 +02:00
< < symbol_table . getTypeSpecificID ( ec_params_and_vars . first ) + 1 < < " ; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ec.vars = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : ec_params_and_vars . second )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ec.istarget = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : ec_params_and_vars . second )
output < < ( get < 1 > ( it ) ? " true " : " false " ) ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ec.scale = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : ec_params_and_vars . second )
output < < get < 2 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ec.isendo = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : ec_params_and_vars . second )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ar.params = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < ( pid ! = - 1 ? symbol_table . getTypeSpecificID ( pid ) + 1 : - 1 ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ar.vars = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < ( vid ! = - 1 ? symbol_table . getTypeSpecificID ( vid ) + 1 : - 1 ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .ar.lags = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < vlag < < " " ;
2021-10-28 14:42:56 +02:00
output < < " ]; " < < endl
< < " M_.pac. " < < name < < " .max_lag = " < < pacEquationMaxLag ( name ) < < " ; " < < endl ;
2021-10-27 18:17:14 +02:00
if ( ! non_optim_vars_params_and_constants . empty ( ) )
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .non_optimizing_behaviour.params = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : non_optim_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .non_optimizing_behaviour.vars = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .non_optimizing_behaviour.isendo = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : non_optim_vars_params_and_constants )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .non_optimizing_behaviour.lags = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .non_optimizing_behaviour.scaling_factor = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
if ( ! additive_vars_params_and_constants . empty ( ) )
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .additive.params = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : additive_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .additive.vars = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : additive_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .additive.isendo = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : additive_vars_params_and_constants )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .additive.lags = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : additive_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .additive.scaling_factor = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : additive_vars_params_and_constants )
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
if ( ! optim_additive_vars_params_and_constants . empty ( ) )
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .optim_additive.params = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : optim_additive_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .optim_additive.vars = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : optim_additive_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .optim_additive.isendo = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : optim_additive_vars_params_and_constants )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .optim_additive.lags = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : optim_additive_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-10-28 14:42:56 +02:00
< < " M_.pac. " < < name < < " .optim_additive.scaling_factor = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto & it : optim_additive_vars_params_and_constants )
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
// Create empty h0 and h1 substructures that will be overwritten later if not empty
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .h0_param_indices = []; " < < endl
< < " M_.pac. " < < name < < " .h1_param_indices = []; " < < endl ;
2021-10-27 18:17:14 +02:00
}
2021-10-28 14:42:56 +02:00
for ( auto & [ name , symb_ids ] : h0_indices )
2021-10-27 18:17:14 +02:00
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .h0_param_indices = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : symb_ids )
output < < symbol_table . getTypeSpecificID ( it ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2021-10-28 14:42:56 +02:00
for ( auto & [ name , symb_ids ] : h1_indices )
2021-10-27 18:17:14 +02:00
{
2021-10-28 14:42:56 +02:00
output < < " M_.pac. " < < name < < " .h1_param_indices = [ " ;
2021-10-27 18:17:14 +02:00
for ( auto it : symb_ids )
output < < symbol_table . getTypeSpecificID ( it ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2021-10-27 16:26:52 +02:00
}
void
PacModelTable : : writeJsonOutput ( ostream & output ) const
{
for ( const auto & name : names )
{
if ( name ! = * names . begin ( ) )
output < < " , " ;
output < < R " ({ " statementName " : " pac_model " ,) "
< < R " ( " model_name " : " ) " << name << R " ( " ,) "
< < R " ( " auxiliary_model_name " : " ) " << aux_model_name.at(name) << R " ( " ,) "
< < R " ( " discount_index " : ) " < < symbol_table . getTypeSpecificID ( discount . at ( name ) ) + 1 ;
if ( growth . at ( name ) )
{
output < < R " (, " growth_str " : " ) " ;
original_growth . at ( name ) - > writeJsonOutput ( output , { } , { } , true ) ;
output < < R " ( " ) " ;
}
output < < " } " < < endl ;
}
}
2021-10-28 14:42:56 +02:00
int
PacModelTable : : pacEquationMaxLag ( const string & name_arg ) const
{
return get < 2 > ( equation_info . at ( name_arg ) ) . size ( ) ;
}