2011-02-04 16:25:38 +01:00
/*
2021-02-19 17:45:02 +01:00
* Copyright © 2007 - 2021 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
2021-06-09 16:52:20 +02:00
* along with Dynare . If not , see < https : //www.gnu.org/licenses/>.
2008-02-03 11:28:36 +01:00
*/
# include <iostream>
# include <algorithm>
2009-04-28 18:21:39 +02:00
# include <cassert>
2008-02-19 15:35:59 +01:00
# include <cmath>
2018-06-04 12:31:07 +02:00
# include <utility>
2019-10-22 11:34:51 +02:00
# include <limits>
2013-11-05 18:13:24 +01:00
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
2018-10-04 17:18:27 +02:00
ExprNode : : ExprNode ( DataTree & datatree_arg , int idx_arg ) : datatree { datatree_arg } , idx { idx_arg }
2008-02-03 11:28:36 +01:00
{
}
2010-09-16 19:18:45 +02:00
expr_t
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)
2019-10-28 11:09:36 +01:00
if ( auto it = non_null_derivatives . find ( deriv_id ) ; it = = non_null_derivatives . end ( ) )
2008-02-03 11:28:36 +01:00
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)
2019-10-28 11:09:36 +01:00
if ( auto it2 = derivatives . find ( deriv_id ) ; it2 ! = derivatives . end ( ) )
2008-02-03 11:28:36 +01:00
return it2 - > second ;
else
{
2010-09-16 19:18:45 +02:00
expr_t d = computeDerivative ( deriv_id ) ;
2009-04-17 18:26:23 +02:00
derivatives [ deriv_id ] = d ;
2008-02-03 11:28:36 +01:00
return d ;
}
}
2009-06-05 16:45:23 +02:00
int
2010-09-16 19:00:48 +02:00
ExprNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & 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
2017-02-20 12:18:11 +01:00
int
ExprNode : : precedenceJson ( const temporary_terms_t & temporary_terms ) const
{
// For a constant, a variable, or a unary op, the precedence is maximal
return 100 ;
}
2008-02-03 11:28:36 +01:00
int
2015-09-03 13:50:02 +02:00
ExprNode : : cost ( int cost , bool is_matlab ) const
{
// For a terminal node, the cost is null
return 0 ;
}
int
2020-05-13 16:58:19 +02:00
ExprNode : : cost ( const vector < vector < temporary_terms_t > > & blocks_temporary_terms , bool is_matlab ) const
2015-09-03 13:50:02 +02:00
{
// For a terminal node, the cost is null
return 0 ;
}
int
2018-11-30 12:22:13 +01:00
ExprNode : : cost ( const map < pair < int , int > , temporary_terms_t > & temp_terms_map , 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
2018-05-25 14:50:08 +02:00
bool
ExprNode : : checkIfTemporaryTermThenWrite ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
const temporary_terms_idxs_t & temporary_terms_idxs ) const
{
2019-10-28 11:09:36 +01:00
if ( auto it = temporary_terms . find ( const_cast < ExprNode * > ( this ) ) ; it = = temporary_terms . end ( ) )
2018-05-25 14:50:08 +02:00
return false ;
2020-05-26 16:21:11 +02:00
auto it2 = temporary_terms_idxs . find ( const_cast < ExprNode * > ( this ) ) ;
// It is the responsibility of the caller to ensure that all temporary terms have their index
assert ( it2 ! = temporary_terms_idxs . end ( ) ) ;
output < < " T " < < LEFT_ARRAY_SUBSCRIPT ( output_type )
2020-06-17 16:49:12 +02:00
< < it2 - > second + ARRAY_SUBSCRIPT_OFFSET ( output_type )
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2020-05-26 16:21:11 +02:00
2018-05-25 14:50:08 +02:00
return true ;
}
2019-10-22 14:56:28 +02:00
pair < expr_t , int >
ExprNode : : getLagEquivalenceClass ( ) const
{
int index = maxLead ( ) ;
if ( index = = numeric_limits < int > : : min ( ) )
index = 0 ; // If no variable in the expression, the equivalence class has size 1
return { decreaseLeadsLags ( index ) , index } ;
}
2013-11-29 15:32:49 +01:00
void
ExprNode : : collectVariables ( SymbolType type , set < int > & result ) const
{
2018-06-04 14:17:36 +02:00
set < pair < int , int > > symbs_lags ;
2013-11-29 15:32:49 +01:00
collectDynamicVariables ( type , symbs_lags ) ;
transform ( symbs_lags . begin ( ) , symbs_lags . end ( ) , inserter ( result , result . begin ( ) ) ,
2018-06-04 16:51:36 +02:00
[ ] ( auto x ) { return x . first ; } ) ;
2013-11-29 15:32:49 +01:00
}
2009-07-10 18:42:08 +02:00
void
2018-06-04 14:17:36 +02:00
ExprNode : : collectEndogenous ( set < pair < int , int > > & result ) const
2009-07-10 18:42:08 +02:00
{
2020-03-20 18:42:59 +01:00
set < pair < int , int > > symb_ids_and_lags ;
collectDynamicVariables ( SymbolType : : endogenous , symb_ids_and_lags ) ;
for ( const auto & [ symb_id , lag ] : symb_ids_and_lags )
result . emplace ( datatree . symbol_table . getTypeSpecificID ( symb_id ) , lag ) ;
2009-07-10 18:42:08 +02:00
}
2008-02-03 11:28:36 +01:00
void
2018-11-30 12:22:13 +01:00
ExprNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
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
2020-05-13 16:58:19 +02:00
ExprNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) 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
2010-03-09 12:16:32 +01:00
ExprNode : : writeOutput ( ostream & output ) const
2008-02-03 11:28:36 +01:00
{
2018-09-05 18:27:13 +02:00
writeOutput ( output , ExprNodeOutputType : : matlabOutsideModel , { } , { } ) ;
2008-02-03 11:28:36 +01:00
}
2010-03-09 12:16:32 +01:00
void
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ) const
{
2018-05-29 11:12:22 +02:00
writeOutput ( output , output_type , { } , { } ) ;
2010-03-09 12:16:32 +01:00
}
2010-03-04 16:40:07 +01:00
void
2018-03-27 17:14:30 +02:00
ExprNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms , const temporary_terms_idxs_t & temporary_terms_idxs ) const
2010-03-04 16:40:07 +01:00
{
2018-05-29 11:59:42 +02:00
writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , { } ) ;
2010-03-04 16:40:07 +01:00
}
2010-12-10 11:50:27 +01:00
void
ExprNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ) const
2010-12-10 11:50:27 +01:00
{
2020-05-13 12:53:47 +02:00
compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , { } ) ;
2010-12-10 11:50:27 +01:00
}
2010-03-04 16:40:07 +01:00
void
ExprNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
// Nothing to do
}
2017-02-20 12:18:11 +01:00
void
ExprNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
// Nothing to do
}
2010-12-10 11:50:27 +01:00
void
ExprNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2011-02-04 16:25:38 +01:00
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
// 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 ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = subst_table . find ( this ) ;
it ! = subst_table . end ( ) )
2009-09-30 17:10:31 +02:00
return const_cast < VariableNode * > ( it - > second ) ;
2010-09-16 19:18:45 +02:00
expr_t substexpr = decreaseLeadsLags ( n - 1 ) ;
2009-09-30 17:10:31 +02:00
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
{
2010-09-16 19:18:45 +02:00
expr_t orig_expr = decreaseLeadsLags ( lag ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = subst_table . find ( orig_expr ) ; it = = subst_table . end ( ) )
2009-09-30 17:10:31 +02:00
{
2016-03-18 14:55:14 +01:00
int symb_id = datatree . symbol_table . addEndoLeadAuxiliaryVar ( orig_expr - > idx , substexpr ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( datatree . AddVariable ( symb_id , 0 ) , substexpr ) ) ;
2009-09-30 17:10:31 +02:00
substexpr = datatree . AddVariable ( symb_id , + 1 ) ;
2019-12-16 19:42:59 +01:00
assert ( dynamic_cast < VariableNode * > ( substexpr ) ) ;
2009-09-30 17:10:31 +02:00
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 ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = subst_table . find ( this ) ;
it ! = subst_table . end ( ) )
2009-10-07 18:34:42 +02:00
return const_cast < VariableNode * > ( it - > second ) ;
2010-09-16 19:18:45 +02:00
expr_t substexpr = decreaseLeadsLags ( n ) ;
2009-10-07 18:34:42 +02:00
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
{
2010-09-16 19:18:45 +02:00
expr_t orig_expr = decreaseLeadsLags ( lag ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = subst_table . find ( orig_expr ) ; it = = subst_table . end ( ) )
2009-10-07 18:34:42 +02:00
{
2016-03-18 14:55:14 +01:00
int symb_id = datatree . symbol_table . addExoLeadAuxiliaryVar ( orig_expr - > idx , substexpr ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( datatree . AddVariable ( symb_id , 0 ) , substexpr ) ) ;
2009-10-07 18:34:42 +02:00
substexpr = datatree . AddVariable ( symb_id , + 1 ) ;
2019-12-16 19:42:59 +01:00
assert ( dynamic_cast < VariableNode * > ( substexpr ) ) ;
2009-10-07 18:34:42 +02:00
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 ;
}
2016-11-25 17:15:13 +01:00
void
ExprNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
}
2019-03-21 18:13:34 +01:00
void
ExprNode : : fillErrorCorrectionRow ( int eqn ,
const vector < int > & nontarget_lhs ,
const vector < int > & target_lhs ,
map < tuple < int , int , int > , expr_t > & A0 ,
map < tuple < int , int , int > , expr_t > & A0star ) const
{
vector < pair < expr_t , int > > terms ;
decomposeAdditiveTerms ( terms , 1 ) ;
for ( const auto & it : terms )
{
pair < int , vector < tuple < int , int , int , double > > > m ;
try
{
m = it . first - > matchParamTimesLinearCombinationOfVariables ( ) ;
for ( auto & t : m . second )
get < 3 > ( t ) * = it . second ; // Update sign of constants
}
catch ( MatchFailureException & e )
{
/* FIXME: we should not just skip them, but rather verify that they are
autoregressive terms or residuals ( probably by merging the two " fill " procedures ) */
continue ;
}
// Helper function
auto one_step_orig = [ this ] ( int symb_id ) {
2019-12-20 16:59:30 +01:00
return datatree . symbol_table . isAuxiliaryVariable ( symb_id ) ?
datatree . symbol_table . getOrigSymbIdForDiffAuxVar ( symb_id ) : symb_id ;
} ;
2019-03-21 18:13:34 +01:00
/* Verify that all variables belong to the error-correction term.
FIXME : same remark as above about skipping terms . */
bool not_ec = false ;
for ( const auto & t : m . second )
{
int vid = one_step_orig ( get < 0 > ( t ) ) ;
not_ec = not_ec | | ( find ( target_lhs . begin ( ) , target_lhs . end ( ) , vid ) = = target_lhs . end ( )
& & find ( nontarget_lhs . begin ( ) , nontarget_lhs . end ( ) , vid ) = = nontarget_lhs . end ( ) ) ;
}
if ( not_ec )
continue ;
// Now fill the matrices
2019-09-11 15:59:23 +02:00
for ( auto [ var_id , lag , param_id , constant ] : m . second )
2019-03-21 18:13:34 +01:00
{
int orig_vid = one_step_orig ( var_id ) ;
int orig_lag = datatree . symbol_table . isAuxiliaryVariable ( var_id ) ? - datatree . symbol_table . getOrigLeadLagForDiffAuxVar ( var_id ) : lag ;
if ( find ( target_lhs . begin ( ) , target_lhs . end ( ) , orig_vid ) = = target_lhs . end ( ) )
{
// This an LHS variable, so fill A0
if ( constant ! = 1 )
{
cerr < < " ERROR in trend component model: LHS variable should not appear with a multiplicative constant in error correction term " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( param_id ! = - 1 )
{
cerr < < " ERROR in trend component model: spurious parameter in error correction term " < < endl ;
exit ( EXIT_FAILURE ) ;
}
int colidx = static_cast < int > ( distance ( nontarget_lhs . begin ( ) , find ( nontarget_lhs . begin ( ) , nontarget_lhs . end ( ) , orig_vid ) ) ) ;
if ( A0 . find ( { eqn , - orig_lag , colidx } ) ! = A0 . end ( ) )
{
cerr < < " ExprNode::fillErrorCorrection: Error filling A0 matrix: "
< < " lag/symb_id encountered more than once in equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
A0 [ { eqn , - orig_lag , colidx } ] = datatree . AddVariable ( m . first ) ;
}
else
{
// This is a target, so fill A0star
int colidx = static_cast < int > ( distance ( target_lhs . begin ( ) , find ( target_lhs . begin ( ) , target_lhs . end ( ) , orig_vid ) ) ) ;
expr_t e = datatree . AddTimes ( datatree . AddVariable ( m . first ) , datatree . AddPossiblyNegativeConstant ( - constant ) ) ;
if ( param_id ! = - 1 )
e = datatree . AddTimes ( e , datatree . AddVariable ( param_id ) ) ;
2019-10-28 11:09:36 +01:00
if ( auto coor = tuple ( eqn , - orig_lag , colidx ) ; A0star . find ( coor ) = = A0star . end ( ) )
2019-03-21 18:13:34 +01:00
A0star [ coor ] = e ;
else
A0star [ coor ] = datatree . AddPlus ( e , A0star [ coor ] ) ;
}
}
}
}
2020-07-28 18:29:45 +02:00
void
ExprNode : : matchMatchedMoment ( vector < int > & symb_ids , vector < int > & lags , vector < int > & powers ) const
{
throw MatchFailureException { " Unsupported expression " } ;
}
2018-09-05 16:41:33 +02:00
NumConstNode : : NumConstNode ( DataTree & datatree_arg , int idx_arg , int id_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
id { id_arg }
2008-02-03 11:28:36 +01:00
{
2009-09-30 17:10:31 +02:00
}
2008-02-03 11:28:36 +01:00
2018-05-31 15:34:25 +02:00
int
NumConstNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-05-31 15:34:25 +02:00
return 0 ;
2018-02-08 13:07:15 +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
}
2010-09-16 19:18:45 +02:00
expr_t
2009-04-17 18:26:23 +02:00
NumConstNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
return datatree . Zero ;
}
void
NumConstNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-05-25 14:50:08 +02:00
if ( ! checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
2009-12-16 18:13:23 +01:00
output < < datatree . num_constants . get ( id ) ;
}
2008-02-03 11:28:36 +01:00
2018-09-18 14:50:31 +02:00
void
NumConstNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " NumConstNode " , " value " : ) " ;
2020-01-28 18:11:55 +01:00
output < < std : : stof ( datatree . num_constants . get ( id ) ) < < " } " ;
2018-09-18 14:50:31 +02:00
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
NumConstNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
output < < datatree . num_constants . get ( id ) ;
}
2015-05-12 16:36:03 +02:00
bool
NumConstNode : : containsExternalFunction ( ) const
{
return false ;
}
2008-02-03 11:28:36 +01:00
double
2018-06-04 12:50:53 +02:00
NumConstNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2008-02-03 11:28:36 +01:00
{
2019-12-16 19:42:59 +01:00
return datatree . num_constants . getDouble ( id ) ;
2008-02-03 11:28:36 +01:00
}
void
2010-12-10 11:50:27 +01:00
NumConstNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
FLDC_ fldc ( datatree . num_constants . getDouble ( id ) ) ;
2010-07-23 11:20:24 +02:00
fldc . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2018-04-16 13:50:31 +02:00
void
NumConstNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2008-02-03 11:28:36 +01:00
void
2018-06-04 14:17:36 +02:00
NumConstNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2013-09-13 20:37:31 +02:00
{
}
2020-04-02 14:36:26 +02:00
void
NumConstNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
{
}
BinaryOpNode *
NumConstNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
2009-12-16 18:13:23 +01:00
{
2020-04-02 14:36:26 +02:00
cerr < < " NumConstNode::normalizeEquation: this should not happen " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
NumConstNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & 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
}
2010-09-16 19:18:45 +02:00
expr_t
2009-04-14 16:39:53 +02:00
NumConstNode : : toStatic ( DataTree & static_datatree ) const
2009-12-16 18:13:23 +01:00
{
2010-11-25 13:45:35 +01:00
return static_datatree . AddNonNegativeConstant ( datatree . num_constants . get ( id ) ) ;
2009-12-16 18:13:23 +01:00
}
2009-04-14 16:39:53 +02:00
2015-12-18 15:17:32 +01:00
void
NumConstNode : : computeXrefs ( EquationInfo & ei ) const
{
}
2010-10-15 19:05:16 +02:00
expr_t
2018-10-10 13:07:25 +02:00
NumConstNode : : clone ( DataTree & datatree ) const
2010-10-15 19:05:16 +02:00
{
2018-10-10 13:07:25 +02:00
return datatree . AddNonNegativeConstant ( datatree . num_constants . get ( id ) ) ;
2010-10-15 19:05:16 +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 ;
}
2010-08-19 15:20:54 +02:00
int
NumConstNode : : maxEndoLag ( ) const
{
return 0 ;
}
int
NumConstNode : : maxExoLag ( ) const
{
return 0 ;
}
2012-05-26 20:53:48 +02:00
int
NumConstNode : : maxLead ( ) const
{
2019-10-22 11:34:51 +02:00
return numeric_limits < int > : : min ( ) ;
2012-05-26 20:53:48 +02:00
}
2018-02-28 17:33:00 +01:00
int
NumConstNode : : maxLag ( ) const
{
2019-10-22 11:34:51 +02:00
return numeric_limits < int > : : min ( ) ;
2018-02-28 17:33:00 +01:00
}
2018-12-05 15:17:00 +01:00
int
NumConstNode : : maxLagWithDiffsExpanded ( ) const
{
2019-10-22 11:34:51 +02:00
return numeric_limits < int > : : min ( ) ;
2018-12-05 15:17:00 +01:00
}
2018-04-17 15:17:28 +02:00
expr_t
NumConstNode : : undiff ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-05-16 12:17:06 +02:00
int
NumConstNode : : VarMinLag ( ) const
{
return 1 ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
NumConstNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2018-06-11 10:40:00 +02:00
return 0 ;
2018-04-16 13:50:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
NumConstNode : : decreaseLeadsLags ( int n ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
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
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
NumConstNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
NumConstNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
NumConstNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
NumConstNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
NumConstNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
NumConstNode : : substituteAdl ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
NumConstNode : : substituteModelLocalVariables ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
NumConstNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
NumConstNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
NumConstNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
NumConstNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
return - 1 ;
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
NumConstNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2017-06-12 14:56:44 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
NumConstNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
NumConstNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-01-30 16:33:16 +01:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2013-04-25 18:09:31 +02:00
expr_t
2013-05-17 16:51:34 +02:00
NumConstNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
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 ;
}
2016-11-25 17:15:13 +01:00
void
NumConstNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
NumConstNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
NumConstNode : : replaceTrendVar ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
expr_t
2013-03-26 16:46:18 +01:00
NumConstNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
NumConstNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2013-04-11 17:07:39 +02:00
bool
NumConstNode : : isInStaticForm ( ) const
{
return true ;
}
2018-08-09 16:14:40 +02:00
bool
NumConstNode : : isParamTimesEndogExpr ( ) const
{
return false ;
}
2016-11-25 17:15:13 +01:00
bool
NumConstNode : : isVarModelReferenced ( const string & model_info_name ) const
{
return false ;
}
2016-03-18 14:55:14 +01:00
expr_t
NumConstNode : : substituteStaticAuxiliaryVariable ( ) const
{
return const_cast < NumConstNode * > ( this ) ;
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
NumConstNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
return const_cast < NumConstNode * > ( this ) ;
}
2018-09-05 16:41:33 +02:00
VariableNode : : VariableNode ( DataTree & datatree_arg , int idx_arg , int symb_id_arg , int lag_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
symb_id { symb_id_arg } ,
lag { lag_arg }
2011-05-10 18:25:33 +02:00
{
// It makes sense to allow a lead/lag on parameters: during steady state calibration, endogenous and parameters can be swapped
2018-10-09 17:50:04 +02:00
assert ( get_type ( ) ! = SymbolType : : externalFunction
& & ( lag = = 0 | | ( get_type ( ) ! = SymbolType : : modelLocalVariable & & get_type ( ) ! = SymbolType : : modFileLocalVariable ) ) ) ;
2011-05-10 18:25:33 +02:00
}
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
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2008-02-03 11:28:36 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
case SymbolType : : exogenousDet :
case SymbolType : : parameter :
case SymbolType : : trend :
case SymbolType : : logTrend :
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 ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
datatree . getLocalVariable ( symb_id ) - > prepareForDerivation ( ) ;
2008-02-03 11:28:36 +01:00
// Non null derivatives are those of the value of the local parameter
2018-09-05 17:41:11 +02:00
non_null_derivatives = datatree . getLocalVariable ( symb_id ) - > non_null_derivatives ;
2008-02-03 11:28:36 +01:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modFileLocalVariable :
case SymbolType : : statementDeclaredVariable :
case SymbolType : : unusedEndogenous :
2008-02-03 11:28:36 +01:00
// Such a variable is never derived
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : externalFunction :
case SymbolType : : endogenousVAR :
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
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 ) ;
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
cerr < < " VariableNode::prepareForDerivation: impossible case: "
< < " You are trying to derive a variable that has been excluded via include_eqs/exclude_eqs: "
< < datatree . symbol_table . getName ( symb_id ) < < endl ;
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
VariableNode : : computeDerivative ( int deriv_id )
2008-02-03 11:28:36 +01:00
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2008-02-03 11:28:36 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
case SymbolType : : exogenousDet :
case SymbolType : : parameter :
case SymbolType : : trend :
case SymbolType : : logTrend :
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 ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > getDerivative ( deriv_id ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modFileLocalVariable :
2019-09-30 14:10:16 +02:00
cerr < < " modFileLocalVariable is not derivable " < < endl ;
2008-10-29 16:33:16 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : statementDeclaredVariable :
2019-09-30 14:10:16 +02:00
cerr < < " statementDeclaredVariable is not derivable " < < endl ;
2011-12-14 13:58:21 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : unusedEndogenous :
2019-09-30 14:10:16 +02:00
cerr < < " unusedEndogenous is not derivable " < < endl ;
2013-09-13 20:37:31 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : externalFunction :
case SymbolType : : endogenousVAR :
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
2018-09-03 17:16:28 +02:00
cerr < < " VariableNode::computeDerivative: 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
}
2015-05-12 16:36:03 +02:00
bool
VariableNode : : containsExternalFunction ( ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > containsExternalFunction ( ) ;
2015-05-12 16:36:03 +02:00
return false ;
}
2018-09-18 14:50:31 +02:00
void
VariableNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " VariableNode " , ) "
< < R " ( " name " : " ) " << datatree.symbol_table.getName(symb_id) << R " ( " , " type " : " ) " ;
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2018-09-18 14:50:31 +02:00
{
case SymbolType : : endogenous :
output < < " endogenous " ;
break ;
case SymbolType : : exogenous :
output < < " exogenous " ;
break ;
case SymbolType : : exogenousDet :
output < < " exogenousDet " ;
break ;
case SymbolType : : parameter :
output < < " parameter " ;
break ;
case SymbolType : : modelLocalVariable :
output < < " modelLocalVariable " ;
break ;
case SymbolType : : modFileLocalVariable :
output < < " modFileLocalVariable " ;
break ;
case SymbolType : : externalFunction :
output < < " externalFunction " ;
break ;
case SymbolType : : trend :
output < < " trend " ;
break ;
case SymbolType : : statementDeclaredVariable :
output < < " statementDeclaredVariable " ;
break ;
case SymbolType : : logTrend :
output < < " logTrend: " ;
break ;
case SymbolType : : unusedEndogenous :
output < < " unusedEndogenous " ;
break ;
case SymbolType : : endogenousVAR :
output < < " endogenousVAR " ;
break ;
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
output < < " epilogue " ;
break ;
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
cerr < < " VariableNode::computeDerivative: Impossible case! " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-09-18 14:50:31 +02:00
}
2019-04-03 16:32:52 +02:00
output < < R " ( " , " lag " : ) " << lag << " } " ;
2018-09-18 14:50:31 +02:00
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
VariableNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < VariableNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
2017-02-02 15:09:43 +01:00
output < < datatree . symbol_table . getName ( symb_id ) ;
2017-10-16 17:24:55 +02:00
if ( isdynamic & & lag ! = 0 )
2017-02-02 15:09:43 +01:00
output < < " ( " < < lag < < " ) " ;
}
2008-02-03 11:28:36 +01:00
void
VariableNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-10-09 17:50:04 +02:00
auto type = get_type ( ) ;
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2008-02-03 11:28:36 +01:00
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2009-12-16 18:13:23 +01:00
{
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : latexDynamicSteadyStateOperator )
2019-04-03 16:32:52 +02:00
output < < R " ( \b ar) " ;
2020-01-06 18:22:31 +01:00
output < < " { " < < datatree . symbol_table . getTeXName ( symb_id ) < < " } " ;
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : latexDynamicModel
2021-02-19 17:45:58 +01:00
& & ( type = = SymbolType : : endogenous | | type = = SymbolType : : exogenous | | type = = SymbolType : : exogenousDet | | type = = SymbolType : : trend | | type = = SymbolType : : logTrend ) )
2009-12-16 18:13:23 +01:00
{
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
}
return ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
int i ;
2020-09-23 17:02:25 +02:00
switch ( type )
2009-12-16 18:13:23 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : parameter :
2020-09-23 17:02:25 +02:00
if ( int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
output_type = = ExprNodeOutputType : : matlabOutsideModel )
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
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2020-05-25 15:42:16 +02:00
if ( output_type = = ExprNodeOutputType : : matlabDynamicSteadyStateOperator
2018-09-05 18:27:13 +02:00
| | output_type = = ExprNodeOutputType : : CDynamicSteadyStateOperator )
2009-12-16 18:13:23 +01:00
{
output < < " ( " ;
2018-09-05 17:41:11 +02:00
datatree . getLocalVariable ( symb_id ) - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " ) " ;
}
else
2018-05-28 16:39:28 +02:00
/* We append underscores to avoid name clashes with "g1" or "oo_".
But we probably never arrive here because MLV are temporary terms … */
2011-02-21 16:32:21 +01:00
output < < datatree . symbol_table . getName ( symb_id ) < < " __ " ;
2009-12-16 18:13:23 +01:00
break ;
2009-06-05 16:45:23 +02:00
2018-07-17 18:34:07 +02:00
case SymbolType : : modFileLocalVariable :
2010-04-23 18:39:07 +02:00
output < < datatree . symbol_table . getName ( symb_id ) ;
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2020-09-23 17:02:25 +02:00
switch ( int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
output_type )
2009-12-16 18:13:23 +01:00
{
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaDynamicModel :
case ExprNodeOutputType : : matlabDynamicModel :
case ExprNodeOutputType : : CDynamicModel :
2009-12-16 18:13:23 +01:00
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 ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CStaticModel :
case ExprNodeOutputType : : juliaStaticModel :
case ExprNodeOutputType : : matlabStaticModel :
2009-12-16 18:13:23 +01:00
i = tsid + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
output < < " y " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabOutsideModel :
2009-12-16 18:13:23 +01:00
output < < " oo_.steady_state( " < < tsid + 1 < < " ) " ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaDynamicSteadyStateOperator :
case ExprNodeOutputType : : matlabDynamicSteadyStateOperator :
2015-07-27 17:02:51 +02:00
output < < " steady_state " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tsid + 1 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CDynamicSteadyStateOperator :
2010-09-20 17:04:38 +02:00
output < < " steady_state[ " < < tsid < < " ] " ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaSteadyStateFile :
case ExprNodeOutputType : : steadyStateFile :
2015-07-28 17:27:56 +02:00
output < < " ys_ " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tsid + 1 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-04-23 18:39:07 +02:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDseries :
2018-03-02 17:50:35 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
if ( lag ! = 0 )
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < lag < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : epilogueFile :
2019-12-12 14:46:45 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
2018-12-19 16:09:30 +01:00
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " t " ;
if ( lag ! = 0 )
output < < lag ;
output < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-09-03 17:16:28 +02:00
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2009-06-05 16:45:23 +02:00
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2020-09-23 17:02:25 +02:00
i = datatree . symbol_table . getTypeSpecificID ( symb_id ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
2009-12-16 18:13:23 +01:00
switch ( output_type )
{
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaDynamicModel :
case ExprNodeOutputType : : matlabDynamicModel :
2009-12-16 18:13:23 +01:00
if ( lag > 0 )
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_+ " < < lag < < " , " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
else if ( lag < 0 )
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_ " < < lag < < " , " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
else
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_, " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CDynamicModel :
2009-12-16 18:13:23 +01:00
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 ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CStaticModel :
case ExprNodeOutputType : : juliaStaticModel :
case ExprNodeOutputType : : matlabStaticModel :
2009-12-16 18:13:23 +01:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabOutsideModel :
2009-12-16 18:13:23 +01:00
assert ( lag = = 0 ) ;
2015-01-14 15:14:57 +01:00
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDynamicSteadyStateOperator :
2015-01-14 15:14:57 +01:00
output < < " oo_.exo_steady_state( " < < i < < " ) " ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaSteadyStateFile :
case ExprNodeOutputType : : steadyStateFile :
2015-07-28 17:27:56 +02:00
output < < " exo_ " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-04-23 18:39:07 +02:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDseries :
2018-03-02 17:50:35 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
if ( lag ! = 0 )
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < lag < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : epilogueFile :
2019-12-12 14:46:45 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
2018-12-19 16:09:30 +01:00
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " t " ;
2018-09-03 17:16:28 +02:00
if ( lag ! = 0 )
2018-12-19 16:09:30 +01:00
output < < lag ;
output < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-09-03 17:16:28 +02:00
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2009-06-05 16:45:23 +02:00
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2020-09-23 17:02:25 +02:00
i = datatree . symbol_table . getTypeSpecificID ( symb_id ) + datatree . symbol_table . exo_nbr ( ) + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
2009-12-16 18:13:23 +01:00
switch ( output_type )
{
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaDynamicModel :
case ExprNodeOutputType : : matlabDynamicModel :
2009-12-16 18:13:23 +01:00
if ( lag > 0 )
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_+ " < < lag < < " , " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
else if ( lag < 0 )
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_ " < < lag < < " , " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
else
2015-07-27 17:02:51 +02:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " it_, " < < i
< < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CDynamicModel :
2009-12-16 18:13:23 +01:00
if ( lag = = 0 )
2010-12-08 11:33:20 +01:00
output < < " x[it_+ " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
else if ( lag > 0 )
2010-12-08 11:33:20 +01:00
output < < " x[it_+ " < < lag < < " + " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
else
2010-12-08 11:33:20 +01:00
output < < " x[it_ " < < lag < < " + " < < i < < " *nb_row_x] " ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CStaticModel :
case ExprNodeOutputType : : juliaStaticModel :
case ExprNodeOutputType : : matlabStaticModel :
2009-12-16 18:13:23 +01:00
output < < " x " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabOutsideModel :
2009-12-16 18:13:23 +01:00
assert ( lag = = 0 ) ;
2020-09-23 17:02:25 +02:00
output < < " oo_.exo_det_steady_state( " < < datatree . symbol_table . getTypeSpecificID ( symb_id ) + 1 < < " ) " ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDynamicSteadyStateOperator :
2020-09-23 17:02:25 +02:00
output < < " oo_.exo_det_steady_state( " < < datatree . symbol_table . getTypeSpecificID ( symb_id ) + 1 < < " ) " ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaSteadyStateFile :
case ExprNodeOutputType : : steadyStateFile :
2015-07-28 17:27:56 +02:00
output < < " exo_ " < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < i < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-04-23 18:39:07 +02:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDseries :
2018-03-02 17:50:35 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
if ( lag ! = 0 )
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < lag < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : epilogueFile :
2019-12-12 14:46:45 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
2018-12-19 16:09:30 +01:00
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " t " ;
2018-09-03 17:16:28 +02:00
if ( lag ! = 0 )
2018-12-19 16:09:30 +01:00
output < < lag ;
output < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-09-03 17:16:28 +02:00
break ;
2009-12-16 18:13:23 +01:00
default :
2011-01-13 15:52:44 +01:00
cerr < < " VariableNode::writeOutput: should not reach this point " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
if ( output_type = = ExprNodeOutputType : : epilogueFile )
{
2019-12-12 14:46:45 +01:00
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
2018-12-19 16:09:30 +01:00
output < < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < " t " ;
2018-12-10 16:11:21 +01:00
if ( lag ! = 0 )
2018-12-19 16:09:30 +01:00
output < < lag ;
output < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-12-10 16:11:21 +01:00
}
2019-12-12 16:06:39 +01:00
else if ( output_type = = ExprNodeOutputType : : matlabDseries )
// Only writing dseries for epilogue_static, hence no need to check lag
output < < " ds. " < < datatree . symbol_table . getName ( symb_id ) ;
2018-12-10 16:11:21 +01:00
else
{
cerr < < " VariableNode::writeOutput: Impossible case " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-12-12 16:06:39 +01:00
break ;
2019-09-30 14:15:36 +02:00
case SymbolType : : unusedEndogenous :
2019-09-30 14:27:58 +02:00
cerr < < " ERROR: You cannot use an endogenous variable in an expression if that variable has not been used in the model block. " < < endl ;
2019-09-30 14:15:36 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : externalFunction :
case SymbolType : : trend :
case SymbolType : : logTrend :
case SymbolType : : statementDeclaredVariable :
case SymbolType : : endogenousVAR :
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
2018-09-03 17:16:28 +02:00
cerr < < " VariableNode::writeOutput: Impossible case " < < endl ;
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
}
2008-02-03 11:28:36 +01:00
2016-03-18 14:55:14 +01:00
expr_t
VariableNode : : substituteStaticAuxiliaryVariable ( ) const
{
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = SymbolType : : endogenous )
2019-10-25 12:29:58 +02:00
try
{
return datatree . symbol_table . getAuxiliaryVarsExprNode ( symb_id ) - > substituteStaticAuxiliaryVariable ( ) ;
}
catch ( SymbolTable : : SearchFailedException & e )
{
}
2016-03-18 14:55:14 +01:00
return const_cast < VariableNode * > ( this ) ;
}
2017-06-01 19:58:32 +02:00
2008-02-03 11:28:36 +01:00
double
2018-06-04 12:50:53 +02:00
VariableNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2008-02-03 11:28:36 +01:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > eval ( eval_context ) ;
2018-06-04 15:03:26 +02:00
auto 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-12-10 11:50:27 +01:00
VariableNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-10-09 17:50:04 +02:00
auto type = get_type ( ) ;
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : modelLocalVariable | | type = = SymbolType : : modFileLocalVariable )
2020-05-13 12:53:47 +02:00
datatree . getLocalVariable ( symb_id ) - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2009-12-16 18:13:23 +01:00
else
{
int tsid = datatree . symbol_table . getTypeSpecificID ( symb_id ) ;
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : exogenousDet )
2009-12-16 18:13:23 +01:00
tsid + = datatree . symbol_table . exo_nbr ( ) ;
if ( ! lhs_rhs )
{
if ( dynamic )
{
2019-12-20 16:59:30 +01:00
if ( steady_dynamic ) // steady state values in a dynamic model
2009-12-16 18:13:23 +01:00
{
2018-07-17 18:34:07 +02:00
FLDVS_ fldvs { static_cast < uint8_t > ( type ) , static_cast < unsigned int > ( tsid ) } ;
2010-07-23 11:20:24 +02:00
fldvs . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : parameter )
2009-12-16 18:13:23 +01:00
{
2018-07-17 18:34:07 +02:00
FLDV_ fldv { static_cast < int > ( type ) , static_cast < unsigned int > ( tsid ) } ;
2010-07-23 11:20:24 +02:00
fldv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2018-07-17 18:34:07 +02:00
FLDV_ fldv { static_cast < int > ( type ) , static_cast < unsigned int > ( tsid ) , lag } ;
2010-07-23 11:20:24 +02:00
fldv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
else
{
2018-07-17 18:34:07 +02:00
FLDSV_ fldsv { static_cast < uint8_t > ( type ) , static_cast < unsigned int > ( tsid ) } ;
2010-07-23 11:20:24 +02:00
fldsv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
else
{
if ( dynamic )
{
2019-12-20 16:59:30 +01:00
if ( steady_dynamic ) // steady state values in a dynamic model
2009-12-16 18:13:23 +01:00
{
cerr < < " Impossible case: steady_state in rhs of equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
{
2018-07-17 18:34:07 +02:00
if ( type = = SymbolType : : parameter )
2009-12-16 18:13:23 +01:00
{
2018-07-17 18:34:07 +02:00
FSTPV_ fstpv { static_cast < int > ( type ) , static_cast < unsigned int > ( tsid ) } ;
2010-07-23 11:20:24 +02:00
fstpv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2018-07-17 18:34:07 +02:00
FSTPV_ fstpv { static_cast < int > ( type ) , static_cast < unsigned int > ( tsid ) , lag } ;
2010-07-23 11:20:24 +02:00
fstpv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
else
{
2018-07-17 18:34:07 +02:00
FSTPSV_ fstpsv { static_cast < uint8_t > ( type ) , static_cast < unsigned int > ( tsid ) } ;
2010-07-23 11:20:24 +02:00
fstpsv . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
}
}
2008-02-03 11:28:36 +01:00
2018-04-16 13:50:31 +02:00
void
VariableNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = SymbolType : : endogenous & & lag = = 0 )
2018-04-16 13:50:31 +02:00
result . insert ( const_cast < VariableNode * > ( this ) ) ;
else
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have endogenous variables or unary ops on LHS of VAR " < < endl ;
2018-04-16 13:50:31 +02:00
exit ( EXIT_FAILURE ) ;
}
}
2008-02-03 11:28:36 +01:00
void
2018-06-04 14:17:36 +02:00
VariableNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2009-07-10 18:42:08 +02:00
{
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = type_arg )
2018-06-04 16:36:46 +02:00
result . emplace ( symb_id , lag ) ;
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
2018-09-05 17:41:11 +02:00
datatree . getLocalVariable ( symb_id ) - > collectDynamicVariables ( type_arg , result ) ;
2013-09-13 20:37:31 +02:00
}
2020-04-02 14:36:26 +02:00
void
VariableNode : : computeSubExprContainingVariable ( int symb_id_arg , int lag_arg , set < expr_t > & contain_var ) const
{
if ( symb_id = = symb_id_arg & & lag = = lag_arg )
contain_var . insert ( const_cast < VariableNode * > ( this ) ) ;
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
datatree . getLocalVariable ( symb_id ) - > computeSubExprContainingVariable ( symb_id_arg , lag_arg , contain_var ) ;
2020-04-02 14:36:26 +02:00
}
BinaryOpNode *
VariableNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
assert ( contain_var . count ( const_cast < VariableNode * > ( this ) ) > 0 ) ;
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > normalizeEquationHelper ( contain_var , rhs ) ;
2020-04-02 14:36:26 +02:00
// This the LHS variable: we have finished the normalization
return datatree . AddEqual ( const_cast < VariableNode * > ( this ) , rhs ) ;
2009-12-16 18:13:23 +01:00
}
2009-06-05 16:45:23 +02:00
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
VariableNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-06-05 16:45:23 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
case SymbolType : : exogenousDet :
case SymbolType : : parameter :
case SymbolType : : trend :
case SymbolType : : logTrend :
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 ;
2020-04-24 17:09:28 +02:00
// If there is in the equation a recursive variable we could use a chaine rule derivation
else if ( auto it = recursive_variables . find ( datatree . getDerivID ( symb_id , lag ) ) ;
it ! = recursive_variables . end ( ) )
2020-10-02 18:31:55 +02:00
return it - > second - > arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2020-04-24 17:09:28 +02:00
else
return datatree . Zero ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modFileLocalVariable :
2019-09-30 14:10:16 +02:00
cerr < < " modFileLocalVariable is not derivable " < < endl ;
2009-06-05 16:45:23 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : statementDeclaredVariable :
2019-09-30 14:10:16 +02:00
cerr < < " statementDeclaredVariable is not derivable " < < endl ;
2011-12-14 13:58:21 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : unusedEndogenous :
2019-09-30 14:10:16 +02:00
cerr < < " unusedEndogenous is not derivable " < < endl ;
2013-09-13 20:37:31 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : externalFunction :
case SymbolType : : endogenousVAR :
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
2018-09-03 17:16:28 +02:00
cerr < < " VariableNode::getChainRuleDerivative: Impossible case " < < endl ;
2009-06-05 16:45:23 +02:00
exit ( EXIT_FAILURE ) ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
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
2015-12-18 15:17:32 +01:00
void
VariableNode : : computeXrefs ( EquationInfo & ei ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2015-12-18 15:17:32 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2018-06-04 16:36:46 +02:00
ei . endo . emplace ( symb_id , lag ) ;
2015-12-18 15:17:32 +01:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2018-06-04 16:36:46 +02:00
ei . exo . emplace ( symb_id , lag ) ;
2015-12-18 15:17:32 +01:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenousDet :
2018-06-04 16:36:46 +02:00
ei . exo_det . emplace ( symb_id , lag ) ;
2015-12-18 15:17:32 +01:00
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : parameter :
2018-06-04 16:36:46 +02:00
ei . param . emplace ( symb_id , 0 ) ;
2015-12-18 15:17:32 +01:00
break ;
2020-09-29 17:54:56 +02:00
case SymbolType : : modFileLocalVariable :
datatree . getLocalVariable ( symb_id ) - > computeXrefs ( ei ) ;
break ;
2018-07-17 18:34:07 +02:00
case SymbolType : : trend :
case SymbolType : : logTrend :
case SymbolType : : modelLocalVariable :
case SymbolType : : statementDeclaredVariable :
case SymbolType : : unusedEndogenous :
case SymbolType : : externalFunction :
case SymbolType : : endogenousVAR :
2018-12-10 16:11:21 +01:00
case SymbolType : : epilogue :
2019-11-18 17:13:49 +01:00
case SymbolType : : excludedVariable :
2015-12-18 15:17:32 +01:00
break ;
}
}
2018-10-09 17:50:04 +02:00
SymbolType
VariableNode : : get_type ( ) const
{
return datatree . symbol_table . getType ( symb_id ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
2018-10-10 13:07:25 +02:00
VariableNode : : clone ( DataTree & datatree ) const
2010-10-15 19:05:16 +02:00
{
2018-10-10 13:07:25 +02:00
return datatree . AddVariable ( symb_id , lag ) ;
2010-10-15 19:05:16 +02:00
}
2009-09-30 17:10:31 +02:00
int
VariableNode : : maxEndoLead ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-09-30 17:10:31 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2009-09-30 17:10:31 +02:00
return max ( lag , 0 ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxEndoLead ( ) ;
2009-09-30 17:10:31 +02:00
default :
return 0 ;
}
}
2009-10-07 18:34:42 +02:00
int
VariableNode : : maxExoLead ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-10-07 18:34:42 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2009-10-07 18:34:42 +02:00
return max ( lag , 0 ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxExoLead ( ) ;
2009-10-07 18:34:42 +02:00
default :
return 0 ;
}
}
2010-08-19 15:20:54 +02:00
int
VariableNode : : maxEndoLag ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2010-08-19 15:20:54 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2010-08-19 15:20:54 +02:00
return max ( - lag , 0 ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxEndoLag ( ) ;
2010-08-19 15:20:54 +02:00
default :
return 0 ;
}
}
int
VariableNode : : maxExoLag ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2010-08-19 15:20:54 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2010-08-19 15:20:54 +02:00
return max ( - lag , 0 ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxExoLag ( ) ;
2010-08-19 15:20:54 +02:00
default :
return 0 ;
}
}
2012-05-26 20:53:48 +02:00
int
VariableNode : : maxLead ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2012-05-26 20:53:48 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
2018-12-05 15:17:00 +01:00
case SymbolType : : exogenousDet :
2012-05-26 20:53:48 +02:00
return lag ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxLead ( ) ;
2012-05-26 20:53:48 +02:00
default :
return 0 ;
}
}
2018-05-16 12:17:06 +02:00
int
VariableNode : : VarMinLag ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2018-05-16 12:17:06 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2018-05-16 12:17:06 +02:00
return - lag ;
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2018-05-16 12:17:06 +02:00
if ( lag > 0 )
return - lag ;
else
return 1 ; // Can have contemporaneus exog in VAR
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > VarMinLag ( ) ;
2018-05-16 12:17:06 +02:00
default :
return 1 ;
}
}
2018-02-28 17:33:00 +01:00
int
VariableNode : : maxLag ( ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2018-02-28 17:33:00 +01:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
2018-12-05 15:17:00 +01:00
case SymbolType : : exogenousDet :
2018-02-28 17:33:00 +01:00
return - lag ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > maxLag ( ) ;
2018-02-28 17:33:00 +01:00
default :
return 0 ;
}
}
2018-12-05 15:17:00 +01:00
int
VariableNode : : maxLagWithDiffsExpanded ( ) const
{
switch ( get_type ( ) )
{
case SymbolType : : endogenous :
case SymbolType : : exogenous :
case SymbolType : : exogenousDet :
2018-12-19 16:09:30 +01:00
case SymbolType : : epilogue :
2018-12-05 15:17:00 +01:00
return - lag ;
case SymbolType : : modelLocalVariable :
return datatree . getLocalVariable ( symb_id ) - > maxLagWithDiffsExpanded ( ) ;
default :
return 0 ;
}
}
2018-04-17 15:17:28 +02:00
expr_t
VariableNode : : undiff ( ) const
{
return const_cast < VariableNode * > ( this ) ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
VariableNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2019-10-22 16:04:24 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
2019-10-25 12:29:58 +02:00
if ( lhs_lag_equiv . find ( lag_equiv_repr ) = = lhs_lag_equiv . end ( ) )
2018-06-11 10:40:00 +02:00
return 0 ;
return maxLag ( ) ;
2018-04-16 13:50:31 +02:00
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
VariableNode : : substituteAdl ( ) const
{
2021-02-19 17:45:02 +01:00
/* Do not recurse into model-local variables definition, rather do it at the
DynamicModel method level ( see the comment there ) */
2018-01-30 10:06:56 +01:00
return const_cast < VariableNode * > ( this ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
VariableNode : : substituteModelLocalVariables ( ) const
{
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) ;
return const_cast < VariableNode * > ( this ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
VariableNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > substituteVarExpectation ( subst_table ) ;
2018-08-01 19:41:44 +02:00
return const_cast < VariableNode * > ( this ) ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
VariableNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
datatree . getLocalVariable ( symb_id ) - > findDiffNodes ( nodes ) ;
2018-03-02 12:32:01 +01:00
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
VariableNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
datatree . getLocalVariable ( symb_id ) - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
VariableNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
return - 1 ;
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
VariableNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2017-06-12 14:56:44 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > substituteDiff ( nodes , subst_table , neweqs ) ;
2017-06-12 14:56:44 +02:00
return const_cast < VariableNode * > ( this ) ;
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
VariableNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
return const_cast < VariableNode * > ( this ) ;
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
VariableNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-01-30 16:33:16 +01:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > substitutePacExpectation ( name , subexpr ) ;
2018-01-30 16:33:16 +01:00
return const_cast < VariableNode * > ( this ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
VariableNode : : decreaseLeadsLags ( int n ) const
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-09-30 17:10:31 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
case SymbolType : : exogenous :
case SymbolType : : exogenousDet :
case SymbolType : : trend :
case SymbolType : : logTrend :
2009-09-30 17:10:31 +02:00
return datatree . AddVariable ( symb_id , lag - n ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2018-09-05 17:41:11 +02:00
return datatree . getLocalVariable ( symb_id ) - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
VariableNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2021-02-19 20:11:33 +01:00
/* Do not recurse into model-local variables definitions, since MLVs are
already handled by DynamicModel : : transformPredeterminedVariables ( ) .
This is also necessary because of # 65. */
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 ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
VariableNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-09-30 17:10:31 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2009-09-30 17:10:31 +02:00
if ( lag < = 1 )
return const_cast < VariableNode * > ( this ) ;
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2019-10-28 11:09:36 +01:00
if ( expr_t value = datatree . getLocalVariable ( symb_id ) ; value - > maxEndoLead ( ) < = 1 )
2009-09-30 17:10:31 +02:00
return const_cast < VariableNode * > ( this ) ;
else
2010-08-18 13:45:07 +02:00
return value - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
2009-09-30 17:10:31 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
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 ;
int cur_lag ;
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-09-30 17:10:31 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2009-09-30 17:10:31 +02:00
if ( lag > = - 1 )
return const_cast < VariableNode * > ( this ) ;
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( this ) ; it ! = subst_table . end ( ) )
2009-09-30 17:10:31 +02:00
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 ) ;
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( orig_expr ) ; it = = subst_table . end ( ) )
2009-09-30 17:10:31 +02:00
{
2016-03-18 14:55:14 +01:00
int aux_symb_id = datatree . symbol_table . addEndoLagAuxiliaryVar ( symb_id , cur_lag + 1 , substexpr ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , substexpr ) ) ;
2009-09-30 17:10:31 +02:00
substexpr = datatree . AddVariable ( aux_symb_id , - 1 ) ;
subst_table [ orig_expr ] = substexpr ;
}
else
substexpr = const_cast < VariableNode * > ( it - > second ) ;
cur_lag - - ;
}
return substexpr ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2019-10-28 11:09:36 +01:00
if ( expr_t value = datatree . getLocalVariable ( symb_id ) ; value - > maxEndoLag ( ) < = 1 )
2010-08-19 15:20:54 +02:00
return const_cast < VariableNode * > ( this ) ;
else
return value - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
VariableNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-10-07 18:34:42 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2009-10-07 18:34:42 +02:00
if ( lag < = 0 )
return const_cast < VariableNode * > ( this ) ;
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2019-10-28 11:09:36 +01:00
if ( expr_t value = datatree . getLocalVariable ( symb_id ) ; value - > maxExoLead ( ) = = 0 )
2009-10-07 18:34:42 +02:00
return const_cast < VariableNode * > ( this ) ;
else
2010-08-18 13:45:07 +02:00
return value - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
default :
return const_cast < VariableNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
VariableNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-10-07 16:07:13 +02:00
{
VariableNode * substexpr ;
int cur_lag ;
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2009-10-07 16:07:13 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : exogenous :
2009-10-07 18:34:42 +02:00
if ( lag > = 0 )
2009-10-07 16:07:13 +02:00
return const_cast < VariableNode * > ( this ) ;
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( this ) ; it ! = subst_table . end ( ) )
2009-10-07 16:07:13 +02:00
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 ) ;
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( orig_expr ) ; it = = subst_table . end ( ) )
2009-10-07 16:07:13 +02:00
{
2016-03-18 14:55:14 +01:00
int aux_symb_id = datatree . symbol_table . addExoLagAuxiliaryVar ( symb_id , cur_lag + 1 , substexpr ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , substexpr ) ) ;
2009-10-07 18:34:42 +02:00
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
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2019-10-28 11:09:36 +01:00
if ( expr_t value = datatree . getLocalVariable ( symb_id ) ; value - > maxExoLag ( ) = = 0 )
2010-08-19 15:20:54 +02:00
return const_cast < VariableNode * > ( this ) ;
else
return value - > 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
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
VariableNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-29 18:16:10 +01:00
return const_cast < VariableNode * > ( this ) ;
}
2013-04-25 18:09:31 +02:00
expr_t
2013-05-17 16:51:34 +02:00
VariableNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
2018-10-09 17:50:04 +02:00
switch ( get_type ( ) )
2013-04-25 18:09:31 +02:00
{
2018-07-17 18:34:07 +02:00
case SymbolType : : endogenous :
2013-04-25 18:09:31 +02:00
assert ( lag < = 1 ) ;
2013-05-17 16:51:34 +02:00
if ( lag < = 0
| | ( subset . size ( ) > 0
& & find ( subset . begin ( ) , subset . end ( ) , datatree . symbol_table . getName ( symb_id ) ) = = subset . end ( ) ) )
2013-04-25 18:09:31 +02:00
return const_cast < VariableNode * > ( this ) ;
else
{
VariableNode * diffvar ;
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( this ) ; it ! = subst_table . end ( ) )
2013-04-25 18:09:31 +02:00
diffvar = const_cast < VariableNode * > ( it - > second ) ;
else
{
2016-03-18 14:55:14 +01:00
int aux_symb_id = datatree . symbol_table . addDiffForwardAuxiliaryVar ( symb_id , datatree . AddMinus ( datatree . AddVariable ( symb_id , 0 ) ,
datatree . AddVariable ( symb_id , - 1 ) ) ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( datatree . AddVariable ( aux_symb_id , 0 ) , datatree . AddMinus ( datatree . AddVariable ( symb_id , 0 ) ,
datatree . AddVariable ( symb_id , - 1 ) ) ) ) ;
2013-04-25 18:09:31 +02:00
diffvar = datatree . AddVariable ( aux_symb_id , 1 ) ;
subst_table [ this ] = diffvar ;
}
return datatree . AddPlus ( datatree . AddVariable ( symb_id , 0 ) , diffvar ) ;
}
2018-07-17 18:34:07 +02:00
case SymbolType : : modelLocalVariable :
2019-10-28 11:09:36 +01:00
if ( expr_t value = datatree . getLocalVariable ( symb_id ) ; value - > maxEndoLead ( ) < = 0 )
2013-04-25 18:09:31 +02:00
return const_cast < VariableNode * > ( this ) ;
else
2013-05-17 16:51:34 +02:00
return value - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
default :
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
{
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = type_arg & & datatree . symbol_table . getTypeSpecificID ( symb_id ) = = variable_id & & lag = = lag_arg )
2010-04-16 16:54:55 +02:00
return true ;
else
return false ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
VariableNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > containsPacExpectation ( pac_model_name ) ;
2018-06-05 18:38:53 +02:00
return false ;
}
2010-10-15 19:05:16 +02:00
expr_t
VariableNode : : replaceTrendVar ( ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > replaceTrendVar ( ) ;
2018-07-17 18:34:07 +02:00
if ( get_type ( ) = = SymbolType : : trend )
2010-10-15 19:05:16 +02:00
return datatree . One ;
2018-07-17 18:34:07 +02:00
else if ( get_type ( ) = = SymbolType : : logTrend )
2013-03-26 16:46:18 +01:00
return datatree . Zero ;
2010-10-15 19:05:16 +02:00
else
return const_cast < VariableNode * > ( this ) ;
}
expr_t
2013-03-26 16:46:18 +01:00
VariableNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > detrend ( symb_id , log_trend , trend ) ;
2018-11-28 14:32:26 +01:00
if ( this - > symb_id ! = symb_id )
2010-10-15 19:05:16 +02:00
return const_cast < VariableNode * > ( this ) ;
2013-03-26 16:46:18 +01:00
if ( log_trend )
{
2018-11-28 14:32:26 +01:00
if ( lag = = 0 )
2013-03-26 16:46:18 +01:00
return datatree . AddPlus ( const_cast < VariableNode * > ( this ) , trend ) ;
else
2018-11-28 14:32:26 +01:00
return datatree . AddPlus ( const_cast < VariableNode * > ( this ) , trend - > decreaseLeadsLags ( - lag ) ) ;
2013-03-26 16:46:18 +01:00
}
2010-10-15 19:05:16 +02:00
else
2013-03-26 16:46:18 +01:00
{
2018-11-28 14:32:26 +01:00
if ( lag = = 0 )
2013-03-26 16:46:18 +01:00
return datatree . AddTimes ( const_cast < VariableNode * > ( this ) , trend ) ;
else
2018-11-28 14:32:26 +01:00
return datatree . AddTimes ( const_cast < VariableNode * > ( this ) , trend - > decreaseLeadsLags ( - lag ) ) ;
2013-03-26 16:46:18 +01:00
}
2010-10-15 19:05:16 +02:00
}
2018-05-31 15:34:25 +02:00
int
VariableNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > countDiffs ( ) ;
2018-05-31 15:34:25 +02:00
return 0 ;
2018-02-08 13:07:15 +01:00
}
2010-10-15 19:05:16 +02:00
expr_t
2019-07-05 18:22:02 +02:00
VariableNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > removeTrendLeadLag ( trend_symbols_map ) ;
2018-11-28 14:32:26 +01:00
if ( ( get_type ( ) ! = SymbolType : : trend & & get_type ( ) ! = SymbolType : : logTrend ) | | lag = = 0 )
2010-10-15 19:05:16 +02:00
return const_cast < VariableNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
auto it = trend_symbols_map . find ( symb_id ) ;
2018-09-05 16:41:33 +02:00
expr_t noTrendLeadLagNode = datatree . AddVariable ( it - > first ) ;
2018-07-17 18:34:07 +02:00
bool log_trend = get_type ( ) = = SymbolType : : logTrend ;
2013-03-26 16:46:18 +01:00
expr_t trend = it - > second ;
2017-06-01 19:58:32 +02:00
2018-11-28 14:32:26 +01:00
if ( lag > 0 )
2010-10-15 19:05:16 +02:00
{
2013-03-26 16:46:18 +01:00
expr_t growthFactorSequence = trend - > decreaseLeadsLags ( - 1 ) ;
if ( log_trend )
{
2018-11-28 14:32:26 +01:00
for ( int i = 1 ; i < lag ; i + + )
2013-03-26 16:46:18 +01:00
growthFactorSequence = datatree . AddPlus ( growthFactorSequence , trend - > decreaseLeadsLags ( - 1 * ( i + 1 ) ) ) ;
return datatree . AddPlus ( noTrendLeadLagNode , growthFactorSequence ) ;
}
else
{
2018-11-28 14:32:26 +01:00
for ( int i = 1 ; i < lag ; i + + )
2013-03-26 16:46:18 +01:00
growthFactorSequence = datatree . AddTimes ( growthFactorSequence , trend - > decreaseLeadsLags ( - 1 * ( i + 1 ) ) ) ;
return datatree . AddTimes ( noTrendLeadLagNode , growthFactorSequence ) ;
}
2010-10-15 19:05:16 +02:00
}
else //get_lag < 0
{
2013-03-26 16:46:18 +01:00
expr_t growthFactorSequence = trend ;
if ( log_trend )
{
2018-11-28 14:32:26 +01:00
for ( int i = 1 ; i < abs ( lag ) ; i + + )
2013-03-26 16:46:18 +01:00
growthFactorSequence = datatree . AddPlus ( growthFactorSequence , trend - > decreaseLeadsLags ( i ) ) ;
return datatree . AddMinus ( noTrendLeadLagNode , growthFactorSequence ) ;
}
else
{
2018-11-28 14:32:26 +01:00
for ( int i = 1 ; i < abs ( lag ) ; i + + )
2013-03-26 16:46:18 +01:00
growthFactorSequence = datatree . AddTimes ( growthFactorSequence , trend - > decreaseLeadsLags ( i ) ) ;
return datatree . AddDivide ( noTrendLeadLagNode , growthFactorSequence ) ;
}
2010-10-15 19:05:16 +02:00
}
}
2013-04-11 17:07:39 +02:00
bool
VariableNode : : isInStaticForm ( ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > isInStaticForm ( ) ;
2013-04-11 17:07:39 +02:00
return lag = = 0 ;
}
2018-08-09 16:14:40 +02:00
bool
VariableNode : : isParamTimesEndogExpr ( ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > isParamTimesEndogExpr ( ) ;
2018-08-09 16:14:40 +02:00
return false ;
}
2016-11-25 17:15:13 +01:00
bool
VariableNode : : isVarModelReferenced ( const string & model_info_name ) const
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > isVarModelReferenced ( model_info_name ) ;
2016-11-25 17:15:13 +01:00
return false ;
}
void
VariableNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
2016-11-18 16:52:13 +01:00
{
2020-09-29 17:54:56 +02:00
if ( get_type ( ) = = SymbolType : : modelLocalVariable )
return datatree . getLocalVariable ( symb_id ) - > getEndosAndMaxLags ( model_endos_and_lags ) ;
2018-10-09 17:50:04 +02:00
if ( get_type ( ) = = SymbolType : : endogenous )
2019-10-28 11:09:36 +01:00
if ( string varname = datatree . symbol_table . getName ( symb_id ) ;
model_endos_and_lags . find ( varname ) = = model_endos_and_lags . end ( ) )
2016-11-25 17:15:13 +01:00
model_endos_and_lags [ varname ] = min ( model_endos_and_lags [ varname ] , lag ) ;
else
model_endos_and_lags [ varname ] = lag ;
2016-11-18 16:52:13 +01:00
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
VariableNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
2021-02-19 20:11:33 +01:00
/* Do not recurse into model-local variables definitions, since MLVs are
already handled by ModelTree : : simplifyEquations ( ) .
This is also necessary because of # 65. */
2019-12-20 16:59:30 +01:00
for ( auto & it : table )
2019-01-29 17:29:24 +01:00
if ( it . first - > symb_id = = symb_id )
return it . second ;
2019-01-28 14:57:30 +01:00
return const_cast < VariableNode * > ( this ) ;
}
2020-07-28 18:29:45 +02:00
void
VariableNode : : matchMatchedMoment ( vector < int > & symb_ids , vector < int > & lags , vector < int > & powers ) const
{
2020-09-29 17:54:56 +02:00
/* Used for simple expression outside model block, so no need to special-case
model local variables */
2020-07-28 18:29:45 +02:00
if ( get_type ( ) ! = SymbolType : : endogenous )
throw MatchFailureException { " Variable " + datatree . symbol_table . getName ( symb_id ) + " is not an endogenous " } ;
symb_ids . push_back ( symb_id ) ;
lags . push_back ( lag ) ;
powers . push_back ( 1 ) ;
}
2018-09-05 16:41:33 +02:00
UnaryOpNode : : UnaryOpNode ( DataTree & datatree_arg , int idx_arg , UnaryOpcode op_code_arg , const expr_t arg_arg , int expectation_information_set_arg , int param1_symb_id_arg , int param2_symb_id_arg , string adl_param_name_arg , vector < int > adl_lags_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
arg { arg_arg } ,
expectation_information_set { expectation_information_set_arg } ,
param1_symb_id { param1_symb_id_arg } ,
param2_symb_id { param2_symb_id_arg } ,
op_code { op_code_arg } ,
adl_param_name { move ( adl_param_name_arg ) } ,
adl_lags { move ( adl_lags_arg ) }
2008-02-03 11:28:36 +01:00
{
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
2011-01-13 18:08:26 +01:00
// Non-null derivatives are those of the argument (except for STEADY_STATE)
2008-02-03 11:28:36 +01:00
non_null_derivatives = arg - > non_null_derivatives ;
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : steadyState | | op_code = = UnaryOpcode : : steadyStateParamDeriv
| | op_code = = UnaryOpcode : : steadyStateParam2ndDeriv )
2011-01-13 18:08:26 +01:00
datatree . addAllParamDerivId ( non_null_derivatives ) ;
2008-02-03 11:28:36 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2011-01-13 18:08:26 +01:00
UnaryOpNode : : composeDerivatives ( expr_t darg , int deriv_id )
2008-02-03 11:28:36 +01:00
{
2012-12-07 21:45:16 +01:00
expr_t t11 , t12 , t13 , t14 ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2008-02-03 11:28:36 +01:00
return datatree . AddUMinus ( darg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2008-02-03 11:28:36 +01:00
return datatree . AddTimes ( darg , this ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2008-02-03 11:28:36 +01:00
return datatree . AddDivide ( darg , arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddExp ( datatree . One ) ;
t12 = datatree . AddLog10 ( t11 ) ;
t13 = datatree . AddDivide ( darg , arg ) ;
return datatree . AddTimes ( t12 , t13 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddSin ( arg ) ;
t12 = datatree . AddUMinus ( t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sin :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddCos ( arg ) ;
return datatree . AddTimes ( darg , t11 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddPlus ( t11 , datatree . One ) ;
return datatree . AddTimes ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddSin ( this ) ;
t12 = datatree . AddDivide ( darg , t11 ) ;
return datatree . AddUMinus ( t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddCos ( this ) ;
return datatree . AddDivide ( darg , t11 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddPlus ( datatree . One , t11 ) ;
return datatree . AddDivide ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
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 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
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 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddTimes ( this , this ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
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 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
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 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddTimes ( arg , arg ) ;
t12 = datatree . AddMinus ( datatree . One , t11 ) ;
return datatree . AddTimes ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddPlus ( this , this ) ;
return datatree . AddDivide ( darg , t11 ) ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
t11 = datatree . AddPower ( arg , datatree . AddDivide ( datatree . Two , datatree . Three ) ) ;
t12 = datatree . AddTimes ( datatree . Three , t11 ) ;
return datatree . AddDivide ( darg , t12 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2011-08-12 13:20:53 +02:00
t11 = datatree . AddSign ( arg ) ;
return datatree . AddTimes ( t11 , darg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sign :
2011-08-12 13:20:53 +02:00
return datatree . Zero ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
2009-12-16 18:13:23 +01:00
if ( datatree . isDynamic ( ) )
2011-01-13 18:08:26 +01:00
{
2018-07-17 18:34:07 +02:00
if ( datatree . getTypeByDerivID ( deriv_id ) = = SymbolType : : parameter )
2011-01-13 18:08:26 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
if ( ! varg )
2011-01-13 18:08:26 +01:00
{
2011-04-12 13:34:04 +02:00
cerr < < " UnaryOpNode::composeDerivatives: STEADY_STATE() should only be used on "
< < " standalone variables (like STEADY_STATE(y)) to be derivable w.r.t. parameters " < < endl ;
2011-01-13 18:08:26 +01:00
exit ( EXIT_FAILURE ) ;
}
2018-07-17 18:34:07 +02:00
if ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous )
2011-01-13 18:08:26 +01:00
return datatree . AddSteadyStateParamDeriv ( arg , datatree . getSymbIDByDerivID ( deriv_id ) ) ;
else
return datatree . Zero ;
}
else
return datatree . Zero ;
}
2009-12-16 18:13:23 +01:00
else
return darg ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParamDeriv :
2011-01-13 18:08:26 +01:00
assert ( datatree . isDynamic ( ) ) ;
2018-07-17 18:34:07 +02:00
if ( datatree . getTypeByDerivID ( deriv_id ) = = SymbolType : : parameter )
2011-01-13 18:08:26 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ) ;
2018-07-17 18:34:07 +02:00
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous ) ;
2011-01-13 18:08:26 +01:00
return datatree . AddSteadyStateParam2ndDeriv ( arg , param1_symb_id , datatree . getSymbIDByDerivID ( deriv_id ) ) ;
}
else
return datatree . Zero ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParam2ndDeriv :
2011-01-13 18:08:26 +01:00
assert ( datatree . isDynamic ( ) ) ;
2018-07-17 18:34:07 +02:00
if ( datatree . getTypeByDerivID ( deriv_id ) = = SymbolType : : parameter )
2011-01-13 18:08:26 +01:00
{
cerr < < " 3rd derivative of STEADY_STATE node w.r.t. three parameters not implemented " < < endl ;
exit ( EXIT_FAILURE ) ;
}
else
return datatree . Zero ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : expectation :
cerr < < " UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::expectation " < < endl ;
2011-01-13 15:52:44 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : erf :
2010-03-11 11:57:34 +01:00
// x^2
t11 = datatree . AddPower ( arg , datatree . Two ) ;
// exp(x^2)
2019-12-20 16:59:30 +01:00
t12 = datatree . AddExp ( t11 ) ;
2010-03-11 11:57:34 +01:00
// sqrt(pi)
t11 = datatree . AddSqrt ( datatree . Pi ) ;
// sqrt(pi)*exp(x^2)
t13 = datatree . AddTimes ( t11 , t12 ) ;
// 2/(sqrt(pi)*exp(x^2));
2012-12-07 21:45:16 +01:00
t14 = datatree . AddDivide ( datatree . Two , t13 ) ;
// (2/(sqrt(pi)*exp(x^2)))*dx;
return datatree . AddTimes ( t14 , darg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
cerr < < " UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::diff " < < endl ;
2017-06-12 14:56:44 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
cerr < < " UnaryOpNode::composeDerivatives: not implemented on UnaryOpcode::adl " < < endl ;
2017-07-03 16:38:44 +02: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
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
UnaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg = arg - > getDerivative ( deriv_id ) ;
2011-01-13 18:08:26 +01:00
return composeDerivatives ( darg , deriv_id ) ;
2009-07-06 11:34:21 +02:00
}
2015-09-03 13:50:02 +02:00
int
2018-11-30 12:22:13 +01:00
UnaryOpNode : : cost ( const map < pair < int , int > , temporary_terms_t > & temp_terms_map , bool is_matlab ) const
2015-09-03 13:50:02 +02:00
{
// For a temporary term, the cost is null
2019-12-20 16:59:30 +01:00
for ( const auto & it : temp_terms_map )
2018-06-04 12:26:16 +02:00
if ( it . second . find ( const_cast < UnaryOpNode * > ( this ) ) ! = it . second . end ( ) )
2015-09-03 13:50:02 +02:00
return 0 ;
return cost ( arg - > cost ( temp_terms_map , is_matlab ) , is_matlab ) ;
}
2008-02-03 11:28:36 +01:00
int
2020-05-13 16:58:19 +02:00
UnaryOpNode : : cost ( const vector < vector < temporary_terms_t > > & blocks_temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a temporary term, the cost is null
2020-05-13 16:58:19 +02:00
for ( const auto & blk_tt : blocks_temporary_terms )
for ( const auto & eq_tt : blk_tt )
if ( eq_tt . find ( const_cast < UnaryOpNode * > ( this ) ) ! = eq_tt . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2020-05-06 17:13:47 +02:00
return cost ( arg - > cost ( blocks_temporary_terms , is_matlab ) , is_matlab ) ;
2015-09-03 13:50:02 +02:00
}
2008-02-03 11:28:36 +01:00
2015-09-03 13:50:02 +02:00
int
UnaryOpNode : : cost ( int cost , bool is_matlab ) const
{
2020-09-23 17:28:18 +02:00
if ( op_code = = UnaryOpcode : : uminus & & dynamic_cast < NumConstNode * > ( arg ) )
return 0 ; // Cost is zero for a negative constant, as for a positive one
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
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
case UnaryOpcode : : sign :
2009-12-16 18:13:23 +01:00
return cost + 70 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2009-12-16 18:13:23 +01:00
return cost + 160 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2009-12-16 18:13:23 +01:00
return cost + 300 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
case UnaryOpcode : : erf :
2009-12-16 18:13:23 +01:00
return cost + 16000 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
case UnaryOpcode : : sin :
case UnaryOpcode : : cosh :
2009-12-16 18:13:23 +01:00
return cost + 210 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2009-12-16 18:13:23 +01:00
return cost + 230 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2009-12-16 18:13:23 +01:00
return cost + 300 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2009-12-16 18:13:23 +01:00
return cost + 310 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2009-12-16 18:13:23 +01:00
return cost + 140 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
2009-12-16 18:13:23 +01:00
return cost + 240 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2009-12-16 18:13:23 +01:00
return cost + 190 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
2009-12-16 18:13:23 +01:00
return cost + 770 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2009-12-16 18:13:23 +01:00
return cost + 460 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2009-12-16 18:13:23 +01:00
return cost + 350 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2009-12-16 18:13:23 +01:00
return cost + 570 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
case UnaryOpcode : : steadyStateParamDeriv :
case UnaryOpcode : : steadyStateParam2ndDeriv :
case UnaryOpcode : : expectation :
2009-12-16 18:13:23 +01:00
return cost ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
cerr < < " UnaryOpNode::cost: not implemented on UnaryOpcode::diff " < < endl ;
2017-06-12 14:56:44 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
cerr < < " UnaryOpNode::cost: not implemented on UnaryOpcode::adl " < < endl ;
2017-07-03 16:38:44 +02:00
exit ( EXIT_FAILURE ) ;
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
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
case UnaryOpcode : : sign :
2009-12-16 18:13:23 +01:00
return cost + 3 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
case UnaryOpcode : : acosh :
2009-12-16 18:13:23 +01:00
return cost + 210 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2009-12-16 18:13:23 +01:00
return cost + 137 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2009-12-16 18:13:23 +01:00
return cost + 139 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
case UnaryOpcode : : sin :
2009-12-16 18:13:23 +01:00
return cost + 160 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2009-12-16 18:13:23 +01:00
return cost + 170 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
case UnaryOpcode : : atan :
2009-12-16 18:13:23 +01:00
return cost + 190 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2009-12-16 18:13:23 +01:00
return cost + 180 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
case UnaryOpcode : : sinh :
case UnaryOpcode : : tanh :
case UnaryOpcode : : erf :
2009-12-16 18:13:23 +01:00
return cost + 240 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2009-12-16 18:13:23 +01:00
return cost + 220 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2009-12-16 18:13:23 +01:00
return cost + 150 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2009-12-16 18:13:23 +01:00
return cost + 90 ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
case UnaryOpcode : : steadyStateParamDeriv :
case UnaryOpcode : : steadyStateParam2ndDeriv :
case UnaryOpcode : : expectation :
2009-12-16 18:13:23 +01:00
return cost ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
cerr < < " UnaryOpNode::cost: not implemented on UnaryOpcode::diff " < < endl ;
2017-06-12 14:56:44 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
cerr < < " UnaryOpNode::cost: not implemented on UnaryOpcode::adl " < < endl ;
2017-07-03 16:38:44 +02:00
exit ( EXIT_FAILURE ) ;
2008-02-03 11:28:36 +01:00
}
2009-12-16 18:13:23 +01:00
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
void
2018-11-30 12:22:13 +01:00
UnaryOpNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < UnaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
2018-11-30 12:22:13 +01:00
reference_count [ this2 ] = { 1 , derivOrder } ;
arg - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-12 18:29:11 +02:00
auto & [ nref , min_order ] = it - > second ;
nref + + ;
if ( nref * cost ( temp_terms_map , is_matlab ) > min_cost ( is_matlab ) )
temp_terms_map [ min_order ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
void
2020-05-13 16:58:19 +02:00
UnaryOpNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < UnaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
2020-05-13 16:58:19 +02:00
reference_count [ this2 ] = { 1 , blk , eq } ;
arg - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 16:58:19 +02:00
auto & [ nref , first_blk , first_eq ] = it - > second ;
2020-05-06 17:13:47 +02:00
nref + + ;
if ( nref * cost ( blocks_temporary_terms , false ) > min_cost_c )
2020-05-13 16:58:19 +02:00
blocks_temporary_terms [ first_blk ] [ first_eq ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
2015-05-12 16:36:03 +02:00
bool
UnaryOpNode : : containsExternalFunction ( ) const
{
return arg - > containsExternalFunction ( ) ;
}
2018-09-18 14:50:31 +02:00
void
UnaryOpNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " UnaryOpNode " , " op " : " ) " ;
2018-09-18 14:50:31 +02:00
switch ( op_code )
{
case UnaryOpcode : : uminus :
output < < " uminus " ;
break ;
case UnaryOpcode : : exp :
output < < " exp " ;
break ;
case UnaryOpcode : : log :
output < < " log " ;
break ;
case UnaryOpcode : : log10 :
output < < " log10 " ;
break ;
case UnaryOpcode : : cos :
output < < " cos " ;
break ;
case UnaryOpcode : : sin :
output < < " sin " ;
break ;
case UnaryOpcode : : tan :
output < < " tan " ;
break ;
case UnaryOpcode : : acos :
output < < " acos " ;
break ;
case UnaryOpcode : : asin :
output < < " asin " ;
break ;
case UnaryOpcode : : atan :
output < < " atan " ;
break ;
case UnaryOpcode : : cosh :
output < < " cosh " ;
break ;
case UnaryOpcode : : sinh :
output < < " sinh " ;
break ;
case UnaryOpcode : : tanh :
output < < " tanh " ;
break ;
case UnaryOpcode : : acosh :
output < < " acosh " ;
break ;
case UnaryOpcode : : asinh :
output < < " asinh " ;
break ;
case UnaryOpcode : : atanh :
output < < " atanh " ;
break ;
case UnaryOpcode : : sqrt :
output < < " sqrt " ;
break ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
output < < " cbrt " ;
break ;
2018-09-18 14:50:31 +02:00
case UnaryOpcode : : abs :
output < < " abs " ;
break ;
case UnaryOpcode : : sign :
output < < " sign " ;
break ;
case UnaryOpcode : : diff :
output < < " diff " ;
break ;
case UnaryOpcode : : adl :
output < < " adl " ;
break ;
case UnaryOpcode : : steadyState :
output < < " steady_state " ;
case UnaryOpcode : : steadyStateParamDeriv :
output < < " steady_state_param_deriv " ;
break ;
case UnaryOpcode : : steadyStateParam2ndDeriv :
output < < " steady_state_param_second_deriv " ;
break ;
case UnaryOpcode : : expectation :
output < < " expectation " ;
break ;
case UnaryOpcode : : erf :
output < < " erf " ;
break ;
}
2019-04-03 16:32:52 +02:00
output < < R " ( " , " arg " : ) " ;
2018-09-18 14:50:31 +02:00
arg - > writeJsonAST ( output ) ;
switch ( op_code )
{
case UnaryOpcode : : adl :
2019-04-03 16:32:52 +02:00
output < < R " (, " adl_param_name " : " ) " << adl_param_name << R " ( " ) "
< < R " (, " lags " : [) " ;
2019-12-16 19:42:59 +01:00
for ( auto it = adl_lags . begin ( ) ; it ! = adl_lags . end ( ) ; + + it )
2018-09-18 14:50:31 +02:00
{
if ( it ! = adl_lags . begin ( ) )
output < < " , " ;
output < < * it ;
}
output < < " ] " ;
break ;
default :
break ;
}
output < < " } " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
UnaryOpNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-20 16:59:30 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < UnaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
2017-02-02 15:09:43 +01:00
// Always put parenthesis around uminus nodes
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus )
2017-02-20 12:18:11 +01:00
output < < " ( " ;
2017-02-02 15:09:43 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2017-02-02 15:09:43 +01:00
output < < " - " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2017-02-02 15:09:43 +01:00
output < < " exp " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2017-02-02 15:09:43 +01:00
output < < " log " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2017-02-02 15:09:43 +01:00
output < < " log10 " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
2017-02-02 15:09:43 +01:00
output < < " cos " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sin :
2017-02-02 15:09:43 +01:00
output < < " sin " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2017-02-02 15:09:43 +01:00
output < < " tan " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2017-02-02 15:09:43 +01:00
output < < " acos " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2017-02-02 15:09:43 +01:00
output < < " asin " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2017-02-02 15:09:43 +01:00
output < < " atan " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
2017-02-02 15:09:43 +01:00
output < < " cosh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
2017-02-02 15:09:43 +01:00
output < < " sinh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2017-02-02 15:09:43 +01:00
output < < " tanh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
2017-02-02 15:09:43 +01:00
output < < " acosh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2017-02-02 15:09:43 +01:00
output < < " asinh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2017-02-02 15:09:43 +01:00
output < < " atanh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2017-02-02 15:09:43 +01:00
output < < " sqrt " ;
break ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
output < < " cbrt " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2017-02-02 15:09:43 +01:00
output < < " abs " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sign :
2017-02-02 15:09:43 +01:00
output < < " sign " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
2017-06-19 18:02:57 +02:00
output < < " diff " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
2018-02-28 11:31:08 +01:00
output < < " adl( " ;
2017-07-03 16:38:44 +02:00
arg - > writeJsonOutput ( output , temporary_terms , tef_terms ) ;
2018-02-28 11:31:08 +01:00
output < < " , ' " < < adl_param_name < < " ', [ " ;
2019-12-16 19:42:59 +01:00
for ( auto it = adl_lags . begin ( ) ; it ! = adl_lags . end ( ) ; + + it )
2018-02-28 11:31:08 +01:00
{
if ( it ! = adl_lags . begin ( ) )
output < < " , " ;
output < < * it ;
}
output < < " ]) " ;
2017-07-03 16:38:44 +02:00
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
2017-02-02 15:09:43 +01:00
output < < " ( " ;
2017-10-16 17:24:55 +02:00
arg - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " ) " ;
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParamDeriv :
2017-02-02 15:09:43 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ) ;
2018-07-17 18:34:07 +02:00
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = SymbolType : : parameter ) ;
2017-02-02 15:09:43 +01:00
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
output < < " ss_param_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param + 1 < < " ) " ;
}
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParam2ndDeriv :
2017-02-02 15:09:43 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ) ;
2018-07-17 18:34:07 +02:00
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = SymbolType : : parameter ) ;
assert ( datatree . symbol_table . getType ( param2_symb_id ) = = SymbolType : : parameter ) ;
2017-02-02 15:09:43 +01:00
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param1 = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
int tsid_param2 = datatree . symbol_table . getTypeSpecificID ( param2_symb_id ) ;
output < < " ss_param_2nd_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param1 + 1
< < " , " < < tsid_param2 + 1 < < " ) " ;
}
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : expectation :
2017-02-02 15:09:43 +01:00
output < < " EXPECTATION( " < < expectation_information_set < < " ) " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : erf :
2017-02-02 15:09:43 +01:00
output < < " erf " ;
break ;
}
2017-06-14 07:01:31 +02:00
bool close_parenthesis = false ;
2017-02-02 15:09:43 +01:00
/* Enclose argument with parentheses if:
- current opcode is not uminus , or
- current opcode is uminus and argument has lowest precedence
*/
2018-07-18 16:18:26 +02:00
if ( op_code ! = UnaryOpcode : : uminus
| | ( op_code = = UnaryOpcode : : uminus
2017-02-20 12:18:11 +01:00
& & arg - > precedenceJson ( temporary_terms ) < precedenceJson ( temporary_terms ) ) )
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
output < < " ( " ;
2017-02-02 15:09:43 +01:00
close_parenthesis = true ;
}
// Write argument
2017-10-16 17:24:55 +02:00
arg - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
if ( close_parenthesis )
2017-02-20 12:18:11 +01:00
output < < " ) " ;
2017-02-02 15:09:43 +01:00
// Close parenthesis for uminus
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus )
2017-02-20 12:18:11 +01:00
output < < " ) " ;
2017-02-02 15:09:43 +01:00
}
2009-12-16 18:13:23 +01:00
void
UnaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2009-12-16 18:13:23 +01:00
// Always put parenthesis around uminus nodes
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus )
2009-12-16 18:13:23 +01:00
output < < LEFT_PAR ( output_type ) ;
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2009-12-16 18:13:23 +01:00
output < < " - " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2019-12-04 11:18:21 +01:00
if ( isLatexOutput ( output_type ) )
output < < R " ( \ exp) " ;
else
output < < " exp " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2019-04-03 16:32:52 +02:00
output < < R " ( \ log) " ;
2017-09-08 11:06:37 +02:00
else
output < < " log " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2019-04-03 16:32:52 +02:00
output < < R " ( \ log_{10}) " ;
2009-12-16 18:13:23 +01:00
else
output < < " log10 " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
2019-12-04 11:18:21 +01:00
if ( isLatexOutput ( output_type ) )
output < < R " ( \ cos) " ;
else
output < < " cos " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sin :
2019-12-04 11:18:21 +01:00
if ( isLatexOutput ( output_type ) )
output < < R " ( \ sin) " ;
else
output < < " sin " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2019-12-04 11:18:21 +01:00
if ( isLatexOutput ( output_type ) )
output < < R " ( \t an) " ;
else
output < < " tan " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2009-12-16 18:13:23 +01:00
output < < " acos " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2009-12-16 18:13:23 +01:00
output < < " asin " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2009-12-16 18:13:23 +01:00
output < < " atan " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
2009-12-16 18:13:23 +01:00
output < < " cosh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
2009-12-16 18:13:23 +01:00
output < < " sinh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2009-12-16 18:13:23 +01:00
output < < " tanh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
2009-12-16 18:13:23 +01:00
output < < " acosh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2009-12-16 18:13:23 +01:00
output < < " asinh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2009-12-16 18:13:23 +01:00
output < < " atanh " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2019-12-04 11:18:21 +01:00
if ( isLatexOutput ( output_type ) )
{
output < < R " ( \ sqrt{) " ;
arg - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " } " ;
return ;
}
2009-12-16 18:13:23 +01:00
output < < " sqrt " ;
break ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
2019-12-04 10:43:46 +01:00
if ( isMatlabOutput ( output_type ) )
{
output < < " nthroot( " ;
arg - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " , 3) " ;
return ;
}
else if ( isLatexOutput ( output_type ) )
{
output < < R " ( \ sqrt[3]{) " ;
arg - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " } " ;
return ;
}
else
output < < " cbrt " ;
2019-07-15 18:18:26 +02:00
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2011-08-12 13:20:53 +02:00
output < < " abs " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sign :
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : CDynamicModel | | output_type = = ExprNodeOutputType : : CStaticModel )
2011-08-12 13:20:53 +02:00
output < < " copysign " ;
else
output < < " sign " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
2009-12-16 18:13:23 +01:00
ExprNodeOutputType new_output_type ;
switch ( output_type )
{
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : matlabDynamicModel :
new_output_type = ExprNodeOutputType : : matlabDynamicSteadyStateOperator ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : latexDynamicModel :
new_output_type = ExprNodeOutputType : : latexDynamicSteadyStateOperator ;
2009-12-16 18:13:23 +01:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : CDynamicModel :
new_output_type = ExprNodeOutputType : : CDynamicSteadyStateOperator ;
2010-09-20 17:04:38 +02:00
break ;
2018-09-05 18:27:13 +02:00
case ExprNodeOutputType : : juliaDynamicModel :
new_output_type = ExprNodeOutputType : : juliaDynamicSteadyStateOperator ;
2015-07-27 17:02:51 +02:00
break ;
2009-12-16 18:13:23 +01:00
default :
new_output_type = output_type ;
break ;
}
2011-08-08 18:48:03 +02:00
output < < " ( " ;
2018-03-27 17:14:30 +02:00
arg - > writeOutput ( output , new_output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2011-08-08 18:48:03 +02:00
output < < " ) " ;
2009-12-16 18:13:23 +01:00
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParamDeriv :
2011-01-13 18:08:26 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ) ;
2018-07-17 18:34:07 +02:00
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = SymbolType : : parameter ) ;
2011-01-13 18:08:26 +01:00
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
2018-09-05 18:27:13 +02:00
assert ( isMatlabOutput ( output_type ) ) ;
2011-01-13 18:08:26 +01:00
output < < " ss_param_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param + 1 < < " ) " ;
}
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParam2ndDeriv :
2011-01-13 18:08:26 +01:00
{
2019-12-16 19:42:59 +01:00
auto varg = dynamic_cast < VariableNode * > ( arg ) ;
assert ( varg ) ;
2018-07-17 18:34:07 +02:00
assert ( datatree . symbol_table . getType ( varg - > symb_id ) = = SymbolType : : endogenous ) ;
assert ( datatree . symbol_table . getType ( param1_symb_id ) = = SymbolType : : parameter ) ;
assert ( datatree . symbol_table . getType ( param2_symb_id ) = = SymbolType : : parameter ) ;
2011-01-13 18:08:26 +01:00
int tsid_endo = datatree . symbol_table . getTypeSpecificID ( varg - > symb_id ) ;
int tsid_param1 = datatree . symbol_table . getTypeSpecificID ( param1_symb_id ) ;
int tsid_param2 = datatree . symbol_table . getTypeSpecificID ( param2_symb_id ) ;
2018-09-05 18:27:13 +02:00
assert ( isMatlabOutput ( output_type ) ) ;
2011-01-13 18:08:26 +01:00
output < < " ss_param_2nd_deriv( " < < tsid_endo + 1 < < " , " < < tsid_param1 + 1
< < " , " < < tsid_param2 + 1 < < " ) " ;
}
return ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : expectation :
2018-09-05 18:27:13 +02:00
if ( ! isLatexOutput ( output_type ) )
2015-02-16 08:31:30 +01:00
{
2018-07-18 16:18:26 +02:00
cerr < < " UnaryOpNode::writeOutput: not implemented on UnaryOpcode::expectation " < < endl ;
2015-02-16 08:31:30 +01:00
exit ( EXIT_FAILURE ) ;
}
2019-04-03 16:32:52 +02:00
output < < R " ( \ mathbb{E}_{t) " ;
2015-02-16 08:31:30 +01:00
if ( expectation_information_set ! = 0 )
{
if ( expectation_information_set > 0 )
output < < " + " ;
output < < expectation_information_set ;
}
output < < " } " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : erf :
2010-03-11 11:57:34 +01:00
output < < " erf " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
2017-06-12 14:56:44 +02:00
output < < " diff " ;
break ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
2017-07-03 16:38:44 +02:00
output < < " adl " ;
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
*/
2018-07-18 16:18:26 +02:00
if ( op_code ! = UnaryOpcode : : uminus
| | ( op_code = = UnaryOpcode : : uminus
2009-12-16 18:13:23 +01:00
& & arg - > precedence ( output_type , temporary_terms ) < precedence ( output_type , temporary_terms ) ) )
{
output < < LEFT_PAR ( output_type ) ;
2018-09-05 18:27:13 +02:00
if ( op_code = = UnaryOpcode : : sign & & ( output_type = = ExprNodeOutputType : : CDynamicModel | | output_type = = ExprNodeOutputType : : CStaticModel ) )
2011-08-12 13:20:53 +02:00
output < < " 1.0, " ;
2009-12-16 18:13:23 +01:00
close_parenthesis = true ;
}
// Write argument
2018-03-27 17:14:30 +02:00
arg - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_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
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus )
2009-12-16 18:13:23 +01:00
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 ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2018-03-27 17:14:30 +02:00
arg - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-04 16:40:07 +01:00
}
2017-02-20 12:18:11 +01:00
void
UnaryOpNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
2017-10-16 17:24:55 +02:00
arg - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
}
2010-12-10 11:50:27 +01:00
void
UnaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2011-02-04 16:25:38 +01:00
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
2020-05-13 12:53:47 +02:00
arg - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
}
2008-02-03 11:28:36 +01:00
double
2018-06-04 12:50:53 +02:00
UnaryOpNode : : eval_opcode ( UnaryOpcode op_code , double v ) noexcept ( false )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2019-12-16 19:42:59 +01:00
return - v ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2019-12-16 19:42:59 +01:00
return exp ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2019-12-16 19:42:59 +01:00
return log ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2019-12-16 19:42:59 +01:00
return log10 ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
2019-12-16 19:42:59 +01:00
return cos ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sin :
2019-12-16 19:42:59 +01:00
return sin ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2019-12-16 19:42:59 +01:00
return tan ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2019-12-16 19:42:59 +01:00
return acos ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2019-12-16 19:42:59 +01:00
return asin ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2019-12-16 19:42:59 +01:00
return atan ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
2019-12-16 19:42:59 +01:00
return cosh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
2019-12-16 19:42:59 +01:00
return sinh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2019-12-16 19:42:59 +01:00
return tanh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
2019-12-16 19:42:59 +01:00
return acosh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2019-12-16 19:42:59 +01:00
return asinh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2019-12-16 19:42:59 +01:00
return atanh ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2019-12-16 19:42:59 +01:00
return sqrt ( v ) ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
2019-12-16 19:42:59 +01:00
return cbrt ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2019-12-16 19:42:59 +01:00
return abs ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sign :
2011-08-12 13:20:53 +02:00
return ( v > 0 ) ? 1 : ( ( v < 0 ) ? - 1 : 0 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
2019-12-16 19:42:59 +01:00
return v ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParamDeriv :
2019-06-19 17:31:33 +02:00
cerr < < " UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::steadyStateParamDeriv " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParam2ndDeriv :
2019-06-19 17:31:33 +02:00
cerr < < " UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::steadyStateParam2ndDeriv " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : expectation :
2019-06-19 17:31:33 +02:00
cerr < < " UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::expectation " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : erf :
2019-12-16 19:42:59 +01:00
return erf ( v ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
cerr < < " UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::diff " < < endl ;
2017-06-12 14:56:44 +02:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
cerr < < " UnaryOpNode::eval_opcode: not implemented on UnaryOpcode::adl " < < endl ;
2017-07-03 16:38:44 +02:00
exit ( EXIT_FAILURE ) ;
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
2018-06-04 12:50:53 +02:00
UnaryOpNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2008-02-03 11:28:36 +01:00
{
double v = arg - > eval ( eval_context ) ;
return eval_opcode ( op_code , v ) ;
}
void
2010-12-10 11:50:27 +01:00
UnaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2020-05-13 12:53:47 +02:00
if ( auto this2 = const_cast < UnaryOpNode * > ( this ) ;
temporary_terms . find ( this2 ) ! = temporary_terms . end ( ) )
2009-12-16 18:13:23 +01:00
{
if ( dynamic )
{
2020-05-13 12:53:47 +02:00
FLDT_ fldt ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 12:53:47 +02:00
FLDST_ fldst ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : steadyState )
2020-05-13 12:53:47 +02:00
arg - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , true , tef_terms ) ;
2009-12-16 18:13:23 +01:00
else
{
2020-05-13 12:53:47 +02:00
arg - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2018-07-18 16:18:26 +02:00
FUNARY_ funary { static_cast < uint8_t > ( op_code ) } ;
2010-07-23 11:20:24 +02:00
funary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
void
2018-04-16 13:50:31 +02:00
UnaryOpNode : : collectVARLHSVariable ( set < expr_t > & result ) const
2009-07-10 18:42:08 +02:00
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : diff )
2018-04-16 13:50:31 +02:00
result . insert ( const_cast < UnaryOpNode * > ( this ) ) ;
2018-02-28 10:44:24 +01:00
else
2018-04-16 13:50:31 +02:00
arg - > collectVARLHSVariable ( result ) ;
}
void
2018-06-04 14:17:36 +02:00
UnaryOpNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2018-04-16 13:50:31 +02:00
{
arg - > collectDynamicVariables ( type_arg , result ) ;
2013-09-13 20:37:31 +02:00
}
2020-04-02 14:36:26 +02:00
void
UnaryOpNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
{
arg - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
if ( contain_var . count ( arg ) > 0 )
contain_var . insert ( const_cast < UnaryOpNode * > ( this ) ) ;
}
BinaryOpNode *
UnaryOpNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
2009-12-16 18:13:23 +01:00
{
2020-04-02 14:36:26 +02:00
assert ( contain_var . count ( const_cast < UnaryOpNode * > ( this ) ) > 0 ) ;
2011-06-10 11:59:34 +02:00
2020-04-02 14:36:26 +02:00
switch ( op_code )
2009-12-16 18:13:23 +01:00
{
2020-04-02 14:36:26 +02:00
case UnaryOpcode : : uminus :
rhs = datatree . AddUMinus ( rhs ) ;
break ;
case UnaryOpcode : : exp :
rhs = datatree . AddLog ( rhs ) ;
break ;
case UnaryOpcode : : log :
rhs = datatree . AddExp ( rhs ) ;
break ;
case UnaryOpcode : : log10 :
rhs = datatree . AddPower ( datatree . AddNonNegativeConstant ( " 10 " ) , rhs ) ;
break ;
case UnaryOpcode : : cos :
rhs = datatree . AddAcos ( rhs ) ;
break ;
case UnaryOpcode : : sin :
rhs = datatree . AddAsin ( rhs ) ;
break ;
case UnaryOpcode : : tan :
rhs = datatree . AddAtan ( rhs ) ;
break ;
case UnaryOpcode : : acos :
rhs = datatree . AddCos ( rhs ) ;
break ;
case UnaryOpcode : : asin :
rhs = datatree . AddSin ( rhs ) ;
break ;
case UnaryOpcode : : atan :
rhs = datatree . AddTan ( rhs ) ;
break ;
case UnaryOpcode : : cosh :
rhs = datatree . AddAcosh ( rhs ) ;
break ;
case UnaryOpcode : : sinh :
rhs = datatree . AddAsinh ( rhs ) ;
break ;
case UnaryOpcode : : tanh :
rhs = datatree . AddAtanh ( rhs ) ;
break ;
case UnaryOpcode : : acosh :
rhs = datatree . AddCosh ( rhs ) ;
break ;
case UnaryOpcode : : asinh :
rhs = datatree . AddSinh ( rhs ) ;
break ;
case UnaryOpcode : : atanh :
rhs = datatree . AddTanh ( rhs ) ;
break ;
case UnaryOpcode : : sqrt :
rhs = datatree . AddPower ( rhs , datatree . Two ) ;
break ;
case UnaryOpcode : : cbrt :
rhs = datatree . AddPower ( rhs , datatree . Three ) ;
break ;
default :
throw NormalizationFailed ( ) ;
2009-12-16 18:13:23 +01:00
}
2020-04-02 14:36:26 +02:00
return arg - > normalizeEquationHelper ( contain_var , rhs ) ;
2009-12-16 18:13:23 +01:00
}
2008-11-14 17:07:47 +01:00
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
UnaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg = arg - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2011-01-13 18:08:26 +01:00
return composeDerivatives ( darg , deriv_id ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
UnaryOpNode : : buildSimilarUnaryOpNode ( expr_t alt_arg , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddUMinus ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddExp ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddLog ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddLog10 ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cos :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddCos ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sin :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddSin ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tan :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddTan ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acos :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAcos ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asin :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAsin ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atan :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAtan ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : cosh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddCosh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sinh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddSinh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : tanh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddTanh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : acosh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAcosh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : asinh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAsinh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : atanh :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddAtanh ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sqrt :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddSqrt ( alt_arg ) ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
return alt_datatree . AddCbrt ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
2011-08-12 13:20:53 +02:00
return alt_datatree . AddAbs ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : sign :
2011-08-12 13:20:53 +02:00
return alt_datatree . AddSign ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyState :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddSteadyState ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParamDeriv :
cerr < < " UnaryOpNode::buildSimilarUnaryOpNode: UnaryOpcode::steadyStateParamDeriv can't be translated " < < endl ;
2011-01-13 18:08:26 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : steadyStateParam2ndDeriv :
cerr < < " UnaryOpNode::buildSimilarUnaryOpNode: UnaryOpcode::steadyStateParam2ndDeriv can't be translated " < < endl ;
2011-01-13 18:08:26 +01:00
exit ( EXIT_FAILURE ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : expectation :
2009-11-06 19:19:52 +01:00
return alt_datatree . AddExpectation ( expectation_information_set , alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : erf :
2010-03-11 11:57:34 +01:00
return alt_datatree . AddErf ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : diff :
2017-06-12 14:56:44 +02:00
return alt_datatree . AddDiff ( alt_arg ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : adl :
2018-02-28 11:31:08 +01:00
return alt_datatree . AddAdl ( alt_arg , adl_param_name , adl_lags ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
UnaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg = arg - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( sarg , static_datatree ) ;
}
2015-12-18 15:17:32 +01:00
void
UnaryOpNode : : computeXrefs ( EquationInfo & ei ) const
{
arg - > computeXrefs ( ei ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
2018-10-10 13:07:25 +02:00
UnaryOpNode : : clone ( DataTree & datatree ) const
2010-10-15 19:05:16 +02:00
{
2018-10-10 13:07:25 +02:00
expr_t substarg = arg - > clone ( datatree ) ;
return buildSimilarUnaryOpNode ( substarg , datatree ) ;
2010-10-15 19:05:16 +02:00
}
2009-09-30 17:10:31 +02:00
int
UnaryOpNode : : maxEndoLead ( ) const
{
return arg - > maxEndoLead ( ) ;
}
2009-10-07 18:34:42 +02:00
int
UnaryOpNode : : maxExoLead ( ) const
{
return arg - > maxExoLead ( ) ;
}
2010-08-19 15:20:54 +02:00
int
UnaryOpNode : : maxEndoLag ( ) const
{
return arg - > maxEndoLag ( ) ;
}
int
UnaryOpNode : : maxExoLag ( ) const
{
return arg - > maxExoLag ( ) ;
}
2012-05-26 20:53:48 +02:00
int
UnaryOpNode : : maxLead ( ) const
{
return arg - > maxLead ( ) ;
}
2018-02-28 17:33:00 +01:00
int
UnaryOpNode : : maxLag ( ) const
{
return arg - > maxLag ( ) ;
}
2018-12-05 15:17:00 +01:00
int
UnaryOpNode : : maxLagWithDiffsExpanded ( ) const
{
if ( op_code = = UnaryOpcode : : diff )
return arg - > maxLagWithDiffsExpanded ( ) + 1 ;
return arg - > maxLagWithDiffsExpanded ( ) ;
}
2018-04-17 15:17:28 +02:00
expr_t
UnaryOpNode : : undiff ( ) const
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : diff )
2018-04-17 15:17:28 +02:00
return arg ;
return arg - > undiff ( ) ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
UnaryOpNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2019-10-22 16:04:24 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
2019-12-16 19:42:59 +01:00
if ( lhs_lag_equiv . find ( lag_equiv_repr ) = = lhs_lag_equiv . end ( ) )
2018-06-11 10:40:00 +02:00
return 0 ;
2018-12-05 15:17:00 +01:00
return arg - > maxLag ( ) ;
2018-04-16 13:50:31 +02:00
}
2018-05-16 12:17:06 +02:00
int
UnaryOpNode : : VarMinLag ( ) const
{
return arg - > VarMinLag ( ) ;
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
UnaryOpNode : : substituteAdl ( ) const
2017-06-12 14:56:44 +02:00
{
2018-07-18 16:18:26 +02:00
if ( op_code ! = UnaryOpcode : : adl )
2017-06-12 14:56:44 +02:00
{
2018-01-30 10:06:56 +01:00
expr_t argsubst = arg - > substituteAdl ( ) ;
2017-06-12 14:56:44 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2018-01-30 10:06:56 +01:00
expr_t arg1subst = arg - > substituteAdl ( ) ;
2018-06-04 12:52:14 +02:00
expr_t retval = nullptr ;
2017-07-03 16:38:44 +02:00
ostringstream inttostr ;
2018-02-28 11:31:08 +01:00
2019-12-16 19:42:59 +01:00
for ( auto it = adl_lags . begin ( ) ; it ! = adl_lags . end ( ) ; + + it )
2018-02-28 11:31:08 +01:00
if ( it = = adl_lags . begin ( ) )
{
inttostr < < * it ;
retval = datatree . AddTimes ( datatree . AddVariable ( datatree . symbol_table . getID ( adl_param_name + " _lag_ " + inttostr . str ( ) ) , 0 ) ,
arg1subst - > decreaseLeadsLags ( * it ) ) ;
}
else
{
inttostr . clear ( ) ;
inttostr . str ( " " ) ;
inttostr < < * it ;
retval = datatree . AddPlus ( retval ,
datatree . AddTimes ( datatree . AddVariable ( datatree . symbol_table . getID ( adl_param_name + " _lag_ "
+ inttostr . str ( ) ) , 0 ) ,
arg1subst - > decreaseLeadsLags ( * it ) ) ) ;
}
2017-07-03 16:38:44 +02:00
return retval ;
2017-06-12 14:56:44 +02:00
}
2020-11-10 18:04:05 +01:00
expr_t
UnaryOpNode : : substituteModelLocalVariables ( ) const
{
expr_t argsubst = arg - > substituteModelLocalVariables ( ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
UnaryOpNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
expr_t argsubst = arg - > substituteVarExpectation ( subst_table ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2018-05-31 15:34:25 +02:00
int
UnaryOpNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : diff )
2018-05-31 15:34:25 +02:00
return arg - > countDiffs ( ) + 1 ;
return arg - > countDiffs ( ) ;
2018-02-08 13:07:15 +01:00
}
2018-05-30 16:48:08 +02:00
bool
2018-06-07 12:53:00 +02:00
UnaryOpNode : : createAuxVarForUnaryOpNode ( ) const
2018-05-30 16:48:08 +02:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
case UnaryOpcode : : log :
case UnaryOpcode : : log10 :
case UnaryOpcode : : cos :
case UnaryOpcode : : sin :
case UnaryOpcode : : tan :
case UnaryOpcode : : acos :
case UnaryOpcode : : asin :
case UnaryOpcode : : atan :
case UnaryOpcode : : cosh :
case UnaryOpcode : : sinh :
case UnaryOpcode : : tanh :
case UnaryOpcode : : acosh :
case UnaryOpcode : : asinh :
case UnaryOpcode : : atanh :
case UnaryOpcode : : sqrt :
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : abs :
case UnaryOpcode : : sign :
case UnaryOpcode : : erf :
2018-05-30 16:48:08 +02:00
return true ;
default :
return false ;
}
}
void
2019-10-22 14:56:28 +02:00
UnaryOpNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
2019-10-22 14:56:28 +02:00
arg - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-06-07 12:53:00 +02:00
if ( ! this - > createAuxVarForUnaryOpNode ( ) )
return ;
2018-05-30 16:48:08 +02:00
2019-10-22 14:56:28 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
nodes [ lag_equiv_repr ] [ index ] = const_cast < UnaryOpNode * > ( this ) ;
2018-05-30 16:48:08 +02:00
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
UnaryOpNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
2019-10-22 14:56:28 +02:00
arg - > findDiffNodes ( nodes ) ;
2018-06-07 12:53:00 +02:00
2018-07-18 16:18:26 +02:00
if ( op_code ! = UnaryOpcode : : diff )
2018-03-02 12:32:01 +01:00
return ;
2019-10-22 14:56:28 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
nodes [ lag_equiv_repr ] [ index ] = const_cast < UnaryOpNode * > ( this ) ;
2018-03-02 12:32:01 +01:00
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
UnaryOpNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
2018-09-13 12:21:23 +02:00
return arg - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
UnaryOpNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2018-01-30 10:06:56 +01:00
{
2019-08-19 18:22:55 +02:00
// If this is not a diff node, then substitute recursively and return
2019-10-22 14:56:28 +02:00
expr_t argsubst = arg - > substituteDiff ( nodes , subst_table , neweqs ) ;
2018-07-18 16:18:26 +02:00
if ( op_code ! = UnaryOpcode : : diff )
2018-06-07 12:53:00 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2018-01-30 10:06:56 +01:00
2019-12-16 19:42:59 +01:00
if ( auto sit = subst_table . find ( this ) ;
sit ! = subst_table . end ( ) )
2018-03-02 12:32:01 +01:00
return const_cast < VariableNode * > ( sit - > second ) ;
2018-01-30 10:06:56 +01:00
2019-10-22 14:56:28 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
auto it = nodes . find ( lag_equiv_repr ) ;
if ( it = = nodes . end ( ) | | it - > second . find ( index ) = = it - > second . end ( )
| | it - > second . at ( index ) ! = this )
2018-04-17 15:17:28 +02:00
{
2019-08-19 18:22:55 +02:00
/* diff does not appear in VAR equations, so simply create aux var and return.
Once the comparison of expression nodes works , come back and remove
this part , folding into the next loop . */
2019-12-19 16:46:00 +01:00
int symb_id = datatree . symbol_table . addDiffAuxiliaryVar ( argsubst - > idx , const_cast < UnaryOpNode * > ( this ) ) ;
2018-06-07 12:53:00 +02:00
VariableNode * aux_var = datatree . AddVariable ( symb_id , 0 ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( aux_var ,
datatree . AddMinus ( argsubst ,
argsubst - > decreaseLeadsLags ( 1 ) ) ) ) ;
2018-06-07 12:53:00 +02:00
subst_table [ this ] = dynamic_cast < VariableNode * > ( aux_var ) ;
return const_cast < VariableNode * > ( subst_table [ this ] ) ;
2018-04-17 15:17:28 +02:00
}
2018-03-02 12:32:01 +01:00
2019-08-19 18:22:55 +02:00
/* At this point, we know that this node (and its lagged/leaded brothers)
must be substituted . We create the auxiliary variable and fill the
substitution table for all those similar nodes , in an iteration going from
leads to lags . */
2019-10-22 14:56:28 +02:00
int last_index = 0 ;
2018-06-04 12:52:14 +02:00
VariableNode * last_aux_var = nullptr ;
2019-08-19 18:22:55 +02:00
for ( auto rit = it - > second . rbegin ( ) ; rit ! = it - > second . rend ( ) ; + + rit )
2018-03-02 12:32:01 +01:00
{
expr_t argsubst = dynamic_cast < UnaryOpNode * > ( rit - > second ) - >
2019-12-20 16:59:30 +01:00
arg - > substituteDiff ( nodes , subst_table , neweqs ) ;
2019-12-16 19:42:59 +01:00
auto vn = dynamic_cast < VariableNode * > ( argsubst ) ;
2019-08-20 12:50:41 +02:00
int symb_id ;
2018-03-02 12:32:01 +01:00
if ( rit = = it - > second . rbegin ( ) )
{
2019-12-16 19:42:59 +01:00
if ( vn )
2019-12-19 16:46:00 +01:00
symb_id = datatree . symbol_table . addDiffAuxiliaryVar ( argsubst - > idx , rit - > second , vn - > symb_id , vn - > lag ) ;
2018-03-02 17:50:35 +01:00
else
2019-12-19 16:46:00 +01:00
symb_id = datatree . symbol_table . addDiffAuxiliaryVar ( argsubst - > idx , rit - > second ) ;
2018-05-31 18:44:06 +02:00
2018-03-02 12:32:01 +01:00
// make originating aux var & equation
2019-10-22 14:56:28 +02:00
last_index = rit - > first ;
2018-03-02 17:50:35 +01:00
last_aux_var = datatree . AddVariable ( symb_id , 0 ) ;
2018-03-02 12:32:01 +01:00
//ORIG_AUX_DIFF = argsubst - argsubst(-1)
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( last_aux_var ,
datatree . AddMinus ( argsubst ,
argsubst - > decreaseLeadsLags ( 1 ) ) ) ) ;
2018-03-02 17:50:35 +01:00
subst_table [ rit - > second ] = dynamic_cast < VariableNode * > ( last_aux_var ) ;
2018-03-02 12:32:01 +01:00
}
else
{
2018-04-17 15:17:28 +02:00
// just add equation of form: AUX_DIFF = LAST_AUX_VAR(-1)
2018-06-04 12:52:14 +02:00
VariableNode * new_aux_var = nullptr ;
2019-10-22 14:56:28 +02:00
for ( int i = last_index ; i > rit - > first ; i - - )
2018-03-02 17:50:35 +01:00
{
2019-10-22 14:56:28 +02:00
if ( i = = last_index )
2019-12-19 16:46:00 +01:00
symb_id = datatree . symbol_table . addDiffLagAuxiliaryVar ( argsubst - > idx , rit - > second ,
2018-11-28 14:32:26 +01:00
last_aux_var - > symb_id , last_aux_var - > lag ) ;
2018-03-02 17:50:35 +01:00
else
2019-12-19 16:46:00 +01:00
symb_id = datatree . symbol_table . addDiffLagAuxiliaryVar ( new_aux_var - > idx , rit - > second ,
2018-11-28 14:32:26 +01:00
last_aux_var - > symb_id , last_aux_var - > lag ) ;
2018-03-02 17:50:35 +01:00
new_aux_var = datatree . AddVariable ( symb_id , 0 ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( new_aux_var ,
last_aux_var - > decreaseLeadsLags ( 1 ) ) ) ;
2018-03-02 17:50:35 +01:00
last_aux_var = new_aux_var ;
}
2018-03-02 12:32:01 +01:00
subst_table [ rit - > second ] = dynamic_cast < VariableNode * > ( new_aux_var ) ;
2019-10-22 14:56:28 +02:00
last_index = rit - > first ;
2018-03-02 12:32:01 +01:00
}
}
return const_cast < VariableNode * > ( subst_table [ this ] ) ;
2018-01-30 10:06:56 +01:00
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
UnaryOpNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
2019-12-16 19:42:59 +01:00
if ( auto sit = subst_table . find ( this ) ;
sit ! = subst_table . end ( ) )
2018-05-30 16:48:08 +02:00
return const_cast < VariableNode * > ( sit - > second ) ;
2019-10-22 14:56:28 +02:00
/* If the equivalence class of this node is not marked for substitution,
2019-08-19 18:22:55 +02:00
then substitute recursively and return . */
2019-10-22 14:56:28 +02:00
auto [ lag_equiv_repr , index ] = getLagEquivalenceClass ( ) ;
auto it = nodes . find ( lag_equiv_repr ) ;
expr_t argsubst = arg - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
if ( it = = nodes . end ( ) )
2018-06-07 12:53:00 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2018-05-30 16:48:08 +02:00
2019-08-19 18:22:55 +02:00
string unary_op ;
2018-10-15 11:59:15 +02:00
switch ( op_code )
{
case UnaryOpcode : : exp :
unary_op = " exp " ;
break ;
case UnaryOpcode : : log :
unary_op = " log " ;
break ;
case UnaryOpcode : : log10 :
unary_op = " log10 " ;
break ;
case UnaryOpcode : : cos :
unary_op = " cos " ;
break ;
case UnaryOpcode : : sin :
unary_op = " sin " ;
break ;
case UnaryOpcode : : tan :
unary_op = " tan " ;
break ;
case UnaryOpcode : : acos :
unary_op = " acos " ;
break ;
case UnaryOpcode : : asin :
unary_op = " asin " ;
break ;
case UnaryOpcode : : atan :
unary_op = " atan " ;
break ;
case UnaryOpcode : : cosh :
unary_op = " cosh " ;
break ;
case UnaryOpcode : : sinh :
unary_op = " sinh " ;
break ;
case UnaryOpcode : : tanh :
unary_op = " tanh " ;
break ;
case UnaryOpcode : : acosh :
unary_op = " acosh " ;
break ;
case UnaryOpcode : : asinh :
unary_op = " asinh " ;
break ;
case UnaryOpcode : : atanh :
unary_op = " atanh " ;
break ;
case UnaryOpcode : : sqrt :
unary_op = " sqrt " ;
break ;
2019-07-15 18:18:26 +02:00
case UnaryOpcode : : cbrt :
unary_op = " cbrt " ;
break ;
2018-10-15 11:59:15 +02:00
case UnaryOpcode : : abs :
unary_op = " abs " ;
break ;
case UnaryOpcode : : sign :
unary_op = " sign " ;
break ;
case UnaryOpcode : : erf :
unary_op = " erf " ;
break ;
default :
2019-08-19 18:22:55 +02:00
cerr < < " UnaryOpNode::substituteUnaryOpNodes: Shouldn't arrive here " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-10-15 11:59:15 +02:00
}
2019-08-19 18:22:55 +02:00
/* At this point, we know that this node (and its lagged/leaded brothers)
must be substituted . We create the auxiliary variable and fill the
substitution table for all those similar nodes , in an iteration going from
leads to lags . */
2019-10-22 14:56:28 +02:00
int base_index = 0 ;
2018-06-04 12:52:14 +02:00
VariableNode * aux_var = nullptr ;
2019-08-19 18:22:55 +02:00
for ( auto rit = it - > second . rbegin ( ) ; rit ! = it - > second . rend ( ) ; + + rit )
2018-06-05 16:38:37 +02:00
if ( rit = = it - > second . rbegin ( ) )
{
2019-08-19 18:23:56 +02:00
/* Verify that we’ re not operating on a node with leads, since the
transformation does take into account the expectation operator . We only
need to do this for the first iteration of the loop , because we ’ re
going from leads to lags . */
if ( rit - > second - > maxLead ( ) > 0 )
{
cerr < < " Cannot substitute unary operations that contain leads " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-06-07 12:53:00 +02:00
int symb_id ;
2019-12-16 19:42:59 +01:00
auto vn = dynamic_cast < VariableNode * > ( argsubst ) ;
if ( ! vn )
2018-10-15 11:59:15 +02:00
symb_id = datatree . symbol_table . addUnaryOpAuxiliaryVar ( this - > idx , dynamic_cast < UnaryOpNode * > ( rit - > second ) , unary_op ) ;
2018-06-07 12:53:00 +02:00
else
2018-10-15 11:59:15 +02:00
symb_id = datatree . symbol_table . addUnaryOpAuxiliaryVar ( this - > idx , dynamic_cast < UnaryOpNode * > ( rit - > second ) , unary_op ,
2018-11-28 14:32:26 +01:00
vn - > symb_id , vn - > lag ) ;
2018-06-05 16:38:37 +02:00
aux_var = datatree . AddVariable ( symb_id , 0 ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( aux_var ,
dynamic_cast < UnaryOpNode * > ( rit - > second ) ) ) ;
2018-06-05 16:38:37 +02:00
subst_table [ rit - > second ] = dynamic_cast < VariableNode * > ( aux_var ) ;
2019-10-22 14:56:28 +02:00
base_index = rit - > first ;
2018-06-05 16:38:37 +02:00
}
else
2019-10-22 14:56:28 +02:00
subst_table [ rit - > second ] = dynamic_cast < VariableNode * > ( aux_var - > decreaseLeadsLags ( base_index - rit - > first ) ) ;
2018-05-30 16:48:08 +02:00
2020-07-08 12:13:35 +02:00
assert ( subst_table . find ( this ) ! = subst_table . end ( ) ) ;
return const_cast < VariableNode * > ( subst_table . at ( this ) ) ;
2018-05-30 16:48:08 +02:00
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
UnaryOpNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2019-02-15 12:52:46 +01:00
{
2019-02-20 12:59:55 +01:00
expr_t argsubst = arg - > substitutePacExpectation ( name , subexpr ) ;
2018-01-30 16:33:16 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
UnaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
UnaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
UnaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus | | deterministic_model )
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
expr_t argsubst = arg - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
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
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
UnaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
UnaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : uminus | | deterministic_model )
2009-10-07 18:34:42 +02:00
{
2010-08-18 13:45:07 +02:00
expr_t argsubst = arg - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
2009-10-07 18:34:42 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
else
{
if ( maxExoLead ( ) > = 1 )
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
else
return const_cast < UnaryOpNode * > ( this ) ;
}
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
UnaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t 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
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
UnaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : expectation )
2009-10-30 06:21:54 +01:00
{
2019-10-28 11:09:36 +01:00
if ( auto it = subst_table . find ( const_cast < UnaryOpNode * > ( this ) ) ; it ! = subst_table . end ( ) )
2011-10-25 16:46:12 +02:00
return const_cast < VariableNode * > ( it - > second ) ;
2009-10-30 06:21:54 +01:00
2011-10-25 16:46:12 +02:00
//Arriving here, we need to create an auxiliary variable for this Expectation Operator:
//AUX_EXPECT_(LEAD/LAG)_(period)_(arg.idx) OR
//AUX_EXPECT_(info_set_name)_(arg.idx)
2019-12-19 16:46:00 +01:00
int symb_id = datatree . symbol_table . addExpectationAuxiliaryVar ( expectation_information_set , arg - > idx , const_cast < UnaryOpNode * > ( this ) ) ;
2011-10-25 16:46:12 +02:00
expr_t newAuxE = datatree . AddVariable ( symb_id , 0 ) ;
2009-10-30 06:21:54 +01:00
2011-10-25 16:46:12 +02:00
if ( partial_information_model & & expectation_information_set = = 0 )
2019-12-16 19:42:59 +01:00
if ( ! dynamic_cast < VariableNode * > ( arg ) )
2009-10-30 06:21:54 +01:00
{
2011-10-25 16:46:12 +02:00
cerr < < " ERROR: In Partial Information models, EXPECTATION(0)(X) "
< < " can only be used when X is a single variable. " < < endl ;
exit ( EXIT_FAILURE ) ;
2009-10-30 06:21:54 +01:00
}
2010-01-18 23:08:44 +01:00
2018-07-18 16:18:26 +02:00
//take care of any nested expectation operators by calling arg->substituteExpectation(.), then decreaseLeadsLags for this UnaryOpcode::expectation operator
2011-10-25 16:46:12 +02:00
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t substexpr = ( arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) - > decreaseLeadsLags ( expectation_information_set ) ;
2019-12-16 19:42:59 +01:00
assert ( substexpr ) ;
2020-04-02 19:10:59 +02:00
neweqs . push_back ( datatree . AddEqual ( newAuxE , substexpr ) ) ; //AUXE_period_arg.idx = arg(lag-period)
2011-10-25 16:46:12 +02:00
newAuxE = datatree . AddVariable ( symb_id , expectation_information_set ) ;
2019-12-16 19:42:59 +01:00
assert ( dynamic_cast < VariableNode * > ( newAuxE ) ) ;
2011-10-25 16:46:12 +02:00
subst_table [ this ] = dynamic_cast < VariableNode * > ( newAuxE ) ;
return newAuxE ;
}
else
{
2010-09-16 19:18:45 +02:00
expr_t argsubst = arg - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-12-16 18:13:23 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2009-10-30 06:21:54 +01:00
}
2009-10-29 18:16:10 +01:00
}
2013-04-25 18:09:31 +02:00
expr_t
2013-05-17 16:51:34 +02:00
UnaryOpNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
2013-05-17 16:51:34 +02:00
expr_t argsubst = arg - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
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 ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
UnaryOpNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
2018-08-13 12:12:20 +02:00
return arg - > containsPacExpectation ( pac_model_name ) ;
2018-06-05 18:38:53 +02:00
}
2010-10-15 19:05:16 +02:00
expr_t
UnaryOpNode : : replaceTrendVar ( ) const
{
expr_t argsubst = arg - > replaceTrendVar ( ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
expr_t
2013-03-26 16:46:18 +01:00
UnaryOpNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
2013-03-26 16:46:18 +01:00
expr_t argsubst = arg - > detrend ( symb_id , log_trend , trend ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
UnaryOpNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
expr_t argsubst = arg - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2013-04-11 17:07:39 +02:00
bool
UnaryOpNode : : isInStaticForm ( ) const
{
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : steadyState | | op_code = = UnaryOpcode : : steadyStateParamDeriv
| | op_code = = UnaryOpcode : : steadyStateParam2ndDeriv
| | op_code = = UnaryOpcode : : expectation )
2013-04-11 17:07:39 +02:00
return false ;
else
return arg - > isInStaticForm ( ) ;
}
2018-08-09 16:14:40 +02:00
bool
UnaryOpNode : : isParamTimesEndogExpr ( ) const
{
return arg - > isParamTimesEndogExpr ( ) ;
}
2016-11-25 17:15:13 +01:00
bool
UnaryOpNode : : isVarModelReferenced ( const string & model_info_name ) const
{
return arg - > isVarModelReferenced ( model_info_name ) ;
}
void
UnaryOpNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
arg - > getEndosAndMaxLags ( model_endos_and_lags ) ;
}
2016-03-18 14:55:14 +01:00
expr_t
UnaryOpNode : : substituteStaticAuxiliaryVariable ( ) const
{
2019-12-19 16:46:00 +01:00
if ( op_code = = UnaryOpcode : : diff )
return datatree . Zero ;
2016-03-18 14:55:14 +01:00
expr_t argsubst = arg - > substituteStaticAuxiliaryVariable ( ) ;
2018-07-18 16:18:26 +02:00
if ( op_code = = UnaryOpcode : : expectation )
2016-03-21 14:42:09 +01:00
return argsubst ;
else
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
2016-03-18 14:55:14 +01:00
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
UnaryOpNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
2019-12-20 16:59:30 +01:00
expr_t argsubst = arg - > replaceVarsInEquation ( table ) ;
2019-01-28 14:57:30 +01:00
return buildSimilarUnaryOpNode ( argsubst , datatree ) ;
}
2018-09-05 16:41:33 +02:00
BinaryOpNode : : BinaryOpNode ( DataTree & datatree_arg , int idx_arg , const expr_t arg1_arg ,
2010-12-13 14:07:05 +01:00
BinaryOpcode op_code_arg , const expr_t arg2_arg , int powerDerivOrder_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
arg1 { arg1_arg } ,
arg2 { arg2_arg } ,
op_code { op_code_arg } ,
powerDerivOrder { powerDerivOrder_arg }
2017-06-23 18:01:07 +02:00
{
assert ( powerDerivOrder > = 0 ) ;
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 ( ) ) ) ;
}
2011-03-21 18:40:57 +01:00
expr_t
BinaryOpNode : : getNonZeroPartofEquation ( ) const
{
assert ( arg1 = = datatree . Zero | | arg2 = = datatree . Zero ) ;
if ( arg1 = = datatree . Zero )
return arg2 ;
return arg1 ;
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : composeDerivatives ( expr_t darg1 , expr_t darg2 )
2008-02-03 11:28:36 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t t11 , t12 , t13 , t14 , t15 ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2008-02-03 11:28:36 +01:00
return datatree . AddPlus ( darg1 , darg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2020-10-07 17:15:53 +02:00
case BinaryOpcode : : equal :
2008-02-03 11:28:36 +01:00
return datatree . AddMinus ( darg1 , darg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2008-02-03 11:28:36 +01:00
t11 = datatree . AddTimes ( darg1 , arg2 ) ;
t12 = datatree . AddTimes ( darg2 , arg1 ) ;
return datatree . AddPlus ( t11 , t12 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
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 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
case BinaryOpcode : : greater :
case BinaryOpcode : : lessEqual :
case BinaryOpcode : : greaterEqual :
case BinaryOpcode : : equalEqual :
case BinaryOpcode : : different :
2008-02-03 11:28:36 +01:00
return datatree . Zero ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2008-02-03 11:28:36 +01:00
if ( darg2 = = datatree . Zero )
2011-02-04 16:25:38 +01:00
if ( darg1 = = datatree . Zero )
2010-12-13 14:07:05 +01:00
return datatree . Zero ;
else
2019-12-16 19:42:59 +01:00
if ( dynamic_cast < NumConstNode * > ( arg2 ) )
2008-02-03 11:28:36 +01:00
{
t11 = datatree . AddMinus ( arg2 , datatree . One ) ;
t12 = datatree . AddPower ( arg1 , t11 ) ;
t13 = datatree . AddTimes ( arg2 , t12 ) ;
return datatree . AddTimes ( darg1 , t13 ) ;
}
2010-12-13 14:07:05 +01:00
else
return datatree . AddTimes ( darg1 , datatree . AddPowerDeriv ( arg1 , arg2 , powerDerivOrder + 1 ) ) ;
2008-02-03 11:28:36 +01:00
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 ) ;
}
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : powerDeriv :
2010-12-13 14:07:05 +01:00
if ( darg2 = = datatree . Zero )
return datatree . AddTimes ( darg1 , datatree . AddPowerDeriv ( arg1 , arg2 , powerDerivOrder + 1 ) ) ;
else
{
t11 = datatree . AddTimes ( darg2 , datatree . AddLog ( arg1 ) ) ;
t12 = datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( powerDerivOrder ) ) ;
t13 = datatree . AddTimes ( darg1 , t12 ) ;
t14 = datatree . AddDivide ( t13 , arg1 ) ;
t15 = datatree . AddPlus ( t11 , t14 ) ;
expr_t f = datatree . AddPower ( arg1 , t12 ) ;
2019-12-20 16:59:30 +01:00
expr_t first_part = datatree . AddTimes ( f , t15 ) ;
2010-12-13 14:07:05 +01:00
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
first_part = datatree . AddTimes ( first_part , datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( i ) ) ) ;
t13 = datatree . Zero ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
{
t11 = datatree . One ;
2011-02-04 16:25:38 +01:00
for ( int j = 0 ; j < powerDerivOrder ; j + + )
2010-12-13 14:07:05 +01:00
if ( i ! = j )
{
t12 = datatree . AddMinus ( arg2 , datatree . AddPossiblyNegativeConstant ( j ) ) ;
t11 = datatree . AddTimes ( t11 , t12 ) ;
}
t13 = datatree . AddPlus ( t13 , t11 ) ;
}
t13 = datatree . AddTimes ( darg2 , t13 ) ;
t14 = datatree . AddTimes ( f , t13 ) ;
return datatree . AddPlus ( first_part , t14 ) ;
}
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
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 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
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
}
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
}
2010-12-13 14:07:05 +01:00
expr_t
BinaryOpNode : : unpackPowerDeriv ( ) const
{
2018-07-18 16:18:26 +02:00
if ( op_code ! = BinaryOpcode : : powerDeriv )
2010-12-13 14:07:05 +01:00
return const_cast < BinaryOpNode * > ( this ) ;
expr_t front = datatree . One ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < powerDerivOrder ; i + + )
2010-12-13 14:07:05 +01:00
front = datatree . AddTimes ( front ,
datatree . AddMinus ( arg2 ,
datatree . AddPossiblyNegativeConstant ( i ) ) ) ;
expr_t tmp = datatree . AddPower ( arg1 ,
datatree . AddMinus ( arg2 ,
datatree . AddPossiblyNegativeConstant ( powerDerivOrder ) ) ) ;
return datatree . AddTimes ( front , tmp ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
BinaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getDerivative ( deriv_id ) ;
expr_t darg2 = arg2 - > getDerivative ( deriv_id ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 ) ;
}
2008-02-03 11:28:36 +01:00
int
2010-09-16 19:00:48 +02:00
BinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
// A temporary term behaves as a variable
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2009-12-16 18:13:23 +01:00
return 100 ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2009-12-16 18:13:23 +01:00
return 0 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
case BinaryOpcode : : different :
2009-12-16 18:13:23 +01:00
return 1 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
case BinaryOpcode : : greaterEqual :
case BinaryOpcode : : less :
case BinaryOpcode : : greater :
2009-12-16 18:13:23 +01:00
return 2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
2009-12-16 18:13:23 +01:00
return 3 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
case BinaryOpcode : : divide :
2009-12-16 18:13:23 +01:00
return 4 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
case BinaryOpcode : : powerDeriv :
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2009-12-16 18:13:23 +01:00
// 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 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
case BinaryOpcode : : max :
2009-12-16 18:13:23 +01:00
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2009-06-05 16:45:23 +02:00
2017-02-20 12:18:11 +01:00
int
BinaryOpNode : : precedenceJson ( const temporary_terms_t & temporary_terms ) const
{
// A temporary term behaves as a variable
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
return 100 ;
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2017-02-20 12:18:11 +01:00
return 0 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
case BinaryOpcode : : different :
2017-02-20 12:18:11 +01:00
return 1 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
case BinaryOpcode : : greaterEqual :
case BinaryOpcode : : less :
case BinaryOpcode : : greater :
2017-02-20 12:18:11 +01:00
return 2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
2017-02-20 12:18:11 +01:00
return 3 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
case BinaryOpcode : : divide :
2017-02-20 12:18:11 +01:00
return 4 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
case BinaryOpcode : : powerDeriv :
2017-02-20 12:18:11 +01:00
return 5 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
case BinaryOpcode : : max :
2017-02-20 12:18:11 +01:00
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2015-09-03 13:50:02 +02:00
int
2018-11-30 12:22:13 +01:00
BinaryOpNode : : cost ( const map < pair < int , int > , temporary_terms_t > & temp_terms_map , bool is_matlab ) const
2015-09-03 13:50:02 +02:00
{
// For a temporary term, the cost is null
2019-12-20 16:59:30 +01:00
for ( const auto & it : temp_terms_map )
2018-06-04 12:26:16 +02:00
if ( it . second . find ( const_cast < BinaryOpNode * > ( this ) ) ! = it . second . end ( ) )
2015-09-03 13:50:02 +02:00
return 0 ;
int arg_cost = arg1 - > cost ( temp_terms_map , is_matlab ) + arg2 - > cost ( temp_terms_map , is_matlab ) ;
return cost ( arg_cost , is_matlab ) ;
}
2009-06-05 16:45:23 +02:00
int
2020-05-13 16:58:19 +02:00
BinaryOpNode : : cost ( const vector < vector < temporary_terms_t > > & blocks_temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a temporary term, the cost is null
2020-05-13 16:58:19 +02:00
for ( const auto & blk_tt : blocks_temporary_terms )
for ( const auto & eq_tt : blk_tt )
if ( eq_tt . find ( const_cast < BinaryOpNode * > ( this ) ) ! = eq_tt . end ( ) )
return 0 ;
2009-06-05 16:45:23 +02:00
2020-05-06 17:13:47 +02:00
int arg_cost = arg1 - > cost ( blocks_temporary_terms , is_matlab ) + arg2 - > cost ( blocks_temporary_terms , is_matlab ) ;
2015-09-03 13:50:02 +02:00
return cost ( arg_cost , is_matlab ) ;
}
2009-06-05 16:45:23 +02:00
2015-09-03 13:50:02 +02:00
int
BinaryOpNode : : cost ( int cost , bool is_matlab ) const
{
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
case BinaryOpcode : : greater :
case BinaryOpcode : : lessEqual :
case BinaryOpcode : : greaterEqual :
case BinaryOpcode : : equalEqual :
case BinaryOpcode : : different :
2009-12-16 18:13:23 +01:00
return cost + 60 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
case BinaryOpcode : : times :
2009-12-16 18:13:23 +01:00
return cost + 90 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
case BinaryOpcode : : min :
2009-12-16 18:13:23 +01:00
return cost + 110 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2009-12-16 18:13:23 +01:00
return cost + 990 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
case BinaryOpcode : : powerDeriv :
2018-07-17 16:32:00 +02:00
return cost + ( min_cost_matlab / 2 + 1 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2009-12-16 18:13:23 +01:00
return cost ;
}
else
// Cost for C files
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
case BinaryOpcode : : greater :
case BinaryOpcode : : lessEqual :
case BinaryOpcode : : greaterEqual :
case BinaryOpcode : : equalEqual :
case BinaryOpcode : : different :
2009-12-16 18:13:23 +01:00
return cost + 2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
case BinaryOpcode : : times :
2009-12-16 18:13:23 +01:00
return cost + 4 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
case BinaryOpcode : : min :
2009-12-16 18:13:23 +01:00
return cost + 5 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2009-12-16 18:13:23 +01:00
return cost + 15 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2009-12-16 18:13:23 +01:00
return cost + 520 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : powerDeriv :
2020-04-21 19:07:57 +02:00
return cost + ( min_cost_c / 2 + 1 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2009-12-16 18:13:23 +01:00
return cost ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
void
2018-11-30 12:22:13 +01:00
BinaryOpNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < BinaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
2018-11-30 12:22:13 +01:00
reference_count [ this2 ] = { 1 , derivOrder } ;
arg1 - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
arg2 - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
2009-12-16 18:13:23 +01:00
}
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 ) */
2020-05-12 18:29:11 +02:00
auto & [ nref , min_order ] = it - > second ;
nref + + ;
if ( nref * cost ( temp_terms_map , is_matlab ) > min_cost ( is_matlab )
2018-07-18 16:18:26 +02:00
& & op_code ! = BinaryOpcode : : equal )
2020-05-12 18:29:11 +02:00
temp_terms_map [ min_order ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
void
2020-05-13 16:58:19 +02:00
BinaryOpNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < BinaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
2020-05-13 16:58:19 +02:00
reference_count [ this2 ] = { 1 , blk , eq } ;
arg1 - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
arg2 - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 16:58:19 +02:00
auto & [ nref , first_blk , first_eq ] = it - > second ;
2020-05-06 17:13:47 +02:00
nref + + ;
if ( nref * cost ( blocks_temporary_terms , false ) > min_cost_c
2018-07-18 16:18:26 +02:00
& & op_code ! = BinaryOpcode : : equal )
2020-05-13 16:58:19 +02:00
blocks_temporary_terms [ first_blk ] [ first_eq ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
double
2018-06-04 12:50:53 +02:00
BinaryOpNode : : eval_opcode ( double v1 , BinaryOpcode op_code , double v2 , int derivOrder ) noexcept ( false )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2019-12-16 19:42:59 +01:00
return v1 + v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2019-12-16 19:42:59 +01:00
return v1 - v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2019-12-16 19:42:59 +01:00
return v1 * v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2019-12-16 19:42:59 +01:00
return v1 / v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2019-12-16 19:42:59 +01:00
return pow ( v1 , v2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : powerDeriv :
2018-07-17 16:32:00 +02:00
if ( fabs ( v1 ) < near_zero & & v2 > 0
2012-05-21 18:34:10 +02:00
& & derivOrder > v2
2018-07-17 16:32:00 +02:00
& & fabs ( v2 - nearbyint ( v2 ) ) < near_zero )
2010-12-13 14:07:05 +01:00
return 0.0 ;
else
{
double dxp = pow ( v1 , v2 - derivOrder ) ;
2011-02-04 16:25:38 +01:00
for ( int i = 0 ; i < derivOrder ; i + + )
2010-12-13 14:07:05 +01:00
dxp * = v2 - - ;
return dxp ;
}
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
2008-02-03 11:28:36 +01:00
if ( v1 < v2 )
return v2 ;
else
return v1 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
2008-02-03 11:28:36 +01:00
if ( v1 > v2 )
return v2 ;
else
return v1 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
2019-12-16 19:42:59 +01:00
return v1 < v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greater :
2019-12-16 19:42:59 +01:00
return v1 > v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
2019-12-16 19:42:59 +01:00
return v1 < = v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greaterEqual :
2019-12-16 19:42:59 +01:00
return v1 > = v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
2019-12-16 19:42:59 +01:00
return v1 = = v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : different :
2019-12-16 19:42:59 +01:00
return v1 ! = v2 ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2008-02-03 11:28:36 +01:00
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
2018-06-04 12:50:53 +02:00
BinaryOpNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2008-02-03 11:28:36 +01:00
{
double v1 = arg1 - > eval ( eval_context ) ;
double v2 = arg2 - > eval ( eval_context ) ;
2010-12-13 14:07:05 +01:00
return eval_opcode ( v1 , op_code , v2 , powerDerivOrder ) ;
2008-02-03 11:28:36 +01:00
}
void
2010-12-10 11:50:27 +01:00
BinaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2020-05-13 12:53:47 +02:00
if ( auto this2 = const_cast < BinaryOpNode * > ( this ) ;
temporary_terms . find ( this2 ) ! = temporary_terms . end ( ) )
2009-12-16 18:13:23 +01:00
{
if ( dynamic )
{
2020-05-13 12:53:47 +02:00
FLDT_ fldt ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 12:53:47 +02:00
FLDST_ fldst ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
2018-07-18 16:18:26 +02:00
if ( op_code = = BinaryOpcode : : powerDeriv )
2010-12-17 17:17:40 +01:00
{
FLDC_ fldc ( powerDerivOrder ) ;
fldc . write ( CompileCode , instruction_number ) ;
}
2020-05-13 12:53:47 +02:00
arg1 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2018-07-18 16:18:26 +02:00
FBINARY_ fbinary { static_cast < int > ( op_code ) } ;
2010-07-23 11:20:24 +02:00
fbinary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2015-05-12 16:36:03 +02:00
bool
BinaryOpNode : : containsExternalFunction ( ) const
{
return arg1 - > containsExternalFunction ( )
| | arg2 - > containsExternalFunction ( ) ;
}
2018-09-18 14:50:31 +02:00
void
BinaryOpNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " BinaryOpNode " ,) "
< < R " ( " op " : " ) " ;
2018-09-18 14:50:31 +02:00
switch ( op_code )
{
case BinaryOpcode : : plus :
output < < " + " ;
break ;
case BinaryOpcode : : minus :
output < < " - " ;
break ;
case BinaryOpcode : : times :
output < < " * " ;
break ;
case BinaryOpcode : : divide :
output < < " / " ;
break ;
case BinaryOpcode : : power :
output < < " ^ " ;
break ;
case BinaryOpcode : : less :
output < < " < " ;
break ;
case BinaryOpcode : : greater :
output < < " > " ;
break ;
case BinaryOpcode : : lessEqual :
output < < " <= " ;
break ;
case BinaryOpcode : : greaterEqual :
output < < " >= " ;
break ;
case BinaryOpcode : : equalEqual :
output < < " == " ;
break ;
case BinaryOpcode : : different :
output < < " != " ;
break ;
case BinaryOpcode : : equal :
output < < " = " ;
break ;
case BinaryOpcode : : max :
output < < " max " ;
break ;
case BinaryOpcode : : min :
output < < " min " ;
break ;
case BinaryOpcode : : powerDeriv :
output < < " power_deriv " ;
break ;
}
2019-04-03 16:32:52 +02:00
output < < R " ( " , " arg1 " : ) " ;
2018-09-18 14:50:31 +02:00
arg1 - > writeJsonAST ( output ) ;
2019-04-03 16:32:52 +02:00
output < < R " (, " arg2 " : ) " ;
2018-09-18 14:50:31 +02:00
arg2 - > writeJsonAST ( output ) ;
output < < " } " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
BinaryOpNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
// If current node is a temporary term
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < BinaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
2018-07-18 16:18:26 +02:00
if ( op_code = = BinaryOpcode : : max | | op_code = = BinaryOpcode : : min )
2017-02-02 15:09:43 +01:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
2017-02-02 15:09:43 +01:00
output < < " max( " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
2017-02-02 15:09:43 +01:00
output < < " min( " ;
break ;
default :
;
}
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " , " ;
2017-10-16 17:24:55 +02:00
arg2 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " ) " ;
return ;
}
2018-07-18 16:18:26 +02:00
if ( op_code = = BinaryOpcode : : powerDeriv )
2017-09-27 15:24:33 +02:00
{
output < < " get_power_deriv( " ;
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-09-27 15:24:33 +02:00
output < < " , " ;
2017-10-16 17:24:55 +02:00
arg2 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-09-27 15:24:33 +02:00
output < < " , " < < powerDerivOrder < < " ) " ;
2017-02-02 15:09:43 +01:00
return ;
}
2017-02-20 12:18:11 +01:00
int prec = precedenceJson ( temporary_terms ) ;
2017-02-02 15:09:43 +01:00
bool close_parenthesis = false ;
// If left argument has a lower precedence, or if current and left argument are both power operators,
// add parenthesis around left argument
2019-12-16 19:42:59 +01:00
if ( auto barg1 = dynamic_cast < BinaryOpNode * > ( arg1 ) ;
2019-10-28 11:09:36 +01:00
arg1 - > precedenceJson ( temporary_terms ) < prec
2019-12-16 19:42:59 +01:00
| | ( op_code = = BinaryOpcode : : power & & barg1 & & barg1 - > op_code = = BinaryOpcode : : power ) )
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
output < < " ( " ;
2017-02-02 15:09:43 +01:00
close_parenthesis = true ;
}
// Write left argument
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
if ( close_parenthesis )
2017-02-20 12:18:11 +01:00
output < < " ) " ;
2017-02-02 15:09:43 +01:00
// Write current operator symbol
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2017-02-02 15:09:43 +01:00
output < < " + " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2017-02-02 15:09:43 +01:00
output < < " - " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2017-02-02 15:09:43 +01:00
output < < " * " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2017-02-02 15:09:43 +01:00
output < < " / " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2017-02-02 15:09:43 +01:00
output < < " ^ " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
2017-02-02 15:09:43 +01:00
output < < " < " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greater :
2017-02-02 15:09:43 +01:00
output < < " > " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
2017-02-02 15:09:43 +01:00
output < < " <= " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greaterEqual :
2017-02-02 15:09:43 +01:00
output < < " >= " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
2017-02-02 15:09:43 +01:00
output < < " == " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : different :
2017-02-02 15:09:43 +01:00
output < < " != " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2017-02-02 15:09:43 +01:00
output < < " = " ;
break ;
default :
;
}
close_parenthesis = false ;
/* 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 */
2019-12-16 19:42:59 +01:00
auto barg2 = dynamic_cast < BinaryOpNode * > ( arg2 ) ;
2019-10-28 11:09:36 +01:00
if ( int arg2_prec = arg2 - > precedenceJson ( temporary_terms ) ; arg2_prec < prec
2019-12-16 19:42:59 +01:00
| | ( op_code = = BinaryOpcode : : power & & barg2 & & barg2 - > op_code = = BinaryOpcode : : power )
2018-07-18 16:18:26 +02:00
| | ( op_code = = BinaryOpcode : : minus & & arg2_prec = = prec )
| | ( op_code = = BinaryOpcode : : divide & & arg2_prec = = prec ) )
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
output < < " ( " ;
2017-02-02 15:09:43 +01:00
close_parenthesis = true ;
}
// Write right argument
2017-10-16 17:24:55 +02:00
arg2 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
if ( close_parenthesis )
2017-02-20 12:18:11 +01:00
output < < " ) " ;
2017-02-02 15:09:43 +01:00
}
2008-02-03 11:28:36 +01:00
void
BinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2008-02-03 11:28:36 +01:00
2010-12-13 14:07:05 +01:00
// Treat derivative of Power
2018-07-18 16:18:26 +02:00
if ( op_code = = BinaryOpcode : : powerDeriv )
2010-12-13 14:07:05 +01:00
{
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2018-03-27 17:14:30 +02:00
unpackPowerDeriv ( ) - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-12-13 14:07:05 +01:00
else
{
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : juliaStaticModel | | output_type = = ExprNodeOutputType : : juliaDynamicModel )
2015-08-18 15:49:48 +02:00
output < < " get_power_deriv( " ;
else
output < < " getPowerDeriv( " ;
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-12-13 14:07:05 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-12-13 14:07:05 +01:00
output < < " , " < < powerDerivOrder < < " ) " ;
}
return ;
}
2009-12-16 18:13:23 +01:00
// Treat special case of power operator in C, and case of max and min operators
2018-09-05 18:27:13 +02:00
if ( ( op_code = = BinaryOpcode : : power & & isCOutput ( output_type ) ) | | op_code = = BinaryOpcode : : max | | op_code = = BinaryOpcode : : min )
2009-12-16 18:13:23 +01:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2009-12-16 18:13:23 +01:00
output < < " pow( " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
2020-06-23 15:59:35 +02:00
if ( isCOutput ( output_type ) )
output < < " fmax( " ;
else
output < < " max( " ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
2020-06-23 15:59:35 +02:00
if ( isCOutput ( output_type ) )
output < < " fmin( " ;
else
output < < " min( " ;
2009-12-16 18:13:23 +01:00
break ;
default :
;
}
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2009-12-16 18:13:23 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2009-12-16 18:13:23 +01:00
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
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) & & op_code = = BinaryOpcode : : divide )
2019-04-03 16:32:52 +02:00
output < < R " ( \f rac{) " ;
2009-12-16 18:13:23 +01:00
else
{
// If left argument has a lower precedence, or if current and left argument are both power operators, add parenthesis around left argument
2019-12-16 19:42:59 +01:00
auto barg1 = dynamic_cast < BinaryOpNode * > ( arg1 ) ;
2009-12-16 18:13:23 +01:00
if ( arg1 - > precedence ( output_type , temporary_terms ) < prec
2018-07-18 16:18:26 +02:00
| | ( op_code = = BinaryOpcode : : power & & barg1 ! = nullptr & & barg1 - > op_code = = BinaryOpcode : : power ) )
2009-12-16 18:13:23 +01:00
{
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
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_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
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) & & op_code = = BinaryOpcode : : divide )
2009-12-16 18:13:23 +01:00
output < < " } " ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
// Write current operator symbol
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2009-12-16 18:13:23 +01:00
output < < " + " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2009-12-16 18:13:23 +01:00
output < < " - " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2019-04-03 16:32:52 +02:00
output < < R " ( \ , ) " ;
2009-12-16 18:13:23 +01:00
else
output < < " * " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2018-09-05 18:27:13 +02:00
if ( ! isLatexOutput ( output_type ) )
2009-12-16 18:13:23 +01:00
output < < " / " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2009-12-16 18:13:23 +01:00
output < < " ^ " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
2009-12-16 18:13:23 +01:00
output < < " < " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greater :
2009-12-16 18:13:23 +01:00
output < < " > " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2019-04-03 16:32:52 +02:00
output < < R " ( \ leq ) " ;
2009-12-16 18:13:23 +01:00
else
output < < " <= " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greaterEqual :
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2019-04-03 16:32:52 +02:00
output < < R " ( \ geq ) " ;
2009-12-16 18:13:23 +01:00
else
output < < " >= " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
2009-12-16 18:13:23 +01:00
output < < " == " ;
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : different :
2018-09-05 18:27:13 +02:00
if ( isMatlabOutput ( output_type ) )
2009-12-16 18:13:23 +01:00
output < < " ~= " ;
else
{
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) | | isJuliaOutput ( output_type ) )
2009-12-16 18:13:23 +01:00
output < < " != " ;
else
2019-04-03 16:32:52 +02:00
output < < R " ( \n eq ) " ;
2009-12-16 18:13:23 +01:00
}
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2009-12-16 18:13:23 +01:00
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
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) & & ( op_code = = BinaryOpcode : : power | | op_code = = BinaryOpcode : : divide ) )
2009-12-16 18:13:23 +01:00
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 */
2019-12-16 19:42:59 +01:00
auto barg2 = dynamic_cast < BinaryOpNode * > ( arg2 ) ;
2019-10-28 11:09:36 +01:00
if ( int arg2_prec = arg2 - > precedence ( output_type , temporary_terms ) ; arg2_prec < prec
2019-12-16 19:42:59 +01:00
| | ( op_code = = BinaryOpcode : : power & & barg2 & & barg2 - > op_code = = BinaryOpcode : : power & & ! isLatexOutput ( output_type ) )
2018-07-18 16:18:26 +02:00
| | ( op_code = = BinaryOpcode : : minus & & arg2_prec = = prec )
2018-09-05 18:27:13 +02:00
| | ( op_code = = BinaryOpcode : : divide & & arg2_prec = = prec & & ! isLatexOutput ( output_type ) ) )
2009-12-16 18:13:23 +01:00
{
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
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2008-02-03 11:28:36 +01:00
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) & & ( op_code = = BinaryOpcode : : power | | op_code = = BinaryOpcode : : divide ) )
2009-12-16 18:13:23 +01:00
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 ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2018-03-27 17:14:30 +02:00
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-04 16:40:07 +01:00
}
2017-02-20 12:18:11 +01:00
void
BinaryOpNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
arg2 - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
}
2010-12-10 11:50:27 +01:00
void
BinaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2011-02-04 16:25:38 +01:00
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
2020-05-13 12:53:47 +02:00
arg1 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
}
2018-05-16 12:17:06 +02:00
int
BinaryOpNode : : VarMinLag ( ) const
{
return min ( arg1 - > VarMinLag ( ) , arg2 - > VarMinLag ( ) ) ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
BinaryOpNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2019-10-22 16:04:24 +02:00
return max ( arg1 - > VarMaxLag ( lhs_lag_equiv ) ,
arg2 - > VarMaxLag ( lhs_lag_equiv ) ) ;
2018-04-16 13:50:31 +02:00
}
void
BinaryOpNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2008-02-03 11:28:36 +01:00
void
2018-06-04 14:17:36 +02:00
BinaryOpNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2009-07-10 18:42:08 +02:00
{
2013-11-29 15:32:49 +01:00
arg1 - > collectDynamicVariables ( type_arg , result ) ;
arg2 - > collectDynamicVariables ( type_arg , result ) ;
2013-09-13 20:37:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : Compute_RHS ( expr_t arg1 , expr_t arg2 , int op , int op_type ) const
2009-08-25 11:43:01 +02:00
{
2009-12-16 18:13:23 +01:00
switch ( op_type )
2009-08-25 11:43:01 +02:00
{
case 0 : /*Unary Operator*/
2018-07-18 16:18:26 +02:00
switch ( static_cast < UnaryOpcode > ( op ) )
2009-08-25 11:43:01 +02:00
{
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : uminus :
2020-04-02 14:36:26 +02:00
return datatree . AddUMinus ( arg1 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : exp :
2020-04-02 14:36:26 +02:00
return datatree . AddExp ( arg1 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log :
2020-04-02 14:36:26 +02:00
return datatree . AddLog ( arg1 ) ;
2018-07-18 16:18:26 +02:00
case UnaryOpcode : : log10 :
2020-04-02 14:36:26 +02:00
return datatree . AddLog10 ( arg1 ) ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " BinaryOpNode::Compute_RHS: case not handled " ;
exit ( EXIT_FAILURE ) ;
2009-12-16 18:13:23 +01:00
}
break ;
case 1 : /*Binary Operator*/
2018-07-18 16:18:26 +02:00
switch ( static_cast < BinaryOpcode > ( op ) )
2009-12-16 18:13:23 +01:00
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2020-04-02 14:36:26 +02:00
return datatree . AddPlus ( arg1 , arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2020-04-02 14:36:26 +02:00
return datatree . AddMinus ( arg1 , arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2020-04-02 14:36:26 +02:00
return datatree . AddTimes ( arg1 , arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2020-04-02 14:36:26 +02:00
return datatree . AddDivide ( arg1 , arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2020-04-02 14:36:26 +02:00
return datatree . AddPower ( arg1 , arg2 ) ;
2011-06-10 11:59:34 +02:00
default :
cerr < < " BinaryOpNode::Compute_RHS: case not handled " ;
exit ( EXIT_FAILURE ) ;
2009-08-25 11:43:01 +02:00
}
break ;
2009-12-16 18:13:23 +01:00
}
2018-06-04 16:39:01 +02:00
return nullptr ;
2009-12-16 18:13:23 +01:00
}
2020-04-02 14:36:26 +02:00
void
BinaryOpNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
{
arg1 - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
arg2 - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
if ( contain_var . count ( arg1 ) > 0 | | contain_var . count ( arg2 ) > 0 )
contain_var . insert ( const_cast < BinaryOpNode * > ( this ) ) ;
}
BinaryOpNode *
BinaryOpNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
assert ( contain_var . count ( const_cast < BinaryOpNode * > ( this ) ) > 0 ) ;
bool arg1_contains_var = contain_var . count ( arg1 ) > 0 ;
bool arg2_contains_var = contain_var . count ( arg2 ) > 0 ;
assert ( arg1_contains_var | | arg2_contains_var ) ;
if ( arg1_contains_var & & arg2_contains_var )
throw NormalizationFailed ( ) ;
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
rhs = datatree . AddMinus ( rhs , arg2 ) ;
else
rhs = datatree . AddMinus ( rhs , arg1 ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
rhs = datatree . AddPlus ( rhs , arg2 ) ;
else
rhs = datatree . AddMinus ( arg1 , rhs ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
rhs = datatree . AddDivide ( rhs , arg2 ) ;
2009-12-16 18:13:23 +01:00
else
2020-04-02 14:36:26 +02:00
rhs = datatree . AddDivide ( rhs , arg1 ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
rhs = datatree . AddTimes ( rhs , arg2 ) ;
2009-12-16 18:13:23 +01:00
else
2020-04-02 14:36:26 +02:00
rhs = datatree . AddDivide ( arg1 , rhs ) ;
2009-12-16 18:13:23 +01:00
break ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
rhs = datatree . AddPower ( rhs , datatree . AddDivide ( datatree . One , arg2 ) ) ;
2009-12-16 18:13:23 +01:00
else
2020-04-02 14:36:26 +02:00
// a^f(X)=rhs is normalized in f(X)=ln(rhs)/ln(a)
rhs = datatree . AddDivide ( datatree . AddLog ( rhs ) , datatree . AddLog ( arg1 ) ) ;
2009-08-25 11:43:01 +02:00
break ;
2020-04-02 14:36:26 +02:00
case BinaryOpcode : : equal :
cerr < < " BinaryOpCode::normalizeEquationHelper: this case should not happen " < < endl ;
exit ( EXIT_FAILURE ) ;
2011-06-10 11:59:34 +02:00
default :
2020-04-02 14:36:26 +02:00
throw NormalizationFailed ( ) ;
2009-08-25 11:43:01 +02:00
}
2020-04-02 14:36:26 +02:00
if ( arg1_contains_var )
return arg1 - > normalizeEquationHelper ( contain_var , rhs ) ;
else
return arg2 - > normalizeEquationHelper ( contain_var , rhs ) ;
}
BinaryOpNode *
BinaryOpNode : : normalizeEquation ( int symb_id , int lag ) const
{
assert ( op_code = = BinaryOpcode : : equal ) ;
set < expr_t > contain_var ;
computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
bool arg1_contains_var = contain_var . count ( arg1 ) > 0 ;
bool arg2_contains_var = contain_var . count ( arg2 ) > 0 ;
assert ( arg1_contains_var | | arg2_contains_var ) ;
if ( arg1_contains_var & & arg2_contains_var )
throw NormalizationFailed ( ) ;
return arg1_contains_var ? arg1 - > normalizeEquationHelper ( contain_var , arg2 )
: arg2 - > normalizeEquationHelper ( contain_var , arg1 ) ;
2009-08-25 11:43:01 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
BinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
BinaryOpNode : : buildSimilarBinaryOpNode ( expr_t alt_arg1 , expr_t alt_arg2 , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : plus :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddPlus ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : minus :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddMinus ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : times :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddTimes ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : divide :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddDivide ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : power :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddPower ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equal :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddEqual ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : max :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddMax ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : min :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddMin ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : less :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddLess ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greater :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddGreater ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : lessEqual :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddLessEqual ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : greaterEqual :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddGreaterEqual ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : equalEqual :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddEqualEqual ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : different :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddDifferent ( alt_arg1 , alt_arg2 ) ;
2018-07-18 16:18:26 +02:00
case BinaryOpcode : : powerDeriv :
2011-03-23 11:36:08 +01:00
return alt_datatree . AddPowerDeriv ( alt_arg1 , alt_arg2 , powerDerivOrder ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
BinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg1 = arg1 - > toStatic ( static_datatree ) ;
expr_t sarg2 = arg2 - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( sarg1 , sarg2 , static_datatree ) ;
}
2015-12-18 15:17:32 +01:00
void
BinaryOpNode : : computeXrefs ( EquationInfo & ei ) const
{
arg1 - > computeXrefs ( ei ) ;
arg2 - > computeXrefs ( ei ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
2018-10-10 13:07:25 +02:00
BinaryOpNode : : clone ( DataTree & datatree ) const
2010-10-15 19:05:16 +02:00
{
2018-10-10 13:07:25 +02:00
expr_t substarg1 = arg1 - > clone ( datatree ) ;
expr_t substarg2 = arg2 - > clone ( datatree ) ;
return buildSimilarBinaryOpNode ( substarg1 , substarg2 , datatree ) ;
2010-10-15 19:05:16 +02:00
}
2009-09-30 17:10:31 +02:00
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 ( ) ) ;
}
2010-08-19 15:20:54 +02:00
int
BinaryOpNode : : maxEndoLag ( ) const
{
return max ( arg1 - > maxEndoLag ( ) , arg2 - > maxEndoLag ( ) ) ;
}
int
BinaryOpNode : : maxExoLag ( ) const
{
return max ( arg1 - > maxExoLag ( ) , arg2 - > maxExoLag ( ) ) ;
}
2012-05-26 20:53:48 +02:00
int
BinaryOpNode : : maxLead ( ) const
{
return max ( arg1 - > maxLead ( ) , arg2 - > maxLead ( ) ) ;
}
2018-02-28 17:33:00 +01:00
int
BinaryOpNode : : maxLag ( ) const
{
return max ( arg1 - > maxLag ( ) , arg2 - > maxLag ( ) ) ;
}
2018-12-05 15:17:00 +01:00
int
BinaryOpNode : : maxLagWithDiffsExpanded ( ) const
{
return max ( arg1 - > maxLagWithDiffsExpanded ( ) , arg2 - > maxLagWithDiffsExpanded ( ) ) ;
}
2018-04-17 15:17:28 +02:00
expr_t
BinaryOpNode : : undiff ( ) const
{
expr_t arg1subst = arg1 - > undiff ( ) ;
expr_t arg2subst = arg2 - > undiff ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
BinaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
BinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
BinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t 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 ) ;
2010-08-18 13:45:07 +02:00
if ( deterministic_model )
2009-09-30 17:10:31 +02:00
{
2010-08-18 13:45:07 +02:00
arg1subst = maxendolead1 > = 2 ? arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxendolead2 > = 2 ? arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg2 ;
2009-09-30 17:10:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2010-08-18 13:45:07 +02:00
}
else
2019-10-25 12:29:58 +02:00
switch ( op_code )
{
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
case BinaryOpcode : : equal :
arg1subst = maxendolead1 > = 2 ? arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxendolead2 > = 2 ? arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case BinaryOpcode : : times :
case BinaryOpcode : : divide :
if ( maxendolead1 > = 2 & & maxendolead2 = = 0 & & arg2 - > maxExoLead ( ) = = 0 )
{
arg1subst = arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxendolead1 = = 0 & & arg1 - > maxExoLead ( ) = = 0
& & maxendolead2 > = 2 & & op_code = = BinaryOpcode : : times )
{
arg2subst = arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
BinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
BinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst , arg2subst ;
2009-10-07 18:34:42 +02:00
int maxexolead1 = arg1 - > maxExoLead ( ) , maxexolead2 = arg2 - > maxExoLead ( ) ;
if ( maxexolead1 < 1 & & maxexolead2 < 1 )
return const_cast < BinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
if ( deterministic_model )
2009-10-07 18:34:42 +02:00
{
2010-08-18 13:45:07 +02:00
arg1subst = maxexolead1 > = 1 ? arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxexolead2 > = 1 ? arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg2 ;
2009-10-07 18:34:42 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2010-08-18 13:45:07 +02:00
}
else
2019-10-25 12:29:58 +02:00
switch ( op_code )
{
case BinaryOpcode : : plus :
case BinaryOpcode : : minus :
case BinaryOpcode : : equal :
arg1subst = maxexolead1 > = 1 ? arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg1 ;
arg2subst = maxexolead2 > = 1 ? arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) : arg2 ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
case BinaryOpcode : : times :
case BinaryOpcode : : divide :
if ( maxexolead1 > = 1 & & maxexolead2 = = 0 & & arg2 - > maxEndoLead ( ) = = 0 )
{
arg1subst = arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2 , datatree ) ;
}
if ( maxexolead1 = = 0 & & arg1 - > maxEndoLead ( ) = = 0
& & maxexolead2 > = 1 & & op_code = = BinaryOpcode : : times )
{
arg2subst = arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
default :
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2009-10-07 18:34:42 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
BinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t 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
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
BinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-30 06:21:54 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2009-10-29 18:16:10 +01:00
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
BinaryOpNode : : substituteAdl ( ) const
{
expr_t arg1subst = arg1 - > substituteAdl ( ) ;
expr_t arg2subst = arg2 - > substituteAdl ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
BinaryOpNode : : substituteModelLocalVariables ( ) const
{
expr_t arg1subst = arg1 - > substituteModelLocalVariables ( ) ;
expr_t arg2subst = arg2 - > substituteModelLocalVariables ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
BinaryOpNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
expr_t arg1subst = arg1 - > substituteVarExpectation ( subst_table ) ;
expr_t arg2subst = arg2 - > substituteVarExpectation ( subst_table ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
BinaryOpNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
2019-10-22 14:56:28 +02:00
arg1 - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
arg2 - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
BinaryOpNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
2019-10-22 14:56:28 +02:00
arg1 - > findDiffNodes ( nodes ) ;
arg2 - > findDiffNodes ( nodes ) ;
2018-03-02 12:32:01 +01:00
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
BinaryOpNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2017-06-12 14:56:44 +02:00
{
2019-10-22 14:56:28 +02:00
expr_t arg1subst = arg1 - > substituteDiff ( nodes , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteDiff ( nodes , subst_table , neweqs ) ;
2017-07-03 16:38:44 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
2017-06-12 14:56:44 +02:00
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
BinaryOpNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
2019-10-22 14:56:28 +02:00
expr_t arg1subst = arg1 - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2018-05-31 15:34:25 +02:00
int
BinaryOpNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-12-05 12:38:46 +01:00
return max ( arg1 - > countDiffs ( ) , arg2 - > countDiffs ( ) ) ;
2018-02-08 13:07:15 +01:00
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
BinaryOpNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-01-30 16:33:16 +01:00
{
2019-02-20 12:59:55 +01:00
expr_t arg1subst = arg1 - > substitutePacExpectation ( name , subexpr ) ;
expr_t arg2subst = arg2 - > substitutePacExpectation ( name , subexpr ) ;
2018-01-30 16:33:16 +01:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2013-04-25 18:09:31 +02:00
expr_t
2013-05-17 16:51:34 +02:00
BinaryOpNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
2013-05-17 16:51:34 +02:00
expr_t arg1subst = arg1 - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2011-03-21 18:40:57 +01:00
expr_t
BinaryOpNode : : addMultipliersToConstraints ( int i )
{
int symb_id = datatree . symbol_table . addMultiplierAuxiliaryVar ( i ) ;
expr_t newAuxLM = datatree . AddVariable ( symb_id , 0 ) ;
return datatree . AddEqual ( datatree . AddTimes ( newAuxLM , datatree . AddMinus ( arg1 , arg2 ) ) , datatree . Zero ) ;
}
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 ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
BinaryOpNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
2019-12-16 19:42:59 +01:00
return arg1 - > containsPacExpectation ( pac_model_name ) | | arg2 - > containsPacExpectation ( pac_model_name ) ;
2018-06-05 18:38:53 +02:00
}
2010-10-15 19:05:16 +02:00
expr_t
BinaryOpNode : : replaceTrendVar ( ) const
{
expr_t arg1subst = arg1 - > replaceTrendVar ( ) ;
expr_t arg2subst = arg2 - > replaceTrendVar ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
expr_t
2013-03-26 16:46:18 +01:00
BinaryOpNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
2013-03-26 16:46:18 +01:00
expr_t arg1subst = arg1 - > detrend ( symb_id , log_trend , trend ) ;
expr_t arg2subst = arg2 - > detrend ( symb_id , log_trend , trend ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
BinaryOpNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
expr_t arg1subst = arg1 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg2subst = arg2 - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2013-04-11 17:07:39 +02:00
bool
BinaryOpNode : : isInStaticForm ( ) const
{
return arg1 - > isInStaticForm ( ) & & arg2 - > isInStaticForm ( ) ;
}
2018-08-31 12:35:51 +02:00
bool
2018-09-13 12:21:23 +02:00
BinaryOpNode : : findTargetVariableHelper1 ( int lhs_symb_id , int rhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
if ( lhs_symb_id = = rhs_symb_id )
return true ;
try
{
if ( datatree . symbol_table . isAuxiliaryVariable ( rhs_symb_id )
& & lhs_symb_id = = datatree . symbol_table . getOrigSymbIdForAuxVar ( rhs_symb_id ) )
return true ;
}
catch ( . . . )
{
}
return false ;
}
int
2018-09-13 12:21:23 +02:00
BinaryOpNode : : findTargetVariableHelper ( const expr_t arg1 , const expr_t arg2 ,
int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
set < int > params ;
arg1 - > collectVariables ( SymbolType : : parameter , params ) ;
if ( params . size ( ) ! = 1 )
return - 1 ;
set < pair < int , int > > endogs ;
arg2 - > collectDynamicVariables ( SymbolType : : endogenous , endogs ) ;
2019-12-16 19:42:59 +01:00
if ( auto testarg2 = dynamic_cast < BinaryOpNode * > ( arg2 ) ;
endogs . size ( ) = = 2 & & testarg2 & & testarg2 - > op_code = = BinaryOpcode : : minus
& & dynamic_cast < VariableNode * > ( testarg2 - > arg1 )
& & dynamic_cast < VariableNode * > ( testarg2 - > arg2 ) )
2018-08-31 12:35:51 +02:00
{
2019-12-16 19:42:59 +01:00
if ( findTargetVariableHelper1 ( lhs_symb_id , endogs . begin ( ) - > first ) )
return endogs . rbegin ( ) - > first ;
else if ( findTargetVariableHelper1 ( lhs_symb_id , endogs . rbegin ( ) - > first ) )
return endogs . begin ( ) - > first ;
2018-08-31 12:35:51 +02:00
}
return - 1 ;
}
int
2018-09-13 12:21:23 +02:00
BinaryOpNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
2018-09-13 12:21:23 +02:00
int retval = findTargetVariableHelper ( arg1 , arg2 , lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
if ( retval < 0 )
2018-09-13 12:21:23 +02:00
retval = findTargetVariableHelper ( arg2 , arg1 , lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
if ( retval < 0 )
2018-09-13 12:21:23 +02:00
retval = arg1 - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
if ( retval < 0 )
2018-09-13 12:21:23 +02:00
retval = arg2 - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
return retval ;
}
2019-03-05 10:57:15 +01:00
2018-02-15 17:06:30 +01:00
void
2019-03-05 10:57:15 +01:00
BinaryOpNode : : getPacAREC ( int lhs_symb_id , int lhs_orig_symb_id ,
2019-03-07 11:31:36 +01:00
pair < int , vector < tuple < int , bool , int > > > & ec_params_and_vars ,
2020-09-11 16:45:19 +02:00
vector < tuple < int , int , int > > & ar_params_and_vars ,
2019-03-05 10:57:15 +01:00
vector < tuple < int , int , int , double > > & additive_vars_params_and_constants ) const
2018-02-15 17:06:30 +01:00
{
2020-07-23 14:45:32 +02:00
ec_params_and_vars . first = - 1 ;
2019-03-05 10:57:15 +01:00
vector < pair < expr_t , int > > terms ;
decomposeAdditiveTerms ( terms , 1 ) ;
2019-12-16 19:42:59 +01:00
for ( auto it = terms . begin ( ) ; it ! = terms . end ( ) ; + + it )
if ( auto bopn = dynamic_cast < BinaryOpNode * > ( it - > first ) ; bopn )
2019-10-28 11:09:36 +01:00
{
2020-07-23 14:45:32 +02:00
try
2019-10-28 11:09:36 +01:00
{
2020-07-23 14:45:32 +02:00
auto [ param_id , target_id ] = bopn - > matchParamTimesTargetMinusVariable ( lhs_orig_symb_id ) ;
ec_params_and_vars = { param_id , { { target_id , true , 1 } , { lhs_orig_symb_id , false , - 1 } } } ;
2019-10-28 11:09:36 +01:00
terms . erase ( it ) ;
break ;
}
2020-07-23 14:45:32 +02:00
catch ( MatchFailureException & e )
{
}
2019-10-28 11:09:36 +01:00
}
2019-03-05 10:57:15 +01:00
if ( ec_params_and_vars . first < 0 )
2018-02-15 17:06:30 +01:00
{
2019-03-05 10:57:15 +01:00
cerr < < " Error finding EC part of PAC equation " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-08-09 16:14:40 +02:00
}
2019-12-20 16:59:30 +01:00
for ( const auto & it : terms )
2019-03-05 10:57:15 +01:00
{
2019-03-19 18:31:27 +01:00
if ( dynamic_cast < PacExpectationNode * > ( it . first ) )
2019-03-07 12:23:19 +01:00
continue ;
2019-03-19 18:31:27 +01:00
2019-05-03 11:54:45 +02:00
pair < int , vector < tuple < int , int , int , double > > > m ;
2019-03-19 18:31:27 +01:00
try
{
2019-05-03 11:54:45 +02:00
m = { - 1 , { it . first - > matchVariableTimesConstantTimesParam ( ) } } ;
2019-03-19 18:31:27 +01:00
}
catch ( MatchFailureException & e )
{
2019-05-03 11:54:45 +02:00
try
2019-12-20 16:59:30 +01:00
{
m = it . first - > matchParamTimesLinearCombinationOfVariables ( ) ;
}
2019-05-03 11:54:45 +02:00
catch ( MatchFailureException & e )
{
cerr < < " Unsupported expression in PAC equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2019-03-19 18:31:27 +01:00
}
2019-05-03 11:54:45 +02:00
for ( auto & t : m . second )
get < 3 > ( t ) * = it . second ; // Update sign of constants
2019-09-11 15:59:23 +02:00
int pid = get < 0 > ( m ) ;
2020-09-11 16:45:19 +02:00
for ( auto [ vid , vlag , pidtmp , constant ] : m . second )
2019-03-05 10:57:15 +01:00
{
2019-05-03 11:54:45 +02:00
if ( pid = = - 1 )
pid = pidtmp ;
2019-12-16 19:42:59 +01:00
else if ( pidtmp > = 0 )
{
cerr < < " unexpected parameter found in PAC equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( int vidorig = datatree . symbol_table . getUltimateOrigSymbID ( vid ) ;
vidorig = = lhs_symb_id | | vidorig = = lhs_orig_symb_id )
2019-03-05 10:57:15 +01:00
{
2019-05-03 11:54:45 +02:00
// This is an autoregressive term
2020-09-11 16:45:19 +02:00
if ( constant ! = 1 | | pid = = - 1 | | ! datatree . symbol_table . isDiffAuxiliaryVariable ( vid ) )
2019-05-03 11:54:45 +02:00
{
2020-09-11 16:45:19 +02:00
cerr < < " BinaryOpNode::getPacAREC: autoregressive terms must be of the form 'parameter*diff_lagged_variable " < < endl ;
2019-05-03 11:54:45 +02:00
exit ( EXIT_FAILURE ) ;
}
2020-09-11 16:45:19 +02:00
int ar_lag = datatree . symbol_table . getOrigLeadLagForDiffAuxVar ( vid ) ;
if ( static_cast < int > ( ar_params_and_vars . size ( ) ) < ar_lag )
ar_params_and_vars . resize ( ar_lag , { - 1 , - 1 , 0 } ) ;
ar_params_and_vars [ ar_lag - 1 ] = { pid , vid , vlag } ;
2019-03-05 10:57:15 +01:00
}
2019-05-03 11:54:45 +02:00
else
// This is a residual additive term
2020-09-11 16:45:19 +02:00
additive_vars_params_and_constants . emplace_back ( vid , vlag , pid , constant ) ;
2019-03-05 10:57:15 +01:00
}
}
2018-08-09 16:14:40 +02:00
}
bool
BinaryOpNode : : isParamTimesEndogExpr ( ) const
{
if ( op_code = = BinaryOpcode : : times )
{
set < int > params ;
2019-12-16 19:42:59 +01:00
auto test_arg1 = dynamic_cast < VariableNode * > ( arg1 ) ;
auto test_arg2 = dynamic_cast < VariableNode * > ( arg2 ) ;
2018-08-09 16:14:40 +02:00
if ( test_arg1 )
arg1 - > collectVariables ( SymbolType : : parameter , params ) ;
else if ( test_arg2 )
arg2 - > collectVariables ( SymbolType : : parameter , params ) ;
else
return false ;
if ( params . size ( ) ! = 1 )
return false ;
params . clear ( ) ;
set < pair < int , int > > endogs , exogs ;
if ( test_arg1 )
{
arg2 - > collectDynamicVariables ( SymbolType : : endogenous , endogs ) ;
arg2 - > collectDynamicVariables ( SymbolType : : exogenous , exogs ) ;
arg2 - > collectVariables ( SymbolType : : parameter , params ) ;
if ( params . size ( ) = = 0 & & exogs . size ( ) = = 0 & & endogs . size ( ) > = 1 )
return true ;
}
else
{
arg1 - > collectDynamicVariables ( SymbolType : : endogenous , endogs ) ;
arg1 - > collectDynamicVariables ( SymbolType : : exogenous , exogs ) ;
arg1 - > collectVariables ( SymbolType : : parameter , params ) ;
if ( params . size ( ) = = 0 & & exogs . size ( ) = = 0 & & endogs . size ( ) > = 1 )
return true ;
}
2018-02-12 17:37:53 +01:00
}
2018-08-09 16:14:40 +02:00
else if ( op_code = = BinaryOpcode : : plus )
return arg1 - > isParamTimesEndogExpr ( ) | | arg2 - > isParamTimesEndogExpr ( ) ;
return false ;
}
2019-02-27 23:12:05 +01:00
expr_t
2020-10-19 18:26:36 +02:00
BinaryOpNode : : getPacNonOptimizingPart ( int optim_share_symb_id ) const
2019-02-27 23:12:05 +01:00
{
2020-10-19 18:26:36 +02:00
vector < pair < expr_t , int > > factors ;
decomposeMultiplicativeFactors ( factors ) ;
// Search for a factor of the form 1-optim_share
expr_t one_minus_optim_share = nullptr ;
for ( auto [ factor , exponent ] : factors )
{
auto bopn = dynamic_cast < BinaryOpNode * > ( factor ) ;
if ( exponent ! = 1 | | ! bopn | | bopn - > op_code ! = BinaryOpcode : : minus )
continue ;
auto arg1 = dynamic_cast < NumConstNode * > ( bopn - > arg1 ) ;
auto arg2 = dynamic_cast < VariableNode * > ( bopn - > arg2 ) ;
if ( arg1 & & arg2 & & arg1 - > eval ( { } ) = = 1 & & arg2 - > symb_id = = optim_share_symb_id )
{
one_minus_optim_share = factor ;
break ;
}
}
2018-08-09 16:14:40 +02:00
2020-10-19 18:26:36 +02:00
if ( ! one_minus_optim_share )
return nullptr ;
2018-08-13 17:22:28 +02:00
2020-10-19 18:26:36 +02:00
// Construct the product formed by the other factors and return it
expr_t non_optim_part = datatree . One ;
for ( auto [ factor , exponent ] : factors )
if ( factor ! = one_minus_optim_share )
if ( exponent = = 1 )
non_optim_part = datatree . AddTimes ( non_optim_part , factor ) ;
else
non_optim_part = datatree . AddDivide ( non_optim_part , factor ) ;
2019-02-27 23:12:05 +01:00
2020-10-19 18:26:36 +02:00
return non_optim_part ;
2019-02-27 23:12:05 +01:00
}
pair < int , expr_t >
2020-07-23 14:45:32 +02:00
BinaryOpNode : : getPacOptimizingShareAndExprNodesHelper ( int lhs_symb_id , int lhs_orig_symb_id ) const
2019-02-27 23:12:05 +01:00
{
int optim_param_symb_id = - 1 ;
expr_t optim_part = nullptr ;
2020-07-23 14:45:32 +02:00
set < int > endogs ;
collectVariables ( SymbolType : : endogenous , endogs ) ;
// Test whether it contains the LHS in level
if ( endogs . count ( lhs_orig_symb_id ) > 0 )
2019-02-27 23:12:05 +01:00
{
set < int > params ;
2020-07-23 14:45:32 +02:00
if ( arg1 - > isParamTimesEndogExpr ( ) & & ! arg2 - > isParamTimesEndogExpr ( ) )
2018-08-13 17:22:28 +02:00
{
2020-07-23 14:45:32 +02:00
optim_part = arg1 ;
arg2 - > collectVariables ( SymbolType : : parameter , params ) ;
2019-02-27 23:12:05 +01:00
optim_param_symb_id = * ( params . begin ( ) ) ;
}
2020-07-23 14:45:32 +02:00
else if ( arg2 - > isParamTimesEndogExpr ( ) & & ! arg1 - > isParamTimesEndogExpr ( ) )
2019-02-27 23:12:05 +01:00
{
2020-07-23 14:45:32 +02:00
optim_part = arg2 ;
arg1 - > collectVariables ( SymbolType : : parameter , params ) ;
2019-02-27 23:12:05 +01:00
optim_param_symb_id = * ( params . begin ( ) ) ;
2018-08-13 17:22:28 +02:00
}
2019-02-27 23:12:05 +01:00
}
return { optim_param_symb_id , optim_part } ;
}
tuple < int , expr_t , expr_t , expr_t >
BinaryOpNode : : getPacOptimizingShareAndExprNodes ( int lhs_symb_id , int lhs_orig_symb_id ) const
{
vector < pair < expr_t , int > > terms ;
decomposeAdditiveTerms ( terms , 1 ) ;
2019-12-20 16:59:30 +01:00
for ( auto & it : terms )
2019-12-16 19:42:59 +01:00
if ( dynamic_cast < PacExpectationNode * > ( it . first ) )
2019-02-27 23:12:05 +01:00
// if the pac_expectation operator is additive in the expression
// there are no optimizing shares
return { - 1 , nullptr , nullptr , nullptr } ;
2018-08-13 17:22:28 +02:00
2019-02-27 23:12:05 +01:00
int optim_share ;
expr_t optim_part , non_optim_part , additive_part ;
optim_part = non_optim_part = additive_part = nullptr ;
2019-12-16 19:42:59 +01:00
for ( auto it = terms . begin ( ) ; it ! = terms . end ( ) ; + + it )
if ( auto bopn = dynamic_cast < BinaryOpNode * > ( it - > first ) ; bopn )
2019-10-28 11:09:36 +01:00
{
2019-12-20 16:59:30 +01:00
tie ( optim_share , optim_part )
2020-07-23 14:45:32 +02:00
= bopn - > getPacOptimizingShareAndExprNodesHelper ( lhs_symb_id , lhs_orig_symb_id ) ;
2019-12-16 19:42:59 +01:00
if ( optim_share > = 0 & & optim_part )
2019-10-28 11:09:36 +01:00
{
terms . erase ( it ) ;
break ;
}
}
2019-02-27 23:12:05 +01:00
2019-12-16 19:42:59 +01:00
if ( ! optim_part )
2019-02-27 23:12:05 +01:00
return { - 1 , nullptr , nullptr , nullptr } ;
2019-12-16 19:42:59 +01:00
for ( auto it = terms . begin ( ) ; it ! = terms . end ( ) ; + + it )
if ( auto bopn = dynamic_cast < BinaryOpNode * > ( it - > first ) ; bopn )
2019-10-28 11:09:36 +01:00
{
2020-10-19 18:26:36 +02:00
non_optim_part = bopn - > getPacNonOptimizingPart ( optim_share ) ;
2019-12-16 19:42:59 +01:00
if ( non_optim_part )
2019-10-28 11:09:36 +01:00
{
terms . erase ( it ) ;
break ;
}
}
2019-02-27 23:12:05 +01:00
2019-12-16 19:42:59 +01:00
if ( ! non_optim_part )
2019-02-27 23:12:05 +01:00
return { - 1 , nullptr , nullptr , nullptr } ;
2019-12-16 19:42:59 +01:00
else
2018-08-09 16:14:40 +02:00
{
2019-02-27 23:12:05 +01:00
additive_part = datatree . Zero ;
for ( auto it : terms )
additive_part = datatree . AddPlus ( additive_part , it . first ) ;
if ( additive_part = = datatree . Zero )
additive_part = nullptr ;
2018-02-15 16:10:01 +01:00
}
2019-02-27 23:12:05 +01:00
return { optim_share , optim_part , non_optim_part , additive_part } ;
2018-08-09 16:14:40 +02:00
}
2018-02-12 17:37:53 +01:00
2018-09-06 17:53:07 +02:00
void
2018-09-07 10:14:18 +02:00
BinaryOpNode : : fillAutoregressiveRow ( int eqn , const vector < int > & lhs , map < tuple < int , int , int > , expr_t > & AR ) const
2019-03-14 17:20:45 +01:00
{
vector < pair < expr_t , int > > terms ;
decomposeAdditiveTerms ( terms , 1 ) ;
2019-12-20 16:59:30 +01:00
for ( const auto & it : terms )
2019-03-14 17:20:45 +01:00
{
2019-03-19 17:03:26 +01:00
int vid , lag , param_id ;
double constant ;
try
2019-03-14 17:20:45 +01:00
{
2019-03-19 17:03:26 +01:00
tie ( vid , lag , param_id , constant ) = it . first - > matchVariableTimesConstantTimesParam ( ) ;
constant * = it . second ;
}
catch ( MatchFailureException & e )
{
continue ;
}
2019-03-14 17:20:45 +01:00
2019-03-19 17:03:26 +01:00
if ( datatree . symbol_table . isDiffAuxiliaryVariable ( vid ) )
{
lag = - datatree . symbol_table . getOrigLeadLagForDiffAuxVar ( vid ) ;
vid = datatree . symbol_table . getOrigSymbIdForDiffAuxVar ( vid ) ;
}
2019-03-14 17:20:45 +01:00
2019-03-19 17:03:26 +01:00
if ( find ( lhs . begin ( ) , lhs . end ( ) , vid ) = = lhs . end ( ) )
continue ;
if ( AR . find ( { eqn , - lag , vid } ) ! = AR . end ( ) )
{
cerr < < " BinaryOpNode::fillAutoregressiveRow: Error filling AR matrix: "
< < " lag/symb_id encountered more than once in equation " < < endl ;
exit ( EXIT_FAILURE ) ;
}
if ( constant ! = 1 | | param_id = = - 1 )
{
cerr < < " BinaryOpNode::fillAutoregressiveRow: autoregressive terms must be of the form 'parameter*lagged_variable " < < endl ;
exit ( EXIT_FAILURE ) ;
2019-03-14 17:20:45 +01:00
}
2019-03-19 17:03:26 +01:00
AR [ { eqn , - lag , vid } ] = datatree . AddVariable ( param_id ) ;
2019-03-14 17:20:45 +01:00
}
}
2019-01-28 14:57:30 +01:00
void
2019-01-29 17:29:24 +01:00
BinaryOpNode : : findConstantEquations ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
if ( op_code = = BinaryOpcode : : equal )
2019-12-18 12:46:24 +01:00
{
if ( dynamic_cast < VariableNode * > ( arg1 ) & & dynamic_cast < NumConstNode * > ( arg2 ) )
table [ dynamic_cast < VariableNode * > ( arg1 ) ] = dynamic_cast < NumConstNode * > ( arg2 ) ;
else if ( dynamic_cast < VariableNode * > ( arg2 ) & & dynamic_cast < NumConstNode * > ( arg1 ) )
table [ dynamic_cast < VariableNode * > ( arg2 ) ] = dynamic_cast < NumConstNode * > ( arg1 ) ;
}
2019-01-28 14:57:30 +01:00
}
expr_t
2019-01-29 17:29:24 +01:00
BinaryOpNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
if ( op_code = = BinaryOpcode : : equal )
2019-12-20 16:59:30 +01:00
for ( auto & it : table )
2019-01-29 17:52:19 +01:00
if ( ( it . first = = arg1 & & it . second = = arg2 ) | | ( it . first = = arg2 & & it . second = = arg1 ) )
2019-01-28 14:57:30 +01:00
return const_cast < BinaryOpNode * > ( this ) ;
expr_t arg1subst = arg1 - > replaceVarsInEquation ( table ) ;
expr_t arg2subst = arg2 - > replaceVarsInEquation ( table ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
2016-11-25 17:15:13 +01:00
bool
BinaryOpNode : : isVarModelReferenced ( const string & model_info_name ) const
{
return arg1 - > isVarModelReferenced ( model_info_name )
| | arg2 - > isVarModelReferenced ( model_info_name ) ;
}
void
BinaryOpNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
arg1 - > getEndosAndMaxLags ( model_endos_and_lags ) ;
arg2 - > getEndosAndMaxLags ( model_endos_and_lags ) ;
}
2016-03-18 14:55:14 +01:00
expr_t
BinaryOpNode : : substituteStaticAuxiliaryVariable ( ) const
{
expr_t arg1subst = arg1 - > substituteStaticAuxiliaryVariable ( ) ;
expr_t arg2subst = arg2 - > substituteStaticAuxiliaryVariable ( ) ;
return buildSimilarBinaryOpNode ( arg1subst , arg2subst , datatree ) ;
}
expr_t
BinaryOpNode : : substituteStaticAuxiliaryDefinition ( ) const
{
expr_t arg2subst = arg2 - > substituteStaticAuxiliaryVariable ( ) ;
return buildSimilarBinaryOpNode ( arg1 , arg2subst , datatree ) ;
}
2020-07-28 18:29:45 +02:00
void
BinaryOpNode : : matchMatchedMoment ( vector < int > & symb_ids , vector < int > & lags , vector < int > & powers ) const
{
if ( op_code = = BinaryOpcode : : times )
{
arg1 - > matchMatchedMoment ( symb_ids , lags , powers ) ;
arg2 - > matchMatchedMoment ( symb_ids , lags , powers ) ;
}
else if ( op_code = = BinaryOpcode : : power )
{
if ( ! dynamic_cast < const VariableNode * > ( arg1 ) )
throw MatchFailureException ( " First argument of power expression must be a variable " ) ;
auto ncn = dynamic_cast < const NumConstNode * > ( arg2 ) ;
if ( ! ncn )
throw MatchFailureException ( " Second argument of power expression must be a positive integer " ) ;
double c = datatree . num_constants . getDouble ( ncn - > id ) ;
if ( c < = 0 | | round ( c ) ! = c )
throw MatchFailureException ( " Second argument of power expression must be a positive integer " ) ;
arg1 - > matchMatchedMoment ( symb_ids , lags , powers ) ;
powers . back ( ) = static_cast < int > ( c ) ;
}
else
throw MatchFailureException ( " Unsupported binary operator " ) ;
}
2018-09-05 16:41:33 +02:00
TrinaryOpNode : : TrinaryOpNode ( DataTree & datatree_arg , int idx_arg , const expr_t arg1_arg ,
2010-09-16 19:18:45 +02:00
TrinaryOpcode op_code_arg , const expr_t arg2_arg , const expr_t arg3_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
arg1 { arg1_arg } ,
arg2 { arg2_arg } ,
arg3 { arg3_arg } ,
op_code { op_code_arg }
2008-02-03 11:28:36 +01:00
{
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 ( ) ) ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
TrinaryOpNode : : composeDerivatives ( expr_t darg1 , expr_t darg2 , expr_t darg3 )
2008-02-03 11:28:36 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t t11 , t12 , t13 , t14 , t15 ;
2008-02-03 11:28:36 +01:00
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
2008-02-03 11:28:36 +01:00
// normal pdf is inlined in the tree
2010-09-16 19:18:45 +02:00
expr_t y ;
2008-02-03 11:28:36 +01:00
// 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 ) ;
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normpdf :
2010-03-11 09:43:16 +01:00
// (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
}
2010-09-16 19:18:45 +02:00
expr_t
2009-07-06 11:34:21 +02:00
TrinaryOpNode : : computeDerivative ( int deriv_id )
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getDerivative ( deriv_id ) ;
expr_t darg2 = arg2 - > getDerivative ( deriv_id ) ;
expr_t darg3 = arg3 - > getDerivative ( deriv_id ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
}
2008-02-03 11:28:36 +01:00
int
2010-09-16 19:00:48 +02:00
TrinaryOpNode : : precedence ( ExprNodeOutputType output_type , const temporary_terms_t & temporary_terms ) const
2009-12-16 18:13:23 +01:00
{
// A temporary term behaves as a variable
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2009-12-16 18:13:23 +01:00
return 100 ;
2009-06-05 16:45:23 +02:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
case TrinaryOpcode : : normpdf :
2009-12-16 18:13:23 +01:00
return 100 ;
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2008-02-03 11:28:36 +01:00
2015-09-03 13:50:02 +02:00
int
2018-11-30 12:22:13 +01:00
TrinaryOpNode : : cost ( const map < pair < int , int > , temporary_terms_t > & temp_terms_map , bool is_matlab ) const
2015-09-03 13:50:02 +02:00
{
// For a temporary term, the cost is null
2019-12-20 16:59:30 +01:00
for ( const auto & it : temp_terms_map )
2018-06-04 12:26:16 +02:00
if ( it . second . find ( const_cast < TrinaryOpNode * > ( this ) ) ! = it . second . end ( ) )
2015-09-03 13:50:02 +02:00
return 0 ;
int arg_cost = arg1 - > cost ( temp_terms_map , is_matlab )
+ arg2 - > cost ( temp_terms_map , is_matlab )
+ arg3 - > cost ( temp_terms_map , is_matlab ) ;
return cost ( arg_cost , is_matlab ) ;
}
2008-02-03 11:28:36 +01:00
int
2020-05-13 16:58:19 +02:00
TrinaryOpNode : : cost ( const vector < vector < temporary_terms_t > > & blocks_temporary_terms , bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
// For a temporary term, the cost is null
2020-05-13 16:58:19 +02:00
for ( const auto & blk_tt : blocks_temporary_terms )
for ( const auto & eq_tt : blk_tt )
if ( eq_tt . find ( const_cast < TrinaryOpNode * > ( this ) ) ! = eq_tt . end ( ) )
return 0 ;
2008-02-03 11:28:36 +01:00
2020-05-06 17:13:47 +02:00
int arg_cost = arg1 - > cost ( blocks_temporary_terms , is_matlab )
+ arg2 - > cost ( blocks_temporary_terms , is_matlab )
+ arg3 - > cost ( blocks_temporary_terms , is_matlab ) ;
2015-09-03 13:50:02 +02:00
return cost ( arg_cost , is_matlab ) ;
}
2008-02-03 11:28:36 +01:00
2015-09-03 13:50:02 +02:00
int
TrinaryOpNode : : cost ( int cost , bool is_matlab ) const
{
2009-12-16 18:13:23 +01:00
if ( is_matlab )
// Cost for Matlab files
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
case TrinaryOpcode : : normpdf :
2009-12-16 18:13:23 +01:00
return cost + 1000 ;
}
else
// Cost for C files
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
case TrinaryOpcode : : normpdf :
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
2018-11-30 12:22:13 +01:00
TrinaryOpNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < TrinaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
// If this node has never been encountered, set its ref count to one,
// and travel through its children
2018-11-30 12:22:13 +01:00
reference_count [ this2 ] = { 1 , derivOrder } ;
arg1 - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
arg2 - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
arg3 - > computeTemporaryTerms ( derivOrder , temp_terms_map , reference_count , is_matlab ) ;
2009-12-16 18:13:23 +01:00
}
else
{
// If the node has already been encountered, increment its ref count
// and declare it as a temporary term if it is too costly
2020-05-12 18:29:11 +02:00
auto & [ nref , min_order ] = it - > second ;
nref + + ;
if ( nref * cost ( temp_terms_map , is_matlab ) > min_cost ( is_matlab ) )
temp_terms_map [ min_order ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
void
2020-05-13 16:58:19 +02:00
TrinaryOpNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2009-12-16 18:13:23 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t this2 = const_cast < TrinaryOpNode * > ( this ) ;
2019-12-16 19:42:59 +01:00
if ( auto it = reference_count . find ( this2 ) ;
it = = reference_count . end ( ) )
2009-12-16 18:13:23 +01:00
{
2020-05-13 16:58:19 +02:00
reference_count [ this2 ] = { 1 , blk , eq } ;
arg1 - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
arg2 - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
arg3 - > computeBlockTemporaryTerms ( blk , eq , blocks_temporary_terms , reference_count ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 16:58:19 +02:00
auto & [ nref , first_blk , first_eq ] = it - > second ;
2020-05-06 17:13:47 +02:00
nref + + ;
if ( nref * cost ( blocks_temporary_terms , false ) > min_cost_c )
2020-05-13 16:58:19 +02:00
blocks_temporary_terms [ first_blk ] [ first_eq ] . insert ( this2 ) ;
2009-12-16 18:13:23 +01:00
}
}
2008-02-03 11:28:36 +01:00
double
2018-06-04 12:50:53 +02:00
TrinaryOpNode : : eval_opcode ( double v1 , TrinaryOpcode op_code , double v2 , double v3 ) noexcept ( false )
2008-02-03 11:28:36 +01:00
{
2009-06-05 16:45:23 +02:00
switch ( op_code )
2008-02-03 11:28:36 +01:00
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
2010-02-23 14:39:49 +01:00
return ( 0.5 * ( 1 + erf ( ( v1 - v2 ) / v3 / M_SQRT2 ) ) ) ;
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normpdf :
2011-02-04 16:25:38 +01:00
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
2018-06-04 12:50:53 +02:00
TrinaryOpNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2008-02-03 11:28:36 +01:00
{
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-12-10 11:50:27 +01:00
TrinaryOpNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
// If current node is a temporary term
2020-05-13 12:53:47 +02:00
if ( auto this2 = const_cast < TrinaryOpNode * > ( this ) ;
temporary_terms . find ( this2 ) ! = temporary_terms . end ( ) )
2009-12-16 18:13:23 +01:00
{
if ( dynamic )
{
2020-05-13 12:53:47 +02:00
FLDT_ fldt ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldt . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
else
{
2020-05-13 12:53:47 +02:00
FLDST_ fldst ( temporary_terms_idxs . at ( this2 ) ) ;
2010-07-23 11:20:24 +02:00
fldst . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
return ;
}
2020-05-13 12:53:47 +02:00
arg1 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg3 - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms , temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2018-07-18 16:18:26 +02:00
FTRINARY_ ftrinary { static_cast < int > ( op_code ) } ;
2010-07-23 11:20:24 +02:00
ftrinary . write ( CompileCode , instruction_number ) ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2015-05-12 16:36:03 +02:00
bool
TrinaryOpNode : : containsExternalFunction ( ) const
{
return arg1 - > containsExternalFunction ( )
| | arg2 - > containsExternalFunction ( )
| | arg3 - > containsExternalFunction ( ) ;
}
2018-09-18 14:50:31 +02:00
void
TrinaryOpNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " TrinaryOpNode " , ) "
< < R " ( " op " : " ) " ;
2018-09-18 14:50:31 +02:00
switch ( op_code )
{
case TrinaryOpcode : : normcdf :
output < < " normcdf " ;
break ;
case TrinaryOpcode : : normpdf :
output < < " normpdf " ;
break ;
}
2019-04-03 16:32:52 +02:00
output < < R " ( " , " arg1 " : ) " ;
2018-09-18 14:50:31 +02:00
arg1 - > writeJsonAST ( output ) ;
2019-04-03 16:32:52 +02:00
output < < R " (, " arg2 " : ) " ;
2018-09-18 14:50:31 +02:00
arg2 - > writeJsonAST ( output ) ;
2019-04-03 16:32:52 +02:00
output < < R " (, " arg2 " : ) " ;
2018-09-18 14:50:31 +02:00
arg3 - > writeJsonAST ( output ) ;
output < < " } " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
TrinaryOpNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
// If current node is a temporary term
2019-10-28 11:09:36 +01:00
if ( temporary_terms . find ( const_cast < TrinaryOpNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
2017-02-02 15:09:43 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
2017-02-02 15:09:43 +01:00
output < < " normcdf( " ;
break ;
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normpdf :
2017-02-02 15:09:43 +01:00
output < < " normpdf( " ;
break ;
}
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " , " ;
2017-10-16 17:24:55 +02:00
arg2 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " , " ;
2017-10-16 17:24:55 +02:00
arg3 - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
output < < " ) " ;
}
2008-02-03 11:28:36 +01:00
void
TrinaryOpNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2008-02-03 11:28:36 +01:00
2009-12-16 18:13:23 +01:00
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-02-23 14:39:49 +01:00
{
// In C, there is no normcdf() primitive, so use erf()
output < < " (0.5*(1+erf((( " ;
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " )-( " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " ))/( " ;
2018-03-27 17:14:30 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " )/M_SQRT2))) " ;
}
else
{
output < < " normcdf( " ;
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-23 14:39:49 +01:00
output < < " ) " ;
}
2010-03-15 12:22:52 +01:00
break ;
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normpdf :
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-03-11 09:43:16 +01:00
{
//(1/(v3*sqrt(2*M_PI)*exp(pow((v1-v2)/v3,2)/2)))
output < < " (1/( " ;
2018-03-27 17:14:30 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " *sqrt(2*M_PI)*exp(pow(( " ;
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " - " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " )/ " ;
2018-03-27 17:14:30 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " ,2)/2))) " ;
}
else
{
output < < " normpdf( " ;
2018-03-27 17:14:30 +02:00
arg1 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg2 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " , " ;
2018-03-27 17:14:30 +02:00
arg3 - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-11 09:43:16 +01:00
output < < " ) " ;
}
2009-12-16 18:13:23 +01:00
break ;
}
}
2008-02-03 11:28:36 +01:00
2010-03-04 16:40:07 +01:00
void
TrinaryOpNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2018-03-27 17:14:30 +02:00
arg1 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
arg2 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
arg3 - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-03-04 16:40:07 +01:00
}
2017-02-20 12:18:11 +01:00
void
TrinaryOpNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
2017-10-16 17:24:55 +02:00
arg1 - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
arg2 - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
arg3 - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
}
2010-12-10 11:50:27 +01:00
void
TrinaryOpNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2011-02-04 16:25:38 +01:00
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
2020-05-13 12:53:47 +02:00
arg1 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg2 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
arg3 - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2010-12-10 11:50:27 +01:00
}
2018-04-16 13:50:31 +02:00
void
TrinaryOpNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2008-02-03 11:28:36 +01:00
void
2018-06-04 14:17:36 +02:00
TrinaryOpNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2013-09-13 20:37:31 +02:00
{
2013-11-29 15:32:49 +01:00
arg1 - > collectDynamicVariables ( type_arg , result ) ;
arg2 - > collectDynamicVariables ( type_arg , result ) ;
arg3 - > collectDynamicVariables ( type_arg , result ) ;
2013-09-13 20:37:31 +02:00
}
2020-04-02 14:36:26 +02:00
void
TrinaryOpNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
{
arg1 - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
arg2 - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
arg3 - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
if ( contain_var . count ( arg1 ) > 0 | | contain_var . count ( arg2 ) > 0 | | contain_var . count ( arg3 ) > 0 )
contain_var . insert ( const_cast < TrinaryOpNode * > ( this ) ) ;
}
BinaryOpNode *
TrinaryOpNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
throw NormalizationFailed ( ) ;
2009-12-16 18:13:23 +01:00
}
2008-11-14 17:07:47 +01:00
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
TrinaryOpNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2009-04-14 16:39:53 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t darg1 = arg1 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg2 = arg2 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
expr_t darg3 = arg3 - > getChainRuleDerivative ( deriv_id , recursive_variables ) ;
2009-07-06 11:34:21 +02:00
return composeDerivatives ( darg1 , darg2 , darg3 ) ;
2009-04-14 16:39:53 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
TrinaryOpNode : : buildSimilarTrinaryOpNode ( expr_t alt_arg1 , expr_t alt_arg2 , expr_t alt_arg3 , DataTree & alt_datatree ) const
2009-09-30 17:10:31 +02:00
{
switch ( op_code )
{
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normcdf :
2009-09-30 17:10:31 +02:00
return alt_datatree . AddNormcdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2018-07-18 16:18:26 +02:00
case TrinaryOpcode : : normpdf :
2010-03-11 09:43:16 +01:00
return alt_datatree . AddNormpdf ( alt_arg1 , alt_arg2 , alt_arg3 ) ;
2009-09-30 17:10:31 +02:00
}
// Suppress GCC warning
exit ( EXIT_FAILURE ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-06-05 16:45:23 +02:00
TrinaryOpNode : : toStatic ( DataTree & static_datatree ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t sarg1 = arg1 - > toStatic ( static_datatree ) ;
expr_t sarg2 = arg2 - > toStatic ( static_datatree ) ;
expr_t sarg3 = arg3 - > toStatic ( static_datatree ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( sarg1 , sarg2 , sarg3 , static_datatree ) ;
}
2009-06-05 16:45:23 +02:00
2015-12-18 15:17:32 +01:00
void
TrinaryOpNode : : computeXrefs ( EquationInfo & ei ) const
{
arg1 - > computeXrefs ( ei ) ;
arg2 - > computeXrefs ( ei ) ;
arg3 - > computeXrefs ( ei ) ;
}
2010-10-15 19:05:16 +02:00
expr_t
2018-10-10 13:07:25 +02:00
TrinaryOpNode : : clone ( DataTree & datatree ) const
2010-10-15 19:05:16 +02:00
{
2018-10-10 13:07:25 +02:00
expr_t substarg1 = arg1 - > clone ( datatree ) ;
expr_t substarg2 = arg2 - > clone ( datatree ) ;
expr_t substarg3 = arg3 - > clone ( datatree ) ;
return buildSimilarTrinaryOpNode ( substarg1 , substarg2 , substarg3 , datatree ) ;
2010-10-15 19:05:16 +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 ( ) ) ) ;
}
2010-08-19 15:20:54 +02:00
int
TrinaryOpNode : : maxEndoLag ( ) const
{
return max ( arg1 - > maxEndoLag ( ) , max ( arg2 - > maxEndoLag ( ) , arg3 - > maxEndoLag ( ) ) ) ;
}
int
TrinaryOpNode : : maxExoLag ( ) const
{
return max ( arg1 - > maxExoLag ( ) , max ( arg2 - > maxExoLag ( ) , arg3 - > maxExoLag ( ) ) ) ;
}
2012-05-26 20:53:48 +02:00
int
TrinaryOpNode : : maxLead ( ) const
{
return max ( arg1 - > maxLead ( ) , max ( arg2 - > maxLead ( ) , arg3 - > maxLead ( ) ) ) ;
}
2018-02-28 17:33:00 +01:00
int
TrinaryOpNode : : maxLag ( ) const
{
return max ( arg1 - > maxLag ( ) , max ( arg2 - > maxLag ( ) , arg3 - > maxLag ( ) ) ) ;
}
2018-12-05 15:17:00 +01:00
int
TrinaryOpNode : : maxLagWithDiffsExpanded ( ) const
{
return max ( arg1 - > maxLagWithDiffsExpanded ( ) ,
max ( arg2 - > maxLagWithDiffsExpanded ( ) , arg3 - > maxLagWithDiffsExpanded ( ) ) ) ;
}
2018-04-17 15:17:28 +02:00
expr_t
TrinaryOpNode : : undiff ( ) const
{
expr_t arg1subst = arg1 - > undiff ( ) ;
expr_t arg2subst = arg2 - > undiff ( ) ;
expr_t arg3subst = arg3 - > undiff ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2018-05-16 12:17:06 +02:00
int
TrinaryOpNode : : VarMinLag ( ) const
{
return min ( min ( arg1 - > VarMinLag ( ) , arg2 - > VarMinLag ( ) ) , arg3 - > VarMinLag ( ) ) ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
TrinaryOpNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2019-10-22 16:04:24 +02:00
return max ( arg1 - > VarMaxLag ( lhs_lag_equiv ) ,
max ( arg2 - > VarMaxLag ( lhs_lag_equiv ) ,
arg3 - > VarMaxLag ( lhs_lag_equiv ) ) ) ;
2018-04-16 13:50:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2009-09-30 17:10:31 +02:00
TrinaryOpNode : : decreaseLeadsLags ( int n ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLags ( n ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLags ( n ) ;
expr_t arg3subst = arg3 - > decreaseLeadsLags ( n ) ;
2009-09-30 17:10:31 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-11-09 12:03:18 +01:00
TrinaryOpNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg2subst = arg2 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
expr_t arg3subst = arg3 - > decreaseLeadsLagsPredeterminedVariables ( ) ;
2009-11-07 19:37:11 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
TrinaryOpNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-09-30 17:10:31 +02:00
{
if ( maxEndoLead ( ) < 2 )
return const_cast < TrinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
else if ( deterministic_model )
{
expr_t arg1subst = arg1 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
expr_t arg2subst = arg2 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
expr_t arg3subst = arg3 - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-09-30 17:10:31 +02:00
else
2009-10-07 16:07:13 +02:00
return createEndoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 16:07:13 +02:00
TrinaryOpNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ;
2009-10-07 16:07:13 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2010-08-18 13:45:07 +02:00
TrinaryOpNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
if ( maxExoLead ( ) = = 0 )
return const_cast < TrinaryOpNode * > ( this ) ;
2010-08-18 13:45:07 +02:00
else if ( deterministic_model )
{
expr_t arg1subst = arg1 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
expr_t arg2subst = arg2 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
expr_t arg3subst = arg3 - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2009-10-07 18:34:42 +02:00
else
return createExoLeadAuxiliaryVarForMyself ( subst_table , neweqs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2009-10-07 18:34:42 +02:00
TrinaryOpNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteExoLag ( subst_table , neweqs ) ;
expr_t 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
2010-09-16 19:18:45 +02:00
expr_t
2009-10-29 18:16:10 +01:00
TrinaryOpNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
2010-09-16 19:18:45 +02:00
expr_t arg1subst = arg1 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg2subst = arg2 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
expr_t arg3subst = arg3 - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ;
2009-10-29 18:16:10 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
TrinaryOpNode : : substituteAdl ( ) const
{
expr_t arg1subst = arg1 - > substituteAdl ( ) ;
expr_t arg2subst = arg2 - > substituteAdl ( ) ;
expr_t arg3subst = arg3 - > substituteAdl ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
TrinaryOpNode : : substituteModelLocalVariables ( ) const
{
expr_t arg1subst = arg1 - > substituteModelLocalVariables ( ) ;
expr_t arg2subst = arg2 - > substituteModelLocalVariables ( ) ;
expr_t arg3subst = arg3 - > substituteModelLocalVariables ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
TrinaryOpNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
expr_t arg1subst = arg1 - > substituteVarExpectation ( subst_table ) ;
expr_t arg2subst = arg2 - > substituteVarExpectation ( subst_table ) ;
expr_t arg3subst = arg3 - > substituteVarExpectation ( subst_table ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
TrinaryOpNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
2019-10-22 14:56:28 +02:00
arg1 - > findDiffNodes ( nodes ) ;
arg2 - > findDiffNodes ( nodes ) ;
arg3 - > findDiffNodes ( nodes ) ;
2018-03-02 12:32:01 +01:00
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
TrinaryOpNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
2019-10-22 14:56:28 +02:00
arg1 - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
arg2 - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
arg3 - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
TrinaryOpNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
2018-09-13 12:21:23 +02:00
int retval = arg1 - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
if ( retval < 0 )
2018-09-13 12:21:23 +02:00
retval = arg2 - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
if ( retval < 0 )
2018-09-13 12:21:23 +02:00
retval = arg3 - > findTargetVariable ( lhs_symb_id ) ;
2018-08-31 12:35:51 +02:00
return retval ;
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
TrinaryOpNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2017-06-12 14:56:44 +02:00
{
2019-10-22 14:56:28 +02:00
expr_t arg1subst = arg1 - > substituteDiff ( nodes , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteDiff ( nodes , subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > substituteDiff ( nodes , subst_table , neweqs ) ;
2017-06-12 14:56:44 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
TrinaryOpNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
2019-10-22 14:56:28 +02:00
expr_t arg1subst = arg1 - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ;
2018-05-30 16:48:08 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2018-05-31 15:34:25 +02:00
int
TrinaryOpNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-12-05 12:38:46 +01:00
return max ( arg1 - > countDiffs ( ) , max ( arg2 - > countDiffs ( ) , arg3 - > countDiffs ( ) ) ) ;
2018-02-08 13:07:15 +01:00
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
TrinaryOpNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2019-02-15 12:52:46 +01:00
{
2019-02-20 12:59:55 +01:00
expr_t arg1subst = arg1 - > substitutePacExpectation ( name , subexpr ) ;
expr_t arg2subst = arg2 - > substitutePacExpectation ( name , subexpr ) ;
expr_t arg3subst = arg3 - > substitutePacExpectation ( name , subexpr ) ;
2018-01-30 16:33:16 +01:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2013-04-25 18:09:31 +02:00
expr_t
2013-05-17 16:51:34 +02:00
TrinaryOpNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
2013-05-17 16:51:34 +02:00
expr_t arg1subst = arg1 - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
expr_t arg2subst = arg2 - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
expr_t arg3subst = arg3 - > differentiateForwardVars ( subset , subst_table , neweqs ) ;
2013-04-25 18:09:31 +02:00
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 ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
TrinaryOpNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
2018-08-13 12:12:20 +02:00
return ( arg1 - > containsPacExpectation ( pac_model_name ) | | arg2 - > containsPacExpectation ( pac_model_name ) | | arg3 - > containsPacExpectation ( pac_model_name ) ) ;
2018-06-05 18:38:53 +02:00
}
2010-10-15 19:05:16 +02:00
expr_t
TrinaryOpNode : : replaceTrendVar ( ) const
{
expr_t arg1subst = arg1 - > replaceTrendVar ( ) ;
expr_t arg2subst = arg2 - > replaceTrendVar ( ) ;
expr_t arg3subst = arg3 - > replaceTrendVar ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
expr_t
2013-03-26 16:46:18 +01:00
TrinaryOpNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
2013-03-26 16:46:18 +01:00
expr_t arg1subst = arg1 - > detrend ( symb_id , log_trend , trend ) ;
expr_t arg2subst = arg2 - > detrend ( symb_id , log_trend , trend ) ;
expr_t arg3subst = arg3 - > detrend ( symb_id , log_trend , trend ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
TrinaryOpNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
expr_t arg1subst = arg1 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg2subst = arg2 - > removeTrendLeadLag ( trend_symbols_map ) ;
expr_t arg3subst = arg3 - > removeTrendLeadLag ( trend_symbols_map ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2013-04-11 17:07:39 +02:00
bool
TrinaryOpNode : : isInStaticForm ( ) const
{
return arg1 - > isInStaticForm ( ) & & arg2 - > isInStaticForm ( ) & & arg3 - > isInStaticForm ( ) ;
}
2018-08-09 16:14:40 +02:00
bool
TrinaryOpNode : : isParamTimesEndogExpr ( ) const
{
return arg1 - > isParamTimesEndogExpr ( )
| | arg2 - > isParamTimesEndogExpr ( )
| | arg3 - > isParamTimesEndogExpr ( ) ;
}
2016-11-25 17:15:13 +01:00
bool
TrinaryOpNode : : isVarModelReferenced ( const string & model_info_name ) const
{
return arg1 - > isVarModelReferenced ( model_info_name )
| | arg2 - > isVarModelReferenced ( model_info_name )
| | arg3 - > isVarModelReferenced ( model_info_name ) ;
}
void
TrinaryOpNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
arg1 - > getEndosAndMaxLags ( model_endos_and_lags ) ;
arg2 - > getEndosAndMaxLags ( model_endos_and_lags ) ;
arg3 - > getEndosAndMaxLags ( model_endos_and_lags ) ;
}
2016-03-18 14:55:14 +01:00
expr_t
TrinaryOpNode : : substituteStaticAuxiliaryVariable ( ) const
{
expr_t arg1subst = arg1 - > substituteStaticAuxiliaryVariable ( ) ;
expr_t arg2subst = arg2 - > substituteStaticAuxiliaryVariable ( ) ;
expr_t arg3subst = arg3 - > substituteStaticAuxiliaryVariable ( ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
TrinaryOpNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
expr_t arg1subst = arg1 - > replaceVarsInEquation ( table ) ;
expr_t arg2subst = arg2 - > replaceVarsInEquation ( table ) ;
expr_t arg3subst = arg3 - > replaceVarsInEquation ( table ) ;
return buildSimilarTrinaryOpNode ( arg1subst , arg2subst , arg3subst , datatree ) ;
}
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : AbstractExternalFunctionNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2014-03-13 11:22:00 +01:00
int symb_id_arg ,
2018-06-04 12:31:07 +02:00
vector < expr_t > arguments_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
symb_id { symb_id_arg } ,
arguments { move ( arguments_arg ) }
2014-03-13 11:22:00 +01:00
{
}
2009-09-30 17:10:31 +02:00
void
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : prepareForDerivation ( )
2009-09-30 17:10:31 +02:00
{
2010-02-22 17:33:38 +01:00
if ( preparedForDerivation )
return ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > prepareForDerivation ( ) ;
2010-02-22 17:33:38 +01:00
non_null_derivatives = arguments . at ( 0 ) - > non_null_derivatives ;
2019-04-23 11:07:32 +02:00
for ( int i = 1 ; i < static_cast < int > ( arguments . size ( ) ) ; i + + )
2010-02-22 17:33:38 +01:00
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
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : 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-09-16 19:18:45 +02:00
vector < expr_t > dargs ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
dargs . push_back ( argument - > getDerivative ( deriv_id ) ) ;
2010-02-22 17:33:38 +01:00
return composeDerivatives ( dargs ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2020-10-02 18:31:55 +02:00
AbstractExternalFunctionNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2008-02-03 11:28:36 +01:00
{
2010-12-10 11:50:27 +01:00
assert ( datatree . external_functions_table . getNargs ( symb_id ) > 0 ) ;
vector < expr_t > dargs ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
dargs . push_back ( argument - > getChainRuleDerivative ( deriv_id , recursive_variables ) ) ;
2010-12-10 11:50:27 +01:00
return composeDerivatives ( dargs ) ;
2008-02-03 11:28:36 +01:00
}
2015-05-11 16:39:06 +02:00
unsigned int
AbstractExternalFunctionNode : : compileExternalFunctionArguments ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2009-12-16 18:13:23 +01:00
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2020-05-13 12:53:47 +02:00
argument - > compile ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2015-05-11 16:39:06 +02:00
return ( arguments . size ( ) ) ;
2010-03-04 16:40:07 +01:00
}
2018-04-16 13:50:31 +02:00
void
AbstractExternalFunctionNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2010-10-05 18:48:15 +02:00
void
2018-06-04 14:17:36 +02:00
AbstractExternalFunctionNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2010-10-05 18:48:15 +02:00
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > collectDynamicVariables ( type_arg , result ) ;
2010-10-05 18:48:15 +02:00
}
2015-05-11 16:39:06 +02:00
double
2018-06-04 12:50:53 +02:00
AbstractExternalFunctionNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2015-05-11 16:39:06 +02:00
{
throw EvalExternalFunctionException ( ) ;
2010-03-04 16:40:07 +01:00
}
2015-05-11 16:39:06 +02:00
int
AbstractExternalFunctionNode : : maxEndoLead ( ) const
2010-12-10 11:50:27 +01:00
{
2015-05-11 16:39:06 +02:00
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxEndoLead ( ) ) ;
2015-05-11 16:39:06 +02:00
return val ;
2010-12-10 11:50:27 +01:00
}
2015-05-11 16:39:06 +02:00
int
AbstractExternalFunctionNode : : maxExoLead ( ) const
2010-12-10 11:50:27 +01:00
{
2015-05-11 16:39:06 +02:00
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxExoLead ( ) ) ;
2015-05-11 16:39:06 +02:00
return val ;
2010-12-10 11:50:27 +01:00
}
2015-05-11 16:39:06 +02:00
int
AbstractExternalFunctionNode : : maxEndoLag ( ) const
2010-03-04 16:40:07 +01:00
{
2015-05-11 16:39:06 +02:00
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxEndoLag ( ) ) ;
2015-05-11 16:39:06 +02:00
return val ;
2009-12-16 18:13:23 +01:00
}
2008-02-03 11:28:36 +01:00
2015-05-11 16:39:06 +02:00
int
AbstractExternalFunctionNode : : maxExoLag ( ) const
2010-12-10 11:50:27 +01:00
{
2015-05-11 16:39:06 +02:00
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxExoLag ( ) ) ;
2015-05-11 16:39:06 +02:00
return val ;
}
2010-12-10 11:50:27 +01:00
2015-05-11 16:39:06 +02:00
int
AbstractExternalFunctionNode : : maxLead ( ) const
{
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxLead ( ) ) ;
2015-05-11 16:39:06 +02:00
return val ;
}
2012-05-26 20:53:48 +02:00
2018-02-28 17:33:00 +01:00
int
AbstractExternalFunctionNode : : maxLag ( ) const
{
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = max ( val , argument - > maxLag ( ) ) ;
2018-02-28 17:33:00 +01:00
return val ;
}
2018-12-05 15:17:00 +01:00
int
AbstractExternalFunctionNode : : maxLagWithDiffsExpanded ( ) const
{
int val = 0 ;
for ( auto argument : arguments )
val = max ( val , argument - > maxLagWithDiffsExpanded ( ) ) ;
return val ;
}
2018-04-17 15:17:28 +02:00
expr_t
AbstractExternalFunctionNode : : undiff ( ) const
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > undiff ( ) ) ;
2018-04-17 15:17:28 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2018-05-16 12:17:06 +02:00
int
AbstractExternalFunctionNode : : VarMinLag ( ) const
{
2019-12-20 16:59:30 +01:00
int val = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
val = min ( val , argument - > VarMinLag ( ) ) ;
2018-05-16 12:17:06 +02:00
return val ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
AbstractExternalFunctionNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2018-06-11 10:40:00 +02:00
int max_lag = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-10-22 16:04:24 +02:00
max_lag = max ( max_lag , argument - > VarMaxLag ( lhs_lag_equiv ) ) ;
2018-06-11 10:40:00 +02:00
return max_lag ;
2018-04-16 13:50:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : decreaseLeadsLags ( int n ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > decreaseLeadsLags ( n ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
2009-11-07 19:37:11 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > decreaseLeadsLagsPredeterminedVariables ( ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-11-07 19:37:11 +01:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 16:07:13 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteEndoLeadGreaterThanTwo ( subst_table , neweqs , deterministic_model ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 16:07:13 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2009-09-30 17:10:31 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteEndoLagGreaterThanTwo ( subst_table , neweqs ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-09-30 17:10:31 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
2009-10-07 18:34:42 +02:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteExoLead ( subst_table , neweqs , deterministic_model ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
2009-10-07 18:34:42 +02:00
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2010-02-22 17:33:38 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteExoLag ( subst_table , neweqs ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
2010-02-22 17:33:38 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteExpectation ( subst_table , neweqs , partial_information_model ) ) ;
2010-02-22 17:33:38 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
AbstractExternalFunctionNode : : substituteAdl ( ) const
2017-06-12 14:56:44 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteAdl ( ) ) ;
2018-01-30 10:06:56 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
AbstractExternalFunctionNode : : substituteModelLocalVariables ( ) const
{
vector < expr_t > arguments_subst ;
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteModelLocalVariables ( ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
AbstractExternalFunctionNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
vector < expr_t > arguments_subst ;
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteVarExpectation ( subst_table ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
AbstractExternalFunctionNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-10-22 14:56:28 +02:00
argument - > findDiffNodes ( nodes ) ;
2018-03-02 12:32:01 +01:00
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
AbstractExternalFunctionNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-10-22 14:56:28 +02:00
argument - > findUnaryOpNodesForAuxVarCreation ( nodes ) ;
2018-05-30 16:48:08 +02:00
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
AbstractExternalFunctionNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
for ( auto argument : arguments )
2019-12-16 19:42:59 +01:00
if ( int retval = argument - > findTargetVariable ( lhs_symb_id ) ;
retval > = 0 )
return retval ;
2018-08-31 12:35:51 +02:00
return - 1 ;
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
AbstractExternalFunctionNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2018-01-30 10:06:56 +01:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-10-22 14:56:28 +02:00
arguments_subst . push_back ( argument - > substituteDiff ( nodes , subst_table , neweqs ) ) ;
2017-06-12 14:56:44 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
AbstractExternalFunctionNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-10-22 14:56:28 +02:00
arguments_subst . push_back ( argument - > substituteUnaryOpNodes ( nodes , subst_table , neweqs ) ) ;
2018-05-30 16:48:08 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2018-05-31 15:34:25 +02:00
int
AbstractExternalFunctionNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-05-31 15:34:25 +02:00
int ndiffs = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2018-12-05 12:38:46 +01:00
ndiffs = max ( ndiffs , argument - > countDiffs ( ) ) ;
2018-05-31 15:34:25 +02:00
return ndiffs ;
2018-02-08 13:07:15 +01:00
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
AbstractExternalFunctionNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-01-30 16:33:16 +01:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2019-02-20 12:59:55 +01:00
arguments_subst . push_back ( argument - > substitutePacExpectation ( name , subexpr ) ) ;
2018-01-30 16:33:16 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2013-04-25 18:09:31 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2013-04-25 18:09:31 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > differentiateForwardVars ( subset , subst_table , neweqs ) ) ;
2013-04-25 18:09:31 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2010-03-04 16:40:07 +01:00
bool
2018-05-29 11:59:42 +02:00
AbstractExternalFunctionNode : : alreadyWrittenAsTefTerm ( int the_symb_id , const deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2019-10-25 12:29:58 +02:00
if ( tef_terms . find ( { the_symb_id , arguments } ) ! = tef_terms . end ( ) )
2010-03-04 16:40:07 +01:00
return true ;
return false ;
}
int
2018-06-04 12:50:53 +02:00
AbstractExternalFunctionNode : : getIndxInTefTerms ( int the_symb_id , const deriv_node_temp_terms_t & tef_terms ) const noexcept ( false )
2010-03-04 16:40:07 +01:00
{
2019-12-16 19:42:59 +01:00
if ( auto it = tef_terms . find ( { the_symb_id , arguments } ) ;
it ! = tef_terms . end ( ) )
2010-03-04 16:40:07 +01:00
return it - > second ;
throw UnknownFunctionNameAndArgs ( ) ;
}
2018-05-29 17:07:18 +02:00
void
2018-11-30 12:22:13 +01:00
AbstractExternalFunctionNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2018-05-29 17:07:18 +02:00
{
/* All external function nodes are declared as temporary terms.
Given that temporary terms are separated in several functions ( residuals ,
jacobian , … ) , we must make sure that all temporary terms derived from a
given external function call are assigned just after that call .
As a consequence , we need to “ promote ” some terms to a previous level ( in
the sense that residuals come before jacobian ) , if a temporary term
corresponding to the same external function call is present in that
previous level . */
2020-05-12 18:29:11 +02:00
expr_t this2 = const_cast < AbstractExternalFunctionNode * > ( this ) ;
2018-11-30 12:22:13 +01:00
for ( auto & tt : temp_terms_map )
2019-12-16 19:42:59 +01:00
if ( auto it = find_if ( tt . second . cbegin ( ) , tt . second . cend ( ) , sameTefTermPredicate ( ) ) ;
it ! = tt . second . cend ( ) )
{
2020-05-12 18:29:11 +02:00
tt . second . insert ( this2 ) ;
2019-12-16 19:42:59 +01:00
return ;
}
2018-05-29 17:07:18 +02:00
2020-05-12 18:29:11 +02:00
temp_terms_map [ derivOrder ] . insert ( this2 ) ;
2018-05-29 17:07:18 +02:00
}
2020-05-06 17:13:47 +02:00
void
2020-05-13 16:58:19 +02:00
AbstractExternalFunctionNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2020-05-06 17:13:47 +02:00
{
// See comments in computeTemporaryTerms() for the logic
expr_t this2 = const_cast < AbstractExternalFunctionNode * > ( this ) ;
2020-05-13 16:58:19 +02:00
for ( auto & btt : blocks_temporary_terms )
for ( auto & tt : btt )
if ( auto it = find_if ( tt . cbegin ( ) , tt . cend ( ) , sameTefTermPredicate ( ) ) ;
it ! = tt . cend ( ) )
{
tt . insert ( this2 ) ;
return ;
}
2020-05-06 17:13:47 +02:00
2020-05-13 16:58:19 +02:00
blocks_temporary_terms [ blk ] [ eq ] . insert ( this2 ) ;
2020-05-06 17:13:47 +02:00
}
2010-04-16 16:54:55 +02:00
bool
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : isNumConstNodeEqualTo ( double value ) const
2010-04-16 16:54:55 +02:00
{
return false ;
}
bool
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
2010-04-16 16:54:55 +02:00
{
return false ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
AbstractExternalFunctionNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
for ( auto argument : arguments )
2019-10-25 12:29:58 +02:00
if ( argument - > containsPacExpectation ( pac_model_name ) )
return true ;
return false ;
2018-06-05 18:38:53 +02:00
}
2010-10-15 19:05:16 +02:00
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : replaceTrendVar ( ) const
2010-10-15 19:05:16 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > replaceTrendVar ( ) ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
expr_t
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
2010-10-15 19:05:16 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > detrend ( symb_id , log_trend , trend ) ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
AbstractExternalFunctionNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2010-10-15 19:05:16 +02:00
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > removeTrendLeadLag ( trend_symbols_map ) ) ;
2010-10-15 19:05:16 +02:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2013-04-11 17:07:39 +02:00
bool
2014-03-13 11:22:00 +01:00
AbstractExternalFunctionNode : : isInStaticForm ( ) const
2013-04-11 17:07:39 +02:00
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
if ( ! argument - > isInStaticForm ( ) )
2013-04-11 17:07:39 +02:00
return false ;
return true ;
}
2018-08-09 16:14:40 +02:00
bool
AbstractExternalFunctionNode : : isParamTimesEndogExpr ( ) const
{
return false ;
}
2016-11-25 17:15:13 +01:00
bool
AbstractExternalFunctionNode : : isVarModelReferenced ( const string & model_info_name ) const
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
if ( ! argument - > isVarModelReferenced ( model_info_name ) )
2016-11-25 17:15:13 +01:00
return true ;
return false ;
}
void
AbstractExternalFunctionNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > getEndosAndMaxLags ( model_endos_and_lags ) ;
2016-11-25 17:15:13 +01:00
}
2020-04-02 14:36:26 +02:00
void
AbstractExternalFunctionNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
2015-05-11 16:39:06 +02:00
{
2020-04-02 14:36:26 +02:00
bool var_present = false ;
for ( auto arg : arguments )
2015-05-11 16:39:06 +02:00
{
2020-04-02 14:36:26 +02:00
arg - > computeSubExprContainingVariable ( symb_id , lag , contain_var ) ;
var_present = var_present | | contain_var . count ( arg ) > 0 ;
2015-05-11 16:39:06 +02:00
}
2020-04-02 14:36:26 +02:00
if ( var_present )
contain_var . insert ( const_cast < AbstractExternalFunctionNode * > ( this ) ) ;
}
BinaryOpNode *
AbstractExternalFunctionNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
throw NormalizationFailed ( ) ;
2015-05-11 16:39:06 +02:00
}
void
AbstractExternalFunctionNode : : writeExternalFunctionArguments ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2015-05-11 16:39:06 +02:00
{
2019-12-16 19:42:59 +01:00
for ( auto it = arguments . begin ( ) ; it ! = arguments . end ( ) ; + + it )
2015-05-11 16:39:06 +02:00
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2018-03-27 17:14:30 +02:00
( * it ) - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2015-05-11 16:39:06 +02:00
}
}
2018-09-18 14:50:31 +02:00
void
AbstractExternalFunctionNode : : writeJsonASTExternalFunctionArguments ( ostream & output ) const
{
int i = 0 ;
output < < " { " ;
2019-12-16 19:42:59 +01:00
for ( auto it = arguments . begin ( ) ; it ! = arguments . end ( ) ; + + it , i + + )
2018-09-18 14:50:31 +02:00
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2019-04-03 16:32:52 +02:00
output < < R " ( " arg ) " << i << R " ( " : ) " ;
2018-09-18 14:50:31 +02:00
( * it ) - > writeJsonAST ( output ) ;
}
2019-12-20 16:59:30 +01:00
output < < " } " ;
2018-09-18 14:50:31 +02:00
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
AbstractExternalFunctionNode : : writeJsonExternalFunctionArguments ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2019-12-16 19:42:59 +01:00
for ( auto it = arguments . begin ( ) ; it ! = arguments . end ( ) ; + + it )
2017-02-02 15:09:43 +01:00
{
if ( it ! = arguments . begin ( ) )
output < < " , " ;
2017-10-16 17:24:55 +02:00
( * it ) - > writeJsonOutput ( output , temporary_terms , tef_terms , isdynamic ) ;
2017-02-02 15:09:43 +01:00
}
}
2015-05-11 16:39:06 +02:00
void
AbstractExternalFunctionNode : : writePrhs ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-05-29 11:12:22 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2020-05-05 20:55:09 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2015-05-11 16:39:06 +02:00
{
int i = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2015-05-11 16:39:06 +02:00
{
2020-05-05 20:55:09 +02:00
output < < " prhs[ " < < i + + < < " ] = mxCreateDoubleScalar( " ; // All external_function arguments are scalars
2018-06-04 12:26:16 +02:00
argument - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2015-05-11 16:39:06 +02:00
output < < " ); " < < endl ;
}
}
2015-05-12 16:36:03 +02:00
bool
AbstractExternalFunctionNode : : containsExternalFunction ( ) const
{
return true ;
}
2016-03-18 14:55:14 +01:00
expr_t
AbstractExternalFunctionNode : : substituteStaticAuxiliaryVariable ( ) const
{
vector < expr_t > arguments_subst ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > substituteStaticAuxiliaryVariable ( ) ) ;
2016-03-18 14:55:14 +01:00
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
AbstractExternalFunctionNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
vector < expr_t > arguments_subst ;
for ( auto argument : arguments )
arguments_subst . push_back ( argument - > replaceVarsInEquation ( table ) ) ;
return buildSimilarExternalFunctionNode ( arguments_subst , datatree ) ;
}
2015-05-11 16:39:06 +02:00
ExternalFunctionNode : : ExternalFunctionNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2015-05-11 16:39:06 +02:00
int symb_id_arg ,
const vector < expr_t > & arguments_arg ) :
2018-10-04 17:18:27 +02:00
AbstractExternalFunctionNode { datatree_arg , idx_arg , symb_id_arg , arguments_arg }
2015-05-11 16:39:06 +02:00
{
}
expr_t
ExternalFunctionNode : : composeDerivatives ( const vector < expr_t > & dargs )
{
vector < expr_t > dNodes ;
2019-04-23 11:07:32 +02:00
for ( int i = 0 ; i < static_cast < int > ( dargs . size ( ) ) ; i + + )
2015-05-11 16:39:06 +02:00
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
datatree . AddFirstDerivExternalFunction ( symb_id , arguments , i + 1 ) ) ) ;
expr_t theDeriv = datatree . Zero ;
2019-12-20 16:59:30 +01:00
for ( auto & dNode : dNodes )
2019-12-16 19:42:59 +01:00
theDeriv = datatree . AddPlus ( theDeriv , dNode ) ;
2015-05-11 16:39:06 +02:00
return theDeriv ;
}
void
ExternalFunctionNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2015-05-11 16:39:06 +02:00
{
2020-05-13 12:53:47 +02:00
if ( auto this2 = const_cast < ExternalFunctionNode * > ( this ) ;
temporary_terms . find ( this2 ) ! = temporary_terms . end ( ) )
2015-05-11 16:39:06 +02:00
{
if ( dynamic )
{
2020-05-13 12:53:47 +02:00
FLDT_ fldt ( temporary_terms_idxs . at ( this2 ) ) ;
2015-05-11 16:39:06 +02:00
fldt . write ( CompileCode , instruction_number ) ;
}
else
{
2020-05-13 12:53:47 +02:00
FLDST_ fldst ( temporary_terms_idxs . at ( this2 ) ) ;
2015-05-11 16:39:06 +02:00
fldst . write ( CompileCode , instruction_number ) ;
}
return ;
}
if ( ! lhs_rhs )
{
FLDTEF_ fldtef ( getIndxInTefTerms ( symb_id , tef_terms ) ) ;
fldtef . write ( CompileCode , instruction_number ) ;
}
else
{
FSTPTEF_ fstptef ( getIndxInTefTerms ( symb_id , tef_terms ) ) ;
fstptef . write ( CompileCode , instruction_number ) ;
}
}
void
ExternalFunctionNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2015-05-11 16:39:06 +02:00
deriv_node_temp_terms_t & tef_terms ) const
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2015-05-11 16:39:06 +02:00
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2020-05-13 12:53:47 +02:00
argument - > compileExternalFunctionOutput ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
2020-05-06 17:13:47 +02:00
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2015-05-11 16:39:06 +02:00
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
2019-04-23 11:07:32 +02:00
tef_terms [ { symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2015-05-11 16:39:06 +02:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2015-05-11 16:39:06 +02:00
unsigned int nb_output_arguments = 0 ;
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
nb_output_arguments = 3 ;
else if ( symb_id = = first_deriv_symb_id )
nb_output_arguments = 2 ;
else
nb_output_arguments = 1 ;
2020-05-13 12:53:47 +02:00
unsigned int nb_input_arguments = compileExternalFunctionArguments ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
2020-05-06 17:13:47 +02:00
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2015-05-11 16:39:06 +02:00
FCALL_ fcall ( nb_output_arguments , nb_input_arguments , datatree . symbol_table . getName ( symb_id ) , indx ) ;
switch ( nb_output_arguments )
{
case 1 :
2018-07-18 16:56:55 +02:00
fcall . set_function_type ( ExternalFunctionType : : withoutDerivative ) ;
2015-05-11 16:39:06 +02:00
break ;
case 2 :
2018-07-18 16:56:55 +02:00
fcall . set_function_type ( ExternalFunctionType : : withFirstDerivative ) ;
2015-05-11 16:39:06 +02:00
break ;
case 3 :
2018-07-18 16:56:55 +02:00
fcall . set_function_type ( ExternalFunctionType : : withFirstAndSecondDerivative ) ;
2015-05-11 16:39:06 +02:00
break ;
}
fcall . write ( CompileCode , instruction_number ) ;
FSTPTEF_ fstptef ( indx ) ;
fstptef . write ( CompileCode , instruction_number ) ;
}
}
2018-09-18 14:50:31 +02:00
void
ExternalFunctionNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " ExternalFunctionNode " , ) "
< < R " ( " name " : " ) " << datatree.symbol_table.getName(symb_id) << R " ( " , " args " : [) " ;
2018-09-18 14:50:31 +02:00
writeJsonASTExternalFunctionArguments ( output ) ;
output < < " ]} " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
ExternalFunctionNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < ExternalFunctionNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
2020-06-05 15:36:19 +02:00
try
{
int tef_idx = getIndxInTefTerms ( symb_id , tef_terms ) ;
output < < " TEF_ " < < tef_idx ;
}
catch ( UnknownFunctionNameAndArgs & )
{
// When writing the JSON output at parsing pass, we don’ t use TEF terms
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
writeJsonExternalFunctionArguments ( output , temporary_terms , tef_terms , isdynamic ) ;
output < < " ) " ;
}
2017-02-02 15:09:43 +01:00
}
2015-05-11 16:39:06 +02:00
void
ExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2015-05-11 16:39:06 +02:00
{
2018-09-05 18:27:13 +02:00
if ( output_type = = ExprNodeOutputType : : matlabOutsideModel | | output_type = = ExprNodeOutputType : : steadyStateFile
| | output_type = = ExprNodeOutputType : : juliaSteadyStateFile
2019-12-12 14:45:49 +01:00
| | output_type = = ExprNodeOutputType : : epilogueFile
2018-09-05 18:27:13 +02:00
| | isLatexOutput ( output_type ) )
2015-05-11 16:39:06 +02:00
{
2018-09-05 18:27:13 +02:00
string name = isLatexOutput ( output_type ) ? datatree . symbol_table . getTeXName ( symb_id )
2015-05-11 16:39:06 +02:00
: datatree . symbol_table . getName ( symb_id ) ;
output < < name < < " ( " ;
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2015-05-11 16:39:06 +02:00
output < < " ) " ;
return ;
}
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2015-05-11 16:39:06 +02:00
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2015-05-11 16:39:06 +02:00
output < < " * " ;
output < < " TEF_ " < < getIndxInTefTerms ( symb_id , tef_terms ) ;
}
void
ExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2015-05-11 16:39:06 +02:00
deriv_node_temp_terms_t & tef_terms ) const
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2015-05-11 16:39:06 +02:00
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2015-05-11 16:39:06 +02:00
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
2019-04-23 11:07:32 +02:00
tef_terms [ { symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2015-05-11 16:39:06 +02:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2015-05-11 16:39:06 +02:00
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2015-05-11 16:39:06 +02:00
{
2020-05-05 20:55:09 +02:00
output < < " double *TEF_ " < < indx ;
if ( symb_id = = first_deriv_symb_id )
output < < " , *TEFD_ " < < indx ;
if ( symb_id = = second_deriv_symb_id )
output < < " , *TEFDD_ " < < indx ;
output < < " ; " < < endl ;
if ( symb_id = = first_deriv_symb_id & & symb_id = = second_deriv_symb_id )
output < < " int TEFDD_ " < < indx < < " _nrows; " < < endl ;
int nlhs =
symb_id = = first_deriv_symb_id & & symb_id = = second_deriv_symb_id ? 3
: symb_id = = first_deriv_symb_id ? 2 : 1 ;
output < < " { " < < endl
< < " mxArray *plhs[ " < < nlhs < < " ], *prhs[ " < < arguments . size ( ) < < " ]; " < < endl ;
writePrhs ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " mexCallMATLAB( " < < nlhs < < " , plhs, " < < arguments . size ( ) < < " , prhs, " < < R " ( " ) "
2019-04-03 16:32:52 +02:00
< < datatree . symbol_table . getName ( symb_id ) < < R " ( " ) ; ) " << endl;
2015-05-11 16:39:06 +02:00
2020-05-05 20:55:09 +02:00
output < < " TEF_ " < < indx < < " = mxGetPr(plhs[0]); " < < endl ;
if ( symb_id = = first_deriv_symb_id )
{
output < < " TEFD_ " < < indx < < " = mxGetPr(plhs[1]); " < < endl ;
if ( symb_id = = second_deriv_symb_id )
output < < " TEFDD_ " < < indx < < " = mxGetPr(plhs[2]); " < < endl
< < " TEFDD_ " < < indx < < " _nrows = (int)mxGetM(plhs[2]); " < < endl ;
}
output < < " } " < < endl ;
2015-05-11 16:39:06 +02:00
}
else
{
if ( symb_id = = first_deriv_symb_id
& & symb_id = = second_deriv_symb_id )
2016-08-25 15:35:32 +02:00
output < < " [TEF_ " < < indx < < " , TEFD_ " < < indx < < " , TEFDD_ " < < indx < < " ] = " ;
2015-05-11 16:39:06 +02:00
else if ( symb_id = = first_deriv_symb_id )
2016-08-25 15:35:32 +02:00
output < < " [TEF_ " < < indx < < " , TEFD_ " < < indx < < " ] = " ;
2015-05-11 16:39:06 +02:00
else
output < < " TEF_ " < < indx < < " = " ;
output < < datatree . symbol_table . getName ( symb_id ) < < " ( " ;
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2015-05-11 16:39:06 +02:00
output < < " ); " < < endl ;
}
}
}
2017-02-20 12:18:11 +01:00
void
ExternalFunctionNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
if ( ! alreadyWrittenAsTefTerm ( symb_id , tef_terms ) )
{
2019-04-23 11:07:32 +02:00
tef_terms [ { symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2017-02-20 12:18:11 +01:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
stringstream ef ;
2019-04-03 16:32:52 +02:00
ef < < R " ({ " external_function " : {) "
< < R " ( " external_function_term " : " TEF_ ) " << indx << R " ( " ) " ;
2017-02-20 12:18:11 +01:00
if ( symb_id = = first_deriv_symb_id )
2019-04-03 16:32:52 +02:00
ef < < R " (, " external_function_term_d " : " TEFD_ ) " << indx << R " ( " ) " ;
2017-02-20 12:18:11 +01:00
if ( symb_id = = second_deriv_symb_id )
2019-04-03 16:32:52 +02:00
ef < < R " (, " external_function_term_dd " : " TEFDD_ ) " << indx << R " ( " ) " ;
2017-02-20 12:18:11 +01:00
2019-04-03 16:32:52 +02:00
ef < < R " (, " value " : " ) " << datatree.symbol_table.getName(symb_id) << " ( " ;
2017-10-16 17:24:55 +02:00
writeJsonExternalFunctionArguments ( ef , temporary_terms , tef_terms , isdynamic ) ;
2019-04-03 16:32:52 +02:00
ef < < R " lit() " } } ) lit " ;
2017-02-20 12:18:11 +01:00
efout . push_back ( ef . str ( ) ) ;
}
}
2015-05-11 16:39:06 +02:00
expr_t
ExternalFunctionNode : : toStatic ( DataTree & static_datatree ) const
{
vector < expr_t > static_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
static_arguments . push_back ( argument - > toStatic ( static_datatree ) ) ;
2015-05-11 16:39:06 +02:00
return static_datatree . AddExternalFunction ( symb_id , static_arguments ) ;
}
2015-12-18 15:17:32 +01:00
void
ExternalFunctionNode : : computeXrefs ( EquationInfo & ei ) const
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > computeXrefs ( ei ) ;
2015-12-18 15:17:32 +01:00
}
2015-05-11 16:39:06 +02:00
expr_t
2018-10-10 13:07:25 +02:00
ExternalFunctionNode : : clone ( DataTree & datatree ) const
2015-05-11 16:39:06 +02:00
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2018-10-10 13:07:25 +02:00
dynamic_arguments . push_back ( argument - > clone ( datatree ) ) ;
return datatree . AddExternalFunction ( symb_id , dynamic_arguments ) ;
2015-05-11 16:39:06 +02:00
}
expr_t
ExternalFunctionNode : : buildSimilarExternalFunctionNode ( vector < expr_t > & alt_args , DataTree & alt_datatree ) const
{
return alt_datatree . AddExternalFunction ( symb_id , alt_args ) ;
}
2018-05-29 17:07:18 +02:00
function < bool ( expr_t ) >
ExternalFunctionNode : : sameTefTermPredicate ( ) const
{
return [ this ] ( expr_t e ) {
2019-12-20 16:59:30 +01:00
auto e2 = dynamic_cast < ExternalFunctionNode * > ( e ) ;
return ( e2 ! = nullptr & & e2 - > symb_id = = symb_id ) ;
} ;
2018-05-29 17:07:18 +02:00
}
2010-02-22 17:33:38 +01:00
FirstDerivExternalFunctionNode : : FirstDerivExternalFunctionNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2010-02-22 17:33:38 +01:00
int top_level_symb_id_arg ,
2010-09-16 19:18:45 +02:00
const vector < expr_t > & arguments_arg ,
2010-02-22 17:33:38 +01:00
int inputIndex_arg ) :
2018-10-04 17:18:27 +02:00
AbstractExternalFunctionNode { datatree_arg , idx_arg , top_level_symb_id_arg , arguments_arg } ,
inputIndex { inputIndex_arg }
2010-02-22 17:33:38 +01:00
{
}
2010-09-16 19:18:45 +02:00
expr_t
FirstDerivExternalFunctionNode : : composeDerivatives ( const vector < expr_t > & dargs )
2010-02-22 17:33:38 +01:00
{
2010-09-16 19:18:45 +02:00
vector < expr_t > dNodes ;
2019-04-23 11:07:32 +02:00
for ( int i = 0 ; i < static_cast < int > ( dargs . size ( ) ) ; i + + )
2014-03-11 17:12:46 +01:00
dNodes . push_back ( datatree . AddTimes ( dargs . at ( i ) ,
2014-03-11 17:38:47 +01:00
datatree . AddSecondDerivExternalFunction ( symb_id , arguments , inputIndex , i + 1 ) ) ) ;
2010-09-16 19:18:45 +02:00
expr_t theDeriv = datatree . Zero ;
2019-12-20 16:59:30 +01:00
for ( auto & dNode : dNodes )
2019-12-16 19:42:59 +01:00
theDeriv = datatree . AddPlus ( theDeriv , dNode ) ;
2010-02-22 17:33:38 +01:00
return theDeriv ;
}
2018-09-18 14:50:31 +02:00
void
FirstDerivExternalFunctionNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " FirstDerivExternalFunctionNode " , ) "
< < R " ( " name " : " ) " << datatree.symbol_table.getName(symb_id) << R " ( " , " args " : [) " ;
2018-09-18 14:50:31 +02:00
writeJsonASTExternalFunctionArguments ( output ) ;
output < < " ]} " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
FirstDerivExternalFunctionNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
// If current node is a temporary term
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < FirstDerivExternalFunctionNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
const int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
const int tmpIndx = inputIndex - 1 ;
if ( first_deriv_symb_id = = symb_id )
output < < " TEFD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < " [ " < < tmpIndx < < " ] " ;
2018-10-02 18:10:12 +02:00
else if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2017-02-20 12:18:11 +01:00
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex ;
else
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
< < " [ " < < tmpIndx < < " ] " ;
2017-02-02 15:09:43 +01:00
}
2010-02-22 17:33:38 +01:00
void
FirstDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
2010-03-04 16:40:07 +01:00
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2014-03-11 15:31:08 +01:00
{
2019-04-03 16:32:52 +02:00
output < < R " ( \f rac{ \ partial ) " < < datatree . symbol_table . getTeXName ( symb_id )
< < R " (}{ \ partial ) " < < inputIndex < < " }( " ;
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2014-03-11 15:31:08 +01:00
output < < " ) " ;
return ;
}
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2010-02-22 17:33:38 +01:00
2014-02-24 15:37:55 +01:00
const int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-03-04 16:40:07 +01:00
2014-02-25 16:00:38 +01:00
const int tmpIndx = inputIndex - 1 + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
2010-10-05 18:48:15 +02:00
2010-03-04 16:40:07 +01:00
if ( first_deriv_symb_id = = symb_id )
2010-10-05 18:48:15 +02:00
output < < " TEFD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndx < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-10-02 18:10:12 +02:00
else if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-10-05 18:48:15 +02:00
{
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-10-05 18:48:15 +02:00
output < < " * " ;
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex ;
}
2010-03-04 16:40:07 +01:00
else
output < < " TEFD_def_ " < < getIndxInTefTerms ( first_deriv_symb_id , tef_terms )
2010-10-05 18:48:15 +02:00
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndx < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
}
2010-12-10 11:50:27 +01:00
void
FirstDerivExternalFunctionNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
2020-05-13 12:53:47 +02:00
if ( auto this2 = const_cast < FirstDerivExternalFunctionNode * > ( this ) ;
temporary_terms . find ( this2 ) ! = temporary_terms . end ( ) )
2010-12-10 11:50:27 +01:00
{
if ( dynamic )
{
2020-05-13 12:53:47 +02:00
FLDT_ fldt ( temporary_terms_idxs . at ( this2 ) ) ;
2010-12-10 11:50:27 +01:00
fldt . write ( CompileCode , instruction_number ) ;
}
else
{
2020-05-13 12:53:47 +02:00
FLDST_ fldst ( temporary_terms_idxs . at ( this2 ) ) ;
2010-12-10 11:50:27 +01:00
fldst . write ( CompileCode , instruction_number ) ;
}
return ;
}
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-12-10 11:50:27 +01:00
if ( ! lhs_rhs )
{
2014-02-24 15:37:55 +01:00
FLDTEFD_ fldtefd ( getIndxInTefTerms ( symb_id , tef_terms ) , inputIndex ) ;
2010-12-10 11:50:27 +01:00
fldtefd . write ( CompileCode , instruction_number ) ;
}
else
{
2014-02-24 15:37:55 +01:00
FSTPTEFD_ fstptefd ( getIndxInTefTerms ( symb_id , tef_terms ) , inputIndex ) ;
2010-12-10 11:50:27 +01:00
fstptefd . write ( CompileCode , instruction_number ) ;
}
}
2010-03-04 16:40:07 +01:00
void
FirstDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
2010-03-04 16:40:07 +01:00
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-03-04 16:40:07 +01:00
2014-03-13 12:26:03 +01:00
/* For a node with derivs provided by the user function, call the method
on the non - derived node */
if ( first_deriv_symb_id = = symb_id )
{
expr_t parent = datatree . AddExternalFunction ( symb_id , arguments ) ;
2018-03-27 17:14:30 +02:00
parent - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs ,
2014-03-13 12:26:03 +01:00
tef_terms ) ;
return ;
}
if ( alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
2010-10-05 18:48:15 +02:00
return ;
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2018-10-02 18:10:12 +02:00
if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-10-05 18:48:15 +02:00
{
2020-05-05 20:55:09 +02:00
output < < " double *TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex < < " ; " < < endl
< < " { " < < endl
< < " const mwSize dims[2] = {1, " < < arguments . size ( ) < < " }; " < < endl
< < " mxArray *plhs[1], *prhs[3]; " < < endl
< < R " ( prhs[0] = mxCreateString( " ) " << datatree.symbol_table.getName(symb_id) << R " ( " );) " < < endl
< < " prhs[1] = mxCreateDoubleScalar( " < < inputIndex < < " ); " < < endl
< < " prhs[2] = mxCreateCellArray(2, dims); " < < endl ;
2010-10-05 18:48:15 +02:00
int i = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2010-10-05 18:48:15 +02:00
{
2020-05-05 20:55:09 +02:00
output < < " mxSetCell(prhs[2], " < < i + + < < " , "
2010-10-05 18:48:15 +02:00
< < " mxCreateDoubleScalar( " ; // All external_function arguments are scalars
2018-06-04 12:26:16 +02:00
argument - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-10-05 18:48:15 +02:00
output < < " )); " < < endl ;
}
2020-05-05 20:55:09 +02:00
output < < " mexCallMATLAB(1, plhs, 3, prhs, " < < R " ( " jacob_element " );) " < < endl
< < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex
< < " = mxGetPr(plhs[0]); " < < endl
< < " } " < < endl ;
2010-10-05 18:48:15 +02:00
}
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { first_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2010-10-05 18:48:15 +02:00
int indx = getIndxInTefTerms ( first_deriv_symb_id , tef_terms ) ;
2020-05-05 20:55:09 +02:00
output < < " double *TEFD_def_ " < < indx < < " ; " < < endl
< < " { " < < endl
< < " mxArray *plhs[1], *prhs[ " < < arguments . size ( ) < < " ]; " < < endl ;
writePrhs ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " mexCallMATLAB(1, plhs, " < < arguments . size ( ) < < " , prhs, " < < R " ( " ) "
< < datatree . symbol_table . getName ( first_deriv_symb_id ) < < R " ( " ) ; ) " << endl
< < " TEFD_def_ " < < indx < < " = mxGetPr(plhs[0]); " < < endl
< < " } " < < endl ;
2010-10-05 18:48:15 +02:00
}
else
2010-02-22 17:33:38 +01:00
{
2018-10-02 18:10:12 +02:00
if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-10-07 14:15:56 +02:00
output < < " TEFD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex < < " = jacob_element(' "
< < datatree . symbol_table . getName ( symb_id ) < < " ', " < < inputIndex < < " ,{ " ;
2010-03-04 16:40:07 +01:00
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { first_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2010-03-04 16:40:07 +01:00
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
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2018-10-02 18:10:12 +02:00
if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-03-04 16:40:07 +01:00
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}
2017-02-20 12:18:11 +01:00
void
FirstDerivExternalFunctionNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
/* For a node with derivs provided by the user function, call the method
on the non - derived node */
if ( first_deriv_symb_id = = symb_id )
{
expr_t parent = datatree . AddExternalFunction ( symb_id , arguments ) ;
2017-10-16 17:24:55 +02:00
parent - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
return ;
}
if ( alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
return ;
stringstream ef ;
2018-10-02 18:10:12 +02:00
if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2019-04-03 16:32:52 +02:00
ef < < R " ({ " first_deriv_external_function " : {) "
< < R " ( " external_function_term " : " TEFD_fdd_ ) " << getIndxInTefTerms(symb_id, tef_terms) << " _ " << inputIndex << R " ( " ) "
< < R " (, " analytic_derivative " : false) "
< < R " (, " wrt " : ) " < < inputIndex
< < R " (, " value " : " ) " << datatree.symbol_table.getName(symb_id) << " ( " ;
2017-02-20 12:18:11 +01:00
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { first_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2019-04-03 16:32:52 +02:00
ef < < R " ({ " first_deriv_external_function " : {) "
< < R " ( " external_function_term " : " TEFD_def_ ) " << getIndxInTefTerms(first_deriv_symb_id, tef_terms) << R " ( " ) "
< < R " (, " analytic_derivative " : true) "
< < R " (, " value " : " ) " << datatree.symbol_table.getName(first_deriv_symb_id) << " ( " ;
2017-02-20 12:18:11 +01:00
}
2017-10-16 17:24:55 +02:00
writeJsonExternalFunctionArguments ( ef , temporary_terms , tef_terms , isdynamic ) ;
2019-04-03 16:32:52 +02:00
ef < < R " lit() " } } ) lit " ;
2017-02-20 12:18:11 +01:00
efout . push_back ( ef . str ( ) ) ;
}
2010-12-10 11:50:27 +01:00
void
FirstDerivExternalFunctionNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2011-02-04 16:25:38 +01:00
deriv_node_temp_terms_t & tef_terms ) const
2010-12-10 11:50:27 +01:00
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( first_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-12-10 11:50:27 +01:00
if ( first_deriv_symb_id = = symb_id | | alreadyWrittenAsTefTerm ( first_deriv_symb_id , tef_terms ) )
return ;
2020-05-13 12:53:47 +02:00
unsigned int nb_add_input_arguments = compileExternalFunctionArguments ( CompileCode , instruction_number , lhs_rhs , temporary_terms ,
2020-05-06 17:13:47 +02:00
temporary_terms_idxs , dynamic , steady_dynamic , tef_terms ) ;
2018-10-02 18:10:12 +02:00
if ( first_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-12-10 11:50:27 +01:00
{
unsigned int nb_input_arguments = 0 ;
unsigned int nb_output_arguments = 1 ;
2020-03-24 18:26:06 +01:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
2010-12-10 11:50:27 +01:00
FCALL_ fcall ( nb_output_arguments , nb_input_arguments , " jacob_element " , indx ) ;
fcall . set_arg_func_name ( datatree . symbol_table . getName ( symb_id ) ) ;
fcall . set_row ( inputIndex ) ;
fcall . set_nb_add_input_arguments ( nb_add_input_arguments ) ;
2018-07-18 16:56:55 +02:00
fcall . set_function_type ( ExternalFunctionType : : numericalFirstDerivative ) ;
2010-12-10 11:50:27 +01:00
fcall . write ( CompileCode , instruction_number ) ;
FSTPTEFD_ fstptefd ( indx , inputIndex ) ;
fstptefd . write ( CompileCode , instruction_number ) ;
}
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { first_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2010-12-10 11:50:27 +01:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-12-10 11:50:27 +01:00
unsigned int nb_output_arguments = 1 ;
FCALL_ fcall ( nb_output_arguments , nb_add_input_arguments , datatree . symbol_table . getName ( first_deriv_symb_id ) , indx ) ;
2018-07-18 16:56:55 +02:00
fcall . set_function_type ( ExternalFunctionType : : firstDerivative ) ;
2010-12-10 11:50:27 +01:00
fcall . write ( CompileCode , instruction_number ) ;
2010-12-31 16:26:25 +01:00
FSTPTEFD_ fstptefd ( indx , inputIndex ) ;
fstptefd . write ( CompileCode , instruction_number ) ;
2010-12-10 11:50:27 +01:00
}
}
2014-03-11 17:33:46 +01:00
expr_t
2018-10-10 13:07:25 +02:00
FirstDerivExternalFunctionNode : : clone ( DataTree & datatree ) const
2014-03-11 17:33:46 +01:00
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2018-10-10 13:07:25 +02:00
dynamic_arguments . push_back ( argument - > clone ( datatree ) ) ;
return datatree . AddFirstDerivExternalFunction ( symb_id , dynamic_arguments ,
2019-12-20 16:59:30 +01:00
inputIndex ) ;
2014-03-11 17:33:46 +01:00
}
2014-03-13 11:22:00 +01:00
expr_t
FirstDerivExternalFunctionNode : : buildSimilarExternalFunctionNode ( vector < expr_t > & alt_args , DataTree & alt_datatree ) const
{
return alt_datatree . AddFirstDerivExternalFunction ( symb_id , alt_args , inputIndex ) ;
}
expr_t
FirstDerivExternalFunctionNode : : toStatic ( DataTree & static_datatree ) const
{
vector < expr_t > static_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
static_arguments . push_back ( argument - > toStatic ( static_datatree ) ) ;
2014-03-13 11:22:00 +01:00
return static_datatree . AddFirstDerivExternalFunction ( symb_id , static_arguments ,
inputIndex ) ;
}
2015-12-18 15:17:32 +01:00
void
FirstDerivExternalFunctionNode : : computeXrefs ( EquationInfo & ei ) const
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > computeXrefs ( ei ) ;
2015-12-18 15:17:32 +01:00
}
2018-05-29 17:07:18 +02:00
function < bool ( expr_t ) >
FirstDerivExternalFunctionNode : : sameTefTermPredicate ( ) const
{
int first_deriv_symb_id = datatree . external_functions_table . getFirstDerivSymbID ( symb_id ) ;
if ( first_deriv_symb_id = = symb_id )
return [ this ] ( expr_t e ) {
auto e2 = dynamic_cast < ExternalFunctionNode * > ( e ) ;
2019-12-16 19:42:59 +01:00
return ( e2 & & e2 - > symb_id = = symb_id ) ;
2018-05-29 17:07:18 +02:00
} ;
else
return [ this ] ( expr_t e ) {
auto e2 = dynamic_cast < FirstDerivExternalFunctionNode * > ( e ) ;
2019-12-16 19:42:59 +01:00
return ( e2 & & e2 - > symb_id = = symb_id ) ;
2018-05-29 17:07:18 +02:00
} ;
}
2010-02-22 17:33:38 +01:00
SecondDerivExternalFunctionNode : : SecondDerivExternalFunctionNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2010-02-22 17:33:38 +01:00
int top_level_symb_id_arg ,
2010-09-16 19:18:45 +02:00
const vector < expr_t > & arguments_arg ,
2010-02-22 17:33:38 +01:00
int inputIndex1_arg ,
int inputIndex2_arg ) :
2018-10-04 17:18:27 +02:00
AbstractExternalFunctionNode { datatree_arg , idx_arg , top_level_symb_id_arg , arguments_arg } ,
inputIndex1 { inputIndex1_arg } ,
inputIndex2 { inputIndex2_arg }
2009-09-30 17:10:31 +02:00
{
}
2009-10-29 18:16:10 +01:00
2010-09-16 19:18:45 +02:00
expr_t
2014-03-13 11:22:00 +01:00
SecondDerivExternalFunctionNode : : composeDerivatives ( const vector < expr_t > & dargs )
2009-10-29 18:16:10 +01:00
{
2013-01-15 11:38:47 +01:00
cerr < < " ERROR: third order derivatives of external functions are not implemented " < < endl ;
2009-10-29 18:16:10 +01:00
exit ( EXIT_FAILURE ) ;
}
2010-02-22 17:33:38 +01:00
2018-09-18 14:50:31 +02:00
void
SecondDerivExternalFunctionNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " SecondDerivExternalFunctionNode " , ) "
< < R " ( " name " : " ) " << datatree.symbol_table.getName(symb_id) << R " ( " , " args " : [) " ;
2018-09-18 14:50:31 +02:00
writeJsonASTExternalFunctionArguments ( output ) ;
output < < " ]} " ;
}
2017-02-02 15:09:43 +01:00
void
2017-02-20 12:18:11 +01:00
SecondDerivExternalFunctionNode : : writeJsonOutput ( ostream & output ,
2017-02-02 15:09:43 +01:00
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-02 15:09:43 +01:00
{
2017-02-20 12:18:11 +01:00
// If current node is a temporary term
2019-10-25 12:29:58 +02:00
if ( temporary_terms . find ( const_cast < SecondDerivExternalFunctionNode * > ( this ) ) ! = temporary_terms . end ( ) )
2017-02-20 12:18:11 +01:00
{
output < < " T " < < idx ;
return ;
}
const int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
const int tmpIndex1 = inputIndex1 - 1 ;
const int tmpIndex2 = inputIndex2 - 1 ;
if ( second_deriv_symb_id = = symb_id )
output < < " TEFDD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < " [ " < < tmpIndex1 < < " , " < < tmpIndex2 < < " ] " ;
2018-10-02 18:10:12 +02:00
else if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2017-02-20 12:18:11 +01:00
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 ;
else
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < " [ " < < tmpIndex1 < < " , " < < tmpIndex2 < < " ] " ;
2017-02-02 15:09:43 +01:00
}
2010-02-22 17:33:38 +01:00
void
SecondDerivExternalFunctionNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2010-02-22 17:33:38 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
2010-03-04 16:40:07 +01:00
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2014-03-11 15:31:08 +01:00
{
2019-04-03 16:32:52 +02:00
output < < R " ( \f rac{ \ partial^2 ) " < < datatree . symbol_table . getTeXName ( symb_id )
< < R " (}{ \ partial ) " < < inputIndex1 < < R " ( \ partial ) " < < inputIndex2 < < " }( " ;
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2014-03-11 15:31:08 +01:00
output < < " ) " ;
return ;
}
2018-05-25 14:50:08 +02:00
if ( checkIfTemporaryTermThenWrite ( output , output_type , temporary_terms , temporary_terms_idxs ) )
return ;
2010-02-22 17:33:38 +01:00
2014-02-24 15:37:55 +01:00
const int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-03-04 16:40:07 +01:00
2014-02-25 16:00:38 +01:00
const int tmpIndex1 = inputIndex1 - 1 + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
const int tmpIndex2 = inputIndex2 - 1 + ARRAY_SUBSCRIPT_OFFSET ( output_type ) ;
2010-10-05 18:48:15 +02:00
int indx = getIndxInTefTerms ( symb_id , tef_terms ) ;
2010-03-04 16:40:07 +01:00
if ( second_deriv_symb_id = = symb_id )
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-10-05 18:48:15 +02:00
output < < " TEFDD_ " < < indx
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " * TEFDD_ " < < indx < < " _nrows + "
< < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " TEFDD_ " < < getIndxInTefTerms ( symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " , " < < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2018-10-02 18:10:12 +02:00
else if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-10-05 18:48:15 +02:00
{
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-10-05 18:48:15 +02:00
output < < " * " ;
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 ;
}
2010-03-04 16:40:07 +01:00
else
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2010-10-05 18:48:15 +02:00
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " * PROBLEM_ " < < indx < < " _nrows "
< < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
else
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < LEFT_ARRAY_SUBSCRIPT ( output_type ) < < tmpIndex1 < < " , " < < tmpIndex2 < < RIGHT_ARRAY_SUBSCRIPT ( output_type ) ;
2010-03-04 16:40:07 +01:00
}
void
SecondDerivExternalFunctionNode : : writeExternalFunctionOutput ( ostream & output , ExprNodeOutputType output_type ,
2010-09-16 19:00:48 +02:00
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2010-09-16 19:00:48 +02:00
deriv_node_temp_terms_t & tef_terms ) const
2010-03-04 16:40:07 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
2010-03-04 16:40:07 +01:00
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2010-03-04 16:40:07 +01:00
2014-03-13 12:26:03 +01:00
/* For a node with derivs provided by the user function, call the method
on the non - derived node */
if ( second_deriv_symb_id = = symb_id )
{
expr_t parent = datatree . AddExternalFunction ( symb_id , arguments ) ;
2018-03-27 17:14:30 +02:00
parent - > writeExternalFunctionOutput ( output , output_type , temporary_terms , temporary_terms_idxs ,
2014-03-13 12:26:03 +01:00
tef_terms ) ;
return ;
}
if ( alreadyWrittenAsTefTerm ( second_deriv_symb_id , tef_terms ) )
2010-10-05 18:48:15 +02:00
return ;
2018-09-05 18:27:13 +02:00
if ( isCOutput ( output_type ) )
2018-10-02 18:10:12 +02:00
if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-10-05 18:48:15 +02:00
{
stringstream ending ;
2020-05-05 20:55:09 +02:00
output < < " double *TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2 < < " ; " < < endl
< < " { " < < endl
< < " const mwSize dims[2]= {1, " < < arguments . size ( ) < < " }; " < < endl
< < " mxArray *plhs[1], *prhs[4]; " < < endl
< < R " ( prhs[0] = mxCreateString( " ) " << datatree.symbol_table.getName(symb_id) << R " ( " );) " < < endl
< < " prhs[1] = mxCreateDoubleScalar( " < < inputIndex1 < < " ); " < < endl
< < " prhs[2] = mxCreateDoubleScalar( " < < inputIndex2 < < " ); " < < endl
< < " prhs[3] = mxCreateCellArray(2, dims); " < < endl ;
2010-10-05 18:48:15 +02:00
int i = 0 ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2010-10-05 18:48:15 +02:00
{
2020-05-05 20:55:09 +02:00
output < < " mxSetCell(prhs[3], " < < i + + < < " , "
< < " mxCreateDoubleScalar( " ; // All external_function arguments are scalars
2018-06-04 12:26:16 +02:00
argument - > writeOutput ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-10-05 18:48:15 +02:00
output < < " )); " < < endl ;
}
2020-05-05 20:55:09 +02:00
output < < " mexCallMATLAB(1, plhs, 4, prhs, " < < R " ( " hess_element " );) " < < endl
< < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2
< < " = mxGetPr(plhs[0]); " < < endl
< < " } " < < endl ;
2010-10-05 18:48:15 +02:00
}
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { second_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2010-10-05 18:48:15 +02:00
int indx = getIndxInTefTerms ( second_deriv_symb_id , tef_terms ) ;
2020-05-05 20:55:09 +02:00
output < < " double *TEFDD_def_ " < < indx < < " ; " < < endl
< < " { " < < endl
< < " mxArray *plhs[1], *prhs[ " < < arguments . size ( ) < < " ]; " < < endl ;
writePrhs ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
output < < " mexCallMATLAB(1, plhs, " < < arguments . size ( ) < < " , prhs, " < < R " ( " ) "
< < datatree . symbol_table . getName ( second_deriv_symb_id ) < < R " ( " ) ; ) " << endl
< < " TEFDD_def_ " < < indx < < " = mxGetPr(plhs[0]); " < < endl
< < " } " < < endl ;
2010-10-05 18:48:15 +02:00
}
else
2010-02-22 17:33:38 +01:00
{
2018-10-02 18:10:12 +02:00
if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-03-04 16:40:07 +01:00
output < < " TEFDD_fdd_ " < < getIndxInTefTerms ( symb_id , tef_terms ) < < " _ " < < inputIndex1 < < " _ " < < inputIndex2
2010-10-07 14:15:56 +02:00
< < " = hess_element(' " < < datatree . symbol_table . getName ( symb_id ) < < " ', "
2010-03-04 16:40:07 +01:00
< < inputIndex1 < < " , " < < inputIndex2 < < " ,{ " ;
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { second_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2010-03-04 16:40:07 +01:00
output < < " TEFDD_def_ " < < getIndxInTefTerms ( second_deriv_symb_id , tef_terms )
< < " = " < < datatree . symbol_table . getName ( second_deriv_symb_id ) < < " ( " ;
}
2018-03-27 17:14:30 +02:00
writeExternalFunctionArguments ( output , output_type , temporary_terms , temporary_terms_idxs , tef_terms ) ;
2010-02-22 17:33:38 +01:00
2018-10-02 18:10:12 +02:00
if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2010-03-04 16:40:07 +01:00
output < < " } " ;
output < < " ); " < < endl ;
}
2010-02-22 17:33:38 +01:00
}
2014-03-11 17:33:46 +01:00
2017-02-20 12:18:11 +01:00
void
SecondDerivExternalFunctionNode : : writeJsonExternalFunctionOutput ( vector < string > & efout ,
const temporary_terms_t & temporary_terms ,
2017-10-16 17:24:55 +02:00
deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-02-20 12:18:11 +01:00
{
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
2018-10-02 18:10:12 +02:00
assert ( second_deriv_symb_id ! = ExternalFunctionsTable : : IDSetButNoNameProvided ) ;
2017-02-20 12:18:11 +01:00
/* For a node with derivs provided by the user function, call the method
on the non - derived node */
if ( second_deriv_symb_id = = symb_id )
{
expr_t parent = datatree . AddExternalFunction ( symb_id , arguments ) ;
2017-10-16 17:24:55 +02:00
parent - > writeJsonExternalFunctionOutput ( efout , temporary_terms , tef_terms , isdynamic ) ;
2017-02-20 12:18:11 +01:00
return ;
}
if ( alreadyWrittenAsTefTerm ( second_deriv_symb_id , tef_terms ) )
return ;
stringstream ef ;
2018-10-02 18:10:12 +02:00
if ( second_deriv_symb_id = = ExternalFunctionsTable : : IDNotSet )
2019-04-03 16:32:52 +02:00
ef < < R " ({ " second_deriv_external_function " : {) "
< < R " ( " external_function_term " : " TEFDD_fdd_ ) " << getIndxInTefTerms(symb_id, tef_terms) << " _ " << inputIndex1 << " _ " << inputIndex2 << R " ( " ) "
< < R " (, " analytic_derivative " : false) "
< < R " (, " wrt1 " : ) " < < inputIndex1
< < R " (, " wrt2 " : ) " < < inputIndex2
< < R " (, " value " : " ) " << datatree.symbol_table.getName(symb_id) << " ( " ;
2017-02-20 12:18:11 +01:00
else
{
2019-04-23 11:07:32 +02:00
tef_terms [ { second_deriv_symb_id , arguments } ] = static_cast < int > ( tef_terms . size ( ) ) ;
2019-04-03 16:32:52 +02:00
ef < < R " ({ " second_deriv_external_function " : {) "
< < R " ( " external_function_term " : " TEFDD_def_ ) " << getIndxInTefTerms(second_deriv_symb_id, tef_terms) << R " ( " ) "
< < R " (, " analytic_derivative " : true) "
< < R " (, " value " : " ) " << datatree.symbol_table.getName(second_deriv_symb_id) << " ( " ;
2017-02-20 12:18:11 +01:00
}
2017-10-16 17:24:55 +02:00
writeJsonExternalFunctionArguments ( ef , temporary_terms , tef_terms , isdynamic ) ;
2019-04-03 16:32:52 +02:00
ef < < R " lit() " } } ) lit " << endl;
2017-02-20 12:18:11 +01:00
efout . push_back ( ef . str ( ) ) ;
}
2014-03-11 17:33:46 +01:00
expr_t
2018-10-10 13:07:25 +02:00
SecondDerivExternalFunctionNode : : clone ( DataTree & datatree ) const
2014-03-11 17:33:46 +01:00
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
2018-10-10 13:07:25 +02:00
dynamic_arguments . push_back ( argument - > clone ( datatree ) ) ;
return datatree . AddSecondDerivExternalFunction ( symb_id , dynamic_arguments ,
inputIndex1 , inputIndex2 ) ;
2014-03-11 17:33:46 +01:00
}
2014-03-13 11:22:00 +01:00
expr_t
SecondDerivExternalFunctionNode : : buildSimilarExternalFunctionNode ( vector < expr_t > & alt_args , DataTree & alt_datatree ) const
{
return alt_datatree . AddSecondDerivExternalFunction ( symb_id , alt_args , inputIndex1 , inputIndex2 ) ;
}
expr_t
SecondDerivExternalFunctionNode : : toStatic ( DataTree & static_datatree ) const
{
vector < expr_t > static_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
static_arguments . push_back ( argument - > toStatic ( static_datatree ) ) ;
2014-03-13 11:22:00 +01:00
return static_datatree . AddSecondDerivExternalFunction ( symb_id , static_arguments ,
inputIndex1 , inputIndex2 ) ;
}
2015-12-18 15:17:32 +01:00
void
SecondDerivExternalFunctionNode : : computeXrefs ( EquationInfo & ei ) const
{
vector < expr_t > dynamic_arguments ;
2018-06-04 12:26:16 +02:00
for ( auto argument : arguments )
argument - > computeXrefs ( ei ) ;
2015-12-18 15:17:32 +01:00
}
2014-03-13 11:22:00 +01:00
void
SecondDerivExternalFunctionNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2014-03-13 11:22:00 +01:00
{
cerr < < " SecondDerivExternalFunctionNode::compile: not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
void
SecondDerivExternalFunctionNode : : compileExternalFunctionOutput ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2014-03-13 11:22:00 +01:00
deriv_node_temp_terms_t & tef_terms ) const
{
cerr < < " SecondDerivExternalFunctionNode::compileExternalFunctionOutput: not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2016-11-18 16:52:13 +01:00
2018-05-29 17:07:18 +02:00
function < bool ( expr_t ) >
SecondDerivExternalFunctionNode : : sameTefTermPredicate ( ) const
{
int second_deriv_symb_id = datatree . external_functions_table . getSecondDerivSymbID ( symb_id ) ;
if ( second_deriv_symb_id = = symb_id )
return [ this ] ( expr_t e ) {
auto e2 = dynamic_cast < ExternalFunctionNode * > ( e ) ;
2019-12-16 19:42:59 +01:00
return ( e2 & & e2 - > symb_id = = symb_id ) ;
2018-05-29 17:07:18 +02:00
} ;
else
return [ this ] ( expr_t e ) {
auto e2 = dynamic_cast < SecondDerivExternalFunctionNode * > ( e ) ;
2019-12-16 19:42:59 +01:00
return ( e2 & & e2 - > symb_id = = symb_id ) ;
2018-05-29 17:07:18 +02:00
} ;
}
2016-11-18 16:52:13 +01:00
VarExpectationNode : : VarExpectationNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2018-08-01 19:41:44 +02:00
string model_name_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
2018-08-01 19:41:44 +02:00
model_name { move ( model_name_arg ) }
2016-11-18 16:52:13 +01:00
{
}
void
2018-11-30 12:22:13 +01:00
VarExpectationNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2016-11-18 16:52:13 +01:00
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::computeTemporaryTerms not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
void
2020-05-13 16:58:19 +02:00
VarExpectationNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2016-11-18 16:52:13 +01:00
{
2020-05-06 17:13:47 +02:00
cerr < < " VarExpectationNode::computeBlocksTemporaryTerms not implemented. " < < endl ;
2018-08-01 19:41:44 +02:00
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : toStatic ( DataTree & static_datatree ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::toStatic not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
2018-10-10 13:07:25 +02:00
VarExpectationNode : : clone ( DataTree & datatree ) const
2016-11-18 16:52:13 +01:00
{
2018-10-10 13:07:25 +02:00
return datatree . AddVarExpectation ( model_name ) ;
2016-11-18 16:52:13 +01:00
}
void
VarExpectationNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2016-11-18 16:52:13 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
2016-11-18 16:52:13 +01:00
2018-09-05 18:27:13 +02:00
if ( isLatexOutput ( output_type ) )
2016-11-18 16:52:13 +01:00
{
2018-08-01 19:41:44 +02:00
output < < " VAR_EXPECTATION( " < < model_name < < ' ) ' ;
2016-11-18 16:52:13 +01:00
return ;
}
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::writeOutput not implemented for non-LaTeX. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
int
VarExpectationNode : : maxEndoLead ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxEndoLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
int
VarExpectationNode : : maxExoLead ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxExoLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
int
VarExpectationNode : : maxEndoLag ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxEndoLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
int
VarExpectationNode : : maxExoLag ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxExoLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
int
VarExpectationNode : : maxLead ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
2018-02-28 17:33:00 +01:00
int
VarExpectationNode : : maxLag ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::maxLag not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-02-28 17:33:00 +01:00
}
2018-12-05 15:17:00 +01:00
int
VarExpectationNode : : maxLagWithDiffsExpanded ( ) const
{
2019-02-22 17:30:09 +01:00
/* This node will be substituted by lagged variables, so in theory we should
return a strictly positive value . But from here this value is not easy to
compute .
We return 0 , because currently this function is only called from
DynamicModel : : setLeadsLagsOrig ( ) , and the maximum lag will nevertheless be
correctly computed because the maximum lag of the VAR will be taken into
account via the corresponding equations . */
return 0 ;
2018-12-05 15:17:00 +01:00
}
2018-04-17 15:17:28 +02:00
expr_t
VarExpectationNode : : undiff ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::undiff not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-17 15:17:28 +02:00
}
2018-05-16 12:17:06 +02:00
int
VarExpectationNode : : VarMinLag ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::VarMinLag not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-05-16 12:17:06 +02:00
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
VarExpectationNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-04-16 13:50:31 +02:00
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::VarMaxLag not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2016-11-18 16:52:13 +01:00
expr_t
VarExpectationNode : : decreaseLeadsLags ( int n ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::decreaseLeadsLags not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
void
VarExpectationNode : : prepareForDerivation ( )
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::prepareForDerivation not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : computeDerivative ( int deriv_id )
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::computeDerivative not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
2020-10-02 18:31:55 +02:00
VarExpectationNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2016-11-18 16:52:13 +01:00
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::getChainRuleDerivative not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
bool
VarExpectationNode : : containsExternalFunction ( ) const
{
return false ;
}
double
2018-06-04 12:50:53 +02:00
VarExpectationNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2016-11-18 16:52:13 +01:00
{
2018-08-01 19:41:44 +02:00
throw EvalException ( ) ;
2016-11-18 16:52:13 +01:00
}
2018-05-31 15:34:25 +02:00
int
VarExpectationNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::countDiffs not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-02-08 13:07:15 +01:00
}
2016-11-18 16:52:13 +01:00
void
VarExpectationNode : : computeXrefs ( EquationInfo & ei ) const
{
}
2018-04-16 13:50:31 +02:00
void
VarExpectationNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2016-11-18 16:52:13 +01:00
void
2018-06-04 14:17:36 +02:00
VarExpectationNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2016-11-18 16:52:13 +01:00
{
}
void
VarExpectationNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2016-11-18 16:52:13 +01:00
{
cerr < < " VarExpectationNode::compile not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2020-04-02 14:36:26 +02:00
void
VarExpectationNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
2016-11-18 16:52:13 +01:00
{
2020-04-02 14:36:26 +02:00
}
BinaryOpNode *
VarExpectationNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
throw NormalizationFailed ( ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::substituteEndoLeadGreaterThanTwo not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::substituteEndoLagGreaterThanTwo not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::substituteExoLead not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::substituteExoLag not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2017-06-12 14:56:44 +02:00
expr_t
2018-01-30 10:06:56 +01:00
VarExpectationNode : : substituteAdl ( ) const
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
VarExpectationNode : : substituteModelLocalVariables ( ) const
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
VarExpectationNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
auto it = subst_table . find ( model_name ) ;
if ( it = = subst_table . end ( ) )
{
cerr < < " ERROR: unknown model ' " < < model_name < < " ' used in var_expectation expression " < < endl ;
exit ( EXIT_FAILURE ) ;
}
return it - > second ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
VarExpectationNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
VarExpectationNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
VarExpectationNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
return - 1 ;
}
2018-01-30 10:06:56 +01:00
expr_t
2019-10-22 14:56:28 +02:00
VarExpectationNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2017-06-12 14:56:44 +02:00
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2018-05-30 16:48:08 +02:00
expr_t
2019-10-22 14:56:28 +02:00
VarExpectationNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2018-01-30 16:33:16 +01:00
expr_t
2019-12-20 16:59:30 +01:00
VarExpectationNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-01-30 16:33:16 +01:00
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2016-11-18 16:52:13 +01:00
expr_t
VarExpectationNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::differentiateForwardVars not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
VarExpectationNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
return false ;
}
2016-11-18 16:52:13 +01:00
bool
VarExpectationNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
expr_t
VarExpectationNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::decreaseLeadsLagsPredeterminedVariables not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
bool
VarExpectationNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
expr_t
VarExpectationNode : : replaceTrendVar ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::replaceTrendVar not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
VarExpectationNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::detrend not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
expr_t
2019-07-05 18:22:02 +02:00
VarExpectationNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2016-11-18 16:52:13 +01:00
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::removeTrendLeadLag not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
bool
VarExpectationNode : : isInStaticForm ( ) const
{
2018-08-01 19:41:44 +02:00
cerr < < " VarExpectationNode::isInStaticForm not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
2016-11-18 16:52:13 +01:00
}
2016-11-25 17:15:13 +01:00
bool
VarExpectationNode : : isVarModelReferenced ( const string & model_info_name ) const
{
2018-08-01 19:41:44 +02:00
/* TODO: should check here whether the var_expectation_model is equal to the
argument ; we probably need a VarModelTable class to do that elegantly */
return false ;
2016-11-25 17:15:13 +01:00
}
void
VarExpectationNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
}
2018-08-09 16:14:40 +02:00
bool
VarExpectationNode : : isParamTimesEndogExpr ( ) const
{
return false ;
}
2016-11-18 16:52:13 +01:00
expr_t
VarExpectationNode : : substituteStaticAuxiliaryVariable ( ) const
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2017-06-19 18:02:57 +02:00
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
VarExpectationNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
return const_cast < VarExpectationNode * > ( this ) ;
}
2018-09-18 14:50:31 +02:00
void
VarExpectationNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " VarExpectationNode " , ) "
< < R " ( " name " : " ) " << model_name << R " ( " }) " ;
2018-09-18 14:50:31 +02:00
}
2017-06-19 18:02:57 +02:00
void
VarExpectationNode : : writeJsonOutput ( ostream & output ,
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2017-06-19 18:02:57 +02:00
{
2019-03-15 16:12:54 +01:00
output < < " var_expectation( "
< < " model_name = " < < model_name
< < " ) " ;
2017-06-19 18:02:57 +02:00
}
2018-01-30 16:33:16 +01:00
PacExpectationNode : : PacExpectationNode ( DataTree & datatree_arg ,
2018-09-05 16:41:33 +02:00
int idx_arg ,
2018-06-04 12:31:07 +02:00
string model_name_arg ) :
2018-10-04 17:18:27 +02:00
ExprNode { datatree_arg , idx_arg } ,
model_name { move ( model_name_arg ) }
2018-01-30 16:33:16 +01:00
{
}
void
2018-11-30 12:22:13 +01:00
PacExpectationNode : : computeTemporaryTerms ( const pair < int , int > & derivOrder ,
map < pair < int , int > , temporary_terms_t > & temp_terms_map ,
map < expr_t , pair < int , pair < int , int > > > & reference_count ,
bool is_matlab ) const
2018-01-30 16:33:16 +01:00
{
2018-11-30 12:22:13 +01:00
temp_terms_map [ derivOrder ] . insert ( const_cast < PacExpectationNode * > ( this ) ) ;
2018-01-30 16:33:16 +01:00
}
void
2020-05-13 16:58:19 +02:00
PacExpectationNode : : computeBlockTemporaryTerms ( int blk , int eq , vector < vector < temporary_terms_t > > & blocks_temporary_terms ,
map < expr_t , tuple < int , int , int > > & reference_count ) const
2018-01-30 16:33:16 +01:00
{
2020-05-13 16:58:19 +02:00
blocks_temporary_terms [ blk ] [ eq ] . insert ( const_cast < PacExpectationNode * > ( this ) ) ;
2018-01-30 16:33:16 +01:00
}
expr_t
PacExpectationNode : : toStatic ( DataTree & static_datatree ) const
{
2018-03-28 18:46:15 +02:00
return static_datatree . AddPacExpectation ( string ( model_name ) ) ;
2018-01-30 16:33:16 +01:00
}
expr_t
2018-10-10 13:07:25 +02:00
PacExpectationNode : : clone ( DataTree & datatree ) const
2018-01-30 16:33:16 +01:00
{
2018-10-10 13:07:25 +02:00
return datatree . AddPacExpectation ( string ( model_name ) ) ;
2018-01-30 16:33:16 +01:00
}
void
PacExpectationNode : : writeOutput ( ostream & output , ExprNodeOutputType output_type ,
const temporary_terms_t & temporary_terms ,
2018-03-27 17:14:30 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2018-01-30 16:33:16 +01:00
{
2018-09-05 18:27:13 +02:00
assert ( output_type ! = ExprNodeOutputType : : matlabOutsideModel ) ;
if ( isLatexOutput ( output_type ) )
2018-01-30 16:33:16 +01:00
{
2018-03-28 18:46:15 +02:00
output < < " PAC_EXPECTATION " < < LEFT_PAR ( output_type ) < < model_name < < RIGHT_PAR ( output_type ) ;
2018-01-30 16:33:16 +01:00
return ;
}
}
int
PacExpectationNode : : maxEndoLead ( ) const
{
return 0 ;
}
int
PacExpectationNode : : maxExoLead ( ) const
{
return 0 ;
}
int
PacExpectationNode : : maxEndoLag ( ) const
{
return 0 ;
}
int
PacExpectationNode : : maxExoLag ( ) const
{
return 0 ;
}
int
PacExpectationNode : : maxLead ( ) const
{
return 0 ;
}
2018-02-28 17:33:00 +01:00
int
PacExpectationNode : : maxLag ( ) const
{
return 0 ;
}
2018-12-05 15:17:00 +01:00
int
PacExpectationNode : : maxLagWithDiffsExpanded ( ) const
{
2019-02-22 17:30:09 +01:00
// Same comment as in VarExpectationNode::maxLagWithDiffsExpanded()
2018-12-05 15:17:00 +01:00
return 0 ;
}
2018-04-17 15:17:28 +02:00
expr_t
PacExpectationNode : : undiff ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2018-05-16 12:17:06 +02:00
int
PacExpectationNode : : VarMinLag ( ) const
{
return 1 ;
}
2018-06-11 10:40:00 +02:00
int
2019-10-22 16:04:24 +02:00
PacExpectationNode : : VarMaxLag ( const set < expr_t > & lhs_lag_equiv ) const
2018-03-28 18:46:15 +02:00
{
return 0 ;
}
2018-01-30 16:33:16 +01:00
expr_t
PacExpectationNode : : decreaseLeadsLags ( int n ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
void
PacExpectationNode : : prepareForDerivation ( )
{
cerr < < " PacExpectationNode::prepareForDerivation: shouldn't arrive here. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
expr_t
PacExpectationNode : : computeDerivative ( int deriv_id )
{
cerr < < " PacExpectationNode::computeDerivative: shouldn't arrive here. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
expr_t
2020-10-02 18:31:55 +02:00
PacExpectationNode : : getChainRuleDerivative ( int deriv_id , const map < int , BinaryOpNode * > & recursive_variables )
2018-01-30 16:33:16 +01:00
{
cerr < < " PacExpectationNode::getChainRuleDerivative: shouldn't arrive here. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
bool
PacExpectationNode : : containsExternalFunction ( ) const
{
return false ;
}
double
2018-06-04 12:50:53 +02:00
PacExpectationNode : : eval ( const eval_context_t & eval_context ) const noexcept ( false )
2018-01-30 16:33:16 +01:00
{
2018-02-09 17:24:21 +01:00
throw EvalException ( ) ;
2018-01-30 16:33:16 +01:00
}
void
PacExpectationNode : : computeXrefs ( EquationInfo & ei ) const
{
}
2018-04-16 13:50:31 +02:00
void
PacExpectationNode : : collectVARLHSVariable ( set < expr_t > & result ) const
{
2018-05-31 15:34:25 +02:00
cerr < < " ERROR: you can only have variables or unary ops on LHS of VAR " < < endl ;
exit ( EXIT_FAILURE ) ;
2018-04-16 13:50:31 +02:00
}
2018-01-30 16:33:16 +01:00
void
2018-06-04 14:17:36 +02:00
PacExpectationNode : : collectDynamicVariables ( SymbolType type_arg , set < pair < int , int > > & result ) const
2018-01-30 16:33:16 +01:00
{
}
void
PacExpectationNode : : compile ( ostream & CompileCode , unsigned int & instruction_number ,
2020-05-13 12:53:47 +02:00
bool lhs_rhs , const temporary_terms_t & temporary_terms ,
2020-05-06 17:13:47 +02:00
const temporary_terms_idxs_t & temporary_terms_idxs , bool dynamic , bool steady_dynamic ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ) const
2018-01-30 16:33:16 +01:00
{
cerr < < " PacExpectationNode::compile not implemented. " < < endl ;
exit ( EXIT_FAILURE ) ;
}
2018-05-31 15:34:25 +02:00
int
PacExpectationNode : : countDiffs ( ) const
2018-02-08 13:07:15 +01:00
{
2018-05-31 15:34:25 +02:00
return 0 ;
2018-02-08 13:07:15 +01:00
}
2020-04-02 14:36:26 +02:00
void
PacExpectationNode : : computeSubExprContainingVariable ( int symb_id , int lag , set < expr_t > & contain_var ) const
2018-01-30 16:33:16 +01:00
{
2020-04-02 14:36:26 +02:00
}
BinaryOpNode *
PacExpectationNode : : normalizeEquationHelper ( const set < expr_t > & contain_var , expr_t rhs ) const
{
throw NormalizationFailed ( ) ;
2018-01-30 16:33:16 +01:00
}
expr_t
PacExpectationNode : : substituteEndoLeadGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : substituteEndoLagGreaterThanTwo ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : substituteExoLead ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool deterministic_model ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : substituteExoLag ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : substituteExpectation ( subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs , bool partial_information_model ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : substituteAdl ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2020-11-10 18:04:05 +01:00
expr_t
PacExpectationNode : : substituteModelLocalVariables ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2018-08-01 19:41:44 +02:00
expr_t
PacExpectationNode : : substituteVarExpectation ( const map < string , expr_t > & subst_table ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2018-03-02 12:32:01 +01:00
void
2019-10-22 14:56:28 +02:00
PacExpectationNode : : findDiffNodes ( lag_equivalence_table_t & nodes ) const
2018-03-02 12:32:01 +01:00
{
}
2018-05-30 16:48:08 +02:00
void
2019-10-22 14:56:28 +02:00
PacExpectationNode : : findUnaryOpNodesForAuxVarCreation ( lag_equivalence_table_t & nodes ) const
2018-05-30 16:48:08 +02:00
{
}
2018-08-31 12:35:51 +02:00
int
2018-09-13 12:21:23 +02:00
PacExpectationNode : : findTargetVariable ( int lhs_symb_id ) const
2018-08-31 12:35:51 +02:00
{
return - 1 ;
}
2018-01-30 16:33:16 +01:00
expr_t
2019-10-22 14:56:28 +02:00
PacExpectationNode : : substituteDiff ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table ,
2018-04-17 15:17:28 +02:00
vector < BinaryOpNode * > & neweqs ) const
2018-05-30 16:48:08 +02:00
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
2019-10-22 14:56:28 +02:00
PacExpectationNode : : substituteUnaryOpNodes ( const lag_equivalence_table_t & nodes , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
2018-01-30 16:33:16 +01:00
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : differentiateForwardVars ( const vector < string > & subset , subst_table_t & subst_table , vector < BinaryOpNode * > & neweqs ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2018-06-05 18:38:53 +02:00
bool
2018-08-13 12:12:20 +02:00
PacExpectationNode : : containsPacExpectation ( const string & pac_model_name ) const
2018-06-05 18:38:53 +02:00
{
2018-08-13 12:12:20 +02:00
if ( pac_model_name . empty ( ) )
return true ;
else
return pac_model_name = = model_name ;
2018-06-05 18:38:53 +02:00
}
2018-01-30 16:33:16 +01:00
bool
PacExpectationNode : : isNumConstNodeEqualTo ( double value ) const
{
return false ;
}
expr_t
PacExpectationNode : : decreaseLeadsLagsPredeterminedVariables ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
bool
PacExpectationNode : : isVariableNodeEqualTo ( SymbolType type_arg , int variable_id , int lag_arg ) const
{
return false ;
}
expr_t
PacExpectationNode : : replaceTrendVar ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
PacExpectationNode : : detrend ( int symb_id , bool log_trend , expr_t trend ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
expr_t
2019-07-05 18:22:02 +02:00
PacExpectationNode : : removeTrendLeadLag ( const map < int , expr_t > & trend_symbols_map ) const
2018-01-30 16:33:16 +01:00
{
return const_cast < PacExpectationNode * > ( this ) ;
}
bool
PacExpectationNode : : isInStaticForm ( ) const
{
return false ;
}
bool
PacExpectationNode : : isVarModelReferenced ( const string & model_info_name ) const
{
return model_name = = model_info_name ;
}
void
PacExpectationNode : : getEndosAndMaxLags ( map < string , int > & model_endos_and_lags ) const
{
}
expr_t
PacExpectationNode : : substituteStaticAuxiliaryVariable ( ) const
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2019-01-28 14:57:30 +01:00
expr_t
2019-01-29 17:29:24 +01:00
PacExpectationNode : : replaceVarsInEquation ( map < VariableNode * , NumConstNode * > & table ) const
2019-01-28 14:57:30 +01:00
{
return const_cast < PacExpectationNode * > ( this ) ;
}
2018-09-18 14:50:31 +02:00
void
PacExpectationNode : : writeJsonAST ( ostream & output ) const
{
2019-04-03 16:32:52 +02:00
output < < R " ({ " node_type " : " PacExpectationNode " , ) "
< < R " ( " name " : " ) " << model_name << R " ( " }) " ;
2018-09-18 14:50:31 +02:00
}
2018-01-30 16:33:16 +01:00
void
PacExpectationNode : : writeJsonOutput ( ostream & output ,
const temporary_terms_t & temporary_terms ,
2018-05-29 11:59:42 +02:00
const deriv_node_temp_terms_t & tef_terms ,
2019-12-16 19:42:59 +01:00
bool isdynamic ) const
2018-01-30 16:33:16 +01:00
{
2019-03-15 16:11:55 +01:00
output < < " pac_expectation( "
< < " model_name = " < < model_name
< < " ) " ;
2018-01-30 16:33:16 +01:00
}
2018-08-09 16:14:40 +02:00
bool
PacExpectationNode : : isParamTimesEndogExpr ( ) const
{
return false ;
}
2018-02-07 13:49:57 +01:00
expr_t
2019-12-20 16:59:30 +01:00
PacExpectationNode : : substitutePacExpectation ( const string & name , expr_t subexpr )
2018-02-07 13:49:57 +01:00
{
2019-02-15 12:52:46 +01:00
if ( model_name ! = name )
return const_cast < PacExpectationNode * > ( this ) ;
2019-02-20 12:59:55 +01:00
return subexpr ;
2019-02-15 12:52:46 +01:00
}
2018-11-27 18:53:28 +01:00
void
ExprNode : : decomposeAdditiveTerms ( vector < pair < expr_t , int > > & terms , int current_sign ) const
{
terms . emplace_back ( const_cast < ExprNode * > ( this ) , current_sign ) ;
}
void
UnaryOpNode : : decomposeAdditiveTerms ( vector < pair < expr_t , int > > & terms , int current_sign ) const
{
if ( op_code = = UnaryOpcode : : uminus )
arg - > decomposeAdditiveTerms ( terms , - current_sign ) ;
else
ExprNode : : decomposeAdditiveTerms ( terms , current_sign ) ;
}
void
BinaryOpNode : : decomposeAdditiveTerms ( vector < pair < expr_t , int > > & terms , int current_sign ) const
{
if ( op_code = = BinaryOpcode : : plus | | op_code = = BinaryOpcode : : minus )
{
arg1 - > decomposeAdditiveTerms ( terms , current_sign ) ;
if ( op_code = = BinaryOpcode : : plus )
arg2 - > decomposeAdditiveTerms ( terms , current_sign ) ;
else
arg2 - > decomposeAdditiveTerms ( terms , - current_sign ) ;
}
else
ExprNode : : decomposeAdditiveTerms ( terms , current_sign ) ;
}
2020-10-19 18:26:36 +02:00
void
ExprNode : : decomposeMultiplicativeFactors ( vector < pair < expr_t , int > > & factors , int current_exponent ) const
{
factors . emplace_back ( const_cast < ExprNode * > ( this ) , current_exponent ) ;
}
void
BinaryOpNode : : decomposeMultiplicativeFactors ( vector < pair < expr_t , int > > & factors , int current_exponent ) const
{
if ( op_code = = BinaryOpcode : : times | | op_code = = BinaryOpcode : : divide )
{
arg1 - > decomposeMultiplicativeFactors ( factors , current_exponent ) ;
if ( op_code = = BinaryOpcode : : times )
arg2 - > decomposeMultiplicativeFactors ( factors , current_exponent ) ;
else
arg2 - > decomposeMultiplicativeFactors ( factors , - current_exponent ) ;
}
else
ExprNode : : decomposeMultiplicativeFactors ( factors , current_exponent ) ;
}
2018-11-27 18:53:28 +01:00
tuple < int , int , int , double >
2019-10-03 16:05:38 +02:00
ExprNode : : matchVariableTimesConstantTimesParam ( bool variable_obligatory ) const
2018-11-27 18:53:28 +01:00
{
int variable_id = - 1 , lag = 0 , param_id = - 1 ;
double constant = 1.0 ;
matchVTCTPHelper ( variable_id , lag , param_id , constant , false ) ;
2019-10-03 16:05:38 +02:00
if ( variable_obligatory & & variable_id = = - 1 )
2018-11-27 18:53:28 +01:00
throw MatchFailureException { " No variable in this expression " } ;
2019-02-21 10:30:25 +01:00
return { variable_id , lag , param_id , constant } ;
2018-11-27 18:53:28 +01:00
}
void
ExprNode : : matchVTCTPHelper ( int & var_id , int & lag , int & param_id , double & constant , bool at_denominator ) const
{
throw MatchFailureException { " Expression not allowed in linear combination of variables " } ;
}
void
NumConstNode : : matchVTCTPHelper ( int & var_id , int & lag , int & param_id , double & constant , bool at_denominator ) const
{
double myvalue = eval ( { } ) ;
if ( at_denominator )
constant / = myvalue ;
else
constant * = myvalue ;
}
void
VariableNode : : matchVTCTPHelper ( int & var_id , int & lag , int & param_id , double & constant , bool at_denominator ) const
{
if ( at_denominator )
throw MatchFailureException { " A variable or parameter cannot appear at denominator " } ;
SymbolType type = get_type ( ) ;
if ( type = = SymbolType : : endogenous | | type = = SymbolType : : exogenous )
{
if ( var_id ! = - 1 )
throw MatchFailureException { " More than one variable in this expression " } ;
var_id = symb_id ;
lag = this - > lag ;
}
else if ( type = = SymbolType : : parameter )
{
if ( param_id ! = - 1 )
throw MatchFailureException { " More than one parameter in this expression " } ;
param_id = symb_id ;
}
else
throw MatchFailureException { " Symbol " + datatree . symbol_table . getName ( symb_id ) + " not allowed here " } ;
}
void
UnaryOpNode : : matchVTCTPHelper ( int & var_id , int & lag , int & param_id , double & constant , bool at_denominator ) const
{
if ( op_code = = UnaryOpcode : : uminus )
{
constant = - constant ;
arg - > matchVTCTPHelper ( var_id , lag , param_id , constant , at_denominator ) ;
}
else
throw MatchFailureException { " Operator not allowed in this expression " } ;
}
void
BinaryOpNode : : matchVTCTPHelper ( int & var_id , int & lag , int & param_id , double & constant , bool at_denominator ) const
{
if ( op_code = = BinaryOpcode : : times | | op_code = = BinaryOpcode : : divide )
{
arg1 - > matchVTCTPHelper ( var_id , lag , param_id , constant , at_denominator ) ;
if ( op_code = = BinaryOpcode : : times )
arg2 - > matchVTCTPHelper ( var_id , lag , param_id , constant , at_denominator ) ;
else
arg2 - > matchVTCTPHelper ( var_id , lag , param_id , constant , ! at_denominator ) ;
}
else
throw MatchFailureException { " Operator not allowed in this expression " } ;
}
vector < tuple < int , int , int , double > >
2019-10-03 16:05:38 +02:00
ExprNode : : matchLinearCombinationOfVariables ( bool variable_obligatory_in_each_term ) const
2018-11-27 18:53:28 +01:00
{
vector < pair < expr_t , int > > terms ;
decomposeAdditiveTerms ( terms ) ;
vector < tuple < int , int , int , double > > result ;
for ( const auto & it : terms )
2018-11-28 17:32:55 +01:00
{
expr_t term = it . first ;
int sign = it . second ;
2019-10-03 16:05:38 +02:00
auto m = term - > matchVariableTimesConstantTimesParam ( variable_obligatory_in_each_term ) ;
2018-11-28 17:32:55 +01:00
get < 3 > ( m ) * = sign ;
result . push_back ( m ) ;
}
return result ;
2018-11-27 18:53:28 +01:00
}
2019-03-21 18:13:34 +01:00
pair < int , vector < tuple < int , int , int , double > > >
ExprNode : : matchParamTimesLinearCombinationOfVariables ( ) const
{
auto bopn = dynamic_cast < const BinaryOpNode * > ( this ) ;
if ( ! bopn | | bopn - > op_code ! = BinaryOpcode : : times )
throw MatchFailureException { " Not a multiplicative expression " } ;
expr_t param = bopn - > arg1 , lincomb = bopn - > arg2 ;
auto is_param = [ ] ( expr_t e ) {
2019-12-20 16:59:30 +01:00
auto vn = dynamic_cast < VariableNode * > ( e ) ;
return vn & & vn - > get_type ( ) = = SymbolType : : parameter ;
} ;
2019-03-21 18:13:34 +01:00
if ( ! is_param ( param ) )
{
swap ( param , lincomb ) ;
if ( ! is_param ( param ) )
throw MatchFailureException { " No parameter on either side of the multiplication " } ;
}
return { dynamic_cast < VariableNode * > ( param ) - > symb_id , lincomb - > matchLinearCombinationOfVariables ( ) } ;
}
2020-07-23 14:45:32 +02:00
pair < int , int >
ExprNode : : matchParamTimesTargetMinusVariable ( int symb_id ) const
{
auto bopn = dynamic_cast < const BinaryOpNode * > ( this ) ;
if ( ! bopn | | bopn - > op_code ! = BinaryOpcode : : times )
throw MatchFailureException { " Not a multiplicative expression " } ;
expr_t param = bopn - > arg1 , minus = bopn - > arg2 ;
auto is_param = [ ] ( expr_t e ) {
auto vn = dynamic_cast < VariableNode * > ( e ) ;
return vn & & vn - > get_type ( ) = = SymbolType : : parameter ;
} ;
if ( ! is_param ( param ) )
{
swap ( param , minus ) ;
if ( ! is_param ( param ) )
throw MatchFailureException { " No parameter on either side of the multiplication " } ;
}
auto bminus = dynamic_cast < const BinaryOpNode * > ( minus ) ;
if ( ! bminus | | bminus - > op_code ! = BinaryOpcode : : minus )
throw MatchFailureException { " Neither factor is a minus operator " } ;
auto lhs_level = dynamic_cast < const VariableNode * > ( bminus - > arg2 ) ;
auto target = dynamic_cast < const VariableNode * > ( bminus - > arg1 ) ;
2020-07-24 12:28:13 +02:00
auto check_target = [ & ] ( )
{
if ( target - > get_type ( ) ! = SymbolType : : endogenous
& & target - > get_type ( ) ! = SymbolType : : exogenous )
return false ;
if ( datatree . symbol_table . isAuxiliaryVariable ( target - > symb_id ) )
{
auto avi = datatree . symbol_table . getAuxVarInfo ( target - > symb_id ) ;
return ( avi . get_type ( ) = = AuxVarType : : unaryOp
& & avi . get_unary_op ( ) = = " log "
& & avi . get_orig_symb_id ( ) ! = - 1
& & ! datatree . symbol_table . isAuxiliaryVariable ( avi . get_orig_symb_id ( ) )
& & target - > lag + avi . get_orig_lead_lag ( ) = = - 1 ) ;
}
else
return target - > lag = = - 1 ;
} ;
if ( lhs_level & & lhs_level - > symb_id = = symb_id & & target & & check_target ( ) )
2020-07-23 14:45:32 +02:00
return { dynamic_cast < VariableNode * > ( param ) - > symb_id , target - > symb_id } ;
else
2020-07-24 12:28:13 +02:00
throw MatchFailureException { " Neither factor is of the form (target-variable) where target is endo or exo (possibly logged), and has one lag " } ;
2020-07-23 14:45:32 +02:00
}