#include "storm/storage/dd/bisimulation/Partition.h" #include "storm/storage/dd/DdManager.h" namespace storm { namespace dd { namespace bisimulation { template Partition::Partition(storm::dd::Add const& partitionAdd, storm::expressions::Variable const& blockVariable, uint64_t nextFreeBlockIndex) : partitionAdd(partitionAdd), blockVariable(blockVariable), nextFreeBlockIndex(nextFreeBlockIndex) { // Intentionally left empty. } template bool Partition::operator==(Partition const& other) { return this->partitionAdd == other.partitionAdd && this->blockVariable == other.blockVariable && this->nextFreeBlockIndex == other.nextFreeBlockIndex; } template Partition Partition::replacePartitionAdd(storm::dd::Add const& newPartitionAdd, uint64_t nextFreeBlockIndex) const { return Partition(newPartitionAdd, blockVariable, nextFreeBlockIndex); } template Partition Partition::create(storm::models::symbolic::Model const& model) { return create(model, model.getLabels()); } template Partition Partition::create(storm::models::symbolic::Model const& model, std::vector const& labels) { std::vector expressions; for (auto const& label : labels) { expressions.push_back(model.getExpression(label)); } return create(model, expressions); } template Partition Partition::create(storm::models::symbolic::Model const& model, std::vector const& expressions) { storm::dd::DdManager& manager = model.getManager(); std::vector> stateSets; for (auto const& expression : expressions) { stateSets.emplace_back(model.getStates(expression)); } storm::expressions::Variable blockVariable = createBlockVariable(manager, model.getReachableStates().getNonZeroCount()); std::pair, uint64_t> partitionAddAndBlockCount = createPartitionAdd(manager, model, stateSets, blockVariable); return Partition(partitionAddAndBlockCount.first, blockVariable, partitionAddAndBlockCount.second); } template uint64_t Partition::getNumberOfBlocks() const { return nextFreeBlockIndex; } template storm::dd::Add const& Partition::getPartitionAdd() const { return partitionAdd; } template storm::expressions::Variable const& Partition::getBlockVariable() const { return blockVariable; } template uint64_t Partition::getNextFreeBlockIndex() const { return nextFreeBlockIndex; } template void enumerateBlocksRec(std::vector> const& stateSets, storm::dd::Bdd const& currentStateSet, uint64_t offset, storm::expressions::Variable const& blockVariable, std::function const&)> const& callback) { if (currentStateSet.isZero()) { return; } if (offset == stateSets.size()) { callback(currentStateSet); } else { enumerateBlocksRec(stateSets, currentStateSet && stateSets[offset], offset + 1, blockVariable, callback); enumerateBlocksRec(stateSets, currentStateSet && !stateSets[offset], offset + 1, blockVariable, callback); } } template std::pair, uint64_t> Partition::createPartitionAdd(storm::dd::DdManager const& manager, storm::models::symbolic::Model const& model, std::vector> const& stateSets, storm::expressions::Variable const& blockVariable) { uint64_t blockCount = 0; storm::dd::Add partitionAdd = manager.template getAddZero(); // Enumerate all realizable blocks. enumerateBlocksRec(stateSets, model.getReachableStates(), 0, blockVariable, [&manager, &partitionAdd, &blockVariable, &blockCount](storm::dd::Bdd const& stateSet) { stateSet.template toAdd().exportToDot("states_" + std::to_string(blockCount) + ".dot"); partitionAdd += (stateSet && manager.getEncoding(blockVariable, blockCount)).template toAdd(); blockCount++; } ); return std::make_pair(partitionAdd, blockCount); } template storm::expressions::Variable Partition::createBlockVariable(storm::dd::DdManager& manager, uint64_t numberOfStates) { storm::expressions::Variable blockVariable; if (manager.hasMetaVariable("blocks")) { int64_t counter = 0; while (manager.hasMetaVariable("block" + std::to_string(counter))) { ++counter; } blockVariable = manager.addMetaVariable("blocks" + std::to_string(counter), 0, numberOfStates, 1).front(); } else { blockVariable = manager.addMetaVariable("blocks", 0, numberOfStates, 1).front(); } return blockVariable; } template class Partition; template class Partition; template class Partition; template class Partition; } } }