Rewrite engine for matching the non-optimizing agents part in PAC

The engine is now more robust and should reject any expression that does not
conform to the expected form. It is also able to deal with more cases, such as
terms appearing with a minus sign, or variables in the middle of a
three-factors product.

BTW, use a std::tuple for storing the result of the matching inside
PacExpectationNode, and change the order of components within the
structure (variable first, scalar last).
issue#70
Sébastien Villemot 2018-11-27 18:53:28 +01:00
parent 003df49e7d
commit 16a97a96fd
No known key found for this signature in database
GPG Key ID: 2CECE9350ECEBE4A
3 changed files with 223 additions and 209 deletions

View File

@ -4243,7 +4243,7 @@ DynamicModel::walkPacParameters()
pair<int, int> lhs (-1, -1);
pair<int, pair<vector<int>, vector<bool>>> ec_params_and_vars;
set<pair<int, pair<int, int>>> ar_params_and_vars;
set<pair<int, pair<pair<int, int>, double>>> non_optim_params_vars_and_scaling_factor;
vector<tuple<int, int, int, double>> non_optim_vars_params_and_constants;
if (equation->containsPacExpectation())
{
@ -4271,12 +4271,12 @@ DynamicModel::walkPacParameters()
{
optim_share_index = *(optim_share.begin());
optim_part->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars);
non_optim_part->getPacNonOptimizingPart(non_optim_params_vars_and_scaling_factor);
non_optim_vars_params_and_constants = non_optim_part->getPacNonOptimizingPart();
}
equation->addParamInfoToPac(lhs,
optim_share_index,
ec_params_and_vars, ar_params_and_vars,
non_optim_params_vars_and_scaling_factor);
non_optim_vars_params_and_constants);
}
}
}

View File

@ -675,13 +675,7 @@ NumConstNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
NumConstNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
}
void
NumConstNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
NumConstNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
}
@ -1951,23 +1945,6 @@ VariableNode::isParamTimesEndogExpr() const
return false;
}
void
VariableNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
if (get_type() != SymbolType::endogenous
&& get_type() != SymbolType::exogenous)
{
cerr << "ERROR VariableNode::getPacNonOptimizingPart: Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
params_vars_and_scaling_factor.emplace(make_pair(-1,
make_pair(make_pair(symb_id, lag),
1.0)));
}
void
VariableNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const
@ -1982,7 +1959,7 @@ VariableNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
VariableNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
VariableNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
}
@ -3767,12 +3744,6 @@ UnaryOpNode::isParamTimesEndogExpr() const
return arg->isParamTimesEndogExpr();
}
void
UnaryOpNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
arg->getPacNonOptimizingPart(params_vars_and_scaling_factor);
}
void
UnaryOpNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
@ -3790,9 +3761,9 @@ UnaryOpNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
UnaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
UnaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
arg->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
}
void
@ -5570,83 +5541,6 @@ BinaryOpNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<i
arg2->getPacOptimizingPart(lhs_orig_symb_id, ec_params_and_vars, ar_params_and_vars);
}
void
BinaryOpNode::getPacNonOptimizingPartHelper(const expr_t arg1, const expr_t arg2,
set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
eval_context_t ec;
set<int> params;
set<pair<int, int>> vars;
arg1->collectDynamicVariables(SymbolType::endogenous, vars);
arg1->collectDynamicVariables(SymbolType::exogenous, vars);
if (vars.size() == 0)
return;
if (vars.size() > 1)
{
cerr << "ERROR BinaryOpNode::getPacNonOptimizingPartHelper: Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
ec[(*(vars.begin())).first] = 1.0;
arg2->collectVariables(SymbolType::parameter, params);
if (params.size() > 1)
{
cerr << "ERROR BinaryOpNode::getPacNonOptimizingPartHelper: 2 Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
int param_idx;
if (params.size() == 1)
{
param_idx = *(params.begin());
ec[param_idx] = 1.0;
}
else
param_idx = -1;
double scaling_factor = 1.0;
try
{
scaling_factor = this->eval(ec);
}
catch (...)
{
}
params_vars_and_scaling_factor.emplace(param_idx,
make_pair(*(vars.begin()), scaling_factor));
}
void
BinaryOpNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
if (op_code == BinaryOpcode::times
|| op_code == BinaryOpcode::divide)
{
size_t orig_size = params_vars_and_scaling_factor.size();
getPacNonOptimizingPartHelper(arg1, arg2, params_vars_and_scaling_factor);
if (orig_size == params_vars_and_scaling_factor.size())
getPacNonOptimizingPartHelper(arg2, arg1, params_vars_and_scaling_factor);
if (orig_size == params_vars_and_scaling_factor.size())
{
cerr << "ERROR BinaryOpNode::getPacNonOptimizingPart: Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
}
else
{
arg1->getPacNonOptimizingPart(params_vars_and_scaling_factor);
arg2->getPacNonOptimizingPart(params_vars_and_scaling_factor);
}
}
bool
BinaryOpNode::isParamTimesEndogExpr() const
{
@ -5895,10 +5789,10 @@ BinaryOpNode::getPacLHS(pair<int, int> &lhs)
}
void
BinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
BinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
arg1->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg2->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg1->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
arg2->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
}
void
@ -6790,15 +6684,6 @@ TrinaryOpNode::isParamTimesEndogExpr() const
|| arg3->isParamTimesEndogExpr();
}
void
TrinaryOpNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
arg1->getPacNonOptimizingPart(params_vars_and_scaling_factor);
arg2->getPacNonOptimizingPart(params_vars_and_scaling_factor);
arg3->getPacNonOptimizingPart(params_vars_and_scaling_factor);
}
void
TrinaryOpNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const
@ -6819,11 +6704,11 @@ TrinaryOpNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
TrinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
TrinaryOpNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
arg1->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg2->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg3->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
arg1->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
arg2->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
arg3->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
}
void
@ -7344,15 +7229,6 @@ AbstractExternalFunctionNode::isParamTimesEndogExpr() const
return false;
}
void
AbstractExternalFunctionNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
cerr << "ERROR AbstractExternalFunctionNode::getPacNonOptimizingPart(: Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
void
AbstractExternalFunctionNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const
@ -7371,10 +7247,10 @@ AbstractExternalFunctionNode::getPacOptimizingShareAndExprNodes(set<int> &optim_
}
void
AbstractExternalFunctionNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
AbstractExternalFunctionNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
for (auto argument : arguments)
argument->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, params_vars_and_scaling_factor_arg);
argument->addParamInfoToPac(lhs_arg, optim_share_arg, ec_params_and_vars_arg, ar_params_and_vars_arg, non_optim_vars_params_and_constants);
}
void
@ -8973,15 +8849,6 @@ VarExpectationNode::isParamTimesEndogExpr() const
return false;
}
void
VarExpectationNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
cerr << "ERROR VarExpectationNode::getPacNonOptimizingPart(: Error in parsing PAC equation"
<< endl;
exit(EXIT_FAILURE);
}
void
VarExpectationNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const
@ -8996,7 +8863,7 @@ VarExpectationNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
VarExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
VarExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants)
{
}
@ -9146,45 +9013,45 @@ PacExpectationNode::writeOutput(ostream &output, ExprNodeOutputType output_type,
output << it->second.second;
}
output << "];" << endl;
if (!params_vars_and_scaling_factor.empty())
if (!non_optim_vars_params_and_constants.empty())
{
output << "M_.pac." << model_name << ".non_optimizing_behaviour.params = [";
for (auto it = params_vars_and_scaling_factor.begin();
it != params_vars_and_scaling_factor.end(); it++)
for (auto it = non_optim_vars_params_and_constants.begin();
it != non_optim_vars_params_and_constants.end(); ++it)
{
if (it != params_vars_and_scaling_factor.begin())
if (it != non_optim_vars_params_and_constants.begin())
output << " ";
if (it->first >= 0)
output << datatree.symbol_table.getTypeSpecificID(it->first) + 1;
if (get<2>(*it) >= 0)
output << datatree.symbol_table.getTypeSpecificID(get<2>(*it)) + 1;
else
output << "NaN";
}
output << "];"
<< "M_.pac." << model_name << ".non_optimizing_behaviour.vars = [";
for (auto it = params_vars_and_scaling_factor.begin();
it != params_vars_and_scaling_factor.end(); it++)
for (auto it = non_optim_vars_params_and_constants.begin();
it != non_optim_vars_params_and_constants.end(); ++it)
{
if (it != params_vars_and_scaling_factor.begin())
if (it != non_optim_vars_params_and_constants.begin())
output << " ";
output << datatree.symbol_table.getTypeSpecificID(it->second.first.first) + 1;
output << datatree.symbol_table.getTypeSpecificID(get<0>(*it)) + 1;
}
output << "];" << endl
<< "M_.pac." << model_name << ".non_optimizing_behaviour.lags = [";
for (auto it = params_vars_and_scaling_factor.begin();
it != params_vars_and_scaling_factor.end(); it++)
for (auto it = non_optim_vars_params_and_constants.begin();
it != non_optim_vars_params_and_constants.end(); ++it)
{
if (it != params_vars_and_scaling_factor.begin())
if (it != non_optim_vars_params_and_constants.begin())
output << " ";
output << it->second.first.second;
output << get<1>(*it);
}
output << "];" << endl
<< "M_.pac." << model_name << ".non_optimizing_behaviour.scaling_factor = [";
for (auto it = params_vars_and_scaling_factor.begin();
it != params_vars_and_scaling_factor.end(); it++)
for (auto it = non_optim_vars_params_and_constants.begin();
it != non_optim_vars_params_and_constants.end(); ++it)
{
if (it != params_vars_and_scaling_factor.begin())
if (it != non_optim_vars_params_and_constants.begin())
output << " ";
output << it->second.second;
output << get<3>(*it);
}
output << "];" << endl;
}
@ -9550,12 +9417,6 @@ PacExpectationNode::isParamTimesEndogExpr() const
return false;
}
void
PacExpectationNode::getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const
{
}
void
PacExpectationNode::getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &ar_params_and_vars) const
@ -9570,7 +9431,7 @@ PacExpectationNode::getPacOptimizingShareAndExprNodes(set<int> &optim_share,
}
void
PacExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg)
PacExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants_arg)
{
if (lhs_arg.first == -1)
{
@ -9588,7 +9449,7 @@ PacExpectationNode::addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_a
optim_share_index = optim_share_arg;
ar_params_and_vars = ar_params_and_vars_arg;
ec_params_and_vars = ec_params_and_vars_arg;
params_vars_and_scaling_factor = params_vars_and_scaling_factor_arg;
non_optim_vars_params_and_constants = non_optim_vars_params_and_constants_arg;
}
@ -9669,3 +9530,137 @@ PacExpectationNode::substitutePacExpectation(map<const PacExpectationNode *, con
return subExpr;
}
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);
}
tuple<int, int, int, double>
ExprNode::matchVariableTimesConstantTimesParam() const
{
int variable_id = -1, lag = 0, param_id = -1;
double constant = 1.0;
matchVTCTPHelper(variable_id, lag, param_id, constant, false);
if (variable_id == -1)
throw MatchFailureException{"No variable in this expression"};
return make_tuple(variable_id, lag, param_id, constant);
}
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>>
ExprNode::getPacNonOptimizingPart() const
{
vector<pair<expr_t, int>> terms;
decomposeAdditiveTerms(terms);
vector<tuple<int, int, int, double>> result;
for (const auto &it : terms)
try
{
expr_t term = it.first;
int sign = it.second;
auto m = term->matchVariableTimesConstantTimesParam();
get<3>(m) *= sign;
result.push_back(m);
}
catch (MatchFailureException &e)
{
cerr << "ExprNode::getPacNonOptimizingPart: Error in parsing PAC equation: "
<< e.message << endl;
exit(EXIT_FAILURE);
}
return result;
}

View File

@ -205,6 +205,10 @@ class ExprNode
bool checkIfTemporaryTermThenWrite(ostream &output, ExprNodeOutputType output_type,
const temporary_terms_t &temporary_terms,
const temporary_terms_idxs_t &temporary_terms_idxs) const;
// Internal helper for matchVariableTimesConstantTimesParam()
virtual void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const;
public:
ExprNode(DataTree &datatree_arg, int idx_arg);
virtual ~ExprNode() = default;
@ -556,9 +560,11 @@ class ExprNode
virtual void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const = 0;
//! Fills info for non optimizing part of PAC equation
virtual void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const = 0;
//! Analyzes the non optimizing part of PAC equation
/*! Returns a list of (variable_id, lag, param_id, constant)
corresponding to the terms in the expression. When there is no
parameter in a term, param_id == -1 */
vector<tuple<int, int, int, double>> getPacNonOptimizingPart() const;
//! Returns true if expression is of the form:
//! param * (endog op endog op ...) + param * (endog op endog op ...) + ...
virtual bool isParamTimesEndogExpr() const = 0;
@ -570,7 +576,7 @@ class ExprNode
expr_t &optim_part,
expr_t &non_optim_part) const = 0;
//! Adds PAC equation param info to pac_expectation
virtual void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) = 0;
virtual void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) = 0;
//! Fills var_model info for pac_expectation node
virtual void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) = 0;
@ -587,7 +593,33 @@ class ExprNode
//! Fills map
virtual void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const = 0;
};
//! Decompose an expression into its additive terms
/*! Returns a list of terms, with their sign (either 1 or -1, depending
on whether the terms appears with a plus or a minus).
The current_sign argument should normally be left to 1.
If current_sign == -1, then all signs are inverted */
virtual void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign = 1) const;
// Matches an expression of the form variable*constant*parameter
/* Returns a tuple (variable_id, lag, param_id, constant).
The variable must be an exogenous or an endogenous.
The constant is optional (in which case 1 is returned); there can be
several multiplicative constants; constants can also appear at the
denominator (i.e. after a divide sign).
The parameter is optional (in which case param_id == -1).
If the expression is not of the expected form, throws a
MatchFailureException */
tuple<int, int, int, double> matchVariableTimesConstantTimesParam() const;
//! Exception thrown by matchVariableTimesConstantTimesParam when matching fails
class MatchFailureException
{
public:
const string message;
MatchFailureException(string message_arg) : message{move(message_arg)} {};
};
};
//! Object used to compare two nodes (using their indexes)
/*! Note that in this ordering, a subexpression is always less than the
@ -667,13 +699,11 @@ public:
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -683,6 +713,7 @@ public:
bool isVarModelReferenced(const string &model_info_name) const override;
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
expr_t substituteStaticAuxiliaryVariable() const override;
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
};
//! Symbol or variable node
@ -764,13 +795,11 @@ public:
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -781,6 +810,7 @@ public:
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
};
//! Unary operator node
@ -890,13 +920,11 @@ public:
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -907,6 +935,8 @@ public:
void getEndosAndMaxLags(map<string, int> &model_endos_and_lags) const override;
//! Substitute auxiliary variables by their expression in static model
expr_t substituteStaticAuxiliaryVariable() const override;
void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign) const override;
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
};
//! Binary operator node
@ -984,11 +1014,6 @@ public:
{
return powerDerivOrder;
}
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacNonOptimizingPartHelper(const expr_t arg1, const expr_t arg2,
set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const;
void getPacOptimizingPartHelper(const expr_t arg1, const expr_t arg2,
int lhs_orig_symb_id,
pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
@ -1044,7 +1069,7 @@ public:
//! Returns the non-zero hand-side of an equation (that must have a hand side equal to zero)
expr_t getNonZeroPartofEquation() const;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &ar_params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRowHelper(expr_t arg1, expr_t arg2,
int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const;
@ -1066,6 +1091,8 @@ public:
expr_t substituteStaticAuxiliaryVariable() const override;
//! Substitute auxiliary variables by their expression in static model auxiliary variable definition
expr_t substituteStaticAuxiliaryDefinition() const;
void decomposeAdditiveTerms(vector<pair<expr_t, int>> &terms, int current_sign) const override;
void matchVTCTPHelper(int &var_id, int &lag, int &param_id, double &constant, bool at_denominator) const override;
};
//! Trinary operator node
@ -1159,13 +1186,11 @@ public:
expr_t clone(DataTree &datatree) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -1284,13 +1309,11 @@ public:
expr_t clone(DataTree &datatree) const override = 0;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -1497,13 +1520,11 @@ public:
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,
@ -1532,7 +1553,7 @@ private:
int optim_share_index;
pair<int, pair<vector<int>, vector<bool>>> ec_params_and_vars;
set<pair<int, pair<int, int>>> ar_params_and_vars;
set<pair<int, pair<pair<int, int>, double>>> params_vars_and_scaling_factor;
vector<tuple<int, int, int, double>> non_optim_vars_params_and_constants;
public:
PacExpectationNode(DataTree &datatree_arg, int idx_arg, string model_name);
void computeTemporaryTerms(map<expr_t, pair<int, NodeTreeReference>> &reference_count,
@ -1596,13 +1617,11 @@ public:
expr_t detrend(int symb_id, bool log_trend, expr_t trend) const override;
expr_t removeTrendLeadLag(map<int, expr_t> trend_symbols_map) const override;
bool isInStaticForm() const override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, set<pair<int, pair<pair<int, int>, double>>> &params_vars_and_scaling_factor_arg) override;
void addParamInfoToPac(pair<int, int> &lhs_arg, int optim_share_arg, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars_arg, set<pair<int, pair<int, int>>> &params_and_vars_arg, const vector<tuple<int, int, int, double>> &non_optim_vars_params_and_constants) override;
void fillPacExpectationVarInfo(string &model_name_arg, vector<int> &lhs_arg, int max_lag_arg, int pac_max_lag_arg, vector<bool> &nonstationary_arg, int growth_symb_id_arg, int equation_number_arg) override;
void fillAutoregressiveRow(int eqn, const vector<int> &lhs, map<tuple<int, int, int>, expr_t> &AR) const override;
void fillErrorCorrectionRow(int eqn, const vector<int> &nontrend_lhs, const vector<int> &trend_lhs, map<tuple<int, int, int>, expr_t> &EC) const override;
bool containsPacExpectation(const string &pac_model_name = "") const override;
void getPacNonOptimizingPart(set<pair<int, pair<pair<int, int>, double>>>
&params_vars_and_scaling_factor) const override;
void getPacOptimizingPart(int lhs_orig_symb_id, pair<int, pair<vector<int>, vector<bool>>> &ec_params_and_vars,
set<pair<int, pair<int, int>>> &params_and_vars) const override;
void getPacOptimizingShareAndExprNodes(set<int> &optim_share,