22template<
typename ValueType,
typename StateType>
23ExplicitDFTModelBuilder<ValueType, StateType>::ModelComponents::ModelComponents()
24 : transitionMatrix(), stateLabeling(), markovianStates(), exitRates(), choiceLabeling() {
28template<
typename ValueType,
typename StateType>
29ExplicitDFTModelBuilder<ValueType, StateType>::MatrixBuilder::MatrixBuilder(
bool canHaveNondeterminism)
30 : mappingOffset(0), stateRemapping(), currentRowGroup(0), currentRow(0), canHaveNondeterminism((canHaveNondeterminism)) {
35template<
typename ValueType,
typename StateType>
39 stateGenerationInfo(
std::make_shared<
storm::dft::storage::DFTStateGenerationInfo>(dft.buildStateGenerationInfo(symmetries))),
40 generator(dft, *stateGenerationInfo),
41 matrixBuilder(!generator.isDeterministicModel()),
42 stateStorage(dft.stateBitVectorSize()),
43 explorationQueue(1, 0, 0.9, false) {
49 this->uniqueFailedState =
true;
58 std::vector<size_t> isubdft;
59 if (child->nrParents() > 1 || child->hasOutgoingDependencies()) {
60 STORM_LOG_TRACE(
"child " << child->name() <<
" does not allow modularisation.");
62 }
else if (dft.
isGate(child->id())) {
63 isubdft = dft.
getGate(child->id())->independentSubDft(
false);
67 STORM_LOG_TRACE(
"child " << child->name() <<
" does not allow modularisation.");
70 isubdft = {child->id()};
73 if (isubdft.empty()) {
78 std::vector<size_t> subtree;
79 for (
size_t id : isubdft) {
81 subtree.push_back(
id);
84 subtreeBEs.push_back(subtree);
88 if (subtreeBEs.empty()) {
90 std::vector<size_t> subtree;
91 for (
size_t id = 0;
id < dft.
nrElements(); ++id) {
93 subtree.push_back(
id);
96 subtreeBEs.push_back(subtree);
99 for (
auto tree : subtreeBEs) {
100 std::stringstream stream;
101 stream <<
"Subtree: ";
102 for (
size_t id : tree) {
103 stream <<
id <<
", ";
109template<
typename ValueType,
typename StateType>
113 usedHeuristic = approximationHeuristic;
115 if (approximationThreshold > 0 && !this->uniqueFailedState) {
118 STORM_LOG_WARN(
"Approximation requires unique failed state. Forcing use of unique failed state.");
119 this->uniqueFailedState =
true;
124 switch (usedHeuristic) {
135 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
139 if (this->uniqueFailedState) {
142 size_t failedStateId = newIndex++;
144 matrixBuilder.stateRemapping.push_back(0);
145 return failedStateId;
148 matrixBuilder.setRemapping(0);
150 matrixBuilder.newRowGroup();
151 setMarkovian(behavior.
begin()->isMarkovian());
157 std::pair<StateType, ValueType> stateProbabilityPair = *(behavior.
begin()->begin());
158 STORM_LOG_ASSERT(stateProbabilityPair.first == 0,
"No self loop for failed state.");
159 STORM_LOG_ASSERT(storm::utility::isOne<ValueType>(stateProbabilityPair.second),
"Probability for failed state != 1.");
160 matrixBuilder.addTransition(stateProbabilityPair.first, stateProbabilityPair.second);
161 matrixBuilder.finishRow();
165 this->stateStorage.initialStateIndices =
166 generator.getInitialStates(std::bind(&ExplicitDFTModelBuilder::getOrAddStateIndex,
this, std::placeholders::_1));
167 STORM_LOG_ASSERT(stateStorage.initialStateIndices.size() == 1,
"Only one initial state assumed.");
168 initialStateIndex = stateStorage.initialStateIndices[0];
173 if (initialStateIndex == 0 && this->uniqueFailedState) {
174 modelComponents.markovianStates.resize(1);
175 modelComponents.deterministicModel = generator.isDeterministicModel();
177 STORM_LOG_TRACE(
"Markovian states: " << modelComponents.markovianStates);
179 STORM_LOG_DEBUG(
"Model is " << (generator.isDeterministicModel() ?
"deterministic" :
"non-deterministic"));
182 modelComponents.transitionMatrix = matrixBuilder.builder.build(1, 1);
183 STORM_LOG_TRACE(
"Transition matrix: \n" << modelComponents.transitionMatrix);
190 STORM_LOG_ASSERT(!statesNotExplored.at(initialStateIndex).second,
"Heuristic for initial state is already initialized");
191 ExplorationHeuristicPointer heuristic;
192 switch (usedHeuristic) {
194 heuristic = std::make_shared<DFTExplorationHeuristicDepth<ValueType>>(initialStateIndex);
197 heuristic = std::make_shared<DFTExplorationHeuristicProbability<ValueType>>(initialStateIndex);
200 heuristic = std::make_shared<DFTExplorationHeuristicBoundDifference<ValueType>>(initialStateIndex);
203 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
205 heuristic->markExpand();
206 statesNotExplored[initialStateIndex].second = heuristic;
207 explorationQueue.push(heuristic);
209 initializeNextIteration();
212 if (approximationThreshold > 0.0) {
213 switch (usedHeuristic) {
215 approximationThreshold = iteration + 1;
219 approximationThreshold = std::pow(2, -(
double)iteration);
222 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
226 auto ftSettings = storm::settings::getModule<storm::dft::settings::modules::FaultTreeSettings>();
227 if (ftSettings.isMaxDepthSet()) {
229 approximationThreshold = ftSettings.getMaxDepth();
232 exploreStateSpace(approximationThreshold);
234 size_t stateSize = stateStorage.getNumberOfStates() + (this->uniqueFailedState ? 1 : 0);
235 modelComponents.markovianStates.resize(stateSize);
236 modelComponents.deterministicModel = generator.isDeterministicModel();
239 STORM_LOG_ASSERT(matrixBuilder.getRemapping(initialStateIndex) == initialStateIndex,
"Initial state should not be remapped.");
241 STORM_LOG_TRACE(
"Remap matrix: " << matrixBuilder.stateRemapping <<
", offset: " << matrixBuilder.mappingOffset);
242 matrixBuilder.remap();
245 STORM_LOG_TRACE(
"Markovian states: " << modelComponents.markovianStates);
247 STORM_LOG_DEBUG(
"Model is " << (generator.isDeterministicModel() ?
"deterministic" :
"non-deterministic"));
250 modelComponents.transitionMatrix = matrixBuilder.builder.build(stateSize, stateSize);
251 if (stateSize <= 15) {
252 STORM_LOG_TRACE(
"Transition matrix: \n" << modelComponents.transitionMatrix);
260template<
typename ValueType,
typename StateType>
267 for (
auto const& skippedState : skippedStates) {
268 statesNotExplored[skippedState.second.first->getId()] = skippedState.second;
269 explorationQueue.push(skippedState.second.second);
274 std::vector<uint_fast64_t> copyRemapping = matrixBuilder.stateRemapping;
275 matrixBuilder = MatrixBuilder(!generator.isDeterministicModel());
276 matrixBuilder.stateRemapping = copyRemapping;
277 StateType nrStates = modelComponents.transitionMatrix.getRowGroupCount();
278 STORM_LOG_ASSERT(nrStates == matrixBuilder.stateRemapping.size(),
"No. of states does not coincide with mapping size.");
281 std::vector<StateType> indexRemapping = std::vector<StateType>(nrStates, 0);
282 auto iterSkipped = skippedStates.begin();
283 size_t skippedBefore = 0;
284 for (
size_t i = 0; i < indexRemapping.size(); ++i) {
285 while (iterSkipped != skippedStates.end() && iterSkipped->first <= i) {
286 STORM_LOG_ASSERT(iterSkipped->first < indexRemapping.size(),
"Skipped is too high.");
290 indexRemapping[i] = i - skippedBefore;
294 size_t nrExpandedStates = nrStates - skippedBefore;
295 matrixBuilder.mappingOffset = nrStates;
297 StateType skippedIndex = nrExpandedStates;
298 std::map<StateType, std::pair<DFTStatePointer, ExplorationHeuristicPointer>> skippedStatesNew;
299 for (
size_t id = 0;
id < matrixBuilder.stateRemapping.size(); ++id) {
300 StateType index = matrixBuilder.getRemapping(
id);
301 auto itFind = skippedStates.find(index);
302 if (itFind != skippedStates.end()) {
304 matrixBuilder.stateRemapping[id] = skippedIndex;
305 skippedStatesNew[skippedIndex] = itFind->second;
306 indexRemapping[index] = skippedIndex;
310 matrixBuilder.stateRemapping[id] = indexRemapping[index];
313 STORM_LOG_TRACE(
"New state remapping: " << matrixBuilder.stateRemapping);
314 std::stringstream ss;
315 ss <<
"Index remapping:\n";
316 for (
auto tmp : indexRemapping) {
324 modelComponents.markovianStates.complement();
325 size_t index = modelComponents.markovianStates.getNextSetIndex(0);
326 while (index < modelComponents.markovianStates.size()) {
327 markovianStatesNew.
set(indexRemapping[index],
false);
328 index = modelComponents.markovianStates.getNextSetIndex(index + 1);
331 "Remapping of markovian states is wrong.");
332 STORM_LOG_ASSERT(markovianStatesNew.
size() == nrStates,
"No. of states does not coincide with markovian size.");
333 modelComponents.markovianStates = markovianStatesNew;
337 for (StateType oldRowGroup = 0; oldRowGroup < modelComponents.transitionMatrix.getRowGroupCount(); ++oldRowGroup) {
338 if (indexRemapping[oldRowGroup] < nrExpandedStates) {
340 matrixBuilder.newRowGroup();
341 for (StateType oldRow = modelComponents.transitionMatrix.getRowGroupIndices()[oldRowGroup];
342 oldRow < modelComponents.transitionMatrix.getRowGroupIndices()[oldRowGroup + 1]; ++oldRow) {
344 itEntry != modelComponents.transitionMatrix.end(oldRow); ++itEntry) {
345 auto itFind = skippedStates.find(itEntry->getColumn());
346 if (itFind != skippedStates.end()) {
348 matrixBuilder.addTransition(matrixBuilder.mappingOffset + itFind->second.first->getId(), itEntry->getValue());
351 matrixBuilder.addTransition(indexRemapping[itEntry->getColumn()], itEntry->getValue());
354 matrixBuilder.finishRow();
359 skippedStates = skippedStatesNew;
361 STORM_LOG_ASSERT(matrixBuilder.getCurrentRowGroup() == nrExpandedStates,
"Row group size does not match.");
362 skippedStates.clear();
365template<
typename ValueType,
typename StateType>
366void ExplicitDFTModelBuilder<ValueType, StateType>::exploreStateSpace(
double approximationThreshold) {
367 size_t nrExpandedStates = 0;
368 size_t nrSkippedStates = 0;
370 progress.startNewMeasurement(0);
372 while (!explorationQueue.empty()) {
374 ExplorationHeuristicPointer currentExplorationHeuristic = explorationQueue.pop();
375 StateType currentId = currentExplorationHeuristic->getId();
376 auto itFind = statesNotExplored.find(currentId);
377 STORM_LOG_ASSERT(itFind != statesNotExplored.end(),
"Id " << currentId <<
" not found");
378 DFTStatePointer currentState = itFind->second.first;
379 STORM_LOG_ASSERT(currentExplorationHeuristic == itFind->second.second,
"Exploration heuristics do not match");
382 statesNotExplored.erase(itFind);
383 STORM_LOG_ASSERT(stateStorage.stateToId.contains(currentState->status()),
"State is not contained in state storage.");
384 STORM_LOG_ASSERT(stateStorage.stateToId.getValue(currentState->status()) == currentId,
"Ids of states do not coincide.");
387 if (currentState->isPseudoState()) {
389 currentState->construct();
394 matrixBuilder.setRemapping(currentId);
396 matrixBuilder.newRowGroup();
399 generator.load(currentState);
402 if (approximationThreshold > 0.0 && currentExplorationHeuristic->isSkip(approximationThreshold)) {
405 STORM_LOG_TRACE(
"Skip expansion of state: " << dft.getStateString(currentState));
410 matrixBuilder.addTransition(0, storm::utility::zero<ValueType>());
412 skippedStates[matrixBuilder.getCurrentRowGroup() - 1] = std::make_pair(currentState, currentExplorationHeuristic);
413 matrixBuilder.finishRow();
418 generator.expand(std::bind(&ExplicitDFTModelBuilder::getOrAddStateIndex,
this, std::placeholders::_1));
420 setMarkovian(behavior.
begin()->isMarkovian());
423 for (
auto const& choice : behavior) {
425 for (
auto const& stateProbabilityPair : choice) {
428 matrixBuilder.addTransition(matrixBuilder.mappingOffset + stateProbabilityPair.first, stateProbabilityPair.second);
430 auto iter = statesNotExplored.find(stateProbabilityPair.first);
431 if (iter != statesNotExplored.end()) {
433 DFTStatePointer state = iter->second.first;
434 if (!iter->second.second) {
436 ExplorationHeuristicPointer heuristic;
437 switch (usedHeuristic) {
440 std::make_shared<DFTExplorationHeuristicDepth<ValueType>>(stateProbabilityPair.first, *currentExplorationHeuristic);
443 heuristic = std::make_shared<DFTExplorationHeuristicProbability<ValueType>>(
444 stateProbabilityPair.first, *currentExplorationHeuristic, stateProbabilityPair.second, choice.getTotalMass());
447 heuristic = std::make_shared<DFTExplorationHeuristicBoundDifference<ValueType>>(
448 stateProbabilityPair.first, *currentExplorationHeuristic, stateProbabilityPair.second, choice.getTotalMass());
451 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
454 iter->second.second = heuristic;
458 if (state->getFailableElements().hasDependencies() ||
459 (!state->getFailableElements().hasDependencies() && !state->getFailableElements().hasBEs())) {
461 iter->second.second->markExpand();
465 if (state->isPseudoState()) {
473 ValueType lowerBound = getLowerBound(state);
474 ValueType upperBound = getUpperBound(state);
475 heuristic->setBounds(lowerBound, upperBound);
478 explorationQueue.push(heuristic);
479 }
else if (!iter->second.second->isExpand()) {
480 bool changedPriority =
false;
481 double oldPriority = iter->second.second->getPriority();
482 switch (usedHeuristic) {
484 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic,
485 stateProbabilityPair.second,
486 stateProbabilityPair.second);
489 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic, stateProbabilityPair.second,
490 choice.getTotalMass());
493 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic, stateProbabilityPair.second,
494 choice.getTotalMass());
497 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
499 if (changedPriority) {
501 explorationQueue.update(iter->second.second, oldPriority);
506 matrixBuilder.finishRow();
513 if (nrExpandedStates % 100 == 0) {
514 progress.updateProgress(nrExpandedStates);
520 STORM_LOG_ASSERT(nrSkippedStates == skippedStates.size(),
"Nr skipped states is wrong");
523template<
typename ValueType,
typename StateType>
524void ExplicitDFTModelBuilder<ValueType, StateType>::buildLabeling() {
525 bool isAddLabelsClaiming = storm::settings::getModule<storm::dft::settings::modules::FaultTreeSettings>().isAddLabelsClaiming();
530 modelComponents.stateLabeling.addLabel(
"init");
531 STORM_LOG_ASSERT(matrixBuilder.getRemapping(initialStateIndex) == initialStateIndex,
"Initial state should not be remapped.");
532 modelComponents.stateLabeling.addLabelToState(
"init", initialStateIndex);
534 modelComponents.stateLabeling.addLabel(
"failed");
538 for (
size_t id = 0;
id < dft.nrElements(); ++id) {
539 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(
id);
540 if (element->isRelevant()) {
541 modelComponents.stateLabeling.addLabel(element->name() +
"_failed");
542 modelComponents.stateLabeling.addLabel(element->name() +
"_dc");
545 std::vector<std::shared_ptr<storm::dft::storage::elements::DFTGate<ValueType>
const>> spares;
546 if (isAddLabelsClaiming) {
548 for (
size_t spareId : dft.getSpareIndices()) {
549 auto const& spare = dft.getGate(spareId);
550 spares.push_back(spare);
551 for (
auto const& child : spare->children()) {
552 modelComponents.stateLabeling.addLabel(spare->name() +
"_claimed_" + child->name());
558 if (this->uniqueFailedState) {
560 modelComponents.stateLabeling.addLabelToState(
"failed", 0);
561 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(dft.getTopLevelIndex());
562 STORM_LOG_ASSERT(element->isRelevant(),
"TLE should be relevant if unique failed state is used.");
563 modelComponents.stateLabeling.addLabelToState(element->name() +
"_failed", 0);
565 for (
auto const& stateIdPair : stateStorage.stateToId) {
567 size_t stateId = matrixBuilder.getRemapping(stateIdPair.second);
568 if (dft.hasFailed(state, *stateGenerationInfo)) {
569 modelComponents.stateLabeling.addLabelToState(
"failed", stateId);
572 for (
size_t id = 0;
id < dft.nrElements(); ++id) {
573 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(
id);
574 if (element->isRelevant()) {
577 switch (elementState) {
579 modelComponents.stateLabeling.addLabelToState(element->name() +
"_failed", stateId);
582 modelComponents.stateLabeling.addLabelToState(element->name() +
"_dc", stateId);
593 if (isAddLabelsClaiming) {
594 for (
auto const& spare : spares) {
595 size_t claimedChildId = dft.uses(state, *stateGenerationInfo, spare->id());
596 if (claimedChildId != spare->id()) {
597 modelComponents.stateLabeling.addLabelToState(spare->name() +
"_claimed_" + dft.getElement(claimedChildId)->name(), stateId);
606template<
typename ValueType,
typename StateType>
608 if (storm::settings::getModule<storm::dft::settings::modules::FaultTreeSettings>().isMaxDepthSet() && skippedStates.size() > 0) {
610 modelComponents.stateLabeling.addLabel(
"skipped");
611 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
612 modelComponents.stateLabeling.addLabelToState(
"skipped", it->first);
615 STORM_LOG_ASSERT(skippedStates.size() == 0,
"Concrete model has skipped states");
618 return createModel(
false);
621template<
typename ValueType,
typename StateType>
626 changeMatrixBound(modelComponents.transitionMatrix, lowerBound);
627 return createModel(
true);
635 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
636 auto matrixEntry = matrix.
getRow(it->first, 0).
begin();
637 STORM_LOG_ASSERT(matrixEntry->getColumn() == 0,
"Transition has wrong target state.");
638 STORM_LOG_ASSERT(!it->second.first->isPseudoState(),
"State is still pseudo state.");
639 matrixEntry->setValue(storm::utility::one<ValueType>());
640 matrixEntry->setColumn(it->first);
645 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
646 failedStates.
set(it->first);
648 labeling.
setStates(
"failed", failedStates);
651 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
652 if (modelComponents.deterministicModel) {
653 model = std::make_shared<storm::models::sparse::Ctmc<ValueType>>(std::move(matrix), std::move(labeling));
658 modelComponents.exitRates = std::vector<ValueType>(modelComponents.markovianStates.size());
659 std::vector<typename storm::storage::SparseMatrix<ValueType>::index_type> indices = matrix.
getRowGroupIndices();
660 for (StateType stateIndex = 0; stateIndex < modelComponents.markovianStates.size(); ++stateIndex) {
661 if (modelComponents.markovianStates[stateIndex]) {
662 modelComponents.exitRates[stateIndex] = matrix.
getRowSum(indices[stateIndex]);
664 modelComponents.exitRates[stateIndex] = storm::utility::zero<ValueType>();
672 maComponents.
exitRates = modelComponents.exitRates;
673 std::shared_ptr<storm::models::sparse::MarkovAutomaton<ValueType>> ma =
674 std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
675 if (ma->hasOnlyTrivialNondeterminism()) {
684 if (model->getNumberOfStates() <= 15) {
685 STORM_LOG_TRACE(
"Transition matrix: \n" << model->getTransitionMatrix());
693template<
typename ValueType,
typename StateType>
695 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
697 if (modelComponents.deterministicModel) {
700 model = std::make_shared<storm::models::sparse::Ctmc<ValueType>>(modelComponents.transitionMatrix, modelComponents.stateLabeling);
703 std::make_shared<storm::models::sparse::Ctmc<ValueType>>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling));
709 modelComponents.exitRates = std::vector<ValueType>(modelComponents.markovianStates.size());
710 std::vector<typename storm::storage::SparseMatrix<ValueType>::index_type> indices = modelComponents.transitionMatrix.getRowGroupIndices();
711 for (StateType stateIndex = 0; stateIndex < modelComponents.markovianStates.size(); ++stateIndex) {
712 if (modelComponents.markovianStates[stateIndex]) {
713 modelComponents.exitRates[stateIndex] = modelComponents.transitionMatrix.getRowSum(indices[stateIndex]);
715 modelComponents.exitRates[stateIndex] = storm::utility::zero<ValueType>();
720 std::shared_ptr<storm::models::sparse::MarkovAutomaton<ValueType>> ma;
723 maComponents.rateTransitions =
true;
724 maComponents.markovianStates = modelComponents.markovianStates;
725 maComponents.exitRates = modelComponents.exitRates;
726 ma = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
729 std::move(modelComponents.stateLabeling));
730 maComponents.rateTransitions =
true;
731 maComponents.markovianStates = std::move(modelComponents.markovianStates);
732 maComponents.exitRates = std::move(modelComponents.exitRates);
733 ma = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
735 if (ma->hasOnlyTrivialNondeterminism()) {
744 if (model->getNumberOfStates() <= 15) {
745 STORM_LOG_TRACE(
"Transition matrix: \n" << model->getTransitionMatrix());
752template<
typename ValueType,
typename StateType>
755 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
756 auto matrixEntry = matrix.
getRow(it->first, 0).
begin();
757 STORM_LOG_ASSERT(matrixEntry->getColumn() == 0,
"Transition has wrong target state.");
758 STORM_LOG_ASSERT(!it->second.first->isPseudoState(),
"State is still pseudo state.");
763 matrixEntry->setValue(getLowerBound(it->second.first));
765 matrixEntry->setValue(getUpperBound(it->second.first));
770template<
typename ValueType,
typename StateType>
771ValueType ExplicitDFTModelBuilder<ValueType, StateType>::getLowerBound(DFTStatePointer
const& state)
const {
773 ValueType lowerBound = storm::utility::zero<ValueType>();
774 STORM_LOG_ASSERT(!state->getFailableElements().hasDependencies(),
"Lower bound should only be computed if dependencies were already handled.");
775 for (
auto it = state->getFailableElements().begin(); it != state->getFailableElements().end(); ++it) {
776 lowerBound += state->getBERate(*it);
778 STORM_LOG_TRACE(
"Lower bound is " << lowerBound <<
" for state " << state->getId());
782template<
typename ValueType,
typename StateType>
783ValueType ExplicitDFTModelBuilder<ValueType, StateType>::getUpperBound(DFTStatePointer
const& state)
const {
784 if (state->hasFailed(dft.getTopLevelIndex())) {
785 return storm::utility::zero<ValueType>();
789 ValueType upperBound = storm::utility::one<ValueType>();
790 ValueType rateSum = storm::utility::zero<ValueType>();
793 for (std::vector<size_t>
const& subtree : subtreeBEs) {
795 std::vector<ValueType> rates;
797 for (
size_t i = 0;
i < subtree.size(); ++
i) {
798 size_t id = subtree[
i];
800 if (state->isOperational(
id)) {
801 auto be = dft.getBasicElement(
id);
802 switch (be->beType()) {
809 if (storm::utility::isZero<ValueType>(rate)) {
811 auto beExp = std::static_pointer_cast<storm::dft::storage::elements::BEExponential<ValueType>
const>(be);
812 rate = beExp->activeFailureRate();
813 STORM_LOG_ASSERT(!storm::utility::isZero<ValueType>(rate),
"Failure rate should not be zero.");
815 coldBEs.set(i,
true);
817 rates.push_back(rate);
822 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"BE of type '" << be->beType() <<
"' is not known.");
830 std::sort(rates.begin(), rates.end());
831 std::vector<size_t> rateCount(rates.size(), 0);
832 size_t lastIndex = 0;
833 for (
size_t i = 0;
i < rates.size(); ++
i) {
834 if (rates[lastIndex] != rates[i]) {
837 ++rateCount[lastIndex];
840 for (
size_t i = 0;
i < rates.size(); ++
i) {
842 if (!coldBEs.get(i) && rateCount[i] > 0) {
843 std::iter_swap(rates.begin() + i, rates.end() - 1);
845 upperBound += rates.back() * rateCount[
i] * computeMTTFAnd(rates, rates.size() - 1);
848 std::iter_swap(rates.begin() + i, rates.end() - 1);
853 STORM_LOG_TRACE(
"Upper bound is " << (rateSum / upperBound) <<
" for state " << state->getId());
856 return rateSum / upperBound;
859template<
typename ValueType,
typename StateType>
860ValueType ExplicitDFTModelBuilder<ValueType, StateType>::computeMTTFAnd(std::vector<ValueType>
const& rates,
size_t size)
const {
861 ValueType result = storm::utility::zero<ValueType>();
893 for (
size_t i1 = 0; i1 < size; ++i1) {
897 for (
size_t i2 = 0; i2 < i1; ++i2) {
900 result -=
one / sum2;
901 for (
size_t i3 = 0; i3 < i2; ++i3) {
903 result +=
one / (sum2 + rates[i3]);
912template<
typename ValueType,
typename StateType>
913StateType ExplicitDFTModelBuilder<ValueType, StateType>::getOrAddStateIndex(DFTStatePointer
const& state) {
915 bool changed =
false;
917 if (stateGenerationInfo->hasSymmetries()) {
920 changed = state->orderBySymmetry();
921 STORM_LOG_TRACE(
"State " << (changed ?
"changed to " :
"did not change") << (changed ? dft.getStateString(state) :
""));
924 if (stateStorage.stateToId.contains(state->status())) {
926 stateId = stateStorage.stateToId.getValue(state->status());
927 STORM_LOG_TRACE(
"State " << dft.getStateString(state) <<
" with id " << stateId <<
" already exists");
931 auto iter = statesNotExplored.find(stateId);
932 if (iter != statesNotExplored.end() && iter->second.first->isPseudoState()) {
934 STORM_LOG_ASSERT(iter->second.first->getId() == stateId,
"Ids do not match.");
935 STORM_LOG_ASSERT(iter->second.first->status() == state->status(),
"Pseudo states do not coincide.");
936 state->setId(stateId);
939 statesNotExplored[stateId] = std::make_pair(state, iter->second.second);
946 STORM_LOG_ASSERT(state->isPseudoState() == changed,
"State type (pseudo/concrete) wrong.");
948 state->setId(newIndex++);
949 stateId = stateStorage.stateToId.findOrAdd(state->status(), state->getId());
952 ExplorationHeuristicPointer nullHeuristic;
953 statesNotExplored[stateId] = std::make_pair(state, nullHeuristic);
955 matrixBuilder.stateRemapping.push_back(0);
956 STORM_LOG_TRACE(
"New " << (state->isPseudoState() ?
"pseudo" :
"concrete") <<
" state: " << dft.getStateString(state));
961template<
typename ValueType,
typename StateType>
962void ExplicitDFTModelBuilder<ValueType, StateType>::setMarkovian(
bool markovian) {
963 if (matrixBuilder.getCurrentRowGroup() > modelComponents.markovianStates.size()) {
965 modelComponents.markovianStates.resize(modelComponents.markovianStates.size() + INITIAL_BITVECTOR_SIZE);
967 modelComponents.markovianStates.set(matrixBuilder.getCurrentRowGroup() - 1, markovian);
970template<
typename ValueType,
typename StateType>
971void ExplicitDFTModelBuilder<ValueType, StateType>::printNotExplored()
const {
972 std::cout <<
"states not explored:\n";
973 for (
auto it : statesNotExplored) {
974 std::cout << it.first <<
" -> " << dft.getStateString(it.second.first) <<
'\n';
979template class ExplicitDFTModelBuilder<double>;
980template class ExplicitDFTModelBuilder<storm::RationalFunction>;
Build a Markov chain from DFT.
std::shared_ptr< storm::models::sparse::Model< ValueType > > getModelApproximation(bool lowerBound, bool expectedTime)
Get the built approximation model for either the lower or upper bound.
std::shared_ptr< storm::models::sparse::Model< ValueType > > getModel()
Get the built model.
void buildModel(size_t iteration, double approximationThreshold=0.0, storm::dft::builder::ApproximationHeuristic approximationHeuristic=storm::dft::builder::ApproximationHeuristic::DEPTH)
Build model from DFT.
Priority queue based on buckets.
Represents a Dynamic Fault Tree.
size_t getTopLevelIndex() const
std::string getRelevantEventsString() const
Get a string containing the list of all relevant events.
std::shared_ptr< storm::dft::storage::elements::DFTBE< ValueType > const > getBasicElement(size_t index) const
storm::dft::storage::elements::DFTElementType getTopLevelType() const
size_t nrElements() const
std::shared_ptr< storm::dft::storage::elements::DFTGate< ValueType > const > getGate(size_t index) const
bool isGate(size_t index) const
std::vector< size_t > const & getRelevantEvents() const
Get all relevant events.
bool isBasicElement(size_t index) const
DFTElementState getElementState(size_t id) const
bool empty() const
Retrieves whether the behavior is empty in the sense that there are no available choices.
std::vector< Choice< ValueType, StateType > >::const_iterator begin() const
Retrieves an iterator to the choices available in the behavior.
std::size_t getNumberOfChoices() const
Retrieves the number of choices in the behavior.
This class manages the labeling of the state space with a number of (atomic) labels.
void setStates(std::string const &label, storage::BitVector const &labeling)
Sets the labeling of states associated with the given label.
A bit vector that is internally represented as a vector of 64-bit values.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true 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.
const_iterator begin() const
Retrieves an iterator that points to the beginning of the rows.
A class that can be used to build a sparse matrix by adding value by value.
A class that holds a possibly non-square matrix in the compressed row storage format.
const_rows getRow(index_type row) const
Returns an object representing the given row.
value_type getRowSum(index_type row) const
Computes the sum of the entries in a given row.
std::vector< MatrixEntry< index_type, value_type > >::const_iterator const_iterator
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
A class that provides convenience operations to display run times.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
ApproximationHeuristic
Enum representing the heuristic used for deciding which states to expand.
SFTBDDChecker::ValueType ValueType
Expression sum(std::vector< storm::expressions::Expression > const &expressions)
bool isTerminate()
Check whether the program should terminate (due to some abort signal).
bool isZero(ValueType const &a)
boost::optional< storm::storage::BitVector > markovianStates
boost::optional< std::vector< ValueType > > exitRates