You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
113 lines
5.7 KiB
113 lines
5.7 KiB
#include "src/storage/expressions/LinearityCheckVisitor.h"
|
|
#include "src/storage/expressions/Expressions.h"
|
|
|
|
#include "src/exceptions/ExceptionMacros.h"
|
|
#include "src/exceptions/InvalidTypeException.h"
|
|
|
|
namespace storm {
|
|
namespace expressions {
|
|
LinearityCheckVisitor::LinearityCheckVisitor() : resultStack() {
|
|
// Intentionally left empty.
|
|
}
|
|
|
|
bool LinearityCheckVisitor::check(Expression const& expression) {
|
|
expression.getBaseExpression().accept(this);
|
|
return resultStack.top() == LinearityStatus::LinearWithoutVariables || resultStack.top() == LinearityStatus::LinearContainsVariables;
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(IfThenElseExpression const* expression) {
|
|
// An if-then-else expression is never linear.
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(BinaryBooleanFunctionExpression const* expression) {
|
|
// Boolean function applications are not allowed in linear expressions.
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(BinaryNumericalFunctionExpression const* expression) {
|
|
LinearityStatus leftResult;
|
|
LinearityStatus rightResult;
|
|
switch (expression->getOperatorType()) {
|
|
case BinaryNumericalFunctionExpression::OperatorType::Plus:
|
|
case BinaryNumericalFunctionExpression::OperatorType::Minus:
|
|
expression->getFirstOperand()->accept(this);
|
|
leftResult = resultStack.top();
|
|
|
|
if (leftResult == LinearityStatus::NonLinear) {
|
|
return;
|
|
} else {
|
|
resultStack.pop();
|
|
expression->getSecondOperand()->accept(this);
|
|
rightResult = resultStack.top();
|
|
if (rightResult == LinearityStatus::NonLinear) {
|
|
return;
|
|
}
|
|
resultStack.pop();
|
|
}
|
|
|
|
resultStack.push(leftResult == LinearityStatus::LinearContainsVariables || rightResult == LinearityStatus::LinearContainsVariables ? LinearityStatus::LinearContainsVariables : LinearityStatus::LinearWithoutVariables);
|
|
break;
|
|
case BinaryNumericalFunctionExpression::OperatorType::Times:
|
|
case BinaryNumericalFunctionExpression::OperatorType::Divide:
|
|
expression->getFirstOperand()->accept(this);
|
|
leftResult = resultStack.top();
|
|
|
|
if (leftResult == LinearityStatus::NonLinear) {
|
|
return;
|
|
} else {
|
|
resultStack.pop();
|
|
expression->getSecondOperand()->accept(this);
|
|
rightResult = resultStack.top();
|
|
if (rightResult == LinearityStatus::NonLinear) {
|
|
return;
|
|
}
|
|
resultStack.pop();
|
|
}
|
|
|
|
if (leftResult == LinearityStatus::LinearContainsVariables && rightResult == LinearityStatus::LinearContainsVariables) {
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
resultStack.push(leftResult == LinearityStatus::LinearContainsVariables || rightResult == LinearityStatus::LinearContainsVariables ? LinearityStatus::LinearContainsVariables : LinearityStatus::LinearWithoutVariables);
|
|
break;
|
|
case BinaryNumericalFunctionExpression::OperatorType::Min: resultStack.push(LinearityStatus::NonLinear); break;
|
|
case BinaryNumericalFunctionExpression::OperatorType::Max: resultStack.push(LinearityStatus::NonLinear); break;
|
|
case BinaryNumericalFunctionExpression::OperatorType::Power: resultStack.push(LinearityStatus::NonLinear); break;
|
|
}
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(BinaryRelationExpression const* expression) {
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(VariableExpression const* expression) {
|
|
resultStack.push(LinearityStatus::LinearContainsVariables);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(UnaryBooleanFunctionExpression const* expression) {
|
|
// Boolean function applications are not allowed in linear expressions.
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(UnaryNumericalFunctionExpression const* expression) {
|
|
switch (expression->getOperatorType()) {
|
|
case UnaryNumericalFunctionExpression::OperatorType::Minus: break;
|
|
case UnaryNumericalFunctionExpression::OperatorType::Floor:
|
|
case UnaryNumericalFunctionExpression::OperatorType::Ceil: resultStack.pop(); resultStack.push(LinearityStatus::NonLinear); break;
|
|
}
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(BooleanLiteralExpression const* expression) {
|
|
resultStack.push(LinearityStatus::NonLinear);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(IntegerLiteralExpression const* expression) {
|
|
resultStack.push(LinearityStatus::LinearWithoutVariables);
|
|
}
|
|
|
|
void LinearityCheckVisitor::visit(DoubleLiteralExpression const* expression) {
|
|
resultStack.push(LinearityStatus::LinearWithoutVariables);
|
|
}
|
|
}
|
|
}
|