Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
FDEPConflictFinder.cpp
Go to the documentation of this file.
2
4
5namespace storm::dft {
6namespace utility {
7
8template<>
9std::vector<std::pair<uint64_t, uint64_t>> FDEPConflictFinder<double>::getDependencyConflicts(storm::dft::storage::DFT<double> const& dft, bool useSMT,
10 uint_fast64_t timeout) {
11 std::shared_ptr<storm::dft::modelchecker::DFTASFChecker> smtChecker = nullptr;
12 if (useSMT) {
14 smtChecker = std::make_shared<storm::dft::modelchecker::DFTASFChecker>(checker);
15 smtChecker->toSolver();
16 }
17
18 std::vector<bool> dynamicBehavior = getDynamicBehavior(dft);
19
20 std::vector<std::pair<uint64_t, uint64_t>> res;
21 uint64_t dep1Index;
22 uint64_t dep2Index;
23 for (size_t i = 0; i < dft.getDependencies().size(); ++i) {
24 dep1Index = dft.getDependencies().at(i);
25 for (size_t j = i + 1; j < dft.getDependencies().size(); ++j) {
26 dep2Index = dft.getDependencies().at(j);
27 if (dynamicBehavior[dep1Index] && dynamicBehavior[dep2Index]) {
28 if (useSMT) { // if an SMT solver is to be used
29 if (dft.getDependency(dep1Index)->triggerEvent() == dft.getDependency(dep2Index)->triggerEvent()) {
30 STORM_LOG_TRACE("Conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name()
31 << ": Same trigger");
32 res.emplace_back(std::pair<uint64_t, uint64_t>(dep1Index, dep2Index));
33 } else {
34 switch (smtChecker->checkDependencyConflict(dep1Index, dep2Index, timeout)) {
36 STORM_LOG_TRACE("Conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
37 res.emplace_back(std::pair<uint64_t, uint64_t>(dep1Index, dep2Index));
38 break;
40 STORM_LOG_TRACE("Unknown: Conflict between " << dft.getElement(dep1Index)->name() << " and "
41 << dft.getElement(dep2Index)->name());
42 res.emplace_back(std::pair<uint64_t, uint64_t>(dep1Index, dep2Index));
43 break;
44 default:
45 STORM_LOG_TRACE("No conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
46 break;
47 }
48 }
49 } else {
50 STORM_LOG_TRACE("Conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
51 res.emplace_back(std::pair<uint64_t, uint64_t>(dep1Index, dep2Index));
52 }
53 } else {
54 STORM_LOG_TRACE("Static behavior: No conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
55 break;
56 }
57 }
58 }
59 return res;
60}
61
62template<>
64 storm::dft::storage::DFT<storm::RationalFunction> const& dft, bool useSMT, uint_fast64_t timeout) {
65 if (useSMT) {
66 STORM_LOG_WARN("SMT encoding for rational functions is not supported");
67 }
68
69 std::vector<bool> dynamicBehavior = getDynamicBehavior(dft);
70
71 std::vector<std::pair<uint64_t, uint64_t>> res;
72 uint64_t dep1Index;
73 uint64_t dep2Index;
74 for (size_t i = 0; i < dft.getDependencies().size(); ++i) {
75 dep1Index = dft.getDependencies().at(i);
76 for (size_t j = i + 1; j < dft.getDependencies().size(); ++j) {
77 dep2Index = dft.getDependencies().at(j);
78 if (dynamicBehavior[dep1Index] && dynamicBehavior[dep2Index]) {
79 STORM_LOG_TRACE("Conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
80 res.emplace_back(std::pair<uint64_t, uint64_t>(dep1Index, dep2Index));
81 } else {
82 STORM_LOG_TRACE("Static behavior: No conflict between " << dft.getElement(dep1Index)->name() << " and " << dft.getElement(dep2Index)->name());
83 break;
84 }
85 }
86 }
87 return res;
88}
89
90template<typename ValueType>
92 std::vector<bool> dynamicBehaviorVector(dft.nrElements(), false);
93
94 std::queue<std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const>> elementQueue;
95
96 // deal with all dynamic elements
97 for (size_t i = 0; i < dft.nrElements(); ++i) {
98 auto element = dft.getElement(i);
99 switch (element->type()) {
103 auto gate = std::static_pointer_cast<storm::dft::storage::elements::DFTChildren<ValueType> const>(element);
104 dynamicBehaviorVector[gate->id()] = true;
105 for (auto const& child : gate->children()) {
106 // only enqueue static children
107 if (!dynamicBehaviorVector.at(child->id())) {
108 elementQueue.push(child);
109 }
110 }
111 break;
112 }
113 // TODO different cases
115 auto spare = std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType> const>(element);
116
117 // Iterate over all children (representatives of spare modules)
118 for (auto const& child : spare->children()) {
119 // Case 1: Shared Module
120 // If child only has one parent, it is this SPARE -> nothing to check
121 if (child->nrParents() > 1) {
122 // TODO make more efficient by directly setting ALL spares which share a module to be dynamic
123 for (auto const& parent : child->parents()) {
124 if (parent->isSpareGate() and parent->id() != spare->id()) {
125 dynamicBehaviorVector[spare->id()] = true;
126 break; // inner loop
127 }
128 }
129 }
130 // Case 2: Triggering outside events
131 // If the SPARE was already detected to have dynamic behavior, do not proceed
132 if (!dynamicBehaviorVector[spare->id()]) {
133 for (auto const& memberID : dft.module(child->id()).getElements()) {
134 // Iterate over all members of the module child represents
135 auto member = dft.getElement(memberID);
136 for (auto const& dep : member->outgoingDependencies()) {
137 // If the member has outgoing dependencies, check if those trigger something outside the module
138 for (auto const& depEvent : dep->dependentEvents()) {
139 // If a dependent event is not found in the module, SPARE is dynamic
140 auto const& childModuleElements = dft.module(child->id()).getElements();
141 if (std::find(childModuleElements.begin(), childModuleElements.end(), depEvent->id()) == childModuleElements.end()) {
142 dynamicBehaviorVector[spare->id()] = true;
143 break; // depEvent-loop
144 }
145 }
146 if (dynamicBehaviorVector[spare->id()]) {
147 break;
148 } // dependency-loop
149 }
150 if (dynamicBehaviorVector[spare->id()]) {
151 break;
152 } // module-loop
153 }
154 }
155 if (dynamicBehaviorVector[spare->id()]) {
156 break;
157 } // child-loop
158 }
159 // if during the computation, dynamic behavior was detected, add children to queue
160 if (dynamicBehaviorVector[spare->id()]) {
161 for (auto const& child : spare->children()) {
162 // only enqueue static children
163 if (!dynamicBehaviorVector.at(child->id())) {
164 elementQueue.push(child);
165 }
166 }
167 }
168 break;
169 }
171 auto seq = std::static_pointer_cast<storm::dft::storage::elements::DFTSeq<ValueType> const>(element);
172 // A SEQ only has dynamic behavior if not all children are BEs
173 if (!seq->allChildrenBEs()) {
174 dynamicBehaviorVector[seq->id()] = true;
175 for (auto const& child : seq->children()) {
176 // only enqueue static children
177 if (!dynamicBehaviorVector.at(child->id())) {
178 elementQueue.push(child);
179 }
180 }
181 }
182 break;
183 }
184 default: {
185 break;
186 }
187 }
188 }
189 // propagate dynamic behavior
190 while (!elementQueue.empty()) {
191 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType> const> currentElement = elementQueue.front();
192 elementQueue.pop();
193 switch (currentElement->type()) {
194 // Static Gates
198 // check all parents and if one has dynamic behavior, propagate it
199 dynamicBehaviorVector[currentElement->id()] = true;
200 auto gate = std::static_pointer_cast<storm::dft::storage::elements::DFTGate<ValueType> const>(currentElement);
201 for (auto const& child : gate->children()) {
202 // only enqueue static children
203 if (!dynamicBehaviorVector.at(child->id())) {
204 elementQueue.push(child);
205 }
206 }
207 break;
208 }
209 // BEs
211 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(currentElement);
212 dynamicBehaviorVector[be->id()] = true;
213 // add all ingoing dependencies to queue
214 for (auto const& dep : be->ingoingDependencies()) {
215 if (!dynamicBehaviorVector.at(dep->id())) {
216 elementQueue.push(dep);
217 }
218 }
219 break;
220 }
222 auto dep = std::static_pointer_cast<storm::dft::storage::elements::DFTDependency<ValueType> const>(currentElement);
223 dynamicBehaviorVector[dep->id()] = true;
224 // add all ingoing dependencies to queue
225 auto trigger = dep->triggerEvent();
226 if (!dynamicBehaviorVector.at(trigger->id())) {
227 elementQueue.push(trigger);
228 }
229 break;
230 }
231 default:
232 break;
233 }
234 }
235 return dynamicBehaviorVector;
236}
237
238template class FDEPConflictFinder<double>;
240
241} // namespace utility
242} // namespace storm::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:224
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
Definition DFT.h:189
std::vector< size_t > const & getDependencies() const
Definition DFT.h:154
size_t nrElements() const
Definition DFT.h:95
storm::dft::storage::DftModule const & module(size_t representativeId) const
Definition DFT.h:129
std::set< size_t > const & getElements() const
Return elements of module.
Definition DftModule.h:39
static std::vector< bool > getDynamicBehavior(storm::dft::storage::DFT< ValueType > const &dft)
static std::vector< std::pair< uint64_t, uint64_t > > getDependencyConflicts(storm::dft::storage::DFT< ValueType > const &dft, bool useSMT=false, uint_fast64_t timeout=10)
Get a vector of index pairs of FDEPs in the DFT which are conflicting.
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_TRACE(message)
Definition logging.h:17