2009-04-14 16:39:53 +02:00
/*
2019-04-16 11:35:31 +02:00
* Copyright © 2003 - 2019 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
* along with Dynare . If not , see < http : //www.gnu.org/licenses/>.
*/
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>
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 ) ) ) ;
2018-10-11 11:21:58 +02:00
auto convert_vector_tt = [ f ] ( vector < temporary_terms_t > vtt )
2018-10-09 18:27:19 +02:00
{
vector < temporary_terms_t > vtt2 ;
for ( const auto & tt : vtt )
{
temporary_terms_t tt2 ;
for ( const auto & it : tt )
tt2 . insert ( f ( it ) ) ;
vtt2 . push_back ( tt2 ) ;
}
return vtt2 ;
} ;
for ( const auto & it : m . v_temporary_terms )
v_temporary_terms . push_back ( convert_vector_tt ( it ) ) ;
for ( const auto & it : m . first_chain_rule_derivatives )
first_chain_rule_derivatives [ it . first ] = f ( it . second ) ;
for ( const auto & it : m . equation_type_and_normalized_equation )
2019-02-21 12:16:22 +01:00
equation_type_and_normalized_equation . emplace_back ( it . first , f ( it . second ) ) ;
2018-10-09 18:27:19 +02:00
for ( const auto & it : m . blocks_derivatives )
{
block_derivatives_equation_variable_laglead_nodeid_t v ;
for ( const auto & it2 : it )
2018-11-23 17:19:59 +01:00
v . emplace_back ( get < 0 > ( it2 ) , get < 1 > ( it2 ) , get < 2 > ( it2 ) , f ( get < 3 > ( it2 ) ) ) ;
2018-10-09 18:27:19 +02:00
blocks_derivatives . push_back ( v ) ;
}
for ( const auto & it : m . dynamic_jacobian )
dynamic_jacobian [ it . first ] = f ( it . second ) ;
2018-10-11 11:21:58 +02:00
auto convert_derivative_t = [ f ] ( derivative_t dt )
2018-10-09 18:27:19 +02:00
{
derivative_t dt2 ;
for ( const auto & it : dt )
dt2 [ it . first ] = f ( it . second ) ;
return dt2 ;
} ;
for ( const auto & it : m . derivative_endo )
derivative_endo . push_back ( convert_derivative_t ( it ) ) ;
for ( const auto & it : m . derivative_other_endo )
derivative_other_endo . push_back ( convert_derivative_t ( it ) ) ;
for ( const auto & it : m . derivative_exo )
derivative_exo . push_back ( convert_derivative_t ( it ) ) ;
for ( const auto & it : m . derivative_exo_det )
derivative_exo_det . push_back ( convert_derivative_t ( it ) ) ;
}
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 ) :
2018-10-09 18:27:19 +02: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 ) :
ModelTree { m } ,
trend_component_model_table { m . trend_component_model_table } ,
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 } ,
2019-11-18 17:13:49 +01:00
static_only_equation_tags_xref { m . static_only_equation_tags_xref } ,
2018-10-09 18:27:19 +02:00
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 } ,
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 } ,
v_temporary_terms_inuse { m . v_temporary_terms_inuse } ,
map_idx { m . map_idx } ,
global_temporary_terms { m . global_temporary_terms } ,
block_type_firstequation_size_mfs { m . block_type_firstequation_size_mfs } ,
blocks_linear { m . blocks_linear } ,
other_endo_block { m . other_endo_block } ,
exo_block { m . exo_block } ,
exo_det_block { m . exo_det_block } ,
block_var_exo { m . block_var_exo } ,
block_exo_index { m . block_exo_index } ,
block_det_exo_index { m . block_det_exo_index } ,
block_other_endo_index { m . block_other_endo_index } ,
block_col_type { m . block_col_type } ,
variable_block_lead_lag { m . variable_block_lead_lag } ,
equation_block { m . equation_block } ,
var_expectation_functions_to_write { m . var_expectation_functions_to_write } ,
endo_max_leadlag_block { m . endo_max_leadlag_block } ,
other_endo_max_leadlag_block { m . other_endo_max_leadlag_block } ,
exo_max_leadlag_block { m . exo_max_leadlag_block } ,
exo_det_max_leadlag_block { m . exo_det_max_leadlag_block } ,
max_leadlag_block { m . max_leadlag_block }
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 ;
2019-11-18 17:13:49 +01:00
static_only_equation_tags_xref = m . static_only_equation_tags_xref ;
2018-10-09 18:27:19 +02:00
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 ;
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 ;
v_temporary_terms . clear ( ) ;
v_temporary_terms_inuse = m . v_temporary_terms_inuse ;
first_chain_rule_derivatives . clear ( ) ;
map_idx = m . map_idx ;
global_temporary_terms = m . global_temporary_terms ;
equation_type_and_normalized_equation . clear ( ) ;
block_type_firstequation_size_mfs = m . block_type_firstequation_size_mfs ;
blocks_derivatives . clear ( ) ;
dynamic_jacobian . clear ( ) ;
blocks_linear = m . blocks_linear ;
derivative_endo . clear ( ) ;
derivative_other_endo . clear ( ) ;
derivative_exo . clear ( ) ;
derivative_exo_det . clear ( ) ;
other_endo_block = m . other_endo_block ;
exo_block = m . exo_block ;
exo_det_block = m . exo_det_block ;
block_var_exo = m . block_var_exo ;
block_exo_index = m . block_exo_index ;
block_det_exo_index = m . block_det_exo_index ;
block_other_endo_index = m . block_other_endo_index ;
block_col_type = m . block_col_type ;
variable_block_lead_lag = m . variable_block_lead_lag ;
equation_block = m . equation_block ;
var_expectation_functions_to_write = m . var_expectation_functions_to_write ;
endo_max_leadlag_block = m . endo_max_leadlag_block ;
other_endo_max_leadlag_block = m . other_endo_max_leadlag_block ;
exo_max_leadlag_block = m . exo_max_leadlag_block ;
exo_det_max_leadlag_block = m . exo_det_max_leadlag_block ;
max_leadlag_block = m . max_leadlag_block ;
copyHelper ( m ) ;
return * this ;
2009-04-16 12:33:30 +02:00
}
2009-04-14 16:39:53 +02:00
void
2010-07-23 11:20:24 +02:00
DynamicModel : : compileDerivative ( ofstream & code_file , unsigned int & instruction_number , int eq , int symb_id , int lag , const map_idx_t & map_idx ) 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 ( ) )
2010-07-23 11:20:24 +02:00
( it - > second ) - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , 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
2010-07-23 11:20:24 +02:00
DynamicModel : : compileChainRuleDerivative ( ofstream & code_file , unsigned int & instruction_number , int eqr , int varr , int lag , const map_idx_t & map_idx ) const
2009-07-21 17:50:12 +02:00
{
2019-10-28 11:09:36 +01:00
if ( auto it = first_chain_rule_derivatives . find ( { eqr , varr , lag } ) ; it ! = first_chain_rule_derivatives . end ( ) )
2010-07-23 11:20:24 +02:00
( it - > second ) - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , 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
2009-12-16 14:21:31 +01:00
DynamicModel : : computeTemporaryTermsOrdered ( )
2009-04-14 16:39:53 +02:00
{
2018-06-04 14:17:36 +02:00
map < expr_t , pair < int , int > > first_occurence ;
2010-09-16 19:18:45 +02:00
map < expr_t , int > reference_count ;
2009-04-14 16:39:53 +02:00
BinaryOpNode * eq_node ;
2010-09-16 19:00:48 +02:00
first_chain_rule_derivatives_t : : const_iterator it_chr ;
2009-04-14 16:39:53 +02:00
ostringstream tmp_s ;
2009-12-16 14:21:31 +01:00
v_temporary_terms . clear ( ) ;
map_idx . clear ( ) ;
2009-04-14 16:39:53 +02:00
2009-12-16 14:21:31 +01:00
unsigned int nb_blocks = getNbBlocks ( ) ;
2018-06-04 14:17:36 +02:00
v_temporary_terms = vector < vector < temporary_terms_t > > ( nb_blocks ) ;
2010-09-16 19:00:48 +02:00
v_temporary_terms_inuse = vector < temporary_terms_inuse_t > ( nb_blocks ) ;
2009-04-14 16:39:53 +02:00
temporary_terms . clear ( ) ;
2009-08-25 11:43:01 +02:00
2009-12-16 18:13:23 +01:00
if ( ! global_temporary_terms )
2009-12-16 14:21:31 +01:00
{
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2009-04-14 16:39:53 +02:00
{
2009-12-16 14:21:31 +01:00
reference_count . clear ( ) ;
temporary_terms . clear ( ) ;
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_nb_mfs = getBlockMfs ( block ) ;
unsigned int block_nb_recursives = block_size - block_nb_mfs ;
2010-09-16 19:00:48 +02:00
v_temporary_terms [ block ] = vector < temporary_terms_t > ( block_size ) ;
2009-12-16 14:21:31 +01:00
for ( unsigned int i = 0 ; i < block_size ; i + + )
2009-04-14 16:39:53 +02:00
{
2009-12-16 18:13:23 +01:00
if ( i < block_nb_recursives & & isBlockEquationRenormalized ( block , i ) )
2010-09-16 19:18:45 +02:00
getBlockEquationRenormalizedExpr ( block , i ) - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , i ) ;
2009-12-16 14:21:31 +01:00
else
2009-04-14 16:39:53 +02:00
{
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2009-12-16 14:21:31 +01:00
eq_node - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , i ) ;
2009-04-14 16:39:53 +02:00
}
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-12-16 14:21:31 +01:00
{
2018-11-23 17:19:59 +01:00
expr_t id = get < 3 > ( it ) ;
2009-12-16 14:21:31 +01:00
id - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : derivative_endo [ block ] )
it . second - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
for ( const auto & it : derivative_other_endo [ block ] )
it . second - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
v_temporary_terms_inuse [ block ] = { } ;
2009-04-14 16:39:53 +02:00
}
}
2009-12-16 14:21:31 +01:00
else
2009-04-14 16:39:53 +02:00
{
2009-12-16 14:21:31 +01:00
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2009-04-14 16:39:53 +02:00
{
2009-12-16 14:21:31 +01:00
// Compute the temporary terms reordered
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_nb_mfs = getBlockMfs ( block ) ;
unsigned int block_nb_recursives = block_size - block_nb_mfs ;
2010-09-16 19:00:48 +02:00
v_temporary_terms [ block ] = vector < temporary_terms_t > ( block_size ) ;
2009-12-16 14:21:31 +01:00
for ( unsigned int i = 0 ; i < block_size ; i + + )
2009-08-25 11:43:01 +02:00
{
2009-12-16 18:13:23 +01:00
if ( i < block_nb_recursives & & isBlockEquationRenormalized ( block , i ) )
2010-09-16 19:18:45 +02:00
getBlockEquationRenormalizedExpr ( block , i ) - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , i ) ;
2009-12-16 14:21:31 +01:00
else
{
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2009-12-16 14:21:31 +01:00
eq_node - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , i ) ;
}
2009-08-25 11:43:01 +02:00
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-04-14 16:39:53 +02:00
{
2018-11-23 17:19:59 +01:00
expr_t id = get < 3 > ( it ) ;
2009-12-16 14:21:31 +01:00
id - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
2009-04-14 16:39:53 +02:00
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : derivative_endo [ block ] )
it . second - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
for ( const auto & it : derivative_other_endo [ block ] )
it . second - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , block , v_temporary_terms , block_size - 1 ) ;
2009-07-10 17:05:09 +02:00
}
2009-12-16 14:21:31 +01:00
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2009-07-10 17:05:09 +02:00
{
2009-12-16 14:21:31 +01:00
// Collect the temporary terms reordered
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_nb_mfs = getBlockMfs ( block ) ;
unsigned int block_nb_recursives = block_size - block_nb_mfs ;
set < int > temporary_terms_in_use ;
for ( unsigned int i = 0 ; i < block_size ; i + + )
2009-04-14 16:39:53 +02:00
{
2009-12-16 18:13:23 +01:00
if ( i < block_nb_recursives & & isBlockEquationRenormalized ( block , i ) )
2010-09-16 19:18:45 +02:00
getBlockEquationRenormalizedExpr ( block , i ) - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
2009-12-16 14:21:31 +01:00
else
2009-04-14 16:39:53 +02:00
{
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2009-12-16 14:21:31 +01:00
eq_node - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
2009-04-14 16:39:53 +02:00
}
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-12-16 14:21:31 +01:00
{
2018-11-23 17:19:59 +01:00
expr_t id = get < 3 > ( it ) ;
2009-12-16 14:21:31 +01:00
id - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
}
2018-11-23 17:19:59 +01:00
for ( const auto & it : derivative_endo [ block ] )
it . second - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
for ( const auto & it : derivative_other_endo [ block ] )
it . second - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
for ( const auto & it : derivative_exo [ block ] )
it . second - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
for ( const auto & it : derivative_exo_det [ block ] )
it . second - > collectTemporary_terms ( temporary_terms , temporary_terms_in_use , block ) ;
2009-12-16 14:21:31 +01:00
v_temporary_terms_inuse [ block ] = temporary_terms_in_use ;
2009-04-14 16:39:53 +02:00
}
2010-01-22 11:03:29 +01:00
computeTemporaryTermsMapping ( ) ;
2009-04-14 16:39:53 +02:00
}
}
2010-01-22 11:03:29 +01:00
void
DynamicModel : : computeTemporaryTermsMapping ( )
{
// Add a mapping form node ID to temporary terms order
int j = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto temporary_term : temporary_terms )
map_idx [ temporary_term - > idx ] = j + + ;
2010-01-22 11:03:29 +01:00
}
2009-04-14 16:39:53 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeModelEquationsOrdered_M ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
string tmp_s , sps ;
ostringstream tmp_output , tmp1_output , global_output ;
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 ;
2013-11-14 12:59:13 +01:00
ostringstream Ufoss ;
vector < string > Uf ( symbol_table . endo_nbr ( ) , " " ) ;
2010-09-16 19:18:45 +02:00
map < expr_t , int > reference_count ;
2010-09-16 19:00:48 +02:00
temporary_terms_t local_temporary_terms ;
2009-12-16 18:13:23 +01:00
ofstream output ;
2010-11-20 15:52:51 +01:00
int nze , nze_exo , nze_exo_det , nze_other_endo ;
2009-12-16 18:13:23 +01:00
vector < int > feedback_variables ;
ExprNodeOutputType local_output_type ;
2013-11-19 12:53:15 +01:00
Ufoss . str ( " " ) ;
2009-04-14 16:39:53 +02:00
2018-09-05 18:27:13 +02:00
local_output_type = ExprNodeOutputType : : matlabDynamicModelSparse ;
2009-12-16 18:13:23 +01:00
if ( global_temporary_terms )
2010-09-16 16:57:35 +02:00
local_temporary_terms = temporary_terms ;
2009-12-16 18:13:23 +01:00
//----------------------------------------------------------------------
//For each block
for ( unsigned int block = 0 ; block < getNbBlocks ( ) ; block + + )
{
//recursive_variables.clear();
feedback_variables . clear ( ) ;
//For a block composed of a single equation determines wether we have to evaluate or to solve the equation
nze = derivative_endo [ block ] . size ( ) ;
nze_other_endo = derivative_other_endo [ block ] . size ( ) ;
nze_exo = derivative_exo [ block ] . size ( ) ;
2010-11-20 15:52:51 +01:00
nze_exo_det = derivative_exo_det [ block ] . size ( ) ;
2009-12-16 18:13:23 +01:00
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_mfs = getBlockMfs ( block ) ;
unsigned int block_recursive = block_size - block_mfs ;
2010-12-10 11:50:27 +01:00
deriv_node_temp_terms_t tef_terms ;
2018-09-05 18:27:13 +02:00
local_output_type = ExprNodeOutputType : : matlabDynamicModelSparse ;
2009-12-16 18:13:23 +01:00
if ( global_temporary_terms )
2010-09-16 16:57:35 +02:00
local_temporary_terms = temporary_terms ;
2009-12-16 18:13:23 +01:00
2010-10-27 15:34:48 +02:00
int prev_lag ;
unsigned int prev_var , count_col , count_col_endo , count_col_exo , count_col_exo_det , count_col_other_endo ;
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > tmp_block_endo_derivative ;
for ( const auto & it : blocks_derivatives [ block ] )
tmp_block_endo_derivative [ { get < 2 > ( it ) , get < 1 > ( it ) , get < 0 > ( it ) } ] = get < 3 > ( it ) ;
2010-10-27 15:34:48 +02:00
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_endo_derivative )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int lag = get < 0 > ( it . first ) ;
unsigned int var = get < 1 > ( it . first ) ;
2010-10-27 15:34:48 +02:00
if ( var ! = prev_var | | lag ! = prev_lag )
{
prev_var = var ;
prev_lag = lag ;
count_col_endo + + ;
}
}
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > tmp_block_exo_derivative ;
for ( const auto & it : derivative_exo [ block ] )
tmp_block_exo_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
2010-10-27 15:34:48 +02:00
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col_exo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_exo_derivative )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int lag = get < 0 > ( it . first ) ;
unsigned int var = get < 1 > ( it . first ) ;
2010-10-27 15:34:48 +02:00
if ( var ! = prev_var | | lag ! = prev_lag )
{
prev_var = var ;
prev_lag = lag ;
count_col_exo + + ;
}
}
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > tmp_block_exo_det_derivative ;
for ( const auto & it : derivative_exo_det [ block ] )
tmp_block_exo_det_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
2010-10-27 15:34:48 +02:00
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col_exo_det = 0 ;
2018-11-23 17:39:18 +01:00
for ( const auto & it : tmp_block_exo_det_derivative )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int lag = get < 0 > ( it . first ) ;
unsigned int var = get < 1 > ( it . first ) ;
2010-10-27 15:34:48 +02:00
if ( var ! = prev_var | | lag ! = prev_lag )
{
prev_var = var ;
prev_lag = lag ;
count_col_exo_det + + ;
}
}
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > tmp_block_other_endo_derivative ;
for ( const auto & it : derivative_other_endo [ block ] )
tmp_block_other_endo_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
2010-10-27 15:34:48 +02:00
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col_other_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_other_endo_derivative )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int lag = get < 0 > ( it . first ) ;
unsigned int var = get < 1 > ( it . first ) ;
2010-10-27 15:34:48 +02:00
if ( var ! = prev_var | | lag ! = prev_lag )
{
prev_var = var ;
prev_lag = lag ;
count_col_other_endo + + ;
}
}
2009-12-16 18:13:23 +01:00
tmp1_output . str ( " " ) ;
2018-06-27 15:01:31 +02:00
tmp1_output < < packageDir ( basename + " .block " ) < < " /dynamic_ " < < block + 1 < < " .m " ;
2018-06-27 15:12:12 +02:00
output . open ( tmp1_output . str ( ) , ios : : out | ios : : binary ) ;
2018-11-23 17:19:59 +01:00
output < < " % " < < endl
< < " % " < < tmp1_output . str ( ) < < " : Computes dynamic model for Dynare " < < endl
< < " % " < < endl
< < " % Warning : this file is generated automatically by Dynare " < < endl
< < " % from model file (.mod) " < < endl < < endl
< < " %/ " < < endl ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
{
2018-11-23 17:19:59 +01:00
output < < " function [y, g1, g2, g3, varargout] = dynamic_ " < < block + 1 < < " (y, x, params, steady_state, jacobian_eval, y_kmin, periods) " < < endl ;
2009-12-16 18:13:23 +01:00
}
else if ( simulation_type = = SOLVE_FORWARD_COMPLETE | | simulation_type = = SOLVE_BACKWARD_COMPLETE )
2018-11-23 17:19:59 +01:00
output < < " function [residual, y, g1, g2, g3, varargout] = dynamic_ " < < block + 1 < < " (y, x, params, steady_state, it_, jacobian_eval) " < < endl ;
2009-12-16 18:13:23 +01:00
else if ( simulation_type = = SOLVE_BACKWARD_SIMPLE | | simulation_type = = SOLVE_FORWARD_SIMPLE )
2018-11-23 17:19:59 +01:00
output < < " function [residual, y, g1, g2, g3, varargout] = dynamic_ " < < block + 1 < < " (y, x, params, steady_state, it_, jacobian_eval) " < < endl ;
2009-12-16 18:13:23 +01:00
else
2018-11-23 17:19:59 +01:00
output < < " function [residual, y, g1, g2, g3, b, varargout] = dynamic_ " < < block + 1 < < " (y, x, params, steady_state, periods, jacobian_eval, y_kmin, y_size, Periods) " < < endl ;
2009-12-16 18:13:23 +01:00
BlockType block_type ;
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
block_type = SIMULTAN ;
else if ( simulation_type = = SOLVE_FORWARD_COMPLETE | | simulation_type = = SOLVE_BACKWARD_COMPLETE )
block_type = SIMULTANS ;
else if ( ( simulation_type = = SOLVE_FORWARD_SIMPLE | | simulation_type = = SOLVE_BACKWARD_SIMPLE
| | simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
& & getBlockFirstEquation ( block ) < prologue )
block_type = PROLOGUE ;
else if ( ( simulation_type = = SOLVE_FORWARD_SIMPLE | | simulation_type = = SOLVE_BACKWARD_SIMPLE
| | simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
& & getBlockFirstEquation ( block ) > = equations . size ( ) - epilogue )
block_type = EPILOGUE ;
else
block_type = SIMULTANS ;
output < < " % //////////////////////////////////////////////////////////////////////// " < < endl
< < " % // " < < string ( " Block " ) . substr ( int ( log10 ( block + 1 ) ) ) < < block + 1 < < " " < < BlockType0 ( block_type )
< < " // " < < endl
< < " % // Simulation type "
< < BlockSim ( simulation_type ) < < " // " < < endl
< < " % //////////////////////////////////////////////////////////////////////// " < < endl ;
//The Temporary terms
if ( simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
{
2018-11-23 17:19:59 +01:00
output < < " if(jacobian_eval) " < < endl
< < " g1 = spalloc( " < < block_mfs < < " , " < < count_col_endo < < " , " < < nze < < " ); " < < endl
< < " g1_x=spalloc( " < < block_size < < " , " < < count_col_exo < < " , " < < nze_exo < < " ); " < < endl
< < " g1_xd=spalloc( " < < block_size < < " , " < < count_col_exo_det < < " , " < < nze_exo_det < < " ); " < < endl
< < " g1_o=spalloc( " < < block_size < < " , " < < count_col_other_endo < < " , " < < nze_other_endo < < " ); " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
else
{
2018-11-23 17:19:59 +01:00
output < < " if(jacobian_eval) " < < endl
< < " g1 = spalloc( " < < block_size < < " , " < < count_col_endo < < " , " < < nze < < " ); " < < endl
< < " g1_x=spalloc( " < < block_size < < " , " < < count_col_exo < < " , " < < nze_exo < < " ); " < < endl
< < " g1_xd=spalloc( " < < block_size < < " , " < < count_col_exo_det < < " , " < < nze_exo_det < < " ); " < < endl
< < " g1_o=spalloc( " < < block_size < < " , " < < count_col_other_endo < < " , " < < nze_other_endo < < " ); " < < endl
< < " else " < < endl ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
2018-11-23 17:19:59 +01:00
output < < " g1 = spalloc( " < < block_mfs < < " *Periods, "
< < block_mfs < < " *(Periods+ " < < max_leadlag_block [ block ] . first + max_leadlag_block [ block ] . second + 1 < < " ) "
< < " , " < < nze < < " *Periods); " < < endl ;
2009-06-05 16:45:23 +02:00
else
2018-11-23 17:19:59 +01:00
output < < " g1 = spalloc( " < < block_mfs
< < " , " < < block_mfs < < " , " < < nze < < " ); " < < endl ;
output < < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
2009-12-16 14:21:31 +01:00
2018-11-23 17:19:59 +01:00
output < < " g2=0;g3=0; " < < endl ;
2009-12-16 18:13:23 +01:00
if ( v_temporary_terms_inuse [ block ] . size ( ) )
{
tmp_output . str ( " " ) ;
2018-06-04 12:26:16 +02:00
for ( int it : v_temporary_terms_inuse [ block ] )
tmp_output < < " T " < < it ;
2018-11-23 17:19:59 +01:00
output < < " global " < < tmp_output . str ( ) < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
}
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
{
2010-09-16 19:00:48 +02:00
temporary_terms_t tt2 ;
2019-04-23 11:07:32 +02:00
for ( int i = 0 ; i < static_cast < int > ( block_size ) ; i + + )
2009-12-16 18:13:23 +01:00
{
if ( v_temporary_terms [ block ] [ i ] . size ( ) & & global_temporary_terms )
{
output < < " " < < " % //Temporary variables initialization " < < endl
< < " " < < " T_zeros = zeros(y_kmin+periods, 1); " < < endl ;
2018-06-04 12:26:16 +02:00
for ( auto it : v_temporary_terms [ block ] [ i ] )
2009-12-16 18:13:23 +01:00
{
output < < " " ;
2018-05-28 11:56:34 +02:00
// In the following, "Static" is used to avoid getting the "(it_)" subscripting
2018-09-05 18:27:13 +02:00
it - > writeOutput ( output , ExprNodeOutputType : : matlabStaticModelSparse , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
output < < " = T_zeros; " < < endl ;
}
}
}
}
if ( simulation_type = = SOLVE_BACKWARD_SIMPLE | | simulation_type = = SOLVE_FORWARD_SIMPLE | | simulation_type = = SOLVE_BACKWARD_COMPLETE | | simulation_type = = SOLVE_FORWARD_COMPLETE )
2018-11-23 17:19:59 +01:00
output < < " residual=zeros( " < < block_mfs < < " ,1); " < < endl ;
2009-12-16 18:13:23 +01:00
else if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
2018-11-23 17:19:59 +01:00
output < < " residual=zeros( " < < block_mfs < < " ,y_kmin+periods); " < < endl ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = EVALUATE_BACKWARD )
2018-11-23 17:19:59 +01:00
output < < " for it_ = (y_kmin+periods):y_kmin+1 " < < endl ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = EVALUATE_FORWARD )
2018-11-23 17:19:59 +01:00
output < < " for it_ = y_kmin+1:(y_kmin+periods) " < < endl ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
{
output < < " b = zeros(periods*y_size,1); " < < endl
< < " for it_ = y_kmin+1:(periods+y_kmin) " < < endl
< < " Per_y_=it_*y_size; " < < endl
< < " Per_J_=(it_-y_kmin-1)*y_size; " < < endl
< < " Per_K_=(it_-1)*y_size; " < < endl ;
sps = " " ;
}
else
if ( simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
sps = " " ;
else
sps = " " ;
// The equations
2018-03-27 17:14:30 +02:00
temporary_terms_idxs_t temporary_terms_idxs ;
2009-12-16 18:13:23 +01:00
for ( unsigned int i = 0 ; i < block_size ; i + + )
{
2010-09-16 19:00:48 +02:00
temporary_terms_t tt2 ;
2009-12-16 18:13:23 +01:00
if ( v_temporary_terms [ block ] . size ( ) )
{
output < < " " < < " % //Temporary variables " < < endl ;
2018-06-04 12:26:16 +02:00
for ( auto it : v_temporary_terms [ block ] [ i ] )
2009-12-16 18:13:23 +01:00
{
2018-06-04 12:52:14 +02:00
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) ! = nullptr )
2018-06-04 12:26:16 +02:00
it - > writeExternalFunctionOutput ( output , local_output_type , tt2 , temporary_terms_idxs , tef_terms ) ;
2010-12-10 11:50:27 +01:00
2009-12-16 18:13:23 +01:00
output < < " " < < sps ;
2018-06-04 12:26:16 +02:00
it - > writeOutput ( output , local_output_type , local_temporary_terms , { } , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " = " ;
2018-06-04 12:26:16 +02:00
it - > writeOutput ( output , local_output_type , tt2 , { } , tef_terms ) ;
2009-12-16 18:13:23 +01:00
// Insert current node into tt2
2018-06-04 12:26:16 +02:00
tt2 . insert ( it ) ;
2009-12-16 18:13:23 +01:00
output < < " ; " < < endl ;
}
}
int variable_ID = getBlockVariableID ( block , i ) ;
int equation_ID = getBlockEquationID ( block , i ) ;
EquationType equ_type = getBlockEquationType ( block , i ) ;
2018-07-17 18:34:07 +02:00
string sModel = symbol_table . getName ( symbol_table . getID ( SymbolType : : endogenous , variable_ID ) ) ;
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2009-12-16 18:13:23 +01:00
tmp_output . str ( " " ) ;
2018-05-28 11:56:34 +02:00
lhs - > writeOutput ( tmp_output , local_output_type , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
switch ( simulation_type )
{
case EVALUATE_BACKWARD :
case EVALUATE_FORWARD :
evaluation : if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
output < < " % equation " < < getBlockEquationID ( block , i ) + 1 < < " variable : " < < sModel
< < " ( " < < variable_ID + 1 < < " ) " < < c_Equation_Type ( equ_type ) < < endl ;
output < < " " ;
if ( equ_type = = E_EVALUATE )
{
output < < tmp_output . str ( ) ;
output < < " = " ;
2018-05-28 11:56:34 +02:00
rhs - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
}
else if ( equ_type = = E_EVALUATE_S )
{
output < < " % " < < tmp_output . str ( ) ;
output < < " = " ;
if ( isBlockEquationRenormalized ( block , i ) )
{
2018-05-28 11:56:34 +02:00
rhs - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-11-23 17:19:59 +01:00
output < < endl < < " " ;
2009-12-16 18:13:23 +01:00
tmp_output . str ( " " ) ;
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationRenormalizedExpr ( block , i ) ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2018-05-28 11:56:34 +02:00
lhs - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
output < < " = " ;
2018-05-28 11:56:34 +02:00
rhs - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
}
}
else
{
2018-11-23 17:19:59 +01:00
cerr < < " Type mismatch for equation " < < equation_ID + 1 < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
2018-11-23 17:19:59 +01:00
output < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_BACKWARD_SIMPLE :
case SOLVE_FORWARD_SIMPLE :
case SOLVE_BACKWARD_COMPLETE :
case SOLVE_FORWARD_COMPLETE :
if ( i < block_recursive )
goto evaluation ;
feedback_variables . push_back ( variable_ID ) ;
output < < " % equation " < < equation_ID + 1 < < " variable : " < < sModel
2018-07-17 18:34:07 +02:00
< < " ( " < < variable_ID + 1 < < " ) " < < c_Equation_Type ( equ_type ) < < " symb_id= " < < symbol_table . getID ( SymbolType : : endogenous , variable_ID ) < < endl ;
2009-12-16 18:13:23 +01:00
output < < " " < < " residual( " < < i + 1 - block_recursive < < " ) = ( " ;
goto end ;
case SOLVE_TWO_BOUNDARIES_COMPLETE :
case SOLVE_TWO_BOUNDARIES_SIMPLE :
if ( i < block_recursive )
goto evaluation ;
feedback_variables . push_back ( variable_ID ) ;
output < < " % equation " < < equation_ID + 1 < < " variable : " < < sModel
2018-07-17 18:34:07 +02:00
< < " ( " < < variable_ID + 1 < < " ) " < < c_Equation_Type ( equ_type ) < < " symb_id= " < < symbol_table . getID ( SymbolType : : endogenous , variable_ID ) < < endl ;
2013-11-14 12:59:13 +01:00
Ufoss < < " b( " < < i + 1 - block_recursive < < " +Per_J_) = -residual( " < < i + 1 - block_recursive < < " , it_) " ;
2013-11-19 12:53:15 +01:00
Uf [ equation_ID ] + = Ufoss . str ( ) ;
2013-11-14 12:59:13 +01:00
Ufoss . str ( " " ) ;
2009-12-16 18:13:23 +01:00
output < < " residual( " < < i + 1 - block_recursive < < " , it_) = ( " ;
goto end ;
default :
end :
output < < tmp_output . str ( ) ;
output < < " ) - ( " ;
2018-05-28 11:56:34 +02:00
rhs - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-11-23 17:19:59 +01:00
output < < " ); " < < endl ;
2009-04-14 16:39:53 +02:00
# ifdef CONDITION
2009-12-16 18:13:23 +01:00
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE )
2018-11-23 17:19:59 +01:00
output < < " condition( " < < i + 1 < < " )=0; " < < endl ;
2009-04-14 16:39:53 +02:00
# endif
2009-12-16 18:13:23 +01:00
}
}
// The Jacobian if we have to solve the block
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE | | simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE )
2010-11-20 15:52:51 +01:00
output < < " " < < sps < < " % Jacobian " < < endl < < " if jacobian_eval " < < endl ;
2009-12-16 18:13:23 +01:00
else
if ( simulation_type = = SOLVE_BACKWARD_SIMPLE | | simulation_type = = SOLVE_FORWARD_SIMPLE
| | simulation_type = = SOLVE_BACKWARD_COMPLETE | | simulation_type = = SOLVE_FORWARD_COMPLETE )
output < < " % Jacobian " < < endl < < " if jacobian_eval " < < endl ;
2009-04-14 16:39:53 +02:00
else
2009-12-16 18:13:23 +01:00
output < < " % Jacobian " < < endl < < " if jacobian_eval " < < endl ;
2010-11-20 15:52:51 +01:00
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_endo_derivative )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
int lag ;
unsigned int var , eq ;
tie ( lag , var , eq ) = it . first ;
2011-06-18 17:53:50 +02:00
int eqr = getBlockEquationID ( block , eq ) ;
int varr = getBlockVariableID ( block , var ) ;
2010-11-20 15:52:51 +01:00
if ( var ! = prev_var | | lag ! = prev_lag )
2009-12-16 18:13:23 +01:00
{
2010-11-20 15:52:51 +01:00
prev_var = var ;
prev_lag = lag ;
count_col + + ;
}
2009-12-16 18:13:23 +01:00
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2009-12-16 18:13:23 +01:00
2010-11-20 15:52:51 +01:00
output < < " g1( " < < eq + 1 < < " , " < < count_col < < " ) = " ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-07-17 18:34:07 +02:00
output < < " ; % variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : endogenous , varr ) )
2010-11-20 15:52:51 +01:00
< < " ( " < < lag
2011-06-18 17:53:50 +02:00
< < " ) " < < varr + 1 < < " , " < < var + 1
< < " , equation= " < < eqr + 1 < < " , " < < eq + 1 < < endl ;
2010-11-20 15:52:51 +01:00
}
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_exo_derivative )
2010-11-20 15:52:51 +01:00
{
2018-11-23 17:19:59 +01:00
int lag ;
unsigned int var , eq ;
tie ( lag , var , eq ) = it . first ;
2010-11-20 15:52:51 +01:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
if ( var ! = prev_var | | lag ! = prev_lag )
2010-07-23 11:20:24 +02:00
{
2010-11-20 15:52:51 +01:00
prev_var = var ;
prev_lag = lag ;
count_col + + ;
2010-07-23 11:20:24 +02:00
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-11-20 15:52:51 +01:00
output < < " g1_x( " < < eqr + 1 < < " , " < < count_col < < " ) = " ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-07-17 18:34:07 +02:00
output < < " ; % variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : exogenous , var ) )
2010-11-20 15:52:51 +01:00
< < " ( " < < lag
< < " ) " < < var + 1
< < " , equation= " < < eq + 1 < < endl ;
}
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_exo_det_derivative )
2010-11-20 15:52:51 +01:00
{
2018-11-23 17:19:59 +01:00
int lag ;
unsigned int var , eq ;
tie ( lag , var , eq ) = it . first ;
2010-11-20 15:52:51 +01:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
if ( var ! = prev_var | | lag ! = prev_lag )
2010-07-23 11:20:24 +02:00
{
2010-11-20 15:52:51 +01:00
prev_var = var ;
prev_lag = lag ;
count_col + + ;
2010-07-23 11:20:24 +02:00
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-11-20 15:52:51 +01:00
output < < " g1_xd( " < < eqr + 1 < < " , " < < count_col < < " ) = " ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-07-17 18:34:07 +02:00
output < < " ; % variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : exogenous , var ) )
2010-11-20 15:52:51 +01:00
< < " ( " < < lag
< < " ) " < < var + 1
< < " , equation= " < < eq + 1 < < endl ;
}
prev_var = 999999999 ;
prev_lag = - 9999999 ;
count_col = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_other_endo_derivative )
2010-11-20 15:52:51 +01:00
{
2018-11-23 17:19:59 +01:00
int lag ;
unsigned int var , eq ;
tie ( lag , var , eq ) = it . first ;
2010-11-20 15:52:51 +01:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
if ( var ! = prev_var | | lag ! = prev_lag )
2009-12-16 18:13:23 +01:00
{
2010-11-20 15:52:51 +01:00
prev_var = var ;
prev_lag = lag ;
count_col + + ;
2009-12-16 18:13:23 +01:00
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-11-20 15:52:51 +01:00
2011-02-04 16:25:38 +01:00
output < < " g1_o( " < < eqr + 1 < < " , " < < /*var+1+(lag+block_max_lag)*block_size*/ count_col < < " ) = " ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-07-17 18:34:07 +02:00
output < < " ; % variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : endogenous , var ) )
2010-11-20 15:52:51 +01:00
< < " ( " < < lag
< < " ) " < < var + 1
< < " , equation= " < < eq + 1 < < endl ;
}
2018-11-23 17:19:59 +01:00
output < < " varargout{1}=g1_x; " < < endl
< < " varargout{2}=g1_xd; " < < endl
< < " varargout{3}=g1_o; " < < endl ;
2010-11-20 15:52:51 +01:00
switch ( simulation_type )
{
case EVALUATE_FORWARD :
case EVALUATE_BACKWARD :
2018-11-23 17:19:59 +01:00
output < < " end; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_BACKWARD_SIMPLE :
case SOLVE_FORWARD_SIMPLE :
case SOLVE_BACKWARD_COMPLETE :
case SOLVE_FORWARD_COMPLETE :
output < < " else " < < endl ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
unsigned int eq , var ;
expr_t id ;
int lag ;
tie ( eq , var , lag , id ) = it ;
2009-12-16 18:13:23 +01:00
unsigned int eqr = getBlockEquationID ( block , eq ) ;
unsigned int varr = getBlockVariableID ( block , var ) ;
2010-08-18 13:45:07 +02:00
if ( lag = = 0 )
{
output < < " g1( " < < eq + 1 < < " , " < < var + 1 - block_recursive < < " ) = " ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2018-07-17 18:34:07 +02:00
output < < " ; % variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : endogenous , varr ) )
2010-08-18 13:45:07 +02:00
< < " ( " < < lag
< < " ) " < < varr + 1
< < " , equation= " < < eqr + 1 < < endl ;
}
2009-12-16 18:13:23 +01:00
}
2018-11-23 17:19:59 +01:00
output < < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_TWO_BOUNDARIES_SIMPLE :
case SOLVE_TWO_BOUNDARIES_COMPLETE :
2010-11-20 15:52:51 +01:00
output < < " else " < < endl ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
unsigned int eq , var ;
int lag ;
expr_t id ;
tie ( eq , var , lag , id ) = it ;
2009-12-16 18:13:23 +01:00
unsigned int eqr = getBlockEquationID ( block , eq ) ;
unsigned int varr = getBlockVariableID ( block , var ) ;
ostringstream tmp_output ;
2010-04-28 16:03:32 +02:00
if ( eq > = block_recursive & & var > = block_recursive )
2009-12-16 18:13:23 +01:00
{
if ( lag = = 0 )
2013-11-14 12:59:13 +01:00
Ufoss < < " +g1( " < < eq + 1 - block_recursive
< < " +Per_J_, " < < var + 1 - block_recursive
< < " +Per_K_)*y(it_, " < < varr + 1 < < " ) " ;
2009-12-16 18:13:23 +01:00
else if ( lag = = 1 )
2013-11-14 12:59:13 +01:00
Ufoss < < " +g1( " < < eq + 1 - block_recursive
< < " +Per_J_, " < < var + 1 - block_recursive
< < " +Per_y_)*y(it_+1, " < < varr + 1 < < " ) " ;
2009-12-16 18:13:23 +01:00
else if ( lag > 0 )
2013-11-14 12:59:13 +01:00
Ufoss < < " +g1( " < < eq + 1 - block_recursive
< < " +Per_J_, " < < var + 1 - block_recursive
< < " +y_size*(it_+ " < < lag - 1 < < " ))*y(it_+ " < < lag < < " , " < < varr + 1 < < " ) " ;
2013-11-14 12:57:00 +01:00
else
2013-11-14 12:59:13 +01:00
Ufoss < < " +g1( " < < eq + 1 - block_recursive
< < " +Per_J_, " < < var + 1 - block_recursive
< < " +y_size*(it_ " < < lag - 1 < < " ))*y(it_ " < < lag < < " , " < < varr + 1 < < " ) " ;
2013-11-19 12:53:15 +01:00
Uf [ eqr ] + = Ufoss . str ( ) ;
2013-11-14 12:59:13 +01:00
Ufoss . str ( " " ) ;
2009-12-16 18:13:23 +01:00
if ( lag = = 0 )
tmp_output < < " g1( " < < eq + 1 - block_recursive < < " +Per_J_, "
< < var + 1 - block_recursive < < " +Per_K_) = " ;
else if ( lag = = 1 )
tmp_output < < " g1( " < < eq + 1 - block_recursive < < " +Per_J_, "
< < var + 1 - block_recursive < < " +Per_y_) = " ;
else if ( lag > 0 )
tmp_output < < " g1( " < < eq + 1 - block_recursive < < " +Per_J_, "
< < var + 1 - block_recursive < < " +y_size*(it_+ " < < lag - 1 < < " )) = " ;
else if ( lag < 0 )
tmp_output < < " g1( " < < eq + 1 - block_recursive < < " +Per_J_, "
< < var + 1 - block_recursive < < " +y_size*(it_ " < < lag - 1 < < " )) = " ;
output < < " " < < tmp_output . str ( ) ;
2018-05-28 11:56:34 +02:00
id - > writeOutput ( output , local_output_type , local_temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
output < < " ; " ;
2018-07-17 18:34:07 +02:00
output < < " %2 variable= " < < symbol_table . getName ( symbol_table . getID ( SymbolType : : endogenous , varr ) )
2009-12-16 18:13:23 +01:00
< < " ( " < < lag < < " ) " < < varr + 1
< < " , equation= " < < eqr + 1 < < " ( " < < eq + 1 < < " ) " < < endl ;
}
2009-12-16 14:21:31 +01:00
2009-04-14 16:39:53 +02:00
# ifdef CONDITION
2018-11-23 17:19:59 +01:00
output < < " if (fabs(condition[ " < < eqr < < " ])<fabs(u[ " < < u < < " +Per_u_])) " < < endl
< < " condition( " < < eqr < < " )=u( " < < u < < " +Per_u_); " < < endl ;
2009-04-14 16:39:53 +02:00
# endif
2009-12-16 18:13:23 +01:00
}
for ( unsigned int i = 0 ; i < block_size ; i + + )
{
if ( i > = block_recursive )
2018-11-23 17:19:59 +01:00
output < < " " < < Uf [ getBlockEquationID ( block , i ) ] < < " ; " < < endl ;
2009-04-14 16:39:53 +02:00
# ifdef CONDITION
2018-11-23 17:19:59 +01:00
output < < " if (fabs(condition( " < < i + 1 < < " ))<fabs(u( " < < i < < " +Per_u_))) " < < endl
< < " condition( " < < i + 1 < < " )=u( " < < i + 1 < < " +Per_u_); " < < endl ;
2009-04-14 16:39:53 +02:00
# endif
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
# ifdef CONDITION
2009-12-16 18:13:23 +01:00
for ( m = 0 ; m < = ModelBlock - > Block_List [ block ] . Max_Lead + ModelBlock - > Block_List [ block ] . Max_Lag ; m + + )
{
k = m - ModelBlock - > Block_List [ block ] . Max_Lag ;
for ( i = 0 ; i < ModelBlock - > Block_List [ block ] . IM_lead_lag [ m ] . size ; i + + )
{
unsigned int eq = ModelBlock - > Block_List [ block ] . IM_lead_lag [ m ] . Equ_Index [ i ] ;
unsigned int var = ModelBlock - > Block_List [ block ] . IM_lead_lag [ m ] . Var_Index [ i ] ;
unsigned int u = ModelBlock - > Block_List [ block ] . IM_lead_lag [ m ] . u [ i ] ;
unsigned int eqr = ModelBlock - > Block_List [ block ] . IM_lead_lag [ m ] . Equ [ i ] ;
2018-11-23 17:19:59 +01:00
output < < " u( " < < u + 1 < < " +Per_u_) = u( " < < u + 1 < < " +Per_u_) / condition( " < < eqr + 1 < < " ); " < < endl ;
2009-12-16 18:13:23 +01:00
}
}
for ( i = 0 ; i < ModelBlock - > Block_List [ block ] . Size ; i + + )
2018-11-23 17:19:59 +01:00
output < < " u( " < < i + 1 < < " +Per_u_) = u( " < < i + 1 < < " +Per_u_) / condition( " < < i + 1 < < " ); " < < endl ;
2009-04-14 16:39:53 +02:00
# endif
2018-11-23 17:19:59 +01:00
output < < " end; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
default :
break ;
}
2010-12-17 14:21:35 +01:00
output < < " end " < < endl ;
2009-12-16 18:13:23 +01:00
output . close ( ) ;
}
}
2009-04-14 16:39:53 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeModelEquationsCode ( const string & basename , const map_idx_t & map_idx ) const
2010-01-22 11:03:29 +01:00
{
2010-11-20 15:52:51 +01:00
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 ;
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/bytecode " ) ;
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 ) )
simulation_type = SOLVE_TWO_BOUNDARIES_COMPLETE ;
else if ( ( max_endo_lag > = 0 ) & & ( max_endo_lead = = 0 ) )
simulation_type = SOLVE_FORWARD_COMPLETE ;
else
simulation_type = SOLVE_BACKWARD_COMPLETE ;
2018-06-27 15:01:31 +02:00
Write_Inf_To_Bin_File ( basename + " /model/bytecode/dynamic.bin " , u_count_int , file_open , simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE , symbol_table . endo_nbr ( ) ) ;
2010-01-22 11:03:29 +01:00
file_open = true ;
//Temporary variables declaration
FDIMT_ fdimt ( temporary_terms . size ( ) ) ;
2010-07-23 11:20:24 +02:00
fdimt . write ( code_file , instruction_number ) ;
vector < unsigned 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 ;
2018-11-15 16:39:53 +01:00
for ( const auto & first_derivative : derivatives [ 1 ] )
2010-10-27 15:34:48 +02:00
{
2018-11-15 16:39:53 +01:00
int deriv_id = first_derivative . first [ 1 ] ;
unsigned int eq = first_derivative . first [ 0 ] ;
2010-10-27 15:34:48 +02:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
unsigned int var = symbol_table . getTypeSpecificID ( symb ) ;
int lag = getLagByDerivID ( deriv_id ) ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2018-11-23 17:19:59 +01:00
first_derivatives_reordered_endo [ { lag , var , eq } ] = first_derivative . second ;
2018-07-17 18:34:07 +02:00
else if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : exogenous | | getTypeByDerivID ( deriv_id ) = = SymbolType : : exogenousDet )
2018-11-23 17:19:59 +01:00
first_derivatives_reordered_exo [ { lag , getTypeByDerivID ( deriv_id ) , var , eq } ] = first_derivative . second ;
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
2018-07-17 18:34:07 +02: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 ( ) ,
variable_reordered ,
equation_reordered ,
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 ,
other_endo
2010-01-22 11:03:29 +01:00
) ;
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2010-01-22 11:03:29 +01:00
2010-07-23 11:20:24 +02:00
compileTemporaryTerms ( code_file , instruction_number , temporary_terms , map_idx , true , false ) ;
2010-01-22 11:03:29 +01:00
2010-07-23 11:20:24 +02:00
compileModelEquations ( code_file , instruction_number , temporary_terms , map_idx , true , false ) ;
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 ( ) ;
2018-11-15 16:39:53 +01:00
for ( const auto & first_derivative : derivatives [ 1 ] )
2010-01-22 11:03:29 +01:00
{
2018-11-15 16:39:53 +01:00
int deriv_id = first_derivative . first [ 1 ] ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2010-01-22 11:03:29 +01:00
{
2018-06-04 12:26:16 +02:00
expr_t d1 = first_derivative . second ;
2018-11-15 16:39:53 +01:00
unsigned int eq = first_derivative . first [ 0 ] ;
2010-01-22 11:03:29 +01:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
unsigned int var = symbol_table . getTypeSpecificID ( symb ) ;
int lag = getLagByDerivID ( deriv_id ) ;
2010-01-22 17:42:08 +01:00
FNUMEXPR_ fnumexpr ( 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 ) ;
2010-07-23 11:20:24 +02:00
d1 - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , 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
{
2018-11-23 17:19: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
{
2018-11-23 17:19:59 +01:00
unsigned int eq ;
int var , lag ;
tie ( lag , var , eq ) = it . first ;
expr_t d1 = it . second ;
2010-10-27 15:34:48 +02:00
FNUMEXPR_ fnumexpr ( FirstEndoDerivative , eq , var , lag ) ;
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 + + ;
}
d1 - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
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 ;
2018-07-17 18:34:07 +02:00
for ( const auto & it : first_derivatives_reordered_exo )
2010-10-27 15:34:48 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , var , eq ;
tie ( lag , ignore , var , eq ) = it . first ;
expr_t d1 = it . second ;
2010-10-27 15:34:48 +02:00
FNUMEXPR_ fnumexpr ( FirstExoDerivative , eq , var , lag ) ;
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 + + ;
}
d1 - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
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
2018-09-21 17:13:19 +02:00
DynamicModel : : writeModelEquationsCode_Block ( const string & basename , const map_idx_t & map_idx , const bool linear_decomposition ) 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 ;
2010-12-10 11:50:27 +01:00
deriv_node_temp_terms_t tef_terms ;
2009-12-16 18:13:23 +01:00
vector < int > feedback_variables ;
bool file_open = false ;
2018-09-21 17:13:19 +02:00
string main_name ;
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/bytecode " ) ;
2018-09-21 17:13:19 +02:00
if ( linear_decomposition )
main_name = basename + " /model/bytecode/non_linear.cod " ;
else
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
FDIMT_ fdimt ( temporary_terms . size ( ) ) ;
2010-07-23 11:20:24 +02:00
fdimt . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
for ( unsigned int block = 0 ; block < getNbBlocks ( ) ; block + + )
{
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 ;
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_mfs = getBlockMfs ( block ) ;
unsigned int block_recursive = block_size - block_mfs ;
int block_max_lag = max_leadlag_block [ block ] . first ;
2014-12-17 09:37:43 +01:00
int block_max_lead = max_leadlag_block [ block ] . second ;
2009-12-16 18:13:23 +01:00
if ( simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE | | simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE
| | simulation_type = = SOLVE_BACKWARD_COMPLETE | | simulation_type = = SOLVE_FORWARD_COMPLETE )
{
2018-06-27 15:01:31 +02:00
Write_Inf_To_Bin_File_Block ( basename , block , u_count_int , file_open ,
2018-09-21 17:13:19 +02:00
simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE , linear_decomposition ) ;
2009-12-16 18:13:23 +01:00
file_open = true ;
}
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > tmp_block_endo_derivative ;
for ( const auto & it : blocks_derivatives [ block ] )
tmp_block_endo_derivative [ { get < 2 > ( it ) , get < 1 > ( it ) , get < 0 > ( it ) } ] = get < 3 > ( it ) ;
map < tuple < int , int , int > , expr_t > tmp_exo_derivative ;
for ( const auto & it : derivative_exo [ block ] )
tmp_exo_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
map < tuple < int , int , int > , expr_t > tmp_exo_det_derivative ;
for ( const auto & it : derivative_exo_det [ block ] )
tmp_exo_det_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
map < tuple < int , int , int > , expr_t > tmp_other_endo_derivative ;
for ( const auto & it : derivative_other_endo [ block ] )
tmp_other_endo_derivative [ { get < 0 > ( it . first ) , get < 2 > ( it . first ) , get < 1 > ( it . first ) } ] = it . second ;
2010-07-23 11:20:24 +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 : tmp_block_endo_derivative )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , var ;
tie ( lag , var , ignore ) = it . first ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_endo + + ;
}
}
2014-12-17 09:37:43 +01:00
unsigned int count_col_det_exo = 0 ;
2010-07-23 11:20:24 +02:00
vector < unsigned int > exo_det ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : exo_det_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( const auto & it1 : it . second )
2014-12-17 09:37:43 +01:00
{
count_col_det_exo + + ;
2018-11-23 17:19:59 +01:00
if ( find ( exo_det . begin ( ) , exo_det . end ( ) , it1 ) = = exo_det . end ( ) )
exo_det . push_back ( it1 ) ;
2014-12-17 09:37:43 +01:00
}
2017-06-01 19:58:32 +02:00
2014-12-17 09:37:43 +01:00
unsigned int count_col_exo = 0 ;
2010-07-23 11:20:24 +02:00
vector < unsigned int > exo ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : exo_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( const auto & it1 : it . second )
2014-12-17 09:37:43 +01:00
{
count_col_exo + + ;
2018-11-23 17:19:59 +01:00
if ( find ( exo . begin ( ) , exo . end ( ) , it1 ) = = exo . end ( ) )
exo . push_back ( it1 ) ;
2014-12-17 09:37:43 +01:00
}
2017-06-01 19:58:32 +02:00
2010-07-23 11:20:24 +02:00
vector < unsigned int > other_endo ;
unsigned int count_col_other_endo = 0 ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : other_endo_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( const auto & it1 : it . second )
2014-12-17 09:37:43 +01:00
{
count_col_other_endo + + ;
2018-11-23 17:19:59 +01:00
if ( find ( other_endo . begin ( ) , other_endo . end ( ) , it1 ) = = other_endo . end ( ) )
other_endo . push_back ( it1 ) ;
2014-12-17 09:37:43 +01:00
}
2017-06-01 19:58:32 +02:00
2009-12-16 18:13:23 +01:00
FBEGINBLOCK_ fbeginblock ( block_mfs ,
simulation_type ,
getBlockFirstEquation ( block ) ,
block_size ,
variable_reordered ,
equation_reordered ,
blocks_linear [ block ] ,
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 ,
count_col_endo ,
2014-12-17 09:37:43 +01:00
exo_det . size ( ) ,
count_col_det_exo ,
exo . size ( ) ,
2010-07-23 11:20:24 +02:00
getBlockExoColSize ( block ) ,
2014-12-17 09:37:43 +01:00
other_endo . size ( ) ,
2010-07-23 11:20:24 +02:00
count_col_other_endo ,
exo_det ,
exo ,
other_endo
2009-12-16 18:13:23 +01:00
) ;
2010-07-23 11:20:24 +02:00
fbeginblock . write ( code_file , instruction_number ) ;
2017-06-01 19:58:32 +02:00
2018-09-21 17:13:19 +02:00
if ( linear_decomposition )
compileTemporaryTerms ( code_file , instruction_number , temporary_terms , map_idx , true , false ) ;
2009-12-16 18:13:23 +01:00
// The equations
2019-04-23 11:07:32 +02:00
for ( i = 0 ; i < static_cast < int > ( block_size ) ; i + + )
2009-12-16 18:13:23 +01:00
{
//The Temporary terms
2010-09-16 19:00:48 +02:00
temporary_terms_t tt2 ;
2018-09-21 17:13:19 +02:00
if ( v_temporary_terms [ block ] [ i ] . size ( ) & & ! linear_decomposition )
2009-12-16 18:13:23 +01:00
{
2018-06-04 12:26:16 +02:00
for ( auto it : v_temporary_terms [ block ] [ i ] )
2009-12-16 18:13:23 +01:00
{
2018-06-04 12:52:14 +02:00
if ( dynamic_cast < AbstractExternalFunctionNode * > ( it ) ! = nullptr )
2018-06-04 12:26:16 +02:00
it - > compileExternalFunctionOutput ( code_file , instruction_number , false , tt2 , map_idx , true , false , tef_terms ) ;
2010-12-10 11:50:27 +01:00
2019-04-23 11:07:32 +02:00
FNUMEXPR_ fnumexpr ( TemporaryTerm , static_cast < int > ( map_idx . find ( it - > idx ) - > second ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2018-06-04 12:26:16 +02:00
it - > compile ( code_file , instruction_number , false , tt2 , map_idx , true , false , tef_terms ) ;
2019-04-23 11:07:32 +02:00
FSTPT_ fstpt ( static_cast < int > ( map_idx . find ( it - > idx ) - > second ) ) ;
2010-07-23 11:20:24 +02:00
fstpt . write ( code_file , instruction_number ) ;
2009-12-16 18:13:23 +01:00
// Insert current node into tt2
2018-06-04 12:26:16 +02:00
tt2 . insert ( it ) ;
2009-04-14 16:39:53 +02:00
# ifdef DEBUGC
2018-11-23 17:19:59 +01:00
cout < < " FSTPT " < < v < < endl ;
2010-07-23 11:20:24 +02:00
instruction_number + + ;
2009-12-16 18:13:23 +01:00
code_file . write ( & FOK , sizeof ( FOK ) ) ;
code_file . write ( reinterpret_cast < char * > ( & k ) , sizeof ( k ) ) ;
ki + + ;
2009-04-14 16:39:53 +02:00
# endif
2009-12-16 18:13:23 +01:00
}
}
2009-04-14 16:39:53 +02:00
# ifdef DEBUGC
2018-11-23 17:19:59 +01:00
for ( const auto & it : v_temporary_terms [ block ] [ i ] )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
auto ii = map_idx . find ( it - > idx ) ;
cout < < " map_idx[ " < < it - > idx < < " ]= " < < ii - > second < < endl ;
2009-12-16 18:13:23 +01:00
}
2009-12-16 14:21:31 +01:00
# endif
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 :
case EVALUATE_BACKWARD :
case EVALUATE_FORWARD :
equ_type = getBlockEquationType ( block , i ) ;
2010-01-22 17:42:08 +01:00
{
FNUMEXPR_ fnumexpr ( 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
}
2009-12-16 18:13:23 +01:00
if ( equ_type = = E_EVALUATE )
{
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2010-07-23 11:20:24 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms , map_idx , true , false ) ;
2009-12-16 18:13:23 +01:00
}
else if ( equ_type = = E_EVALUATE_S )
{
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationRenormalizedExpr ( block , i ) ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2010-07-23 11:20:24 +02:00
rhs - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
lhs - > compile ( code_file , instruction_number , true , temporary_terms , map_idx , true , false ) ;
2009-12-16 18:13:23 +01:00
}
break ;
case SOLVE_BACKWARD_COMPLETE :
case SOLVE_FORWARD_COMPLETE :
case SOLVE_TWO_BOUNDARIES_COMPLETE :
case SOLVE_TWO_BOUNDARIES_SIMPLE :
2019-04-23 11:07:32 +02:00
if ( i < static_cast < int > ( 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 :
2010-01-22 17:42:08 +01:00
FNUMEXPR_ fnumexpr ( ModelEquation , getBlockEquationID ( block , i ) ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
2019-04-23 11:07:32 +02:00
eq_node = static_cast < BinaryOpNode * > ( getBlockEquationExpr ( block , i ) ) ;
2018-11-28 14:32:26 +01:00
lhs = eq_node - > arg1 ;
rhs = eq_node - > arg2 ;
2010-07-23 11:20:24 +02:00
lhs - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
rhs - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , 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
2009-12-16 18:13:23 +01:00
if ( simulation_type ! = EVALUATE_BACKWARD
& & simulation_type ! = EVALUATE_FORWARD )
{
switch ( simulation_type )
{
case SOLVE_BACKWARD_SIMPLE :
case SOLVE_FORWARD_SIMPLE :
2010-01-22 17:42:08 +01:00
{
2010-07-23 11:20:24 +02:00
FNUMEXPR_ fnumexpr ( FirstEndoDerivative , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , 0 ) ;
fnumexpr . write ( code_file , instruction_number ) ;
2010-01-22 17:42:08 +01:00
}
2010-07-23 11:20:24 +02:00
compileDerivative ( code_file , instruction_number , getBlockEquationID ( block , 0 ) , getBlockVariableID ( block , 0 ) , 0 , map_idx ) ;
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 ;
case SOLVE_BACKWARD_COMPLETE :
case SOLVE_FORWARD_COMPLETE :
case SOLVE_TWO_BOUNDARIES_COMPLETE :
case SOLVE_TWO_BOUNDARIES_SIMPLE :
count_u = feedback_variables . size ( ) ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
unsigned int eq , var ;
int lag ;
tie ( eq , var , lag , ignore ) = it ;
2009-12-16 18:13:23 +01:00
unsigned int eqr = getBlockEquationID ( block , eq ) ;
unsigned 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
{
2010-08-18 13:45:07 +02:00
if ( lag ! = 0 & & ( simulation_type = = SOLVE_FORWARD_COMPLETE | | simulation_type = = SOLVE_BACKWARD_COMPLETE ) )
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 ;
2010-01-22 17:42:08 +01:00
FNUMEXPR_ fnumexpr ( FirstEndoDerivative , eqr , varr , lag ) ;
2010-07-23 11:20:24 +02:00
fnumexpr . write ( code_file , instruction_number ) ;
compileChainRuleDerivative ( code_file , instruction_number , eqr , varr , lag , map_idx ) ;
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 + + ;
}
}
2019-04-23 11:07:32 +02:00
for ( i = 0 ; i < static_cast < int > ( block_size ) ; i + + )
2009-12-16 18:13:23 +01:00
{
2019-04-23 11:07:32 +02:00
if ( i > = static_cast < int > ( 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
prev_var = - 1 ;
prev_lag = - 999999999 ;
count_col_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_block_endo_derivative )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , var ;
unsigned int eq ;
tie ( lag , var , eq ) = it . first ;
2010-07-23 11:20:24 +02:00
unsigned int eqr = getBlockEquationID ( block , eq ) ;
unsigned int varr = getBlockVariableID ( block , var ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_endo + + ;
}
FNUMEXPR_ fnumexpr ( FirstEndoDerivative , eqr , varr , lag ) ;
fnumexpr . write ( code_file , instruction_number ) ;
compileDerivative ( code_file , instruction_number , eqr , varr , lag , map_idx ) ;
FSTPG3_ fstpg3 ( eq , var , lag , count_col_endo - 1 ) ;
fstpg3 . write ( code_file , instruction_number ) ;
}
prev_var = - 1 ;
prev_lag = - 999999999 ;
2014-12-17 09:37:43 +01:00
count_col_exo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_exo_derivative )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , eq , var ;
tie ( lag , var , eq ) = it . first ;
2010-07-23 11:20:24 +02:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
int varr = getBlockInitialExogenousID ( block , var ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_exo + + ;
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-07-23 11:20:24 +02:00
FNUMEXPR_ fnumexpr ( FirstExoDerivative , eqr , varr , lag ) ;
fnumexpr . write ( code_file , instruction_number ) ;
id - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
2011-02-04 16:25:38 +01:00
FSTPG3_ fstpg3 ( eq , var , lag , /*var*/ count_col_exo - 1 ) ;
2010-07-23 11:20:24 +02:00
fstpg3 . write ( code_file , instruction_number ) ;
}
prev_var = - 1 ;
prev_lag = - 999999999 ;
int count_col_exo_det = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_exo_det_derivative )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , eq , var ;
tie ( lag , var , eq ) = it . first ;
2010-07-23 11:20:24 +02:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
int varr = getBlockInitialDetExogenousID ( block , var ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_exo_det + + ;
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-07-23 11:20:24 +02:00
FNUMEXPR_ fnumexpr ( FirstExodetDerivative , eqr , varr , lag ) ;
fnumexpr . write ( code_file , instruction_number ) ;
id - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
FSTPG3_ fstpg3 ( eq , var , lag , count_col_exo_det - 1 ) ;
fstpg3 . write ( code_file , instruction_number ) ;
}
prev_var = - 1 ;
prev_lag = - 999999999 ;
count_col_other_endo = 0 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : tmp_other_endo_derivative )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag , eq , var ;
tie ( lag , var , eq ) = it . first ;
2010-07-23 11:20:24 +02:00
int eqr = getBlockInitialEquationID ( block , eq ) ;
int varr = getBlockInitialOtherEndogenousID ( block , var ) ; ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_other_endo + + ;
}
2018-11-23 17:19:59 +01:00
expr_t id = it . second ;
2010-07-23 11:20:24 +02:00
FNUMEXPR_ fnumexpr ( FirstOtherEndoDerivative , eqr , varr , lag ) ;
fnumexpr . write ( code_file , instruction_number ) ;
id - > compile ( code_file , instruction_number , false , temporary_terms , map_idx , true , false ) ;
FSTPG3_ fstpg3 ( eq , var , lag , count_col_other_endo - 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 ) ;
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
2018-06-27 15:01:31 +02:00
DynamicModel : : writeDynamicCFile ( const string & basename , const int order ) const
2009-12-16 18:13:23 +01:00
{
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/src " ) ;
2018-06-27 15:01:31 +02:00
string filename = basename + " /model/src/dynamic.c " ;
string filename_mex = basename + " /model/src/dynamic_mex.c " ;
2011-12-22 14:55:57 +01:00
ofstream mDynamicModelFile , mDynamicMexFile ;
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
2018-06-27 15:12:12 +02:00
mDynamicModelFile . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 18:13:23 +01:00
if ( ! mDynamicModelFile . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
mDynamicModelFile < < " /* " < < endl
< < " * " < < filename < < " : Computes dynamic model for Dynare " < < endl
< < " * " < < endl
< < " * Warning : this file is generated automatically by Dynare " < < endl
< < " * from model file (.mod) " < < endl
< < " */ " < < endl
2011-12-22 14:55:57 +01:00
< < " #include <math.h> " < < endl ;
2019-03-26 15:41:48 +01:00
mDynamicModelFile < < " #include <stdlib.h> " < < endl ;
2011-12-22 14:55:57 +01:00
if ( external_functions_table . get_total_number_of_unique_model_block_external_functions ( ) )
// External Matlab function, implies Dynamic function will call mex
2019-04-24 14:08:32 +02:00
mDynamicModelFile
# ifndef __APPLE__
< < " #include <uchar.h> " < < endl // For MATLAB ≤ R2011a
# else
< < " typedef uint_least16_t char16_t; " < < endl
< < " typedef uint_least32_t char32_t; " < < endl // uchar.h does not exist on macOS
# endif
< < R " (#include " mex . h " ) " < < endl ;
2011-12-22 14:55:57 +01:00
mDynamicModelFile < < " #define max(a, b) (((a) > (b)) ? (a) : (b)) " < < endl
2009-12-16 18:13:23 +01:00
< < " #define min(a, b) (((a) > (b)) ? (b) : (a)) " < < endl ;
2018-07-18 16:18:26 +02:00
// Write function definition if BinaryOpcode::powerDeriv is used
2010-12-13 14:07:05 +01:00
writePowerDerivCHeader ( mDynamicModelFile ) ;
2018-09-25 19:15:22 +02:00
mDynamicModelFile < < endl ;
2009-12-16 18:13:23 +01:00
// Writing the function body
2015-07-27 17:02:51 +02:00
writeDynamicModel ( mDynamicModelFile , true , false ) ;
2009-12-16 18:13:23 +01:00
2018-09-25 19:15:22 +02:00
mDynamicModelFile < < endl ;
2016-10-14 14:30:14 +02:00
writePowerDeriv ( mDynamicModelFile ) ;
2009-12-16 18:13:23 +01:00
mDynamicModelFile . close ( ) ;
2011-12-22 14:55:57 +01:00
2018-06-27 15:12:12 +02:00
mDynamicMexFile . open ( filename_mex , ios : : out | ios : : binary ) ;
2011-12-22 14:55:57 +01:00
if ( ! mDynamicMexFile . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename_mex < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
// Writing the gateway routine
mDynamicMexFile < < " /* " < < endl
< < " * " < < filename_mex < < " : The gateway routine used to call the Dynamic function "
< < " located in " < < filename < < endl
< < " * " < < endl
< < " * Warning : this file is generated automatically by Dynare " < < endl
< < " * from model file (.mod) " < < endl
< < endl
2018-09-25 19:15:22 +02:00
< < " */ " < < endl
< < endl
< < " #include <stdlib.h> " < < endl
2019-04-24 14:08:32 +02:00
# ifndef __APPLE__
2019-03-26 15:41:48 +01:00
< < " #include <uchar.h> " < < endl // For MATLAB ≤ R2011a
2019-04-24 14:08:32 +02:00
# else
< < " typedef uint_least16_t char16_t; " < < endl
< < " typedef uint_least32_t char32_t; " < < endl // uchar.h does not exist on macOS
# endif
2019-04-03 16:32:52 +02:00
< < R " (#include " mex . h " ) " < < endl
2018-09-25 19:15:22 +02:00
< < endl
< < " void dynamic_resid_tt(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); " < < endl
< < " void dynamic_resid(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *residual); " < < endl
< < " void dynamic_g1_tt(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); " < < endl
< < " void dynamic_g1(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *g1); " < < endl
< < " void dynamic_g2_tt(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); " < < endl
< < " void dynamic_g2(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v2); " < < endl
< < " void dynamic_g3_tt(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T); " < < endl
< < " void dynamic_g3(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double *v3); " < < endl
2011-12-22 14:55:57 +01:00
< < " void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) " < < endl
< < " { " < < endl
< < " /* Check that no derivatives of higher order than computed are being requested */ " < < endl
< < " if (nlhs > " < < order + 1 < < " ) " < < endl
2019-04-03 16:32:52 +02:00
< < R " ( mexErrMsgTxt( " Derivatives of higher order than computed have been requested " );) " < < endl
2011-12-22 14:55:57 +01:00
< < " /* Create a pointer to the input matrix y. */ " < < endl
2018-09-25 19:15:22 +02:00
< < " double *y = mxGetPr(prhs[0]); " < < endl
2011-12-22 14:55:57 +01:00
< < endl
< < " /* Create a pointer to the input matrix x. */ " < < endl
2018-09-25 19:15:22 +02:00
< < " double *x = mxGetPr(prhs[1]); " < < endl
2011-12-22 14:55:57 +01:00
< < endl
< < " /* Create a pointer to the input matrix params. */ " < < endl
2018-09-25 19:15:22 +02:00
< < " double *params = mxGetPr(prhs[2]); " < < endl
2011-12-22 14:55:57 +01:00
< < endl
< < " /* Create a pointer to the input matrix steady_state. */ " < < endl
2018-09-25 19:15:22 +02:00
< < " double *steady_state = mxGetPr(prhs[3]); " < < endl
2011-12-22 14:55:57 +01:00
< < endl
< < " /* Fetch time index */ " < < endl
2018-09-25 19:15:22 +02:00
< < " int it_ = (int) mxGetScalar(prhs[4]) - 1; " < < endl
2011-12-22 14:55:57 +01:00
< < endl
< < " /* Gets number of rows of matrix x. */ " < < endl
2018-09-25 19:15:22 +02:00
< < " int nb_row_x = mxGetM(prhs[1]); " < < endl
< < endl
2019-04-12 15:41:52 +02:00
< < " double *T = (double *) malloc(sizeof(double)* " < < ntt < < " ); "
2011-12-22 14:55:57 +01:00
< < endl
< < " if (nlhs >= 1) " < < endl
< < " { " < < endl
< < " /* Set the output pointer to the output matrix residual. */ " < < endl
< < " plhs[0] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " ,1, mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " 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
2011-12-22 14:55:57 +01:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 2) " < < endl
< < " { " < < endl
< < " /* Set the output pointer to the output matrix g1. */ " < < endl
< < " plhs[1] = mxCreateDoubleMatrix( " < < equations . size ( ) < < " , " < < dynJacobianColsNbr < < " , mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " 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
2011-12-22 14:55:57 +01:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 3) " < < endl
< < " { " < < endl
< < " /* Set the output pointer to the output matrix v2. */ " < < endl
2018-11-15 16:39:53 +01:00
< < " plhs[2] = mxCreateDoubleMatrix( " < < NNZDerivatives [ 2 ] < < " , " < < 3
2011-12-22 14:55:57 +01:00
< < " , mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " double *v2 = mxGetPr(plhs[2]); " < < endl
< < " dynamic_g2_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
< < " dynamic_g2(y, x, nb_row_x, params, steady_state, it_, T, v2); " < < endl
2011-12-22 14:55:57 +01:00
< < " } " < < endl
< < endl
< < " if (nlhs >= 4) " < < endl
< < " { " < < endl
< < " /* Set the output pointer to the output matrix v3. */ " < < endl
2018-11-15 16:39:53 +01:00
< < " plhs[3] = mxCreateDoubleMatrix( " < < NNZDerivatives [ 3 ] < < " , " < < 3 < < " , mxREAL); " < < endl
2018-09-25 19:15:22 +02:00
< < " double *v3 = mxGetPr(plhs[3]); " < < endl
< < " dynamic_g3_tt(y, x, nb_row_x, params, steady_state, it_, T); " < < endl
< < " dynamic_g3(y, x, nb_row_x, params, steady_state, it_, T, v3); " < < endl
2011-12-22 14:55:57 +01:00
< < " } " < < endl
< < endl
2018-09-25 19:15:22 +02:00
< < " free(T); "
2011-12-22 14:55:57 +01:00
< < " } " < < endl ;
mDynamicMexFile . close ( ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
string
2009-12-16 18:13:23 +01:00
DynamicModel : : reform ( const string name1 ) const
{
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
}
return ( name ) ;
}
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
{
if ( nonzero_hessian_eqs . size ( ) ! = 1 )
output < < " [ " ;
2018-06-04 15:03:26 +02:00
for ( auto it = nonzero_hessian_eqs . begin ( ) ;
2018-01-11 12:55:36 +01:00
it ! = nonzero_hessian_eqs . end ( ) ; it + + )
{
if ( it ! = nonzero_hessian_eqs . begin ( ) )
output < < " " ;
output < < it - > first ;
}
if ( nonzero_hessian_eqs . size ( ) ! = 1 )
output < < " ] " ;
}
void
DynamicModel : : setNonZeroHessianEquations ( map < int , string > & eqs )
2016-07-27 21:01:54 +02:00
{
2018-11-15 16:39:53 +01:00
for ( const auto & it : derivatives [ 2 ] )
2018-06-05 15:34:34 +02:00
{
2018-11-15 16:39:53 +01:00
int eq = it . first [ 0 ] ;
2018-06-05 15:34:34 +02:00
if ( nonzero_hessian_eqs . find ( eq ) = = nonzero_hessian_eqs . end ( ) )
{
nonzero_hessian_eqs [ eq ] = " " ;
for ( auto & equation_tag : equation_tags )
if ( equation_tag . first = = eq )
if ( equation_tag . second . first = = " name " )
{
nonzero_hessian_eqs [ eq ] = equation_tag . second . second ;
break ;
}
}
}
2018-01-11 12:55:36 +01:00
eqs = nonzero_hessian_eqs ;
2016-07-27 21:01:54 +02:00
}
2009-04-14 16:39:53 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : Write_Inf_To_Bin_File_Block ( const string & basename , const int & num ,
2018-09-21 17:13:19 +02:00
int & u_count_int , bool & file_open , bool is_two_boundaries , const bool linear_decomposition ) const
2009-12-16 18:13:23 +01:00
{
int j ;
std : : ofstream SaveCode ;
2018-09-21 17:13:19 +02:00
string filename ;
if ( ! linear_decomposition )
filename = basename + " /model/bytecode/dynamic.bin " ;
else
filename = basename + " /model/bytecode/non_linear.bin " ;
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 ;
unsigned int block_size = getBlockSize ( num ) ;
unsigned int block_mfs = getBlockMfs ( num ) ;
unsigned int block_recursive = block_size - block_mfs ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ num ] )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
unsigned int eq , var ;
int lag ;
tie ( eq , var , lag , ignore ) = it ;
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 ) ) ;
SaveCode . write ( reinterpret_cast < char * > ( & lag ) , sizeof ( lag ) ) ;
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 ;
2019-04-23 11:07:32 +02:00
for ( j = block_recursive ; j < static_cast < int > ( block_size ) ; j + + )
2009-12-16 18:13:23 +01:00
{
unsigned int varr = getBlockVariableID ( num , j ) ;
SaveCode . write ( reinterpret_cast < char * > ( & varr ) , sizeof ( varr ) ) ;
}
2019-04-23 11:07:32 +02:00
for ( j = block_recursive ; j < static_cast < int > ( block_size ) ; j + + )
2009-12-16 18:13:23 +01:00
{
unsigned int eqr = getBlockEquationID ( num , j ) ;
SaveCode . write ( reinterpret_cast < char * > ( & eqr ) , sizeof ( eqr ) ) ;
}
SaveCode . close ( ) ;
}
2009-04-14 16:39:53 +02:00
void
2018-06-27 15:01:31 +02:00
DynamicModel : : writeSparseDynamicMFile ( const string & basename ) const
2009-12-16 18:13:23 +01:00
{
string sp ;
ofstream mDynamicModelFile ;
ostringstream tmp , tmp1 , tmp_eq ;
bool OK ;
2018-06-27 15:01:31 +02:00
string filename = packageDir ( basename ) + " /dynamic.m " ;
2018-06-27 15:12:12 +02:00
mDynamicModelFile . open ( filename , ios : : out | ios : : binary ) ;
2009-12-16 18:13:23 +01:00
if ( ! mDynamicModelFile . is_open ( ) )
{
cerr < < " Error: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " % " < < 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 ;
2009-12-16 18:13:23 +01:00
int Nb_SGE = 0 ;
2014-10-04 12:19:52 +02:00
bool open_par = false ;
2009-12-16 18:13:23 +01:00
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " function [varargout] = dynamic(options_, M_, oo_, varargin) " < < endl
< < " g2=[];g3=[]; " < < endl ;
2009-12-16 18:13:23 +01:00
//Temporary variables declaration
OK = true ;
ostringstream tmp_output ;
2018-06-04 12:26:16 +02:00
for ( auto temporary_term : temporary_terms )
2009-12-16 18:13:23 +01:00
{
if ( OK )
OK = false ;
else
tmp_output < < " " ;
2018-05-28 11:56:34 +02:00
// In the following, "Static" is used to avoid getting the "(it_)" subscripting
2018-09-05 18:27:13 +02:00
temporary_term - > writeOutput ( tmp_output , ExprNodeOutputType : : matlabStaticModelSparse , temporary_terms , { } ) ;
2009-12-16 18:13:23 +01:00
}
if ( tmp_output . str ( ) . length ( ) > 0 )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " global " < < tmp_output . str ( ) < < " ; " < < endl ;
2009-08-25 11:43:01 +02:00
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " T_init=zeros(1,options_.periods+M_.maximum_lag+M_.maximum_lead); " < < endl ;
2009-12-16 18:13:23 +01:00
tmp_output . str ( " " ) ;
2018-06-04 12:26:16 +02:00
for ( auto temporary_term : temporary_terms )
2009-12-16 18:13:23 +01:00
{
tmp_output < < " " ;
2018-05-28 11:56:34 +02:00
// In the following, "Static" is used to avoid getting the "(it_)" subscripting
2018-09-05 18:27:13 +02:00
temporary_term - > writeOutput ( tmp_output , ExprNodeOutputType : : matlabStaticModelSparse , temporary_terms , { } ) ;
2018-11-23 17:19:59 +01:00
tmp_output < < " =T_init; " < < endl ;
2009-12-16 18:13:23 +01:00
}
if ( tmp_output . str ( ) . length ( ) > 0 )
mDynamicModelFile < < tmp_output . str ( ) ;
mDynamicModelFile < < " y_kmin=M_.maximum_lag; " < < endl
< < " y_kmax=M_.maximum_lead; " < < endl
< < " y_size=M_.endo_nbr; " < < endl
< < " if(length(varargin)>0) " < < endl
< < " %it is a simple evaluation of the dynamic model for time _it " < < endl
2010-10-27 15:34:48 +02:00
< < " y=varargin{1}; " < < endl
< < " x=varargin{2}; " < < endl
2009-12-16 18:13:23 +01:00
< < " params=varargin{3}; " < < endl
2011-03-13 17:06:57 +01:00
< < " steady_state=varargin{4}; " < < endl
< < " it_=varargin{5}; " < < endl
< < " dr=varargin{6}; " < < endl
2009-12-16 18:13:23 +01:00
< < " Per_u_=0; " < < endl
< < " Per_y_=it_*y_size; " < < endl
2010-10-27 15:34:48 +02:00
< < " ys=y(it_,:); " < < endl ;
2009-12-16 18:13:23 +01:00
tmp . str ( " " ) ;
tmp_eq . str ( " " ) ;
unsigned int nb_blocks = getNbBlocks ( ) ;
unsigned int block = 0 ;
for ( int count_call = 1 ; block < nb_blocks ; block + + , count_call + + )
{
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_mfs = getBlockMfs ( block ) ;
unsigned int block_recursive = block_size - block_mfs ;
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
if ( simulation_type = = EVALUATE_FORWARD | | simulation_type = = EVALUATE_BACKWARD )
{
for ( unsigned int ik = 0 ; ik < block_size ; ik + + )
{
tmp < < " " < < getBlockVariableID ( block , ik ) + 1 ;
tmp_eq < < " " < < getBlockEquationID ( block , ik ) + 1 ;
}
}
else
{
for ( unsigned int ik = block_recursive ; ik < block_size ; ik + + )
{
tmp < < " " < < getBlockVariableID ( block , ik ) + 1 ;
tmp_eq < < " " < < getBlockEquationID ( block , ik ) + 1 ;
}
}
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " y_index_eq=[ " < < tmp_eq . str ( ) < < " ]; " < < endl
< < " y_index=[ " < < tmp . str ( ) < < " ]; " < < endl ;
2009-12-16 18:13:23 +01:00
switch ( simulation_type )
{
case EVALUATE_FORWARD :
case EVALUATE_BACKWARD :
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " [y, dr( " < < count_call < < " ).g1, dr( " < < count_call < < " ).g2, dr( " < < count_call < < " ).g3, dr( " < < count_call < < " ).g1_x, dr( " < < count_call < < " ).g1_xd, dr( " < < count_call < < " ).g1_o]= " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, 1, it_-1, 1); " < < endl
< < " residual(y_index_eq)=ys(y_index)-y(it_, y_index); " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_FORWARD_SIMPLE :
case SOLVE_BACKWARD_SIMPLE :
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " [r, y, dr( " < < count_call < < " ).g1, dr( " < < count_call < < " ).g2, dr( " < < count_call < < " ).g3, dr( " < < count_call < < " ).g1_x, dr( " < < count_call < < " ).g1_xd, dr( " < < count_call < < " ).g1_o]= " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, it_, 1); " < < endl
< < " residual(y_index_eq)=r; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_FORWARD_COMPLETE :
case SOLVE_BACKWARD_COMPLETE :
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " [r, y, dr( " < < count_call < < " ).g1, dr( " < < count_call < < " ).g2, dr( " < < count_call < < " ).g3, dr( " < < count_call < < " ).g1_x, dr( " < < count_call < < " ).g1_xd, dr( " < < count_call < < " ).g1_o]= " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, it_, 1); " < < endl
< < " residual(y_index_eq)=r; " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
case SOLVE_TWO_BOUNDARIES_COMPLETE :
case SOLVE_TWO_BOUNDARIES_SIMPLE :
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " [r, y, dr( " < < count_call < < " ).g1, dr( " < < count_call < < " ).g2, dr( " < < count_call < < " ).g3, b, dr( " < < count_call < < " ).g1_x, dr( " < < count_call < < " ).g1_xd, dr( " < < count_call < < " ).g1_o]= " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, it_- " < < max_lag < < " , 1, " < < max_lag < < " , " < < block_recursive < < " , " < < " options_.periods " < < " ); " < < endl
< < " residual(y_index_eq)=r(:,M_.maximum_lag+1); " < < endl ;
2009-12-16 18:13:23 +01:00
break ;
default :
break ;
}
tmp_eq . str ( " " ) ;
tmp . str ( " " ) ;
}
if ( tmp1 . str ( ) . length ( ) )
{
mDynamicModelFile < < tmp1 . str ( ) ;
tmp1 . str ( " " ) ;
}
mDynamicModelFile < < " varargout{1}=residual; " < < endl
< < " varargout{2}=dr; " < < endl
< < " return; " < < endl
< < " end; " < < endl
< < " %it is the deterministic simulation of the block decomposed dynamic model " < < endl
2010-09-17 09:57:38 +02:00
< < " if(options_.stack_solve_algo==0) " < < endl
2009-12-16 18:13:23 +01:00
< < " mthd='Sparse LU'; " < < endl
2010-09-17 09:57:38 +02:00
< < " elseif(options_.stack_solve_algo==1) " < < endl
< < " mthd='Relaxation'; " < < endl
2009-12-16 18:13:23 +01:00
< < " elseif(options_.stack_solve_algo==2) " < < endl
< < " mthd='GMRES'; " < < endl
< < " elseif(options_.stack_solve_algo==3) " < < endl
< < " mthd='BICGSTAB'; " < < endl
< < " elseif(options_.stack_solve_algo==4) " < < endl
< < " mthd='OPTIMPATH'; " < < endl
< < " else " < < endl
< < " mthd='UNKNOWN'; " < < endl
< < " end; " < < endl
2017-06-01 19:58:32 +02:00
< < " if options_.verbosity " < < endl
2015-02-20 14:44:45 +01:00
< < " printline(41) " < < endl
< < " disp(sprintf('MODEL SIMULATION (method=%s):',mthd)) " < < endl
2017-06-01 19:58:32 +02:00
< < " skipline() " < < endl
< < " end " < < endl
2009-12-16 18:13:23 +01:00
< < " periods=options_.periods; " < < endl
2013-10-09 13:06:06 +02:00
< < " maxit_=options_.simul.maxit; " < < endl
2009-12-16 18:13:23 +01:00
< < " solve_tolf=options_.solve_tolf; " < < endl
< < " y=oo_.endo_simul'; " < < endl
2018-11-23 17:19:59 +01:00
< < " x=oo_.exo_simul; " < < endl
< < " params=M_.params; " < < endl
< < " steady_state=oo_.steady_state; " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl ;
2009-12-16 18:13:23 +01:00
for ( block = 0 ; block < nb_blocks ; block + + )
{
unsigned int block_size = getBlockSize ( block ) ;
unsigned int block_mfs = getBlockMfs ( block ) ;
unsigned int block_recursive = block_size - block_mfs ;
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
if ( ( simulation_type = = EVALUATE_FORWARD ) & & ( block_size ) )
{
2014-10-04 12:19:52 +02:00
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end " < < endl ;
mDynamicModelFile < < " oo_.deterministic_simulation.status = 1; " < < endl
< < " oo_.deterministic_simulation.error = 0; " < < endl
< < " oo_.deterministic_simulation.iterations = 0; " < < endl
< < " if(isfield(oo_.deterministic_simulation,'block')) " < < endl
< < " blck_num = length(oo_.deterministic_simulation.block)+1; " < < endl
< < " else " < < endl
< < " blck_num = 1; " < < endl
< < " end; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).status = 1; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).error = 0; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).iterations = 0; " < < endl
< < " g1=[];g2=[];g3=[]; " < < endl
< < " y= " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, 0, y_kmin, periods); " < < endl
< < " tmp = y(:,M_.block_structure.block( " < < block + 1 < < " ).variable); " < < endl
< < " if any(isnan(tmp) | isinf(tmp)) " < < endl
< < " disp(['Inf or Nan value during the evaluation of block " < < block < < " ']); " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl
< < " oo_.deterministic_simulation.error = 100; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
else if ( ( simulation_type = = EVALUATE_BACKWARD ) & & ( block_size ) )
{
2014-10-04 12:19:52 +02:00
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end " < < endl ;
mDynamicModelFile < < " oo_.deterministic_simulation.status = 1; " < < endl
< < " oo_.deterministic_simulation.error = 0; " < < endl
< < " oo_.deterministic_simulation.iterations = 0; " < < endl
< < " if(isfield(oo_.deterministic_simulation,'block')) " < < endl
< < " blck_num = length(oo_.deterministic_simulation.block)+1; " < < endl
< < " else " < < endl
< < " blck_num = 1; " < < endl
< < " end; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).status = 1; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).error = 0; " < < endl
< < " oo_.deterministic_simulation.block(blck_num).iterations = 0; " < < endl
< < " g1=[];g2=[];g3=[]; " < < endl
< < " " < < basename < < " .block.dynamic_ " < < block + 1 < < " (y, x, params, steady_state, 0, y_kmin, periods); " < < endl
< < " tmp = y(:,M_.block_structure.block( " < < block + 1 < < " ).variable); " < < endl
< < " if any(isnan(tmp) | isinf(tmp)) " < < endl
< < " disp(['Inf or Nan value during the evaluation of block " < < block < < " ']); " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl
< < " oo_.deterministic_simulation.error = 100; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
else if ( ( simulation_type = = SOLVE_FORWARD_COMPLETE | | simulation_type = = SOLVE_FORWARD_SIMPLE ) & & ( block_size ) )
{
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end " < < endl ;
2009-12-16 18:13:23 +01:00
open_par = false ;
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " g1=0; " < < endl
< < " r=0; " < < endl ;
2009-12-16 18:13:23 +01:00
tmp . str ( " " ) ;
for ( unsigned int ik = block_recursive ; ik < block_size ; ik + + )
2018-11-23 17:19:59 +01:00
tmp < < " " < < getBlockVariableID ( block , ik ) + 1 ;
mDynamicModelFile < < " y_index = [ " < < tmp . str ( ) < < " ]; " < < endl ;
2009-12-16 18:13:23 +01:00
int nze = blocks_derivatives [ block ] . size ( ) ;
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " if(isfield(oo_.deterministic_simulation,'block')) " < < endl
< < " blck_num = length(oo_.deterministic_simulation.block)+1; " < < endl
< < " else " < < endl
< < " blck_num = 1; " < < endl
< < " end; " < < endl
< < " y = solve_one_boundary(' " < < basename < < " .block.dynamic_ " < < block + 1 < < " ' "
< < " , y, x, params, steady_state, y_index, " < < nze
< < " , options_.periods, " < < blocks_linear [ block ]
< < " , blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " < < cutoff < < " , options_.stack_solve_algo, 1, 1, 0); " < < endl
< < " tmp = y(:,M_.block_structure.block( " < < block + 1 < < " ).variable); " < < endl
< < " if any(isnan(tmp) | isinf(tmp)) " < < endl
< < " disp(['Inf or Nan value during the resolution of block " < < block < < " ']); " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl
< < " oo_.deterministic_simulation.error = 100; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
else if ( ( simulation_type = = SOLVE_BACKWARD_COMPLETE | | simulation_type = = SOLVE_BACKWARD_SIMPLE ) & & ( block_size ) )
{
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end " < < endl ;
2009-12-16 18:13:23 +01:00
open_par = false ;
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " g1=0; " < < endl
< < " r=0; " < < endl ;
2009-12-16 18:13:23 +01:00
tmp . str ( " " ) ;
for ( unsigned int ik = block_recursive ; ik < block_size ; ik + + )
2018-11-23 17:19:59 +01:00
tmp < < " " < < getBlockVariableID ( block , ik ) + 1 ;
mDynamicModelFile < < " y_index = [ " < < tmp . str ( ) < < " ]; " < < endl ;
2009-12-16 18:13:23 +01:00
int nze = blocks_derivatives [ block ] . size ( ) ;
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " if(isfield(oo_.deterministic_simulation,'block')) " < < endl
< < " blck_num = length(oo_.deterministic_simulation.block)+1; " < < endl
< < " else " < < endl
< < " blck_num = 1; " < < endl
< < " end; " < < endl
< < " y = solve_one_boundary(' " < < basename < < " .block.dynamic_ " < < block + 1 < < " ' "
2011-03-13 17:06:57 +01:00
< < " , y, x, params, steady_state, y_index, " < < nze
2009-12-16 18:13:23 +01:00
< < " , options_.periods, " < < blocks_linear [ block ]
2018-11-23 17:19:59 +01:00
< < " , blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " < < cutoff < < " , options_.stack_solve_algo, 1, 1, 0); " < < endl
< < " tmp = y(:,M_.block_structure.block( " < < block + 1 < < " ).variable); " < < endl
< < " if any(isnan(tmp) | isinf(tmp)) " < < endl
< < " disp(['Inf or Nan value during the resolution of block " < < block < < " ']); " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl
< < " oo_.deterministic_simulation.error = 100; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
else if ( ( simulation_type = = SOLVE_TWO_BOUNDARIES_COMPLETE | | simulation_type = = SOLVE_TWO_BOUNDARIES_SIMPLE ) & & ( block_size ) )
{
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end " < < endl ;
2009-12-16 18:13:23 +01:00
open_par = false ;
Nb_SGE + + ;
int nze = blocks_derivatives [ block ] . size ( ) ;
mDynamicModelFile < < " y_index=[ " ;
for ( unsigned int ik = block_recursive ; ik < block_size ; ik + + )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " " < < getBlockVariableID ( block , ik ) + 1 ;
mDynamicModelFile < < " ]; " < < endl
< < " if(isfield(oo_.deterministic_simulation,'block')) " < < endl
< < " blck_num = length(oo_.deterministic_simulation.block)+1; " < < endl
< < " else " < < endl
< < " blck_num = 1; " < < endl
< < " end; " < < endl
< < " [y oo_] = solve_two_boundaries(' " < < basename < < " .block.dynamic_ " < < block + 1 < < " ' "
2011-03-13 17:06:57 +01:00
< < " , y, x, params, steady_state, y_index, " < < nze
2009-12-16 18:13:23 +01:00
< < " , options_.periods, " < < max_leadlag_block [ block ] . first
< < " , " < < max_leadlag_block [ block ] . second
< < " , " < < blocks_linear [ block ]
2018-11-23 17:19:59 +01:00
< < " , blck_num, y_kmin, options_.simul.maxit, options_.solve_tolf, options_.slowc, " < < cutoff < < " , options_.stack_solve_algo, options_, M_, oo_); " < < endl
< < " tmp = y(:,M_.block_structure.block( " < < block + 1 < < " ).variable); " < < endl
< < " if any(isnan(tmp) | isinf(tmp)) " < < endl
< < " disp(['Inf or Nan value during the resolution of block " < < block < < " ']); " < < endl
< < " oo_.deterministic_simulation.status = 0; " < < endl
< < " oo_.deterministic_simulation.error = 100; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
}
}
if ( open_par )
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " end; " < < endl ;
2009-12-16 18:13:23 +01:00
open_par = false ;
2018-11-23 17:19:59 +01:00
mDynamicModelFile < < " oo_.endo_simul = y'; " < < endl
< < " varargout{1} = oo_; " < < endl
< < " return; " < < endl
< < " end " < < endl ;
2010-12-13 14:07:05 +01:00
2009-12-16 18:13:23 +01:00
mDynamicModelFile . close ( ) ;
2009-04-14 16:39:53 +02:00
2018-06-27 15:01:31 +02:00
writeModelEquationsOrdered_M ( basename ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
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 " )
2018-06-27 15:01:31 +02: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-04-12 15:41:52 +02:00
vector < ostringstream > d_output ( derivatives . size ( ) ) ; // Derivatives output (at all orders, including 0=residual)
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
2018-11-15 16:39:53 +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 . */
ostringstream col0_output , col1_output , col2_output ;
int k = 0 ; // Current line index in the 3-column matrix
for ( const auto & dit : derivatives [ i ] )
{
const vector < int > & vidx = dit . first ;
expr_t d = dit . second ;
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
{
2019-04-12 15:41:52 +02:00
sparseHelper ( i , col0_output , k , 0 , output_type ) ;
2018-11-19 15:18:09 +01:00
col0_output < < " = " < < eq + 1 < < " ; " < < endl ;
2015-08-20 12:18:19 +02:00
2019-04-12 15:41:52 +02:00
sparseHelper ( i , col1_output , k , 1 , output_type ) ;
col1_output < < " = " < < col_idx + 1 < < " ; " < < endl ;
2015-08-20 12:18:19 +02:00
2019-04-12 15:41:52 +02:00
sparseHelper ( i , col2_output , k , 2 , output_type ) ;
2018-11-19 15:18:09 +01:00
col2_output < < " = " ;
2019-04-12 15:41:52 +02:00
d - > writeOutput ( col2_output , output_type , temp_term_union , temporary_terms_idxs , tef_terms ) ;
2018-11-19 15:18:09 +01:00
col2_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
{
sparseHelper ( 2 , col0_output , k , 0 , output_type ) ;
col0_output < < " = " < < eq + 1 < < " ; " < < endl ;
sparseHelper ( 2 , col1_output , k , 1 , output_type ) ;
col1_output < < " = " < < col_idx_sym + 1 < < " ; " < < endl ;
sparseHelper ( 2 , col2_output , k , 2 , output_type ) ;
col2_output < < " = " ;
sparseHelper ( 2 , col2_output , k - 1 , 2 , output_type ) ;
col2_output < < " ; " < < endl ;
k + + ;
}
}
}
if ( output_type ! = ExprNodeOutputType : : juliaDynamicModel )
d_output [ i ] < < col0_output . str ( ) < < col1_output . str ( ) < < col2_output . str ( ) ;
}
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 vname = " v " + to_string ( i ) ;
string gprevname = " g " + to_string ( i - 1 ) ;
init_output . str ( " " ) ;
end_output . str ( " " ) ;
if ( derivatives [ i ] . size ( ) )
{
init_output < < vname < < " = zeros( " < < NNZDerivatives [ i ] < < " ,3); " ;
end_output < < gname < < " = sparse( "
< < vname < < " (:,1), "
< < vname < < " (:,2), "
< < vname < < " (:,3), "
< < 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 ) ;
string argname = i = = 0 ? " residual " : i = = 1 ? " g1 " : " v " + to_string ( i ) ;
DynamicOutput < < " void dynamic_ " < < funcname < < " _tt(const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, double *T) " < < endl
< < " { " < < endl
< < tt_output [ i ] . str ( )
< < " } " < < endl
< < endl
< < " void dynamic_ " < < funcname < < " (const double *y, const double *x, int nb_row_x, const double *params, const double *steady_state, int it_, const double *T, double * " < < argname < < " ) " < < endl
< < " { " < < 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
{
2018-06-27 15:01:31 +02:00
string filename = basename + " Dynamic.jl " ;
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 ) ;
}
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
< < " using Utils " < < 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
< < " [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
< < " 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
< < " end " < < endl ;
output . close ( ) ;
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)
for ( const auto & it : derivatives [ 1 ] )
{
if ( symbol_table . getType ( getSymbIDByDerivID ( it . first [ 1 ] ) ) ! = SymbolType : : endogenous )
continue ;
int tsid = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( it . first [ 1 ] ) ) ;
int lag = getLagByDerivID ( it . first [ 1 ] ) ;
if ( lag = = - 1 )
nzij_pred . emplace_back ( tsid , it . first [ 0 ] ) ;
else if ( lag = = 0 )
nzij_current . emplace_back ( tsid , it . first [ 0 ] ) ;
else
nzij_fwrd . emplace_back ( tsid , it . first [ 0 ] ) ;
}
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 ;
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 + + ;
}
} ;
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
DynamicModel : : parseIncludeExcludeEquations ( const string & inc_exc_eq_tags , set < pair < string , string > > & eq_tag_set , bool exclude_eqs )
{
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 ) ;
regex q ( " ^ \\ w+ \\ s*= " ) ;
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 = " '[^']+' " ;
string non_quote_regex = " [^, \\ s]+ " ;
regex r ( " ( \\ s* " + quote_regex + " | " + non_quote_regex + " \\ s*) ( , \ \ s * ( " + quote_regex + " | " + non_quote_regex + " ) \ \ s * ) * " ) ;
if ( ! regex_match ( tags , r ) )
{
cerr < < " Error: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " )
< < " : argument is of incorrect format. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
regex s ( quote_regex + " | " + non_quote_regex ) ;
for ( auto it = sregex_iterator ( tags . begin ( ) , tags . end ( ) , s ) ;
it ! = sregex_iterator ( ) ; it + + )
{
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
DynamicModel : : includeExcludeEquations ( const string & eqs , bool exclude_eqs )
{
if ( eqs . empty ( ) )
return ;
set < pair < string , string > > eq_tag_set ;
parseIncludeExcludeEquations ( eqs , eq_tag_set , exclude_eqs ) ;
vector < int > excluded_vars =
ModelTree : : includeExcludeEquations ( eq_tag_set , exclude_eqs ,
equations , equations_lineno ,
equation_tags , equation_tags_xref , false ) ;
// `static_only_equation_tags` is `vector<vector<pair<string, string>>>`
// while `equation_tags` is `vector<pair<int, pair<string, string>>>`
// so convert former structure to latter to conform with function call
int n = 0 ;
vector < pair < int , pair < string , string > > > tmp_static_only_equation_tags ;
for ( auto & eqn_tags : static_only_equations_equation_tags )
{
for ( auto & eqn_tag : eqn_tags )
tmp_static_only_equation_tags . emplace_back ( make_pair ( n , eqn_tag ) ) ;
n + + ;
}
// 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 ,
tmp_static_only_equation_tags ,
static_only_equation_tags_xref , true ) ;
if ( ! eq_tag_set . empty ( ) )
{
cerr < < " ERROR: " < < ( exclude_eqs ? " exclude_eqs " : " include_eqs " ) < < " : The equations specified by ` " ;
cerr < < eq_tag_set . begin ( ) - > first < < " = " ;
for ( auto & it : eq_tag_set )
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 ) ;
}
// convert back static equation info
if ( static_only_equations . empty ( ) )
static_only_equations_equation_tags . clear ( ) ;
else
{
static_only_equations_equation_tags . resize ( static_only_equations . size ( ) ) ;
fill ( static_only_equations_equation_tags . begin ( ) , static_only_equations_equation_tags . end ( ) , vector < pair < string , string > > ( ) ) ;
for ( auto & it : tmp_static_only_equation_tags )
static_only_equations_equation_tags . at ( it . first ) . emplace_back ( it . second ) ;
}
// Collect list of used variables in updated list of equations
set < pair < int , int > > eqn_vars ;
for ( const auto & eqn : equations )
eqn - > collectDynamicVariables ( SymbolType : : endogenous , eqn_vars ) ;
for ( const auto & eqn : static_only_equations )
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 ;
for ( const auto & it : eqn_vars )
if ( it . first = = ev )
{
symbol_table . changeType ( ev , SymbolType : : exogenous ) ;
found = true ;
break ;
}
if ( ! found )
symbol_table . changeType ( ev , SymbolType : : excludedVariable ) ;
}
}
2009-04-14 16:39:53 +02:00
void
2018-09-21 17:13:19 +02:00
DynamicModel : : writeOutput ( ostream & output , const string & basename , bool block_decomposition , bool linear_decomposition , bool byte_code , bool use_dll , int order , bool estimation_present , bool compute_xrefs , bool julia ) 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 .
*/
2015-07-29 14:59:09 +02:00
string modstruct ;
string outstruct ;
if ( julia )
{
2016-05-19 18:32:48 +02:00
modstruct = " model_. " ;
outstruct = " oo_. " ;
2015-07-29 14:59:09 +02:00
}
else
{
modstruct = " M_. " ;
outstruct = " oo_. " ;
}
2019-09-24 14:03:38 +02:00
output < < modstruct < < " orig_maximum_endo_lag = " < < max_endo_lag_orig < < " ; " < < endl
2018-03-01 09:58:04 +01:00
< < modstruct < < " orig_maximum_endo_lead = " < < max_endo_lead_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_exo_lag = " < < max_exo_lag_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_exo_lead = " < < max_exo_lead_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_exo_det_lag = " < < max_exo_det_lag_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_exo_det_lead = " < < max_exo_det_lead_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_lag = " < < max_lag_orig < < " ; " < < endl
< < modstruct < < " orig_maximum_lead = " < < max_lead_orig < < " ; " < < endl
2018-12-11 17:26:50 +01:00
< < modstruct < < " orig_maximum_lag_with_diffs_expanded = " < < max_lag_with_diffs_expanded_orig < < " ; " < < endl
2017-07-27 18:33:19 +02:00
< < modstruct < < " 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 ,
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 ,
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 ;
nfwrd + = sfwrd ;
npred + = spred ;
nboth + = sboth ;
2009-12-16 18:13:23 +01:00
output < < " ; " ;
}
output < < " ]'; " < < endl ;
2015-07-29 14:59:09 +02:00
output < < modstruct < < " nstatic = " < < nstatic < < " ; " < < endl
< < modstruct < < " nfwrd = " < < nfwrd < < " ; " < < endl
< < modstruct < < " npred = " < < npred < < " ; " < < endl
< < modstruct < < " nboth = " < < nboth < < " ; " < < endl
< < modstruct < < " nsfwrd = " < < nfwrd + nboth < < " ; " < < endl
< < modstruct < < " nspred = " < < npred + nboth < < " ; " < < endl
< < modstruct < < " ndynamic = " < < npred + nboth + nfwrd < < " ; " < < endl ;
2018-03-28 18:53:02 +02:00
if ( ! julia )
2019-04-12 15:41:52 +02:00
{
output < < modstruct < < " dynamic_tmp_nbr = [ " ;
for ( size_t i = 0 ; i < temporary_terms_derivatives . size ( ) ; i + + )
2019-05-14 17:08:23 +02:00
output < < temporary_terms_derivatives [ i ] . size ( ) + ( i = = 0 ? temporary_terms_mlv . size ( ) : 0 ) < < " ; " ;
2019-04-12 15:41:52 +02:00
output < < " ]; " < < endl ;
}
2009-12-16 18:13:23 +01:00
// Write equation tags
2015-07-29 14:59:09 +02:00
if ( julia )
{
2015-08-21 16:28:43 +02:00
output < < modstruct < < " equation_tags = [ " < < endl ;
2018-06-04 12:26:16 +02:00
for ( const auto & equation_tag : equation_tags )
2015-08-21 16:28:43 +02:00
output < < " EquationTag( "
2019-04-03 16:32:52 +02:00
< < equation_tag . first + 1 < < R " ( , " ) "
< < equation_tag . second . first < < R " ( " , " ) "
< < equation_tag . second . second < < R " ( " ) ) " << endl;
2015-08-21 16:28:43 +02:00
output < < " ] " < < endl ;
2015-07-29 14:59:09 +02:00
}
else
{
output < < modstruct < < " equations_tags = { " < < endl ;
2018-06-04 12:26:16 +02:00
for ( const auto & equation_tag : equation_tags )
output < < " " < < equation_tag . first + 1 < < " , ' "
< < equation_tag . second . first < < " ' , ' "
< < equation_tag . second . second < < " ' ; " < < endl ;
2015-07-29 14:59:09 +02:00
output < < " }; " < < endl ;
}
2009-12-16 18:13:23 +01:00
2019-10-16 17:34:27 +02:00
// Write mapping for variables and equations they are present in
for ( const auto & variable : variableMapping )
{
output < < modstruct < < " mapping. " < < symbol_table . getName ( variable . first ) < < " .eqidx = [ " ;
for ( auto equation : variable . second )
output < < equation + 1 < < " " ;
output < < " ]; " < < endl ;
}
2013-04-11 17:07:39 +02:00
/* Say if static and dynamic models differ (because of [static] and [dynamic]
equation tags ) */
2015-07-29 14:59:09 +02:00
output < < modstruct < < " static_and_dynamic_models_differ = "
2019-03-19 14:05:41 +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 ;
for ( size_t eq = 0 ; eq < equations . size ( ) ; eq + + )
if ( equations [ eq ] - > containsExternalFunction ( ) )
{
has_external_function = true ;
break ;
}
output < < modstruct < < " has_external_function = "
< < ( has_external_function ? " true " : " false " )
< < ' ; ' < < endl ;
2016-07-20 23:09:46 +02:00
vector < int > state_var ;
for ( int endoID = 0 ; endoID < symbol_table . endo_nbr ( ) ; endoID + + )
// Loop on periods
for ( int lag = - max_endo_lag ; lag < 0 ; lag + + )
try
{
2018-07-17 18:34:07 +02:00
getDerivID ( symbol_table . getID ( SymbolType : : endogenous , variable_reordered [ endoID ] ) , lag ) ;
2016-07-20 23:09:46 +02:00
if ( lag < 0 & & find ( state_var . begin ( ) , state_var . end ( ) , variable_reordered [ endoID ] + 1 ) = = state_var . end ( ) )
state_var . push_back ( variable_reordered [ endoID ] + 1 ) ;
}
catch ( UnknownDerivIDException & e )
{
}
2009-12-16 18:13:23 +01:00
//In case of sparse model, writes the block_decomposition structure of the model
2018-09-21 17:13:19 +02:00
if ( block_decomposition | | linear_decomposition )
2009-12-16 18:13:23 +01:00
{
2016-07-20 23:09:46 +02:00
vector < int > state_equ ;
2009-12-16 18:13:23 +01:00
int count_lead_lag_incidence = 0 ;
2010-07-23 11:20:24 +02:00
int max_lead , max_lag , max_lag_endo , max_lead_endo , max_lag_exo , max_lead_exo , max_lag_exo_det , max_lead_exo_det ;
2009-12-16 18:13:23 +01:00
unsigned int nb_blocks = getNbBlocks ( ) ;
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
{
//For a block composed of a single equation determines wether we have to evaluate or to solve the equation
count_lead_lag_incidence = 0 ;
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
int block_size = getBlockSize ( block ) ;
max_lag = max_leadlag_block [ block ] . first ;
max_lead = max_leadlag_block [ block ] . second ;
max_lag_endo = endo_max_leadlag_block [ block ] . first ;
max_lead_endo = endo_max_leadlag_block [ block ] . second ;
2010-07-23 11:20:24 +02:00
max_lag_exo = exo_max_leadlag_block [ block ] . first ;
max_lead_exo = exo_max_leadlag_block [ block ] . second ;
max_lag_exo_det = exo_det_max_leadlag_block [ block ] . first ;
max_lead_exo_det = exo_det_max_leadlag_block [ block ] . second ;
2009-12-16 18:13:23 +01:00
ostringstream tmp_s , tmp_s_eq ;
tmp_s . str ( " " ) ;
tmp_s_eq . str ( " " ) ;
for ( int i = 0 ; i < block_size ; i + + )
{
tmp_s < < " " < < getBlockVariableID ( block , i ) + 1 ;
tmp_s_eq < < " " < < getBlockEquationID ( block , i ) + 1 ;
}
2010-07-23 11:20:24 +02:00
set < int > exogenous ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : exo_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( int it1 : it . second )
exogenous . insert ( it1 ) ;
2010-07-23 11:20:24 +02:00
set < int > exogenous_det ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : exo_det_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( int it1 : it . second )
exogenous_det . insert ( it1 ) ;
2010-07-23 11:20:24 +02:00
set < int > other_endogenous ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : other_endo_block [ block ] )
2018-11-23 17:19:59 +01:00
for ( int it1 : it . second )
other_endogenous . insert ( it1 ) ;
output < < " block_structure.block( " < < block + 1 < < " ).Simulation_Type = " < < simulation_type < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_lag = " < < max_lag < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_lead = " < < max_lead < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_endo_lag = " < < max_lag_endo < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_endo_lead = " < < max_lead_endo < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_exo_lag = " < < max_lag_exo < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_exo_lead = " < < max_lead_exo < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_exo_det_lag = " < < max_lag_exo_det < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).maximum_exo_det_lead = " < < max_lead_exo_det < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).endo_nbr = " < < block_size < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).mfs = " < < getBlockMfs ( block ) < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).equation = [ " < < tmp_s_eq . str ( ) < < " ]; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).variable = [ " < < tmp_s . str ( ) < < " ]; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).exo_nbr = " < < getBlockExoSize ( block ) < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).exogenous = [ " ;
2009-12-16 18:13:23 +01:00
int i = 0 ;
2018-06-04 12:26:16 +02:00
for ( int exogenou : exogenous )
if ( exogenou > = 0 )
2009-06-05 16:45:23 +02:00
{
2018-06-04 12:26:16 +02:00
output < < " " < < exogenou + 1 ;
2009-12-16 18:13:23 +01:00
i + + ;
2009-06-05 16:45:23 +02:00
}
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).exogenous_det = [ " ;
2010-07-23 11:20:24 +02:00
i = 0 ;
2018-06-04 12:26:16 +02:00
for ( int it_exogenous_det : exogenous_det )
if ( it_exogenous_det > = 0 )
2010-07-23 11:20:24 +02:00
{
2018-06-04 12:26:16 +02:00
output < < " " < < it_exogenous_det + 1 ;
2010-07-23 11:20:24 +02:00
i + + ;
}
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).exo_det_nbr = " < < i < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).other_endogenous = [ " ;
2010-07-23 11:20:24 +02:00
i = 0 ;
2018-06-04 12:26:16 +02:00
for ( int other_endogenou : other_endogenous )
if ( other_endogenou > = 0 )
2010-07-23 11:20:24 +02:00
{
2018-06-04 12:26:16 +02:00
output < < " " < < other_endogenou + 1 ;
2010-07-23 11:20:24 +02:00
i + + ;
}
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).other_endogenous_block = [ " ;
2011-06-18 17:53:50 +02:00
i = 0 ;
2018-06-04 12:26:16 +02:00
for ( int other_endogenou : other_endogenous )
if ( other_endogenou > = 0 )
2011-06-18 17:53:50 +02:00
{
bool OK = true ;
unsigned int j ;
for ( j = 0 ; j < block & & OK ; j + + )
for ( unsigned int k = 0 ; k < getBlockSize ( j ) & & OK ; k + + )
{
//printf("*it_other_endogenous=%d, getBlockVariableID(%d, %d)=%d\n",*it_other_endogenous, j, k, getBlockVariableID(j, k));
2018-06-04 12:26:16 +02:00
OK = other_endogenou ! = getBlockVariableID ( j , k ) ;
2011-06-18 17:53:50 +02:00
}
if ( ! OK )
output < < " " < < j ;
i + + ;
}
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
2017-06-01 19:58:32 +02:00
2011-06-18 17:53:50 +02:00
//vector<int> inter_state_var;
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).tm1 = zeros( " < < i < < " , " < < state_var . size ( ) < < " ); " < < endl ;
2011-06-18 17:53:50 +02:00
int count_other_endogenous = 1 ;
2018-06-04 12:26:16 +02:00
for ( int other_endogenou : other_endogenous )
2011-06-18 17:53:50 +02:00
{
2018-11-23 17:19:59 +01:00
for ( auto it = state_var . begin ( ) ; it ! = state_var . end ( ) ; + + it )
2011-06-18 17:53:50 +02:00
{
//cout << "block = " << block+1 << " state_var = " << *it << " it_other_endogenous=" << *it_other_endogenous + 1 << "\n";
2018-06-04 12:26:16 +02:00
if ( * it = = other_endogenou + 1 )
2011-06-18 17:53:50 +02:00
{
2017-06-01 19:58:32 +02:00
output < < " block_structure.block( " < < block + 1 < < " ).tm1( "
< < count_other_endogenous < < " , "
2018-11-23 17:19:59 +01:00
< < it - state_var . begin ( ) + 1 < < " ) = 1; " < < endl ;
2017-06-01 19:58:32 +02:00
/*output << "block_structure.block(" << block+1 << ").tm1("
< < it - state_var . begin ( ) + 1 < < " , "
< < count_other_endogenous < < " ) = 1; \n " ; */
2011-06-18 17:53:50 +02:00
//cout << "=>\n";
}
}
count_other_endogenous + + ;
}
2017-06-01 19:58:32 +02:00
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).other_endo_nbr = " < < i < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
tmp_s . str ( " " ) ;
count_lead_lag_incidence = 0 ;
2010-09-16 19:00:48 +02:00
dynamic_jacob_map_t reordered_dynamic_jacobian ;
2018-06-04 12:26:16 +02:00
for ( const auto & it : blocks_derivatives [ block ] )
2018-11-23 17:19:59 +01:00
reordered_dynamic_jacobian [ { get < 2 > ( it ) , get < 1 > ( it ) , get < 0 > ( it ) } ] = get < 3 > ( it ) ;
output < < " block_structure.block( " < < block + 1 < < " ).lead_lag_incidence = []; " < < endl ;
2009-12-16 18:13:23 +01:00
int last_var = - 1 ;
2011-06-18 17:53:50 +02:00
vector < int > local_state_var ;
2012-02-17 10:48:28 +01:00
vector < int > local_stat_var ;
int n_static = 0 , n_backward = 0 , n_forward = 0 , n_mixed = 0 ;
2011-06-18 17:53:50 +02:00
for ( int lag = - 1 ; lag < 1 + 1 ; lag + + )
2009-12-16 18:13:23 +01:00
{
2010-07-23 11:20:24 +02:00
last_var = - 1 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : reordered_dynamic_jacobian )
2009-06-05 16:45:23 +02:00
{
2018-11-23 17:19:59 +01:00
if ( lag = = get < 0 > ( it . first ) & & last_var ! = get < 1 > ( it . first ) )
2009-12-16 18:13:23 +01:00
{
2011-06-18 17:53:50 +02:00
if ( lag = = - 1 )
2012-02-17 10:48:28 +01:00
{
2018-11-23 17:19:59 +01:00
local_state_var . push_back ( getBlockVariableID ( block , get < 1 > ( it . first ) ) + 1 ) ;
2012-02-17 10:48:28 +01:00
n_backward + + ;
}
else if ( lag = = 0 )
{
2018-11-23 17:19:59 +01:00
if ( find ( local_state_var . begin ( ) , local_state_var . end ( ) , getBlockVariableID ( block , get < 1 > ( it . first ) ) + 1 ) = = local_state_var . end ( ) )
2012-02-17 10:48:28 +01:00
{
2018-11-23 17:19:59 +01:00
local_stat_var . push_back ( getBlockVariableID ( block , get < 1 > ( it . first ) ) + 1 ) ;
2017-06-01 19:58:32 +02:00
n_static + + ;
2012-02-17 10:48:28 +01:00
}
}
else
{
2018-11-23 17:19:59 +01:00
if ( find ( local_state_var . begin ( ) , local_state_var . end ( ) , getBlockVariableID ( block , get < 1 > ( it . first ) ) + 1 ) ! = local_state_var . end ( ) )
2012-02-17 10:48:28 +01:00
{
n_backward - - ;
n_mixed + + ;
}
else
{
2018-11-23 17:19:59 +01:00
if ( find ( local_stat_var . begin ( ) , local_stat_var . end ( ) , getBlockVariableID ( block , get < 1 > ( it . first ) ) + 1 ) ! = local_stat_var . end ( ) )
2012-02-17 10:48:28 +01:00
n_static - - ;
n_forward + + ;
}
}
2009-12-16 18:13:23 +01:00
count_lead_lag_incidence + + ;
2018-11-23 17:19:59 +01:00
for ( int i = last_var ; i < get < 1 > ( it . first ) - 1 ; i + + )
2009-12-16 18:13:23 +01:00
tmp_s < < " 0 " ;
if ( tmp_s . str ( ) . length ( ) )
tmp_s < < " " ;
tmp_s < < count_lead_lag_incidence ;
2018-11-23 17:19:59 +01:00
last_var = get < 1 > ( it . first ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
}
2009-12-16 18:13:23 +01:00
for ( int i = last_var + 1 ; i < block_size ; i + + )
tmp_s < < " 0 " ;
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).lead_lag_incidence = [ block_structure.block( " < < block + 1 < < " ).lead_lag_incidence; " < < tmp_s . str ( ) < < " ]; %lag = " < < lag < < endl ;
2009-12-16 18:13:23 +01:00
tmp_s . str ( " " ) ;
}
2011-06-18 17:53:50 +02:00
vector < int > inter_state_var ;
2019-01-15 11:08:47 +01:00
for ( int & it_l : local_state_var )
2018-11-23 17:19:59 +01:00
for ( auto it = state_var . begin ( ) ; it ! = state_var . end ( ) ; + + it )
2019-01-15 11:08:47 +01:00
if ( * it = = it_l )
2011-06-18 17:53:50 +02:00
inter_state_var . push_back ( it - state_var . begin ( ) + 1 ) ;
output < < " block_structure.block( " < < block + 1 < < " ).sorted_col_dr_ghx = [ " ;
2018-11-23 17:19:59 +01:00
for ( int it : inter_state_var )
output < < it < < " " ;
output < < " ]; " < < endl ;
2011-01-31 17:47:22 +01:00
count_lead_lag_incidence = 0 ;
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).lead_lag_incidence_other = []; " < < endl ;
2011-01-31 17:47:22 +01:00
for ( int lag = - 1 ; lag < = 1 ; lag + + )
{
tmp_s . str ( " " ) ;
2018-06-04 12:26:16 +02:00
for ( int other_endogenou : other_endogenous )
2011-01-31 17:47:22 +01:00
{
bool done = false ;
for ( int i = 0 ; i < block_size ; i + + )
{
unsigned int eq = getBlockEquationID ( block , i ) ;
2018-11-23 17:19:59 +01:00
auto it = derivative_other_endo [ block ] . find ( { lag , eq , other_endogenou } ) ;
2011-01-31 17:47:22 +01:00
if ( it ! = derivative_other_endo [ block ] . end ( ) )
{
count_lead_lag_incidence + + ;
tmp_s < < " " < < count_lead_lag_incidence ;
done = true ;
break ;
}
}
if ( ! done )
tmp_s < < " 0 " ;
}
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).lead_lag_incidence_other = [ block_structure.block( " < < block + 1 < < " ).lead_lag_incidence_other; " < < tmp_s . str ( ) < < " ]; %lag = " < < lag < < endl ;
2011-01-31 17:47:22 +01:00
}
2018-11-23 17:19:59 +01:00
output < < " block_structure.block( " < < block + 1 < < " ).n_static = " < < n_static < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).n_forward = " < < n_forward < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).n_backward = " < < n_backward < < " ; " < < endl
< < " block_structure.block( " < < block + 1 < < " ).n_mixed = " < < n_mixed < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
}
2018-11-23 17:19:59 +01:00
output < < modstruct < < " block_structure.block = block_structure.block; " < < endl ;
2009-12-16 18:13:23 +01:00
string cst_s ;
int nb_endo = symbol_table . endo_nbr ( ) ;
2015-07-29 14:59:09 +02:00
output < < modstruct < < " block_structure.variable_reordered = [ " ;
2009-12-16 18:13:23 +01:00
for ( int i = 0 ; i < nb_endo ; i + + )
output < < " " < < variable_reordered [ i ] + 1 ;
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
2015-07-29 14:59:09 +02:00
output < < modstruct < < " block_structure.equation_reordered = [ " ;
2009-12-16 18:13:23 +01:00
for ( int i = 0 ; i < nb_endo ; i + + )
output < < " " < < equation_reordered [ i ] + 1 ;
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
2011-09-20 14:18:31 +02:00
vector < int > variable_inv_reordered ( nb_endo ) ;
2017-06-01 19:58:32 +02:00
for ( int i = 0 ; i < nb_endo ; i + + )
2011-09-20 14:18:31 +02:00
variable_inv_reordered [ variable_reordered [ i ] ] = i ;
2017-06-01 19:58:32 +02:00
2018-11-23 17:19:59 +01:00
for ( int it : state_var )
state_equ . push_back ( equation_reordered [ variable_inv_reordered [ it - 1 ] ] + 1 ) ;
2011-09-20 14:18:31 +02:00
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , int > lag_row_incidence ;
2018-11-15 16:39:53 +01:00
for ( const auto & first_derivative : derivatives [ 1 ] )
2009-12-16 18:13:23 +01:00
{
2018-11-15 16:39:53 +01:00
int deriv_id = first_derivative . first [ 1 ] ;
2018-07-17 18:34:07 +02:00
if ( getTypeByDerivID ( deriv_id ) = = SymbolType : : endogenous )
2009-12-16 18:13:23 +01:00
{
2018-11-15 16:39:53 +01:00
int eq = first_derivative . first [ 0 ] ;
2009-12-16 18:13:23 +01:00
int symb = getSymbIDByDerivID ( deriv_id ) ;
int var = symbol_table . getTypeSpecificID ( symb ) ;
int lag = getLagByDerivID ( deriv_id ) ;
2018-11-23 17:19:59 +01:00
lag_row_incidence [ { lag , eq , var } ] = 1 ;
2009-12-16 18:13:23 +01:00
}
}
int prev_lag = - 1000000 ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : lag_row_incidence )
2009-12-16 18:13:23 +01:00
{
2018-11-23 17:19:59 +01:00
if ( prev_lag ! = get < 0 > ( it . first ) )
2009-12-16 18:13:23 +01:00
{
if ( prev_lag ! = - 1000000 )
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
prev_lag = get < 0 > ( it . first ) ;
output < < modstruct < < " block_structure.incidence( " < < max_endo_lag + get < 0 > ( it . first ) + 1 < < " ).lead_lag = " < < prev_lag < < " ; " < < endl
< < modstruct < < " block_structure.incidence( " < < max_endo_lag + get < 0 > ( it . first ) + 1 < < " ).sparse_IM = [ " ;
2009-12-16 18:13:23 +01:00
}
2018-11-23 17:19:59 +01:00
output < < get < 1 > ( it . first ) + 1 < < " " < < get < 2 > ( it . first ) + 1 < < " ; " < < endl ;
2009-12-16 18:13:23 +01:00
}
2018-11-23 17:19:59 +01:00
output < < " ]; " < < endl ;
2011-09-20 14:18:31 +02:00
if ( estimation_present )
{
ofstream KF_index_file ;
2019-04-04 17:01:37 +02:00
filesystem : : create_directories ( basename + " /model/bytecode " ) ;
2018-06-27 15:01:31 +02:00
string main_name = basename + " /model/bytecode/kfi " ;
2018-06-27 15:12:12 +02:00
KF_index_file . open ( main_name , ios : : out | ios : : binary | ios : : ate ) ;
2011-09-20 14:18:31 +02:00
int n_obs = symbol_table . observedVariablesNbr ( ) ;
int n_state = state_var . size ( ) ;
2018-11-23 17:19:59 +01:00
for ( int it : state_var )
if ( symbol_table . isObservedVariable ( symbol_table . getID ( SymbolType : : endogenous , it - 1 ) ) )
2011-10-28 22:25:05 +02:00
n_obs - - ;
2011-09-20 14:18:31 +02:00
int n = n_obs + n_state ;
2015-07-29 14:59:09 +02:00
output < < modstruct < < " nobs_non_statevar = " < < n_obs < < " ; " < < endl ;
2011-09-20 14:18:31 +02:00
int nb_diag = 0 ;
//map<pair<int,int>, int>::const_iterator row_state_var_incidence_it = row_state_var_incidence.begin();
2011-10-28 22:25:05 +02:00
2011-09-20 14:18:31 +02:00
vector < int > i_nz_state_var ( n ) ;
for ( int i = 0 ; i < n_obs ; i + + )
i_nz_state_var [ i ] = n ;
2011-10-28 22:25:05 +02:00
unsigned int lp = n_obs ;
2017-06-01 19:58:32 +02:00
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2011-09-20 14:18:31 +02:00
{
int block_size = getBlockSize ( block ) ;
int nze = 0 ;
2017-06-01 19:58:32 +02:00
2011-09-20 14:18:31 +02:00
for ( int i = 0 ; i < block_size ; i + + )
{
int var = getBlockVariableID ( block , i ) ;
2018-11-23 17:19:59 +01:00
auto it_state_var = find ( state_var . begin ( ) , state_var . end ( ) , var + 1 ) ;
2011-09-20 14:18:31 +02:00
if ( it_state_var ! = state_var . end ( ) )
nze + + ;
}
if ( block = = 0 )
{
2018-06-04 14:17:36 +02:00
set < pair < int , int > > row_state_var_incidence ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : blocks_derivatives [ block ] )
2011-09-20 14:18:31 +02:00
{
2018-11-23 17:19:59 +01:00
auto it_state_var = find ( state_var . begin ( ) , state_var . end ( ) , getBlockVariableID ( block , get < 1 > ( it ) ) + 1 ) ;
2011-09-20 14:18:31 +02:00
if ( it_state_var ! = state_var . end ( ) )
{
2018-11-23 17:19:59 +01:00
auto it_state_equ = find ( state_equ . begin ( ) , state_equ . end ( ) , getBlockEquationID ( block , get < 0 > ( it ) ) + 1 ) ;
2011-09-20 14:18:31 +02:00
if ( it_state_equ ! = state_equ . end ( ) )
2018-06-04 16:36:46 +02:00
row_state_var_incidence . emplace ( it_state_equ - state_equ . begin ( ) , it_state_var - state_var . begin ( ) ) ;
2017-06-01 19:58:32 +02:00
}
2011-09-20 14:18:31 +02:00
}
/*tmp_block_endo_derivative[make_pair(it->second.first, make_pair(it->first.second, it->first.first))] = it->second.second;
2017-06-01 19:58:32 +02:00
if ( block = = 0 )
{
vector < int > : : const_iterator it_state_equ = find ( state_equ . begin ( ) , state_equ . end ( ) , getBlockEquationID ( block , i ) + 1 ) ;
if ( it_state_equ ! = state_equ . end ( ) )
{
cout < < " row_state_var_incidence[make_pair([ " < < * it_state_equ < < " ] " < < it_state_equ - state_equ . begin ( ) < < " , [ " < < * it_state_var < < " ] " < < it_state_var - state_var . begin ( ) < < " )] = 1; \n " ;
row_state_var_incidence . insert ( make_pair ( it_state_equ - state_equ . begin ( ) , it_state_var - state_var . begin ( ) ) ) ;
}
} */
2018-06-04 15:03:26 +02:00
auto row_state_var_incidence_it = row_state_var_incidence . begin ( ) ;
2011-09-20 14:18:31 +02:00
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 + + ;
}
2017-06-01 19:58:32 +02:00
2011-09-20 14:18:31 +02:00
}
2018-06-04 14:17:36 +02:00
set < pair < int , int > > col_state_var_incidence ;
2018-06-04 12:26:16 +02:00
for ( const auto & row_state_var_incidence_it : row_state_var_incidence )
2018-06-04 16:36:46 +02:00
col_state_var_incidence . emplace ( row_state_var_incidence_it . second , row_state_var_incidence_it . first ) ;
2018-06-04 15:03:26 +02:00
auto col_state_var_incidence_it = col_state_var_incidence . begin ( ) ;
2011-09-20 14:18:31 +02:00
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 + + ;
}
}
2017-06-01 19:58:32 +02:00
nb_diag = min ( nb_diag_r , nb_diag_c ) ;
2011-09-20 14:18:31 +02:00
row_state_var_incidence . clear ( ) ;
col_state_var_incidence . clear ( ) ;
}
for ( int i = 0 ; i < nze ; i + + )
2017-06-01 19:58:32 +02:00
i_nz_state_var [ lp + i ] = lp + nze ;
lp + = nze ;
2011-09-20 14:18:31 +02:00
}
2015-07-29 14:59:09 +02:00
output < < modstruct < < " nz_state_var = [ " ;
2012-06-06 16:30:36 +02:00
for ( unsigned int i = 0 ; i < lp ; i + + )
2011-09-20 14:18:31 +02:00
output < < i_nz_state_var [ i ] < < " " ;
output < < " ]; " < < endl ;
2015-07-29 14:59:09 +02:00
output < < modstruct < < " n_diag = " < < nb_diag < < " ; " < < endl ;
2011-09-20 14:18:31 +02:00
KF_index_file . write ( reinterpret_cast < char * > ( & nb_diag ) , sizeof ( nb_diag ) ) ;
2017-06-01 19:58:32 +02:00
2018-06-04 14:31:26 +02:00
using index_KF = pair < int , pair < int , int > > ;
2011-09-20 14:18:31 +02:00
vector < index_KF > v_index_KF ;
for ( int i = 0 ; i < n ; i + + )
//int i = 0;
for ( int j = n_obs ; j < n ; j + + )
{
int j1 = j - n_obs ;
2017-06-01 19:58:32 +02:00
int j1_n_state = j1 * n_state - n_obs ;
2011-09-20 14:18:31 +02:00
if ( ( i < n_obs ) | | ( i > = nb_diag + n_obs ) | | ( j1 > = nb_diag ) )
for ( int k = n_obs ; k < i_nz_state_var [ i ] ; k + + )
{
2019-10-24 10:49:13 +02:00
v_index_KF . emplace_back ( i + j1 * n , pair ( i + k * n , k + j1_n_state ) ) ;
2011-09-20 14:18:31 +02:00
}
}
int size_v_index_KF = v_index_KF . size ( ) ;
2011-10-12 14:45:53 +02:00
2017-06-01 19:58:32 +02:00
KF_index_file . write ( reinterpret_cast < char * > ( & size_v_index_KF ) , sizeof ( size_v_index_KF ) ) ;
2018-06-04 12:26:16 +02:00
for ( auto & it : v_index_KF )
KF_index_file . write ( reinterpret_cast < char * > ( & it ) , sizeof ( index_KF ) ) ;
2011-09-20 14:18:31 +02:00
vector < index_KF > v_index_KF_2 ;
int n_n_obs = n * n_obs ;
for ( int i = 0 ; i < n ; i + + )
2017-06-01 19:58:32 +02:00
//i = 0;
2011-09-20 14:18:31 +02:00
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 ;
2019-10-24 10:49:13 +02:00
v_index_KF_2 . emplace_back ( i * n + j , pair ( i + k_n - n_n_obs , j + k_n ) ) ;
2011-09-20 14:18:31 +02:00
}
}
int size_v_index_KF_2 = v_index_KF_2 . size ( ) ;
2011-10-12 14:45:53 +02:00
2017-06-01 19:58:32 +02:00
KF_index_file . write ( reinterpret_cast < char * > ( & size_v_index_KF_2 ) , sizeof ( size_v_index_KF_2 ) ) ;
2018-06-04 12:26:16 +02:00
for ( auto & it : v_index_KF_2 )
KF_index_file . write ( reinterpret_cast < char * > ( & it ) , sizeof ( index_KF ) ) ;
2011-09-20 14:18:31 +02:00
KF_index_file . close ( ) ;
}
2009-12-16 18:13:23 +01:00
}
2012-09-28 18:41:18 +02:00
2016-07-20 23:09:46 +02:00
output < < modstruct < < " state_var = [ " ;
2018-11-23 17:19:59 +01:00
for ( int it : state_var )
output < < it < < ( julia ? " , " : " " ) ;
2016-07-20 23:09:46 +02:00
output < < " ]; " < < endl ;
2009-12-16 18:13:23 +01:00
// Writing initialization for some other variables
2015-08-12 19:03:29 +02:00
if ( ! julia )
2015-08-17 11:17:26 +02:00
output < < modstruct < < " exo_names_orig_ord = [1: " < < symbol_table . exo_nbr ( ) < < " ]; " < < endl ;
2015-08-12 19:03:29 +02:00
else
2015-08-17 11:17:26 +02:00
output < < modstruct < < " exo_names_orig_ord = collect(1: " < < symbol_table . exo_nbr ( ) < < " ); " < < endl ;
2013-11-04 16:02:28 +01:00
2015-08-12 19:03:29 +02:00
output < < modstruct < < " maximum_lag = " < < max_lag < < " ; " < < endl
2015-07-29 14:59:09 +02:00
< < modstruct < < " maximum_lead = " < < max_lead < < " ; " < < endl ;
2013-11-04 16:02:28 +01:00
2015-07-29 14:59:09 +02:00
output < < modstruct < < " maximum_endo_lag = " < < max_endo_lag < < " ; " < < endl
< < modstruct < < " maximum_endo_lead = " < < max_endo_lead < < " ; " < < endl
2017-06-01 19:58:32 +02:00
< < outstruct < < " steady_state = zeros( " < < symbol_table . endo_nbr ( ) < < ( julia ? " ) " : " , 1); " ) < < endl ;
2013-11-04 16:02:28 +01:00
2015-07-29 14:59:09 +02:00
output < < modstruct < < " maximum_exo_lag = " < < max_exo_lag < < " ; " < < endl
< < modstruct < < " maximum_exo_lead = " < < max_exo_lead < < " ; " < < endl
2017-06-01 19:58:32 +02:00
< < outstruct < < " exo_steady_state = zeros( " < < symbol_table . exo_nbr ( ) < < ( julia ? " ) " : " , 1); " ) < < endl ;
2013-11-04 16:02:28 +01:00
2009-12-16 18:13:23 +01:00
if ( symbol_table . exo_det_nbr ( ) )
{
2015-07-29 14:59:09 +02:00
output < < modstruct < < " maximum_exo_det_lag = " < < max_exo_det_lag < < " ; " < < endl
< < modstruct < < " maximum_exo_det_lead = " < < max_exo_det_lead < < " ; " < < endl
2017-06-01 19:58:32 +02:00
< < outstruct < < " exo_det_steady_state = zeros( " < < symbol_table . exo_det_nbr ( ) < < ( julia ? " ) " : " , 1); " ) < < endl ;
2009-12-16 18:13:23 +01:00
}
2013-11-04 16:02:28 +01:00
2015-07-29 14:59:09 +02:00
output < < modstruct < < " params = " < < ( julia ? " fill(NaN, " : " NaN( " )
2017-06-01 19:58:32 +02:00
< < symbol_table . param_nbr ( ) < < ( julia ? " ) " : " , 1); " ) < < endl ;
2009-12-16 18:13:23 +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
2019-04-12 15:41:52 +02:00
output < < modstruct < < ( julia ? " nnzderivatives " : " NNZDerivatives " ) < < " = [ " ;
for ( int i = 1 ; i < static_cast < int > ( NNZDerivatives . size ( ) ) ; i + + )
output < < ( i > 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
for ( auto & it : pac_mce_alpha_symb_ids )
{
2019-02-19 16:36:10 +01:00
output < < modstruct < < " 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
for ( auto & it : pac_mce_z1_symb_ids )
output < < modstruct < < " pac. " < < it . first . first < < " .equations. " < < it . first . second < < " .mce.z1 = "
< < symbol_table . getTypeSpecificID ( it . second ) + 1 < < " ; " < < endl ;
// Write Pac lag info
for ( auto & it : pac_eqtag_and_lag )
output < < modstruct < < " pac. " < < it . first . first < < " .equations. " < < it . second . first < < " .max_lag = " < < it . second . second < < " ; " < < endl ;
// Write Pac equation tag info
map < string , vector < pair < string , string > > > for_writing ;
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
for ( auto & it : for_writing )
{
output < < modstruct < < " pac. " < < it . first < < " .tag_map = [ " ;
for ( auto & it1 : it . second )
output < < " {' " < < it1 . first < < " ', ' " < < it1 . second < < " '}; " ;
output < < " ]; " < < endl ;
}
2019-02-20 12:59:55 +01:00
for ( auto & it : pac_model_info )
{
vector < int > lhs = get < 0 > ( it . second ) ;
output < < modstruct < < " pac. " < < it . first < < " .lhs = [ " ;
for ( auto it : lhs )
output < < it + 1 < < " " ;
output < < " ]; " < < endl ;
2019-02-20 16:38:44 +01:00
int growth_param_index = get < 1 > ( it . second ) ;
if ( growth_param_index > = 0 )
output < < modstruct < < " pac. " < < it . first < < " .growth_neutrality_param_index = "
< < symbol_table . getTypeSpecificID ( growth_param_index ) + 1 < < " ; " < < endl ;
2019-02-20 16:42:22 +01:00
output < < modstruct < < " pac. " < < it . first < < " .auxiliary_model_type = ' " < < get < 2 > ( it . second ) < < " '; " < < endl ;
2019-02-20 12:59:55 +01:00
}
for ( auto & pit : pac_equation_info )
{
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 + " . " ;
2019-02-20 16:46:47 +01:00
output < < modstruct < < " 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 )
2019-02-20 16:46:47 +01:00
output < < modstruct < < " pac. " < < substruct < < " share_of_optimizing_agents_index = "
2019-02-20 12:59:55 +01:00
< < symbol_table . getTypeSpecificID ( optim_share_index ) + 1 < < " ; " < < endl ;
2019-02-20 16:46:47 +01:00
output < < modstruct < < " pac. " < < substruct < < " ec.params = "
2019-02-20 12:59:55 +01:00
< < symbol_table . getTypeSpecificID ( ec_params_and_vars . first ) + 1 < < " ; " < < endl
2019-02-20 16:46:47 +01:00
< < modstruct < < " 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
< < modstruct < < " pac. " < < substruct < < " ec.istarget = [ " ;
for ( auto it : ec_params_and_vars . second )
2019-03-07 11:31:36 +01:00
output < < ( get < 1 > ( it ) ? " true " : " false " ) ;
output < < " ]; " < < endl
< < modstruct < < " pac. " < < substruct < < " ec.scale = [ " ;
for ( auto it : ec_params_and_vars . second )
output < < get < 2 > ( it ) < < " " ;
2019-02-20 12:59:55 +01:00
output < < " ]; " < < endl
2019-02-20 16:46:47 +01:00
< < modstruct < < " 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
2019-02-20 16:46:47 +01:00
< < modstruct < < " pac. " < < substruct < < " ar.params = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : ar_params_and_vars )
output < < symbol_table . getTypeSpecificID ( it . first ) + 1 < < " " ;
output < < " ]; " < < endl
2019-02-20 16:46:47 +01:00
< < modstruct < < " pac. " < < substruct < < " ar.vars = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : ar_params_and_vars )
output < < symbol_table . getTypeSpecificID ( it . second . first ) + 1 < < " " ;
output < < " ]; " < < endl
2019-02-20 16:46:47 +01:00
< < modstruct < < " pac. " < < substruct < < " ar.lags = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : ar_params_and_vars )
output < < it . second . second < < " " ;
output < < " ]; " < < endl ;
if ( ! non_optim_vars_params_and_constants . empty ( ) )
{
2019-02-22 12:31:58 +01:00
output < < modstruct < < " pac. " < < substruct < < " non_optimizing_behaviour.params = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2019-02-22 12:31:58 +01:00
< < modstruct < < " pac. " < < substruct < < " non_optimizing_behaviour.vars = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
2019-02-27 15:10:48 +01:00
output < < " ]; " < < endl
2019-02-27 15:35:14 +01:00
< < modstruct < < " pac. " < < substruct < < " non_optimizing_behaviour.isendo = [ " ;
2019-02-27 15:10:48 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
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
2019-02-22 12:31:58 +01:00
< < modstruct < < " pac. " < < substruct < < " non_optimizing_behaviour.lags = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2019-02-22 12:31:58 +01:00
< < modstruct < < " pac. " < < substruct < < " non_optimizing_behaviour.scaling_factor = [ " ;
2019-02-20 12:59:55 +01:00
for ( auto & it : non_optim_vars_params_and_constants )
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
2019-02-27 23:12:05 +01:00
if ( ! additive_vars_params_and_constants . empty ( ) )
{
output < < modstruct < < " pac. " < < substruct < < " additive.params = [ " ;
for ( auto & it : additive_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
< < modstruct < < " pac. " < < substruct < < " additive.vars = [ " ;
for ( auto & it : additive_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
< < modstruct < < " pac. " < < substruct < < " additive.isendo = [ " ;
for ( auto & it : additive_vars_params_and_constants )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
< < modstruct < < " pac. " < < substruct < < " additive.lags = [ " ;
for ( auto & it : additive_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
< < modstruct < < " pac. " < < substruct < < " additive.scaling_factor = [ " ;
for ( auto & it : additive_vars_params_and_constants )
output < < get < 3 > ( it ) < < " " ;
output < < " ]; " < < endl ;
}
2019-03-07 12:35:30 +01:00
if ( ! optim_additive_vars_params_and_constants . empty ( ) )
{
2019-03-07 12:57:47 +01:00
output < < modstruct < < " pac. " < < substruct < < " optim_additive.params = [ " ;
2019-03-07 12:35:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
if ( get < 2 > ( it ) > = 0 )
output < < symbol_table . getTypeSpecificID ( get < 2 > ( it ) ) + 1 < < " " ;
else
output < < " NaN " ;
output < < " ]; " < < endl
2019-03-07 12:57:47 +01:00
< < modstruct < < " pac. " < < substruct < < " optim_additive.vars = [ " ;
2019-03-07 12:35:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
output < < symbol_table . getTypeSpecificID ( get < 0 > ( it ) ) + 1 < < " " ;
output < < " ]; " < < endl
2019-03-07 12:57:47 +01:00
< < modstruct < < " pac. " < < substruct < < " optim_additive.isendo = [ " ;
2019-03-07 12:35:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
switch ( symbol_table . getType ( get < 0 > ( it ) ) )
{
case SymbolType : : endogenous :
output < < " true " ;
break ;
case SymbolType : : exogenous :
output < < " false " ;
break ;
default :
cerr < < " expecting endogenous or exogenous " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " ]; " < < endl
2019-03-07 12:57:47 +01:00
< < modstruct < < " pac. " < < substruct < < " optim_additive.lags = [ " ;
2019-03-07 12:35:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
output < < get < 1 > ( it ) < < " " ;
output < < " ]; " < < endl
2019-03-07 12:57:47 +01:00
< < modstruct < < " pac. " < < substruct < < " optim_additive.scaling_factor = [ " ;
2019-03-07 12:35:30 +01:00
for ( auto & it : optim_additive_vars_params_and_constants )
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
output < < modstruct < < " pac. " < < substruct < < " h0_param_indices = []; " < < endl
< < modstruct < < " pac. " < < substruct < < " h1_param_indices = []; " < < endl ;
2019-02-20 12:59:55 +01:00
}
for ( auto & it : pac_h0_indices )
{
2019-02-20 16:46:47 +01:00
output < < modstruct < < " 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 ;
}
for ( auto & it : pac_h1_indices )
{
2019-02-20 16:46:47 +01:00
output < < modstruct < < " 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
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t >
2009-06-05 17:30:32 +02:00
DynamicModel : : collect_first_order_derivatives_endogenous ( )
2009-05-16 00:41:51 +02:00
{
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > endo_derivatives ;
2018-11-15 16:39:53 +01:00
for ( auto & first_derivative : derivatives [ 1 ] )
2009-05-16 00:41:51 +02:00
{
2018-11-15 16:39:53 +01:00
if ( getTypeByDerivID ( first_derivative . first [ 1 ] ) = = SymbolType : : endogenous )
2009-05-16 00:41:51 +02:00
{
2018-11-15 16:39:53 +01:00
int eq = first_derivative . first [ 0 ] ;
int var = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( first_derivative . first [ 1 ] ) ) ;
int lag = getLagByDerivID ( first_derivative . first [ 1 ] ) ;
2018-11-23 17:19:59 +01:00
endo_derivatives [ { eq , var , lag } ] = first_derivative . second ;
2009-05-16 00:41:51 +02:00
}
}
2009-12-16 18:13:23 +01:00
return endo_derivatives ;
2009-05-16 00:41:51 +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 ;
for ( const auto & it : eqnums )
{
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 ( ) ;
2018-08-22 15:12:17 +02: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 ;
2018-08-22 15:12:17 +02:00
for ( const auto & eqtag : it . second )
2018-08-21 11:46:59 +02:00
{
int eqn = - 1 ;
set < pair < int , int > > lhs_set , lhs_tmp_set , rhs_set ;
2018-08-22 15:12:17 +02:00
for ( const auto & equation_tag : equation_tags )
2018-08-21 11:46:59 +02:00
if ( equation_tag . second . first = = " name "
& & equation_tag . second . second = = eqtag )
{
eqn = equation_tag . first ;
break ;
}
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 ) ;
2018-08-23 13:03:52 +02:00
for ( const auto & itrhs : rhs_set )
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 ;
2018-08-22 15:12:17 +02: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 ;
2018-08-22 15:12:17 +02: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 ( ) ;
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 )
{
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 ( ) ;
2018-08-22 15:12:17 +02: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 ;
2018-08-22 15:12:17 +02:00
for ( const auto & eqtag : it . second )
2018-01-30 16:33:16 +01:00
{
2018-08-14 14:23:21 +02:00
int eqn = - 1 ;
2018-08-22 15:12:17 +02:00
for ( const auto & equation_tag : equation_tags )
2018-08-14 14:23:21 +02:00
if ( equation_tag . second . first = = " name "
& & equation_tag . second . second = = eqtag )
{
eqn = equation_tag . first ;
break ;
}
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
2018-08-22 15:12:17 +02: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 ;
2018-08-22 15:12:17 +02:00
for ( const auto & eqtag : it . second )
2018-08-14 14:23:21 +02:00
{
int eqn = - 1 ;
set < pair < int , int > > lhs_set , lhs_tmp_set , rhs_set ;
2018-08-22 15:12:17 +02:00
for ( const auto & equation_tag : equation_tags )
2018-08-14 14:23:21 +02:00
if ( equation_tag . second . first = = " name "
& & equation_tag . second . second = = eqtag )
{
eqn = equation_tag . first ;
break ;
}
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 ) ;
2018-08-23 13:03:52 +02:00
for ( const auto & itrhs : rhs_set )
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 ;
2018-09-12 17:56:30 +02: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 ;
2018-08-22 15:12:17 +02: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
2018-11-28 14:32:26 +01:00
equations [ eqn ] - > arg1 - > countDiffs ( ) > 0 ?
2018-08-14 14:23:21 +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-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 ;
2018-08-22 15:12:17 +02: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 ;
map < string , pair < SymbolList , int > > var_symbol_list_and_order =
var_model_table . getSymbolListAndOrder ( ) ;
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 ;
2018-08-21 11:46:59 +02:00
for ( const auto & it : var_symbol_list_and_order )
2018-06-04 12:26:16 +02:00
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 ;
2016-11-25 17:15:13 +01:00
for ( vector < string > : : const_iterator it1 = symbol_list . begin ( ) ;
it1 ! = symbol_list . end ( ) ; it1 + + )
if ( order > 2 )
if ( var_endos_and_lags . find ( * it1 ) ! = var_endos_and_lags . end ( ) )
var_endos_and_lags [ * it1 ] = min ( var_endos_and_lags [ * it1 ] , - 1 * order ) ;
else
var_endos_and_lags [ * it1 ] = - 1 * order ;
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
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
equation - > getEndosAndMaxLags ( model_endos_and_lags ) ;
2016-11-25 17:15:13 +01:00
int count = 0 ;
for ( map < string , int > : : const_iterator it = var_endos_and_lags . begin ( ) ;
it ! = var_endos_and_lags . end ( ) ; it + + )
{
map < string , int > : : const_iterator it1 = model_endos_and_lags . find ( it - > first ) ;
if ( it1 = = model_endos_and_lags . end ( ) )
2017-05-04 16:54:47 +02:00
cerr < < " WARNING: Variable used in VAR that is not used in the model: " < < it - > first < < endl ;
2016-11-25 17:15:13 +01:00
else
if ( it - > second < it1 - > 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 + + ;
}
}
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 ;
for ( vector < int > : : const_iterator it1 = eqnumber . begin ( ) ;
2018-04-17 15:17:28 +02:00
it1 ! = eqnumber . end ( ) ; it1 + + , i + + )
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 ;
ExprNode : : subst_table_t : : const_iterator it1 ;
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 ) ;
for ( it1 = diff_subst_table . begin ( ) ; it1 ! = diff_subst_table . end ( ) ; it1 + + )
if ( it1 - > second = = aux_var )
{
node = const_cast < expr_t > ( it1 - > first ) ;
break ;
}
2018-06-04 12:52:14 +02:00
if ( node = = nullptr )
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 ( ) ;
it1 = diff_subst_table . find ( node ) ;
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 ;
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2018-02-12 17:37:53 +01:00
{
2018-02-15 16:10:01 +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 ;
2018-08-28 13:37:49 +02:00
set < pair < int , pair < 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
if ( equation - > containsPacExpectation ( ) )
{
2019-02-20 12:59:55 +01:00
set < pair < int , int > > lhss ;
equation - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhss ) ;
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 ) ;
if ( arg2 = = nullptr )
{
cerr < < " Pac equation in incorrect format " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-09-11 15:59:23 +02:00
auto [ optim_share_index , optim_part , non_optim_part , additive_part ] =
2019-02-27 23:12:05 +01:00
arg2 - > getPacOptimizingShareAndExprNodes ( lhs_symb_id , lhs_orig_symb_id ) ;
2018-08-09 16:14:40 +02:00
if ( optim_part = = nullptr )
2019-03-05 10:57:15 +01:00
{
auto bopn = dynamic_cast < BinaryOpNode * > ( equation - > arg2 ) ;
if ( bopn = = nullptr )
{
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 ) ;
if ( bopn = = nullptr )
{
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-02-27 23:12:05 +01:00
if ( additive_part ! = nullptr )
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
string eqtag = " " ;
for ( auto & tag : equation_tags )
if ( tag . first = = ( & equation - & equations [ 0 ] ) )
if ( tag . second . first = = " name " )
{
eqtag = tag . second . second ;
break ;
}
if ( eqtag = = " " )
{
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 )
{
cerr < < " walkPacParameters: error obtaining LHS varibale. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-03-05 10:57:15 +01:00
if ( ec_params_and_vars . second . empty ( ) | | ar_params_and_vars . 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 } ;
2019-02-21 10:30:25 +01:00
eqtag_and_lag [ { name , eqtag } ] = { eq , 0 } ;
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-19 16:36:10 +01:00
void
DynamicModel : : getPacMaxLag ( const string & pac_model_name , map < pair < string , string > , pair < string , int > > & eqtag_and_lag ) const
2018-08-13 12:12:20 +02:00
{
for ( auto & equation : equations )
if ( equation - > containsPacExpectation ( pac_model_name ) )
{
set < pair < int , int > > endogs ;
2018-11-28 14:32:26 +01:00
equation - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , endogs ) ;
2018-08-13 12:12:20 +02:00
if ( endogs . size ( ) ! = 1 )
{
cerr < < " The LHS of the PAC equation may only be comprised of one endogenous variable "
< < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-02-19 16:36:10 +01:00
string eqtag = " " ;
for ( auto & tag : equation_tags )
if ( tag . first = = ( & equation - & equations [ 0 ] ) )
if ( tag . second . first = = " name " )
{
eqtag = tag . second . second ;
break ;
}
2019-02-21 10:30:25 +01:00
string eq = eqtag_and_lag [ { pac_model_name , eqtag } ] . first ;
2019-02-21 12:16:22 +01:00
eqtag_and_lag [ { pac_model_name , eqtag } ] = { eq , equation - > PacMaxLag ( endogs . begin ( ) - > first ) } ;
2018-08-13 12:12:20 +02:00
}
}
2019-02-15 12:52:46 +01:00
int
DynamicModel : : getPacTargetSymbId ( const string & pac_model_name ) const
{
for ( auto & equation : equations )
if ( equation - > containsPacExpectation ( pac_model_name ) )
{
pair < int , int > lhs ( - 1 , - 1 ) ;
2019-02-20 12:59:55 +01:00
set < pair < int , int > > lhss ;
equation - > arg1 - > collectDynamicVariables ( SymbolType : : endogenous , lhss ) ;
lhs = * ( lhss . begin ( ) ) ;
2019-02-15 12:52:46 +01:00
int lhs_symb_id = lhs . first ;
int lhs_orig_symb_id = lhs_symb_id ;
if ( symbol_table . isAuxiliaryVariable ( lhs_symb_id ) )
try
{
lhs_orig_symb_id = symbol_table . getOrigSymbIdForAuxVar ( lhs_symb_id ) ;
}
catch ( . . . )
{
}
return equation - > arg2 - > getPacTargetSymbId ( lhs_symb_id , lhs_orig_symb_id ) ;
}
return - 1 ;
}
2019-02-25 15:29:46 +01:00
void
DynamicModel : : declarePacModelConsistentExpectationEndogs ( const string & name )
{
int i = 0 ;
for ( auto & equation : equations )
if ( equation - > containsPacExpectation ( ) )
{
string eqtag = " " ;
for ( auto & tag : equation_tags )
if ( tag . first = = ( & equation - & equations [ 0 ] ) )
if ( tag . second . first = = " name " )
{
eqtag = tag . second . second ;
break ;
}
if ( eqtag = = " " )
{
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
{
pac_mce_z1_symb_ids [ { name , standard_eqtag } ] =
symbol_table . addSymbol ( " mce_Z1_ " + name + " _ " + standard_eqtag , SymbolType : : endogenous ) ;
}
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-02-20 12:59:55 +01:00
DynamicModel : : addPacModelConsistentExpectationEquation ( const string & name , int discount_symb_id ,
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 )
{
2019-02-20 12:59:55 +01:00
int pac_target_symb_id = getPacTargetSymbId ( name ) ;
2019-02-19 16:36:10 +01:00
pac_eqtag_and_lag . insert ( eqtag_and_lag . begin ( ) , eqtag_and_lag . end ( ) ) ;
int neqs = 0 ;
for ( auto & it : eqtag_and_lag )
2019-02-15 12:52:46 +01:00
{
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 ;
expr_t diff_node_to_search = AddDiff ( AddVariable ( pac_target_symb_id ) ) ;
2019-02-21 10:52:59 +01:00
auto sit = diff_subst_table . find ( diff_node_to_search ) ;
2019-02-19 16:36:10 +01:00
if ( sit ! = diff_subst_table . end ( ) )
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 ) ;
2019-04-23 11:07:32 +02:00
addEquation ( dynamic_cast < BinaryOpNode * > ( AddEqual ( const_cast < VariableNode * > ( target_base_diff_node ) ,
2019-02-19 16:36:10 +01:00
AddMinus ( AddVariable ( pac_target_symb_id ) ,
AddVariable ( pac_target_symb_id , - 1 ) ) ) ) , - 1 ) ;
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 + + )
{
expr_t this_diff_node = AddDiff ( AddVariable ( pac_target_symb_id , i ) ) ;
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 ) ;
addEquation ( dynamic_cast < BinaryOpNode * > ( AddEqual ( current_aux_var ,
AddVariable ( last_aux_var - > symb_id , 1 ) ) ) , - 1 ) ;
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
}
2019-02-19 16:36:10 +01:00
addEquation ( AddEqual ( AddVariable ( mce_z1_symb_id ) ,
2019-04-23 11:07:32 +02:00
AddMinus ( AddTimes ( A , AddMinus ( const_cast < VariableNode * > ( target_base_diff_node ) , fs ) ) , fp ) ) , - 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
}
2019-02-19 16:36:10 +01:00
cout < < " Pac Model Consistent Expectation: added " < < neqs < < " auxiliary variables and equations. " < < 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-05-13 17:43:16 +02:00
if ( growth ! = nullptr )
2019-02-20 16:38:44 +01:00
growth_param_index = symbol_table . addSymbol ( pac_model_name +
" _pac_growth_neutrality_correction " ,
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-05-13 17:43:16 +02:00
if ( growth ! = nullptr )
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
DynamicModel : : substitutePacExpectation ( const string & pac_model_name )
{
for ( auto & it : pac_expectation_substitution )
if ( it . first . first = = pac_model_name )
for ( auto & equation : equations )
for ( auto & tag : equation_tags )
if ( tag . first = = ( & equation - & equations [ 0 ] ) )
if ( tag . second . first = = " name " & & tag . second . second = = it . first . second )
{
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - > substitutePacExpectation ( pac_model_name , it . second ) ) ;
assert ( substeq ! = nullptr ) ;
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 ,
2018-12-20 17:04:28 +01:00
bool bytecode , bool linear_decomposition )
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 ;
2009-06-05 16:45:23 +02:00
for ( deriv_id_table_t : : const_iterator it = deriv_id_table . begin ( ) ;
it ! = deriv_id_table . end ( ) ; it + + )
2009-04-20 12:48:54 +02:00
{
2009-04-20 17:54:19 +02: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 ) ) )
2009-04-20 17:54:19 +02:00
vars . insert ( it - > second ) ;
2009-04-20 12:48:54 +02:00
}
2009-04-14 16:39:53 +02:00
// Launch computations
2018-12-20 17:04:28 +01:00
cout < < " Computing " < < ( linear_decomposition ? " nonlinear " : " " )
< < " 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
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
jacob_map_t contemporaneous_jacobian , static_jacobian ;
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int > , expr_t > first_order_endo_derivatives ;
2018-09-21 17:13:19 +02:00
// for each block contains pair<Size, Feddback_variable>
vector < pair < int , int > > blocks ;
vector < unsigned int > n_static , n_forward , n_backward , n_mixed ;
if ( linear_decomposition )
2009-04-14 16:39:53 +02:00
{
2018-11-23 17:19:59 +01:00
first_order_endo_derivatives = collect_first_order_derivatives_endogenous ( ) ;
2018-09-21 17:13:19 +02:00
is_equation_linear = equationLinear ( first_order_endo_derivatives ) ;
evaluateAndReduceJacobian ( eval_context , contemporaneous_jacobian , static_jacobian , dynamic_jacobian , cutoff , false ) ;
if ( ! computeNaturalNormalization ( ) )
computeNonSingularNormalization ( contemporaneous_jacobian , cutoff , static_jacobian , dynamic_jacobian ) ;
2009-04-14 16:39:53 +02:00
2018-09-21 17:13:19 +02:00
lag_lead_vector_t equation_lag_lead , variable_lag_lead ;
blocks = select_non_linear_equations_and_variables ( is_equation_linear , dynamic_jacobian , equation_reordered , variable_reordered ,
inv_equation_reordered , inv_variable_reordered ,
equation_lag_lead , variable_lag_lead ,
n_static , n_forward , n_backward , n_mixed ) ;
equation_type_and_normalized_equation = equationTypeDetermination ( first_order_endo_derivatives , variable_reordered , equation_reordered , 0 ) ;
prologue = 0 ;
epilogue = 0 ;
block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination ( dynamic_jacobian , blocks , equation_type_and_normalized_equation , variable_reordered , equation_reordered , n_static , n_forward , n_backward , n_mixed , block_col_type , linear_decomposition ) ;
computeChainRuleJacobian ( blocks_derivatives ) ;
blocks_linear = BlockLinear ( blocks_derivatives , variable_reordered ) ;
collect_block_first_order_derivatives ( ) ;
collectBlockVariables ( ) ;
global_temporary_terms = true ;
if ( ! no_tmp_terms )
computeTemporaryTermsOrdered ( ) ;
}
if ( block )
{
2009-04-14 16:39:53 +02:00
2009-12-16 14:21:31 +01:00
evaluateAndReduceJacobian ( eval_context , contemporaneous_jacobian , static_jacobian , dynamic_jacobian , cutoff , false ) ;
2009-12-21 11:29:21 +01:00
computeNonSingularNormalization ( contemporaneous_jacobian , cutoff , static_jacobian , dynamic_jacobian ) ;
2009-12-16 14:21:31 +01:00
2010-09-16 17:51:50 +02:00
computePrologueAndEpilogue ( static_jacobian , equation_reordered , variable_reordered ) ;
2009-04-14 16:39:53 +02:00
2018-09-21 17:13:19 +02:00
first_order_endo_derivatives = collect_first_order_derivatives_endogenous ( ) ;
2009-05-13 01:03:40 +02:00
2010-09-16 17:51:50 +02:00
equation_type_and_normalized_equation = equationTypeDetermination ( first_order_endo_derivatives , variable_reordered , equation_reordered , 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
2010-07-23 11:20:24 +02:00
lag_lead_vector_t equation_lag_lead , variable_lag_lead ;
2009-12-16 14:21:31 +01:00
2010-07-23 11:20:24 +02:00
computeBlockDecompositionAndFeedbackVariablesForEachBlock ( static_jacobian , dynamic_jacobian , equation_reordered , variable_reordered , blocks , equation_type_and_normalized_equation , false , true , mfs , inv_equation_reordered , inv_variable_reordered , equation_lag_lead , variable_lag_lead , n_static , n_forward , n_backward , n_mixed ) ;
2018-09-21 17:13:19 +02:00
block_type_firstequation_size_mfs = reduceBlocksAndTypeDetermination ( dynamic_jacobian , blocks , equation_type_and_normalized_equation , variable_reordered , equation_reordered , n_static , n_forward , n_backward , n_mixed , block_col_type , linear_decomposition ) ;
2009-12-16 14:21:31 +01:00
printBlockDecomposition ( blocks ) ;
computeChainRuleJacobian ( blocks_derivatives ) ;
2009-08-25 11:43:01 +02:00
2009-12-16 14:21:31 +01:00
blocks_linear = BlockLinear ( blocks_derivatives , variable_reordered ) ;
2009-08-25 11:43:01 +02:00
2009-12-16 14:21:31 +01:00
collect_block_first_order_derivatives ( ) ;
2009-08-25 11:43:01 +02:00
2010-07-23 11:20:24 +02:00
collectBlockVariables ( ) ;
2009-12-16 14:21:31 +01:00
global_temporary_terms = true ;
2009-04-14 16:39:53 +02:00
if ( ! no_tmp_terms )
2009-12-16 14:21:31 +01:00
computeTemporaryTermsOrdered ( ) ;
2010-07-23 11:20:24 +02:00
int k = 0 ;
2018-11-23 17:19:59 +01:00
equation_block . resize ( equations . size ( ) ) ;
variable_block_lead_lag = vector < tuple < int , int , int > > ( equations . size ( ) ) ;
2010-07-23 11:20:24 +02:00
for ( unsigned int i = 0 ; i < getNbBlocks ( ) ; i + + )
{
2011-02-04 16:25:38 +01:00
for ( unsigned int j = 0 ; j < getBlockSize ( i ) ; j + + )
2010-07-23 11:20:24 +02:00
{
equation_block [ equation_reordered [ k ] ] = i ;
int l = variable_reordered [ k ] ;
2018-11-23 17:19:59 +01:00
variable_block_lead_lag [ l ] = { i , variable_lag_lead [ l ] . first , variable_lag_lead [ l ] . second } ;
2010-07-23 11:20:24 +02:00
k + + ;
}
}
2009-04-14 16:39:53 +02:00
}
else
2018-09-25 15:56:52 +02:00
{
computeTemporaryTerms ( ! use_dll , no_tmp_terms ) ;
if ( bytecode & & ! no_tmp_terms )
computeTemporaryTermsMapping ( ) ;
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 ;
2018-06-04 12:26:16 +02: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 ;
for ( map < int , ExprNode : : EquationInfo > : : const_iterator it = xrefs . begin ( ) ;
it ! = xrefs . end ( ) ; it + + , i + + )
{
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
{
2018-06-04 12:26:16 +02: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 ;
2018-06-04 15:03:26 +02:00
for ( auto it = xrefs . begin ( ) ;
2017-03-06 16:34:08 +01:00
it ! = xrefs . end ( ) ; it + + , i + + )
{
output < < " M_.xref1.param{ " < < i < < " } = [ " ;
2018-06-04 12:26:16 +02:00
for ( const auto & it1 : it - > second . param )
output < < symbol_table . getTypeSpecificID ( it1 . first ) + 1 < < " " ;
2017-03-06 16:34:08 +01:00
output < < " ]; " < < endl ;
output < < " M_.xref1.endo{ " < < i < < " } = [ " ;
2018-06-04 12:26:16 +02:00
for ( const auto & it1 : it - > second . endo )
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 < < " } = [ " ;
2018-06-04 12:26:16 +02:00
for ( const auto & it1 : it - > second . exo )
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 < < " } = [ " ;
2018-06-04 12:26:16 +02:00
for ( const auto & it1 : it - > second . exo_det )
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 ;
2018-06-04 12:26:16 +02: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 ;
2018-06-04 15:03:26 +02:00
for ( auto it1 = it . second . begin ( ) ;
2018-06-04 12:26:16 +02:00
it1 ! = it . second . end ( ) ; it1 + + )
2017-03-06 16:34:08 +01:00
if ( type = = " param " )
output < < * it1 + 1 < < " " ;
else
2018-06-04 12:26:16 +02: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
}
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int , int , int > , int >
2009-12-16 14:21:31 +01:00
DynamicModel : : get_Derivatives ( int block )
{
2011-06-18 17:53:50 +02:00
int max_lag , max_lead ;
2018-11-23 17:19:59 +01:00
map < tuple < int , int , int , int , int > , int > Derivatives ;
2011-06-18 17:53:50 +02:00
BlockSimulationType simulation_type = getBlockSimulationType ( block ) ;
if ( simulation_type = = EVALUATE_BACKWARD | | simulation_type = = EVALUATE_FORWARD )
{
max_lag = 1 ;
max_lead = 1 ;
setBlockLeadLag ( block , max_lag , max_lead ) ;
}
else
{
max_lag = getBlockMaxLag ( block ) ;
max_lead = getBlockMaxLead ( block ) ;
}
2009-12-16 14:21:31 +01:00
int block_size = getBlockSize ( block ) ;
int block_nb_recursive = block_size - getBlockMfs ( block ) ;
2009-12-16 18:13:23 +01:00
for ( int lag = - max_lag ; lag < = max_lead ; lag + + )
2009-12-16 14:21:31 +01:00
{
2009-12-16 18:13:23 +01:00
for ( int eq = 0 ; eq < block_size ; eq + + )
2009-12-16 14:21:31 +01:00
{
int eqr = getBlockEquationID ( block , eq ) ;
2009-12-16 18:13:23 +01:00
for ( int var = 0 ; var < block_size ; var + + )
2009-12-16 14:21:31 +01:00
{
int varr = getBlockVariableID ( block , var ) ;
2018-11-23 17:19:59 +01:00
if ( dynamic_jacobian . find ( { lag , eqr , varr } ) ! = dynamic_jacobian . end ( ) )
2009-12-16 14:21:31 +01:00
{
bool OK = true ;
2018-11-23 17:19:59 +01:00
auto its = Derivatives . find ( { lag , eq , var , eqr , varr } ) ;
2009-12-16 18:13:23 +01:00
if ( its ! = Derivatives . end ( ) )
2009-12-16 14:21:31 +01:00
{
2009-12-16 18:13:23 +01:00
if ( its - > second = = 2 )
OK = false ;
2009-12-16 14:21:31 +01:00
}
2009-12-16 18:13:23 +01:00
if ( OK )
2009-12-16 14:21:31 +01:00
{
2010-04-28 16:03:32 +02:00
if ( getBlockEquationType ( block , eq ) = = E_EVALUATE_S & & eq < block_nb_recursive )
2009-12-16 14:21:31 +01:00
//It's a normalized equation, we have to recompute the derivative using chain rule derivative function
2018-11-23 17:19:59 +01:00
Derivatives [ { lag , eq , var , eqr , varr } ] = 1 ;
2009-12-16 14:21:31 +01:00
else
//It's a feedback equation we can use the derivatives
2018-11-23 17:19:59 +01:00
Derivatives [ { lag , eq , var , eqr , varr } ] = 0 ;
2009-12-16 14:21:31 +01:00
}
2009-12-16 18:13:23 +01:00
if ( var < block_nb_recursive )
2009-12-16 14:21:31 +01:00
{
int eqs = getBlockEquationID ( block , var ) ;
2009-12-16 18:13:23 +01:00
for ( int vars = block_nb_recursive ; vars < block_size ; vars + + )
2009-12-16 14:21:31 +01:00
{
int varrs = getBlockVariableID ( block , vars ) ;
//A new derivative needs to be computed using the chain rule derivative function (a feedback variable appears in a recursive equation)
2018-11-23 17:19:59 +01:00
if ( Derivatives . find ( { lag , var , vars , eqs , varrs } ) ! = Derivatives . end ( ) )
Derivatives [ { lag , eq , vars , eqr , varrs } ] = 2 ;
2009-12-16 14:21:31 +01:00
}
}
}
}
}
}
2018-11-23 17:19:59 +01:00
return Derivatives ;
2009-12-16 14:21:31 +01:00
}
void
2010-07-23 11:20:24 +02:00
DynamicModel : : computeChainRuleJacobian ( blocks_derivatives_t & blocks_endo_derivatives )
2009-12-16 14:21:31 +01:00
{
2010-09-16 19:18:45 +02:00
map < int , expr_t > recursive_variables ;
2009-12-16 14:21:31 +01:00
unsigned int nb_blocks = getNbBlocks ( ) ;
2010-07-23 11:20:24 +02:00
blocks_endo_derivatives = blocks_derivatives_t ( nb_blocks ) ;
2009-12-16 18:13:23 +01:00
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2009-12-16 14:21:31 +01:00
{
2010-09-16 19:00:48 +02:00
block_derivatives_equation_variable_laglead_nodeid_t tmp_derivatives ;
2009-12-16 14:21:31 +01:00
recursive_variables . clear ( ) ;
int block_size = getBlockSize ( block ) ;
int block_nb_mfs = getBlockMfs ( block ) ;
int block_nb_recursives = block_size - block_nb_mfs ;
2010-07-23 11:20:24 +02:00
blocks_endo_derivatives . push_back ( block_derivatives_equation_variable_laglead_nodeid_t ( 0 ) ) ;
for ( int i = 0 ; i < block_nb_recursives ; i + + )
2009-12-16 14:21:31 +01:00
{
2010-07-23 11:20:24 +02:00
if ( getBlockEquationType ( block , i ) = = E_EVALUATE_S )
2018-07-17 18:34:07 +02:00
recursive_variables [ getDerivID ( symbol_table . getID ( SymbolType : : endogenous , getBlockVariableID ( block , i ) ) , 0 ) ] = getBlockEquationRenormalizedExpr ( block , i ) ;
2010-07-23 11:20:24 +02:00
else
2018-07-17 18:34:07 +02:00
recursive_variables [ getDerivID ( symbol_table . getID ( SymbolType : : endogenous , getBlockVariableID ( block , i ) ) , 0 ) ] = getBlockEquationExpr ( block , i ) ;
2009-12-16 14:21:31 +01:00
}
2018-11-23 17:19:59 +01:00
auto Derivatives = get_Derivatives ( block ) ;
for ( const auto & it : Derivatives )
2009-12-16 14:21:31 +01:00
{
2018-11-23 17:19:59 +01:00
int Deriv_type = it . second ;
2019-09-11 15:59:23 +02:00
auto [ lag , eq , var , eqr , varr ] = it . first ;
2010-07-23 11:20:24 +02:00
if ( Deriv_type = = 0 )
2018-11-23 17:19:59 +01:00
first_chain_rule_derivatives [ { eqr , varr , lag } ] = derivatives [ 1 ] [ { eqr , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , varr ) , lag ) } ] ;
2010-07-23 11:20:24 +02:00
else if ( Deriv_type = = 1 )
2018-11-23 17:19:59 +01:00
first_chain_rule_derivatives [ { eqr , varr , lag } ] = ( equation_type_and_normalized_equation [ eqr ] . second ) - > getChainRuleDerivative ( getDerivID ( symbol_table . getID ( SymbolType : : endogenous , varr ) , lag ) , recursive_variables ) ;
2010-07-23 11:20:24 +02:00
else if ( Deriv_type = = 2 )
2009-12-16 14:21:31 +01:00
{
2010-07-23 11:20:24 +02:00
if ( getBlockEquationType ( block , eq ) = = E_EVALUATE_S & & eq < block_nb_recursives )
2018-11-23 17:19:59 +01:00
first_chain_rule_derivatives [ { eqr , varr , lag } ] = ( equation_type_and_normalized_equation [ eqr ] . second ) - > getChainRuleDerivative ( getDerivID ( symbol_table . getID ( SymbolType : : endogenous , varr ) , lag ) , recursive_variables ) ;
2009-12-16 14:21:31 +01:00
else
2018-11-23 17:19:59 +01:00
first_chain_rule_derivatives [ { eqr , varr , lag } ] = equations [ eqr ] - > getChainRuleDerivative ( getDerivID ( symbol_table . getID ( SymbolType : : endogenous , varr ) , lag ) , recursive_variables ) ;
2009-12-16 14:21:31 +01:00
}
2018-11-23 17:19:59 +01:00
tmp_derivatives . emplace_back ( eq , var , lag , first_chain_rule_derivatives [ { eqr , varr , lag } ] ) ;
2009-12-16 14:21:31 +01:00
}
2010-07-23 11:20:24 +02:00
blocks_endo_derivatives [ block ] = tmp_derivatives ;
2009-12-16 14:21:31 +01:00
}
}
void
DynamicModel : : collect_block_first_order_derivatives ( )
{
//! vector for an equation or a variable indicates the block number
2018-11-23 17:19:59 +01:00
vector < int > equation_2_block ( equation_reordered . size ( ) ) , variable_2_block ( variable_reordered . size ( ) ) ;
2009-12-16 14:21:31 +01:00
unsigned int nb_blocks = getNbBlocks ( ) ;
2009-12-16 18:13:23 +01:00
for ( unsigned int block = 0 ; block < nb_blocks ; block + + )
2009-12-16 14:21:31 +01:00
{
unsigned int block_size = getBlockSize ( block ) ;
2009-12-16 18:13:23 +01:00
for ( unsigned int i = 0 ; i < block_size ; i + + )
2009-12-16 14:21:31 +01:00
{
equation_2_block [ getBlockEquationID ( block , i ) ] = block ;
variable_2_block [ getBlockVariableID ( block , i ) ] = block ;
}
}
2010-09-16 19:00:48 +02:00
other_endo_block = vector < lag_var_t > ( nb_blocks ) ;
exo_block = vector < lag_var_t > ( nb_blocks ) ;
exo_det_block = vector < lag_var_t > ( nb_blocks ) ;
derivative_endo = vector < derivative_t > ( nb_blocks ) ;
derivative_other_endo = vector < derivative_t > ( nb_blocks ) ;
derivative_exo = vector < derivative_t > ( nb_blocks ) ;
derivative_exo_det = vector < derivative_t > ( nb_blocks ) ;
2018-06-04 16:36:46 +02:00
endo_max_leadlag_block = vector < pair < int , int > > ( nb_blocks , { 0 , 0 } ) ;
other_endo_max_leadlag_block = vector < pair < int , int > > ( nb_blocks , { 0 , 0 } ) ;
exo_max_leadlag_block = vector < pair < int , int > > ( nb_blocks , { 0 , 0 } ) ;
exo_det_max_leadlag_block = vector < pair < int , int > > ( nb_blocks , { 0 , 0 } ) ;
max_leadlag_block = vector < pair < int , int > > ( nb_blocks , { 0 , 0 } ) ;
2018-11-15 16:39:53 +01:00
for ( auto & first_derivative : derivatives [ 1 ] )
2009-12-16 14:21:31 +01:00
{
2018-11-15 16:39:53 +01:00
int eq = first_derivative . first [ 0 ] ;
int var = symbol_table . getTypeSpecificID ( getSymbIDByDerivID ( first_derivative . first [ 1 ] ) ) ;
int lag = getLagByDerivID ( first_derivative . first [ 1 ] ) ;
2009-12-16 14:21:31 +01:00
int block_eq = equation_2_block [ eq ] ;
2017-06-01 19:58:32 +02:00
int block_var = 0 ;
2010-09-16 19:00:48 +02:00
derivative_t tmp_derivative ;
lag_var_t lag_var ;
2018-11-15 16:39:53 +01:00
switch ( getTypeByDerivID ( first_derivative . first [ 1 ] ) )
2009-12-16 14:21:31 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2015-01-21 13:33:29 +01:00
block_var = variable_2_block [ var ] ;
2009-12-16 18:13:23 +01:00
if ( block_eq = = block_var )
{
if ( lag < 0 & & lag < - endo_max_leadlag_block [ block_eq ] . first )
2018-06-04 16:36:46 +02:00
endo_max_leadlag_block [ block_eq ] = { - lag , endo_max_leadlag_block [ block_eq ] . second } ;
2009-12-16 18:13:23 +01:00
if ( lag > 0 & & lag > endo_max_leadlag_block [ block_eq ] . second )
2018-06-04 16:36:46 +02:00
endo_max_leadlag_block [ block_eq ] = { endo_max_leadlag_block [ block_eq ] . first , lag } ;
2009-12-16 18:13:23 +01:00
tmp_derivative = derivative_endo [ block_eq ] ;
2018-11-23 17:19:59 +01:00
tmp_derivative [ { lag , eq , var } ] = derivatives [ 1 ] [ { eq , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , var ) , lag ) } ] ;
2009-12-16 18:13:23 +01:00
derivative_endo [ block_eq ] = tmp_derivative ;
}
else
{
if ( lag < 0 & & lag < - other_endo_max_leadlag_block [ block_eq ] . first )
2018-06-04 16:36:46 +02:00
other_endo_max_leadlag_block [ block_eq ] = { - lag , other_endo_max_leadlag_block [ block_eq ] . second } ;
2009-12-16 18:13:23 +01:00
if ( lag > 0 & & lag > other_endo_max_leadlag_block [ block_eq ] . second )
2018-06-04 16:36:46 +02:00
other_endo_max_leadlag_block [ block_eq ] = { other_endo_max_leadlag_block [ block_eq ] . first , lag } ;
2009-12-16 18:13:23 +01:00
tmp_derivative = derivative_other_endo [ block_eq ] ;
2011-02-04 16:25:38 +01:00
{
2018-11-23 17:19:59 +01:00
auto it = block_other_endo_index . find ( block_eq ) ;
2011-02-04 16:25:38 +01:00
if ( it = = block_other_endo_index . end ( ) )
block_other_endo_index [ block_eq ] [ var ] = 0 ;
else
{
2018-06-04 15:03:26 +02:00
auto it1 = it - > second . find ( var ) ;
2011-02-04 16:25:38 +01:00
if ( it1 = = it - > second . end ( ) )
{
int size = block_other_endo_index [ block_eq ] . size ( ) ;
block_other_endo_index [ block_eq ] [ var ] = size ;
}
}
}
2018-11-23 17:19:59 +01:00
tmp_derivative [ { lag , eq , var } ] = derivatives [ 1 ] [ { eq , getDerivID ( symbol_table . getID ( SymbolType : : endogenous , var ) , lag ) } ] ;
2009-12-16 18:13:23 +01:00
derivative_other_endo [ block_eq ] = tmp_derivative ;
lag_var = other_endo_block [ block_eq ] ;
if ( lag_var . find ( lag ) = = lag_var . end ( ) )
lag_var [ lag ] . clear ( ) ;
lag_var [ lag ] . insert ( var ) ;
other_endo_block [ block_eq ] = lag_var ;
}
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2009-12-16 18:13:23 +01:00
if ( lag < 0 & & lag < - exo_max_leadlag_block [ block_eq ] . first )
2018-06-04 16:36:46 +02:00
exo_max_leadlag_block [ block_eq ] = { - lag , exo_max_leadlag_block [ block_eq ] . second } ;
2009-12-16 18:13:23 +01:00
if ( lag > 0 & & lag > exo_max_leadlag_block [ block_eq ] . second )
2018-06-04 16:36:46 +02:00
exo_max_leadlag_block [ block_eq ] = { exo_max_leadlag_block [ block_eq ] . first , lag } ;
2009-12-16 18:13:23 +01:00
tmp_derivative = derivative_exo [ block_eq ] ;
2011-02-04 16:25:38 +01:00
{
2018-11-23 17:19:59 +01:00
auto it = block_exo_index . find ( block_eq ) ;
2011-02-04 16:25:38 +01:00
if ( it = = block_exo_index . end ( ) )
block_exo_index [ block_eq ] [ var ] = 0 ;
else
{
2018-06-04 15:03:26 +02:00
auto it1 = it - > second . find ( var ) ;
2011-02-04 16:25:38 +01:00
if ( it1 = = it - > second . end ( ) )
{
int size = block_exo_index [ block_eq ] . size ( ) ;
block_exo_index [ block_eq ] [ var ] = size ;
}
}
}
2018-11-23 17:19:59 +01:00
tmp_derivative [ { lag , eq , var } ] = derivatives [ 1 ] [ { eq , getDerivID ( symbol_table . getID ( SymbolType : : exogenous , var ) , lag ) } ] ;
2009-12-16 18:13:23 +01:00
derivative_exo [ block_eq ] = tmp_derivative ;
lag_var = exo_block [ block_eq ] ;
if ( lag_var . find ( lag ) = = lag_var . end ( ) )
lag_var [ lag ] . clear ( ) ;
lag_var [ lag ] . insert ( var ) ;
exo_block [ block_eq ] = lag_var ;
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2009-12-16 18:13:23 +01:00
if ( lag < 0 & & lag < - exo_det_max_leadlag_block [ block_eq ] . first )
2018-06-04 16:36:46 +02:00
exo_det_max_leadlag_block [ block_eq ] = { - lag , exo_det_max_leadlag_block [ block_eq ] . second } ;
2009-12-16 18:13:23 +01:00
if ( lag > 0 & & lag > exo_det_max_leadlag_block [ block_eq ] . second )
2018-06-04 16:36:46 +02:00
exo_det_max_leadlag_block [ block_eq ] = { exo_det_max_leadlag_block [ block_eq ] . first , lag } ;
2009-12-16 18:13:23 +01:00
tmp_derivative = derivative_exo_det [ block_eq ] ;
2011-02-04 16:25:38 +01:00
{
2018-11-23 17:19:59 +01:00
auto it = block_det_exo_index . find ( block_eq ) ;
2011-02-04 16:25:38 +01:00
if ( it = = block_det_exo_index . end ( ) )
block_det_exo_index [ block_eq ] [ var ] = 0 ;
else
{
2018-06-04 15:03:26 +02:00
auto it1 = it - > second . find ( var ) ;
2011-02-04 16:25:38 +01:00
if ( it1 = = it - > second . end ( ) )
{
int size = block_det_exo_index [ block_eq ] . size ( ) ;
block_det_exo_index [ block_eq ] [ var ] = size ;
}
}
}
2018-11-23 17:19:59 +01:00
tmp_derivative [ { lag , eq , var } ] = derivatives [ 1 ] [ { eq , getDerivID ( symbol_table . getID ( SymbolType : : exogenous , var ) , lag ) } ] ;
2009-12-16 18:13:23 +01:00
derivative_exo_det [ block_eq ] = tmp_derivative ;
lag_var = exo_det_block [ block_eq ] ;
if ( lag_var . find ( lag ) = = lag_var . end ( ) )
lag_var [ lag ] . clear ( ) ;
lag_var [ lag ] . insert ( var ) ;
exo_det_block [ block_eq ] = lag_var ;
break ;
default :
break ;
2009-12-16 14:21:31 +01:00
}
2009-12-16 18:13:23 +01:00
if ( lag < 0 & & lag < - max_leadlag_block [ block_eq ] . first )
2018-06-04 16:36:46 +02:00
max_leadlag_block [ block_eq ] = { - lag , max_leadlag_block [ block_eq ] . second } ;
2009-12-16 18:13:23 +01:00
if ( lag > 0 & & lag > max_leadlag_block [ block_eq ] . second )
2018-06-04 16:36:46 +02:00
max_leadlag_block [ block_eq ] = { max_leadlag_block [ block_eq ] . first , lag } ;
2009-12-16 14:21:31 +01:00
}
}
2011-02-04 16:25:38 +01:00
void
DynamicModel : : collectBlockVariables ( )
2010-07-23 11:20:24 +02:00
{
for ( unsigned int block = 0 ; block < getNbBlocks ( ) ; block + + )
{
int prev_var = - 1 ;
int prev_lag = - 999999999 ;
int count_col_exo = 0 ;
var_t tmp_var_exo ;
2018-11-23 17:19:59 +01:00
for ( const auto & it : exo_block [ block ] )
2010-07-23 11:20:24 +02:00
{
2018-11-23 17:19:59 +01:00
int lag = it . first ;
for ( int var : it . second )
2010-07-23 11:20:24 +02:00
{
tmp_var_exo . insert ( var ) ;
2011-02-04 16:25:38 +01:00
if ( prev_var ! = var | | prev_lag ! = lag )
2010-07-23 11:20:24 +02:00
{
prev_var = var ;
prev_lag = lag ;
count_col_exo + + ;
}
}
}
2018-06-04 12:48:09 +02:00
block_var_exo . emplace_back ( tmp_var_exo , count_col_exo ) ;
2010-07-23 11:20:24 +02:00
}
}
2009-04-14 16:39:53 +02:00
void
2019-04-04 17:01:37 +02:00
DynamicModel : : writeDynamicFile ( const string & basename , bool block , bool linear_decomposition , bool bytecode , bool use_dll , const string & mexext , const filesystem : : path & matlabroot , const filesystem : : path & dynareroot , int order , bool julia ) const
2009-12-16 18:13:23 +01:00
{
if ( block & & bytecode )
2018-09-21 17:13:19 +02:00
writeModelEquationsCode_Block ( basename , map_idx , linear_decomposition ) ;
2011-02-04 16:25:38 +01:00
else if ( ! block & & bytecode )
2018-09-21 17:13:19 +02:00
{
if ( linear_decomposition )
writeModelEquationsCode_Block ( basename , map_idx , linear_decomposition ) ;
writeModelEquationsCode ( basename , map_idx ) ;
}
2009-12-16 18:13:23 +01:00
else if ( block & & ! bytecode )
2018-06-27 15:01:31 +02:00
writeSparseDynamicMFile ( basename ) ;
2009-12-16 18:13:23 +01:00
else if ( use_dll )
2018-10-26 11:44:26 +02:00
{
writeDynamicCFile ( basename , order ) ;
compileDll ( basename , " dynamic " , mexext , matlabroot , dynareroot ) ;
}
2015-07-27 17:02:51 +02:00
else if ( julia )
writeDynamicJuliaFile ( basename ) ;
2009-12-16 18:13:23 +01:00
else
2019-10-17 15:03:26 +02:00
writeDynamicMFile ( basename ) ;
writeSetAuxiliaryVariables ( basename , julia ) ;
2018-03-02 17:50:35 +01:00
}
void
DynamicModel : : writeSetAuxiliaryVariables ( const string & basename , const bool julia ) const
{
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 ;
2018-06-27 15:01:31 +02:00
string func_name = julia ? basename + " _dynamic_set_auxiliary_series " : " dynamic_set_auxiliary_series " ;
string filename = julia ? func_name + " .jl " : packageDir ( basename ) + " / " + func_name + " .m " ;
2018-03-02 17:50:35 +01:00
string comment = julia ? " # " : " % " ;
ofstream output ;
2018-06-27 15:12:12 +02:00
output . open ( filename , ios : : out | ios : : binary ) ;
2018-03-02 17:50:35 +01:00
if ( ! output . is_open ( ) )
{
cerr < < " ERROR: Can't open file " < < filename < < " for writing " < < endl ;
exit ( EXIT_FAILURE ) ;
}
output < < " function ds = " < < func_name + " (ds, params) " < < endl
< < 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
< < output_func_body . str ( ) ;
2018-03-02 18:39:16 +01:00
output . close ( ) ;
2018-03-02 17:50:35 +01:00
}
void
DynamicModel : : writeAuxVarRecursiveDefinitions ( ostream & output , ExprNodeOutputType output_type ) const
{
deriv_node_temp_terms_t tef_terms ;
temporary_terms_t temporary_terms ;
2018-03-27 17:14:30 +02:00
temporary_terms_idxs_t temporary_terms_idxs ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
if ( dynamic_cast < ExprNode * > ( aux_equation ) - > containsExternalFunction ( ) )
dynamic_cast < ExprNode * > ( aux_equation ) - > writeExternalFunctionOutput ( output , output_type ,
2018-03-27 17:14:30 +02:00
temporary_terms ,
temporary_terms_idxs ,
tef_terms ) ;
2018-06-04 12:26:16 +02:00
for ( auto aux_equation : aux_equations )
2018-03-02 17:50:35 +01:00
{
2018-06-04 12:26:16 +02:00
dynamic_cast < ExprNode * > ( aux_equation ) - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , 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
2011-03-21 18:40:57 +01:00
void
DynamicModel : : replaceMyEquations ( DynamicModel & dynamic_model ) const
{
dynamic_model . equations . clear ( ) ;
2014-01-27 16:41:43 +01:00
for ( size_t i = 0 ; i < equations . size ( ) ; i + + )
2018-10-10 13:07:25 +02:00
dynamic_model . addEquation ( equations [ i ] - > clone ( dynamic_model ) ,
2014-01-27 16:41:43 +01:00
equations_lineno [ i ] ) ;
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
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equations [ i ] - > addMultipliersToConstraints ( i ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
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
// Add Planner Objective to equations to include in computeDerivIDs
assert ( static_model . equations . size ( ) = = 1 ) ;
2018-10-10 13:07:25 +02:00
addEquation ( static_model . equations [ 0 ] - > clone ( * this ) , static_model . equations_lineno [ 0 ] ) ;
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 ;
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02:00
for ( const auto & dynvar : dynvars )
2011-03-21 18:40:57 +01:00
{
2018-06-04 12:26:16 +02:00
int lag = dynvar . second ;
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 ;
2011-03-21 18:40:57 +01:00
std : : stringstream lagstream ;
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 ) ;
}
equations . clear ( ) ;
2014-01-27 16:41:43 +01:00
addEquation ( AddEqual ( lagrangian , Zero ) , - 1 ) ;
2011-03-21 18:40:57 +01:00
computeDerivIDs ( ) ;
//Compute derivatives and overwrite equations
vector < expr_t > neweqs ;
for ( deriv_id_table_t : : const_iterator it = deriv_id_table . begin ( ) ;
it ! = deriv_id_table . end ( ) ; it + + )
// For all endogenous variables with zero lag
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( it - > first . first ) = = SymbolType : : endogenous & & it - > first . second = = 0 )
2011-03-21 18:40:57 +01:00
neweqs . push_back ( AddEqual ( equations [ 0 ] - > getNonZeroPartofEquation ( ) - > getDerivative ( it - > second ) , Zero ) ) ;
// Add new equations
equations . clear ( ) ;
2018-06-04 12:26:16 +02:00
for ( auto & neweq : neweqs )
addEquation ( neweq , - 1 ) ;
2011-03-21 18:40:57 +01:00
}
2018-09-21 17:13:19 +02:00
void
DynamicModel : : toNonlinearPart ( DynamicModel & non_linear_equations_dynamic_model ) const
{
// Convert model local variables (need to be done first)
2018-11-23 17:19:59 +01:00
for ( const auto & it : local_variables_table )
non_linear_equations_dynamic_model . AddLocalVariable ( it . first , it . second ) ;
2018-09-21 17:13:19 +02: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 ( )
{
set < int > existing_tags ;
for ( const auto & eqn : equation_tags )
if ( eqn . second . first = = " name " )
existing_tags . insert ( eqn . first ) ;
for ( int eq = 0 ; eq < static_cast < int > ( equations . size ( ) ) ; eq + + )
if ( existing_tags . find ( eq ) = = existing_tags . end ( ) )
if ( auto lhs_expr = dynamic_cast < VariableNode * > ( equations [ eq ] - > arg1 ) ; lhs_expr & & equation_tags_xref . find ( pair ( " name " , symbol_table . getName ( lhs_expr - > symb_id ) ) ) = = equation_tags_xref . end ( ) )
{
equation_tags . push_back ( pair ( eq , pair ( " name " , symbol_table . getName ( lhs_expr - > symb_id ) ) ) ) ;
equation_tags_xref . emplace ( pair ( " name " , symbol_table . getName ( lhs_expr - > symb_id ) ) , eq ) ;
}
else if ( equation_tags_xref . find ( pair ( " name " , to_string ( eq + 1 ) ) ) = = equation_tags_xref . end ( ) )
{
equation_tags . push_back ( pair ( eq , pair ( " name " , to_string ( eq + 1 ) ) ) ) ;
equation_tags_xref . emplace ( pair ( " name " , to_string ( eq + 1 ) ) , eq ) ;
}
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 ) ;
}
sort ( equation_tags . begin ( ) , equation_tags . end ( ) ) ;
}
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 ;
2018-06-04 12:26:16 +02: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 ;
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02: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
}
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02: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 ( ) ;
2018-06-04 12:26:16 +02: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
}
2018-06-04 12:26:16 +02: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 ;
2009-06-05 16:45:23 +02:00
for ( deriv_id_table_t : : const_iterator it = deriv_id_table . begin ( ) ;
it ! = deriv_id_table . end ( ) ; it + + )
2009-04-17 18:26:23 +02:00
{
const int & symb_id = it - > first . first ;
const int & lag = it - > first . second ;
const int & deriv_id = it - > second ;
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 ;
2009-06-05 16:45:23 +02:00
for ( map < pair < int , int > , int > : : const_iterator it = ordered_dyn_endo . begin ( ) ;
it ! = ordered_dyn_endo . end ( ) ; it + + )
2009-04-17 18:26:23 +02: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
{
2018-06-04 15:03:26 +02:00
auto it = dyn_jacobian_cols_table . find ( deriv_id ) ;
2009-04-17 18:26:23 +02:00
if ( it = = dyn_jacobian_cols_table . end ( ) )
throw UnknownDerivIDException ( ) ;
else
return it - > second ;
}
2010-10-15 19:05:16 +02:00
void
DynamicModel : : testTrendDerivativesEqualToZero ( const eval_context_t & eval_context )
{
for ( deriv_id_table_t : : const_iterator it = deriv_id_table . begin ( ) ;
it ! = deriv_id_table . end ( ) ; it + + )
2018-07-17 18:34:07 +02:00
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)
testeq = testeq - > getDerivative ( it - > second ) ; // d F / d Trend
for ( deriv_id_table_t : : const_iterator endogit = deriv_id_table . begin ( ) ;
endogit ! = deriv_id_table . end ( ) ; endogit + + )
2018-07-17 18:34:07 +02:00
if ( symbol_table . getType ( endogit - > first . first ) = = SymbolType : : endogenous )
2010-10-15 19:05:16 +02:00
{
2013-10-29 11:46:54 +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 "
2013-10-29 11:46:54 +01:00
< < symbol_table . getName ( it - > first . first ) < < " and endogenous variable "
2019-11-14 17:51:16 +01:00
< < symbol_table . getName ( endogit - > first . first ) < < " is not null (abs. value = "
< < 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 ) ;
2018-11-16 18:13:34 +01:00
ostringstream tt_output ; // Used for storing model temp vars and equations
2019-08-22 15:55:00 +02:00
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
2019-08-22 17:00:36 +02:00
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
2018-11-15 16:39:53 +01:00
for ( const auto & residuals_params_derivative : params_derivatives . find ( { 0 , 1 } ) - > second )
2009-12-16 18:13:23 +01:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , param ] = vectorToTuple < 2 > ( residuals_params_derivative . first ) ;
2018-06-04 12:26:16 +02:00
expr_t d1 = residuals_params_derivative . second ;
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
2018-11-15 16:39:53 +01:00
for ( const auto & jacobian_params_derivative : params_derivatives . find ( { 1 , 1 } ) - > second )
2010-03-16 10:15:19 +01:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , var , param ] = vectorToTuple < 3 > ( jacobian_params_derivative . first ) ;
2018-06-04 12:26:16 +02:00
expr_t d2 = jacobian_params_derivative . second ;
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 ;
2018-11-15 16:39:53 +01:00
for ( const auto & it : params_derivatives . find ( { 0 , 2 } ) - > second )
2009-12-16 18:13:23 +01:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , param1 , param2 ] = vectorToTuple < 3 > ( it . first ) ;
2018-06-05 15:34:34 +02:00
expr_t d2 = it . second ;
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 ;
2018-11-15 16:39:53 +01:00
for ( const auto & it : params_derivatives . find ( { 1 , 2 } ) - > second )
2010-03-15 16:02:07 +01:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , var , param1 , param2 ] = vectorToTuple < 4 > ( it . first ) ;
2018-06-05 15:34:34 +02:00
expr_t d2 = it . second ;
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 ;
2018-11-15 16:39:53 +01:00
for ( const auto & it : params_derivatives . find ( { 2 , 1 } ) - > second )
2010-03-11 16:46:19 +01:00
{
2019-09-11 15:59:23 +02:00
auto [ eq , var1 , var2 , param ] = vectorToTuple < 4 > ( it . first ) ;
2018-06-05 15:34:34 +02:00
expr_t d2 = it . second ;
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 ;
for ( const auto & it : params_derivatives . find ( { 3 , 1 } ) - > second )
{
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 ;
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
2017-04-04 15:28:27 +02:00
DynamicModel : : writeLatexFile ( const string & basename , const 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
2017-08-24 15:35:10 +02:00
DynamicModel : : writeLatexOriginalFile ( const string & basename , const 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 ;
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02: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
}
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( subst ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2009-09-30 17:10:31 +02:00
}
// Add new equations
2018-06-04 12:26:16 +02: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
{
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
equation = dynamic_cast < BinaryOpNode * > ( equation - > substituteAdl ( ) ) ;
2018-01-30 10:06:56 +01:00
}
2019-08-19 14:51:21 +02:00
vector < int >
DynamicModel : : getEquationNumbersFromTags ( const set < string > & eqtags ) const
2018-05-30 16:48:08 +02:00
{
2019-08-19 14:51:21 +02:00
vector < int > eqnumbers ;
2018-06-05 18:38:53 +02:00
for ( auto & eqtag : eqtags )
2019-11-18 17:13:49 +01:00
{
bool found = false ;
for ( const auto & equation_tag : equation_tags )
if ( equation_tag . second . first = = " name "
& & equation_tag . second . second = = eqtag )
{
found = true ;
eqnumbers . push_back ( equation_tag . first ) ;
break ;
}
if ( ! found )
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
}
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
DynamicModel : : findPacExpectationEquationNumbers ( vector < int > & eqnumbers ) const
{
int i = 0 ;
for ( auto & equation : equations )
{
if ( equation - > containsPacExpectation ( ) )
if ( find ( eqnumbers . begin ( ) , eqnumbers . end ( ) , i ) = = eqnumbers . end ( ) )
eqnumbers . push_back ( i ) ;
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
{
2019-08-19 14:51:21 +02:00
vector < int > eqnumbers = getEquationNumbersFromTags ( var_model_eqtags ) ;
2018-06-07 12:53:00 +02:00
findPacExpectationEquationNumbers ( eqnumbers ) ;
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 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 ) ;
2018-06-04 12:26:16 +02:00
for ( auto & it : local_variables_table )
2018-06-05 16:38:37 +02:00
if ( used_local_vars . find ( it . first ) ! = used_local_vars . end ( ) )
2019-10-22 14:56:28 +02:00
it . second - > 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 ;
2018-06-04 12:26:16 +02:00
for ( auto & it : local_variables_table )
2019-10-22 14:56:28 +02:00
it . second = it . second - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
// Substitute in equations
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2018-05-30 16:48:08 +02:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - >
2019-10-22 14:56:28 +02:00
substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2018-05-30 16:48:08 +02:00
}
// Add new equations
2018-06-04 12:26:16 +02: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 ;
2018-06-07 12:53:00 +02:00
for ( const auto & equation : equations )
2018-07-17 18:34:07 +02:00
equation - > collectVariables ( SymbolType : : modelLocalVariable , used_local_vars ) ;
2018-06-04 12:26:16 +02: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
2018-06-07 12:53:00 +02: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-11-07 20:17:49 +01:00
for ( const auto & gv : pac_growth )
if ( gv ! = nullptr )
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 ;
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2018-01-30 10:06:56 +01:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - >
2019-10-22 14:56:28 +02:00
substituteDiff ( diff_nodes , diff_subst_table , neweqs ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2018-01-30 10:06:56 +01:00
}
2019-02-28 19:22:34 +01:00
for ( auto & it : pac_growth )
if ( it ! = nullptr )
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
2018-06-04 12:26:16 +02: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
2018-06-04 12:26:16 +02:00
for ( auto & it : local_variables_table )
it . second = it . second - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-29 18:16:10 +01:00
// Substitute in equations
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2009-10-29 18:16:10 +01:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = substeq ;
2009-10-29 18:16:10 +01:00
}
// Add new equations
2018-06-04 12:26:16 +02: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 ( )
{
2018-06-04 12:26:16 +02:00
for ( auto & it : local_variables_table )
it . second = it . second - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2018-04-18 14:29:40 +02:00
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2009-11-07 19:37:11 +01:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - > decreaseLeadsLagsPredeterminedVariables ( ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
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
for ( nonstationary_symbols_map_t : : const_reverse_iterator it = nonstationary_symbols_map . rbegin ( ) ;
it ! = nonstationary_symbols_map . rend ( ) ; + + it )
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - > detrend ( it - > first , it - > second . first , it - > second . second ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( substeq ) ;
2010-10-15 19:05:16 +02:00
}
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2018-06-04 12:26:16 +02:00
BinaryOpNode * substeq = dynamic_cast < BinaryOpNode * > ( equation - > removeTrendLeadLag ( trend_symbols_map ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
2018-06-04 12:26:16 +02:00
equation = dynamic_cast < BinaryOpNode * > ( substeq ) ;
2010-10-15 19:05:16 +02:00
}
}
void
DynamicModel : : removeTrendVariableFromEquations ( )
{
2018-06-04 12:26:16 +02:00
for ( auto & equation : equations )
2010-10-15 19:05:16 +02:00
{
2018-06-04 15:03:26 +02:00
auto * substeq = dynamic_cast < BinaryOpNode * > ( equation - > replaceTrendVar ( ) ) ;
2018-06-04 12:52:14 +02:00
assert ( substeq ! = nullptr ) ;
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 ) ;
auto * auxvar = dynamic_cast < VariableNode * > ( aux_equation - > arg1 ) ;
2018-06-04 12:52:14 +02:00
assert ( auxvar ! = nullptr ) ;
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
vector < int > trendVars = symbol_table . getTrendVarIds ( ) ;
for ( vector < int > : : const_iterator it = trendVars . begin ( ) ;
it ! = trendVars . end ( ) ; it + + )
2017-06-01 19:58:32 +02:00
eval_context [ * it ] = 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
2012-02-17 10:48:28 +01:00
bool
2011-10-14 14:35:32 +02:00
DynamicModel : : isModelLocalVariableUsed ( ) const
{
set < int > used_local_vars ;
size_t i = 0 ;
while ( i < equations . size ( ) & & used_local_vars . size ( ) = = 0 )
{
2018-07-17 18:34:07 +02:00
equations [ i ] - > collectVariables ( SymbolType : : modelLocalVariable , used_local_vars ) ;
2011-10-14 14:35:32 +02:00
i + + ;
}
return used_local_vars . size ( ) > 0 ;
}
2013-04-11 17:07:39 +02:00
void
2018-06-04 14:17:36 +02:00
DynamicModel : : addStaticOnlyEquation ( expr_t eq , int lineno , const vector < pair < string , string > > & eq_tags )
2013-04-11 17:07:39 +02:00
{
2018-06-04 15:03:26 +02:00
auto * beq = dynamic_cast < BinaryOpNode * > ( eq ) ;
2018-11-28 14:32:26 +01:00
assert ( beq ! = nullptr & & beq - > op_code = = BinaryOpcode : : equal ) ;
2013-04-11 17:07:39 +02:00
2018-06-04 14:17:36 +02:00
vector < pair < string , string > > soe_eq_tags ;
2018-06-04 12:26:16 +02:00
for ( const auto & eq_tag : eq_tags )
soe_eq_tags . push_back ( eq_tag ) ;
2017-08-24 15:35:10 +02:00
2019-11-18 17:13:49 +01:00
int n = static_only_equations . size ( ) ;
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 ) ;
2017-08-24 15:35:10 +02:00
static_only_equations_equation_tags . push_back ( soe_eq_tags ) ;
2019-11-18 17:13:49 +01:00
for ( auto & it : soe_eq_tags )
static_only_equation_tags_xref . emplace ( it , n ) ;
2013-04-11 17:07:39 +02:00
}
size_t
DynamicModel : : staticOnlyEquationsNbr ( ) const
{
return static_only_equations . size ( ) ;
}
size_t
DynamicModel : : dynamicOnlyEquationsNbr ( ) const
{
set < int > eqs ;
2018-06-04 12:26:16 +02:00
for ( const auto & equation_tag : equation_tags )
if ( equation_tag . second . first = = " dynamic " )
eqs . insert ( equation_tag . first ) ;
2013-04-11 17:07:39 +02:00
return eqs . size ( ) ;
}
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
2018-06-04 12:26:16 +02:00
for ( const auto & equation_tag : equation_tags )
buffer < < " " < < equation_tag . first + 1
< < equation_tag . second . first
2019-10-07 15:57:19 +02:00
< < equation_tag . second . second < < endl ;
2013-09-17 15:11:57 +02:00
2018-09-25 19:15:22 +02:00
ExprNodeOutputType buffer_type = block ? ExprNodeOutputType : : matlabDynamicModelSparse : 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
{
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
for ( const auto & equation_tag : equation_tags )
if ( equation_tag . first = = eq )
eqtags . push_back ( equation_tag . second ) ;
if ( ! eqtags . empty ( ) )
{
2019-04-03 16:32:52 +02:00
output < < R " (, " tags " : {) " ;
2018-09-18 14:50:31 +02:00
int i = 0 ;
for ( vector < pair < string , string > > : : const_iterator it = eqtags . begin ( ) ; it ! = eqtags . end ( ) ; it + + , i + + )
{
if ( i ! = 0 )
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ( " ) " << it->first << R " ( " : " ) " << it->second << R " ( " ) " ;
2018-09-18 14:50:31 +02:00
}
output < < " } " ;
eqtags . clear ( ) ;
}
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 ;
int ii = 0 ;
int end_idx_map = static_cast < int > ( variableMapping . size ( ) - 1 ) ;
for ( const auto & variable : variableMapping )
{
output < < R " ({ " name " : " ) " << symbol_table.getName(variable.first) << R " ( " , " equations " :[) " ;
int it = 0 ;
int end_idx_eq = static_cast < int > ( variable . second . size ( ) ) - 1 ;
for ( const auto & equation : variable . second )
for ( const auto & equation_tag : equation_tags )
if ( equation_tag . first = = equation & & equation_tag . second . first = = " name " )
output < < R " ( " ) " << equation_tag.second.second << (it++ == end_idx_eq ? R " ( " ]) " : R " ( " , ) " );
output < < ( ii + + = = end_idx_map ? R " (}) " : R " (},) " ) < < endl ;
}
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
{
2018-06-04 15:03:26 +02:00
for ( auto it = xrefs . begin ( ) ;
2017-10-13 16:21:13 +02:00
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 " : [) " ;
2018-06-04 15:03:26 +02:00
for ( auto it1 = it - > second . begin ( ) ;
2017-03-10 17:23:35 +01:00
it1 ! = it - > second . end ( ) ; it1 + + )
{
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 " : [) " ;
2017-10-13 16:21:13 +02: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 ,
nfwrd = 0 ,
npred = 0 ,
nboth = 0 ;
for ( int endoID = 0 ; endoID < symbol_table . endo_nbr ( ) ; endoID + + )
{
if ( endoID ! = 0 )
output < < " , " ;
output < < " [ " ;
int sstatic = 1 ,
sfwrd = 0 ,
spred = 0 ,
sboth = 0 ;
// 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 ;
nfwrd + = sfwrd ;
npred + = spred ;
nboth + = sboth ;
output < < " ] " ;
}
output < < " ], "
2019-04-03 16:32:52 +02:00
< < R " ( " nstatic " : ) " < < nstatic < < " , "
< < R " ( " nfwrd " : ) " < < nfwrd < < " , "
< < R " ( " npred " : ) " < < npred < < " , "
< < R " ( " nboth " : ) " < < nboth < < " , "
< < R " ( " nsfwrd " : ) " < < nfwrd + nboth < < " , "
< < R " ( " nspred " : ) " < < npred + nboth < < " , "
< < R " ( " ndynamic " : ) " < < npred + nboth + nfwrd < < 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
{
ostringstream model_local_vars_output ; // Used for storing model local vars
2019-04-18 17:07:55 +02:00
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
writeJsonModelLocalVariables ( model_local_vars_output , tef_terms ) ;
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 " ( " ) "
< < R " (, " shift ) " << (i > 1 ? to_string(j) : " " ) << R " ( " : ) " < < getLagByDerivID ( vidx [ j ] ) ;
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-04-18 17:07:55 +02:00
d_output [ i ] < < " ]} " ;
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 ;
ostringstream model_local_vars_output ; // Used for storing model local vars
ostringstream model_output ; // Used for storing model temp vars and equations
2019-08-22 15:55:00 +02:00
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
2019-08-22 17:00:36 +02:00
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 ;
writeJsonModelLocalVariables ( model_local_vars_output , tef_terms ) ;
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 ;
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 ;
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 )
{
for ( auto & equation : equations )
equation = dynamic_cast < BinaryOpNode * > ( equation - > substituteVarExpectation ( subst_table ) ) ;
}