You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

197 lines
11 KiB

#include "src/storage/dd/sylvan/SylvanAddIterator.h"
#include "src/storage/dd/sylvan/InternalSylvanAdd.h"
#include "src/storage/dd/DdManager.h"
#include "src/storage/expressions/ExpressionManager.h"
#include "src/utility/macros.h"
#include "src/exceptions/NotImplementedException.h"
#include <cmath>
#include "src/adapters/CarlAdapter.h"
#include "storm-config.h"
namespace storm {
namespace dd {
template<typename ValueType>
AddIterator<DdType::Sylvan, ValueType>::AddIterator() {
// Intentionally left empty.
}
template<typename ValueType>
AddIterator<DdType::Sylvan, ValueType>::AddIterator(DdManager<DdType::Sylvan> const& ddManager, sylvan::Mtbdd mtbdd, sylvan::Bdd variables, uint_fast64_t numberOfDdVariables, bool isAtEnd, std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables) : ddManager(&ddManager), mtbdd(mtbdd), variables(variables), cube(numberOfDdVariables), leaf(), isAtEnd(isAtEnd), metaVariables(metaVariables), enumerateDontCareMetaVariables(enumerateDontCareMetaVariables), cubeCounter(0), relevantDontCareDdVariables(), currentValuation(ddManager.getExpressionManager().getSharedPointer()) {
// 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) {
this->createGlobalToLocalIndexMapping();
// And then get ready for treating the first cube.
leaf = mtbdd_enum_first(mtbdd.GetMTBDD(), variables.GetBDD(), cube.data(), &mtbdd_isnonzero);
if (leaf != mtbdd_false) {
this->treatNewCube();
} else {
this->isAtEnd = true;
}
}
}
template<typename ValueType>
void AddIterator<DdType::Sylvan, ValueType>::createGlobalToLocalIndexMapping() {
// Create the global to local index mapping.
std::vector<uint_fast64_t> globalIndices;
for (auto const& metaVariable : *this->metaVariables) {
auto const& ddMetaVariable = this->ddManager->getMetaVariable(metaVariable);
for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
globalIndices.push_back(ddVariable.getIndex());
}
}
std::sort(globalIndices.begin(), globalIndices.end());
for (auto it = globalIndices.begin(), ite = globalIndices.end(); it != ite; ++it) {
globalToLocalIndexMap[*it] = std::distance(globalIndices.begin(), it);
}
}
template<typename ValueType>
AddIterator<DdType::Sylvan, ValueType> AddIterator<DdType::Sylvan, ValueType>::createBeginIterator(DdManager<DdType::Sylvan> const& ddManager, sylvan::Mtbdd mtbdd, sylvan::Bdd variables, uint_fast64_t numberOfDdVariables, std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables) {
return AddIterator<DdType::Sylvan, ValueType>(ddManager, mtbdd, variables, numberOfDdVariables, false, metaVariables, enumerateDontCareMetaVariables);
}
template<typename ValueType>
AddIterator<DdType::Sylvan, ValueType> AddIterator<DdType::Sylvan, ValueType>::createEndIterator(DdManager<DdType::Sylvan> const& ddManager) {
return AddIterator<DdType::Sylvan, ValueType>(ddManager, sylvan::Mtbdd(), sylvan::Bdd(), 0, true, nullptr, false);
}
template<typename ValueType>
AddIterator<DdType::Sylvan, ValueType>& AddIterator<DdType::Sylvan, ValueType>::operator++() {
STORM_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) {
leaf = mtbdd_enum_next(mtbdd.GetMTBDD(), variables.GetBDD(), cube.data(), &mtbdd_isnonzero);
if (leaf != mtbdd_false) {
this->treatNewCube();
} else {
this->isAtEnd = true;
}
} else {
// Treat the next solution of the cube.
this->treatNextInCube();
}
return *this;
}
template<typename ValueType>
bool AddIterator<DdType::Sylvan, ValueType>::operator==(AddIterator<DdType::Sylvan, ValueType> const& other) const {
if (this->isAtEnd && other.isAtEnd) {
return true;
} else {
return this->ddManager == other.ddManager && this->mtbdd == other.mtbdd && this->variables == other.variables
&& this->cube == other.cube && this->leaf == other.leaf && this->isAtEnd == other.isAtEnd
&& this->metaVariables == other.metaVariables && this->cubeCounter == other.cubeCounter
&& this->relevantDontCareDdVariables == other.relevantDontCareDdVariables
&& this->currentValuation == other.currentValuation;
}
}
template<typename ValueType>
bool AddIterator<DdType::Sylvan, ValueType>::operator!=(AddIterator<DdType::Sylvan, ValueType> const& other) const {
return !(*this == other);
}
template<typename ValueType>
std::pair<storm::expressions::SimpleValuation, ValueType> AddIterator<DdType::Sylvan, ValueType>::operator*() const {
return std::make_pair(currentValuation, static_cast<ValueType>(InternalAdd<DdType::Sylvan, ValueType>::getValue(leaf)));
}
template<typename ValueType>
void AddIterator<DdType::Sylvan, ValueType>::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& metaVariable : *this->metaVariables) {
bool metaVariableAppearsInCube = false;
std::vector<std::tuple<storm::expressions::Variable, uint_fast64_t>> localRelenvantDontCareDdVariables;
auto const& ddMetaVariable = this->ddManager->getMetaVariable(metaVariable);
if (ddMetaVariable.getType() == MetaVariableType::Bool) {
if (this->cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables().front().getIndex())] == 0) {
metaVariableAppearsInCube = true;
currentValuation.setBooleanValue(metaVariable, false);
} else if (this->cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables().front().getIndex())] == 1) {
metaVariableAppearsInCube = true;
currentValuation.setBooleanValue(metaVariable, true);
} else {
localRelenvantDontCareDdVariables.push_back(std::make_tuple(metaVariable, 0));
}
} else {
int_fast64_t intValue = 0;
for (uint_fast64_t bitIndex = 0; bitIndex < ddMetaVariable.getNumberOfDdVariables(); ++bitIndex) {
if (cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables()[bitIndex].getIndex())] == 0) {
// Leave bit unset.
metaVariableAppearsInCube = true;
} else if (cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables()[bitIndex].getIndex())] == 1) {
intValue |= 1ull << (ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1);
metaVariableAppearsInCube = true;
} else {
// Temporarily leave bit unset so we can iterate trough the other option later.
// Add the bit to the relevant don't care bits.
localRelenvantDontCareDdVariables.push_back(std::make_tuple(metaVariable, ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1));
}
}
if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
currentValuation.setBitVectorValue(metaVariable, intValue + ddMetaVariable.getLow());
}
}
// If all meta variables are to be enumerated or the meta variable appeared in the cube, we register the
// missing bits to later enumerate all possible valuations.
if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
relevantDontCareDdVariables.insert(relevantDontCareDdVariables.end(), localRelenvantDontCareDdVariables.begin(), localRelenvantDontCareDdVariables.end());
}
}
// Finally, reset the cube counter.
this->cubeCounter = 0;
}
template<typename ValueType>
void AddIterator<DdType::Sylvan, ValueType>::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& ddMetaVariable = this->ddManager->getMetaVariable(std::get<0>(this->relevantDontCareDdVariables[index]));
if (ddMetaVariable.getType() == MetaVariableType::Bool) {
if ((this->cubeCounter & (1ull << index)) != 0) {
currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), true);
} else {
currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), false);
}
} else {
storm::expressions::Variable const& metaVariable = std::get<0>(this->relevantDontCareDdVariables[index]);
if ((this->cubeCounter & (1ull << index)) != 0) {
currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) | (1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) + ddMetaVariable.getLow());
} else {
currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) & ~(1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) + ddMetaVariable.getLow());
}
}
}
}
template class AddIterator<DdType::Sylvan, double>;
template class AddIterator<DdType::Sylvan, uint_fast64_t>;
#ifdef STORM_HAVE_CARL
template class AddIterator<DdType::Sylvan, storm::RationalFunction>;
#endif
}
}