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
-
18src/abstraction/MenuGame.h
-
1src/abstraction/MenuGameAbstractor.cpp
-
16src/abstraction/MenuGameAbstractor.h
-
154src/abstraction/StateSetAbstractor.cpp
-
145src/abstraction/StateSetAbstractor.h
-
10src/abstraction/prism/AbstractCommand.cpp
-
23src/abstraction/prism/AbstractCommand.h
-
10src/abstraction/prism/AbstractModule.cpp
-
23src/abstraction/prism/AbstractModule.h
-
9src/abstraction/prism/AbstractProgram.cpp
-
25src/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