Browse Source

work on location support for JANI abstraction

tempestpy_adaptions
dehnert 8 years ago
parent
commit
ccf8631617
  1. 74
      src/storm/abstraction/AbstractionInformation.cpp
  2. 86
      src/storm/abstraction/AbstractionInformation.h
  3. 195
      src/storm/abstraction/ExpressionTranslator.cpp
  4. 53
      src/storm/abstraction/ExpressionTranslator.h
  5. 2
      src/storm/abstraction/LocalExpressionInformation.cpp
  6. 11
      src/storm/abstraction/MenuGameAbstractor.h
  7. 42
      src/storm/abstraction/StateSetAbstractor.cpp
  8. 2
      src/storm/abstraction/StateSetAbstractor.h
  9. 26
      src/storm/abstraction/jani/AutomatonAbstractor.cpp
  10. 20
      src/storm/abstraction/jani/AutomatonAbstractor.h
  11. 24
      src/storm/abstraction/jani/EdgeAbstractor.cpp
  12. 18
      src/storm/abstraction/jani/EdgeAbstractor.h
  13. 48
      src/storm/abstraction/jani/JaniAbstractionInformation.cpp
  14. 22
      src/storm/abstraction/jani/JaniMenuGameAbstractor.cpp
  15. 11
      src/storm/abstraction/jani/JaniMenuGameAbstractor.h
  16. 4
      src/storm/abstraction/prism/PrismMenuGameAbstractor.cpp
  17. 2
      src/storm/abstraction/prism/PrismMenuGameAbstractor.h
  18. 2
      src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp
  19. 4
      src/storm/storage/expressions/BaseExpression.cpp
  20. 6
      src/storm/storage/expressions/BaseExpression.h

74
src/storm/abstraction/AbstractionInformation.cpp

@ -14,13 +14,13 @@ namespace storm {
namespace abstraction { namespace abstraction {
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
AbstractionInformation<DdType>::AbstractionInformation(storm::expressions::ExpressionManager& expressionManager, std::set<storm::expressions::Variable> const& allVariables, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver, std::shared_ptr<storm::dd::DdManager<DdType>> ddManager) : expressionManager(expressionManager), equivalenceChecker(std::move(smtSolver)), variables(allVariables), ddManager(ddManager), allPredicateIdentities(ddManager->getBddOne()), expressionToBddMap() {
AbstractionInformation<DdType>::AbstractionInformation(storm::expressions::ExpressionManager& expressionManager, std::set<storm::expressions::Variable> const& abstractedVariables, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver, std::shared_ptr<storm::dd::DdManager<DdType>> ddManager) : expressionManager(expressionManager), equivalenceChecker(std::move(smtSolver)), abstractedVariables(abstractedVariables), ddManager(ddManager), allPredicateIdentities(ddManager->getBddOne()), expressionToBddMap() {
// Intentionally left empty. // Intentionally left empty.
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
void AbstractionInformation<DdType>::addExpressionVariable(storm::expressions::Variable const& variable) { void AbstractionInformation<DdType>::addExpressionVariable(storm::expressions::Variable const& variable) {
variables.insert(variable);
abstractedVariables.insert(variable);
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
@ -29,11 +29,6 @@ namespace storm {
addConstraint(constraint); addConstraint(constraint);
} }
template<storm::dd::DdType DdType>
std::set<storm::expressions::Variable> AbstractionInformation<DdType>::getExpressionVariables() const {
return variables;
}
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
void AbstractionInformation<DdType>::addConstraint(storm::expressions::Expression const& constraint) { void AbstractionInformation<DdType>::addConstraint(storm::expressions::Expression const& constraint) {
constraints.push_back(constraint); constraints.push_back(constraint);
@ -68,8 +63,8 @@ namespace storm {
allPredicateIdentities &= predicateIdentities.back(); allPredicateIdentities &= predicateIdentities.back();
sourceVariables.insert(newMetaVariable.first); sourceVariables.insert(newMetaVariable.first);
successorVariables.insert(newMetaVariable.second); successorVariables.insert(newMetaVariable.second);
orderedSourceVariables.push_back(newMetaVariable.first);
orderedSuccessorVariables.push_back(newMetaVariable.second);
orderedSourcePredicateVariables.push_back(newMetaVariable.first);
orderedSuccessorPredicateVariables.push_back(newMetaVariable.second);
ddVariableIndexToPredicateIndexMap[predicateIdentities.back().getIndex()] = predicateIndex; ddVariableIndexToPredicateIndexMap[predicateIdentities.back().getIndex()] = predicateIndex;
expressionToBddMap[predicate] = predicateBdds[predicateIndex].first && !bottomStateBdds.first; expressionToBddMap[predicate] = predicateBdds[predicateIndex].first && !bottomStateBdds.first;
@ -164,8 +159,8 @@ namespace storm {
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
std::set<storm::expressions::Variable> const& AbstractionInformation<DdType>::getVariables() const {
return variables;
std::set<storm::expressions::Variable> const& AbstractionInformation<DdType>::getAbstractedVariables() const {
return abstractedVariables;
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
@ -284,15 +279,15 @@ namespace storm {
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
std::vector<storm::expressions::Variable> const& AbstractionInformation<DdType>::getOrderedSuccessorVariables() const {
return orderedSuccessorVariables;
std::vector<storm::expressions::Variable> const& AbstractionInformation<DdType>::getOrderedSourcePredicateVariables() const {
return orderedSourcePredicateVariables;
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
std::vector<storm::expressions::Variable> const& AbstractionInformation<DdType>::getOrderedSourceVariables() const {
return orderedSourceVariables;
std::vector<storm::expressions::Variable> const& AbstractionInformation<DdType>::getOrderedSuccessorPredicateVariables() const {
return orderedSuccessorPredicateVariables;
} }
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
storm::dd::Bdd<DdType> const& AbstractionInformation<DdType>::getAllPredicateIdentities() const { storm::dd::Bdd<DdType> const& AbstractionInformation<DdType>::getAllPredicateIdentities() const {
return allPredicateIdentities; return allPredicateIdentities;
@ -432,8 +427,8 @@ namespace storm {
storm::dd::Add<DdType, double> add = state.template toAdd<double>(); storm::dd::Add<DdType, double> add = state.template toAdd<double>();
auto it = add.begin(); auto it = add.begin();
auto stateValuePair = *it; auto stateValuePair = *it;
for (uint_fast64_t index = 0; index < this->getOrderedSourceVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSourceVariables()[index];
for (uint_fast64_t index = 0; index < this->getOrderedSourcePredicateVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSourcePredicateVariables()[index];
if (stateValuePair.first.getBooleanValue(successorVariable)) { if (stateValuePair.first.getBooleanValue(successorVariable)) {
statePredicates.set(index); statePredicates.set(index);
} }
@ -452,8 +447,8 @@ namespace storm {
uint_fast64_t updateIndex = this->decodeAux(successorValuePair.first, 0, this->getAuxVariableCount()); uint_fast64_t updateIndex = this->decodeAux(successorValuePair.first, 0, this->getAuxVariableCount());
storm::storage::BitVector successor(this->getNumberOfPredicates()); storm::storage::BitVector successor(this->getNumberOfPredicates());
for (uint_fast64_t index = 0; index < this->getOrderedSuccessorVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSuccessorVariables()[index];
for (uint_fast64_t index = 0; index < this->getOrderedSuccessorPredicateVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSuccessorPredicateVariables()[index];
if (successorValuePair.first.getBooleanValue(successorVariable)) { if (successorValuePair.first.getBooleanValue(successorVariable)) {
successor.set(index); successor.set(index);
} }
@ -475,8 +470,8 @@ namespace storm {
auto stateValuePair = *it; auto stateValuePair = *it;
uint64_t choiceIndex = this->decodePlayer1Choice(stateValuePair.first, this->getPlayer1VariableCount()); uint64_t choiceIndex = this->decodePlayer1Choice(stateValuePair.first, this->getPlayer1VariableCount());
uint64_t updateIndex = this->decodeAux(stateValuePair.first, 0, this->getAuxVariableCount()); uint64_t updateIndex = this->decodeAux(stateValuePair.first, 0, this->getAuxVariableCount());
for (uint_fast64_t index = 0; index < this->getOrderedSourceVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSourceVariables()[index];
for (uint_fast64_t index = 0; index < this->getOrderedSourcePredicateVariables().size(); ++index) {
auto const& successorVariable = this->getOrderedSourcePredicateVariables()[index];
if (stateValuePair.first.getBooleanValue(successorVariable)) { if (stateValuePair.first.getBooleanValue(successorVariable)) {
statePredicates.set(index); statePredicates.set(index);
@ -486,6 +481,41 @@ namespace storm {
return std::make_tuple(statePredicates, choiceIndex, updateIndex); return std::make_tuple(statePredicates, choiceIndex, updateIndex);
} }
template <storm::dd::DdType DdType>
std::pair<std::pair<storm::expressions::Variable, storm::expressions::Variable>, uint64_t> AbstractionInformation<DdType>::addLocationVariables(uint64_t highestLocationIndex) {
locationVariablePairs.emplace_back(ddManager->addMetaVariable("loc_" + std::to_string(locationVariablePairs.size()), 0, highestLocationIndex));
allSourceLocationVariables.insert(locationVariablePairs.back().first);
sourceVariables.insert(locationVariablePairs.back().first);
allSuccessorLocationVariables.insert(locationVariablePairs.back().second);
successorVariables.insert(locationVariablePairs.back().second);
extendedPredicateDdVariables.emplace_back(locationVariablePairs.back());
return std::make_pair(locationVariablePairs.back(), locationVariablePairs.size() - 1);
}
template <storm::dd::DdType DdType>
storm::expressions::Variable AbstractionInformation<DdType>::getLocationVariable(uint64_t locationVariableIndex, bool source) const {
if (source) {
return locationVariablePairs[locationVariableIndex].first;
} else {
return locationVariablePairs[locationVariableIndex].second;
}
}
template <storm::dd::DdType DdType>
std::set<storm::expressions::Variable> const& AbstractionInformation<DdType>::getSourceLocationVariables() const {
return allSourceLocationVariables;
}
template <storm::dd::DdType DdType>
std::set<storm::expressions::Variable> const& AbstractionInformation<DdType>::getSuccessorLocationVariables() const {
return allSuccessorLocationVariables;
}
template <storm::dd::DdType DdType>
storm::dd::Bdd<DdType> AbstractionInformation<DdType>::encodeLocation(storm::expressions::Variable const& locationVariable, uint64_t locationIndex) const {
return this->getDdManager().getEncoding(locationVariable, locationIndex);
}
template class AbstractionInformation<storm::dd::DdType::CUDD>; template class AbstractionInformation<storm::dd::DdType::CUDD>;
template class AbstractionInformation<storm::dd::DdType::Sylvan>; template class AbstractionInformation<storm::dd::DdType::Sylvan>;

86
src/storm/abstraction/AbstractionInformation.h

@ -34,11 +34,11 @@ namespace storm {
* Creates a new abstraction information object. * Creates a new abstraction information object.
* *
* @param expressionManager The manager responsible for all variables and expressions during the abstraction process. * @param expressionManager The manager responsible for all variables and expressions during the abstraction process.
* @param allVariables All expression variables that can appear in predicates known to this object.
* @param abstractedVariables All expression variables that can appear in predicates known to this object.
* @param smtSolver An SMT solver that is used to detect equivalent predicates. * @param smtSolver An SMT solver that is used to detect equivalent predicates.
* @param ddManager The manager responsible for the DDs. * @param ddManager The manager responsible for the DDs.
*/ */
AbstractionInformation(storm::expressions::ExpressionManager& expressionManager, std::set<storm::expressions::Variable> const& allVariables, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver, std::shared_ptr<storm::dd::DdManager<DdType>> ddManager = std::make_shared<storm::dd::DdManager<DdType>>());
AbstractionInformation(storm::expressions::ExpressionManager& expressionManager, std::set<storm::expressions::Variable> const& abstractedVariables, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver, std::shared_ptr<storm::dd::DdManager<DdType>> ddManager = std::make_shared<storm::dd::DdManager<DdType>>());
/*! /*!
* Adds the given variable. * Adds the given variable.
@ -46,13 +46,6 @@ namespace storm {
* @param variable The variable to add. * @param variable The variable to add.
*/ */
void addExpressionVariable(storm::expressions::Variable const& variable); void addExpressionVariable(storm::expressions::Variable const& variable);
/*!
* Retrieves all known variables that may be used in predicates.
*
* @return All known variables.
*/
std::set<storm::expressions::Variable> getExpressionVariables() const;
/*! /*!
* Adds the given variable whose range is restricted. * Adds the given variable whose range is restricted.
@ -181,7 +174,7 @@ namespace storm {
* *
* @return The set of known variables. * @return The set of known variables.
*/ */
std::set<storm::expressions::Variable> const& getVariables() const;
std::set<storm::expressions::Variable> const& getAbstractedVariables() const;
/*! /*!
* Creates the given number of variables used to encode the choices of player 1/2 and auxiliary information. * Creates the given number of variables used to encode the choices of player 1/2 and auxiliary information.
@ -347,20 +340,6 @@ namespace storm {
* @return All successor meta variables. * @return All successor meta variables.
*/ */
std::set<storm::expressions::Variable> const& getSuccessorVariables() const; std::set<storm::expressions::Variable> const& getSuccessorVariables() const;
/*!
* Retrieves the ordered collection of source meta variables.
*
* @return All source meta variables.
*/
std::vector<storm::expressions::Variable> const& getOrderedSourceVariables() const;
/*!
* Retrieves the ordered collection of successor meta variables.
*
* @return All successor meta variables.
*/
std::vector<storm::expressions::Variable> const& getOrderedSuccessorVariables() const;
/*! /*!
* Retrieves a BDD representing the identities of all predicates. * Retrieves a BDD representing the identities of all predicates.
@ -466,7 +445,46 @@ namespace storm {
*/ */
std::tuple<storm::storage::BitVector, uint64_t, uint64_t> decodeStatePlayer1ChoiceAndUpdate(storm::dd::Bdd<DdType> const& stateChoiceAndUpdate) const; std::tuple<storm::storage::BitVector, uint64_t, uint64_t> decodeStatePlayer1ChoiceAndUpdate(storm::dd::Bdd<DdType> const& stateChoiceAndUpdate) const;
private:
/*!
* Adds a location variable of appropriate range and returns the pair of meta variables.
*/
std::pair<std::pair<storm::expressions::Variable, storm::expressions::Variable>, uint64_t> addLocationVariables(uint64_t highestLocationIndex);
/*!
* Retrieves the location variable with the given index as either source or successor.
*/
storm::expressions::Variable getLocationVariable(uint64_t locationVariableIndex, bool source) const;
/*!
* Retrieves the source location variables.
*/
std::set<storm::expressions::Variable> const& getSourceLocationVariables() const;
/*!
* Retrieves the source location variables.
*/
std::set<storm::expressions::Variable> const& getSuccessorLocationVariables() const;
/*!
* Encodes the given location index as either source or successor.
*/
storm::dd::Bdd<DdType> encodeLocation(storm::expressions::Variable const& locationVariable, uint64_t locationIndex) const;
protected:
/*!
* Retrieves the ordered collection of source predicate meta variables.
*
* @return All source meta variables.
*/
std::vector<storm::expressions::Variable> const& getOrderedSourcePredicateVariables() const;
/*!
* Retrieves the ordered collection of successor predicate meta variables.
*
* @return All successor meta variables.
*/
std::vector<storm::expressions::Variable> const& getOrderedSuccessorPredicateVariables() const;
/*! /*!
* Encodes the given index with the given number of variables from the given variables. * Encodes the given index with the given number of variables from the given variables.
* *
@ -503,8 +521,8 @@ namespace storm {
/// The current set of predicates used in the abstraction. /// The current set of predicates used in the abstraction.
std::vector<storm::expressions::Expression> predicates; std::vector<storm::expressions::Expression> predicates;
/// The set of all variables.
std::set<storm::expressions::Variable> variables;
/// The set of all abstracted variables.
std::set<storm::expressions::Variable> abstractedVariables;
/// The expressions characterizing legal variable values. /// The expressions characterizing legal variable values.
std::vector<storm::expressions::Expression> constraints; std::vector<storm::expressions::Expression> constraints;
@ -527,10 +545,10 @@ namespace storm {
std::set<storm::expressions::Variable> successorVariables; std::set<storm::expressions::Variable> successorVariables;
/// An ordered collection of the source variables. /// An ordered collection of the source variables.
std::vector<storm::expressions::Variable> orderedSourceVariables;
std::vector<storm::expressions::Variable> orderedSourcePredicateVariables;
/// An ordered collection of the successor variables. /// An ordered collection of the successor variables.
std::vector<storm::expressions::Variable> orderedSuccessorVariables;
std::vector<storm::expressions::Variable> orderedSuccessorPredicateVariables;
/// The BDDs corresponding to the predicates. /// The BDDs corresponding to the predicates.
std::vector<std::pair<storm::dd::Bdd<DdType>, storm::dd::Bdd<DdType>>> predicateBdds; std::vector<std::pair<storm::dd::Bdd<DdType>, storm::dd::Bdd<DdType>>> predicateBdds;
@ -570,6 +588,16 @@ namespace storm {
/// A mapping from expressions to the corresponding BDDs. /// A mapping from expressions to the corresponding BDDs.
std::map<storm::expressions::Expression, storm::dd::Bdd<DdType>> expressionToBddMap; std::map<storm::expressions::Expression, storm::dd::Bdd<DdType>> expressionToBddMap;
/// The location variable pairs (source/successor).
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> locationVariablePairs;
// All source location variables.
std::set<storm::expressions::Variable> allSourceLocationVariables;
// All successor location variables.
std::set<storm::expressions::Variable> allSuccessorLocationVariables;
}; };
} }

195
src/storm/abstraction/ExpressionTranslator.cpp

@ -0,0 +1,195 @@
#include "storm/abstraction/ExpressionTranslator.h"
#include "storm/abstraction/AbstractionInformation.h"
#include "storm/storage/dd/DdManager.h"
#include "storm/storage/dd/Bdd.h"
#include "storm/storage/expressions/Expression.h"
#include "storm/utility/macros.h"
#include "storm/exceptions/NotSupportedException.h"
namespace storm {
namespace abstraction {
using namespace storm::expressions;
template <storm::dd::DdType DdType>
ExpressionTranslator<DdType>::ExpressionTranslator(AbstractionInformation<DdType>& abstractionInformation, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver) : abstractionInformation(abstractionInformation), equivalenceChecker(std::move(smtSolver)), locationVariables(abstractionInformation.getSourceLocationVariables()), abstractedVariables(abstractionInformation.getAbstractedVariables()) {
// Intentionally left empty.
}
template <storm::dd::DdType DdType>
storm::dd::Bdd<DdType> ExpressionTranslator<DdType>::translate(storm::expressions::Expression const& expression) {
return boost::any_cast<storm::dd::Bdd<DdType>>(expression.accept(*this, boost::none));
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(IfThenElseExpression const& expression, boost::any const& data) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(BinaryBooleanFunctionExpression const& expression, boost::any const& data) {
// Check whether the expression is either fully contained in the location variables fragment or the abstracted
// variables fragment.
std::set<storm::expressions::Variable> variablesInExpression;
expression.gatherVariables(variablesInExpression);
std::set<storm::expressions::Variable> tmp;
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), locationVariables.begin(), locationVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasLocationVariables = !tmp.empty();
tmp.clear();
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), abstractedVariables.begin(), abstractedVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasAbstractedVariables = !tmp.empty();
STORM_LOG_THROW(hasLocationVariables || hasAbstractedVariables, storm::exceptions::NotSupportedException, "Expressions without variables are currently not supported by the abstraction expression translator.");
if (hasAbstractedVariables && !hasLocationVariables) {
for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.get().getNumberOfPredicates(); ++predicateIndex) {
if (equivalenceChecker.areEquivalent(abstractionInformation.get().getPredicateByIndex(predicateIndex), expression.toExpression())) {
return abstractionInformation.get().encodePredicateAsSource(predicateIndex);
}
}
// At this point, none of the predicates was found to be equivalent, so we split the expression.
}
storm::dd::Bdd<DdType> left = boost::any_cast<storm::dd::Bdd<DdType>>(expression.getFirstOperand()->accept(*this, boost::none));
storm::dd::Bdd<DdType> right = boost::any_cast<storm::dd::Bdd<DdType>>(expression.getFirstOperand()->accept(*this, boost::none));
switch (expression.getOperatorType()) {
case BinaryBooleanFunctionExpression::OperatorType::And: return left && right;
case BinaryBooleanFunctionExpression::OperatorType::Or: return left || right;
case BinaryBooleanFunctionExpression::OperatorType::Xor: return left.exclusiveOr(right);
case BinaryBooleanFunctionExpression::OperatorType::Implies: return !left || right;
case BinaryBooleanFunctionExpression::OperatorType::Iff: return (left && right) || (!left && !right);
}
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(BinaryNumericalFunctionExpression const& expression, boost::any const& data) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(BinaryRelationExpression const& expression, boost::any const& data) {
// Check whether the expression is either fully contained in the location variables fragment or the abstracted
// variables fragment.
std::set<storm::expressions::Variable> variablesInExpression;
expression.gatherVariables(variablesInExpression);
std::set<storm::expressions::Variable> tmp;
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), locationVariables.begin(), locationVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasLocationVariables = !tmp.empty();
tmp.clear();
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), abstractedVariables.begin(), abstractedVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasAbstractedVariables = !tmp.empty();
STORM_LOG_THROW(hasLocationVariables || hasAbstractedVariables, storm::exceptions::NotSupportedException, "Expressions without variables are currently not supported by the abstraction expression translator.");
STORM_LOG_THROW(!hasLocationVariables || !hasAbstractedVariables, storm::exceptions::NotSupportedException, "Expressions with two types (location variables and abstracted variables) of variables are currently not supported by the abstraction expression translator.");
if (hasLocationVariables) {
storm::dd::Add<DdType, double> left = boost::any_cast<storm::dd::Add<DdType, double>>(expression.getFirstOperand()->accept(*this, boost::none));
storm::dd::Add<DdType, double> right = boost::any_cast<storm::dd::Add<DdType, double>>(expression.getFirstOperand()->accept(*this, boost::none));
switch (expression.getRelationType()) {
case BinaryRelationExpression::RelationType::Equal: return left.equals(right);
case BinaryRelationExpression::RelationType::NotEqual: return left.notEquals(right);
case BinaryRelationExpression::RelationType::Less: return left.less(right);
case BinaryRelationExpression::RelationType::LessOrEqual: return left.lessOrEqual(right);
case BinaryRelationExpression::RelationType::Greater: return left.greater(right);
case BinaryRelationExpression::RelationType::GreaterOrEqual: return left.greaterOrEqual(right);
}
} else {
for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.get().getNumberOfPredicates(); ++predicateIndex) {
if (equivalenceChecker.areEquivalent(abstractionInformation.get().getPredicateByIndex(predicateIndex), expression.toExpression())) {
return abstractionInformation.get().encodePredicateAsSource(predicateIndex);
}
}
// At this point, none of the predicates was found to be equivalent, but there is no need to split as the subexpressions are not valid predicates.
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
}
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(VariableExpression const& expression, boost::any const& data) {
if (abstractedVariables.find(expression.getVariable()) != abstractedVariables.end()) {
for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.get().getNumberOfPredicates(); ++predicateIndex) {
if (equivalenceChecker.areEquivalent(abstractionInformation.get().getPredicateByIndex(predicateIndex), expression.toExpression())) {
return abstractionInformation.get().encodePredicateAsSource(predicateIndex);
}
}
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
} else {
return abstractionInformation.get().getDdManager().template getIdentity<double>(expression.getVariable());
}
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(UnaryBooleanFunctionExpression const& expression, boost::any const& data) {
// Check whether the expression is either fully contained in the location variables fragment or the abstracted
// variables fragment.
std::set<storm::expressions::Variable> variablesInExpression;
expression.gatherVariables(variablesInExpression);
std::set<storm::expressions::Variable> tmp;
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), locationVariables.begin(), locationVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasLocationVariables = !tmp.empty();
tmp.clear();
std::set_intersection(variablesInExpression.begin(), variablesInExpression.end(), abstractedVariables.begin(), abstractedVariables.end(), std::inserter(tmp, tmp.begin()));
bool hasAbstractedVariables = !tmp.empty();
STORM_LOG_THROW(hasLocationVariables || hasAbstractedVariables, storm::exceptions::NotSupportedException, "Expressions without variables are currently not supported by the abstraction expression translator.");
if (hasAbstractedVariables && !hasLocationVariables) {
for (uint64_t predicateIndex = 0; predicateIndex < abstractionInformation.get().getNumberOfPredicates(); ++predicateIndex) {
if (equivalenceChecker.areEquivalent(abstractionInformation.get().getPredicateByIndex(predicateIndex), expression.toExpression())) {
return abstractionInformation.get().encodePredicateAsSource(predicateIndex);
}
}
// At this point, none of the predicates was found to be equivalent, so we split the expression.
}
storm::dd::Bdd<DdType> sub = boost::any_cast<storm::dd::Bdd<DdType>>(expression.getOperand()->accept(*this, boost::none));
switch (expression.getOperatorType()) {
case UnaryBooleanFunctionExpression::OperatorType::Not: return !sub;
}
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(UnaryNumericalFunctionExpression const& expression, boost::any const& data) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(BooleanLiteralExpression const& expression, boost::any const& data) {
if (expression.isTrue()) {
return abstractionInformation.get().getDdManager().getBddOne();
} else {
return abstractionInformation.get().getDdManager().getBddZero();
}
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(IntegerLiteralExpression const& expression, boost::any const& data) {
return abstractionInformation.get().getDdManager().template getConstant(expression.getValue());
}
template <storm::dd::DdType DdType>
boost::any ExpressionTranslator<DdType>::visit(RationalLiteralExpression const& expression, boost::any const& data) {
STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Expressions of this kind are currently not supported by the abstraction expression translator.");
}
template class ExpressionTranslator<storm::dd::DdType::CUDD>;
template class ExpressionTranslator<storm::dd::DdType::Sylvan>;
}
}

53
src/storm/abstraction/ExpressionTranslator.h

@ -0,0 +1,53 @@
#pragma once
#include <set>
#include "storm/storage/dd/DdType.h"
#include "storm/storage/expressions/ExpressionVisitor.h"
#include "storm/storage/expressions/EquivalenceChecker.h"
#include "storm/solver/SmtSolver.h"
namespace storm {
namespace dd {
template<storm::dd::DdType DdType>
class Bdd;
}
namespace expressions {
class Expression;
}
namespace abstraction {
template<storm::dd::DdType DdType>
class AbstractionInformation;
template <storm::dd::DdType DdType>
class ExpressionTranslator : public storm::expressions::ExpressionVisitor {
public:
ExpressionTranslator(AbstractionInformation<DdType>& abstractionInformation, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver);
storm::dd::Bdd<DdType> translate(storm::expressions::Expression const& expression);
virtual boost::any visit(storm::expressions::IfThenElseExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::BinaryBooleanFunctionExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::BinaryNumericalFunctionExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::BinaryRelationExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::VariableExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::UnaryBooleanFunctionExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::UnaryNumericalFunctionExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::BooleanLiteralExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::IntegerLiteralExpression const& expression, boost::any const& data);
virtual boost::any visit(storm::expressions::RationalLiteralExpression const& expression, boost::any const& data);
private:
std::reference_wrapper<AbstractionInformation<DdType>> abstractionInformation;
storm::expressions::EquivalenceChecker equivalenceChecker;
std::set<storm::expressions::Variable> locationVariables;
std::set<storm::expressions::Variable> abstractedVariables;
};
}
}

2
src/storm/abstraction/LocalExpressionInformation.cpp

@ -10,7 +10,7 @@ namespace storm {
namespace abstraction { namespace abstraction {
template <storm::dd::DdType DdType> template <storm::dd::DdType DdType>
LocalExpressionInformation<DdType>::LocalExpressionInformation(AbstractionInformation<DdType> const& abstractionInformation) : relevantVariables(abstractionInformation.getVariables()), expressionBlocks(relevantVariables.size()), abstractionInformation(abstractionInformation) {
LocalExpressionInformation<DdType>::LocalExpressionInformation(AbstractionInformation<DdType> const& abstractionInformation) : relevantVariables(abstractionInformation.getAbstractedVariables()), expressionBlocks(relevantVariables.size()), abstractionInformation(abstractionInformation) {
// Assign each variable to a new block. // Assign each variable to a new block.
uint_fast64_t currentBlock = 0; uint_fast64_t currentBlock = 0;
variableBlocks.resize(relevantVariables.size()); variableBlocks.resize(relevantVariables.size());

11
src/storm/abstraction/MenuGameAbstractor.h

@ -11,6 +11,11 @@
#include "storm/storage/expressions/Expression.h" #include "storm/storage/expressions/Expression.h"
namespace storm { namespace storm {
namespace dd {
template <storm::dd::DdType DdType>
class Bdd;
}
namespace abstraction { namespace abstraction {
template <storm::dd::DdType DdType> template <storm::dd::DdType DdType>
@ -29,6 +34,12 @@ namespace storm {
virtual std::map<storm::expressions::Variable, storm::expressions::Expression> getVariableUpdates(uint64_t player1Choice, uint64_t auxiliaryChoice) const = 0; virtual std::map<storm::expressions::Variable, storm::expressions::Expression> getVariableUpdates(uint64_t player1Choice, uint64_t auxiliaryChoice) const = 0;
virtual storm::expressions::Expression getInitialExpression() const = 0; virtual storm::expressions::Expression getInitialExpression() const = 0;
/*!
* Retrieves a BDD that characterizes the states corresponding to the given expression. For this to work,
* appropriate predicates must have been used to refine the abstraction, otherwise this will fail.
*/
virtual storm::dd::Bdd<DdType> getStates(storm::expressions::Expression const& expression) const = 0;
/// Methods to refine the abstraction. /// Methods to refine the abstraction.
virtual void refine(RefinementCommand const& command) = 0; virtual void refine(RefinementCommand const& command) = 0;

42
src/storm/abstraction/StateSetAbstractor.cpp

@ -14,7 +14,7 @@ namespace storm {
namespace abstraction { namespace abstraction {
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
StateSetAbstractor<DdType, ValueType>::StateSetAbstractor(AbstractionInformation<DdType>& abstractionInformation, std::vector<storm::expressions::Expression> const& statePredicates, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())), abstractionInformation(abstractionInformation), localExpressionInformation(abstractionInformation), relevantPredicatesAndVariables(), concretePredicateVariables(), needsRecomputation(false), cachedBdd(abstractionInformation.getDdManager().getBddOne()), constraint(abstractionInformation.getDdManager().getBddOne()) {
StateSetAbstractor<DdType, ValueType>::StateSetAbstractor(AbstractionInformation<DdType>& abstractionInformation, std::vector<storm::expressions::Expression> const& statePredicates, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())), abstractionInformation(abstractionInformation), localExpressionInformation(abstractionInformation), relevantPredicatesAndVariables(), concretePredicateVariables(), forceRecomputation(true), cachedBdd(abstractionInformation.getDdManager().getBddOne()), constraint(abstractionInformation.getDdManager().getBddOne()) {
// Assert all state predicates. // Assert all state predicates.
for (auto const& predicate : statePredicates) { for (auto const& predicate : statePredicates) {
@ -46,7 +46,22 @@ namespace storm {
for (auto const& predicateIndex : newPredicates) { for (auto const& predicateIndex : newPredicates) {
localExpressionInformation.addExpression(predicateIndex); localExpressionInformation.addExpression(predicateIndex);
} }
needsRecomputation = true;
std::set<uint_fast64_t> newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables);
// Since the number of relevant predicates is monotonic, we can simply check for the size here.
STORM_LOG_ASSERT(newRelevantPredicateIndices.size() >= relevantPredicatesAndVariables.size(), "Illegal size of relevant predicates.");
if (newRelevantPredicateIndices.size() > relevantPredicatesAndVariables.size()) {
// Before adding the missing predicates, we need to remove the constraint BDD.
this->popConstraintBdd();
// If we need to recompute the BDD, we start by introducing decision variables and the corresponding
// constraints in the SMT problem.
addMissingPredicates(newRelevantPredicateIndices);
// Then re-add the constraint BDD.
this->pushConstraintBdd();
forceRecomputation = true;
}
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
@ -78,27 +93,6 @@ namespace storm {
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
void StateSetAbstractor<DdType, ValueType>::recomputeCachedBdd() { void StateSetAbstractor<DdType, ValueType>::recomputeCachedBdd() {
// Now check whether we need to recompute the cached BDD.
std::set<uint_fast64_t> newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables);
// Since the number of relevant predicates is monotonic, we can simply check for the size here.
STORM_LOG_ASSERT(newRelevantPredicateIndices.size() >= relevantPredicatesAndVariables.size(), "Illegal size of relevant predicates.");
bool recomputeBdd = newRelevantPredicateIndices.size() > relevantPredicatesAndVariables.size();
if (!recomputeBdd) {
return;
}
// Before adding the missing predicates, we need to remove the constraint BDD.
this->popConstraintBdd();
// If we need to recompute the BDD, we start by introducing decision variables and the corresponding
// constraints in the SMT problem.
addMissingPredicates(newRelevantPredicateIndices);
// Then re-add the constraint BDD.
this->pushConstraintBdd();
STORM_LOG_TRACE("Recomputing BDD for state set abstraction."); STORM_LOG_TRACE("Recomputing BDD for state set abstraction.");
storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero(); storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero();
@ -141,7 +135,7 @@ namespace storm {
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getAbstractStates() { storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getAbstractStates() {
if (needsRecomputation) {
if (forceRecomputation) {
this->recomputeCachedBdd(); this->recomputeCachedBdd();
} }
return cachedBdd; return cachedBdd;

2
src/storm/abstraction/StateSetAbstractor.h

@ -146,7 +146,7 @@ namespace storm {
std::vector<storm::expressions::Variable> decisionVariables; std::vector<storm::expressions::Variable> decisionVariables;
// A flag indicating whether the cached BDD needs recomputation. // A flag indicating whether the cached BDD needs recomputation.
bool needsRecomputation;
bool forceRecomputation;
// The cached BDD representing the abstraction. This variable is written to in refinement steps (if work // The cached BDD representing the abstraction. This variable is written to in refinement steps (if work
// needed to be done). // needed to be done).

26
src/storm/abstraction/jani/AutomatonAbstractor.cpp

@ -2,7 +2,7 @@
#include "storm/abstraction/BottomStateResult.h" #include "storm/abstraction/BottomStateResult.h"
#include "storm/abstraction/GameBddResult.h" #include "storm/abstraction/GameBddResult.h"
#include "storm/abstraction/jani/JaniAbstractionInformation.h"
#include "storm/abstraction/AbstractionInformation.h"
#include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/DdManager.h"
#include "storm/storage/dd/Add.h" #include "storm/storage/dd/Add.h"
@ -23,7 +23,7 @@ namespace storm {
using storm::settings::modules::AbstractionSettings; using storm::settings::modules::AbstractionSettings;
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
AutomatonAbstractor<DdType, ValueType>::AutomatonAbstractor(storm::jani::Automaton const& automaton, JaniAbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition) : smtSolverFactory(smtSolverFactory), abstractionInformation(abstractionInformation), edges(), automaton(automaton) {
AutomatonAbstractor<DdType, ValueType>::AutomatonAbstractor(storm::jani::Automaton const& automaton, AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition) : smtSolverFactory(smtSolverFactory), abstractionInformation(abstractionInformation), edges(), automaton(automaton) {
// For each concrete command, we create an abstract counterpart. // For each concrete command, we create an abstract counterpart.
uint64_t edgeId = 0; uint64_t edgeId = 0;
@ -31,6 +31,10 @@ namespace storm {
edges.emplace_back(edgeId, edge, abstractionInformation, smtSolverFactory, useDecomposition); edges.emplace_back(edgeId, edge, abstractionInformation, smtSolverFactory, useDecomposition);
++edgeId; ++edgeId;
} }
if (automaton.getNumberOfLocations() > 1) {
locationVariables = abstractionInformation.addLocationVariables(automaton.getNumberOfLocations() - 1).first;
}
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
@ -87,7 +91,21 @@ namespace storm {
storm::dd::Add<DdType, ValueType> AutomatonAbstractor<DdType, ValueType>::getEdgeDecoratorAdd() const { storm::dd::Add<DdType, ValueType> AutomatonAbstractor<DdType, ValueType>::getEdgeDecoratorAdd() const {
storm::dd::Add<DdType, ValueType> result = this->getAbstractionInformation().getDdManager().template getAddZero<ValueType>(); storm::dd::Add<DdType, ValueType> result = this->getAbstractionInformation().getDdManager().template getAddZero<ValueType>();
for (auto const& edge : edges) { for (auto const& edge : edges) {
result += edge.getEdgeDecoratorAdd();
result += edge.getEdgeDecoratorAdd(locationVariables);
}
return result;
}
template <storm::dd::DdType DdType, typename ValueType>
storm::dd::Bdd<DdType> AutomatonAbstractor<DdType, ValueType>::getInitialLocationsBdd() const {
if (automaton.get().getNumberOfLocations()) {
return this->getAbstractionInformation().getDdManager().getBddOne();
}
std::set<uint64_t> const& initialLocationIndices = automaton.get().getInitialLocationIndices();
storm::dd::Bdd<DdType> result = this->getAbstractionInformation().getDdManager().getBddZero();
for (auto const& initialLocationIndex : initialLocationIndices) {
result |= this->getAbstractionInformation().encodeLocation(locationVariables.get().first, initialLocationIndex);
} }
return result; return result;
} }
@ -108,7 +126,7 @@ namespace storm {
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
JaniAbstractionInformation<DdType> const& AutomatonAbstractor<DdType, ValueType>::getAbstractionInformation() const {
AbstractionInformation<DdType> const& AutomatonAbstractor<DdType, ValueType>::getAbstractionInformation() const {
return abstractionInformation.get(); return abstractionInformation.get();
} }

20
src/storm/abstraction/jani/AutomatonAbstractor.h

@ -17,13 +17,13 @@ namespace storm {
} }
namespace abstraction { namespace abstraction {
template <storm::dd::DdType DdType>
class AbstractionInformation;
template<storm::dd::DdType DdType> template<storm::dd::DdType DdType>
struct BottomStateResult; struct BottomStateResult;
namespace jani { namespace jani {
template <storm::dd::DdType DdType>
class JaniAbstractionInformation;
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
class AutomatonAbstractor { class AutomatonAbstractor {
public: public:
@ -35,7 +35,7 @@ namespace storm {
* @param smtSolverFactory A factory that is to be used for creating new SMT solvers. * @param smtSolverFactory A factory that is to be used for creating new SMT solvers.
* @param useDecomposition A flag indicating whether to use the decomposition during abstraction. * @param useDecomposition A flag indicating whether to use the decomposition during abstraction.
*/ */
AutomatonAbstractor(storm::jani::Automaton const& automaton, JaniAbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition);
AutomatonAbstractor(storm::jani::Automaton const& automaton, AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition);
AutomatonAbstractor(AutomatonAbstractor const&) = default; AutomatonAbstractor(AutomatonAbstractor const&) = default;
AutomatonAbstractor& operator=(AutomatonAbstractor const&) = default; AutomatonAbstractor& operator=(AutomatonAbstractor const&) = default;
@ -86,6 +86,11 @@ namespace storm {
*/ */
storm::dd::Add<DdType, ValueType> getEdgeDecoratorAdd() const; storm::dd::Add<DdType, ValueType> getEdgeDecoratorAdd() const;
/*!
* Retrieves a BDD that encodes all initial locations of this abstract automaton.
*/
storm::dd::Bdd<DdType> getInitialLocationsBdd() const;
/*! /*!
* Retrieves the abstract edges of this abstract automton. * Retrieves the abstract edges of this abstract automton.
* *
@ -113,19 +118,22 @@ namespace storm {
* *
* @return The abstraction information. * @return The abstraction information.
*/ */
JaniAbstractionInformation<DdType> const& getAbstractionInformation() const;
AbstractionInformation<DdType> const& getAbstractionInformation() const;
// A factory that can be used to create new SMT solvers. // A factory that can be used to create new SMT solvers.
std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory; std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory;
// The DD-related information. // The DD-related information.
std::reference_wrapper<JaniAbstractionInformation<DdType> const> abstractionInformation;
std::reference_wrapper<AbstractionInformation<DdType> const> abstractionInformation;
// The abstract edge of the abstract automaton. // The abstract edge of the abstract automaton.
std::vector<EdgeAbstractor<DdType, ValueType>> edges; std::vector<EdgeAbstractor<DdType, ValueType>> edges;
// The concrete module this abstract automaton refers to. // The concrete module this abstract automaton refers to.
std::reference_wrapper<storm::jani::Automaton const> automaton; std::reference_wrapper<storm::jani::Automaton const> automaton;
// If the automaton has more than one location, we need variables to encode that.
boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>> locationVariables;
}; };
} }
} }

24
src/storm/abstraction/jani/EdgeAbstractor.cpp

@ -5,7 +5,7 @@
#include <boost/iterator/transform_iterator.hpp> #include <boost/iterator/transform_iterator.hpp>
#include "storm/abstraction/BottomStateResult.h" #include "storm/abstraction/BottomStateResult.h"
#include "storm/abstraction/jani/JaniAbstractionInformation.h"
#include "storm/abstraction/AbstractionInformation.h"
#include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/DdManager.h"
#include "storm/storage/dd/Add.h" #include "storm/storage/dd/Add.h"
@ -23,7 +23,7 @@ namespace storm {
namespace abstraction { namespace abstraction {
namespace jani { namespace jani {
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
EdgeAbstractor<DdType, ValueType>::EdgeAbstractor(uint64_t edgeId, storm::jani::Edge const& edge, JaniAbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition) : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())), abstractionInformation(abstractionInformation), edgeId(edgeId), edge(edge), localExpressionInformation(abstractionInformation), evaluator(abstractionInformation.getExpressionManager()), relevantPredicatesAndVariables(), cachedDd(abstractionInformation.getDdManager().getBddZero(), 0), decisionVariables(), useDecomposition(useDecomposition), skipBottomStates(false), forceRecomputation(true), abstractGuard(abstractionInformation.getDdManager().getBddZero()), bottomStateAbstractor(abstractionInformation, {!edge.getGuard()}, smtSolverFactory) {
EdgeAbstractor<DdType, ValueType>::EdgeAbstractor(uint64_t edgeId, storm::jani::Edge const& edge, AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition) : smtSolver(smtSolverFactory->create(abstractionInformation.getExpressionManager())), abstractionInformation(abstractionInformation), edgeId(edgeId), edge(edge), localExpressionInformation(abstractionInformation), evaluator(abstractionInformation.getExpressionManager()), relevantPredicatesAndVariables(), cachedDd(abstractionInformation.getDdManager().getBddZero(), 0), decisionVariables(), useDecomposition(useDecomposition), skipBottomStates(false), forceRecomputation(true), abstractGuard(abstractionInformation.getDdManager().getBddZero()), bottomStateAbstractor(abstractionInformation, {!edge.getGuard()}, smtSolverFactory) {
// Make the second component of relevant predicates have the right size. // Make the second component of relevant predicates have the right size.
relevantPredicatesAndVariables.second.resize(edge.getNumberOfDestinations()); relevantPredicatesAndVariables.second.resize(edge.getNumberOfDestinations());
@ -653,12 +653,22 @@ namespace storm {
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
storm::dd::Add<DdType, ValueType> EdgeAbstractor<DdType, ValueType>::getEdgeDecoratorAdd() const {
storm::dd::Add<DdType, ValueType> EdgeAbstractor<DdType, ValueType>::getEdgeDecoratorAdd(boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& locationVariables) const {
storm::dd::Add<DdType, ValueType> result = this->getAbstractionInformation().getDdManager().template getAddZero<ValueType>(); storm::dd::Add<DdType, ValueType> result = this->getAbstractionInformation().getDdManager().template getAddZero<ValueType>();
for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) { for (uint_fast64_t destinationIndex = 0; destinationIndex < edge.get().getNumberOfDestinations(); ++destinationIndex) {
result += this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount()).template toAdd<ValueType>() * this->getAbstractionInformation().getDdManager().getConstant(evaluator.asRational(edge.get().getDestination(destinationIndex).getProbability())) * this->getAbstractionInformation().encodeLocation(edge.get().getDestination(destinationIndex).getLocationIndex(), false).template toAdd<ValueType>();
result += this->getAbstractionInformation().encodeAux(destinationIndex, 0, this->getAbstractionInformation().getAuxVariableCount()).template toAdd<ValueType>() * this->getAbstractionInformation().getDdManager().getConstant(evaluator.asRational(edge.get().getDestination(destinationIndex).getProbability()));
if (locationVariables) {
result *= this->getAbstractionInformation().encodeLocation(locationVariables.get().second, edge.get().getDestination(destinationIndex).getLocationIndex()).template toAdd<ValueType>();
}
}
storm::dd::Add<DdType, ValueType> tmp = this->getAbstractionInformation().getDdManager().template getAddOne<ValueType>();
if (locationVariables) {
tmp *= this->getAbstractionInformation().encodeLocation(locationVariables.get().first, edge.get().getSourceLocationIndex()).template toAdd<ValueType>();
} }
result *= this->getAbstractionInformation().encodeLocation(edge.get().getSourceLocationIndex(), true).template toAdd<ValueType>() * this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount()).template toAdd<ValueType>();
tmp *= this->getAbstractionInformation().encodePlayer1Choice(edgeId, this->getAbstractionInformation().getPlayer1VariableCount()).template toAdd<ValueType>();
result *= tmp;
return result; return result;
} }
@ -668,12 +678,12 @@ namespace storm {
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
JaniAbstractionInformation<DdType> const& EdgeAbstractor<DdType, ValueType>::getAbstractionInformation() const {
AbstractionInformation<DdType> const& EdgeAbstractor<DdType, ValueType>::getAbstractionInformation() const {
return abstractionInformation.get(); return abstractionInformation.get();
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
JaniAbstractionInformation<DdType>& EdgeAbstractor<DdType, ValueType>::getAbstractionInformation() {
AbstractionInformation<DdType>& EdgeAbstractor<DdType, ValueType>::getAbstractionInformation() {
return abstractionInformation.get(); return abstractionInformation.get();
} }

18
src/storm/abstraction/jani/EdgeAbstractor.h

@ -39,13 +39,13 @@ namespace storm {
} }
namespace abstraction { namespace abstraction {
template <storm::dd::DdType DdType>
class AbstractionInformation;
template <storm::dd::DdType DdType> template <storm::dd::DdType DdType>
class BottomStateResult; class BottomStateResult;
namespace jani { namespace jani {
template <storm::dd::DdType DdType>
class JaniAbstractionInformation;
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
class EdgeAbstractor { class EdgeAbstractor {
public: public:
@ -58,7 +58,7 @@ namespace storm {
* @param smtSolverFactory A factory that is to be used for creating new SMT solvers. * @param smtSolverFactory A factory that is to be used for creating new SMT solvers.
* @param useDecomposition A flag indicating whether to use an edge decomposition during abstraction. * @param useDecomposition A flag indicating whether to use an edge decomposition during abstraction.
*/ */
EdgeAbstractor(uint64_t edgeId, storm::jani::Edge const& edge, JaniAbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition);
EdgeAbstractor(uint64_t edgeId, storm::jani::Edge const& edge, AbstractionInformation<DdType>& abstractionInformation, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory, bool useDecomposition);
/*! /*!
* Refines the abstract edge with the given predicates. * Refines the abstract edge with the given predicates.
@ -98,9 +98,11 @@ namespace storm {
/*! /*!
* Retrieves an ADD that maps the encoding of the edge, source/target locations and its updates to their probabilities. * Retrieves an ADD that maps the encoding of the edge, source/target locations and its updates to their probabilities.
* *
* @param locationVariables If provided, the location variables are used to encode the source/destination locations of the edge
* and its destinations.
* @return The decorator ADD. * @return The decorator ADD.
*/ */
storm::dd::Add<DdType, ValueType> getEdgeDecoratorAdd() const;
storm::dd::Add<DdType, ValueType> getEdgeDecoratorAdd(boost::optional<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& locationVariables) const;
/*! /*!
* Retrieves the concrete edge that is abstracted by this abstract edge. * Retrieves the concrete edge that is abstracted by this abstract edge.
@ -194,14 +196,14 @@ namespace storm {
* *
* @return The abstraction information object. * @return The abstraction information object.
*/ */
JaniAbstractionInformation<DdType> const& getAbstractionInformation() const;
AbstractionInformation<DdType> const& getAbstractionInformation() const;
/*! /*!
* Retrieves the abstraction information object. * Retrieves the abstraction information object.
* *
* @return The abstraction information object. * @return The abstraction information object.
*/ */
JaniAbstractionInformation<DdType>& getAbstractionInformation();
AbstractionInformation<DdType>& getAbstractionInformation();
/*! /*!
* Computes the globally missing state identities. * Computes the globally missing state identities.
@ -215,7 +217,7 @@ namespace storm {
std::unique_ptr<storm::solver::SmtSolver> smtSolver; std::unique_ptr<storm::solver::SmtSolver> smtSolver;
// The abstraction-related information. // The abstraction-related information.
std::reference_wrapper<JaniAbstractionInformation<DdType>> abstractionInformation;
std::reference_wrapper<AbstractionInformation<DdType>> abstractionInformation;
// The ID of the edge. // The ID of the edge.
uint64_t edgeId; uint64_t edgeId;

48
src/storm/abstraction/jani/JaniAbstractionInformation.cpp

@ -1,48 +0,0 @@
#include "storm/abstraction/jani/JaniAbstractionInformation.h"
#include "storm/storage/dd/DdManager.h"
namespace storm {
namespace abstraction {
namespace jani {
template<storm::dd::DdType DdType>
JaniAbstractionInformation<DdType>::JaniAbstractionInformation(storm::expressions::ExpressionManager& expressionManager, std::set<storm::expressions::Variable> const& allVariables, uint64_t numberOfLocations, std::unique_ptr<storm::solver::SmtSolver>&& smtSolver, std::shared_ptr<storm::dd::DdManager<DdType>> ddManager) : AbstractionInformation<DdType>(expressionManager, allVariables, std::move(smtSolver), ddManager) {
// Create the location variable to have the appropriate dimension.
if (numberOfLocations > 1) {
locationVariables = ddManager->addMetaVariable("loc", 0, numberOfLocations - 1);
sourceLocationVariables.insert(locationVariables.get().first);
successorLocationVariables.insert(locationVariables.get().second);
}
}
template<storm::dd::DdType DdType>
storm::dd::Bdd<DdType> JaniAbstractionInformation<DdType>::encodeLocation(uint64_t locationIndex, bool source) const {
if (locationVariables) {
if (source) {
return this->getDdManager().getEncoding(locationVariables.get().first, locationIndex);
} else {
return this->getDdManager().getEncoding(locationVariables.get().second, locationIndex);
}
} else {
return this->getDdManager().getBddOne();
}
}
template<storm::dd::DdType DdType>
std::set<storm::expressions::Variable> const& JaniAbstractionInformation<DdType>::getSourceLocationVariables() const {
return sourceLocationVariables;
}
template<storm::dd::DdType DdType>
std::set<storm::expressions::Variable> const& JaniAbstractionInformation<DdType>::getSuccessorLocationVariables() const {
return successorLocationVariables;
}
template class JaniAbstractionInformation<storm::dd::DdType::CUDD>;
template class JaniAbstractionInformation<storm::dd::DdType::Sylvan>;
}
}
}

22
src/storm/abstraction/jani/JaniMenuGameAbstractor.cpp

@ -31,7 +31,7 @@ namespace storm {
using storm::settings::modules::AbstractionSettings; using storm::settings::modules::AbstractionSettings;
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
JaniMenuGameAbstractor<DdType, ValueType>::JaniMenuGameAbstractor(storm::jani::Model const& model, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : model(model), smtSolverFactory(smtSolverFactory), abstractionInformation(model.getManager(), model.getAllExpressionVariables(), model.getAutomaton(0).getNumberOfLocations(), smtSolverFactory->create(model.getManager())), automata(), initialStateAbstractor(abstractionInformation, {model.getInitialStatesExpression()}, this->smtSolverFactory), validBlockAbstractor(abstractionInformation, smtSolverFactory), currentGame(nullptr), refinementPerformed(false) {
JaniMenuGameAbstractor<DdType, ValueType>::JaniMenuGameAbstractor(storm::jani::Model const& model, std::shared_ptr<storm::utility::solver::SmtSolverFactory> const& smtSolverFactory) : model(model), smtSolverFactory(smtSolverFactory), abstractionInformation(model.getManager(), model.getAllExpressionVariables(), smtSolverFactory->create(model.getManager())), automata(), initialStateAbstractor(abstractionInformation, {model.getInitialStatesExpression()}, this->smtSolverFactory), validBlockAbstractor(abstractionInformation, smtSolverFactory), currentGame(nullptr), refinementPerformed(false) {
// For now, we assume that there is a single module. If the program has more than one module, it needs // For now, we assume that there is a single module. If the program has more than one module, it needs
// to be flattened before the procedure. // to be flattened before the procedure.
@ -65,7 +65,8 @@ namespace storm {
automata.emplace_back(automaton, abstractionInformation, this->smtSolverFactory, useDecomposition); automata.emplace_back(automaton, abstractionInformation, this->smtSolverFactory, useDecomposition);
} }
// Retrieve the decorator ADD, so we can multiply it with the abstraction BDD later.
// Retrieve global BDDs/ADDs so we can multiply them in the abstraction process.
initialLocationsBdd = automata.front().getInitialLocationsBdd();
edgeDecoratorAdd = automata.front().getEdgeDecoratorAdd(); edgeDecoratorAdd = automata.front().getEdgeDecoratorAdd();
} }
@ -127,7 +128,7 @@ namespace storm {
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
storm::dd::Bdd<DdType> JaniMenuGameAbstractor<DdType, ValueType>::getStates(storm::expressions::Expression const& predicate) {
storm::dd::Bdd<DdType> JaniMenuGameAbstractor<DdType, ValueType>::getStates(storm::expressions::Expression const& predicate) const {
STORM_LOG_ASSERT(currentGame != nullptr, "Game was not properly created."); STORM_LOG_ASSERT(currentGame != nullptr, "Game was not properly created.");
return abstractionInformation.getPredicateSourceVariable(predicate); return abstractionInformation.getPredicateSourceVariable(predicate);
} }
@ -137,6 +138,9 @@ namespace storm {
// As long as there is only one module, we only build its game representation. // As long as there is only one module, we only build its game representation.
GameBddResult<DdType> game = automata.front().abstract(); GameBddResult<DdType> game = automata.front().abstract();
// Add the locations to the transitions.
game.bdd &= edgeDecoratorAdd.notZero();
// Construct a set of all unnecessary variables, so we can abstract from it. // Construct a set of all unnecessary variables, so we can abstract from it.
std::set<storm::expressions::Variable> variablesToAbstract(abstractionInformation.getPlayer1VariableSet(abstractionInformation.getPlayer1VariableCount())); std::set<storm::expressions::Variable> variablesToAbstract(abstractionInformation.getPlayer1VariableSet(abstractionInformation.getPlayer1VariableCount()));
auto player2Variables = abstractionInformation.getPlayer2VariableSet(game.numberOfPlayer2Variables); auto player2Variables = abstractionInformation.getPlayer2VariableSet(game.numberOfPlayer2Variables);
@ -146,7 +150,7 @@ namespace storm {
// Do a reachability analysis on the raw transition relation. // Do a reachability analysis on the raw transition relation.
storm::dd::Bdd<DdType> transitionRelation = game.bdd.existsAbstract(variablesToAbstract); storm::dd::Bdd<DdType> transitionRelation = game.bdd.existsAbstract(variablesToAbstract);
storm::dd::Bdd<DdType> initialStates = initialStateAbstractor.getAbstractStates();
storm::dd::Bdd<DdType> initialStates = initialLocationsBdd && initialStateAbstractor.getAbstractStates();
storm::dd::Bdd<DdType> reachableStates = storm::utility::dd::computeReachableStates(initialStates, transitionRelation, abstractionInformation.getSourceVariables(), abstractionInformation.getSuccessorVariables()); storm::dd::Bdd<DdType> reachableStates = storm::utility::dd::computeReachableStates(initialStates, transitionRelation, abstractionInformation.getSourceVariables(), abstractionInformation.getSuccessorVariables());
// Find the deadlock states in the model. Note that this does not find the 'deadlocks' in bottom states, // Find the deadlock states in the model. Note that this does not find the 'deadlocks' in bottom states,
@ -162,7 +166,7 @@ namespace storm {
// Compute bottom states and the appropriate transitions if necessary. // Compute bottom states and the appropriate transitions if necessary.
BottomStateResult<DdType> bottomStateResult(abstractionInformation.getDdManager().getBddZero(), abstractionInformation.getDdManager().getBddZero()); BottomStateResult<DdType> bottomStateResult(abstractionInformation.getDdManager().getBddZero(), abstractionInformation.getDdManager().getBddZero());
bottomStateResult = automata.front().getBottomStateTransitions(reachableStates, game.numberOfPlayer2Variables);
bottomStateResult = automata.front().getBottomStateTransitions(reachableStates.existsAbstract(abstractionInformation.getSourceLocationVariables()), game.numberOfPlayer2Variables);
bool hasBottomStates = !bottomStateResult.states.isZero(); bool hasBottomStates = !bottomStateResult.states.isZero();
// Construct the transition matrix by cutting away the transitions of unreachable states. // Construct the transition matrix by cutting away the transitions of unreachable states.
@ -181,19 +185,15 @@ namespace storm {
reachableStates |= bottomStateResult.states; reachableStates |= bottomStateResult.states;
} }
std::set<storm::expressions::Variable> usedPlayer2Variables(abstractionInformation.getPlayer2Variables().begin(), abstractionInformation.getPlayer2Variables().begin() + game.numberOfPlayer2Variables);
std::set<storm::expressions::Variable> allNondeterminismVariables = usedPlayer2Variables;
std::set<storm::expressions::Variable> allNondeterminismVariables = player2Variables;
allNondeterminismVariables.insert(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end()); allNondeterminismVariables.insert(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end());
std::set<storm::expressions::Variable> allSourceVariables(abstractionInformation.getSourceVariables()); std::set<storm::expressions::Variable> allSourceVariables(abstractionInformation.getSourceVariables());
allSourceVariables.insert(abstractionInformation.getBottomStateVariable(true)); allSourceVariables.insert(abstractionInformation.getBottomStateVariable(true));
allSourceVariables.insert(abstractionInformation.getSourceLocationVariables().begin(), abstractionInformation.getSourceLocationVariables().end());
std::set<storm::expressions::Variable> allSuccessorVariables(abstractionInformation.getSuccessorVariables()); std::set<storm::expressions::Variable> allSuccessorVariables(abstractionInformation.getSuccessorVariables());
allSuccessorVariables.insert(abstractionInformation.getBottomStateVariable(false)); allSuccessorVariables.insert(abstractionInformation.getBottomStateVariable(false));
allSuccessorVariables.insert(abstractionInformation.getSuccessorLocationVariables().begin(), abstractionInformation.getSuccessorLocationVariables().end());
return std::make_unique<MenuGame<DdType, ValueType>>(abstractionInformation.getDdManagerAsSharedPointer(), reachableStates, initialStates, abstractionInformation.getDdManager().getBddZero(), transitionMatrix, bottomStateResult.states, allSourceVariables, allSuccessorVariables, abstractionInformation.getExtendedSourceSuccessorVariablePairs(), std::set<storm::expressions::Variable>(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end()), usedPlayer2Variables, allNondeterminismVariables, auxVariables, abstractionInformation.getPredicateToBddMap());
return std::make_unique<MenuGame<DdType, ValueType>>(abstractionInformation.getDdManagerAsSharedPointer(), reachableStates, initialStates, abstractionInformation.getDdManager().getBddZero(), transitionMatrix, bottomStateResult.states, allSourceVariables, allSuccessorVariables, abstractionInformation.getExtendedSourceSuccessorVariablePairs(), std::set<storm::expressions::Variable>(abstractionInformation.getPlayer1Variables().begin(), abstractionInformation.getPlayer1Variables().end()), player2Variables, allNondeterminismVariables, auxVariables, abstractionInformation.getPredicateToBddMap());
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>

11
src/storm/abstraction/jani/JaniMenuGameAbstractor.h

@ -6,7 +6,7 @@
#include "storm/abstraction/MenuGame.h" #include "storm/abstraction/MenuGame.h"
#include "storm/abstraction/RefinementCommand.h" #include "storm/abstraction/RefinementCommand.h"
#include "storm/abstraction/ValidBlockAbstractor.h" #include "storm/abstraction/ValidBlockAbstractor.h"
#include "storm/abstraction/jani/JaniAbstractionInformation.h"
#include "storm/abstraction/AbstractionInformation.h"
#include "storm/abstraction/jani/AutomatonAbstractor.h" #include "storm/abstraction/jani/AutomatonAbstractor.h"
#include "storm/storage/dd/Add.h" #include "storm/storage/dd/Add.h"
@ -98,7 +98,7 @@ namespace storm {
* @param predicate The predicate for which to retrieve the states. * @param predicate The predicate for which to retrieve the states.
* @return The BDD representing the set of states. * @return The BDD representing the set of states.
*/ */
storm::dd::Bdd<DdType> getStates(storm::expressions::Expression const& predicate);
storm::dd::Bdd<DdType> getStates(storm::expressions::Expression const& predicate) const override;
/*! /*!
* Performs the given refinement command. * Performs the given refinement command.
@ -139,7 +139,7 @@ namespace storm {
std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory; std::shared_ptr<storm::utility::solver::SmtSolverFactory> smtSolverFactory;
// An object containing all information about the abstraction like predicates and the corresponding DDs. // An object containing all information about the abstraction like predicates and the corresponding DDs.
JaniAbstractionInformation<DdType> abstractionInformation;
AbstractionInformation<DdType> abstractionInformation;
// The abstract modules of the abstract program. // The abstract modules of the abstract program.
std::vector<AutomatonAbstractor<DdType, ValueType>> automata; std::vector<AutomatonAbstractor<DdType, ValueType>> automata;
@ -149,7 +149,10 @@ namespace storm {
// An object that is used to compute the valid blocks. // An object that is used to compute the valid blocks.
ValidBlockAbstractor<DdType> validBlockAbstractor; ValidBlockAbstractor<DdType> validBlockAbstractor;
// A BDD characterizing the initial locations of the abstracted automata.
storm::dd::Bdd<DdType> initialLocationsBdd;
// An ADD characterizing the probabilities and source/target locations of edges and their updates. // An ADD characterizing the probabilities and source/target locations of edges and their updates.
storm::dd::Add<DdType, ValueType> edgeDecoratorAdd; storm::dd::Add<DdType, ValueType> edgeDecoratorAdd;

4
src/storm/abstraction/prism/PrismMenuGameAbstractor.cpp

@ -129,9 +129,9 @@ namespace storm {
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>
storm::dd::Bdd<DdType> PrismMenuGameAbstractor<DdType, ValueType>::getStates(storm::expressions::Expression const& predicate) {
storm::dd::Bdd<DdType> PrismMenuGameAbstractor<DdType, ValueType>::getStates(storm::expressions::Expression const& expression) const {
STORM_LOG_ASSERT(currentGame != nullptr, "Game was not properly created."); STORM_LOG_ASSERT(currentGame != nullptr, "Game was not properly created.");
return abstractionInformation.getPredicateSourceVariable(predicate);
return abstractionInformation.getPredicateSourceVariable(expression);
} }
template <storm::dd::DdType DdType, typename ValueType> template <storm::dd::DdType DdType, typename ValueType>

2
src/storm/abstraction/prism/PrismMenuGameAbstractor.h

@ -98,7 +98,7 @@ namespace storm {
* @param predicate The predicate for which to retrieve the states. * @param predicate The predicate for which to retrieve the states.
* @return The BDD representing the set of states. * @return The BDD representing the set of states.
*/ */
storm::dd::Bdd<DdType> getStates(storm::expressions::Expression const& predicate);
storm::dd::Bdd<DdType> getStates(storm::expressions::Expression const& expression) const;
/*! /*!
* Performs the given refinement command. * Performs the given refinement command.

2
src/storm/modelchecker/abstraction/GameBasedMdpModelChecker.cpp

@ -407,7 +407,7 @@ namespace storm {
auto quantitativeEnd = std::chrono::high_resolution_clock::now(); auto quantitativeEnd = std::chrono::high_resolution_clock::now();
STORM_LOG_DEBUG("Obtained quantitative bounds [" << quantitativeResult.min.initialStateValue << ", " << quantitativeResult.max.initialStateValue << "] on the actual value for the initial states in " << std::chrono::duration_cast<std::chrono::milliseconds>(quantitativeEnd - quantitativeStart).count() << "ms."); STORM_LOG_DEBUG("Obtained quantitative bounds [" << quantitativeResult.min.initialStateValue << ", " << quantitativeResult.max.initialStateValue << "] on the actual value for the initial states in " << std::chrono::duration_cast<std::chrono::milliseconds>(quantitativeEnd - quantitativeStart).count() << "ms.");
// (9) Check whether the lower and upper bounds are close enough to terminate with an answer. // (9) Check whether the lower and upper bounds are close enough to terminate with an answer.
result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, quantitativeResult.min.initialStateValue, quantitativeResult.max.initialStateValue, comparator); result = checkForResultAfterQuantitativeCheck<ValueType>(checkTask, quantitativeResult.min.initialStateValue, quantitativeResult.max.initialStateValue, comparator);
if (result) { if (result) {

4
src/storm/storage/expressions/BaseExpression.cpp

@ -12,6 +12,10 @@ namespace storm {
// Intentionally left empty. // Intentionally left empty.
} }
Expression BaseExpression::toExpression() const {
return Expression(shared_from_this());
}
Type const& BaseExpression::getType() const { Type const& BaseExpression::getType() const {
return this->type; return this->type;
} }

6
src/storm/storage/expressions/BaseExpression.h

@ -16,6 +16,7 @@ namespace storm {
// Forward-declare expression classes. // Forward-declare expression classes.
class ExpressionManager; class ExpressionManager;
class Variable; class Variable;
class Expression;
class Valuation; class Valuation;
class ExpressionVisitor; class ExpressionVisitor;
enum struct OperatorType; enum struct OperatorType;
@ -53,6 +54,11 @@ namespace storm {
// Make the destructor virtual (to allow destruction via base class pointer) and default it. // Make the destructor virtual (to allow destruction via base class pointer) and default it.
virtual ~BaseExpression() = default; virtual ~BaseExpression() = default;
/*!
* Converts the base expression to a proper expression.
*/
Expression toExpression() const;
/*! /*!
* Evaluates the expression under the valuation of unknowns (variables and constants) given by the * Evaluates the expression under the valuation of unknowns (variables and constants) given by the

Loading…
Cancel
Save