Browse Source

First version of DD iterator; small test included.

Former-commit-id: 2ec2323886
main
dehnert 11 years ago
parent
commit
6078e07476
  1. 2
      resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc
  2. 2
      resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh
  3. 11
      src/storage/dd/CuddDd.cpp
  4. 16
      src/storage/dd/CuddDd.h
  5. 148
      src/storage/dd/CuddDdForwardIterator.cpp
  6. 102
      src/storage/dd/CuddDdForwardIterator.h
  7. 12
      src/storage/dd/CuddDdManager.cpp
  8. 14
      src/storage/dd/CuddDdManager.h
  9. 15
      src/storage/dd/DdMetaVariable.cpp
  10. 25
      src/storage/dd/DdMetaVariable.h
  11. 11
      src/storage/expressions/SimpleValuation.cpp
  12. 21
      test/functional/storage/CuddDdTest.cpp

2
resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.cc

@ -5280,7 +5280,7 @@ int
ABDD::NextCube( ABDD::NextCube(
DdGen * gen, DdGen * gen,
int ** cube, int ** cube,
CUDD_VALUE_TYPE * value) const
CUDD_VALUE_TYPE * value)
{ {
return Cudd_NextCube(gen, cube, value); return Cudd_NextCube(gen, cube, value);

2
resources/3rdparty/cudd-2.5.0/src/obj/cuddObj.hh

@ -192,7 +192,7 @@ public:
const; const;
int CountLeaves() const; int CountLeaves() const;
DdGen * FirstCube(int ** cube, CUDD_VALUE_TYPE * value) const; DdGen * FirstCube(int ** cube, CUDD_VALUE_TYPE * value) const;
int NextCube(DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value) const;
static int NextCube(DdGen * gen, int ** cube, CUDD_VALUE_TYPE * value);
double Density(int nvars) const; double Density(int nvars) const;
}; // ABDD }; // ABDD

11
src/storage/dd/CuddDd.cpp

@ -434,6 +434,17 @@ namespace storm {
return this->ddManager; return this->ddManager;
} }
DdForwardIterator<DdType::CUDD> Dd<DdType::CUDD>::begin() const {
int* cube;
double value;
DdGen* generator = this->getCuddAdd().FirstCube(&cube, &value);
return DdForwardIterator<DdType::CUDD>(this->getDdManager(), generator, cube, value, Cudd_IsGenEmpty(generator), &this->getContainedMetaVariableNames());
}
DdForwardIterator<DdType::CUDD> Dd<DdType::CUDD>::end() const {
return DdForwardIterator<DdType::CUDD>(this->getDdManager(), nullptr, nullptr, 0, true, nullptr);
}
std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) { std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd) {
dd.exportToDot(); dd.exportToDot();
return out; return out;

16
src/storage/dd/CuddDd.h

@ -7,6 +7,7 @@
#include <iostream> #include <iostream>
#include "src/storage/dd/Dd.h" #include "src/storage/dd/Dd.h"
#include "src/storage/dd/CuddDdForwardIterator.h"
#include "src/utility/OsDetection.h" #include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD. // Include the C++-interface of CUDD.
@ -22,6 +23,7 @@ namespace storm {
public: public:
// Declare the DdManager and DdIterator class as friend so it can access the internals of a DD. // Declare the DdManager and DdIterator class as friend so it can access the internals of a DD.
friend class DdManager<DdType::CUDD>; friend class DdManager<DdType::CUDD>;
friend class DdForwardIterator<DdType::CUDD>;
// Instantiate all copy/move constructors/assignments with the default implementation. // Instantiate all copy/move constructors/assignments with the default implementation.
Dd() = default; Dd() = default;
@ -405,6 +407,20 @@ namespace storm {
*/ */
std::shared_ptr<DdManager<DdType::CUDD>> getDdManager() const; std::shared_ptr<DdManager<DdType::CUDD>> getDdManager() const;
/*!
* Retrieves an iterator that points to the first meta variable assignment with a non-zero function value.
*
* @return An iterator that points to the first meta variable assignment with a non-zero function value.
*/
DdForwardIterator<DdType::CUDD> begin() const;
/*!
* Retrieves an iterator that points past the end of the container.
*
* @return An iterator that points past the end of the container.
*/
DdForwardIterator<DdType::CUDD> end() const;
friend std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd); friend std::ostream & operator<<(std::ostream& out, const Dd<DdType::CUDD>& dd);
private: private:
/*! /*!

148
src/storage/dd/CuddDdForwardIterator.cpp

@ -1,24 +1,152 @@
#include "src/storage/dd/CuddDdForwardIterator.h" #include "src/storage/dd/CuddDdForwardIterator.h"
#include "src/storage/dd/CuddDdManager.h"
#include "src/storage/dd/DdMetaVariable.h"
#include "src/exceptions/ExceptionMacros.h"
namespace storm { namespace storm {
namespace dd { namespace dd {
DdForwardIterator<DdType::CUDD>::DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd) : ddManager(ddManager), value(0), cube(nullptr), cuddAdd(cuddAdd), isAtEnd(false), generator(nullptr) {
// Start by getting the first cube.
this->generator = this->cuddAdd.FirstCube(&cube, &value);
// If the generator is already empty, we set the corresponding flag.
this->isAtEnd = Cudd_IsGenEmpty(generator);
DdForwardIterator<DdType::CUDD>::DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<std::string> const* metaVariables) : ddManager(ddManager), generator(generator), cube(cube), value(value), isAtEnd(isAtEnd), metaVariables(metaVariables), cubeCounter(), relevantDontCareDdVariables(), currentValuation() {
// If the given generator is not yet at its end, we need to create the current valuation from the cube from
// scratch.
if (!this->isAtEnd) {
// Start by registering all meta variables in the valuation with the appropriate type.
for (auto const& metaVariableName : *this->metaVariables) {
auto const& metaVariable = this->ddManager->getMetaVariable(metaVariableName);
switch (metaVariable.getType()) {
case DdMetaVariable<DdType::CUDD>::MetaVariableType::Bool: currentValuation.addBooleanIdentifier(metaVariableName); break;
case DdMetaVariable<DdType::CUDD>::MetaVariableType::Int: currentValuation.addIntegerIdentifier(metaVariableName); break;
}
}
// And then get ready for treating the first cube.
this->treatNewCube();
}
}
DdForwardIterator<DdType::CUDD>::DdForwardIterator(DdForwardIterator<DdType::CUDD>&& other) : ddManager(other.ddManager), generator(other.generator), cube(other.cube), value(other.value), isAtEnd(other.isAtEnd), metaVariables(other.metaVariables), cubeCounter(other.cubeCounter), relevantDontCareDdVariables(other.relevantDontCareDdVariables), currentValuation(other.currentValuation) {
// Null-out the pointers of which we took possession.
other.cube = nullptr;
other.generator = nullptr;
}
DdForwardIterator<DdType::CUDD>& DdForwardIterator<DdType::CUDD>::operator=(DdForwardIterator<DdType::CUDD>&& other) {
if (this != &other) {
this->ddManager = other.ddManager;
this->generator = other.generator;
this->cube = other.cube;
this->value = other.value;
this->isAtEnd = other.isAtEnd;
this->metaVariables = other.metaVariables;
this->cubeCounter = other.cubeCounter;
this->relevantDontCareDdVariables = other.relevantDontCareDdVariables;
this->currentValuation = other.currentValuation;
// Null-out the pointers of which we took possession.
other.cube = nullptr;
other.generator = nullptr;
}
return *this;
}
DdForwardIterator<DdType::CUDD>::~DdForwardIterator() {
if (this->cube != nullptr) {
free(this->cube);
}
if (this->generator != nullptr) {
free(this->generator);
}
} }
DdForwardIterator<DdType::CUDD>& DdForwardIterator<DdType::CUDD>::operator++() { DdForwardIterator<DdType::CUDD>& DdForwardIterator<DdType::CUDD>::operator++() {
// TODO: eliminate current
LOG_ASSERT(!this->isAtEnd, "Illegally incrementing iterator that is already at its end.");
// If there were no (relevant) don't cares or we have enumerated all combination, we need to eliminate the
// found solutions and get the next "first" cube.
if (this->relevantDontCareDdVariables.empty() || this->cubeCounter >= std::pow(2, this->relevantDontCareDdVariables.size()) - 1) {
// Get the next cube and check for emptiness.
ABDD::NextCube(generator, &cube, &value);
this->isAtEnd = Cudd_IsGenEmpty(generator);
// In case we are not done yet, we get ready to treat the next cube.
if (!this->isAtEnd) {
this->treatNewCube();
}
} else {
// Treat the next solution of the cube.
this->treatNextInCube();
}
return *this;
}
void DdForwardIterator<DdType::CUDD>::treatNextInCube() {
// Start by increasing the counter and check which bits we need to set/unset in the new valuation.
++this->cubeCounter;
for (uint_fast64_t index = 0; index < this->relevantDontCareDdVariables.size(); ++index) {
auto const& metaVariable = this->ddManager->getMetaVariable(std::get<1>(this->relevantDontCareDdVariables[index]));
if (metaVariable.getType() == DdMetaVariable<DdType::CUDD>::MetaVariableType::Bool) {
if ((this->cubeCounter & (1ull << index)) != 0) {
currentValuation.setBooleanValue(metaVariable.getName(), true);
} else {
currentValuation.setBooleanValue(metaVariable.getName(), false);
}
} else {
if ((this->cubeCounter & (1ull << index)) != 0) {
currentValuation.setIntegerValue(metaVariable.getName(), ((currentValuation.getIntegerValue(metaVariable.getName()) - metaVariable.getLow()) | (1ull << std::get<2>(this->relevantDontCareDdVariables[index]))) + metaVariable.getLow());
} else {
currentValuation.setIntegerValue(metaVariable.getName(), ((currentValuation.getIntegerValue(metaVariable.getName()) - metaVariable.getLow()) & ~(1ull << std::get<2>(this->relevantDontCareDdVariables[index]))) + metaVariable.getLow());
}
}
}
}
void DdForwardIterator<DdType::CUDD>::treatNewCube() {
this->relevantDontCareDdVariables.clear();
// Now loop through the bits of all meta variables and check whether they need to be set, not set or are
// don't cares. In the latter case, we add them to a special list, so we can iterate over their concrete
// valuations later.
for (auto const& metaVariableName : *this->metaVariables) {
auto const& metaVariable = this->ddManager->getMetaVariable(metaVariableName);
if (metaVariable.getType() == DdMetaVariable<DdType::CUDD>::MetaVariableType::Bool) {
if (this->cube[metaVariable.getDdVariables()[0].getCuddAdd().NodeReadIndex()] == 0) {
currentValuation.setBooleanValue(metaVariableName, false);
} else if (this->cube[metaVariable.getDdVariables()[0].getCuddAdd().NodeReadIndex()] == 1) {
currentValuation.setBooleanValue(metaVariableName, true);
} else {
relevantDontCareDdVariables.push_back(std::make_tuple(metaVariable.getDdVariables()[0].getCuddAdd(), metaVariableName, 0));
}
} else {
int_fast64_t intValue = 0;
for (uint_fast64_t bitIndex = 0; bitIndex < metaVariable.getNumberOfDdVariables(); ++bitIndex) {
if (cube[metaVariable.getDdVariables()[bitIndex].getCuddAdd().NodeReadIndex()] == 0) {
// Leave bit unset.
} else if (cube[metaVariable.getDdVariables()[bitIndex].getCuddAdd().NodeReadIndex()] == 1) {
intValue |= 1ull << (metaVariable.getNumberOfDdVariables() - bitIndex - 1);
} else {
// Temporarily leave bit unset so we can iterate trough the other option later.
// Add the bit to the relevant don't care bits.
this->relevantDontCareDdVariables.push_back(std::make_tuple(metaVariable.getDdVariables()[bitIndex].getCuddAdd(), metaVariableName, metaVariable.getNumberOfDdVariables() - bitIndex - 1));
}
}
currentValuation.setIntegerValue(metaVariableName, intValue + metaVariable.getLow());
}
}
// Finally, reset the cube counter.
this->cubeCounter = 0;
} }
bool DdForwardIterator<DdType::CUDD>::operator==(DdForwardIterator<DdType::CUDD> const& other) const { bool DdForwardIterator<DdType::CUDD>::operator==(DdForwardIterator<DdType::CUDD> const& other) const {
if (this->isAtEnd && other.isAtEnd) { if (this->isAtEnd && other.isAtEnd) {
return true; return true;
} else { } else {
return this->cuddAdd == other.cuddAdd;
return this->ddManager.get() == other.ddManager.get() && this->generator == other.generator
&& this->cube == other.cube && this->value == other.value && this->isAtEnd == other.isAtEnd
&& this->metaVariables == other.metaVariables && this->cubeCounter == other.cubeCounter
&& this->relevantDontCareDdVariables == other.relevantDontCareDdVariables
&& this->currentValuation == other.currentValuation;
} }
} }
@ -26,8 +154,8 @@ namespace storm {
return !(*this == other); return !(*this == other);
} }
storm::expressions::SimpleValuation DdForwardIterator<DdType::CUDD>::operator*() const {
// FIXME: construct valuation and return it.
std::pair<storm::expressions::SimpleValuation, double> DdForwardIterator<DdType::CUDD>::operator*() const {
return std::make_pair(currentValuation, value);
} }
} }
} }

102
src/storage/dd/CuddDdForwardIterator.h

@ -3,6 +3,9 @@
#include <memory> #include <memory>
#include <cstdint> #include <cstdint>
#include <set>
#include <tuple>
#include <utility>
#include "src/storage/dd/DdForwardIterator.h" #include "src/storage/dd/DdForwardIterator.h"
#include "src/storage/expressions/SimpleValuation.h" #include "src/storage/expressions/SimpleValuation.h"
@ -12,33 +15,114 @@
namespace storm { namespace storm {
namespace dd { namespace dd {
// Forward-declare the DdManager class.
template<DdType Type> class DdManager;
template<DdType Type> class Dd;
template<> template<>
class DdForwardIterator<DdType::CUDD> { class DdForwardIterator<DdType::CUDD> {
public: public:
// Forward-declare the DdManager class.
template<DdType Type> class DdManager;
friend class Dd<DdType::CUDD>;
// Default-instantiate the constructor.
DdForwardIterator() = default;
// Forbid copy-construction and copy assignment, because ownership of the internal pointer is unclear then.
DdForwardIterator(DdForwardIterator<DdType::CUDD> const& other) = delete;
DdForwardIterator& operator=(DdForwardIterator<DdType::CUDD> const& other) = delete;
// Provide move-construction and move-assignment, though.
DdForwardIterator(DdForwardIterator<DdType::CUDD>&& other);
DdForwardIterator& operator=(DdForwardIterator<DdType::CUDD>&& other);
/*!
* Destroys the forward iterator and frees the generator as well as the cube if they are not the nullptr.
*/
~DdForwardIterator();
/*!
* Moves the iterator one position forward.
*/
DdForwardIterator<DdType::CUDD>& operator++(); DdForwardIterator<DdType::CUDD>& operator++();
storm::expressions::SimpleValuation operator*() const;
/*!
* Returns a pair consisting of a valuation of meta variables and the value to which this valuation is
* mapped. Note that the result is returned by value.
*
* @return A pair of a valuation and the function value.
*/
std::pair<storm::expressions::SimpleValuation, double> operator*() const;
/*!
* Compares the iterator with the given one. Two iterators are considered equal when all their underlying
* data members are the same or they both are at their end.
*
* @param other The iterator with which to compare.
* @return True if the two iterators are considered equal.
*/
bool operator==(DdForwardIterator<DdType::CUDD> const& other) const; bool operator==(DdForwardIterator<DdType::CUDD> const& other) const;
/*!
* Compares the iterator with the given one. Two iterators are considered unequal iff they are not
* considered equal.
*
* @param other The iterator with which to compare.
* @return True if the two iterators are considered unequal.
*/
bool operator!=(DdForwardIterator<DdType::CUDD> const& other) const; bool operator!=(DdForwardIterator<DdType::CUDD> const& other) const;
private: private:
DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, ADD cuddAdd, std::vector<ADD> const& relevantDdVariables);
/*!
* Constructs a forward iterator using the given generator with the given set of relevant meta variables.
*
* @param ddManager The manager responsible for the DD over which to iterate.
* @param generator The generator used to enumerate the cubes of the DD.
* @param cube The cube as represented by CUDD.
* @param value The value the cube is mapped to.
* @param isAtEnd A flag that indicates whether the iterator is at its end and may not be moved forward any
* more.
* @param metaVariables The meta variables that appear in the DD.
*/
DdForwardIterator(std::shared_ptr<DdManager<DdType::CUDD>> ddManager, DdGen* generator, int* cube, double value, bool isAtEnd, std::set<std::string> const* metaVariables = nullptr);
/*!
* Recreates the internal information when a new cube needs to be treated.
*/
void treatNewCube();
/*!
* Updates the internal information when the next solution of the current cube needs to be treated.
*/
void treatNextInCube();
// The manager responsible for the meta variables (and therefore the underlying DD).
std::shared_ptr<DdManager<DdType::CUDD>> ddManager; std::shared_ptr<DdManager<DdType::CUDD>> ddManager;
double value;
// The CUDD generator used to enumerate the cubes of the DD.
DdGen* generator;
// The currently considered cube of the DD.
int* cube; int* cube;
uint_fast64_t positionInCube;
ADD cuddAdd;
// The function value of the current cube.
double value;
// A flag that indicates whether the iterator is at its end and may not be moved further. This is also used
// for the check against the end iterator.
bool isAtEnd; bool isAtEnd;
DdGen* generator;
// The set of meta variables appearing in the DD.
std::set<std::string> const* metaVariables;
// A number that represents how many assignments of the current cube have already been returned previously.
// This is needed, because cubes may represent many assignments (if they have don't care variables).
uint_fast64_t cubeCounter;
// A vector of tuples of the form <variable, metaVariableName, bitIndex>.
std::vector<std::tuple<ADD, std::string, uint_fast64_t>> relevantDontCareDdVariables;
// The current valuation of meta variables.
storm::expressions::SimpleValuation currentValuation;
}; };
} }
} }

12
src/storage/dd/CuddDdManager.cpp

@ -111,6 +111,18 @@ namespace storm {
metaVariableMap.emplace(name, DdMetaVariable<DdType::CUDD>(name, low, high, variables, this->shared_from_this())); metaVariableMap.emplace(name, DdMetaVariable<DdType::CUDD>(name, low, high, variables, this->shared_from_this()));
} }
void DdManager<DdType::CUDD>::addMetaVariable(std::string const& name) {
// Check whether a meta variable already exists.
if (this->hasMetaVariable(name)) {
throw storm::exceptions::InvalidArgumentException() << "A meta variable '" << name << "' already exists.";
}
std::vector<Dd<DdType::CUDD>> variables;
variables.emplace_back(Dd<DdType::CUDD>(this->shared_from_this(), cuddManager.addVar(), {name}));
metaVariableMap.emplace(name, DdMetaVariable<DdType::CUDD>(name, variables, this->shared_from_this()));
}
void DdManager<DdType::CUDD>::addMetaVariablesInterleaved(std::vector<std::string> const& names, int_fast64_t low, int_fast64_t high) { void DdManager<DdType::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. // Make sure that at least one meta variable is added.
if (names.size() == 0) { if (names.size() == 0) {

14
src/storage/dd/CuddDdManager.h

@ -5,7 +5,6 @@
#include "src/storage/dd/DdManager.h" #include "src/storage/dd/DdManager.h"
#include "src/storage/dd/DdMetaVariable.h" #include "src/storage/dd/DdMetaVariable.h"
#include "src/storage/dd/CuddDd.h"
#include "src/utility/OsDetection.h" #include "src/utility/OsDetection.h"
// Include the C++-interface of CUDD. // Include the C++-interface of CUDD.
@ -16,7 +15,6 @@ namespace storm {
template<> template<>
class DdManager<DdType::CUDD> : public std::enable_shared_from_this<DdManager<DdType::CUDD>> { class DdManager<DdType::CUDD> : public std::enable_shared_from_this<DdManager<DdType::CUDD>> {
public: public:
// To break the cylic dependencies, we need to forward-declare the other DD-related classes.
friend class Dd<DdType::CUDD>; friend class Dd<DdType::CUDD>;
/*! /*!
@ -83,7 +81,7 @@ namespace storm {
Dd<DdType::CUDD> getIdentity(std::string const& metaVariableName); Dd<DdType::CUDD> getIdentity(std::string const& metaVariableName);
/*! /*!
* Adds a meta variable with the given name and range.
* Adds an integer meta variable with the given name and range.
* *
* @param name The name of the meta variable. * @param name The name of the meta variable.
* @param low The lowest value of the range of the variable. * @param low The lowest value of the range of the variable.
@ -92,7 +90,15 @@ namespace storm {
void addMetaVariable(std::string const& name, int_fast64_t low, int_fast64_t high); 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.
* Adds a boolean meta variable with the given name.
*
* @param name The name of the meta variable.
*/
void addMetaVariable(std::string const& name);
/*!
* Adds integer 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 names The names of the variables.
* @param low The lowest value of the ranges of the variables. * @param low The lowest value of the ranges of the variables.

15
src/storage/dd/DdMetaVariable.cpp

@ -4,7 +4,15 @@
namespace storm { namespace storm {
namespace dd { namespace dd {
template<DdType Type> 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) {
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), type(MetaVariableType::Int), 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>
DdMetaVariable<Type>::DdMetaVariable(std::string const& name, std::vector<Dd<Type>> const& ddVariables, std::shared_ptr<DdManager<Type>> manager) : name(name), type(MetaVariableType::Bool), ddVariables(ddVariables), cube(manager->getOne()), manager(manager) {
// Create the cube of all variables of this meta variable. // Create the cube of all variables of this meta variable.
for (auto const& ddVariable : this->ddVariables) { for (auto const& ddVariable : this->ddVariables) {
this->cube *= ddVariable; this->cube *= ddVariable;
@ -16,6 +24,11 @@ namespace storm {
return this->name; return this->name;
} }
template<DdType Type>
typename DdMetaVariable<Type>::MetaVariableType DdMetaVariable<Type>::getType() const {
return this->type;
}
template<DdType Type> template<DdType Type>
int_fast64_t DdMetaVariable<Type>::getLow() const { int_fast64_t DdMetaVariable<Type>::getLow() const {
return this->low; return this->low;

25
src/storage/dd/DdMetaVariable.h

@ -8,6 +8,7 @@
#include "utility/OsDetection.h" #include "utility/OsDetection.h"
#include "src/storage/dd/CuddDd.h" #include "src/storage/dd/CuddDd.h"
#include "src/storage/expressions/Expression.h"
namespace storm { namespace storm {
namespace dd { namespace dd {
@ -20,9 +21,13 @@ namespace storm {
// Declare the DdManager class as friend so it can access the internals of a meta variable. // Declare the DdManager class as friend so it can access the internals of a meta variable.
friend class DdManager<Type>; friend class DdManager<Type>;
friend class Dd<Type>; friend class Dd<Type>;
friend class DdForwardIterator<Type>;
// An enumeration for all legal types of meta variables.
enum class MetaVariableType { Bool, Int };
/*! /*!
* Creates a meta variable with the given name, range bounds.
* Creates an integer meta variable with the given name and range bounds.
* *
* @param name The name of the meta variable. * @param name The name of the meta variable.
* @param low The lowest value of the range of the variable. * @param low The lowest value of the range of the variable.
@ -32,6 +37,14 @@ namespace storm {
*/ */
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); 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);
/*!
* Creates a boolean meta variable with the given name.
* @param name The name of the meta 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, std::vector<Dd<Type>> const& ddVariables, std::shared_ptr<DdManager<Type>> manager);
// Explictly generate all default versions of copy/move constructors/assignments. // Explictly generate all default versions of copy/move constructors/assignments.
DdMetaVariable(DdMetaVariable const& other) = default; DdMetaVariable(DdMetaVariable const& other) = default;
DdMetaVariable& operator=(DdMetaVariable const& other) = default; DdMetaVariable& operator=(DdMetaVariable const& other) = default;
@ -47,6 +60,13 @@ namespace storm {
*/ */
std::string const& getName() const; std::string const& getName() const;
/*!
* Retrieves the type of the meta variable.
*
* @return The type of the meta variable.
*/
MetaVariableType getType() const;
/*! /*!
* Retrieves the lowest value of the range of the variable. * Retrieves the lowest value of the range of the variable.
* *
@ -93,6 +113,9 @@ namespace storm {
// The name of the meta variable. // The name of the meta variable.
std::string name; std::string name;
// The type of the variable.
MetaVariableType type;
// The lowest value of the range of the variable. // The lowest value of the range of the variable.
int_fast64_t low; int_fast64_t low;

11
src/storage/expressions/SimpleValuation.cpp

@ -1,6 +1,7 @@
#include "src/storage/expressions/SimpleValuation.h"
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include "src/storage/expressions/SimpleValuation.h"
#include "src/exceptions/ExceptionMacros.h"
#include "src/exceptions/InvalidArgumentException.h"
namespace storm { namespace storm {
namespace expressions { namespace expressions {
@ -13,16 +14,22 @@ namespace storm {
} }
void SimpleValuation::addBooleanIdentifier(std::string const& name, bool initialValue) { void SimpleValuation::addBooleanIdentifier(std::string const& name, bool initialValue) {
LOG_THROW(this->booleanIdentifierToIndexMap->find(name) == this->booleanIdentifierToIndexMap->end(), storm::exceptions::InvalidArgumentException, "Boolean identifier '" << name << "' already registered.");
this->booleanIdentifierToIndexMap->emplace(name, this->booleanValues.size()); this->booleanIdentifierToIndexMap->emplace(name, this->booleanValues.size());
this->booleanValues.push_back(false); this->booleanValues.push_back(false);
} }
void SimpleValuation::addIntegerIdentifier(std::string const& name, int_fast64_t initialValue) { void SimpleValuation::addIntegerIdentifier(std::string const& name, int_fast64_t initialValue) {
LOG_THROW(this->booleanIdentifierToIndexMap->find(name) == this->booleanIdentifierToIndexMap->end(), storm::exceptions::InvalidArgumentException, "Integer identifier '" << name << "' already registered.");
this->integerIdentifierToIndexMap->emplace(name, this->integerValues.size()); this->integerIdentifierToIndexMap->emplace(name, this->integerValues.size());
this->integerValues.push_back(initialValue); this->integerValues.push_back(initialValue);
} }
void SimpleValuation::addDoubleIdentifier(std::string const& name, double initialValue) { void SimpleValuation::addDoubleIdentifier(std::string const& name, double initialValue) {
LOG_THROW(this->booleanIdentifierToIndexMap->find(name) == this->booleanIdentifierToIndexMap->end(), storm::exceptions::InvalidArgumentException, "Double identifier '" << name << "' already registered.");
this->doubleIdentifierToIndexMap->emplace(name, this->doubleValues.size()); this->doubleIdentifierToIndexMap->emplace(name, this->doubleValues.size());
this->doubleValues.push_back(initialValue); this->doubleValues.push_back(initialValue);
} }

21
test/functional/storage/CuddDdTest.cpp

@ -273,3 +273,24 @@ TEST(CuddDd, GetSetValueTest) {
metaVariableToValueMap.emplace("x", 4); metaVariableToValueMap.emplace("x", 4);
EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap)); EXPECT_EQ(2, dd1.getValue(metaVariableToValueMap));
} }
TEST(CuddDd, ForwardIteratorTest) {
std::shared_ptr<storm::dd::DdManager<storm::dd::DdType::CUDD>> manager(new storm::dd::DdManager<storm::dd::DdType::CUDD>());
manager->addMetaVariable("x", 1, 9);
manager->addMetaVariable("y", 0, 3);
storm::dd::Dd<storm::dd::DdType::CUDD> dd;
ASSERT_NO_THROW(dd = manager->getRange("x"));
storm::dd::DdForwardIterator<storm::dd::DdType::CUDD> it, ite;
ASSERT_NO_THROW(it = dd.begin());
ASSERT_NO_THROW(ite = dd.end());
std::pair<storm::expressions::SimpleValuation, double> valuationValuePair;
uint_fast64_t numberOfValuations = 0;
while (it != ite) {
ASSERT_NO_THROW(valuationValuePair = *it);
ASSERT_NO_THROW(++it);
++numberOfValuations;
}
EXPECT_EQ(9, numberOfValuations);
}
Loading…
Cancel
Save