Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DftModularizer.cpp
Go to the documentation of this file.
1#include "DftModularizer.h"
2
4
5namespace storm::dft {
6namespace utility {
7
8template<typename ValueType>
10 // Initialize data structures
11 // dfsCounters/elementInfos must not be cleared because they are either not initialized or were cleared in a previous call of computeModules()
12 for (auto const &id : dft.getAllIds()) {
13 dfsCounters[id] = DfsCounter{};
14 modInfos[id] = ModularizationInfo{};
15 }
16 lastDate = 0;
17
18 // First depth first search of the LTA/DR algorithm.
19 populateDfsCounters(dft.getTopLevelElement());
20
21 // Second depth first search of the LTA/DR algorithm.
22 obtainModules(dft.getTopLevelElement());
23 auto &topModInfo{modInfos.at(dft.getTopLevelElement()->id())};
24 STORM_LOG_ASSERT(topModInfo.isModule, "Top element should form module.");
25 STORM_LOG_ASSERT(topModInfo.elements.empty(), "Top module does not exist.");
26 STORM_LOG_ASSERT(topModInfo.submodules.size() == 1, "Top element should form unique module.");
27 // Get top module
28 storm::dft::storage::DftIndependentModule topModule = *topModInfo.submodules.begin();
29
30 // Free some space
31 dfsCounters.clear();
32 modInfos.clear();
33
34 return topModule;
35}
36
37template<typename ValueType>
38void DftModularizer<ValueType>::populateDfsCounters(DFTElementCPointer const element) {
39 auto &counter{dfsCounters.at(element->id())};
40
41 ++lastDate;
42 if (counter.firstVisit == 0) {
43 // parent was never visited before
44 // as 0 can never be a valid firstVisit
45 counter.firstVisit = lastDate;
46
47 // Recursively visit children
48 for (auto const &child : getChildren(element)) {
49 populateDfsCounters(child);
50 }
51 ++lastDate;
52 counter.secondVisit = lastDate;
53 }
54 if (counter.secondVisit == 0) {
55 // Will set lastDate before secondDate -> encountered cycle
56 STORM_LOG_WARN("Modularizer encountered a cycle containing the element " << *element << ".");
57 // The algorithm still terminates as the children have not been visited again.
58 }
59 counter.lastVisit = lastDate;
60}
61
62template<typename ValueType>
63void DftModularizer<ValueType>::obtainModules(DFTElementCPointer const element) {
64 auto &counter{dfsCounters.at(element->id())};
65 auto &modInfo{modInfos.at(element->id())};
66
67 if (counter.minFirstVisit == 0) {
68 // element was never visited before as min can never be 0
69 // Add current element
70 modInfo.elements.insert(element->id());
71
72 // minFirstVisit <= secondVisit
73 counter.minFirstVisit = counter.secondVisit;
74 // maxLastVisit >= firstVisit
75 counter.maxLastVisit = counter.firstVisit;
76 for (auto const &child : getChildren(element)) {
77 obtainModules(child);
78
79 // Set min/max visit times
80 auto const &childCounter{dfsCounters.at(child->id())};
81 counter.minFirstVisit = std::min({counter.minFirstVisit, childCounter.firstVisit, childCounter.minFirstVisit});
82 counter.maxLastVisit = std::max({counter.maxLastVisit, childCounter.lastVisit, childCounter.maxLastVisit});
83
84 // Fill information
85 auto const &childInfo{modInfos.at(child->id())};
86 // Only insert elements and submodules once
87 modInfo.elements.insert(childInfo.elements.begin(), childInfo.elements.end());
88 modInfo.submodules.insert(childInfo.submodules.begin(), childInfo.submodules.end());
89 modInfo.fullyStatic = modInfo.fullyStatic && childInfo.fullyStatic;
90 if (!childInfo.isStatic && !childInfo.isModule) {
91 modInfo.isStatic = false;
92 }
93 }
94
95 if (!element->isStaticElement()) {
96 modInfo.isStatic = false;
97 modInfo.fullyStatic = false;
98 }
99
100 if (counter.firstVisit < counter.minFirstVisit && counter.maxLastVisit < counter.secondVisit) {
101 // Create new module
102 storm::dft::storage::DftIndependentModule module(element->id(), modInfo.elements, modInfo.submodules, modInfo.isStatic, modInfo.fullyStatic,
103 element->isBasicElement());
104 // Update information
105 modInfo.elements = {};
106 modInfo.submodules = {module};
107 modInfo.isModule = true;
108 }
109 }
110}
111
112template<typename ValueType>
113std::vector<typename DftModularizer<ValueType>::DFTElementCPointer> DftModularizer<ValueType>::getChildren(DFTElementCPointer const element) {
114 std::vector<DFTElementCPointer> children{};
115 if (element->isDependency()) {
116 auto const dependency{std::static_pointer_cast<storm::dft::storage::elements::DFTDependency<ValueType> const>(element)};
117 auto const triggerElement{std::static_pointer_cast<storm::dft::storage::elements::DFTElement<ValueType> const>(dependency->triggerEvent())};
118 children.push_back(triggerElement);
119 children.insert(children.end(), dependency->dependentEvents().begin(), dependency->dependentEvents().end());
120 } else if (element->isGate() || element->isRestriction()) {
121 auto const parent{std::static_pointer_cast<storm::dft::storage::elements::DFTChildren<ValueType> const>(element)};
122 children.insert(children.end(), parent->children().begin(), parent->children().end());
123 } else {
124 STORM_LOG_ASSERT(element->isBasicElement(), "Element " << *element << " has invalid type.");
125 }
126
127 // For each child we also compute the dependencies/restrictions affecting each child
128 // These "affecting elements" also act as children of the given element
129 // That way, we model dependencies/restrictions affecting a child as having a dummy input to the given element
130 std::vector<DFTElementCPointer> affectingElements{};
131 for (auto const &child : children) {
132 if (child->isBasicElement()) {
133 // Add ingoing dependencies
134 auto const be{std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(child)};
135 for (auto const &ingoingDependency : be->ingoingDependencies()) {
136 if (ingoingDependency->id() != element->id() && !containsElement(affectingElements, ingoingDependency)) {
137 affectingElements.push_back(ingoingDependency);
138 }
139 }
140 }
141
142 for (auto const &restriction : child->restrictions()) {
143 if (restriction->id() != element->id() && !containsElement(affectingElements, restriction)) {
144 affectingElements.push_back(restriction);
145 }
146 }
147
148 for (auto const &outgoingDependency : child->outgoingDependencies()) {
149 if (outgoingDependency->id() != element->id() && !containsElement(affectingElements, outgoingDependency)) {
150 affectingElements.push_back(outgoingDependency);
151 }
152 }
153 }
154
155 children.insert(children.end(), affectingElements.begin(), affectingElements.end());
156 return children;
157}
158
159template<typename ValueType>
160bool DftModularizer<ValueType>::containsElement(std::vector<DFTElementCPointer> const &list, DFTElementCPointer const element) {
161 return std::find_if(list.begin(), list.end(), [&element](auto const &elem) { return element->id() == elem->id(); }) != list.end();
162}
163
164template<typename ValueType>
165std::vector<typename DftModularizer<ValueType>::DFTElementCPointer> DftModularizer<ValueType>::getAffectingElements(DFTElementCPointer const element) {
166 std::vector<DFTElementCPointer> affectingElements{};
167
168 if (element->isBasicElement()) {
169 auto const be{std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(element)};
170 auto const &dependencies{be->ingoingDependencies()};
171 affectingElements.insert(affectingElements.end(), dependencies.begin(), dependencies.end());
172 }
173
174 auto const &restrictions{element->restrictions()};
175 affectingElements.insert(affectingElements.end(), restrictions.begin(), restrictions.end());
176
177 auto const &dependencies{element->outgoingDependencies()};
178 affectingElements.insert(affectingElements.end(), dependencies.begin(), dependencies.end());
179
180 return affectingElements;
181}
182
183// Explicitly instantiate the class.
184template class DftModularizer<double>;
185template class DftModularizer<RationalFunction>;
186
187} // namespace utility
188} // namespace storm::dft
Represents a Dynamic Fault Tree.
Definition DFT.h:52
std::set< size_t > getAllIds() const
Get Ids of all elements.
Definition DFT.cpp:669
DFTElementCPointer getTopLevelElement() const
Definition DFT.h:215
Represents an independent module/subtree.
Definition DftModule.h:66
Find modules (independent subtrees) in DFT.
storm::dft::storage::DftIndependentModule computeModules(storm::dft::storage::DFT< ValueType > const &dft)
Compute modules of DFT by applying the LTA/DR algorithm.
#define STORM_LOG_WARN(message)
Definition logging.h:25
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11