#pragma once #include "DFTElement.h" namespace storm { namespace storage { /*! * Dependency gate with probability p. * If p=1 the gate is a functional dependency (FDEP), otherwise it is a probabilistic dependency (PDEP). * * If the trigger event (i.e., the first child) fails, a coin is flipped. * With probability p the failure is forwarded to all other children. * With probability 1-p the failure is not forwarded and the dependency has no effect. * * The failure forwarding to the children happens in a strict (non-deterministically chosen) order. */ template class DFTDependency : public DFTElement { using DFTGatePointer = std::shared_ptr>; using DFTBEPointer = std::shared_ptr>; public: /*! * Constructor. * @param id Id. * @param name Name. * @param probability Probability p of failure forwarding. */ DFTDependency(size_t id, std::string const& name, ValueType probability) : DFTElement(id, name), mProbability(probability) { // We cannot assert 0<=p<=1 in general, because ValueType might be RationalFunction. } DFTElementType type() const override { return DFTElementType::PDEP; } /*! * Get probability of forwarding the failure. * @return Probability. */ ValueType const& probability() const { return mProbability; } /*! * Get trigger event, i.e., the first child. * @return Trigger event. */ DFTGatePointer const& triggerEvent() const { STORM_LOG_ASSERT(mTriggerEvent, "Trigger does not exist."); return mTriggerEvent; } /*! * Set the trigger event, i.e., the first child. * @param triggerEvent Trigger event. */ void setTriggerElement(DFTGatePointer const& triggerEvent) { mTriggerEvent = triggerEvent; } /*! * Get dependent events. * @return Dependent events. */ std::vector const& dependentEvents() const { STORM_LOG_ASSERT(mDependentEvents.size() > 0, "Dependent event does not exists."); return mDependentEvents; } /*! * Add dependent event. * @param dependentEvent Dependent event. */ void addDependentEvent(DFTBEPointer const& dependentEvent) { mDependentEvents.push_back(dependentEvent); } /*! * Check whether the given element is a dependent event. * @param id Id of element to search for. * @return True iff element was found in dependent events. */ bool containsDependentEvent(size_t id) { auto it = std::find_if(this->mDependentEvents.begin(), this->mDependentEvents.end(), [&id](DFTBEPointer be) -> bool { return be->id() == id; }); return it != this->mDependentEvents.end(); } virtual size_t nrChildren() const override { return 1; } bool isDependency() const override { return true; } /*! * Check whether the dependency is an FDEP, i.e., p=1. * @return True iff p=1. */ bool isFDEP() const { return storm::utility::isOne(this->probability()); } bool isTypeEqualTo(DFTElement const& other) const override { if (!DFTElement::isTypeEqualTo(other)) { return false; } auto& otherDEP = static_cast const&>(other); return this->probability() == otherDEP.probability(); } void extendSpareModule(std::set& elementsInSpareModule) const override { // Do nothing } std::vector independentUnit() const override { std::set unit = {this->mId}; for (auto const& depEv : mDependentEvents) { depEv->extendUnit(unit); if (unit.count(mTriggerEvent->id()) != 0) { return {}; } } return std::vector(unit.begin(), unit.end()); } void extendSubDft(std::set& elemsInSubtree, std::vector const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { if (elemsInSubtree.count(this->id())) { return; } DFTElement::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if (elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } for (auto const& depEv : mDependentEvents) { depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); if (elemsInSubtree.empty()) { return; } } if (elemsInSubtree.empty()) { // Parent in the subdft, ie it is *not* a subdft return; } mTriggerEvent->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); } std::string toString() const override { std::stringstream stream; stream << "{" << this->name() << "} " << (this->isFDEP() ? "FDEP" : "PDEP") << "(" << this->triggerEvent()->name() << " => { "; for (auto const& depEv : this->dependentEvents()) { stream << depEv->name() << " "; } stream << "}"; if (!this->isFDEP()) { stream << " with probability " << this->probability(); } return stream.str(); } private: ValueType mProbability; DFTGatePointer mTriggerEvent; std::vector mDependentEvents; }; } }