Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftValidator.cpp
Go to the documentation of this file.
1#include "DftValidator.h"
2
3#include <algorithm>
4
6
7namespace storm::dft {
8namespace utility {
9
10template<typename ValueType>
12 // 1. DFT is acyclic
13 // was already checked in DFTBuilder::topologicalVisit()
14
15 // 2. Exactly the BEs have no children
16 // was already checked in DFTBuilder::addGate()
17
18 // 3. Valid threshold for VOT
19 // was already checked in DFTBuilder::addVotingGate()
20
21 // 4. TLE is neither SEQ nor PDEP
22 auto const& tle = dft.getTopLevelElement();
23 if (tle->isDependency()) {
24 stream << "Top level element " << *tle << " should not be a dependency.";
25 return false;
26 }
27 if (tle->isRestriction()) {
28 stream << "Top level element " << *tle << " should not be a restriction.";
29 return false;
30 }
31 // 5. SEQ and PDEP have no parents
32 // was already checked in DFTBuilder::build()
33
34 // 6. SEQ and PDEP are at least binary
35 // was already checked in DFTBuilder::addRestriction() and DFTBuilder::addDependency()
36 return true;
37}
38
39template<typename ValueType>
42 // DFT is not even well-formed
43 // Output of isDftWellFormed() is enough
44 return false;
45 }
46
47 // 7. Restriction to exponential distributions
49 stream << "DFT has BE distributions which are neither exponential nor constant failed/failsafe.";
50 return false;
51 }
52
53 // 8. Independence of spare modules
54 auto spareModules = dft.getSpareModules();
55 for (auto module1 = spareModules.begin(); module1 != spareModules.end(); ++module1) {
56 auto const& module1Elements = module1->getElements();
57 if (!module1Elements.empty()) {
58 // If module is empty, it overlaps with the top module. Potential modeling issues are checked separately in hasPotentialModelingIssues().
59 for (auto module2 = std::next(module1); module2 != spareModules.end(); ++module2) {
60 // Check that spare modules do not overlap
61 auto const& module2Elements = module2->getElements();
62 std::vector<size_t> intersection;
63 std::set_intersection(module1Elements.begin(), module1Elements.end(), module2Elements.begin(), module2Elements.end(),
64 std::back_inserter(intersection));
65 if (!intersection.empty()) {
66 stream << "Spare modules of '" << dft.getElement(module1->getRepresentative())->name() << "' and '"
67 << dft.getElement(module2->getRepresentative())->name() << "' should not overlap.";
68 return false;
69 }
70 }
71 }
72 }
73
74 // Collect primary modules (used for 9. and 10.)
75 std::vector<size_t> primaryModuleIds;
76 for (size_t spareId : dft.getSpareIndices()) {
77 primaryModuleIds.push_back(dft.getGate(spareId)->children()[0]->id());
78 }
79
80 // 9. No constant failed events in primary module
81 for (size_t primaryModuleId : primaryModuleIds) {
82 for (size_t elementId : dft.module(primaryModuleId).getElements()) {
83 if (dft.isBasicElement(elementId)) {
84 auto const& be = dft.getBasicElement(elementId);
86 auto beConst = std::static_pointer_cast<storm::dft::storage::elements::BEConst<ValueType> const>(be);
87 if (beConst->canFail()) {
88 stream << "Spare module of '" << dft.getElement(primaryModuleId)->name() << "' contains a constant failed BE '" << beConst->name()
89 << "'.";
90 return false;
91 }
92 }
93 }
94 }
95 }
96
97 // 10. No sharing of primary modules
98 for (auto module1It = primaryModuleIds.begin(); module1It != primaryModuleIds.end(); ++module1It) {
99 for (auto module2It = std::next(module1It); module2It != primaryModuleIds.end(); ++module2It) {
100 if (*module1It == *module2It) {
101 stream << "Module of '" << dft.getElement(*module1It)->name() << "' is shared primary module of multiple SPAREs.";
102 return false;
103 }
104 }
105 }
106
107 // 11. Dependent events of PDEPs are BEs
108 // was already checked in DFTBuilder::build()
109
110 // 12. Unique constant failed BE
112 stream << "DFT has more than one constant failed BE.";
113 return false;
114 }
115
116 // Dependencies must be binary
118 stream << "DFT has dependency with more than one dependent event.";
119 return false;
120 }
121
122 return true;
123}
124
125template<typename ValueType>
127 bool potentialIssues = false;
128
129 // Warn if spare module is connected to top level module.
130 // In this case, the spare module is activated from the beginning.
131 for (auto spareModule : dft.getSpareModules()) {
132 if (spareModule.getElements().empty()) {
133 stream << "Elements of spare module '" << dft.getElement(spareModule.getRepresentative())->name()
134 << "' also contained in top module. All elements of this spare module will be activated from the beginning on.";
135 potentialIssues = true;
136 }
137 }
138
139 // Warn if spare module also contains the parent SPARE gate.
140 // If the SPARE gate has no module path to the top level element, the SPARE gate is never activated in this case.
141 for (size_t spareId : dft.getSpareIndices()) {
142 auto spare = dft.getGate(spareId);
143 for (auto const& child : spare->children()) {
144 auto module = dft.module(child->id());
145 auto const& moduleElements = module.getElements();
146 if (std::find(moduleElements.begin(), moduleElements.end(), spare->id()) != moduleElements.end()) {
147 stream << "Spare module '" << dft.getElement(module.getRepresentative())->name() << "' also contains the parent SPARE-gate '" << spare->name()
148 << "'. This can prevent proper activation of the spare module. Consider introducing dependencies to properly separate the spare module "
149 << "from the SPARE-gate.";
150 potentialIssues = true;
151 }
152 }
153 }
154
155 return potentialIssues;
156}
157
158// Explicitly instantiate the class.
159template class DftValidator<double>;
160template class DftValidator<RationalFunction>;
161
162} // namespace utility
163} // namespace storm::dft
Represents a Dynamic Fault Tree.
Definition DFT.h:52
std::shared_ptr< storm::dft::storage::elements::DFTBE< ValueType > const > getBasicElement(size_t index) const
Definition DFT.h:210
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
Definition DFT.h:189
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:215
std::shared_ptr< storm::dft::storage::elements::DFTGate< ValueType > const > getGate(size_t index) const
Definition DFT.h:219
std::vector< size_t > getSpareIndices() const
Definition DFT.h:119
std::vector< storm::dft::storage::DftModule > getSpareModules() const
Definition DFT.h:134
storm::dft::storage::DftModule const & module(size_t representativeId) const
Definition DFT.h:129
bool isBasicElement(size_t index) const
Definition DFT.h:194
std::set< size_t > const & getElements() const
Return elements of module.
Definition DftModule.h:39
Transformer for operations on DFT.
static bool isDftValidForMarkovianAnalysis(storm::dft::storage::DFT< ValueType > const &dft, std::ostream &stream)
Check whether the DFT can be analysed by translation to a Markov model, i.e.
static bool isDftWellFormed(storm::dft::storage::DFT< ValueType > const &dft, std::ostream &stream)
Check whether the DFT is well-formed.
static bool hasPotentialModelingIssues(storm::dft::storage::DFT< ValueType > const &dft, std::ostream &stream)
Check whether the DFT has potential modeling issues.