finishing implementation of optional transformation of log and non

integer power arguments   to insure that they are positive
issue#70
Michel Juillard 2012-05-26 20:53:48 +02:00
parent 73b4052f2b
commit 78bd465294
2 changed files with 170 additions and 31 deletions

View File

@ -382,6 +382,12 @@ NumConstNode::maxExoLag() const
return 0;
}
int
NumConstNode::maxLead() const
{
return 0;
}
expr_t
NumConstNode::decreaseLeadsLags(int n) const
{
@ -445,6 +451,12 @@ NumConstNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
bool
NumConstNode::containsEndogenous(void) const
{
return false;
}
expr_t
NumConstNode::replaceTrendVar() const
{
@ -1007,6 +1019,22 @@ VariableNode::maxExoLag() const
}
}
int
VariableNode::maxLead() const
{
switch (type)
{
case eEndogenous:
return lag;
case eExogenous:
return lag;
case eModelLocalVariable:
return datatree.local_variables_table[symb_id]->maxLead();
default:
return 0;
}
}
expr_t
VariableNode::decreaseLeadsLags(int n) const
{
@ -1206,6 +1234,15 @@ VariableNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
bool
VariableNode::containsEndogenous(void) const
{
if (type == eEndogenous)
return true;
else
return false;
}
expr_t
VariableNode::replaceTrendVar() const
{
@ -2109,6 +2146,12 @@ UnaryOpNode::maxExoLag() const
return arg->maxExoLag();
}
int
UnaryOpNode::maxLead() const
{
return arg->maxLead();
}
expr_t
UnaryOpNode::decreaseLeadsLags(int n) const
{
@ -2215,23 +2258,30 @@ UnaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpNo
expr_t
UnaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const
{
if (op_code==oLog)
if (op_code==oLog && this->containsEndogenous() )
{
subst_table_t::iterator it = subst_table.find(const_cast<UnaryOpNode *>(this));
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second);
//take care of any nested log expressions by calling arg->substituteLogPow(.), then decreaseLeadsLags for this oExpectation operator
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t substexpr = arg->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(substexpr != NULL);
int k = substexpr->maxLead();
if (k)
substexpr = substexpr->decreaseLeadsLags(k);
it = subst_table.find(substexpr);
if (it != subst_table.end())
return (it->second)->decreaseLeadsLags(-k);
//Arriving here, we need to create an auxiliary variable for the argument of the log expression:
//AUX_LOG_(arg.idx)
int symb_id = datatree.symbol_table.addLogAuxiliaryVar(arg->idx);
expr_t newAuxE = datatree.AddVariable(symb_id, 0);
assert(dynamic_cast<VariableNode *>(newAuxE) != NULL);
subst_table[this] = dynamic_cast<VariableNode *>(newAuxE);
subst_table[substexpr] = dynamic_cast<VariableNode *>(newAuxE);
//take care of any nested log expressions by calling arg->substituteLogPow(.), then decreaseLeadsLags for this oExpectation operator
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t substexpr = arg->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(substexpr != NULL);
// auxiliary equation with the exponential of the auxiliary variable
expr_t lhs = datatree.AddExp(newAuxE);
neweqs1.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(lhs, substexpr)));
@ -2239,25 +2289,40 @@ UnaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *>
expr_t definition = datatree.AddLog(substexpr);
neweqs2.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(newAuxE,definition)));
return newAuxE;
return newAuxE->decreaseLeadsLags(-k);
}
else if (op_code==oSqrt)
else if (op_code==oSqrt && this->containsEndogenous() )
{
subst_table_t::iterator it = subst_table.find(const_cast<UnaryOpNode *>(this));
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second);
{
// expression to be used instead of sqrt
expr_t constant = datatree.AddNonNegativeConstant("0.5");
return datatree.AddExp(datatree.AddTimes(constant,const_cast<VariableNode *>(it->second)));
}
//take care of any nested log expressions by calling arg->substituteLogPow(.), then decreaseLeadsLags for this oExpectation operator
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t substexpr = arg->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(substexpr != NULL);
int k = substexpr->maxLead();
if (k)
substexpr = substexpr->decreaseLeadsLags(k);
it = subst_table.find(substexpr);
if (it != subst_table.end())
{
// expression to be used instead of sqrt
expr_t constant = datatree.AddNonNegativeConstant("0.5");
return datatree.AddExp(datatree.AddTimes(constant,(it->second)->decreaseLeadsLags(-k)));
}
//Arriving here, we need to create an auxiliary variable for the argument of the log expression:
//AUX_LOG_(arg.idx)
int symb_id = datatree.symbol_table.addPowAuxiliaryVar(arg->idx);
expr_t newAuxE = datatree.AddVariable(symb_id, 0);
assert(dynamic_cast<VariableNode *>(newAuxE) != NULL);
subst_table[this] = dynamic_cast<VariableNode *>(newAuxE);
subst_table[substexpr] = dynamic_cast<VariableNode *>(newAuxE);
//take care of any nested log expressions by calling arg->substituteLogPow(.), then decreaseLeadsLags for this oExpectation operator
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t substexpr = arg->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(substexpr != NULL);
// auxiliary equation with the exponential of the auxiliary variable
expr_t lhs = datatree.AddExp(newAuxE);
neweqs1.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(lhs, substexpr)));
@ -2267,9 +2332,7 @@ UnaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *>
// expression to be used instead of sqrt
expr_t constant = datatree.AddNonNegativeConstant("0.5");
newAuxE = datatree.AddTimes(constant,newAuxE);
newAuxE = datatree.AddExp(newAuxE);
return newAuxE;
return datatree.AddExp(datatree.AddTimes(constant,newAuxE->decreaseLeadsLags(-k)));
}
else
{
@ -2290,6 +2353,12 @@ UnaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag
return false;
}
bool
UnaryOpNode::containsEndogenous(void) const
{
return arg->containsEndogenous();
}
expr_t
UnaryOpNode::replaceTrendVar() const
{
@ -3363,6 +3432,12 @@ BinaryOpNode::maxExoLag() const
return max(arg1->maxExoLag(), arg2->maxExoLag());
}
int
BinaryOpNode::maxLead() const
{
return max(arg1->maxLead(), arg2->maxLead());
}
expr_t
BinaryOpNode::decreaseLeadsLags(int n) const
{
@ -3494,7 +3569,7 @@ BinaryOpNode::substituteExpectation(subst_table_t &subst_table, vector<BinaryOpN
expr_t
BinaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const
{
if (op_code==oPower)
if (op_code==oPower && this->containsEndogenous() )
{
NumConstNode *arg2_node = dynamic_cast<NumConstNode *>(arg2);
if (arg2_node != NULL)
@ -3511,21 +3586,30 @@ BinaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *
}
subst_table_t::iterator it = subst_table.find(const_cast<BinaryOpNode *>(this));
if (it != subst_table.end())
return const_cast<VariableNode *>(it->second);
return datatree.AddExp(datatree.AddTimes(arg2,const_cast<VariableNode *>(it->second)));
//Arriving here, we need to create an auxiliary variable for the argument of the log expression:
//AUX_LOG_(arg.idx)
int symb_id = datatree.symbol_table.addPowAuxiliaryVar(arg1->idx);
expr_t newAuxE = datatree.AddVariable(symb_id, 0);
assert(dynamic_cast<VariableNode *>(newAuxE) != NULL);
subst_table[this] = dynamic_cast<VariableNode *>(newAuxE);
//take care of any nested pow expressions by calling arg->substituteLogPow(.), then decreaseLeadsLags for this oExpectation operator
//take care of any nested pow expressions by calling arg->substituteLogPow(.),
//arg(lag-period) (holds entire subtree of arg(lag-period)
expr_t arg1substexpr = arg1->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(arg1substexpr != NULL);
expr_t arg2substexpr = arg2->substituteLogPow(subst_table, neweqs1, neweqs2);
assert(arg2substexpr != NULL);
// look for identical expression at the current period
int k = arg1substexpr->maxLead();
if (k)
arg1substexpr = arg1substexpr->decreaseLeadsLags(k);
it = subst_table.find(arg1substexpr);
// if it exists return it with the appropriate lead/lag
if (it != subst_table.end())
return datatree.AddExp(datatree.AddTimes(arg2substexpr,(it->second)->decreaseLeadsLags(-k)));
// if not, create an auxiliary variable for the argument of the power expression:
//AUX_POW_(arg.idx)
int symb_id = datatree.symbol_table.addPowAuxiliaryVar(arg1->idx);
expr_t newAuxE = datatree.AddVariable(symb_id, 0);
assert(dynamic_cast<VariableNode *>(newAuxE) != NULL);
subst_table[arg1substexpr] = dynamic_cast<VariableNode *>(newAuxE);
// auxiliary equation with the exponential of the auxiliary variable
expr_t lhs = datatree.AddExp(newAuxE);
neweqs1.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(lhs, arg1substexpr)));
@ -3533,10 +3617,8 @@ BinaryOpNode::substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *
expr_t definition = datatree.AddLog(arg1substexpr);
neweqs2.push_back(dynamic_cast<BinaryOpNode *>(datatree.AddEqual(newAuxE,definition)));
// expression to be used instead of sqrt
newAuxE = datatree.AddTimes(arg2substexpr,newAuxE);
newAuxE = datatree.AddExp(newAuxE);
return newAuxE;
// expression to be used instead of power
return datatree.AddExp(datatree.AddTimes(arg2substexpr,newAuxE->decreaseLeadsLags(-k)));
}
else
{
@ -3566,6 +3648,12 @@ BinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int la
return false;
}
bool
BinaryOpNode::containsEndogenous(void) const
{
return (arg1->containsEndogenous() || arg2->containsEndogenous());
}
expr_t
BinaryOpNode::replaceTrendVar() const
{
@ -4059,6 +4147,12 @@ TrinaryOpNode::maxExoLag() const
return max(arg1->maxExoLag(), max(arg2->maxExoLag(), arg3->maxExoLag()));
}
int
TrinaryOpNode::maxLead() const
{
return max(arg1->maxLead(), max(arg2->maxLead(), arg3->maxLead()));
}
expr_t
TrinaryOpNode::decreaseLeadsLags(int n) const
{
@ -4157,6 +4251,12 @@ TrinaryOpNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int l
return false;
}
bool
TrinaryOpNode::containsEndogenous(void) const
{
return (arg1->containsEndogenous() || arg2->containsEndogenous() || arg3->containsEndogenous());
}
expr_t
TrinaryOpNode::replaceTrendVar() const
{
@ -4616,6 +4716,16 @@ ExternalFunctionNode::maxExoLag() const
return val;
}
int
ExternalFunctionNode::maxLead() const
{
int val = 0;
for (vector<expr_t>::const_iterator it = arguments.begin();
it != arguments.end(); it++)
val = max(val, (*it)->maxLead());
return val;
}
expr_t
ExternalFunctionNode::decreaseLeadsLags(int n) const
{
@ -4724,6 +4834,15 @@ ExternalFunctionNode::isVariableNodeEqualTo(SymbolType type_arg, int variable_id
return false;
}
bool
ExternalFunctionNode::containsEndogenous(void) const
{
bool result = false;
for (vector<expr_t>::const_iterator it = arguments.begin(); it != arguments.end(); it++)
result = result || (*it)->containsEndogenous();
return result;
}
expr_t
ExternalFunctionNode::replaceTrendVar() const
{

View File

@ -235,6 +235,7 @@ public:
virtual void collectModelLocalVariables(set<int> &result) const;
virtual void collectTemporary_terms(const temporary_terms_t &temporary_terms, temporary_terms_inuse_t &temporary_terms_inuse, int Curr_Block) const = 0;
virtual void computeTemporaryTerms(map<expr_t, int> &reference_count,
temporary_terms_t &temporary_terms,
map<expr_t, pair<int, int> > &first_occurence,
@ -280,6 +281,10 @@ public:
/*! Always returns a non-negative value */
virtual int maxExoLag() const = 0;
//! Returns the relative period of the most forward term in this expression
/*! A negative value means that the expression contains only lagged variables */
virtual int maxLead() const = 0;
//! Returns a new expression where all the leads/lags have been shifted backwards by the same amount
/*!
Only acts on endogenous, exogenous, exogenous det
@ -368,6 +373,9 @@ public:
*/
virtual bool isNumConstNodeEqualTo(double value) const = 0;
//! Returns true if the expression contains one or several endogenous variable
virtual bool containsEndogenous(void) const = 0;
//! Return true if the nodeID is a variable withe a type equal to type_arg, a specific variable id aqual to varfiable_id and a lag equal to lag_arg and false otherwise
/*!
\param[in] the type (type_arg), specifique variable id (variable_id and the lag (lag_arg)
@ -431,6 +439,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@ -440,6 +449,7 @@ public:
virtual expr_t substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
@ -490,6 +500,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@ -499,6 +510,7 @@ public:
virtual expr_t substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
@ -562,6 +574,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
//! Creates another UnaryOpNode with the same opcode, but with a possibly different datatree and argument
@ -573,6 +586,7 @@ public:
virtual expr_t substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
@ -649,6 +663,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
//! Creates another BinaryOpNode with the same opcode, but with a possibly different datatree and arguments
@ -660,6 +675,7 @@ public:
virtual expr_t substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
@ -716,6 +732,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
//! Creates another TrinaryOpNode with the same opcode, but with a possibly different datatree and arguments
@ -727,6 +744,7 @@ public:
virtual expr_t substituteLogPow(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs1, vector<BinaryOpNode *> &neweqs2) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual expr_t replaceTrendVar() const;
virtual expr_t detrend(int symb_id, expr_t trend) const;
@ -788,6 +806,7 @@ public:
virtual int maxExoLead() const;
virtual int maxEndoLag() const;
virtual int maxExoLag() const;
virtual int maxLead() const;
virtual expr_t decreaseLeadsLags(int n) const;
virtual expr_t substituteEndoLeadGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs, bool deterministic_model) const;
virtual expr_t substituteEndoLagGreaterThanTwo(subst_table_t &subst_table, vector<BinaryOpNode *> &neweqs) const;
@ -798,6 +817,7 @@ public:
virtual expr_t buildSimilarExternalFunctionNode(vector<expr_t> &alt_args, DataTree &alt_datatree) const;
virtual expr_t decreaseLeadsLagsPredeterminedVariables() const;
virtual bool isNumConstNodeEqualTo(double value) const;
virtual bool containsEndogenous(void) const;
virtual bool isVariableNodeEqualTo(SymbolType type_arg, int variable_id, int lag_arg) const;
virtual void writePrhs(ostream &output, ExprNodeOutputType output_type, const temporary_terms_t &temporary_terms, deriv_node_temp_terms_t &tef_terms, const string &ending) const;
virtual expr_t replaceTrendVar() const;