#ifndef DFTELEMENTS_H #define DFTELEMENTS_H #include #include #include #include #include #include #include #include "DFTState.h" #include "DFTStateSpaceGenerationQueues.h" #include "src/utility/constants.h" #include "src/adapters/CarlAdapter.h" using std::size_t; namespace storm { namespace storage { template class DFTGate; template class DFTElement { using DFTGatePointer = std::shared_ptr>; using DFTGateVector = std::vector; protected: size_t mId; std::string mName; size_t mRank = -1; DFTGateVector mParents; public: DFTElement(size_t id, std::string const& name) : mId(id), mName(name) {} virtual ~DFTElement() {} virtual size_t id() const { return mId; } virtual void setRank(size_t rank) { mRank = rank; } virtual size_t rank() const { return mRank; } virtual bool isConstant() const { return false; } virtual bool isGate() const { return false; } virtual bool isBasicElement() const { return false; } virtual bool isColdBasicElement() const { return false; } virtual bool isSpareGate() const { return false; } virtual void setId(size_t newId) { mId = newId; } virtual std::string const& name() const { return mName; } bool addParent(DFTGatePointer const& e) { if(std::find(mParents.begin(), mParents.end(), e) != mParents.end()) { return false; } else { mParents.push_back(e); return true; } } bool hasParents() const { return !mParents.empty(); } DFTGateVector const& parents() const { return mParents; } virtual void extendSpareModule(std::set& elementsInModule) const; virtual size_t nrChildren() const = 0; virtual std::string toString() const = 0; virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; virtual std::vector independentUnit() const = 0; virtual void extendUnit(std::set& unit) const; void checkForSymmetricChildren() const; }; enum class DFTElementTypes {AND, COUNTING, OR, VOT, BE, CONSTF, CONSTS, PAND, SPARE, POR, FDEP, SEQAND}; inline bool isGateType(DFTElementTypes const& tp) { switch(tp) { case DFTElementTypes::AND: case DFTElementTypes::COUNTING: case DFTElementTypes::OR: case DFTElementTypes::VOT: case DFTElementTypes::PAND: case DFTElementTypes::SPARE: case DFTElementTypes::POR: case DFTElementTypes::SEQAND: return true; case DFTElementTypes::BE: case DFTElementTypes::CONSTF: case DFTElementTypes::CONSTS: case DFTElementTypes::FDEP: return false; default: assert(false); } } template class DFTGate : public DFTElement { using DFTElementPointer = std::shared_ptr>; using DFTElementVector = std::vector; protected: DFTElementVector mChildren; public: DFTGate(size_t id, std::string const& name, DFTElementVector const& children) : DFTElement(id, name), mChildren(children) {} virtual ~DFTGate() {} void pushBackChild(DFTElementPointer elem) { return mChildren.push_back(elem); } size_t nrChildren() const override { return mChildren.size(); } DFTElementVector const& children() const { return mChildren; } virtual bool isGate() const override { return true; } virtual std::string typestring() const = 0; virtual void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; virtual void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const = 0; virtual void extendSpareModule(std::set& elementsInSpareModule) const override { DFTElement::extendSpareModule(elementsInSpareModule); for(auto const& child : mChildren) { if(elementsInSpareModule.count(child->id()) == 0) { elementsInSpareModule.insert(child->id()); child->extendSpareModule(elementsInSpareModule); } } } virtual std::vector independentUnit() const override { std::set unit = {this->mId}; for(auto const& child : mChildren) { child->extendUnit(unit); } for(auto const& parent : this->mParents) { if(unit.count(parent->id()) != 0) { return {}; } } return std::vector(unit.begin(), unit.end()); } virtual std::string toString() const override { std::stringstream stream; stream << "{" << this->name() << "} " << typestring() << "( "; typename DFTElementVector::const_iterator it = mChildren.begin(); stream << (*it)->name(); ++it; while(it != mChildren.end()) { stream << ", " << (*it)->name(); ++it; } stream << ")"; return stream.str(); } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const override { if(DFTElement::checkDontCareAnymore(state, queues)) { childrenDontCare(state, queues); return true; } return false; } virtual void extendUnit(std::set& unit) const override { DFTElement::extendUnit(unit); for(auto const& child : mChildren) { child->extendUnit(unit); } } protected: void fail(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { for(std::shared_ptr parent : this->mParents) { if(state.isOperational(parent->id())) { queues.propagateFailure(parent); } } state.setFailed(this->mId); } void failsafe(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { for(std::shared_ptr parent : this->mParents) { if(state.isOperational(parent->id())) { queues.propagateFailsafe(parent); } } state.setFailsafe(this->mId); } void childrenDontCare(DFTState& state, DFTStateSpaceGenerationQueues& queues) const { queues.propagateDontCare(mChildren); } bool hasFailsafeChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.isFailsafe(child->id())) { return true; } } return false; } bool hasFailedChild(DFTState& state) const { for(auto const& child : mChildren) { if(state.hasFailed(child->id())) { return true; } } return false; } }; template class DFTBE : public DFTElement { ValueType mActiveFailureRate; ValueType mPassiveFailureRate; public: DFTBE(size_t id, std::string const& name, ValueType failureRate, ValueType dormancyFactor) : DFTElement(id, name), mActiveFailureRate(failureRate), mPassiveFailureRate(dormancyFactor * failureRate) {} virtual size_t nrChildren() const { return 0; } ValueType const& activeFailureRate() const { return mActiveFailureRate; } ValueType const& passiveFailureRate() const { return mPassiveFailureRate; } std::string toString() const { std::stringstream stream; stream << *this; return stream.str(); } bool isBasicElement() const { return true; } bool isColdBasicElement() const { return storm::utility::isZero(mPassiveFailureRate); } virtual std::vector independentUnit() const { return {this->mId}; } virtual bool checkDontCareAnymore(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const; }; template inline std::ostream& operator<<(std::ostream& os, DFTBE const& be) { return os << "{" << be.name() << "} BE(" << be.activeFailureRate() << ", " << be.passiveFailureRate() << ")"; } template class DFTConst : public DFTElement { bool mFailed; public: DFTConst(size_t id, std::string const& name, bool failed) : DFTElement(id, name), mFailed(failed) {} bool failed() const { return mFailed; } virtual bool isConstant() const { return true; } virtual size_t nrChildren() const { return 0; } }; template class DFTAnd : public DFTGate { public: DFTAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(state.isOperational(this->mId)) { for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { return; } } this->fail(state, queues); } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { this->failsafe(state, queues); this->childrenDontCare(state, queues); } } std::string typestring() const { return "AND"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTAnd const& gate) { return os << gate.toString(); } template class DFTOr : public DFTGate { public: DFTOr(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { assert(this->hasFailedChild(state)); if(state.isOperational(this->mId)) { this->fail(state, queues); } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ for(auto const& child : this->mChildren) { if(!state.isFailsafe(child->id())) { return; } } this->failsafe(state, queues); } std::string typestring() const { return "OR"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTOr const& gate) { return os << gate.toString(); } template class DFTSeqAnd : public DFTGate { public: DFTSeqAnd(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(!state.hasFailed(this->mId)) { bool childOperationalBefore = false; for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { childOperationalBefore = true; } else { if(childOperationalBefore) { state.markAsInvalid(); return; } } } if(!childOperationalBefore) { fail(state, queues); } } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(hasFailsafeChild(state)); if(state.isOperational(this->mId)) { failsafe(state, queues); //return true; } //return false; } std::string typestring() const { return "SEQAND"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTSeqAnd const& gate) { return os << gate.toString(); } template class DFTPand : public DFTGate { public: DFTPand(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(state.isOperational(this->mId)) { bool childOperationalBefore = false; for(auto const& child : this->mChildren) { if(!state.hasFailed(child->id())) { childOperationalBefore = true; } else if(childOperationalBefore && state.hasFailed(child->id())){ this->failsafe(state, queues); this->childrenDontCare(state, queues); return; } } if(!childOperationalBefore) { this->fail(state, queues); } } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { this->failsafe(state, queues); this->childrenDontCare(state, queues); } } std::string typestring() const { return "PAND"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTPand const& gate) { return os << gate.toString(); } template class DFTPor : public DFTGate { public: DFTPor(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { assert(false); } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(false); } std::string typestring() const { return "POR"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTPor const& gate) { return os << gate.toString(); } template class DFTVot : public DFTGate { private: unsigned mThreshold; public: DFTVot(size_t id, std::string const& name, unsigned threshold, std::vector>> const& children = {}) : DFTGate(id, name, children), mThreshold(threshold) {} void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(state.isOperational(this->mId)) { unsigned nrFailedChildren = 0; for(auto const& child : this->mChildren) { if(state.hasFailed(child->id())) { ++nrFailedChildren; if(nrFailedChildren >= mThreshold) { this->fail(state, queues); return; } } } } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const{ assert(this->hasFailsafeChild(state)); if(state.isOperational(this->mId)) { unsigned nrFailsafeChildren = 0; for(auto const& child : this->mChildren) { if(state.isFailsafe(child->id())) { ++nrFailsafeChildren; if(nrFailsafeChildren > this->nrChildren() - mThreshold) { this->failsafe(state, queues); this->childrenDontCare(state, queues); return; } } } } } std::string typestring() const { return "VOT (" + std::to_string(mThreshold) + ")"; } }; template inline std::ostream& operator<<(std::ostream& os, DFTVot const& gate) { return os << gate.toString(); } template class DFTSpare : public DFTGate { private: size_t mUseIndex; size_t mActiveIndex; public: DFTSpare(size_t id, std::string const& name, std::vector>> const& children = {}) : DFTGate(id, name, children) {} std::string typestring() const { return "SPARE"; } bool isSpareGate() const { return true; } void setUseIndex(size_t useIndex) { mUseIndex = useIndex; } void setActiveIndex(size_t activeIndex) { mActiveIndex = activeIndex; } void initializeUses(storm::storage::DFTState& state) { assert(this->mChildren.size() > 0); state.setUsesAtPosition(mUseIndex, this->mChildren[0]->id()); } void checkFails(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(state.isOperational(this->mId)) { size_t uses = state.extractUses(mUseIndex); if(!state.isOperational(uses)) { bool claimingSuccessful = state.claimNew(this->mId, mUseIndex, uses, this->mChildren); if(!claimingSuccessful) { this->fail(state, queues); } } } } void checkFailsafe(storm::storage::DFTState& state, DFTStateSpaceGenerationQueues& queues) const { if(state.isOperational(this->mId)) { if(state.isFailsafe(state.extractUses((mUseIndex)))) { this->failsafe(state, queues); this->childrenDontCare(state, queues); } } } }; } } #endif /* DFTELEMENTS_H */