41 changed files with 998 additions and 18 deletions
-
6CHANGELOG.md
-
15src/storm-parsers/parser/ExpressionCreator.cpp
-
1src/storm-parsers/parser/ExpressionCreator.h
-
11src/storm-parsers/parser/ExpressionParser.cpp
-
15src/storm-parsers/parser/ExpressionParser.h
-
11src/storm-parsers/parser/PrismParser.h
-
8src/storm/storage/expressions/BaseExpression.cpp
-
4src/storm/storage/expressions/BaseExpression.h
-
32src/storm/storage/expressions/Expression.cpp
-
9src/storm/storage/expressions/Expression.h
-
11src/storm/storage/expressions/ExpressionVisitor.cpp
-
2src/storm/storage/expressions/ExpressionVisitor.h
-
1src/storm/storage/expressions/Expressions.h
-
3src/storm/storage/expressions/OperatorType.cpp
-
5src/storm/storage/expressions/OperatorType.h
-
100src/storm/storage/expressions/PredicateExpression.cpp
-
66src/storm/storage/expressions/PredicateExpression.h
-
171src/storm/storage/expressions/SimplificationVisitor.cpp
-
41src/storm/storage/expressions/SimplificationVisitor.h
-
20src/storm/storage/expressions/SubstitutionVisitor.cpp
-
3src/storm/storage/expressions/SubstitutionVisitor.h
-
291src/storm/storage/expressions/ToDiceStringVisitor.cpp
-
37src/storm/storage/expressions/ToDiceStringVisitor.h
-
4src/storm/storage/prism/Assignment.cpp
-
4src/storm/storage/prism/Assignment.h
-
4src/storm/storage/prism/BooleanVariable.cpp
-
3src/storm/storage/prism/BooleanVariable.h
-
12src/storm/storage/prism/Command.cpp
-
3src/storm/storage/prism/Command.h
-
9src/storm/storage/prism/Formula.cpp
-
1src/storm/storage/prism/Formula.h
-
4src/storm/storage/prism/IntegerVariable.cpp
-
4src/storm/storage/prism/IntegerVariable.h
-
9src/storm/storage/prism/Label.cpp
-
3src/storm/storage/prism/Label.h
-
22src/storm/storage/prism/Module.cpp
-
4src/storm/storage/prism/Module.h
-
46src/storm/storage/prism/Program.cpp
-
5src/storm/storage/prism/Program.h
-
14src/storm/storage/prism/Update.cpp
-
2src/storm/storage/prism/Update.h
@ -0,0 +1,11 @@ |
|||
#include "storm/storage/expressions/ExpressionVisitor.h"
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/exceptions/NotImplementedException.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
boost::any ExpressionVisitor::visit(PredicateExpression const&, boost::any const&) { |
|||
STORM_LOG_THROW(false,storm::exceptions::NotImplementedException, "Predicate Expressions are not supported by this visitor"); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,100 @@ |
|||
|
|||
#include "storm/storage/expressions/PredicateExpression.h"
|
|||
|
|||
#include "storm/storage/expressions/ExpressionVisitor.h"
|
|||
#include "storm/utility/macros.h"
|
|||
#include "storm/storage/BitVector.h"
|
|||
#include "storm/exceptions/InvalidTypeException.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
OperatorType toOperatorType(PredicateExpression::PredicateType tp) { |
|||
switch (tp) { |
|||
case PredicateExpression::PredicateType::AtMostOneOf: return OperatorType::AtMostOneOf; |
|||
case PredicateExpression::PredicateType::AtLeastOneOf: return OperatorType::AtLeastOneOf; |
|||
case PredicateExpression::PredicateType::ExactlyOneOf: return OperatorType::ExactlyOneOf; |
|||
} |
|||
STORM_LOG_ASSERT(false, "Predicate type not supported"); |
|||
} |
|||
|
|||
PredicateExpression::PredicateExpression(ExpressionManager const &manager, Type const& type, std::vector <std::shared_ptr<BaseExpression const>> const &operands, PredicateType predicateType) : BaseExpression(manager, type), predicate(predicateType), operands(operands) {} |
|||
|
|||
// Override base class methods.
|
|||
storm::expressions::OperatorType PredicateExpression::getOperator() const { |
|||
return toOperatorType(predicate); |
|||
} |
|||
|
|||
bool PredicateExpression::evaluateAsBool(Valuation const *valuation) const { |
|||
STORM_LOG_THROW(this->hasBooleanType(), storm::exceptions::InvalidTypeException, "Unable to evaluate expression as boolean."); |
|||
storm::storage::BitVector results(operands.size()); |
|||
uint64_t i = 0; |
|||
for(auto const& operand : operands) { |
|||
results.set(i, operand->evaluateAsBool(valuation)); |
|||
++i; |
|||
} |
|||
switch(predicate) { |
|||
case PredicateType::ExactlyOneOf: return results.getNumberOfSetBits() == 1; |
|||
case PredicateType::AtMostOneOf: return results.getNumberOfSetBits() <= 1; |
|||
case PredicateType::AtLeastOneOf: return results.getNumberOfSetBits() >= 1; |
|||
} |
|||
STORM_LOG_ASSERT(false, "Unknown predicate type"); |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> PredicateExpression::simplify() const { |
|||
std::vector<std::shared_ptr<BaseExpression const>> simplifiedOperands; |
|||
for (auto const& operand : operands) { |
|||
simplifiedOperands.push_back(operand->simplify()); |
|||
} |
|||
return std::shared_ptr<BaseExpression>(new PredicateExpression(this->getManager(), this->getType(), simplifiedOperands, predicate)); |
|||
} |
|||
|
|||
boost::any PredicateExpression::accept(ExpressionVisitor &visitor, boost::any const &data) const { |
|||
return visitor.visit(*this, data); |
|||
} |
|||
|
|||
bool PredicateExpression::isPredicateExpression() const { |
|||
return true; |
|||
} |
|||
|
|||
bool PredicateExpression::isFunctionApplication() const { |
|||
return true; |
|||
} |
|||
|
|||
bool PredicateExpression::containsVariables() const { |
|||
for(auto const& operand : operands) { |
|||
if(operand->containsVariables()) { |
|||
return true; |
|||
} |
|||
} |
|||
return false; |
|||
} |
|||
|
|||
uint_fast64_t PredicateExpression::getArity() const { |
|||
return operands.size(); |
|||
} |
|||
|
|||
std::shared_ptr<BaseExpression const> PredicateExpression::getOperand(uint_fast64_t operandIndex) const { |
|||
STORM_LOG_ASSERT(operandIndex < this->getArity(), "Invalid operand access"); |
|||
return operands[operandIndex]; |
|||
} |
|||
|
|||
void PredicateExpression::gatherVariables(std::set<storm::expressions::Variable>& variables) const { |
|||
for(auto const& operand : operands) { |
|||
operand->gatherVariables(variables); |
|||
} |
|||
} |
|||
|
|||
/*!
|
|||
* Retrieves the relation associated with the expression. |
|||
* |
|||
* @return The relation associated with the expression. |
|||
*/ |
|||
PredicateExpression::PredicateType PredicateExpression::getPredicateType() const { |
|||
return predicate; |
|||
} |
|||
|
|||
void PredicateExpression::printToStream(std::ostream& stream) const { |
|||
|
|||
} |
|||
} |
|||
} |
@ -0,0 +1,66 @@ |
|||
#pragma once |
|||
|
|||
#include "storm/storage/expressions/BaseExpression.h" |
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
/*! |
|||
* The base class of all binary expressions. |
|||
*/ |
|||
class PredicateExpression : public BaseExpression { |
|||
public: |
|||
enum class PredicateType { AtLeastOneOf, AtMostOneOf, ExactlyOneOf }; |
|||
|
|||
PredicateExpression(ExpressionManager const &manager,Type const& type, |
|||
std::vector <std::shared_ptr<BaseExpression const>> const &operands, |
|||
PredicateType predicateType); |
|||
|
|||
// Instantiate constructors and assignments with their default implementations. |
|||
PredicateExpression(PredicateExpression const &other) = default; |
|||
|
|||
PredicateExpression &operator=(PredicateExpression const &other) = delete; |
|||
|
|||
PredicateExpression(PredicateExpression &&) = default; |
|||
|
|||
PredicateExpression &operator=(PredicateExpression &&) = delete; |
|||
|
|||
virtual ~PredicateExpression() = default; |
|||
|
|||
// Override base class methods. |
|||
virtual storm::expressions::OperatorType getOperator() const override; |
|||
|
|||
virtual bool evaluateAsBool(Valuation const *valuation = nullptr) const override; |
|||
|
|||
virtual std::shared_ptr<BaseExpression const> simplify() const override; |
|||
|
|||
virtual boost::any accept(ExpressionVisitor &visitor, boost::any const &data) const override; |
|||
|
|||
virtual bool isPredicateExpression() const override; |
|||
|
|||
virtual bool isFunctionApplication() const override; |
|||
|
|||
virtual bool containsVariables() const override; |
|||
|
|||
virtual uint_fast64_t getArity() const override; |
|||
|
|||
virtual std::shared_ptr<BaseExpression const> getOperand(uint_fast64_t operandIndex) const override; |
|||
|
|||
virtual void gatherVariables(std::set<storm::expressions::Variable>& variables) const override; |
|||
|
|||
/*! |
|||
* Retrieves the relation associated with the expression. |
|||
* |
|||
* @return The relation associated with the expression. |
|||
*/ |
|||
PredicateType getPredicateType() const; |
|||
|
|||
protected: |
|||
// Override base class method. |
|||
virtual void printToStream(std::ostream& stream) const override; |
|||
|
|||
private: |
|||
PredicateType predicate; |
|||
std::vector<std::shared_ptr<BaseExpression const>> operands; |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,171 @@ |
|||
#include <map>
|
|||
#include <unordered_map>
|
|||
#include <string>
|
|||
|
|||
#include "storm/storage/expressions/SimplificationVisitor.h"
|
|||
#include "storm/storage/expressions/Expressions.h"
|
|||
#include "storm/storage/expressions/PredicateExpression.h"
|
|||
#include "storm/storage/expressions/ExpressionManager.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
SimplificationVisitor::SimplificationVisitor() { |
|||
// Intentionally left empty.
|
|||
} |
|||
|
|||
Expression SimplificationVisitor::substitute(Expression const &expression) { |
|||
return Expression(boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getBaseExpression().accept(*this, boost::none))); |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(IfThenElseExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> conditionExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getCondition()->accept(*this, data)); |
|||
std::shared_ptr<BaseExpression const> thenExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getThenExpression()->accept(*this, data)); |
|||
std::shared_ptr<BaseExpression const> elseExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getElseExpression()->accept(*this, data)); |
|||
|
|||
// If the arguments did not change, we simply push the expression itself.
|
|||
if (conditionExpression.get() == expression.getCondition().get() && |
|||
thenExpression.get() == expression.getThenExpression().get() && |
|||
elseExpression.get() == expression.getElseExpression().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new IfThenElseExpression(expression.getManager(), expression.getType(), conditionExpression, |
|||
thenExpression, elseExpression))); |
|||
} |
|||
} |
|||
|
|||
boost::any |
|||
SimplificationVisitor::visit(BinaryBooleanFunctionExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> firstExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getFirstOperand()->accept(*this, data)); |
|||
std::shared_ptr<BaseExpression const> secondExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getSecondOperand()->accept(*this, data)); |
|||
|
|||
// If the arguments did not change, we simply push the expression itself.
|
|||
if (firstExpression.get() == expression.getFirstOperand().get() && |
|||
secondExpression.get() == expression.getSecondOperand().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new BinaryBooleanFunctionExpression(expression.getManager(), expression.getType(), |
|||
firstExpression, secondExpression, |
|||
expression.getOperatorType()))); |
|||
} |
|||
} |
|||
|
|||
boost::any |
|||
SimplificationVisitor::visit(BinaryNumericalFunctionExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> firstExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getFirstOperand()->accept(*this, data)); |
|||
std::shared_ptr<BaseExpression const> secondExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getSecondOperand()->accept(*this, data)); |
|||
|
|||
// If the arguments did not change, we simply push the expression itself.
|
|||
if (firstExpression.get() == expression.getFirstOperand().get() && |
|||
secondExpression.get() == expression.getSecondOperand().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new BinaryNumericalFunctionExpression(expression.getManager(), expression.getType(), |
|||
firstExpression, secondExpression, |
|||
expression.getOperatorType()))); |
|||
} |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(BinaryRelationExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> firstExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getFirstOperand()->accept(*this, data)); |
|||
std::shared_ptr<BaseExpression const> secondExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getSecondOperand()->accept(*this, data)); |
|||
|
|||
// If the arguments did not change, we simply push the expression itself.
|
|||
if (firstExpression.get() == expression.getFirstOperand().get() && |
|||
secondExpression.get() == expression.getSecondOperand().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new BinaryRelationExpression(expression.getManager(), expression.getType(), firstExpression, |
|||
secondExpression, expression.getRelationType()))); |
|||
} |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(VariableExpression const &expression, boost::any const &) { |
|||
|
|||
return expression.getSharedPointer(); |
|||
|
|||
} |
|||
|
|||
boost::any |
|||
SimplificationVisitor::visit(UnaryBooleanFunctionExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> operandExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getOperand()->accept(*this, data)); |
|||
|
|||
// If the argument did not change, we simply push the expression itself.
|
|||
if (operandExpression.get() == expression.getOperand().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new UnaryBooleanFunctionExpression(expression.getManager(), expression.getType(), |
|||
operandExpression, expression.getOperatorType()))); |
|||
} |
|||
} |
|||
|
|||
boost::any |
|||
SimplificationVisitor::visit(UnaryNumericalFunctionExpression const &expression, boost::any const &data) { |
|||
std::shared_ptr<BaseExpression const> operandExpression = boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getOperand()->accept(*this, data)); |
|||
|
|||
// If the argument did not change, we simply push the expression itself.
|
|||
if (operandExpression.get() == expression.getOperand().get()) { |
|||
return expression.getSharedPointer(); |
|||
} else { |
|||
return std::const_pointer_cast<BaseExpression const>(std::shared_ptr<BaseExpression>( |
|||
new UnaryNumericalFunctionExpression(expression.getManager(), expression.getType(), |
|||
operandExpression, expression.getOperatorType()))); |
|||
} |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(PredicateExpression const &expression, boost::any const &data) { |
|||
std::vector<Expression> newExpressions; |
|||
for (uint64_t i = 0; i < expression.getArity(); ++i) { |
|||
newExpressions.emplace_back(boost::any_cast<std::shared_ptr<BaseExpression const>>( |
|||
expression.getOperand(i)->accept(*this, data))); |
|||
} |
|||
std::vector<Expression> newSumExpressions; |
|||
for (auto const &expr : newExpressions) { |
|||
newSumExpressions.push_back( |
|||
ite(expr, expression.getManager().integer(1), expression.getManager().integer(0))); |
|||
} |
|||
|
|||
storm::expressions::Expression finalexpr; |
|||
if (expression.getPredicateType() == PredicateExpression::PredicateType::AtLeastOneOf) { |
|||
finalexpr = storm::expressions::sum(newSumExpressions) > expression.getManager().integer(0); |
|||
} else if (expression.getPredicateType() == PredicateExpression::PredicateType::AtMostOneOf) { |
|||
finalexpr = storm::expressions::sum(newSumExpressions) <= expression.getManager().integer(1); |
|||
} else if (expression.getPredicateType() == PredicateExpression::PredicateType::ExactlyOneOf) { |
|||
finalexpr = storm::expressions::sum(newSumExpressions) == expression.getManager().integer(1); |
|||
} else { |
|||
STORM_LOG_ASSERT(false, "Unknown predicate type."); |
|||
} |
|||
return std::const_pointer_cast<BaseExpression const>(finalexpr.getBaseExpressionPointer()); |
|||
} |
|||
|
|||
|
|||
boost::any SimplificationVisitor::visit(BooleanLiteralExpression const &expression, boost::any const &) { |
|||
return expression.getSharedPointer(); |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(IntegerLiteralExpression const &expression, boost::any const &) { |
|||
return expression.getSharedPointer(); |
|||
} |
|||
|
|||
boost::any SimplificationVisitor::visit(RationalLiteralExpression const &expression, boost::any const &) { |
|||
return expression.getSharedPointer(); |
|||
} |
|||
|
|||
} |
|||
} |
@ -0,0 +1,41 @@ |
|||
#pragma once |
|||
#include <stack> |
|||
|
|||
#include "storm/storage/expressions/Expression.h" |
|||
#include "storm/storage/expressions/ExpressionVisitor.h" |
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
class SimplificationVisitor : public ExpressionVisitor { |
|||
public: |
|||
/*! |
|||
* Creates a new simplification visitor that replaces predicates by other (simpler?) predicates. |
|||
* |
|||
* Configuration: |
|||
* Currently, the visitor only replaces nonstandard predicates |
|||
* |
|||
*/ |
|||
SimplificationVisitor(); |
|||
|
|||
/*! |
|||
* Simplifies based on the configuration. |
|||
*/ |
|||
Expression substitute(Expression const& expression); |
|||
|
|||
virtual boost::any visit(IfThenElseExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryRelationExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(VariableExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BooleanLiteralExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(IntegerLiteralExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(RationalLiteralExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(PredicateExpression const& expression, boost::any const& data) override; |
|||
|
|||
protected: |
|||
// |
|||
}; |
|||
} |
|||
} |
@ -0,0 +1,291 @@ |
|||
#include "storm/exceptions/NotSupportedException.h"
|
|||
#include "storm/storage/expressions/ToDiceStringVisitor.h"
|
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
ToDiceStringVisitor::ToDiceStringVisitor(uint64 nrBits) : nrBits(nrBits) { |
|||
|
|||
} |
|||
|
|||
std::string ToDiceStringVisitor::toString(Expression const& expression) { |
|||
return toString(expression.getBaseExpressionPointer().get()); |
|||
} |
|||
|
|||
std::string ToDiceStringVisitor::toString(BaseExpression const* expression) { |
|||
stream.str(""); |
|||
stream.clear(); |
|||
expression->accept(*this, boost::none); |
|||
return stream.str(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(IfThenElseExpression const& expression, boost::any const& data) { |
|||
stream << "if "; |
|||
expression.getCondition()->accept(*this, data); |
|||
stream << " then "; |
|||
expression.getThenExpression()->accept(*this, data); |
|||
stream << " else "; |
|||
expression.getElseExpression()->accept(*this, data); |
|||
stream << ""; |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) { |
|||
switch (expression.getOperatorType()) { |
|||
case BinaryBooleanFunctionExpression::OperatorType::And: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << " && "; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryBooleanFunctionExpression::OperatorType::Or: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << " || "; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryBooleanFunctionExpression::OperatorType::Xor: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << " ^ "; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryBooleanFunctionExpression::OperatorType::Implies: |
|||
stream << "(!("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << ") || "; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryBooleanFunctionExpression::OperatorType::Iff: |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << " <=> "; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
break; |
|||
} |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) { |
|||
switch (expression.getOperatorType()) { |
|||
case BinaryNumericalFunctionExpression::OperatorType::Plus: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "+"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Minus: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "-"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Times: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "*"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Divide: { |
|||
STORM_LOG_THROW(expression.getSecondOperand()->isIntegerLiteralExpression(), |
|||
storm::exceptions::NotSupportedException, |
|||
"Dice does not support modulo with nonconst rhs"); |
|||
uint64_t denominator = expression.getSecondOperand()->evaluateAsInt(); |
|||
int shifts = 0; |
|||
while (denominator % 2 == 0) { |
|||
denominator = denominator >> 1; |
|||
shifts++; |
|||
} |
|||
denominator = denominator >> 1; |
|||
if (denominator > 0) { |
|||
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, |
|||
"Dice does not support division with non-powers of two"); |
|||
} |
|||
if (shifts > 0) { |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << " >> " << shifts; |
|||
stream << ")"; |
|||
} else { |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
} |
|||
|
|||
} |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Power: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "^"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Modulo: |
|||
STORM_LOG_THROW(expression.getSecondOperand()->isIntegerLiteralExpression(), storm::exceptions::NotSupportedException, "Dice does not support modulo with nonconst rhs"); |
|||
STORM_LOG_THROW(expression.getSecondOperand()->evaluateAsInt() == 2, storm::exceptions::NotSupportedException, "Dice does not support modulo with rhs != 2"); |
|||
|
|||
stream << "( nth_bit(int(" << nrBits << "," << nrBits-1 << "), "; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "))"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Max: |
|||
stream << "max("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << ","; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryNumericalFunctionExpression::OperatorType::Min: |
|||
stream << "min("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << ","; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
} |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(BinaryRelationExpression const& expression, boost::any const& data) { |
|||
switch (expression.getRelationType()) { |
|||
case BinaryRelationExpression::RelationType::Equal: |
|||
if (expression.getFirstOperand()->isBinaryNumericalFunctionExpression()) { |
|||
if (expression.getFirstOperand()->asBinaryNumericalFunctionExpression().getOperatorType() == BinaryNumericalFunctionExpression::OperatorType::Modulo) { |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
} |
|||
} else { |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "=="; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
} |
|||
|
|||
break; |
|||
case BinaryRelationExpression::RelationType::NotEqual: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "!="; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryRelationExpression::RelationType::Less: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "<"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryRelationExpression::RelationType::LessOrEqual: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << "<="; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryRelationExpression::RelationType::Greater: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << ">"; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case BinaryRelationExpression::RelationType::GreaterOrEqual: |
|||
stream << "("; |
|||
expression.getFirstOperand()->accept(*this, data); |
|||
stream << ">="; |
|||
expression.getSecondOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
} |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(VariableExpression const& expression, boost::any const&) { |
|||
stream << expression.getVariable().getName(); |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) { |
|||
switch (expression.getOperatorType()) { |
|||
case UnaryBooleanFunctionExpression::OperatorType::Not: |
|||
stream << "!("; |
|||
expression.getOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
} |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) { |
|||
switch (expression.getOperatorType()) { |
|||
case UnaryNumericalFunctionExpression::OperatorType::Minus: |
|||
stream << "-("; |
|||
expression.getOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case UnaryNumericalFunctionExpression::OperatorType::Floor: |
|||
stream << "floor("; |
|||
expression.getOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
case UnaryNumericalFunctionExpression::OperatorType::Ceil: |
|||
stream << "ceil("; |
|||
expression.getOperand()->accept(*this, data); |
|||
stream << ")"; |
|||
break; |
|||
} |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(PredicateExpression const& expression, boost::any const& data) { |
|||
auto pdt = expression.getPredicateType(); |
|||
STORM_LOG_ASSERT(pdt == PredicateExpression::PredicateType::ExactlyOneOf || pdt == PredicateExpression::PredicateType::AtLeastOneOf || pdt == PredicateExpression::PredicateType::AtMostOneOf, "Only some predicate types are supported."); |
|||
stream << "("; |
|||
if (expression.getPredicateType() == PredicateExpression::PredicateType::ExactlyOneOf || expression.getPredicateType() == PredicateExpression::PredicateType::AtMostOneOf) { |
|||
stream << "(true "; |
|||
for (uint64_t operandi = 0; operandi < expression.getArity(); ++operandi) { |
|||
for (uint64_t operandj = operandi + 1; operandj < expression.getArity(); ++operandj) { |
|||
stream << "&& !("; |
|||
expression.getOperand(operandi)->accept(*this, data); |
|||
stream << " && "; |
|||
expression.getOperand(operandj)->accept(*this, data); |
|||
stream << ")"; |
|||
} |
|||
} |
|||
stream << ")"; |
|||
} |
|||
if (expression.getPredicateType() == PredicateExpression::PredicateType::ExactlyOneOf) { |
|||
stream << " && "; |
|||
} |
|||
if (expression.getPredicateType() == PredicateExpression::PredicateType::ExactlyOneOf || expression.getPredicateType() == PredicateExpression::PredicateType::AtLeastOneOf) { |
|||
stream << "( false"; |
|||
for (uint64_t operandj = 0; operandj < expression.getArity(); ++operandj) { |
|||
stream << "|| "; |
|||
expression.getOperand(operandj)->accept(*this, data); |
|||
} |
|||
stream << ")"; |
|||
} |
|||
stream << ")"; |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(BooleanLiteralExpression const& expression, boost::any const&) { |
|||
stream << (expression.getValue() ? " true " : " false "); |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(IntegerLiteralExpression const& expression, boost::any const&) { |
|||
stream << "int(" << nrBits << "," << expression.getValue() << ")"; |
|||
return boost::any(); |
|||
} |
|||
|
|||
boost::any ToDiceStringVisitor::visit(RationalLiteralExpression const& expression, boost::any const&) { |
|||
stream << std::scientific << std::setprecision(std::numeric_limits<double>::max_digits10) << "(" << expression.getValueAsDouble() << ")"; |
|||
return boost::any(); |
|||
} |
|||
} |
|||
} |
@ -0,0 +1,37 @@ |
|||
#pragma once |
|||
|
|||
#include <sstream> |
|||
|
|||
#include "storm/storage/expressions/Expression.h" |
|||
#include "storm/storage/expressions/Expressions.h" |
|||
#include "storm/storage/expressions/ExpressionVisitor.h" |
|||
|
|||
namespace storm { |
|||
namespace expressions { |
|||
class ToDiceStringVisitor : public ExpressionVisitor { |
|||
public: |
|||
ToDiceStringVisitor(uint64 nrBits); |
|||
|
|||
std::string toString(Expression const& expression); |
|||
std::string toString(BaseExpression const* expression); |
|||
|
|||
virtual boost::any visit(IfThenElseExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BinaryRelationExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(VariableExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(PredicateExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(BooleanLiteralExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(IntegerLiteralExpression const& expression, boost::any const& data) override; |
|||
virtual boost::any visit(RationalLiteralExpression const& expression, boost::any const& data) override; |
|||
|
|||
|
|||
private: |
|||
std::stringstream stream; |
|||
uint64_t nrBits; |
|||
}; |
|||
} |
|||
} |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue