16template<
typename ValueType>
18 : mElements(
elements), mNrOfBEs(0), mNrOfSpares(0), mNrRepresentatives(0), mTopLevelIndex(tle->id()), mMaxSpareChildCount(0) {
22 for (
auto& elem : mElements) {
26 if (elem->isBasicElement()) {
28 }
else if (elem->isSpareGate()) {
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);
46 }
else if (elem->isDependency()) {
47 mDependencies.push_back(elem->id());
48 mDependencyInConflict.insert(std::make_pair(elem->id(),
true));
53 std::set<size_t> topModuleSet;
55 for (
auto const& elem : mElements) {
56 if (elem->isBasicElement() || elem->isSpareGate()) {
57 topModuleSet.insert(elem->id());
61 for (
auto const&
module : mModules) {
62 for (
auto const& index :
module.second.getElements()) {
63 topModuleSet.erase(index);
67 mElements[mTopLevelIndex]->extendSpareModule(topModuleSet);
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()) {
82 mModules.insert(std::make_pair(mTopLevelIndex, topModule));
85 for (
auto const&
module : mModules) {
86 if (
module.first != mTopLevelIndex) {
87 for (
auto const& index :
module.second.getElements()) {
88 mRepresentants.insert(std::make_pair(index,
module.first));
94 ++mMaxSpareChildCount;
104template<
typename ValueType>
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);
176 for (
size_t symmetryIndex : symmetries) {
177 STORM_LOG_ASSERT(!visited[symmetryIndex],
"Element already considered for symmetry.");
178 auto const& symmetryGroup = symmetries.getSymmetryGroup(symmetryIndex);
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);
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);
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);
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());
258 for (
size_t i = 0; i < visited.
size(); ++i) {
272 return generationInfo;
275template<
typename ValueType>
289 if (mElements[
id]->isSpareGate()) {
297template<
typename ValueType>
299 size_t stateIndex)
const {
300 while (!visitQueue.empty()) {
301 size_t id = visitQueue.front();
310 if (mElements[
id]->
isGate()) {
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.");
331 isubdft =
getGate(child->id())->independentSubDft(
false);
335 STORM_LOG_TRACE(
"child " << child->name() <<
" does not allow modularisation.");
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) {
353 builder.cloneElement(mElements[
id]);
355 builder.setTopLevel(mElements[subdft.first]->name());
356 res.push_back(
builder.build());
361template<
typename ValueType>
364 for (
auto const& e : mElements) {
365 if (e->rank() > max) {
372template<
typename ValueType>
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());
455 return newDft.optimize();
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>
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 element->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();
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;
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.");
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.");
789 stream <<
"=============DFT Statistics==============\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>;
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 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.
size_t nrBasicElements() const
size_t getTopLevelIndex() const
bool isRepresentative(size_t id) const
std::string getRelevantEventsString() const
Get a string containing the list of all relevant events.
std::shared_ptr< storm::dft::storage::elements::DFTDependency< ValueType > const > getDependency(size_t index) const
void setRelevantEvents(storm::dft::utility::RelevantEvents const &relevantEvents, bool const allowDCForRelevant) const
Set the relevance flag for all elements according to the given relevant events.
std::shared_ptr< storm::dft::storage::elements::DFTBE< ParametricType > const > getBasicElement(size_t index) const
size_t nrDynamicElements() const
size_t getNrChild(size_t spareId, size_t childId) const
std::string getModulesString() const
std::set< size_t > getAllIds() const
Get Ids of all elements.
std::vector< size_t > findModularisationRewrite() const
DFTElementCPointer getElement(size_t index) const
Get a pointer to an element in the DFT.
void writeStatsToStream(std::ostream &stream) const
std::string getElementsWithStateString(DFTStatePointer const &state) const
std::vector< size_t > const & getDependencies() const
bool existsName(std::string const &name) const
Check whether an element with the given name exists.
size_t nrElements() const
std::shared_ptr< storm::dft::storage::elements::DFTGate< ParametricType > const > getGate(size_t index) const
std::string getStateString(DFTStatePointer const &state) const
size_t uses(storm::storage::BitVector const &state, DFTStateGenerationInfo const &stateGenerationInfo, size_t id) const
Return id of used child for a given spare gate.
std::string getInfoString() const
size_t generateStateInfo(DFTStateGenerationInfo &generationInfo, size_t id, storm::storage::BitVector &visited, size_t stateIndex) const
DFTStateGenerationInfo buildStateGenerationInfo(storm::dft::storage::DftSymmetries const &symmetries) const
bool isGate(size_t index) const
DFT(DFTElementVector const &elements, DFTElementPointer const &tle)
size_t nrStaticElements() const
std::vector< size_t > const & getRelevantEvents() const
Get all relevant events.
size_t getIndex(std::string const &name) const
Get id for the given element name.
size_t performStateGenerationInfoDFS(DFTStateGenerationInfo &generationInfo, std::queue< size_t > &visitQueue, storm::storage::BitVector &visited, size_t stateIndex) const
bool canHaveNondeterminism() const
std::vector< size_t > immediateFailureCauses(size_t index) const
size_t getChild(size_t spareId, size_t nrUsedChild) const
std::string getElementsString() const
storm::dft::storage::DftModule const & module(size_t representativeId) const
std::vector< DFT< ValueType > > topModularisation() const
DFT< ValueType > optimize() const
bool isBasicElement(size_t index) const
static size_t getStateVectorSize(size_t nrElements, size_t nrOfSpares, size_t nrRepresentatives, size_t maxSpareChildCount)
Get length of BitVector capturing DFT state.
size_t getStateIndex(size_t id) const
size_t getSpareActivationIndex(size_t id) const
size_t getSpareUsageIndex(size_t id) const
void addImmediateFailedBE(size_t id)
void addSpareActivationIndex(size_t id, size_t index)
size_t usageInfoBits() const
void generateSymmetries()
Generate more symmetries by combining two symmetries.
void setRestrictionPostElements(size_t id, std::vector< size_t > const &elems)
void addStateIndex(size_t id, size_t index)
void setRestrictionPreElements(size_t id, std::vector< size_t > const &elems)
void addSymmetry(size_t length, std::vector< size_t > &startingIndices)
void addSpareUsageIndex(size_t id, size_t index)
void setMutexElements(size_t id, std::vector< size_t > const &elems)
DFTDependencyState getDependencyState(size_t id) const
DFTElementState getElementState(size_t id) const
Represents a module/subtree in a DFT.
std::set< size_t > const & getElements() const
Return elements of module.
size_t nrSymmetries() const
Abstract base class for DFT elements.
Abstract base class for gates.
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.
bool full() const
Retrieves whether all bits are set in this bit vector.
void set(uint64_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_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
char toChar(DFTElementState st)
std::set< storm::RationalFunctionVariable > getParameters(DFT< storm::RationalFunction > const &dft)
Get all rate/probability parameters occurring in the DFT.
std::string toString(std::vector< ValueType > const &vector)
Output vector as string.