2009-04-14 16:39:53 +02:00
/*
2021-01-25 18:03:37 +01:00
* Copyright © 2003 - 2021 Dynare Team
2009-04-14 16:39:53 +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/>.
2009-04-14 16:39:53 +02:00
*/
2009-07-06 12:36:36 +02:00
# include <iostream>
2009-04-14 16:39:53 +02:00
# include <cmath>
2009-04-14 16:47:57 +02:00
# include <cstdlib>
2009-04-28 18:21:39 +02:00
# include <cassert>
2009-12-16 14:21:31 +01:00
# include <algorithm>
2018-06-07 12:53:00 +02:00
# include <numeric>
2019-11-18 17:13:49 +01:00
# include <regex>
2021-04-23 17:30:38 +02:00
# include <sstream>
2009-04-14 16:39:53 +02:00
2018-06-27 15:01:31 +02:00
# include "DynamicModel.hh"
2009-04-14 16:39:53 +02:00
2018-10-09 18:27:19 +02:00
void
DynamicModel : : copyHelper ( const DynamicModel & m )
{
2018-10-10 13:07:25 +02:00
auto f = [ this ] ( const ExprNode * e ) { return e - > clone ( * this ) ; } ;
2018-10-09 18:27:19 +02:00
for ( const auto & it : m . static_only_equations )
static_only_equations . push_back ( dynamic_cast < BinaryOpNode * > ( f ( it ) ) ) ;
2020-04-30 16:00:16 +02:00
auto convert_block_derivative = [ f ] ( const map < tuple < int , int , int > , expr_t > & dt )
{
map < tuple < int , int , int > , expr_t > dt2 ;
for ( const auto & it : dt )
dt2 [ it . first ] = f ( it . second ) ;
return dt2 ;
} ;
for ( const auto & it : m . blocks_derivatives_other_endo )
blocks_derivatives_other_endo . emplace_back ( convert_block_derivative ( it ) ) ;
for ( const auto & it : m . blocks_derivatives_exo )
blocks_derivatives_exo . emplace_back ( convert_block_derivative ( it ) ) ;
for ( const auto & it : m . blocks_derivatives_exo_det )
blocks_derivatives_exo_det . emplace_back ( convert_block_derivative ( it ) ) ;
2020-05-05 16:34:51 +02:00
for ( const auto & [ key , expr ] : m . pac_expectation_substitution )
pac_expectation_substitution . emplace ( key , f ( expr ) ) ;
2018-10-09 18:27:19 +02:00
}
2009-04-14 16:39:53 +02:00
DynamicModel : : DynamicModel ( SymbolTable & symbol_table_arg ,
2010-02-22 17:33:38 +01:00
NumericalConstants & num_constants_arg ,
2018-08-14 14:23:21 +02:00
ExternalFunctionsTable & external_functions_table_arg ,
2018-08-21 11:46:59 +02:00
TrendComponentModelTable & trend_component_model_table_arg ,
VarModelTable & var_model_table_arg ) :
2019-12-20 16:59:30 +01:00
ModelTree { symbol_table_arg , num_constants_arg , external_functions_table_arg , true } ,
2018-10-04 17:18:27 +02:00
trend_component_model_table { trend_component_model_table_arg } ,
var_model_table { var_model_table_arg }
2009-04-14 16:39:53 +02:00
{
}
2018-10-09 18:27:19 +02:00
DynamicModel : : DynamicModel ( const DynamicModel & m ) :
2019-12-20 16:59:30 +01:00
ModelTree { m } ,
trend_component_model_table { m . trend_component_model_table } ,
var_model_table { m . var_model_table } ,
balanced_growth_test_tol { m . balanced_growth_test_tol } ,
static_only_equations_lineno { m . static_only_equations_lineno } ,
static_only_equations_equation_tags { m . static_only_equations_equation_tags } ,
deriv_id_table { m . deriv_id_table } ,
inv_deriv_id_table { m . inv_deriv_id_table } ,
dyn_jacobian_cols_table { m . dyn_jacobian_cols_table } ,
max_lag { m . max_lag } ,
max_lead { m . max_lead } ,
max_endo_lag { m . max_endo_lag } ,
max_endo_lead { m . max_endo_lead } ,
max_exo_lag { m . max_exo_lag } ,
max_exo_lead { m . max_exo_lead } ,
max_exo_det_lag { m . max_exo_det_lag } ,
max_exo_det_lead { m . max_exo_det_lead } ,
max_lag_orig { m . max_lag_orig } ,
max_lead_orig { m . max_lead_orig } ,
max_lag_with_diffs_expanded_orig { m . max_lag_with_diffs_expanded_orig } ,
max_endo_lag_orig { m . max_endo_lag_orig } ,
max_endo_lead_orig { m . max_endo_lead_orig } ,
max_exo_lag_orig { m . max_exo_lag_orig } ,
max_exo_lead_orig { m . max_exo_lead_orig } ,
max_exo_det_lag_orig { m . max_exo_det_lag_orig } ,
max_exo_det_lead_orig { m . max_exo_det_lead_orig } ,
xrefs { m . xrefs } ,
xref_param { m . xref_param } ,
xref_endo { m . xref_endo } ,
xref_exo { m . xref_exo } ,
xref_exo_det { m . xref_exo_det } ,
nonzero_hessian_eqs { m . nonzero_hessian_eqs } ,
2020-04-30 14:57:50 +02:00
dynJacobianColsNbr { m . dynJacobianColsNbr } ,
variableMapping { m . variableMapping } ,
2020-05-06 14:02:58 +02:00
blocks_other_endo { m . blocks_other_endo } ,
blocks_exo { m . blocks_exo } ,
blocks_exo_det { m . blocks_exo_det } ,
blocks_jacob_cols_endo { m . blocks_jacob_cols_endo } ,
blocks_jacob_cols_other_endo { m . blocks_jacob_cols_other_endo } ,
blocks_jacob_cols_exo { m . blocks_jacob_cols_exo } ,
blocks_jacob_cols_exo_det { m . blocks_jacob_cols_exo_det } ,
2020-05-05 16:34:51 +02:00
var_expectation_functions_to_write { m . var_expectation_functions_to_write } ,
pac_mce_alpha_symb_ids { m . pac_mce_alpha_symb_ids } ,
pac_h0_indices { m . pac_h0_indices } ,
pac_h1_indices { m . pac_h1_indices } ,
pac_mce_z1_symb_ids { m . pac_mce_z1_symb_ids } ,
pac_eqtag_and_lag { m . pac_eqtag_and_lag } ,
pac_model_info { m . pac_model_info } ,
pac_equation_info { m . pac_equation_info }
2009-04-16 12:33:30 +02:00
{
2018-10-09 18:27:19 +02:00
copyHelper ( m ) ;
}
DynamicModel &
DynamicModel : : operator = ( const DynamicModel & m )
{
ModelTree : : operator = ( m ) ;
assert ( & trend_component_model_table = = & m . trend_component_model_table ) ;
assert ( & var_model_table = = & m . var_model_table ) ;
2019-11-14 17:51:16 +01:00
balanced_growth_test_tol = m . balanced_growth_test_tol ;
2018-10-09 18:27:19 +02:00
static_only_equations_lineno = m . static_only_equations_lineno ;
static_only_equations_equation_tags = m . static_only_equations_equation_tags ;
deriv_id_table = m . deriv_id_table ;
inv_deriv_id_table = m . inv_deriv_id_table ;
dyn_jacobian_cols_table = m . dyn_jacobian_cols_table ;
max_lag = m . max_lag ;
max_lead = m . max_lead ;
max_endo_lag = m . max_endo_lag ;
max_endo_lead = m . max_endo_lead ;
max_exo_lag = m . max_exo_lag ;
max_exo_lead = m . max_exo_lead ;
max_exo_det_lag = m . max_exo_det_lag ;
max_exo_det_lead = m . max_exo_det_lead ;
max_lag_orig = m . max_lag_orig ;
max_lead_orig = m . max_lead_orig ;
2018-12-11 17:26:50 +01:00
max_lag_with_diffs_expanded_orig = m . max_lag_with_diffs_expanded_orig ;
2018-10-09 18:27:19 +02:00
max_endo_lag_orig = m . max_endo_lag_orig ;
max_endo_lead_orig = m . max_endo_lead_orig ;
max_exo_lag_orig = m . max_exo_lag_orig ;
max_exo_lead_orig = m . max_exo_lead_orig ;
max_exo_det_lag_orig = m . max_exo_det_lag_orig ;
max_exo_det_lead_orig = m . max_exo_det_lead_orig ;
xrefs = m . xrefs ;
2019-12-20 16:59:30 +01:00
xref_param = m . xref_param ;
2018-10-09 18:27:19 +02:00
xref_endo = m . xref_endo ;
xref_exo = m . xref_exo ;
xref_exo_det = m . xref_exo_det ;
nonzero_hessian_eqs = m . nonzero_hessian_eqs ;
2020-04-30 14:57:50 +02:00
dynJacobianColsNbr = m . dynJacobianColsNbr ;
variableMapping = m . variableMapping ;
2020-04-30 16:00:16 +02:00
blocks_derivatives_other_endo . clear ( ) ;
blocks_derivatives_exo . clear ( ) ;
blocks_derivatives_exo_det . clear ( ) ;
2020-05-06 14:02:58 +02:00
blocks_other_endo = m . blocks_other_endo ;
blocks_exo = m . blocks_exo ;
blocks_exo_det = m . blocks_exo_det ;
blocks_jacob_cols_endo = m . blocks_jacob_cols_endo ;
blocks_jacob_cols_other_endo = m . blocks_jacob_cols_other_endo ;
blocks_jacob_cols_exo = m . blocks_jacob_cols_exo ;
blocks_jacob_cols_exo_det = m . blocks_jacob_cols_exo_det ;
2018-10-09 18:27:19 +02:00
var_expectation_functions_to_write = m . var_expectation_functions_to_write ;
2020-05-05 16:34:51 +02:00
pac_mce_alpha_symb_ids = m . pac_mce_alpha_symb_ids ;
pac_h0_indices = m . pac_h0_indices ;
pac_h1_indices = m . pac_h1_indices ;
pac_mce_z1_symb_ids = m . pac_mce_z1_symb_ids ;
pac_eqtag_and_lag = m . pac_eqtag_and_lag ;
pac_expectation_substitution . clear ( ) ;
pac_model_info = m . pac_model_info ;
pac_equation_info = m . pac_equation_info ;
2018-10-09 18:27:19 +02:00
copyHelper ( m ) ;
return * this ;
2009-04-16 12:33:30 +02:00
}
2009-04-14 16:39:53 +02:00
void
2020-05-13 12:53:47 +02:00
DynamicModel : : compileDerivative ( ofstream & code_file , unsigned int & instruction_number , int eq , int symb_id , int lag , const temporary_terms_t & temporary_terms , const temporary_terms_idxs_t & temporary_terms_idxs ) const
2009-12-16 18:13:23 +01:00
{
2019-10-28 11:09:36 +01:00
if ( auto it = derivatives [ 1 ] . find ( { eq , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , symb_id ) , lag ) } ) ;
it ! = derivatives [ 1 ] . end ( ) )
2020-05-13 12:53:47 +02:00
it - > second - > compile ( code_file , instruction_number , false , temporary_terms , temporary_terms_idxs , true , false ) ;
2009-12-16 18:13:23 +01:00
else
{
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
2009-07-21 17:50:12 +02:00
void
2020-05-13 12:53:47 +02:00
DynamicModel : : compileChainRuleDerivative ( ofstream & code_file , unsigned int & instruction_number , int blk , int eq , int var , int lag , const temporary_terms_t & temporary_terms , const temporary_terms_idxs_t & temporary_terms_idxs ) const
2009-07-21 17:50:12 +02:00
{
2020-04-24 12:29:02 +02:00
if ( auto it = blocks_derivatives [ blk ] . find ( { eq , var , lag } ) ;
it ! = blocks_derivatives [ blk ] . end ( ) )
2020-05-13 12:53:47 +02:00
it - > second - > compile ( code_file , instruction_number , false , temporary_terms , temporary_terms_idxs , true , false ) ;
2009-07-21 17:50:12 +02:00
else
2009-10-16 18:34:27 +02:00
{
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-10-16 18:34:27 +02:00
}
2009-07-21 17:50:12 +02:00
}
2009-04-14 16:39:53 +02:00
void
2020-05-06 17:13:47 +02:00
DynamicModel : : additionalBlockTemporaryTerms ( int blk ,
2020-05-13 16:58:19 +02:00
vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2009-04-14 16:39:53 +02:00
{
2020-05-06 17:13:47 +02:00
for ( const auto & [ ignore , d ] : blocks_derivatives_exo [ blk ] )
2020-05-13 16:58:19 +02:00
d - > computeBlockTemporaryTerms ( blk , blocks [ blk ] . size , blocks_temporary_terms , reference_count ) ;
2020-05-06 17:13:47 +02:00
for ( const auto & [ ignore , d ] : blocks_derivatives_exo_det [ blk ] )
2020-05-13 16:58:19 +02:00
d - > computeBlockTemporaryTerms ( blk , blocks [ blk ] . size , blocks_temporary_terms , reference_count ) ;
2020-05-06 17:13:47 +02:00
for ( const auto & [ ignore , d ] : blocks_derivatives_other_endo [ blk ] )
2020-05-13 16:58:19 +02:00
d - > computeBlockTemporaryTerms ( blk , blocks [ blk ] . size , blocks_temporary_terms , reference_count ) ;
2010-01-22 11:03:29 +01:00
}
2020-06-22 12:46:33 +02:00
void
DynamicModel : : writeDynamicPerBlockHelper ( int blk , ostream & output , ExprNodeOutputType output_type , temporary_terms_t & temporary_terms , int nze_stochastic , int nze_deterministic , int nze_exo , int nze_exo_det , int nze_other_endo ) const
{
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
int block_size = blocks [ blk ] . size ;
int block_mfs_size = blocks [ blk ] . mfs_size ;
int block_recursive_size = blocks [ blk ] . getRecursiveSize ( ) ;
deriv_node_temp_terms_t tef_terms ;
auto write_eq_tt = [ & ] ( int eq )
{
for ( auto it : blocks_temporary_terms [ blk ] [ eq ] )
{
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) )
it - > writeExternalFunctionOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs , tef_terms ) ;
output < < " " ;
it - > writeOutput ( output , output_type , blocks_temporary_terms [ blk ] [ eq ] , blocks_temporary_terms_idxs , tef_terms ) ;
output < < ' = ' ;
it - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs , tef_terms ) ;
temporary_terms . insert ( it ) ;
output < < ' ; ' < < endl ;
}
} ;
// The equations
for ( int eq = 0 ; eq < block_size ; eq + + )
{
write_eq_tt ( eq ) ;
EquationType equ_type = getBlockEquationType ( blk , eq ) ;
BinaryOpNode * e = getBlockEquationExpr ( blk , eq ) ;
expr_t lhs = e - > arg1 , rhs = e - > arg2 ;
switch ( simulation_type )
{
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
evaluation :
if ( equ_type = = EquationType : : evaluateRenormalized )
{
e = getBlockEquationRenormalizedExpr ( blk , eq ) ;
lhs = e - > arg1 ;
rhs = e - > arg2 ;
}
else if ( equ_type ! = EquationType : : evaluate )
{
cerr < < " Type mismatch for equation " < < getBlockEquationID ( blk , eq ) + 1 < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " " ;
lhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < ' = ' ;
rhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < ' ; ' < < endl ;
break ;
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
case BlockSimulationType : : solveTwoBoundariesComplete :
case BlockSimulationType : : solveTwoBoundariesSimple :
if ( eq < block_recursive_size )
goto evaluation ;
output < < " residual " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < eq - block_recursive_size + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " =( " ;
goto end ;
default :
end :
lhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < " )-( " ;
rhs - > writeOutput ( output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
output < < " ); " < < endl ;
}
}
// The Jacobian if we have to solve the block
// Write temporary terms for derivatives
write_eq_tt ( blocks [ blk ] . size ) ;
2020-06-23 15:13:04 +02:00
if ( isCOutput ( output_type ) )
output < < " if (stochastic_mode) { " < < endl ;
else
output < < " if stochastic_mode " < < endl ;
2020-06-22 12:46:33 +02:00
ostringstream i_output , j_output , v_output ;
int line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
auto [ eq , var , lag ] = indices ;
int jacob_col = blocks_jacob_cols_endo [ blk ] . at ( { var , lag } ) ;
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
2020-06-23 15:13:04 +02:00
assert ( line_counter = = nze_stochastic + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
2020-06-22 12:46:33 +02:00
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_exo [ blk ] )
{
auto [ eq , var , lag ] = indices ;
int jacob_col = blocks_jacob_cols_exo [ blk ] . at ( { var , lag } ) ;
i_output < < " g1_x_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_x_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_x_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
2020-06-23 15:13:04 +02:00
assert ( line_counter = = nze_exo + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
2020-06-22 12:46:33 +02:00
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_exo_det [ blk ] )
{
auto [ eq , var , lag ] = indices ;
int jacob_col = blocks_jacob_cols_exo_det [ blk ] . at ( { var , lag } ) ;
i_output < < " g1_xd_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_xd_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_xd_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
2020-06-23 15:13:04 +02:00
assert ( line_counter = = nze_exo_det + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
2020-06-22 12:46:33 +02:00
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
for ( const auto & [ indices , d ] : blocks_derivatives_other_endo [ blk ] )
{
auto [ eq , var , lag ] = indices ;
int jacob_col = blocks_jacob_cols_other_endo [ blk ] . at ( { var , lag } ) ;
i_output < < " g1_o_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < eq + 1 < < ' ; ' < < endl ;
j_output < < " g1_o_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' < < jacob_col + 1 < < ' ; ' < < endl ;
v_output < < " g1_o_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
2020-06-23 15:13:04 +02:00
assert ( line_counter = = nze_other_endo + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
2020-06-22 12:46:33 +02:00
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
// Deterministic mode
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
{
2020-06-23 15:13:04 +02:00
if ( isCOutput ( output_type ) )
output < < " } else { " < < endl ;
else
output < < " else " < < endl ;
2020-06-22 12:46:33 +02:00
i_output . str ( " " ) ;
j_output . str ( " " ) ;
v_output . str ( " " ) ;
line_counter = ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
if ( simulation_type = = BlockSimulationType : : solveBackwardSimple
| | simulation_type = = BlockSimulationType : : solveForwardSimple
| | simulation_type = = BlockSimulationType : : solveBackwardComplete
| | simulation_type = = BlockSimulationType : : solveForwardComplete )
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
auto [ eq , var , lag ] = indices ;
2020-10-07 18:52:34 +02:00
if ( lag = = 0 & & eq > = block_recursive_size & & var > = block_recursive_size )
2020-06-22 12:46:33 +02:00
{
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
2020-10-07 18:52:34 +02:00
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < eq + 1 - block_recursive_size < < ' ; ' < < endl ;
2020-06-22 12:46:33 +02:00
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < var + 1 - block_recursive_size < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
}
else // solveTwoBoundariesSimple || solveTwoBoundariesComplete
for ( const auto & [ indices , d ] : blocks_derivatives [ blk ] )
{
auto [ eq , var , lag ] = indices ;
assert ( lag > = - 1 & & lag < = 1 ) ;
if ( eq > = block_recursive_size & & var > = block_recursive_size )
{
i_output < < " g1_i " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < eq + 1 - block_recursive_size < < ' ; ' < < endl ;
j_output < < " g1_j " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = '
< < var + 1 - block_recursive_size + block_mfs_size * ( lag + 1 ) < < ' ; ' < < endl ;
v_output < < " g1_v " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < line_counter
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < ' = ' ;
d - > writeOutput ( v_output , output_type , temporary_terms , blocks_temporary_terms_idxs ) ;
v_output < < ' ; ' < < endl ;
line_counter + + ;
}
}
2020-06-23 15:13:04 +02:00
assert ( line_counter = = nze_deterministic + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ) ;
2020-06-22 12:46:33 +02:00
output < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
}
2020-06-23 15:13:04 +02:00
if ( isCOutput ( output_type ) )
output < < " } " < < endl ;
else
output < < " end " < < endl ;
}
int
DynamicModel : : nzeDeterministicJacobianForBlock ( int blk ) const
{
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
int block_recursive_size = blocks [ blk ] . getRecursiveSize ( ) ;
int nze_deterministic = 0 ;
if ( simulation_type = = BlockSimulationType : : solveTwoBoundariesComplete
| | simulation_type = = BlockSimulationType : : solveTwoBoundariesSimple )
nze_deterministic = count_if ( blocks_derivatives [ blk ] . begin ( ) , blocks_derivatives [ blk ] . end ( ) ,
[ = ] ( const auto & kv ) {
auto [ eq , var , lag ] = kv . first ;
return eq > = block_recursive_size & & var > = block_recursive_size ;
} ) ;
else if ( simulation_type = = BlockSimulationType : : solveBackwardSimple
| | simulation_type = = BlockSimulationType : : solveForwardSimple
| | simulation_type = = BlockSimulationType : : solveBackwardComplete
| | simulation_type = = BlockSimulationType : : solveForwardComplete )
nze_deterministic = count_if ( blocks_derivatives [ blk ] . begin ( ) , blocks_derivatives [ blk ] . end ( ) ,
2020-10-07 18:52:34 +02:00
[ = ] ( const auto & kv ) {
2020-06-23 15:13:04 +02:00
auto [ eq , var , lag ] = kv . first ;
2020-10-07 18:52:34 +02:00
return lag = = 0 & & eq > = block_recursive_size & & var > = block_recursive_size ;
2020-06-23 15:13:04 +02:00
} ) ;
return nze_deterministic ;
2020-06-22 12:46:33 +02:00
}
2009-04-14 16:39:53 +02:00
void
2020-05-19 16:56:53 +02:00
DynamicModel : : writeDynamicPerBlockMFiles ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
2020-05-06 17:13:47 +02:00
temporary_terms_t temporary_terms ; // Temp terms written so far
2009-12-16 18:13:23 +01:00
2020-05-19 16:56:53 +02:00
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
2009-12-16 18:13:23 +01:00
{
2020-05-19 16:56:53 +02:00
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
int block_size = blocks [ blk ] . size ;
int block_mfs_size = blocks [ blk ] . mfs_size ;
2020-06-19 15:15:15 +02:00
// Number of nonzero derivatives for the various Jacobians
int nze_stochastic = blocks_derivatives [ blk ] . size ( ) ;
2020-06-23 15:13:04 +02:00
int nze_deterministic = nzeDeterministicJacobianForBlock ( blk ) ;
2020-06-19 15:15:15 +02:00
int nze_other_endo = blocks_derivatives_other_endo [ blk ] . size ( ) ;
int nze_exo = blocks_derivatives_exo [ blk ] . size ( ) ;
int nze_exo_det = blocks_derivatives_exo_det [ blk ] . size ( ) ;
2020-05-19 16:56:53 +02:00
string filename = packageDir ( basename + " .block " ) + " /dynamic_ " + to_string ( blk + 1 ) + " .m " ;
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
2020-06-23 15:13:04 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-12-16 18:13:23 +01:00
2018-11-23 17:19:59 +01:00
output < < " % " < < endl
2020-05-19 16:56:53 +02:00
< < " % " < < filename < < " : Computes dynamic version of one block " < < endl
2018-11-23 17:19:59 +01:00
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
2020-05-19 16:56:53 +02:00
< < " % " < < endl ;
2020-03-20 17:31:14 +01:00
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-06-16 15:54:51 +02:00
output < < " function [y, T, g1, varargout] = dynamic_ " < < blk + 1 < < " (y, x, params, steady_state, T, it_, stochastic_mode) " < < endl ;
2009-12-16 18:13:23 +01:00
else
2020-10-06 17:16:50 +02:00
output < < " function [residual, y, T, g1, varargout] = dynamic_ " < < blk + 1 < < " (y, x, params, steady_state, T, it_, stochastic_mode) " < < endl ;
2020-04-30 12:48:16 +02:00
2009-12-16 18:13:23 +01:00
output < < " % //////////////////////////////////////////////////////////////////////// " < < endl
2020-05-19 16:56:53 +02:00
< < " % // " < < string ( " Block " ) . substr ( static_cast < int > ( log10 ( blk + 1 ) ) ) < < blk + 1
2020-04-30 12:48:16 +02:00
< < " // " < < endl
2009-12-16 18:13:23 +01:00
< < " % // Simulation type "
< < BlockSim ( simulation_type ) < < " // " < < endl
2020-06-19 16:09:38 +02:00
< < " % //////////////////////////////////////////////////////////////////////// " < < endl ;
2009-12-16 14:21:31 +01:00
2020-06-22 12:46:33 +02:00
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
2020-06-16 15:34:45 +02:00
output < < " residual=zeros( " < < block_mfs_size < < " ,1); " < < endl ;
2020-05-06 17:13:47 +02:00
2020-06-22 12:46:33 +02:00
output < < " if stochastic_mode " < < endl
< < " g1_i=zeros( " < < nze_stochastic < < " ,1); " < < endl
< < " g1_j=zeros( " < < nze_stochastic < < " ,1); " < < endl
< < " g1_v=zeros( " < < nze_stochastic < < " ,1); " < < endl
< < " g1_x_i=zeros( " < < nze_exo < < " ,1); " < < endl
< < " g1_x_j=zeros( " < < nze_exo < < " ,1); " < < endl
< < " g1_x_v=zeros( " < < nze_exo < < " ,1); " < < endl
< < " g1_xd_i=zeros( " < < nze_exo_det < < " ,1); " < < endl
< < " g1_xd_j=zeros( " < < nze_exo_det < < " ,1); " < < endl
< < " g1_xd_v=zeros( " < < nze_exo_det < < " ,1); " < < endl
< < " g1_o_i=zeros( " < < nze_other_endo < < " ,1); " < < endl
< < " g1_o_j=zeros( " < < nze_other_endo < < " ,1); " < < endl
< < " g1_o_v=zeros( " < < nze_other_endo < < " ,1); " < < endl ;
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
output < < " else " < < endl
< < " g1_i=zeros( " < < nze_deterministic < < " ,1); " < < endl
< < " g1_j=zeros( " < < nze_deterministic < < " ,1); " < < endl
< < " g1_v=zeros( " < < nze_deterministic < < " ,1); " < < endl ;
output < < " end " < < endl
< < endl ;
2020-05-13 16:58:19 +02:00
2020-06-22 12:46:33 +02:00
writeDynamicPerBlockHelper ( blk , output , ExprNodeOutputType : : matlabDynamicModel , temporary_terms ,
nze_stochastic , nze_deterministic , nze_exo , nze_exo_det , nze_other_endo ) ;
2020-05-13 16:58:19 +02:00
2020-06-22 12:46:33 +02:00
output < < endl
2020-06-19 16:09:38 +02:00
< < " if stochastic_mode " < < endl
2020-06-22 12:46:33 +02:00
< < " g1=sparse(g1_i, g1_j, g1_v, " < < block_size < < " , " < < blocks_jacob_cols_endo [ blk ] . size ( ) < < " ); " < < endl
2020-06-19 16:09:38 +02:00
< < " varargout{1}=sparse(g1_x_i, g1_x_j, g1_x_v, " < < block_size < < " , " < < blocks_jacob_cols_exo [ blk ] . size ( ) < < " ); " < < endl
< < " varargout{2}=sparse(g1_xd_i, g1_xd_j, g1_xd_v, " < < block_size < < " , " < < blocks_jacob_cols_exo_det [ blk ] . size ( ) < < " ); " < < endl
2020-06-19 18:33:53 +02:00
< < " varargout{3}=sparse(g1_o_i, g1_o_j, g1_o_v, " < < block_size < < " , " < < blocks_jacob_cols_other_endo [ blk ] . size ( ) < < " ); " < < endl
< < " else " < < endl ;
2010-11-20 15:52:51 +01:00
switch ( simulation_type )
{
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : evaluateForward :
case BlockSimulationType : : evaluateBackward :
2020-06-22 12:46:33 +02:00
output < < " g1=[]; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
2020-06-22 12:46:33 +02:00
output < < " g1=sparse(g1_i, g1_j, g1_v, " < < block_mfs_size
2020-06-19 18:33:53 +02:00
< < " , " < < block_mfs_size < < " ); " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveTwoBoundariesSimple :
case BlockSimulationType : : solveTwoBoundariesComplete :
2020-06-22 12:46:33 +02:00
output < < " g1=sparse(g1_i, g1_j, g1_v, " < < block_mfs_size
2020-06-19 18:33:53 +02:00
< < " , " < < 3 * block_mfs_size < < " ); " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
default :
break ;
}
2020-06-19 18:33:53 +02:00
output < < " end " < < endl
< < " end " < < endl ;
2009-12-16 18:13:23 +01:00
output . close ( ) ;
}
}
2009-04-14 16:39:53 +02:00
2020-06-23 15:13:04 +02:00
void
DynamicModel : : writeDynamicPerBlockCFiles ( const string & basename ) const
{
temporary_terms_t temporary_terms ; // Temp terms written so far
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
int block_size = blocks [ blk ] . size ;
int block_mfs_size = blocks [ blk ] . mfs_size ;
// Number of nonzero derivatives for the various Jacobians
int nze_stochastic = blocks_derivatives [ blk ] . size ( ) ;
int nze_deterministic = nzeDeterministicJacobianForBlock ( blk ) ;
int nze_other_endo = blocks_derivatives_other_endo [ blk ] . size ( ) ;
int nze_exo = blocks_derivatives_exo [ blk ] . size ( ) ;
int nze_exo_det = blocks_derivatives_exo_det [ blk ] . size ( ) ;
string filename = basename + " /model/src/dynamic_ " + to_string ( blk + 1 ) + " .c " ;
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " /* Block " < < blk + 1 < < endl
< < " " < < BlockSim ( simulation_type ) < < " */ " < < endl
< < endl
< < " #include <math.h> " < < endl
< < " #include <stdlib.h> " < < endl
< < " #include <stdbool.h> " < < endl
< < R " (#include " mex . h " ) " < < endl
< < endl ;
// Write function definition if BinaryOpcode::powerDeriv is used
writePowerDerivHeader ( output ) ;
output < < endl ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-09-03 17:52:12 +02:00
output < < " void dynamic_ " < < blk + 1 < < " (double *restrict y, const double *restrict x, int nb_row_x, const double *restrict params, const double *restrict steady_state, double *restrict T, int it_, bool stochastic_mode, double *restrict g1_i, double *restrict g1_j, double *restrict g1_v, double *restrict g1_x_i, double *restrict g1_x_j, double *restrict g1_x_v, double *restrict g1_xd_i, double *restrict g1_xd_j, double *restrict g1_xd_v, double *restrict g1_o_i, double *restrict g1_o_j, double *restrict g1_o_v) " < < endl ;
2020-06-23 15:13:04 +02:00
else
2020-10-06 17:16:50 +02:00
output < < " void dynamic_ " < < blk + 1 < < " (double *restrict y, const double *restrict x, int nb_row_x, const double *restrict params, const double *restrict steady_state, double *restrict T, int it_, bool stochastic_mode, double *restrict residual, double *restrict g1_i, double *restrict g1_j, double *restrict g1_v, double *restrict g1_x_i, double *restrict g1_x_j, double *restrict g1_x_v, double *restrict g1_xd_i, double *restrict g1_xd_j, double *restrict g1_xd_v, double *restrict g1_o_i, double *restrict g1_o_j, double *restrict g1_o_v) " < < endl ;
2020-06-23 15:13:04 +02:00
output < < ' { ' < < endl ;
writeDynamicPerBlockHelper ( blk , output , ExprNodeOutputType : : CDynamicModel , temporary_terms ,
nze_stochastic , nze_deterministic , nze_exo , nze_exo_det , nze_other_endo ) ;
output < < ' } ' < < endl
< < endl ;
ostringstream header ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
header < < " void dynamic_ " < < blk + 1 < < " _mx(mxArray *y, const mxArray *x, const mxArray *params, const mxArray *steady_state, mxArray *T, const mxArray *it_, const mxArray *stochastic_mode, mxArray **g1, mxArray **g1_x, mxArray **g1_xd, mxArray **g1_o) " ;
else
2020-10-06 17:16:50 +02:00
header < < " void dynamic_ " < < blk + 1 < < " _mx(mxArray *y, const mxArray *x, const mxArray *params, const mxArray *steady_state, mxArray *T, const mxArray *it_, const mxArray *stochastic_mode, mxArray **residual, mxArray **g1, mxArray **g1_x, mxArray **g1_xd, mxArray **g1_o) " ;
2020-06-23 15:13:04 +02:00
output < < header . str ( ) < < endl
< < ' { ' < < endl
< < " int nb_row_x = mxGetM(x); " < < endl ;
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
output < < " *residual = mxCreateDoubleMatrix( " < < block_mfs_size < < " ,1,mxREAL); " < < endl ;
output < < " mxArray *g1_i = NULL, *g1_j = NULL, *g1_v = NULL; " < < endl
< < " mxArray *g1_x_i = NULL, *g1_x_j = NULL, *g1_x_v = NULL; " < < endl
< < " mxArray *g1_xd_i = NULL, *g1_xd_j = NULL, *g1_xd_v = NULL; " < < endl
< < " mxArray *g1_o_i = NULL, *g1_o_j = NULL, *g1_o_v = NULL; " < < endl
< < " if (mxGetScalar(stochastic_mode)) { " < < endl
< < " g1_i=mxCreateDoubleMatrix( " < < nze_stochastic < < " ,1,mxREAL); " < < endl
< < " g1_j=mxCreateDoubleMatrix( " < < nze_stochastic < < " ,1,mxREAL); " < < endl
< < " g1_v=mxCreateDoubleMatrix( " < < nze_stochastic < < " ,1,mxREAL); " < < endl
< < " g1_x_i=mxCreateDoubleMatrix( " < < nze_exo < < " ,1,mxREAL); " < < endl
< < " g1_x_j=mxCreateDoubleMatrix( " < < nze_exo < < " ,1,mxREAL); " < < endl
< < " g1_x_v=mxCreateDoubleMatrix( " < < nze_exo < < " ,1,mxREAL); " < < endl
< < " g1_xd_i=mxCreateDoubleMatrix( " < < nze_exo_det < < " ,1,mxREAL); " < < endl
< < " g1_xd_j=mxCreateDoubleMatrix( " < < nze_exo_det < < " ,1,mxREAL); " < < endl
< < " g1_xd_v=mxCreateDoubleMatrix( " < < nze_exo_det < < " ,1,mxREAL); " < < endl
< < " g1_o_i=mxCreateDoubleMatrix( " < < nze_other_endo < < " ,1,mxREAL); " < < endl
< < " g1_o_j=mxCreateDoubleMatrix( " < < nze_other_endo < < " ,1,mxREAL); " < < endl
< < " g1_o_v=mxCreateDoubleMatrix( " < < nze_other_endo < < " ,1,mxREAL); " < < endl ;
if ( simulation_type ! = BlockSimulationType : : evaluateForward
& & simulation_type ! = BlockSimulationType : : evaluateBackward )
output < < " } else { " < < endl
< < " g1_i=mxCreateDoubleMatrix( " < < nze_deterministic < < " ,1,mxREAL); " < < endl
< < " g1_j=mxCreateDoubleMatrix( " < < nze_deterministic < < " ,1,mxREAL); " < < endl
< < " g1_v=mxCreateDoubleMatrix( " < < nze_deterministic < < " ,1,mxREAL); " < < endl ;
output < < " } " < < endl
< < endl ;
2020-06-25 15:19:49 +02:00
// N.B.: In the following, it_ is decreased by 1, to follow C convention
2020-06-23 15:13:04 +02:00
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
2020-06-25 15:19:49 +02:00
output < < " dynamic_ " < < blk + 1 < < " (mxGetPr(y), mxGetPr(x), nb_row_x, mxGetPr(params), mxGetPr(steady_state), mxGetPr(T), mxGetScalar(it_)-1, mxGetScalar(stochastic_mode), g1_i ? mxGetPr(g1_i) : NULL, g1_j ? mxGetPr(g1_j) : NULL, g1_v ? mxGetPr(g1_v) : NULL, g1_x_i ? mxGetPr(g1_x_i) : NULL, g1_x_j ? mxGetPr(g1_x_j) : NULL, g1_x_v ? mxGetPr(g1_x_v) : NULL, g1_xd_i ? mxGetPr(g1_xd_i) : NULL, g1_xd_j ? mxGetPr(g1_xd_j) : NULL, g1_xd_v ? mxGetPr(g1_xd_v) : NULL, g1_o_i ? mxGetPr(g1_o_i) : NULL, g1_o_j ? mxGetPr(g1_o_j) : NULL, g1_o_v ? mxGetPr(g1_o_v) : NULL); " < < endl ;
2020-06-23 15:13:04 +02:00
else
2020-06-25 15:19:49 +02:00
output < < " dynamic_ " < < blk + 1 < < " (mxGetPr(y), mxGetPr(x), nb_row_x, mxGetPr(params), mxGetPr(steady_state), mxGetPr(T), mxGetScalar(it_)-1, mxGetScalar(stochastic_mode), mxGetPr(*residual), g1_i ? mxGetPr(g1_i) : NULL, g1_j ? mxGetPr(g1_j) : NULL, g1_v ? mxGetPr(g1_v) : NULL, g1_x_i ? mxGetPr(g1_x_i) : NULL, g1_x_j ? mxGetPr(g1_x_j) : NULL, g1_x_v ? mxGetPr(g1_x_v) : NULL, g1_xd_i ? mxGetPr(g1_xd_i) : NULL, g1_xd_j ? mxGetPr(g1_xd_j) : NULL, g1_xd_v ? mxGetPr(g1_xd_v) : NULL, g1_o_i ? mxGetPr(g1_o_i) : NULL, g1_o_j ? mxGetPr(g1_o_j) : NULL, g1_o_v ? mxGetPr(g1_o_v) : NULL); " < < endl ;
2020-06-23 15:13:04 +02:00
output < < endl
< < " if (mxGetScalar(stochastic_mode)) { " < < endl
< < " mxArray *m = mxCreateDoubleScalar( " < < block_size < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < blocks_jacob_cols_endo [ blk ] . size ( ) < < " ); " < < endl
< < " mxArray *plhs[1]; " < < endl
< < " mxArray *prhs[5] = { g1_i, g1_j, g1_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs, " sparse " );) " < < endl
< < " *g1=plhs[0]; " < < endl
< < " mxDestroyArray(g1_i); " < < endl
< < " mxDestroyArray(g1_j); " < < endl
< < " mxDestroyArray(g1_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " n = mxCreateDoubleScalar( " < < blocks_jacob_cols_exo [ blk ] . size ( ) < < " ); " < < endl
< < " mxArray *prhs_x[5] = { g1_x_i, g1_x_j, g1_x_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs_x, " sparse " );) " < < endl
< < " *g1_x=plhs[0]; " < < endl
< < " mxDestroyArray(g1_x_i); " < < endl
< < " mxDestroyArray(g1_x_j); " < < endl
< < " mxDestroyArray(g1_x_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " n = mxCreateDoubleScalar( " < < blocks_jacob_cols_exo_det [ blk ] . size ( ) < < " ); " < < endl
< < " mxArray *prhs_xd[5] = { g1_xd_i, g1_xd_j, g1_xd_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs_xd, " sparse " );) " < < endl
< < " *g1_xd=plhs[0]; " < < endl
< < " mxDestroyArray(g1_xd_i); " < < endl
< < " mxDestroyArray(g1_xd_j); " < < endl
< < " mxDestroyArray(g1_xd_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " n = mxCreateDoubleScalar( " < < blocks_jacob_cols_other_endo [ blk ] . size ( ) < < " ); " < < endl
< < " mxArray *prhs_o[5] = { g1_o_i, g1_o_j, g1_o_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs_o, " sparse " );) " < < endl
< < " *g1_o=plhs[0]; " < < endl
< < " mxDestroyArray(g1_o_i); " < < endl
< < " mxDestroyArray(g1_o_j); " < < endl
< < " mxDestroyArray(g1_o_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " mxDestroyArray(m); " < < endl
< < " } else { " < < endl ;
switch ( simulation_type )
{
case BlockSimulationType : : evaluateForward :
case BlockSimulationType : : evaluateBackward :
output < < " *g1=mxCreateDoubleMatrix(0,0,mxREAL); " < < endl ;
break ;
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
output < < " mxArray *m = mxCreateDoubleScalar( " < < block_mfs_size < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < block_mfs_size < < " ); " < < endl
< < " mxArray *plhs[1]; " < < endl
< < " mxArray *prhs[5] = { g1_i, g1_j, g1_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs, " sparse " );) " < < endl
< < " *g1=plhs[0]; " < < endl
< < " mxDestroyArray(g1_i); " < < endl
< < " mxDestroyArray(g1_j); " < < endl
< < " mxDestroyArray(g1_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " mxDestroyArray(m); " < < endl ;
break ;
case BlockSimulationType : : solveTwoBoundariesSimple :
case BlockSimulationType : : solveTwoBoundariesComplete :
output < < " mxArray *m = mxCreateDoubleScalar( " < < block_mfs_size < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < 3 * block_mfs_size < < " ); " < < endl
< < " mxArray *plhs[1]; " < < endl
< < " mxArray *prhs[5] = { g1_i, g1_j, g1_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs, 5, prhs, " sparse " );) " < < endl
< < " *g1=plhs[0]; " < < endl
< < " mxDestroyArray(g1_i); " < < endl
< < " mxDestroyArray(g1_j); " < < endl
< < " mxDestroyArray(g1_v); " < < endl
< < " mxDestroyArray(n); " < < endl
< < " mxDestroyArray(m); " < < endl ;
break ;
default :
break ;
}
output < < " *g1_x=mxCreateDoubleMatrix(0,0,mxREAL); " < < endl
< < " *g1_xd=mxCreateDoubleMatrix(0,0,mxREAL); " < < endl
< < " *g1_o=mxCreateDoubleMatrix(0,0,mxREAL); " < < endl
< < " } " < < endl
< < " } " < < endl ;
output . close ( ) ;
filename = basename + " /model/src/dynamic_ " + to_string ( blk + 1 ) + " .h " ;
ofstream header_output ;
header_output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! header_output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
header_output < < header . str ( ) < < ' ; ' < < endl ;
header_output . close ( ) ;
}
}
2009-04-14 16:39:53 +02:00
void
2020-05-19 17:43:35 +02:00
DynamicModel : : writeDynamicBytecode ( const string & basename ) const
2010-01-22 11:03:29 +01:00
{
ostringstream tmp_output ;
ofstream code_file ;
2010-07-23 11:20:24 +02:00
unsigned int instruction_number = 0 ;
2010-01-22 11:03:29 +01:00
bool file_open = false ;
2018-06-27 15:01:31 +02:00
string main_name = basename + " /model/bytecode/dynamic.cod " ;
2018-06-27 15:12:12 +02:00
code_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
2010-01-22 11:03:29 +01:00
if ( ! code_file . is_open ( ) )
{
2019-04-03 16:32:52 +02:00
cerr < < R " (Error : Can't open file " ) " << main_name << R " ( " for writing) " < < endl ;
2010-01-22 11:03:29 +01:00
exit ( EXIT_FAILURE ) ;
}
int count_u ;
int u_count_int = 0 ;
BlockSimulationType simulation_type ;
if ( ( max_endo_lag > 0 ) & & ( max_endo_lead > 0 ) )
2020-03-20 17:31:14 +01:00
simulation_type = BlockSimulationType : : solveTwoBoundariesComplete ;
2010-01-22 11:03:29 +01:00
else if ( ( max_endo_lag > = 0 ) & & ( max_endo_lead = = 0 ) )
2020-03-20 17:31:14 +01:00
simulation_type = BlockSimulationType : : solveForwardComplete ;
2010-01-22 11:03:29 +01:00
else
2020-03-20 17:31:14 +01:00
simulation_type = BlockSimulationType : : solveBackwardComplete ;
2010-01-22 11:03:29 +01:00
2020-05-19 17:43:35 +02:00
writeBytecodeBinFile ( basename + " /model/bytecode/dynamic.bin " , u_count_int , file_open , simulation_type = = BlockSimulationType : : solveTwoBoundariesComplete ) ;
2010-01-22 11:03:29 +01:00
file_open = true ;
//Temporary variables declaration
2020-05-13 15:16:38 +02:00
FDIMT_ fdimt ( temporary_terms_idxs . size ( ) ) ;
2010-07-23 11:20:24 +02:00
fdimt . write ( code_file , instruction_number ) ;
2020-05-06 14:02:58 +02:00
vector < int > exo , exo_det , other_endo ;
2010-01-22 11:03:29 +01:00
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < symbol_table . exo_det_nbr ( ) ; i + + )
2010-07-23 11:20:24 +02:00
exo_det . push_back ( i ) ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < symbol_table . exo_nbr ( ) ; i + + )
2010-07-23 11:20:24 +02:00
exo . push_back ( i ) ;
2010-10-27 15:34:48 +02:00
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > first_derivatives_reordered_endo ;
map < tuple < int , SymbolType , int , int > , expr_t > first_derivatives_reordered_exo ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2010-10-27 15:34:48 +02:00
{
2019-12-16 19:42:59 +01:00
int deriv_id = indices [ 1 ] ;
2020-03-24 18:26:06 +01:00
int eq = indices [ 0 ] ;
2010-10-27 15:34:48 +02:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
2020-03-24 18:26:06 +01:00
int var = symbol_table . getTypeSpecificID ( symb ) ;
2010-10-27 15:34:48 +02:00
int lag = getLagByDerivID ( deriv_id ) ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2019-12-16 19:42:59 +01:00
first_derivatives_reordered_endo [ { lag , var , eq } ] = d1 ;
2018-07-17 18:34:07 +02:00
else if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : exogenous | | getTypeByDerivID ( deriv_id ) = = SymbolType : : exogenousDet )
2019-12-16 19:42:59 +01:00
first_derivatives_reordered_exo [ { lag , getTypeByDerivID ( deriv_id ) , var , eq } ] = d1 ;
2010-10-27 15:34:48 +02:00
}
int prev_var = - 1 ;
int prev_lag = - 999999999 ;
int count_col_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : first_derivatives_reordered_endo )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int var , lag ;
tie ( lag , var , ignore ) = it . first ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-10-27 15:34:48 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_endo + + ;
}
}
2010-11-20 15:52:51 +01:00
prev_var = - 1 ;
prev_lag = - 999999999 ;
2018-07-17 18:34:07 +02:00
SymbolType prev_type { SymbolType : : unusedEndogenous } ; // Any non-exogenous type would do here
2010-11-20 15:52:51 +01:00
int count_col_exo = 0 ;
2014-12-17 09:37:43 +01:00
int count_col_det_exo = 0 ;
2010-11-20 15:52:51 +01:00
2019-12-20 16:59:30 +01:00
for ( const auto & it : first_derivatives_reordered_exo )
2010-11-20 15:52:51 +01:00
{
2018-11-23 17:19:59 +01:00
int var , lag ;
SymbolType type ;
tie ( lag , type , var , ignore ) = it . first ;
2011-03-18 01:09:20 +01:00
if ( prev_var ! = var | | prev_lag ! = lag | | prev_type ! = type )
2010-11-20 15:52:51 +01:00
{
prev_var = var ;
prev_lag = lag ;
2011-03-18 01:09:20 +01:00
prev_type = type ;
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : exogenous )
2014-12-17 09:37:43 +01:00
count_col_exo + + ;
2018-07-17 18:34:07 +02:00
else if ( type = = SymbolType : : exogenousDet )
2014-12-17 09:37:43 +01:00
count_col_det_exo + + ;
2010-11-20 15:52:51 +01:00
}
}
2017-06-01 19:58:32 +02:00
2010-01-22 11:03:29 +01:00
FBEGINBLOCK_ fbeginblock ( symbol_table . endo_nbr ( ) ,
simulation_type ,
0 ,
symbol_table . endo_nbr ( ) ,
2020-04-17 14:55:55 +02:00
endo_idx_block2orig ,
eq_idx_block2orig ,
2010-01-22 11:03:29 +01:00
false ,
symbol_table . endo_nbr ( ) ,
2014-12-17 09:37:43 +01:00
max_endo_lag ,
max_endo_lead ,
2010-07-23 11:20:24 +02:00
u_count_int ,
2010-10-27 15:34:48 +02:00
count_col_endo ,
2010-07-23 11:20:24 +02:00
symbol_table . exo_det_nbr ( ) ,
2014-12-17 09:37:43 +01:00
count_col_det_exo ,
symbol_table . exo_nbr ( ) ,
2010-11-20 15:52:51 +01:00
count_col_exo ,
2014-12-17 09:37:43 +01:00
0 ,
2010-07-23 11:20:24 +02:00
0 ,
exo_det ,
exo ,
2020-05-06 14:02:58 +02:00
other_endo ) ;
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
2020-05-13 12:53:47 +02:00
temporary_terms_t temporary_terms_union ;
compileTemporaryTerms ( code_file , instruction_number , true , false , temporary_terms_union , temporary_terms_idxs ) ;
2010-01-22 11:03:29 +01:00
2020-05-13 12:53:47 +02:00
compileModelEquations ( code_file , instruction_number , true , false , temporary_terms_union , temporary_terms_idxs ) ;
2010-01-22 11:03:29 +01:00
FENDEQU_ fendequ ;
2010-07-23 11:20:24 +02:00
fendequ . write ( code_file , instruction_number ) ;
2010-10-27 15:34:48 +02:00
// Get the current code_file position and jump if eval = true
streampos pos1 = code_file . tellp ( ) ;
FJMPIFEVAL_ fjmp_if_eval ( 0 ) ;
fjmp_if_eval . write ( code_file , instruction_number ) ;
int prev_instruction_number = instruction_number ;
2018-11-23 17:19:59 +01:00
vector < vector < tuple < int , int , int > > > my_derivatives ( symbol_table . endo_nbr ( ) ) ; ;
2010-01-22 11:03:29 +01:00
count_u = symbol_table . endo_nbr ( ) ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2010-01-22 11:03:29 +01:00
{
2019-12-16 19:42:59 +01:00
int deriv_id = indices [ 1 ] ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2010-01-22 11:03:29 +01:00
{
2020-03-24 18:26:06 +01:00
int eq = indices [ 0 ] ;
2010-01-22 11:03:29 +01:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
2020-03-24 18:26:06 +01:00
int var = symbol_table . getTypeSpecificID ( symb ) ;
2010-01-22 11:03:29 +01:00
int lag = getLagByDerivID ( deriv_id ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eq , var , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( ! my_derivatives [ eq ] . size ( ) )
my_derivatives [ eq ] . clear ( ) ;
2018-11-23 17:19:59 +01:00
my_derivatives [ eq ] . emplace_back ( var , lag , count_u ) ;
2020-05-13 12:53:47 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms_union , temporary_terms_idxs , true , false ) ;
2010-01-22 11:03:29 +01:00
FSTPU_ fstpu ( count_u ) ;
2010-07-23 11:20:24 +02:00
fstpu . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
count_u + + ;
}
}
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
{
FLDR_ fldr ( i ) ;
2010-07-23 11:20:24 +02:00
fldr . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( my_derivatives [ i ] . size ( ) )
2010-01-22 11:03:29 +01:00
{
2019-12-16 19:42:59 +01:00
for ( auto it = my_derivatives [ i ] . begin ( ) ; it ! = my_derivatives [ i ] . end ( ) ; + + it )
2010-01-22 11:03:29 +01:00
{
2018-11-23 17:19:59 +01:00
FLDU_ fldu ( get < 2 > ( * it ) ) ;
2010-11-20 15:52:51 +01:00
fldu . write ( code_file , instruction_number ) ;
2018-11-23 17:19:59 +01:00
FLDV_ fldv { static_cast < int > ( SymbolType : : endogenous ) , static_cast < unsigned int > ( get < 0 > ( * it ) ) , get < 1 > ( * it ) } ;
2010-11-20 15:52:51 +01:00
fldv . write ( code_file , instruction_number ) ;
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : times ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2018-11-15 16:39:53 +01:00
if ( it ! = my_derivatives [ i ] . begin ( ) )
2010-11-20 15:52:51 +01:00
{
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : plus ) } ;
2010-11-20 15:52:51 +01:00
fbinary . write ( code_file , instruction_number ) ;
}
2010-01-22 11:03:29 +01:00
}
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-11-20 15:52:51 +01:00
fbinary . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
}
FSTPU_ fstpu ( i ) ;
2010-07-23 11:20:24 +02:00
fstpu . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
}
2010-10-27 15:34:48 +02:00
// Get the current code_file position and jump = true
streampos pos2 = code_file . tellp ( ) ;
FJMP_ fjmp ( 0 ) ;
fjmp . write ( code_file , instruction_number ) ;
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump
streampos pos3 = code_file . tellp ( ) ;
code_file . seekp ( pos1 ) ;
FJMPIFEVAL_ fjmp_if_eval1 ( instruction_number - prev_instruction_number ) ;
fjmp_if_eval1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos3 ) ;
2011-02-04 16:25:38 +01:00
prev_instruction_number = instruction_number ;
2010-10-27 15:34:48 +02:00
// The Jacobian
prev_var = - 1 ;
prev_lag = - 999999999 ;
count_col_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : first_derivatives_reordered_endo )
2010-10-27 15:34:48 +02:00
{
2020-03-24 18:26:06 +01:00
auto [ lag , var , eq ] = it . first ;
2018-11-23 17:19:59 +01:00
expr_t d1 = it . second ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eq , var , lag ) ;
2010-10-27 15:34:48 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-10-27 15:34:48 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_endo + + ;
}
2020-05-13 12:53:47 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms_union , temporary_terms_idxs , true , false ) ;
2010-10-27 15:34:48 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , count_col_endo - 1 ) ;
fstpg3 . write ( code_file , instruction_number ) ;
}
prev_var = - 1 ;
prev_lag = - 999999999 ;
2010-11-20 15:52:51 +01:00
count_col_exo = 0 ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : first_derivatives_reordered_exo )
2010-10-27 15:34:48 +02:00
{
2020-03-24 18:26:06 +01:00
auto [ lag , ignore , var , eq ] = it . first ;
2018-11-23 17:19:59 +01:00
expr_t d1 = it . second ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstExoDerivative , eq , var , lag ) ;
2010-10-27 15:34:48 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-10-27 15:34:48 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_exo + + ;
}
2020-05-13 12:53:47 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms_union , temporary_terms_idxs , true , false ) ;
2010-10-27 15:34:48 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , count_col_exo - 1 ) ;
fstpg3 . write ( code_file , instruction_number ) ;
}
// Set codefile position to previous JMP_ and set the number of instructions to jump
pos1 = code_file . tellp ( ) ;
code_file . seekp ( pos2 ) ;
FJMP_ fjmp1 ( instruction_number - prev_instruction_number ) ;
fjmp1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos1 ) ;
2010-01-22 11:03:29 +01:00
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
FEND_ fend ;
2010-07-23 11:20:24 +02:00
fend . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
code_file . close ( ) ;
}
void
2021-01-25 18:03:37 +01:00
DynamicModel : : writeDynamicBlockBytecode ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
struct Uff_l
2009-04-14 16:39:53 +02:00
{
2009-12-16 18:13:23 +01:00
int u , var , lag ;
Uff_l * pNext ;
} ;
struct Uff
{
Uff_l * Ufl , * Ufl_First ;
} ;
int i , v ;
string tmp_s ;
ostringstream tmp_output ;
ofstream code_file ;
2010-07-23 11:20:24 +02:00
unsigned int instruction_number = 0 ;
2018-06-04 12:52:14 +02:00
expr_t lhs = nullptr , rhs = nullptr ;
2009-12-16 18:13:23 +01:00
BinaryOpNode * eq_node ;
Uff Uf [ symbol_table . endo_nbr ( ) ] ;
2010-09-16 19:18:45 +02:00
map < expr_t , int > reference_count ;
2009-12-16 18:13:23 +01:00
vector < int > feedback_variables ;
bool file_open = false ;
2021-01-25 18:03:37 +01:00
string main_name = basename + " /model/bytecode/dynamic.cod " ;
2018-06-27 15:12:12 +02:00
code_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
2009-12-16 18:13:23 +01:00
if ( ! code_file . is_open ( ) )
{
2019-04-03 16:32:52 +02:00
cerr < < R " (Error : Can't open file " ) " << main_name << R " ( " for writing) " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
//Temporary variables declaration
2020-05-06 17:13:47 +02:00
FDIMT_ fdimt ( blocks_temporary_terms_idxs . size ( ) ) ;
2010-07-23 11:20:24 +02:00
fdimt . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
2020-04-23 16:04:02 +02:00
for ( int block = 0 ; block < static_cast < int > ( blocks . size ( ) ) ; block + + )
2009-12-16 18:13:23 +01:00
{
feedback_variables . clear ( ) ;
if ( block > 0 )
{
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
int count_u ;
int u_count_int = 0 ;
2020-04-23 16:04:02 +02:00
BlockSimulationType simulation_type = blocks [ block ] . simulation_type ;
int block_size = blocks [ block ] . size ;
int block_mfs = blocks [ block ] . mfs_size ;
int block_recursive = blocks [ block ] . getRecursiveSize ( ) ;
2020-04-30 11:15:55 +02:00
int block_max_lag = blocks [ block ] . max_lag ;
int block_max_lead = blocks [ block ] . max_lead ;
2009-12-16 18:13:23 +01:00
2020-03-20 17:31:14 +01:00
if ( simulation_type = = BlockSimulationType : : solveTwoBoundariesSimple
| | simulation_type = = BlockSimulationType : : solveTwoBoundariesComplete
| | simulation_type = = BlockSimulationType : : solveBackwardComplete
| | simulation_type = = BlockSimulationType : : solveForwardComplete )
2009-12-16 18:13:23 +01:00
{
2020-05-19 17:43:35 +02:00
writeBlockBytecodeBinFile ( basename , block , u_count_int , file_open ,
2021-01-25 18:03:37 +01:00
simulation_type = = BlockSimulationType : : solveTwoBoundariesComplete | | simulation_type = = BlockSimulationType : : solveTwoBoundariesSimple ) ;
2009-12-16 18:13:23 +01:00
file_open = true ;
}
2017-06-01 19:58:32 +02:00
2009-12-16 18:13:23 +01:00
FBEGINBLOCK_ fbeginblock ( block_mfs ,
simulation_type ,
2020-04-23 16:04:02 +02:00
blocks [ block ] . first_equation ,
2009-12-16 18:13:23 +01:00
block_size ,
2020-04-17 14:55:55 +02:00
endo_idx_block2orig ,
eq_idx_block2orig ,
2020-04-21 18:10:46 +02:00
blocks [ block ] . linear ,
2009-12-16 18:13:23 +01:00
symbol_table . endo_nbr ( ) ,
block_max_lag ,
2014-12-17 09:37:43 +01:00
block_max_lead ,
2010-07-23 11:20:24 +02:00
u_count_int ,
2020-05-06 14:02:58 +02:00
blocks_jacob_cols_endo [ block ] . size ( ) ,
blocks_exo_det [ block ] . size ( ) ,
blocks_jacob_cols_exo_det [ block ] . size ( ) ,
blocks_exo [ block ] . size ( ) ,
blocks_jacob_cols_exo [ block ] . size ( ) ,
blocks_other_endo [ block ] . size ( ) ,
blocks_jacob_cols_other_endo [ block ] . size ( ) ,
vector < int > ( blocks_exo_det [ block ] . begin ( ) , blocks_exo_det [ block ] . end ( ) ) ,
vector < int > ( blocks_exo [ block ] . begin ( ) , blocks_exo [ block ] . end ( ) ) ,
vector < int > ( blocks_other_endo [ block ] . begin ( ) , blocks_other_endo [ block ] . end ( ) ) ) ;
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2017-06-01 19:58:32 +02:00
2020-05-13 12:53:47 +02:00
temporary_terms_t temporary_terms_union ;
2009-04-14 16:39:53 +02:00
2020-05-06 17:13:47 +02:00
//The Temporary terms
deriv_node_temp_terms_t tef_terms ;
2020-05-13 16:58:19 +02:00
auto write_eq_tt = [ & ] ( int eq )
{
for ( auto it : blocks_temporary_terms [ block ] [ eq ] )
{
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) )
it - > compileExternalFunctionOutput ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false , tef_terms ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : TemporaryTerm , static_cast < int > ( blocks_temporary_terms_idxs . at ( it ) ) ) ;
2020-05-13 16:58:19 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
it - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false , tef_terms ) ;
FSTPT_ fstpt ( static_cast < int > ( blocks_temporary_terms_idxs . at ( it ) ) ) ;
fstpt . write ( code_file , instruction_number ) ;
temporary_terms_union . insert ( it ) ;
2009-04-14 16:39:53 +02:00
# ifdef DEBUGC
2020-05-13 16:58:19 +02:00
cout < < " FSTPT " < < v < < endl ;
instruction_number + + ;
code_file . write ( & FOK , sizeof ( FOK ) ) ;
code_file . write ( reinterpret_cast < char * > ( & k ) , sizeof ( k ) ) ;
ki + + ;
2009-12-16 14:21:31 +01:00
# endif
2020-05-13 16:58:19 +02:00
}
} ;
2009-12-16 14:21:31 +01:00
2020-05-06 17:13:47 +02:00
// The equations
for ( i = 0 ; i < block_size ; i + + )
{
2021-01-25 18:03:37 +01:00
write_eq_tt ( i ) ;
2020-05-13 16:58:19 +02:00
2009-12-16 18:13:23 +01:00
int variable_ID , equation_ID ;
EquationType equ_type ;
2009-12-16 14:21:31 +01:00
2009-12-16 18:13:23 +01:00
switch ( simulation_type )
{
evaluation :
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : evaluateBackward :
case BlockSimulationType : : evaluateForward :
2009-12-16 18:13:23 +01:00
equ_type = getBlockEquationType ( block , i ) ;
2010-01-22 17:42:08 +01:00
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2010-01-22 17:42:08 +01:00
}
2020-03-20 18:00:56 +01:00
if ( equ_type = = EquationType : : evaluate )
2009-12-16 18:13:23 +01:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2009-12-16 18:13:23 +01:00
}
2020-05-20 11:49:32 +02:00
else if ( equ_type = = EquationType : : evaluateRenormalized )
2009-12-16 18:13:23 +01:00
{
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationRenormalizedExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
case BlockSimulationType : : solveTwoBoundariesComplete :
case BlockSimulationType : : solveTwoBoundariesSimple :
2020-03-24 18:26:06 +01:00
if ( i < block_recursive )
2009-12-16 18:13:23 +01:00
goto evaluation ;
variable_ID = getBlockVariableID ( block , i ) ;
equation_ID = getBlockEquationID ( block , i ) ;
feedback_variables . push_back ( variable_ID ) ;
2018-06-04 12:52:14 +02:00
Uf [ equation_ID ] . Ufl = nullptr ;
2009-12-16 18:13:23 +01:00
goto end ;
default :
end :
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-07 15:20:11 +02:00
eq_node = getBlockEquationExpr ( block , i ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2020-05-13 12:53:47 +02:00
lhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
rhs - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2009-12-16 18:13:23 +01:00
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FSTPR_ fstpr ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fstpr . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
FENDEQU_ fendequ ;
2010-07-23 11:20:24 +02:00
fendequ . write ( code_file , instruction_number ) ;
// Get the current code_file position and jump if eval = true
streampos pos1 = code_file . tellp ( ) ;
FJMPIFEVAL_ fjmp_if_eval ( 0 ) ;
fjmp_if_eval . write ( code_file , instruction_number ) ;
int prev_instruction_number = instruction_number ;
2010-10-27 15:34:48 +02:00
// The Jacobian if we have to solve the block determinsitic block
2020-03-20 17:31:14 +01:00
if ( simulation_type ! = BlockSimulationType : : evaluateBackward
& & simulation_type ! = BlockSimulationType : : evaluateForward )
2009-12-16 18:13:23 +01:00
{
2020-05-13 16:58:19 +02:00
// Write temporary terms for derivatives
2021-01-25 18:03:37 +01:00
write_eq_tt ( blocks [ block ] . size ) ;
2020-05-13 16:58:19 +02:00
2009-12-16 18:13:23 +01:00
switch ( simulation_type )
{
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardSimple :
case BlockSimulationType : : solveForwardSimple :
2010-01-22 17:42:08 +01:00
{
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , 0 ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2010-01-22 17:42:08 +01:00
}
2020-05-13 12:53:47 +02:00
compileDerivative ( code_file , instruction_number , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , 0 , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2009-06-05 16:45:23 +02:00
{
2009-12-16 18:13:23 +01:00
FSTPG_ fstpg ( 0 ) ;
2010-07-23 11:20:24 +02:00
fstpg . write ( code_file , instruction_number ) ;
2009-06-05 16:45:23 +02:00
}
2009-12-16 18:13:23 +01:00
break ;
2020-03-20 17:31:14 +01:00
case BlockSimulationType : : solveBackwardComplete :
case BlockSimulationType : : solveForwardComplete :
case BlockSimulationType : : solveTwoBoundariesComplete :
case BlockSimulationType : : solveTwoBoundariesSimple :
2009-12-16 18:13:23 +01:00
count_u = feedback_variables . size ( ) ;
2020-04-24 12:29:02 +02:00
for ( const auto & [ indices , ignore ] : blocks_derivatives [ block ] )
2009-12-16 18:13:23 +01:00
{
2020-04-24 12:29:02 +02:00
auto [ eq , var , lag ] = indices ;
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( block , eq ) ;
int varr = getBlockVariableID ( block , var ) ;
2010-07-23 11:20:24 +02:00
if ( eq > = block_recursive and var > = block_recursive )
2009-12-16 18:13:23 +01:00
{
2020-03-20 17:31:14 +01:00
if ( lag ! = 0
& & ( simulation_type = = BlockSimulationType : : solveForwardComplete
| | simulation_type = = BlockSimulationType : : solveBackwardComplete ) )
2010-08-18 13:45:07 +02:00
continue ;
2009-12-16 18:13:23 +01:00
if ( ! Uf [ eqr ] . Ufl )
{
2019-04-23 11:07:32 +02:00
Uf [ eqr ] . Ufl = static_cast < Uff_l * > ( malloc ( sizeof ( Uff_l ) ) ) ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl_First = Uf [ eqr ] . Ufl ;
}
else
{
2019-04-23 11:07:32 +02:00
Uf [ eqr ] . Ufl - > pNext = static_cast < Uff_l * > ( malloc ( sizeof ( Uff_l ) ) ) ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl = Uf [ eqr ] . Ufl - > pNext ;
}
2018-06-04 12:52:14 +02:00
Uf [ eqr ] . Ufl - > pNext = nullptr ;
2009-12-16 18:13:23 +01:00
Uf [ eqr ] . Ufl - > u = count_u ;
Uf [ eqr ] . Ufl - > var = varr ;
Uf [ eqr ] . Ufl - > lag = lag ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
compileChainRuleDerivative ( code_file , instruction_number , block , eq , var , lag , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2009-12-16 18:13:23 +01:00
FSTPU_ fstpu ( count_u ) ;
2010-07-23 11:20:24 +02:00
fstpu . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
count_u + + ;
}
}
2020-03-24 18:26:06 +01:00
for ( i = 0 ; i < block_size ; i + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
if ( i > = block_recursive )
2009-12-16 18:13:23 +01:00
{
FLDR_ fldr ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fldr . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FLDZ_ fldz ;
2010-07-23 11:20:24 +02:00
fldz . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
v = getBlockEquationID ( block , i ) ;
for ( Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ; Uf [ v ] . Ufl ; Uf [ v ] . Ufl = Uf [ v ] . Ufl - > pNext )
{
FLDU_ fldu ( Uf [ v ] . Ufl - > u ) ;
2010-07-23 11:20:24 +02:00
fldu . write ( code_file , instruction_number ) ;
2018-07-17 18:34:07 +02:00
FLDV_ fldv { static_cast < int > ( SymbolType : : endogenous ) , static_cast < unsigned int > ( Uf [ v ] . Ufl - > var ) , Uf [ v ] . Ufl - > lag } ;
2010-07-23 11:20:24 +02:00
fldv . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : times ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FCUML_ fcuml ;
2010-07-23 11:20:24 +02:00
fcuml . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ;
while ( Uf [ v ] . Ufl )
{
Uf [ v ] . Ufl_First = Uf [ v ] . Ufl - > pNext ;
free ( Uf [ v ] . Ufl ) ;
Uf [ v ] . Ufl = Uf [ v ] . Ufl_First ;
}
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( BinaryOpcode : : minus ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FSTPU_ fstpu ( i - block_recursive ) ;
2010-07-23 11:20:24 +02:00
fstpu . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
break ;
default :
break ;
}
}
2010-07-23 11:20:24 +02:00
// Get the current code_file position and jump = true
streampos pos2 = code_file . tellp ( ) ;
FJMP_ fjmp ( 0 ) ;
fjmp . write ( code_file , instruction_number ) ;
// Set code_file position to previous JMPIFEVAL_ and set the number of instructions to jump
streampos pos3 = code_file . tellp ( ) ;
code_file . seekp ( pos1 ) ;
FJMPIFEVAL_ fjmp_if_eval1 ( instruction_number - prev_instruction_number ) ;
fjmp_if_eval1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos3 ) ;
2011-02-04 16:25:38 +01:00
prev_instruction_number = instruction_number ;
2010-10-27 15:34:48 +02:00
// The Jacobian if we have to solve the block determinsitic block
2010-07-23 11:20:24 +02:00
2020-05-06 14:02:58 +02:00
for ( const auto & [ indices , d ] : blocks_derivatives [ block ] )
2010-07-23 11:20:24 +02:00
{
2020-05-06 14:02:58 +02:00
auto [ eq , var , lag ] = indices ;
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( block , eq ) ;
int varr = getBlockVariableID ( block , var ) ;
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstEndoDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
compileDerivative ( code_file , instruction_number , eqr , varr , lag , temporary_terms_union , blocks_temporary_terms_idxs ) ;
2020-05-06 14:02:58 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , blocks_jacob_cols_endo [ block ] . at ( { var , lag } ) ) ;
2010-07-23 11:20:24 +02:00
fstpg3 . write ( code_file , instruction_number ) ;
}
2020-05-06 14:02:58 +02:00
for ( const auto & [ indices , d ] : blocks_derivatives_exo [ block ] )
2010-07-23 11:20:24 +02:00
{
2020-05-06 14:02:58 +02:00
auto [ eqr , var , lag ] = indices ;
2020-04-30 16:00:16 +02:00
int eq = getBlockEquationID ( block , eqr ) ;
2020-05-05 17:15:08 +02:00
int varr = 0 ; // Dummy value, actually unused by the bytecode MEX
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstExoDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
d - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2020-05-06 14:02:58 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , blocks_jacob_cols_exo [ block ] . at ( { var , lag } ) ) ;
2010-07-23 11:20:24 +02:00
fstpg3 . write ( code_file , instruction_number ) ;
}
2020-05-06 14:02:58 +02:00
for ( const auto & [ indices , d ] : blocks_derivatives_exo_det [ block ] )
2010-07-23 11:20:24 +02:00
{
2020-05-06 14:02:58 +02:00
auto [ eqr , var , lag ] = indices ;
2020-04-30 16:00:16 +02:00
int eq = getBlockEquationID ( block , eqr ) ;
2020-05-05 17:15:08 +02:00
int varr = 0 ; // Dummy value, actually unused by the bytecode MEX
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstExodetDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
d - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2020-05-06 14:02:58 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , blocks_jacob_cols_exo_det [ block ] . at ( { var , lag } ) ) ;
2010-07-23 11:20:24 +02:00
fstpg3 . write ( code_file , instruction_number ) ;
}
2020-05-06 14:02:58 +02:00
for ( const auto & [ indices , d ] : blocks_derivatives_other_endo [ block ] )
2010-07-23 11:20:24 +02:00
{
2020-05-06 14:02:58 +02:00
auto [ eqr , var , lag ] = indices ;
2020-04-30 16:00:16 +02:00
int eq = getBlockEquationID ( block , eqr ) ;
2020-05-05 17:15:08 +02:00
int varr = 0 ; // Dummy value, actually unused by the bytecode MEX
2021-02-01 11:10:59 +01:00
FNUMEXPR_ fnumexpr ( ExpressionType : : FirstOtherEndoDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2020-05-13 12:53:47 +02:00
d - > compile ( code_file , instruction_number , false , temporary_terms_union , blocks_temporary_terms_idxs , true , false ) ;
2020-05-06 14:02:58 +02:00
FSTPG3_ fstpg3 ( eq , var , lag , blocks_jacob_cols_other_endo [ block ] . at ( { var , lag } ) ) ;
2010-07-23 11:20:24 +02:00
fstpg3 . write ( code_file , instruction_number ) ;
}
// Set codefile position to previous JMP_ and set the number of instructions to jump
pos1 = code_file . tellp ( ) ;
code_file . seekp ( pos2 ) ;
FJMP_ fjmp1 ( instruction_number - prev_instruction_number ) ;
fjmp1 . write ( code_file , instruction_number ) ;
code_file . seekp ( pos1 ) ;
2009-12-16 18:13:23 +01:00
}
FENDBLOCK_ fendblock ;
2010-07-23 11:20:24 +02:00
fendblock . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
FEND_ fend ;
2010-07-23 11:20:24 +02:00
fend . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
code_file . close ( ) ;
}
2009-04-14 16:39:53 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicMFile ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
2018-06-27 15:01:31 +02:00
writeDynamicModel ( basename , false , false ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2015-07-27 17:02:51 +02:00
void
DynamicModel : : writeDynamicJuliaFile ( const string & basename ) const
{
2018-03-27 17:14:30 +02:00
writeDynamicModel ( basename , false , true ) ;
2015-07-27 17:02:51 +02:00
}
2009-04-14 16:39:53 +02:00
void
2020-01-20 17:22:32 +01:00
DynamicModel : : writeDynamicCFile ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
2018-06-27 15:01:31 +02:00
string filename = basename + " /model/src/dynamic.c " ;
2009-12-16 18:13:23 +01:00
2018-11-15 16:39:53 +01:00
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) ;
2018-09-25 19:15:22 +02:00
2020-05-29 16:12:01 +02:00
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
2009-12-16 18:13:23 +01:00
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2020-05-29 16:12:01 +02:00
output < < " /* " < < endl
< < " * " < < filename < < " : Computes dynamic model for Dynare " < < endl
< < " * " < < endl
< < " * Warning : this file is generated automatically by Dynare " < < endl
< < " * from model file (.mod) " < < endl
< < " */ " < < endl
< < endl
< < " #include <math.h> " < < endl
< < " #include <stdlib.h> " < < endl
< < R " (#include " mex . h " ) " < < endl
< < endl ;
2009-12-16 18:13:23 +01:00
2018-07-18 16:18:26 +02:00
// Write function definition if BinaryOpcode::powerDeriv is used
2020-05-29 16:12:01 +02:00
writePowerDeriv ( output ) ;
2018-09-25 19:15:22 +02:00
2020-05-29 16:12:01 +02:00
output < < endl ;
2009-12-16 18:13:23 +01:00
2020-05-29 16:12:01 +02:00
writeDynamicModel ( output , true , false ) ;
2018-09-25 19:15:22 +02:00
2020-05-29 16:12:01 +02:00
output < < " void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) " < < endl
< < " { " < < endl
2020-06-23 16:30:21 +02:00
< < " if (nlhs > " < < min ( computed_derivs_order + 1 , 4 ) < < " ) " < < endl
2020-05-29 16:12:01 +02:00
< < R " ( mexErrMsgTxt( " Derivatives of higher order than computed have been requested " );) " < < endl
2020-06-23 16:30:21 +02:00
< < " if (nrhs != 5) " < < endl
< < R " ( mexErrMsgTxt( " Requires exactly 5 input arguments " );) " < < endl
2020-05-29 16:12:01 +02:00
< < endl
< < " double *y = mxGetPr(prhs[0]); " < < endl
< < " double *x = mxGetPr(prhs[1]); " < < endl
< < " double *params = mxGetPr(prhs[2]); " < < endl
< < " double *steady_state = mxGetPr(prhs[3]); " < < endl
< < " int it_ = (int) mxGetScalar(prhs[4]) - 1; " < < endl
< < " int nb_row_x = mxGetM(prhs[1]); " < < endl
< < endl
< < " double *T = (double *) malloc(sizeof(double)* " < < ntt < < " ); " < < endl
< < endl
< < " if (nlhs >= 1) " < < endl
< < " { " < < endl
< < " plhs[0] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " ,1, mxREAL); " < < endl
< < " double *residual = mxGetPr(plhs[0]); " < < endl
< < " dynamic_resid_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
< < " dynamic_resid(y, x, nb_row_x, params, steady_state, it_, T, residual); " < < endl
< < " } " < < endl
< < endl
< < " if (nlhs >= 2) " < < endl
< < " { " < < endl
< < " plhs[1] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " , " < < dynJacobianColsNbr < < " , mxREAL); " < < endl
< < " double *g1 = mxGetPr(plhs[1]); " < < endl
< < " dynamic_g1_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
< < " dynamic_g1(y, x, nb_row_x, params, steady_state, it_, T, g1); " < < endl
< < " } " < < endl
< < endl
< < " if (nlhs >= 3) " < < endl
< < " { " < < endl
2020-06-23 17:50:50 +02:00
< < " mxArray *g2_i = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g2_j = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g2_v = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 1 < < " , mxREAL); " < < endl
2020-05-29 16:12:01 +02:00
< < " dynamic_g2_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
2020-06-23 17:50:50 +02:00
< < " dynamic_g2(y, x, nb_row_x, params, steady_state, it_, T, mxGetPr(g2_i), mxGetPr(g2_j), mxGetPr(g2_v)); " < < endl
< < " mxArray *m = mxCreateDoubleScalar( " < < equations . size ( ) < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < dynJacobianColsNbr * dynJacobianColsNbr < < " ); " < < endl
< < " mxArray *plhs_sparse[1], *prhs_sparse[5] = { g2_i, g2_j, g2_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs_sparse, 5, prhs_sparse, " sparse " );) " < < endl
< < " plhs[2] = plhs_sparse[0]; " < < endl
< < " mxDestroyArray(g2_i); " < < endl
< < " mxDestroyArray(g2_j); " < < endl
< < " mxDestroyArray(g2_v); " < < endl
< < " mxDestroyArray(m); " < < endl
< < " mxDestroyArray(n); " < < endl
2020-05-29 16:12:01 +02:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 4) " < < endl
< < " { " < < endl
2020-06-23 17:50:50 +02:00
< < " mxArray *g3_i = mxCreateDoubleMatrix( " < < NNZDerivatives [ 3 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g3_j = mxCreateDoubleMatrix( " < < NNZDerivatives [ 3 ] < < " , " < < 1 < < " , mxREAL); " < < endl
< < " mxArray *g3_v = mxCreateDoubleMatrix( " < < NNZDerivatives [ 3 ] < < " , " < < 1 < < " , mxREAL); " < < endl
2020-05-29 16:12:01 +02:00
< < " dynamic_g3_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
2020-06-23 17:50:50 +02:00
< < " dynamic_g3(y, x, nb_row_x, params, steady_state, it_, T, mxGetPr(g3_i), mxGetPr(g3_j), mxGetPr(g3_v)); " < < endl
< < " mxArray *m = mxCreateDoubleScalar( " < < equations . size ( ) < < " ); " < < endl
< < " mxArray *n = mxCreateDoubleScalar( " < < dynJacobianColsNbr * dynJacobianColsNbr * dynJacobianColsNbr < < " ); " < < endl
< < " mxArray *plhs_sparse[1], *prhs_sparse[5] = { g3_i, g3_j, g3_v, m, n }; " < < endl
< < R " ( mexCallMATLAB(1, plhs_sparse, 5, prhs_sparse, " sparse " );) " < < endl
< < " plhs[3] = plhs_sparse[0]; " < < endl
< < " mxDestroyArray(g3_i); " < < endl
< < " mxDestroyArray(g3_j); " < < endl
< < " mxDestroyArray(g3_v); " < < endl
< < " mxDestroyArray(m); " < < endl
< < " mxDestroyArray(n); " < < endl
2020-05-29 16:12:01 +02:00
< < " } " < < endl
< < endl
2020-06-23 16:30:21 +02:00
< < " free(T); " < < endl
2020-05-29 16:12:01 +02:00
< < " } " < < endl ;
2011-12-22 14:55:57 +01:00
2020-05-29 16:12:01 +02:00
output . close ( ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
string
2019-12-16 19:42:59 +01:00
DynamicModel : : reform ( const string & name1 ) const
2009-12-16 18:13:23 +01:00
{
string name = name1 ;
2019-04-03 16:32:52 +02:00
int pos = name . find ( R " ( \ ) " , 0 ) ;
2009-12-16 18:13:23 +01:00
while ( pos > = 0 )
{
2019-04-03 16:32:52 +02:00
if ( name . substr ( pos + 1 , 1 ) ! = R " ( \ ) " )
2009-12-16 18:13:23 +01:00
{
2019-04-03 16:32:52 +02:00
name = name . insert ( pos , R " ( \ ) " ) ;
2009-12-16 18:13:23 +01:00
pos + + ;
}
pos + + ;
2019-04-03 16:32:52 +02:00
pos = name . find ( R " ( \ ) " , pos ) ;
2009-12-16 18:13:23 +01:00
}
2019-12-16 19:42:59 +01:00
return name ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2016-07-27 21:01:54 +02:00
void
2018-01-11 12:55:36 +01:00
DynamicModel : : printNonZeroHessianEquations ( ostream & output ) const
{
2019-12-16 19:42:59 +01:00
if ( nonzero_hessian_eqs . size ( ) ! = 1 )
2018-01-11 12:55:36 +01:00
output < < " [ " ;
2018-06-04 15:03:26 +02:00
for ( auto it = nonzero_hessian_eqs . begin ( ) ;
2019-12-16 19:42:59 +01:00
it ! = nonzero_hessian_eqs . end ( ) ; + + it )
2018-01-11 12:55:36 +01:00
{
if ( it ! = nonzero_hessian_eqs . begin ( ) )
output < < " " ;
2019-12-13 22:31:49 +01:00
output < < * it + 1 ;
2018-01-11 12:55:36 +01:00
}
if ( nonzero_hessian_eqs . size ( ) ! = 1 )
output < < " ] " ;
}
2009-04-14 16:39:53 +02:00
void
2020-05-19 17:43:35 +02:00
DynamicModel : : writeBlockBytecodeBinFile ( const string & basename , int num , int & u_count_int ,
2021-01-25 18:03:37 +01:00
bool & file_open , bool is_two_boundaries ) const
2009-12-16 18:13:23 +01:00
{
int j ;
std : : ofstream SaveCode ;
2021-01-25 18:03:37 +01:00
string filename = basename + " /model/bytecode/dynamic.bin " ;
2018-09-21 17:13:19 +02:00
2009-12-16 18:13:23 +01:00
if ( file_open )
2018-06-27 15:01:31 +02:00
SaveCode . open ( filename , ios : : out | ios : : in | ios : : binary | ios : : ate ) ;
2009-12-16 18:13:23 +01:00
else
2018-06-27 15:01:31 +02:00
SaveCode . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 18:13:23 +01:00
if ( ! SaveCode . is_open ( ) )
{
2019-04-03 16:32:52 +02:00
cerr < < R " (Error : Can't open file " ) " << filename << R " ( " for writing) " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
u_count_int = 0 ;
2020-04-23 16:04:02 +02:00
int block_size = blocks [ num ] . size ;
int block_mfs = blocks [ num ] . mfs_size ;
int block_recursive = blocks [ num ] . getRecursiveSize ( ) ;
2020-04-24 12:29:02 +02:00
for ( const auto & [ indices , ignore ] : blocks_derivatives [ num ] )
2009-12-16 18:13:23 +01:00
{
2020-04-24 12:29:02 +02:00
auto [ eq , var , lag ] = indices ;
2010-08-18 13:45:07 +02:00
if ( lag ! = 0 & & ! is_two_boundaries )
continue ;
2010-04-28 16:03:32 +02:00
if ( eq > = block_recursive & & var > = block_recursive )
2009-12-16 18:13:23 +01:00
{
int v = eq - block_recursive ;
SaveCode . write ( reinterpret_cast < char * > ( & v ) , sizeof ( v ) ) ;
int varr = var - block_recursive + lag * block_mfs ;
SaveCode . write ( reinterpret_cast < char * > ( & varr ) , sizeof ( varr ) ) ;
2020-03-24 18:26:06 +01:00
SaveCode . write ( reinterpret_cast < const char * > ( & lag ) , sizeof ( lag ) ) ;
2009-12-16 18:13:23 +01:00
int u = u_count_int + block_mfs ;
SaveCode . write ( reinterpret_cast < char * > ( & u ) , sizeof ( u ) ) ;
u_count_int + + ;
}
}
if ( is_two_boundaries )
u_count_int + = block_mfs ;
2020-03-24 18:26:06 +01:00
for ( j = block_recursive ; j < block_size ; j + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
int varr = getBlockVariableID ( num , j ) ;
2009-12-16 18:13:23 +01:00
SaveCode . write ( reinterpret_cast < char * > ( & varr ) , sizeof ( varr ) ) ;
}
2020-03-24 18:26:06 +01:00
for ( j = block_recursive ; j < block_size ; j + + )
2009-12-16 18:13:23 +01:00
{
2020-03-24 18:26:06 +01:00
int eqr = getBlockEquationID ( num , j ) ;
2009-12-16 18:13:23 +01:00
SaveCode . write ( reinterpret_cast < char * > ( & eqr ) , sizeof ( eqr ) ) ;
}
SaveCode . close ( ) ;
}
2009-04-14 16:39:53 +02:00
void
2020-05-19 16:56:53 +02:00
DynamicModel : : writeDynamicBlockMFile ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
2020-06-19 18:33:53 +02:00
ofstream output ;
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " /dynamic.m " ;
2020-06-19 18:33:53 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
2009-12-16 18:13:23 +01:00
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2020-06-19 18:33:53 +02:00
output < < " function [residual, y, T, g1, varargout] = dynamic(nblock, y, x, params, steady_state, T, it_, stochastic_mode) " < < endl
< < " switch nblock " < < endl ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
output < < " case " < < blk + 1 < < endl ;
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
output < < " [y, T, g1, varargout{1:nargout-4}] = " < < basename < < " .block.dynamic_ " < < blk + 1 < < " (y, x, params, steady_state, T, it_, stochastic_mode); " < < endl
< < " residual = []; " < < endl ;
else
2020-10-06 17:16:50 +02:00
output < < " [residual, y, T, g1, varargout{1:nargout-4}] = " < < basename < < " .block.dynamic_ " < < blk + 1 < < " (y, x, params, steady_state, T, it_, stochastic_mode); " < < endl ;
2020-06-19 18:33:53 +02:00
}
output < < " end " < < endl
< < " end " < < endl ;
output . close ( ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2020-06-23 15:13:04 +02:00
void
DynamicModel : : writeDynamicBlockCFile ( const string & basename ) const
{
string filename = basename + " /model/src/dynamic.c " ;
ofstream output ;
output . open ( filename , ios : : out | ios : : binary ) ;
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " #include <math.h> " < < endl
< < R " (#include " mex . h " ) " < < endl ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
output < < R " (#include " dynamic_ ) " << blk+1 << R " ( . h " ) " < < endl ;
output < < endl ;
writePowerDeriv ( output ) ;
output < < endl
< < " void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) " < < endl
< < " { " < < endl
< < " if (nrhs != 8) " < < endl
< < R " ( mexErrMsgTxt( " Requires exactly 8 input arguments " );) " < < endl
< < " if (nlhs > 7) " < < endl
< < R " ( mexErrMsgTxt( " Accepts at most 7 output arguments " );) " < < endl
< < " int nblock = (int) mxGetScalar(prhs[0]); " < < endl
< < " const mxArray *y = prhs[1], *x = prhs[2], *params = prhs[3], *steady_state = prhs[4], *T = prhs[5], *it_ = prhs[6], *stochastic_mode = prhs[7]; " < < endl
< < " mxArray *T_new = mxDuplicateArray(T); " < < endl
< < " mxArray *y_new = mxDuplicateArray(y); " < < endl
< < " mxArray *residual, *g1, *g1_x, *g1_xd, *g1_o; " < < endl
< < " switch (nblock) " < < endl
< < " { " < < endl ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
output < < " case " < < blk + 1 < < ' : ' < < endl ;
BlockSimulationType simulation_type = blocks [ blk ] . simulation_type ;
if ( simulation_type = = BlockSimulationType : : evaluateBackward
| | simulation_type = = BlockSimulationType : : evaluateForward )
output < < " dynamic_ " < < blk + 1 < < " _mx(y_new, x, params, steady_state, T_new, it_, stochastic_mode, &g1, &g1_x, &g1_xd, &g1_o); " < < endl
< < " residual = mxCreateDoubleMatrix(0,0,mxREAL); " < < endl ;
else
2020-10-06 17:16:50 +02:00
output < < " dynamic_ " < < blk + 1 < < " _mx(y_new, x, params, steady_state, T_new, it_, stochastic_mode, &residual, &g1, &g1_x, &g1_xd, &g1_o); " < < endl ;
2020-06-23 15:13:04 +02:00
output < < " break; " < < endl ;
}
output < < " } " < < endl
< < endl
< < " if (nlhs >= 1) " < < endl
< < " plhs[0] = residual; " < < endl
< < " else " < < endl
< < " mxDestroyArray(residual); " < < endl
< < " if (nlhs >= 2) " < < endl
< < " plhs[1] = y_new; " < < endl
< < " else " < < endl
< < " mxDestroyArray(y_new); " < < endl
< < " if (nlhs >= 3) " < < endl
< < " plhs[2] = T_new; " < < endl
< < " else " < < endl
< < " mxDestroyArray(T_new); " < < endl
< < " if (nlhs >= 4) " < < endl
< < " plhs[3] = g1; " < < endl
< < " else " < < endl
< < " mxDestroyArray(g1); " < < endl
< < " if (nlhs >= 5) " < < endl
< < " plhs[4] = g1_x; " < < endl
< < " else " < < endl
< < " mxDestroyArray(g1_x); " < < endl
< < " if (nlhs >= 6) " < < endl
< < " plhs[5] = g1_xd; " < < endl
< < " else " < < endl
< < " mxDestroyArray(g1_xd); " < < endl
< < " if (nlhs >= 7) " < < endl
< < " plhs[6] = g1_o; " < < endl
< < " else " < < endl
< < " mxDestroyArray(g1_o); " < < endl
< < " } " < < endl ;
output . close ( ) ;
}
2018-03-27 17:14:30 +02:00
void
DynamicModel : : writeWrapperFunctions ( const string & basename , const string & ending ) const
{
string name ;
if ( ending = = " g1 " )
2018-06-27 15:01:31 +02:00
name = " dynamic_resid_g1 " ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2019-12-20 16:59:30 +01:00
name = " dynamic_resid_g1_g2 " ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-06-27 15:01:31 +02:00
name = " dynamic_resid_g1_g2_g3 " ;
2018-03-27 17:14:30 +02:00
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " / " + name + " .m " ;
2018-03-27 17:14:30 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-27 17:14:30 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( ending = = " g1 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl
< < " % function [residual, g1] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1, g2] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl
< < " % function [residual, g1, g2] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-05-23 17:32:50 +02:00
output < < " function [residual, g1, g2, g3] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl
< < " % function [residual, g1, g2, g3] = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl ;
2018-03-27 17:14:30 +02:00
output < < " % " < < endl
< < " % Wrapper function automatically created by Dynare " < < endl
2018-05-23 17:32:50 +02:00
< < " % " < < endl
< < endl
< < " if T_flag " < < endl
2018-06-27 15:01:31 +02:00
< < " T = " < < basename < < " .dynamic_ " < < ending < < " _tt(T, y, x, params, steady_state, it_); " < < endl
2018-05-23 17:32:50 +02:00
< < " end " < < endl ;
2018-03-27 17:14:30 +02:00
if ( ending = = " g1 " )
2018-06-27 15:01:31 +02:00
output < < " residual = " < < basename < < " .dynamic_resid(T, y, x, params, steady_state, it_, false); " < < endl
< < " g1 = " < < basename < < " .dynamic_g1(T, y, x, params, steady_state, it_, false); " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g2 " )
2018-06-27 15:01:31 +02:00
output < < " [residual, g1] = " < < basename < < " .dynamic_resid_g1(T, y, x, params, steady_state, it_, false); " < < endl
< < " g2 = " < < basename < < " .dynamic_g2(T, y, x, params, steady_state, it_, false); " < < endl ;
2018-03-27 17:14:30 +02:00
else if ( ending = = " g3 " )
2018-06-27 15:01:31 +02:00
output < < " [residual, g1, g2] = " < < basename < < " .dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, false); " < < endl
< < " g3 = " < < basename < < " .dynamic_g3(T, y, x, params, steady_state, it_, false); " < < endl ;
2018-03-27 17:14:30 +02:00
output < < endl < < " end " < < endl ;
output . close ( ) ;
}
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicModelHelper ( const string & basename ,
const string & name , const string & retvalname ,
2018-03-27 17:14:30 +02:00
const string & name_tt , size_t ttlen ,
const string & previous_tt_name ,
const ostringstream & init_s ,
const ostringstream & end_s ,
const ostringstream & s , const ostringstream & s_tt ) const
{
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " / " + name_tt + " .m " ;
2018-03-27 17:14:30 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-27 17:14:30 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " function T = " < < name_tt < < " (T, y, x, params, steady_state, it_) " < < endl
< < " % function T = " < < name_tt < < " (T, y, x, params, steady_state, it_) " < < endl
< < " % " < < endl
< < " % File created by Dynare Preprocessor from .mod file " < < endl
< < " % " < < endl
< < " % Inputs: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms to be filled by function " < < endl
< < " % y [#dynamic variables by 1] double vector of endogenous variables in the order stored " < < endl
< < " % in M_.lead_lag_incidence; see the Manual " < < endl
< < " % x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order) " < < endl
< < " % for all simulation periods " < < endl
< < " % steady_state [M_.endo_nbr by 1] double vector of steady state values " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % it_ scalar double time period for exogenous variables for which " < < endl
< < " % to evaluate the model " < < endl
< < " % " < < endl
< < " % Output: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms " < < endl
< < " % " < < endl < < endl
< < " assert(length(T) >= " < < ttlen < < " ); " < < endl
< < endl ;
if ( ! previous_tt_name . empty ( ) )
2018-06-27 15:01:31 +02:00
output < < " T = " < < basename < < " . " < < previous_tt_name < < " (T, y, x, params, steady_state, it_); " < < endl < < endl ;
2018-03-27 17:14:30 +02:00
output < < s_tt . str ( ) < < endl
< < " end " < < endl ;
output . close ( ) ;
2018-06-27 15:01:31 +02:00
filename = packageDir ( basename ) + " / " + name + " .m " ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-27 17:14:30 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " function " < < retvalname < < " = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl
< < " % function " < < retvalname < < " = " < < name < < " (T, y, x, params, steady_state, it_, T_flag) " < < endl
< < " % " < < endl
< < " % File created by Dynare Preprocessor from .mod file " < < endl
< < " % " < < endl
< < " % Inputs: " < < endl
< < " % T [#temp variables by 1] double vector of temporary terms to be filled by function " < < endl
< < " % y [#dynamic variables by 1] double vector of endogenous variables in the order stored " < < endl
< < " % in M_.lead_lag_incidence; see the Manual " < < endl
< < " % x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order) " < < endl
< < " % for all simulation periods " < < endl
< < " % steady_state [M_.endo_nbr by 1] double vector of steady state values " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % it_ scalar double time period for exogenous variables for which " < < endl
< < " % to evaluate the model " < < endl
< < " % T_flag boolean boolean flag saying whether or not to calculate temporary terms " < < endl
< < " % " < < endl
< < " % Output: " < < endl
< < " % " < < retvalname < < endl
< < " % " < < endl < < endl ;
if ( ! name_tt . empty ( ) )
output < < " if T_flag " < < endl
2018-06-27 15:01:31 +02:00
< < " T = " < < basename < < " . " < < name_tt < < " (T, y, x, params, steady_state, it_); " < < endl
2018-03-27 17:14:30 +02:00
< < " end " < < endl ;
output < < init_s . str ( ) < < endl
< < s . str ( )
< < end_s . str ( ) < < endl
< < " end " < < endl ;
output . close ( ) ;
}
2018-05-23 16:10:26 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicMatlabCompatLayer ( const string & basename ) const
2018-05-23 16:10:26 +02:00
{
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " /dynamic.m " ;
2018-05-23 16:10:26 +02:00
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-05-23 16:10:26 +02:00
if ( ! output . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-11-15 16:39:53 +01:00
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) ;
2018-05-23 16:10:26 +02:00
2018-06-27 15:01:31 +02:00
output < < " function [residual, g1, g2, g3] = dynamic(y, x, params, steady_state, it_) " < < endl
2018-05-23 16:10:26 +02:00
< < " T = NaN( " < < ntt < < " , 1); " < < endl
< < " if nargout <= 1 " < < endl
2018-06-27 15:01:31 +02:00
< < " residual = " < < basename < < " .dynamic_resid(T, y, x, params, steady_state, it_, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " elseif nargout == 2 " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1] = " < < basename < < " .dynamic_resid_g1(T, y, x, params, steady_state, it_, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " elseif nargout == 3 " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1, g2] = " < < basename < < " .dynamic_resid_g1_g2(T, y, x, params, steady_state, it_, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " else " < < endl
2018-06-27 15:01:31 +02:00
< < " [residual, g1, g2, g3] = " < < basename < < " .dynamic_resid_g1_g2_g3(T, y, x, params, steady_state, it_, true); " < < endl
2018-05-23 16:10:26 +02:00
< < " end " < < endl
< < " end " < < endl ;
output . close ( ) ;
}
2009-04-14 16:39:53 +02:00
void
2015-07-27 17:02:51 +02:00
DynamicModel : : writeDynamicModel ( ostream & DynamicOutput , bool use_dll , bool julia ) const
2009-12-16 18:13:23 +01:00
{
2018-03-27 17:14:30 +02:00
writeDynamicModel ( " " , DynamicOutput , use_dll , julia ) ;
}
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicModel ( const string & basename , bool use_dll , bool julia ) const
2018-03-27 17:14:30 +02:00
{
ofstream DynamicOutput ;
2018-06-27 15:01:31 +02:00
writeDynamicModel ( basename , DynamicOutput , use_dll , julia ) ;
2018-03-27 17:14:30 +02:00
}
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicModel ( const string & basename , ostream & DynamicOutput , bool use_dll , bool julia ) const
2018-03-27 17:14:30 +02:00
{
2019-12-20 16:59:30 +01:00
vector < ostringstream > d_output ( derivatives . size ( ) ) ; // Derivatives output (at all orders, including 0=residual)
2019-04-12 15:41:52 +02:00
vector < ostringstream > tt_output ( derivatives . size ( ) ) ; // Temp terms output (at all orders)
2009-12-16 18:13:23 +01:00
2018-09-05 18:27:13 +02:00
ExprNodeOutputType output_type = ( use_dll ? ExprNodeOutputType : : CDynamicModel :
julia ? ExprNodeOutputType : : juliaDynamicModel : ExprNodeOutputType : : matlabDynamicModel ) ;
2009-12-16 18:13:23 +01:00
2011-04-12 16:41:29 +02:00
deriv_node_temp_terms_t tef_terms ;
2018-03-27 17:14:30 +02:00
temporary_terms_t temp_term_union ;
2013-10-22 18:31:59 +02:00
2018-11-16 18:13:34 +01:00
writeModelLocalVariableTemporaryTerms ( temp_term_union , temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 0 ] , output_type , tef_terms ) ;
2009-06-05 16:45:23 +02:00
2018-11-15 16:39:53 +01:00
writeTemporaryTerms ( temporary_terms_derivatives [ 0 ] ,
2018-05-24 19:29:53 +02:00
temp_term_union ,
2018-05-28 15:23:15 +02:00
temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 0 ] , output_type , tef_terms ) ;
2009-06-05 16:45:23 +02:00
2019-04-12 15:41:52 +02:00
writeModelEquations ( d_output [ 0 ] , output_type , temp_term_union ) ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
int nrows = equations . size ( ) ;
int hessianColsNbr = dynJacobianColsNbr * dynJacobianColsNbr ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
// Writing Jacobian
2018-11-15 16:39:53 +01:00
if ( ! derivatives [ 1 ] . empty ( ) )
2009-12-16 18:13:23 +01:00
{
2018-11-15 16:39:53 +01:00
writeTemporaryTerms ( temporary_terms_derivatives [ 1 ] ,
2018-05-24 19:29:53 +02:00
temp_term_union ,
2018-05-28 15:23:15 +02:00
temporary_terms_idxs ,
2019-04-12 15:41:52 +02:00
tt_output [ 1 ] , output_type , tef_terms ) ;
2009-12-16 18:13:23 +01:00
2019-12-20 16:59:30 +01:00
for ( const auto & first_derivative : derivatives [ 1 ] )
2018-03-27 17:14:30 +02:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , var ] = vectorToTuple < 2 > ( first_derivative . first ) ;
2018-06-04 12:26:16 +02:00
expr_t d1 = first_derivative . second ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
jacobianHelper ( d_output [ 1 ] , eq , getDynJacobianCol ( var ) , output_type ) ;
d_output [ 1 ] < < " = " ;
d1 - > writeOutput ( d_output [ 1 ] , output_type ,
2018-05-24 19:29:53 +02:00
temp_term_union , temporary_terms_idxs , tef_terms ) ;
2019-04-12 15:41:52 +02:00
d_output [ 1 ] < < " ; " < < endl ;
2018-03-27 17:14:30 +02:00
}
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2019-04-12 15:41:52 +02:00
// Write derivatives for order ≥ 2
for ( size_t i = 2 ; i < derivatives . size ( ) ; i + + )
if ( ! derivatives [ i ] . empty ( ) )
{
writeTemporaryTerms ( temporary_terms_derivatives [ i ] ,
temp_term_union ,
temporary_terms_idxs ,
tt_output [ i ] , output_type , tef_terms ) ;
/* When creating the sparse matrix (in MATLAB or C mode), since storage
is in column - major order , output the first column , then the second ,
then the third . This gives a significant performance boost in use_dll
mode ( at both compilation and runtime ) , because it facilitates memory
accesses and expression reusage . */
2020-06-23 17:50:50 +02:00
ostringstream i_output , j_output , v_output ;
2019-04-12 15:41:52 +02:00
int k = 0 ; // Current line index in the 3-column matrix
2019-12-16 19:42:59 +01:00
for ( const auto & [ vidx , d ] : derivatives [ i ] )
2019-04-12 15:41:52 +02:00
{
int eq = vidx [ 0 ] ;
2015-08-20 12:18:19 +02:00
2019-04-12 15:41:52 +02:00
int col_idx = 0 ;
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
{
col_idx * = dynJacobianColsNbr ;
col_idx + = getDynJacobianCol ( vidx [ j ] ) ;
}
2015-08-20 12:18:19 +02:00
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : juliaDynamicModel )
2019-04-12 15:41:52 +02:00
{
d_output [ i ] < < " @inbounds " < < " g " < < i < < " [ " < < eq + 1 < < " , " < < col_idx + 1 < < " ] = " ;
d - > writeOutput ( d_output [ i ] , output_type , temp_term_union , temporary_terms_idxs , tef_terms ) ;
d_output [ i ] < < endl ;
}
2018-03-27 17:14:30 +02:00
else
{
2020-06-23 17:50:50 +02:00
i_output < < " g " < < i < < " _i " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < eq + 1 < < " ; " < < endl ;
j_output < < " g " < < i < < " _j " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < col_idx + 1 < < " ; " < < endl ;
v_output < < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d - > writeOutput ( v_output , output_type , temp_term_union , temporary_terms_idxs , tef_terms ) ;
v_output < < " ; " < < endl ;
2015-08-20 12:18:19 +02:00
2018-03-27 17:14:30 +02:00
k + + ;
}
2009-06-25 11:56:41 +02:00
2019-06-17 15:28:33 +02:00
// Output symetric elements at order 2
2019-04-12 15:41:52 +02:00
if ( i = = 2 & & vidx [ 1 ] ! = vidx [ 2 ] )
{
int col_idx_sym = getDynJacobianCol ( vidx [ 2 ] ) * dynJacobianColsNbr + getDynJacobianCol ( vidx [ 1 ] ) ;
if ( output_type = = ExprNodeOutputType : : juliaDynamicModel )
d_output [ 2 ] < < " @inbounds g2[ " < < eq + 1 < < " , " < < col_idx_sym + 1 < < " ] = "
< < " g2[ " < < eq + 1 < < " , " < < col_idx + 1 < < " ] " < < endl ;
else
{
2020-06-23 17:50:50 +02:00
i_output < < " g " < < i < < " _i " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < eq + 1 < < " ; " < < endl ;
j_output < < " g " < < i < < " _j " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " = " < < col_idx_sym + 1 < < " ; " < < endl ;
v_output < < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = "
< < " g " < < i < < " _v " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
< < k - 1 + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
2019-04-12 15:41:52 +02:00
k + + ;
}
}
}
if ( output_type ! = ExprNodeOutputType : : juliaDynamicModel )
2020-06-23 17:50:50 +02:00
d_output [ i ] < < i_output . str ( ) < < j_output . str ( ) < < v_output . str ( ) ;
2019-04-12 15:41:52 +02:00
}
2009-10-12 18:09:16 +02:00
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : matlabDynamicModel )
2009-12-16 18:13:23 +01:00
{
2016-12-28 14:02:50 +01:00
// Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
2016-12-30 11:26:56 +01:00
map < string , string > tmp_paren_vars ;
2017-01-05 15:19:13 +01:00
bool message_printed = false ;
2019-04-12 15:41:52 +02:00
for ( auto & it : tt_output )
fixNestedParenthesis ( it , tmp_paren_vars , message_printed ) ;
for ( auto & it : d_output )
fixNestedParenthesis ( it , tmp_paren_vars , message_printed ) ;
2018-03-27 17:14:30 +02:00
ostringstream init_output , end_output ;
init_output < < " residual = zeros( " < < nrows < < " , 1); " ;
2018-06-27 15:01:31 +02:00
writeDynamicModelHelper ( basename , " dynamic_resid " , " residual " ,
" dynamic_resid_tt " ,
2018-11-15 16:39:53 +01:00
temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) ,
2018-03-27 17:14:30 +02:00
" " , init_output , end_output ,
2019-04-12 15:41:52 +02:00
d_output [ 0 ] , tt_output [ 0 ] ) ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
init_output . str ( " " ) ;
2018-03-27 17:14:30 +02:00
init_output < < " g1 = zeros( " < < nrows < < " , " < < dynJacobianColsNbr < < " ); " ;
2018-06-27 15:01:31 +02:00
writeDynamicModelHelper ( basename , " dynamic_g1 " , " g1 " ,
" dynamic_g1_tt " ,
2018-11-15 16:39:53 +01:00
temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) ,
2018-06-27 15:01:31 +02:00
" dynamic_resid_tt " ,
2018-03-27 17:14:30 +02:00
init_output , end_output ,
2019-04-12 15:41:52 +02:00
d_output [ 1 ] , tt_output [ 1 ] ) ;
2018-06-27 15:01:31 +02:00
writeWrapperFunctions ( basename , " g1 " ) ;
2018-03-27 17:14:30 +02:00
2019-04-12 15:41:52 +02:00
// For order ≥ 2
int ncols = dynJacobianColsNbr ;
int ntt = temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) ;
for ( size_t i = 2 ; i < derivatives . size ( ) ; i + + )
2018-03-27 17:14:30 +02:00
{
2019-04-12 15:41:52 +02:00
ncols * = dynJacobianColsNbr ;
ntt + = temporary_terms_derivatives [ i ] . size ( ) ;
string gname = " g " + to_string ( i ) ;
string gprevname = " g " + to_string ( i - 1 ) ;
init_output . str ( " " ) ;
end_output . str ( " " ) ;
if ( derivatives [ i ] . size ( ) )
{
2020-06-23 17:50:50 +02:00
init_output < < gname < < " _i = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl
< < gname < < " _j = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl
< < gname < < " _v = zeros( " < < NNZDerivatives [ i ] < < " ,1); " < < endl ;
2019-04-12 15:41:52 +02:00
end_output < < gname < < " = sparse( "
2020-06-23 17:50:50 +02:00
< < gname < < " _i, " < < gname < < " _j, " < < gname < < " _v, "
2019-04-12 15:41:52 +02:00
< < nrows < < " , " < < ncols < < " ); " ;
}
else
init_output < < gname < < " = sparse([],[],[], " < < nrows < < " , " < < ncols < < " ); " ;
writeDynamicModelHelper ( basename , " dynamic_ " + gname , gname ,
" dynamic_ " + gname + " _tt " ,
ntt ,
" dynamic_ " + gprevname + " _tt " ,
init_output , end_output ,
d_output [ i ] , tt_output [ i ] ) ;
if ( i < = 3 )
writeWrapperFunctions ( basename , gname ) ;
2018-03-27 17:14:30 +02:00
}
2018-05-23 16:10:26 +02:00
2018-06-27 15:01:31 +02:00
writeDynamicMatlabCompatLayer ( basename ) ;
2009-12-16 18:13:23 +01:00
}
2018-09-05 18:27:13 +02:00
else if ( output_type = = ExprNodeOutputType : : CDynamicModel )
2009-12-16 18:13:23 +01:00
{
2019-04-12 15:41:52 +02:00
for ( size_t i = 0 ; i < d_output . size ( ) ; i + + )
{
string funcname = i = = 0 ? " resid " : " g " + to_string ( i ) ;
2020-09-03 17:52:12 +02:00
DynamicOutput < < " void dynamic_ " < < funcname < < " _tt(const double *restrict y, const double *restrict x, int nb_row_x, const double *restrict params, const double *restrict steady_state, int it_, double *restrict T) " < < endl
2019-04-12 15:41:52 +02:00
< < " { " < < endl
< < tt_output [ i ] . str ( )
< < " } " < < endl
< < endl
2020-09-03 17:52:12 +02:00
< < " void dynamic_ " < < funcname < < " (const double *restrict y, const double *restrict x, int nb_row_x, const double *restrict params, const double *restrict steady_state, int it_, const double *restrict T, " ;
2020-06-23 17:50:50 +02:00
if ( i = = 0 )
2020-09-03 17:52:12 +02:00
DynamicOutput < < " double *restrict residual " ;
2020-06-23 17:50:50 +02:00
else if ( i = = 1 )
2020-09-03 17:52:12 +02:00
DynamicOutput < < " double *restrict g1 " ;
2020-06-23 17:50:50 +02:00
else
2020-09-03 17:52:12 +02:00
DynamicOutput < < " double *restrict " < < funcname < < " _i, double *restrict " < < funcname < < " _j, double *restrict " < < funcname < < " _v " ;
2020-06-23 17:50:50 +02:00
DynamicOutput < < " ) " < < endl
2019-04-12 15:41:52 +02:00
< < " { " < < endl ;
if ( i = = 0 )
DynamicOutput < < " double lhs, rhs; " < < endl ;
DynamicOutput < < d_output [ i ] . str ( )
< < " } " < < endl
< < endl ;
}
2009-12-16 18:13:23 +01:00
}
2015-08-18 13:13:56 +02:00
else
{
2021-04-22 18:03:47 +02:00
stringstream output ;
2015-08-18 13:13:56 +02:00
2018-06-27 15:01:31 +02:00
output < < " module " < < basename < < " Dynamic " < < endl
2018-03-27 17:14:30 +02:00
< < " # " < < endl
< < " # NB: this file was automatically generated by Dynare " < < endl
2018-06-27 15:01:31 +02:00
< < " # from " < < basename < < " .mod " < < endl
2018-03-27 17:14:30 +02:00
< < " # " < < endl
2021-04-22 15:47:43 +02:00
< < " using StatsFuns " < < endl < < endl
2018-03-28 17:50:58 +02:00
< < " export tmp_nbr, dynamic!, dynamicResid!, dynamicG1!, dynamicG2!, dynamicG3! " < < endl < < endl
2018-03-27 17:14:30 +02:00
< < " #= " < < endl
< < " # The comments below apply to all functions contained in this module # " < < endl
< < " NB: The arguments contained on the first line of the function " < < endl
< < " definition are those that are modified in place " < < endl < < endl
< < " ## Exported Functions ## " < < endl
< < " dynamic! : Wrapper function; computes residuals, Jacobian, Hessian, " < < endl
< < " and third derivatives depending on the arguments provided " < < endl
< < " dynamicResid! : Computes the dynamic model residuals " < < endl
< < " dynamicG1! : Computes the dynamic model Jacobian " < < endl
< < " dynamicG2! : Computes the dynamic model Hessian " < < endl
< < " dynamicG3! : Computes the dynamic model third derivatives " < < endl < < endl
2018-03-29 11:31:25 +02:00
< < " ## Exported Variables ## " < < endl
< < " tmp_nbr : Vector{Int}(4) respectively the number of temporary variables " < < endl
< < " for the residuals, g1, g2 and g3. " < < endl < < endl
2018-03-27 17:14:30 +02:00
< < " ## Local Functions ## " < < endl
< < " dynamicResidTT! : Computes the dynamic model temporary terms for the residuals " < < endl
< < " dynamicG1TT! : Computes the dynamic model temporary terms for the Jacobian " < < endl
< < " dynamicG2TT! : Computes the dynamic model temporary terms for the Hessian " < < endl
< < " dynamicG3TT! : Computes the dynamic model temporary terms for the third derivatives " < < endl < < endl
< < " ## Function Arguments ## " < < endl
2018-03-29 11:31:25 +02:00
< < " T : Vector{Float64}(num_temp_terms), temporary terms " < < endl
< < " y : Vector{Float64}(num_dynamic_vars), endogenous variables in the order stored model_.lead_lag_incidence; see the manual " < < endl
< < " x : Matrix{Float64}(nperiods,model_.exo_nbr), exogenous variables (in declaration order) for all simulation periods " < < endl
< < " params : Vector{Float64}(model_.param_nbr), parameter values in declaration order " < < endl
< < " steady_state : Vector{Float64}(model_endo_nbr) " < < endl
< < " it_ : Int, time period for exogenous variables for which to evaluate the model " < < endl
< < " residual : Vector{Float64}(model_.eq_nbr), residuals of the dynamic model equations in order of declaration of the equations. " < < endl
< < " g1 : Matrix{Float64}(model_.eq_nbr, num_dynamic_vars), Jacobian matrix of the dynamic model equations " < < endl
< < " The rows and columns respectively correspond to equations in order of declaration and variables in order " < < endl
< < " stored in model_.lead_lag_incidence " < < endl
< < " g2 : spzeros(model_.eq_nbr, (num_dynamic_vars)^2) Hessian matrix of the dynamic model equations " < < endl
< < " The rows and columns respectively correspond to equations in order of declaration and variables in order " < < endl
< < " stored in model_.lead_lag_incidence " < < endl
< < " g3 : spzeros(model_.eq_nbr, (num_dynamic_vars)^3) Third order derivative matrix of the dynamic model equations; " < < endl
< < " The rows and columns respectively correspond to equations in order of declaration and variables in order " < < endl
< < " stored in model_.lead_lag_incidence " < < endl < < endl
< < " ## Remarks ## " < < endl
< < " [1] `num_dynamic_vars` is the number of non zero entries in the lead lag incidence matrix, `model_.lead_lag_incidence.` " < < endl
2019-12-20 16:59:30 +01:00
< < " [2] The size of `T`, ie the value of `num_temp_terms`, depends on the version of the dynamic model called. The number of temporary variables " < < endl
2018-03-29 11:31:25 +02:00
< < " used for the different returned objects (residuals, jacobian, hessian or third order derivatives) is given by the elements in `tmp_nbr` " < < endl
< < " exported vector. The first element is the number of temporaries used for the computation of the residuals, the second element is the " < < endl
< < " number of temporaries used for the evaluation of the jacobian matrix, etc. If one calls the version of the dynamic model computing the " < < endl
< < " residuals, the jacobian and hessian matrices, then `T` must have at least `sum(tmp_nbr[1:3])` elements. " < < endl
2018-03-27 17:14:30 +02:00
< < " =# " < < endl < < endl ;
2018-03-28 17:50:58 +02:00
// Write the number of temporary terms
output < < " tmp_nbr = zeros(Int,4) " < < endl
2018-11-15 16:39:53 +01:00
< < " tmp_nbr[1] = " < < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) < < " # Number of temporary terms for the residuals " < < endl
< < " tmp_nbr[2] = " < < temporary_terms_derivatives [ 1 ] . size ( ) < < " # Number of temporary terms for g1 (jacobian) " < < endl
< < " tmp_nbr[3] = " < < temporary_terms_derivatives [ 2 ] . size ( ) < < " # Number of temporary terms for g2 (hessian) " < < endl
< < " tmp_nbr[4] = " < < temporary_terms_derivatives [ 3 ] . size ( ) < < " # Number of temporary terms for g3 (third order derivates) " < < endl < < endl ;
2018-03-28 17:50:58 +02:00
2018-03-27 17:14:30 +02:00
// dynamicResidTT!
output < < " function dynamicResidTT!(T::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 0 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamic!
output < < " function dynamicResid!(T::Vector{Float64}, residual::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool) " < < endl
2018-11-15 16:39:53 +01:00
< < " @assert length(T) >= " < < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert length(residual) == " < < nrows < < endl
< < " @assert length(y)+size(x, 2) == " < < dynJacobianColsNbr < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
< < " if T_flag " < < endl
< < " dynamicResidTT!(T, y, x, params, steady_state, it_) " < < endl
< < " end " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 0 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG1TT!
output < < " function dynamicG1TT!(T::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicResidTT!(T, y, x, params, steady_state, it_) " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 1 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG1!
output < < " function dynamicG1!(T::Vector{Float64}, g1::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool) " < < endl
< < " @assert length(T) >= "
2018-11-15 16:39:53 +01:00
< < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert size(g1) == ( " < < nrows < < " , " < < dynJacobianColsNbr < < " ) " < < endl
< < " @assert length(y)+size(x, 2) == " < < dynJacobianColsNbr < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
< < " if T_flag " < < endl
< < " dynamicG1TT!(T, y, x, params, steady_state, it_) " < < endl
< < " end " < < endl
< < " fill!(g1, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 1 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG2TT!
output < < " function dynamicG2TT!(T::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicG1TT!(T, y, x, params, steady_state, it_) " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 2 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG2!
output < < " function dynamicG2!(T::Vector{Float64}, g2::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool) " < < endl
2018-11-15 16:39:53 +01:00
< < " @assert length(T) >= " < < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert size(g2) == ( " < < nrows < < " , " < < hessianColsNbr < < " ) " < < endl
< < " @assert length(y)+size(x, 2) == " < < dynJacobianColsNbr < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
< < " if T_flag " < < endl
< < " dynamicG2TT!(T, y, x, params, steady_state, it_) " < < endl
< < " end " < < endl
< < " fill!(g2, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 2 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG3TT!
output < < " function dynamicG3TT!(T::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicG2TT!(T, y, x, params, steady_state, it_) " < < endl
2019-04-12 15:41:52 +02:00
< < tt_output [ 3 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamicG3!
2015-08-20 11:32:26 +02:00
int ncols = hessianColsNbr * dynJacobianColsNbr ;
2018-03-27 17:14:30 +02:00
output < < " function dynamicG3!(T::Vector{Float64}, g3::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int, T_flag::Bool) " < < endl
< < " @assert length(T) >= "
2018-11-15 16:39:53 +01:00
< < temporary_terms_mlv . size ( ) + temporary_terms_derivatives [ 0 ] . size ( ) + temporary_terms_derivatives [ 1 ] . size ( ) + temporary_terms_derivatives [ 2 ] . size ( ) + temporary_terms_derivatives [ 3 ] . size ( ) < < endl
2018-03-27 17:14:30 +02:00
< < " @assert size(g3) == ( " < < nrows < < " , " < < ncols < < " ) " < < endl
< < " @assert length(y)+size(x, 2) == " < < dynJacobianColsNbr < < endl
< < " @assert length(params) == " < < symbol_table . param_nbr ( ) < < endl
< < " if T_flag " < < endl
< < " dynamicG3TT!(T, y, x, params, steady_state, it_) " < < endl
< < " end " < < endl
< < " fill!(g3, 0.0) " < < endl
2019-04-12 15:41:52 +02:00
< < d_output [ 3 ] . str ( )
2018-03-27 17:14:30 +02:00
< < " return nothing " < < endl
< < " end " < < endl < < endl ;
// dynamic!
output < < " function dynamic!(T::Vector{Float64}, residual::Vector{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicResid!(T, residual, y, x, params, steady_state, it_, true) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
< < endl
< < " function dynamic!(T::Vector{Float64}, residual::Vector{Float64}, g1::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicG1!(T, g1, y, x, params, steady_state, it_, true) " < < endl
< < " dynamicResid!(T, residual, y, x, params, steady_state, it_, false) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
< < endl
< < " function dynamic!(T::Vector{Float64}, residual::Vector{Float64}, g1::Matrix{Float64}, g2::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicG2!(T, g2, y, x, params, steady_state, it_, true) " < < endl
< < " dynamicG1!(T, g1, y, x, params, steady_state, it_, false) " < < endl
< < " dynamicResid!(T, residual, y, x, params, steady_state, it_, false) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
< < endl
< < " function dynamic!(T::Vector{Float64}, residual::Vector{Float64}, g1::Matrix{Float64}, g2::Matrix{Float64}, g3::Matrix{Float64}, " < < endl
< < " y::Vector{Float64}, x::Matrix{Float64}, "
< < " params::Vector{Float64}, steady_state::Vector{Float64}, it_::Int) " < < endl
< < " dynamicG3!(T, g3, y, x, params, steady_state, it_, true) " < < endl
< < " dynamicG2!(T, g2, y, x, params, steady_state, it_, false) " < < endl
< < " dynamicG1!(T, g1, y, x, params, steady_state, it_, false) " < < endl
< < " dynamicResid!(T, residual, y, x, params, steady_state, it_, false) " < < endl
< < " return nothing " < < endl
< < " end " < < endl
2021-04-26 12:52:18 +02:00
< < endl ;
// Write function definition if BinaryOpcode::powerDeriv is used
writePowerDerivJulia ( output ) ;
output < < " end " < < endl ;
2021-04-22 18:03:47 +02:00
writeToFileIfModified ( output , basename + " Dynamic.jl " ) ;
2015-08-18 13:13:56 +02:00
}
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2019-05-03 19:24:55 +02:00
void
DynamicModel : : writeDynamicJacobianNonZeroElts ( const string & basename ) const
{
vector < pair < int , int > > nzij_pred , nzij_current , nzij_fwrd ; // pairs (tsid, equation)
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
2019-05-03 19:24:55 +02:00
{
2019-12-16 19:42:59 +01:00
if ( symbol_table . getType ( getSymbIDByDerivID ( indices [ 1 ] ) ) ! = SymbolType : : endogenous )
2019-05-03 19:24:55 +02:00
continue ;
2019-12-16 19:42:59 +01:00
int tsid = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( indices [ 1 ] ) ) ;
int lag = getLagByDerivID ( indices [ 1 ] ) ;
2019-05-03 19:24:55 +02:00
if ( lag = = - 1 )
2019-12-16 19:42:59 +01:00
nzij_pred . emplace_back ( tsid , indices [ 0 ] ) ;
2019-05-03 19:24:55 +02:00
else if ( lag = = 0 )
2019-12-16 19:42:59 +01:00
nzij_current . emplace_back ( tsid , indices [ 0 ] ) ;
2019-05-03 19:24:55 +02:00
else
2019-12-16 19:42:59 +01:00
nzij_fwrd . emplace_back ( tsid , indices [ 0 ] ) ;
2019-05-03 19:24:55 +02:00
}
sort ( nzij_pred . begin ( ) , nzij_pred . end ( ) ) ;
sort ( nzij_current . begin ( ) , nzij_current . end ( ) ) ;
sort ( nzij_fwrd . begin ( ) , nzij_fwrd . end ( ) ) ;
ofstream output { " + " + basename + " /dynamic_g1_nz.m " , ios : : out | ios : : binary } ;
output < < " function [nzij_pred, nzij_current, nzij_fwrd] = dynamic_g1_nz() " < < endl
< < " % Returns the coordinates of non-zero elements in the Jacobian, in column-major order, for each lead/lag (only for endogenous) " < < endl ;
2019-12-20 16:59:30 +01:00
auto print_nzij = [ & output ] ( const vector < pair < int , int > > & nzij , const string & name ) {
output < < " " < < name < < " = zeros( " < < nzij . size ( ) < < " , 2, 'int32'); " < < endl ;
int idx = 1 ;
for ( const auto & it : nzij )
{
output < < " " < < name < < " ( " < < idx < < " ,1)= " < < it . second + 1 < < ' ; '
< < " " < < name < < " ( " < < idx < < " ,2)= " < < it . first + 1 < < ' ; ' < < endl ;
idx + + ;
}
} ;
2019-05-03 19:24:55 +02:00
print_nzij ( nzij_pred , " nzij_pred " ) ;
print_nzij ( nzij_current , " nzij_current " ) ;
print_nzij ( nzij_fwrd , " nzij_fwrd " ) ;
output < < " end " < < endl ;
output . close ( ) ;
}
2019-11-18 17:13:49 +01:00
void
2020-02-20 15:29:10 +01:00
DynamicModel : : parseIncludeExcludeEquations ( const string & inc_exc_eq_tags ,
set < pair < string , string > > & eq_tag_set , bool exclude_eqs )
2019-11-18 17:13:49 +01:00
{
string tags ;
if ( filesystem : : exists ( inc_exc_eq_tags ) )
{
ifstream exclude_file ;
exclude_file . open ( inc_exc_eq_tags , ifstream : : in ) ;
if ( ! exclude_file . is_open ( ) )
{
cerr < < " ERROR: Could not open " < < inc_exc_eq_tags < < endl ;
exit ( EXIT_FAILURE ) ;
}
string line ;
bool tagname_on_first_line = false ;
while ( getline ( exclude_file , line ) )
{
removeLeadingTrailingWhitespace ( line ) ;
if ( ! line . empty ( ) )
if ( tags . empty ( ) & & line . find ( " = " ) ! = string : : npos )
{
tagname_on_first_line = true ;
tags + = line + " ( " ;
}
else
if ( line . find ( " ' " ) ! = string : : npos )
tags + = line + " , " ;
else
tags + = " ' " + line + " ', " ;
}
if ( ! tags . empty ( ) )
{
tags = tags . substr ( 0 , tags . size ( ) - 1 ) ;
if ( tagname_on_first_line )
tags + = " ) " ;
}
}
else
tags = inc_exc_eq_tags ;
removeLeadingTrailingWhitespace ( tags ) ;
if ( tags . front ( ) = = ' [ ' & & tags . back ( ) ! = ' ] ' )
{
cerr < < " Error: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " )
< < " : if the first character is '[' the last must be ']' " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( tags . front ( ) = = ' [ ' & & tags . back ( ) = = ' ] ' )
tags = tags . substr ( 1 , tags . length ( ) - 2 ) ;
removeLeadingTrailingWhitespace ( tags ) ;
2019-12-20 16:59:30 +01:00
regex q ( R " (^ \ w+ \ s*=) " ) ;
2019-11-18 17:13:49 +01:00
smatch matches ;
string tagname = " name " ;
if ( regex_search ( tags , matches , q ) )
{
tagname = matches [ 0 ] . str ( ) ;
tags = tags . substr ( tagname . size ( ) , tags . length ( ) - tagname . size ( ) + 1 ) ;
removeLeadingTrailingWhitespace ( tags ) ;
if ( tags . front ( ) = = ' ( ' & & tags . back ( ) = = ' ) ' )
{
tags = tags . substr ( 1 , tags . length ( ) - 2 ) ;
removeLeadingTrailingWhitespace ( tags ) ;
}
tagname = tagname . substr ( 0 , tagname . size ( ) - 1 ) ;
removeLeadingTrailingWhitespace ( tagname ) ;
}
string quote_regex = " '[^']+' " ;
2019-12-16 19:42:59 +01:00
string non_quote_regex = R " ([^, \ s]+) " ;
2019-12-20 16:59:30 +01:00
regex r ( R " (( \ s*) " + quote_regex + " | " + non_quote_regex + R " ( \ s * ) ( , \ s * ( ) " + quote_regex + " | " + non_quote_regex + R " ( ) \ s * ) * ) " ) ;
if ( ! regex_match ( tags , r ) )
2019-11-18 17:13:49 +01:00
{
cerr < < " Error: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " )
< < " : argument is of incorrect format. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-12-20 16:59:30 +01:00
regex s ( quote_regex + " | " + non_quote_regex ) ;
2019-11-18 17:13:49 +01:00
for ( auto it = sregex_iterator ( tags . begin ( ) , tags . end ( ) , s ) ;
2019-12-20 16:59:30 +01:00
it ! = sregex_iterator ( ) ; + + it )
2019-11-18 17:13:49 +01:00
{
auto str = it - > str ( ) ;
if ( str [ 0 ] = = ' \' ' & & str [ str . size ( ) - 1 ] = = ' \' ' )
str = str . substr ( 1 , str . size ( ) - 2 ) ;
eq_tag_set . insert ( { tagname , str } ) ;
}
}
void
2019-12-20 16:59:30 +01:00
DynamicModel : : includeExcludeEquations ( const string & eqs , bool exclude_eqs )
2019-11-18 17:13:49 +01:00
{
if ( eqs . empty ( ) )
return ;
set < pair < string , string > > eq_tag_set ;
parseIncludeExcludeEquations ( eqs , eq_tag_set , exclude_eqs ) ;
2019-12-20 16:59:30 +01:00
vector < int > excluded_vars
= ModelTree : : includeExcludeEquations ( eq_tag_set , exclude_eqs ,
equations , equations_lineno ,
2020-02-20 15:29:10 +01:00
equation_tags , false ) ;
2019-11-18 17:13:49 +01:00
// Ignore output because variables are not excluded when equations marked 'static' are excluded
ModelTree : : includeExcludeEquations ( eq_tag_set , exclude_eqs ,
static_only_equations , static_only_equations_lineno ,
2020-02-20 15:29:10 +01:00
static_only_equations_equation_tags , true ) ;
2019-11-18 17:13:49 +01:00
if ( ! eq_tag_set . empty ( ) )
{
cerr < < " ERROR: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " ) < < " : The equations specified by ` " ;
cerr < < eq_tag_set . begin ( ) - > first < < " = " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : eq_tag_set )
2019-11-18 17:13:49 +01:00
cerr < < it . second < < " , " ;
cerr < < " ` were not found. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( staticOnlyEquationsNbr ( ) ! = dynamicOnlyEquationsNbr ( ) )
{
cerr < < " ERROR: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " )
< < " : You must remove the same number of equations marked `static` as equations marked `dynamic`. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
// Collect list of used variables in updated list of equations
set < pair < int , int > > eqn_vars ;
2019-12-20 16:59:30 +01:00
for ( const auto & eqn : equations )
2019-11-18 17:13:49 +01:00
eqn - > collectDynamicVariables ( SymbolType : : endogenous , eqn_vars ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & eqn : static_only_equations )
2019-11-18 17:13:49 +01:00
eqn - > collectDynamicVariables ( SymbolType : : endogenous , eqn_vars ) ;
// Change LHS variable type of excluded equation if it is used in an eqution that has been kept
for ( auto ev : excluded_vars )
{
bool found = false ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : eqn_vars )
2019-11-18 17:13:49 +01:00
if ( it . first = = ev )
{
symbol_table . changeType ( ev , SymbolType : : exogenous ) ;
found = true ;
break ;
}
if ( ! found )
symbol_table . changeType ( ev , SymbolType : : excludedVariable ) ;
}
}
2020-05-20 11:35:14 +02:00
void
2021-04-19 14:51:34 +02:00
DynamicModel : : writeBlockDriverOutput ( ostream & output , const string & basename ,
2020-05-20 11:35:14 +02:00
const vector < int > & state_var , bool estimation_present ) const
{
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
int block_size = blocks [ blk ] . size ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).Simulation_Type = " < < static_cast < int > ( blocks [ blk ] . simulation_type ) < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_lag = " < < blocks [ blk ] . max_lag < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_lead = " < < blocks [ blk ] . max_lead < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_endo_lag = " < < blocks [ blk ] . max_endo_lag < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_endo_lead = " < < blocks [ blk ] . max_endo_lead < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_exo_lag = " < < blocks [ blk ] . max_exo_lag < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_exo_lead = " < < blocks [ blk ] . max_exo_lead < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_exo_det_lag = " < < blocks [ blk ] . max_exo_det_lag < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).maximum_exo_det_lead = " < < blocks [ blk ] . max_exo_det_lead < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).endo_nbr = " < < block_size < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).mfs = " < < blocks [ blk ] . mfs_size < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).equation = [ " ;
2020-05-20 11:35:14 +02:00
for ( int eq = 0 ; eq < block_size ; eq + + )
output < < " " < < getBlockEquationID ( blk , eq ) + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.block( " < < blk + 1 < < " ).variable = [ " ;
2020-05-20 11:35:14 +02:00
for ( int var = 0 ; var < block_size ; var + + )
output < < " " < < getBlockVariableID ( blk , var ) + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.block( " < < blk + 1 < < " ).exogenous = [ " ;
2020-05-20 11:35:14 +02:00
for ( int exo : blocks_exo [ blk ] )
output < < " " < < exo + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.block( " < < blk + 1 < < " ).exo_nbr = " < < blocks_exo [ blk ] . size ( ) < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).exogenous_det = [ " ;
2020-05-20 11:35:14 +02:00
for ( int exo_det : blocks_exo_det [ blk ] )
output < < " " < < exo_det + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.block( " < < blk + 1 < < " ).exo_det_nbr = " < < blocks_exo_det [ blk ] . size ( ) < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).other_endogenous = [ " ;
2020-05-20 11:35:14 +02:00
for ( int other_endo : blocks_other_endo [ blk ] )
output < < " " < < other_endo + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.block( " < < blk + 1 < < " ).other_endogenous_block = [ " ;
2020-05-20 11:35:14 +02:00
for ( int other_endo : blocks_other_endo [ blk ] )
output < < " " < < endo2block [ other_endo ] + 1 ;
output < < " ]; " < < endl ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).tm1 = zeros( " < < blocks_other_endo [ blk ] . size ( ) < < " , " < < state_var . size ( ) < < " ); " < < endl ;
2020-05-20 11:35:14 +02:00
int line = 1 ;
for ( auto other_endo : blocks_other_endo [ blk ] )
{
if ( auto it = find ( state_var . begin ( ) , state_var . end ( ) , other_endo ) ;
it ! = state_var . end ( ) )
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).tm1( "
2020-05-20 11:35:14 +02:00
< < line < < " , "
< < distance ( state_var . begin ( ) , it ) + 1 < < " ) = 1; " < < endl ;
line + + ;
}
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).other_endo_nbr = " < < blocks_other_endo [ blk ] . size ( ) < < " ; " < < endl ;
2020-05-20 11:35:14 +02:00
int count_lead_lag_incidence = 0 ;
vector < int > local_state_var ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).lead_lag_incidence = [ " < < endl ;
2020-05-20 11:35:14 +02:00
for ( int lag = - 1 ; lag < = 1 ; lag + + )
{
for ( int var = 0 ; var < block_size ; var + + )
{
for ( int eq = 0 ; eq < block_size ; eq + + )
if ( blocks_derivatives [ blk ] . find ( { eq , var , lag } )
! = blocks_derivatives [ blk ] . end ( ) )
{
if ( lag = = - 1 )
local_state_var . push_back ( getBlockVariableID ( blk , var ) ) ;
output < < " " < < + + count_lead_lag_incidence ;
goto var_found ;
}
output < < " 0 " ;
var_found :
;
}
output < < " ; " < < endl ;
}
output < < " ]; " < < endl ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).sorted_col_dr_ghx = [ " ;
2020-05-20 11:35:14 +02:00
for ( int lsv : local_state_var )
output < < distance ( state_var . begin ( ) , find ( state_var . begin ( ) , state_var . end ( ) , lsv ) ) + 1 < < " " ;
output < < " ]; " < < endl ;
count_lead_lag_incidence = 0 ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).lead_lag_incidence_other = [ " < < endl ;
2020-05-20 11:35:14 +02:00
for ( int lag = - 1 ; lag < = 1 ; lag + + )
{
for ( int other_endo : blocks_other_endo [ blk ] )
{
for ( int eq = 0 ; eq < block_size ; eq + + )
if ( blocks_derivatives_other_endo [ blk ] . find ( { eq , other_endo , lag } )
! = blocks_derivatives_other_endo [ blk ] . end ( ) )
{
output < < " " < < + + count_lead_lag_incidence ;
goto other_endo_found ;
}
output < < " 0 " ;
other_endo_found :
;
}
output < < " ; " < < endl ;
}
output < < " ]; " < < endl ;
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.block( " < < blk + 1 < < " ).n_static = " < < blocks [ blk ] . n_static < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).n_forward = " < < blocks [ blk ] . n_forward < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).n_backward = " < < blocks [ blk ] . n_backward < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).n_mixed = " < < blocks [ blk ] . n_mixed < < " ; " < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).is_linear = " < < ( blocks [ blk ] . linear ? " true " : " false " ) < < ' ; ' < < endl
< < " M_.block_structure.block( " < < blk + 1 < < " ).NNZDerivatives = " < < blocks_derivatives [ blk ] . size ( ) < < ' ; ' < < endl ;
2020-05-20 11:35:14 +02:00
}
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.variable_reordered = [ " ;
2020-05-20 11:35:14 +02:00
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
output < < " " < < endo_idx_block2orig [ i ] + 1 ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.block_structure.equation_reordered = [ " ;
2020-05-20 11:35:14 +02:00
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
output < < " " < < eq_idx_block2orig [ i ] + 1 ;
output < < " ]; " < < endl ;
map < int , set < pair < int , int > > > lag_row_incidence ;
for ( const auto & [ indices , d1 ] : derivatives [ 1 ] )
if ( int deriv_id = indices [ 1 ] ;
getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
{
int eq = indices [ 0 ] ;
int var = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( deriv_id ) ) ;
int lag = getLagByDerivID ( deriv_id ) ;
lag_row_incidence [ lag ] . insert ( { eq , var } ) ;
}
for ( auto [ lag , eq_var_set ] : lag_row_incidence )
{
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.incidence( " < < max_endo_lag + lag + 1 < < " ).lead_lag = " < < lag < < " ; " < < endl
< < " M_.block_structure.incidence( " < < max_endo_lag + lag + 1 < < " ).sparse_IM = [ " < < endl ;
2020-05-20 11:35:14 +02:00
for ( auto [ eq , var ] : eq_var_set )
output < < " " < < eq + 1 < < " " < < var + 1 < < " ; " < < endl ;
output < < " ]; " < < endl ;
}
2021-04-19 14:51:34 +02:00
output < < " M_.block_structure.dyn_tmp_nbr = " < < blocks_temporary_terms_idxs . size ( ) < < ' ; ' < < endl ;
2020-05-20 11:35:14 +02:00
if ( estimation_present )
{
filesystem : : create_directories ( basename + " /model/bytecode " ) ;
string main_name = basename + " /model/bytecode/kfi " ;
ofstream KF_index_file ;
KF_index_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
int n_obs = symbol_table . observedVariablesNbr ( ) ;
int n_state = state_var . size ( ) ;
for ( int it : state_var )
if ( symbol_table . isObservedVariable ( symbol_table . getID ( SymbolType : : endogenous , it ) ) )
n_obs - - ;
int n = n_obs + n_state ;
2021-04-19 14:51:34 +02:00
output < < " M_.nobs_non_statevar = " < < n_obs < < " ; " < < endl ;
2020-05-20 11:35:14 +02:00
int nb_diag = 0 ;
vector < int > i_nz_state_var ( n ) ;
for ( int i = 0 ; i < n_obs ; i + + )
i_nz_state_var [ i ] = n ;
int lp = n_obs ;
vector < int > state_equ ;
for ( int it : state_var )
state_equ . push_back ( eq_idx_block2orig [ endo_idx_orig2block [ it ] ] ) ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
{
int nze = 0 ;
for ( int i = 0 ; i < blocks [ blk ] . size ; i + + )
if ( int var = getBlockVariableID ( blk , i ) ;
find ( state_var . begin ( ) , state_var . end ( ) , var ) ! = state_var . end ( ) )
nze + + ;
if ( blk = = 0 )
{
set < pair < int , int > > row_state_var_incidence ;
for ( const auto & [ idx , ignore ] : blocks_derivatives [ blk ] )
if ( auto it_state_var = find ( state_var . begin ( ) , state_var . end ( ) , getBlockVariableID ( blk , get < 1 > ( idx ) ) ) ;
it_state_var ! = state_var . end ( ) )
if ( auto it_state_equ = find ( state_equ . begin ( ) , state_equ . end ( ) , getBlockEquationID ( blk , get < 0 > ( idx ) ) ) ;
it_state_equ ! = state_equ . end ( ) )
row_state_var_incidence . emplace ( it_state_equ - state_equ . begin ( ) , it_state_var - state_var . begin ( ) ) ;
auto row_state_var_incidence_it = row_state_var_incidence . begin ( ) ;
bool diag = true ;
int nb_diag_r = 0 ;
while ( row_state_var_incidence_it ! = row_state_var_incidence . end ( ) & & diag )
{
diag = ( row_state_var_incidence_it - > first = = row_state_var_incidence_it - > second ) ;
if ( diag )
{
int equ = row_state_var_incidence_it - > first ;
row_state_var_incidence_it + + ;
if ( equ ! = row_state_var_incidence_it - > first )
nb_diag_r + + ;
}
}
set < pair < int , int > > col_state_var_incidence ;
for ( auto [ equ , var ] : row_state_var_incidence )
col_state_var_incidence . emplace ( var , equ ) ;
auto col_state_var_incidence_it = col_state_var_incidence . begin ( ) ;
diag = true ;
int nb_diag_c = 0 ;
while ( col_state_var_incidence_it ! = col_state_var_incidence . end ( ) & & diag )
{
diag = ( col_state_var_incidence_it - > first = = col_state_var_incidence_it - > second ) ;
if ( diag )
{
int var = col_state_var_incidence_it - > first ;
col_state_var_incidence_it + + ;
if ( var ! = col_state_var_incidence_it - > first )
nb_diag_c + + ;
}
}
nb_diag = min ( nb_diag_r , nb_diag_c ) ;
row_state_var_incidence . clear ( ) ;
col_state_var_incidence . clear ( ) ;
}
for ( int i = 0 ; i < nze ; i + + )
i_nz_state_var [ lp + i ] = lp + nze ;
lp + = nze ;
}
2021-04-19 14:51:34 +02:00
output < < " M_.nz_state_var = [ " ;
2020-05-20 11:35:14 +02:00
for ( int i = 0 ; i < lp ; i + + )
output < < i_nz_state_var [ i ] < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.n_diag = " < < nb_diag < < " ; " < < endl ;
2020-05-20 11:35:14 +02:00
KF_index_file . write ( reinterpret_cast < char * > ( & nb_diag ) , sizeof ( nb_diag ) ) ;
using index_KF = pair < int , pair < int , int > > ;
vector < index_KF > v_index_KF ;
for ( int i = 0 ; i < n ; i + + )
for ( int j = n_obs ; j < n ; j + + )
{
int j1 = j - n_obs ;
int j1_n_state = j1 * n_state - n_obs ;
if ( ( i < n_obs ) | | ( i > = nb_diag + n_obs ) | | ( j1 > = nb_diag ) )
for ( int k = n_obs ; k < i_nz_state_var [ i ] ; k + + )
v_index_KF . emplace_back ( i + j1 * n , pair ( i + k * n , k + j1_n_state ) ) ;
}
int size_v_index_KF = v_index_KF . size ( ) ;
KF_index_file . write ( reinterpret_cast < char * > ( & size_v_index_KF ) , sizeof ( size_v_index_KF ) ) ;
for ( auto & it : v_index_KF )
KF_index_file . write ( reinterpret_cast < char * > ( & it ) , sizeof ( index_KF ) ) ;
vector < index_KF > v_index_KF_2 ;
int n_n_obs = n * n_obs ;
for ( int i = 0 ; i < n ; i + + )
for ( int j = i ; j < n ; j + + )
if ( ( i < n_obs ) | | ( i > = nb_diag + n_obs ) | | ( j < n_obs ) | | ( j > = nb_diag + n_obs ) )
for ( int k = n_obs ; k < i_nz_state_var [ j ] ; k + + )
{
int k_n = k * n ;
v_index_KF_2 . emplace_back ( i * n + j , pair ( i + k_n - n_n_obs , j + k_n ) ) ;
}
int size_v_index_KF_2 = v_index_KF_2 . size ( ) ;
KF_index_file . write ( reinterpret_cast < char * > ( & size_v_index_KF_2 ) , sizeof ( size_v_index_KF_2 ) ) ;
for ( auto & it : v_index_KF_2 )
KF_index_file . write ( reinterpret_cast < char * > ( & it ) , sizeof ( index_KF ) ) ;
KF_index_file . close ( ) ;
}
}
2009-04-14 16:39:53 +02:00
void
2021-02-22 18:26:21 +01:00
DynamicModel : : writeDriverOutput ( ostream & output , const string & basename , bool block_decomposition , bool use_dll , bool occbin , bool estimation_present , bool compute_xrefs ) const
2009-12-16 18:13:23 +01:00
{
/* Writing initialisation for M_.lead_lag_incidence matrix
M_ . lead_lag_incidence is a matrix with as many columns as there are
endogenous variables and as many rows as there are periods in the
models ( nbr of rows = M_ . max_lag + M_ . max_lead + 1 )
The matrix elements are equal to zero if a variable isn ' t present in the
model at a given period .
*/
2021-04-19 14:51:34 +02:00
output < < " M_.orig_maximum_endo_lag = " < < max_endo_lag_orig < < " ; " < < endl
< < " M_.orig_maximum_endo_lead = " < < max_endo_lead_orig < < " ; " < < endl
< < " M_.orig_maximum_exo_lag = " < < max_exo_lag_orig < < " ; " < < endl
< < " M_.orig_maximum_exo_lead = " < < max_exo_lead_orig < < " ; " < < endl
< < " M_.orig_maximum_exo_det_lag = " < < max_exo_det_lag_orig < < " ; " < < endl
< < " M_.orig_maximum_exo_det_lead = " < < max_exo_det_lead_orig < < " ; " < < endl
< < " M_.orig_maximum_lag = " < < max_lag_orig < < " ; " < < endl
< < " M_.orig_maximum_lead = " < < max_lead_orig < < " ; " < < endl
< < " M_.orig_maximum_lag_with_diffs_expanded = " < < max_lag_with_diffs_expanded_orig < < " ; " < < endl
< < " M_.lead_lag_incidence = [ " ;
2009-12-16 18:13:23 +01:00
// Loop on endogenous variables
2017-06-01 19:58:32 +02:00
int nstatic = 0 ,
2019-12-16 19:42:59 +01:00
nfwrd = 0 ,
npred = 0 ,
nboth = 0 ;
2009-12-16 18:13:23 +01:00
for ( int endoID = 0 ; endoID < symbol_table . endo_nbr ( ) ; endoID + + )
{
output < < endl ;
2017-06-01 19:58:32 +02:00
int sstatic = 1 ,
2019-12-16 19:42:59 +01:00
sfwrd = 0 ,
spred = 0 ,
sboth = 0 ;
2009-12-16 18:13:23 +01:00
// Loop on periods
for ( int lag = - max_endo_lag ; lag < = max_endo_lead ; lag + + )
{
// Print variableID if exists with current period, otherwise print 0
try
{
2018-07-17 18:34:07 +02:00
int varID = getDerivID ( symbol_table . getID ( SymbolType : : endogenous , endoID ) , lag ) ;
2009-12-16 18:13:23 +01:00
output < < " " < < getDynJacobianCol ( varID ) + 1 ;
2011-06-18 17:53:50 +02:00
if ( lag = = - 1 )
{
sstatic = 0 ;
spred = 1 ;
}
else if ( lag = = 1 )
{
if ( spred = = 1 )
{
sboth = 1 ;
spred = 0 ;
}
else
{
sstatic = 0 ;
sfwrd = 1 ;
}
}
2009-12-16 18:13:23 +01:00
}
catch ( UnknownDerivIDException & e )
{
output < < " 0 " ;
}
}
2011-06-18 17:53:50 +02:00
nstatic + = sstatic ;
2019-12-20 16:59:30 +01:00
nfwrd + = sfwrd ;
npred + = spred ;
nboth + = sboth ;
2009-12-16 18:13:23 +01:00
output < < " ; " ;
}
output < < " ]'; " < < endl ;
2021-04-19 14:51:34 +02:00
output < < " M_.nstatic = " < < nstatic < < " ; " < < endl
< < " M_.nfwrd = " < < nfwrd < < " ; " < < endl
< < " M_.npred = " < < npred < < " ; " < < endl
< < " M_.nboth = " < < nboth < < " ; " < < endl
< < " M_.nsfwrd = " < < nfwrd + nboth < < " ; " < < endl
< < " M_.nspred = " < < npred + nboth < < " ; " < < endl
< < " M_.ndynamic = " < < npred + nboth + nfwrd < < " ; " < < endl ;
output < < " M_.dynamic_tmp_nbr = [ " ;
for ( size_t i = 0 ; i < temporary_terms_derivatives . size ( ) ; i + + )
output < < temporary_terms_derivatives [ i ] . size ( ) + ( i = = 0 ? temporary_terms_mlv . size ( ) : 0 ) < < " ; " ;
output < < " ]; " < < endl ;
2020-06-05 17:11:29 +02:00
2021-04-19 14:51:34 +02:00
/* Write mapping between model local variables and indices in the temporary
terms vector ( dynare # 1722 ) */
output < < " M_.model_local_variables_dynamic_tt_idxs = { " < < endl ;
for ( auto [ mlv , value ] : temporary_terms_mlv )
output < < " ' " < < symbol_table . getName ( mlv - > symb_id ) < < " ', "
< < temporary_terms_idxs . at ( mlv ) + 1 < < ' ; ' < < endl ;
output < < " }; " < < endl ;
2009-12-16 18:13:23 +01:00
// Write equation tags
2021-04-19 14:51:34 +02:00
equation_tags . writeOutput ( output ) ;
2009-12-16 18:13:23 +01:00
2020-02-11 14:12:24 +01:00
// Write Occbin tags
2021-02-22 18:26:21 +01:00
if ( occbin )
equation_tags . writeOccbinOutput ( output ) ;
2020-02-11 14:12:24 +01:00
2019-10-16 17:34:27 +02:00
// Write mapping for variables and equations they are present in
2021-04-19 14:51:34 +02:00
for ( const auto & variable : variableMapping )
2019-10-16 17:34:27 +02:00
{
2021-04-19 14:51:34 +02:00
output < < " M_.mapping. " < < symbol_table . getName ( variable . first ) < < " .eqidx = [ " ;
for ( auto equation : variable . second )
output < < equation + 1 < < " " ;
output < < " ]; " < < endl ;
2019-10-16 17:34:27 +02:00
}
2013-04-11 17:07:39 +02:00
/* Say if static and dynamic models differ (because of [static] and [dynamic]
equation tags ) */
2021-04-19 14:51:34 +02:00
output < < " M_.static_and_dynamic_models_differ = "
2019-12-20 16:59:30 +01:00
< < ( static_only_equations . size ( ) > 0 ? " true " : " false " )
2013-04-11 17:07:39 +02:00
< < " ; " < < endl ;
2019-05-15 15:02:36 +02:00
// Say if model contains an external function call
bool has_external_function = false ;
2019-12-16 19:42:59 +01:00
for ( auto equation : equations )
if ( equation - > containsExternalFunction ( ) )
2019-05-15 15:02:36 +02:00
{
has_external_function = true ;
break ;
}
2021-04-19 14:51:34 +02:00
output < < " M_.has_external_function = "
2019-05-15 15:02:36 +02:00
< < ( has_external_function ? " true " : " false " )
< < ' ; ' < < endl ;
2020-05-20 11:35:14 +02:00
// Compute list of state variables, ordered in block-order
2016-07-20 23:09:46 +02:00
vector < int > state_var ;
for ( int endoID = 0 ; endoID < symbol_table . endo_nbr ( ) ; endoID + + )
2020-05-20 11:35:14 +02:00
// Loop on negative lags
2016-07-20 23:09:46 +02:00
for ( int lag = - max_endo_lag ; lag < 0 ; lag + + )
try
{
2020-04-17 14:55:55 +02:00
getDerivID ( symbol_table . getID ( SymbolType : : endogenous , endo_idx_block2orig [ endoID ] ) , lag ) ;
2020-05-20 11:35:14 +02:00
if ( find ( state_var . begin ( ) , state_var . end ( ) , endo_idx_block2orig [ endoID ] ) = = state_var . end ( ) )
state_var . push_back ( endo_idx_block2orig [ endoID ] ) ;
2016-07-20 23:09:46 +02:00
}
catch ( UnknownDerivIDException & e )
{
}
2020-05-20 11:35:14 +02:00
// Write the block structure of the model
2021-01-25 18:03:37 +01:00
if ( block_decomposition )
2021-04-19 14:51:34 +02:00
writeBlockDriverOutput ( output , basename , state_var , estimation_present ) ;
2012-09-28 18:41:18 +02:00
2021-04-19 14:51:34 +02:00
output < < " M_.state_var = [ " ;
2018-11-23 17:19:59 +01:00
for ( int it : state_var )
2021-04-19 14:51:34 +02:00
output < < it + 1 < < " " ;
2016-07-20 23:09:46 +02:00
output < < " ]; " < < endl ;
2009-12-16 18:13:23 +01:00
// Writing initialization for some other variables
2021-04-19 14:51:34 +02:00
output < < " M_.exo_names_orig_ord = [1: " < < symbol_table . exo_nbr ( ) < < " ]; " < < endl ;
2013-11-04 16:02:28 +01:00
2021-04-19 14:51:34 +02:00
output < < " M_.maximum_lag = " < < max_lag < < " ; " < < endl
< < " M_.maximum_lead = " < < max_lead < < " ; " < < endl ;
2013-11-04 16:02:28 +01:00
2021-04-19 14:51:34 +02:00
output < < " M_.maximum_endo_lag = " < < max_endo_lag < < " ; " < < endl
< < " M_.maximum_endo_lead = " < < max_endo_lead < < " ; " < < endl
< < " oo_.steady_state = zeros( " < < symbol_table . endo_nbr ( ) < < " , 1); " < < endl ;
2013-11-04 16:02:28 +01:00
2021-04-19 14:51:34 +02:00
output < < " M_.maximum_exo_lag = " < < max_exo_lag < < " ; " < < endl
< < " M_.maximum_exo_lead = " < < max_exo_lead < < " ; " < < endl
< < " oo_.exo_steady_state = zeros( " < < symbol_table . exo_nbr ( ) < < " , 1); " < < endl ;
2013-11-04 16:02:28 +01:00
2009-12-16 18:13:23 +01:00
if ( symbol_table . exo_det_nbr ( ) )
{
2021-04-19 14:51:34 +02:00
output < < " M_.maximum_exo_det_lag = " < < max_exo_det_lag < < " ; " < < endl
< < " M_.maximum_exo_det_lead = " < < max_exo_det_lead < < " ; " < < endl
< < " oo_.exo_det_steady_state = zeros( " < < symbol_table . exo_det_nbr ( ) < < " , 1); " < < endl ;
2009-12-16 18:13:23 +01:00
}
2013-11-04 16:02:28 +01:00
2021-04-19 14:51:34 +02:00
output < < " M_.params = " < < " NaN( " < < symbol_table . param_nbr ( ) < < " , 1); " < < endl ;
2009-12-16 18:13:23 +01:00
2021-04-19 14:51:34 +02:00
string empty_cell = " cell( " + to_string ( symbol_table . endo_nbr ( ) ) + " , 1) " ;
output < < " M_.endo_trends = struct('deflator', " < < empty_cell
< < " , 'log_deflator', " < < empty_cell < < " , 'growth_factor', " < < empty_cell
< < " , 'log_growth_factor', " < < empty_cell < < " ); " < < endl ;
for ( int i = 0 ; i < symbol_table . endo_nbr ( ) ; i + + )
2019-12-13 17:27:50 +01:00
{
2021-04-19 14:51:34 +02:00
int symb_id = symbol_table . getID ( SymbolType : : endogenous , i ) ;
if ( auto it = nonstationary_symbols_map . find ( symb_id ) ; it ! = nonstationary_symbols_map . end ( ) )
2019-12-13 17:27:50 +01:00
{
2021-04-19 14:51:34 +02:00
auto [ is_log , deflator ] = it - > second ;
output < < " M_.endo_trends( " < < i < < " ). "
< < ( is_log ? " log_deflator " : " deflator " ) < < " = ' " ;
deflator - > writeJsonOutput ( output , { } , { } ) ;
output < < " '; " < < endl ;
auto growth_factor = const_cast < DynamicModel * > ( this ) - > AddDivide ( deflator , deflator - > decreaseLeadsLags ( 1 ) ) - > removeTrendLeadLag ( trend_symbols_map ) - > replaceTrendVar ( ) ;
output < < " M_.endo_trends( " < < i < < " ). "
< < ( is_log ? " log_growth_factor " : " growth_factor " ) < < " = ' " ;
growth_factor - > writeJsonOutput ( output , { } , { } ) ;
output < < " '; " < < endl ;
2019-12-13 17:27:50 +01:00
}
}
2016-02-23 13:55:02 +01:00
if ( compute_xrefs )
writeXrefs ( output ) ;
2015-12-18 15:17:32 +01:00
2009-12-16 18:13:23 +01:00
// Write number of non-zero derivatives
2010-07-17 10:14:22 +02:00
// Use -1 if the derivatives have not been computed
2021-04-19 14:51:34 +02:00
output < < " M_.NNZDerivatives = [ " ;
2019-04-12 15:41:52 +02:00
for ( int i = 1 ; i < static_cast < int > ( NNZDerivatives . size ( ) ) ; i + + )
2020-01-20 17:22:32 +01:00
output < < ( i > computed_derivs_order ? - 1 : NNZDerivatives [ i ] ) < < " ; " ;
2015-07-29 14:52:15 +02:00
output < < " ]; " < < endl ;
2018-02-07 13:49:57 +01:00
2019-02-15 12:52:46 +01:00
// Write Pac Model Consistent Expectation parameter info
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_mce_alpha_symb_ids )
2019-02-15 12:52:46 +01:00
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first . first < < " .equations. " < < it . first . second < < " .mce.alpha = [ " ;
2019-02-15 12:52:46 +01:00
for ( auto it : it . second )
output < < symbol_table . getTypeSpecificID ( it ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2019-02-19 16:36:10 +01:00
// Write Pac Model Consistent Expectation Z1 info
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_mce_z1_symb_ids )
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first . first < < " .equations. " < < it . first . second < < " .mce.z1 = "
2019-02-19 16:36:10 +01:00
< < symbol_table . getTypeSpecificID ( it . second ) + 1 < < " ; " < < endl ;
// Write Pac lag info
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_eqtag_and_lag )
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first . first < < " .equations. " < < it . second . first < < " .max_lag = " < < it . second . second < < " ; " < < endl ;
2019-02-19 16:36:10 +01:00
// Write Pac equation tag info
map < string , vector < pair < string , string > > > for_writing ;
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_eqtag_and_lag )
2019-02-21 12:15:50 +01:00
for_writing [ it . first . first ] . emplace_back ( it . first . second , it . second . first ) ;
2019-02-19 16:36:10 +01:00
2019-12-20 16:59:30 +01:00
for ( auto & it : for_writing )
2019-02-19 16:36:10 +01:00
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first < < " .tag_map = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it1 : it . second )
output < < " {' " < < it1 . first < < " ', ' " < < it1 . second < < " '}; " ;
2019-02-19 16:36:10 +01:00
output < < " ]; " < < endl ;
}
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_model_info )
2019-02-20 12:59:55 +01:00
{
vector < int > lhs = get < 0 > ( it . second ) ;
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first < < " .lhs = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto it : lhs )
output < < it + 1 < < " " ;
output < < " ]; " < < endl ;
2019-02-20 16:38:44 +01:00
2019-12-16 19:42:59 +01:00
if ( int growth_param_index = get < 1 > ( it . second ) ;
growth_param_index > = 0 )
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first < < " .growth_neutrality_param_index = "
2019-02-20 16:38:44 +01:00
< < symbol_table . getTypeSpecificID ( growth_param_index ) + 1 < < " ; " < < endl ;
2019-02-20 16:42:22 +01:00
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first < < " .auxiliary_model_type = ' " < < get < 2 > ( it . second ) < < " '; " < < endl ;
2019-02-20 12:59:55 +01:00
}
2019-12-20 16:59:30 +01:00
for ( auto & pit : pac_equation_info )
2019-02-20 12:59:55 +01:00
{
2019-09-11 15:59:23 +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 ] = pit . second ;
2019-02-20 12:59:55 +01:00
string substruct = pit . first . first + " .equations. " + pit . first . second + " . " ;
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " lhs_var = "
2019-02-20 12:59:55 +01:00
< < symbol_table . getTypeSpecificID ( lhs_pac_var . first ) + 1 < < " ; " < < endl ;
if ( optim_share_index > = 0 )
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " share_of_optimizing_agents_index = "
2019-02-20 12:59:55 +01:00
< < symbol_table . getTypeSpecificID ( optim_share_index ) + 1 < < " ; " < < endl ;
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " ec.params = "
2019-02-20 12:59:55 +01:00
< < symbol_table . getTypeSpecificID ( ec_params_and_vars . first ) + 1 < < " ; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ec.vars = [ " ;
2019-03-05 10:57:15 +01:00
for ( auto it : ec_params_and_vars . second )
2019-03-07 11:31:36 +01:00
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
2019-03-05 10:57:15 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ec.istarget = [ " ;
2019-03-05 10:57:15 +01:00
for ( auto it : ec_params_and_vars . second )
2019-03-07 11:31:36 +01:00
output < < ( get < 1 > ( it ) ? " true " : " false " ) ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ec.scale = [ " ;
2019-03-07 11:31:36 +01:00
for ( auto it : ec_params_and_vars . second )
output < < get < 2 > ( it ) < < " " ;
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ec.isendo = [ " ;
2019-03-05 10:57:15 +01:00
for ( auto it : ec_params_and_vars . second )
2019-03-07 11:31:36 +01:00
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
2019-03-05 10:57:15 +01:00
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ar.params = [ " ;
2020-09-11 16:45:19 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < ( pid ! = - 1 ? symbol_table . getTypeSpecificID ( pid ) + 1 : - 1 ) < < " " ;
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ar.vars = [ " ;
2020-09-11 16:45:19 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < ( vid ! = - 1 ? symbol_table . getTypeSpecificID ( vid ) + 1 : - 1 ) < < " " ;
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " ar.lags = [ " ;
2020-09-11 16:45:19 +02:00
for ( auto & [ pid , vid , vlag ] : ar_params_and_vars )
output < < vlag < < " " ;
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl ;
if ( ! non_optim_vars_params_and_constants . empty ( ) )
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " non_optimizing_behaviour.params = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
2019-02-20 12:59:55 +01:00
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " non_optimizing_behaviour.vars = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
2019-02-20 12:59:55 +01:00
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
2019-02-27 15:10:48 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " non_optimizing_behaviour.isendo = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
2019-02-27 15:10:48 +01:00
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
2019-02-27 15:35:14 +01:00
output < < " true " ;
2019-02-27 15:10:48 +01:00
break ;
case SymbolType : : exogenous :
2019-02-27 15:35:14 +01:00
output < < " false " ;
2019-02-27 15:10:48 +01:00
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " non_optimizing_behaviour.lags = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
2019-02-20 12:59:55 +01:00
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " non_optimizing_behaviour.scaling_factor = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
2019-02-20 12:59:55 +01:00
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
2019-02-27 23:12:05 +01:00
if ( ! additive_vars_params_and_constants . empty ( ) )
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " additive.params = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : additive_vars_params_and_constants )
2019-02-27 23:12:05 +01:00
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " additive.vars = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : additive_vars_params_and_constants )
2019-02-27 23:12:05 +01:00
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " additive.isendo = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : additive_vars_params_and_constants )
2019-02-27 23:12:05 +01:00
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-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " additive.lags = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : additive_vars_params_and_constants )
2019-02-27 23:12:05 +01:00
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " additive.scaling_factor = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : additive_vars_params_and_constants )
2019-02-27 23:12:05 +01:00
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
2019-03-07 12:35:30 +01:00
if ( ! optim_additive_vars_params_and_constants . empty ( ) )
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " optim_additive.params = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
2019-03-07 12:35:30 +01:00
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " optim_additive.vars = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
2019-03-07 12:35:30 +01:00
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " optim_additive.isendo = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
2019-03-07 12:35:30 +01:00
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-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " optim_additive.lags = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
2019-03-07 12:35:30 +01:00
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2021-04-19 14:51:34 +02:00
< < " M_.pac. " < < substruct < < " optim_additive.scaling_factor = [ " ;
2019-12-20 16:59:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
2019-03-07 12:35:30 +01:00
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
2019-02-22 11:52:07 +01:00
// Create empty h0 and h1 substructures that will be overwritten later if not empty
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < substruct < < " h0_param_indices = []; " < < endl
< < " M_.pac. " < < substruct < < " h1_param_indices = []; " < < endl ;
2019-02-20 12:59:55 +01:00
}
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_h0_indices )
2019-02-20 12:59:55 +01:00
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first . first < < " .equations. " < < it . first . second < < " .h0_param_indices = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto it1 : it . second )
output < < symbol_table . getTypeSpecificID ( it1 ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_h1_indices )
2019-02-20 12:59:55 +01:00
{
2021-04-19 14:51:34 +02:00
output < < " M_.pac. " < < it . first . first < < " .equations. " < < it . first . second < < " .h1_param_indices = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto it1 : it . second )
output < < symbol_table . getTypeSpecificID ( it1 ) + 1 < < " " ;
output < < " ]; " < < endl ;
}
2009-12-16 18:13:23 +01:00
}
2009-05-13 01:03:40 +02:00
2010-10-15 19:05:16 +02:00
void
DynamicModel : : runTrendTest ( const eval_context_t & eval_context )
{
computeDerivIDs ( ) ;
testTrendDerivativesEqualToZero ( eval_context ) ;
}
2018-08-23 13:56:58 +02:00
void
2018-09-03 15:05:30 +02:00
DynamicModel : : updateVarAndTrendModel ( ) const
2018-08-23 13:56:58 +02:00
{
for ( int i = 0 ; i < 2 ; i + + )
{
2018-09-03 15:05:30 +02:00
map < string , vector < int > > eqnums , trend_eqnums ;
2018-08-23 13:56:58 +02:00
if ( i = = 0 )
eqnums = var_model_table . getEqNums ( ) ;
else if ( i = = 1 )
2018-09-03 15:05:30 +02:00
{
eqnums = trend_component_model_table . getEqNums ( ) ;
2018-09-13 12:21:23 +02:00
trend_eqnums = trend_component_model_table . getTargetEqNums ( ) ;
2018-09-03 15:05:30 +02:00
}
2018-08-23 13:56:58 +02:00
2018-08-31 12:35:51 +02:00
map < string , vector < int > > trend_varr ;
2018-08-23 13:56:58 +02:00
map < string , vector < set < pair < int , int > > > > rhsr ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : eqnums )
2018-08-23 13:56:58 +02:00
{
2018-09-03 15:05:30 +02:00
vector < int > lhs , trend_var , trend_lhs ;
2018-08-23 13:56:58 +02:00
vector < set < pair < int , int > > > rhs ;
2018-09-03 15:05:30 +02:00
2018-08-31 12:35:51 +02:00
if ( i = = 1 )
2018-09-03 15:05:30 +02:00
{
lhs = trend_component_model_table . getLhs ( it . first ) ;
for ( auto teqn : trend_eqnums . at ( it . first ) )
{
int eqnidx = 0 ;
for ( auto eqn : it . second )
{
if ( eqn = = teqn )
trend_lhs . push_back ( lhs [ eqnidx ] ) ;
eqnidx + + ;
}
}
}
int lhs_idx = 0 ;
2018-08-23 13:56:58 +02:00
for ( auto eqn : it . second )
{
set < pair < int , int > > rhs_set ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg2 - > collectDynamicVariables ( SymbolType : : endogenous , rhs_set ) ;
2018-08-23 13:56:58 +02:00
rhs . push_back ( rhs_set ) ;
2018-09-03 15:05:30 +02:00
2018-08-31 12:35:51 +02:00
if ( i = = 1 )
{
int lhs_symb_id = lhs [ lhs_idx + + ] ;
if ( symbol_table . isAuxiliaryVariable ( lhs_symb_id ) )
try
{
lhs_symb_id = symbol_table . getOrigSymbIdForAuxVar ( lhs_symb_id ) ;
}
catch ( . . . )
{
}
2018-11-28 14:32:26 +01:00
int trend_var_symb_id = equations [ eqn ] - > arg2 - > findTargetVariable ( lhs_symb_id ) ;
2018-09-03 15:05:30 +02:00
if ( trend_var_symb_id > = 0 )
{
if ( symbol_table . isAuxiliaryVariable ( trend_var_symb_id ) )
try
{
trend_var_symb_id = symbol_table . getOrigSymbIdForAuxVar ( trend_var_symb_id ) ;
}
catch ( . . . )
{
}
if ( find ( trend_lhs . begin ( ) , trend_lhs . end ( ) , trend_var_symb_id ) = = trend_lhs . end ( ) )
{
cerr < < " ERROR: trend found in trend_component equation # " < < eqn < < " ( "
< < symbol_table . getName ( trend_var_symb_id ) < < " ) does not correspond to a trend equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2018-09-03 17:25:42 +02:00
trend_var . push_back ( trend_var_symb_id ) ;
2018-08-31 12:35:51 +02:00
}
2018-08-23 13:56:58 +02:00
}
2018-09-03 15:05:30 +02:00
2018-08-23 13:56:58 +02:00
rhsr [ it . first ] = rhs ;
2018-09-03 15:05:30 +02:00
if ( i = = 1 )
trend_varr [ it . first ] = trend_var ;
2018-08-23 13:56:58 +02:00
}
if ( i = = 0 )
var_model_table . setRhs ( rhsr ) ;
else if ( i = = 1 )
2018-08-31 12:35:51 +02:00
{
trend_component_model_table . setRhs ( rhsr ) ;
2018-09-13 12:21:23 +02:00
trend_component_model_table . setTargetVar ( trend_varr ) ;
2018-08-31 12:35:51 +02:00
}
2018-08-23 13:56:58 +02:00
}
}
2018-08-21 11:46:59 +02:00
void
DynamicModel : : fillVarModelTable ( ) const
{
map < string , vector < int > > eqnums , lhsr ;
map < string , vector < expr_t > > lhs_expr_tr ;
map < string , vector < set < pair < int , int > > > > rhsr ;
map < string , vector < string > > eqtags = var_model_table . getEqTags ( ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : eqtags )
2018-08-21 11:46:59 +02:00
{
vector < int > eqnumber , lhs ;
vector < expr_t > lhs_expr_t ;
vector < set < pair < int , int > > > rhs ;
2019-12-20 16:59:30 +01:00
for ( const auto & eqtag : it . second )
2018-08-21 11:46:59 +02:00
{
set < pair < int , int > > lhs_set , lhs_tmp_set , rhs_set ;
2020-02-20 15:29:10 +01:00
int eqn = equation_tags . getEqnByTag ( " name " , eqtag ) ;
2018-08-21 11:46:59 +02:00
if ( eqn = = - 1 )
{
cerr < < " ERROR: equation tag ' " < < eqtag < < " ' not found " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhs_set ) ;
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : exogenous , lhs_tmp_set ) ;
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : parameter , lhs_tmp_set ) ;
2018-08-21 11:46:59 +02:00
if ( lhs_set . size ( ) ! = 1 | | ! lhs_tmp_set . empty ( ) )
{
cerr < < " ERROR: in Equation " < < eqtag
< < " . A VAR may only have one endogenous variable on the LHS. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-08-23 13:03:52 +02:00
auto itlhs = lhs_set . begin ( ) ;
if ( itlhs - > second ! = 0 )
2018-08-21 11:46:59 +02:00
{
cerr < < " ERROR: in Equation " < < eqtag
< < " . The variable on the LHS of a VAR may not appear with a lead or a lag. "
< < endl ;
exit ( EXIT_FAILURE ) ;
}
eqnumber . push_back ( eqn ) ;
2018-08-23 13:03:52 +02:00
lhs . push_back ( itlhs - > first ) ;
2018-08-21 11:46:59 +02:00
lhs_set . clear ( ) ;
set < expr_t > lhs_expr_t_set ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectVARLHSVariable ( lhs_expr_t_set ) ;
2018-08-21 11:46:59 +02:00
lhs_expr_t . push_back ( * ( lhs_expr_t_set . begin ( ) ) ) ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg2 - > collectDynamicVariables ( SymbolType : : endogenous , rhs_set ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & itrhs : rhs_set )
2018-08-23 13:03:52 +02:00
if ( itrhs . second > 0 )
2018-08-21 11:46:59 +02:00
{
cerr < < " ERROR: in Equation " < < eqtag
< < " . A VAR may not have leaded or contemporaneous variables on the RHS. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
rhs . push_back ( rhs_set ) ;
}
eqnums [ it . first ] = eqnumber ;
lhsr [ it . first ] = lhs ;
lhs_expr_tr [ it . first ] = lhs_expr_t ;
rhsr [ it . first ] = rhs ;
}
var_model_table . setEqNums ( eqnums ) ;
var_model_table . setLhs ( lhsr ) ;
var_model_table . setRhs ( rhsr ) ;
var_model_table . setLhsExprT ( lhs_expr_tr ) ;
2018-09-25 15:47:52 +02:00
// Fill AR Matrix
2019-03-15 12:27:32 +01:00
var_model_table . setAR ( fillAutoregressiveMatrix ( true ) ) ;
2018-08-21 11:46:59 +02:00
}
void
2019-10-22 16:04:24 +02:00
DynamicModel : : fillVarModelTableFromOrigModel ( ) const
2018-08-21 11:46:59 +02:00
{
map < string , vector < int > > lags , orig_diff_var ;
map < string , vector < bool > > diff ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : var_model_table . getEqNums ( ) )
2018-08-21 11:46:59 +02:00
{
set < expr_t > lhs ;
vector < int > orig_diff_var_vec ;
vector < bool > diff_vec ;
for ( auto eqn : it . second )
{
// ensure no leads in equations
2018-11-28 14:32:26 +01:00
if ( equations [ eqn ] - > arg2 - > VarMinLag ( ) < = 0 )
2018-08-21 11:46:59 +02:00
{
cerr < < " ERROR in VAR model Equation (# " < < eqn < < " ). "
< < " Leaded exogenous variables "
< < " and leaded or contemporaneous endogenous variables not allowed in VAR "
< < endl ;
exit ( EXIT_FAILURE ) ;
}
// save lhs variables
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectVARLHSVariable ( lhs ) ;
2018-08-21 11:46:59 +02:00
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > countDiffs ( ) > 0 ?
2018-08-21 11:46:59 +02:00
diff_vec . push_back ( true ) : diff_vec . push_back ( false ) ;
if ( diff_vec . back ( ) )
{
set < pair < int , int > > diff_set ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , diff_set ) ;
2018-08-21 11:46:59 +02:00
if ( diff_set . size ( ) ! = 1 )
{
cerr < < " ERROR: problem getting variable for LHS diff operator in equation "
< < eqn < < endl ;
exit ( EXIT_FAILURE ) ;
}
orig_diff_var_vec . push_back ( diff_set . begin ( ) - > first ) ;
}
else
orig_diff_var_vec . push_back ( - 1 ) ;
}
if ( it . second . size ( ) ! = lhs . size ( ) )
{
cerr < < " ERROR: The LHS variables of the VAR model are not unique " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-10-22 16:04:24 +02:00
set < expr_t > lhs_lag_equiv ;
2019-12-20 16:59:30 +01:00
for ( const auto & lh : lhs )
2019-10-22 16:04:24 +02:00
{
auto [ lag_equiv_repr , index ] = lh - > getLagEquivalenceClass ( ) ;
lhs_lag_equiv . insert ( lag_equiv_repr ) ;
}
2018-08-21 11:46:59 +02:00
vector < int > max_lag ;
for ( auto eqn : it . second )
2019-10-22 16:04:24 +02:00
max_lag . push_back ( equations [ eqn ] - > arg2 - > VarMaxLag ( lhs_lag_equiv ) ) ;
2018-08-21 11:46:59 +02:00
lags [ it . first ] = max_lag ;
diff [ it . first ] = diff_vec ;
orig_diff_var [ it . first ] = orig_diff_var_vec ;
}
var_model_table . setDiff ( diff ) ;
var_model_table . setMaxLags ( lags ) ;
var_model_table . setOrigDiffVar ( orig_diff_var ) ;
2018-09-06 17:53:07 +02:00
}
2019-03-14 17:20:45 +01:00
map < string , map < tuple < int , int , int > , expr_t > >
2019-03-15 12:27:32 +01:00
DynamicModel : : fillAutoregressiveMatrix ( bool is_var ) const
2019-03-14 17:20:45 +01:00
{
map < string , map < tuple < int , int , int > , expr_t > > ARr ;
2019-03-15 12:27:32 +01:00
auto eqnums = is_var ?
var_model_table . getEqNums ( ) : trend_component_model_table . getNonTargetEqNums ( ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : eqnums )
2019-03-14 17:20:45 +01:00
{
int i = 0 ;
map < tuple < int , int , int > , expr_t > AR ;
2019-03-15 12:27:32 +01:00
vector < int > lhs = is_var ?
var_model_table . getLhsOrigIds ( it . first ) : trend_component_model_table . getNonTargetLhs ( it . first ) ;
2019-03-14 17:20:45 +01:00
for ( auto eqn : it . second )
{
2019-12-16 19:42:59 +01:00
auto bopn = dynamic_cast < BinaryOpNode * > ( equations [ eqn ] - > arg2 ) ;
2019-03-15 12:27:32 +01:00
bopn - > fillAutoregressiveRow ( i + + , lhs , AR ) ;
2019-03-14 17:20:45 +01:00
}
ARr [ it . first ] = AR ;
}
return ARr ;
}
2016-11-18 16:52:13 +01:00
void
2018-08-14 14:23:21 +02:00
DynamicModel : : fillTrendComponentModelTable ( ) const
2018-01-30 16:33:16 +01:00
{
2018-08-14 14:23:21 +02:00
map < string , vector < int > > eqnums , trend_eqnums , lhsr ;
map < string , vector < expr_t > > lhs_expr_tr ;
map < string , vector < set < pair < int , int > > > > rhsr ;
map < string , vector < string > > eqtags = trend_component_model_table . getEqTags ( ) ;
2018-09-13 12:21:23 +02:00
map < string , vector < string > > trend_eqtags = trend_component_model_table . getTargetEqTags ( ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : trend_eqtags )
2018-01-30 16:33:16 +01:00
{
2018-08-14 14:23:21 +02:00
vector < int > trend_eqnumber ;
2019-12-20 16:59:30 +01:00
for ( const auto & eqtag : it . second )
2018-01-30 16:33:16 +01:00
{
2020-02-20 15:29:10 +01:00
int eqn = equation_tags . getEqnByTag ( " name " , eqtag ) ;
2018-08-14 14:23:21 +02:00
if ( eqn = = - 1 )
{
cerr < < " ERROR: trend equation tag ' " < < eqtag < < " ' not found " < < endl ;
exit ( EXIT_FAILURE ) ;
}
trend_eqnumber . push_back ( eqn ) ;
2018-02-08 13:07:15 +01:00
}
2018-08-14 14:23:21 +02:00
trend_eqnums [ it . first ] = trend_eqnumber ;
}
2018-01-30 16:33:16 +01:00
2019-12-20 16:59:30 +01:00
for ( const auto & it : eqtags )
2018-08-14 14:23:21 +02:00
{
vector < int > eqnumber , lhs ;
vector < expr_t > lhs_expr_t ;
vector < set < pair < int , int > > > rhs ;
2019-12-20 16:59:30 +01:00
for ( const auto & eqtag : it . second )
2018-08-14 14:23:21 +02:00
{
set < pair < int , int > > lhs_set , lhs_tmp_set , rhs_set ;
2020-02-20 15:29:10 +01:00
int eqn = equation_tags . getEqnByTag ( " name " , eqtag ) ;
2018-08-14 14:23:21 +02:00
if ( eqn = = - 1 )
2018-01-30 16:33:16 +01:00
{
2018-08-14 14:23:21 +02:00
cerr < < " ERROR: equation tag ' " < < eqtag < < " ' not found " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-01-30 16:33:16 +01:00
}
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhs_set ) ;
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : exogenous , lhs_tmp_set ) ;
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : parameter , lhs_tmp_set ) ;
2018-01-30 16:33:16 +01:00
2018-08-14 14:23:21 +02:00
if ( lhs_set . size ( ) ! = 1 | | ! lhs_tmp_set . empty ( ) )
{
cerr < < " ERROR: in Equation " < < eqtag
2018-09-17 14:34:25 +02:00
< < " . A trend component model may only have one endogenous variable on the LHS. " < < endl ;
2018-08-14 14:23:21 +02:00
exit ( EXIT_FAILURE ) ;
}
2018-08-23 13:03:52 +02:00
auto itlhs = lhs_set . begin ( ) ;
if ( itlhs - > second ! = 0 )
2018-08-14 14:23:21 +02:00
{
cerr < < " ERROR: in Equation " < < eqtag
2018-08-21 11:46:59 +02:00
< < " . The variable on the LHS of a trend component model may not appear with a lead or a lag. "
2018-08-14 14:23:21 +02:00
< < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-01-30 16:33:16 +01:00
2018-08-14 14:23:21 +02:00
eqnumber . push_back ( eqn ) ;
2018-08-23 13:03:52 +02:00
lhs . push_back ( itlhs - > first ) ;
2018-08-14 14:23:21 +02:00
lhs_set . clear ( ) ;
set < expr_t > lhs_expr_t_set ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectVARLHSVariable ( lhs_expr_t_set ) ;
2018-08-14 14:23:21 +02:00
lhs_expr_t . push_back ( * ( lhs_expr_t_set . begin ( ) ) ) ;
2018-02-08 13:07:15 +01:00
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg2 - > collectDynamicVariables ( SymbolType : : endogenous , rhs_set ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & itrhs : rhs_set )
2018-08-23 13:03:52 +02:00
if ( itrhs . second > 0 )
2018-08-14 14:23:21 +02:00
{
cerr < < " ERROR: in Equation " < < eqtag
2018-08-21 11:46:59 +02:00
< < " . A trend component model may not have leaded or contemporaneous variables on the RHS. " < < endl ;
2018-08-14 14:23:21 +02:00
exit ( EXIT_FAILURE ) ;
}
rhs . push_back ( rhs_set ) ;
}
eqnums [ it . first ] = eqnumber ;
lhsr [ it . first ] = lhs ;
lhs_expr_tr [ it . first ] = lhs_expr_t ;
rhsr [ it . first ] = rhs ;
2018-02-08 13:07:15 +01:00
}
2018-08-14 14:23:21 +02:00
trend_component_model_table . setRhs ( rhsr ) ;
2018-10-24 15:57:07 +02:00
trend_component_model_table . setVals ( eqnums , trend_eqnums , lhsr , lhs_expr_tr ) ;
2018-09-10 17:13:51 +02:00
}
2019-08-19 14:51:21 +02:00
pair < map < string , map < tuple < int , int , int > , expr_t > > , map < string , map < tuple < int , int , int > , expr_t > > >
DynamicModel : : fillErrorComponentMatrix ( const ExprNode : : subst_table_t & diff_subst_table ) const
2018-09-10 17:13:51 +02:00
{
2019-08-19 14:51:21 +02:00
map < string , map < tuple < int , int , int > , expr_t > > A0r , A0starr ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : trend_component_model_table . getEqNums ( ) )
2018-09-10 17:13:51 +02:00
{
int i = 0 ;
2019-02-19 12:08:00 +01:00
map < tuple < int , int , int > , expr_t > A0 , A0star ;
2019-02-14 11:44:06 +01:00
vector < int > target_lhs = trend_component_model_table . getTargetLhs ( it . first ) ;
vector < int > nontarget_eqnums = trend_component_model_table . getNonTargetEqNums ( it . first ) ;
vector < int > undiff_nontarget_lhs = getUndiffLHSForPac ( it . first , diff_subst_table ) ;
vector < int > parsed_undiff_nontarget_lhs ;
2018-09-12 17:56:30 +02:00
for ( auto eqn : it . second )
{
2019-02-14 11:44:06 +01:00
if ( find ( nontarget_eqnums . begin ( ) , nontarget_eqnums . end ( ) , eqn ) ! = nontarget_eqnums . end ( ) )
parsed_undiff_nontarget_lhs . push_back ( undiff_nontarget_lhs . at ( i ) ) ;
2018-09-12 17:56:30 +02:00
i + + ;
}
i = 0 ;
2018-09-10 17:13:51 +02:00
for ( auto eqn : it . second )
2019-02-14 11:44:06 +01:00
if ( find ( nontarget_eqnums . begin ( ) , nontarget_eqnums . end ( ) , eqn ) ! = nontarget_eqnums . end ( ) )
2019-02-19 12:08:00 +01:00
equations [ eqn ] - > arg2 - > fillErrorCorrectionRow ( i + + , parsed_undiff_nontarget_lhs , target_lhs , A0 , A0star ) ;
A0r [ it . first ] = A0 ;
A0starr [ it . first ] = A0star ;
2018-09-10 17:13:51 +02:00
}
2019-08-19 14:51:21 +02:00
return { A0r , A0starr } ;
2018-02-08 13:07:15 +01:00
}
2018-05-16 12:17:06 +02:00
void
2019-10-22 16:04:24 +02:00
DynamicModel : : fillTrendComponentModelTableFromOrigModel ( ) const
2018-05-16 12:17:06 +02:00
{
2018-08-14 14:23:21 +02:00
map < string , vector < int > > lags , orig_diff_var ;
map < string , vector < bool > > diff ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : trend_component_model_table . getEqNums ( ) )
2018-05-16 12:17:06 +02:00
{
2018-08-14 14:23:21 +02:00
set < expr_t > lhs ;
vector < int > orig_diff_var_vec ;
vector < bool > diff_vec ;
for ( auto eqn : it . second )
2018-05-16 12:17:06 +02:00
{
2018-08-14 14:23:21 +02:00
// ensure no leads in equations
2018-11-28 14:32:26 +01:00
if ( equations [ eqn ] - > arg2 - > VarMinLag ( ) < = 0 )
2018-08-14 14:23:21 +02:00
{
2018-08-21 11:46:59 +02:00
cerr < < " ERROR in trend component model Equation (# " < < eqn < < " ). "
2018-08-14 14:23:21 +02:00
< < " Leaded exogenous variables "
< < " and leaded or contemporaneous endogenous variables not allowed in VAR "
< < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-05-31 15:34:25 +02:00
2018-08-14 14:23:21 +02:00
// save lhs variables
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectVARLHSVariable ( lhs ) ;
2018-04-16 13:50:31 +02:00
2019-12-16 19:42:59 +01:00
if ( equations [ eqn ] - > arg1 - > countDiffs ( ) > 0 )
diff_vec . push_back ( true ) ;
else
diff_vec . push_back ( false ) ;
2018-08-14 14:23:21 +02:00
if ( diff_vec . back ( ) )
{
set < pair < int , int > > diff_set ;
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , diff_set ) ;
2018-04-16 13:50:31 +02:00
2018-08-14 14:23:21 +02:00
if ( diff_set . size ( ) ! = 1 )
{
cerr < < " ERROR: problem getting variable for LHS diff operator in equation "
< < eqn < < endl ;
exit ( EXIT_FAILURE ) ;
}
orig_diff_var_vec . push_back ( diff_set . begin ( ) - > first ) ;
}
else
orig_diff_var_vec . push_back ( - 1 ) ;
2018-04-16 13:50:31 +02:00
2018-08-14 14:23:21 +02:00
}
2018-04-16 13:50:31 +02:00
2018-08-14 14:23:21 +02:00
if ( it . second . size ( ) ! = lhs . size ( ) )
2018-02-08 13:07:15 +01:00
{
2018-08-21 11:46:59 +02:00
cerr < < " ERROR: The LHS variables of the trend component model are not unique " < < endl ;
2018-08-14 14:23:21 +02:00
exit ( EXIT_FAILURE ) ;
2018-02-08 13:07:15 +01:00
}
2018-08-14 14:23:21 +02:00
2019-10-22 16:04:24 +02:00
set < expr_t > lhs_lag_equiv ;
2019-12-20 16:59:30 +01:00
for ( const auto & lh : lhs )
2019-10-22 16:04:24 +02:00
{
auto [ lag_equiv_repr , index ] = lh - > getLagEquivalenceClass ( ) ;
lhs_lag_equiv . insert ( lag_equiv_repr ) ;
}
2018-08-14 14:23:21 +02:00
vector < int > max_lag ;
for ( auto eqn : it . second )
2019-10-22 16:04:24 +02:00
max_lag . push_back ( equations [ eqn ] - > arg2 - > VarMaxLag ( lhs_lag_equiv ) ) ;
2018-08-14 14:23:21 +02:00
lags [ it . first ] = max_lag ;
diff [ it . first ] = diff_vec ;
orig_diff_var [ it . first ] = orig_diff_var_vec ;
2018-01-30 16:33:16 +01:00
}
2018-08-14 14:23:21 +02:00
trend_component_model_table . setDiff ( diff ) ;
trend_component_model_table . setMaxLags ( lags ) ;
trend_component_model_table . setOrigDiffVar ( orig_diff_var ) ;
2018-01-30 16:33:16 +01:00
}
2018-08-21 11:46:59 +02:00
2018-09-12 17:56:30 +02:00
void
2019-08-19 14:51:21 +02:00
DynamicModel : : fillTrendComponentmodelTableAREC ( const ExprNode : : subst_table_t & diff_subst_table ) const
2018-09-12 17:56:30 +02:00
{
2019-08-19 14:51:21 +02:00
auto ARr = fillAutoregressiveMatrix ( false ) ;
2018-09-12 17:56:30 +02:00
trend_component_model_table . setAR ( ARr ) ;
2019-09-11 15:59:23 +02:00
auto [ A0r , A0starr ] = fillErrorComponentMatrix ( diff_subst_table ) ;
2019-02-19 12:08:00 +01:00
trend_component_model_table . setA0 ( A0r , A0starr ) ;
2018-09-12 17:56:30 +02:00
}
2016-11-25 17:15:13 +01:00
void
2018-08-21 11:46:59 +02:00
DynamicModel : : addEquationsForVar ( )
2016-11-25 17:15:13 +01:00
{
2018-08-21 11:46:59 +02:00
if ( var_model_table . empty ( ) )
return ;
2019-12-16 19:42:59 +01:00
auto var_symbol_list_and_order = var_model_table . getSymbolListAndOrder ( ) ;
2018-08-21 11:46:59 +02:00
2016-11-25 17:15:13 +01:00
// List of endogenous variables and the minimum lag value that must exist in the model equations
map < string , int > var_endos_and_lags , model_endos_and_lags ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : var_symbol_list_and_order )
for ( auto & equation : equations )
2018-08-21 11:46:59 +02:00
if ( equation - > isVarModelReferenced ( it . first ) )
2016-11-25 17:15:13 +01:00
{
2018-08-21 11:46:59 +02:00
vector < string > symbol_list = it . second . first . get_symbols ( ) ;
int order = it . second . second ;
2019-12-20 16:59:30 +01:00
for ( auto & it1 : symbol_list )
2016-11-25 17:15:13 +01:00
if ( order > 2 )
2019-12-16 19:42:59 +01:00
if ( var_endos_and_lags . find ( it1 ) ! = var_endos_and_lags . end ( ) )
var_endos_and_lags [ it1 ] = min ( var_endos_and_lags [ it1 ] , - order ) ;
2016-11-25 17:15:13 +01:00
else
2019-12-16 19:42:59 +01:00
var_endos_and_lags [ it1 ] = - order ;
2016-11-25 17:15:13 +01:00
break ;
}
if ( var_endos_and_lags . empty ( ) )
return ;
2018-08-21 11:46:59 +02:00
// Ensure that the minimum lag value exists in the model equations.
// If not, add an equation for it
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-06-04 12:26:16 +02:00
equation - > getEndosAndMaxLags ( model_endos_and_lags ) ;
2016-11-25 17:15:13 +01:00
int count = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & it : var_endos_and_lags )
2019-12-16 19:42:59 +01:00
if ( auto it2 = model_endos_and_lags . find ( it . first ) ;
it2 = = model_endos_and_lags . end ( ) )
cerr < < " WARNING: Variable used in VAR that is not used in the model: " < < it . first < < endl ;
else
if ( it . second < it2 - > second )
{
int symb_id = symbol_table . getID ( it . first ) ;
expr_t newvar = AddVariable ( symb_id , it . second ) ;
expr_t auxvar = AddVariable ( symbol_table . addVarModelEndoLagAuxiliaryVar ( symb_id , it . second , newvar ) , 0 ) ;
addEquation ( AddEqual ( newvar , auxvar ) , - 1 ) ;
addAuxEquation ( AddEqual ( newvar , auxvar ) ) ;
count + + ;
}
2016-11-25 17:15:13 +01:00
if ( count > 0 )
2018-08-21 11:46:59 +02:00
cout < < " Accounting for var_model lags not in model block: added "
< < count < < " auxiliary variables and equations. " < < endl ;
2016-11-25 17:15:13 +01:00
}
2018-08-21 11:46:59 +02:00
2018-08-14 14:23:21 +02:00
vector < int >
DynamicModel : : getUndiffLHSForPac ( const string & aux_model_name ,
2019-08-19 14:51:21 +02:00
const ExprNode : : subst_table_t & diff_subst_table ) const
2018-03-28 18:46:15 +02:00
{
2018-08-14 14:23:21 +02:00
vector < expr_t > lhs_expr_t = trend_component_model_table . getLhsExprT ( aux_model_name ) ;
vector < int > lhs = trend_component_model_table . getLhs ( aux_model_name ) ;
vector < bool > diff = trend_component_model_table . getDiff ( aux_model_name ) ;
vector < int > orig_diff_var = trend_component_model_table . getOrigDiffVar ( aux_model_name ) ;
vector < int > eqnumber = trend_component_model_table . getEqNums ( aux_model_name ) ;
2018-09-13 12:21:23 +02:00
vector < int > nontrend_eqnums = trend_component_model_table . getNonTargetEqNums ( aux_model_name ) ;
2018-08-14 14:23:21 +02:00
for ( auto eqn : nontrend_eqnums )
2018-03-28 18:46:15 +02:00
{
int i = 0 ;
2019-12-16 19:42:59 +01:00
for ( auto it1 = eqnumber . begin ( ) ; it1 ! = eqnumber . end ( ) ; + + it1 , i + + )
2018-04-17 15:17:28 +02:00
if ( * it1 = = eqn )
break ;
2018-03-28 18:46:15 +02:00
2018-04-17 15:17:28 +02:00
if ( eqnumber [ i ] ! = eqn )
2018-03-28 18:46:15 +02:00
{
2018-05-28 15:54:20 +02:00
cerr < < " ERROR: equation " < < eqn < < " not found in VAR " < < endl ;
2018-03-28 18:46:15 +02:00
exit ( EXIT_FAILURE ) ;
}
2018-05-28 15:55:01 +02:00
if ( diff . at ( i ) ! = true )
2018-03-28 18:46:15 +02:00
{
2018-08-14 14:23:21 +02:00
cerr < < " ERROR: the variable on the LHS of equation # " < < eqn
< < " does not have the diff operator applied to it yet you are trying to undiff it. "
< < endl ;
2018-03-28 18:46:15 +02:00
exit ( EXIT_FAILURE ) ;
}
2018-04-17 15:17:28 +02:00
bool printerr = false ;
2018-06-04 12:52:14 +02:00
expr_t node = nullptr ;
2018-04-17 15:17:28 +02:00
expr_t aux_var = lhs_expr_t . at ( i ) ;
2019-12-16 19:42:59 +01:00
for ( const auto & it : diff_subst_table )
if ( it . second = = aux_var )
2018-04-17 15:17:28 +02:00
{
2019-12-16 19:42:59 +01:00
node = const_cast < expr_t > ( it . first ) ;
2018-04-17 15:17:28 +02:00
break ;
}
2019-12-16 19:42:59 +01:00
if ( ! node )
2018-04-17 15:17:28 +02:00
{
cerr < < " Unexpected error encountered. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-08-14 14:23:21 +02:00
node = node - > undiff ( ) ;
2019-12-16 19:42:59 +01:00
auto it1 = diff_subst_table . find ( node ) ;
2018-08-14 14:23:21 +02:00
if ( it1 = = diff_subst_table . end ( ) )
printerr = true ;
2018-04-17 15:17:28 +02:00
if ( printerr )
{ // we have undiffed something like diff(x), hence x is not in diff_subst_table
lhs_expr_t . at ( i ) = node ;
2018-11-28 14:32:26 +01:00
lhs . at ( i ) = dynamic_cast < VariableNode * > ( node ) - > symb_id ;
2018-04-17 15:17:28 +02:00
}
else
{
lhs_expr_t . at ( i ) = const_cast < expr_t > ( it1 - > first ) ;
2018-11-28 14:32:26 +01:00
lhs . at ( i ) = const_cast < VariableNode * > ( it1 - > second ) - > symb_id ;
2018-04-17 15:17:28 +02:00
}
2018-03-28 18:46:15 +02:00
}
2018-08-14 14:23:21 +02:00
return lhs ;
2018-03-28 18:46:15 +02:00
}
2019-08-19 14:51:21 +02:00
map < pair < string , string > , pair < string , int > >
DynamicModel : : walkPacParameters ( const string & name )
2018-02-12 17:37:53 +01:00
{
2019-08-19 14:51:21 +02:00
map < pair < string , string > , pair < string , int > > eqtag_and_lag ;
2019-02-19 16:36:10 +01:00
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-02-12 17:37:53 +01:00
{
2019-12-16 19:42:59 +01:00
pair < int , int > lhs ( - 1 , - 1 ) ;
2019-03-07 11:31:36 +01:00
pair < int , vector < tuple < int , bool , int > > > ec_params_and_vars ;
2020-09-11 16:45:19 +02:00
vector < tuple < int , int , int > > ar_params_and_vars ;
2019-03-07 12:35:30 +01:00
vector < tuple < int , int , int , double > > non_optim_vars_params_and_constants , optim_additive_vars_params_and_constants , additive_vars_params_and_constants ;
2018-08-09 16:14:40 +02:00
2020-07-22 12:16:38 +02:00
if ( equation - > containsPacExpectation ( name ) )
2018-08-09 16:14:40 +02:00
{
2019-02-20 12:59:55 +01:00
set < pair < int , int > > lhss ;
equation - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhss ) ;
2019-12-16 19:42:59 +01:00
lhs = * lhss . begin ( ) ;
2019-02-27 23:12:05 +01:00
int lhs_symb_id = lhs . first ;
int lhs_orig_symb_id = lhs_symb_id ;
2018-09-04 10:39:05 +02:00
if ( symbol_table . isAuxiliaryVariable ( lhs_orig_symb_id ) )
try
{
lhs_orig_symb_id = symbol_table . getOrigSymbIdForAuxVar ( lhs_orig_symb_id ) ;
}
catch ( . . . )
{
}
2019-02-27 23:12:05 +01:00
auto arg2 = dynamic_cast < BinaryOpNode * > ( equation - > arg2 ) ;
2019-12-16 19:42:59 +01:00
if ( ! arg2 )
2019-02-27 23:12:05 +01:00
{
cerr < < " Pac equation in incorrect format " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-12-20 16:59:30 +01:00
auto [ optim_share_index , optim_part , non_optim_part , additive_part ]
= arg2 - > getPacOptimizingShareAndExprNodes ( lhs_symb_id , lhs_orig_symb_id ) ;
2019-02-27 23:12:05 +01:00
2019-12-16 19:42:59 +01:00
if ( ! optim_part )
2019-03-05 10:57:15 +01:00
{
auto bopn = dynamic_cast < BinaryOpNode * > ( equation - > arg2 ) ;
2019-12-16 19:42:59 +01:00
if ( ! bopn )
2019-03-05 10:57:15 +01:00
{
cerr < < " Error in PAC equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
bopn - > getPacAREC ( lhs_symb_id , lhs_orig_symb_id , ec_params_and_vars , ar_params_and_vars , additive_vars_params_and_constants ) ;
}
2018-08-09 16:14:40 +02:00
else
{
2019-03-05 10:57:15 +01:00
auto bopn = dynamic_cast < BinaryOpNode * > ( optim_part ) ;
2019-12-16 19:42:59 +01:00
if ( ! bopn )
2019-03-05 10:57:15 +01:00
{
cerr < < " Error in PAC equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-03-07 12:57:47 +01:00
bopn - > getPacAREC ( lhs_symb_id , lhs_orig_symb_id , ec_params_and_vars , ar_params_and_vars , optim_additive_vars_params_and_constants ) ;
2018-11-28 17:32:55 +01:00
try
{
non_optim_vars_params_and_constants = non_optim_part - > matchLinearCombinationOfVariables ( ) ;
2019-12-16 19:42:59 +01:00
if ( additive_part )
2019-03-07 12:57:47 +01:00
additive_vars_params_and_constants = additive_part - > matchLinearCombinationOfVariables ( ) ;
2018-11-28 17:32:55 +01:00
}
catch ( ExprNode : : MatchFailureException & e )
{
2019-02-27 23:12:05 +01:00
cerr < < " Error in parsing non-optimizing agents or additive part of PAC equation: "
2018-11-28 17:32:55 +01:00
< < e . message < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-08-09 16:14:40 +02:00
}
2019-02-19 16:36:10 +01:00
2020-02-20 15:29:10 +01:00
string eqtag = equation_tags . getTagValueByEqnAndKey ( & equation - & equations [ 0 ] , " name " ) ;
2019-12-16 19:42:59 +01:00
if ( eqtag . empty ( ) )
2019-02-19 16:36:10 +01:00
{
cerr < < " Every equation with a pac expectation must have been assigned an equation tag name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-20 12:59:55 +01:00
if ( lhs . first = = - 1 )
{
2020-02-25 15:20:33 +01:00
cerr < < " walkPacParameters: error obtaining LHS variable. " < < endl ;
2019-02-20 12:59:55 +01:00
exit ( EXIT_FAILURE ) ;
}
2020-09-11 16:45:19 +02:00
if ( ec_params_and_vars . second . empty ( ) )
2019-02-20 12:59:55 +01:00
{
cerr < < " walkPacParameters: error obtaining RHS parameters. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-19 16:36:10 +01:00
string eq = " eq " + to_string ( i + + ) ;
2019-02-21 10:30:25 +01:00
pac_equation_info [ { name , eq } ] = { lhs , optim_share_index ,
ar_params_and_vars , ec_params_and_vars ,
2019-02-27 23:12:05 +01:00
non_optim_vars_params_and_constants ,
2019-03-07 12:35:30 +01:00
additive_vars_params_and_constants ,
optim_additive_vars_params_and_constants } ;
2020-09-11 16:45:19 +02:00
int max_lag = ar_params_and_vars . size ( ) ;
eqtag_and_lag [ { name , eqtag } ] = { eq , max_lag } ;
2018-08-09 16:14:40 +02:00
}
2018-02-12 17:37:53 +01:00
}
2019-08-19 14:51:21 +02:00
return eqtag_and_lag ;
2018-02-12 17:37:53 +01:00
}
2019-02-15 12:52:46 +01:00
int
DynamicModel : : getPacTargetSymbId ( const string & pac_model_name ) const
{
2020-07-23 14:45:32 +02:00
for ( auto equation : equations )
2019-02-15 12:52:46 +01:00
if ( equation - > containsPacExpectation ( pac_model_name ) )
{
2019-02-20 12:59:55 +01:00
set < pair < int , int > > lhss ;
equation - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhss ) ;
2020-07-23 14:45:32 +02:00
if ( lhss . size ( ) ! = 1 )
throw PacTargetNotIdentifiedException { pac_model_name , " LHS must contain a single endogenous " } ;
2020-07-10 14:55:28 +02:00
int lhs_symb_id = lhss . begin ( ) - > first ;
2020-07-23 14:45:32 +02:00
if ( ! symbol_table . isDiffAuxiliaryVariable ( lhs_symb_id ) )
throw PacTargetNotIdentifiedException { pac_model_name , " LHS must be a diff operator " } ;
int undiff_lhs_symb_id = symbol_table . getOrigSymbIdForAuxVar ( lhs_symb_id ) ;
auto barg2 = dynamic_cast < BinaryOpNode * > ( equation - > arg2 ) ;
if ( ! barg2 )
throw PacTargetNotIdentifiedException { pac_model_name , " RHS must be a binary operator " } ;
auto [ optim_share_index , optim_part , non_optim_part , additive_part ]
= barg2 - > getPacOptimizingShareAndExprNodes ( lhs_symb_id , undiff_lhs_symb_id ) ;
/* If there is an optimization part, restrict the search to that part,
since it contains the MCE . */
expr_t mce = optim_part ? optim_part : equation - > arg2 ;
vector < pair < expr_t , int > > terms ;
mce - > decomposeAdditiveTerms ( terms ) ;
for ( auto [ term , sign ] : terms )
2019-02-15 12:52:46 +01:00
try
{
2020-07-23 14:45:32 +02:00
auto [ param_id , target_id ] = term - > matchParamTimesTargetMinusVariable ( undiff_lhs_symb_id ) ;
return target_id ;
2019-02-15 12:52:46 +01:00
}
2020-07-23 14:45:32 +02:00
catch ( ExprNode : : MatchFailureException & )
2019-02-15 12:52:46 +01:00
{
}
2020-07-23 14:45:32 +02:00
throw PacTargetNotIdentifiedException { pac_model_name , " No term of the form parameter*(target-LHS_level) " } ;
2019-02-15 12:52:46 +01:00
}
2020-07-23 14:45:32 +02:00
throw PacTargetNotIdentifiedException { pac_model_name , " No equation with the corresponding pac_expectation operator " } ;
2019-02-15 12:52:46 +01:00
}
2019-02-25 15:29:46 +01:00
void
DynamicModel : : declarePacModelConsistentExpectationEndogs ( const string & name )
{
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2020-07-22 12:16:38 +02:00
if ( equation - > containsPacExpectation ( name ) )
2019-02-25 15:29:46 +01:00
{
2020-02-20 15:29:10 +01:00
if ( ! equation_tags . exists ( & equation - & equations [ 0 ] , " name " ) )
2019-02-25 15:29:46 +01:00
{
cerr < < " Every equation with a pac expectation must have been assigned an equation tag name " < < endl ;
exit ( EXIT_FAILURE ) ;
}
string standard_eqtag = " eq " + to_string ( i + + ) ;
try
{
2019-12-20 16:59:30 +01:00
pac_mce_z1_symb_ids [ { name , standard_eqtag } ]
= symbol_table . addSymbol ( " mce_Z1_ " + name + " _ " + standard_eqtag , SymbolType : : endogenous ) ;
2019-02-25 15:29:46 +01:00
}
catch ( SymbolTable : : AlreadyDeclaredException & e )
{
cerr < < " Variable name needed by PAC (mce_Z1_ " < < name < < " _ " < < standard_eqtag < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
}
2019-02-19 16:36:10 +01:00
void
2019-12-20 16:59:30 +01:00
DynamicModel : : addPacModelConsistentExpectationEquation ( const string & name , int discount_symb_id ,
2019-02-20 12:59:55 +01:00
const map < pair < string , string > , pair < string , int > > & eqtag_and_lag ,
2019-02-15 12:52:46 +01:00
ExprNode : : subst_table_t & diff_subst_table )
{
2020-07-23 14:45:32 +02:00
int pac_target_symb_id ;
try
{
pac_target_symb_id = getPacTargetSymbId ( name ) ;
}
catch ( PacTargetNotIdentifiedException & e )
{
cerr < < " Can't identify target for PAC model " < < name < < " : " < < e . message ;
exit ( EXIT_FAILURE ) ;
}
2019-02-19 16:36:10 +01:00
pac_eqtag_and_lag . insert ( eqtag_and_lag . begin ( ) , eqtag_and_lag . end ( ) ) ;
int neqs = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & it : eqtag_and_lag )
2019-02-15 12:52:46 +01:00
{
2020-07-22 12:16:38 +02:00
assert ( it . first . first = = name ) ;
2019-02-20 12:59:55 +01:00
string eqtag = it . first . second ;
string standard_eqtag = it . second . first ;
2019-02-25 10:48:53 +01:00
int pac_max_lag_m = it . second . second + 1 ;
2019-02-20 12:59:55 +01:00
string append_to_name = name + " _ " + standard_eqtag ;
2019-02-25 15:29:46 +01:00
if ( pac_mce_z1_symb_ids . find ( { name , standard_eqtag } ) = = pac_mce_z1_symb_ids . end ( ) )
2019-02-19 16:36:10 +01:00
{
2019-02-25 15:29:46 +01:00
cerr < < " Error finding pac MCE Z1 symb id " < < endl ;
2019-02-19 16:36:10 +01:00
exit ( EXIT_FAILURE ) ;
}
2019-02-25 15:29:46 +01:00
int mce_z1_symb_id = pac_mce_z1_symb_ids [ { name , standard_eqtag } ] ;
2019-02-15 12:52:46 +01:00
2019-02-19 16:36:10 +01:00
expr_t A = One ;
expr_t fp = Zero ;
expr_t beta = AddVariable ( discount_symb_id ) ;
for ( int i = 1 ; i < = pac_max_lag_m ; i + + )
try
{
int alpha_i_symb_id = symbol_table . addSymbol ( " mce_alpha_ " + append_to_name + " _ " + to_string ( i ) ,
SymbolType : : parameter ) ;
2019-02-21 10:30:25 +01:00
pac_mce_alpha_symb_ids [ { name , standard_eqtag } ] . push_back ( alpha_i_symb_id ) ;
2019-02-19 16:36:10 +01:00
A = AddPlus ( A , AddVariable ( alpha_i_symb_id ) ) ;
fp = AddPlus ( fp ,
AddTimes ( AddTimes ( AddVariable ( alpha_i_symb_id ) ,
AddPower ( beta , AddPossiblyNegativeConstant ( i ) ) ) ,
AddVariable ( mce_z1_symb_id , i ) ) ) ;
2019-02-15 12:52:46 +01:00
2019-02-19 16:36:10 +01:00
}
catch ( SymbolTable : : AlreadyDeclaredException & e )
{
cerr < < " Variable name needed by PAC (mce_alpha_ " < < append_to_name < < " _ " < < i < < " ) " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-15 12:52:46 +01:00
2019-02-19 16:36:10 +01:00
// Add diff nodes and eqs for pac_target_symb_id
const VariableNode * target_base_diff_node ;
2020-07-24 12:28:13 +02:00
auto create_target_lag = [ & ] ( int lag )
{
if ( symbol_table . isAuxiliaryVariable ( pac_target_symb_id ) )
{
// We know it is a log, see ExprNode::matchParamTimesTargetMinusVariable()
/* We don’ t use SymbolTable::getOrigSymbIdForAuxVar(), because it
does not work for unary ops , and changing this behaviour might
break stuff that relies on an exception in this case . */
auto avi = symbol_table . getAuxVarInfo ( pac_target_symb_id ) ;
return AddLog ( AddVariable ( avi . get_orig_symb_id ( ) , lag ) ) ;
}
else
return dynamic_cast < ExprNode * > ( AddVariable ( pac_target_symb_id , lag ) ) ;
} ;
expr_t diff_node_to_search = AddDiff ( create_target_lag ( 0 ) ) ;
2019-12-16 19:42:59 +01:00
if ( auto sit = diff_subst_table . find ( diff_node_to_search ) ;
sit ! = diff_subst_table . end ( ) )
2019-02-19 16:36:10 +01:00
target_base_diff_node = sit - > second ;
else
{
int symb_id = symbol_table . addDiffAuxiliaryVar ( diff_node_to_search - > idx , diff_node_to_search ) ;
target_base_diff_node = AddVariable ( symb_id ) ;
2020-07-08 18:46:34 +02:00
auto neweq = AddEqual ( const_cast < VariableNode * > ( target_base_diff_node ) ,
2020-07-24 12:28:13 +02:00
AddMinus ( create_target_lag ( 0 ) ,
create_target_lag ( - 1 ) ) ) ;
2020-07-08 18:46:34 +02:00
addEquation ( neweq , - 1 ) ;
addAuxEquation ( neweq ) ;
2019-02-19 16:36:10 +01:00
neqs + + ;
}
2019-02-15 12:52:46 +01:00
2019-02-19 16:36:10 +01:00
map < int , VariableNode * > target_aux_var_to_add ;
const VariableNode * last_aux_var = target_base_diff_node ;
for ( int i = 1 ; i < = pac_max_lag_m - 1 ; i + + , neqs + + )
{
2020-07-24 12:28:13 +02:00
expr_t this_diff_node = AddDiff ( create_target_lag ( i ) ) ;
2019-02-19 16:36:10 +01:00
int symb_id = symbol_table . addDiffLeadAuxiliaryVar ( this_diff_node - > idx , this_diff_node ,
last_aux_var - > symb_id , last_aux_var - > lag ) ;
VariableNode * current_aux_var = AddVariable ( symb_id ) ;
2020-07-08 18:46:34 +02:00
auto neweq = AddEqual ( current_aux_var , AddVariable ( last_aux_var - > symb_id , 1 ) ) ;
addEquation ( neweq , - 1 ) ;
addAuxEquation ( neweq ) ;
2019-02-19 16:36:10 +01:00
last_aux_var = current_aux_var ;
target_aux_var_to_add [ i ] = current_aux_var ;
}
2019-02-15 12:52:46 +01:00
2019-02-19 16:36:10 +01:00
expr_t fs = Zero ;
for ( int k = 1 ; k < = pac_max_lag_m - 1 ; k + + )
2019-02-15 12:52:46 +01:00
{
2019-02-19 16:36:10 +01:00
expr_t ssum = Zero ;
for ( int j = k + 1 ; j < = pac_max_lag_m ; j + + )
2019-02-15 12:52:46 +01:00
{
2019-02-19 16:36:10 +01:00
int alpha_j_symb_id = - 1 ;
string varname = " mce_alpha_ " + append_to_name + " _ " + to_string ( j ) ;
try
{
alpha_j_symb_id = symbol_table . getID ( varname ) ;
}
catch ( SymbolTable : : UnknownSymbolNameException & e )
{
alpha_j_symb_id = symbol_table . addSymbol ( varname , SymbolType : : parameter ) ;
}
ssum = AddPlus ( ssum ,
AddTimes ( AddVariable ( alpha_j_symb_id ) , AddPower ( beta , AddPossiblyNegativeConstant ( j ) ) ) ) ;
2019-02-15 12:52:46 +01:00
}
2019-02-19 16:36:10 +01:00
fs = AddPlus ( fs , AddTimes ( ssum , target_aux_var_to_add [ k ] ) ) ;
2019-02-15 12:52:46 +01:00
}
2020-07-08 18:46:34 +02:00
auto neweq = AddEqual ( AddVariable ( mce_z1_symb_id ) ,
AddMinus ( AddTimes ( A , AddMinus ( const_cast < VariableNode * > ( target_base_diff_node ) , fs ) ) , fp ) ) ;
addEquation ( neweq , - 1 ) ;
2019-02-19 16:36:10 +01:00
neqs + + ;
2019-02-21 10:30:25 +01:00
pac_expectation_substitution [ { name , eqtag } ] = AddVariable ( mce_z1_symb_id ) ;
2019-02-15 12:52:46 +01:00
}
2020-07-22 16:08:16 +02:00
cout < < " Pac Model Consistent Expectation: added " < < neqs < < " auxiliary variables and equations for model " < < name < < " . " < < endl ;
2019-02-15 12:52:46 +01:00
}
2018-01-30 16:33:16 +01:00
void
2019-02-20 12:59:55 +01:00
DynamicModel : : fillPacModelInfo ( const string & pac_model_name ,
2019-02-20 16:38:44 +01:00
vector < int > lhs ,
2019-02-20 12:59:55 +01:00
int max_lag ,
2019-02-20 16:42:22 +01:00
string aux_model_type ,
2019-02-20 12:59:55 +01:00
const map < pair < string , string > , pair < string , int > > & eqtag_and_lag ,
const vector < bool > & nonstationary ,
2019-05-13 17:43:16 +02:00
expr_t growth )
2018-01-30 16:33:16 +01:00
{
2019-02-19 16:36:10 +01:00
pac_eqtag_and_lag . insert ( eqtag_and_lag . begin ( ) , eqtag_and_lag . end ( ) ) ;
2019-02-15 12:52:46 +01:00
2019-09-24 16:02:40 +02:00
bool stationary_vars_present = any_of ( nonstationary . begin ( ) , nonstationary . end ( ) , logical_not < bool > ( ) ) ;
bool nonstationary_vars_present = any_of ( nonstationary . begin ( ) , nonstationary . end ( ) , [ ] ( bool b ) { return b ; } ) ; // FIXME: use std::identity instead of an anonymous function when we upgrade to C++20
2018-01-30 16:33:16 +01:00
2019-02-20 12:59:55 +01:00
int growth_param_index = - 1 ;
2019-12-16 19:42:59 +01:00
if ( growth )
2019-12-20 16:59:30 +01:00
growth_param_index = symbol_table . addSymbol ( pac_model_name
+ " _pac_growth_neutrality_correction " ,
2019-02-20 16:38:44 +01:00
SymbolType : : parameter ) ;
2019-02-20 12:59:55 +01:00
2019-02-20 16:38:44 +01:00
for ( auto pac_models_and_eqtags : pac_eqtag_and_lag )
2018-01-30 16:33:16 +01:00
{
2019-02-20 12:59:55 +01:00
if ( pac_models_and_eqtags . first . first ! = pac_model_name )
continue ;
string eqtag = pac_models_and_eqtags . first . second ;
string standard_eqtag = pac_models_and_eqtags . second . first ;
expr_t subExpr = Zero ;
if ( stationary_vars_present )
for ( int i = 1 ; i < max_lag + 1 ; i + + )
for ( auto lhsit : lhs )
{
stringstream param_name_h0 ;
param_name_h0 < < " h0_ " < < pac_model_name
< < " _ " < < standard_eqtag
< < " _var_ " < < symbol_table . getName ( lhsit )
< < " _lag_ " < < i ;
int new_param_symb_id = symbol_table . addSymbol ( param_name_h0 . str ( ) , SymbolType : : parameter ) ;
2019-02-21 10:30:25 +01:00
pac_h0_indices [ { pac_model_name , standard_eqtag } ] . push_back ( new_param_symb_id ) ;
2019-02-20 12:59:55 +01:00
subExpr = AddPlus ( subExpr ,
AddTimes ( AddVariable ( new_param_symb_id ) ,
AddVariable ( lhsit , - i ) ) ) ;
}
if ( nonstationary_vars_present )
for ( int i = 1 ; i < max_lag + 1 ; i + + )
for ( auto lhsit : lhs )
{
stringstream param_name_h1 ;
param_name_h1 < < " h1_ " < < pac_model_name
< < " _ " < < standard_eqtag
< < " _var_ " < < symbol_table . getName ( lhsit )
< < " _lag_ " < < i ;
int new_param_symb_id = symbol_table . addSymbol ( param_name_h1 . str ( ) , SymbolType : : parameter ) ;
2019-02-21 10:30:25 +01:00
pac_h1_indices [ { pac_model_name , standard_eqtag } ] . push_back ( new_param_symb_id ) ;
2019-02-20 12:59:55 +01:00
subExpr = AddPlus ( subExpr ,
AddTimes ( AddVariable ( new_param_symb_id ) ,
AddVariable ( lhsit , - i ) ) ) ;
}
2019-12-16 19:42:59 +01:00
if ( growth )
2019-02-20 12:59:55 +01:00
subExpr = AddPlus ( subExpr ,
2019-05-13 17:43:16 +02:00
AddTimes ( AddVariable ( growth_param_index ) , growth ) ) ;
2019-02-20 12:59:55 +01:00
2019-02-21 10:30:25 +01:00
pac_expectation_substitution [ { pac_model_name , eqtag } ] = subExpr ;
2018-01-30 16:33:16 +01:00
}
2019-02-21 10:30:25 +01:00
pac_model_info [ pac_model_name ] = { move ( lhs ) , growth_param_index , move ( aux_model_type ) } ;
2019-02-20 12:59:55 +01:00
}
void
2019-12-20 16:59:30 +01:00
DynamicModel : : substitutePacExpectation ( const string & pac_model_name )
2019-02-20 12:59:55 +01:00
{
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_expectation_substitution )
2019-02-20 12:59:55 +01:00
if ( it . first . first = = pac_model_name )
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2020-02-20 15:29:10 +01:00
if ( equation_tags . exists ( & equation - & equations [ 0 ] , " name " , it . first . second ) )
{
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > substitutePacExpectation ( pac_model_name , it . second ) ) ;
assert ( substeq ) ;
equation = substeq ;
break ;
}
2018-01-30 16:33:16 +01:00
}
2009-04-14 16:39:53 +02:00
void
2018-11-22 14:32:40 +01:00
DynamicModel : : computingPass ( bool jacobianExo , int derivsOrder , int paramsDerivsOrder ,
2016-02-23 13:55:02 +01:00
const eval_context_t & eval_context , bool no_tmp_terms , bool block , bool use_dll ,
2021-01-25 18:03:37 +01:00
bool bytecode )
2009-04-14 16:39:53 +02:00
{
2018-11-22 14:32:40 +01:00
assert ( jacobianExo | | ( derivsOrder < 2 & & paramsDerivsOrder = = 0 ) ) ;
2009-04-20 12:48:54 +02:00
2011-06-22 11:34:25 +02:00
initializeVariablesAndEquations ( ) ;
2017-06-01 19:58:32 +02:00
2009-09-30 17:10:31 +02:00
// Prepare for derivation
computeDerivIDs ( ) ;
// Computes dynamic jacobian columns, must be done after computeDerivIDs()
2009-04-20 12:48:54 +02:00
computeDynJacobianCols ( jacobianExo ) ;
2009-04-14 16:39:53 +02:00
2009-04-20 12:48:54 +02:00
// Compute derivatives w.r. to all endogenous, and possibly exogenous and exogenous deterministic
set < int > vars ;
2019-12-20 16:59:30 +01:00
for ( auto & it : deriv_id_table )
2009-04-20 12:48:54 +02:00
{
2019-12-16 19:42:59 +01:00
SymbolType type = symbol_table . getType ( it . first . first ) ;
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : endogenous | | ( jacobianExo & & ( type = = SymbolType : : exogenous | | type = = SymbolType : : exogenousDet ) ) )
2019-12-16 19:42:59 +01:00
vars . insert ( it . second ) ;
2009-04-20 12:48:54 +02:00
}
2009-04-14 16:39:53 +02:00
// Launch computations
2021-01-25 18:03:37 +01:00
cout < < " Computing dynamic model derivatives (order " < < derivsOrder < < " ). " < < endl ;
2009-04-20 12:48:54 +02:00
2018-11-22 14:32:40 +01:00
computeDerivatives ( derivsOrder , vars ) ;
2009-04-20 12:48:54 +02:00
2019-12-13 17:15:03 +01:00
if ( derivsOrder > 1 )
2020-01-20 17:22:32 +01:00
for ( const auto & [ indices , d2 ] : derivatives [ 2 ] )
nonzero_hessian_eqs . insert ( indices [ 0 ] ) ;
2019-12-13 17:15:03 +01:00
2016-05-18 12:26:19 +02:00
if ( paramsDerivsOrder > 0 )
2009-04-20 15:58:15 +02:00
{
2018-12-20 17:04:28 +01:00
cout < < " Computing dynamic model derivatives w.r.t. parameters (order " < < paramsDerivsOrder < < " ). " < < endl ;
2016-05-18 12:26:19 +02:00
computeParamsDerivatives ( paramsDerivsOrder ) ;
2009-04-20 15:58:15 +02:00
}
2018-09-21 17:13:19 +02:00
2021-01-25 18:03:37 +01:00
if ( block )
2018-09-21 17:13:19 +02:00
{
2020-05-06 18:09:44 +02:00
auto contemporaneous_jacobian = evaluateAndReduceJacobian ( eval_context ) ;
2009-12-16 14:21:31 +01:00
2020-05-06 18:09:44 +02:00
computeNonSingularNormalization ( contemporaneous_jacobian ) ;
2009-12-16 14:21:31 +01:00
2020-04-30 12:48:16 +02:00
auto [ prologue , epilogue ] = computePrologueAndEpilogue ( ) ;
2009-04-14 16:39:53 +02:00
2020-04-21 18:10:46 +02:00
auto first_order_endo_derivatives = collectFirstOrderDerivativesEndogenous ( ) ;
2009-05-13 01:03:40 +02:00
2020-03-20 15:23:23 +01:00
equationTypeDetermination ( first_order_endo_derivatives , mfs ) ;
2009-12-16 14:21:31 +01:00
2018-12-20 17:04:28 +01:00
cout < < " Finding the optimal block decomposition of the model ... " < < endl ;
2009-12-16 14:21:31 +01:00
2020-04-30 12:48:16 +02:00
computeBlockDecomposition ( prologue , epilogue ) ;
2010-07-23 11:20:24 +02:00
2020-04-30 12:48:16 +02:00
reduceBlockDecomposition ( ) ;
2009-12-16 14:21:31 +01:00
2020-04-15 17:56:28 +02:00
printBlockDecomposition ( ) ;
2009-12-16 14:21:31 +01:00
2020-03-19 17:46:10 +01:00
computeChainRuleJacobian ( ) ;
2009-08-25 11:43:01 +02:00
2020-03-20 15:23:23 +01:00
determineLinearBlocks ( ) ;
2009-08-25 11:43:01 +02:00
2020-05-06 14:02:58 +02:00
computeBlockDynJacobianCols ( ) ;
2009-08-25 11:43:01 +02:00
2009-04-14 16:39:53 +02:00
if ( ! no_tmp_terms )
2020-05-06 17:13:47 +02:00
computeBlockTemporaryTerms ( ) ;
2009-04-14 16:39:53 +02:00
}
else
2018-09-25 15:56:52 +02:00
{
computeTemporaryTerms ( ! use_dll , no_tmp_terms ) ;
2018-11-16 18:13:34 +01:00
/* Must be called after computeTemporaryTerms(), because it depends on
temporary_terms_mlv to be filled */
if ( paramsDerivsOrder > 0 & & ! no_tmp_terms )
computeParamsDerivativesTemporaryTerms ( ) ;
2018-09-25 15:56:52 +02:00
}
2017-03-06 16:34:08 +01:00
}
2015-12-18 15:17:32 +01:00
2017-03-06 16:34:08 +01:00
void
DynamicModel : : computeXrefs ( )
{
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2017-03-06 16:34:08 +01:00
{
ExprNode : : EquationInfo ei ;
2018-06-04 12:26:16 +02:00
equation - > computeXrefs ( ei ) ;
2017-03-06 16:34:08 +01:00
xrefs [ i + + ] = ei ;
}
i = 0 ;
2019-12-16 19:42:59 +01:00
for ( auto it = xrefs . begin ( ) ; it ! = xrefs . end ( ) ; + + it , i + + )
2017-03-06 16:34:08 +01:00
{
computeRevXref ( xref_param , it - > second . param , i ) ;
computeRevXref ( xref_endo , it - > second . endo , i ) ;
computeRevXref ( xref_exo , it - > second . exo , i ) ;
computeRevXref ( xref_exo_det , it - > second . exo_det , i ) ;
}
}
void
2018-06-04 14:17:36 +02:00
DynamicModel : : computeRevXref ( map < pair < int , int > , set < int > > & xrefset , const set < pair < int , int > > & eiref , int eqn )
2017-03-06 16:34:08 +01:00
{
2019-12-20 16:59:30 +01:00
for ( const auto & it : eiref )
2017-03-06 16:34:08 +01:00
{
set < int > eq ;
2018-06-04 12:26:16 +02:00
if ( xrefset . find ( it ) ! = xrefset . end ( ) )
eq = xrefset [ it ] ;
2017-03-06 16:34:08 +01:00
eq . insert ( eqn ) ;
2018-06-04 12:26:16 +02:00
xrefset [ it ] = eq ;
2017-03-06 16:34:08 +01:00
}
}
void
DynamicModel : : writeXrefs ( ostream & output ) const
{
output < < " M_.xref1.param = cell(1, M_.eq_nbr); " < < endl
< < " M_.xref1.endo = cell(1, M_.eq_nbr); " < < endl
< < " M_.xref1.exo = cell(1, M_.eq_nbr); " < < endl
< < " M_.xref1.exo_det = cell(1, M_.eq_nbr); " < < endl ;
int i = 1 ;
2019-12-16 19:42:59 +01:00
for ( auto it = xrefs . begin ( ) ; it ! = xrefs . end ( ) ; + + it , i + + )
2017-03-06 16:34:08 +01:00
{
output < < " M_.xref1.param{ " < < i < < " } = [ " ;
2019-12-20 16:59:30 +01:00
for ( const auto & it1 : it - > second . param )
2018-06-04 12:26:16 +02:00
output < < symbol_table . getTypeSpecificID ( it1 . first ) + 1 < < " " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
output < < " M_.xref1.endo{ " < < i < < " } = [ " ;
2019-12-20 16:59:30 +01:00
for ( const auto & it1 : it - > second . endo )
2018-06-04 12:26:16 +02:00
output < < " struct('id', " < < symbol_table . getTypeSpecificID ( it1 . first ) + 1 < < " , 'shift', " < < it1 . second < < " ); " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
output < < " M_.xref1.exo{ " < < i < < " } = [ " ;
2019-12-20 16:59:30 +01:00
for ( const auto & it1 : it - > second . exo )
2018-06-04 12:26:16 +02:00
output < < " struct('id', " < < symbol_table . getTypeSpecificID ( it1 . first ) + 1 < < " , 'shift', " < < it1 . second < < " ); " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
output < < " M_.xref1.exo_det{ " < < i < < " } = [ " ;
2019-12-20 16:59:30 +01:00
for ( const auto & it1 : it - > second . exo_det )
2018-06-04 12:26:16 +02:00
output < < " struct('id', " < < symbol_table . getTypeSpecificID ( it1 . first ) + 1 < < " , 'shift', " < < it1 . second < < " ); " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
}
output < < " M_.xref2.param = cell(1, M_.param_nbr); " < < endl
< < " M_.xref2.endo = cell(1, M_.endo_nbr); " < < endl
< < " M_.xref2.exo = cell(1, M_.exo_nbr); " < < endl
< < " M_.xref2.exo_det = cell(1, M_.exo_det_nbr); " < < endl ;
writeRevXrefs ( output , xref_param , " param " ) ;
writeRevXrefs ( output , xref_endo , " endo " ) ;
writeRevXrefs ( output , xref_exo , " exo " ) ;
writeRevXrefs ( output , xref_exo_det , " exo_det " ) ;
}
void
2018-06-04 14:17:36 +02:00
DynamicModel : : writeRevXrefs ( ostream & output , const map < pair < int , int > , set < int > > & xrefmap , const string & type ) const
2017-03-06 16:34:08 +01:00
{
int last_tsid = - 1 ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : xrefmap )
2017-03-06 16:34:08 +01:00
{
2018-06-04 12:26:16 +02:00
int tsid = symbol_table . getTypeSpecificID ( it . first . first ) + 1 ;
2017-03-06 16:34:08 +01:00
output < < " M_.xref2. " < < type < < " { " < < tsid < < " } = [ " ;
if ( last_tsid = = tsid )
output < < " M_.xref2. " < < type < < " { " < < tsid < < " }; " ;
else
last_tsid = tsid ;
2019-12-16 19:42:59 +01:00
for ( const auto & it1 : it . second )
2017-03-06 16:34:08 +01:00
if ( type = = " param " )
2019-12-16 19:42:59 +01:00
output < < it1 + 1 < < " " ;
2017-03-06 16:34:08 +01:00
else
2019-12-16 19:42:59 +01:00
output < < " struct('shift', " < < it . first . second < < " , 'eq', " < < it1 + 1 < < " ); " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
}
2009-04-14 16:39:53 +02:00
}
2009-12-16 14:21:31 +01:00
2020-04-24 12:29:02 +02:00
map < tuple < int , int , int > , DynamicModel : : BlockDerivativeType >
DynamicModel : : determineBlockDerivativesType ( int blk )
{
map < tuple < int , int , int > , BlockDerivativeType > derivType ;
int size = blocks [ blk ] . size ;
int nb_recursive = blocks [ blk ] . getRecursiveSize ( ) ;
for ( int lag = - blocks [ blk ] . max_lag ; lag < = blocks [ blk ] . max_lead ; lag + + )
for ( int eq = 0 ; eq < size ; eq + + )
2020-04-28 18:00:26 +02:00
{
set < pair < int , int > > endos_and_lags ;
int eq_orig = getBlockEquationID ( blk , eq ) ;
equations [ eq_orig ] - > collectEndogenous ( endos_and_lags ) ;
for ( int var = 0 ; var < size ; var + + )
if ( int var_orig = getBlockVariableID ( blk , var ) ;
endos_and_lags . find ( { var_orig , lag } ) ! = endos_and_lags . end ( ) )
{
2020-05-20 11:49:32 +02:00
if ( getBlockEquationType ( blk , eq ) = = EquationType : : evaluateRenormalized
2020-04-28 18:00:26 +02:00
& & eq < nb_recursive )
/* It’ s a normalized recursive equation, we have to recompute
the derivative using the chain rule */
derivType [ { lag , eq , var } ] = BlockDerivativeType : : normalizedChainRule ;
else if ( derivType . find ( { lag , eq , var } ) = = derivType . end ( ) )
derivType [ { lag , eq , var } ] = BlockDerivativeType : : standard ;
if ( var < nb_recursive )
for ( int feedback_var = nb_recursive ; feedback_var < size ; feedback_var + + )
if ( derivType . find ( { lag , var , feedback_var } ) ! = derivType . end ( ) )
/* A new derivative needs to be computed using the chain rule
( a feedback variable appears in the recursive equation
defining the current variable ) */
derivType [ { lag , eq , feedback_var } ] = BlockDerivativeType : : chainRule ;
}
}
2020-04-24 12:29:02 +02:00
return derivType ;
2009-12-16 14:21:31 +01:00
}
void
2020-03-19 17:46:10 +01:00
DynamicModel : : computeChainRuleJacobian ( )
2009-12-16 14:21:31 +01:00
{
2020-04-23 16:04:02 +02:00
int nb_blocks = blocks . size ( ) ;
2020-03-19 17:46:10 +01:00
blocks_derivatives . resize ( nb_blocks ) ;
2020-04-24 12:29:02 +02:00
for ( int blk = 0 ; blk < nb_blocks ; blk + + )
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
int nb_recursives = blocks [ blk ] . getRecursiveSize ( ) ;
// Create a map from recursive vars to their defining (normalized) equation
2020-10-02 18:31:55 +02:00
map < int , BinaryOpNode * > recursive_vars ;
2020-04-24 12:29:02 +02:00
for ( int i = 0 ; i < nb_recursives ; i + + )
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
int deriv_id = getDerivID ( symbol_table . getID ( SymbolType : : endogenous , getBlockVariableID ( blk , i ) ) , 0 ) ;
2020-05-20 11:49:32 +02:00
if ( getBlockEquationType ( blk , i ) = = EquationType : : evaluateRenormalized )
2020-04-24 12:29:02 +02:00
recursive_vars [ deriv_id ] = getBlockEquationRenormalizedExpr ( blk , i ) ;
2010-07-23 11:20:24 +02:00
else
2020-04-24 12:29:02 +02:00
recursive_vars [ deriv_id ] = getBlockEquationExpr ( blk , i ) ;
2009-12-16 14:21:31 +01:00
}
2020-04-24 12:29:02 +02:00
// Compute the block derivatives
for ( const auto & [ indices , derivType ] : determineBlockDerivativesType ( blk ) )
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
auto [ lag , eq , var ] = indices ;
int eq_orig = getBlockEquationID ( blk , eq ) , var_orig = getBlockVariableID ( blk , var ) ;
int deriv_id = getDerivID ( symbol_table . getID ( SymbolType : : endogenous , var_orig ) , lag ) ;
expr_t d { nullptr } ;
switch ( derivType )
2009-12-16 14:21:31 +01:00
{
2020-04-24 12:29:02 +02:00
case BlockDerivativeType : : standard :
d = derivatives [ 1 ] [ { eq_orig , deriv_id } ] ;
break ;
case BlockDerivativeType : : chainRule :
d = equations [ eq_orig ] - > getChainRuleDerivative ( deriv_id , recursive_vars ) ;
break ;
case BlockDerivativeType : : normalizedChainRule :
d = equation_type_and_normalized_equation [ eq_orig ] . second - > getChainRuleDerivative ( deriv_id , recursive_vars ) ;
break ;
2009-12-16 14:21:31 +01:00
}
2020-04-24 12:29:02 +02:00
2020-05-06 14:21:33 +02:00
if ( d ! = Zero )
blocks_derivatives [ blk ] [ { eq , var , lag } ] = d ;
2009-12-16 14:21:31 +01:00
}
}
}
void
2020-05-06 14:02:58 +02:00
DynamicModel : : computeBlockDynJacobianCols ( )
2009-12-16 14:21:31 +01:00
{
2020-04-23 16:04:02 +02:00
int nb_blocks = blocks . size ( ) ;
2020-04-30 16:00:16 +02:00
blocks_derivatives_other_endo . resize ( nb_blocks ) ;
blocks_derivatives_exo . resize ( nb_blocks ) ;
blocks_derivatives_exo_det . resize ( nb_blocks ) ;
2020-05-06 14:02:58 +02:00
blocks_other_endo . resize ( nb_blocks ) ;
blocks_exo . resize ( nb_blocks ) ;
blocks_exo_det . resize ( nb_blocks ) ;
// Structures used for lexicographic ordering over (lag, var ID)
vector < set < pair < int , int > > > dynamic_endo ( nb_blocks ) , dynamic_other_endo ( nb_blocks ) ,
dynamic_exo ( nb_blocks ) , dynamic_exo_det ( nb_blocks ) ;
2019-12-16 19:42:59 +01:00
for ( auto & [ indices , d1 ] : derivatives [ 1 ] )
2009-12-16 14:21:31 +01:00
{
2020-04-30 16:00:16 +02:00
int eq_orig = indices [ 0 ] ;
int block_eq = eq2block [ eq_orig ] ;
int eq = getBlockInitialEquationID ( block_eq , eq_orig ) ;
2019-12-16 19:42:59 +01:00
int var = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( indices [ 1 ] ) ) ;
int lag = getLagByDerivID ( indices [ 1 ] ) ;
switch ( getTypeByDerivID ( indices [ 1 ] ) )
2009-12-16 14:21:31 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2020-05-06 14:02:58 +02:00
if ( block_eq = = endo2block [ var ] )
{
int var_in_block = getBlockInitialVariableID ( block_eq , var ) ;
dynamic_endo [ block_eq ] . emplace ( lag , var_in_block ) ;
}
else
2009-12-16 18:13:23 +01:00
{
2020-04-30 16:00:16 +02:00
blocks_derivatives_other_endo [ block_eq ] [ { eq , var , lag } ] = derivatives [ 1 ] [ { eq_orig , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , var ) , lag ) } ] ;
2020-05-06 14:02:58 +02:00
blocks_other_endo [ block_eq ] . insert ( var ) ;
dynamic_other_endo [ block_eq ] . emplace ( lag , var ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2020-04-30 16:00:16 +02:00
blocks_derivatives_exo [ block_eq ] [ { eq , var , lag } ] = derivatives [ 1 ] [ { eq_orig , getDerivID ( symbol_table . getID ( SymbolType : : exogenous , var ) , lag ) } ] ;
2020-05-06 14:02:58 +02:00
blocks_exo [ block_eq ] . insert ( var ) ;
dynamic_exo [ block_eq ] . emplace ( lag , var ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2020-04-30 16:00:16 +02:00
blocks_derivatives_exo_det [ block_eq ] [ { eq , var , lag } ] = derivatives [ 1 ] [ { eq_orig , getDerivID ( symbol_table . getID ( SymbolType : : exogenous , var ) , lag ) } ] ;
2020-05-06 14:02:58 +02:00
blocks_exo_det [ block_eq ] . insert ( var ) ;
dynamic_exo_det [ block_eq ] . emplace ( lag , var ) ;
2009-12-16 18:13:23 +01:00
break ;
default :
break ;
2009-12-16 14:21:31 +01:00
}
}
2020-05-06 14:02:58 +02:00
// Compute Jacobian column indices
blocks_jacob_cols_endo . resize ( nb_blocks ) ;
blocks_jacob_cols_other_endo . resize ( nb_blocks ) ;
blocks_jacob_cols_exo . resize ( nb_blocks ) ;
blocks_jacob_cols_exo_det . resize ( nb_blocks ) ;
for ( int blk = 0 ; blk < nb_blocks ; blk + + )
{
int index = 0 ;
for ( auto [ lag , var ] : dynamic_endo [ blk ] )
blocks_jacob_cols_endo [ blk ] [ { var , lag } ] = index + + ;
index = 0 ;
for ( auto [ lag , var ] : dynamic_other_endo [ blk ] )
blocks_jacob_cols_other_endo [ blk ] [ { var , lag } ] = index + + ;
index = 0 ;
for ( auto [ lag , var ] : dynamic_exo [ blk ] )
blocks_jacob_cols_exo [ blk ] [ { var , lag } ] = index + + ;
index = 0 ;
for ( auto [ lag , var ] : dynamic_exo_det [ blk ] )
blocks_jacob_cols_exo_det [ blk ] [ { var , lag } ] = index + + ;
}
2009-12-16 14:21:31 +01:00
}
2009-04-14 16:39:53 +02:00
void
2021-01-25 18:03:37 +01:00
DynamicModel : : writeDynamicFile ( const string & basename , bool block , bool bytecode , bool use_dll , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot , bool julia ) const
2009-12-16 18:13:23 +01:00
{
2020-06-23 15:13:04 +02:00
filesystem : : path model_dir { basename } ;
model_dir / = " model " ;
if ( use_dll )
filesystem : : create_directories ( model_dir / " src " ) ;
if ( bytecode )
filesystem : : create_directories ( model_dir / " bytecode " ) ;
2021-01-25 18:03:37 +01:00
if ( block )
2018-10-26 11:44:26 +02:00
{
2020-06-23 15:13:04 +02:00
if ( bytecode )
2021-01-25 18:03:37 +01:00
writeDynamicBlockBytecode ( basename ) ;
2020-06-23 15:13:04 +02:00
else if ( use_dll )
{
writeDynamicPerBlockCFiles ( basename ) ;
writeDynamicBlockCFile ( basename ) ;
vector < filesystem : : path > src_files { blocks . size ( ) + 1 } ;
for ( int blk = 0 ; blk < static_cast < int > ( blocks . size ( ) ) ; blk + + )
src_files [ blk ] = model_dir / " src " / ( " dynamic_ " + to_string ( blk + 1 ) + " .c " ) ;
src_files [ blocks . size ( ) ] = model_dir / " src " / " dynamic.c " ;
compileMEX ( basename , " dynamic " , mexext , src_files , matlabroot , dynareroot ) ;
}
else if ( julia )
{
cerr < < " 'block' option is not available with Julia " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else // M-files
{
writeDynamicPerBlockMFiles ( basename ) ;
writeDynamicBlockMFile ( basename ) ;
}
2018-10-26 11:44:26 +02:00
}
2009-12-16 18:13:23 +01:00
else
2020-06-23 15:13:04 +02:00
{
if ( bytecode )
writeDynamicBytecode ( basename ) ;
else if ( use_dll )
{
writeDynamicCFile ( basename ) ;
compileMEX ( basename , " dynamic " , mexext , { model_dir / " src " / " dynamic.c " } ,
matlabroot , dynareroot ) ;
}
else if ( julia )
writeDynamicJuliaFile ( basename ) ;
else
writeDynamicMFile ( basename ) ;
}
2019-10-17 15:03:26 +02:00
writeSetAuxiliaryVariables ( basename , julia ) ;
2018-03-02 17:50:35 +01:00
}
void
2019-12-16 19:42:59 +01:00
DynamicModel : : writeSetAuxiliaryVariables ( const string & basename , bool julia ) const
2018-03-02 17:50:35 +01:00
{
ostringstream output_func_body ;
2018-09-05 18:27:13 +02:00
writeAuxVarRecursiveDefinitions ( output_func_body , ExprNodeOutputType : : matlabDseries ) ;
2018-03-02 17:50:35 +01:00
if ( output_func_body . str ( ) . empty ( ) )
return ;
2021-04-23 17:55:28 +02:00
string func_name = julia ? basename + " _dynamic_set_auxiliary_series! " : " dynamic_set_auxiliary_series " ;
2018-03-02 17:50:35 +01:00
string comment = julia ? " # " : " % " ;
2021-04-23 17:30:38 +02:00
stringstream output ;
2021-04-23 17:55:28 +02:00
if ( julia )
output < < " module " < < basename < < " DynamicSetAuxiliarySeries " < < endl
< < " export " < < func_name < < endl ;
output < < " function " ;
if ( ! julia )
output < < " ds = " ;
output < < func_name + " (ds, params) " < < endl
2018-03-02 17:50:35 +01:00
< < comment < < endl
< < comment < < " Status : Computes Auxiliary variables of the dynamic model and returns a dseries " < < endl
< < comment < < endl
< < comment < < " Warning : this file is generated automatically by Dynare " < < endl
< < comment < < " from model file (.mod) " < < endl < < endl
2021-04-23 17:55:28 +02:00
< < output_func_body . str ( )
< < " end " < < endl ;
if ( julia )
output < < " end " < < endl ;
2018-03-02 18:39:16 +01:00
2021-04-23 17:55:28 +02:00
writeToFileIfModified ( output , julia ? basename + " DynamicSetAuxiliarySeries.jl " : packageDir ( basename ) + " / " + func_name + " .m " ) ;
2018-03-02 17:50:35 +01:00
}
void
DynamicModel : : writeAuxVarRecursiveDefinitions ( ostream & output , ExprNodeOutputType output_type ) const
{
deriv_node_temp_terms_t tef_terms ;
2019-12-16 19:42:59 +01:00
for ( auto aux_eq : aux_equations )
2020-07-08 18:46:09 +02:00
if ( aux_eq - > containsExternalFunction ( ) )
aux_eq - > writeExternalFunctionOutput ( output , output_type , { } , { } , tef_terms ) ;
2019-12-16 19:42:59 +01:00
for ( auto aux_eq : aux_equations )
{
2020-07-08 18:46:09 +02:00
aux_eq - > writeOutput ( output , output_type , { } , { } , tef_terms ) ;
2018-03-02 17:50:35 +01:00
output < < " ; " < < endl ;
}
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2020-01-06 18:26:35 +01:00
void
DynamicModel : : clearEquations ( )
{
equations . clear ( ) ;
equations_lineno . clear ( ) ;
equation_tags . clear ( ) ;
}
2011-03-21 18:40:57 +01:00
void
DynamicModel : : replaceMyEquations ( DynamicModel & dynamic_model ) const
{
2020-01-06 18:26:35 +01:00
dynamic_model . clearEquations ( ) ;
2014-01-27 16:41:43 +01:00
for ( size_t i = 0 ; i < equations . size ( ) ; i + + )
2020-01-06 18:26:35 +01:00
dynamic_model . addEquation ( equations [ i ] - > clone ( dynamic_model ) , equations_lineno [ i ] ) ;
dynamic_model . equation_tags = equation_tags ;
2011-03-21 18:40:57 +01:00
}
void
2018-12-20 17:04:28 +01:00
DynamicModel : : computeRamseyPolicyFOCs ( const StaticModel & static_model )
2011-03-21 18:40:57 +01:00
{
// Add aux LM to constraints in equations
2011-05-25 06:43:59 +02:00
// equation[i]->lhs = rhs becomes equation[i]->MULT_(i+1)*(lhs-rhs) = 0
2011-03-21 18:40:57 +01:00
int i ;
2019-04-23 11:07:32 +02:00
for ( i = 0 ; i < static_cast < int > ( equations . size ( ) ) ; i + + )
2011-03-21 18:40:57 +01:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equations [ i ] - > addMultipliersToConstraints ( i ) ) ;
assert ( substeq ) ;
2011-03-21 18:40:57 +01:00
equations [ i ] = substeq ;
}
2018-12-20 17:04:28 +01:00
cout < < " Ramsey Problem: added " < < i < < " Multipliers. " < < endl ;
2011-03-21 18:40:57 +01:00
2020-01-06 18:26:35 +01:00
// Add Planner Objective to equations so that it appears in Lagrangian
2011-03-21 18:40:57 +01:00
assert ( static_model . equations . size ( ) = = 1 ) ;
2020-01-06 18:26:35 +01:00
addEquation ( static_model . equations [ 0 ] - > clone ( * this ) , - 1 ) ;
2011-03-21 18:40:57 +01:00
// Get max endo lead and max endo lag
2018-06-04 14:17:36 +02:00
set < pair < int , int > > dynvars ;
2011-03-21 18:40:57 +01:00
int max_eq_lead = 0 ;
int max_eq_lag = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectDynamicVariables ( SymbolType : : endogenous , dynvars ) ;
2011-03-21 18:40:57 +01:00
2020-01-06 18:26:35 +01:00
for ( const auto & [ symb_id , lag ] : dynvars )
2011-03-21 18:40:57 +01:00
{
if ( max_eq_lead < lag )
max_eq_lead = lag ;
else if ( - max_eq_lag > lag )
max_eq_lag = - lag ;
}
2011-03-29 18:18:32 +02:00
// Get Discount Factor
2011-05-24 15:34:03 +02:00
assert ( symbol_table . exists ( " optimal_policy_discount_factor " ) ) ;
int symb_id = symbol_table . getID ( " optimal_policy_discount_factor " ) ;
2018-07-17 18:34:07 +02:00
assert ( symbol_table . getType ( symb_id ) = = SymbolType : : parameter ) ;
2011-03-29 18:18:32 +02:00
expr_t discount_factor_node = AddVariable ( symb_id , 0 ) ;
2011-03-21 18:40:57 +01:00
// Create (modified) Lagrangian (so that we can take the derivative once at time t)
expr_t lagrangian = Zero ;
2019-04-23 11:07:32 +02:00
for ( i = 0 ; i < static_cast < int > ( equations . size ( ) ) ; i + + )
2011-03-21 18:40:57 +01:00
for ( int lag = - max_eq_lag ; lag < = max_eq_lead ; lag + + )
{
2018-06-04 12:52:14 +02:00
expr_t dfpower = nullptr ;
2019-12-16 19:42:59 +01:00
stringstream lagstream ;
2011-03-21 18:40:57 +01:00
lagstream < < abs ( lag ) ;
if ( lag < 0 )
dfpower = AddNonNegativeConstant ( lagstream . str ( ) ) ;
else if ( lag = = 0 )
dfpower = Zero ;
else
dfpower = AddMinus ( Zero , AddNonNegativeConstant ( lagstream . str ( ) ) ) ;
lagrangian = AddPlus ( AddTimes ( AddPower ( discount_factor_node , dfpower ) ,
equations [ i ] - > getNonZeroPartofEquation ( ) - > decreaseLeadsLags ( lag ) ) , lagrangian ) ;
}
2020-01-06 18:26:35 +01:00
// Save line numbers and tags, see below
auto old_equations_lineno = equations_lineno ;
auto old_equation_tags = equation_tags ;
// Prepare derivation of the Lagrangian
clearEquations ( ) ;
2014-01-27 16:41:43 +01:00
addEquation ( AddEqual ( lagrangian , Zero ) , - 1 ) ;
2011-03-21 18:40:57 +01:00
computeDerivIDs ( ) ;
2020-01-06 18:26:35 +01:00
/* Compute Lagrangian derivatives.
Also restore line numbers and tags for FOCs w . r . t . a Lagrange multiplier
( i . e . a FOC identical to an equation of the original model ) */
2011-03-21 18:40:57 +01:00
vector < expr_t > neweqs ;
2020-01-06 18:26:35 +01:00
vector < int > neweqs_lineno ;
2020-02-20 15:29:10 +01:00
map < int , map < string , string > > neweqs_tags ;
2020-01-06 18:26:35 +01:00
for ( auto & [ symb_id_and_lag , deriv_id ] : deriv_id_table )
{
auto & [ symb_id , lag ] = symb_id_and_lag ;
if ( symbol_table . getType ( symb_id ) = = SymbolType : : endogenous & & lag = = 0 )
{
neweqs . push_back ( AddEqual ( equations [ 0 ] - > getNonZeroPartofEquation ( ) - > getDerivative ( deriv_id ) , Zero ) ) ;
if ( int i = symbol_table . getEquationNumberForMultiplier ( symb_id ) ;
i ! = - 1 )
{
// This is a derivative w.r.t. a Lagrange multiplier
neweqs_lineno . push_back ( old_equations_lineno [ i ] ) ;
2020-02-20 15:29:10 +01:00
map < string , string > tags ;
auto tmp = old_equation_tags . getTagsByEqn ( i ) ;
for ( const auto & [ key , value ] : tmp )
tags [ key ] = value ;
2020-01-06 18:26:35 +01:00
neweqs_tags [ neweqs . size ( ) - 1 ] = tags ;
}
else
neweqs_lineno . push_back ( - 1 ) ;
}
}
2011-03-21 18:40:57 +01:00
2020-01-06 18:26:35 +01:00
// Overwrite equations with the Lagrangian derivatives
clearEquations ( ) ;
for ( size_t i = 0 ; i < neweqs . size ( ) ; i + + )
addEquation ( neweqs [ i ] , neweqs_lineno [ i ] , neweqs_tags [ i ] ) ;
2011-03-21 18:40:57 +01:00
}
2015-07-30 14:40:03 +02:00
bool
DynamicModel : : ParamUsedWithLeadLag ( ) const
{
return ParamUsedWithLeadLagInternal ( ) ;
}
2019-10-16 17:34:27 +02:00
void
DynamicModel : : createVariableMapping ( int orig_eq_nbr )
{
for ( int ii = 0 ; ii < orig_eq_nbr ; ii + + )
{
set < int > eqvars ;
equations [ ii ] - > collectVariables ( SymbolType : : endogenous , eqvars ) ;
equations [ ii ] - > collectVariables ( SymbolType : : exogenous , eqvars ) ;
for ( auto eqvar : eqvars )
{
2019-11-07 20:18:47 +01:00
eqvar = symbol_table . getUltimateOrigSymbID ( eqvar ) ;
if ( eqvar > = 0 & & ! symbol_table . isAuxiliaryVariable ( eqvar ) )
variableMapping [ eqvar ] . emplace ( ii ) ;
2019-10-16 17:34:27 +02:00
}
}
}
void
DynamicModel : : expandEqTags ( )
{
2020-02-20 15:29:10 +01:00
set < int > existing_tags = equation_tags . getEqnsByKey ( " name " ) ;
2019-10-16 17:34:27 +02:00
for ( int eq = 0 ; eq < static_cast < int > ( equations . size ( ) ) ; eq + + )
if ( existing_tags . find ( eq ) = = existing_tags . end ( ) )
2020-02-20 15:29:10 +01:00
if ( auto lhs_expr = dynamic_cast < VariableNode * > ( equations [ eq ] - > arg1 ) ;
lhs_expr
& & ! equation_tags . exists ( " name " , symbol_table . getName ( lhs_expr - > symb_id ) ) )
equation_tags . add ( eq , " name " , symbol_table . getName ( lhs_expr - > symb_id ) ) ;
else if ( ! equation_tags . exists ( " name " , to_string ( eq + 1 ) ) )
equation_tags . add ( eq , " name " , to_string ( eq + 1 ) ) ;
2019-10-16 17:34:27 +02:00
else
{
cerr < < " Error creating default equation tag: cannot assign default tag to equation number " < < eq + 1 < < " because it is already in use " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2013-11-29 15:32:49 +01:00
set < int >
DynamicModel : : findUnusedEndogenous ( )
2013-09-13 20:37:31 +02:00
{
2013-11-29 15:32:49 +01:00
set < int > usedEndo , unusedEndo ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectVariables ( SymbolType : : endogenous , usedEndo ) ;
2013-11-29 15:32:49 +01:00
set < int > allEndo = symbol_table . getEndogenous ( ) ;
set_difference ( allEndo . begin ( ) , allEndo . end ( ) ,
usedEndo . begin ( ) , usedEndo . end ( ) ,
inserter ( unusedEndo , unusedEndo . begin ( ) ) ) ;
return unusedEndo ;
2013-09-13 20:37:31 +02:00
}
2013-11-29 16:03:15 +01:00
set < int >
DynamicModel : : findUnusedExogenous ( )
{
2016-10-14 16:35:15 +02:00
set < int > usedExo , unusedExo , unobservedExo ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectVariables ( SymbolType : : exogenous , usedExo ) ;
2018-03-13 09:20:14 +01:00
set < int > observedExo = symbol_table . getObservedExogenous ( ) ;
2013-11-29 16:03:15 +01:00
set < int > allExo = symbol_table . getExogenous ( ) ;
set_difference ( allExo . begin ( ) , allExo . end ( ) ,
2016-10-14 16:35:15 +02:00
observedExo . begin ( ) , observedExo . end ( ) ,
inserter ( unobservedExo , unobservedExo . begin ( ) ) ) ;
set_difference ( unobservedExo . begin ( ) , unobservedExo . end ( ) ,
2013-11-29 16:03:15 +01:00
usedExo . begin ( ) , usedExo . end ( ) ,
inserter ( unusedExo , unusedExo . begin ( ) ) ) ;
return unusedExo ;
}
2017-07-27 18:33:19 +02:00
void
DynamicModel : : setLeadsLagsOrig ( )
{
2018-06-04 14:17:36 +02:00
set < pair < int , int > > dynvars ;
2017-07-27 18:33:19 +02:00
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2017-07-27 18:33:19 +02:00
{
2018-07-17 18:34:07 +02:00
equation - > collectDynamicVariables ( SymbolType : : endogenous , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : exogenous , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : exogenousDet , dynvars ) ;
2018-12-11 17:26:50 +01:00
max_lag_with_diffs_expanded_orig = max ( equation - > maxLagWithDiffsExpanded ( ) ,
max_lag_with_diffs_expanded_orig ) ;
2017-07-27 18:33:19 +02:00
}
2019-12-20 16:59:30 +01:00
for ( const auto & dynvar : dynvars )
2017-07-27 18:33:19 +02:00
{
2018-06-04 12:26:16 +02:00
int lag = dynvar . second ;
2019-09-24 14:03:38 +02:00
SymbolType type = symbol_table . getType ( dynvar . first ) ;
2017-07-27 18:33:19 +02:00
2019-03-21 17:21:06 +01:00
max_lead_orig = max ( lag , max_lead_orig ) ;
max_lag_orig = max ( - lag , max_lag_orig ) ;
2017-07-27 18:33:19 +02:00
2019-09-24 14:03:38 +02:00
switch ( type )
2017-07-27 18:33:19 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2019-09-24 14:03:38 +02:00
max_endo_lead_orig = max ( lag , max_endo_lead_orig ) ;
max_endo_lag_orig = max ( - lag , max_endo_lag_orig ) ;
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2019-09-24 14:03:38 +02:00
max_exo_lead_orig = max ( lag , max_exo_lead_orig ) ;
max_exo_lag_orig = max ( - lag , max_exo_lag_orig ) ;
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2019-03-21 17:21:06 +01:00
max_exo_det_lead_orig = max ( lag , max_exo_det_lead_orig ) ;
max_exo_det_lag_orig = max ( - lag , max_exo_det_lag_orig ) ;
2017-07-27 18:33:19 +02:00
break ;
default :
break ;
}
}
}
2009-09-30 17:10:31 +02:00
void
DynamicModel : : computeDerivIDs ( )
2009-04-17 18:26:23 +02:00
{
2018-06-04 14:17:36 +02:00
set < pair < int , int > > dynvars ;
2009-04-17 18:26:23 +02:00
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectDynamicVariables ( SymbolType : : endogenous , dynvars ) ;
2009-04-17 18:26:23 +02:00
2009-09-30 17:10:31 +02:00
dynJacobianColsNbr = dynvars . size ( ) ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2009-04-17 18:26:23 +02:00
{
2018-07-17 18:34:07 +02:00
equation - > collectDynamicVariables ( SymbolType : : exogenous , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : exogenousDet , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : parameter , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : trend , dynvars ) ;
equation - > collectDynamicVariables ( SymbolType : : logTrend , dynvars ) ;
2009-04-17 18:26:23 +02:00
}
2019-12-20 16:59:30 +01:00
for ( const auto & dynvar : dynvars )
2009-09-30 17:10:31 +02:00
{
2018-06-04 12:26:16 +02:00
int lag = dynvar . second ;
SymbolType type = symbol_table . getType ( dynvar . first ) ;
2009-04-17 18:26:23 +02:00
2010-11-18 11:21:20 +01:00
/* Setting maximum and minimum lags.
We don ' t want these to be affected by lead / lags on parameters : they
are accepted for facilitating variable flipping , but are simply
ignored . */
2019-03-21 17:21:06 +01:00
if ( type ! = SymbolType : : parameter )
{
max_lead = max ( lag , max_lead ) ;
max_lag = max ( - lag , max_lag ) ;
}
2009-04-17 18:26:23 +02:00
2009-09-30 17:10:31 +02:00
switch ( type )
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2019-03-21 17:21:06 +01:00
max_endo_lead = max ( lag , max_endo_lead ) ;
max_endo_lag = max ( - lag , max_endo_lag ) ;
2009-09-30 17:10:31 +02:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2019-03-21 17:21:06 +01:00
max_exo_lead = max ( lag , max_exo_lead ) ;
max_exo_lag = max ( - lag , max_exo_lag ) ;
2009-09-30 17:10:31 +02:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2019-03-21 17:21:06 +01:00
max_exo_det_lead = max ( lag , max_exo_det_lead ) ;
max_exo_det_lag = max ( - lag , max_exo_det_lag ) ;
2009-09-30 17:10:31 +02:00
break ;
default :
break ;
}
2009-04-17 18:26:23 +02:00
2009-09-30 17:10:31 +02:00
// Create a new deriv_id
int deriv_id = deriv_id_table . size ( ) ;
2009-04-17 18:26:23 +02:00
2018-06-04 12:26:16 +02:00
deriv_id_table [ dynvar ] = deriv_id ;
inv_deriv_id_table . push_back ( dynvar ) ;
2009-09-30 17:10:31 +02:00
}
2009-04-17 18:26:23 +02:00
}
2009-04-20 12:48:54 +02:00
SymbolType
2018-06-04 12:50:53 +02:00
DynamicModel : : getTypeByDerivID ( int deriv_id ) const noexcept ( false )
2009-04-17 18:26:23 +02:00
{
return symbol_table . getType ( getSymbIDByDerivID ( deriv_id ) ) ;
}
int
2018-06-04 12:50:53 +02:00
DynamicModel : : getLagByDerivID ( int deriv_id ) const noexcept ( false )
2009-04-17 18:26:23 +02:00
{
2019-04-23 11:07:32 +02:00
if ( deriv_id < 0 | | deriv_id > = static_cast < int > ( inv_deriv_id_table . size ( ) ) )
2009-04-17 18:26:23 +02:00
throw UnknownDerivIDException ( ) ;
return inv_deriv_id_table [ deriv_id ] . second ;
}
int
2018-06-04 12:50:53 +02:00
DynamicModel : : getSymbIDByDerivID ( int deriv_id ) const noexcept ( false )
2009-04-17 18:26:23 +02:00
{
2019-04-23 11:07:32 +02:00
if ( deriv_id < 0 | | deriv_id > = static_cast < int > ( inv_deriv_id_table . size ( ) ) )
2009-04-17 18:26:23 +02:00
throw UnknownDerivIDException ( ) ;
return inv_deriv_id_table [ deriv_id ] . first ;
}
int
2018-06-04 12:50:53 +02:00
DynamicModel : : getDerivID ( int symb_id , int lag ) const noexcept ( false )
2009-04-17 18:26:23 +02:00
{
2018-06-04 16:36:46 +02:00
auto it = deriv_id_table . find ( { symb_id , lag } ) ;
2009-04-17 18:26:23 +02:00
if ( it = = deriv_id_table . end ( ) )
throw UnknownDerivIDException ( ) ;
else
return it - > second ;
}
2011-01-13 18:08:26 +01:00
void
DynamicModel : : addAllParamDerivId ( set < int > & deriv_id_set )
{
for ( size_t i = 0 ; i < inv_deriv_id_table . size ( ) ; i + + )
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( inv_deriv_id_table [ i ] . first ) = = SymbolType : : parameter )
2011-01-13 18:08:26 +01:00
deriv_id_set . insert ( i ) ;
}
2009-04-17 18:26:23 +02:00
void
2009-04-20 12:48:54 +02:00
DynamicModel : : computeDynJacobianCols ( bool jacobianExo )
2009-04-17 18:26:23 +02:00
{
/* Sort the dynamic endogenous variables by lexicographic order over (lag, type_specific_symbol_id)
and fill the dynamic columns for exogenous and exogenous deterministic */
map < pair < int , int > , int > ordered_dyn_endo ;
2019-12-20 16:59:30 +01:00
for ( auto & it : deriv_id_table )
2009-04-17 18:26:23 +02:00
{
2019-12-16 19:42:59 +01:00
int symb_id = it . first . first ;
int lag = it . first . second ;
int deriv_id = it . second ;
2009-04-17 18:26:23 +02:00
SymbolType type = symbol_table . getType ( symb_id ) ;
int tsid = symbol_table . getTypeSpecificID ( symb_id ) ;
2009-05-13 01:03:40 +02:00
2009-06-05 16:45:23 +02:00
switch ( type )
2009-04-17 18:26:23 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2018-06-04 16:36:46 +02:00
ordered_dyn_endo [ { lag , tsid } ] = deriv_id ;
2009-04-17 18:26:23 +02:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2009-04-20 12:48:54 +02:00
// At this point, dynJacobianColsNbr contains the number of dynamic endogenous
if ( jacobianExo )
dyn_jacobian_cols_table [ deriv_id ] = dynJacobianColsNbr + tsid ;
2009-04-17 18:26:23 +02:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2009-04-20 12:48:54 +02:00
// At this point, dynJacobianColsNbr contains the number of dynamic endogenous
if ( jacobianExo )
dyn_jacobian_cols_table [ deriv_id ] = dynJacobianColsNbr + symbol_table . exo_nbr ( ) + tsid ;
2009-04-17 18:26:23 +02:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : parameter :
case SymbolType : : trend :
case SymbolType : : logTrend :
2010-10-15 19:05:16 +02:00
// We don't assign a dynamic jacobian column to parameters or trend variables
2009-04-20 15:58:15 +02:00
break ;
2009-04-17 18:26:23 +02:00
default :
// Shut up GCC
2009-04-20 15:58:15 +02:00
cerr < < " DynamicModel::computeDynJacobianCols: impossible case " < < endl ;
2009-04-17 18:26:23 +02:00
exit ( EXIT_FAILURE ) ;
}
}
// Fill in dynamic jacobian columns for endogenous
int sorted_id = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & it : ordered_dyn_endo )
2019-12-16 19:42:59 +01:00
dyn_jacobian_cols_table [ it . second ] = sorted_id + + ;
2009-04-20 12:48:54 +02:00
// Set final value for dynJacobianColsNbr
if ( jacobianExo )
dynJacobianColsNbr + = symbol_table . exo_nbr ( ) + symbol_table . exo_det_nbr ( ) ;
2009-04-17 18:26:23 +02:00
}
int
2018-06-04 12:50:53 +02:00
DynamicModel : : getDynJacobianCol ( int deriv_id ) const noexcept ( false )
2009-04-17 18:26:23 +02:00
{
2019-12-16 19:42:59 +01:00
if ( auto it = dyn_jacobian_cols_table . find ( deriv_id ) ;
it = = dyn_jacobian_cols_table . end ( ) )
2009-04-17 18:26:23 +02:00
throw UnknownDerivIDException ( ) ;
else
return it - > second ;
}
2010-10-15 19:05:16 +02:00
void
DynamicModel : : testTrendDerivativesEqualToZero ( const eval_context_t & eval_context )
{
2019-12-16 19:42:59 +01:00
for ( auto & it : deriv_id_table )
if ( symbol_table . getType ( it . first . first ) = = SymbolType : : trend
| | symbol_table . getType ( it . first . first ) = = SymbolType : : logTrend )
2019-04-23 11:07:32 +02:00
for ( int eq = 0 ; eq < static_cast < int > ( equations . size ( ) ) ; eq + + )
2010-10-15 19:05:16 +02:00
{
2018-11-28 14:32:26 +01:00
expr_t homogeneq = AddMinus ( equations [ eq ] - > arg1 ,
equations [ eq ] - > arg2 ) ;
2013-10-29 11:46:54 +01:00
// Do not run the test if the term inside the log is zero
2018-07-17 16:32:00 +02:00
if ( fabs ( homogeneq - > eval ( eval_context ) ) > zero_band )
2013-10-29 11:46:54 +01:00
{
expr_t testeq = AddLog ( homogeneq ) ; // F = log(lhs-rhs)
2019-12-16 19:42:59 +01:00
testeq = testeq - > getDerivative ( it . second ) ; // d F / d Trend
2019-12-20 16:59:30 +01:00
for ( auto & endogit : deriv_id_table )
2019-12-16 19:42:59 +01:00
if ( symbol_table . getType ( endogit . first . first ) = = SymbolType : : endogenous )
2010-10-15 19:05:16 +02:00
{
2019-12-16 19:42:59 +01:00
double nearZero = testeq - > getDerivative ( endogit . second ) - > eval ( eval_context ) ; // eval d F / d Trend d Endog
2019-11-14 17:51:16 +01:00
if ( fabs ( nearZero ) > balanced_growth_test_tol )
2013-10-29 11:46:54 +01:00
{
2019-11-14 17:51:16 +01:00
cerr < < " ERROR: trends not compatible with balanced growth path; the second-order cross partial of equation " < < eq + 1 < < " (line "
2014-01-27 16:41:43 +01:00
< < equations_lineno [ eq ] < < " ) w.r.t. trend variable "
2019-12-16 19:42:59 +01:00
< < symbol_table . getName ( it . first . first ) < < " and endogenous variable "
< < symbol_table . getName ( endogit . first . first ) < < " is not null (abs. value = "
2019-11-14 17:51:16 +01:00
< < fabs ( nearZero ) < < " ). If you are confident that your trends are correctly specified, you can raise the value of option 'balanced_growth_test_tol' in the 'model' block. " < < endl ;
exit ( EXIT_FAILURE ) ;
2013-10-29 11:46:54 +01:00
}
2010-10-15 19:05:16 +02:00
}
2013-10-29 11:46:54 +01:00
}
2010-10-15 19:05:16 +02:00
}
}
2009-04-20 15:58:15 +02:00
void
2015-07-28 14:59:55 +02:00
DynamicModel : : writeParamsDerivativesFile ( const string & basename , bool julia ) const
2009-12-16 18:13:23 +01:00
{
2018-11-15 16:39:53 +01:00
if ( ! params_derivatives . size ( ) )
2009-12-16 18:13:23 +01:00
return ;
2009-04-20 15:58:15 +02:00
2018-09-05 18:27:13 +02:00
ExprNodeOutputType output_type = ( julia ? ExprNodeOutputType : : juliaDynamicModel : ExprNodeOutputType : : matlabDynamicModel ) ;
2019-12-20 16:59:30 +01:00
ostringstream tt_output ; // Used for storing model temp vars and equations
ostringstream rp_output ; // 1st deriv. of residuals w.r.t. parameters
ostringstream gp_output ; // 1st deriv. of Jacobian w.r.t. parameters
ostringstream rpp_output ; // 2nd deriv of residuals w.r.t. parameters
ostringstream gpp_output ; // 2nd deriv of Jacobian w.r.t. parameters
ostringstream hp_output ; // 1st deriv. of Hessian w.r.t. parameters
ostringstream g3p_output ; // 1st deriv. of 3rd deriv. matrix w.r.t. parameters
2009-09-08 10:06:06 +02:00
2018-11-16 16:53:07 +01:00
temporary_terms_t temp_term_union ;
2011-04-12 16:41:29 +02:00
deriv_node_temp_terms_t tef_terms ;
2011-03-07 11:59:12 +01:00
2018-11-16 18:13:34 +01:00
writeModelLocalVariableTemporaryTerms ( temp_term_union , params_derivs_temporary_terms_idxs , tt_output , output_type , tef_terms ) ;
2018-11-30 12:22:13 +01:00
for ( const auto & it : params_derivs_temporary_terms )
writeTemporaryTerms ( it . second , temp_term_union , params_derivs_temporary_terms_idxs , tt_output , output_type , tef_terms ) ;
2009-09-08 10:06:06 +02:00
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d1 ] : params_derivatives . find ( { 0 , 1 } ) - > second )
2009-12-16 18:13:23 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , param ] = vectorToTuple < 2 > ( indices ) ;
2009-09-08 10:06:06 +02:00
2009-12-16 18:13:23 +01:00
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2009-04-20 15:58:15 +02:00
2019-08-22 15:55:00 +02:00
rp_output < < " rp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < eq + 1 < < " , " < < param_col
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d1 - > writeOutput ( rp_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
rp_output < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
}
2009-04-20 15:58:15 +02:00
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 1 , 1 } ) - > second )
2010-03-16 10:15:19 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var , param ] = vectorToTuple < 3 > ( indices ) ;
2010-03-16 10:15:19 +01:00
2010-06-07 16:42:27 +02:00
int var_col = getDynJacobianCol ( var ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2010-03-16 10:15:19 +01:00
2019-08-22 15:55:00 +02:00
gp_output < < " gp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < eq + 1 < < " , " < < var_col
< < " , " < < param_col < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d2 - > writeOutput ( gp_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
gp_output < < " ; " < < endl ;
2010-03-16 10:15:19 +01:00
}
2010-06-07 18:46:57 +02:00
int i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 0 , 2 } ) - > second )
2009-12-16 18:13:23 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , param1 , param2 ] = vectorToTuple < 3 > ( indices ) ;
2009-04-20 15:58:15 +02:00
2010-06-07 16:42:27 +02:00
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
2009-04-30 15:14:33 +02:00
2019-08-22 15:55:00 +02:00
rpp_output < < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d2 - > writeOutput ( rpp_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
rpp_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 15:41:11 +01:00
if ( param1 ! = param2 )
{
// Treat symmetric elements
2019-08-22 15:55:00 +02:00
rpp_output < < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =rpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
2018-11-22 15:41:11 +01:00
i + + ;
}
2009-12-16 18:13:23 +01:00
}
2009-07-21 17:50:12 +02:00
2010-06-07 18:46:57 +02:00
i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 1 , 2 } ) - > second )
2010-03-15 16:02:07 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var , param1 , param2 ] = vectorToTuple < 4 > ( indices ) ;
2010-03-15 16:02:07 +01:00
int var_col = getDynJacobianCol ( var ) + 1 ;
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
2019-08-22 15:55:00 +02:00
gpp_output < < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d2 - > writeOutput ( gpp_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
gpp_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 15:41:11 +01:00
if ( param1 ! = param2 )
{
// Treat symmetric elements
2019-08-22 15:55:00 +02:00
gpp_output < < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param2_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param1_col < < " ; " < < endl
< < " gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =gpp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
2018-11-22 15:41:11 +01:00
i + + ;
}
2010-03-15 16:02:07 +01:00
}
2010-03-11 16:46:19 +01:00
2010-06-07 18:46:57 +02:00
i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 2 , 1 } ) - > second )
2010-03-11 16:46:19 +01:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var1 , var2 , param ] = vectorToTuple < 4 > ( indices ) ;
2010-03-11 16:46:19 +01:00
int var1_col = getDynJacobianCol ( var1 ) + 1 ;
int var2_col = getDynJacobianCol ( var2 ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
2019-08-22 15:55:00 +02:00
hp_output < < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var1_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var2_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d2 - > writeOutput ( hp_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
hp_output < < " ; " < < endl ;
2018-06-05 15:34:34 +02:00
i + + ;
2018-11-22 17:49:47 +01:00
if ( var1 ! = var2 )
{
// Treat symmetric elements
2019-08-22 15:55:00 +02:00
hp_output < < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var2_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var1_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param_col < < " ; " < < endl
< < " hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type )
< < " =hp " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i - 1 < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " ; " < < endl ;
2018-11-22 17:49:47 +01:00
i + + ;
}
2010-03-11 16:46:19 +01:00
}
2019-08-22 17:00:36 +02:00
i = 1 ;
2019-12-16 19:42:59 +01:00
for ( const auto & [ indices , d2 ] : params_derivatives . find ( { 3 , 1 } ) - > second )
2019-08-22 17:00:36 +02:00
{
2019-12-16 19:42:59 +01:00
auto [ eq , var1 , var2 , var3 , param ] = vectorToTuple < 5 > ( indices ) ;
2019-08-22 17:00:36 +02:00
int var1_col = getDynJacobianCol ( var1 ) + 1 ;
int var2_col = getDynJacobianCol ( var2 ) + 1 ;
int var3_col = getDynJacobianCol ( var3 ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
g3p_output < < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,1 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < eq + 1 < < " ; " < < endl
< < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,2 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var1_col < < " ; " < < endl
< < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,3 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var2_col < < " ; " < < endl
< < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,4 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < var3_col < < " ; " < < endl
< < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,5 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " < < param_col < < " ; " < < endl
< < " g3p " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < " ,6 "
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) < < " = " ;
d2 - > writeOutput ( g3p_output , output_type , temp_term_union , params_derivs_temporary_terms_idxs , tef_terms ) ;
g3p_output < < " ; " < < endl ;
i + + ;
}
2018-06-27 15:01:31 +02:00
string filename = julia ? basename + " DynamicParamsDerivs.jl " : packageDir ( basename ) + " /dynamic_params_derivs.m " ;
2017-01-05 17:31:48 +01:00
ofstream paramsDerivsFile ;
2018-06-27 15:12:12 +02:00
paramsDerivsFile . open ( filename , ios : : out | ios : : binary ) ;
2017-01-05 17:31:48 +01:00
if ( ! paramsDerivsFile . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( ! julia )
{
// Check that we don't have more than 32 nested parenthesis because Matlab does not suppor this. See Issue #1201
map < string , string > tmp_paren_vars ;
bool message_printed = false ;
2018-11-16 18:13:34 +01:00
fixNestedParenthesis ( tt_output , tmp_paren_vars , message_printed ) ;
2019-08-22 15:55:00 +02:00
fixNestedParenthesis ( rp_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( gp_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( rpp_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( gpp_output , tmp_paren_vars , message_printed ) ;
fixNestedParenthesis ( hp_output , tmp_paren_vars , message_printed ) ;
2019-08-22 17:00:36 +02:00
fixNestedParenthesis ( g3p_output , tmp_paren_vars , message_printed ) ;
paramsDerivsFile < < " function [rp, gp, rpp, gpp, hp, g3p] = dynamic_params_derivs(y, x, params, steady_state, it_, ss_param_deriv, ss_param_2nd_deriv) " < < endl
2017-01-05 17:31:48 +01:00
< < " % " < < endl
< < " % Compute the derivatives of the dynamic model with respect to the parameters " < < endl
< < " % Inputs : " < < endl
< < " % y [#dynamic variables by 1] double vector of endogenous variables in the order stored " < < endl
< < " % in M_.lead_lag_incidence; see the Manual " < < endl
< < " % x [nperiods by M_.exo_nbr] double matrix of exogenous variables (in declaration order) " < < endl
< < " % for all simulation periods " < < endl
< < " % params [M_.param_nbr by 1] double vector of parameter values in declaration order " < < endl
< < " % steady_state [M_.endo_nbr by 1] double vector of steady state values " < < endl
< < " % it_ scalar double time period for exogenous variables for which to evaluate the model " < < endl
< < " % ss_param_deriv [M_.eq_nbr by #params] Jacobian matrix of the steady states values with respect to the parameters " < < endl
< < " % ss_param_2nd_deriv [M_.eq_nbr by #params by #params] Hessian matrix of the steady states values with respect to the parameters " < < endl
< < " % " < < endl
< < " % Outputs: " < < endl
< < " % rp [M_.eq_nbr by #params] double Jacobian matrix of dynamic model equations with respect to parameters " < < endl
< < " % Dynare may prepend or append auxiliary equations, see M_.aux_vars " < < endl
< < " % gp [M_.endo_nbr by #dynamic variables by #params] double Derivative of the Jacobian matrix of the dynamic model equations with respect to the parameters " < < endl
< < " % rows: equations in order of declaration " < < endl
< < " % columns: variables in order stored in M_.lead_lag_incidence " < < endl
< < " % rpp [#second_order_residual_terms by 4] double Hessian matrix of second derivatives of residuals with respect to parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: number of the first parameter in derivative " < < endl
< < " % 3rd column: number of the second parameter in derivative " < < endl
< < " % 4th column: value of the Hessian term " < < endl
< < " % gpp [#second_order_Jacobian_terms by 5] double Hessian matrix of second derivatives of the Jacobian with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of variable in Jacobian of the dynamic model " < < endl
< < " % 3rd column: number of the first parameter in derivative " < < endl
< < " % 4th column: number of the second parameter in derivative " < < endl
< < " % 5th column: value of the Hessian term " < < endl
< < " % hp [#first_order_Hessian_terms by 5] double Jacobian matrix of derivatives of the dynamic Hessian with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of first variable in Hessian of the dynamic model " < < endl
< < " % 3rd column: column number of second variable in Hessian of the dynamic model " < < endl
< < " % 4th column: number of the parameter in derivative " < < endl
< < " % 5th column: value of the Hessian term " < < endl
2019-08-22 17:00:36 +02:00
< < " % g3p [#first_order_g3_terms by 6] double Jacobian matrix of derivatives of g3 (dynamic 3rd derivs) with respect to the parameters; " < < endl
< < " % rows: respective derivative term " < < endl
< < " % 1st column: equation number of the term appearing " < < endl
< < " % 2nd column: column number of first variable in g3 of the dynamic model " < < endl
< < " % 3rd column: column number of second variable in g3 of the dynamic model " < < endl
< < " % 4th column: column number of third variable in g3 of the dynamic model " < < endl
< < " % 5th column: number of the parameter in derivative " < < endl
< < " % 6th column: value of the Hessian term " < < endl
2017-01-05 17:31:48 +01:00
< < " % " < < endl
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
2018-05-28 15:23:15 +02:00
< < " T = NaN( " < < params_derivs_temporary_terms_idxs . size ( ) < < " ,1); " < < endl
2018-11-16 18:13:34 +01:00
< < tt_output . str ( )
2017-02-24 11:20:54 +01:00
< < " rp = zeros( " < < equations . size ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
2019-08-22 15:55:00 +02:00
< < rp_output . str ( )
2017-02-24 11:20:54 +01:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < dynJacobianColsNbr < < " , " < < symbol_table . param_nbr ( ) < < " ); " < < endl
2019-08-22 15:55:00 +02:00
< < gp_output . str ( )
2017-01-05 17:31:48 +01:00
< < " if nargout >= 3 " < < endl
2018-11-15 16:39:53 +01:00
< < " rpp = zeros( " < < params_derivatives . find ( { 0 , 2 } ) - > second . size ( ) < < " ,4); " < < endl
2019-08-22 15:55:00 +02:00
< < rpp_output . str ( )
2018-11-15 16:39:53 +01:00
< < " gpp = zeros( " < < params_derivatives . find ( { 1 , 2 } ) - > second . size ( ) < < " ,5); " < < endl
2019-08-22 15:55:00 +02:00
< < gpp_output . str ( )
2017-01-05 17:31:48 +01:00
< < " end " < < endl
< < " if nargout >= 5 " < < endl
2018-11-15 16:39:53 +01:00
< < " hp = zeros( " < < params_derivatives . find ( { 2 , 1 } ) - > second . size ( ) < < " ,5); " < < endl
2019-08-22 15:55:00 +02:00
< < hp_output . str ( )
2017-01-05 17:31:48 +01:00
< < " end " < < endl
2019-08-22 17:00:36 +02:00
< < " if nargout >= 6 " < < endl
< < " g3p = zeros( " < < params_derivatives . find ( { 3 , 1 } ) - > second . size ( ) < < " ,6); " < < endl
< < g3p_output . str ( )
< < " end " < < endl
2017-01-05 17:31:48 +01:00
< < " end " < < endl ;
}
else
paramsDerivsFile < < " module " < < basename < < " DynamicParamsDerivs " < < endl
< < " # " < < endl
< < " # NB: this file was automatically generated by Dynare " < < endl
< < " # from " < < basename < < " .mod " < < endl
< < " # " < < endl
< < " export params_derivs " < < endl < < endl
< < " function params_derivs(y, x, paramssteady_state, it_, "
< < " ss_param_deriv, ss_param_2nd_deriv) " < < endl
2018-11-16 18:13:34 +01:00
< < tt_output . str ( )
2017-02-24 11:20:54 +01:00
< < " rp = zeros( " < < equations . size ( ) < < " , "
2017-01-05 17:31:48 +01:00
< < symbol_table . param_nbr ( ) < < " ); " < < endl
2019-08-22 15:55:00 +02:00
< < rp_output . str ( )
2017-02-24 11:20:54 +01:00
< < " gp = zeros( " < < equations . size ( ) < < " , " < < dynJacobianColsNbr < < " , " < < symbol_table . param_nbr ( ) < < " ); " < < endl
2019-08-22 15:55:00 +02:00
< < gp_output . str ( )
2018-11-15 16:39:53 +01:00
< < " rpp = zeros( " < < params_derivatives . find ( { 0 , 2 } ) - > second . size ( ) < < " ,4); " < < endl
2019-08-22 15:55:00 +02:00
< < rpp_output . str ( )
2018-11-15 16:39:53 +01:00
< < " gpp = zeros( " < < params_derivatives . find ( { 1 , 2 } ) - > second . size ( ) < < " ,5); " < < endl
2019-08-22 15:55:00 +02:00
< < gpp_output . str ( )
2018-11-15 16:39:53 +01:00
< < " hp = zeros( " < < params_derivatives . find ( { 2 , 1 } ) - > second . size ( ) < < " ,5); " < < endl
2019-08-22 15:55:00 +02:00
< < hp_output . str ( )
2019-08-22 17:00:36 +02:00
< < " g3p = zeros( " < < params_derivatives . find ( { 3 , 1 } ) - > second . size ( ) < < " ,6); " < < endl
< < g3p_output . str ( )
< < " (rp, gp, rpp, gpp, hp, g3p) " < < endl
2017-01-05 17:31:48 +01:00
< < " end " < < endl
< < " end " < < endl ;
2009-12-16 18:13:23 +01:00
paramsDerivsFile . close ( ) ;
}
2009-07-21 17:50:12 +02:00
2009-04-30 15:14:33 +02:00
void
2019-12-16 19:42:59 +01:00
DynamicModel : : writeLatexFile ( const string & basename , bool write_equation_tags ) const
2009-12-16 18:13:23 +01:00
{
2019-07-11 17:33:53 +02:00
writeLatexModelFile ( basename , " dynamic " , ExprNodeOutputType : : latexDynamicModel , write_equation_tags ) ;
2009-12-16 18:13:23 +01:00
}
2009-07-07 16:20:48 +02:00
2015-02-16 08:31:30 +01:00
void
2019-12-16 19:42:59 +01:00
DynamicModel : : writeLatexOriginalFile ( const string & basename , bool write_equation_tags ) const
2015-02-16 08:31:30 +01:00
{
2019-07-11 17:33:53 +02:00
writeLatexModelFile ( basename , " original " , ExprNodeOutputType : : latexDynamicModel , write_equation_tags ) ;
2015-02-16 08:31:30 +01:00
}
2009-09-30 17:10:31 +02:00
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteEndoLeadGreaterThanTwo ( bool deterministic_model )
2009-09-30 17:10:31 +02:00
{
2018-12-20 17:04:28 +01:00
substituteLeadLagInternal ( AuxVarType : : endoLead , deterministic_model , { } ) ;
2009-10-07 16:07:13 +02:00
}
2009-09-30 17:10:31 +02:00
2009-10-07 16:07:13 +02:00
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteEndoLagGreaterThanTwo ( bool deterministic_model )
2009-10-07 16:07:13 +02:00
{
2018-12-20 17:04:28 +01:00
substituteLeadLagInternal ( AuxVarType : : endoLag , deterministic_model , { } ) ;
2009-10-07 16:07:13 +02:00
}
2009-09-30 17:10:31 +02:00
2009-10-07 16:07:13 +02:00
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteExoLead ( bool deterministic_model )
2009-10-07 16:07:13 +02:00
{
2018-12-20 17:04:28 +01:00
substituteLeadLagInternal ( AuxVarType : : exoLead , deterministic_model , { } ) ;
2009-09-30 17:10:31 +02:00
}
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteExoLag ( bool deterministic_model )
2009-10-07 18:34:42 +02:00
{
2018-12-20 17:04:28 +01:00
substituteLeadLagInternal ( AuxVarType : : exoLag , deterministic_model , { } ) ;
2009-10-07 18:34:42 +02:00
}
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteLeadLagInternal ( AuxVarType type , bool deterministic_model , const vector < string > & subset )
2009-09-30 17:10:31 +02:00
{
ExprNode : : subst_table_t subst_table ;
vector < BinaryOpNode * > neweqs ;
2010-10-11 12:52:27 +02:00
// Substitute in used model local variables
set < int > used_local_vars ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectVariables ( SymbolType : : modelLocalVariable , used_local_vars ) ;
2010-10-11 12:52:27 +02:00
2018-06-04 12:26:16 +02:00
for ( int used_local_var : used_local_vars )
2009-10-07 16:07:13 +02:00
{
2018-06-04 12:26:16 +02:00
const expr_t value = local_variables_table . find ( used_local_var ) - > second ;
2010-09-16 19:18:45 +02:00
expr_t subst ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 16:07:13 +02:00
{
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLead :
2010-10-11 12:52:27 +02:00
subst = value - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLag :
2010-10-11 12:52:27 +02:00
subst = value - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLead :
2010-10-11 12:52:27 +02:00
subst = value - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLag :
2010-10-11 12:52:27 +02:00
subst = value - > substituteExoLag ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : diffForward :
2013-05-17 16:51:34 +02:00
subst = value - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
break ;
2009-11-02 19:31:50 +01:00
default :
cerr < < " DynamicModel::substituteLeadLagInternal: impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-10-07 16:07:13 +02:00
}
2018-06-04 12:26:16 +02:00
local_variables_table [ used_local_var ] = subst ;
2009-10-07 16:07:13 +02:00
}
2009-09-30 17:10:31 +02:00
// Substitute in equations
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t subst ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 16:07:13 +02:00
{
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLead :
2018-06-04 12:26:16 +02:00
subst = equation - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLag :
2018-06-04 12:26:16 +02:00
subst = equation - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLead :
2018-06-04 12:26:16 +02:00
subst = equation - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLag :
2018-06-04 12:26:16 +02:00
subst = equation - > substituteExoLag ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : diffForward :
2018-06-04 12:26:16 +02:00
subst = equation - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
break ;
2009-11-02 19:31:50 +01:00
default :
cerr < < " DynamicModel::substituteLeadLagInternal: impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-10-07 16:07:13 +02:00
}
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( subst ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2009-09-30 17:10:31 +02:00
}
// Add new equations
2019-12-20 16:59:30 +01:00
for ( auto & neweq : neweqs )
2019-12-03 14:19:32 +01:00
{
addEquation ( neweq , - 1 ) ;
aux_equations . push_back ( neweq ) ;
}
2009-09-30 17:10:31 +02:00
2018-12-20 17:04:28 +01:00
if ( neweqs . size ( ) > 0 )
2009-10-07 16:07:13 +02:00
{
cout < < " Substitution of " ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 16:07:13 +02:00
{
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLead :
2009-10-07 16:07:13 +02:00
cout < < " endo leads >= 2 " ;
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : endoLag :
2009-10-07 16:07:13 +02:00
cout < < " endo lags >= 2 " ;
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLead :
2009-10-07 18:34:42 +02:00
cout < < " exo leads " ;
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : exoLag :
2009-10-07 18:34:42 +02:00
cout < < " exo lags " ;
2009-10-07 16:07:13 +02:00
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : expectation :
2009-10-30 06:21:54 +01:00
cout < < " expectation " ;
break ;
2018-07-17 17:38:26 +02:00
case AuxVarType : : diffForward :
2013-04-25 18:09:31 +02:00
cout < < " forward vars " ;
break ;
2016-11-25 17:15:13 +01:00
default :
cerr < < " DynamicModel::substituteLeadLagInternal: impossible case " < < endl ;
2011-03-21 18:40:57 +01:00
exit ( EXIT_FAILURE ) ;
2009-10-07 16:07:13 +02:00
}
cout < < " : added " < < neweqs . size ( ) < < " auxiliary variables and equations. " < < endl ;
}
2009-09-30 17:10:31 +02:00
}
2017-06-12 14:56:44 +02:00
void
2018-01-30 10:06:56 +01:00
DynamicModel : : substituteAdl ( )
2017-06-12 14:56:44 +02:00
{
2021-02-19 17:45:02 +01:00
/* Contrary to other substitution methods, we do the substitution in MLV
definitions here , instead of doing it at the ExprNode method level ,
because otherwise this would substitute MLV in the original model ( see
# 65). * /
for ( auto & [ id , definition ] : local_variables_table )
definition = definition - > substituteAdl ( ) ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( equation - > substituteAdl ( ) ) ;
2018-01-30 10:06:56 +01:00
}
2020-11-10 18:04:05 +01:00
void
DynamicModel : : substituteModelLocalVariables ( )
{
for ( auto & equation : equations )
equation = dynamic_cast < BinaryOpNode * > ( equation - > substituteModelLocalVariables ( ) ) ;
/* We can’ t clear local_variables_table at this point, because in case of
ramsey_policy , the original model is saved via DynamicModel : : operator = ( )
before computing the FOC . But since DataTree : : operator = ( ) clones all
nodes , it will try to clone nodes containing model - local variables , and
this will fail at the point where DataTree methods try to evaluate those
nodes to a numerical value . */
}
2020-02-20 15:29:10 +01:00
set < int >
2019-08-19 14:51:21 +02:00
DynamicModel : : getEquationNumbersFromTags ( const set < string > & eqtags ) const
2018-05-30 16:48:08 +02:00
{
2020-02-20 15:29:10 +01:00
set < int > eqnumbers ;
2019-12-20 16:59:30 +01:00
for ( auto & eqtag : eqtags )
2019-11-18 17:13:49 +01:00
{
2020-02-20 15:29:10 +01:00
set < int > tmp = equation_tags . getEqnsByTag ( " name " , eqtag ) ;
if ( tmp . empty ( ) )
2018-06-05 16:38:37 +02:00
{
2019-11-18 17:13:49 +01:00
cerr < < " ERROR: looking for equation tag " < < eqtag < < " failed. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-06-05 16:38:37 +02:00
}
2020-02-20 15:29:10 +01:00
eqnumbers . insert ( tmp . begin ( ) , tmp . end ( ) ) ;
2019-11-18 17:13:49 +01:00
}
2019-08-19 14:51:21 +02:00
return eqnumbers ;
2018-06-05 18:38:53 +02:00
}
void
2020-02-20 15:29:10 +01:00
DynamicModel : : findPacExpectationEquationNumbers ( set < int > & eqnumbers ) const
2018-06-05 18:38:53 +02:00
{
int i = 0 ;
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-06-05 18:38:53 +02:00
{
2019-12-20 16:59:30 +01:00
if ( equation - > containsPacExpectation ( )
& & find ( eqnumbers . begin ( ) , eqnumbers . end ( ) , i ) = = eqnumbers . end ( ) )
2020-02-20 15:29:10 +01:00
eqnumbers . insert ( i ) ;
2018-06-05 18:38:53 +02:00
i + + ;
}
}
2019-10-22 14:56:28 +02:00
pair < lag_equivalence_table_t , ExprNode : : subst_table_t >
DynamicModel : : substituteUnaryOps ( )
2018-06-07 12:53:00 +02:00
{
vector < int > eqnumbers ( equations . size ( ) ) ;
iota ( eqnumbers . begin ( ) , eqnumbers . end ( ) , 0 ) ;
2019-10-22 14:56:28 +02:00
return substituteUnaryOps ( eqnumbers ) ;
2018-06-07 12:53:00 +02:00
}
2019-10-22 14:56:28 +02:00
pair < lag_equivalence_table_t , ExprNode : : subst_table_t >
DynamicModel : : substituteUnaryOps ( const set < string > & var_model_eqtags )
2018-06-07 12:53:00 +02:00
{
2020-02-20 15:29:10 +01:00
set < int > eqnumbers = getEquationNumbersFromTags ( var_model_eqtags ) ;
2018-06-07 12:53:00 +02:00
findPacExpectationEquationNumbers ( eqnumbers ) ;
2020-02-20 15:29:10 +01:00
vector < int > eqnumbers_vec ( eqnumbers . begin ( ) , eqnumbers . end ( ) ) ;
return substituteUnaryOps ( eqnumbers_vec ) ;
2018-06-07 12:53:00 +02:00
}
2019-10-22 14:56:28 +02:00
pair < lag_equivalence_table_t , ExprNode : : subst_table_t >
DynamicModel : : substituteUnaryOps ( const vector < int > & eqnumbers )
2018-06-05 18:38:53 +02:00
{
2019-10-22 14:56:28 +02:00
lag_equivalence_table_t nodes ;
2019-08-19 14:51:21 +02:00
ExprNode : : subst_table_t subst_table ;
2019-08-19 18:22:55 +02:00
// Mark unary ops to be substituted in model local variables that appear in selected equations
2018-06-05 16:38:37 +02:00
set < int > used_local_vars ;
2018-06-07 12:53:00 +02:00
for ( int eqnumber : eqnumbers )
2018-07-17 18:34:07 +02:00
equations [ eqnumber ] - > collectVariables ( SymbolType : : modelLocalVariable , used_local_vars ) ;
2020-07-08 12:13:35 +02:00
for ( int mlv : used_local_vars )
local_variables_table [ mlv ] - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
2019-08-19 18:22:55 +02:00
// Mark unary ops to be substituted in selected equations
2018-06-07 12:53:00 +02:00
for ( int eqnumber : eqnumbers )
2019-10-22 14:56:28 +02:00
equations [ eqnumber ] - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
// Substitute in model local variables
vector < BinaryOpNode * > neweqs ;
2020-07-08 12:13:35 +02:00
for ( int mlv : used_local_vars )
local_variables_table [ mlv ] = local_variables_table [ mlv ] - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
// Substitute in equations
2020-07-08 12:13:35 +02:00
for ( int eq : eqnumbers )
2018-05-30 16:48:08 +02:00
{
2020-07-08 12:13:35 +02:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equations [ eq ] - >
2019-12-16 19:42:59 +01:00
substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ) ;
assert ( substeq ) ;
2020-07-08 12:13:35 +02:00
equations [ eq ] = substeq ;
2018-05-30 16:48:08 +02:00
}
// Add new equations
2019-12-20 16:59:30 +01:00
for ( auto & neweq : neweqs )
2019-12-03 14:19:32 +01:00
{
addEquation ( neweq , - 1 ) ;
aux_equations . push_back ( neweq ) ;
}
2018-05-30 16:48:08 +02:00
2018-12-20 17:04:28 +01:00
if ( subst_table . size ( ) > 0 )
2018-05-30 16:48:08 +02:00
cout < < " Substitution of Unary Ops: added " < < neweqs . size ( ) < < " auxiliary variables and equations. " < < endl ;
2019-08-19 14:51:21 +02:00
return { nodes , subst_table } ;
2018-05-30 16:48:08 +02:00
}
2019-10-22 14:56:28 +02:00
pair < lag_equivalence_table_t , ExprNode : : subst_table_t >
DynamicModel : : substituteDiff ( vector < expr_t > & pac_growth )
2018-01-30 10:06:56 +01:00
{
2019-08-20 12:50:41 +02:00
/* Note: at this point, we know that there is no diff operator with a lead,
because they have been expanded by DataTree : : AddDiff ( ) .
Hence we can go forward with the substitution without worrying about the
expectation operator . */
2019-10-22 14:56:28 +02:00
lag_equivalence_table_t diff_nodes ;
2019-08-19 14:51:21 +02:00
ExprNode : : subst_table_t diff_subst_table ;
2019-08-20 12:50:41 +02:00
// Mark diff operators to be substituted in model local variables
2018-06-05 18:38:53 +02:00
set < int > used_local_vars ;
2019-12-20 16:59:30 +01:00
for ( const auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectVariables ( SymbolType : : modelLocalVariable , used_local_vars ) ;
2019-12-20 16:59:30 +01:00
for ( auto & it : local_variables_table )
2018-06-05 18:38:53 +02:00
if ( used_local_vars . find ( it . first ) ! = used_local_vars . end ( ) )
2019-10-22 14:56:28 +02:00
it . second - > findDiffNodes ( diff_nodes ) ;
2018-03-02 12:32:01 +01:00
2019-08-20 12:50:41 +02:00
// Mark diff operators to be substituted in equations
2019-12-20 16:59:30 +01:00
for ( const auto & equation : equations )
2019-10-22 14:56:28 +02:00
equation - > findDiffNodes ( diff_nodes ) ;
2018-01-30 10:06:56 +01:00
2019-12-20 16:59:30 +01:00
for ( const auto & gv : pac_growth )
2019-12-16 19:42:59 +01:00
if ( gv )
2019-11-07 20:17:49 +01:00
gv - > findDiffNodes ( diff_nodes ) ;
2018-01-30 10:06:56 +01:00
// Substitute in model local variables
2018-02-28 17:33:00 +01:00
vector < BinaryOpNode * > neweqs ;
2019-12-20 16:59:30 +01:00
for ( auto & it : local_variables_table )
2019-10-22 14:56:28 +02:00
it . second = it . second - > substituteDiff ( diff_nodes , diff_subst_table , neweqs ) ;
2018-01-30 10:06:56 +01:00
// Substitute in equations
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-01-30 10:06:56 +01:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - >
substituteDiff ( diff_nodes , diff_subst_table , neweqs ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2018-01-30 10:06:56 +01:00
}
2019-12-20 16:59:30 +01:00
for ( auto & it : pac_growth )
2019-12-16 19:42:59 +01:00
if ( it )
2019-10-22 14:56:28 +02:00
it = it - > substituteDiff ( diff_nodes , diff_subst_table , neweqs ) ;
2019-02-28 19:22:34 +01:00
2018-01-30 10:06:56 +01:00
// Add new equations
2019-12-20 16:59:30 +01:00
for ( auto & neweq : neweqs )
2019-12-03 14:19:32 +01:00
{
addEquation ( neweq , - 1 ) ;
aux_equations . push_back ( neweq ) ;
}
2018-03-02 16:40:19 +01:00
2018-12-20 17:04:28 +01:00
if ( diff_subst_table . size ( ) > 0 )
2018-01-30 10:06:56 +01:00
cout < < " Substitution of Diff operator: added " < < neweqs . size ( ) < < " auxiliary variables and equations. " < < endl ;
2019-08-19 14:51:21 +02:00
2019-10-22 14:56:28 +02:00
return { diff_nodes , diff_subst_table } ;
2017-06-12 14:56:44 +02:00
}
2009-10-29 18:16:10 +01:00
void
2018-12-20 17:04:28 +01:00
DynamicModel : : substituteExpectation ( bool partial_information_model )
2009-10-29 18:16:10 +01:00
{
ExprNode : : subst_table_t subst_table ;
vector < BinaryOpNode * > neweqs ;
2009-11-09 16:13:47 +01:00
// Substitute in model local variables
2019-12-20 16:59:30 +01:00
for ( auto & it : local_variables_table )
2018-06-04 12:26:16 +02:00
it . second = it . second - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-29 18:16:10 +01:00
// Substitute in equations
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2009-10-29 18:16:10 +01:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2009-10-29 18:16:10 +01:00
}
// Add new equations
2019-12-20 16:59:30 +01:00
for ( auto & neweq : neweqs )
2019-12-03 14:19:32 +01:00
{
addEquation ( neweq , - 1 ) ;
aux_equations . push_back ( neweq ) ;
}
2009-10-29 18:16:10 +01:00
2018-12-20 17:04:28 +01:00
if ( subst_table . size ( ) > 0 )
2009-11-09 16:13:47 +01:00
{
if ( partial_information_model )
cout < < " Substitution of Expectation operator: added " < < subst_table . size ( ) < < " auxiliary variables and " < < neweqs . size ( ) < < " auxiliary equations. " < < endl ;
else
cout < < " Substitution of Expectation operator: added " < < neweqs . size ( ) < < " auxiliary variables and equations. " < < endl ;
}
2009-10-29 18:16:10 +01:00
}
2009-11-07 19:37:11 +01:00
void
DynamicModel : : transformPredeterminedVariables ( )
{
2021-02-19 20:09:48 +01:00
for ( auto & [ id , definition ] : local_variables_table )
definition = definition - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2018-04-18 14:29:40 +02:00
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2009-11-07 19:37:11 +01:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > decreaseLeadsLagsPredeterminedVariables ( ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2009-11-07 19:37:11 +01:00
}
}
2010-10-15 19:05:16 +02:00
void
DynamicModel : : detrendEquations ( )
{
2013-10-29 11:46:54 +01:00
// We go backwards in the list of trend_vars, to deal correctly with I(2) processes
2019-12-11 16:21:18 +01:00
for ( auto it = nonstationary_symbols_map . crbegin ( ) ;
it ! = nonstationary_symbols_map . crend ( ) ; + + it )
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > detrend ( it - > first , it - > second . first , it - > second . second ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( substeq ) ;
2010-10-15 19:05:16 +02:00
}
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > removeTrendLeadLag ( trend_symbols_map ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( substeq ) ;
2010-10-15 19:05:16 +02:00
}
}
void
DynamicModel : : removeTrendVariableFromEquations ( )
{
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2019-12-16 19:42:59 +01:00
auto substeq = dynamic_cast < BinaryOpNode * > ( equation - > replaceTrendVar ( ) ) ;
assert ( substeq ) ;
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( substeq ) ;
2010-10-15 19:05:16 +02:00
}
}
2013-04-25 18:09:31 +02:00
void
2018-12-20 17:04:28 +01:00
DynamicModel : : differentiateForwardVars ( const vector < string > & subset )
2013-04-25 18:09:31 +02:00
{
2018-12-20 17:04:28 +01:00
substituteLeadLagInternal ( AuxVarType : : diffForward , true , subset ) ;
2013-04-25 18:09:31 +02:00
}
2009-09-30 17:10:31 +02:00
void
2010-09-16 19:00:48 +02:00
DynamicModel : : fillEvalContext ( eval_context_t & eval_context ) const
2009-09-30 17:10:31 +02:00
{
// First, auxiliary variables
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2009-09-30 17:10:31 +02:00
{
2018-11-28 14:32:26 +01:00
assert ( aux_equation - > op_code = = BinaryOpcode : : equal ) ;
2019-12-16 19:42:59 +01:00
auto auxvar = dynamic_cast < VariableNode * > ( aux_equation - > arg1 ) ;
assert ( auxvar ) ;
2009-09-30 17:10:31 +02:00
try
{
2018-11-28 14:32:26 +01:00
double val = aux_equation - > arg2 - > eval ( eval_context ) ;
eval_context [ auxvar - > symb_id ] = val ;
2009-09-30 17:10:31 +02:00
}
2009-12-16 18:13:23 +01:00
catch ( ExprNode : : EvalException & e )
2009-09-30 17:10:31 +02:00
{
// Do nothing
}
}
2009-07-10 17:37:51 +02:00
2009-09-30 17:10:31 +02:00
// Second, model local variables
2018-06-04 12:26:16 +02:00
for ( auto it : local_variables_table )
2009-09-30 17:10:31 +02:00
{
try
{
2018-06-04 12:26:16 +02:00
const expr_t expression = it . second ;
2009-09-30 17:10:31 +02:00
double val = expression - > eval ( eval_context ) ;
2018-06-04 12:26:16 +02:00
eval_context [ it . first ] = val ;
2009-09-30 17:10:31 +02:00
}
2009-12-16 18:13:23 +01:00
catch ( ExprNode : : EvalException & e )
2009-09-30 17:10:31 +02:00
{
// Do nothing
}
}
2010-10-15 19:05:16 +02:00
//Third, trend variables
2020-01-30 12:47:59 +01:00
for ( int trendVar : symbol_table . getTrendVarIds ( ) )
2019-12-20 16:59:30 +01:00
eval_context [ trendVar ] = 2 ; //not <= 0 bc of log, not 1 bc of powers
2009-09-30 17:10:31 +02:00
}
2011-10-14 14:35:32 +02:00
2013-04-11 17:07:39 +02:00
void
2020-02-20 15:29:10 +01:00
DynamicModel : : addStaticOnlyEquation ( expr_t eq , int lineno , const map < string , string > & eq_tags )
2013-04-11 17:07:39 +02:00
{
2019-12-16 19:42:59 +01:00
auto beq = dynamic_cast < BinaryOpNode * > ( eq ) ;
assert ( beq & & beq - > op_code = = BinaryOpcode : : equal ) ;
2013-04-11 17:07:39 +02:00
2020-02-20 15:29:10 +01:00
static_only_equations_equation_tags . add ( static_only_equations . size ( ) , eq_tags ) ;
2013-04-11 17:07:39 +02:00
static_only_equations . push_back ( beq ) ;
2014-01-27 16:41:43 +01:00
static_only_equations_lineno . push_back ( lineno ) ;
2013-04-11 17:07:39 +02:00
}
size_t
DynamicModel : : staticOnlyEquationsNbr ( ) const
{
return static_only_equations . size ( ) ;
}
size_t
DynamicModel : : dynamicOnlyEquationsNbr ( ) const
{
2020-02-20 15:29:10 +01:00
return equation_tags . getDynamicEqns ( ) . size ( ) ;
2013-04-11 17:07:39 +02:00
}
2015-05-10 18:16:11 +02:00
bool
2018-09-25 19:15:22 +02:00
DynamicModel : : isChecksumMatching ( const string & basename , bool block ) const
2015-05-10 18:16:11 +02:00
{
2019-10-07 15:20:07 +02:00
stringstream buffer ;
2015-05-10 18:16:11 +02:00
// Write equation tags
2020-02-20 15:29:10 +01:00
equation_tags . writeCheckSumInfo ( buffer ) ;
2013-09-17 15:11:57 +02:00
2020-06-17 16:49:12 +02:00
ExprNodeOutputType buffer_type = ExprNodeOutputType : : CDynamicModel ;
2013-09-17 15:11:57 +02:00
2019-10-07 15:57:19 +02:00
deriv_node_temp_terms_t tef_terms ;
temporary_terms_t temp_term_union ;
writeModelLocalVariableTemporaryTerms ( temp_term_union , temporary_terms_idxs ,
buffer , buffer_type , tef_terms ) ;
2015-05-10 18:16:11 +02:00
2019-10-07 15:57:19 +02:00
writeTemporaryTerms ( temporary_terms_derivatives [ 0 ] ,
temp_term_union , temporary_terms_idxs ,
buffer , buffer_type , tef_terms ) ;
2015-05-10 18:16:11 +02:00
2019-10-07 15:57:19 +02:00
writeModelEquations ( buffer , buffer_type , temp_term_union ) ;
2013-09-17 15:11:57 +02:00
2019-10-07 15:20:07 +02:00
size_t result = hash < string > { } ( buffer . str ( ) ) ;
2015-05-13 17:11:39 +02:00
2015-05-11 08:52:50 +02:00
// check whether basename directory exist. If not, create it.
2019-10-07 15:20:07 +02:00
// If it does, read old checksum if it exists, return if equal to result
2015-05-10 18:16:11 +02:00
fstream checksum_file ;
2019-10-07 15:20:07 +02:00
auto filename = filesystem : : path { basename } / " checksum " ;
if ( ! filesystem : : create_directory ( basename ) )
2015-05-11 08:52:50 +02:00
{
2018-06-27 15:12:12 +02:00
checksum_file . open ( filename , ios : : in | ios : : binary ) ;
2015-05-11 08:52:50 +02:00
if ( checksum_file . is_open ( ) )
2017-06-01 19:58:32 +02:00
{
2019-10-07 15:20:07 +02:00
size_t old_checksum ;
2017-06-01 19:58:32 +02:00
checksum_file > > old_checksum ;
checksum_file . close ( ) ;
2019-10-07 15:20:07 +02:00
if ( old_checksum = = result )
return true ;
2017-06-01 19:58:32 +02:00
}
2015-05-11 08:52:50 +02:00
}
2019-10-07 15:20:07 +02:00
2015-05-11 08:52:50 +02:00
// write new checksum file if none or different from old checksum
2019-10-07 15:20:07 +02:00
checksum_file . open ( filename , ios : : out | ios : : binary ) ;
if ( ! checksum_file . is_open ( ) )
2017-06-01 19:58:32 +02:00
{
2019-10-07 15:20:07 +02:00
cerr < < " ERROR: Can't open file " < < filename < < endl ;
exit ( EXIT_FAILURE ) ;
2017-06-01 19:58:32 +02:00
}
2019-10-07 15:20:07 +02:00
checksum_file < < result ;
checksum_file . close ( ) ;
return false ;
2015-05-10 18:16:11 +02:00
}
2015-07-21 17:26:08 +02:00
2017-02-02 15:09:43 +01:00
void
DynamicModel : : writeJsonOutput ( ostream & output ) const
{
2020-06-05 16:07:52 +02:00
deriv_node_temp_terms_t tef_terms ;
writeJsonModelLocalVariables ( output , false , tef_terms ) ;
output < < " , " ;
2017-02-20 12:18:11 +01:00
writeJsonModelEquations ( output , false ) ;
2017-03-10 17:23:35 +01:00
output < < " , " ;
writeJsonXrefs ( output ) ;
2018-09-18 14:50:31 +02:00
output < < " , " ;
writeJsonAST ( output ) ;
2019-10-16 17:34:27 +02:00
output < < " , " ;
writeJsonVariableMapping ( output ) ;
2018-09-18 14:50:31 +02:00
}
void
DynamicModel : : writeJsonAST ( ostream & output ) const
{
vector < pair < string , string > > eqtags ;
2019-04-03 16:32:52 +02:00
output < < R " ( " abstract_syntax_tree " :[) " < < endl ;
2019-04-23 11:07:32 +02:00
for ( int eq = 0 ; eq < static_cast < int > ( equations . size ( ) ) ; eq + + )
2018-09-18 14:50:31 +02:00
{
if ( eq ! = 0 )
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ({ " number " :) " < < eq
< < R " (, " line " :) " < < equations_lineno [ eq ] ;
2018-09-18 14:50:31 +02:00
2020-02-20 15:29:10 +01:00
equation_tags . writeJsonAST ( output , eq ) ;
2018-09-18 14:50:31 +02:00
2019-04-03 16:32:52 +02:00
output < < R " (, " AST " : ) " ;
2018-09-18 14:50:31 +02:00
equations [ eq ] - > writeJsonAST ( output ) ;
output < < " } " ;
}
output < < " ] " ;
2017-03-10 17:23:35 +01:00
}
2019-10-16 17:34:27 +02:00
void
DynamicModel : : writeJsonVariableMapping ( ostream & output ) const
{
output < < R " ( " variable_mapping " :[) " < < endl ;
2020-12-09 16:45:30 +01:00
for ( auto it = variableMapping . begin ( ) ; it ! = variableMapping . end ( ) ; + + it )
{
if ( it ! = variableMapping . begin ( ) )
output < < " , " ;
auto [ var , eqs ] = * it ;
output < < R " ({ " name " : " ) " << symbol_table.getName(var) << R " ( " , " equations " :[) " ;
bool first_eq = true ;
2021-02-10 16:48:46 +01:00
for ( int it2 : eqs )
if ( auto tmp = equation_tags . getTagValueByEqnAndKey ( it2 , " name " ) ;
2020-12-09 16:45:30 +01:00
! tmp . empty ( ) )
{
if ( first_eq )
first_eq = false ;
else
output < < " , " ;
output < < ' " ' < < tmp < < ' " ' ;
}
output < < " ]} " < < endl ;
2019-10-16 17:34:27 +02:00
}
output < < " ] " ;
}
2017-03-10 17:23:35 +01:00
void
2018-06-04 14:17:36 +02:00
DynamicModel : : writeJsonXrefsHelper ( ostream & output , const map < pair < int , int > , set < int > > & xrefs ) const
2017-03-10 17:23:35 +01:00
{
2019-12-16 19:42:59 +01:00
for ( auto it = xrefs . begin ( ) ; it ! = xrefs . end ( ) ; + + it )
2017-03-10 17:23:35 +01:00
{
2017-10-13 16:21:13 +02:00
if ( it ! = xrefs . begin ( ) )
2017-03-10 17:23:35 +01:00
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ({ " name " : " ) " << symbol_table.getName(it->first.first) << R " ( " ) "
< < R " (, " shift " : ) " < < it - > first . second
< < R " (, " equations " : [) " ;
2019-12-16 19:42:59 +01:00
for ( auto it1 = it - > second . begin ( ) ; it1 ! = it - > second . end ( ) ; + + it1 )
2017-03-10 17:23:35 +01:00
{
if ( it1 ! = it - > second . begin ( ) )
output < < " , " ;
output < < * it1 + 1 ;
}
output < < " ]} " ;
}
2017-10-13 16:21:13 +02:00
}
void
DynamicModel : : writeJsonXrefs ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ( " xrefs " : {) "
< < R " ( " parameters " : [) " ;
2017-10-13 16:21:13 +02:00
writeJsonXrefsHelper ( output , xref_param ) ;
2017-03-10 17:23:35 +01:00
output < < " ] "
2019-04-03 16:32:52 +02:00
< < R " (, " endogenous " : [) " ;
2017-10-13 16:21:13 +02:00
writeJsonXrefsHelper ( output , xref_endo ) ;
2017-03-10 17:23:35 +01:00
output < < " ] "
2019-04-03 16:32:52 +02:00
< < R " (, " exogenous " : [) " ;
2019-12-16 19:42:59 +01:00
writeJsonXrefsHelper ( output , xref_exo ) ;
2017-03-10 17:23:35 +01:00
output < < " ] "
2019-04-03 16:32:52 +02:00
< < R " (, " exogenous_deterministic " : [) " ;
2017-10-13 16:21:13 +02:00
writeJsonXrefsHelper ( output , xref_exo_det ) ;
2017-03-10 17:23:35 +01:00
output < < " ]} " < < endl ;
2017-02-20 12:18:11 +01:00
}
2017-06-23 14:20:48 +02:00
void
DynamicModel : : writeJsonOriginalModelOutput ( ostream & output ) const
{
writeJsonModelEquations ( output , false ) ;
2018-09-18 14:50:31 +02:00
output < < " , " ;
writeJsonAST ( output ) ;
2017-06-23 14:20:48 +02:00
}
2017-06-28 17:11:24 +02:00
void
DynamicModel : : writeJsonDynamicModelInfo ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ( " model_info " : {) "
< < R " ( " lead_lag_incidence " : [) " ;
2017-06-28 17:11:24 +02:00
// Loop on endogenous variables
int nstatic = 0 ,
2019-12-16 19:42:59 +01:00
nfwrd = 0 ,
npred = 0 ,
nboth = 0 ;
2017-06-28 17:11:24 +02:00
for ( int endoID = 0 ; endoID < symbol_table . endo_nbr ( ) ; endoID + + )
{
if ( endoID ! = 0 )
output < < " , " ;
output < < " [ " ;
int sstatic = 1 ,
2019-12-16 19:42:59 +01:00
sfwrd = 0 ,
spred = 0 ,
sboth = 0 ;
2017-06-28 17:11:24 +02:00
// Loop on periods
for ( int lag = - max_endo_lag ; lag < = max_endo_lead ; lag + + )
{
// Print variableID if exists with current period, otherwise print 0
try
{
if ( lag ! = - max_endo_lag )
output < < " , " ;
2018-07-17 18:34:07 +02:00
int varID = getDerivID ( symbol_table . getID ( SymbolType : : endogenous , endoID ) , lag ) ;
2017-06-28 17:11:24 +02:00
output < < " " < < getDynJacobianCol ( varID ) + 1 ;
if ( lag = = - 1 )
{
sstatic = 0 ;
spred = 1 ;
}
else if ( lag = = 1 )
{
if ( spred = = 1 )
{
sboth = 1 ;
spred = 0 ;
}
else
{
sstatic = 0 ;
sfwrd = 1 ;
}
}
}
catch ( UnknownDerivIDException & e )
{
output < < " 0 " ;
}
}
nstatic + = sstatic ;
2019-12-20 16:59:30 +01:00
nfwrd + = sfwrd ;
npred + = spred ;
nboth + = sboth ;
2017-06-28 17:11:24 +02:00
output < < " ] " ;
}
output < < " ], "
2020-07-02 09:32:50 +02:00
< < R " ( " nstatic " : ) " < < nstatic < < " , " < < endl
< < R " ( " nfwrd " : ) " < < nfwrd < < " , " < < endl
< < R " ( " npred " : ) " < < npred < < " , " < < endl
< < R " ( " nboth " : ) " < < nboth < < " , " < < endl
< < R " ( " nsfwrd " : ) " < < nfwrd + nboth < < " , " < < endl
< < R " ( " nspred " : ) " < < npred + nboth < < " , " < < endl
< < R " ( " ndynamic " : ) " < < npred + nboth + nfwrd < < " , " < < endl
< < R " ( " maximum_endo_lag " : ) " < < max_endo_lag < < " , " < < endl
< < R " ( " maximum_endo_lead " : ) " < < max_endo_lead < < " , " < < endl
< < R " ( " maximum_exo_lag " : ) " < < max_exo_lag < < " , " < < endl
< < R " ( " maximum_exo_lead " : ) " < < max_exo_lead < < " , " < < endl
< < R " ( " maximum_exo_det_lag " : ) " < < max_exo_det_lag < < " , " < < endl
< < R " ( " maximum_exo_det_lead " : ) " < < max_exo_det_lead < < " , " < < endl
< < R " ( " maximum_lag " : ) " < < max_lag < < " , " < < endl
< < R " ( " maximum_lead " : ) " < < max_lead < < " , " < < endl
< < R " ( " orig_maximum_endo_lag " : ) " < < max_endo_lag_orig < < " , " < < endl
< < R " ( " orig_maximum_endo_lead " : ) " < < max_endo_lead_orig < < " , " < < endl
< < R " ( " orig_maximum_exo_lag " : ) " < < max_exo_lag_orig < < " , " < < endl
< < R " ( " orig_maximum_exo_lead " : ) " < < max_exo_lead_orig < < " , " < < endl
< < R " ( " orig_maximum_exo_det_lag " : ) " < < max_exo_det_lag_orig < < " , " < < endl
< < R " ( " orig_maximum_exo_det_lead " : ) " < < max_exo_det_lead_orig < < " , " < < endl
< < R " ( " orig_maximum_lag " : ) " < < max_lag_orig < < " , " < < endl
< < R " ( " orig_maximum_lead " : ) " < < max_lead_orig < < " , " < < endl
< < R " ( " orig_maximum_lag_with_diffs_expanded " : ) " < < max_lag_with_diffs_expanded_orig
< < endl ;
2017-06-28 17:11:24 +02:00
output < < " } " ;
}
2017-02-20 12:18:11 +01:00
void
2017-03-02 18:34:18 +01:00
DynamicModel : : writeJsonComputingPassOutput ( ostream & output , bool writeDetails ) const
2017-02-20 12:18:11 +01:00
{
2019-12-20 16:59:30 +01:00
ostringstream model_local_vars_output ; // Used for storing model local vars
vector < ostringstream > d_output ( derivatives . size ( ) ) ; // Derivatives output (at all orders, including 0=residual)
2017-02-20 12:18:11 +01:00
deriv_node_temp_terms_t tef_terms ;
2019-04-18 14:34:48 +02:00
temporary_terms_t temp_term_union ;
2017-02-20 12:18:11 +01:00
2020-06-05 16:07:52 +02:00
writeJsonModelLocalVariables ( model_local_vars_output , true , tef_terms ) ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
writeJsonTemporaryTerms ( temporary_terms_derivatives [ 0 ] , temp_term_union , d_output [ 0 ] , tef_terms , " " ) ;
d_output [ 0 ] < < " , " ;
writeJsonModelEquations ( d_output [ 0 ] , true ) ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
int ncols = dynJacobianColsNbr ;
for ( size_t i = 1 ; i < derivatives . size ( ) ; i + + )
{
string matrix_name = i = = 1 ? " jacobian " : i = = 2 ? " hessian " : i = = 3 ? " third_derivative " : to_string ( i ) + " th_derivative " ;
writeJsonTemporaryTerms ( temporary_terms_derivatives [ i ] , temp_term_union , d_output [ i ] , tef_terms , matrix_name ) ;
temp_term_union . insert ( temporary_terms_derivatives [ i ] . begin ( ) , temporary_terms_derivatives [ i ] . end ( ) ) ;
d_output [ i ] < < R " (, " ) " << matrix_name << R " ( " : {) "
2019-04-03 16:32:52 +02:00
< < R " ( " nrows " : ) " < < equations . size ( )
2019-04-18 17:07:55 +02:00
< < R " (, " ncols " : ) " < < ncols
2019-04-03 16:32:52 +02:00
< < R " (, " entries " : [) " ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
for ( auto it = derivatives [ i ] . begin ( ) ; it ! = derivatives [ i ] . end ( ) ; + + it )
{
if ( it ! = derivatives [ i ] . begin ( ) )
d_output [ i ] < < " , " ;
2017-02-20 12:18:11 +01:00
2019-04-18 17:07:55 +02:00
const vector < int > & vidx = it - > first ;
expr_t d = it - > second ;
int eq = vidx [ 0 ] ;
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
int col_idx = 0 ;
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
{
col_idx * = dynJacobianColsNbr ;
col_idx + = getDynJacobianCol ( vidx [ j ] ) ;
}
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
if ( writeDetails )
d_output [ i ] < < R " ({ " eq " : ) " < < eq + 1 ;
else
d_output [ i ] < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-04-18 17:07:55 +02:00
d_output [ i ] < < R " (, " col " : ) " < < ( i > 1 ? " [ " : " " ) < < col_idx + 1 ;
if ( i = = 2 & & vidx [ 1 ] ! = vidx [ 2 ] ) // Symmetric elements in hessian
{
int col_idx_sym = getDynJacobianCol ( vidx [ 2 ] ) * dynJacobianColsNbr + getDynJacobianCol ( vidx [ 1 ] ) ;
d_output [ i ] < < " , " < < col_idx_sym + 1 ;
}
if ( i > 1 )
d_output [ i ] < < " ] " ;
if ( writeDetails )
for ( size_t j = 1 ; j < vidx . size ( ) ; j + + )
d_output [ i ] < < R " (, " var ) " << (i > 1 ? to_string(j) : " " ) << R " ( " : " ) " << symbol_table.getName(getSymbIDByDerivID(vidx[j])) << R " ( " ) "
2019-12-20 16:59:30 +01:00
< < R " (, " shift ) " << (i > 1 ? to_string(j) : " " ) << R " ( " : ) " < < getLagByDerivID ( vidx [ j ] ) ;
2019-04-18 17:07:55 +02:00
d_output [ i ] < < R " (, " val " : " ) " ;
d - > writeJsonOutput ( d_output [ i ] , temp_term_union , tef_terms ) ;
d_output [ i ] < < R " ( " } ) " << endl;
2017-03-02 18:34:18 +01:00
}
2019-12-20 16:59:30 +01:00
d_output [ i ] < < " ]} " ;
2019-04-18 17:07:55 +02:00
2019-12-20 16:59:30 +01:00
ncols * = dynJacobianColsNbr ;
2017-02-20 12:18:11 +01:00
}
2017-03-02 18:34:18 +01:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
output < < R " ( " dynamic_model " : {) " ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
output < < R " ( " dynamic_model_simple " : {) " ;
2019-04-18 17:07:55 +02:00
output < < model_local_vars_output . str ( ) ;
for ( const auto & it : d_output )
output < < " , " < < it . str ( ) ;
output < < " } " ;
2017-02-20 12:18:11 +01:00
}
void
2017-03-02 18:34:18 +01:00
DynamicModel : : writeJsonParamsDerivativesFile ( ostream & output , bool writeDetails ) const
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( ! params_derivatives . size ( ) )
2017-02-20 12:18:11 +01:00
return ;
2019-12-20 16:59:30 +01:00
ostringstream model_local_vars_output ; // Used for storing model local vars
ostringstream model_output ; // Used for storing model temp vars and equations
ostringstream rp_output ; // 1st deriv. of residuals w.r.t. parameters
ostringstream gp_output ; // 1st deriv. of Jacobian w.r.t. parameters
ostringstream rpp_output ; // 2nd deriv of residuals w.r.t. parameters
ostringstream gpp_output ; // 2nd deriv of Jacobian w.r.t. parameters
ostringstream hp_output ; // 1st deriv. of Hessian w.r.t. parameters
ostringstream g3p_output ; // 1st deriv. of 3rd deriv. matrix w.r.t. parameters
2017-02-20 12:18:11 +01:00
deriv_node_temp_terms_t tef_terms ;
2020-06-05 16:07:52 +02:00
writeJsonModelLocalVariables ( model_local_vars_output , true , tef_terms ) ;
2017-02-20 12:18:11 +01:00
2018-11-16 18:24:06 +01:00
temporary_terms_t temp_term_union ;
2018-11-30 12:22:13 +01:00
for ( const auto & it : params_derivs_temporary_terms )
2019-04-18 14:34:48 +02:00
writeJsonTemporaryTerms ( it . second , temp_term_union , model_output , tef_terms , " all " ) ;
2018-11-16 18:24:06 +01:00
2019-08-22 15:55:00 +02:00
rp_output < < R " ( " deriv_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & rp = params_derivatives . find ( { 0 , 1 } ) - > second ;
2019-12-16 19:42:59 +01:00
for ( auto it = rp . begin ( ) ; it ! = rp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = rp . begin ( ) )
2019-08-22 15:55:00 +02:00
rp_output < < " , " ;
2017-02-20 12:18:11 +01:00
2019-09-11 15:59:23 +02:00
auto [ eq , param ] = vectorToTuple < 2 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d1 = it - > second ;
2017-03-02 18:34:18 +01:00
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-08-22 15:55:00 +02:00
rp_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-08-22 15:55:00 +02:00
rp_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
rp_output < < R " (, " param_col " : ) " < < param_col + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-08-22 15:55:00 +02:00
rp_output < < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
rp_output < < R " (, " val " : " ) " ;
d1 - > writeJsonOutput ( rp_output , temp_term_union , tef_terms ) ;
rp_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
2019-08-22 15:55:00 +02:00
rp_output < < " ]} " ;
2018-11-15 16:39:53 +01:00
2019-08-22 15:55:00 +02:00
gp_output < < R " ( " deriv_jacobian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvarcols " : ) " < < dynJacobianColsNbr
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & gp = params_derivatives . find ( { 1 , 1 } ) - > second ;
2019-12-16 19:42:59 +01:00
for ( auto it = gp . begin ( ) ; it ! = gp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = gp . begin ( ) )
2019-08-22 15:55:00 +02:00
gp_output < < " , " ;
2017-02-20 12:18:11 +01:00
2019-09-11 15:59:23 +02:00
auto [ eq , var , param ] = vectorToTuple < 3 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var_col = getDynJacobianCol ( var ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-08-22 15:55:00 +02:00
gp_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-08-22 15:55:00 +02:00
gp_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
gp_output < < R " (, " var_col " : ) " < < var_col + 1
< < R " (, " param_col " : ) " < < param_col + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-08-22 15:55:00 +02:00
gp_output < < R " (, " var " : " ) " << symbol_table.getName(getSymbIDByDerivID(var)) << R " ( " ) "
< < R " (, " lag " : ) " < < getLagByDerivID ( var )
< < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
gp_output < < R " (, " val " : " ) " ;
d2 - > writeJsonOutput ( gp_output , temp_term_union , tef_terms ) ;
gp_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
2019-08-22 15:55:00 +02:00
gp_output < < " ]} " ;
2017-02-20 12:18:11 +01:00
2019-08-22 15:55:00 +02:00
rpp_output < < R " ( " second_deriv_residuals_wrt_params " : {) "
< < R " ( " nrows " : ) " < < equations . size ( )
< < R " (, " nparam1cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " nparam2cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & rpp = params_derivatives . find ( { 0 , 2 } ) - > second ;
for ( auto it = rpp . begin ( ) ; it ! = rpp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = rpp . begin ( ) )
2019-08-22 15:55:00 +02:00
rpp_output < < " , " ;
2017-02-20 12:18:11 +01:00
2019-09-11 15:59:23 +02:00
auto [ eq , param1 , param2 ] = vectorToTuple < 3 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
if ( writeDetails )
2019-08-22 15:55:00 +02:00
rpp_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-08-22 15:55:00 +02:00
rpp_output < < R " ({ " row " : ) " < < eq + 1 ;
rpp_output < < R " (, " param1_col " : ) " < < param1_col + 1
< < R " (, " param2_col " : ) " < < param2_col + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-08-22 15:55:00 +02:00
rpp_output < < R " (, " param1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param1)) << R " ( " ) "
< < R " (, " param2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param2)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
rpp_output < < R " (, " val " : " ) " ;
d2 - > writeJsonOutput ( rpp_output , temp_term_union , tef_terms ) ;
rpp_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
2019-08-22 15:55:00 +02:00
rpp_output < < " ]} " ;
2018-11-15 16:39:53 +01:00
2019-08-22 15:55:00 +02:00
gpp_output < < R " ( " second_deriv_jacobian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvarcols " : ) " < < dynJacobianColsNbr
< < R " (, " nparam1cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " nparam2cols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & gpp = params_derivatives . find ( { 1 , 2 } ) - > second ;
for ( auto it = gpp . begin ( ) ; it ! = gpp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = gpp . begin ( ) )
2019-08-22 15:55:00 +02:00
gpp_output < < " , " ;
2017-02-20 12:18:11 +01:00
2019-09-11 15:59:23 +02:00
auto [ eq , var , param1 , param2 ] = vectorToTuple < 4 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var_col = getDynJacobianCol ( var ) + 1 ;
int param1_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param1 ) ) + 1 ;
int param2_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param2 ) ) + 1 ;
if ( writeDetails )
2019-08-22 15:55:00 +02:00
gpp_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-08-22 15:55:00 +02:00
gpp_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
gpp_output < < R " (, " var_col " : ) " < < var_col + 1
< < R " (, " param1_col " : ) " < < param1_col + 1
< < R " (, " param2_col " : ) " < < param2_col + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-08-22 15:55:00 +02:00
gpp_output < < R " (, " var " : " ) " << symbol_table.getName(var) << R " ( " ) "
< < R " (, " lag " : ) " < < getLagByDerivID ( var )
< < R " (, " param1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param1)) << R " ( " ) "
< < R " (, " param2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(param2)) << R " ( " ) " ;
gpp_output < < R " (, " val " : " ) " ;
d2 - > writeJsonOutput ( gpp_output , temp_term_union , tef_terms ) ;
gpp_output < < R " ( " } ) " << endl;
}
gpp_output < < " ]} " < < endl ;
hp_output < < R " ( " derivative_hessian_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvar1cols " : ) " < < dynJacobianColsNbr
< < R " (, " nvar2cols " : ) " < < dynJacobianColsNbr
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
2018-11-15 16:39:53 +01:00
auto & hp = params_derivatives . find ( { 2 , 1 } ) - > second ;
for ( auto it = hp . begin ( ) ; it ! = hp . end ( ) ; + + it )
2017-02-20 12:18:11 +01:00
{
2018-11-15 16:39:53 +01:00
if ( it ! = hp . begin ( ) )
2019-08-22 15:55:00 +02:00
hp_output < < " , " ;
2017-02-20 12:18:11 +01:00
2019-09-11 15:59:23 +02:00
auto [ eq , var1 , var2 , param ] = vectorToTuple < 4 > ( it - > first ) ;
2017-02-20 12:18:11 +01:00
expr_t d2 = it - > second ;
2017-03-02 18:34:18 +01:00
int var1_col = getDynJacobianCol ( var1 ) + 1 ;
int var2_col = getDynJacobianCol ( var2 ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
2019-08-22 15:55:00 +02:00
hp_output < < R " ({ " eq " : ) " < < eq + 1 ;
2017-03-02 18:34:18 +01:00
else
2019-08-22 15:55:00 +02:00
hp_output < < R " ({ " row " : ) " < < eq + 1 ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
hp_output < < R " (, " var1_col " : ) " < < var1_col + 1
< < R " (, " var2_col " : ) " < < var2_col + 1
< < R " (, " param_col " : ) " < < param_col + 1 ;
2017-06-29 12:42:28 +02:00
if ( writeDetails )
2019-08-22 15:55:00 +02:00
hp_output < < R " (, " var1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var1)) << R " ( " ) "
< < R " (, " lag1 " : ) " < < getLagByDerivID ( var1 )
< < R " (, " var2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var2)) << R " ( " ) "
< < R " (, " lag2 " : ) " < < getLagByDerivID ( var2 )
< < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
2017-06-29 12:42:28 +02:00
2019-08-22 15:55:00 +02:00
hp_output < < R " (, " val " : " ) " ;
d2 - > writeJsonOutput ( hp_output , temp_term_union , tef_terms ) ;
hp_output < < R " ( " } ) " << endl;
2017-02-20 12:18:11 +01:00
}
2019-08-22 15:55:00 +02:00
hp_output < < " ]} " < < endl ;
2017-02-20 12:18:11 +01:00
2019-08-22 17:00:36 +02:00
g3p_output < < R " ( " derivative_g3_wrt_params " : {) "
< < R " ( " neqs " : ) " < < equations . size ( )
< < R " (, " nvar1cols " : ) " < < dynJacobianColsNbr
< < R " (, " nvar2cols " : ) " < < dynJacobianColsNbr
< < R " (, " nvar3cols " : ) " < < dynJacobianColsNbr
< < R " (, " nparamcols " : ) " < < symbol_table . param_nbr ( )
< < R " (, " entries " : [) " ;
auto & g3p = params_derivatives . find ( { 3 , 1 } ) - > second ;
for ( auto it = g3p . begin ( ) ; it ! = g3p . end ( ) ; + + it )
{
if ( it ! = g3p . begin ( ) )
g3p_output < < " , " ;
2019-09-11 15:59:23 +02:00
auto [ eq , var1 , var2 , var3 , param ] = vectorToTuple < 5 > ( it - > first ) ;
2019-08-22 17:00:36 +02:00
expr_t d2 = it - > second ;
int var1_col = getDynJacobianCol ( var1 ) + 1 ;
int var2_col = getDynJacobianCol ( var2 ) + 1 ;
int var3_col = getDynJacobianCol ( var3 ) + 1 ;
int param_col = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( param ) ) + 1 ;
if ( writeDetails )
g3p_output < < R " ({ " eq " : ) " < < eq + 1 ;
else
g3p_output < < R " ({ " row " : ) " < < eq + 1 ;
g3p_output < < R " (, " var1_col " : ) " < < var1_col + 1
< < R " (, " var2_col " : ) " < < var2_col + 1
< < R " (, " var3_col " : ) " < < var3_col + 1
< < R " (, " param_col " : ) " < < param_col + 1 ;
if ( writeDetails )
g3p_output < < R " (, " var1 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var1)) << R " ( " ) "
< < R " (, " lag1 " : ) " < < getLagByDerivID ( var1 )
< < R " (, " var2 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var2)) << R " ( " ) "
< < R " (, " lag2 " : ) " < < getLagByDerivID ( var2 )
< < R " (, " var3 " : " ) " << symbol_table.getName(getSymbIDByDerivID(var3)) << R " ( " ) "
< < R " (, " lag3 " : ) " < < getLagByDerivID ( var3 )
< < R " (, " param " : " ) " << symbol_table.getName(getSymbIDByDerivID(param)) << R " ( " ) " ;
g3p_output < < R " (, " val " : " ) " ;
d2 - > writeJsonOutput ( g3p_output , temp_term_union , tef_terms ) ;
g3p_output < < R " ( " } ) " << endl;
}
g3p_output < < " ]} " < < endl ;
2017-03-02 18:34:18 +01:00
if ( writeDetails )
2019-04-03 16:32:52 +02:00
output < < R " ( " dynamic_model_params_derivative " : {) " ;
2017-03-02 18:34:18 +01:00
else
2019-04-03 16:32:52 +02:00
output < < R " ( " dynamic_model_params_derivatives_simple " : {) " ;
2017-03-02 18:34:18 +01:00
output < < model_local_vars_output . str ( )
2017-02-20 12:18:11 +01:00
< < " , " < < model_output . str ( )
2019-08-22 15:55:00 +02:00
< < " , " < < rp_output . str ( )
< < " , " < < gp_output . str ( )
< < " , " < < rpp_output . str ( )
< < " , " < < gpp_output . str ( )
< < " , " < < hp_output . str ( )
2019-08-22 17:00:36 +02:00
< < " , " < < g3p_output . str ( )
2017-02-20 12:18:11 +01:00
< < " } " ;
2017-02-02 15:09:43 +01:00
}
2018-08-01 19:41:44 +02:00
void
DynamicModel : : substituteVarExpectation ( const map < string , expr_t > & subst_table )
{
2019-12-20 16:59:30 +01:00
for ( auto & equation : equations )
2018-08-01 19:41:44 +02:00
equation = dynamic_cast < BinaryOpNode * > ( equation - > substituteVarExpectation ( subst_table ) ) ;
}
2020-09-10 14:24:20 +02:00
void
DynamicModel : : checkNoRemainingPacExpectation ( ) const
{
for ( size_t eq = 0 ; eq < equations . size ( ) ; eq + + )
if ( equations [ eq ] - > containsPacExpectation ( ) )
{
cerr < < " ERROR: in equation " < < equation_tags . getTagValueByEqnAndKey ( eq , " name " )
< < " , the pac_expectation operator references an unknown pac_model " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}