stop processing when certain functions are used in a linear context on endogenous/exogenous variables. closes dynare#1537
parent
d1be4f4946
commit
0c1373bc5e
|
@ -765,6 +765,20 @@ DataTree::isUnaryOpUsed(UnaryOpcode opcode) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const
|
||||
{
|
||||
set<int> var;
|
||||
for (const auto & it : unary_op_node_map)
|
||||
if (get<1>(it.first) == opcode)
|
||||
{
|
||||
it.second->collectVariables(type, var);
|
||||
if (!var.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
|
||||
{
|
||||
|
@ -775,6 +789,20 @@ DataTree::isBinaryOpUsed(BinaryOpcode opcode) const
|
|||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const
|
||||
{
|
||||
set<int> var;
|
||||
for (const auto & it : binary_op_node_map)
|
||||
if (get<2>(it.first) == opcode)
|
||||
{
|
||||
it.second->collectVariables(type, var);
|
||||
if (!var.empty())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
DataTree::isTrinaryOpUsed(TrinaryOpcode opcode) const
|
||||
{
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright © 2003-2018 Dynare Team
|
||||
* Copyright © 2003-2019 Dynare Team
|
||||
*
|
||||
* This file is part of Dynare.
|
||||
*
|
||||
|
@ -261,8 +261,12 @@ public:
|
|||
bool isSymbolUsed(int symb_id) const;
|
||||
//! Checks if a given unary op is used somewhere in the data tree
|
||||
bool isUnaryOpUsed(UnaryOpcode opcode) const;
|
||||
//! Checks if a given unary op is used somewhere in the data tree on an endogenous variable
|
||||
bool isUnaryOpUsedOnType(SymbolType type, UnaryOpcode opcode) const;
|
||||
//! Checks if a given binary op is used somewhere in the data tree
|
||||
bool isBinaryOpUsed(BinaryOpcode opcode) const;
|
||||
//! Checks if a given binary op is used somewhere in the data tree on an endogenous variable
|
||||
bool isBinaryOpUsedOnType(SymbolType type, BinaryOpcode opcode) const;
|
||||
//! Checks if a given trinary op is used somewhere in the data tree
|
||||
bool isTrinaryOpUsed(TrinaryOpcode opcode) const;
|
||||
//! Checks if a given external function is used somewhere in the data tree
|
||||
|
|
|
@ -307,17 +307,41 @@ ModFile::checkPass(bool nostrict, bool stochastic)
|
|||
warnings << R"(WARNING: you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which is unsuitable for a stochastic context; see the reference manual, section about "Expressions", for more details.)" << endl;
|
||||
|
||||
if (linear
|
||||
&& (dynamic_model.isUnaryOpUsed(UnaryOpcode::sign)
|
||||
|| dynamic_model.isUnaryOpUsed(UnaryOpcode::abs)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::max)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::min)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::greater)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::less)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::greaterEqual)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::lessEqual)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::equalEqual)
|
||||
|| dynamic_model.isBinaryOpUsed(BinaryOpcode::different)))
|
||||
warnings << "WARNING: you have declared your model 'linear' but you are using a function (max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) which potentially makes it non-linear." << endl;
|
||||
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::endogenous, UnaryOpcode::sign)
|
||||
|| dynamic_model.isUnaryOpUsedOnType(SymbolType::endogenous, UnaryOpcode::abs)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::max)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::min)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::greater)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::less)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::greaterEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::lessEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::equalEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::endogenous, BinaryOpcode::different)))
|
||||
{
|
||||
cerr << "ERROR: you have declared your model 'linear' but you are using a function "
|
||||
<< "(max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
|
||||
<< "endogenous variable." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (linear
|
||||
&& !mod_file_struct.perfect_foresight_solver_present
|
||||
&& (dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::sign)
|
||||
|| dynamic_model.isUnaryOpUsedOnType(SymbolType::exogenous, UnaryOpcode::abs)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::max)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::min)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::greater)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::less)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::greaterEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::lessEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::equalEqual)
|
||||
|| dynamic_model.isBinaryOpUsedOnType(SymbolType::exogenous, BinaryOpcode::different)))
|
||||
{
|
||||
cerr << "ERROR: you have declared your model 'linear' but you are using a function "
|
||||
<< "(max, min, abs, sign) or an operator (<, >, <=, >=, ==, !=) on an "
|
||||
<< "exogenous variable in a non-perfect-foresight context." << endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Test if some estimated parameters are used within the values of shocks
|
||||
// statements (see issue #469)
|
||||
|
@ -1193,7 +1217,7 @@ ModFile::writeExternalFilesJulia(const string &basename, FileOutputType output)
|
|||
jlOutputFile << endl
|
||||
<< "options_ = dynare_options()" << endl
|
||||
<< R"(options_.dynare_version = ")" << PACKAGE_VERSION << R"(")" << endl;
|
||||
if (linear == 1)
|
||||
if (linear)
|
||||
jlOutputFile << "options_.linear = true" << endl;
|
||||
|
||||
// Write Model
|
||||
|
|
Loading…
Reference in New Issue