You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
6.6 KiB
177 lines
6.6 KiB
#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>>;
|
|
|
|
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<ValueType>(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<DFTBEPointer> 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<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();
|
|
}
|
|
|
|
void extendSpareModule(std::set<size_t>& elementsInSpareModule) const override {
|
|
// Do nothing
|
|
}
|
|
|
|
std::vector<size_t> independentUnit() const override {
|
|
std::set<size_t> unit = {this->mId};
|
|
for (auto const& depEv : mDependentEvents) {
|
|
depEv->extendUnit(unit);
|
|
if (unit.count(mTriggerEvent->id()) != 0) {
|
|
return {};
|
|
}
|
|
}
|
|
return std::vector<size_t>(unit.begin(), unit.end());
|
|
}
|
|
|
|
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
|
|
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<DFTBEPointer> mDependentEvents;
|
|
|
|
};
|
|
|
|
}
|
|
}
|