106 DFTStateGenerationInfo generationInfo(nrElements(), mNrOfSpares, mNrRepresentatives, mMaxSpareChildCount);
108 for (
auto const& elem : mElements) {
110 if (elem->isBasicElement()) {
111 auto be = std::static_pointer_cast<storm::dft::storage::elements::DFTBE<ValueType>
const>(elem);
118 if (!elem->isDependency() && !elem->isRestriction()) {
120 std::vector<size_t> seqRestrictionPres;
122 std::vector<size_t> seqRestrictionPosts;
124 std::vector<size_t> mutexRestrictionElements;
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()) {
134 STORM_LOG_ASSERT(it != restr->children().cend(),
"Child " << elem->id() <<
" not found in restriction " << *restr);
137 if (it != restr->children().cend()) {
138 seqRestrictionPosts.push_back((*it)->id());
142 if (it != restr->children().cbegin()) {
144 seqRestrictionPres.push_back((*it)->id());
147 STORM_LOG_ASSERT(restr->isMutex(),
"Restriction " << *restr <<
" is neither SEQ nor MUTEX.");
149 for (
auto it = restr->children().cbegin(); it != restr->children().cend(); ++it) {
150 if ((*it)->id() != elem->id()) {
151 mutexRestrictionElements.push_back((*it)->id());
156 STORM_LOG_ASSERT(found,
"Child " << elem->id() <<
" is not included in restriction " << *restr);
166 size_t stateIndex = 0;
167 std::queue<size_t> visitQueue;
172 visitQueue.push(mTopLevelIndex);
173 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
176 for (
size_t symmetryIndex : symmetries) {
177 STORM_LOG_ASSERT(!visited[symmetryIndex],
"Element already considered for 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]));
187 stateIndex = generateStateInfo(generationInfo, symmetryElement[0], visited, stateIndex);
190 size_t offset = stateIndex - groupIndex;
193 size_t noSymmetricElements = symmetryGroup.front().size();
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]]) {
200 for (
size_t index : symmetricElements) {
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;
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);
218 generationInfo.
addStateIndex(symmetricElement, index + offset * i);
221 STORM_LOG_ASSERT((activationIndex > 0) == isRepresentative(symmetricElement),
"Bits for representative incorrect.");
222 if (activationIndex > 0) {
227 STORM_LOG_ASSERT((usageIndex > 0) == mElements[symmetricElement]->isSpareGate(),
"Bits for usage incorrect.");
228 if (usageIndex > 0) {
236 std::vector<size_t> symmetryIndices;
237 for (
size_t i = 0; i < noSymmetricElements; ++i) {
238 symmetryIndices.push_back(groupIndex + i * offset);
240 generationInfo.
addSymmetry(offset, symmetryIndices);
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());
254 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
258 for (
size_t i = 0; i < visited.
size(); ++i) {
261 stateIndex = performStateGenerationInfoDFS(generationInfo, visitQueue, visited, stateIndex);
272 return generationInfo;
275template<
typename ValueType>
284 if (isRepresentative(
id)) {
289 if (mElements[
id]->isSpareGate()) {
297template<
typename ValueType>
299 size_t stateIndex)
const {
300 while (!visitQueue.empty()) {
301 size_t id = visitQueue.front();
307 stateIndex = generateStateInfo(generationInfo,
id, visited, stateIndex);
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());
319template<
typename ValueType>
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.");
330 if (isGate(child->id())) {
331 isubdft = getGate(child->id())->independentSubDft(
false);
334 if (getBasicElement(child->id())->hasIngoingDependencies()) {
338 isubdft = {child->id()};
341 if (isubdft.empty()) {
344 subdfts[child->id()] = isubdft;
348 std::vector<DFT<ValueType>> res;
349 for (
auto const& subdft : subdfts) {
352 for (
size_t id : subdft.second) {
356 res.push_back(builder.
build());
361template<
typename ValueType>
364 for (
auto const& e : mElements) {
365 if (e->rank() > max) {
372template<
typename ValueType>
374 std::vector<size_t> modIdea = findModularisationRewrite();
377 if (modIdea.empty()) {
382 std::vector<std::vector<size_t>> rewriteIds;
383 rewriteIds.push_back(modIdea);
388 std::set<size_t> rewriteSet;
389 for (std::vector<size_t> rewrites : rewriteIds) {
390 rewriteSet.insert(rewrites.front());
393 for (
auto elem : mElements) {
394 if (rewriteSet.count(elem->id()) == 0) {
399 size_t uniqueIndex = 0;
401 for (std::vector<size_t> rewrites : rewriteIds) {
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(),
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);
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(),
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());
422 childrenNames.push_back(mElements[rewrites[i]]->name());
426 switch (originalParent->type()) {
428 builder.
addAndGate(newParentName, childrenNames);
431 builder.
addOrGate(newParentName, childrenNames);
435 STORM_LOG_ASSERT(
false,
"Dft type " << originalParent->type() <<
" can not be rewritten.");
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()) {
445 childrenNames.push_back(child->name());
451 builder.
setTopLevel(mElements[mTopLevelIndex]->name());
458template<
typename ValueType>
461 for (
auto const& elem : mElements) {
462 switch (elem->type()) {
477 STORM_LOG_ASSERT(
false,
"DFT element type " << elem->type() <<
" not known.");
484template<
typename ValueType>
487 for (
auto const& elem : mElements) {
488 switch (elem->type()) {
503 STORM_LOG_ASSERT(
false,
"DFT element type " << elem->type() <<
" not known.");
510template<
typename ValueType>
512 std::stringstream stream;
513 for (
auto const& elem : mElements) {
514 stream <<
"[" << elem->id() <<
"]" << *elem <<
'\n';
519template<
typename ValueType>
521 std::stringstream stream;
522 stream <<
"Top level index: " << mTopLevelIndex <<
", Nr BEs" << mNrOfBEs;
526template<
typename ValueType>
528 std::stringstream stream;
529 for (
auto const& module : mModules) {
530 stream <<
module.second.toString(*this) << "\n";
535template<
typename ValueType>
537 std::stringstream stream;
538 for (
auto const& elem : mElements) {
539 stream <<
"[" << elem->id() <<
"]";
541 if (elem->isDependency()) {
545 if (elem->isSpareGate()) {
546 size_t useId = state->uses(elem->id());
547 if (useId == elem->id() || state->isActive(useId)) {
548 stream <<
"actively ";
550 stream <<
"using " << useId;
558template<
typename ValueType>
560 std::stringstream stream;
561 stream <<
"(" << state->getId() <<
") ";
562 for (
auto const& elem : mElements) {
563 if (elem->isDependency()) {
567 if (elem->isSpareGate()) {
569 size_t useId = state->uses(elem->id());
570 if (useId == elem->id() || state->isActive(useId)) {
571 stream <<
"actively ";
573 stream <<
"using " << useId <<
"]";
580template<
typename ValueType>
582 std::stringstream stream;
583 stream <<
"(" <<
id <<
") ";
584 for (
auto const& elem : mElements) {
585 if (elem->isDependency()) {
589 if (elem->isSpareGate()) {
591 size_t useId = this->uses(status, stateGenerationInfo, elem->id());
593 stream <<
"actively ";
595 stream <<
"using " << useId <<
"]";
602template<
typename ValueType>
604 STORM_LOG_ASSERT(mElements[spareId]->isSpareGate(),
"Element is no spare.");
605 return getGate(spareId)->children()[nrUsedChild]->id();
608template<
typename ValueType>
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) {
621template<
typename ValueType>
631template<
typename ValueType>
633 return !getDependencies().empty();
636template<
typename ValueType>
638 for (
auto const& e : mElements) {
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);
647 std::vector<size_t> rewrite = {e->id(), child->id()};
648 for (
size_t isdElemId : ISD) {
649 if (isdElemId == child->id())
651 if (std::find_if(children.begin(), children.end(),
653 return e->id() == isdElemId;
654 }) != children.end()) {
656 rewrite.push_back(isdElemId);
659 if (rewrite.size() > 2 && rewrite.size() < children.size() - 1) {
668template<
typename ValueType>
670 std::set<size_t> ids;
671 for (
auto const& elem : mElements) {
672 ids.insert(elem->id());
677template<
typename ValueType>
679 return std::find_if(mElements.begin(), mElements.end(), [&name](DFTElementPointer
const& e) { return e->name() == name; }) != mElements.end();
682template<
typename ValueType>
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();
689template<
typename ValueType>
691 mRelevantEvents.clear();
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()) {
701 mRelevantEvents.push_back(elem->id());
704 elem->setRelevance(
false);
705 elem->setAllowDC(
true);
710template<
typename ValueType>
712 return mRelevantEvents;
715template<
typename ValueType>
717 std::stringstream stream;
719 for (
size_t relevant_id : getRelevantEvents()) {
725 stream << getElement(relevant_id)->name() <<
" [" << relevant_id <<
"]";
730template<
typename ValueType>
740 size_t noDependency = 0;
741 size_t noRestriction = 0;
742 for (
auto const& elem : mElements) {
743 switch (elem->type()) {
773 STORM_LOG_ASSERT(
false,
"DFT element type " << elem->type() <<
" not known.");
777 size_t noStatic = nrStaticElements();
778 size_t noDynamic = nrDynamicElements();
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.");
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";
796 stream <<
"Number of BEs: " << noBE <<
'\n';
799 stream <<
"Number of AND gates: " << noAnd <<
'\n';
802 stream <<
"Number of OR gates: " << noOr <<
'\n';
805 stream <<
"Number of VOT gates: " << noVot <<
'\n';
808 stream <<
"Number of PAND gates: " << noPand <<
'\n';
811 stream <<
"Number of POR gates: " << noPor <<
'\n';
814 stream <<
"Number of SPARE gates: " << noSpare <<
'\n';
816 if (noDependency > 0) {
817 stream <<
"Number of Dependencies: " << noDependency <<
'\n';
819 if (noRestriction > 0) {
820 stream <<
"Number of Restrictions: " << noRestriction <<
'\n';
822 stream <<
"=========================================\n";
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);
840 auto dep = std::static_pointer_cast<storm::dft::storage::elements::DFTDependency<storm::RationalFunction>
const>(element);
841 dep->probability().gatherVariables(result);
855 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"DFT type '" << element->type() <<
"' not known.");
862template class DFT<double>;
863template class DFT<RationalFunction>;