Browse Source
moved menu-game abstraction to separate folder and made everything compile again
moved menu-game abstraction to separate folder and made everything compile again
Former-commit-id: a833ca1152
tempestpy_adaptions
dehnert
9 years ago
32 changed files with 1235 additions and 1255 deletions
-
2resources/3rdparty/include_cudd.cmake
-
5src/CMakeLists.txt
-
97src/abstraction/AbstractionDdInformation.cpp
-
113src/abstraction/AbstractionDdInformation.h
-
64src/abstraction/AbstractionExpressionInformation.cpp
-
126src/abstraction/AbstractionExpressionInformation.h
-
196src/abstraction/LocalExpressionInformation.cpp
-
165src/abstraction/LocalExpressionInformation.h
-
67src/abstraction/MenuGame.cpp
-
16src/abstraction/MenuGame.h
-
1src/abstraction/MenuGameAbstractor.cpp
-
16src/abstraction/MenuGameAbstractor.h
-
154src/abstraction/StateSetAbstractor.cpp
-
145src/abstraction/StateSetAbstractor.h
-
8src/abstraction/prism/AbstractCommand.cpp
-
13src/abstraction/prism/AbstractCommand.h
-
8src/abstraction/prism/AbstractModule.cpp
-
13src/abstraction/prism/AbstractModule.h
-
7src/abstraction/prism/AbstractProgram.cpp
-
23src/abstraction/prism/AbstractProgram.h
-
2src/storage/dd/cudd/InternalCuddDdManager.cpp
-
99src/storage/prism/menu_games/AbstractionDdInformation.cpp
-
118src/storage/prism/menu_games/AbstractionDdInformation.h
-
66src/storage/prism/menu_games/AbstractionExpressionInformation.cpp
-
130src/storage/prism/menu_games/AbstractionExpressionInformation.h
-
197src/storage/prism/menu_games/LocalExpressionInformation.cpp
-
170src/storage/prism/menu_games/LocalExpressionInformation.h
-
69src/storage/prism/menu_games/MenuGame.cpp
-
156src/storage/prism/menu_games/StateSetAbstractor.cpp
-
150src/storage/prism/menu_games/StateSetAbstractor.h
-
50test/functional/abstraction/PrismMenuGameTest.cpp
-
14test/functional/utility/GraphTest.cpp
@ -0,0 +1,97 @@ |
|||||
|
#include "src/abstraction/AbstractionDdInformation.h"
|
||||
|
|
||||
|
#include <sstream>
|
||||
|
|
||||
|
#include "src/storage/expressions/ExpressionManager.h"
|
||||
|
#include "src/storage/expressions/Expression.h"
|
||||
|
|
||||
|
#include "src/storage/dd/DdManager.h"
|
||||
|
#include "src/storage/dd/Bdd.h"
|
||||
|
#include "src/storage/dd/Add.h"
|
||||
|
|
||||
|
#include "src/utility/macros.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
AbstractionDdInformation<DdType, ValueType>::AbstractionDdInformation(std::shared_ptr<storm::dd::DdManager<DdType>> const& manager, std::vector<storm::expressions::Expression> const& initialPredicates) : manager(manager), allPredicateIdentities(manager->getBddOne()), bddVariableIndexToPredicateMap() { |
||||
|
for (auto const& predicate : initialPredicates) { |
||||
|
this->addPredicate(predicate); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
storm::dd::Bdd<DdType> AbstractionDdInformation<DdType, ValueType>::encodeDistributionIndex(uint_fast64_t numberOfVariables, uint_fast64_t distributionIndex) const { |
||||
|
storm::dd::Bdd<DdType> result = manager->getBddOne(); |
||||
|
for (uint_fast64_t bitIndex = 0; bitIndex < numberOfVariables; ++bitIndex) { |
||||
|
STORM_LOG_ASSERT(!(optionDdVariables[bitIndex].second.isZero() || optionDdVariables[bitIndex].second.isOne()), "Option variable is corrupted."); |
||||
|
if ((distributionIndex & 1) != 0) { |
||||
|
result &= optionDdVariables[bitIndex].second; |
||||
|
} else { |
||||
|
result &= !optionDdVariables[bitIndex].second; |
||||
|
} |
||||
|
distributionIndex >>= 1; |
||||
|
} |
||||
|
STORM_LOG_ASSERT(!result.isZero(), "Update BDD encoding must not be zero."); |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void AbstractionDdInformation<DdType, ValueType>::addPredicate(storm::expressions::Expression const& predicate) { |
||||
|
std::stringstream stream; |
||||
|
stream << predicate; |
||||
|
std::pair<storm::expressions::Variable, storm::expressions::Variable> newMetaVariable; |
||||
|
|
||||
|
// Create the new predicate variable below all other predicate variables.
|
||||
|
if (predicateDdVariables.empty()) { |
||||
|
newMetaVariable = manager->addMetaVariable(stream.str()); |
||||
|
} else { |
||||
|
newMetaVariable = manager->addMetaVariable(stream.str(), std::make_pair(storm::dd::MetaVariablePosition::Below, predicateDdVariables.back().second)); |
||||
|
} |
||||
|
|
||||
|
predicateDdVariables.push_back(newMetaVariable); |
||||
|
predicateBdds.emplace_back(manager->getEncoding(newMetaVariable.first, 1), manager->getEncoding(newMetaVariable.second, 1)); |
||||
|
predicateIdentities.push_back(manager->getEncoding(newMetaVariable.first, 1).iff(manager->getEncoding(newMetaVariable.second, 1))); |
||||
|
allPredicateIdentities &= predicateIdentities.back(); |
||||
|
sourceVariables.insert(newMetaVariable.first); |
||||
|
successorVariables.insert(newMetaVariable.second); |
||||
|
expressionToBddMap[predicate] = predicateBdds.back().first; |
||||
|
bddVariableIndexToPredicateMap[predicateIdentities.back().getIndex()] = predicate; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
storm::dd::Bdd<DdType> AbstractionDdInformation<DdType, ValueType>::getMissingOptionVariableCube(uint_fast64_t begin, uint_fast64_t end) const { |
||||
|
storm::dd::Bdd<DdType> result = manager->getBddOne(); |
||||
|
|
||||
|
for (uint_fast64_t index = begin; index < end; ++index) { |
||||
|
result &= optionDdVariables[index].second; |
||||
|
} |
||||
|
|
||||
|
STORM_LOG_ASSERT(!result.isZero(), "Update variable cube must not be zero."); |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> AbstractionDdInformation<DdType, ValueType>::declareNewVariables(storm::expressions::ExpressionManager& manager, std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> const& oldRelevantPredicates, std::set<uint_fast64_t> const& newRelevantPredicates) { |
||||
|
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> result; |
||||
|
|
||||
|
auto oldIt = oldRelevantPredicates.begin(); |
||||
|
auto oldIte = oldRelevantPredicates.end(); |
||||
|
for (auto newIt = newRelevantPredicates.begin(), newIte = newRelevantPredicates.end(); newIt != newIte; ++newIt) { |
||||
|
// If the new variable does not yet exist as a source variable, we create it now.
|
||||
|
if (oldIt == oldIte || oldIt->second != *newIt) { |
||||
|
result.push_back(std::make_pair(manager.declareFreshBooleanVariable(), *newIt)); |
||||
|
} else { |
||||
|
++oldIt; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
template struct AbstractionDdInformation<storm::dd::DdType::CUDD, double>; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,113 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <vector> |
||||
|
#include <set> |
||||
|
#include <map> |
||||
|
#include <unordered_map> |
||||
|
|
||||
|
#include "src/storage/dd/DdType.h" |
||||
|
#include "src/storage/expressions/Variable.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace dd { |
||||
|
template <storm::dd::DdType DdType> |
||||
|
class DdManager; |
||||
|
|
||||
|
template <storm::dd::DdType DdType> |
||||
|
class Bdd; |
||||
|
} |
||||
|
|
||||
|
namespace expressions { |
||||
|
class Expression; |
||||
|
} |
||||
|
|
||||
|
namespace abstraction { |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
struct AbstractionDdInformation { |
||||
|
public: |
||||
|
/*! |
||||
|
* Creates a new DdInformation that uses the given manager. |
||||
|
* |
||||
|
* @param manager The manager to use. |
||||
|
* @param initialPredicates The initially considered predicates. |
||||
|
*/ |
||||
|
AbstractionDdInformation(std::shared_ptr<storm::dd::DdManager<DdType>> const& manager, std::vector<storm::expressions::Expression> const& initialPredicates = std::vector<storm::expressions::Expression>()); |
||||
|
|
||||
|
/*! |
||||
|
* Encodes the given distribution index by using the given number of variables from the optionDdVariables |
||||
|
* vector. |
||||
|
* |
||||
|
* @param numberOfVariables The number of variables to use. |
||||
|
* @param distributionIndex The distribution index to encode. |
||||
|
* @return The encoded distribution index. |
||||
|
*/ |
||||
|
storm::dd::Bdd<DdType> encodeDistributionIndex(uint_fast64_t numberOfVariables, uint_fast64_t distributionIndex) const; |
||||
|
|
||||
|
/*! |
||||
|
* Adds the given predicate and creates all associated ressources. |
||||
|
* |
||||
|
* @param predicate The predicate to add. |
||||
|
*/ |
||||
|
void addPredicate(storm::expressions::Expression const& predicate); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the cube of option variables in the range [begin, end) the given indices. |
||||
|
* |
||||
|
* @param begin The first variable of the range to return. |
||||
|
* @param end One past the last variable of the range to return. |
||||
|
* @return The cube of variables in the given range. |
||||
|
*/ |
||||
|
storm::dd::Bdd<DdType> getMissingOptionVariableCube(uint_fast64_t begin, uint_fast64_t end) const; |
||||
|
|
||||
|
/*! |
||||
|
* Examines the old and new relevant predicates and declares decision variables for the missing relevant |
||||
|
* predicates. |
||||
|
* |
||||
|
* @param manager The manager in which to declare the decision variable. |
||||
|
* @param oldRelevantPredicates The previously relevant predicates. |
||||
|
* @param newRelevantPredicates The new relevant predicates. |
||||
|
* @return Pairs of decision variables and their index for the missing predicates. |
||||
|
*/ |
||||
|
static std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> declareNewVariables(storm::expressions::ExpressionManager& manager, std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> const& oldRelevantPredicates, std::set<uint_fast64_t> const& newRelevantPredicates); |
||||
|
|
||||
|
// The manager responsible for the DDs. |
||||
|
std::shared_ptr<storm::dd::DdManager<DdType>> manager; |
||||
|
|
||||
|
// The DD variables corresponding to the predicates. |
||||
|
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> predicateDdVariables; |
||||
|
|
||||
|
// The set of all source variables. |
||||
|
std::set<storm::expressions::Variable> sourceVariables; |
||||
|
|
||||
|
// The set of all source variables. |
||||
|
std::set<storm::expressions::Variable> successorVariables; |
||||
|
|
||||
|
// The BDDs corresponding to the predicates. |
||||
|
std::vector<std::pair<storm::dd::Bdd<DdType>, storm::dd::Bdd<DdType>>> predicateBdds; |
||||
|
|
||||
|
// The BDDs representing the predicate identities (i.e. source and successor variable have the same truth value). |
||||
|
std::vector<storm::dd::Bdd<DdType>> predicateIdentities; |
||||
|
|
||||
|
// A BDD that represents the identity of all predicate variables. |
||||
|
storm::dd::Bdd<DdType> allPredicateIdentities; |
||||
|
|
||||
|
// The DD variable encoding the command (i.e., the nondeterministic choices of player 1). |
||||
|
storm::expressions::Variable commandDdVariable; |
||||
|
|
||||
|
// The DD variable encoding the update IDs for all actions. |
||||
|
storm::expressions::Variable updateDdVariable; |
||||
|
|
||||
|
// The DD variables encoding the nondeterministic choices of player 2. |
||||
|
std::vector<std::pair<storm::expressions::Variable, storm::dd::Bdd<DdType>>> optionDdVariables; |
||||
|
|
||||
|
// A mapping from the predicates to the BDDs. |
||||
|
std::map<storm::expressions::Expression, storm::dd::Bdd<DdType>> expressionToBddMap; |
||||
|
|
||||
|
// A mapping from the indices of the BDD variables to the predicates. |
||||
|
std::unordered_map<uint_fast64_t, storm::expressions::Expression> bddVariableIndexToPredicateMap; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,64 @@ |
|||||
|
#include "src/abstraction/AbstractionExpressionInformation.h"
|
||||
|
|
||||
|
#include "src/storage/expressions/ExpressionManager.h"
|
||||
|
#include "src/storage/expressions/Expression.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
AbstractionExpressionInformation::AbstractionExpressionInformation(storm::expressions::ExpressionManager& manager, std::vector<storm::expressions::Expression> const& predicates, std::set<storm::expressions::Variable> const& variables, std::vector<storm::expressions::Expression> const& rangeExpressions) : manager(manager), predicates(predicates), variables(variables), rangeExpressions(rangeExpressions) { |
||||
|
// Intentionally left empty.
|
||||
|
} |
||||
|
|
||||
|
void AbstractionExpressionInformation::addPredicate(storm::expressions::Expression const& predicate) { |
||||
|
predicates.push_back(predicate); |
||||
|
} |
||||
|
|
||||
|
void AbstractionExpressionInformation::addPredicates(std::vector<storm::expressions::Expression> const& predicates) { |
||||
|
for (auto const& predicate : predicates) { |
||||
|
this->addPredicate(predicate); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
storm::expressions::ExpressionManager& AbstractionExpressionInformation::getManager() { |
||||
|
return manager; |
||||
|
} |
||||
|
|
||||
|
storm::expressions::ExpressionManager const& AbstractionExpressionInformation::getManager() const { |
||||
|
return manager; |
||||
|
} |
||||
|
|
||||
|
std::vector<storm::expressions::Expression>& AbstractionExpressionInformation::getPredicates() { |
||||
|
return predicates; |
||||
|
} |
||||
|
|
||||
|
std::vector<storm::expressions::Expression> const& AbstractionExpressionInformation::getPredicates() const { |
||||
|
return predicates; |
||||
|
} |
||||
|
|
||||
|
storm::expressions::Expression const& AbstractionExpressionInformation::getPredicateByIndex(uint_fast64_t index) const { |
||||
|
return predicates[index]; |
||||
|
} |
||||
|
|
||||
|
std::size_t AbstractionExpressionInformation::getNumberOfPredicates() const { |
||||
|
return predicates.size(); |
||||
|
} |
||||
|
|
||||
|
std::set<storm::expressions::Variable>& AbstractionExpressionInformation::getVariables() { |
||||
|
return variables; |
||||
|
} |
||||
|
|
||||
|
std::set<storm::expressions::Variable> const& AbstractionExpressionInformation::getVariables() const { |
||||
|
return variables; |
||||
|
} |
||||
|
|
||||
|
std::vector<storm::expressions::Expression>& AbstractionExpressionInformation::getRangeExpressions() { |
||||
|
return rangeExpressions; |
||||
|
} |
||||
|
|
||||
|
std::vector<storm::expressions::Expression> const& AbstractionExpressionInformation::getRangeExpressions() const { |
||||
|
return rangeExpressions; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,126 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <vector> |
||||
|
#include <set> |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace expressions { |
||||
|
class ExpressionManager; |
||||
|
class Expression; |
||||
|
class Variable; |
||||
|
} |
||||
|
|
||||
|
namespace abstraction { |
||||
|
|
||||
|
struct AbstractionExpressionInformation { |
||||
|
public: |
||||
|
/*! |
||||
|
* Creates an expression information object with the given expression manager. |
||||
|
* |
||||
|
* @param manager The expression manager to use. |
||||
|
* @param predicates The initial set of predicates. |
||||
|
* @param variables The variables. |
||||
|
* @param rangeExpressions A set of expressions that enforce the variable bounds. |
||||
|
*/ |
||||
|
AbstractionExpressionInformation(storm::expressions::ExpressionManager& manager, std::vector<storm::expressions::Expression> const& predicates = std::vector<storm::expressions::Expression>(), std::set<storm::expressions::Variable> const& variables = std::set<storm::expressions::Variable>(), std::vector<storm::expressions::Expression> const& rangeExpressions = std::vector<storm::expressions::Expression>()); |
||||
|
|
||||
|
/*! |
||||
|
* Adds the given predicate. |
||||
|
* |
||||
|
* @param predicate The predicate to add. |
||||
|
*/ |
||||
|
void addPredicate(storm::expressions::Expression const& predicate); |
||||
|
|
||||
|
/*! |
||||
|
* Adds the given predicates. |
||||
|
* |
||||
|
* @param predicates The predicates to add. |
||||
|
*/ |
||||
|
void addPredicates(std::vector<storm::expressions::Expression> const& predicates); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the expression manager. |
||||
|
* |
||||
|
* @return The manager. |
||||
|
*/ |
||||
|
storm::expressions::ExpressionManager& getManager(); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the expression manager. |
||||
|
* |
||||
|
* @return The manager. |
||||
|
*/ |
||||
|
storm::expressions::ExpressionManager const& getManager() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all currently known predicates. |
||||
|
* |
||||
|
* @return The list of known predicates. |
||||
|
*/ |
||||
|
std::vector<storm::expressions::Expression>& getPredicates(); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all currently known predicates. |
||||
|
* |
||||
|
* @return The list of known predicates. |
||||
|
*/ |
||||
|
std::vector<storm::expressions::Expression> const& getPredicates() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the predicate with the given index. |
||||
|
* |
||||
|
* @param index The index of the predicate. |
||||
|
*/ |
||||
|
storm::expressions::Expression const& getPredicateByIndex(uint_fast64_t index) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the number of predicates. |
||||
|
* |
||||
|
* @return The number of predicates. |
||||
|
*/ |
||||
|
std::size_t getNumberOfPredicates() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all currently known variables. |
||||
|
* |
||||
|
* @return The set of known variables. |
||||
|
*/ |
||||
|
std::set<storm::expressions::Variable>& getVariables(); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves all currently known variables. |
||||
|
* |
||||
|
* @return The set of known variables. |
||||
|
*/ |
||||
|
std::set<storm::expressions::Variable> const& getVariables() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves a list of expressions that ensure the ranges of the variables. |
||||
|
* |
||||
|
* @return The range expressions. |
||||
|
*/ |
||||
|
std::vector<storm::expressions::Expression>& getRangeExpressions(); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves a list of expressions that ensure the ranges of the variables. |
||||
|
* |
||||
|
* @return The range expressions. |
||||
|
*/ |
||||
|
std::vector<storm::expressions::Expression> const& getRangeExpressions() const; |
||||
|
|
||||
|
private: |
||||
|
// The manager responsible for the expressions of the program and the SMT solvers. |
||||
|
storm::expressions::ExpressionManager& manager; |
||||
|
|
||||
|
// The current set of predicates used in the abstraction. |
||||
|
std::vector<storm::expressions::Expression> predicates; |
||||
|
|
||||
|
// The set of all variables. |
||||
|
std::set<storm::expressions::Variable> variables; |
||||
|
|
||||
|
// The expression characterizing the legal ranges of all variables. |
||||
|
std::vector<storm::expressions::Expression> rangeExpressions; |
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,196 @@ |
|||||
|
#include "src/abstraction/LocalExpressionInformation.h"
|
||||
|
|
||||
|
#include <boost/algorithm/string/join.hpp>
|
||||
|
|
||||
|
#include "src/utility/macros.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
LocalExpressionInformation::LocalExpressionInformation(std::set<storm::expressions::Variable> const& relevantVariables, std::vector<std::pair<storm::expressions::Expression, uint_fast64_t>> const& expressionIndexPairs) : relevantVariables(relevantVariables), expressionBlocks(relevantVariables.size()) { |
||||
|
// Assign each variable to a new block.
|
||||
|
uint_fast64_t currentBlock = 0; |
||||
|
variableBlocks.resize(relevantVariables.size()); |
||||
|
for (auto const& variable : relevantVariables) { |
||||
|
this->variableToBlockMapping[variable] = currentBlock; |
||||
|
this->variableToExpressionsMapping[variable] = std::set<uint_fast64_t>(); |
||||
|
variableBlocks[currentBlock].insert(variable); |
||||
|
++currentBlock; |
||||
|
} |
||||
|
|
||||
|
// Add all expressions, which might relate some variables.
|
||||
|
for (auto const& expressionIndexPair : expressionIndexPairs) { |
||||
|
this->addExpression(expressionIndexPair.first, expressionIndexPair.second); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool LocalExpressionInformation::addExpression(storm::expressions::Expression const& expression, uint_fast64_t globalExpressionIndex) { |
||||
|
// Register the expression for all variables that appear in it.
|
||||
|
std::set<storm::expressions::Variable> expressionVariables = expression.getVariables(); |
||||
|
for (auto const& variable : expressionVariables) { |
||||
|
variableToExpressionsMapping[variable].insert(this->expressions.size()); |
||||
|
} |
||||
|
|
||||
|
// Add the expression to the block of the first variable. When relating the variables, the blocks will
|
||||
|
// get merged (if necessary).
|
||||
|
STORM_LOG_ASSERT(!expressionVariables.empty(), "Found no variables in expression."); |
||||
|
expressionBlocks[getBlockIndexOfVariable(*expressionVariables.begin())].insert(this->expressions.size()); |
||||
|
|
||||
|
// Add expression and relate all the appearing variables.
|
||||
|
this->globalToLocalIndexMapping[globalExpressionIndex] = this->expressions.size(); |
||||
|
this->expressions.push_back(expression); |
||||
|
return this->relate(expressionVariables); |
||||
|
} |
||||
|
|
||||
|
bool LocalExpressionInformation::areRelated(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable) { |
||||
|
return getBlockIndexOfVariable(firstVariable) == getBlockIndexOfVariable(secondVariable); |
||||
|
} |
||||
|
|
||||
|
bool LocalExpressionInformation::relate(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable) { |
||||
|
return this->relate({firstVariable, secondVariable}); |
||||
|
} |
||||
|
|
||||
|
bool LocalExpressionInformation::relate(std::set<storm::expressions::Variable> const& variables) { |
||||
|
// Determine all blocks that need to be merged.
|
||||
|
std::set<uint_fast64_t> blocksToMerge; |
||||
|
for (auto const& variable : variables) { |
||||
|
blocksToMerge.insert(getBlockIndexOfVariable(variable)); |
||||
|
} |
||||
|
|
||||
|
STORM_LOG_ASSERT(!blocksToMerge.empty(), "Found no blocks to merge."); |
||||
|
|
||||
|
// If we found a single block only, there is nothing to do.
|
||||
|
if (blocksToMerge.size() == 1) { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
this->mergeBlocks(blocksToMerge); |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
void LocalExpressionInformation::mergeBlocks(std::set<uint_fast64_t> const& blocksToMerge) { |
||||
|
// Merge all blocks into the block to keep.
|
||||
|
std::vector<std::set<storm::expressions::Variable>> newVariableBlocks; |
||||
|
std::vector<std::set<uint_fast64_t>> newExpressionBlocks; |
||||
|
|
||||
|
std::set<uint_fast64_t>::const_iterator blocksToMergeIt = blocksToMerge.begin(); |
||||
|
std::set<uint_fast64_t>::const_iterator blocksToMergeIte = blocksToMerge.end(); |
||||
|
|
||||
|
// Determine which block to keep (to merge the other blocks into).
|
||||
|
uint_fast64_t blockToKeep = *blocksToMergeIt; |
||||
|
++blocksToMergeIt; |
||||
|
|
||||
|
for (uint_fast64_t blockIndex = 0; blockIndex < variableBlocks.size(); ++blockIndex) { |
||||
|
// If the block is the next one to merge into the block to keep, do so now.
|
||||
|
if (blocksToMergeIt != blocksToMergeIte && *blocksToMergeIt == blockIndex && blockIndex != blockToKeep) { |
||||
|
// Adjust the mapping for all variables of the old block.
|
||||
|
for (auto const& variable : variableBlocks[blockIndex]) { |
||||
|
variableToBlockMapping[variable] = blockToKeep; |
||||
|
} |
||||
|
|
||||
|
newVariableBlocks[blockToKeep].insert(variableBlocks[blockIndex].begin(), variableBlocks[blockIndex].end()); |
||||
|
newExpressionBlocks[blockToKeep].insert(expressionBlocks[blockIndex].begin(), expressionBlocks[blockIndex].end()); |
||||
|
++blocksToMergeIt; |
||||
|
} else { |
||||
|
// Otherwise just move the current block to the new partition.
|
||||
|
|
||||
|
// Adjust the mapping for all variables of the old block.
|
||||
|
for (auto const& variable : variableBlocks[blockIndex]) { |
||||
|
variableToBlockMapping[variable] = newVariableBlocks.size(); |
||||
|
} |
||||
|
|
||||
|
newVariableBlocks.emplace_back(std::move(variableBlocks[blockIndex])); |
||||
|
newExpressionBlocks.emplace_back(std::move(expressionBlocks[blockIndex])); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
variableBlocks = std::move(newVariableBlocks); |
||||
|
expressionBlocks = std::move(newExpressionBlocks); |
||||
|
} |
||||
|
|
||||
|
std::set<storm::expressions::Variable> const& LocalExpressionInformation::getBlockOfVariable(storm::expressions::Variable const& variable) const { |
||||
|
return variableBlocks[getBlockIndexOfVariable(variable)]; |
||||
|
} |
||||
|
|
||||
|
uint_fast64_t LocalExpressionInformation::getNumberOfBlocks() const { |
||||
|
return this->variableBlocks.size(); |
||||
|
} |
||||
|
|
||||
|
std::set<storm::expressions::Variable> const& LocalExpressionInformation::getVariableBlockWithIndex(uint_fast64_t blockIndex) const { |
||||
|
return this->variableBlocks[blockIndex]; |
||||
|
} |
||||
|
|
||||
|
uint_fast64_t LocalExpressionInformation::getBlockIndexOfVariable(storm::expressions::Variable const& variable) const { |
||||
|
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
||||
|
return this->variableToBlockMapping.find(variable)->second; |
||||
|
} |
||||
|
|
||||
|
std::set<uint_fast64_t> const& LocalExpressionInformation::getRelatedExpressions(storm::expressions::Variable const& variable) const { |
||||
|
return this->expressionBlocks[getBlockIndexOfVariable(variable)]; |
||||
|
} |
||||
|
|
||||
|
std::set<uint_fast64_t> LocalExpressionInformation::getRelatedExpressions(std::set<storm::expressions::Variable> const& variables) const { |
||||
|
// Start by determining the indices of all expression blocks that are related to any of the variables.
|
||||
|
std::set<uint_fast64_t> relatedExpressionBlockIndices; |
||||
|
for (auto const& variable : variables) { |
||||
|
relatedExpressionBlockIndices.insert(getBlockIndexOfVariable(variable)); |
||||
|
} |
||||
|
|
||||
|
// Then join the expressions of these blocks and return the result.
|
||||
|
std::set<uint_fast64_t> result; |
||||
|
for (auto const& blockIndex : relatedExpressionBlockIndices) { |
||||
|
result.insert(expressionBlocks[blockIndex].begin(), expressionBlocks[blockIndex].end()); |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
std::set<uint_fast64_t> const& LocalExpressionInformation::getExpressionsUsingVariable(storm::expressions::Variable const& variable) const { |
||||
|
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
||||
|
return this->variableToExpressionsMapping.find(variable)->second; |
||||
|
} |
||||
|
|
||||
|
std::set<uint_fast64_t> LocalExpressionInformation::getExpressionsUsingVariables(std::set<storm::expressions::Variable> const& variables) const { |
||||
|
std::set<uint_fast64_t> result; |
||||
|
|
||||
|
for (auto const& variable : variables) { |
||||
|
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
||||
|
auto it = this->variableToExpressionsMapping.find(variable); |
||||
|
result.insert(it->second.begin(), it->second.end()); |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
storm::expressions::Expression const& LocalExpressionInformation::getExpression(uint_fast64_t expressionIndex) const { |
||||
|
return this->expressions[expressionIndex]; |
||||
|
} |
||||
|
|
||||
|
std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition) { |
||||
|
std::vector<std::string> blocks; |
||||
|
for (uint_fast64_t index = 0; index < partition.variableBlocks.size(); ++index) { |
||||
|
auto const& variableBlock = partition.variableBlocks[index]; |
||||
|
auto const& expressionBlock = partition.expressionBlocks[index]; |
||||
|
|
||||
|
std::vector<std::string> variablesInBlock; |
||||
|
for (auto const& variable : variableBlock) { |
||||
|
variablesInBlock.push_back(variable.getName()); |
||||
|
} |
||||
|
|
||||
|
std::vector<std::string> expressionsInBlock; |
||||
|
for (auto const& expression : expressionBlock) { |
||||
|
std::stringstream stream; |
||||
|
stream << partition.expressions[expression]; |
||||
|
expressionsInBlock.push_back(stream.str()); |
||||
|
} |
||||
|
|
||||
|
blocks.push_back("<[" + boost::algorithm::join(variablesInBlock, ", ") + "], [" + boost::algorithm::join(expressionsInBlock, ", ") + "]>"); |
||||
|
} |
||||
|
|
||||
|
out << "{"; |
||||
|
out << boost::join(blocks, ", "); |
||||
|
out << "}"; |
||||
|
return out; |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,165 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <unordered_map> |
||||
|
#include <set> |
||||
|
#include <vector> |
||||
|
#include <ostream> |
||||
|
|
||||
|
#include "src/storage/expressions/Variable.h" |
||||
|
#include "src/storage/expressions/Expression.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
class LocalExpressionInformation { |
||||
|
public: |
||||
|
/*! |
||||
|
* Constructs a new variable partition. |
||||
|
* |
||||
|
* @param relevantVariables The variables of this partition. |
||||
|
* @param expressionIndexPairs The (initial) pairs of expressions and their global indices. |
||||
|
*/ |
||||
|
LocalExpressionInformation(std::set<storm::expressions::Variable> const& relevantVariables, std::vector<std::pair<storm::expressions::Expression, uint_fast64_t>> const& expressionIndexPairs = {}); |
||||
|
|
||||
|
/*! |
||||
|
* Adds the expression and therefore indirectly may cause blocks of variables to be merged. |
||||
|
* |
||||
|
* @param expression The expression to add. |
||||
|
* @param globalExpressionIndex The global index of the expression. |
||||
|
* @return True iff the partition changed. |
||||
|
*/ |
||||
|
bool addExpression(storm::expressions::Expression const& expression, uint_fast64_t globalExpressionIndex); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves whether the two given variables are in the same block of the partition. |
||||
|
* |
||||
|
* @param firstVariable The first variable. |
||||
|
* @param secondVariable The second variable. |
||||
|
* @return True iff the two variables are in the same block. |
||||
|
*/ |
||||
|
bool areRelated(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable); |
||||
|
|
||||
|
/*! |
||||
|
* Places the given variables in the same block of the partition and performs the implied merges. |
||||
|
* |
||||
|
* @param firstVariable The first variable. |
||||
|
* @param secondVariable The second variable. |
||||
|
* @return True iff the partition changed. |
||||
|
*/ |
||||
|
bool relate(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable); |
||||
|
|
||||
|
/*! |
||||
|
* Places the given variables in the same block of the partition and performs the implied merges. |
||||
|
* |
||||
|
* @param variables The variables to relate. |
||||
|
* @return True iff the partition changed. |
||||
|
*/ |
||||
|
bool relate(std::set<storm::expressions::Variable> const& variables); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the block of related variables of the given variable. |
||||
|
* |
||||
|
* @param variable The variable whose block to retrieve. |
||||
|
* @return The block of the variable. |
||||
|
*/ |
||||
|
std::set<storm::expressions::Variable> const& getBlockOfVariable(storm::expressions::Variable const& variable) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the block index of the given variable. |
||||
|
* |
||||
|
* @param variable The variable for which to retrieve the block. |
||||
|
* @return The block index of the given variable. |
||||
|
*/ |
||||
|
uint_fast64_t getBlockIndexOfVariable(storm::expressions::Variable const& variable) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the number of blocks of the variable partition. |
||||
|
* |
||||
|
* @return The number of blocks in this partition. |
||||
|
*/ |
||||
|
uint_fast64_t getNumberOfBlocks() const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the block with the given index. |
||||
|
* |
||||
|
* @param blockIndex The index of the block to retrieve. |
||||
|
* @return The block with the given index. |
||||
|
*/ |
||||
|
std::set<storm::expressions::Variable> const& getVariableBlockWithIndex(uint_fast64_t blockIndex) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the indices of the expressions related to the given variable. |
||||
|
* |
||||
|
* @param variable The variable for which to retrieve the related expressions. |
||||
|
* @return The related expressions. |
||||
|
*/ |
||||
|
std::set<uint_fast64_t> const& getRelatedExpressions(storm::expressions::Variable const& variable) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the indices of the expressions related to any of the given variables. |
||||
|
* |
||||
|
* @param variables The variables for which to retrieve the related expressions. |
||||
|
* @return The related expressions. |
||||
|
*/ |
||||
|
std::set<uint_fast64_t> getRelatedExpressions(std::set<storm::expressions::Variable> const& variables) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the indices of the expressions in which the given variable appears. |
||||
|
* |
||||
|
* @param variable The variable for which to retrieve the expressions. |
||||
|
* @return The indices of all expressions using the given variable. |
||||
|
*/ |
||||
|
std::set<uint_fast64_t> const& getExpressionsUsingVariable(storm::expressions::Variable const& variable) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the indices of the expressions in which the given variables appear. |
||||
|
* |
||||
|
* @param variables The variables for which to retrieve the expressions. |
||||
|
* @return The indices of all expressions using the given variables. |
||||
|
*/ |
||||
|
std::set<uint_fast64_t> getExpressionsUsingVariables(std::set<storm::expressions::Variable> const& variables) const; |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the expression with the given index. |
||||
|
* |
||||
|
* @param expressionIndex The index of the expression to retrieve. |
||||
|
* @return The corresponding expression. |
||||
|
*/ |
||||
|
storm::expressions::Expression const& getExpression(uint_fast64_t expressionIndex) const; |
||||
|
|
||||
|
friend std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition); |
||||
|
|
||||
|
private: |
||||
|
/*! |
||||
|
* Merges the blocks with the given indices. |
||||
|
* |
||||
|
* @param blocksToMerge The indices of the blocks to merge. |
||||
|
*/ |
||||
|
void mergeBlocks(std::set<uint_fast64_t> const& blocksToMerge); |
||||
|
|
||||
|
// The set of variables relevant for this partition. |
||||
|
std::set<storm::expressions::Variable> relevantVariables; |
||||
|
|
||||
|
// A mapping from variables to their blocks. |
||||
|
std::unordered_map<storm::expressions::Variable, uint_fast64_t> variableToBlockMapping; |
||||
|
|
||||
|
// The variable blocks of the partition. |
||||
|
std::vector<std::set<storm::expressions::Variable>> variableBlocks; |
||||
|
|
||||
|
// The expression blocks of the partition. |
||||
|
std::vector<std::set<uint_fast64_t>> expressionBlocks; |
||||
|
|
||||
|
// A mapping from variables to the indices of all expressions they appear in. |
||||
|
std::unordered_map<storm::expressions::Variable, std::set<uint_fast64_t>> variableToExpressionsMapping; |
||||
|
|
||||
|
// A mapping from global expression indices to local ones. |
||||
|
std::unordered_map<uint_fast64_t, uint_fast64_t> globalToLocalIndexMapping; |
||||
|
|
||||
|
// The vector of all expressions. |
||||
|
std::vector<storm::expressions::Expression> expressions; |
||||
|
}; |
||||
|
|
||||
|
std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition); |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,67 @@ |
|||||
|
#include "src/abstraction/MenuGame.h"
|
||||
|
|
||||
|
#include "src/exceptions/InvalidOperationException.h"
|
||||
|
#include "src/exceptions/InvalidArgumentException.h"
|
||||
|
|
||||
|
#include "src/storage/dd/Bdd.h"
|
||||
|
#include "src/storage/dd/Add.h"
|
||||
|
|
||||
|
#include "src/models/symbolic/StandardRewardModel.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
MenuGame<Type, ValueType>::MenuGame(std::shared_ptr<storm::dd::DdManager<Type>> manager, |
||||
|
storm::dd::Bdd<Type> reachableStates, |
||||
|
storm::dd::Bdd<Type> initialStates, |
||||
|
storm::dd::Bdd<Type> deadlockStates, |
||||
|
storm::dd::Add<Type, ValueType> transitionMatrix, |
||||
|
storm::dd::Bdd<Type> bottomStates, |
||||
|
std::set<storm::expressions::Variable> const& rowVariables, |
||||
|
std::set<storm::expressions::Variable> const& columnVariables, |
||||
|
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, |
||||
|
std::set<storm::expressions::Variable> const& player1Variables, |
||||
|
std::set<storm::expressions::Variable> const& player2Variables, |
||||
|
std::set<storm::expressions::Variable> const& allNondeterminismVariables, |
||||
|
storm::expressions::Variable const& updateVariable, |
||||
|
std::map<storm::expressions::Expression, storm::dd::Bdd<Type>> const& expressionToBddMap) : storm::models::symbolic::StochasticTwoPlayerGame<Type>(manager, reachableStates, initialStates, deadlockStates, transitionMatrix.sumAbstract({updateVariable}), rowVariables, nullptr, columnVariables, nullptr, rowColumnMetaVariablePairs, player1Variables, player2Variables, allNondeterminismVariables), updateVariable(updateVariable), expressionToBddMap(expressionToBddMap), bottomStates(bottomStates) { |
||||
|
// Intentionally left empty.
|
||||
|
} |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(std::string const& label) const { |
||||
|
STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Menu games do not provide labels."); |
||||
|
} |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(storm::expressions::Expression const& expression) const { |
||||
|
return this->getStates(expression, false); |
||||
|
} |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(storm::expressions::Expression const& expression, bool negated) const { |
||||
|
auto it = expressionToBddMap.find(expression); |
||||
|
STORM_LOG_THROW(it != expressionToBddMap.end(), storm::exceptions::InvalidArgumentException, "The given expression was not used in the abstraction process and can therefore not be retrieved."); |
||||
|
if (negated) { |
||||
|
return !it->second && this->getReachableStates(); |
||||
|
} else { |
||||
|
return it->second && this->getReachableStates(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getBottomStates() const { |
||||
|
return bottomStates; |
||||
|
} |
||||
|
|
||||
|
template<storm::dd::DdType Type, typename ValueType> |
||||
|
bool MenuGame<Type, ValueType>::hasLabel(std::string const& label) const { |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
template class MenuGame<storm::dd::DdType::CUDD, double>; |
||||
|
|
||||
|
} |
||||
|
} |
||||
|
|
@ -0,0 +1 @@ |
|||||
|
#include "src/abstraction/MenuGameAbstractor.h"
|
@ -0,0 +1,16 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include "src/storage/dd/DdType.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
class MenuGameAbstractor { |
||||
|
|
||||
|
|
||||
|
|
||||
|
}; |
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,154 @@ |
|||||
|
#include "src/abstraction/StateSetAbstractor.h"
|
||||
|
|
||||
|
#include "src/abstraction/AbstractionExpressionInformation.h"
|
||||
|
#include "src/abstraction/AbstractionDdInformation.h"
|
||||
|
|
||||
|
#include "src/storage/dd/DdManager.h"
|
||||
|
|
||||
|
#include "src/utility/macros.h"
|
||||
|
#include "src/utility/solver.h"
|
||||
|
|
||||
|
namespace storm { |
||||
|
namespace abstraction { |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
StateSetAbstractor<DdType, ValueType>::StateSetAbstractor(AbstractionExpressionInformation& globalExpressionInformation, AbstractionDdInformation<DdType, ValueType> const& ddInformation, std::vector<storm::expressions::Expression> const& statePredicates, storm::utility::solver::SmtSolverFactory const& smtSolverFactory) : smtSolver(smtSolverFactory.create(globalExpressionInformation.getManager())), globalExpressionInformation(globalExpressionInformation), ddInformation(ddInformation), localExpressionInformation(globalExpressionInformation.getVariables()), relevantPredicatesAndVariables(), concretePredicateVariables(), needsRecomputation(false), cachedBdd(ddInformation.manager->getBddZero()), constraint(ddInformation.manager->getBddOne()) { |
||||
|
|
||||
|
// Assert all range expressions to enforce legal variable values.
|
||||
|
for (auto const& rangeExpression : globalExpressionInformation.getRangeExpressions()) { |
||||
|
smtSolver->add(rangeExpression); |
||||
|
} |
||||
|
|
||||
|
// Assert all state predicates.
|
||||
|
for (auto const& predicate : statePredicates) { |
||||
|
smtSolver->add(predicate); |
||||
|
|
||||
|
// Extract the variables of the predicate, so we know which variables were used when abstracting.
|
||||
|
std::set<storm::expressions::Variable> usedVariables = predicate.getVariables(); |
||||
|
concretePredicateVariables.insert(usedVariables.begin(), usedVariables.end()); |
||||
|
localExpressionInformation.relate(usedVariables); |
||||
|
} |
||||
|
|
||||
|
// Refine the command based on all initial predicates.
|
||||
|
std::vector<uint_fast64_t> allPredicateIndices(globalExpressionInformation.getPredicates().size()); |
||||
|
for (auto index = 0; index < globalExpressionInformation.getPredicates().size(); ++index) { |
||||
|
allPredicateIndices[index] = index; |
||||
|
} |
||||
|
this->refine(allPredicateIndices); |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::addMissingPredicates(std::set<uint_fast64_t> const& newRelevantPredicateIndices) { |
||||
|
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newPredicateVariables = AbstractionDdInformation<DdType, ValueType>::declareNewVariables(globalExpressionInformation.getManager(), relevantPredicatesAndVariables, newRelevantPredicateIndices); |
||||
|
|
||||
|
for (auto const& element : newPredicateVariables) { |
||||
|
smtSolver->add(storm::expressions::iff(element.first, globalExpressionInformation.getPredicates()[element.second])); |
||||
|
decisionVariables.push_back(element.first); |
||||
|
} |
||||
|
|
||||
|
relevantPredicatesAndVariables.insert(relevantPredicatesAndVariables.end(), newPredicateVariables.begin(), newPredicateVariables.end()); |
||||
|
std::sort(relevantPredicatesAndVariables.begin(), relevantPredicatesAndVariables.end(), [] (std::pair<storm::expressions::Variable, uint_fast64_t> const& firstPair, std::pair<storm::expressions::Variable, uint_fast64_t> const& secondPair) { return firstPair.second < secondPair.second; } ); |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::refine(std::vector<uint_fast64_t> const& newPredicates) { |
||||
|
// Make the partition aware of the new predicates, which may make more predicates relevant to the abstraction.
|
||||
|
for (auto const& predicateIndex : newPredicates) { |
||||
|
localExpressionInformation.addExpression(globalExpressionInformation.getPredicateByIndex(predicateIndex), predicateIndex); |
||||
|
} |
||||
|
needsRecomputation = true; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::constrain(storm::dd::Bdd<DdType> const& newConstraint) { |
||||
|
// If the constraint is different from the last one, we add it to the solver.
|
||||
|
if (newConstraint != this->constraint) { |
||||
|
constraint = newConstraint; |
||||
|
this->pushConstraintBdd(); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getStateBdd(storm::solver::SmtSolver::ModelReference const& model) const { |
||||
|
STORM_LOG_TRACE("Building source state BDD."); |
||||
|
storm::dd::Bdd<DdType> result = ddInformation.manager->getBddOne(); |
||||
|
for (auto const& variableIndexPair : relevantPredicatesAndVariables) { |
||||
|
if (model.getBooleanValue(variableIndexPair.first)) { |
||||
|
result &= ddInformation.predicateBdds[variableIndexPair.second].first; |
||||
|
} else { |
||||
|
result &= !ddInformation.predicateBdds[variableIndexPair.second].first; |
||||
|
} |
||||
|
} |
||||
|
return result; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::recomputeCachedBdd() { |
||||
|
// Now check whether we need to recompute the cached BDD.
|
||||
|
std::set<uint_fast64_t> newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables); |
||||
|
STORM_LOG_TRACE("Found " << newRelevantPredicateIndices.size() << " relevant predicates in abstractor."); |
||||
|
|
||||
|
// 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::dd::Bdd<DdType> result = ddInformation.manager->getBddZero(); |
||||
|
uint_fast64_t modelCounter = 0; |
||||
|
smtSolver->allSat(decisionVariables, [&result,this,&modelCounter] (storm::solver::SmtSolver::ModelReference const& model) { result |= getStateBdd(model); return true; } ); |
||||
|
|
||||
|
cachedBdd = result; |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::popConstraintBdd() { |
||||
|
// If the last constraint was not the constant one BDD, we need to pop the constraint from the solver.
|
||||
|
if (this->constraint.isOne()) { |
||||
|
return; |
||||
|
} |
||||
|
smtSolver->pop(); |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
void StateSetAbstractor<DdType, ValueType>::pushConstraintBdd() { |
||||
|
if (this->constraint.isOne()) { |
||||
|
return; |
||||
|
} |
||||
|
|
||||
|
// Create a new backtracking point before adding the constraint.
|
||||
|
smtSolver->push(); |
||||
|
|
||||
|
// Then add the constraint.
|
||||
|
std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, storm::expressions::Variable>> result = constraint.toExpression(globalExpressionInformation.getManager(), ddInformation.bddVariableIndexToPredicateMap); |
||||
|
|
||||
|
for (auto const& expression : result.first) { |
||||
|
smtSolver->add(expression); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getAbstractStates() { |
||||
|
if (needsRecomputation) { |
||||
|
this->recomputeCachedBdd(); |
||||
|
} |
||||
|
return cachedBdd; |
||||
|
} |
||||
|
|
||||
|
template class StateSetAbstractor<storm::dd::DdType::CUDD, double>; |
||||
|
} |
||||
|
} |
@ -0,0 +1,145 @@ |
|||||
|
#pragma once |
||||
|
|
||||
|
#include <memory> |
||||
|
#include <set> |
||||
|
#include <boost/optional.hpp> |
||||
|
|
||||
|
#include "src/utility/OsDetection.h" |
||||
|
|
||||
|
#include "src/storage/dd/DdType.h" |
||||
|
|
||||
|
#include "src/solver/SmtSolver.h" |
||||
|
|
||||
|
#include "src/abstraction/LocalExpressionInformation.h" |
||||
|
|
||||
|
namespace storm { |
||||
|
namespace utility { |
||||
|
namespace solver { |
||||
|
class SmtSolverFactory; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
namespace dd { |
||||
|
template <storm::dd::DdType DdType> |
||||
|
class Bdd; |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
class Add; |
||||
|
} |
||||
|
|
||||
|
namespace abstraction { |
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
class AbstractionDdInformation; |
||||
|
|
||||
|
class AbstractionExpressionInformation; |
||||
|
|
||||
|
template <storm::dd::DdType DdType, typename ValueType> |
||||
|
class StateSetAbstractor { |
||||
|
public: |
||||
|
// Provide a no-op default constructor. |
||||
|
StateSetAbstractor() = default; |
||||
|
|
||||
|
StateSetAbstractor(StateSetAbstractor const& other) = default; |
||||
|
StateSetAbstractor& operator=(StateSetAbstractor const& other) = default; |
||||
|
|
||||
|
#ifndef WINDOWS |
||||
|
StateSetAbstractor(StateSetAbstractor&& other) = default; |
||||
|
StateSetAbstractor& operator=(StateSetAbstractor&& other) = default; |
||||
|
#endif |
||||
|
|
||||
|
/*! |
||||
|
* Creates a state set abstractor. |
||||
|
* |
||||
|
* @param expressionInformation The expression-related information including the manager and the predicates. |
||||
|
* @param ddInformation The DD-related information including the manager. |
||||
|
* @param statePredicates A set of predicates that have to hold in the concrete states this abstractor is |
||||
|
* supposed to abstract. |
||||
|
* @param smtSolverFactory A factory that can create new SMT solvers. |
||||
|
*/ |
||||
|
StateSetAbstractor(AbstractionExpressionInformation& expressionInformation, AbstractionDdInformation<DdType, ValueType> const& ddInformation, std::vector<storm::expressions::Expression> const& statePredicates, storm::utility::solver::SmtSolverFactory const& smtSolverFactory); |
||||
|
|
||||
|
/*! |
||||
|
* Refines the abstractor by making the given predicates new abstract predicates. |
||||
|
* |
||||
|
* @param newPredicateIndices The indices of the new predicates. |
||||
|
*/ |
||||
|
void refine(std::vector<uint_fast64_t> const& newPredicateIndices); |
||||
|
|
||||
|
/*! |
||||
|
* Constraints the abstract states with the given BDD. |
||||
|
* |
||||
|
* @param newConstraint The BDD used as the constraint. |
||||
|
*/ |
||||
|
void constrain(storm::dd::Bdd<DdType> const& newConstraint); |
||||
|
|
||||
|
/*! |
||||
|
* Retrieves the set of abstract states matching all predicates added to this abstractor. |
||||
|
* |
||||
|
* @return The set of matching abstract states in the form of a BDD |
||||
|
*/ |
||||
|
storm::dd::Bdd<DdType> getAbstractStates(); |
||||
|
|
||||
|
private: |
||||
|
/*! |
||||
|
* Creates decision variables and the corresponding constraints for the missing predicates. |
||||
|
* |
||||
|
* @param newRelevantPredicateIndices The set of all relevant predicate indices. |
||||
|
*/ |
||||
|
void addMissingPredicates(std::set<uint_fast64_t> const& newRelevantPredicateIndices); |
||||
|
|
||||
|
/*! |
||||
|
* Adds the current constraint BDD to the solver. |
||||
|
*/ |
||||
|
void pushConstraintBdd(); |
||||
|
|
||||
|
/*! |
||||
|
* Removes the current constraint BDD (if any) from the solver. |
||||
|
*/ |
||||
|
void popConstraintBdd(); |
||||
|
|
||||
|
/*! |
||||
|
* Recomputes the cached BDD. This needs to be triggered if any relevant predicates change. |
||||
|
*/ |
||||
|
void recomputeCachedBdd(); |
||||
|
|
||||
|
/*! |
||||
|
* Translates the given model to a state DD. |
||||
|
* |
||||
|
* @param model The model to translate. |
||||
|
* @return The state encoded as a DD. |
||||
|
*/ |
||||
|
storm::dd::Bdd<DdType> getStateBdd(storm::solver::SmtSolver::ModelReference const& model) const; |
||||
|
|
||||
|
// The SMT solver used for abstracting the set of states. |
||||
|
std::unique_ptr<storm::solver::SmtSolver> smtSolver; |
||||
|
|
||||
|
// The global expression-related information. |
||||
|
AbstractionExpressionInformation& globalExpressionInformation; |
||||
|
|
||||
|
// The DD-related information. |
||||
|
AbstractionDdInformation<DdType, ValueType> const& ddInformation; |
||||
|
|
||||
|
// The local expression-related information. |
||||
|
LocalExpressionInformation localExpressionInformation; |
||||
|
|
||||
|
// The set of relevant predicates and the corresponding decision variables. |
||||
|
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> relevantPredicatesAndVariables; |
||||
|
|
||||
|
// The set of all variables appearing in the concrete predicates. |
||||
|
std::set<storm::expressions::Variable> concretePredicateVariables; |
||||
|
|
||||
|
// The set of all decision variables over which to perform the all-sat enumeration. |
||||
|
std::vector<storm::expressions::Variable> decisionVariables; |
||||
|
|
||||
|
// A flag indicating whether the cached BDD needs recomputation. |
||||
|
bool needsRecomputation; |
||||
|
|
||||
|
// The cached BDD representing the abstraction. This variable is written to in refinement steps (if work |
||||
|
// needed to be done). |
||||
|
storm::dd::Bdd<DdType> cachedBdd; |
||||
|
|
||||
|
// This BDD currently constrains the search for solutions. |
||||
|
storm::dd::Bdd<DdType> constraint; |
||||
|
}; |
||||
|
} |
||||
|
} |
@ -1,99 +0,0 @@ |
|||||
#include "src/storage/prism/menu_games/AbstractionDdInformation.h"
|
|
||||
|
|
||||
#include <sstream>
|
|
||||
|
|
||||
#include "src/storage/expressions/ExpressionManager.h"
|
|
||||
#include "src/storage/expressions/Expression.h"
|
|
||||
|
|
||||
#include "src/storage/dd/DdManager.h"
|
|
||||
#include "src/storage/dd/Bdd.h"
|
|
||||
#include "src/storage/dd/Add.h"
|
|
||||
|
|
||||
#include "src/utility/macros.h"
|
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
AbstractionDdInformation<DdType, ValueType>::AbstractionDdInformation(std::shared_ptr<storm::dd::DdManager<DdType>> const& manager, std::vector<storm::expressions::Expression> const& initialPredicates) : manager(manager), allPredicateIdentities(manager->getBddOne()), bddVariableIndexToPredicateMap() { |
|
||||
for (auto const& predicate : initialPredicates) { |
|
||||
this->addPredicate(predicate); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
storm::dd::Bdd<DdType> AbstractionDdInformation<DdType, ValueType>::encodeDistributionIndex(uint_fast64_t numberOfVariables, uint_fast64_t distributionIndex) const { |
|
||||
storm::dd::Bdd<DdType> result = manager->getBddOne(); |
|
||||
for (uint_fast64_t bitIndex = 0; bitIndex < numberOfVariables; ++bitIndex) { |
|
||||
STORM_LOG_ASSERT(!(optionDdVariables[bitIndex].second.isZero() || optionDdVariables[bitIndex].second.isOne()), "Option variable is corrupted."); |
|
||||
if ((distributionIndex & 1) != 0) { |
|
||||
result &= optionDdVariables[bitIndex].second; |
|
||||
} else { |
|
||||
result &= !optionDdVariables[bitIndex].second; |
|
||||
} |
|
||||
distributionIndex >>= 1; |
|
||||
} |
|
||||
STORM_LOG_ASSERT(!result.isZero(), "Update BDD encoding must not be zero."); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void AbstractionDdInformation<DdType, ValueType>::addPredicate(storm::expressions::Expression const& predicate) { |
|
||||
std::stringstream stream; |
|
||||
stream << predicate; |
|
||||
std::pair<storm::expressions::Variable, storm::expressions::Variable> newMetaVariable; |
|
||||
|
|
||||
// Create the new predicate variable below all other predicate variables.
|
|
||||
if (predicateDdVariables.empty()) { |
|
||||
newMetaVariable = manager->addMetaVariable(stream.str()); |
|
||||
} else { |
|
||||
newMetaVariable = manager->addMetaVariable(stream.str(), std::make_pair(storm::dd::MetaVariablePosition::Below, predicateDdVariables.back().second)); |
|
||||
} |
|
||||
|
|
||||
predicateDdVariables.push_back(newMetaVariable); |
|
||||
predicateBdds.emplace_back(manager->getEncoding(newMetaVariable.first, 1), manager->getEncoding(newMetaVariable.second, 1)); |
|
||||
predicateIdentities.push_back(manager->getEncoding(newMetaVariable.first, 1).iff(manager->getEncoding(newMetaVariable.second, 1))); |
|
||||
allPredicateIdentities &= predicateIdentities.back(); |
|
||||
sourceVariables.insert(newMetaVariable.first); |
|
||||
successorVariables.insert(newMetaVariable.second); |
|
||||
expressionToBddMap[predicate] = predicateBdds.back().first; |
|
||||
bddVariableIndexToPredicateMap[predicateIdentities.back().getIndex()] = predicate; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
storm::dd::Bdd<DdType> AbstractionDdInformation<DdType, ValueType>::getMissingOptionVariableCube(uint_fast64_t begin, uint_fast64_t end) const { |
|
||||
storm::dd::Bdd<DdType> result = manager->getBddOne(); |
|
||||
|
|
||||
for (uint_fast64_t index = begin; index < end; ++index) { |
|
||||
result &= optionDdVariables[index].second; |
|
||||
} |
|
||||
|
|
||||
STORM_LOG_ASSERT(!result.isZero(), "Update variable cube must not be zero."); |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> AbstractionDdInformation<DdType, ValueType>::declareNewVariables(storm::expressions::ExpressionManager& manager, std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> const& oldRelevantPredicates, std::set<uint_fast64_t> const& newRelevantPredicates) { |
|
||||
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> result; |
|
||||
|
|
||||
auto oldIt = oldRelevantPredicates.begin(); |
|
||||
auto oldIte = oldRelevantPredicates.end(); |
|
||||
for (auto newIt = newRelevantPredicates.begin(), newIte = newRelevantPredicates.end(); newIt != newIte; ++newIt) { |
|
||||
// If the new variable does not yet exist as a source variable, we create it now.
|
|
||||
if (oldIt == oldIte || oldIt->second != *newIt) { |
|
||||
result.push_back(std::make_pair(manager.declareFreshBooleanVariable(), *newIt)); |
|
||||
} else { |
|
||||
++oldIt; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template struct AbstractionDdInformation<storm::dd::DdType::CUDD, double>; |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,118 +0,0 @@ |
|||||
#ifndef STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONDDINFORMATION_H_ |
|
||||
#define STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONDDINFORMATION_H_ |
|
||||
|
|
||||
#include <memory> |
|
||||
#include <vector> |
|
||||
#include <set> |
|
||||
#include <map> |
|
||||
#include <unordered_map> |
|
||||
|
|
||||
#include "src/storage/dd/DdType.h" |
|
||||
#include "src/storage/expressions/Variable.h" |
|
||||
|
|
||||
namespace storm { |
|
||||
namespace dd { |
|
||||
template <storm::dd::DdType DdType> |
|
||||
class DdManager; |
|
||||
|
|
||||
template <storm::dd::DdType DdType> |
|
||||
class Bdd; |
|
||||
} |
|
||||
|
|
||||
namespace expressions { |
|
||||
class Expression; |
|
||||
} |
|
||||
|
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
struct AbstractionDdInformation { |
|
||||
public: |
|
||||
/*! |
|
||||
* Creates a new DdInformation that uses the given manager. |
|
||||
* |
|
||||
* @param manager The manager to use. |
|
||||
* @param initialPredicates The initially considered predicates. |
|
||||
*/ |
|
||||
AbstractionDdInformation(std::shared_ptr<storm::dd::DdManager<DdType>> const& manager, std::vector<storm::expressions::Expression> const& initialPredicates = std::vector<storm::expressions::Expression>()); |
|
||||
|
|
||||
/*! |
|
||||
* Encodes the given distribution index by using the given number of variables from the optionDdVariables |
|
||||
* vector. |
|
||||
* |
|
||||
* @param numberOfVariables The number of variables to use. |
|
||||
* @param distributionIndex The distribution index to encode. |
|
||||
* @return The encoded distribution index. |
|
||||
*/ |
|
||||
storm::dd::Bdd<DdType> encodeDistributionIndex(uint_fast64_t numberOfVariables, uint_fast64_t distributionIndex) const; |
|
||||
|
|
||||
/*! |
|
||||
* Adds the given predicate and creates all associated ressources. |
|
||||
* |
|
||||
* @param predicate The predicate to add. |
|
||||
*/ |
|
||||
void addPredicate(storm::expressions::Expression const& predicate); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the cube of option variables in the range [begin, end) the given indices. |
|
||||
* |
|
||||
* @param begin The first variable of the range to return. |
|
||||
* @param end One past the last variable of the range to return. |
|
||||
* @return The cube of variables in the given range. |
|
||||
*/ |
|
||||
storm::dd::Bdd<DdType> getMissingOptionVariableCube(uint_fast64_t begin, uint_fast64_t end) const; |
|
||||
|
|
||||
/*! |
|
||||
* Examines the old and new relevant predicates and declares decision variables for the missing relevant |
|
||||
* predicates. |
|
||||
* |
|
||||
* @param manager The manager in which to declare the decision variable. |
|
||||
* @param oldRelevantPredicates The previously relevant predicates. |
|
||||
* @param newRelevantPredicates The new relevant predicates. |
|
||||
* @return Pairs of decision variables and their index for the missing predicates. |
|
||||
*/ |
|
||||
static std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> declareNewVariables(storm::expressions::ExpressionManager& manager, std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> const& oldRelevantPredicates, std::set<uint_fast64_t> const& newRelevantPredicates); |
|
||||
|
|
||||
// The manager responsible for the DDs. |
|
||||
std::shared_ptr<storm::dd::DdManager<DdType>> manager; |
|
||||
|
|
||||
// The DD variables corresponding to the predicates. |
|
||||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> predicateDdVariables; |
|
||||
|
|
||||
// The set of all source variables. |
|
||||
std::set<storm::expressions::Variable> sourceVariables; |
|
||||
|
|
||||
// The set of all source variables. |
|
||||
std::set<storm::expressions::Variable> successorVariables; |
|
||||
|
|
||||
// The BDDs corresponding to the predicates. |
|
||||
std::vector<std::pair<storm::dd::Bdd<DdType>, storm::dd::Bdd<DdType>>> predicateBdds; |
|
||||
|
|
||||
// The BDDs representing the predicate identities (i.e. source and successor variable have the same truth value). |
|
||||
std::vector<storm::dd::Bdd<DdType>> predicateIdentities; |
|
||||
|
|
||||
// A BDD that represents the identity of all predicate variables. |
|
||||
storm::dd::Bdd<DdType> allPredicateIdentities; |
|
||||
|
|
||||
// The DD variable encoding the command (i.e., the nondeterministic choices of player 1). |
|
||||
storm::expressions::Variable commandDdVariable; |
|
||||
|
|
||||
// The DD variable encoding the update IDs for all actions. |
|
||||
storm::expressions::Variable updateDdVariable; |
|
||||
|
|
||||
// The DD variables encoding the nondeterministic choices of player 2. |
|
||||
std::vector<std::pair<storm::expressions::Variable, storm::dd::Bdd<DdType>>> optionDdVariables; |
|
||||
|
|
||||
// A mapping from the predicates to the BDDs. |
|
||||
std::map<storm::expressions::Expression, storm::dd::Bdd<DdType>> expressionToBddMap; |
|
||||
|
|
||||
// A mapping from the indices of the BDD variables to the predicates. |
|
||||
std::unordered_map<uint_fast64_t, storm::expressions::Expression> bddVariableIndexToPredicateMap; |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif /* STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONDDINFORMATION_H_ */ |
|
@ -1,66 +0,0 @@ |
|||||
#include "src/storage/prism/menu_games/AbstractionExpressionInformation.h"
|
|
||||
|
|
||||
#include "src/storage/expressions/ExpressionManager.h"
|
|
||||
#include "src/storage/expressions/Expression.h"
|
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
AbstractionExpressionInformation::AbstractionExpressionInformation(storm::expressions::ExpressionManager& manager, std::vector<storm::expressions::Expression> const& predicates, std::set<storm::expressions::Variable> const& variables, std::vector<storm::expressions::Expression> const& rangeExpressions) : manager(manager), predicates(predicates), variables(variables), rangeExpressions(rangeExpressions) { |
|
||||
// Intentionally left empty.
|
|
||||
} |
|
||||
|
|
||||
void AbstractionExpressionInformation::addPredicate(storm::expressions::Expression const& predicate) { |
|
||||
predicates.push_back(predicate); |
|
||||
} |
|
||||
|
|
||||
void AbstractionExpressionInformation::addPredicates(std::vector<storm::expressions::Expression> const& predicates) { |
|
||||
for (auto const& predicate : predicates) { |
|
||||
this->addPredicate(predicate); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
storm::expressions::ExpressionManager& AbstractionExpressionInformation::getManager() { |
|
||||
return manager; |
|
||||
} |
|
||||
|
|
||||
storm::expressions::ExpressionManager const& AbstractionExpressionInformation::getManager() const { |
|
||||
return manager; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::expressions::Expression>& AbstractionExpressionInformation::getPredicates() { |
|
||||
return predicates; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::expressions::Expression> const& AbstractionExpressionInformation::getPredicates() const { |
|
||||
return predicates; |
|
||||
} |
|
||||
|
|
||||
storm::expressions::Expression const& AbstractionExpressionInformation::getPredicateByIndex(uint_fast64_t index) const { |
|
||||
return predicates[index]; |
|
||||
} |
|
||||
|
|
||||
std::size_t AbstractionExpressionInformation::getNumberOfPredicates() const { |
|
||||
return predicates.size(); |
|
||||
} |
|
||||
|
|
||||
std::set<storm::expressions::Variable>& AbstractionExpressionInformation::getVariables() { |
|
||||
return variables; |
|
||||
} |
|
||||
|
|
||||
std::set<storm::expressions::Variable> const& AbstractionExpressionInformation::getVariables() const { |
|
||||
return variables; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::expressions::Expression>& AbstractionExpressionInformation::getRangeExpressions() { |
|
||||
return rangeExpressions; |
|
||||
} |
|
||||
|
|
||||
std::vector<storm::expressions::Expression> const& AbstractionExpressionInformation::getRangeExpressions() const { |
|
||||
return rangeExpressions; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,130 +0,0 @@ |
|||||
#ifndef STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONEXPRESSIONINFORMATION_H_ |
|
||||
#define STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONEXPRESSIONINFORMATION_H_ |
|
||||
|
|
||||
#include <vector> |
|
||||
#include <set> |
|
||||
|
|
||||
namespace storm { |
|
||||
namespace expressions { |
|
||||
class ExpressionManager; |
|
||||
class Expression; |
|
||||
class Variable; |
|
||||
} |
|
||||
|
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
struct AbstractionExpressionInformation { |
|
||||
public: |
|
||||
/*! |
|
||||
* Creates an expression information object with the given expression manager. |
|
||||
* |
|
||||
* @param manager The expression manager to use. |
|
||||
* @param predicates The initial set of predicates. |
|
||||
* @param variables The variables. |
|
||||
* @param rangeExpressions A set of expressions that enforce the variable bounds. |
|
||||
*/ |
|
||||
AbstractionExpressionInformation(storm::expressions::ExpressionManager& manager, std::vector<storm::expressions::Expression> const& predicates = std::vector<storm::expressions::Expression>(), std::set<storm::expressions::Variable> const& variables = std::set<storm::expressions::Variable>(), std::vector<storm::expressions::Expression> const& rangeExpressions = std::vector<storm::expressions::Expression>()); |
|
||||
|
|
||||
/*! |
|
||||
* Adds the given predicate. |
|
||||
* |
|
||||
* @param predicate The predicate to add. |
|
||||
*/ |
|
||||
void addPredicate(storm::expressions::Expression const& predicate); |
|
||||
|
|
||||
/*! |
|
||||
* Adds the given predicates. |
|
||||
* |
|
||||
* @param predicates The predicates to add. |
|
||||
*/ |
|
||||
void addPredicates(std::vector<storm::expressions::Expression> const& predicates); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the expression manager. |
|
||||
* |
|
||||
* @return The manager. |
|
||||
*/ |
|
||||
storm::expressions::ExpressionManager& getManager(); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the expression manager. |
|
||||
* |
|
||||
* @return The manager. |
|
||||
*/ |
|
||||
storm::expressions::ExpressionManager const& getManager() const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves all currently known predicates. |
|
||||
* |
|
||||
* @return The list of known predicates. |
|
||||
*/ |
|
||||
std::vector<storm::expressions::Expression>& getPredicates(); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves all currently known predicates. |
|
||||
* |
|
||||
* @return The list of known predicates. |
|
||||
*/ |
|
||||
std::vector<storm::expressions::Expression> const& getPredicates() const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the predicate with the given index. |
|
||||
* |
|
||||
* @param index The index of the predicate. |
|
||||
*/ |
|
||||
storm::expressions::Expression const& getPredicateByIndex(uint_fast64_t index) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the number of predicates. |
|
||||
* |
|
||||
* @return The number of predicates. |
|
||||
*/ |
|
||||
std::size_t getNumberOfPredicates() const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves all currently known variables. |
|
||||
* |
|
||||
* @return The set of known variables. |
|
||||
*/ |
|
||||
std::set<storm::expressions::Variable>& getVariables(); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves all currently known variables. |
|
||||
* |
|
||||
* @return The set of known variables. |
|
||||
*/ |
|
||||
std::set<storm::expressions::Variable> const& getVariables() const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves a list of expressions that ensure the ranges of the variables. |
|
||||
* |
|
||||
* @return The range expressions. |
|
||||
*/ |
|
||||
std::vector<storm::expressions::Expression>& getRangeExpressions(); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves a list of expressions that ensure the ranges of the variables. |
|
||||
* |
|
||||
* @return The range expressions. |
|
||||
*/ |
|
||||
std::vector<storm::expressions::Expression> const& getRangeExpressions() const; |
|
||||
|
|
||||
private: |
|
||||
// The manager responsible for the expressions of the program and the SMT solvers. |
|
||||
storm::expressions::ExpressionManager& manager; |
|
||||
|
|
||||
// The current set of predicates used in the abstraction. |
|
||||
std::vector<storm::expressions::Expression> predicates; |
|
||||
|
|
||||
// The set of all variables. |
|
||||
std::set<storm::expressions::Variable> variables; |
|
||||
|
|
||||
// The expression characterizing the legal ranges of all variables. |
|
||||
std::vector<storm::expressions::Expression> rangeExpressions; |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif /* STORM_STORAGE_PRISM_MENU_GAMES_ABSTRACTIONEXPRESSIONINFORMATION_H_ */ |
|
@ -1,197 +0,0 @@ |
|||||
#include "src/storage/prism/menu_games/LocalExpressionInformation.h"
|
|
||||
|
|
||||
#include <boost/algorithm/string/join.hpp>
|
|
||||
|
|
||||
#include "src/utility/macros.h"
|
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
LocalExpressionInformation::LocalExpressionInformation(std::set<storm::expressions::Variable> const& relevantVariables, std::vector<std::pair<storm::expressions::Expression, uint_fast64_t>> const& expressionIndexPairs) : relevantVariables(relevantVariables), expressionBlocks(relevantVariables.size()) { |
|
||||
// Assign each variable to a new block.
|
|
||||
uint_fast64_t currentBlock = 0; |
|
||||
variableBlocks.resize(relevantVariables.size()); |
|
||||
for (auto const& variable : relevantVariables) { |
|
||||
this->variableToBlockMapping[variable] = currentBlock; |
|
||||
this->variableToExpressionsMapping[variable] = std::set<uint_fast64_t>(); |
|
||||
variableBlocks[currentBlock].insert(variable); |
|
||||
++currentBlock; |
|
||||
} |
|
||||
|
|
||||
// Add all expressions, which might relate some variables.
|
|
||||
for (auto const& expressionIndexPair : expressionIndexPairs) { |
|
||||
this->addExpression(expressionIndexPair.first, expressionIndexPair.second); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
bool LocalExpressionInformation::addExpression(storm::expressions::Expression const& expression, uint_fast64_t globalExpressionIndex) { |
|
||||
// Register the expression for all variables that appear in it.
|
|
||||
std::set<storm::expressions::Variable> expressionVariables = expression.getVariables(); |
|
||||
for (auto const& variable : expressionVariables) { |
|
||||
variableToExpressionsMapping[variable].insert(this->expressions.size()); |
|
||||
} |
|
||||
|
|
||||
// Add the expression to the block of the first variable. When relating the variables, the blocks will
|
|
||||
// get merged (if necessary).
|
|
||||
STORM_LOG_ASSERT(!expressionVariables.empty(), "Found no variables in expression."); |
|
||||
expressionBlocks[getBlockIndexOfVariable(*expressionVariables.begin())].insert(this->expressions.size()); |
|
||||
|
|
||||
// Add expression and relate all the appearing variables.
|
|
||||
this->globalToLocalIndexMapping[globalExpressionIndex] = this->expressions.size(); |
|
||||
this->expressions.push_back(expression); |
|
||||
return this->relate(expressionVariables); |
|
||||
} |
|
||||
|
|
||||
bool LocalExpressionInformation::areRelated(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable) { |
|
||||
return getBlockIndexOfVariable(firstVariable) == getBlockIndexOfVariable(secondVariable); |
|
||||
} |
|
||||
|
|
||||
bool LocalExpressionInformation::relate(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable) { |
|
||||
return this->relate({firstVariable, secondVariable}); |
|
||||
} |
|
||||
|
|
||||
bool LocalExpressionInformation::relate(std::set<storm::expressions::Variable> const& variables) { |
|
||||
// Determine all blocks that need to be merged.
|
|
||||
std::set<uint_fast64_t> blocksToMerge; |
|
||||
for (auto const& variable : variables) { |
|
||||
blocksToMerge.insert(getBlockIndexOfVariable(variable)); |
|
||||
} |
|
||||
|
|
||||
STORM_LOG_ASSERT(!blocksToMerge.empty(), "Found no blocks to merge."); |
|
||||
|
|
||||
// If we found a single block only, there is nothing to do.
|
|
||||
if (blocksToMerge.size() == 1) { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
this->mergeBlocks(blocksToMerge); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
void LocalExpressionInformation::mergeBlocks(std::set<uint_fast64_t> const& blocksToMerge) { |
|
||||
// Merge all blocks into the block to keep.
|
|
||||
std::vector<std::set<storm::expressions::Variable>> newVariableBlocks; |
|
||||
std::vector<std::set<uint_fast64_t>> newExpressionBlocks; |
|
||||
|
|
||||
std::set<uint_fast64_t>::const_iterator blocksToMergeIt = blocksToMerge.begin(); |
|
||||
std::set<uint_fast64_t>::const_iterator blocksToMergeIte = blocksToMerge.end(); |
|
||||
|
|
||||
// Determine which block to keep (to merge the other blocks into).
|
|
||||
uint_fast64_t blockToKeep = *blocksToMergeIt; |
|
||||
++blocksToMergeIt; |
|
||||
|
|
||||
for (uint_fast64_t blockIndex = 0; blockIndex < variableBlocks.size(); ++blockIndex) { |
|
||||
// If the block is the next one to merge into the block to keep, do so now.
|
|
||||
if (blocksToMergeIt != blocksToMergeIte && *blocksToMergeIt == blockIndex && blockIndex != blockToKeep) { |
|
||||
// Adjust the mapping for all variables of the old block.
|
|
||||
for (auto const& variable : variableBlocks[blockIndex]) { |
|
||||
variableToBlockMapping[variable] = blockToKeep; |
|
||||
} |
|
||||
|
|
||||
newVariableBlocks[blockToKeep].insert(variableBlocks[blockIndex].begin(), variableBlocks[blockIndex].end()); |
|
||||
newExpressionBlocks[blockToKeep].insert(expressionBlocks[blockIndex].begin(), expressionBlocks[blockIndex].end()); |
|
||||
++blocksToMergeIt; |
|
||||
} else { |
|
||||
// Otherwise just move the current block to the new partition.
|
|
||||
|
|
||||
// Adjust the mapping for all variables of the old block.
|
|
||||
for (auto const& variable : variableBlocks[blockIndex]) { |
|
||||
variableToBlockMapping[variable] = newVariableBlocks.size(); |
|
||||
} |
|
||||
|
|
||||
newVariableBlocks.emplace_back(std::move(variableBlocks[blockIndex])); |
|
||||
newExpressionBlocks.emplace_back(std::move(expressionBlocks[blockIndex])); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
variableBlocks = std::move(newVariableBlocks); |
|
||||
expressionBlocks = std::move(newExpressionBlocks); |
|
||||
} |
|
||||
|
|
||||
std::set<storm::expressions::Variable> const& LocalExpressionInformation::getBlockOfVariable(storm::expressions::Variable const& variable) const { |
|
||||
return variableBlocks[getBlockIndexOfVariable(variable)]; |
|
||||
} |
|
||||
|
|
||||
uint_fast64_t LocalExpressionInformation::getNumberOfBlocks() const { |
|
||||
return this->variableBlocks.size(); |
|
||||
} |
|
||||
|
|
||||
std::set<storm::expressions::Variable> const& LocalExpressionInformation::getVariableBlockWithIndex(uint_fast64_t blockIndex) const { |
|
||||
return this->variableBlocks[blockIndex]; |
|
||||
} |
|
||||
|
|
||||
uint_fast64_t LocalExpressionInformation::getBlockIndexOfVariable(storm::expressions::Variable const& variable) const { |
|
||||
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
|
||||
return this->variableToBlockMapping.find(variable)->second; |
|
||||
} |
|
||||
|
|
||||
std::set<uint_fast64_t> const& LocalExpressionInformation::getRelatedExpressions(storm::expressions::Variable const& variable) const { |
|
||||
return this->expressionBlocks[getBlockIndexOfVariable(variable)]; |
|
||||
} |
|
||||
|
|
||||
std::set<uint_fast64_t> LocalExpressionInformation::getRelatedExpressions(std::set<storm::expressions::Variable> const& variables) const { |
|
||||
// Start by determining the indices of all expression blocks that are related to any of the variables.
|
|
||||
std::set<uint_fast64_t> relatedExpressionBlockIndices; |
|
||||
for (auto const& variable : variables) { |
|
||||
relatedExpressionBlockIndices.insert(getBlockIndexOfVariable(variable)); |
|
||||
} |
|
||||
|
|
||||
// Then join the expressions of these blocks and return the result.
|
|
||||
std::set<uint_fast64_t> result; |
|
||||
for (auto const& blockIndex : relatedExpressionBlockIndices) { |
|
||||
result.insert(expressionBlocks[blockIndex].begin(), expressionBlocks[blockIndex].end()); |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
std::set<uint_fast64_t> const& LocalExpressionInformation::getExpressionsUsingVariable(storm::expressions::Variable const& variable) const { |
|
||||
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
|
||||
return this->variableToExpressionsMapping.find(variable)->second; |
|
||||
} |
|
||||
|
|
||||
std::set<uint_fast64_t> LocalExpressionInformation::getExpressionsUsingVariables(std::set<storm::expressions::Variable> const& variables) const { |
|
||||
std::set<uint_fast64_t> result; |
|
||||
|
|
||||
for (auto const& variable : variables) { |
|
||||
STORM_LOG_ASSERT(this->relevantVariables.find(variable) != this->relevantVariables.end(), "Illegal variable '" << variable.getName() << "' for partition."); |
|
||||
auto it = this->variableToExpressionsMapping.find(variable); |
|
||||
result.insert(it->second.begin(), it->second.end()); |
|
||||
} |
|
||||
|
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
storm::expressions::Expression const& LocalExpressionInformation::getExpression(uint_fast64_t expressionIndex) const { |
|
||||
return this->expressions[expressionIndex]; |
|
||||
} |
|
||||
|
|
||||
std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition) { |
|
||||
std::vector<std::string> blocks; |
|
||||
for (uint_fast64_t index = 0; index < partition.variableBlocks.size(); ++index) { |
|
||||
auto const& variableBlock = partition.variableBlocks[index]; |
|
||||
auto const& expressionBlock = partition.expressionBlocks[index]; |
|
||||
|
|
||||
std::vector<std::string> variablesInBlock; |
|
||||
for (auto const& variable : variableBlock) { |
|
||||
variablesInBlock.push_back(variable.getName()); |
|
||||
} |
|
||||
|
|
||||
std::vector<std::string> expressionsInBlock; |
|
||||
for (auto const& expression : expressionBlock) { |
|
||||
std::stringstream stream; |
|
||||
stream << partition.expressions[expression]; |
|
||||
expressionsInBlock.push_back(stream.str()); |
|
||||
} |
|
||||
|
|
||||
blocks.push_back("<[" + boost::algorithm::join(variablesInBlock, ", ") + "], [" + boost::algorithm::join(expressionsInBlock, ", ") + "]>"); |
|
||||
} |
|
||||
|
|
||||
out << "{"; |
|
||||
out << boost::join(blocks, ", "); |
|
||||
out << "}"; |
|
||||
return out; |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,170 +0,0 @@ |
|||||
#ifndef STORM_STORAGE_PRISM_MENU_GAMES_LOCALEXPRESSIONINFORMATION_H_ |
|
||||
#define STORM_STORAGE_PRISM_MENU_GAMES_LOCALEXPRESSIONINFORMATION_H_ |
|
||||
|
|
||||
#include <unordered_map> |
|
||||
#include <set> |
|
||||
#include <vector> |
|
||||
#include <ostream> |
|
||||
|
|
||||
#include "src/storage/expressions/Variable.h" |
|
||||
#include "src/storage/expressions/Expression.h" |
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
class LocalExpressionInformation { |
|
||||
public: |
|
||||
/*! |
|
||||
* Constructs a new variable partition. |
|
||||
* |
|
||||
* @param relevantVariables The variables of this partition. |
|
||||
* @param expressionIndexPairs The (initial) pairs of expressions and their global indices. |
|
||||
*/ |
|
||||
LocalExpressionInformation(std::set<storm::expressions::Variable> const& relevantVariables, std::vector<std::pair<storm::expressions::Expression, uint_fast64_t>> const& expressionIndexPairs = {}); |
|
||||
|
|
||||
/*! |
|
||||
* Adds the expression and therefore indirectly may cause blocks of variables to be merged. |
|
||||
* |
|
||||
* @param expression The expression to add. |
|
||||
* @param globalExpressionIndex The global index of the expression. |
|
||||
* @return True iff the partition changed. |
|
||||
*/ |
|
||||
bool addExpression(storm::expressions::Expression const& expression, uint_fast64_t globalExpressionIndex); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves whether the two given variables are in the same block of the partition. |
|
||||
* |
|
||||
* @param firstVariable The first variable. |
|
||||
* @param secondVariable The second variable. |
|
||||
* @return True iff the two variables are in the same block. |
|
||||
*/ |
|
||||
bool areRelated(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable); |
|
||||
|
|
||||
/*! |
|
||||
* Places the given variables in the same block of the partition and performs the implied merges. |
|
||||
* |
|
||||
* @param firstVariable The first variable. |
|
||||
* @param secondVariable The second variable. |
|
||||
* @return True iff the partition changed. |
|
||||
*/ |
|
||||
bool relate(storm::expressions::Variable const& firstVariable, storm::expressions::Variable const& secondVariable); |
|
||||
|
|
||||
/*! |
|
||||
* Places the given variables in the same block of the partition and performs the implied merges. |
|
||||
* |
|
||||
* @param variables The variables to relate. |
|
||||
* @return True iff the partition changed. |
|
||||
*/ |
|
||||
bool relate(std::set<storm::expressions::Variable> const& variables); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the block of related variables of the given variable. |
|
||||
* |
|
||||
* @param variable The variable whose block to retrieve. |
|
||||
* @return The block of the variable. |
|
||||
*/ |
|
||||
std::set<storm::expressions::Variable> const& getBlockOfVariable(storm::expressions::Variable const& variable) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the block index of the given variable. |
|
||||
* |
|
||||
* @param variable The variable for which to retrieve the block. |
|
||||
* @return The block index of the given variable. |
|
||||
*/ |
|
||||
uint_fast64_t getBlockIndexOfVariable(storm::expressions::Variable const& variable) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the number of blocks of the variable partition. |
|
||||
* |
|
||||
* @return The number of blocks in this partition. |
|
||||
*/ |
|
||||
uint_fast64_t getNumberOfBlocks() const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the block with the given index. |
|
||||
* |
|
||||
* @param blockIndex The index of the block to retrieve. |
|
||||
* @return The block with the given index. |
|
||||
*/ |
|
||||
std::set<storm::expressions::Variable> const& getVariableBlockWithIndex(uint_fast64_t blockIndex) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the indices of the expressions related to the given variable. |
|
||||
* |
|
||||
* @param variable The variable for which to retrieve the related expressions. |
|
||||
* @return The related expressions. |
|
||||
*/ |
|
||||
std::set<uint_fast64_t> const& getRelatedExpressions(storm::expressions::Variable const& variable) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the indices of the expressions related to any of the given variables. |
|
||||
* |
|
||||
* @param variables The variables for which to retrieve the related expressions. |
|
||||
* @return The related expressions. |
|
||||
*/ |
|
||||
std::set<uint_fast64_t> getRelatedExpressions(std::set<storm::expressions::Variable> const& variables) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the indices of the expressions in which the given variable appears. |
|
||||
* |
|
||||
* @param variable The variable for which to retrieve the expressions. |
|
||||
* @return The indices of all expressions using the given variable. |
|
||||
*/ |
|
||||
std::set<uint_fast64_t> const& getExpressionsUsingVariable(storm::expressions::Variable const& variable) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the indices of the expressions in which the given variables appear. |
|
||||
* |
|
||||
* @param variables The variables for which to retrieve the expressions. |
|
||||
* @return The indices of all expressions using the given variables. |
|
||||
*/ |
|
||||
std::set<uint_fast64_t> getExpressionsUsingVariables(std::set<storm::expressions::Variable> const& variables) const; |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the expression with the given index. |
|
||||
* |
|
||||
* @param expressionIndex The index of the expression to retrieve. |
|
||||
* @return The corresponding expression. |
|
||||
*/ |
|
||||
storm::expressions::Expression const& getExpression(uint_fast64_t expressionIndex) const; |
|
||||
|
|
||||
friend std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition); |
|
||||
|
|
||||
private: |
|
||||
/*! |
|
||||
* Merges the blocks with the given indices. |
|
||||
* |
|
||||
* @param blocksToMerge The indices of the blocks to merge. |
|
||||
*/ |
|
||||
void mergeBlocks(std::set<uint_fast64_t> const& blocksToMerge); |
|
||||
|
|
||||
// The set of variables relevant for this partition. |
|
||||
std::set<storm::expressions::Variable> relevantVariables; |
|
||||
|
|
||||
// A mapping from variables to their blocks. |
|
||||
std::unordered_map<storm::expressions::Variable, uint_fast64_t> variableToBlockMapping; |
|
||||
|
|
||||
// The variable blocks of the partition. |
|
||||
std::vector<std::set<storm::expressions::Variable>> variableBlocks; |
|
||||
|
|
||||
// The expression blocks of the partition. |
|
||||
std::vector<std::set<uint_fast64_t>> expressionBlocks; |
|
||||
|
|
||||
// A mapping from variables to the indices of all expressions they appear in. |
|
||||
std::unordered_map<storm::expressions::Variable, std::set<uint_fast64_t>> variableToExpressionsMapping; |
|
||||
|
|
||||
// A mapping from global expression indices to local ones. |
|
||||
std::unordered_map<uint_fast64_t, uint_fast64_t> globalToLocalIndexMapping; |
|
||||
|
|
||||
// The vector of all expressions. |
|
||||
std::vector<storm::expressions::Expression> expressions; |
|
||||
}; |
|
||||
|
|
||||
std::ostream& operator<<(std::ostream& out, LocalExpressionInformation const& partition); |
|
||||
|
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif /* STORM_STORAGE_PRISM_MENU_GAMES_LOCALEXPRESSIONINFORMATION_H_ */ |
|
@ -1,69 +0,0 @@ |
|||||
#include "src/storage/prism/menu_games/MenuGame.h"
|
|
||||
|
|
||||
#include "src/exceptions/InvalidOperationException.h"
|
|
||||
#include "src/exceptions/InvalidArgumentException.h"
|
|
||||
|
|
||||
#include "src/storage/dd/Bdd.h"
|
|
||||
#include "src/storage/dd/Add.h"
|
|
||||
|
|
||||
#include "src/models/symbolic/StandardRewardModel.h"
|
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
MenuGame<Type, ValueType>::MenuGame(std::shared_ptr<storm::dd::DdManager<Type>> manager, |
|
||||
storm::dd::Bdd<Type> reachableStates, |
|
||||
storm::dd::Bdd<Type> initialStates, |
|
||||
storm::dd::Bdd<Type> deadlockStates, |
|
||||
storm::dd::Add<Type, ValueType> transitionMatrix, |
|
||||
storm::dd::Bdd<Type> bottomStates, |
|
||||
std::set<storm::expressions::Variable> const& rowVariables, |
|
||||
std::set<storm::expressions::Variable> const& columnVariables, |
|
||||
std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& rowColumnMetaVariablePairs, |
|
||||
std::set<storm::expressions::Variable> const& player1Variables, |
|
||||
std::set<storm::expressions::Variable> const& player2Variables, |
|
||||
std::set<storm::expressions::Variable> const& allNondeterminismVariables, |
|
||||
storm::expressions::Variable const& updateVariable, |
|
||||
std::map<storm::expressions::Expression, storm::dd::Bdd<Type>> const& expressionToBddMap) : storm::models::symbolic::StochasticTwoPlayerGame<Type>(manager, reachableStates, initialStates, deadlockStates, transitionMatrix.sumAbstract({updateVariable}), rowVariables, nullptr, columnVariables, nullptr, rowColumnMetaVariablePairs, player1Variables, player2Variables, allNondeterminismVariables), updateVariable(updateVariable), expressionToBddMap(expressionToBddMap), bottomStates(bottomStates) { |
|
||||
// Intentionally left empty.
|
|
||||
} |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(std::string const& label) const { |
|
||||
STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Menu games do not provide labels."); |
|
||||
} |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(storm::expressions::Expression const& expression) const { |
|
||||
return this->getStates(expression, false); |
|
||||
} |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getStates(storm::expressions::Expression const& expression, bool negated) const { |
|
||||
auto it = expressionToBddMap.find(expression); |
|
||||
STORM_LOG_THROW(it != expressionToBddMap.end(), storm::exceptions::InvalidArgumentException, "The given expression was not used in the abstraction process and can therefore not be retrieved."); |
|
||||
if (negated) { |
|
||||
return !it->second && this->getReachableStates(); |
|
||||
} else { |
|
||||
return it->second && this->getReachableStates(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
storm::dd::Bdd<Type> MenuGame<Type, ValueType>::getBottomStates() const { |
|
||||
return bottomStates; |
|
||||
} |
|
||||
|
|
||||
template<storm::dd::DdType Type, typename ValueType> |
|
||||
bool MenuGame<Type, ValueType>::hasLabel(std::string const& label) const { |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
template class MenuGame<storm::dd::DdType::CUDD, double>; |
|
||||
|
|
||||
} // namespace menu_games
|
|
||||
} // namespace prism
|
|
||||
} // namespace storm
|
|
||||
|
|
@ -1,156 +0,0 @@ |
|||||
#include "src/storage/prism/menu_games/StateSetAbstractor.h"
|
|
||||
|
|
||||
#include "src/storage/prism/menu_games/AbstractionExpressionInformation.h"
|
|
||||
#include "src/storage/prism/menu_games/AbstractionDdInformation.h"
|
|
||||
|
|
||||
#include "src/storage/dd/DdManager.h"
|
|
||||
|
|
||||
#include "src/utility/macros.h"
|
|
||||
#include "src/utility/solver.h"
|
|
||||
|
|
||||
namespace storm { |
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
StateSetAbstractor<DdType, ValueType>::StateSetAbstractor(AbstractionExpressionInformation& globalExpressionInformation, AbstractionDdInformation<DdType, ValueType> const& ddInformation, std::vector<storm::expressions::Expression> const& statePredicates, storm::utility::solver::SmtSolverFactory const& smtSolverFactory) : smtSolver(smtSolverFactory.create(globalExpressionInformation.getManager())), globalExpressionInformation(globalExpressionInformation), ddInformation(ddInformation), localExpressionInformation(globalExpressionInformation.getVariables()), relevantPredicatesAndVariables(), concretePredicateVariables(), needsRecomputation(false), cachedBdd(ddInformation.manager->getBddZero()), constraint(ddInformation.manager->getBddOne()) { |
|
||||
|
|
||||
// Assert all range expressions to enforce legal variable values.
|
|
||||
for (auto const& rangeExpression : globalExpressionInformation.getRangeExpressions()) { |
|
||||
smtSolver->add(rangeExpression); |
|
||||
} |
|
||||
|
|
||||
// Assert all state predicates.
|
|
||||
for (auto const& predicate : statePredicates) { |
|
||||
smtSolver->add(predicate); |
|
||||
|
|
||||
// Extract the variables of the predicate, so we know which variables were used when abstracting.
|
|
||||
std::set<storm::expressions::Variable> usedVariables = predicate.getVariables(); |
|
||||
concretePredicateVariables.insert(usedVariables.begin(), usedVariables.end()); |
|
||||
localExpressionInformation.relate(usedVariables); |
|
||||
} |
|
||||
|
|
||||
// Refine the command based on all initial predicates.
|
|
||||
std::vector<uint_fast64_t> allPredicateIndices(globalExpressionInformation.getPredicates().size()); |
|
||||
for (auto index = 0; index < globalExpressionInformation.getPredicates().size(); ++index) { |
|
||||
allPredicateIndices[index] = index; |
|
||||
} |
|
||||
this->refine(allPredicateIndices); |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::addMissingPredicates(std::set<uint_fast64_t> const& newRelevantPredicateIndices) { |
|
||||
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> newPredicateVariables = AbstractionDdInformation<DdType, ValueType>::declareNewVariables(globalExpressionInformation.getManager(), relevantPredicatesAndVariables, newRelevantPredicateIndices); |
|
||||
|
|
||||
for (auto const& element : newPredicateVariables) { |
|
||||
smtSolver->add(storm::expressions::iff(element.first, globalExpressionInformation.getPredicates()[element.second])); |
|
||||
decisionVariables.push_back(element.first); |
|
||||
} |
|
||||
|
|
||||
relevantPredicatesAndVariables.insert(relevantPredicatesAndVariables.end(), newPredicateVariables.begin(), newPredicateVariables.end()); |
|
||||
std::sort(relevantPredicatesAndVariables.begin(), relevantPredicatesAndVariables.end(), [] (std::pair<storm::expressions::Variable, uint_fast64_t> const& firstPair, std::pair<storm::expressions::Variable, uint_fast64_t> const& secondPair) { return firstPair.second < secondPair.second; } ); |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::refine(std::vector<uint_fast64_t> const& newPredicates) { |
|
||||
// Make the partition aware of the new predicates, which may make more predicates relevant to the abstraction.
|
|
||||
for (auto const& predicateIndex : newPredicates) { |
|
||||
localExpressionInformation.addExpression(globalExpressionInformation.getPredicateByIndex(predicateIndex), predicateIndex); |
|
||||
} |
|
||||
needsRecomputation = true; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::constrain(storm::dd::Bdd<DdType> const& newConstraint) { |
|
||||
// If the constraint is different from the last one, we add it to the solver.
|
|
||||
if (newConstraint != this->constraint) { |
|
||||
constraint = newConstraint; |
|
||||
this->pushConstraintBdd(); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getStateBdd(storm::solver::SmtSolver::ModelReference const& model) const { |
|
||||
STORM_LOG_TRACE("Building source state BDD."); |
|
||||
storm::dd::Bdd<DdType> result = ddInformation.manager->getBddOne(); |
|
||||
for (auto const& variableIndexPair : relevantPredicatesAndVariables) { |
|
||||
if (model.getBooleanValue(variableIndexPair.first)) { |
|
||||
result &= ddInformation.predicateBdds[variableIndexPair.second].first; |
|
||||
} else { |
|
||||
result &= !ddInformation.predicateBdds[variableIndexPair.second].first; |
|
||||
} |
|
||||
} |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::recomputeCachedBdd() { |
|
||||
// Now check whether we need to recompute the cached BDD.
|
|
||||
std::set<uint_fast64_t> newRelevantPredicateIndices = localExpressionInformation.getRelatedExpressions(concretePredicateVariables); |
|
||||
STORM_LOG_TRACE("Found " << newRelevantPredicateIndices.size() << " relevant predicates in abstractor."); |
|
||||
|
|
||||
// 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::dd::Bdd<DdType> result = ddInformation.manager->getBddZero(); |
|
||||
uint_fast64_t modelCounter = 0; |
|
||||
smtSolver->allSat(decisionVariables, [&result,this,&modelCounter] (storm::solver::SmtSolver::ModelReference const& model) { result |= getStateBdd(model); return true; } ); |
|
||||
|
|
||||
cachedBdd = result; |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::popConstraintBdd() { |
|
||||
// If the last constraint was not the constant one BDD, we need to pop the constraint from the solver.
|
|
||||
if (this->constraint.isOne()) { |
|
||||
return; |
|
||||
} |
|
||||
smtSolver->pop(); |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
void StateSetAbstractor<DdType, ValueType>::pushConstraintBdd() { |
|
||||
if (this->constraint.isOne()) { |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// Create a new backtracking point before adding the constraint.
|
|
||||
smtSolver->push(); |
|
||||
|
|
||||
// Then add the constraint.
|
|
||||
std::pair<std::vector<storm::expressions::Expression>, std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, storm::expressions::Variable>> result = constraint.toExpression(globalExpressionInformation.getManager(), ddInformation.bddVariableIndexToPredicateMap); |
|
||||
|
|
||||
for (auto const& expression : result.first) { |
|
||||
smtSolver->add(expression); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
storm::dd::Bdd<DdType> StateSetAbstractor<DdType, ValueType>::getAbstractStates() { |
|
||||
if (needsRecomputation) { |
|
||||
this->recomputeCachedBdd(); |
|
||||
} |
|
||||
return cachedBdd; |
|
||||
} |
|
||||
|
|
||||
template class StateSetAbstractor<storm::dd::DdType::CUDD, double>; |
|
||||
} |
|
||||
} |
|
||||
} |
|
@ -1,150 +0,0 @@ |
|||||
#ifndef STORM_STORAGE_PRISM_MENU_GAMES_STATESETABSTRACTOR_H_ |
|
||||
#define STORM_STORAGE_PRISM_MENU_GAMES_STATESETABSTRACTOR_H_ |
|
||||
|
|
||||
#include <memory> |
|
||||
#include <set> |
|
||||
#include <boost/optional.hpp> |
|
||||
|
|
||||
#include "src/utility/OsDetection.h" |
|
||||
|
|
||||
#include "src/storage/dd/DdType.h" |
|
||||
|
|
||||
#include "src/solver/SmtSolver.h" |
|
||||
|
|
||||
#include "src/storage/prism/menu_games/LocalExpressionInformation.h" |
|
||||
|
|
||||
namespace storm { |
|
||||
namespace utility { |
|
||||
namespace solver { |
|
||||
class SmtSolverFactory; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
namespace dd { |
|
||||
template <storm::dd::DdType DdType> |
|
||||
class Bdd; |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
class Add; |
|
||||
} |
|
||||
|
|
||||
namespace prism { |
|
||||
namespace menu_games { |
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
class AbstractionDdInformation; |
|
||||
|
|
||||
class AbstractionExpressionInformation; |
|
||||
|
|
||||
template <storm::dd::DdType DdType, typename ValueType> |
|
||||
class StateSetAbstractor { |
|
||||
public: |
|
||||
// Provide a no-op default constructor. |
|
||||
StateSetAbstractor() = default; |
|
||||
|
|
||||
StateSetAbstractor(StateSetAbstractor const& other) = default; |
|
||||
StateSetAbstractor& operator=(StateSetAbstractor const& other) = default; |
|
||||
|
|
||||
#ifndef WINDOWS |
|
||||
StateSetAbstractor(StateSetAbstractor&& other) = default; |
|
||||
StateSetAbstractor& operator=(StateSetAbstractor&& other) = default; |
|
||||
#endif |
|
||||
|
|
||||
/*! |
|
||||
* Creates a state set abstractor. |
|
||||
* |
|
||||
* @param expressionInformation The expression-related information including the manager and the predicates. |
|
||||
* @param ddInformation The DD-related information including the manager. |
|
||||
* @param statePredicates A set of predicates that have to hold in the concrete states this abstractor is |
|
||||
* supposed to abstract. |
|
||||
* @param smtSolverFactory A factory that can create new SMT solvers. |
|
||||
*/ |
|
||||
StateSetAbstractor(AbstractionExpressionInformation& expressionInformation, AbstractionDdInformation<DdType, ValueType> const& ddInformation, std::vector<storm::expressions::Expression> const& statePredicates, storm::utility::solver::SmtSolverFactory const& smtSolverFactory); |
|
||||
|
|
||||
/*! |
|
||||
* Refines the abstractor by making the given predicates new abstract predicates. |
|
||||
* |
|
||||
* @param newPredicateIndices The indices of the new predicates. |
|
||||
*/ |
|
||||
void refine(std::vector<uint_fast64_t> const& newPredicateIndices); |
|
||||
|
|
||||
/*! |
|
||||
* Constraints the abstract states with the given BDD. |
|
||||
* |
|
||||
* @param newConstraint The BDD used as the constraint. |
|
||||
*/ |
|
||||
void constrain(storm::dd::Bdd<DdType> const& newConstraint); |
|
||||
|
|
||||
/*! |
|
||||
* Retrieves the set of abstract states matching all predicates added to this abstractor. |
|
||||
* |
|
||||
* @return The set of matching abstract states in the form of a BDD |
|
||||
*/ |
|
||||
storm::dd::Bdd<DdType> getAbstractStates(); |
|
||||
|
|
||||
private: |
|
||||
/*! |
|
||||
* Creates decision variables and the corresponding constraints for the missing predicates. |
|
||||
* |
|
||||
* @param newRelevantPredicateIndices The set of all relevant predicate indices. |
|
||||
*/ |
|
||||
void addMissingPredicates(std::set<uint_fast64_t> const& newRelevantPredicateIndices); |
|
||||
|
|
||||
/*! |
|
||||
* Adds the current constraint BDD to the solver. |
|
||||
*/ |
|
||||
void pushConstraintBdd(); |
|
||||
|
|
||||
/*! |
|
||||
* Removes the current constraint BDD (if any) from the solver. |
|
||||
*/ |
|
||||
void popConstraintBdd(); |
|
||||
|
|
||||
/*! |
|
||||
* Recomputes the cached BDD. This needs to be triggered if any relevant predicates change. |
|
||||
*/ |
|
||||
void recomputeCachedBdd(); |
|
||||
|
|
||||
/*! |
|
||||
* Translates the given model to a state DD. |
|
||||
* |
|
||||
* @param model The model to translate. |
|
||||
* @return The state encoded as a DD. |
|
||||
*/ |
|
||||
storm::dd::Bdd<DdType> getStateBdd(storm::solver::SmtSolver::ModelReference const& model) const; |
|
||||
|
|
||||
// The SMT solver used for abstracting the set of states. |
|
||||
std::unique_ptr<storm::solver::SmtSolver> smtSolver; |
|
||||
|
|
||||
// The global expression-related information. |
|
||||
AbstractionExpressionInformation& globalExpressionInformation; |
|
||||
|
|
||||
// The DD-related information. |
|
||||
AbstractionDdInformation<DdType, ValueType> const& ddInformation; |
|
||||
|
|
||||
// The local expression-related information. |
|
||||
LocalExpressionInformation localExpressionInformation; |
|
||||
|
|
||||
// The set of relevant predicates and the corresponding decision variables. |
|
||||
std::vector<std::pair<storm::expressions::Variable, uint_fast64_t>> relevantPredicatesAndVariables; |
|
||||
|
|
||||
// The set of all variables appearing in the concrete predicates. |
|
||||
std::set<storm::expressions::Variable> concretePredicateVariables; |
|
||||
|
|
||||
// The set of all decision variables over which to perform the all-sat enumeration. |
|
||||
std::vector<storm::expressions::Variable> decisionVariables; |
|
||||
|
|
||||
// A flag indicating whether the cached BDD needs recomputation. |
|
||||
bool needsRecomputation; |
|
||||
|
|
||||
// The cached BDD representing the abstraction. This variable is written to in refinement steps (if work |
|
||||
// needed to be done). |
|
||||
storm::dd::Bdd<DdType> cachedBdd; |
|
||||
|
|
||||
// This BDD currently constrains the search for solutions. |
|
||||
storm::dd::Bdd<DdType> constraint; |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
#endif /* STORM_STORAGE_PRISM_MENU_GAMES_STATESETABSTRACTOR_H_ */ |
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue