2008-02-03 11:28:36 +01:00
/*
2010-02-22 17:33:38 +01:00
* Copyright ( C ) 2007 - 2010 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/>.
*/
# include <iostream>
# include <iterator>
# include <algorithm>
2009-07-13 11:13:42 +02:00
// For select1st()
# ifdef __GNUC__
# include <ext / functional>
using namespace __gnu_cxx ;
# endif
2009-07-10 18:42:08 +02:00
2009-04-28 18:21:39 +02:00
# include <cassert>
2008-02-19 15:35:59 +01:00
# include <cmath>
2008-02-03 11:28:36 +01:00
# include "ExprNode.hh"
# include "DataTree.hh"
2009-10-29 18:16:10 +01:00
# include "ModFile.hh"
2008-02-03 11:28:36 +01:00
2009-09-30 17:10:31 +02:00
ExprNode : : ExprNode ( DataTree & datatree_arg ) : datatree ( datatree_arg ) , preparedForDerivation ( false )
2008-02-03 11:28:36 +01:00
{
// Add myself to datatree
datatree . node_list . push_back ( this ) ;
// Set my index and increment counter
idx = datatree . node_counter + + ;
}
ExprNode : : ~ ExprNode ( )
{
}
NodeID
2009-04-17 18:26:23 +02:00
ExprNode : : getDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2009-09-30 17:10:31 +02:00
if ( ! preparedForDerivation )
prepareForDerivation ( ) ;
2009-10-02 19:02:35 +02:00
2008-02-03 11:28:36 +01:00
// Return zero if derivative is necessarily null (using symbolic a priori)
2009-04-17 18:26:23 +02:00
set < int > : : const_iterator it = non_null_derivatives . find ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
if ( it = = non_null_derivatives . end ( ) )
return datatree . Zero ;
2009-10-02 19:02:35 +02:00
2008-02-03 11:28:36 +01:00
// If derivative is stored in cache, use the cached value, otherwise compute it (and cache it)
2009-04-17 18:26:23 +02:00
map < int , NodeID > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
2009-04-17 18:26:23 +02:00
NodeID d = computeDerivative ( deriv_id ) ;
derivatives [ deriv_id ] = d ;
2008-02-03 11:28:36 +01:00
return d ;
}
}
2009-06-05 16:45:23 +02:00
int
ExprNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
// For a constant, a variable, or a unary op, the precedence is maximal
return 100 ;
}
2009-06-05 16:45:23 +02:00
2008-02-03 11:28:36 +01:00
int
ExprNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a terminal node, the cost is null
return 0 ;
}
2008-02-03 11:28:36 +01:00
2009-07-10 18:42:08 +02:00
void
ExprNode : : collectEndogenous ( set < pair < int , int > > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eEndogenous , symb_ids ) ;
2009-12-16 18:13:23 +01:00
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
2009-07-10 18:42:08 +02:00
result . insert ( make_pair ( datatree . symbol_table . getTypeSpecificID ( it - > first ) , it - > second ) ) ;
}
void
ExprNode : : collectExogenous ( set < pair < int , int > > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eExogenous , symb_ids ) ;
2009-12-16 18:13:23 +01:00
for ( set < pair < int , int > > : : const_iterator it = symb_ids . begin ( ) ;
it ! = symb_ids . end ( ) ; it + + )
2009-07-10 18:42:08 +02:00
result . insert ( make_pair ( datatree . symbol_table . getTypeSpecificID ( it - > first ) , it - > second ) ) ;
}
void
ExprNode : : collectModelLocalVariables ( set < int > & result ) const
{
set < pair < int , int > > symb_ids ;
collectVariables ( eModelLocalVariable , symb_ids ) ;
transform ( symb_ids . begin ( ) , symb_ids . end ( ) , inserter ( result , result . begin ( ) ) ,
2009-07-13 11:13:42 +02:00
select1st < pair < int , int > > ( ) ) ;
2009-07-10 18:42:08 +02:00
}
2008-02-03 11:28:36 +01:00
void
ExprNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// Nothing to do for a terminal node
}
2008-02-03 11:28:36 +01:00
void
ExprNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
2009-01-02 14:00:43 +01:00
map < NodeID , pair < int , int > > & first_occurence ,
2008-02-03 11:28:36 +01:00
int Curr_block ,
2009-12-16 14:21:31 +01:00
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
2009-12-16 18:13:23 +01:00
{
// Nothing to do for a terminal node
}
2008-02-03 11:28:36 +01:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
ExprNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
return ( make_pair ( 0 , ( NodeID ) NULL ) ) ;
}
2009-08-25 11:43:01 +02:00
2008-02-03 11:28:36 +01:00
void
2010-03-09 12:16:32 +01:00
ExprNode : : writeOutput ( ostream & output ) const
2008-02-03 11:28:36 +01:00
{
writeOutput ( output , oMatlabOutsideModel , temporary_terms_type ( ) ) ;
}
2010-03-09 12:16:32 +01:00
void
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ) const
{
writeOutput ( output , output_type , temporary_terms_type ( ) ) ;
}
2010-03-04 16:40:07 +01:00
void
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
{
deriv_node_temp_terms_type tef_terms ;
writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
void
ExprNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
// Nothing to do
}
2009-09-30 17:10:31 +02:00
VariableNode *
2009-10-07 16:07:13 +02:00
ExprNode : : createEndoLeadAuxiliaryVarForMyself ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
int n = maxEndoLead ( ) ;
assert ( n > = 2 ) ;
subst_table_t : : const_iterator it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
NodeID substexpr = decreaseLeadsLags ( n - 1 ) ;
int lag = n - 2 ;
// Each iteration tries to create an auxvar such that auxvar(+1)=expr(-lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to expr(-lag-1) (resp. expr(-lag))
2009-12-16 18:13:23 +01:00
while ( lag > = 0 )
2009-09-30 17:10:31 +02:00
{
NodeID orig_expr = decreaseLeadsLags ( lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
2009-10-07 16:07:13 +02:00
int symb_id = datatree . symbol_table . addEndoLeadAuxiliaryVar ( orig_expr - > idx ) ;
2009-09-30 17:10:31 +02:00
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( symb_id , + 1 ) ;
assert ( dynamic_cast < VariableNode * > ( substexpr ) ! = NULL ) ;
subst_table [ orig_expr ] = dynamic_cast < VariableNode * > ( substexpr ) ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
lag - - ;
}
return dynamic_cast < VariableNode * > ( substexpr ) ;
}
2009-10-07 18:34:42 +02:00
VariableNode *
ExprNode : : createExoLeadAuxiliaryVarForMyself ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
int n = maxExoLead ( ) ;
assert ( n > = 1 ) ;
subst_table_t : : const_iterator it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
NodeID substexpr = decreaseLeadsLags ( n ) ;
int lag = n - 1 ;
// Each iteration tries to create an auxvar such that auxvar(+1)=expr(-lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to expr(-lag-1) (resp. expr(-lag))
2009-12-16 18:13:23 +01:00
while ( lag > = 0 )
2009-10-07 18:34:42 +02:00
{
NodeID orig_expr = decreaseLeadsLags ( lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
int symb_id = datatree . symbol_table . addExoLeadAuxiliaryVar ( orig_expr - > idx ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( symb_id , + 1 ) ;
assert ( dynamic_cast < VariableNode * > ( substexpr ) ! = NULL ) ;
subst_table [ orig_expr ] = dynamic_cast < VariableNode * > ( substexpr ) ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
lag - - ;
}
return dynamic_cast < VariableNode * > ( substexpr ) ;
}
2010-04-16 16:54:55 +02:00
bool
ExprNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
ExprNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2008-02-03 11:28:36 +01:00
NumConstNode : : NumConstNode ( DataTree & datatree_arg , int id_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
id ( id_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the num const map
datatree . num_const_node_map [ id ] = this ;
2009-09-30 17:10:31 +02:00
}
2008-02-03 11:28:36 +01:00
2009-09-30 17:10:31 +02:00
void
NumConstNode : : prepareForDerivation ( )
{
preparedForDerivation = true ;
2008-02-03 11:28:36 +01:00
// All derivatives are null, so non_null_derivatives is left empty
}
NodeID
2009-04-17 18:26:23 +02:00
NumConstNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
return datatree . Zero ;
}
2008-12-24 16:49:01 +01:00
void
2009-12-16 14:21:31 +01:00
NumConstNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
NumConstNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < NumConstNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2008-02-03 11:28:36 +01:00
else
2009-12-16 18:13:23 +01:00
output < < " T " < < idx ;
else
output < < datatree . num_constants . get ( id ) ;
}
2008-02-03 11:28:36 +01:00
double
NumConstNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
2009-12-16 18:13:23 +01:00
return ( datatree . num_constants . getDouble ( id ) ) ;
2008-02-03 11:28:36 +01:00
}
void
2010-01-22 17:42:08 +01:00
NumConstNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
FLDC_ fldc ( datatree . num_constants . getDouble ( id ) ) ;
fldc . write ( CompileCode ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
NumConstNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
NumConstNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
return ( make_pair ( 0 , datatree . AddNumConstant ( datatree . num_constants . get ( id ) ) ) ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
2009-07-06 11:34:21 +02:00
NumConstNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2008-11-14 17:07:47 +01:00
{
2009-06-05 16:45:23 +02:00
return datatree . Zero ;
2008-11-14 17:07:47 +01:00
}
2009-04-14 16:39:53 +02:00
NodeID
NumConstNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
return static_datatree . AddNumConstant ( datatree . num_constants . get ( id ) ) ;
}
2009-04-14 16:39:53 +02:00
2009-09-30 17:10:31 +02:00
int
NumConstNode : : maxEndoLead ( ) const
{
return 0 ;
}
2008-11-14 17:07:47 +01:00
2009-10-07 18:34:42 +02:00
int
NumConstNode : : maxExoLead ( ) const
{
return 0 ;
}
2009-09-30 17:10:31 +02:00
NodeID
NumConstNode : : decreaseLeadsLags ( int n ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2009-11-07 19:37:11 +01:00
NodeID
2009-11-09 12:03:18 +01:00
NumConstNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
return const_cast < NumConstNode * > ( this ) ;
2009-11-07 19:37:11 +01:00
}
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
NumConstNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
NodeID
2009-10-07 16:07:13 +02:00
NumConstNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
NodeID
2009-10-07 18:34:42 +02:00
NumConstNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
NodeID
NumConstNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2009-10-29 18:16:10 +01:00
NodeID
NumConstNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2009-09-30 17:10:31 +02:00
VariableNode : : VariableNode ( DataTree & datatree_arg , int symb_id_arg , int lag_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
type ( datatree . symbol_table . getType ( symb_id_arg ) ) ,
lag ( lag_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the variable map
2009-02-27 13:19:25 +01:00
datatree . variable_node_map [ make_pair ( symb_id , lag ) ] = this ;
2008-02-03 11:28:36 +01:00
2008-10-13 18:44:20 +02:00
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
2010-02-22 17:33:38 +01:00
assert ( type ! = eExternalFunction
2009-09-30 17:10:31 +02:00
& & ( lag = = 0 | | ( type ! = eModelLocalVariable & & type ! = eModFileLocalVariable ) ) ) ;
}
2010-04-16 16:54:55 +02:00
bool
NumConstNode : : isNumConstNodeEqualTo ( double value ) const
{
if ( datatree . num_constants . getDouble ( id ) = = value )
return true ;
else
return false ;
}
bool
NumConstNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2009-09-30 17:10:31 +02:00
void
VariableNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
2009-10-02 19:02:35 +02:00
2009-09-30 17:10:31 +02:00
preparedForDerivation = true ;
2008-10-13 18:44:20 +02:00
2008-02-03 11:28:36 +01:00
// Fill in non_null_derivatives
2009-06-05 16:45:23 +02:00
switch ( type )
2008-02-03 11:28:36 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
case eParameter :
2009-04-20 15:58:15 +02:00
// For a variable or a parameter, the only non-null derivative is with respect to itself
2009-10-02 19:02:35 +02:00
non_null_derivatives . insert ( datatree . getDerivID ( symb_id , lag ) ) ;
2008-02-03 11:28:36 +01:00
break ;
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
datatree . local_variables_table [ symb_id ] - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non null derivatives are those of the value of the local parameter
non_null_derivatives = datatree . local_variables_table [ symb_id ] - > non_null_derivatives ;
break ;
case eModFileLocalVariable :
// Such a variable is never derived
break ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2009-09-30 17:10:31 +02:00
cerr < < " VariableNode::prepareForDerivation: impossible case " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
}
NodeID
2009-09-30 17:10:31 +02:00
VariableNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( type )
2008-02-03 11:28:36 +01:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
2009-04-20 15:58:15 +02:00
case eParameter :
2009-09-30 17:10:31 +02:00
if ( deriv_id = = datatree . getDerivID ( symb_id , lag ) )
2008-02-03 11:28:36 +01:00
return datatree . One ;
else
return datatree . Zero ;
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
return datatree . local_variables_table [ symb_id ] - > getDerivative ( deriv_id ) ;
2008-02-03 11:28:36 +01:00
case eModFileLocalVariable :
cerr < < " ModFileLocalVariable is not derivable " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2008-02-03 11:28:36 +01:00
cerr < < " Impossible case! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2008-12-24 16:49:01 +01:00
void
2009-12-16 14:21:31 +01:00
VariableNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
VariableNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) )
{
if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " \\ bar{ " ;
output < < datatree . symbol_table . getTeXName ( symb_id ) ;
if ( output_type = = oLatexDynamicModel
& & ( type = = eEndogenous | | type = = eExogenous | | type = = eExogenousDet | | type = = eModelLocalVariable ) )
{
output < < " _{t " ;
if ( lag ! = 0 )
{
if ( lag > 0 )
output < < " + " ;
output < < lag ;
}
2009-09-11 11:16:52 +02:00
output < < " } " ;
2009-12-16 18:13:23 +01:00
}
else if ( output_type = = oLatexDynamicSteadyStateOperator )
output < < " } " ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
int i ;
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
switch ( type )
{
case eParameter :
2010-04-23 18:39:07 +02:00
if ( output_type = = oMatlabOutsideModel | | output_type = = oSteadyStateFile )
2009-12-16 18:13:23 +01:00
output < < " M_.params " < < " ( " < < tsid + 1 < < " ) " ;
else
output < < " params " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
case eModelLocalVariable :
if ( output_type = = oMatlabDynamicModelSparse | | output_type = = oMatlabStaticModelSparse | | output_type = = oMatlabDynamicModelSparseLocalTemporaryTerms )
{
output < < " ( " ;
datatree . local_variables_table [ symb_id ] - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
}
else
output < < datatree . symbol_table . getName ( symb_id ) ;
break ;
2009-06-05 16:45:23 +02:00
2010-04-23 18:39:07 +02:00
case eModFileLocalVariable :
output < < datatree . symbol_table . getName ( symb_id ) ;
break ;
2009-12-16 18:13:23 +01:00
case eEndogenous :
switch ( output_type )
{
case oMatlabDynamicModel :
case oCDynamicModel :
i = datatree . getDynJacobianCol ( datatree . getDerivID ( symb_id , lag ) ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabDynamicModelSparse :
case oMatlabDynamicModelSparseLocalTemporaryTerms :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
if ( lag > 0 )
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_+ " < < lag < < " , " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else if ( lag < 0 )
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_ " < < lag < < " , " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_, " < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " ys_( " < < tsid + 1 < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
assert ( false ) ;
}
break ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
case eExogenous :
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
switch ( output_type )
{
case oMatlabDynamicModel :
case oMatlabDynamicModelSparse :
case oMatlabDynamicModelSparseLocalTemporaryTerms :
if ( lag > 0 )
output < < " x(it_+ " < < lag < < " , " < < i < < " ) " ;
else if ( lag < 0 )
output < < " x(it_ " < < lag < < " , " < < i < < " ) " ;
else
output < < " x(it_, " < < i < < " ) " ;
break ;
case oCDynamicModel :
if ( lag = = 0 )
output < < " x[it_+ " < < i < < " *nb_row_x] " ;
else if ( lag > 0 )
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_x] " ;
else
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_x] " ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " exo_( " < < i < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
assert ( false ) ;
}
break ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
case eExogenousDet :
i = tsid + datatree . symbol_table . exo_nbr ( ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
switch ( output_type )
{
case oMatlabDynamicModel :
case oMatlabDynamicModelSparse :
case oMatlabDynamicModelSparseLocalTemporaryTerms :
if ( lag > 0 )
output < < " x(it_+ " < < lag < < " , " < < i < < " ) " ;
else if ( lag < 0 )
output < < " x(it_ " < < lag < < " , " < < i < < " ) " ;
else
output < < " x(it_, " < < i < < " ) " ;
break ;
case oCDynamicModel :
if ( lag = = 0 )
output < < " x[it_+ " < < i < < " *nb_row_xd] " ;
else if ( lag > 0 )
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_xd] " ;
else
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_xd] " ;
break ;
case oMatlabStaticModel :
case oMatlabStaticModelSparse :
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
case oMatlabOutsideModel :
assert ( lag = = 0 ) ;
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
break ;
case oMatlabDynamicSteadyStateOperator :
output < < " oo_.exo_det_steady_state( " < < tsid + 1 < < " ) " ;
break ;
2010-04-23 18:39:07 +02:00
case oSteadyStateFile :
output < < " exo_( " < < i < < " ) " ;
break ;
2009-12-16 18:13:23 +01:00
default :
assert ( false ) ;
}
break ;
2009-06-05 16:45:23 +02:00
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2009-12-16 18:13:23 +01:00
cerr < < " Impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
}
}
2008-02-03 11:28:36 +01:00
double
VariableNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
2009-02-27 13:19:25 +01:00
eval_context_type : : const_iterator it = eval_context . find ( symb_id ) ;
2008-02-03 11:28:36 +01:00
if ( it = = eval_context . end ( ) )
2009-02-27 13:19:25 +01:00
throw EvalException ( ) ;
2008-02-03 11:28:36 +01:00
return it - > second ;
}
void
2010-01-22 17:42:08 +01:00
VariableNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
if ( type = = eModelLocalVariable | | type = = eModFileLocalVariable )
datatree . local_variables_table [ symb_id ] - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
else
{
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
if ( type = = eExogenousDet )
tsid + = datatree . symbol_table . exo_nbr ( ) ;
if ( ! lhs_rhs )
{
if ( dynamic )
{
if ( steady_dynamic ) // steady state values in a dynamic model
{
FLDVS_ fldvs ( type , tsid ) ;
fldvs . write ( CompileCode ) ;
}
else
{
if ( type = = eParameter )
{
FLDV_ fldv ( type , tsid ) ;
fldv . write ( CompileCode ) ;
}
else
{
FLDV_ fldv ( type , tsid , lag ) ;
fldv . write ( CompileCode ) ;
}
}
}
else
{
FLDSV_ fldsv ( type , tsid ) ;
fldsv . write ( CompileCode ) ;
}
}
else
{
if ( dynamic )
{
if ( steady_dynamic ) // steady state values in a dynamic model
{
cerr < < " Impossible case: steady_state in rhs of equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
{
if ( type = = eParameter )
{
FSTPV_ fstpv ( type , tsid ) ;
fstpv . write ( CompileCode ) ;
}
else
{
FSTPV_ fstpv ( type , tsid , lag ) ;
fstpv . write ( CompileCode ) ;
}
}
}
else
{
FSTPSV_ fstpsv ( type , tsid ) ;
fstpsv . write ( CompileCode ) ;
}
}
}
}
2008-02-03 11:28:36 +01:00
2009-01-02 14:00:43 +01:00
void
VariableNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
2009-12-16 14:21:31 +01:00
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
2009-12-16 18:13:23 +01:00
{
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
2009-01-02 14:00:43 +01:00
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
VariableNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
if ( type = = type_arg )
result . insert ( make_pair ( symb_id , lag ) ) ;
if ( type = = eModelLocalVariable )
datatree . local_variables_table [ symb_id ] - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
VariableNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
if ( type = = eEndogenous )
{
if ( datatree . symbol_table . getTypeSpecificID ( symb_id ) = = var_endo & & lag = = 0 )
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
else
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
}
else
{
if ( type = = eParameter )
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , 0 ) ) ) ;
else
return ( make_pair ( 0 , datatree . AddVariableInternal ( symb_id , lag ) ) ) ;
}
}
2009-06-05 16:45:23 +02:00
2009-04-14 16:39:53 +02:00
NodeID
2009-09-30 17:10:31 +02:00
VariableNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-06-05 16:45:23 +02:00
switch ( type )
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
case eParameter :
2009-09-30 17:10:31 +02:00
if ( deriv_id = = datatree . getDerivID ( symb_id , lag ) )
2009-06-05 16:45:23 +02:00
return datatree . One ;
else
{
//if there is in the equation a recursive variable we could use a chaine rule derivation
2009-09-30 17:10:31 +02:00
map < int , NodeID > : : const_iterator it = recursive_variables . find ( datatree . getDerivID ( symb_id , lag ) ) ;
2009-07-06 11:34:21 +02:00
if ( it ! = recursive_variables . end ( ) )
2009-06-05 16:45:23 +02:00
{
2009-09-30 17:10:31 +02:00
map < int , NodeID > : : const_iterator it2 = derivatives . find ( deriv_id ) ;
2009-08-25 11:43:01 +02:00
if ( it2 ! = derivatives . end ( ) )
return it2 - > second ;
else
{
map < int , NodeID > recursive_vars2 ( recursive_variables ) ;
recursive_vars2 . erase ( it - > first ) ;
//NodeID c = datatree.AddNumConstant("1");
2009-09-30 17:10:31 +02:00
NodeID d = datatree . AddUMinus ( it - > second - > getChainRuleDerivative ( deriv_id , recursive_vars2 ) ) ;
2009-08-25 11:43:01 +02:00
//d = datatree.AddTimes(c, d);
2009-09-30 17:10:31 +02:00
derivatives [ deriv_id ] = d ;
2009-08-25 11:43:01 +02:00
return d ;
}
2009-06-05 16:45:23 +02:00
}
else
return datatree . Zero ;
}
case eModelLocalVariable :
2009-09-30 17:10:31 +02:00
return datatree . local_variables_table [ symb_id ] - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-06-05 16:45:23 +02:00
case eModFileLocalVariable :
cerr < < " ModFileLocalVariable is not derivable " < < endl ;
exit ( EXIT_FAILURE ) ;
2010-02-22 17:33:38 +01:00
case eExternalFunction :
2009-06-05 16:45:23 +02:00
cerr < < " Impossible case! " < < endl ;
exit ( EXIT_FAILURE ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2009-04-14 16:39:53 +02:00
}
2009-06-05 16:45:23 +02:00
NodeID
VariableNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
2010-03-16 12:23:59 +01:00
return static_datatree . AddVariable ( symb_id ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
int
VariableNode : : maxEndoLead ( ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
return max ( lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxEndoLead ( ) ;
default :
return 0 ;
}
}
2009-10-07 18:34:42 +02:00
int
VariableNode : : maxExoLead ( ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 18:34:42 +02:00
{
case eExogenous :
return max ( lag , 0 ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > maxExoLead ( ) ;
default :
return 0 ;
}
}
2009-09-30 17:10:31 +02:00
NodeID
VariableNode : : decreaseLeadsLags ( int n ) const
{
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
case eExogenous :
case eExogenousDet :
return datatree . AddVariable ( symb_id , lag - n ) ;
case eModelLocalVariable :
return datatree . local_variables_table [ symb_id ] - > decreaseLeadsLags ( n ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2009-11-07 19:37:11 +01:00
NodeID
2009-11-09 12:03:18 +01:00
VariableNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
if ( datatree . symbol_table . isPredetermined ( symb_id ) )
2009-11-07 19:37:11 +01:00
return decreaseLeadsLags ( 1 ) ;
else
return const_cast < VariableNode * > ( this ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
VariableNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
NodeID value ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
if ( lag < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
case eModelLocalVariable :
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxEndoLead ( ) < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
2009-10-07 16:07:13 +02:00
return value - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
NodeID
2009-10-07 16:07:13 +02:00
VariableNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
VariableNode * substexpr ;
subst_table_t : : const_iterator it ;
int cur_lag ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-09-30 17:10:31 +02:00
{
case eEndogenous :
if ( lag > = - 1 )
return const_cast < VariableNode * > ( this ) ;
it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
substexpr = datatree . AddVariable ( symb_id , - 1 ) ;
cur_lag = - 2 ;
// Each iteration tries to create an auxvar such that auxvar(-1)=curvar(cur_lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to curvar(cur_lag+1) (resp. curvar(cur_lag))
2009-12-16 18:13:23 +01:00
while ( cur_lag > = lag )
2009-09-30 17:10:31 +02:00
{
VariableNode * orig_expr = datatree . AddVariable ( symb_id , cur_lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
{
2009-10-07 16:07:13 +02:00
int aux_symb_id = datatree . symbol_table . addEndoLagAuxiliaryVar ( symb_id , cur_lag + 1 ) ;
2009-09-30 17:10:31 +02:00
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( aux_symb_id , - 1 ) ;
subst_table [ orig_expr ] = substexpr ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
cur_lag - - ;
}
return substexpr ;
case eModelLocalVariable :
2009-10-07 16:07:13 +02:00
return datatree . local_variables_table [ symb_id ] - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
NodeID
2009-10-07 18:34:42 +02:00
VariableNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID value ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 18:34:42 +02:00
{
case eExogenous :
if ( lag < = 0 )
return const_cast < VariableNode * > ( this ) ;
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
case eModelLocalVariable :
value = datatree . local_variables_table [ symb_id ] ;
if ( value - > maxExoLead ( ) = = 0 )
return const_cast < VariableNode * > ( this ) ;
else
return value - > substituteExoLead ( subst_table , neweqs ) ;
default :
return const_cast < VariableNode * > ( this ) ;
}
}
NodeID
VariableNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-10-07 16:07:13 +02:00
{
VariableNode * substexpr ;
subst_table_t : : const_iterator it ;
int cur_lag ;
2009-12-16 18:13:23 +01:00
switch ( type )
2009-10-07 16:07:13 +02:00
{
case eExogenous :
2009-10-07 18:34:42 +02:00
if ( lag > = 0 )
2009-10-07 16:07:13 +02:00
return const_cast < VariableNode * > ( this ) ;
it = subst_table . find ( this ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
2009-10-07 18:34:42 +02:00
substexpr = datatree . AddVariable ( symb_id , 0 ) ;
cur_lag = - 1 ;
2009-10-07 16:07:13 +02:00
2009-10-07 18:34:42 +02:00
// Each iteration tries to create an auxvar such that auxvar(-1)=curvar(cur_lag)
// At the beginning (resp. end) of each iteration, substexpr is an expression (possibly an auxvar) equivalent to curvar(cur_lag+1) (resp. curvar(cur_lag))
2009-12-16 18:13:23 +01:00
while ( cur_lag > = lag )
2009-10-07 16:07:13 +02:00
{
2009-10-07 18:34:42 +02:00
VariableNode * orig_expr = datatree . AddVariable ( symb_id , cur_lag ) ;
it = subst_table . find ( orig_expr ) ;
if ( it = = subst_table . end ( ) )
2009-10-07 16:07:13 +02:00
{
2009-10-07 18:34:42 +02:00
int aux_symb_id = datatree . symbol_table . addExoLagAuxiliaryVar ( symb_id , cur_lag + 1 ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , substexpr ) ) ) ;
substexpr = datatree . AddVariable ( aux_symb_id , - 1 ) ;
subst_table [ orig_expr ] = substexpr ;
2009-10-07 16:07:13 +02:00
}
2009-10-07 18:34:42 +02:00
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
cur_lag - - ;
2009-10-07 16:07:13 +02:00
}
2009-10-07 18:34:42 +02:00
return substexpr ;
2009-10-07 16:07:13 +02:00
case eModelLocalVariable :
2009-10-07 18:34:42 +02:00
return datatree . local_variables_table [ symb_id ] - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2009-10-29 18:16:10 +01:00
NodeID
VariableNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < VariableNode * > ( this ) ;
}
2010-04-16 16:54:55 +02:00
bool
VariableNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
VariableNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
if ( type = = type_arg & & datatree . symbol_table . getTypeSpecificID ( symb_id ) = = variable_id & & lag = = lag_arg )
return true ;
else
return false ;
}
2010-01-18 23:08:44 +01:00
UnaryOpNode : : UnaryOpNode ( DataTree & datatree_arg , UnaryOpcode op_code_arg , const NodeID arg_arg , const int expectation_information_set_arg , const string & expectation_information_set_name_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg ( arg_arg ) ,
expectation_information_set ( expectation_information_set_arg ) ,
2010-01-18 23:08:44 +01:00
expectation_information_set_name ( expectation_information_set_name_arg ) ,
2009-12-16 18:13:23 +01:00
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
// Add myself to the unary op map
datatree . unary_op_node_map [ make_pair ( arg , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
UnaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are those of the argument
non_null_derivatives = arg - > non_null_derivatives ;
}
NodeID
2009-07-06 11:34:21 +02:00
UnaryOpNode : : composeDerivatives ( NodeID darg )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
return datatree . AddUMinus ( darg ) ;
case oExp :
return datatree . AddTimes ( darg , this ) ;
case oLog :
return datatree . AddDivide ( darg , arg ) ;
case oLog10 :
t11 = datatree . AddExp ( datatree . One ) ;
t12 = datatree . AddLog10 ( t11 ) ;
t13 = datatree . AddDivide ( darg , arg ) ;
return datatree . AddTimes ( t12 , t13 ) ;
case oCos :
t11 = datatree . AddSin ( arg ) ;
t12 = datatree . AddUMinus ( t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oSin :
t11 = datatree . AddCos ( arg ) ;
return datatree . AddTimes ( darg , t11 ) ;
case oTan :
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddPlus ( t11 , datatree . One ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oAcos :
t11 = datatree . AddSin ( this ) ;
t12 = datatree . AddDivide ( darg , t11 ) ;
return datatree . AddUMinus ( t12 ) ;
case oAsin :
t11 = datatree . AddCos ( this ) ;
return datatree . AddDivide ( darg , t11 ) ;
case oAtan :
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddPlus ( datatree . One , t11 ) ;
return datatree . AddDivide ( darg , t12 ) ;
case oCosh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddSinh ( arg ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( darg , t11 ) ;
case oSinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( arg ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( darg , t11 ) ;
case oTanh :
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oAcosh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddSinh ( this ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddDivide ( darg , t11 ) ;
case oAsinh :
2009-04-16 12:33:30 +02:00
t11 = datatree . AddCosh ( this ) ;
2008-02-03 11:28:36 +01:00
return datatree . AddDivide ( darg , t11 ) ;
case oAtanh :
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
case oSqrt :
t11 = datatree . AddPlus ( this , this ) ;
return datatree . AddDivide ( darg , t11 ) ;
2009-09-10 22:09:16 +02:00
case oSteadyState :
2009-12-16 18:13:23 +01:00
if ( datatree . isDynamic ( ) )
return datatree . Zero ;
else
return darg ;
2009-10-30 06:21:54 +01:00
case oExpectation :
assert ( 0 ) ;
2010-03-11 11:57:34 +01:00
case oErf :
// x^2
t11 = datatree . AddPower ( arg , datatree . Two ) ;
// exp(x^2)
t12 = datatree . AddExp ( t11 ) ;
// sqrt(pi)
t11 = datatree . AddSqrt ( datatree . Pi ) ;
// sqrt(pi)*exp(x^2)
t13 = datatree . AddTimes ( t11 , t12 ) ;
// 2/(sqrt(pi)*exp(x^2));
return datatree . AddDivide ( datatree . Two , t13 ) ;
break ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
UnaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg = arg - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg ) ;
}
2008-02-03 11:28:36 +01:00
int
UnaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a temporary term, the cost is null
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
int cost = arg - > cost ( temporary_terms , is_matlab ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
2009-06-05 16:45:23 +02:00
{
2009-12-16 18:13:23 +01:00
case oUminus :
return cost + 70 ;
case oExp :
return cost + 160 ;
case oLog :
return cost + 300 ;
case oLog10 :
2010-03-11 11:57:34 +01:00
case oErf :
2009-12-16 18:13:23 +01:00
return cost + 16000 ;
case oCos :
case oSin :
case oCosh :
return cost + 210 ;
case oTan :
return cost + 230 ;
case oAcos :
return cost + 300 ;
case oAsin :
return cost + 310 ;
case oAtan :
return cost + 140 ;
case oSinh :
return cost + 240 ;
case oTanh :
return cost + 190 ;
case oAcosh :
return cost + 770 ;
case oAsinh :
return cost + 460 ;
case oAtanh :
return cost + 350 ;
case oSqrt :
return cost + 570 ;
case oSteadyState :
case oExpectation :
return cost ;
2009-06-05 16:45:23 +02:00
}
2009-12-16 18:13:23 +01:00
else
// Cost for C files
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
2009-12-16 18:13:23 +01:00
return cost + 3 ;
2008-02-03 11:28:36 +01:00
case oExp :
2009-12-16 18:13:23 +01:00
case oAcosh :
return cost + 210 ;
2008-02-03 11:28:36 +01:00
case oLog :
2009-12-16 18:13:23 +01:00
return cost + 137 ;
2008-02-03 11:28:36 +01:00
case oLog10 :
2009-12-16 18:13:23 +01:00
return cost + 139 ;
2008-02-03 11:28:36 +01:00
case oCos :
case oSin :
2009-12-16 18:13:23 +01:00
return cost + 160 ;
2008-02-03 11:28:36 +01:00
case oTan :
2009-12-16 18:13:23 +01:00
return cost + 170 ;
2008-02-03 11:28:36 +01:00
case oAcos :
2009-06-05 16:45:23 +02:00
case oAtan :
2009-12-16 18:13:23 +01:00
return cost + 190 ;
case oAsin :
return cost + 180 ;
2008-02-03 11:28:36 +01:00
case oCosh :
case oSinh :
case oTanh :
2010-03-11 11:57:34 +01:00
case oErf :
2009-12-16 18:13:23 +01:00
return cost + 240 ;
2008-02-03 11:28:36 +01:00
case oAsinh :
2009-12-16 18:13:23 +01:00
return cost + 220 ;
2008-02-03 11:28:36 +01:00
case oAtanh :
2009-12-16 18:13:23 +01:00
return cost + 150 ;
2008-02-03 11:28:36 +01:00
case oSqrt :
2009-12-16 18:13:23 +01:00
return cost + 90 ;
2009-09-18 18:34:11 +02:00
case oSteadyState :
2009-10-30 06:21:54 +01:00
case oExpectation :
2009-12-16 18:13:23 +01:00
return cost ;
2008-02-03 11:28:36 +01:00
}
2009-12-16 18:13:23 +01:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
void
UnaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
NodeID this2 = const_cast < UnaryOpNode * > ( this ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
arg - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab ) )
temporary_terms . insert ( this2 ) ;
}
}
void
UnaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
{
NodeID this2 = const_cast < UnaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
void
UnaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
arg - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
void
UnaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
// Always put parenthesis around uminus nodes
if ( op_code = = oUminus )
output < < LEFT_PAR ( output_type ) ;
switch ( op_code )
{
case oUminus :
output < < " - " ;
break ;
case oExp :
output < < " exp " ;
break ;
case oLog :
output < < " log " ;
break ;
case oLog10 :
if ( IS_LATEX ( output_type ) )
output < < " log_{10} " ;
else
output < < " log10 " ;
break ;
case oCos :
output < < " cos " ;
break ;
case oSin :
output < < " sin " ;
break ;
case oTan :
output < < " tan " ;
break ;
case oAcos :
output < < " acos " ;
break ;
case oAsin :
output < < " asin " ;
break ;
case oAtan :
output < < " atan " ;
break ;
case oCosh :
output < < " cosh " ;
break ;
case oSinh :
output < < " sinh " ;
break ;
case oTanh :
output < < " tanh " ;
break ;
case oAcosh :
output < < " acosh " ;
break ;
case oAsinh :
output < < " asinh " ;
break ;
case oAtanh :
output < < " atanh " ;
break ;
case oSqrt :
output < < " sqrt " ;
break ;
case oSteadyState :
ExprNodeOutputType new_output_type ;
switch ( output_type )
{
case oMatlabDynamicModel :
new_output_type = oMatlabDynamicSteadyStateOperator ;
break ;
case oLatexDynamicModel :
new_output_type = oLatexDynamicSteadyStateOperator ;
break ;
case oCDynamicModel :
cerr < < " Steady State Operator not implemented for oCDynamicModel. " < < endl ;
exit ( EXIT_FAILURE ) ;
case oMatlabDynamicModelSparse :
case oMatlabDynamicModelSparseLocalTemporaryTerms :
cerr < < " Steady State Operator not implemented for oMatlabDynamicModelSparse. " < < endl ;
exit ( EXIT_FAILURE ) ;
default :
new_output_type = output_type ;
break ;
}
arg - > writeOutput ( output , new_output_type , temporary_terms ) ;
return ;
case oExpectation :
assert ( 0 ) ;
2010-03-11 11:57:34 +01:00
case oErf :
output < < " erf " ;
break ;
2009-12-16 18:13:23 +01:00
}
bool close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
/* Enclose argument with parentheses if:
- current opcode is not uminus , or
- current opcode is uminus and argument has lowest precedence
*/
if ( op_code ! = oUminus
| | ( op_code = = oUminus
& & arg - > precedence ( output_type , temporary_terms ) < precedence ( output_type , temporary_terms ) ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
// Write argument
arg - > writeOutput ( output , output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Close parenthesis for uminus
if ( op_code = = oUminus )
output < < RIGHT_PAR ( output_type ) ;
}
2008-02-03 11:28:36 +01:00
2010-03-04 16:40:07 +01:00
void
UnaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
arg - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2008-02-03 11:28:36 +01:00
double
UnaryOpNode : : eval_opcode ( UnaryOpcode op_code , double v ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oUminus :
2009-12-16 18:13:23 +01:00
return ( - v ) ;
2008-02-03 11:28:36 +01:00
case oExp :
2009-12-16 18:13:23 +01:00
return ( exp ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oLog :
2009-12-16 18:13:23 +01:00
return ( log ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oLog10 :
2009-12-16 18:13:23 +01:00
return ( log10 ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oCos :
2009-12-16 18:13:23 +01:00
return ( cos ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oSin :
2009-12-16 18:13:23 +01:00
return ( sin ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oTan :
2009-12-16 18:13:23 +01:00
return ( tan ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAcos :
2009-12-16 18:13:23 +01:00
return ( acos ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAsin :
2009-12-16 18:13:23 +01:00
return ( asin ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAtan :
2009-12-16 18:13:23 +01:00
return ( atan ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oCosh :
2009-12-16 18:13:23 +01:00
return ( cosh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oSinh :
2009-12-16 18:13:23 +01:00
return ( sinh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oTanh :
2009-12-16 18:13:23 +01:00
return ( tanh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAcosh :
2009-12-16 18:13:23 +01:00
return ( acosh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAsinh :
2009-12-16 18:13:23 +01:00
return ( asinh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oAtanh :
2009-12-16 18:13:23 +01:00
return ( atanh ( v ) ) ;
2008-02-03 11:28:36 +01:00
case oSqrt :
2009-12-16 18:13:23 +01:00
return ( sqrt ( v ) ) ;
2009-10-30 06:21:54 +01:00
case oSteadyState :
2009-12-16 18:13:23 +01:00
return ( v ) ;
2009-10-30 06:21:54 +01:00
case oExpectation :
throw EvalException ( ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return ( erf ( v ) ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
double
UnaryOpNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
double v = arg - > eval ( eval_context ) ;
return eval_opcode ( op_code , v ) ;
}
void
2010-01-22 17:42:08 +01:00
UnaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDT_ fldt ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldt . write ( CompileCode ) ;
}
else
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDST_ fldst ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldst . write ( CompileCode ) ;
}
return ;
}
if ( op_code = = oSteadyState )
arg - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , true ) ;
else
{
arg - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
FUNARY_ funary ( op_code ) ;
funary . write ( CompileCode ) ;
}
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
UnaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
UnaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
pair < bool , NodeID > res = arg - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
int is_endogenous_present = res . first ;
NodeID New_NodeID = res . second ;
/*if(res.second.second)*/
if ( is_endogenous_present = = 2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present )
{
switch ( op_code )
{
case oUminus :
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oExp :
List_of_Op_RHS . push_back ( make_pair ( oLog , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oLog :
List_of_Op_RHS . push_back ( make_pair ( oExp , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oLog10 :
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( NodeID ) NULL , datatree . AddNumConstant ( " 10 " ) ) ) ) ;
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oCos :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSin :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oTan :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAcos :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAsin :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAtan :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oCosh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSinh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oTanh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAcosh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAsinh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oAtanh :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSqrt :
2010-03-11 12:04:06 +01:00
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( ( NodeID ) NULL , datatree . Two ) ) ) ;
2009-12-16 18:13:23 +01:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oSteadyState :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
case oExpectation :
assert ( 0 ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-12-16 18:13:23 +01:00
}
}
else
{
switch ( op_code )
{
case oUminus :
return ( make_pair ( 0 , datatree . AddUMinus ( New_NodeID ) ) ) ;
case oExp :
return ( make_pair ( 0 , datatree . AddExp ( New_NodeID ) ) ) ;
case oLog :
return ( make_pair ( 0 , datatree . AddLog ( New_NodeID ) ) ) ;
case oLog10 :
return ( make_pair ( 0 , datatree . AddLog10 ( New_NodeID ) ) ) ;
case oCos :
return ( make_pair ( 0 , datatree . AddCos ( New_NodeID ) ) ) ;
case oSin :
return ( make_pair ( 0 , datatree . AddSin ( New_NodeID ) ) ) ;
case oTan :
return ( make_pair ( 0 , datatree . AddTan ( New_NodeID ) ) ) ;
case oAcos :
return ( make_pair ( 0 , datatree . AddAcos ( New_NodeID ) ) ) ;
case oAsin :
return ( make_pair ( 0 , datatree . AddAsin ( New_NodeID ) ) ) ;
case oAtan :
return ( make_pair ( 0 , datatree . AddAtan ( New_NodeID ) ) ) ;
case oCosh :
return ( make_pair ( 0 , datatree . AddCosh ( New_NodeID ) ) ) ;
case oSinh :
return ( make_pair ( 0 , datatree . AddSinh ( New_NodeID ) ) ) ;
case oTanh :
return ( make_pair ( 0 , datatree . AddTanh ( New_NodeID ) ) ) ;
case oAcosh :
return ( make_pair ( 0 , datatree . AddAcosh ( New_NodeID ) ) ) ;
case oAsinh :
return ( make_pair ( 0 , datatree . AddAsinh ( New_NodeID ) ) ) ;
case oAtanh :
return ( make_pair ( 0 , datatree . AddAtanh ( New_NodeID ) ) ) ;
case oSqrt :
return ( make_pair ( 0 , datatree . AddSqrt ( New_NodeID ) ) ) ;
case oSteadyState :
return ( make_pair ( 0 , datatree . AddSteadyState ( New_NodeID ) ) ) ;
case oExpectation :
assert ( 0 ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return ( make_pair ( 0 , datatree . AddErf ( New_NodeID ) ) ) ;
2009-12-16 18:13:23 +01:00
}
}
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
}
2008-11-14 17:07:47 +01:00
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
UnaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg = arg - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
UnaryOpNode : : buildSimilarUnaryOpNode ( NodeID alt_arg , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oUminus :
return alt_datatree . AddUMinus ( alt_arg ) ;
case oExp :
return alt_datatree . AddExp ( alt_arg ) ;
case oLog :
return alt_datatree . AddLog ( alt_arg ) ;
case oLog10 :
return alt_datatree . AddLog10 ( alt_arg ) ;
case oCos :
return alt_datatree . AddCos ( alt_arg ) ;
case oSin :
return alt_datatree . AddSin ( alt_arg ) ;
case oTan :
return alt_datatree . AddTan ( alt_arg ) ;
case oAcos :
return alt_datatree . AddAcos ( alt_arg ) ;
case oAsin :
return alt_datatree . AddAsin ( alt_arg ) ;
case oAtan :
return alt_datatree . AddAtan ( alt_arg ) ;
case oCosh :
return alt_datatree . AddCosh ( alt_arg ) ;
case oSinh :
return alt_datatree . AddSinh ( alt_arg ) ;
case oTanh :
return alt_datatree . AddTanh ( alt_arg ) ;
case oAcosh :
return alt_datatree . AddAcosh ( alt_arg ) ;
case oAsinh :
return alt_datatree . AddAsinh ( alt_arg ) ;
case oAtanh :
return alt_datatree . AddAtanh ( alt_arg ) ;
case oSqrt :
return alt_datatree . AddSqrt ( alt_arg ) ;
case oSteadyState :
return alt_datatree . AddSteadyState ( alt_arg ) ;
2009-10-30 06:21:54 +01:00
case oExpectation :
2009-11-06 19:19:52 +01:00
return alt_datatree . AddExpectation ( expectation_information_set , alt_arg ) ;
2010-03-11 11:57:34 +01:00
case oErf :
return alt_datatree . AddErf ( alt_arg ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
UnaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg = arg - > toStatic ( static_datatree ) ;
return buildSimilarUnaryOpNode ( sarg , static_datatree ) ;
}
int
UnaryOpNode : : maxEndoLead ( ) const
{
return arg - > maxEndoLead ( ) ;
}
2009-10-07 18:34:42 +02:00
int
UnaryOpNode : : maxExoLead ( ) const
{
return arg - > maxExoLead ( ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
UnaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID argsubst = arg - > decreaseLeadsLags ( n ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2009-11-07 19:37:11 +01:00
NodeID
2009-11-09 12:03:18 +01:00
UnaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
NodeID argsubst = arg - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
UnaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
if ( op_code = = oUminus )
{
2009-10-07 16:07:13 +02:00
NodeID argsubst = arg - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxEndoLead ( ) > = 2 )
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
UnaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID argsubst = arg - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
NodeID
2009-10-07 18:34:42 +02:00
UnaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2009-10-07 18:34:42 +02:00
if ( op_code = = oUminus )
{
NodeID argsubst = arg - > substituteExoLead ( subst_table , neweqs ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxExoLead ( ) > = 1 )
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
NodeID
UnaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID argsubst = arg - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2009-06-05 16:45:23 +02:00
2009-10-29 18:16:10 +01:00
NodeID
UnaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2009-12-16 18:13:23 +01:00
switch ( op_code )
2009-10-30 06:21:54 +01:00
{
case oExpectation :
{
subst_table_t : : iterator it = subst_table . find ( const_cast < UnaryOpNode * > ( this ) ) ;
if ( it ! = subst_table . end ( ) )
return const_cast < VariableNode * > ( it - > second ) ;
//Arriving here, we need to create an auxiliary variable for this Expectation Operator:
2010-01-18 23:08:44 +01:00
//AUX_EXPECT_(LEAD/LAG)_(period)_(arg.idx) OR
//AUX_EXPECT_(info_set_name)_(arg.idx)
int symb_id = datatree . symbol_table . addExpectationAuxiliaryVar ( expectation_information_set , arg - > idx , expectation_information_set_name ) ;
2009-10-30 06:21:54 +01:00
NodeID newAuxE = datatree . AddVariable ( symb_id , 0 ) ;
2009-12-16 18:13:23 +01:00
if ( partial_information_model & & expectation_information_set = = 0 )
2009-10-30 06:21:54 +01:00
{
if ( dynamic_cast < VariableNode * > ( arg ) = = NULL )
{
2010-01-18 23:08:44 +01:00
cerr < < " ERROR: In Partial Information models, EXPECTATION( " ;
if ( expectation_information_set_name . empty ( ) )
cerr < < 0 ;
else
cerr < < expectation_information_set_name ;
cerr < < " )(X) can only be used when X is a single variable. " < < endl ;
2009-10-30 06:21:54 +01:00
exit ( EXIT_FAILURE ) ;
}
}
2010-01-18 23:08:44 +01:00
if ( ! expectation_information_set_name . empty ( ) )
{
if ( ! partial_information_model )
{
cerr < < " ERROR: EXPECTATION( " < < expectation_information_set_name < < " )(X) is only valid in models with partial information. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( expectation_information_set ! = 0 )
{
cerr < < " ERROR: UnaryOpNode::substituteExpectation() should not arrive here. Please inform Dynare Team. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else if ( dynamic_cast < VariableNode * > ( arg ) - > get_lag ( ) ! = 0 )
{
cerr < < " ERROR: EXPECTATION( " < < expectation_information_set_name < < " )(X) requres that X be from the current period. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
//Will not have nested Expectation operators of this type since we require that X be a single endogenous variable.
//Hence, the newAuxE with lag = 0 is all we need here.
}
2009-10-30 06:21:54 +01:00
else
{
2009-11-09 16:13:47 +01:00
//take care of any nested expectation operators by calling arg->substituteExpectation(.), then decreaseLeadsLags for this oExpectation operator
2009-10-30 06:21:54 +01:00
//arg(lag-period) (holds entire subtree of arg(lag-period)
2009-11-06 19:19:52 +01:00
NodeID substexpr = ( arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) - > decreaseLeadsLags ( expectation_information_set ) ;
2009-10-30 06:21:54 +01:00
assert ( substexpr ! = NULL ) ;
neweqs . push_back ( dynamic_cast < BinaryOpNode * > ( datatree . AddEqual ( newAuxE , substexpr ) ) ) ; //AUXE_period_arg.idx = arg(lag-period)
2009-11-09 16:13:47 +01:00
newAuxE = datatree . AddVariable ( symb_id , expectation_information_set ) ;
2009-10-30 06:21:54 +01:00
}
2009-11-09 16:13:47 +01:00
assert ( dynamic_cast < VariableNode * > ( newAuxE ) ! = NULL ) ;
2009-10-30 06:21:54 +01:00
subst_table [ this ] = dynamic_cast < VariableNode * > ( newAuxE ) ;
return newAuxE ;
}
default :
2009-12-16 18:13:23 +01:00
NodeID argsubst = arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2009-10-30 06:21:54 +01:00
}
2009-10-29 18:16:10 +01:00
}
2010-04-16 16:54:55 +02:00
bool
UnaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
UnaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2008-02-03 11:28:36 +01:00
BinaryOpNode : : BinaryOpNode ( DataTree & datatree_arg , const NodeID arg1_arg ,
BinaryOpcode op_code_arg , const NodeID arg2_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
datatree . binary_op_node_map [ make_pair ( make_pair ( arg1 , arg2 ) , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
BinaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg1 - > prepareForDerivation ( ) ;
arg2 - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are the union of those of the arguments
// Compute set union of arg1->non_null_derivatives and arg2->non_null_derivatives
set_union ( arg1 - > non_null_derivatives . begin ( ) ,
arg1 - > non_null_derivatives . end ( ) ,
arg2 - > non_null_derivatives . begin ( ) ,
arg2 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
}
NodeID
2009-07-06 11:34:21 +02:00
BinaryOpNode : : composeDerivatives ( NodeID darg1 , NodeID darg2 )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 , t14 , t15 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oPlus :
return datatree . AddPlus ( darg1 , darg2 ) ;
case oMinus :
return datatree . AddMinus ( darg1 , darg2 ) ;
case oTimes :
t11 = datatree . AddTimes ( darg1 , arg2 ) ;
t12 = datatree . AddTimes ( darg2 , arg1 ) ;
return datatree . AddPlus ( t11 , t12 ) ;
case oDivide :
2009-12-16 18:13:23 +01:00
if ( darg2 ! = datatree . Zero )
2009-06-05 16:45:23 +02:00
{
t11 = datatree . AddTimes ( darg1 , arg2 ) ;
t12 = datatree . AddTimes ( darg2 , arg1 ) ;
t13 = datatree . AddMinus ( t11 , t12 ) ;
t14 = datatree . AddTimes ( arg2 , arg2 ) ;
return datatree . AddDivide ( t13 , t14 ) ;
}
else
return datatree . AddDivide ( darg1 , arg2 ) ;
2008-02-03 11:28:36 +01:00
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return datatree . Zero ;
case oPower :
if ( darg2 = = datatree . Zero )
{
if ( darg1 = = datatree . Zero )
return datatree . Zero ;
else
{
t11 = datatree . AddMinus ( arg2 , datatree . One ) ;
t12 = datatree . AddPower ( arg1 , t11 ) ;
t13 = datatree . AddTimes ( arg2 , t12 ) ;
return datatree . AddTimes ( darg1 , t13 ) ;
}
}
else
{
t11 = datatree . AddLog ( arg1 ) ;
t12 = datatree . AddTimes ( darg2 , t11 ) ;
t13 = datatree . AddTimes ( darg1 , arg2 ) ;
t14 = datatree . AddDivide ( t13 , arg1 ) ;
t15 = datatree . AddPlus ( t12 , t14 ) ;
return datatree . AddTimes ( t15 , this ) ;
}
case oMax :
2009-12-16 18:13:23 +01:00
t11 = datatree . AddGreater ( arg1 , arg2 ) ;
t12 = datatree . AddTimes ( t11 , darg1 ) ;
t13 = datatree . AddMinus ( datatree . One , t11 ) ;
t14 = datatree . AddTimes ( t13 , darg2 ) ;
return datatree . AddPlus ( t14 , t12 ) ;
2008-02-03 11:28:36 +01:00
case oMin :
2009-12-16 18:13:23 +01:00
t11 = datatree . AddGreater ( arg2 , arg1 ) ;
t12 = datatree . AddTimes ( t11 , darg1 ) ;
t13 = datatree . AddMinus ( datatree . One , t11 ) ;
t14 = datatree . AddTimes ( t13 , darg2 ) ;
return datatree . AddPlus ( t14 , t12 ) ;
2008-02-03 11:28:36 +01:00
case oEqual :
return datatree . AddMinus ( darg1 , darg2 ) ;
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
BinaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg1 = arg1 - > getDerivative ( deriv_id ) ;
NodeID darg2 = arg2 - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg1 , darg2 ) ;
}
2008-02-03 11:28:36 +01:00
int
BinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
return 100 ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oEqual :
return 0 ;
case oEqualEqual :
case oDifferent :
return 1 ;
case oLessEqual :
case oGreaterEqual :
case oLess :
case oGreater :
return 2 ;
case oPlus :
case oMinus :
return 3 ;
case oTimes :
case oDivide :
return 4 ;
case oPower :
if ( IS_C ( output_type ) )
// In C, power operator is of the form pow(a, b)
2009-06-05 16:45:23 +02:00
return 100 ;
2009-12-16 18:13:23 +01:00
else
return 5 ;
case oMin :
case oMax :
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
int
BinaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return cost + 60 ;
case oPlus :
case oMinus :
case oTimes :
return cost + 90 ;
case oMax :
case oMin :
return cost + 110 ;
case oDivide :
return cost + 990 ;
case oPower :
return cost + 1160 ;
case oEqual :
return cost ;
}
else
// Cost for C files
switch ( op_code )
{
case oLess :
case oGreater :
case oLessEqual :
case oGreaterEqual :
case oEqualEqual :
case oDifferent :
return cost + 2 ;
case oPlus :
case oMinus :
case oTimes :
return cost + 4 ;
case oMax :
case oMin :
return cost + 5 ;
case oDivide :
return cost + 15 ;
case oPower :
return cost + 520 ;
case oEqual :
return cost ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
NodeID this2 = const_cast < BinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
reference_count [ this2 ] = 1 ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
2010-05-05 10:10:01 +02:00
/* If the node has already been encountered, increment its ref count
and declare it as a temporary term if it is too costly ( except if it is
an equal node : we don ' t want them as temporary terms ) */
2009-12-16 18:13:23 +01:00
reference_count [ this2 ] + + ;
2010-05-05 10:10:01 +02:00
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab )
& & op_code ! = oEqual )
2009-12-16 18:13:23 +01:00
temporary_terms . insert ( this2 ) ;
}
}
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
2009-01-02 14:00:43 +01:00
map < NodeID , pair < int , int > > & first_occurence ,
2008-02-03 11:28:36 +01:00
int Curr_block ,
2009-12-16 14:21:31 +01:00
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
2009-12-16 18:13:23 +01:00
{
NodeID this2 = const_cast < BinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
2010-05-05 10:10:01 +02:00
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C
& & op_code ! = oEqual )
2009-12-16 18:13:23 +01:00
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
2008-02-03 11:28:36 +01:00
double
BinaryOpNode : : eval_opcode ( double v1 , BinaryOpcode op_code , double v2 ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oPlus :
2009-12-16 18:13:23 +01:00
return ( v1 + v2 ) ;
2008-02-03 11:28:36 +01:00
case oMinus :
2009-12-16 18:13:23 +01:00
return ( v1 - v2 ) ;
2008-02-03 11:28:36 +01:00
case oTimes :
2009-12-16 18:13:23 +01:00
return ( v1 * v2 ) ;
2008-02-03 11:28:36 +01:00
case oDivide :
2009-12-16 18:13:23 +01:00
return ( v1 / v2 ) ;
2008-02-03 11:28:36 +01:00
case oPower :
2009-12-16 18:13:23 +01:00
return ( pow ( v1 , v2 ) ) ;
2008-02-03 11:28:36 +01:00
case oMax :
if ( v1 < v2 )
return v2 ;
else
return v1 ;
case oMin :
if ( v1 > v2 )
return v2 ;
else
return v1 ;
case oLess :
return ( v1 < v2 ) ;
case oGreater :
return ( v1 > v2 ) ;
case oLessEqual :
return ( v1 < = v2 ) ;
case oGreaterEqual :
return ( v1 > = v2 ) ;
case oEqualEqual :
return ( v1 = = v2 ) ;
case oDifferent :
return ( v1 ! = v2 ) ;
case oEqual :
throw EvalException ( ) ;
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
double
BinaryOpNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
double v1 = arg1 - > eval ( eval_context ) ;
double v2 = arg2 - > eval ( eval_context ) ;
return eval_opcode ( v1 , op_code , v2 ) ;
}
void
2010-01-22 17:42:08 +01:00
BinaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDT_ fldt ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldt . write ( CompileCode ) ;
}
else
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDST_ fldst ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldst . write ( CompileCode ) ;
}
return ;
}
arg1 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg2 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
FBINARY_ fbinary ( op_code ) ;
fbinary . write ( CompileCode ) ;
}
2008-02-03 11:28:36 +01:00
2008-12-24 16:49:01 +01:00
void
2009-12-16 14:21:31 +01:00
BinaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Treat special case of power operator in C, and case of max and min operators
if ( ( op_code = = oPower & & IS_C ( output_type ) ) | | op_code = = oMax | | op_code = = oMin )
{
switch ( op_code )
{
case oPower :
output < < " pow( " ;
break ;
case oMax :
output < < " max( " ;
break ;
case oMin :
output < < " min( " ;
break ;
default :
;
}
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
int prec = precedence ( output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
bool close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & op_code = = oDivide )
output < < " \\ frac{ " ;
else
{
// If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
BinaryOpNode * barg1 = dynamic_cast < BinaryOpNode * > ( arg1 ) ;
if ( arg1 - > precedence ( output_type , temporary_terms ) < prec
| | ( op_code = = oPower & & barg1 ! = NULL & & barg1 - > op_code = = oPower ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Write left argument
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & op_code = = oDivide )
output < < " } " ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Write current operator symbol
switch ( op_code )
{
case oPlus :
output < < " + " ;
break ;
case oMinus :
output < < " - " ;
break ;
case oTimes :
if ( IS_LATEX ( output_type ) )
output < < " \\ , " ;
else
output < < " * " ;
break ;
case oDivide :
if ( ! IS_LATEX ( output_type ) )
output < < " / " ;
break ;
case oPower :
output < < " ^ " ;
break ;
case oLess :
output < < " < " ;
break ;
case oGreater :
output < < " > " ;
break ;
case oLessEqual :
if ( IS_LATEX ( output_type ) )
output < < " \\ leq " ;
else
output < < " <= " ;
break ;
case oGreaterEqual :
if ( IS_LATEX ( output_type ) )
output < < " \\ geq " ;
else
output < < " >= " ;
break ;
case oEqualEqual :
output < < " == " ;
break ;
case oDifferent :
if ( IS_MATLAB ( output_type ) )
output < < " ~= " ;
else
{
if ( IS_C ( output_type ) )
output < < " != " ;
else
output < < " \\ neq " ;
}
break ;
case oEqual :
output < < " = " ;
break ;
default :
;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
close_parenthesis = false ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & ( op_code = = oPower | | op_code = = oDivide ) )
output < < " { " ;
else
{
/* Add parenthesis around right argument if:
- its precedence is lower than those of the current node
- it is a power operator and current operator is also a power operator
- it is a minus operator with same precedence than current operator
- it is a divide operator with same precedence than current operator */
BinaryOpNode * barg2 = dynamic_cast < BinaryOpNode * > ( arg2 ) ;
int arg2_prec = arg2 - > precedence ( output_type , temporary_terms ) ;
if ( arg2_prec < prec
| | ( op_code = = oPower & & barg2 ! = NULL & & barg2 - > op_code = = oPower & & ! IS_LATEX ( output_type ) )
| | ( op_code = = oMinus & & arg2_prec = = prec )
| | ( op_code = = oDivide & & arg2_prec = = prec & & ! IS_LATEX ( output_type ) ) )
{
output < < LEFT_PAR ( output_type ) ;
close_parenthesis = true ;
}
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Write right argument
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( IS_LATEX ( output_type ) & & ( op_code = = oPower | | op_code = = oDivide ) )
output < < " } " ;
2009-04-30 15:14:33 +02:00
2009-12-16 18:13:23 +01:00
if ( close_parenthesis )
output < < RIGHT_PAR ( output_type ) ;
}
2008-02-03 11:28:36 +01:00
2010-03-04 16:40:07 +01:00
void
BinaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
BinaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg1 - > collectVariables ( type_arg , result ) ;
arg2 - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
NodeID
BinaryOpNode : : Compute_RHS ( NodeID arg1 , NodeID arg2 , int op , int op_type ) const
{
temporary_terms_type temp ;
2009-12-16 18:13:23 +01:00
switch ( op_type )
2009-08-25 11:43:01 +02:00
{
case 0 : /*Unary Operator*/
2009-12-16 18:13:23 +01:00
switch ( op )
2009-08-25 11:43:01 +02:00
{
case oUminus :
2009-12-16 18:13:23 +01:00
return ( datatree . AddUMinus ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oExp :
2009-12-16 18:13:23 +01:00
return ( datatree . AddExp ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oLog :
2009-12-16 18:13:23 +01:00
return ( datatree . AddLog ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
case oLog10 :
2009-12-16 18:13:23 +01:00
return ( datatree . AddLog10 ( arg1 ) ) ;
break ;
}
break ;
case 1 : /*Binary Operator*/
switch ( op )
{
case oPlus :
return ( datatree . AddPlus ( arg1 , arg2 ) ) ;
break ;
case oMinus :
return ( datatree . AddMinus ( arg1 , arg2 ) ) ;
break ;
case oTimes :
return ( datatree . AddTimes ( arg1 , arg2 ) ) ;
break ;
case oDivide :
return ( datatree . AddDivide ( arg1 , arg2 ) ) ;
break ;
case oPower :
return ( datatree . AddPower ( arg1 , arg2 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
}
break ;
2009-12-16 18:13:23 +01:00
}
return ( ( NodeID ) NULL ) ;
}
pair < int , NodeID >
BinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
{
vector < pair < int , pair < NodeID , NodeID > > > List_of_Op_RHS1 , List_of_Op_RHS2 ;
int is_endogenous_present_1 , is_endogenous_present_2 ;
pair < int , NodeID > res ;
NodeID NodeID_1 , NodeID_2 ;
res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS1 ) ;
is_endogenous_present_1 = res . first ;
NodeID_1 = res . second ;
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS2 ) ;
is_endogenous_present_2 = res . first ;
NodeID_2 = res . second ;
if ( is_endogenous_present_1 = = 2 | | is_endogenous_present_2 = = 2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
return ( make_pair ( 2 , ( NodeID ) NULL ) ) ;
else if ( is_endogenous_present_1 )
{
if ( op_code = = oEqual )
{
pair < int , pair < NodeID , NodeID > > it ;
int oo = List_of_Op_RHS1 . size ( ) ;
for ( int i = 0 ; i < oo ; i + + )
{
it = List_of_Op_RHS1 . back ( ) ;
List_of_Op_RHS1 . pop_back ( ) ;
if ( it . second . first & & ! it . second . second ) /*Binary operator*/
NodeID_2 = Compute_RHS ( NodeID_2 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
NodeID_2 = Compute_RHS ( it . second . second , NodeID_2 , it . first , 1 ) ;
else if ( it . second . second & & it . second . first ) /*Binary operator*/
NodeID_2 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
else /*Unary operator*/
NodeID_2 = Compute_RHS ( ( UnaryOpNode * ) NodeID_2 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
}
}
else
List_of_Op_RHS = List_of_Op_RHS1 ;
}
else if ( is_endogenous_present_2 )
{
if ( op_code = = oEqual )
{
int oo = List_of_Op_RHS2 . size ( ) ;
for ( int i = 0 ; i < oo ; i + + )
{
pair < int , pair < NodeID , NodeID > > it ;
it = List_of_Op_RHS2 . back ( ) ;
List_of_Op_RHS2 . pop_back ( ) ;
if ( it . second . first & & ! it . second . second ) /*Binary operator*/
NodeID_1 = Compute_RHS ( ( BinaryOpNode * ) NodeID_1 , ( BinaryOpNode * ) it . second . first , it . first , 1 ) ;
else if ( it . second . second & & ! it . second . first ) /*Binary operator*/
NodeID_1 = Compute_RHS ( ( BinaryOpNode * ) it . second . second , ( BinaryOpNode * ) NodeID_1 , it . first , 1 ) ;
else if ( it . second . second & & it . second . first ) /*Binary operator*/
NodeID_1 = Compute_RHS ( it . second . first , it . second . second , it . first , 1 ) ;
else
NodeID_1 = Compute_RHS ( ( UnaryOpNode * ) NodeID_1 , ( UnaryOpNode * ) it . second . first , it . first , 0 ) ;
}
}
else
List_of_Op_RHS = List_of_Op_RHS2 ;
}
switch ( op_code )
{
case oPlus :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddPlus ( NodeID_1 , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddPlus ( NodeID_1 , NodeID_2 ) ) ) ;
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
break ;
case oMinus :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( datatree . AddMinus ( NodeID_1 , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 0 , datatree . AddMinus ( NodeID_1 , NodeID_2 ) ) ) ;
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oUminus , make_pair ( ( NodeID ) NULL , ( NodeID ) NULL ) ) ) ;
List_of_Op_RHS . push_back ( make_pair ( oMinus , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oPlus , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , datatree . AddUMinus ( NodeID_2 ) ) ) ;
}
break ;
case oTimes :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddTimes ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( NodeID_1 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oDivide :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddDivide ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oDivide , make_pair ( ( NodeID ) NULL , NodeID_1 ) ) ) ;
return ( make_pair ( 1 , NodeID_1 ) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
List_of_Op_RHS . push_back ( make_pair ( oTimes , make_pair ( NodeID_2 , ( NodeID ) NULL ) ) ) ;
return ( make_pair ( 1 , NodeID_2 ) ) ;
}
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oPower :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddPower ( NodeID_1 , NodeID_2 ) ) ) ;
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
2010-03-11 12:04:06 +01:00
List_of_Op_RHS . push_back ( make_pair ( oPower , make_pair ( datatree . AddDivide ( datatree . One , NodeID_2 ) , ( NodeID ) NULL ) ) ) ;
2009-12-16 18:13:23 +01:00
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
}
break ;
case oEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-03-16 12:23:59 +01:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , datatree . AddMinus ( NodeID_2 , NodeID_1 ) )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( is_endogenous_present_1 & & is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-03-16 12:23:59 +01:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , datatree . Zero )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( ! is_endogenous_present_1 & & is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-03-16 12:23:59 +01:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , /*datatree.AddUMinus(NodeID_1)*/ NodeID_1 )
2009-12-16 18:13:23 +01:00
) ) ;
}
else if ( is_endogenous_present_1 & & ! is_endogenous_present_2 )
{
return ( make_pair ( 0 ,
2010-03-16 12:23:59 +01:00
datatree . AddEqual ( datatree . AddVariable ( datatree . symbol_table . getID ( eEndogenous , var_endo ) , 0 ) , NodeID_2 )
2009-12-16 18:13:23 +01:00
) ) ;
}
break ;
case oMax :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddMax ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oMin :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddMin ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oLess :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddLess ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oGreater :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddGreater ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oLessEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddLessEqual ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oGreaterEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddGreaterEqual ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oEqualEqual :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddEqualEqual ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
break ;
case oDifferent :
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 )
return ( make_pair ( 0 , datatree . AddDifferent ( NodeID_1 , NodeID_2 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
2009-08-25 11:43:01 +02:00
break ;
}
2009-12-16 18:13:23 +01:00
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2009-08-25 11:43:01 +02:00
}
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
BinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg1 , darg2 ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
BinaryOpNode : : buildSimilarBinaryOpNode ( NodeID alt_arg1 , NodeID alt_arg2 , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oPlus :
return alt_datatree . AddPlus ( alt_arg1 , alt_arg2 ) ;
case oMinus :
return alt_datatree . AddMinus ( alt_arg1 , alt_arg2 ) ;
case oTimes :
return alt_datatree . AddTimes ( alt_arg1 , alt_arg2 ) ;
case oDivide :
return alt_datatree . AddDivide ( alt_arg1 , alt_arg2 ) ;
case oPower :
return alt_datatree . AddPower ( alt_arg1 , alt_arg2 ) ;
case oEqual :
return alt_datatree . AddEqual ( alt_arg1 , alt_arg2 ) ;
case oMax :
return alt_datatree . AddMax ( alt_arg1 , alt_arg2 ) ;
case oMin :
return alt_datatree . AddMin ( alt_arg1 , alt_arg2 ) ;
case oLess :
return alt_datatree . AddLess ( alt_arg1 , alt_arg2 ) ;
case oGreater :
return alt_datatree . AddGreater ( alt_arg1 , alt_arg2 ) ;
case oLessEqual :
return alt_datatree . AddLessEqual ( alt_arg1 , alt_arg2 ) ;
case oGreaterEqual :
return alt_datatree . AddGreaterEqual ( alt_arg1 , alt_arg2 ) ;
case oEqualEqual :
return alt_datatree . AddEqualEqual ( alt_arg1 , alt_arg2 ) ;
case oDifferent :
return alt_datatree . AddDifferent ( alt_arg1 , alt_arg2 ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
BinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg1 = arg1 - > toStatic ( static_datatree ) ;
NodeID sarg2 = arg2 - > toStatic ( static_datatree ) ;
return buildSimilarBinaryOpNode ( sarg1 , sarg2 , static_datatree ) ;
}
int
BinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , arg2 - > maxEndoLead ( ) ) ;
}
2009-06-05 16:45:23 +02:00
2009-10-07 18:34:42 +02:00
int
BinaryOpNode : : maxExoLead ( ) const
{
return max ( arg1 - > maxExoLead ( ) , arg2 - > maxExoLead ( ) ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
BinaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2009-11-07 19:37:11 +01:00
NodeID
2009-11-09 12:03:18 +01:00
BinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
NodeID arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
BinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
NodeID arg1subst , arg2subst ;
2009-10-07 18:34:42 +02:00
int maxendolead1 = arg1 - > maxEndoLead ( ) , maxendolead2 = arg2 - > maxEndoLead ( ) ;
2009-09-30 17:10:31 +02:00
2009-10-07 18:34:42 +02:00
if ( maxendolead1 < 2 & & maxendolead2 < 2 )
2009-09-30 17:10:31 +02:00
return const_cast < BinaryOpNode * > ( this ) ;
2009-12-16 18:13:23 +01:00
switch ( op_code )
2009-09-30 17:10:31 +02:00
{
case oPlus :
case oMinus :
case oEqual :
2009-10-07 18:34:42 +02:00
arg1subst = maxendolead1 > = 2 ? arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) : arg1 ;
arg2subst = maxendolead2 > = 2 ? arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) : arg2 ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case oTimes :
case oDivide :
2010-06-11 19:21:03 +02:00
if ( maxendolead1 > = 2 & & maxendolead2 = = 0 & & arg2 - > maxExoLead ( ) = = 0 )
2009-09-30 17:10:31 +02:00
{
2009-10-07 16:07:13 +02:00
arg1subst = arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
2009-10-07 18:34:42 +02:00
if ( maxendolead1 = = 0 & & arg1 - > maxExoLead ( ) = = 0
& & maxendolead2 > = 2 & & op_code = = oTimes )
2009-09-30 17:10:31 +02:00
{
2009-10-07 16:07:13 +02:00
arg2subst = arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
default :
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
}
}
NodeID
2009-10-07 16:07:13 +02:00
BinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
NodeID
2009-10-07 18:34:42 +02:00
BinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst , arg2subst ;
int maxexolead1 = arg1 - > maxExoLead ( ) , maxexolead2 = arg2 - > maxExoLead ( ) ;
if ( maxexolead1 < 1 & & maxexolead2 < 1 )
return const_cast < BinaryOpNode * > ( this ) ;
2009-12-16 18:13:23 +01:00
switch ( op_code )
2009-10-07 18:34:42 +02:00
{
case oPlus :
case oMinus :
case oEqual :
arg1subst = maxexolead1 > = 1 ? arg1 - > substituteExoLead ( subst_table , neweqs ) : arg1 ;
arg2subst = maxexolead2 > = 1 ? arg2 - > substituteExoLead ( subst_table , neweqs ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case oTimes :
case oDivide :
2010-06-11 19:21:03 +02:00
if ( maxexolead1 > = 1 & & maxexolead2 = = 0 & & arg2 - > maxEndoLead ( ) = = 0 )
2009-10-07 18:34:42 +02:00
{
arg1subst = arg1 - > substituteExoLead ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxexolead1 = = 0 & & arg1 - > maxEndoLead ( ) = = 0
& & maxexolead2 > = 1 & & op_code = = oTimes )
{
arg2subst = arg2 - > substituteExoLead ( subst_table , neweqs ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
}
NodeID
BinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2009-10-07 18:34:42 +02:00
NodeID arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2009-04-14 16:39:53 +02:00
2009-10-29 18:16:10 +01:00
NodeID
BinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2009-10-30 06:21:54 +01:00
NodeID arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
NodeID arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2009-10-29 18:16:10 +01:00
}
2010-04-16 16:54:55 +02:00
bool
BinaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
BinaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2008-02-03 11:28:36 +01:00
TrinaryOpNode : : TrinaryOpNode ( DataTree & datatree_arg , const NodeID arg1_arg ,
2009-01-23 11:59:37 +01:00
TrinaryOpcode op_code_arg , const NodeID arg2_arg , const NodeID arg3_arg ) :
2009-12-16 18:13:23 +01:00
ExprNode ( datatree_arg ) ,
arg1 ( arg1_arg ) ,
arg2 ( arg2_arg ) ,
arg3 ( arg3_arg ) ,
op_code ( op_code_arg )
2008-02-03 11:28:36 +01:00
{
datatree . trinary_op_node_map [ make_pair ( make_pair ( make_pair ( arg1 , arg2 ) , arg3 ) , op_code ) ] = this ;
2009-09-30 17:10:31 +02:00
}
void
TrinaryOpNode : : prepareForDerivation ( )
{
if ( preparedForDerivation )
return ;
preparedForDerivation = true ;
arg1 - > prepareForDerivation ( ) ;
arg2 - > prepareForDerivation ( ) ;
arg3 - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non-null derivatives are the union of those of the arguments
// Compute set union of arg{1,2,3}->non_null_derivatives
2008-11-14 17:07:47 +01:00
set < int > non_null_derivatives_tmp ;
2008-02-03 11:28:36 +01:00
set_union ( arg1 - > non_null_derivatives . begin ( ) ,
arg1 - > non_null_derivatives . end ( ) ,
arg2 - > non_null_derivatives . begin ( ) ,
arg2 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives_tmp , non_null_derivatives_tmp . begin ( ) ) ) ;
set_union ( non_null_derivatives_tmp . begin ( ) ,
non_null_derivatives_tmp . end ( ) ,
arg3 - > non_null_derivatives . begin ( ) ,
arg3 - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
}
NodeID
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : composeDerivatives ( NodeID darg1 , NodeID darg2 , NodeID darg3 )
2008-02-03 11:28:36 +01:00
{
NodeID t11 , t12 , t13 , t14 , t15 ;
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oNormcdf :
// normal pdf is inlined in the tree
NodeID y ;
// sqrt(2*pi)
2009-04-16 12:33:30 +02:00
t14 = datatree . AddSqrt ( datatree . AddTimes ( datatree . Two , datatree . Pi ) ) ;
2008-02-03 11:28:36 +01:00
// x - mu
2009-12-16 18:13:23 +01:00
t12 = datatree . AddMinus ( arg1 , arg2 ) ;
2008-02-03 11:28:36 +01:00
// y = (x-mu)/sigma
2009-12-16 18:13:23 +01:00
y = datatree . AddDivide ( t12 , arg3 ) ;
2008-02-03 11:28:36 +01:00
// (x-mu)^2/sigma^2
2009-12-16 18:13:23 +01:00
t12 = datatree . AddTimes ( y , y ) ;
2008-02-03 11:28:36 +01:00
// -(x-mu)^2/sigma^2
t13 = datatree . AddUMinus ( t12 ) ;
// -((x-mu)^2/sigma^2)/2
2009-04-17 23:22:44 +02:00
t12 = datatree . AddDivide ( t13 , datatree . Two ) ;
2008-02-03 11:28:36 +01:00
// exp(-((x-mu)^2/sigma^2)/2)
t13 = datatree . AddExp ( t12 ) ;
// derivative of a standardized normal
// t15 = (1/sqrt(2*pi))*exp(-y^2/2)
2009-12-16 18:13:23 +01:00
t15 = datatree . AddDivide ( t13 , t14 ) ;
2008-02-03 11:28:36 +01:00
// derivatives thru x
2009-12-16 18:13:23 +01:00
t11 = datatree . AddDivide ( darg1 , arg3 ) ;
2008-02-03 11:28:36 +01:00
// derivatives thru mu
2009-12-16 18:13:23 +01:00
t12 = datatree . AddDivide ( darg2 , arg3 ) ;
2008-02-03 11:28:36 +01:00
// intermediary sum
2009-12-16 18:13:23 +01:00
t14 = datatree . AddMinus ( t11 , t12 ) ;
2008-02-03 11:28:36 +01:00
// derivatives thru sigma
2009-12-16 18:13:23 +01:00
t11 = datatree . AddDivide ( y , arg3 ) ;
t12 = datatree . AddTimes ( t11 , darg3 ) ;
2008-02-03 11:28:36 +01:00
//intermediary sum
2009-12-16 18:13:23 +01:00
t11 = datatree . AddMinus ( t14 , t12 ) ;
2008-02-03 11:28:36 +01:00
// total derivative:
2009-05-04 14:59:21 +02:00
// (darg1/sigma - darg2/sigma - darg3*(x-mu)/sigma^2) * t15
// where t15 is the derivative of a standardized normal
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( t11 , t15 ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
// (x - mu)
t11 = datatree . AddMinus ( arg1 , arg2 ) ;
// (x - mu)/sigma
t12 = datatree . AddDivide ( t11 , arg3 ) ;
// darg3 * (x - mu)/sigma
t11 = datatree . AddTimes ( darg3 , t12 ) ;
// darg2 - darg1
t13 = datatree . AddMinus ( darg2 , darg1 ) ;
// darg2 - darg1 + darg3 * (x - mu)/sigma
t14 = datatree . AddPlus ( t13 , t11 ) ;
// ((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma)
t11 = datatree . AddTimes ( t12 , t14 ) ;
// ((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma) - darg3
t12 = datatree . AddMinus ( t11 , darg3 ) ;
// this / sigma
t11 = datatree . AddDivide ( this , arg3 ) ;
// total derivative:
// (this / sigma) * (((x - mu)/sigma) * (darg2 - darg1 + darg3 * (x - mu)/sigma) - darg3)
return datatree . AddTimes ( t11 , t12 ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-07-06 11:34:21 +02:00
NodeID
TrinaryOpNode : : computeDerivative ( int deriv_id )
{
NodeID darg1 = arg1 - > getDerivative ( deriv_id ) ;
NodeID darg2 = arg2 - > getDerivative ( deriv_id ) ;
NodeID darg3 = arg3 - > getDerivative ( deriv_id ) ;
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
}
2008-02-03 11:28:36 +01:00
int
TrinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_type & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
// A temporary term behaves as a variable
if ( it ! = temporary_terms . end ( ) )
return 100 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
int
TrinaryOpNode : : cost ( const temporary_terms_type & temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
// For a temporary term, the cost is null
if ( it ! = temporary_terms . end ( ) )
return 0 ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
int cost = arg1 - > cost ( temporary_terms , is_matlab ) ;
cost + = arg2 - > cost ( temporary_terms , is_matlab ) ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return cost + 1000 ;
}
else
// Cost for C files
switch ( op_code )
{
case oNormcdf :
2010-03-11 09:43:16 +01:00
case oNormpdf :
2009-12-16 18:13:23 +01:00
return cost + 1000 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
NodeID this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
reference_count [ this2 ] = 1 ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
arg3 - > computeTemporaryTerms ( reference_count , temporary_terms , is_matlab ) ;
}
else
{
// If the node has already been encountered, increment its ref count
// and declare it as a temporary term if it is too costly
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , is_matlab ) > MIN_COST ( is_matlab ) )
temporary_terms . insert ( this2 ) ;
}
}
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-01-23 11:59:37 +01:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
2009-12-16 14:21:31 +01:00
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
2009-12-16 18:13:23 +01:00
{
NodeID this2 = const_cast < TrinaryOpNode * > ( this ) ;
map < NodeID , int > : : iterator it = reference_count . find ( this2 ) ;
if ( it = = reference_count . end ( ) )
{
reference_count [ this2 ] = 1 ;
first_occurence [ this2 ] = make_pair ( Curr_block , equation ) ;
arg1 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
arg2 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
arg3 - > computeTemporaryTerms ( reference_count , temporary_terms , first_occurence , Curr_block , v_temporary_terms , equation ) ;
}
else
{
reference_count [ this2 ] + + ;
if ( reference_count [ this2 ] * cost ( temporary_terms , false ) > MIN_COST_C )
{
temporary_terms . insert ( this2 ) ;
v_temporary_terms [ first_occurence [ this2 ] . first ] [ first_occurence [ this2 ] . second ] . insert ( this2 ) ;
}
}
}
2008-02-03 11:28:36 +01:00
double
TrinaryOpNode : : eval_opcode ( double v1 , TrinaryOpcode op_code , double v2 , double v3 ) throw ( EvalException )
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
case oNormcdf :
2010-02-23 14:39:49 +01:00
return ( 0.5 * ( 1 + erf ( ( v1 - v2 ) / v3 / M_SQRT2 ) ) ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
return ( 1 / ( v3 * sqrt ( 2 * M_PI ) * exp ( pow ( ( v1 - v2 ) / v3 , 2 ) / 2 ) ) ) ;
2008-02-03 11:28:36 +01:00
}
2009-04-16 12:33:30 +02:00
// Suppress GCC warning
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
double
TrinaryOpNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
{
double v1 = arg1 - > eval ( eval_context ) ;
double v2 = arg2 - > eval ( eval_context ) ;
double v3 = arg3 - > eval ( eval_context ) ;
return eval_opcode ( v1 , op_code , v2 , v3 ) ;
}
void
2010-01-22 17:42:08 +01:00
TrinaryOpNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( dynamic )
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDT_ fldt ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldt . write ( CompileCode ) ;
}
else
{
2010-01-22 17:42:08 +01:00
map_idx_type : : const_iterator ii = map_idx . find ( idx ) ;
FLDST_ fldst ( ii - > second ) ;
2009-12-16 18:13:23 +01:00
fldst . write ( CompileCode ) ;
}
return ;
}
arg1 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg2 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
arg3 - > compile ( CompileCode , lhs_rhs , temporary_terms , map_idx , dynamic , steady_dynamic ) ;
2010-04-16 16:54:55 +02:00
FTRINARY_ ftrinary ( op_code ) ;
ftrinary . write ( CompileCode ) ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2008-12-24 16:49:01 +01:00
void
2009-12-16 14:21:31 +01:00
TrinaryOpNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
arg1 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg2 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
arg3 - > collectTemporary_terms ( temporary_terms , temporary_terms_inuse , Curr_Block ) ;
}
}
2008-12-24 16:49:01 +01:00
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
output < < " T " < < idx ;
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
case oNormcdf :
2010-02-23 14:39:49 +01:00
if ( IS_C ( output_type ) )
{
// In C, there is no normcdf() primitive, so use erf()
output < < " (0.5*(1+erf((( " ;
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " )-( " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ))/( " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " )/M_SQRT2))) " ;
}
else
{
output < < " normcdf( " ;
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
}
2010-03-15 12:22:52 +01:00
break ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
if ( IS_C ( output_type ) )
{
//(1/(v3*sqrt(2*M_PI)*exp(pow((v1-v2)/v3,2)/2)))
output < < " (1/( " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " *sqrt(2*M_PI)*exp(pow(( " ;
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " - " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " )/ " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ,2)/2))) " ;
}
else
{
output < < " normpdf( " ;
arg1 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg2 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " , " ;
arg3 - > writeOutput ( output , output_type , temporary_terms ) ;
output < < " ) " ;
}
2009-12-16 18:13:23 +01:00
break ;
2010-03-15 12:22:52 +01:00
default :
assert ( false ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
2010-03-04 16:40:07 +01:00
void
TrinaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
arg3 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
2008-02-03 11:28:36 +01:00
void
2009-07-10 18:42:08 +02:00
TrinaryOpNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
{
arg1 - > collectVariables ( type_arg , result ) ;
arg2 - > collectVariables ( type_arg , result ) ;
arg3 - > collectVariables ( type_arg , result ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
TrinaryOpNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
pair < int , NodeID > res = arg1 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
bool is_endogenous_present_1 = res . first ;
NodeID NodeID_1 = res . second ;
res = arg2 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
bool is_endogenous_present_2 = res . first ;
NodeID NodeID_2 = res . second ;
res = arg3 - > normalizeEquation ( var_endo , List_of_Op_RHS ) ;
bool is_endogenous_present_3 = res . first ;
NodeID NodeID_3 = res . second ;
if ( ! is_endogenous_present_1 & & ! is_endogenous_present_2 & & ! is_endogenous_present_3 )
return ( make_pair ( 0 , datatree . AddNormcdf ( NodeID_1 , NodeID_2 , NodeID_3 ) ) ) ;
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
}
2008-11-14 17:07:47 +01:00
2009-04-14 16:39:53 +02:00
NodeID
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2009-07-06 11:34:21 +02:00
NodeID darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
NodeID darg3 = arg3 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
2009-04-14 16:39:53 +02:00
}
2009-09-30 17:10:31 +02:00
NodeID
TrinaryOpNode : : buildSimilarTrinaryOpNode ( NodeID alt_arg1 , NodeID alt_arg2 , NodeID alt_arg3 , DataTree & alt_datatree ) const
{
switch ( op_code )
{
case oNormcdf :
return alt_datatree . AddNormcdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2010-03-11 09:43:16 +01:00
case oNormpdf :
return alt_datatree . AddNormpdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
NodeID
TrinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
NodeID sarg1 = arg1 - > toStatic ( static_datatree ) ;
NodeID sarg2 = arg2 - > toStatic ( static_datatree ) ;
NodeID sarg3 = arg3 - > toStatic ( static_datatree ) ;
return buildSimilarTrinaryOpNode ( sarg1 , sarg2 , sarg3 , static_datatree ) ;
}
2009-06-05 16:45:23 +02:00
2009-09-30 17:10:31 +02:00
int
TrinaryOpNode : : maxEndoLead ( ) const
{
return max ( arg1 - > maxEndoLead ( ) , max ( arg2 - > maxEndoLead ( ) , arg3 - > maxEndoLead ( ) ) ) ;
}
2009-10-07 18:34:42 +02:00
int
TrinaryOpNode : : maxExoLead ( ) const
{
return max ( arg1 - > maxExoLead ( ) , max ( arg2 - > maxExoLead ( ) , arg3 - > maxExoLead ( ) ) ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
TrinaryOpNode : : decreaseLeadsLags ( int n ) const
{
NodeID arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
NodeID arg3subst = arg3 - > decreaseLeadsLags ( n ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-11-07 19:37:11 +01:00
NodeID
2009-11-09 12:03:18 +01:00
TrinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2009-11-09 12:03:18 +01:00
NodeID arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
NodeID arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
NodeID arg3subst = arg3 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-09-30 17:10:31 +02:00
NodeID
2009-10-07 16:07:13 +02:00
TrinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
if ( maxEndoLead ( ) < 2 )
return const_cast < TrinaryOpNode * > ( this ) ;
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
NodeID
TrinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
NodeID arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
NodeID arg3subst = arg3 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
NodeID
2009-10-07 18:34:42 +02:00
TrinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
if ( maxExoLead ( ) = = 0 )
return const_cast < TrinaryOpNode * > ( this ) ;
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
NodeID
TrinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2009-10-07 18:34:42 +02:00
NodeID arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
NodeID arg2subst = arg2 - > substituteExoLag ( subst_table , neweqs ) ;
NodeID arg3subst = arg3 - > substituteExoLag ( subst_table , neweqs ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2008-11-14 17:07:47 +01:00
2009-10-29 18:16:10 +01:00
NodeID
TrinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
NodeID arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
NodeID arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
NodeID arg3subst = arg3 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-04-16 16:54:55 +02:00
bool
TrinaryOpNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
TrinaryOpNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : ExternalFunctionNode ( DataTree & datatree_arg ,
2009-12-16 18:13:23 +01:00
int symb_id_arg ,
const vector < NodeID > & arguments_arg ) :
ExprNode ( datatree_arg ) ,
symb_id ( symb_id_arg ) ,
arguments ( arguments_arg )
2008-02-03 11:28:36 +01:00
{
2010-03-03 11:43:22 +01:00
// Add myself to the external function map
datatree . external_function_node_map [ make_pair ( arguments , symb_id ) ] = this ;
2008-02-03 11:28:36 +01:00
}
2009-09-30 17:10:31 +02:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : prepareForDerivation ( )
2009-09-30 17:10:31 +02:00
{
2010-02-22 17:33:38 +01:00
if ( preparedForDerivation )
return ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
( * it ) - > prepareForDerivation ( ) ;
non_null_derivatives = arguments . at ( 0 ) - > non_null_derivatives ;
for ( int i = 1 ; i < ( int ) arguments . size ( ) ; i + + )
set_union ( non_null_derivatives . begin ( ) ,
non_null_derivatives . end ( ) ,
arguments . at ( i ) - > non_null_derivatives . begin ( ) ,
arguments . at ( i ) - > non_null_derivatives . end ( ) ,
inserter ( non_null_derivatives , non_null_derivatives . begin ( ) ) ) ;
preparedForDerivation = true ;
2009-09-30 17:10:31 +02:00
}
2008-02-03 11:28:36 +01:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2010-03-03 11:40:13 +01:00
assert ( datatree . external_functions_table . getNargs ( symb_id ) > 0 ) ;
2010-02-22 17:33:38 +01:00
vector < NodeID > dargs ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
dargs . push_back ( ( * it ) - > getDerivative ( deriv_id ) ) ;
return composeDerivatives ( dargs ) ;
}
NodeID
ExternalFunctionNode : : composeDerivatives ( const vector < NodeID > & dargs )
{
vector < NodeID > dNodes ;
for ( int i = 0 ; i < ( int ) dargs . size ( ) ; i + + )
if ( dargs . at ( i ) ! = 0 )
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
datatree . AddFirstDerivExternalFunctionNode ( symb_id , arguments , i + 1 ) ) ) ;
NodeID theDeriv = datatree . Zero ;
for ( vector < NodeID > : : const_iterator it = dNodes . begin ( ) ; it ! = dNodes . end ( ) ; it + + )
theDeriv = datatree . AddPlus ( theDeriv , * it ) ;
return theDeriv ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : getChainRuleDerivative ( int deriv_id , const map < int , NodeID > & recursive_variables )
2008-02-03 11:28:36 +01:00
{
2010-02-22 17:33:38 +01:00
cerr < < " ExternalFunctionNode::getChainRuleDerivative: operation impossible! " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-06-05 16:45:23 +02:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-12-16 18:13:23 +01:00
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
2010-03-04 16:40:07 +01:00
temporary_terms . insert ( const_cast < ExternalFunctionNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
void
2010-03-04 16:40:07 +01:00
ExternalFunctionNode : : writeExternalFunctionArguments ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2010-03-04 16:40:07 +01:00
( * it ) - > writeOutput ( output , output_type , temporary_terms , tef_terms ) ;
}
}
void
ExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
if ( output_type = = oMatlabOutsideModel )
{
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
output < < " ) " ;
return ;
}
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
{
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
else
output < < " T " < < idx ;
return ;
}
output < < " TEF_ " < < getIndxInTefTerms ( symb_id , tef_terms ) ;
}
void
ExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
( * it ) - > writeExternalFunctionOutput ( output , output_type , temporary_terms , tef_terms ) ;
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
tef_terms [ make_pair ( symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( symb_id = = first_deriv_symb_id & &
symb_id = = second_deriv_symb_id )
output < < " [TEF_ " < < indx < < " TEFD_ " < < indx < < " TEFDD_ " < < indx < < " ] = " ;
else if ( symb_id = = first_deriv_symb_id )
output < < " [TEF_ " < < indx < < " TEFD_ " < < indx < < " ] = " ;
else
output < < " TEF_ " < < indx < < " = " ;
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
output < < " ); " < < endl ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
2009-12-16 18:13:23 +01:00
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
{
2010-02-22 17:33:38 +01:00
cerr < < " ExternalFunctionNode::computeTemporaryTerms: not implemented " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : collectVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2009-07-10 18:42:08 +02:00
{
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
( * it ) - > collectVariables ( type_arg , result ) ;
}
2008-11-14 17:07:47 +01:00
2008-12-24 16:49:01 +01:00
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : collectTemporary_terms ( const temporary_terms_type & temporary_terms , temporary_terms_inuse_type & temporary_terms_inuse , int Curr_Block ) const
2009-12-16 18:13:23 +01:00
{
2010-02-22 17:33:38 +01:00
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ;
2009-12-16 18:13:23 +01:00
if ( it ! = temporary_terms . end ( ) )
temporary_terms_inuse . insert ( idx ) ;
else
{
//arg->collectTemporary_terms(temporary_terms, result);
}
}
2008-11-14 17:07:47 +01:00
2008-02-03 11:28:36 +01:00
double
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : eval ( const eval_context_type & eval_context ) const throw ( EvalException )
2008-02-03 11:28:36 +01:00
{
throw EvalException ( ) ;
}
void
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : compile ( ostream & CompileCode , bool lhs_rhs , const temporary_terms_type & temporary_terms , const map_idx_type & map_idx , bool dynamic , bool steady_dynamic ) const
2009-12-16 18:13:23 +01:00
{
2010-02-22 17:33:38 +01:00
cerr < < " ExternalFunctionNode::compile: operation impossible! " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
2009-08-25 11:43:01 +02:00
pair < int , NodeID >
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : normalizeEquation ( int var_endo , vector < pair < int , pair < NodeID , NodeID > > > & List_of_Op_RHS ) const
2009-12-16 18:13:23 +01:00
{
vector < pair < bool , NodeID > > V_arguments ;
vector < NodeID > V_NodeID ;
bool present = false ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
{
V_arguments . push_back ( ( * it ) - > normalizeEquation ( var_endo , List_of_Op_RHS ) ) ;
present = present | | V_arguments [ V_arguments . size ( ) - 1 ] . first ;
V_NodeID . push_back ( V_arguments [ V_arguments . size ( ) - 1 ] . second ) ;
}
if ( ! present )
2010-03-16 12:17:17 +01:00
return ( make_pair ( 0 , datatree . AddExternalFunction ( symb_id , V_NodeID ) ) ) ;
2009-12-16 18:13:23 +01:00
else
return ( make_pair ( 1 , ( NodeID ) NULL ) ) ;
}
2009-04-14 16:39:53 +02:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
vector < NodeID > static_arguments ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
static_arguments . push_back ( ( * it ) - > toStatic ( static_datatree ) ) ;
2010-03-16 12:17:17 +01:00
return static_datatree . AddExternalFunction ( symb_id , static_arguments ) ;
2009-12-16 18:13:23 +01:00
}
2009-09-30 17:10:31 +02:00
int
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : maxEndoLead ( ) const
2009-09-30 17:10:31 +02:00
{
int val = 0 ;
2009-12-16 18:13:23 +01:00
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
2009-09-30 17:10:31 +02:00
val = max ( val , ( * it ) - > maxEndoLead ( ) ) ;
return val ;
}
2009-10-07 18:34:42 +02:00
int
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : maxExoLead ( ) const
2009-10-07 18:34:42 +02:00
{
int val = 0 ;
2009-12-16 18:13:23 +01:00
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ;
it ! = arguments . end ( ) ; it + + )
2009-10-07 18:34:42 +02:00
val = max ( val , ( * it ) - > maxExoLead ( ) ) ;
return val ;
}
2009-09-30 17:10:31 +02:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : decreaseLeadsLags ( int n ) const
2009-09-30 17:10:31 +02:00
{
2010-02-22 17:33:38 +01:00
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > decreaseLeadsLags ( n ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2009-11-07 19:37:11 +01:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-02-22 17:33:38 +01:00
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > decreaseLeadsLagsPredeterminedVariables ( ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-11-07 19:37:11 +01:00
}
2009-09-30 17:10:31 +02:00
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-10-07 16:07:13 +02:00
{
2010-02-22 17:33:38 +01:00
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 16:07:13 +02:00
}
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-02-22 17:33:38 +01:00
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-10-07 18:34:42 +02:00
{
2010-02-22 17:33:38 +01:00
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > substituteExoLead ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 18:34:42 +02:00
}
NodeID
2010-02-22 17:33:38 +01:00
ExternalFunctionNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > substituteExoLag ( subst_table , neweqs ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
NodeID
ExternalFunctionNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
vector < NodeID > arguments_subst ;
for ( vector < NodeID > : : const_iterator it = arguments . begin ( ) ; it ! = arguments . end ( ) ; it + + )
arguments_subst . push_back ( ( * it ) - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
NodeID
ExternalFunctionNode : : buildSimilarExternalFunctionNode ( vector < NodeID > & alt_args , DataTree & alt_datatree ) const
{
return alt_datatree . AddExternalFunction ( symb_id , alt_args ) ;
}
2010-03-04 16:40:07 +01:00
bool
ExternalFunctionNode : : alreadyWrittenAsTefTerm ( int the_symb_id , deriv_node_temp_terms_type & tef_terms ) const
{
deriv_node_temp_terms_type : : const_iterator it = tef_terms . find ( make_pair ( the_symb_id , arguments ) ) ;
if ( it ! = tef_terms . end ( ) )
return true ;
return false ;
}
int
ExternalFunctionNode : : getIndxInTefTerms ( int the_symb_id , deriv_node_temp_terms_type & tef_terms ) const throw ( UnknownFunctionNameAndArgs )
{
deriv_node_temp_terms_type : : const_iterator it = tef_terms . find ( make_pair ( the_symb_id , arguments ) ) ;
if ( it ! = tef_terms . end ( ) )
return it - > second ;
throw UnknownFunctionNameAndArgs ( ) ;
}
2010-04-16 16:54:55 +02:00
bool
ExternalFunctionNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
bool
ExternalFunctionNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
2010-02-22 17:33:38 +01:00
FirstDerivExternalFunctionNode : : FirstDerivExternalFunctionNode ( DataTree & datatree_arg ,
int top_level_symb_id_arg ,
const vector < NodeID > & arguments_arg ,
int inputIndex_arg ) :
ExternalFunctionNode ( datatree_arg , top_level_symb_id_arg , arguments_arg ) ,
inputIndex ( inputIndex_arg )
{
2010-03-03 11:43:22 +01:00
// Add myself to the first derivative external function map
datatree . first_deriv_external_function_node_map [ make_pair ( make_pair ( arguments , inputIndex ) , symb_id ) ] = this ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
void
FirstDerivExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
temporary_terms . insert ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ;
}
void
FirstDerivExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
{
cerr < < " FirstDerivExternalFunctionNode::computeTemporaryTerms: not implemented " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
NodeID
FirstDerivExternalFunctionNode : : composeDerivatives ( const vector < NodeID > & dargs )
{
vector < NodeID > dNodes ;
for ( int i = 0 ; i < ( int ) dargs . size ( ) ; i + + )
if ( dargs . at ( i ) ! = 0 )
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
datatree . AddSecondDerivExternalFunctionNode ( symb_id , arguments , inputIndex , i + 1 ) ) ) ;
NodeID theDeriv = datatree . Zero ;
for ( vector < NodeID > : : const_iterator it = dNodes . begin ( ) ; it ! = dNodes . end ( ) ; it + + )
theDeriv = datatree . AddPlus ( theDeriv , * it ) ;
return theDeriv ;
}
void
FirstDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
assert ( output_type ! = oMatlabOutsideModel ) ;
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2010-02-22 17:33:38 +01:00
else
2010-03-04 16:40:07 +01:00
output < < " T " < < idx ;
return ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( first_deriv_symb_id = = symb_id )
output < < " TEFD_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " ( " < < inputIndex < < " ) " ;
else if ( first_deriv_symb_id = = eExtFunNotSet )
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex ;
else
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
< < " ( " < < inputIndex < < " ) " ;
}
void
FirstDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
assert ( output_type ! = oMatlabOutsideModel ) ;
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
assert ( first_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( ! alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( first_deriv_symb_id = = symb_id )
return ;
else if ( first_deriv_symb_id = = eExtFunNotSet )
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex < < " = jacob_element(@ "
< < datatree . symbol_table . getName ( symb_id ) < < " , " < < inputIndex < < " ,{ " ;
else
{
tef_terms [ make_pair ( first_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
< < " = " < < datatree . symbol_table . getName ( first_deriv_symb_id ) < < " ( " ;
}
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
if ( first_deriv_symb_id = = eExtFunNotSet )
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}
SecondDerivExternalFunctionNode : : SecondDerivExternalFunctionNode ( DataTree & datatree_arg ,
int top_level_symb_id_arg ,
const vector < NodeID > & arguments_arg ,
int inputIndex1_arg ,
int inputIndex2_arg ) :
ExternalFunctionNode ( datatree_arg , top_level_symb_id_arg , arguments_arg ) ,
inputIndex1 ( inputIndex1_arg ) ,
inputIndex2 ( inputIndex2_arg )
2009-09-30 17:10:31 +02:00
{
2010-03-03 11:43:22 +01:00
// Add myself to the second derivative external function map
datatree . second_deriv_external_function_node_map [ make_pair ( make_pair ( arguments , make_pair ( inputIndex1 , inputIndex2 ) ) , symb_id ) ] = this ;
2009-09-30 17:10:31 +02:00
}
2009-10-29 18:16:10 +01:00
2010-03-04 16:40:07 +01:00
void
SecondDerivExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
bool is_matlab ) const
{
temporary_terms . insert ( const_cast < SecondDerivExternalFunctionNode * > ( this ) ) ;
}
void
SecondDerivExternalFunctionNode : : computeTemporaryTerms ( map < NodeID , int > & reference_count ,
temporary_terms_type & temporary_terms ,
map < NodeID , pair < int , int > > & first_occurence ,
int Curr_block ,
vector < vector < temporary_terms_type > > & v_temporary_terms ,
int equation ) const
{
cerr < < " SecondDerivExternalFunctionNode::computeTemporaryTerms: not implemented " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2009-10-29 18:16:10 +01:00
NodeID
2010-02-22 17:33:38 +01:00
SecondDerivExternalFunctionNode : : computeDerivative ( int deriv_id )
2009-10-29 18:16:10 +01:00
{
2010-02-22 17:33:38 +01:00
cerr < < " ERROR: SecondDerivExternalFunctionNode::computeDerivative(). Not implemented " < < endl ;
2009-10-29 18:16:10 +01:00
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
void
SecondDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-03-04 16:40:07 +01:00
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
assert ( output_type ! = oMatlabOutsideModel ) ;
// If current node is a temporary term
temporary_terms_type : : const_iterator it = temporary_terms . find ( const_cast < SecondDerivExternalFunctionNode * > ( this ) ) ;
if ( it ! = temporary_terms . end ( ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( output_type = = oMatlabDynamicModelSparse )
output < < " T " < < idx < < " (it_) " ;
2010-02-22 17:33:38 +01:00
else
2010-03-04 16:40:07 +01:00
output < < " T " < < idx ;
return ;
2010-02-22 17:33:38 +01:00
}
2010-03-04 16:40:07 +01:00
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( second_deriv_symb_id = = symb_id )
output < < " TEFDD_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " ( " < < inputIndex1 < < " , " < < inputIndex2 < < " ) " ;
else if ( second_deriv_symb_id = = eExtFunNotSet )
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 ;
else
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < " ( " < < inputIndex1 < < " , " < < inputIndex2 < < " ) " ;
}
void
SecondDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_type & temporary_terms ,
deriv_node_temp_terms_type & tef_terms ) const
{
assert ( output_type ! = oMatlabOutsideModel ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
assert ( second_deriv_symb_id ! = eExtFunSetButNoNameProvided ) ;
if ( ! alreadyWrittenAsTefTerm ( second_deriv_symb_id , tef_terms ) )
2010-02-22 17:33:38 +01:00
{
2010-03-04 16:40:07 +01:00
if ( second_deriv_symb_id = = symb_id )
return ;
else if ( second_deriv_symb_id = = eExtFunNotSet )
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2
< < " = hess_element(@ " < < datatree . symbol_table . getName ( symb_id ) < < " , "
< < inputIndex1 < < " , " < < inputIndex2 < < " ,{ " ;
else
{
tef_terms [ make_pair ( second_deriv_symb_id , arguments ) ] = ( int ) tef_terms . size ( ) ;
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < " = " < < datatree . symbol_table . getName ( second_deriv_symb_id ) < < " ( " ;
}
writeExternalFunctionArguments ( output , output_type , temporary_terms , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2010-03-04 16:40:07 +01:00
if ( second_deriv_symb_id = = eExtFunNotSet )
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}