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