Browse Source

merge with master

Former-commit-id: bf2c19c1b3
tempestpy_adaptions
sjunges 11 years ago
parent
commit
7ca7baeb34
  1. 1
      .gitignore
  2. 13
      CMakeLists.txt
  3. 0
      StormCPackConfig.cmake
  4. 7
      src/adapters/ExplicitModelAdapter.h
  5. 2
      src/adapters/SymbolicModelAdapter.h
  6. 10
      src/counterexamples/MILPMinimalLabelSetGenerator.h
  7. 17
      src/ir/Module.cpp
  8. 6
      src/ir/Module.h
  9. 2
      src/models/MarkovAutomaton.h
  10. 2
      src/solver/GlpkLpSolver.cpp
  11. 1
      src/solver/GmmxxLinearEquationSolver.cpp
  12. 1
      src/solver/GmmxxNondeterministicLinearEquationSolver.cpp
  13. 1
      src/solver/NativeLinearEquationSolver.cpp
  14. 1
      src/solver/NativeNondeterministicLinearEquationSolver.cpp
  15. 2
      src/storage/BitVector.cpp
  16. 1
      src/storage/SparseMatrix.cpp
  17. 354
      src/storage/dd/CuddDd.cpp
  18. 407
      src/storage/dd/CuddDd.h
  19. 149
      src/storage/dd/CuddDdManager.cpp
  20. 141
      src/storage/dd/CuddDdManager.h
  21. 13
      src/storage/dd/Dd.h
  22. 13
      src/storage/dd/DdManager.h
  23. 52
      src/storage/dd/DdMetaVariable.cpp
  24. 114
      src/storage/dd/DdMetaVariable.h
  25. 12
      src/storage/dd/DdType.h
  26. 3
      src/storm.cpp
  27. 1
      src/utility/vector.h
  28. 7
      storm-config.h.in
  29. 12
      storm-version.h.in
  30. 71
      test/functional/storage/CuddDdTest.cpp

1
.gitignore

@ -33,6 +33,7 @@ resources/3rdparty/cudd-2.5.0/
ipch/
obj/
CMakeFiles/
CPackConfig.cmake
# The build Dir
build/
build//CMakeLists.txt

13
CMakeLists.txt

@ -223,6 +223,13 @@ configure_file (
"${PROJECT_SOURCE_DIR}/storm-config.h.in"
"${PROJECT_BINARY_DIR}/include/storm-config.h"
)
# Configure a header file to pass the storm version to the source code
configure_file (
"${PROJECT_SOURCE_DIR}/storm-version.h.in"
"${PROJECT_BINARY_DIR}/include/storm-version.h"
)
# Add the binary dir include directory for storm-config.h
include_directories("${PROJECT_BINARY_DIR}/include")
@ -249,7 +256,8 @@ file(GLOB STORM_PARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/*.h ${PROJECT_SOUR
file(GLOB_RECURSE STORM_PARSER_PRISMPARSER_FILES ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.h ${PROJECT_SOURCE_DIR}/src/parser/prismparser/*.cpp)
file(GLOB_RECURSE STORM_SETTINGS_FILES ${PROJECT_SOURCE_DIR}/src/settings/*.h ${PROJECT_SOURCE_DIR}/src/settings/*.cpp)
file(GLOB_RECURSE STORM_SOLVER_FILES ${PROJECT_SOURCE_DIR}/src/solver/*.h ${PROJECT_SOURCE_DIR}/src/solver/*.cpp)
file(GLOB_RECURSE STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp)
file(GLOB STORM_STORAGE_FILES ${PROJECT_SOURCE_DIR}/src/storage/*.h ${PROJECT_SOURCE_DIR}/src/storage/*.cpp)
file(GLOB_RECURSE STORM_STORAGE_DD_FILES ${PROJECT_SOURCE_DIR}/src/storage/dd/*.h ${PROJECT_SOURCE_DIR}/src/storage/dd/*.cpp)
file(GLOB_RECURSE STORM_UTILITY_FILES ${PROJECT_SOURCE_DIR}/src/utility/*.h ${PROJECT_SOURCE_DIR}/src/utility/*.cpp)
file(GLOB STORM_IR_FILES ${PROJECT_SOURCE_DIR}/src/ir/*.h ${PROJECT_SOURCE_DIR}/src/ir/*.cpp)
file(GLOB_RECURSE STORM_IR_EXPRESSIONS_FILES ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.h ${PROJECT_SOURCE_DIR}/src/ir/expressions/*.cpp)
@ -282,6 +290,7 @@ source_group(parser\\prismparser FILES ${STORM_PARSER_PRISMPARSER_FILES})
source_group(settings FILES ${STORM_SETTINGS_FILES})
source_group(solver FILES ${STORM_SOLVER_FILES})
source_group(storage FILES ${STORM_STORAGE_FILES})
source_group(storage\\dd FILES ${STORM_STORAGE_DD_FILES})
source_group(utility FILES ${STORM_UTILITY_FILES})
source_group(functional-test FILES ${STORM_FUNCTIONAL_TEST_FILES})
source_group(performance-test FILES ${STORM_PERFORMANCE_TEST_FILES})
@ -539,4 +548,4 @@ INSTALL(TARGETS storm storm-functional-tests storm-performance-tests
LIBRARY DESTINATION lib
ARCHIVE DESTINATION lib
)
include(CPackConfig.cmake)
include(StormCPackConfig.cmake)

0
CPackConfig.cmake → StormCPackConfig.cmake

7
src/adapters/ExplicitModelAdapter.h

@ -233,6 +233,13 @@ namespace storm {
}
std::set<uint_fast64_t> const& commandIndices = module.getCommandsByAction(action);
// If the module contains the action, but there is no command in the module that is labeled with
// this action, we don't have any feasible command combinations.
if (commandIndices.empty()) {
return boost::optional<std::vector<std::list<storm::ir::Command>>>();
}
std::list<storm::ir::Command> commands;
// Look up commands by their indices and add them if the guard evaluates to true in the given state.

2
src/adapters/SymbolicModelAdapter.h

@ -157,7 +157,6 @@ private:
for (uint_fast64_t j = 0; j < module.getNumberOfBooleanVariables(); ++j) {
storm::ir::BooleanVariable const& booleanVariable = module.getBooleanVariable(j);
bool initialValue = booleanVariable.getInitialValue()->getValueAsBool(nullptr);
*initialStates *= *cuddUtility->getConstantEncoding(1, variableToRowDecisionDiagramVariableMap[booleanVariable.getName()]);
}
for (uint_fast64_t j = 0; j < module.getNumberOfIntegerVariables(); ++j) {
@ -187,7 +186,6 @@ private:
}
bool changed;
int iter = 0;
do {
changed = false;
*newReachableStates = *reachableStates * *systemAdd01;

10
src/counterexamples/MILPMinimalLabelSetGenerator.h

@ -169,7 +169,6 @@ namespace storm {
* @return A mapping from labels to variable indices.
*/
static std::pair<std::unordered_map<uint_fast64_t, uint_fast64_t>, uint_fast64_t> createLabelVariables(storm::solver::LpSolver& solver, boost::container::flat_set<uint_fast64_t> const& relevantLabels) {
int error = 0;
std::stringstream variableNameBuffer;
std::unordered_map<uint_fast64_t, uint_fast64_t> resultingMap;
for (auto const& label : relevantLabels) {
@ -190,7 +189,6 @@ namespace storm {
* @return A mapping from states to a list of choice variable indices.
*/
static std::pair<std::unordered_map<uint_fast64_t, std::list<uint_fast64_t>>, uint_fast64_t> createSchedulerVariables(storm::solver::LpSolver& solver, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation) {
int error = 0;
std::stringstream variableNameBuffer;
uint_fast64_t numberOfVariablesCreated = 0;
std::unordered_map<uint_fast64_t, std::list<uint_fast64_t>> resultingMap;
@ -219,7 +217,6 @@ namespace storm {
* @return A mapping from initial states to choice variable indices.
*/
static std::pair<std::unordered_map<uint_fast64_t, uint_fast64_t>, uint_fast64_t> createInitialChoiceVariables(storm::solver::LpSolver& solver, storm::models::Mdp<T> const& labeledMdp, StateInformation const& stateInformation) {
int error = 0;
std::stringstream variableNameBuffer;
uint_fast64_t numberOfVariablesCreated = 0;
std::unordered_map<uint_fast64_t, uint_fast64_t> resultingMap;
@ -245,7 +242,6 @@ namespace storm {
* @return A mapping from states to the index of the corresponding probability variables.
*/
static std::pair<std::unordered_map<uint_fast64_t, uint_fast64_t>, uint_fast64_t> createProbabilityVariables(storm::solver::LpSolver& solver, StateInformation const& stateInformation) {
int error = 0;
std::stringstream variableNameBuffer;
uint_fast64_t numberOfVariablesCreated = 0;
std::unordered_map<uint_fast64_t, uint_fast64_t> resultingMap;
@ -269,7 +265,6 @@ namespace storm {
* @return The index of the variable for the probability of the virtual initial state.
*/
static std::pair<uint_fast64_t, uint_fast64_t> createVirtualInitialStateVariable(storm::solver::LpSolver& solver, bool maximizeProbability = false) {
int error = 0;
std::stringstream variableNameBuffer;
variableNameBuffer << "pinit";
@ -285,7 +280,6 @@ namespace storm {
* @return A mapping from problematic states to the index of the corresponding variables.
*/
static std::pair<std::unordered_map<uint_fast64_t, uint_fast64_t>, uint_fast64_t> createProblematicStateVariables(storm::solver::LpSolver& solver, storm::models::Mdp<T> const& labeledMdp, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation) {
int error = 0;
std::stringstream variableNameBuffer;
uint_fast64_t numberOfVariablesCreated = 0;
std::unordered_map<uint_fast64_t, uint_fast64_t> resultingMap;
@ -329,7 +323,6 @@ namespace storm {
* @return A mapping from problematic choices to the index of the corresponding variables.
*/
static std::pair<std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, uint_fast64_t, PairHash>, uint_fast64_t> createProblematicChoiceVariables(storm::solver::LpSolver& solver, storm::models::Mdp<T> const& labeledMdp, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation) {
int error = 0;
std::stringstream variableNameBuffer;
uint_fast64_t numberOfVariablesCreated = 0;
std::unordered_map<std::pair<uint_fast64_t, uint_fast64_t>, uint_fast64_t, PairHash> resultingMap;
@ -539,7 +532,6 @@ namespace storm {
*/
static uint_fast64_t assertReachabilityProbabilities(storm::solver::LpSolver& solver, storm::models::Mdp<T> const& labeledMdp, storm::storage::BitVector const& psiStates, StateInformation const& stateInformation, ChoiceInformation const& choiceInformation, VariableInformation const& variableInformation) {
uint_fast64_t numberOfConstraintsCreated = 0;
int error = 0;
for (auto state : stateInformation.relevantStates) {
std::vector<double> coefficients;
std::vector<uint_fast64_t> variables;
@ -1021,7 +1013,7 @@ namespace storm {
LOG4CPLUS_ERROR(logger, "Illegal comparison operator in formula " << probBoundFormula->toString() << ". Only upper bounds are supported for counterexample generation.");
throw storm::exceptions::InvalidPropertyException() << "Illegal comparison operator in formula " << probBoundFormula->toString() << ". Only upper bounds are supported for counterexample generation.";
}
bool strictBound = !probBoundFormula->getComparisonOperator() == storm::property::ComparisonType::LESS;
bool strictBound = !(probBoundFormula->getComparisonOperator() == storm::property::ComparisonType::LESS);
// Now derive the probability threshold we need to exceed as well as the phi and psi states. Simultaneously, check whether the formula is of a valid shape.
double bound = probBoundFormula->getBound();

17
src/ir/Module.cpp

@ -169,11 +169,16 @@ namespace storm {
if (actionsCommandSetPair != this->actionsToCommandIndexMap.end()) {
return actionsCommandSetPair->second;
}
LOG4CPLUS_ERROR(logger, "Action name '" << action << "' does not exist in module.");
throw storm::exceptions::OutOfRangeException() << "Action name '" << action << "' does not exist in module.";
}
void Module::collectActions() {
// Clear the current mapping.
this->actionsToCommandIndexMap.clear();
// Add the mapping for all commands.
for (unsigned int id = 0; id < this->commands.size(); id++) {
std::string const& action = this->commands[id].getActionName();
if (action != "") {
@ -184,9 +189,18 @@ namespace storm {
this->actions.insert(action);
}
}
// For all actions that are "in the module", but for which no command exists, we add the mapping to an empty
// set of commands.
for (auto const& action : this->actions) {
if (this->actionsToCommandIndexMap.find(action) == this->actionsToCommandIndexMap.end()) {
this->actionsToCommandIndexMap[action] = std::set<uint_fast64_t>();
}
}
}
void Module::restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet) {
// First construct the new vector of commands.
std::vector<storm::ir::Command> newCommands;
for (auto const& command : commands) {
if (indexSet.find(command.getGlobalIndex()) != indexSet.end()) {
@ -194,6 +208,9 @@ namespace storm {
}
}
commands = std::move(newCommands);
// Then refresh the internal mappings.
this->collectActions();
}
} // namespace ir

6
src/ir/Module.h

@ -188,8 +188,8 @@ namespace storm {
* @param indexSet The set of indices for which to keep the commands.
*/
void restrictCommands(boost::container::flat_set<uint_fast64_t> const& indexSet);
private:
private:
/*!
* Computes the locally maintained mappings for fast data retrieval.
*/
@ -217,11 +217,7 @@ namespace storm {
std::set<std::string> actions;
// A map of actions to the set of commands labeled with this action.
#ifdef LINUX
boost::container::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap;
#else
std::map<std::string, std::set<uint_fast64_t>> actionsToCommandIndexMap;
#endif
};
} // namespace ir

2
src/models/MarkovAutomaton.h

@ -123,7 +123,7 @@ namespace storm {
}
// Then compute how many rows the new matrix is going to have.
uint_fast64_t newNumberOfRows = this->getNumberOfChoices() - numberOfHybridStates;
//uint_fast64_t newNumberOfRows = this->getNumberOfChoices() - numberOfHybridStates;
// Create the matrix for the new transition relation and the corresponding nondeterministic choice vector.
storm::storage::SparseMatrixBuilder<T> newTransitionMatrixBuilder(0, 0, 0, true, this->getNumberOfStates() + 1);

2
src/solver/GlpkLpSolver.cpp

@ -110,8 +110,6 @@ namespace storm {
glp_set_row_name(this->lp, nextConstraintIndex, name.c_str());
// Determine the type of the constraint and add it properly.
bool isUpperBound = boundType == LESS || boundType == LESS_EQUAL;
bool isStrict = boundType == LESS || boundType == GREATER;
switch (boundType) {
case LESS:
glp_set_row_bnds(this->lp, nextConstraintIndex, GLP_UP, 0, rightHandSideValue - storm::settings::Settings::getInstance()->getOptionByLongName("precision").getArgument(0).getValueAsDouble());

1
src/solver/GmmxxLinearEquationSolver.cpp

@ -152,7 +152,6 @@ namespace storm {
// Set up some temporary variables so that we can just swap pointers instead of copying the result after
// each iteration.
std::vector<ValueType>* swap = nullptr;
std::vector<ValueType>* currentX = &x;
bool multiplyResultProvided = true;

1
src/solver/GmmxxNondeterministicLinearEquationSolver.cpp

@ -59,7 +59,6 @@ namespace storm {
newX = new std::vector<ValueType>(x.size());
xMemoryProvided = false;
}
std::vector<ValueType>* swap = nullptr;
uint_fast64_t iterations = 0;
bool converged = false;

1
src/solver/NativeLinearEquationSolver.cpp

@ -106,7 +106,6 @@ namespace storm {
void NativeLinearEquationSolver<ValueType>::performMatrixVectorMultiplication(storm::storage::SparseMatrix<ValueType> const& A, std::vector<ValueType>& x, std::vector<ValueType>* b, uint_fast64_t n, std::vector<ValueType>* multiplyResult) const {
// Set up some temporary variables so that we can just swap pointers instead of copying the result after
// each iteration.
std::vector<ValueType>* swap = nullptr;
std::vector<ValueType>* currentX = &x;
bool multiplyResultProvided = true;

1
src/solver/NativeNondeterministicLinearEquationSolver.cpp

@ -54,7 +54,6 @@ namespace storm {
newX = new std::vector<ValueType>(x.size());
xMemoryProvided = false;
}
std::vector<ValueType>* swap = nullptr;
uint_fast64_t iterations = 0;
bool converged = false;

2
src/storage/BitVector.cpp

@ -200,7 +200,6 @@ namespace storm {
}
BitVector& BitVector::operator&=(BitVector const& other) {
uint_fast64_t minSize = std::min(other.bucketVector.size(), bucketVector.size());
std::vector<uint64_t>::iterator it = bucketVector.begin();
for (std::vector<uint64_t>::const_iterator otherIt = other.bucketVector.begin(); it != bucketVector.end() && otherIt != other.bucketVector.end(); ++it, ++otherIt) {
@ -224,7 +223,6 @@ namespace storm {
}
BitVector& BitVector::operator|=(BitVector const& other) {
uint_fast64_t minSize = std::min(other.bucketVector.size(), bucketVector.size());
std::vector<uint64_t>::iterator it = bucketVector.begin();
for (std::vector<uint64_t>::const_iterator otherIt = other.bucketVector.begin(); it != bucketVector.end() && otherIt != other.bucketVector.end(); ++it, ++otherIt) {

1
src/storage/SparseMatrix.cpp

@ -753,7 +753,6 @@ namespace storm {
const_iterator it = this->begin();
const_iterator ite;
typename std::vector<uint_fast64_t>::const_iterator rowIterator = rowIndications.begin();
typename std::vector<uint_fast64_t>::const_iterator rowIteratorEnd = rowIndications.end();
typename std::vector<T>::iterator resultIterator = result.begin();
typename std::vector<T>::iterator resultIteratorEnd = result.end();

354
src/storage/dd/CuddDd.cpp

@ -0,0 +1,354 @@
#include <algorithm>
#include "src/storage/dd/CuddDd.h"
#include "src/storage/dd/CuddDdManager.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm {
namespace dd {
Dd<CUDD>::Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames) : ddManager(ddManager), cuddAdd(cuddAdd), containedMetaVariableNames(containedMetaVariableNames) {
// Intentionally left empty.
}
bool Dd<CUDD>::operator==(Dd<CUDD> const& other) const {
return this->getCuddAdd() == other.getCuddAdd();
}
Dd<CUDD> Dd<CUDD>::operator+(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result += other;
return result;
}
Dd<CUDD>& Dd<CUDD>::operator+=(Dd<CUDD> const& other) {
this->getCuddAdd() += other.getCuddAdd();
// Join the variable sets of the two participating DDs.
this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
return *this;
}
Dd<CUDD> Dd<CUDD>::operator*(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result *= other;
return result;
}
Dd<CUDD>& Dd<CUDD>::operator*=(Dd<CUDD> const& other) {
this->getCuddAdd() *= other.getCuddAdd();
// Join the variable sets of the two participating DDs.
this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
return *this;
}
Dd<CUDD> Dd<CUDD>::operator-(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result -= other;
return result;
}
Dd<CUDD>& Dd<CUDD>::operator-=(Dd<CUDD> const& other) {
this->getCuddAdd() -= other.getCuddAdd();
// Join the variable sets of the two participating DDs.
this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
return *this;
}
Dd<CUDD> Dd<CUDD>::operator/(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result /= other;
return result;
}
Dd<CUDD>& Dd<CUDD>::operator/=(Dd<CUDD> const& other) {
this->getCuddAdd().Divide(other.getCuddAdd());
// Join the variable sets of the two participating DDs.
this->getContainedMetaVariableNames().insert(other.getContainedMetaVariableNames().begin(), other.getContainedMetaVariableNames().end());
return *this;
}
Dd<CUDD> Dd<CUDD>::operator~() const {
Dd<CUDD> result(*this);
result.complement();
return result;
}
Dd<CUDD>& Dd<CUDD>::complement() {
this->getCuddAdd() = ~this->getCuddAdd();
return *this;
}
Dd<CUDD> Dd<CUDD>::equals(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().Equals(other.getCuddAdd());
return result;
}
Dd<CUDD> Dd<CUDD>::notEquals(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().NotEquals(other.getCuddAdd());
return result;
}
Dd<CUDD> Dd<CUDD>::less(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().LessThan(other.getCuddAdd());
return result;
}
Dd<CUDD> Dd<CUDD>::lessOrEqual(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().LessThanOrEqual(other.getCuddAdd());
return result;
}
Dd<CUDD> Dd<CUDD>::greater(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().GreaterThan(other.getCuddAdd());
return result;
}
Dd<CUDD> Dd<CUDD>::greaterOrEqual(Dd<CUDD> const& other) const {
Dd<CUDD> result(*this);
result.getCuddAdd().GreaterThanOrEqual(other.getCuddAdd());
return result;
}
void Dd<CUDD>::existsAbstract(std::set<std::string> const& metaVariableNames) {
Dd<CUDD> cubeDd(this->getDdManager()->getOne());
for (auto const& metaVariableName : metaVariableNames) {
// First check whether the DD contains the meta variable and erase it, if this is the case.
if (!this->containsMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "Cannot abstract from meta variable that is not present in the DD.";
}
this->getContainedMetaVariableNames().erase(metaVariableName);
DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
cubeDd *= metaVariable.getCube();
}
this->getCuddAdd().OrAbstract(cubeDd.getCuddAdd());
}
void Dd<CUDD>::sumAbstract(std::set<std::string> const& metaVariableNames) {
Dd<CUDD> cubeDd(this->getDdManager()->getOne());
for (auto const& metaVariableName : metaVariableNames) {
// First check whether the DD contains the meta variable and erase it, if this is the case.
if (!this->containsMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "Cannot abstract from meta variable that is not present in the DD.";
}
this->getContainedMetaVariableNames().erase(metaVariableName);
DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
cubeDd *= metaVariable.getCube();
}
this->getCuddAdd().ExistAbstract(cubeDd.getCuddAdd());
}
void Dd<CUDD>::minAbstract(std::set<std::string> const& metaVariableNames) {
Dd<CUDD> cubeDd(this->getDdManager()->getOne());
for (auto const& metaVariableName : metaVariableNames) {
// First check whether the DD contains the meta variable and erase it, if this is the case.
if (!this->containsMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "Cannot abstract from meta variable that is not present in the DD.";
}
this->getContainedMetaVariableNames().erase(metaVariableName);
DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
cubeDd *= metaVariable.getCube();
}
this->getCuddAdd().Minimum(cubeDd.getCuddAdd());
}
void Dd<CUDD>::maxAbstract(std::set<std::string> const& metaVariableNames) {
Dd<CUDD> cubeDd(this->getDdManager()->getOne());
for (auto const& metaVariableName : metaVariableNames) {
// First check whether the DD contains the meta variable and erase it, if this is the case.
if (!this->containsMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "Cannot abstract from meta variable that is not present in the DD.";
}
this->getContainedMetaVariableNames().erase(metaVariableName);
DdMetaVariable<CUDD> const& metaVariable = this->getDdManager()->getMetaVariable(metaVariableName);
cubeDd *= metaVariable.getCube();
}
this->getCuddAdd().Maximum(cubeDd.getCuddAdd());
}
void Dd<CUDD>::swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs) {
std::vector<ADD> from;
std::vector<ADD> to;
for (auto const& metaVariablePair : metaVariablePairs) {
DdMetaVariable<CUDD> const& variable1 = this->getDdManager()->getMetaVariable(metaVariablePair.first);
DdMetaVariable<CUDD> const& variable2 = this->getDdManager()->getMetaVariable(metaVariablePair.second);
// Check if it's legal so swap the meta variables.
if (variable1.getNumberOfDdVariables() != variable2.getNumberOfDdVariables()) {
throw storm::exceptions::InvalidArgumentException() << "Unable to swap meta variables with different size.";
}
// Keep track of the contained meta variables in the DD.
bool containsVariable1 = this->containsMetaVariable(metaVariablePair.first);
bool containsVariable2 = this->containsMetaVariable(metaVariablePair.second);
if (containsVariable1 && !containsVariable2) {
this->removeContainedMetaVariable(metaVariablePair.first);
this->addContainedMetaVariable(metaVariablePair.second);
} else if (!containsVariable1 && containsVariable2) {
this->removeContainedMetaVariable(metaVariablePair.second);
this->addContainedMetaVariable(metaVariablePair.first);
}
// Add the variables to swap to the corresponding vectors.
for (auto const& ddVariable : variable1.getDdVariables()) {
from.push_back(ddVariable.getCuddAdd());
}
for (auto const& ddVariable : variable2.getDdVariables()) {
to.push_back(ddVariable.getCuddAdd());
}
}
// Finally, call CUDD to swap the variables.
this->getCuddAdd().SwapVariables(from, to);
}
Dd<CUDD> Dd<CUDD>::multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames) {
std::vector<ADD> summationDdVariables;
// Create the CUDD summation variables.
for (auto const& metaVariableName : summationMetaVariableNames) {
for (auto const& ddVariable : this->getDdManager()->getMetaVariable(metaVariableName).getDdVariables()) {
summationDdVariables.push_back(ddVariable.getCuddAdd());
}
}
std::set<std::string> unionOfMetaVariableNames;
std::set_union(this->getContainedMetaVariableNames().begin(), this->getContainedMetaVariableNames().end(), otherMatrix.getContainedMetaVariableNames().begin(), otherMatrix.getContainedMetaVariableNames().end(), std::inserter(unionOfMetaVariableNames, unionOfMetaVariableNames.begin()));
std::set<std::string> containedMetaVariableNames;
std::set_difference(unionOfMetaVariableNames.begin(), unionOfMetaVariableNames.end(), summationMetaVariableNames.begin(), summationMetaVariableNames.end(), std::inserter(containedMetaVariableNames, containedMetaVariableNames.begin()));
return Dd<CUDD>(this->getDdManager(), this->getCuddAdd().MatrixMultiply(otherMatrix.getCuddAdd(), summationDdVariables), containedMetaVariableNames);
}
uint_fast64_t Dd<CUDD>::getNonZeroCount() const {
std::size_t numberOfDdVariables = 0;
for (auto const& metaVariableName : this->containedMetaVariableNames) {
numberOfDdVariables += this->getDdManager()->getMetaVariable(metaVariableName).getNumberOfDdVariables();
}
return static_cast<uint_fast64_t>(this->cuddAdd.CountMinterm(static_cast<int>(numberOfDdVariables)));
}
uint_fast64_t Dd<CUDD>::getLeafCount() const {
return static_cast<uint_fast64_t>(this->cuddAdd.CountLeaves());
}
uint_fast64_t Dd<CUDD>::getNodeCount() const {
return static_cast<uint_fast64_t>(this->cuddAdd.nodeCount());
}
double Dd<CUDD>::getMin() const {
ADD constantMinAdd = this->getCuddAdd().FindMin();
return static_cast<double>(Cudd_V(constantMinAdd.getNode()));
}
double Dd<CUDD>::getMax() const {
ADD constantMaxAdd = this->getCuddAdd().FindMax();
return static_cast<double>(Cudd_V(constantMaxAdd.getNode()));
}
void Dd<CUDD>::setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue) {
std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap;
metaVariableNameToValueMap.emplace(metaVariableName, variableValue);
this->setValue(metaVariableNameToValueMap, targetValue);
}
void Dd<CUDD>::setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue) {
std::unordered_map<std::string, int_fast64_t> metaVariableNameToValueMap;
metaVariableNameToValueMap.emplace(metaVariableName1, variableValue1);
metaVariableNameToValueMap.emplace(metaVariableName2, variableValue2);
this->setValue(metaVariableNameToValueMap, targetValue);
}
void Dd<CUDD>::setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue) {
Dd<CUDD> valueEncoding(this->getDdManager()->getOne());
for (auto const& nameValuePair : metaVariableNameToValueMap) {
valueEncoding *= this->getDdManager()->getEncoding(nameValuePair.first, nameValuePair.second);
}
this->getCuddAdd() = valueEncoding.getCuddAdd().Ite(this->getDdManager()->getConstant(targetValue).getCuddAdd(), this->cuddAdd);
}
bool Dd<CUDD>::isOne() const {
return *this == this->getDdManager()->getOne();
}
bool Dd<CUDD>::isZero() const {
return *this == this->getDdManager()->getZero();
}
bool Dd<CUDD>::containsMetaVariable(std::string const& metaVariableName) const {
auto const& metaVariable = containedMetaVariableNames.find(metaVariableName);
return metaVariable != containedMetaVariableNames.end();
}
bool Dd<CUDD>::containsMetaVariables(std::set<std::string> metaVariableNames) const {
for (auto const& metaVariableName : metaVariableNames) {
auto const& metaVariable = containedMetaVariableNames.find(metaVariableName);
if (metaVariable == containedMetaVariableNames.end()) {
return false;
}
}
return true;
}
std::set<std::string> const& Dd<CUDD>::getContainedMetaVariableNames() const {
return this->containedMetaVariableNames;
}
std::set<std::string>& Dd<CUDD>::getContainedMetaVariableNames() {
return this->containedMetaVariableNames;
}
void Dd<CUDD>::exportToDot(std::string const& filename) const {
FILE* filePointer = fopen(filename.c_str() , "w");
this->getDdManager()->getCuddManager().DumpDot({this->cuddAdd}, nullptr, nullptr, filePointer);
fclose(filePointer);
}
ADD Dd<CUDD>::getCuddAdd() {
return this->cuddAdd;
}
ADD const& Dd<CUDD>::getCuddAdd() const {
return this->cuddAdd;
}
void Dd<CUDD>::addContainedMetaVariable(std::string const& metaVariableName) {
this->getContainedMetaVariableNames().insert(metaVariableName);
}
void Dd<CUDD>::removeContainedMetaVariable(std::string const& metaVariableName) {
this->getContainedMetaVariableNames().erase(metaVariableName);
}
std::shared_ptr<DdManager<CUDD>> Dd<CUDD>::getDdManager() const {
return this->ddManager;
}
}
}

407
src/storage/dd/CuddDd.h

@ -0,0 +1,407 @@
#ifndef STORM_STORAGE_DD_CUDDDD_H_
#define STORM_STORAGE_DD_CUDDDD_H_
#include <unordered_map>
#include <set>
#include <memory>
#include "src/storage/dd/Dd.h"
#include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD.
#include "cuddObj.hh"
namespace storm {
namespace dd {
// Forward-declare the DdManager class.
template<DdType Type> class DdManager;
template<>
class Dd<CUDD> {
public:
// Declare the DdManager class as friend so it can access the internals of a DD.
friend class DdManager<CUDD>;
// Instantiate all copy/move constructors/assignments with the default implementation.
Dd() = default;
Dd(Dd<CUDD> const& other) = default;
Dd& operator=(Dd<CUDD> const& other) = default;
#ifndef WINDOWS
Dd(Dd<CUDD>&& other) = default;
Dd& operator=(Dd<CUDD>&& other) = default;
#endif
/*!
* Retrieves whether the two DDs represent the same function.
*
* @param other The DD that is to be compared with the current one.
*/
bool operator==(Dd<CUDD> const& other) const;
/*!
* Adds the two DDs.
*
* @param other The DD to add to the current one.
* @return The result of the addition.
*/
Dd<CUDD> operator+(Dd<CUDD> const& other) const;
/*!
* Adds the given DD to the current one.
*
* @param other The DD to add to the current one.
* @return A reference to the current DD after the operation.
*/
Dd<CUDD>& operator+=(Dd<CUDD> const& other);
/*!
* Multiplies the two DDs.
*
* @param other The DD to multiply with the current one.
* @return The result of the multiplication.
*/
Dd<CUDD> operator*(Dd<CUDD> const& other) const;
/*!
* Multiplies the given DD with the current one and assigns the result to the current DD.
*
* @param other The DD to multiply with the current one.
* @return A reference to the current DD after the operation.
*/
Dd<CUDD>& operator*=(Dd<CUDD> const& other);
/*!
* Subtracts the given DD from the current one.
*
* @param other The DD to subtract from the current one.
* @return The result of the subtraction.
*/
Dd<CUDD> operator-(Dd<CUDD> const& other) const;
/*!
* Subtracts the given DD from the current one and assigns the result to the current DD.
*
* @param other The DD to subtract from the current one.
* @return A reference to the current DD after the operation.
*/
Dd<CUDD>& operator-=(Dd<CUDD> const& other);
/*!
* Divides the current DD by the given one.
*
* @param other The DD by which to divide the current one.
* @return The result of the division.
*/
Dd<CUDD> operator/(Dd<CUDD> const& other) const;
/*!
* Divides the current DD by the given one and assigns the result to the current DD.
*
* @param other The DD by which to divide the current one.
* @return A reference to the current DD after the operation.
*/
Dd<CUDD>& operator/=(Dd<CUDD> const& other);
/*!
* Subtracts the DD from the constant zero function.
*
* @return The resulting function represented as a DD.
*/
Dd<CUDD> minus() const;
/*!
* Retrieves the logical complement of the current DD. The result will map all encodings with a value
* unequal to zero to false and all others to true.
*
* @return The logical complement of the current DD.
*/
Dd<CUDD> operator~() const;
/*!
* Logically complements the current DD. The result will map all encodings with a value
* unequal to zero to false and all others to true.
*
* @return A reference to the current DD after the operation.
*/
Dd<CUDD>& complement();
/*!
* Retrieves the function that maps all evaluations to one that have an identical function values.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> equals(Dd<CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one that have distinct function values.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> notEquals(Dd<CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first DD are less
* than the one in the given DD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> less(Dd<CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first DD are less or
* equal than the one in the given DD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> lessOrEqual(Dd<CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
* than the one in the given DD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> greater(Dd<CUDD> const& other) const;
/*!
* Retrieves the function that maps all evaluations to one whose function value in the first DD are greater
* or equal than the one in the given DD.
*
* @param other The DD with which to perform the operation.
* @return The resulting function represented as a DD.
*/
Dd<CUDD> greaterOrEqual(Dd<CUDD> const& other) const;
/*!
* Existentially abstracts from the given meta variables.
*
* @param metaVariableNames The names of all meta variables from which to abstract.
*/
void existsAbstract(std::set<std::string> const& metaVariableNames);
/*!
* Sum-abstracts from the given meta variables.
*
* @param metaVariableNames The names of all meta variables from which to abstract.
*/
void sumAbstract(std::set<std::string> const& metaVariableNames);
/*!
* Min-abstracts from the given meta variables.
*
* @param metaVariableNames The names of all meta variables from which to abstract.
*/
void minAbstract(std::set<std::string> const& metaVariableNames);
/*!
* Max-abstracts from the given meta variables.
*
* @param metaVariableNames The names of all meta variables from which to abstract.
*/
void maxAbstract(std::set<std::string> const& metaVariableNames);
/*!
* Swaps the given pairs of meta variables in the DD. The pairs of meta variables must be guaranteed to have
* the same number of underlying DD variables.
*
* @param metaVariablePairs A vector of meta variable pairs that are to be swapped for one another.
*/
void swapVariables(std::vector<std::pair<std::string, std::string>> const& metaVariablePairs);
/*!
* Multiplies the current DD (representing a matrix) with the given matrix by summing over the given meta
* variables.
*
* @param otherMatrix The matrix with which to multiply.
* @param summationMetaVariableNames The names of the meta variables over which to sum during the matrix-
* matrix multiplication.
* @return A DD representing the result of the matrix-matrix multiplication.
*/
Dd<CUDD> multiplyMatrix(Dd<CUDD> const& otherMatrix, std::set<std::string> const& summationMetaVariableNames);
/*!
* Retrieves the number of encodings that are mapped to a non-zero value.
*
* @return The number of encodings that are mapped to a non-zero value.
*/
uint_fast64_t getNonZeroCount() const;
/*!
* Retrieves the number of leaves of the DD.
*
* @return The number of leaves of the DD.
*/
uint_fast64_t getLeafCount() const;
/*!
* Retrieves the number of nodes necessary to represent the DD.
*
* @return The number of nodes in this DD.
*/
uint_fast64_t getNodeCount() const;
/*!
* Retrieves the lowest function value of any encoding.
*
* @return The lowest function value of any encoding.
*/
double getMin() const;
/*!
* Retrieves the highest function value of any encoding.
*
* @return The highest function value of any encoding.
*/
double getMax() const;
/*!
* Sets the function values of all encodings that have the given value of the meta variable to the given
* target value.
*
* @param metaVariableName The name of the meta variable that has to be equal to the given value.
* @param variableValue The value that the meta variable is supposed to have. This must be within the range
* of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(std::string const& metaVariableName, int_fast64_t variableValue, double targetValue);
/*!
* Sets the function values of all encodings that have the given values of the two meta variables to the
* given target value.
*
* @param metaVariableName1 The name of the first meta variable that has to be equal to the first given
* value.
* @param variableValue1 The value that the first meta variable is supposed to have. This must be within the
* range of the meta variable.
* @param metaVariableName2 The name of the first meta variable that has to be equal to the second given
* value.
* @param variableValue2 The value that the second meta variable is supposed to have. This must be within
* the range of the meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(std::string const& metaVariableName1, int_fast64_t variableValue1, std::string const& metaVariableName2, int_fast64_t variableValue2, double targetValue);
/*!
* Sets the function values of all encodings that have the given values of the given meta variables to the
* given target value.
*
* @param metaVariableNameToValueMap A mapping of meta variable names to the values they are supposed to
* have. All values must be within the range of the respective meta variable.
* @param targetValue The new function value of the modified encodings.
*/
void setValue(std::unordered_map<std::string, int_fast64_t> const& metaVariableNameToValueMap, double targetValue);
/*!
* Retrieves whether this DD represents the constant one function.
*
* @return True if this DD represents the constant one function.
*/
bool isOne() const;
/*!
* Retrieves whether this DD represents the constant zero function.
*
* @return True if this DD represents the constant zero function.
*/
bool isZero() const;
/*!
* Retrieves whether the given meta variable is contained in the DD.
*
* @param metaVariableName The name of the meta variable for which to query membership.
* @return True iff the meta variable is contained in the DD.
*/
bool containsMetaVariable(std::string const& metaVariableName) const;
/*!
* Retrieves whether the given meta variables are all contained in the DD.
*
* @param metaVariableNames The names of the meta variable for which to query membership.
* @return True iff all meta variables are contained in the DD.
*/
bool containsMetaVariables(std::set<std::string> metaVariableNames) const;
/*!
* Retrieves the set of all names of meta variables contained in the DD.
*
* @return The set of names of all meta variables contained in the DD.
*/
std::set<std::string> const& getContainedMetaVariableNames() const;
/*!
* Retrieves the set of all names of meta variables contained in the DD.
*
* @return The set of names of all meta variables contained in the DD.
*/
std::set<std::string>& getContainedMetaVariableNames();
/*!
* Exports the DD to the given file in the dot format.
*
* @param filename The name of the file to which the DD is to be exported.
*/
void exportToDot(std::string const& filename) const;
/*!
* Retrieves the manager that is responsible for this DD.
*
* A pointer to the manager that is responsible for this DD.
*/
std::shared_ptr<DdManager<CUDD>> getDdManager() const;
private:
/*!
* Retrieves the CUDD ADD object associated with this DD.
*
* @return The CUDD ADD object assoicated with this DD.
*/
ADD getCuddAdd();
/*!
* Retrieves the CUDD ADD object associated with this DD.
*
* @return The CUDD ADD object assoicated with this DD.
*/
ADD const& getCuddAdd() const;
/*!
* Adds the given meta variable name to the set of meta variables that are contained in this DD.
*
* @param metaVariableName The name of the meta variable to add.
*/
void addContainedMetaVariable(std::string const& metaVariableName);
/*!
* Removes the given meta variable name to the set of meta variables that are contained in this DD.
*
* @param metaVariableName The name of the meta variable to remove.
*/
void removeContainedMetaVariable(std::string const& metaVariableName);
/*!
* Creates a DD that encapsulates the given CUDD ADD.
*
* @param ddManager The manager responsible for this DD.
* @param cuddAdd The CUDD ADD to store.
* @param
*/
Dd(std::shared_ptr<DdManager<CUDD>> ddManager, ADD cuddAdd, std::set<std::string> const& containedMetaVariableNames = std::set<std::string>());
// A pointer to the manager responsible for this DD.
std::shared_ptr<DdManager<CUDD>> ddManager;
// The ADD created by CUDD.
ADD cuddAdd;
// The names of all meta variables that appear in this DD.
std::set<std::string> containedMetaVariableNames;
};
}
}
#endif /* STORM_STORAGE_DD_CUDDDD_H_ */

149
src/storage/dd/CuddDdManager.cpp

@ -0,0 +1,149 @@
#include <cmath>
#include <algorithm>
#include "src/storage/dd/CuddDdManager.h"
#include "src/exceptions/InvalidArgumentException.h"
#include <iostream>
namespace storm {
namespace dd {
DdManager<CUDD>::DdManager() : metaVariableMap(), cuddManager() {
// Intentionally left empty.
}
Dd<CUDD> DdManager<CUDD>::getOne() {
return Dd<CUDD>(this->shared_from_this(), cuddManager.addOne());
}
Dd<CUDD> DdManager<CUDD>::getZero() {
return Dd<CUDD>(this->shared_from_this(), cuddManager.addZero());
}
Dd<CUDD> DdManager<CUDD>::getConstant(double value) {
return Dd<CUDD>(this->shared_from_this(), cuddManager.constant(value));
}
Dd<CUDD> DdManager<CUDD>::getEncoding(std::string const& metaVariableName, int_fast64_t value) {
std::vector<Dd<CUDD>> ddVariables = this->getMetaVariable(metaVariableName).getDdVariables();
Dd<CUDD> result;
if (value & (1ull << (ddVariables.size() - 1))) {
result = ddVariables[0];
} else {
result = ddVariables[0];
}
for (std::size_t i = 1; i < ddVariables.size(); ++i) {
if (value & (1ull << (ddVariables.size() - i - 1))) {
result *= ddVariables[i];
} else {
result *= ~ddVariables[i];
}
}
return result;
}
Dd<CUDD> DdManager<CUDD>::getRange(std::string const metaVariableName) {
storm::dd::DdMetaVariable<CUDD> const& metaVariable = this->getMetaVariable(metaVariableName);
Dd<CUDD> result = this->getZero();
for (int_fast64_t value = metaVariable.getLow(); value <= metaVariable.getHigh(); ++value) {
result.setValue(metaVariableName, value - metaVariable.getLow(), static_cast<double>(value));
}
return result;
}
void DdManager<CUDD>::addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high) {
// Check whether a meta variable already exists.
if (this->hasMetaVariable(name)) {
throw storm::exceptions::InvalidArgumentException() << "A meta variable '" << name << "' already exists.";
}
// Check that the range is legal.
if (high == low) {
throw storm::exceptions::InvalidArgumentException() << "Range of meta variable must be at least 2 elements.";
}
std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1)));
std::vector<Dd<CUDD>> variables;
for (std::size_t i = 0; i < numberOfBits; ++i) {
variables.emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {name}));
}
metaVariableMap.emplace(name, DdMetaVariable<CUDD>(name, low, high, variables, this->shared_from_this()));
}
void DdManager<CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) {
// Make sure that at least one meta variable is added.
if (names.size() == 0) {
throw storm::exceptions::InvalidArgumentException() << "Illegal to add zero meta variables.";
}
// Check that there are no duplicate names in the given name vector.
std::vector<std::string> nameCopy(names);
std::sort(nameCopy.begin(), nameCopy.end());
if (std::adjacent_find(nameCopy.begin(), nameCopy.end()) != nameCopy.end()) {
throw storm::exceptions::InvalidArgumentException() << "Cannot add duplicate meta variables.";
}
// Check that the range is legal.
if (high == low) {
throw storm::exceptions::InvalidArgumentException() << "Range of meta variable must be at least 2 elements.";
}
// Check whether a meta variable already exists.
for (auto const& metaVariableName : names) {
if (this->hasMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "A meta variable '" << metaVariableName << "' already exists.";
}
}
// Add the variables in interleaved order.
std::size_t numberOfBits = static_cast<std::size_t>(std::ceil(std::log2(high - low + 1)));
std::vector<std::vector<Dd<CUDD>>> variables(names.size());
for (uint_fast64_t bit = 0; bit < numberOfBits; ++bit) {
for (uint_fast64_t i = 0; i < names.size(); ++i) {
variables[i].emplace_back(Dd<CUDD>(this->shared_from_this(), cuddManager.addVar(), {names[i]}));
}
}
// Now add the meta variables.
for (uint_fast64_t i = 0; i < names.size(); ++i) {
metaVariableMap.emplace(names[i], DdMetaVariable<CUDD>(names[i], low, high, variables[i], this->shared_from_this()));
}
}
DdMetaVariable<CUDD> const& DdManager<CUDD>::getMetaVariable(std::string const& metaVariableName) const {
auto const& nameVariablePair = metaVariableMap.find(metaVariableName);
if (!this->hasMetaVariable(metaVariableName)) {
throw storm::exceptions::InvalidArgumentException() << "Unknown meta variable name.";
}
return nameVariablePair->second;
}
std::set<std::string> DdManager<CUDD>::getAllMetaVariableNames() const {
std::set<std::string> result;
for (auto const& nameValuePair : metaVariableMap) {
result.insert(nameValuePair.first);
}
return result;
}
std::size_t DdManager<CUDD>::getNumberOfMetaVariables() const {
return this->metaVariableMap.size();
}
bool DdManager<CUDD>::hasMetaVariable(std::string const& metaVariableName) const {
return this->metaVariableMap.find(metaVariableName) != this->metaVariableMap.end();
}
Cudd& DdManager<CUDD>::getCuddManager() {
return this->cuddManager;
}
}
}

141
src/storage/dd/CuddDdManager.h

@ -0,0 +1,141 @@
#ifndef STORM_STORAGE_DD_CUDDDDMANAGER_H_
#define STORM_STORAGE_DD_CUDDDDMANAGER_H_
#include <unordered_map>
#include "src/storage/dd/DdManager.h"
#include "src/storage/dd/DdMetaVariable.h"
#include "src/storage/dd/CuddDd.h"
#include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD.
#include "cuddObj.hh"
namespace storm {
namespace dd {
template<>
class DdManager<CUDD> : public std::enable_shared_from_this<DdManager<CUDD>> {
public:
// To break the cylic dependencies, we need to forward-declare the other DD-related classes.
friend class Dd<CUDD>;
/*!
* Creates an empty manager without any meta variables.
*/
DdManager();
// Explictly forbid copying a DdManager, but allow moving it.
DdManager(DdManager<CUDD> const& other) = delete;
DdManager<CUDD>& operator=(DdManager<CUDD> const& other) = delete;
#ifndef WINDOWS
DdManager(DdManager<CUDD>&& other) = default;
DdManager<CUDD>& operator=(DdManager<CUDD>&& other) = default;
#endif
/*!
* Retrieves a DD representing the constant one function.
*
* @return A DD representing the constant one function.
*/
Dd<CUDD> getOne();
/*!
* Retrieves a DD representing the constant zero function.
*
* @return A DD representing the constant zero function.
*/
Dd<CUDD> getZero();
/*!
* Retrieves a DD representing the constant function with the given value.
*
* @return A DD representing the constant function with the given value.
*/
Dd<CUDD> getConstant(double value);
/*!
* Retrieves the DD representing the function that maps all inputs which have the given meta variable equal
* to the given value one.
*
* @param metaVariableName The meta variable that is supposed to have the given value.
* @param value The value the meta variable is supposed to have.
* @return The DD representing the function that maps all inputs which have the given meta variable equal
* to the given value one.
*/
Dd<CUDD> getEncoding(std::string const& metaVariableName, int_fast64_t value);
/*!
* Retrieves the DD representing the range of the meta variable, i.e., a function that maps all legal values
* of the range of the meta variable to one.
*
* @param metaVariableName The name of the meta variable whose range to retrieve.
* @return The range of the meta variable
*/
Dd<CUDD> getRange(std::string const metaVariableName);
/*!
* Adds a meta variable with the given name and range.
*
* @param name The name of the meta variable.
* @param low The lowest value of the range of the variable.
* @param high The highest value of the range of the variable.
*/
void addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high);
/*!
* Adds meta variables with the given names and (equal) range and arranges the DD variables in an interleaved order.
*
* @param names The names of the variables.
* @param low The lowest value of the ranges of the variables.
* @param high The highest value of the ranges of the variables.
*/
void addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high);
/*!
* Retrieves the meta variable with the given name if it exists.
*
* @param metaVariableName The name of the meta variable to retrieve.
* @return The meta variable with the given name.
*/
DdMetaVariable<CUDD> const& getMetaVariable(std::string const& metaVariableName) const;
/*!
* Retrieves the names of all meta variables that have been added to the manager.
*
* @return The set of all meta variable names of the manager.
*/
std::set<std::string> getAllMetaVariableNames() const;
/*!
* Retrieves the number of meta variables that are contained in this manager.
*
* @return The number of meta variables contained in this manager.
*/
std::size_t getNumberOfMetaVariables() const;
/*!
* Retrieves whether the given meta variable name is already in use.
*
* @param metaVariableName The meta variable name whose membership to query.
* @return True if the given meta variable name is managed by this manager.
*/
bool hasMetaVariable(std::string const& metaVariableName) const;
private:
/*!
* Retrieves the underlying CUDD manager.
*
* @return The underlying CUDD manager.
*/
Cudd& getCuddManager();
// A mapping from variable names to the meta variable information.
std::unordered_map<std::string, DdMetaVariable<CUDD>> metaVariableMap;
// The manager responsible for the DDs created/modified with this DdManager.
Cudd cuddManager;
};
}
}
#endif /* STORM_STORAGE_DD_CUDDDDMANAGER_H_ */

13
src/storage/dd/Dd.h

@ -0,0 +1,13 @@
#ifndef STORM_STORAGE_DD_DD_H_
#define STORM_STORAGE_DD_DD_H_
#include "src/storage/dd/DdType.h"
namespace storm {
namespace dd {
// Declare Dd class so we can then specialize it for the different DD types.
template<DdType Type> class Dd;
}
}
#endif /* STORM_STORAGE_DD_DD_H_ */

13
src/storage/dd/DdManager.h

@ -0,0 +1,13 @@
#ifndef STORM_STORAGE_DD_DDMANAGER_H_
#define STORM_STORAGE_DD_DDMANAGER_H_
#include "src/storage/dd/DdType.h"
namespace storm {
namespace dd {
// Declare DdManager class so we can then specialize it for the different DD types.
template<DdType Type> class DdManager;
}
}
#endif /* STORM_STORAGE_DD_DDMANAGER_H_ */

52
src/storage/dd/DdMetaVariable.cpp

@ -0,0 +1,52 @@
#include "src/storage/dd/DdMetaVariable.h"
#include "src/storage/dd/CuddDdManager.h"
namespace storm {
namespace dd {
template<DdType Type>
DdMetaVariable<Type>::DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Dd<Type>> const& ddVariables, std::shared_ptr<DdManager<Type>> manager) : name(name), low(low), high(high), ddVariables(ddVariables), cube(manager->getOne()), manager(manager) {
// Create the cube of all variables of this meta variable.
for (auto const& ddVariable : this->ddVariables) {
this->cube *= ddVariable;
}
}
template<DdType Type>
std::string const& DdMetaVariable<Type>::getName() const {
return this->name;
}
template<DdType Type>
int_fast64_t DdMetaVariable<Type>::getLow() const {
return this->low;
}
template<DdType Type>
int_fast64_t DdMetaVariable<Type>::getHigh() const {
return this->high;
}
template<DdType Type>
std::size_t DdMetaVariable<Type>::getNumberOfDdVariables() const {
return this->ddVariables.size();
}
template<DdType Type>
std::shared_ptr<DdManager<Type>> DdMetaVariable<Type>::getDdManager() const {
return this->manager;
}
template<DdType Type>
std::vector<Dd<Type>> const& DdMetaVariable<Type>::getDdVariables() const {
return this->ddVariables;
}
template<DdType Type>
Dd<Type> const& DdMetaVariable<Type>::getCube() const {
return this->cube;
}
// Explicitly instantiate DdMetaVariable.
template class DdMetaVariable<CUDD>;
}
}

114
src/storage/dd/DdMetaVariable.h

@ -0,0 +1,114 @@
#ifndef STORM_STORAGE_DD_DDMETAVARIABLE_H_
#define STORM_STORAGE_DD_DDMETAVARIABLE_H_
#include <memory>
#include <vector>
#include <cstdint>
#include <string>
#include "utility/OsDetection.h"
#include "src/storage/dd/CuddDd.h"
namespace storm {
namespace dd {
// Forward-declare the DdManager class.
template<DdType Type> class DdManager;
template <DdType Type>
class DdMetaVariable {
public:
// Declare the DdManager class as friend so it can access the internals of a meta variable.
friend class DdManager<Type>;
friend class Dd<Type>;
/*!
* Creates a meta variable with the given name, range bounds.
*
* @param name The name of the meta variable.
* @param low The lowest value of the range of the variable.
* @param high The highest value of the range of the variable.
* @param ddVariables The vector of variables used to encode this variable.
* @param manager A pointer to the manager that is responsible for this meta variable.
*/
DdMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high, std::vector<Dd<Type>> const& ddVariables, std::shared_ptr<DdManager<Type>> manager);
// Explictly generate all default versions of copy/move constructors/assignments.
DdMetaVariable(DdMetaVariable const& other) = default;
DdMetaVariable& operator=(DdMetaVariable const& other) = default;
#ifndef WINDOWS
DdMetaVariable(DdMetaVariable&& other) = default;
DdMetaVariable& operator=(DdMetaVariable&& other) = default;
#endif
/*!
* Retrieves the name of the meta variable.
*
* @return The name of the variable.
*/
std::string const& getName() const;
/*!
* Retrieves the lowest value of the range of the variable.
*
* @return The lowest value of the range of the variable.
*/
int_fast64_t getLow() const;
/*!
* Retrieves the highest value of the range of the variable.
*
* @return The highest value of the range of the variable.
*/
int_fast64_t getHigh() const;
/*!
* Retrieves the manager that is responsible for this meta variable.
*
* A pointer to the manager that is responsible for this meta variable.
*/
std::shared_ptr<DdManager<Type>> getDdManager() const;
/*!
* Retrieves the number of DD variables for this meta variable.
*
* @return The number of DD variables for this meta variable.
*/
std::size_t getNumberOfDdVariables() const;
private:
/*!
* Retrieves the variables used to encode the meta variable.
*
* @return A vector of variables used to encode the meta variable.
*/
std::vector<Dd<Type>> const& getDdVariables() const;
/*!
* Retrieves the cube of all variables that encode this meta variable.
*
* @return The cube of all variables that encode this meta variable.
*/
Dd<Type> const& getCube() const;
// The name of the meta variable.
std::string name;
// The lowest value of the range of the variable.
int_fast64_t low;
// The highest value of the range of the variable.
int_fast64_t high;
// The vector of variables that are used to encode the meta variable.
std::vector<Dd<Type>> ddVariables;
// The cube consisting of all variables that encode the meta variable.
Dd<Type> cube;
// A pointer to the manager responsible for this meta variable.
std::shared_ptr<DdManager<Type>> manager;
};
}
}
#endif /* STORM_STORAGE_DD_DDMETAVARIABLE_H_ */

12
src/storage/dd/DdType.h

@ -0,0 +1,12 @@
#ifndef STORM_STORAGE_DD_DDTYPE_H_
#define STORM_STORAGE_DD_DDTYPE_H_
namespace storm {
namespace dd {
enum DdType {
CUDD
};
}
}
#endif /* STORM_STORAGE_DD_DDTYPE_H_ */

3
src/storm.cpp

@ -21,6 +21,7 @@
#include <vector>
#include "storm-config.h"
#include "storm-version.h"
#include "src/models/Dtmc.h"
#include "src/models/MarkovAutomaton.h"
#include "src/storage/SparseMatrix.h"
@ -240,7 +241,7 @@ void setUp() {
* Performs some necessary clean-up.
*/
void cleanUp() {
delete storm::utility::cuddUtilityInstance();
// Intentionally left empty.
}
/*!

1
src/utility/vector.h

@ -94,7 +94,6 @@ namespace storm {
*/
template<class T>
void selectVectorValues(std::vector<T>& vector, std::vector<uint_fast64_t> const& rowGroupToRowIndexMapping, std::vector<uint_fast64_t> const& rowGrouping, std::vector<T> const& values) {
uint_fast64_t oldPosition = 0;
for (uint_fast64_t i = 0; i < vector.size(); ++i) {
vector[i] = values[rowGrouping[i] + rowGroupToRowIndexMapping[i]];
}

7
storm-config.h.in

@ -8,13 +8,6 @@
#ifndef STORM_GENERATED_STORMCONFIG_H_
#define STORM_GENERATED_STORMCONFIG_H_
// Version Information
#define STORM_CPP_VERSION_MAJOR @STORM_CPP_VERSION_MAJOR@ // The major version of StoRM
#define STORM_CPP_VERSION_MINOR @STORM_CPP_VERSION_MINOR@ // The minor version of StoRM
#define STORM_CPP_VERSION_PATCH @STORM_CPP_VERSION_PATCH@ // The patch version of StoRM
#define STORM_CPP_VERSION_COMMITS_AHEAD @STORM_CPP_VERSION_COMMITS_AHEAD@ // How many commits passed since the tag was last set
#define STORM_CPP_VERSION_HASH "@STORM_CPP_VERSION_HASH@" // The short hash of the git commit this build is bases on
#define STORM_CPP_VERSION_DIRTY @STORM_CPP_VERSION_DIRTY@ // 0 iff there no files were modified in the checkout, 1 else
// The path of the sources from which StoRM will be/was build
#define STORM_CPP_BASE_PATH "@PROJECT_SOURCE_DIR@"

12
storm-version.h.in

@ -0,0 +1,12 @@
#ifndef STORM_GENERATED_VERSION_H_
#define STORM_GENERATED_VERSION_H_
// Version Information
#define STORM_CPP_VERSION_MAJOR @STORM_CPP_VERSION_MAJOR@ // The major version of StoRM
#define STORM_CPP_VERSION_MINOR @STORM_CPP_VERSION_MINOR@ // The minor version of StoRM
#define STORM_CPP_VERSION_PATCH @STORM_CPP_VERSION_PATCH@ // The patch version of StoRM
#define STORM_CPP_VERSION_COMMITS_AHEAD @STORM_CPP_VERSION_COMMITS_AHEAD@ // How many commits passed since the tag was last set
#define STORM_CPP_VERSION_HASH "@STORM_CPP_VERSION_HASH@" // The short hash of the git commit this build is bases on
#define STORM_CPP_VERSION_DIRTY @STORM_CPP_VERSION_DIRTY@ // 0 iff there no files were modified in the checkout, 1 else
#endif

71
test/functional/storage/CuddDdTest.cpp

@ -0,0 +1,71 @@
#include "gtest/gtest.h"
#include "storm-config.h"
#include "src/exceptions/InvalidArgumentException.h"
#include "src/storage/dd/CuddDdManager.h"
#include "src/storage/dd/CuddDd.h"
#include "src/storage/dd/DdMetaVariable.h"
TEST(CuddDdManager, Constants) {
std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>());
storm::dd::Dd<storm::dd::CUDD> zero;
ASSERT_NO_THROW(zero = manager->getZero());
EXPECT_EQ(0, zero.getNonZeroCount());
EXPECT_EQ(1, zero.getLeafCount());
EXPECT_EQ(1, zero.getNodeCount());
EXPECT_EQ(0, zero.getMin());
EXPECT_EQ(0, zero.getMax());
storm::dd::Dd<storm::dd::CUDD> one;
ASSERT_NO_THROW(one = manager->getOne());
EXPECT_EQ(1, one.getNonZeroCount());
EXPECT_EQ(1, one.getLeafCount());
EXPECT_EQ(1, one.getNodeCount());
EXPECT_EQ(1, one.getMin());
EXPECT_EQ(1, one.getMax());
storm::dd::Dd<storm::dd::CUDD> two;
ASSERT_NO_THROW(two = manager->getConstant(2));
EXPECT_EQ(1, two.getNonZeroCount());
EXPECT_EQ(1, two.getLeafCount());
EXPECT_EQ(1, two.getNodeCount());
EXPECT_EQ(2, two.getMin());
EXPECT_EQ(2, two.getMax());
}
TEST(CuddDdManager, MetaVariableTest) {
std::shared_ptr<storm::dd::DdManager<storm::dd::CUDD>> manager(new storm::dd::DdManager<storm::dd::CUDD>());
ASSERT_NO_THROW(manager->addMetaVariable("x", 1, 9));
EXPECT_EQ(1, manager->getNumberOfMetaVariables());
std::vector<std::string> names = {"x", "x'"};
ASSERT_THROW(manager->addMetaVariablesInterleaved(names, 0, 3), storm::exceptions::InvalidArgumentException);
names = {"y", "y"};
ASSERT_THROW(manager->addMetaVariablesInterleaved(names, 0, 3), storm::exceptions::InvalidArgumentException);
names = {"y", "y'"};
ASSERT_NO_THROW(manager->addMetaVariablesInterleaved(names, 0, 3));
EXPECT_EQ(3, manager->getNumberOfMetaVariables());
EXPECT_FALSE(manager->hasMetaVariable("x'"));
EXPECT_TRUE(manager->hasMetaVariable("y'"));
std::set<std::string> metaVariableSet = {"x", "y", "y'"};
EXPECT_EQ(metaVariableSet, manager->getAllMetaVariableNames());
ASSERT_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x'"), storm::exceptions::InvalidArgumentException);
ASSERT_NO_THROW(storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x"));
storm::dd::DdMetaVariable<storm::dd::CUDD> const& metaVariableX = manager->getMetaVariable("x");
EXPECT_EQ(1, metaVariableX.getLow());
EXPECT_EQ(9, metaVariableX.getHigh());
EXPECT_EQ("x", metaVariableX.getName());
EXPECT_EQ(manager, metaVariableX.getDdManager());
EXPECT_EQ(4, metaVariableX.getNumberOfDdVariables());
}
Loading…
Cancel
Save