diff --git a/src/storage/dft/DFT.cpp b/src/storage/dft/DFT.cpp index bf68a095c..a4a15947c 100644 --- a/src/storage/dft/DFT.cpp +++ b/src/storage/dft/DFT.cpp @@ -2,6 +2,7 @@ #include #include "DFT.h" +#include "DFTBuilder.h" #include "src/exceptions/NotSupportedException.h" #include "DFTIsomorphism.h" @@ -228,7 +229,87 @@ namespace storm { } return stateIndex; } - + + template + DFT DFT::optimize() const { + std::vector> rewriteIds = findModulesRewrite(); + if (rewriteIds.empty()) { + // No rewrite needed + return *this; + } + + DFTBuilder builder; + + // Accumulate elements which must be rewritten + std::set rewriteSet; + for (std::vector rewrites : rewriteIds) { + rewriteSet.insert(rewrites.front()); + } + // Copy all other elements which do not change + for (auto elem : mElements) { + if (rewriteSet.count(elem->id()) == 0) { + builder.copyElement(elem); + } + } + + // Add rewritten elements + for (std::vector rewrites : rewriteIds) { + assert(rewrites.size() > 1); + assert(mElements[rewrites[1]]->hasParents()); + assert(mElements[rewrites[1]]->parents().front()->isGate()); + DFTGatePointer originalParent = std::static_pointer_cast>(mElements[rewrites[1]]->parents().front()); + std::string newParentName = builder.getUniqueName(originalParent->name()); + + // Accumulate children names + std::vector childrenNames; + for (size_t i = 1; i < rewrites.size(); ++i) { + assert(mElements[rewrites[i]]->parents().front()->id() == originalParent->id()); // Children have the same father + childrenNames.push_back(mElements[rewrites[i]]->name()); + } + + // Add element inbetween parent and children + switch (originalParent->type()) { + case DFTElementType::AND: + builder.addAndElement(newParentName, childrenNames); + break; + case DFTElementType::OR: + builder.addOrElement(newParentName, childrenNames); + break; + case DFTElementType::BE: + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + case DFTElementType::VOT: + case DFTElementType::PAND: + case DFTElementType::SPARE: + case DFTElementType::POR: + case DFTElementType::PDEP: + case DFTElementType::SEQ: + case DFTElementType::MUTEX: + // Other elements are not supported + assert(false); + break; + default: + assert(false); + } + + // Add parent with the new child newParent and all its remaining children + childrenNames.clear(); + childrenNames.push_back(newParentName); + for (auto const& child : originalParent->children()) { + if (std::find(rewrites.begin()+1, rewrites.end(), child->id()) == rewrites.end()) { + // Child was not rewritten and must be kept + childrenNames.push_back(child->name()); + } + } + builder.copyGate(originalParent, childrenNames); + } + + builder.setTopLevel(mElements[mTopLevelIndex]->name()); + // TODO use reference? + DFT newDft = builder.build(); + return newDft.optimize(); + } + template std::string DFT::getElementsString() const { std::stringstream stream; @@ -449,6 +530,13 @@ namespace storm { return res; } + template + std::vector> DFT::findModulesRewrite() const { + std::vector> modulesRewrite; + // TODO write + return modulesRewrite; + } + // Explicitly instantiate the class. template class DFT; diff --git a/src/storage/dft/DFT.h b/src/storage/dft/DFT.h index 32e807197..557914d7e 100644 --- a/src/storage/dft/DFT.h +++ b/src/storage/dft/DFT.h @@ -34,6 +34,8 @@ namespace storm { // Forward declarations template class DFTColouring; + + template class DFTBuilder; @@ -72,6 +74,10 @@ namespace storm { size_t generateStateInfo(DFTStateGenerationInfo& generationInfo, size_t id, storm::storage::BitVector& visited, size_t stateIndex) const; size_t performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue& visitQueue, storm::storage::BitVector& visited, size_t stateIndex) const; + + DFT optimize() const; + + void copyElements(std::vector elements, DFTBuilder builder) const; size_t stateVectorSize() const { return mStateVectorSize; @@ -236,6 +242,9 @@ namespace storm { DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; std::vector immediateFailureCauses(size_t index) const; + + std::vector> findModulesRewrite() const; + private: std::pair, std::vector> getSortedParentAndOutDepIds(size_t index) const; diff --git a/src/storage/dft/DFTBuilder.cpp b/src/storage/dft/DFTBuilder.cpp index 08d85d879..f3d83e4c0 100644 --- a/src/storage/dft/DFTBuilder.cpp +++ b/src/storage/dft/DFTBuilder.cpp @@ -70,7 +70,8 @@ namespace storm { for(DFTElementPointer e : elems) { e->setId(id++); } - return DFT(elems, mElements[topLevelIdentifier]); + assert(!mTopLevelIdentifier.empty()); + return DFT(elems, mElements[mTopLevelIdentifier]); } template @@ -180,7 +181,6 @@ namespace storm { } } - // TODO Matthias: use typedefs template std::vector>> DFTBuilder::topoSort() { std::map> visited; @@ -195,6 +195,87 @@ namespace storm { //std::reverse(L.begin(), L.end()); return L; } + + template + std::string DFTBuilder::getUniqueName(std::string name) { + return name + "_" + std::to_string(++mUniqueOffset); + } + + template + void DFTBuilder::copyElement(DFTElementPointer element) { + std::vector children; + switch (element->type()) { + case DFTElementType::AND: + case DFTElementType::OR: + case DFTElementType::PAND: + case DFTElementType::POR: + case DFTElementType::SPARE: + case DFTElementType::VOT: + { + for (DFTElementPointer const& elem : std::static_pointer_cast>(element)->children()) { + children.push_back(elem->name()); + } + copyGate(std::static_pointer_cast>(element), children); + break; + } + case DFTElementType::BE: + { + std::shared_ptr> be = std::static_pointer_cast>(element); + ValueType dormancyFactor = storm::utility::zero(); + if (!storm::utility::isZero(be->passiveFailureRate())) { + dormancyFactor = be->activeFailureRate() / be->passiveFailureRate(); + } + addBasicElement(be->name(), be->activeFailureRate(), dormancyFactor); + break; + } + case DFTElementType::CONSTF: + case DFTElementType::CONSTS: + // TODO + assert(false); + break; + case DFTElementType::PDEP: + { + DFTDependencyPointer dependency = std::static_pointer_cast>(element); + children.push_back(dependency->triggerEvent()->name()); + children.push_back(dependency->dependentEvent()->name()); + addDepElement(element->name(), children, dependency->probability()); + break; + } + case DFTElementType::SEQ: + case DFTElementType::MUTEX: + { + for (DFTElementPointer const& elem : std::static_pointer_cast>(element)->children()) { + children.push_back(elem->name()); + } + addRestriction(element->name(), children, element->type()); + break; + } + default: + assert(false); + break; + } + } + + template + void DFTBuilder::copyGate(DFTGatePointer gate, std::vector const& children) { + switch (gate->type()) { + case DFTElementType::AND: + case DFTElementType::OR: + case DFTElementType::PAND: + case DFTElementType::POR: + case DFTElementType::SPARE: + addStandardGate(gate->name(), children, gate->type()); + break; + case DFTElementType::VOT: + addVotElement(gate->name(), std::static_pointer_cast>(gate)->threshold(), children); + break; + default: + assert(false); + break; + } + } + + // Explicitly instantiate the class. template class DFTBuilder; diff --git a/src/storage/dft/DFTBuilder.h b/src/storage/dft/DFTBuilder.h index 8ef0d6cf1..6c6fcc143 100644 --- a/src/storage/dft/DFTBuilder.h +++ b/src/storage/dft/DFTBuilder.h @@ -26,7 +26,8 @@ namespace storm { private: std::size_t mNextId = 0; - std::string topLevelIdentifier; + std::size_t mUniqueOffset = 0; + std::string mTopLevelIdentifier; std::unordered_map mElements; std::unordered_map> mChildNames; std::unordered_map> mRestrictionChildNames; @@ -140,18 +141,36 @@ namespace storm { } bool setTopLevel(std::string const& tle) { - topLevelIdentifier = tle; + mTopLevelIdentifier = tle; return mElements.count(tle) > 0; } + std::string getUniqueName(std::string name); + DFT build(); + + /** + * Copy element and insert it again in the builder. + * + * @param element Element to copy. + */ + void copyElement(DFTElementPointer element); + + /** + * Copy gate with given children and insert it again in the builder. The current children of the element + * are discarded. + * + * @param gate Gate to copy. + * @param children New children of copied element. + */ + void copyGate(DFTGatePointer gate, std::vector const& children); - private: unsigned computeRank(DFTElementPointer const& elem); bool addStandardGate(std::string const& name, std::vector const& children, DFTElementType tp); + bool addRestriction(std::string const& name, std::vector const& children, DFTElementType tp); enum class topoSortColour {WHITE, BLACK, GREY}; diff --git a/src/storage/dft/elements/DFTVot.h b/src/storage/dft/elements/DFTVot.h index 0233d979d..776055848 100644 --- a/src/storage/dft/elements/DFTVot.h +++ b/src/storage/dft/elements/DFTVot.h @@ -51,6 +51,10 @@ namespace storm { } } } + + unsigned threshold() const { + return mThreshold; + } virtual DFTElementType type() const override { return DFTElementType::VOT; diff --git a/src/storm-dyftee.cpp b/src/storm-dyftee.cpp index 13b43f5ff..6240bf374 100644 --- a/src/storm-dyftee.cpp +++ b/src/storm-dyftee.cpp @@ -29,6 +29,9 @@ void analyzeDFT(std::string filename, std::string property, bool symred = false) std::vector> formulas(parsedFormulas.begin(), parsedFormulas.end()); assert(formulas.size() == 1); std::cout << "Parsed formula." << std::endl; + + dft = dft.optimize(); + std::map>> emptySymmetry; storm::storage::DFTIndependentSymmetries symmetries(emptySymmetry); if(symred) {