#pragma once #include #include #include #include #include #include #include "storm/storage/BitVector.h" #include "storm/utility/math.h" #include "storm/utility/macros.h" #include "storm/exceptions/NotSupportedException.h" #include "storm-dft/storage/dft/DFTElements.h" #include "storm-dft/storage/dft/SymmetricUnits.h" #include "storm-dft/storage/dft/DFTStateGenerationInfo.h" #include "storm-dft/storage/dft/DFTLayoutInfo.h" namespace storm { namespace builder { // Forward declaration template class DFTBuilder; } namespace storage { template struct DFTElementSort { bool operator()(std::shared_ptr> const& a, std::shared_ptr> const& b) const { if (a->rank() == 0 && b->rank() == 0) { return a->isConstant(); } else { return a->rank() < b->rank(); } } }; // Forward declaration template class DFTColouring; /** * Represents a Dynamic Fault Tree */ template class DFT { using DFTElementPointer = std::shared_ptr>; using DFTElementCPointer = std::shared_ptr const>; using DFTElementVector = std::vector; using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; using DFTStatePointer = std::shared_ptr>; private: DFTElementVector mElements; size_t mNrOfBEs; size_t mNrOfSpares; size_t mNrRepresentatives; size_t mTopLevelIndex; size_t mStateVectorSize; size_t mMaxSpareChildCount; std::map> mSpareModules; std::vector mDependencies; std::vector mTopModule; std::map mRepresentants; // id element -> id representative std::vector> mSymmetries; std::map mLayoutInfo; mutable std::vector mRelevantEvents; std::vector mDynamicBehavior; std::map mDependencyInConflict; public: DFT(DFTElementVector const &elements, DFTElementPointer const &tle); DFTStateGenerationInfo buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const; 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, storm::builder::DFTBuilder builder) const; void setDynamicBehaviorInfo(); size_t stateBitVectorSize() const { // Ensure multiple of 64 return (mStateVectorSize / 64 + (mStateVectorSize % 64 != 0)) * 64; } size_t nrElements() const { return mElements.size(); } size_t nrBasicElements() const { return mNrOfBEs; } size_t nrDynamicElements() const; size_t nrStaticElements() const; size_t getTopLevelIndex() const { return mTopLevelIndex; } DFTElementType topLevelType() const { return mElements[getTopLevelIndex()]->type(); } size_t getMaxSpareChildCount() const { return mMaxSpareChildCount; } std::vector getSpareIndices() const { std::vector indices; for(auto const& elem : mElements) { if(elem->isSpareGate()) { indices.push_back(elem->id()); } } return indices; } std::vector const& module(size_t representativeId) const { if(representativeId == mTopLevelIndex) { return mTopModule; } else { STORM_LOG_ASSERT(mSpareModules.count(representativeId) > 0, "Representative not found."); return mSpareModules.find(representativeId)->second; } } bool isDependencyInConflict(size_t id) const { STORM_LOG_ASSERT(isDependency(id), "Not a dependency."); return mDependencyInConflict.at(id); } void setDependencyNotInConflict(size_t id) { STORM_LOG_ASSERT(isDependency(id), "Not a dependency."); mDependencyInConflict.at(id) = false; } std::vector const& getDependencies() const { return mDependencies; } std::vector const &getDynamicBehavior() const { return mDynamicBehavior; } std::vector nonColdBEs() const { std::vector result; for (DFTElementPointer elem : mElements) { if (elem->isBasicElement()) { std::shared_ptr> be = std::static_pointer_cast>(elem); if (be->canFail()) { switch (be->type()) { case storm::storage::DFTElementType::BE_EXP: { auto beExp = std::static_pointer_cast>(be); if (!beExp->isColdBasicElement()) { result.push_back(be->id()); } break; } case storm::storage::DFTElementType::BE_CONST: result.push_back(be->id()); break; default: STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "BE type '" << be->type() << "' is not supported."); } } } } return result; } /** * Get a pointer to an element in the DFT * @param index The id of the element */ DFTElementCPointer getElement(size_t index) const { STORM_LOG_ASSERT(index < nrElements(), "Index invalid."); return mElements[index]; } bool isBasicElement(size_t index) const { return getElement(index)->isBasicElement(); } bool isGate(size_t index) const { return getElement(index)->isGate(); } bool isDependency(size_t index) const { return getElement(index)->isDependency(); } bool isRestriction(size_t index) const { return getElement(index)->isRestriction(); } std::shared_ptr const> getBasicElement(size_t index) const { STORM_LOG_ASSERT(isBasicElement(index), "Element is no BE."); return std::static_pointer_cast const>(mElements[index]); } std::shared_ptr const> getTopLevelGate() const { return getGate(mTopLevelIndex); } std::shared_ptr const> getGate(size_t index) const { STORM_LOG_ASSERT(isGate(index), "Element is no gate."); return std::static_pointer_cast const>(mElements[index]); } std::shared_ptr const> getDependency(size_t index) const { STORM_LOG_ASSERT(isDependency(index), "Element is no dependency."); return std::static_pointer_cast const>(mElements[index]); } std::shared_ptr const> getRestriction(size_t index) const { STORM_LOG_ASSERT(isRestriction(index), "Element is no restriction."); return std::static_pointer_cast const>(mElements[index]); } std::vector>> getBasicElements() const { std::vector>> elements; for (DFTElementPointer elem : mElements) { if (elem->isBasicElement()) { elements.push_back(std::static_pointer_cast>(elem)); } } return elements; } bool canHaveNondeterminism() const; /*! * Check if the DFT is well-formed. * * @param validForAnalysis If true, additional (more restrictive) checks are performed to check whether the DFT is valid for analysis. * @param stream Output stream where warnings about non-well-formed parts are written. * @return True iff the DFT is well-formed. */ bool checkWellFormedness(bool validForAnalysis, std::ostream& stream) const; uint64_t maxRank() const; std::vector> topModularisation() const; bool isRepresentative(size_t id) const { for (auto const& parent : getElement(id)->parents()) { if (parent->isSpareGate()) { return true; } } return false; } bool hasRepresentant(size_t id) const { return mRepresentants.find(id) != mRepresentants.end(); } size_t getRepresentant(size_t id) const { STORM_LOG_ASSERT(hasRepresentant(id), "Element has no representant."); return mRepresentants.find(id)->second; } bool hasFailed(DFTStatePointer const& state) const { return state->hasFailed(mTopLevelIndex); } bool hasFailed(storm::storage::BitVector const& state, DFTStateGenerationInfo const& stateGenerationInfo) const { return storm::storage::DFTState::hasFailed(state, stateGenerationInfo.getStateIndex(mTopLevelIndex)); } bool isFailsafe(DFTStatePointer const& state) const { return state->isFailsafe(mTopLevelIndex); } bool isFailsafe(storm::storage::BitVector const& state, DFTStateGenerationInfo const& stateGenerationInfo) const { return storm::storage::DFTState::isFailsafe(state, stateGenerationInfo.getStateIndex(mTopLevelIndex)); } size_t getChild(size_t spareId, size_t nrUsedChild) const; size_t getNrChild(size_t spareId, size_t childId) const; std::string getElementsString() const; std::string getInfoString() const; std::string getSpareModulesString() const; std::string getElementsWithStateString(DFTStatePointer const& state) const; std::string getStateString(DFTStatePointer const& state) const; std::string getStateString(storm::storage::BitVector const& status, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) const; std::vector getIndependentSubDftRoots(size_t index) const; DFTColouring colourDFT() const; std::map findBijection(size_t index1, size_t index2, DFTColouring const& colouring, bool sparesAsLeaves) const; DFTIndependentSymmetries findSymmetries(DFTColouring const& colouring) const; void findSymmetriesHelper(std::vector const& candidates, DFTColouring const& colouring, std::map>>& result) const; std::vector immediateFailureCauses(size_t index) const; std::vector findModularisationRewrite() const; void setElementLayoutInfo(size_t id, DFTLayoutInfo const& layoutInfo) { mLayoutInfo[id] = layoutInfo; } DFTLayoutInfo const& getElementLayoutInfo(size_t id) const { return mLayoutInfo.at(id); } void writeStatsToStream(std::ostream& stream) const; /*! * Get Ids of all elements. * @return All element ids. */ std::set getAllIds() const; /*! * Get id for the given element name. * @param name Name of element. * @return Index of element. */ size_t getIndex(std::string const& name) const; /*! * Get all relevant events. * @return List of all relevant events. */ std::vector const& getRelevantEvents() const; /*! * Set the relevance flag for all elements according to the given relevant events. * @param relevantEvents All elements which should be to relevant. All elements not occurring are set to irrelevant. * @param allowDCForRelevantEvents Flag whether Don't Care propagation is allowed even for relevant events. */ void setRelevantEvents(std::set const& relevantEvents, bool allowDCForRelevantEvents) const; /*! * Get a string containing the list of all relevant events. * @return String containing all relevant events. */ std::string getRelevantEventsString() const; private: std::tuple, std::vector, std::vector> getSortedParentAndDependencyIds(size_t index) const; bool elementIndicesCorrect() const { for(size_t i = 0; i < mElements.size(); ++i) { if(mElements[i]->id() != i) return false; } return true; } }; } }