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