Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftTransformer.cpp
Go to the documentation of this file.
1#include "DftTransformer.h"
2
5
7
8namespace storm::dft {
9namespace transformations {
10
11template<typename ValueType>
13 // Count number of constant failed BE or BE with constant probability distribution (as they can also be immediately failed).
14 // Return false if this number exceeds 1.
15 size_t noConstFailed = 0;
16 for (size_t i = 0; i < dft.nrElements(); ++i) {
17 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> element = dft.getElement(i);
18 if (element->isBasicElement()) {
19 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(element);
21 auto beConst = std::static_pointer_cast<storm::dft::storage::elements::BEConst<ValueType> const>(be);
22 if (beConst->canFail()) {
23 ++noConstFailed;
24 if (noConstFailed > 1) {
25 return false;
26 }
27 }
28 } else if (be->beType() == storm::dft::storage::elements::BEType::PROBABILITY) {
29 ++noConstFailed;
30 if (noConstFailed > 1) {
31 return false;
32 }
33 }
34 }
35 }
36 return true;
37}
38
39template<typename ValueType>
40std::shared_ptr<storm::dft::storage::DFT<ValueType>> DftTransformer<ValueType>::transformUniqueFailedBE(storm::dft::storage::DFT<ValueType> const &dft) {
42 std::vector<std::string> failedBEs;
43
44 for (size_t i = 0; i < dft.nrElements(); ++i) {
45 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> element = dft.getElement(i);
46 switch (element->type()) {
48 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(element);
49 switch (be->beType()) {
51 // Remember constant failed BEs for later
52 auto beConst = std::static_pointer_cast<storm::dft::storage::elements::BEConst<ValueType> const>(be);
53 if (beConst->canFail()) {
54 STORM_LOG_TRACE("Transform " << *beConst << " to failsafe BE.");
55 failedBEs.push_back(beConst->name());
56 }
57 // All original constant BEs are set to failsafe, failed BEs are later triggered by a new element
58 builder.addBasicElementConst(beConst->name(), false);
59 break;
60 }
62 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException,
63 "BE with constant probability distribution are not supported and need to be transformed before.");
64 break;
65 }
66 default:
67 // Clone other types of BEs
68 builder.cloneElement(element);
69 break;
70 }
71 break;
72 }
73 default:
74 // Clone other elements
75 builder.cloneElement(element);
76 break;
77 }
78 }
79 // At this point the DFT is an exact copy of the original, except for all constant failure probabilities being 0
80
81 // Introduce new constantly failed BE and FDEPs to trigger all failures
82 if (!failedBEs.empty()) {
83 STORM_LOG_TRACE("Add unique constant failed BE 'Unique_Constant_Failure'");
84 builder.addBasicElementConst("Unique_Constant_Failure", true);
85 failedBEs.insert(failedBEs.begin(), "Unique_Constant_Failure");
86 STORM_LOG_TRACE("Add FDEP 'Failure_Trigger'");
87 builder.addPdep("Failure_Trigger", failedBEs, storm::utility::one<ValueType>());
88 }
89
90 builder.setTopLevel(dft.getTopLevelElement()->name());
91 return std::make_shared<storm::dft::storage::DFT<ValueType>>(builder.build());
92}
93
94template<typename ValueType>
96 if (dft.getDependencies().empty()) {
97 return false;
98 }
99 for (size_t dependencyId : dft.getDependencies()) {
100 if (dft.getDependency(dependencyId)->dependentEvents().size() > 1) {
101 return true;
102 }
103 }
104 return false;
105}
106
107template<typename ValueType>
108std::shared_ptr<storm::dft::storage::DFT<ValueType>> DftTransformer<ValueType>::transformBinaryDependencies(storm::dft::storage::DFT<ValueType> const &dft) {
110
111 for (size_t i = 0; i < dft.nrElements(); ++i) {
112 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> element = dft.getElement(i);
113 switch (element->type()) {
115 auto dep = std::static_pointer_cast<storm::dft::storage::elements::DFTDependency<ValueType> const>(element);
116 if (dep->dependentEvents().size() == 1) {
117 // Already binary dependency -> simply clone element
118 builder.cloneElement(dep);
119 } else {
120 if (!storm::utility::isOne(dep->probability())) {
121 // PDEP with probability < 1
122 STORM_LOG_TRACE("Transform " << *element);
123 // Introduce additional element to first capture the probabilistic dependency
124 std::string nameAdditional = dep->name() + "_additional";
125 STORM_LOG_TRACE("Add auxiliary BE " << nameAdditional);
126 builder.addBasicElementConst(nameAdditional, false);
127 STORM_LOG_TRACE("Add PDEP " << dep->name() << "_pdep");
128 // First consider probabilistic dependency
129 builder.addPdep(dep->name() + "_pdep", {dep->triggerEvent()->name(), nameAdditional}, dep->probability());
130 // Then consider dependencies to the children if probabilistic dependency failed
131 for (size_t j = 0; j < dep->dependentEvents().size(); ++j) {
132 std::string nameDep = dep->name() + "_" + std::to_string(j);
133 std::string dependentName = dep->dependentEvents()[j]->name();
134 STORM_LOG_TRACE("Add FDEP " << nameDep << " for " << dependentName);
135 builder.addPdep(nameDep, {nameAdditional, dependentName}, storm::utility::one<ValueType>());
136 }
137 } else {
138 // FDEP -> add explicit dependencies for each dependent event
139 STORM_LOG_TRACE("Transform " << *element);
140 for (size_t j = 0; j < dep->dependentEvents().size(); ++j) {
141 std::string nameDep = dep->name() + "_" + std::to_string(j);
142 std::string dependentName = dep->dependentEvents()[j]->name();
143 STORM_LOG_TRACE("Add FDEP " << nameDep << " for " << dependentName);
144 builder.addPdep(nameDep, {dep->triggerEvent()->name(), dependentName}, storm::utility::one<ValueType>());
145 }
146 }
147 }
148 break;
149 }
150 default:
151 // Clone other elements
152 builder.cloneElement(element);
153 break;
154 }
155 }
156
157 builder.setTopLevel(dft.getTopLevelElement()->name());
158 return std::make_shared<storm::dft::storage::DFT<ValueType>>(builder.build());
159}
160
161template<typename ValueType>
163 for (size_t i = 0; i < dft.nrElements(); ++i) {
164 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> element = dft.getElement(i);
165 if (element->isBasicElement()) {
166 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(element);
168 return false;
169 }
170 }
171 }
172 return true;
173}
174
175template<typename ValueType>
176std::shared_ptr<storm::dft::storage::DFT<ValueType>> DftTransformer<ValueType>::transformExponentialDistributions(
179
180 for (size_t i = 0; i < dft.nrElements(); ++i) {
181 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> element = dft.getElement(i);
182 switch (element->type()) {
184 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(element);
185 switch (be->beType()) {
187 STORM_LOG_TRACE("Replace " << *be << " with constant failsafe BE and PDEP.");
188 auto beProb = std::static_pointer_cast<storm::dft::storage::elements::BEProbability<ValueType> const>(be);
189 // Model BE with constant probability by PDEP
190 // Introduce constant failed element as trigger
191 std::string triggerName = "constantBeTrigger_" + beProb->name();
192 builder.addBasicElementConst(triggerName, true);
193 // Add constant failsafe element for original BE
194 builder.addBasicElementConst(beProb->name(), false);
195 // Add PDEP in which the probability corresponds to the failure probability of the original BE
196 builder.addPdep(beProb->name() + "_pdep", {triggerName, beProb->name()}, beProb->activeFailureProbability());
197 break;
198 }
200 STORM_LOG_TRACE("Replace " << *be << " with multiple BE and SEQ.");
201 auto beErlang = std::static_pointer_cast<storm::dft::storage::elements::BEErlang<ValueType> const>(be);
202 // Model BE with Erlang distribution by using SEQ over BEs instead.
203 std::vector<std::string> childNames;
204 builder.addBasicElementExponential(beErlang->name(), beErlang->activeFailureRate(), beErlang->dormancyFactor());
205 // For each phase a BE is added
206 for (size_t j = 0; j < beErlang->phases() - 1; ++j) {
207 std::string beName = beErlang->name() + "_" + std::to_string(j);
208 childNames.push_back(beName);
209 builder.addBasicElementExponential(beName, beErlang->activeFailureRate(), beErlang->dormancyFactor());
210 }
211 childNames.push_back(beErlang->name());
212 // SEQ ensures the ordered failure.
213 builder.addSequenceEnforcer(beErlang->name() + "_seq", childNames);
214 break;
215 }
216 default:
217 // Clone other types of BEs
218 builder.cloneElement(be);
219 break;
220 }
221 break;
222 }
223 default:
224 // Clone other elements
225 builder.cloneElement(element);
226 break;
227 }
228 }
229
230 builder.setTopLevel(dft.getTopLevelElement()->name());
231 return std::make_shared<storm::dft::storage::DFT<ValueType>>(builder.build());
232}
233
234// Explicitly instantiate the class.
235template class DftTransformer<double>;
237
238} // namespace transformations
239} // namespace storm::dft
void addPdep(std::string const &name, std::vector< std::string > const &children, ValueType probability)
Create (probabilistic) dependency (PDEP) and add it to DFT.
void addBasicElementConst(std::string const &name, bool failed)
Create BE which is constant failed or constant failsafe and add it to DFT.
storm::dft::storage::DFT< ValueType > build()
Create DFT.
void cloneElement(DFTElementCPointer element)
Clone element and add it via the builder.
void setTopLevel(std::string const &tle)
Set top level element.
void addBasicElementExponential(std::string const &name, ValueType rate, ValueType dormancyFactor, bool transient=false)
Create BE with exponential distribution and add it to DFT.
void addSequenceEnforcer(std::string const &name, std::vector< std::string > const &children)
Create sequence enforcer (SEQ) and add it to DFT.
Represents a Dynamic Fault Tree.
Definition DFT.h:52
std::shared_ptr< storm::dft::storage::elements::DFTDependency< ValueType > const > getDependency(size_t index) const
Definition DFT.h:223
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
Definition DFT.h:188
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:214
std::vector< size_t > const & getDependencies() const
Definition DFT.h:153
size_t nrElements() const
Definition DFT.h:94
Transformer for operations on DFT.
static bool hasUniqueFailedBE(storm::dft::storage::DFT< ValueType > const &dft)
Check whether at most one constant failed BE is present in the DFT.
static std::shared_ptr< storm::dft::storage::DFT< ValueType > > transformUniqueFailedBE(storm::dft::storage::DFT< ValueType > const &dft)
Introduce unique BE which is always failed (instead of multiple ones).
static bool hasNonBinaryDependency(storm::dft::storage::DFT< ValueType > const &dft)
Check whether the DFT has dependencies with multiple dependent events.
static std::shared_ptr< storm::dft::storage::DFT< ValueType > > transformBinaryDependencies(storm::dft::storage::DFT< ValueType > const &dft)
Introduce binary dependencies (with only one dependent event) instead of dependencies with multiple d...
static bool hasOnlyExponentialDistributions(storm::dft::storage::DFT< ValueType > const &dft)
Check whether the DFT contains only BEs with exponential distributions (or constant failed/failsafe B...
static std::shared_ptr< storm::dft::storage::DFT< ValueType > > transformExponentialDistributions(storm::dft::storage::DFT< ValueType > const &dft)
Replace certain BE distributions by DFT constructs using only exponential distributions to make them ...
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
bool isOne(ValueType const &a)
Definition constants.cpp:36