Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
DFT.cpp
Go to the documentation of this file.
2
3#include <map>
4
9
12
13namespace storm::dft {
14namespace storage {
15
16template<typename ValueType>
17DFT<ValueType>::DFT(DFTElementVector const& elements, DFTElementPointer const& tle)
18 : mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mNrRepresentatives(0), mTopLevelIndex(tle->id()), mMaxSpareChildCount(0) {
19 // Check that ids correspond to indices in the element vector
20 STORM_LOG_ASSERT(elementIndicesCorrect(), "Ids incorrect.");
21
22 for (auto& elem : mElements) {
23 if (isRepresentative(elem->id())) {
24 ++mNrRepresentatives;
25 }
26 if (elem->isBasicElement()) {
27 ++mNrOfBEs;
28 } else if (elem->isSpareGate()) {
29 // Build spare modules by setting representatives and representants
30 ++mNrOfSpares;
31 mMaxSpareChildCount =
32 std::max(mMaxSpareChildCount, std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>>(elem)->children().size());
33 for (auto const& spareReprs : std::static_pointer_cast<storm::dft::storage::elements::DFTSpare<ValueType>>(elem)->children()) {
34 STORM_LOG_THROW(spareReprs->isGate() || spareReprs->isBasicElement(), storm::exceptions::WrongFormatException,
35 "Child '" << spareReprs->name() << "' of spare '" << elem->name() << "' must be gate or BE.");
36 std::set<size_t> module = {spareReprs->id()};
37 spareReprs->extendSpareModule(module);
38 std::set<size_t> sparesAndBes;
39 for (size_t modelem : module) {
40 if (mElements[modelem]->isSpareGate() || mElements[modelem]->isBasicElement()) {
41 sparesAndBes.insert(modelem);
42 }
43 }
44 mModules.insert(std::make_pair(spareReprs->id(), storm::dft::storage::DftModule(spareReprs->id(), sparesAndBes)));
45 }
46 } else if (elem->isDependency()) {
47 mDependencies.push_back(elem->id());
48 mDependencyInConflict.insert(std::make_pair(elem->id(), true));
49 }
50 }
51
52 // For the top module, we assume, contrary to [Jun15], that we have all spare gates and basic elements which are not in another module.
53 std::set<size_t> topModuleSet;
54 // Initialize with all ids.
55 for (auto const& elem : mElements) {
56 if (elem->isBasicElement() || elem->isSpareGate()) {
57 topModuleSet.insert(elem->id());
58 }
59 }
60 // Erase spare modules
61 for (auto const& module : mModules) {
62 for (auto const& index : module.second.getElements()) {
63 topModuleSet.erase(index);
64 }
65 }
66 // Extend top module and insert those elements which are part of the top module and a spare module
67 mElements[mTopLevelIndex]->extendSpareModule(topModuleSet);
68 storm::dft::storage::DftModule topModule(mTopLevelIndex, topModuleSet);
69
70 // Clear all spare modules where at least one element is also in the top module.
71 // These spare modules will be activated from the beginning.
72 if (!topModule.getElements().empty()) {
73 size_t topModuleId = *topModule.getElements().begin();
74 for (auto& module : mModules) {
75 auto& spareModule = module.second;
76 auto const& spareModuleElements = spareModule.getElements();
77 if (std::find(spareModuleElements.begin(), spareModuleElements.end(), topModuleId) != spareModuleElements.end()) {
78 STORM_LOG_WARN("Elements of spare module '"
79 << getElement(spareModule.getRepresentative())->name()
80 << "' also contained in top module. All elements of this spare module will be activated from the beginning on.");
81 spareModule.clear();
82 }
83 }
84 }
85 mModules.insert(std::make_pair(mTopLevelIndex, topModule));
86
87 // Set representants for all spare modules
88 for (auto const& module : mModules) {
89 if (module.first != mTopLevelIndex) {
90 for (auto const& index : module.second.getElements()) {
91 mRepresentants.insert(std::make_pair(index, module.first));
92 }
93 }
94 }
95
96 // Reserve space for failed spares
97 ++mMaxSpareChildCount;
98 mStateVectorSize = DFTStateGenerationInfo::getStateVectorSize(nrElements(), mNrOfSpares, mNrRepresentatives, mMaxSpareChildCount);
99
100 // Set relevant events: empty list corresponds to only setting the top-level event as relevant
101 setRelevantEvents({}, false);
103
104template<typename ValueType>
106 DFTStateGenerationInfo generationInfo(nrElements(), mNrOfSpares, mNrRepresentatives, mMaxSpareChildCount);
107
108 for (auto const& elem : mElements) {
109 // Check if BEs are immediately failed
110 if (elem->isBasicElement()) {
111 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType> const>(elem);
112 if ((be->beType() == storm::dft::storage::elements::BEType::CONSTANT && be->canFail()) ||
114 generationInfo.addImmediateFailedBE(be->id());
115 }
116 }
117 // Generate pre- and post-set info for restrictions, and mutexes
118 if (!elem->isDependency() && !elem->isRestriction()) {
119 // Ids of elements which are the direct predecessor in the list of children of a restriction
120 std::vector<size_t> seqRestrictionPres;
121 // Ids of elements which are the direct successor in the list of children of a restriction
122 std::vector<size_t> seqRestrictionPosts;
123 // Ids of elements which are under the same mutex
124 std::vector<size_t> mutexRestrictionElements;
125
126 for (auto const& restr : elem->restrictions()) {
127 if (restr->isSeqEnforcer()) {
128 auto it = restr->children().cbegin();
129 for (; it != restr->children().cend(); ++it) {
130 if ((*it)->id() == elem->id()) {
131 break;
132 }
133 }
134 STORM_LOG_ASSERT(it != restr->children().cend(), "Child " << elem->id() << " not found in restriction " << *restr);
135 // Add child following element in SEQ
136 ++it;
137 if (it != restr->children().cend()) {
138 seqRestrictionPosts.push_back((*it)->id());
139 }
140 // Add child before element in SEQ
141 --it;
142 if (it != restr->children().cbegin()) {
143 --it;
144 seqRestrictionPres.push_back((*it)->id());
145 }
146 } else {
147 STORM_LOG_ASSERT(restr->isMutex(), "Restriction " << *restr << " is neither SEQ nor MUTEX.");
148 bool found = false;
149 for (auto it = restr->children().cbegin(); it != restr->children().cend(); ++it) {
150 if ((*it)->id() != elem->id()) {
151 mutexRestrictionElements.push_back((*it)->id());
152 } else {
153 found = true;
154 }
155 }
156 STORM_LOG_ASSERT(found, "Child " << elem->id() << " is not included in restriction " << *restr);
157 }
158 }
159
160 generationInfo.setRestrictionPreElements(elem->id(), seqRestrictionPres);
161 generationInfo.setRestrictionPostElements(elem->id(), seqRestrictionPosts);
162 generationInfo.setMutexElements(elem->id(), mutexRestrictionElements);
163 }
164 }
165
166 size_t stateIndex = 0;
167 std::queue<size_t> visitQueue;
168 storm::storage::BitVector visited(nrElements(), false);
169
170 if (symmetries.nrSymmetries() == 0) {
171 // Perform DFS for whole tree
172 visitQueue.push(mTopLevelIndex);
173 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
174 } else {
175 // Generate information according to symmetries
176 for (size_t symmetryIndex : symmetries) {
177 STORM_LOG_ASSERT(!visited[symmetryIndex], "Element already considered for symmetry.");
178 auto const& symmetryGroup = symmetries.getSymmetryGroup(symmetryIndex);
179 STORM_LOG_ASSERT(!symmetryGroup.empty(), "No symmetry available.");
180
181 // Insert all elements of first subtree of each symmetry
182 size_t groupIndex = stateIndex;
183 for (std::vector<size_t> const& symmetryElement : symmetryGroup) {
184 if (visited[symmetryElement[0]]) {
185 groupIndex = std::min(groupIndex, generationInfo.getStateIndex(symmetryElement[0]));
186 } else {
187 stateIndex = generateStateInfo(generationInfo, symmetryElement[0], visited, stateIndex);
188 }
189 }
190 size_t offset = stateIndex - groupIndex;
191
192 // Mirror symmetries
193 size_t noSymmetricElements = symmetryGroup.front().size();
194 STORM_LOG_ASSERT(noSymmetricElements > 1, "No symmetry available.");
195
196 for (std::vector<size_t> symmetricElements : symmetryGroup) {
197 STORM_LOG_ASSERT(symmetricElements.size() == noSymmetricElements, "No. of symmetric elements do not coincide.");
198 if (visited[symmetricElements[1]]) {
199 // Elements already mirrored
200 for (size_t index : symmetricElements) {
201 STORM_LOG_ASSERT(visited[index], "Element not mirrored.");
202 }
203 continue;
204 }
205
206 // Initialize for original element
207 size_t originalElement = symmetricElements[0];
208 size_t index = generationInfo.getStateIndex(originalElement);
209 size_t activationIndex = isRepresentative(originalElement) ? generationInfo.getSpareActivationIndex(originalElement) : 0;
210 size_t usageIndex = mElements[originalElement]->isSpareGate() ? generationInfo.getSpareUsageIndex(originalElement) : 0;
211
212 // Mirror symmetry for each element
213 for (size_t i = 1; i < symmetricElements.size(); ++i) {
214 size_t symmetricElement = symmetricElements[i];
215 STORM_LOG_ASSERT(!visited[symmetricElement], "Symmetric element " << symmetricElement << " already considered before.");
216 visited.set(symmetricElement);
217
218 generationInfo.addStateIndex(symmetricElement, index + offset * i);
219 stateIndex += 2;
220
221 STORM_LOG_ASSERT((activationIndex > 0) == isRepresentative(symmetricElement), "Bits for representative incorrect.");
222 if (activationIndex > 0) {
223 generationInfo.addSpareActivationIndex(symmetricElement, activationIndex + offset * i);
224 ++stateIndex;
225 }
226
227 STORM_LOG_ASSERT((usageIndex > 0) == mElements[symmetricElement]->isSpareGate(), "Bits for usage incorrect.");
228 if (usageIndex > 0) {
229 generationInfo.addSpareUsageIndex(symmetricElement, usageIndex + offset * i);
230 stateIndex += generationInfo.usageInfoBits();
231 }
232 }
233 }
234
235 // Store starting indices of symmetry groups
236 std::vector<size_t> symmetryIndices;
237 for (size_t i = 0; i < noSymmetricElements; ++i) {
238 symmetryIndices.push_back(groupIndex + i * offset);
239 }
240 generationInfo.addSymmetry(offset, symmetryIndices);
241 }
242 }
244 // TODO symmetries in dependencies?
245 // Consider dependencies
246 for (size_t idDependency : getDependencies()) {
247 std::shared_ptr<storm::dft::storage::elements::DFTDependency<ValueType> const> dependency = getDependency(idDependency);
248 visitQueue.push(dependency->id());
249 visitQueue.push(dependency->triggerEvent()->id());
250 STORM_LOG_THROW(dependency->dependentEvents().size() == 1, storm::exceptions::NotSupportedException,
251 "Direct state generation does not support n-ary dependencies. Consider rewriting them by setting the binary dependency flag.");
252 visitQueue.push(dependency->dependentEvents()[0]->id());
253 }
254 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
255 STORM_LOG_ASSERT(visitQueue.empty(), "VisitQueue not empty");
256
257 // Visit all remaining states
258 for (size_t i = 0; i < visited.size(); ++i) {
259 if (!visited[i]) {
260 visitQueue.push(i);
261 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
262 }
263 }
264
265 generationInfo.generateSymmetries();
266
267 STORM_LOG_TRACE(generationInfo);
268 STORM_LOG_ASSERT(stateIndex == mStateVectorSize, "Id incorrect.");
269 STORM_LOG_ASSERT(visited.full(), "Not all elements considered.");
270 generationInfo.checkSymmetries();
271
272 return generationInfo;
273}
274
275template<typename ValueType>
276size_t DFT<ValueType>::generateStateInfo(DFTStateGenerationInfo& generationInfo, size_t id, storm::storage::BitVector& visited, size_t stateIndex) const {
277 STORM_LOG_ASSERT(!visited[id], "Element already visited.");
278 visited.set(id);
279
280 // Reserve bits for element
281 generationInfo.addStateIndex(id, stateIndex);
282 stateIndex += 2;
283
284 if (isRepresentative(id)) {
285 generationInfo.addSpareActivationIndex(id, stateIndex);
286 ++stateIndex;
287 }
288
289 if (mElements[id]->isSpareGate()) {
290 generationInfo.addSpareUsageIndex(id, stateIndex);
291 stateIndex += generationInfo.usageInfoBits();
292 }
293
294 return stateIndex;
295}
296
297template<typename ValueType>
298size_t DFT<ValueType>::performStateGenerationInfoDFS(DFTStateGenerationInfo& generationInfo, std::queue<size_t>& visitQueue, storm::storage::BitVector& visited,
299 size_t stateIndex) const {
300 while (!visitQueue.empty()) {
301 size_t id = visitQueue.front();
302 visitQueue.pop();
303 if (visited[id]) {
304 // Already visited
305 continue;
306 }
307 stateIndex = generateStateInfo(generationInfo, id, visited, stateIndex);
308
309 // Insert children
310 if (mElements[id]->isGate()) {
311 for (auto const& child : std::static_pointer_cast<storm::dft::storage::elements::DFTGate<ValueType>>(mElements[id])->children()) {
312 visitQueue.push(child->id());
314 }
316 return stateIndex;
318
319template<typename ValueType>
320std::vector<DFT<ValueType>> DFT<ValueType>::topModularisation() const {
321 STORM_LOG_ASSERT(isGate(mTopLevelIndex), "Top level element is no gate.");
322 auto const& children = getGate(mTopLevelIndex)->children();
323 std::map<size_t, std::vector<size_t>> subdfts;
324 for (auto const& child : children) {
325 std::vector<size_t> isubdft;
326 if (child->nrParents() > 1 || child->hasOutgoingDependencies() || child->hasRestrictions()) {
327 STORM_LOG_TRACE("child " << child->name() << " does not allow modularisation.");
328 return {*this};
330 if (isGate(child->id())) {
331 isubdft = getGate(child->id())->independentSubDft(false);
332 } else {
333 STORM_LOG_ASSERT(isBasicElement(child->id()), "Child is no BE.");
334 if (getBasicElement(child->id())->hasIngoingDependencies()) {
335 STORM_LOG_TRACE("child " << child->name() << " does not allow modularisation.");
336 return {*this};
337 } else {
338 isubdft = {child->id()};
339 }
340 }
341 if (isubdft.empty()) {
342 return {*this};
343 } else {
344 subdfts[child->id()] = isubdft;
345 }
346 }
347
348 std::vector<DFT<ValueType>> res;
349 for (auto const& subdft : subdfts) {
351
352 for (size_t id : subdft.second) {
353 builder.cloneElement(mElements[id]);
354 }
355 builder.setTopLevel(mElements[subdft.first]->name());
356 res.push_back(builder.build());
357 }
358 return res;
359}
360
361template<typename ValueType>
362uint64_t DFT<ValueType>::maxRank() const {
363 uint64_t max = 0;
364 for (auto const& e : mElements) {
365 if (e->rank() > max) {
366 max = e->rank();
367 }
369 return max;
370}
371
372template<typename ValueType>
374 std::vector<size_t> modIdea = findModularisationRewrite();
375 STORM_LOG_DEBUG("Modularisation idea: " << storm::utility::vector::toString(modIdea));
376
377 if (modIdea.empty()) {
378 // No rewrite needed
379 return *this;
380 }
381
382 std::vector<std::vector<size_t>> rewriteIds;
383 rewriteIds.push_back(modIdea);
384
386
387 // Accumulate elements which must be rewritten
388 std::set<size_t> rewriteSet;
389 for (std::vector<size_t> rewrites : rewriteIds) {
390 rewriteSet.insert(rewrites.front());
391 }
392 // Copy all other elements which do not change
393 for (auto elem : mElements) {
394 if (rewriteSet.count(elem->id()) == 0) {
395 builder.cloneElement(elem);
396 }
397 }
398
399 size_t uniqueIndex = 0; // Counter to ensure unique names
400 // Add rewritten elements
401 for (std::vector<size_t> rewrites : rewriteIds) {
402 STORM_LOG_ASSERT(rewrites.size() > 1, "No rewritten elements.");
403 STORM_LOG_ASSERT(mElements[rewrites[1]]->hasParents(), "Rewritten elements has no parents.");
404 STORM_LOG_ASSERT(mElements[rewrites[1]]->parents().front()->isGate(), "Rewritten element has no parent gate.");
405 DFTGatePointer originalParent = std::static_pointer_cast<storm::dft::storage::elements::DFTGate<ValueType>>(mElements[rewrites[0]]);
406 STORM_LOG_ASSERT(std::find_if(mElements[rewrites[1]]->parents().begin(), mElements[rewrites[1]]->parents().end(),
407 [&originalParent](std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>> const& p) {
408 return p->id() == originalParent->id();
409 }) != mElements[rewrites[1]]->parents().end(),
410 "Rewritten element has not the same parent");
411 std::string newParentName = originalParent->name() + "_" + std::to_string(++uniqueIndex);
412
413 // Accumulate children names
414 std::vector<std::string> childrenNames;
415 for (size_t i = 1; i < rewrites.size(); ++i) {
416 STORM_LOG_ASSERT(std::find_if(mElements[rewrites[i]]->parents().begin(), mElements[rewrites[i]]->parents().end(),
417 [&originalParent](std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>> const& p) {
418 return p->id() == originalParent->id();
419 }) != mElements[rewrites[i]]->parents().end(),
420 "Children have not the same father for rewrite " << mElements[rewrites[i]]->name());
421
422 childrenNames.push_back(mElements[rewrites[i]]->name());
423 }
424
425 // Add element in-between parent and children
426 switch (originalParent->type()) {
428 builder.addAndGate(newParentName, childrenNames);
429 break;
431 builder.addOrGate(newParentName, childrenNames);
432 break;
433 default:
434 // Other elements are not supported
435 STORM_LOG_ASSERT(false, "Dft type " << originalParent->type() << " can not be rewritten.");
436 break;
437 }
438
439 // Add parent with the new child newParent and all its remaining children
440 childrenNames.clear();
441 childrenNames.push_back(newParentName);
442 for (auto const& child : originalParent->children()) {
443 if (std::find(rewrites.begin() + 1, rewrites.end(), child->id()) == rewrites.end()) {
444 // Child was not rewritten and must be kept
445 childrenNames.push_back(child->name());
446 }
447 }
448 builder.cloneElementWithNewChildren(originalParent, childrenNames);
449 }
450
451 builder.setTopLevel(mElements[mTopLevelIndex]->name());
452 // TODO use reference?
453 DFT<ValueType> newDft = builder.build();
455 return newDft.optimize();
456}
457
458template<typename ValueType>
460 size_t noDyn = 0;
461 for (auto const& elem : mElements) {
462 switch (elem->type()) {
467 break;
474 noDyn += 1;
475 break;
476 default:
477 STORM_LOG_ASSERT(false, "DFT element type " << elem->type() << " not known.");
478 break;
479 }
480 }
481 return noDyn;
482}
483
484template<typename ValueType>
486 size_t noStatic = 0;
487 for (auto const& elem : mElements) {
488 switch (elem->type()) {
492 ++noStatic;
493 break;
501 break;
502 default:
503 STORM_LOG_ASSERT(false, "DFT element type " << elem->type() << " not known.");
504 break;
505 }
506 }
507 return noStatic;
508}
509
510template<typename ValueType>
512 std::stringstream stream;
513 for (auto const& elem : mElements) {
514 stream << "[" << elem->id() << "]" << *elem << '\n';
515 }
516 return stream.str();
517}
518
519template<typename ValueType>
520std::string DFT<ValueType>::getInfoString() const {
521 std::stringstream stream;
522 stream << "Top level index: " << mTopLevelIndex << ", Nr BEs" << mNrOfBEs;
523 return stream.str();
524}
525
526template<typename ValueType>
528 std::stringstream stream;
529 for (auto const& module : mModules) {
530 stream << module.second.toString(*this) << "\n";
531 }
532 return stream.str();
533}
534
535template<typename ValueType>
536std::string DFT<ValueType>::getElementsWithStateString(DFTStatePointer const& state) const {
537 std::stringstream stream;
538 for (auto const& elem : mElements) {
539 stream << "[" << elem->id() << "]";
540 stream << *elem;
541 if (elem->isDependency()) {
542 stream << "\t** " << storm::dft::storage::toChar(state->getDependencyState(elem->id())) << "[dep]";
543 } else {
544 stream << "\t** " << storm::dft::storage::toChar(state->getElementState(elem->id()));
545 if (elem->isSpareGate()) {
546 size_t useId = state->uses(elem->id());
547 if (useId == elem->id() || state->isActive(useId)) {
548 stream << "actively ";
549 }
550 stream << "using " << useId;
551 }
552 }
553 stream << '\n';
554 }
555 return stream.str();
556}
557
558template<typename ValueType>
559std::string DFT<ValueType>::getStateString(DFTStatePointer const& state) const {
560 std::stringstream stream;
561 stream << "(" << state->getId() << ") ";
562 for (auto const& elem : mElements) {
563 if (elem->isDependency()) {
564 stream << storm::dft::storage::toChar(state->getDependencyState(elem->id())) << "[dep]";
565 } else {
566 stream << storm::dft::storage::toChar(state->getElementState(elem->id()));
567 if (elem->isSpareGate()) {
568 stream << "[";
569 size_t useId = state->uses(elem->id());
570 if (useId == elem->id() || state->isActive(useId)) {
571 stream << "actively ";
572 }
573 stream << "using " << useId << "]";
574 }
575 }
576 }
577 return stream.str();
578}
579
580template<typename ValueType>
581std::string DFT<ValueType>::getStateString(storm::storage::BitVector const& status, DFTStateGenerationInfo const& stateGenerationInfo, size_t id) const {
582 std::stringstream stream;
583 stream << "(" << id << ") ";
584 for (auto const& elem : mElements) {
585 if (elem->isDependency()) {
586 stream << storm::dft::storage::toChar(DFTState<ValueType>::getDependencyState(status, stateGenerationInfo, elem->id())) << "[dep]";
587 } else {
588 stream << storm::dft::storage::toChar(DFTState<ValueType>::getElementState(status, stateGenerationInfo, elem->id()));
589 if (elem->isSpareGate()) {
590 stream << "[";
591 size_t useId = this->uses(status, stateGenerationInfo, elem->id());
592 if (useId == elem->id() || status[stateGenerationInfo.getSpareActivationIndex(useId)]) {
593 stream << "actively ";
594 }
595 stream << "using " << useId << "]";
596 }
597 }
598 }
599 return stream.str();
600}
601
602template<typename ValueType>
603size_t DFT<ValueType>::getChild(size_t spareId, size_t nrUsedChild) const {
604 STORM_LOG_ASSERT(mElements[spareId]->isSpareGate(), "Element is no spare.");
605 return getGate(spareId)->children()[nrUsedChild]->id();
606}
607
608template<typename ValueType>
609size_t DFT<ValueType>::getNrChild(size_t spareId, size_t childId) const {
610 STORM_LOG_ASSERT(mElements[spareId]->isSpareGate(), "Element is no spare.");
611 DFTElementVector children = getGate(spareId)->children();
612 for (size_t nrChild = 0; nrChild < children.size(); ++nrChild) {
613 if (children[nrChild]->id() == childId) {
614 return nrChild;
615 }
616 }
617 STORM_LOG_ASSERT(false, "Child not found.");
618 return 0;
619}
620
621template<typename ValueType>
622std::vector<size_t> DFT<ValueType>::immediateFailureCauses(size_t index) const {
623 if (isGate(index)) {
624 STORM_LOG_ASSERT(false, "Is gate.");
625 return {};
626 } else {
627 return {index};
628 }
629}
630
631template<typename ValueType>
633 return !getDependencies().empty();
634}
635
636template<typename ValueType>
637std::vector<size_t> DFT<ValueType>::findModularisationRewrite() const {
638 for (auto const& e : mElements) {
639 if (e->isGate() &&
641 // suitable parent gate! - Lets check the independent submodules of the children
642 auto const& children = std::static_pointer_cast<storm::dft::storage::elements::DFTGate<ValueType>>(e)->children();
643 for (auto const& child : children) {
644 auto ISD = std::static_pointer_cast<storm::dft::storage::elements::DFTGate<ValueType>>(child)->independentSubDft(true);
645 // In the ISD, check for other children:
646
647 std::vector<size_t> rewrite = {e->id(), child->id()};
648 for (size_t isdElemId : ISD) {
649 if (isdElemId == child->id())
650 continue;
651 if (std::find_if(children.begin(), children.end(),
652 [&isdElemId](std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>> const& e) {
653 return e->id() == isdElemId;
654 }) != children.end()) {
655 // element in subtree is also child
656 rewrite.push_back(isdElemId);
657 }
658 }
659 if (rewrite.size() > 2 && rewrite.size() < children.size() - 1) {
660 return rewrite;
661 }
662 }
663 }
664 }
665 return {};
666}
667
668template<typename ValueType>
669std::set<size_t> DFT<ValueType>::getAllIds() const {
670 std::set<size_t> ids;
671 for (auto const& elem : mElements) {
672 ids.insert(elem->id());
673 }
674 return ids;
675}
676
677template<typename ValueType>
678bool DFT<ValueType>::existsName(std::string const& name) const {
679 return std::find_if(mElements.begin(), mElements.end(), [&name](DFTElementPointer const& e) { return e->name() == name; }) != mElements.end();
680}
681
682template<typename ValueType>
683size_t DFT<ValueType>::getIndex(std::string const& name) const {
684 auto iter = std::find_if(mElements.begin(), mElements.end(), [&name](DFTElementPointer const& e) { return e->name() == name; });
685 STORM_LOG_THROW(iter != mElements.end(), storm::exceptions::InvalidArgumentException, "Event name '" << name << "' not known.");
686 return (*iter)->id();
687}
688
689template<typename ValueType>
690void DFT<ValueType>::setRelevantEvents(storm::dft::utility::RelevantEvents const& relevantEvents, bool const allowDCForRelevant) const {
691 mRelevantEvents.clear();
692 STORM_LOG_THROW(relevantEvents.checkRelevantNames(*this), storm::exceptions::InvalidArgumentException, "One of the relevant elements does not exist.");
693 // Top level element is first element
694 mRelevantEvents.push_back(this->getTopLevelIndex());
695 for (auto& elem : mElements) {
696 if (relevantEvents.isRelevant(elem->name()) || elem->id() == this->getTopLevelIndex()) {
697 elem->setRelevance(true);
698 elem->setAllowDC(allowDCForRelevant);
699 if (elem->id() != this->getTopLevelIndex()) {
700 // Top level element was already added
701 mRelevantEvents.push_back(elem->id());
702 }
703 } else {
704 elem->setRelevance(false);
705 elem->setAllowDC(true);
706 }
707 }
708}
709
710template<typename ValueType>
711std::vector<size_t> const& DFT<ValueType>::getRelevantEvents() const {
712 return mRelevantEvents;
713}
714
715template<typename ValueType>
717 std::stringstream stream;
718 bool first = true;
719 for (size_t relevant_id : getRelevantEvents()) {
720 if (first) {
721 first = false;
722 } else {
723 stream << ", ";
724 }
725 stream << getElement(relevant_id)->name() << " [" << relevant_id << "]";
726 }
727 return stream.str();
728}
729
730template<typename ValueType>
731void DFT<ValueType>::writeStatsToStream(std::ostream& stream) const {
732 // Count individual types of elements
733 size_t noBE = 0;
734 size_t noAnd = 0;
735 size_t noOr = 0;
736 size_t noVot = 0;
737 size_t noPand = 0;
738 size_t noPor = 0;
739 size_t noSpare = 0;
740 size_t noDependency = 0;
741 size_t noRestriction = 0;
742 for (auto const& elem : mElements) {
743 switch (elem->type()) {
745 ++noBE;
746 break;
748 ++noAnd;
749 break;
751 ++noOr;
752 break;
754 ++noVot;
755 break;
757 ++noPand;
758 break;
760 ++noPor;
761 break;
763 ++noSpare;
764 break;
766 ++noDependency;
767 break;
770 ++noRestriction;
771 break;
772 default:
773 STORM_LOG_ASSERT(false, "DFT element type " << elem->type() << " not known.");
774 break;
775 }
776 }
777 size_t noStatic = nrStaticElements();
778 size_t noDynamic = nrDynamicElements();
779
780 // Check whether numbers are correct
781 STORM_LOG_ASSERT(noBE == nrBasicElements(), "No. of BEs does not match.");
782 STORM_LOG_ASSERT(noSpare == mNrOfSpares, "No. of SPAREs does not match.");
783 STORM_LOG_ASSERT(noDependency == mDependencies.size(), "No. of Dependencies does not match.");
784 STORM_LOG_ASSERT(noAnd + noOr + noVot == noStatic, "No. of static gates does not match.");
785 STORM_LOG_ASSERT(noPand + noPor + noSpare + noDependency + noRestriction == noDynamic, "No. of dynamic gates does not match.");
786 STORM_LOG_ASSERT(noBE + noStatic + noDynamic == nrElements(), "No. of elements does not match.");
787
788 // Print output
789 stream << "=============DFT Statistics==============\n";
790 stream << "Number of BEs: " << nrBasicElements() << '\n';
791 stream << "Number of static elements: " << noStatic << '\n';
792 stream << "Number of dynamic elements: " << noDynamic << '\n';
793 stream << "Number of elements: " << nrElements() << '\n';
794 stream << "-----------------------------------------\n";
795 if (noBE > 0) {
796 stream << "Number of BEs: " << noBE << '\n';
797 }
798 if (noAnd > 0) {
799 stream << "Number of AND gates: " << noAnd << '\n';
800 }
801 if (noOr > 0) {
802 stream << "Number of OR gates: " << noOr << '\n';
803 }
804 if (noVot > 0) {
805 stream << "Number of VOT gates: " << noVot << '\n';
806 }
807 if (noPand > 0) {
808 stream << "Number of PAND gates: " << noPand << '\n';
809 }
810 if (noPor > 0) {
811 stream << "Number of POR gates: " << noPor << '\n';
812 }
813 if (noSpare > 0) {
814 stream << "Number of SPARE gates: " << noSpare << '\n';
815 }
816 if (noDependency > 0) {
817 stream << "Number of Dependencies: " << noDependency << '\n';
818 }
819 if (noRestriction > 0) {
820 stream << "Number of Restrictions: " << noRestriction << '\n';
821 }
822 stream << "=========================================\n";
823}
824
825std::set<storm::RationalFunctionVariable> getParameters(DFT<storm::RationalFunction> const& dft) {
826 std::set<storm::RationalFunctionVariable> result;
827 for (size_t i = 0; i < dft.nrElements(); ++i) {
828 std::shared_ptr<storm::dft::storage::elements::DFTElement<storm::RationalFunction> const> element = dft.getElement(i);
829 switch (element->type()) {
831 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<storm::RationalFunction> const>(element);
833 auto beExp = std::static_pointer_cast<storm::dft::storage::elements::BEExponential<storm::RationalFunction> const>(element);
834 beExp->activeFailureRate().gatherVariables(result);
835 beExp->dormancyFactor().gatherVariables(result);
836 }
837 break;
838 }
840 auto dep = std::static_pointer_cast<storm::dft::storage::elements::DFTDependency<storm::RationalFunction> const>(element);
841 dep->probability().gatherVariables(result);
842 break;
843 }
852 // Do nothing
853 break;
854 default:
855 STORM_LOG_THROW(false, storm::exceptions::NotImplementedException, "DFT type '" << element->type() << "' not known.");
856 }
857 }
858 return result;
859}
860
861// Explicitly instantiate the class.
862template class DFT<double>;
863template class DFT<RationalFunction>;
864
865} // namespace storage
866} // namespace storm::dft
void addOrGate(std::string const &name, std::vector< std::string > const &children)
Create OR-gate and add it to DFT.
storm::dft::storage::DFT< ValueType > build()
Create DFT.
void addAndGate(std::string const &name, std::vector< std::string > const &children)
Create AND-gate and add it to DFT.
void cloneElement(DFTElementCPointer element)
Clone element and add it via the builder.
void setTopLevel(std::string const &tle)
Set top level element.
void cloneElementWithNewChildren(DFTChildrenCPointer elemWithChildren, std::vector< std::string > const &children)
Clone element, replace its children with the given children and add it via the builder.
Represents a Dynamic Fault Tree.
Definition DFT.h:52
bool isRepresentative(size_t id) const
Definition DFT.h:249
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
Definition DFT.h:188
size_t nrElements() const
Definition DFT.h:94
DFT(DFTElementVector const &elements, DFTElementPointer const &tle)
Definition DFT.cpp:17
std::string getElementsString() const
Definition DFT.cpp:511
storm::dft::storage::DftModule const & module(size_t representativeId) const
Definition DFT.h:128
DFT< ValueType > optimize() const
Definition DFT.cpp:373
void addSpareActivationIndex(size_t id, size_t index)
void generateSymmetries()
Generate more symmetries by combining two symmetries.
void setRestrictionPostElements(size_t id, std::vector< size_t > const &elems)
void setRestrictionPreElements(size_t id, std::vector< size_t > const &elems)
void addSymmetry(size_t length, std::vector< size_t > &startingIndices)
void setMutexElements(size_t id, std::vector< size_t > const &elems)
Represents a module/subtree in a DFT.
Definition DftModule.h:18
std::vector< std::vector< size_t > > const & getSymmetryGroup(size_t index) const
Get symmetry group corresponding to give top level index.
Abstract base class for DFT elements.
Definition DFTElement.h:39
bool checkRelevantNames(storm::dft::storage::DFT< ValueType > const &dft) const
Check that the relevant names correspond to existing elements in the DFT.
bool isRelevant(std::string const &name) const
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
bool full() const
Retrieves whether all bits are set in this bit vector.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
#define STORM_LOG_WARN(message)
Definition logging.h:30
#define STORM_LOG_DEBUG(message)
Definition logging.h:23
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
char toChar(DFTElementState st)
std::set< storm::RationalFunctionVariable > getParameters(DFT< storm::RationalFunction > const &dft)
Get all rate/probability parameters occurring in the DFT.
Definition DFT.cpp:825
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.
Definition vector.h:1298
LabParser.cpp.
Definition cli.cpp:18