stop processing when certain functions are used in a linear context on endogenous/exogenous variables. closes dynare#1537

issue#70
Houtan Bastani 2019-09-10 12:37:11 +02:00
parent d1be4f4946
commit 0c1373bc5e
No known key found for this signature in database
GPG Key ID: 000094FB955BE169
3 changed files with 69 additions and 13 deletions

View File

@ -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
{

View File

@ -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

View File

@ -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