|
|
@ -1,76 +1,125 @@ |
|
|
|
#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<typename ValueType> |
|
|
|
class DFTDependency : public DFTElement<ValueType> { |
|
|
|
|
|
|
|
using DFTGatePointer = std::shared_ptr<DFTGate<ValueType>>; |
|
|
|
using DFTBEPointer = std::shared_ptr<DFTBE<ValueType>>; |
|
|
|
|
|
|
|
protected: |
|
|
|
ValueType mProbability; |
|
|
|
DFTGatePointer mTriggerEvent; |
|
|
|
std::vector<DFTBEPointer> mDependentEvents; |
|
|
|
|
|
|
|
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 { |
|
|
|
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<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; |
|
|
|
} |
|
|
|
|
|
|
|
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 { |
|
|
|
return 1; |
|
|
|
} |
|
|
|
|
|
|
|
virtual bool isDependency() const override { |
|
|
|
bool isDependency() const override { |
|
|
|
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 |
|
|
|
} |
|
|
|
|
|
|
|
virtual std::vector<size_t> independentUnit() const override { |
|
|
|
std::vector<size_t> independentUnit() const override { |
|
|
|
std::set<size_t> unit = {this->mId}; |
|
|
|
for (auto const& depEv : mDependentEvents) { |
|
|
|
depEv->extendUnit(unit); |
|
|
@ -81,8 +130,10 @@ namespace storm { |
|
|
|
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); |
|
|
|
if (elemsInSubtree.empty()) { |
|
|
|
// Parent in the subdft, ie it is *not* a subdft |
|
|
@ -90,7 +141,9 @@ namespace storm { |
|
|
|
} |
|
|
|
for (auto const& depEv : mDependentEvents) { |
|
|
|
depEv->extendSubDft(elemsInSubtree, parentsOfSubRoot, blockParents, sparesAsLeaves); |
|
|
|
if (elemsInSubtree.empty()) return; |
|
|
|
if (elemsInSubtree.empty()) { |
|
|
|
return; |
|
|
|
} |
|
|
|
} |
|
|
|
if (elemsInSubtree.empty()) { |
|
|
|
// 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; |
|
|
|
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()) { |
|
|
|
stream << depEv->name() << " "; |
|
|
|
} |
|
|
|
stream << "}"; |
|
|
|
if (!isFDEP) { |
|
|
|
if (!this->isFDEP()) { |
|
|
|
stream << " with probability " << this->probability(); |
|
|
|
} |
|
|
|
return stream.str(); |
|
|
|
} |
|
|
|
|
|
|
|
protected: |
|
|
|
private: |
|
|
|
ValueType mProbability; |
|
|
|
DFTGatePointer mTriggerEvent; |
|
|
|
std::vector<DFTBEPointer> mDependentEvents; |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|