#include #include "storm/storage/dd/Bdd.h" #include "storm/storage/dd/Add.h" #include "storm/storage/dd/Odd.h" #include "storm/logic/ComparisonType.h" #include "storm/storage/dd/DdMetaVariable.h" #include "storm/storage/dd/DdManager.h" #include "storm/storage/dd/Odd.h" #include "storm/storage/BitVector.h" #include "storm/utility/macros.h" #include "storm/exceptions/InvalidArgumentException.h" #include "storm/exceptions/InvalidOperationException.h" #include "storm-config.h" #include "storm/adapters/RationalFunctionAdapter.h" namespace storm { namespace dd { template Bdd::Bdd(DdManager const& ddManager, InternalBdd const& internalBdd, std::set const& containedMetaVariables) : Dd(ddManager, containedMetaVariables), internalBdd(internalBdd) { // Intentionally left empty. } template struct FromVectorHelper { static Bdd fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, ValueType value) { switch (comparisonType) { case storm::logic::ComparisonType::Less: return Bdd(ddManager, InternalBdd::fromVector(&ddManager.getInternalDdManager(), odd, ddManager.getSortedVariableIndices(metaVariables), [&value, &explicitValues] (uint64_t offset) { return explicitValues[offset] < value; }), metaVariables); case storm::logic::ComparisonType::LessEqual: return Bdd(ddManager, InternalBdd::fromVector(&ddManager.getInternalDdManager(), odd, ddManager.getSortedVariableIndices(metaVariables), [&value, &explicitValues] (uint64_t offset) { return explicitValues[offset] <= value; }), metaVariables); case storm::logic::ComparisonType::Greater: return Bdd(ddManager, InternalBdd::fromVector(&ddManager.getInternalDdManager(), odd, ddManager.getSortedVariableIndices(metaVariables), [&value, &explicitValues] (uint64_t offset) { return explicitValues[offset] > value; }), metaVariables); case storm::logic::ComparisonType::GreaterEqual: return Bdd(ddManager, InternalBdd::fromVector(&ddManager.getInternalDdManager(), odd, ddManager.getSortedVariableIndices(metaVariables), [&value, &explicitValues] (uint64_t offset) { return explicitValues[offset] >= value; }), metaVariables); } return Bdd(); } }; template struct FromVectorHelper { static Bdd fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, storm::RationalFunction value) { STORM_LOG_THROW(false, storm::exceptions::InvalidOperationException, "Cannot compare rational functions to bound."); return Bdd(); } }; template template Bdd Bdd::fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, ValueType value) { return FromVectorHelper::fromVector(ddManager, explicitValues, odd, metaVariables, comparisonType, value); } template Bdd Bdd::fromVector(DdManager const& ddManager, storm::storage::BitVector const& truthValues, storm::dd::Odd const& odd, std::set const& metaVariables) { return Bdd(ddManager, InternalBdd::fromVector(&ddManager.getInternalDdManager(), odd, ddManager.getSortedVariableIndices(metaVariables), [&truthValues] (uint64_t offset) { return truthValues[offset]; } ), metaVariables); } template bool Bdd::operator==(Bdd const& other) const { return internalBdd == other.internalBdd; } template bool Bdd::operator!=(Bdd const& other) const { return internalBdd != other.internalBdd; } template Bdd Bdd::ite(Bdd const& thenBdd, Bdd const& elseBdd) const { std::set metaVariables = Dd::joinMetaVariables(thenBdd, elseBdd); metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end()); return Bdd(this->getDdManager(), internalBdd.ite(thenBdd.internalBdd, elseBdd.internalBdd), metaVariables); } template template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const { std::set metaVariables = Dd::joinMetaVariables(thenAdd, elseAdd); metaVariables.insert(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end()); return Add(this->getDdManager(), internalBdd.ite(thenAdd.internalAdd, elseAdd.internalAdd), metaVariables); } template Bdd Bdd::operator||(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd || other.internalBdd, Dd::joinMetaVariables(*this, other)); } template Bdd& Bdd::operator|=(Bdd const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalBdd |= other.internalBdd; return *this; } template Bdd Bdd::operator&&(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd && other.internalBdd, Dd::joinMetaVariables(*this, other)); } template Bdd& Bdd::operator&=(Bdd const& other) { this->addMetaVariables(other.getContainedMetaVariables()); internalBdd &= other.internalBdd; return *this; } template Bdd Bdd::iff(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd.iff(other.internalBdd), Dd::joinMetaVariables(*this, other)); } template Bdd Bdd::exclusiveOr(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd.exclusiveOr(other.internalBdd), Dd::joinMetaVariables(*this, other)); } template Bdd Bdd::implies(Bdd const& other) const { return Bdd(this->getDdManager(), internalBdd.implies(other.internalBdd), Dd::joinMetaVariables(*this, other)); } template Bdd Bdd::operator!() const { return Bdd(this->getDdManager(), !internalBdd, this->getContainedMetaVariables()); } template Bdd& Bdd::complement() { internalBdd.complement(); return *this; } template Bdd Bdd::existsAbstract(std::set const& metaVariables) const { Bdd cube = getCube(this->getDdManager(), metaVariables); return Bdd(this->getDdManager(), internalBdd.existsAbstract(cube.getInternalBdd()), Dd::subtractMetaVariables(*this, cube)); } template Bdd Bdd::existsAbstractRepresentative(std::set const& metaVariables) const { Bdd cube = getCube(this->getDdManager(), metaVariables); return Bdd(this->getDdManager(), internalBdd.existsAbstractRepresentative(cube.getInternalBdd()), this->getContainedMetaVariables()); } template Bdd Bdd::universalAbstract(std::set const& metaVariables) const { Bdd cube = getCube(this->getDdManager(), metaVariables); return Bdd(this->getDdManager(), internalBdd.universalAbstract(cube.getInternalBdd()), Dd::subtractMetaVariables(*this, cube)); } template Bdd Bdd::andExists(Bdd const& other, std::set const& existentialVariables) const { Bdd cube = getCube(this->getDdManager(), existentialVariables); std::set unionOfMetaVariables; std::set_union(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), other.getContainedMetaVariables().begin(), other.getContainedMetaVariables().end(), std::inserter(unionOfMetaVariables, unionOfMetaVariables.begin())); std::set containedMetaVariables; std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), existentialVariables.begin(), existentialVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin())); return Bdd(this->getDdManager(), internalBdd.andExists(other.getInternalBdd(), cube.getInternalBdd()), containedMetaVariables); } template Bdd Bdd::constrain(Bdd const& constraint) const { return Bdd(this->getDdManager(), internalBdd.constrain(constraint.getInternalBdd()), Dd::joinMetaVariables(*this, constraint)); } template Bdd Bdd::restrict(Bdd const& constraint) const { return Bdd(this->getDdManager(), internalBdd.restrict(constraint.getInternalBdd()), Dd::joinMetaVariables(*this, constraint)); } template Bdd Bdd::relationalProduct(Bdd const& relation, std::set const& rowMetaVariables, std::set const& columnMetaVariables) const { std::set newMetaVariables; std::set_difference(relation.getContainedMetaVariables().begin(), relation.getContainedMetaVariables().end(), columnMetaVariables.begin(), columnMetaVariables.end(), std::inserter(newMetaVariables, newMetaVariables.begin())); std::vector> rowVariables; for (auto const& metaVariable : rowMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { rowVariables.push_back(ddVariable.getInternalBdd()); } } std::vector> columnVariables; for (auto const& metaVariable : columnMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { columnVariables.push_back(ddVariable.getInternalBdd()); } } return Bdd(this->getDdManager(), internalBdd.relationalProduct(relation.getInternalBdd(), rowVariables, columnVariables), newMetaVariables); } template Bdd Bdd::inverseRelationalProduct(Bdd const& relation, std::set const& rowMetaVariables, std::set const& columnMetaVariables) const { std::set newMetaVariables; std::set_difference(relation.getContainedMetaVariables().begin(), relation.getContainedMetaVariables().end(), columnMetaVariables.begin(), columnMetaVariables.end(), std::inserter(newMetaVariables, newMetaVariables.begin())); std::vector> rowVariables; for (auto const& metaVariable : rowMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { rowVariables.push_back(ddVariable.getInternalBdd()); } } std::vector> columnVariables; for (auto const& metaVariable : columnMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { columnVariables.push_back(ddVariable.getInternalBdd()); } } return Bdd(this->getDdManager(), internalBdd.inverseRelationalProduct(relation.getInternalBdd(), rowVariables, columnVariables), newMetaVariables); } template Bdd Bdd::inverseRelationalProductWithExtendedRelation(Bdd const& relation, std::set const& rowMetaVariables, std::set const& columnMetaVariables) const { std::set newMetaVariables; std::set_difference(relation.getContainedMetaVariables().begin(), relation.getContainedMetaVariables().end(), columnMetaVariables.begin(), columnMetaVariables.end(), std::inserter(newMetaVariables, newMetaVariables.begin())); std::vector> rowVariables; for (auto const& metaVariable : rowMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { rowVariables.push_back(ddVariable.getInternalBdd()); } } std::vector> columnVariables; for (auto const& metaVariable : columnMetaVariables) { DdMetaVariable const& variable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : variable.getDdVariables()) { columnVariables.push_back(ddVariable.getInternalBdd()); } } return Bdd(this->getDdManager(), internalBdd.inverseRelationalProductWithExtendedRelation(relation.getInternalBdd(), rowVariables, columnVariables), newMetaVariables); } template Bdd Bdd::swapVariables(std::vector> const& metaVariablePairs) const { std::set newContainedMetaVariables; std::set deletedMetaVariables; std::vector> from; std::vector> to; for (auto const& metaVariablePair : metaVariablePairs) { DdMetaVariable const& variable1 = this->getDdManager().getMetaVariable(metaVariablePair.first); DdMetaVariable const& variable2 = this->getDdManager().getMetaVariable(metaVariablePair.second); // Keep track of the contained meta variables in the DD. if (this->containsMetaVariable(metaVariablePair.first)) { if (this->containsMetaVariable(metaVariablePair.second)) { // Nothing to do here. } else { newContainedMetaVariables.insert(metaVariablePair.second); deletedMetaVariables.insert(metaVariablePair.first); } } else { if (!this->containsMetaVariable(metaVariablePair.second)) { // Nothing to do here. } else { newContainedMetaVariables.insert(metaVariablePair.first); deletedMetaVariables.insert(metaVariablePair.second); } } for (auto const& ddVariable : variable1.getDdVariables()) { from.emplace_back(ddVariable.getInternalBdd()); } for (auto const& ddVariable : variable2.getDdVariables()) { to.emplace_back(ddVariable.getInternalBdd()); } } std::set tmp; std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), deletedMetaVariables.begin(), deletedMetaVariables.end(), std::inserter(tmp, tmp.begin())); std::set containedMetaVariables; std::set_union(tmp.begin(), tmp.end(), newContainedMetaVariables.begin(), newContainedMetaVariables.end(), std::inserter(containedMetaVariables, containedMetaVariables.begin())); return Bdd(this->getDdManager(), internalBdd.swapVariables(from, to), containedMetaVariables); } template Bdd Bdd::renameVariables(std::set const& from, std::set const& to) const { std::vector> fromBdds; std::vector> toBdds; for (auto const& metaVariable : from) { STORM_LOG_THROW(this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException, "Cannot rename variable '" << metaVariable.getName() << "' that is not present."); DdMetaVariable const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : ddMetaVariable.getDdVariables()) { fromBdds.push_back(ddVariable.getInternalBdd()); } } for (auto const& metaVariable : to) { STORM_LOG_THROW(!this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException, "Cannot rename to variable '" << metaVariable.getName() << "' that is already present."); DdMetaVariable const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable); for (auto const& ddVariable : ddMetaVariable.getDdVariables()) { toBdds.push_back(ddVariable.getInternalBdd()); } } std::set newContainedMetaVariables = to; std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), from.begin(), from.end(), std::inserter(newContainedMetaVariables, newContainedMetaVariables.begin())); STORM_LOG_THROW(fromBdds.size() == toBdds.size(), storm::exceptions::InvalidArgumentException, "Unable to rename mismatching meta variables."); return Bdd(this->getDdManager(), internalBdd.swapVariables(fromBdds, toBdds), newContainedMetaVariables); } template template Add Bdd::toAdd() const { return Add(this->getDdManager(), internalBdd.template toAdd(), this->getContainedMetaVariables()); } template storm::storage::BitVector Bdd::toVector(storm::dd::Odd const& rowOdd) const { return internalBdd.toVector(rowOdd, this->getSortedVariableIndices()); } template std::pair, std::unordered_map> Bdd::toExpression(storm::expressions::ExpressionManager& manager) const { return internalBdd.toExpression(manager); } template Bdd Bdd::getSupport() const { return Bdd(this->getDdManager(), internalBdd.getSupport(), this->getContainedMetaVariables()); } template uint_fast64_t Bdd::getNonZeroCount() const { std::size_t numberOfDdVariables = 0; for (auto const& metaVariable : this->getContainedMetaVariables()) { numberOfDdVariables += this->getDdManager().getMetaVariable(metaVariable).getNumberOfDdVariables(); } return internalBdd.getNonZeroCount(numberOfDdVariables); } template uint_fast64_t Bdd::getLeafCount() const { return internalBdd.getLeafCount(); } template uint_fast64_t Bdd::getNodeCount() const { return internalBdd.getNodeCount(); } template uint_fast64_t Bdd::getIndex() const { return internalBdd.getIndex(); } template uint_fast64_t Bdd::getLevel() const { return internalBdd.getLevel(); } template bool Bdd::isOne() const { return internalBdd.isOne(); } template bool Bdd::isZero() const { return internalBdd.isZero(); } template void Bdd::exportToDot(std::string const& filename) const { internalBdd.exportToDot(filename, this->getDdManager().getDdVariableNames()); } template Bdd Bdd::getCube(DdManager const& manager, std::set const& metaVariables) { Bdd cube = manager.getBddOne(); for (auto const& metaVariable : metaVariables) { cube &= manager.getMetaVariable(metaVariable).getCube(); } return cube; } template Odd Bdd::createOdd() const { return internalBdd.createOdd(this->getSortedVariableIndices()); } template InternalBdd const& Bdd::getInternalBdd() const { return internalBdd; } template template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const { std::vector result(this->getNonZeroCount()); internalBdd.filterExplicitVector(odd, this->getSortedVariableIndices(), values, result); return result; } template storm::storage::BitVector Bdd::filterExplicitVector(Odd const& odd, storm::storage::BitVector const& values) const { storm::storage::BitVector result(this->getNonZeroCount()); internalBdd.filterExplicitVector(odd, this->getSortedVariableIndices(), values, result); return result; } template class Bdd; template Bdd Bdd::fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, double value); template Add Bdd::toAdd() const; template Add Bdd::toAdd() const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; template class Bdd; template Bdd Bdd::fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, double value); #ifdef STORM_HAVE_CARL template Bdd Bdd::fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, storm::RationalNumber value); template Bdd Bdd::fromVector(DdManager const& ddManager, std::vector const& explicitValues, storm::dd::Odd const& odd, std::set const& metaVariables, storm::logic::ComparisonType comparisonType, storm::RationalFunction value); #endif template Add Bdd::toAdd() const; template Add Bdd::toAdd() const; #ifdef STORM_HAVE_CARL template Add Bdd::toAdd() const; template Add Bdd::toAdd() const; #endif template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; #ifdef STORM_HAVE_CARL template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; template std::vector Bdd::filterExplicitVector(Odd const& odd, std::vector const& values) const; #endif template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; #ifdef STORM_HAVE_CARL template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; template Add Bdd::ite(Add const& thenAdd, Add const& elseAdd) const; #endif } }