|  | @ -1,76 +1,125 @@ | 
		
	
		
			
				|  |  | #pragma once |  |  | #pragma once | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  | #include "DFTElement.h" |  |  | #include "DFTElement.h" | 
		
	
		
			
				|  |  |  |  |  | 
 | 
		
	
		
			
				|  |  | namespace storm { |  |  | namespace storm { | 
		
	
		
			
				|  |  |     namespace storage { |  |  |     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<typename ValueType> |  |  |         template<typename ValueType> | 
		
	
		
			
				|  |  |         class DFTDependency : public DFTElement<ValueType> { |  |  |         class DFTDependency : public DFTElement<ValueType> { | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             using DFTGatePointer = std::shared_ptr<DFTGate<ValueType>>; |  |  |             using DFTGatePointer = std::shared_ptr<DFTGate<ValueType>>; | 
		
	
		
			
				|  |  |             using DFTBEPointer = std::shared_ptr<DFTBE<ValueType>>; |  |  |             using DFTBEPointer = std::shared_ptr<DFTBE<ValueType>>; | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         protected: |  |  |  | 
		
	
		
			
				|  |  |             ValueType mProbability; |  |  |  | 
		
	
		
			
				|  |  |             DFTGatePointer mTriggerEvent; |  |  |  | 
		
	
		
			
				|  |  |             std::vector<DFTBEPointer> mDependentEvents; |  |  |  | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  |         public: |  |  |         public: | 
		
	
		
			
				|  |  |             DFTDependency(size_t id, std::string const& name, ValueType probability) : |  |  |  | 
		
	
		
			
				|  |  |                 DFTElement<ValueType>(id, name), mProbability(probability) |  |  |  | 
		
	
		
			
				|  |  |             { |  |  |  | 
		
	
		
			
				|  |  |             } |  |  |  | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  |             virtual ~DFTDependency() {} |  |  |  | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  |             void setTriggerElement(DFTGatePointer const& triggerEvent) { |  |  |  | 
		
	
		
			
				|  |  |                 mTriggerEvent = triggerEvent; |  |  |  | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             /*! | 
		
	
		
			
				|  |  |  |  |  |              * 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<ValueType>(id, name), mProbability(probability) { | 
		
	
		
			
				|  |  |  |  |  |                 // We cannot assert 0<=p<=1 in general, because ValueType might be RationalFunction. | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             void setDependentEvents(std::vector<DFTBEPointer> const& dependentEvents) { |  |  |  | 
		
	
		
			
				|  |  |                 mDependentEvents = dependentEvents; |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             DFTElementType type() const override { | 
		
	
		
			
				|  |  |  |  |  |                 return DFTElementType::PDEP; | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  | 
 |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             /*! | 
		
	
		
			
				|  |  |  |  |  |              * Get probability of forwarding the failure. | 
		
	
		
			
				|  |  |  |  |  |              * @return Probability. | 
		
	
		
			
				|  |  |  |  |  |              */ | 
		
	
		
			
				|  |  |             ValueType const& probability() const { |  |  |             ValueType const& probability() const { | 
		
	
		
			
				|  |  |                 return mProbability; |  |  |                 return mProbability; | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |  |  |  |             /*! | 
		
	
		
			
				|  |  |  |  |  |              * Get trigger event, i.e., the first child. | 
		
	
		
			
				|  |  |  |  |  |              * @return Trigger event. | 
		
	
		
			
				|  |  |  |  |  |              */ | 
		
	
		
			
				|  |  |             DFTGatePointer const& triggerEvent() const { |  |  |             DFTGatePointer const& triggerEvent() const { | 
		
	
		
			
				|  |  |                 STORM_LOG_ASSERT(mTriggerEvent, "Trigger does not exist."); |  |  |                 STORM_LOG_ASSERT(mTriggerEvent, "Trigger does not exist."); | 
		
	
		
			
				|  |  |                 return mTriggerEvent; |  |  |                 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<DFTBEPointer> const& dependentEvents() const { |  |  |             std::vector<DFTBEPointer> const& dependentEvents() const { | 
		
	
		
			
				|  |  |                 STORM_LOG_ASSERT(mDependentEvents.size() > 0, "Dependent element does not exists."); |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 STORM_LOG_ASSERT(mDependentEvents.size() > 0, "Dependent event does not exists."); | 
		
	
		
			
				|  |  |                 return mDependentEvents; |  |  |                 return mDependentEvents; | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             DFTElementType type() const override { |  |  |  | 
		
	
		
			
				|  |  |                 return DFTElementType::PDEP; |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             /*! | 
		
	
		
			
				|  |  |  |  |  |              * 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 { |  |  |             virtual size_t nrChildren() const override { | 
		
	
		
			
				|  |  |                 return 1; |  |  |                 return 1; | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual bool isDependency() const override { |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             bool isDependency() const override { | 
		
	
		
			
				|  |  |                 return true; |  |  |                 return true; | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual bool isTypeEqualTo(DFTElement<ValueType> const& other) const override { |  |  |  | 
		
	
		
			
				|  |  |                 if(!DFTElement<ValueType>::isTypeEqualTo(other)) return false; |  |  |  | 
		
	
		
			
				|  |  |                 DFTDependency<ValueType> const& otherDEP= static_cast<DFTDependency<ValueType> const&>(other); |  |  |  | 
		
	
		
			
				|  |  |                 return (mProbability == otherDEP.mProbability); |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             /*! | 
		
	
		
			
				|  |  |  |  |  |              * 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<ValueType> const& other) const override { | 
		
	
		
			
				|  |  |  |  |  |                 if (!DFTElement<ValueType>::isTypeEqualTo(other)) { | 
		
	
		
			
				|  |  |  |  |  |                     return false; | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |  |  |  |                 auto& otherDEP = static_cast<DFTDependency<ValueType> const&>(other); | 
		
	
		
			
				|  |  |  |  |  |                 return this->probability() == otherDEP.probability(); | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual void extendSpareModule(std::set<size_t>& elementsInSpareModule) const override { |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             void extendSpareModule(std::set<size_t>& elementsInSpareModule) const override { | 
		
	
		
			
				|  |  |                 // Do nothing |  |  |                 // Do nothing | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual std::vector<size_t> independentUnit() const override { |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             std::vector<size_t> independentUnit() const override { | 
		
	
		
			
				|  |  |                 std::set<size_t> unit = {this->mId}; |  |  |                 std::set<size_t> unit = {this->mId}; | 
		
	
		
			
				|  |  |                 for (auto const& depEv : mDependentEvents) { |  |  |                 for (auto const& depEv : mDependentEvents) { | 
		
	
		
			
				|  |  |                     depEv->extendUnit(unit); |  |  |                     depEv->extendUnit(unit); | 
		
	
	
		
			
				|  | @ -81,8 +130,10 @@ namespace storm { | 
		
	
		
			
				|  |  |                 return std::vector<size_t>(unit.begin(), unit.end()); |  |  |                 return std::vector<size_t>(unit.begin(), unit.end()); | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual void extendSubDft(std::set<size_t>& elemsInSubtree, std::vector<size_t> const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { |  |  |  | 
		
	
		
			
				|  |  |                 if(elemsInSubtree.count(this->id())) return; |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             void extendSubDft(std::set<size_t>& elemsInSubtree, std::vector<size_t> const& parentsOfSubRoot, bool blockParents, bool sparesAsLeaves) const override { | 
		
	
		
			
				|  |  |  |  |  |                 if (elemsInSubtree.count(this->id())) { | 
		
	
		
			
				|  |  |  |  |  |                     return; | 
		
	
		
			
				|  |  |  |  |  |                 } | 
		
	
		
			
				|  |  |                 DFTElement<ValueType>::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); |  |  |                 DFTElement<ValueType>::extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); | 
		
	
		
			
				|  |  |                 if (elemsInSubtree.empty()) { |  |  |                 if (elemsInSubtree.empty()) { | 
		
	
		
			
				|  |  |                     // Parent in the subdft, ie it is *not* a subdft |  |  |                     // Parent in the subdft, ie it is *not* a subdft | 
		
	
	
		
			
				|  | @ -90,7 +141,9 @@ namespace storm { | 
		
	
		
			
				|  |  |                 } |  |  |                 } | 
		
	
		
			
				|  |  |                 for (auto const& depEv : mDependentEvents) { |  |  |                 for (auto const& depEv : mDependentEvents) { | 
		
	
		
			
				|  |  |                     depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); |  |  |                     depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); | 
		
	
		
			
				|  |  |                     if (elemsInSubtree.empty()) return; |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                     if (elemsInSubtree.empty()) { | 
		
	
		
			
				|  |  |  |  |  |                         return; | 
		
	
		
			
				|  |  |  |  |  |                     } | 
		
	
		
			
				|  |  |                 } |  |  |                 } | 
		
	
		
			
				|  |  |                 if (elemsInSubtree.empty()) { |  |  |                 if (elemsInSubtree.empty()) { | 
		
	
		
			
				|  |  |                     // Parent in the subdft, ie it is *not* a subdft |  |  |                     // Parent in the subdft, ie it is *not* a subdft | 
		
	
	
		
			
				|  | @ -100,21 +153,23 @@ namespace storm { | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |             virtual std::string toString() const override { |  |  |  | 
		
	
		
			
				|  |  |  |  |  |             std::string toString() const override { | 
		
	
		
			
				|  |  |                 std::stringstream stream; |  |  |                 std::stringstream stream; | 
		
	
		
			
				|  |  |                 bool isFDEP = storm::utility::isOne(this->probability()); |  |  |  | 
		
	
		
			
				|  |  |                 stream << "{" << this->name() << "} " << (isFDEP ? "FDEP" : "PDEP") << "(" << this->triggerEvent()->name() << " => { "; |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 stream << "{" << this->name() << "} " << (this->isFDEP() ? "FDEP" : "PDEP") << "(" << this->triggerEvent()->name() << " => { "; | 
		
	
		
			
				|  |  |                 for (auto const& depEv : this->dependentEvents()) { |  |  |                 for (auto const& depEv : this->dependentEvents()) { | 
		
	
		
			
				|  |  |                     stream << depEv->name() << " "; |  |  |                     stream << depEv->name() << " "; | 
		
	
		
			
				|  |  |                 } |  |  |                 } | 
		
	
		
			
				|  |  |                 stream << "}"; |  |  |                 stream << "}"; | 
		
	
		
			
				|  |  |                 if (!isFDEP) { |  |  |  | 
		
	
		
			
				|  |  |  |  |  |                 if (!this->isFDEP()) { | 
		
	
		
			
				|  |  |                     stream << " with probability " << this->probability(); |  |  |                     stream << " with probability " << this->probability(); | 
		
	
		
			
				|  |  |                 } |  |  |                 } | 
		
	
		
			
				|  |  |                 return stream.str(); |  |  |                 return stream.str(); | 
		
	
		
			
				|  |  |             } |  |  |             } | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         protected: |  |  |  | 
		
	
		
			
				|  |  |  |  |  |         private: | 
		
	
		
			
				|  |  |  |  |  |             ValueType mProbability; | 
		
	
		
			
				|  |  |  |  |  |             DFTGatePointer mTriggerEvent; | 
		
	
		
			
				|  |  |  |  |  |             std::vector<DFTBEPointer> mDependentEvents; | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
		
			
				|  |  |         }; |  |  |         }; | 
		
	
		
			
				|  |  | 
 |  |  | 
 | 
		
	
	
		
			
				|  | 
 |