#ifndef STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ #define STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ #include #include #include #include #include "storm/storage/expressions/BaseExpression.h" #include "storm/utility/OsDetection.h" namespace storm { namespace expressions { // Foward-declare expression manager class. class ExpressionManager; class Variable; class ExpressionVisitor; class Expression { public: friend class ExpressionManager; friend class Variable; template friend class SubstitutionVisitor; friend Expression operator+(Expression const& first, Expression const& second); friend Expression operator+(Expression const& first, int64_t second); friend Expression operator+(int64_t first, Expression const& second); friend Expression operator-(Expression const& first, Expression const& second); friend Expression operator-(Expression const& first, int64_t second); friend Expression operator-(int64_t first, Expression const& second); friend Expression operator-(Expression const& first); friend Expression operator*(Expression const& first, Expression const& second); friend Expression operator/(Expression const& first, Expression const& second); friend Expression operator^(Expression const& first, Expression const& second); friend Expression operator&&(Expression const& first, Expression const& second); friend Expression operator||(Expression const& first, Expression const& second); friend Expression operator!(Expression const& first); friend Expression operator==(Expression const& first, Expression const& second); friend Expression operator!=(Expression const& first, Expression const& second); friend Expression operator>(Expression const& first, Expression const& second); friend Expression operator>=(Expression const& first, Expression const& second); friend Expression operator<(Expression const& first, Expression const& second); friend Expression operator<=(Expression const& first, Expression const& second); friend Expression operator>(Expression const& first, int64_t second); friend Expression operator>=(Expression const& first, int64_t second); friend Expression operator<(Expression const& first, int64_t second); friend Expression operator<=(Expression const& first, int64_t second); friend Expression ite(Expression const& condition, Expression const& thenExpression, Expression const& elseExpression); friend Expression implies(Expression const& first, Expression const& second); friend Expression iff(Expression const& first, Expression const& second); friend Expression xclusiveor(Expression const& first, Expression const& second); friend Expression abs(Expression const& first); friend Expression truncate(Expression const& first); friend Expression sign(Expression const& first); friend Expression floor(Expression const& first); friend Expression ceil(Expression const& first); friend Expression minimum(Expression const& first, Expression const& second); friend Expression maximum(Expression const& first, Expression const& second); Expression() = default; /*! * Creates an expression representing the given variable. * * @param variable The variable to represent. */ Expression(Variable const& variable); /*! * Creates an expression with the given underlying base expression. * * @param expressionPtr A pointer to the underlying base expression. */ Expression(std::shared_ptr const& expressionPtr); // Instantiate constructors and assignments with their default implementations. Expression(Expression const& other) = default; Expression& operator=(Expression const& other) = default; #ifndef WINDOWS Expression(Expression&&) = default; Expression& operator=(Expression&&) = default; #endif /*! * Converts the expression to an expression over the variables of the provided expression manager. */ Expression changeManager(ExpressionManager const& newExpressionManager) const; /*! * Substitutes all occurrences of the variables according to the given map. Note that this substitution is * done simultaneously, i.e., variables appearing in the expressions that were "plugged in" are not * substituted. * * @param variableToExpressionMap A mapping from variables to the expression they are substituted with. * @return An expression in which all identifiers in the key set of the mapping are replaced by the * expression they are mapped to. */ Expression substitute(std::map const& variableToExpressionMap) const; /*! * Substitutes all occurrences of the variables according to the given map. Note that this substitution is * done simultaneously, i.e., variables appearing in the expressions that were "plugged in" are not * substituted. * * @param variableToExpressionMap A mapping from variables to the expression they are substituted with. * @return An expression in which all identifiers in the key set of the mapping are replaced by the * expression they are mapped to. */ Expression substitute(std::unordered_map const& variableToExpressionMap) const; /*! * Evaluates the expression under the valuation of variables given by the valuation and returns the * resulting boolean value. If the return type of the expression is not a boolean an exception is thrown. * * @param valuation The valuation of unknowns under which to evaluate the expression. * @return The boolean value of the expression under the given valuation. */ bool evaluateAsBool(Valuation const* valuation = nullptr) const; /*! * Evaluates the expression under the valuation of variables given by the valuation and returns the * resulting integer value. If the return type of the expression is not an integer an exception is thrown. * * @param valuation The valuation of unknowns under which to evaluate the expression. * @return The integer value of the expression under the given valuation. */ int_fast64_t evaluateAsInt(Valuation const* valuation = nullptr) const; /*! * Evaluates the expression under the valuation of variables given by the valuation and returns the * resulting double value. If the return type of the expression is not a double an exception is thrown. * * @param valuation The valuation of unknowns under which to evaluate the expression. * @return The double value of the expression under the given valuation. */ double evaluateAsDouble(Valuation const* valuation = nullptr) const; /*! * Simplifies the expression according to some basic rules. * * @return The simplified expression. */ Expression simplify() const; /*! * Retrieves the operator of a function application. This is only legal to call if the expression is * function application. * * @return The operator associated with the function application. */ OperatorType getOperator() const; /*! * Checks if the expression is a function application (of any sort). * * @return True iff the expression is a function application. */ bool isFunctionApplication() const; /*! * Retrieves the arity of the expression. * * @return The arity of the expression. */ uint_fast64_t getArity() const; /*! * Retrieves the given operand from the expression. * * @param operandIndex The index of the operand to retrieve. This must be lower than the arity of the expression. * @return The operand at the given index. */ Expression getOperand(uint_fast64_t operandIndex) const; /*! * Retrieves the identifier associated with this expression. This is only legal to call if the expression * is a variable. * * @return The identifier associated with this expression. */ std::string const& getIdentifier() const; /*! * Retrieves whether the expression contains a variable. * * @return True iff the expression contains a variable. */ bool containsVariables() const; /*! * Retrieves whether the expression is a literal. * * @return True iff the expression is a literal. */ bool isLiteral() const; /*! * Retrieves whether the expression is a variable. * * @return True iff the expression is a variable. */ bool isVariable() const; /*! * Checks if the expression is equal to the boolean literal true. * * @return True iff the expression is equal to the boolean literal true. */ bool isTrue() const; /*! * Checks if the expression is equal to the boolean literal false. * * @return True iff the expression is equal to the boolean literal false. */ bool isFalse() const; /*! * Checks whether the two expressions are the same. Note that this does not check for syntactical or even * semantical equivalence, but only returns true if both are the very same expressions. * * @return True iff the two expressions are the same. */ bool areSame(storm::expressions::Expression const& other) const; /*! * Retrieves whether this expression is a relation expression, i.e., an expression that has a relation * (equal, not equal, less, less or equal, etc.) as its top-level operator. * * @return True iff the expression is a relation expression. */ bool isRelationalExpression() const; /*! * Retrieves whether this expression is a linear expression. * * @return True iff the expression is linear. */ bool isLinear() const; /*! * Retrieves the set of all variables that appear in the expression. * * @return The set of all variables that appear in the expression. */ std::set getVariables() const; /*! * Retrieves whether the expression contains any of the given variables. * * @param variables The variables to search for. * @return True iff any of the variables appear in the expression. */ bool containsVariable(std::set const& variables) const; /*! * Retrieves the base expression underlying this expression object. Note that prior to calling this, the * expression object must be properly initialized. * * @return A reference to the underlying base expression. */ BaseExpression const& getBaseExpression() const; /*! * Retrieves a pointer to the base expression underlying this expression object. * * @return A pointer to the underlying base expression. */ std::shared_ptr const& getBaseExpressionPointer() const; /*! * Retrieves the manager responsible for this expression. * * @return The manager responsible for this expression. */ ExpressionManager const& getManager() const; /*! * Retrieves the type of the expression. * * @return The type of the expression. */ Type const& getType() const; /*! * Retrieves whether the expression has a numerical return type, i.e., integer or double. * * @return True iff the expression has a numerical return type. */ bool hasNumericalType() const; /*! * Retrieves whether the expression has a rational return type. * * @return True iff the expression has a rational return type. */ bool hasRationalType() const; /*! * Retrieves whether the expression has a boolean return type. * * @return True iff the expression has a boolean return type. */ bool hasBooleanType() const; /*! * Retrieves whether the expression has an integral return type. * * @return True iff the expression has a integral return type. */ bool hasIntegerType() const; /*! * Retrieves whether the expression has an integral return type. * * @return True iff the expression has a integral return type. */ bool hasBitVectorType() const; /*! * Accepts the given visitor. * * @param visitor The visitor to accept. */ boost::any accept(ExpressionVisitor& visitor, boost::any const& data) const; /*! * Converts the expression into a string. * * @return The string representation of the expression. */ std::string toString() const; /*! * Checks whether the object encapsulates a base-expression. */ bool isInitialized() const; /*! * Checks whether the two expressions are syntatically the same. */ bool isSyntacticallyEqual(storm::expressions::Expression const& other) const; friend std::ostream& operator<<(std::ostream& stream, Expression const& expression); private: // A pointer to the underlying base expression. std::shared_ptr expressionPtr; }; // Provide operator overloads to conveniently construct new expressions from other expressions. Expression operator+(Expression const& first, Expression const& second); Expression operator+(Expression const& first, int64_t second); Expression operator+(int64_t first, Expression const& second); Expression operator-(Expression const& first, Expression const& second); Expression operator-(Expression const& first, int64_t second); Expression operator-(int64_t first, Expression const& second); Expression operator-(Expression const& first); Expression operator*(Expression const& first, Expression const& second); Expression operator/(Expression const& first, Expression const& second); Expression operator^(Expression const& first, Expression const& second); Expression operator&&(Expression const& first, Expression const& second); Expression operator||(Expression const& first, Expression const& second); Expression operator!(Expression const& first); Expression operator==(Expression const& first, Expression const& second); Expression operator!=(Expression const& first, Expression const& second); Expression operator>(Expression const& first, Expression const& second); Expression operator>=(Expression const& first, Expression const& second); Expression operator<(Expression const& first, Expression const& second); Expression operator<=(Expression const& first, Expression const& second); Expression operator>(Expression const& first, int64_t second); Expression operator>=(Expression const& first, int64_t second); Expression operator<(Expression const& first, int64_t second); Expression operator<=(Expression const& first, int64_t second); Expression ite(Expression const& condition, Expression const& thenExpression, Expression const& elseExpression); Expression implies(Expression const& first, Expression const& second); Expression iff(Expression const& first, Expression const& second); Expression xclusiveor(Expression const& first, Expression const& second); Expression abs(Expression const& first); Expression truncate(Expression const& first); Expression sign(Expression const& first); Expression floor(Expression const& first); Expression ceil(Expression const& first); Expression minimum(Expression const& first, Expression const& second); Expression maximum(Expression const& first, Expression const& second); Expression disjunction(std::vector const& expressions); Expression conjunction(std::vector const& expressions); Expression sum(std::vector const& expressions); Expression apply(std::vector const& expressions, std::function const& function); } } namespace std { template <> struct less { bool operator()(storm::expressions::Expression const& lhs, storm::expressions::Expression const& rhs) const { return lhs.getBaseExpressionPointer() < rhs.getBaseExpressionPointer(); } }; template <> struct hash { size_t operator()(storm::expressions::Expression const& e) const { return reinterpret_cast(e.getBaseExpressionPointer().get()); } }; template <> struct equal_to { bool operator()(storm::expressions::Expression const& e1, storm::expressions::Expression const& e2) const { return e1.areSame(e2); } }; } #endif /* STORM_STORAGE_EXPRESSIONS_EXPRESSION_H_ */