|
|
@ -17,12 +17,15 @@ namespace storm { |
|
|
|
namespace storage { |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
DFT<ValueType>::DFT(DFTElementVector const &elements, DFTElementPointer const &tle, |
|
|
|
std::vector<bool> const &dynamicBehavior) : |
|
|
|
mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()), mMaxSpareChildCount(0), |
|
|
|
mDynamicBehavior(dynamicBehavior) { |
|
|
|
DFT<ValueType>::DFT(DFTElementVector const &elements, DFTElementPointer const &tle) : |
|
|
|
mElements(elements), mNrOfBEs(0), mNrOfSpares(0), mTopLevelIndex(tle->id()), mMaxSpareChildCount(0) { |
|
|
|
// Check that ids correspond to indices in the element vector
|
|
|
|
STORM_LOG_ASSERT(elementIndicesCorrect(), "Ids incorrect."); |
|
|
|
|
|
|
|
// Initialize dynamic behavior vector with TRUE to preserve correct behavior
|
|
|
|
// We don't directly call setDynamicBehaviorInfo to not slow down DFT generation if possible
|
|
|
|
mDynamicBehavior = std::vector<bool>(mElements.size()); |
|
|
|
std::fill(mDynamicBehavior.begin(), mDynamicBehavior.end(), true); |
|
|
|
size_t nrRepresentatives = 0; |
|
|
|
|
|
|
|
for (auto& elem : mElements) { |
|
|
@ -88,6 +91,151 @@ namespace storm { |
|
|
|
mStateVectorSize = nrElements() * 2 + mNrOfSpares * usageInfoBits + nrRepresentatives; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
void DFT<ValueType>::setDynamicBehaviorInfo() { |
|
|
|
std::vector<bool> dynamicBehaviorVector(mElements.size()); |
|
|
|
|
|
|
|
std::queue <DFTElementPointer> elementQueue; |
|
|
|
|
|
|
|
// deal with all dynamic elements
|
|
|
|
for (auto const &element : mElements) { |
|
|
|
switch (element->type()) { |
|
|
|
case storage::DFTElementType::PAND: |
|
|
|
case storage::DFTElementType::POR: |
|
|
|
case storage::DFTElementType::MUTEX: { |
|
|
|
auto gate = std::static_pointer_cast<storm::storage::DFTChildren<ValueType>>(element); |
|
|
|
dynamicBehaviorVector[gate->id()] = true; |
|
|
|
for (auto const &child : gate->children()) { |
|
|
|
// only enqueue static children
|
|
|
|
if (!dynamicBehaviorVector.at(child->id())) { |
|
|
|
elementQueue.push(child); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
// TODO different cases
|
|
|
|
case storage::DFTElementType::SPARE: { |
|
|
|
auto spare = std::static_pointer_cast<storm::storage::DFTSpare<ValueType>>(element); |
|
|
|
|
|
|
|
// Iterate over all children (representatives of spare modules)
|
|
|
|
for (auto const &child : spare->children()) { |
|
|
|
// Case 1: Shared Module
|
|
|
|
// If child only has one parent, it is this SPARE -> nothing to check
|
|
|
|
if (child->nrParents() > 1) { |
|
|
|
// TODO make more efficient by directly setting ALL spares which share a module to be dynamic
|
|
|
|
for (auto const &parent : child->parents()) { |
|
|
|
if (parent->isSpareGate() and parent->id() != spare->id()) { |
|
|
|
dynamicBehaviorVector[spare->id()] = true; |
|
|
|
break; // inner loop
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
// Case 2: Triggering outside events
|
|
|
|
// If the SPARE was already detected to have dynamic behavior, do not proceed
|
|
|
|
if (!dynamicBehaviorVector[spare->id()]) { |
|
|
|
for (auto const &memberID : module(child->id())) { |
|
|
|
// Iterate over all members of the module child represents
|
|
|
|
auto member = getElement(memberID); |
|
|
|
for (auto const dep : member->outgoingDependencies()) { |
|
|
|
// If the member has outgoing dependencies, check if those trigger something outside the module
|
|
|
|
for (auto const depEvent : dep->dependentEvents()) { |
|
|
|
// If a dependent event is not found in the module, SPARE is dynamic
|
|
|
|
if (std::find(module(child->id()).begin(), module(child->id()).end(), |
|
|
|
depEvent->id()) == module(child->id()).end()) { |
|
|
|
dynamicBehaviorVector[spare->id()] = true; |
|
|
|
break; //depEvent-loop
|
|
|
|
} |
|
|
|
} |
|
|
|
if (dynamicBehaviorVector[spare->id()]) { break; } //dependency-loop
|
|
|
|
} |
|
|
|
if (dynamicBehaviorVector[spare->id()]) { break; } //module-loop
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
if (dynamicBehaviorVector[spare->id()]) { break; } //child-loop
|
|
|
|
} |
|
|
|
// if during the computation, dynamic behavior was detected, add children to queue
|
|
|
|
if (dynamicBehaviorVector[spare->id()]) { |
|
|
|
for (auto const &child : spare->children()) { |
|
|
|
// only enqueue static children
|
|
|
|
if (!dynamicBehaviorVector.at(child->id())) { |
|
|
|
elementQueue.push(child); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
case storage::DFTElementType::SEQ: { |
|
|
|
auto seq = std::static_pointer_cast<storm::storage::DFTSeq<ValueType>>(element); |
|
|
|
// A SEQ only has dynamic behavior if not all children are BEs
|
|
|
|
if (!seq->allChildrenBEs()) { |
|
|
|
dynamicBehaviorVector[seq->id()] = true; |
|
|
|
for (auto const &child : seq->children()) { |
|
|
|
// only enqueue static children
|
|
|
|
if (!dynamicBehaviorVector.at(child->id())) { |
|
|
|
elementQueue.push(child); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
default: { |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
// propagate dynamic behavior
|
|
|
|
while (!elementQueue.empty()) { |
|
|
|
DFTElementPointer currentElement = elementQueue.front(); |
|
|
|
elementQueue.pop(); |
|
|
|
switch (currentElement->type()) { |
|
|
|
// Static Gates
|
|
|
|
case storage::DFTElementType::AND: |
|
|
|
case storage::DFTElementType::OR: |
|
|
|
case storage::DFTElementType::VOT: { |
|
|
|
// check all parents and if one has dynamic behavior, propagate it
|
|
|
|
dynamicBehaviorVector[currentElement->id()] = true; |
|
|
|
auto gate = std::static_pointer_cast<storm::storage::DFTGate<ValueType>>(currentElement); |
|
|
|
for (auto const &child : gate->children()) { |
|
|
|
// only enqueue static children
|
|
|
|
if (!dynamicBehaviorVector.at(child->id())) { |
|
|
|
elementQueue.push(child); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
//BEs
|
|
|
|
case storage::DFTElementType::BE_EXP: |
|
|
|
case storage::DFTElementType::BE_CONST: |
|
|
|
case storage::DFTElementType::BE: { |
|
|
|
auto be = std::static_pointer_cast<storm::storage::DFTBE<ValueType>>(currentElement); |
|
|
|
dynamicBehaviorVector[be->id()] = true; |
|
|
|
// add all ingoing dependencies to queue
|
|
|
|
for (auto const &dep : be->ingoingDependencies()) { |
|
|
|
if (!dynamicBehaviorVector.at(dep->id())) { |
|
|
|
elementQueue.push(dep); |
|
|
|
} |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
case storage::DFTElementType::PDEP: { |
|
|
|
auto dep = std::static_pointer_cast<storm::storage::DFTDependency<ValueType>>(currentElement); |
|
|
|
dynamicBehaviorVector[dep->id()] = true; |
|
|
|
// add all ingoing dependencies to queue
|
|
|
|
auto trigger = dep->triggerEvent(); |
|
|
|
if (!dynamicBehaviorVector.at(trigger->id())) { |
|
|
|
elementQueue.push(trigger); |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
default: |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
mDynamicBehavior = dynamicBehaviorVector; |
|
|
|
} |
|
|
|
|
|
|
|
template<typename ValueType> |
|
|
|
DFTStateGenerationInfo DFT<ValueType>::buildStateGenerationInfo(storm::storage::DFTIndependentSymmetries const& symmetries) const { |
|
|
|
DFTStateGenerationInfo generationInfo(nrElements(), mMaxSpareChildCount); |