2008-02-03 11:28:36 +01:00
/*
2011-01-13 18:08:26 +01:00
* Copyright ( C ) 2003 - 2011 Dynare Team
2008-02-03 11:28:36 +01:00
*
* This file is part of Dynare .
*
* Dynare is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Dynare is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Dynare . If not , see < http : //www.gnu.org/licenses/>.
*/
# ifndef _MODELTREE_HH
# define _MODELTREE_HH
using namespace std ;
# include <string>
# include <vector>
2009-09-30 17:10:31 +02:00
# include <deque>
2008-02-03 11:28:36 +01:00
# include <map>
# include <ostream>
# include "DataTree.hh"
2010-09-16 19:18:45 +02:00
//! Vector describing equations: BlockSimulationType, if BlockSimulationType == EVALUATE_s then a expr_t on the new normalized equation
typedef vector < pair < EquationType , expr_t > > equation_type_and_normalized_equation_t ;
2009-12-16 14:21:31 +01:00
//! Vector describing variables: max_lag in the block, max_lead in the block
2010-09-16 19:00:48 +02:00
typedef vector < pair < int , int > > lag_lead_vector_t ;
2009-12-16 14:21:31 +01:00
//! for each block contains pair< pair<Simulation_Type, first_equation>, pair < Block_Size, Recursive_part_Size > >
2010-09-16 19:00:48 +02:00
typedef vector < pair < pair < BlockSimulationType , int > , pair < int , int > > > block_type_firstequation_size_mfs_t ;
2009-12-16 14:21:31 +01:00
2010-09-16 19:18:45 +02:00
//! for a block contains derivatives pair< pair<block_equation_number, block_variable_number> , pair<lead_lag, expr_t> >
typedef vector < pair < pair < int , int > , pair < int , expr_t > > > block_derivatives_equation_variable_laglead_nodeid_t ;
2009-12-16 14:21:31 +01:00
//! for all blocks derivatives description
2010-09-16 19:00:48 +02:00
typedef vector < block_derivatives_equation_variable_laglead_nodeid_t > blocks_derivatives_t ;
2009-12-16 14:21:31 +01:00
2010-10-15 19:05:16 +02:00
//! for all trends
typedef map < int , expr_t > trend_symbols_map_t ;
2009-04-14 16:39:53 +02:00
//! Shared code for static and dynamic models
2008-02-03 11:28:36 +01:00
class ModelTree : public DataTree
{
2009-12-16 14:21:31 +01:00
friend class DynamicModel ;
friend class StaticModel ;
2009-04-14 16:39:53 +02:00
protected :
2009-09-30 17:10:31 +02:00
//! Stores declared and generated auxiliary equations
2008-02-03 11:28:36 +01:00
vector < BinaryOpNode * > equations ;
2009-09-30 17:10:31 +02:00
//! Only stores generated auxiliary equations, in an order meaningful for evaluation
deque < BinaryOpNode * > aux_equations ;
2009-09-02 16:37:59 +02:00
//! Stores equation tags
vector < pair < int , pair < string , string > > > equation_tags ;
2009-05-12 22:32:27 +02:00
//! Number of non-zero derivatives
int NNZDerivatives [ 3 ] ;
2010-09-16 19:18:45 +02:00
typedef map < pair < int , int > , expr_t > first_derivatives_t ;
2008-02-03 11:28:36 +01:00
//! First order derivatives
/*! First index is equation number, second is variable w.r. to which is computed the derivative.
Only non - null derivatives are stored in the map .
2009-04-17 18:26:23 +02:00
Variable indices are those of the getDerivID ( ) method .
2008-02-03 11:28:36 +01:00
*/
2010-09-16 19:00:48 +02:00
first_derivatives_t first_derivatives ;
2008-02-03 11:28:36 +01:00
2010-09-16 19:18:45 +02:00
typedef map < pair < int , pair < int , int > > , expr_t > second_derivatives_t ;
2008-02-03 11:28:36 +01:00
//! Second order derivatives
/*! First index is equation number, second and third are variables w.r. to which is computed the derivative.
Only non - null derivatives are stored in the map .
Contains only second order derivatives where var1 > = var2 ( for obvious symmetry reasons ) .
2009-04-17 18:26:23 +02:00
Variable indices are those of the getDerivID ( ) method .
2008-02-03 11:28:36 +01:00
*/
2010-09-16 19:00:48 +02:00
second_derivatives_t second_derivatives ;
2008-02-03 11:28:36 +01:00
2010-09-16 19:18:45 +02:00
typedef map < pair < int , pair < int , pair < int , int > > > , expr_t > third_derivatives_t ;
2008-02-03 11:28:36 +01:00
//! Third order derivatives
/*! First index is equation number, second, third and fourth are variables w.r. to which is computed the derivative.
Only non - null derivatives are stored in the map .
Contains only third order derivatives where var1 > = var2 > = var3 ( for obvious symmetry reasons ) .
2009-04-17 18:26:23 +02:00
Variable indices are those of the getDerivID ( ) method .
2008-02-03 11:28:36 +01:00
*/
2010-09-16 19:00:48 +02:00
third_derivatives_t third_derivatives ;
2008-02-03 11:28:36 +01:00
//! Temporary terms (those which will be noted Txxxx)
2010-09-16 19:00:48 +02:00
temporary_terms_t temporary_terms ;
2010-10-15 19:05:16 +02:00
//! Trend variables and their growth factors
trend_symbols_map_t trend_symbols_map ;
//! Nonstationary variables and their deflators
trend_symbols_map_t nonstationary_symbols_map ;
2008-02-03 11:28:36 +01:00
2011-06-22 11:56:07 +02:00
//! vector of block reordered variables and equations
vector < int > equation_reordered , variable_reordered , inv_equation_reordered , inv_variable_reordered ;
//! the file containing the model and the derivatives code
ofstream code_file ;
2009-04-20 12:48:54 +02:00
//! Computes 1st derivatives
/*! \param vars the derivation IDs w.r. to which compute the derivatives */
void computeJacobian ( const set < int > & vars ) ;
//! Computes 2nd derivatives
/*! \param vars the derivation IDs w.r. to which derive the 1st derivatives */
void computeHessian ( const set < int > & vars ) ;
//! Computes 3rd derivatives
/*! \param vars the derivation IDs w.r. to which derive the 2nd derivatives */
void computeThirdDerivatives ( const set < int > & vars ) ;
2008-02-03 11:28:36 +01:00
//! Write derivative of an equation w.r. to a variable
2010-09-16 19:00:48 +02:00
void writeDerivative ( ostream & output , int eq , int symb_id , int lag , ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const ;
2009-04-20 12:48:54 +02:00
//! Computes temporary terms (for all equations and derivatives)
2009-07-07 16:20:48 +02:00
void computeTemporaryTerms ( bool is_matlab ) ;
2008-02-03 11:28:36 +01:00
//! Writes temporary terms
2011-04-12 16:41:29 +02:00
void writeTemporaryTerms ( const temporary_terms_t & tt , ostream & output , ExprNodeOutputType output_type , deriv_node_temp_terms_t & tef_terms ) const ;
2010-01-22 11:03:29 +01:00
//! Compiles temporary terms
2010-07-23 11:20:24 +02:00
void compileTemporaryTerms ( ostream & code_file , unsigned int & instruction_number , const temporary_terms_t & tt , map_idx_t map_idx , bool dynamic , bool steady_dynamic ) const ;
2010-01-22 11:03:29 +01:00
//! Adds informations for simulation in a binary file
void Write_Inf_To_Bin_File ( const string & basename , int & u_count_int , bool & file_open , bool is_two_boundaries , int block_mfs ) const ;
2008-02-03 11:28:36 +01:00
//! Writes model local variables
/*! No temporary term is used in the output, so that local parameters declarations can be safely put before temporary terms declaration in the output files */
2011-04-12 16:41:29 +02:00
void writeModelLocalVariables ( ostream & output , ExprNodeOutputType output_type , deriv_node_temp_terms_t & tef_terms ) const ;
2008-02-03 11:28:36 +01:00
//! Writes model equations
void writeModelEquations ( ostream & output , ExprNodeOutputType output_type ) const ;
2010-01-22 11:03:29 +01:00
//! Compiles model equations
2010-07-23 11:20:24 +02:00
void compileModelEquations ( ostream & code_file , unsigned int & instruction_number , const temporary_terms_t & tt , const map_idx_t & map_idx , bool dynamic , bool steady_dynamic ) const ;
2008-02-03 11:28:36 +01:00
2009-04-30 15:14:33 +02:00
//! Writes LaTeX model file
void writeLatexModelFile ( const string & filename , ExprNodeOutputType output_type ) const ;
2009-12-16 14:21:31 +01:00
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is equation number, second index is endogenous type specific ID */
2010-09-16 19:00:48 +02:00
typedef map < pair < int , int > , double > jacob_map_t ;
2009-12-16 14:21:31 +01:00
//! Sparse matrix of double to store the values of the Jacobian
/*! First index is lag, second index is equation number, third index is endogenous type specific ID */
2010-09-16 19:18:45 +02:00
typedef map < pair < int , pair < int , int > > , expr_t > dynamic_jacob_map_t ;
2009-12-16 14:21:31 +01:00
//! Normalization of equations
/*! Maps endogenous type specific IDs to equation numbers */
vector < int > endo2eq ;
//! number of equation in the prologue and in the epilogue
unsigned int epilogue , prologue ;
//! for each block contains pair< max_lag, max_lead>
2010-09-16 19:00:48 +02:00
lag_lead_vector_t block_lag_lead ;
2009-12-16 14:21:31 +01:00
//! Compute the matching between endogenous and variable using the jacobian contemporaneous_jacobian
2009-12-21 11:29:21 +01:00
/*!
\ param contemporaneous_jacobian Jacobian used as an incidence matrix : all elements declared in the map ( even if they are zero ) , are used as vertices of the incidence matrix
\ return True if a complete normalization has been achieved
*/
2010-09-16 19:00:48 +02:00
bool computeNormalization ( const jacob_map_t & contemporaneous_jacobian , bool verbose ) ;
2009-12-21 11:29:21 +01:00
2009-12-16 14:21:31 +01:00
//! Try to compute the matching between endogenous and variable using a decreasing cutoff
2009-12-21 11:29:21 +01:00
/*!
Applied to the jacobian contemporaneous_jacobian and stop when a matching is found .
If no matching is found using a strictly positive cutoff , then a zero cutoff is applied ( i . e . use a symbolic normalization ) ; in that case , the method adds zeros in the jacobian matrices to reflect all the edges in the symbolic incidence matrix .
If no matching is found with a zero cutoff close to zero an error message is printout .
*/
2010-09-16 19:00:48 +02:00
void computeNonSingularNormalization ( jacob_map_t & contemporaneous_jacobian , double cutoff , jacob_map_t & static_jacobian , dynamic_jacob_map_t & dynamic_jacobian ) ;
2009-12-21 11:29:21 +01:00
2009-12-16 14:21:31 +01:00
//! Try to normalized each unnormalized equation (matched endogenous variable only on the LHS)
void computeNormalizedEquations ( multimap < int , int > & endo2eqs ) const ;
//! Evaluate the jacobian and suppress all the elements below the cutoff
2010-09-16 19:00:48 +02:00
void evaluateAndReduceJacobian ( const eval_context_t & eval_context , jacob_map_t & contemporaneous_jacobian , jacob_map_t & static_jacobian , dynamic_jacob_map_t & dynamic_jacobian , double cutoff , bool verbose ) ;
2009-12-16 14:21:31 +01:00
//! Search the equations and variables belonging to the prologue and the epilogue of the model
2010-09-16 19:00:48 +02:00
void computePrologueAndEpilogue ( const jacob_map_t & static_jacobian , vector < int > & equation_reordered , vector < int > & variable_reordered ) ;
2009-12-16 14:21:31 +01:00
//! Determine the type of each equation of model and try to normalized the unnormalized equation using computeNormalizedEquations
2010-09-16 19:18:45 +02:00
equation_type_and_normalized_equation_t equationTypeDetermination ( const map < pair < int , pair < int , int > > , expr_t > & first_order_endo_derivatives , const vector < int > & Index_Var_IM , const vector < int > & Index_Equ_IM , int mfs ) const ;
2009-12-16 14:21:31 +01:00
//! Compute the block decomposition and for a non-recusive block find the minimum feedback set
2010-07-23 11:20:24 +02:00
void computeBlockDecompositionAndFeedbackVariablesForEachBlock ( const jacob_map_t & static_jacobian , const dynamic_jacob_map_t & dynamic_jacobian , vector < int > & equation_reordered , vector < int > & variable_reordered , vector < pair < int , int > > & blocks , const equation_type_and_normalized_equation_t & Equation_Type , bool verbose_ , bool select_feedback_variable , int mfs , vector < int > & inv_equation_reordered , vector < int > & inv_variable_reordered , lag_lead_vector_t & equation_lag_lead , lag_lead_vector_t & variable_lag_lead_t , vector < unsigned int > & n_static , vector < unsigned int > & n_forward , vector < unsigned int > & n_backward , vector < unsigned int > & n_mixed ) const ;
2009-12-16 14:21:31 +01:00
//! Reduce the number of block merging the same type equation in the prologue and the epilogue and determine the type of each block
2011-02-04 16:25:38 +01:00
block_type_firstequation_size_mfs_t reduceBlocksAndTypeDetermination ( const dynamic_jacob_map_t & dynamic_jacobian , vector < pair < int , int > > & blocks , const equation_type_and_normalized_equation_t & Equation_Type , const vector < int > & variable_reordered , const vector < int > & equation_reordered , vector < unsigned int > & n_static , vector < unsigned int > & n_forward , vector < unsigned int > & n_backward , vector < unsigned int > & n_mixed , vector < pair < pair < int , int > , pair < int , int > > > & block_col_type ) ;
2009-12-16 14:21:31 +01:00
//! Determine the maximum number of lead and lag for the endogenous variable in a bloc
2010-09-16 19:00:48 +02:00
void getVariableLeadLagByBlock ( const dynamic_jacob_map_t & dynamic_jacobian , const vector < int > & components_set , int nb_blck_sim , lag_lead_vector_t & equation_lead_lag , lag_lead_vector_t & variable_lead_lag , const vector < int > & equation_reordered , const vector < int > & variable_reordered ) const ;
2009-12-16 14:21:31 +01:00
//! Print an abstract of the block structure of the model
2010-09-16 17:51:50 +02:00
void printBlockDecomposition ( const vector < pair < int , int > > & blocks ) const ;
2009-12-16 14:21:31 +01:00
//! Determine for each block if it is linear or not
2010-09-16 19:00:48 +02:00
vector < bool > BlockLinear ( const blocks_derivatives_t & blocks_derivatives , const vector < int > & variable_reordered ) const ;
2009-12-16 14:21:31 +01:00
//! Determine the simulation type of each block
virtual BlockSimulationType getBlockSimulationType ( int block_number ) const = 0 ;
//! Return the number of blocks
virtual unsigned int getNbBlocks ( ) const = 0 ;
//! Return the first equation number of a block
virtual unsigned int getBlockFirstEquation ( int block_number ) const = 0 ;
//! Return the size of the block block_number
virtual unsigned int getBlockSize ( int block_number ) const = 0 ;
2010-07-23 11:20:24 +02:00
//! Return the number of exogenous variable in the block block_number
virtual unsigned int getBlockExoSize ( int block_number ) const = 0 ;
//! Return the number of colums in the jacobian matrix for exogenous variable in the block block_number
virtual unsigned int getBlockExoColSize ( int block_number ) const = 0 ;
2009-12-16 14:21:31 +01:00
//! Return the number of feedback variable of the block block_number
virtual unsigned int getBlockMfs ( int block_number ) const = 0 ;
//! Return the maximum lag in a block
virtual unsigned int getBlockMaxLag ( int block_number ) const = 0 ;
//! Return the maximum lead in a block
virtual unsigned int getBlockMaxLead ( int block_number ) const = 0 ;
2011-06-18 17:53:50 +02:00
inline void setBlockLeadLag ( int block , int max_lag , int max_lead )
{
block_lag_lead [ block ] = make_pair ( max_lag , max_lead ) ;
} ;
2009-12-16 14:21:31 +01:00
//! Return the type of equation (equation_number) belonging to the block block_number
virtual EquationType getBlockEquationType ( int block_number , int equation_number ) const = 0 ;
//! Return true if the equation has been normalized
virtual bool isBlockEquationRenormalized ( int block_number , int equation_number ) const = 0 ;
2010-09-16 19:18:45 +02:00
//! Return the expr_t of the equation equation_number belonging to the block block_number
virtual expr_t getBlockEquationExpr ( int block_number , int equation_number ) const = 0 ;
//! Return the expr_t of the renormalized equation equation_number belonging to the block block_number
virtual expr_t getBlockEquationRenormalizedExpr ( int block_number , int equation_number ) const = 0 ;
2009-12-16 14:21:31 +01:00
//! Return the original number of equation equation_number belonging to the block block_number
virtual int getBlockEquationID ( int block_number , int equation_number ) const = 0 ;
//! Return the original number of variable variable_number belonging to the block block_number
virtual int getBlockVariableID ( int block_number , int variable_number ) const = 0 ;
2010-07-23 11:20:24 +02:00
//! Return the original number of the exogenous variable varexo_number belonging to the block block_number
virtual int getBlockVariableExoID ( int block_number , int variable_number ) const = 0 ;
2009-12-16 14:21:31 +01:00
//! Return the position of equation_number in the block number belonging to the block block_number
virtual int getBlockInitialEquationID ( int block_number , int equation_number ) const = 0 ;
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int getBlockInitialVariableID ( int block_number , int variable_number ) const = 0 ;
2010-07-23 11:20:24 +02:00
//! Return the position of variable_number in the block number belonging to the block block_number
virtual int getBlockInitialExogenousID ( int block_number , int variable_number ) const = 0 ;
//! Return the position of the deterministic exogenous variable_number in the block number belonging to the block block_number
virtual int getBlockInitialDetExogenousID ( int block_number , int variable_number ) const = 0 ;
//! Return the position of the other endogenous variable_number in the block number belonging to the block block_number
virtual int getBlockInitialOtherEndogenousID ( int block_number , int variable_number ) const = 0 ;
2011-06-22 11:56:07 +02:00
//! Initialize equation_reordered & variable_reordered
void initializeVariablesAndEquations ( ) ;
2008-02-03 11:28:36 +01:00
public :
2010-02-22 17:33:38 +01:00
ModelTree ( SymbolTable & symbol_table_arg , NumericalConstants & num_constants_arg , ExternalFunctionsTable & external_functions_table_arg ) ;
2011-06-22 11:56:07 +02:00
//! Absolute value under which a number is considered to be zero
double cutoff ;
//! Compute the minimum feedback set
/*! 0 : all endogenous variables are considered as feedback variables
1 : the variables belonging to non normalized equation are considered as feedback variables
2 : the variables belonging to a non linear equation are considered as feedback variables
3 : the variables belonging to a non normalizable non linear equation are considered as feedback variables
default value = 0 */
int mfs ;
2008-02-03 11:28:36 +01:00
//! Declare a node as an equation of the model
2010-09-16 19:18:45 +02:00
void addEquation ( expr_t eq ) ;
2009-09-02 16:37:59 +02:00
//! Adds tags to equation number i
void addEquationTags ( int i , const string & key , const string & value ) ;
2009-09-30 17:10:31 +02:00
//! Declare a node as an auxiliary equation of the model, adding it at the end of the list of auxiliary equations
2010-09-16 19:18:45 +02:00
void addAuxEquation ( expr_t eq ) ;
2008-10-17 19:21:22 +02:00
//! Returns the number of equations in the model
2008-02-03 11:28:36 +01:00
int equation_number ( ) const ;
2010-10-15 19:05:16 +02:00
//! Adds a trend variable with its growth factor
void addTrendVariables ( vector < int > trend_vars , expr_t growth_factor ) throw ( TrendException ) ;
//! Adds a nonstationary variable with its deflator
void addNonstationaryVariables ( vector < int > nonstationary_vars , expr_t deflator ) throw ( TrendException ) ;
2011-06-22 11:56:07 +02:00
void set_cutoff_to_zero ( ) ;
2011-08-19 15:05:57 +02:00
//! Helper for writing the Jacobian elements in MATLAB and C
/*! Writes either (i+1,j+1) or [i+j*no_eq] */
void jacobianHelper ( ostream & output , int eq_nb , int col_nb , ExprNodeOutputType output_type ) const ;
//! Helper for writing the sparse Hessian or third derivatives in MATLAB and C
/*! If order=2, writes either v2(i+1,j+1) or v2[i+j*NNZDerivatives[1]]
If order = 3 , writes either v3 ( i + 1 , j + 1 ) or v3 [ i + j * NNZDerivatives [ 2 ] ] */
void sparseHelper ( int order , ostream & output , int row_nb , int col_nb , ExprNodeOutputType output_type ) const ;
2009-12-16 18:13:23 +01:00
inline static std : : string
c_Equation_Type ( int type )
{
char c_Equation_Type [ 4 ] [ 13 ] =
{
" E_UNKNOWN " ,
" E_EVALUATE " ,
" E_EVALUATE_S " ,
" E_SOLVE "
} ;
return ( c_Equation_Type [ type ] ) ;
} ;
inline static std : : string
BlockType0 ( BlockType type )
{
switch ( type )
{
case SIMULTANS :
return ( " SIMULTANEOUS TIME SEPARABLE " ) ;
break ;
case PROLOGUE :
return ( " PROLOGUE " ) ;
break ;
case EPILOGUE :
return ( " EPILOGUE " ) ;
break ;
case SIMULTAN :
return ( " SIMULTANEOUS TIME UNSEPARABLE " ) ;
break ;
default :
return ( " UNKNOWN " ) ;
break ;
}
} ;
inline static std : : string
BlockSim ( int type )
{
switch ( type )
{
case EVALUATE_FORWARD :
return ( " EVALUATE FORWARD " ) ;
break ;
case EVALUATE_BACKWARD :
return ( " EVALUATE BACKWARD " ) ;
break ;
case SOLVE_FORWARD_SIMPLE :
return ( " SOLVE FORWARD SIMPLE " ) ;
break ;
case SOLVE_BACKWARD_SIMPLE :
return ( " SOLVE BACKWARD SIMPLE " ) ;
break ;
case SOLVE_TWO_BOUNDARIES_SIMPLE :
return ( " SOLVE TWO BOUNDARIES SIMPLE " ) ;
break ;
case SOLVE_FORWARD_COMPLETE :
return ( " SOLVE FORWARD COMPLETE " ) ;
break ;
case SOLVE_BACKWARD_COMPLETE :
return ( " SOLVE BACKWARD COMPLETE " ) ;
break ;
case SOLVE_TWO_BOUNDARIES_COMPLETE :
return ( " SOLVE TWO BOUNDARIES COMPLETE " ) ;
break ;
default :
return ( " UNKNOWN " ) ;
break ;
}
} ;
2008-02-03 11:28:36 +01:00
} ;
# endif