23template<
typename ValueType,
typename StateType>
24ExplicitDFTModelBuilder<ValueType, StateType>::ModelComponents::ModelComponents()
25 : transitionMatrix(), stateLabeling(), markovianStates(), exitRates(), choiceLabeling() {
29template<
typename ValueType,
typename StateType>
30ExplicitDFTModelBuilder<ValueType, StateType>::MatrixBuilder::MatrixBuilder(
bool canHaveNondeterminism)
31 : mappingOffset(0), stateRemapping(), currentRowGroup(0), currentRow(0), canHaveNondeterminism((canHaveNondeterminism)) {
36template<
typename ValueType,
typename StateType>
40 stateGenerationInfo(
std::make_shared<
storm::dft::storage::DFTStateGenerationInfo>(dft.buildStateGenerationInfo(symmetries))),
41 generator(dft, *stateGenerationInfo),
42 matrixBuilder(!generator.isDeterministicModel()),
43 stateStorage(dft.stateBitVectorSize()),
44 explorationQueue(1, 0, 0.9, false) {
50 this->uniqueFailedState =
true;
59 std::vector<size_t> isubdft;
60 if (child->nrParents() > 1 || child->hasOutgoingDependencies()) {
61 STORM_LOG_TRACE(
"child " << child->name() <<
" does not allow modularisation.");
63 }
else if (dft.
isGate(child->id())) {
64 isubdft = dft.
getGate(child->id())->independentSubDft(
false);
68 STORM_LOG_TRACE(
"child " << child->name() <<
" does not allow modularisation.");
71 isubdft = {child->id()};
74 if (isubdft.empty()) {
79 std::vector<size_t> subtree;
80 for (
size_t id : isubdft) {
82 subtree.push_back(
id);
85 subtreeBEs.push_back(subtree);
89 if (subtreeBEs.empty()) {
91 std::vector<size_t> subtree;
92 for (
size_t id = 0;
id < dft.
nrElements(); ++id) {
94 subtree.push_back(
id);
97 subtreeBEs.push_back(subtree);
100 for (
auto tree : subtreeBEs) {
101 std::stringstream stream;
102 stream <<
"Subtree: ";
103 for (
size_t id : tree) {
104 stream <<
id <<
", ";
110template<
typename ValueType,
typename StateType>
114 usedHeuristic = approximationHeuristic;
116 if (approximationThreshold > 0 && !this->uniqueFailedState) {
119 STORM_LOG_WARN(
"Approximation requires unique failed state. Forcing use of unique failed state.");
120 this->uniqueFailedState =
true;
125 switch (usedHeuristic) {
136 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
140 if (this->uniqueFailedState) {
143 size_t failedStateId = newIndex++;
145 matrixBuilder.stateRemapping.push_back(0);
146 return failedStateId;
149 matrixBuilder.setRemapping(0);
151 matrixBuilder.newRowGroup();
152 setMarkovian(behavior.
begin()->isMarkovian());
158 std::pair<StateType, ValueType> stateProbabilityPair = *(behavior.
begin()->begin());
159 STORM_LOG_ASSERT(stateProbabilityPair.first == 0,
"No self loop for failed state.");
160 STORM_LOG_ASSERT(storm::utility::isOne<ValueType>(stateProbabilityPair.second),
"Probability for failed state != 1.");
161 matrixBuilder.addTransition(stateProbabilityPair.first, stateProbabilityPair.second);
162 matrixBuilder.finishRow();
166 this->stateStorage.initialStateIndices =
167 generator.getInitialStates(std::bind(&ExplicitDFTModelBuilder::getOrAddStateIndex,
this, std::placeholders::_1));
168 STORM_LOG_ASSERT(stateStorage.initialStateIndices.size() == 1,
"Only one initial state assumed.");
169 initialStateIndex = stateStorage.initialStateIndices[0];
174 if (initialStateIndex == 0 && this->uniqueFailedState) {
175 modelComponents.markovianStates.resize(1);
176 modelComponents.deterministicModel = generator.isDeterministicModel();
178 STORM_LOG_TRACE(
"Markovian states: " << modelComponents.markovianStates);
180 STORM_LOG_DEBUG(
"Model is " << (generator.isDeterministicModel() ?
"deterministic" :
"non-deterministic"));
183 modelComponents.transitionMatrix = matrixBuilder.builder.build(1, 1);
184 STORM_LOG_TRACE(
"Transition matrix: \n" << modelComponents.transitionMatrix);
191 STORM_LOG_ASSERT(!statesNotExplored.at(initialStateIndex).second,
"Heuristic for initial state is already initialized");
192 ExplorationHeuristicPointer heuristic;
193 switch (usedHeuristic) {
195 heuristic = std::make_shared<DFTExplorationHeuristicDepth<ValueType>>(initialStateIndex);
198 heuristic = std::make_shared<DFTExplorationHeuristicProbability<ValueType>>(initialStateIndex);
201 heuristic = std::make_shared<DFTExplorationHeuristicBoundDifference<ValueType>>(initialStateIndex);
204 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
206 heuristic->markExpand();
207 statesNotExplored[initialStateIndex].second = heuristic;
208 explorationQueue.push(heuristic);
210 initializeNextIteration();
213 if (approximationThreshold > 0.0) {
214 switch (usedHeuristic) {
216 approximationThreshold = iteration + 1;
220 approximationThreshold = std::pow(2, -(
double)iteration);
223 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
228 if (ftSettings.isMaxDepthSet()) {
230 approximationThreshold = ftSettings.getMaxDepth();
233 exploreStateSpace(approximationThreshold);
235 size_t stateSize = stateStorage.getNumberOfStates() + (this->uniqueFailedState ? 1 : 0);
236 modelComponents.markovianStates.resize(stateSize);
237 modelComponents.deterministicModel = generator.isDeterministicModel();
240 STORM_LOG_ASSERT(matrixBuilder.getRemapping(initialStateIndex) == initialStateIndex,
"Initial state should not be remapped.");
242 STORM_LOG_TRACE(
"Remap matrix: " << matrixBuilder.stateRemapping <<
", offset: " << matrixBuilder.mappingOffset);
243 matrixBuilder.remap();
246 STORM_LOG_TRACE(
"Markovian states: " << modelComponents.markovianStates);
248 STORM_LOG_DEBUG(
"Model is " << (generator.isDeterministicModel() ?
"deterministic" :
"non-deterministic"));
251 modelComponents.transitionMatrix = matrixBuilder.builder.build(stateSize, stateSize);
252 if (stateSize <= 15) {
253 STORM_LOG_TRACE(
"Transition matrix: \n" << modelComponents.transitionMatrix);
261template<
typename ValueType,
typename StateType>
268 for (
auto const& skippedState : skippedStates) {
269 statesNotExplored[skippedState.second.first->getId()] = skippedState.second;
270 explorationQueue.push(skippedState.second.second);
275 std::vector<uint_fast64_t> copyRemapping = matrixBuilder.stateRemapping;
276 matrixBuilder = MatrixBuilder(!generator.isDeterministicModel());
277 matrixBuilder.stateRemapping = copyRemapping;
278 StateType nrStates = modelComponents.transitionMatrix.getRowGroupCount();
279 STORM_LOG_ASSERT(nrStates == matrixBuilder.stateRemapping.size(),
"No. of states does not coincide with mapping size.");
282 std::vector<StateType> indexRemapping = std::vector<StateType>(nrStates, 0);
283 auto iterSkipped = skippedStates.begin();
284 size_t skippedBefore = 0;
285 for (
size_t i = 0; i < indexRemapping.size(); ++i) {
286 while (iterSkipped != skippedStates.end() && iterSkipped->first <= i) {
287 STORM_LOG_ASSERT(iterSkipped->first < indexRemapping.size(),
"Skipped is too high.");
291 indexRemapping[i] = i - skippedBefore;
295 size_t nrExpandedStates = nrStates - skippedBefore;
296 matrixBuilder.mappingOffset = nrStates;
298 StateType skippedIndex = nrExpandedStates;
299 std::map<StateType, std::pair<DFTStatePointer, ExplorationHeuristicPointer>> skippedStatesNew;
300 for (
size_t id = 0;
id < matrixBuilder.stateRemapping.size(); ++id) {
301 StateType index = matrixBuilder.getRemapping(
id);
302 auto itFind = skippedStates.find(index);
303 if (itFind != skippedStates.end()) {
305 matrixBuilder.stateRemapping[id] = skippedIndex;
306 skippedStatesNew[skippedIndex] = itFind->second;
307 indexRemapping[index] = skippedIndex;
311 matrixBuilder.stateRemapping[id] = indexRemapping[index];
314 STORM_LOG_TRACE(
"New state remapping: " << matrixBuilder.stateRemapping);
315 std::stringstream ss;
316 ss <<
"Index remapping:\n";
317 for (
auto tmp : indexRemapping) {
325 modelComponents.markovianStates.complement();
326 size_t index = modelComponents.markovianStates.getNextSetIndex(0);
327 while (index < modelComponents.markovianStates.size()) {
328 markovianStatesNew.
set(indexRemapping[index],
false);
329 index = modelComponents.markovianStates.getNextSetIndex(index + 1);
332 "Remapping of markovian states is wrong.");
333 STORM_LOG_ASSERT(markovianStatesNew.
size() == nrStates,
"No. of states does not coincide with markovian size.");
334 modelComponents.markovianStates = markovianStatesNew;
338 for (StateType oldRowGroup = 0; oldRowGroup < modelComponents.transitionMatrix.getRowGroupCount(); ++oldRowGroup) {
339 if (indexRemapping[oldRowGroup] < nrExpandedStates) {
341 matrixBuilder.newRowGroup();
342 for (StateType oldRow = modelComponents.transitionMatrix.getRowGroupIndices()[oldRowGroup];
343 oldRow < modelComponents.transitionMatrix.getRowGroupIndices()[oldRowGroup + 1]; ++oldRow) {
345 itEntry != modelComponents.transitionMatrix.end(oldRow); ++itEntry) {
346 auto itFind = skippedStates.find(itEntry->getColumn());
347 if (itFind != skippedStates.end()) {
349 matrixBuilder.addTransition(matrixBuilder.mappingOffset + itFind->second.first->getId(), itEntry->getValue());
352 matrixBuilder.addTransition(indexRemapping[itEntry->getColumn()], itEntry->getValue());
355 matrixBuilder.finishRow();
360 skippedStates = skippedStatesNew;
362 STORM_LOG_ASSERT(matrixBuilder.getCurrentRowGroup() == nrExpandedStates,
"Row group size does not match.");
363 skippedStates.clear();
366template<
typename ValueType,
typename StateType>
367void ExplicitDFTModelBuilder<ValueType, StateType>::exploreStateSpace(
double approximationThreshold) {
368 size_t nrExpandedStates = 0;
369 size_t nrSkippedStates = 0;
371 progress.startNewMeasurement(0);
373 while (!explorationQueue.empty()) {
375 ExplorationHeuristicPointer currentExplorationHeuristic = explorationQueue.pop();
376 StateType currentId = currentExplorationHeuristic->getId();
377 auto itFind = statesNotExplored.find(currentId);
378 STORM_LOG_ASSERT(itFind != statesNotExplored.end(),
"Id " << currentId <<
" not found");
379 DFTStatePointer currentState = itFind->second.first;
380 STORM_LOG_ASSERT(currentExplorationHeuristic == itFind->second.second,
"Exploration heuristics do not match");
383 statesNotExplored.erase(itFind);
384 STORM_LOG_ASSERT(stateStorage.stateToId.contains(currentState->status()),
"State is not contained in state storage.");
385 STORM_LOG_ASSERT(stateStorage.stateToId.getValue(currentState->status()) == currentId,
"Ids of states do not coincide.");
388 if (currentState->isPseudoState()) {
390 currentState->construct();
395 matrixBuilder.setRemapping(currentId);
397 matrixBuilder.newRowGroup();
400 generator.load(currentState);
403 if (approximationThreshold > 0.0 && currentExplorationHeuristic->isSkip(approximationThreshold)) {
406 STORM_LOG_TRACE(
"Skip expansion of state: " << dft.getStateString(currentState));
411 matrixBuilder.addTransition(0, storm::utility::zero<ValueType>());
413 skippedStates[matrixBuilder.getCurrentRowGroup() - 1] = std::make_pair(currentState, currentExplorationHeuristic);
414 matrixBuilder.finishRow();
419 generator.expand(std::bind(&ExplicitDFTModelBuilder::getOrAddStateIndex,
this, std::placeholders::_1));
421 setMarkovian(behavior.
begin()->isMarkovian());
424 for (
auto const& choice : behavior) {
426 for (
auto const& stateProbabilityPair : choice) {
429 matrixBuilder.addTransition(matrixBuilder.mappingOffset + stateProbabilityPair.first, stateProbabilityPair.second);
431 auto iter = statesNotExplored.find(stateProbabilityPair.first);
432 if (iter != statesNotExplored.end()) {
434 DFTStatePointer state = iter->second.first;
435 if (!iter->second.second) {
437 ExplorationHeuristicPointer heuristic;
438 switch (usedHeuristic) {
441 std::make_shared<DFTExplorationHeuristicDepth<ValueType>>(stateProbabilityPair.first, *currentExplorationHeuristic);
444 heuristic = std::make_shared<DFTExplorationHeuristicProbability<ValueType>>(
445 stateProbabilityPair.first, *currentExplorationHeuristic, stateProbabilityPair.second, choice.getTotalMass());
448 heuristic = std::make_shared<DFTExplorationHeuristicBoundDifference<ValueType>>(
449 stateProbabilityPair.first, *currentExplorationHeuristic, stateProbabilityPair.second, choice.getTotalMass());
452 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
455 iter->second.second = heuristic;
459 if (state->getFailableElements().hasDependencies() ||
460 (!state->getFailableElements().hasDependencies() && !state->getFailableElements().hasBEs())) {
462 iter->second.second->markExpand();
466 if (state->isPseudoState()) {
474 ValueType lowerBound = getLowerBound(state);
475 ValueType upperBound = getUpperBound(state);
476 heuristic->setBounds(lowerBound, upperBound);
479 explorationQueue.push(heuristic);
480 }
else if (!iter->second.second->isExpand()) {
481 bool changedPriority =
false;
482 double oldPriority = iter->second.second->getPriority();
483 switch (usedHeuristic) {
485 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic,
486 stateProbabilityPair.second,
487 stateProbabilityPair.second);
490 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic, stateProbabilityPair.second,
491 choice.getTotalMass());
494 changedPriority = iter->second.second->updateHeuristicValues(*currentExplorationHeuristic, stateProbabilityPair.second,
495 choice.getTotalMass());
498 STORM_LOG_THROW(
false, storm::exceptions::IllegalArgumentException,
"Heuristic not known.");
500 if (changedPriority) {
502 explorationQueue.update(iter->second.second, oldPriority);
507 matrixBuilder.finishRow();
514 if (nrExpandedStates % 100 == 0) {
515 progress.updateProgress(nrExpandedStates);
521 STORM_LOG_ASSERT(nrSkippedStates == skippedStates.size(),
"Nr skipped states is wrong");
524template<
typename ValueType,
typename StateType>
525void ExplicitDFTModelBuilder<ValueType, StateType>::buildLabeling() {
531 modelComponents.stateLabeling.addLabel(
"init");
532 STORM_LOG_ASSERT(matrixBuilder.getRemapping(initialStateIndex) == initialStateIndex,
"Initial state should not be remapped.");
533 modelComponents.stateLabeling.addLabelToState(
"init", initialStateIndex);
535 modelComponents.stateLabeling.addLabel(
"failed");
539 for (
size_t id = 0;
id < dft.nrElements(); ++id) {
540 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(
id);
541 if (element->isRelevant()) {
542 modelComponents.stateLabeling.addLabel(element->name() +
"_failed");
543 modelComponents.stateLabeling.addLabel(element->name() +
"_dc");
546 std::vector<std::shared_ptr<storm::dft::storage::elements::DFTGate<ValueType>
const>> spares;
547 if (isAddLabelsClaiming) {
549 for (
size_t spareId : dft.getSpareIndices()) {
550 auto const& spare = dft.getGate(spareId);
551 spares.push_back(spare);
552 for (
auto const& child : spare->children()) {
553 modelComponents.stateLabeling.addLabel(spare->name() +
"_claimed_" + child->name());
559 if (this->uniqueFailedState) {
561 modelComponents.stateLabeling.addLabelToState(
"failed", 0);
562 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(dft.getTopLevelIndex());
563 STORM_LOG_ASSERT(element->isRelevant(),
"TLE should be relevant if unique failed state is used.");
564 modelComponents.stateLabeling.addLabelToState(element->name() +
"_failed", 0);
566 for (
auto const& stateIdPair : stateStorage.stateToId) {
568 size_t stateId = matrixBuilder.getRemapping(stateIdPair.second);
569 if (dft.hasFailed(state, *stateGenerationInfo)) {
570 modelComponents.stateLabeling.addLabelToState(
"failed", stateId);
573 for (
size_t id = 0;
id < dft.nrElements(); ++id) {
574 std::shared_ptr<storm::dft::storage::elements::DFTElement<ValueType>
const> element = dft.getElement(
id);
575 if (element->isRelevant()) {
578 switch (elementState) {
580 modelComponents.stateLabeling.addLabelToState(element->name() +
"_failed", stateId);
583 modelComponents.stateLabeling.addLabelToState(element->name() +
"_dc", stateId);
594 if (isAddLabelsClaiming) {
595 for (
auto const& spare : spares) {
596 size_t claimedChildId = dft.uses(state, *stateGenerationInfo, spare->id());
597 if (claimedChildId != spare->id()) {
598 modelComponents.stateLabeling.addLabelToState(spare->name() +
"_claimed_" + dft.getElement(claimedChildId)->name(), stateId);
607template<
typename ValueType,
typename StateType>
611 modelComponents.stateLabeling.addLabel(
"skipped");
612 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
613 modelComponents.stateLabeling.addLabelToState(
"skipped", it->first);
616 STORM_LOG_ASSERT(skippedStates.size() == 0,
"Concrete model has skipped states");
619 return createModel(
false);
622template<
typename ValueType,
typename StateType>
627 changeMatrixBound(modelComponents.transitionMatrix, lowerBound);
628 return createModel(
true);
636 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
637 auto matrixEntry = matrix.
getRow(it->first, 0).
begin();
638 STORM_LOG_ASSERT(matrixEntry->getColumn() == 0,
"Transition has wrong target state.");
639 STORM_LOG_ASSERT(!it->second.first->isPseudoState(),
"State is still pseudo state.");
640 matrixEntry->setValue(storm::utility::one<ValueType>());
641 matrixEntry->setColumn(it->first);
646 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
647 failedStates.
set(it->first);
649 labeling.
setStates(
"failed", failedStates);
652 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
653 if (modelComponents.deterministicModel) {
654 model = std::make_shared<storm::models::sparse::Ctmc<ValueType>>(std::move(matrix), std::move(labeling));
659 modelComponents.exitRates = std::vector<ValueType>(modelComponents.markovianStates.size());
660 std::vector<typename storm::storage::SparseMatrix<ValueType>::index_type> indices = matrix.
getRowGroupIndices();
661 for (StateType stateIndex = 0; stateIndex < modelComponents.markovianStates.size(); ++stateIndex) {
662 if (modelComponents.markovianStates[stateIndex]) {
663 modelComponents.exitRates[stateIndex] = matrix.
getRowSum(indices[stateIndex]);
665 modelComponents.exitRates[stateIndex] = storm::utility::zero<ValueType>();
673 maComponents.
exitRates = modelComponents.exitRates;
674 std::shared_ptr<storm::models::sparse::MarkovAutomaton<ValueType>> ma =
675 std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
676 if (ma->hasOnlyTrivialNondeterminism()) {
685 if (model->getNumberOfStates() <= 15) {
686 STORM_LOG_TRACE(
"Transition matrix: \n" << model->getTransitionMatrix());
694template<
typename ValueType,
typename StateType>
696 std::shared_ptr<storm::models::sparse::Model<ValueType>> model;
698 if (modelComponents.deterministicModel) {
701 model = std::make_shared<storm::models::sparse::Ctmc<ValueType>>(modelComponents.transitionMatrix, modelComponents.stateLabeling);
704 std::make_shared<storm::models::sparse::Ctmc<ValueType>>(std::move(modelComponents.transitionMatrix), std::move(modelComponents.stateLabeling));
710 modelComponents.exitRates = std::vector<ValueType>(modelComponents.markovianStates.size());
711 std::vector<typename storm::storage::SparseMatrix<ValueType>::index_type> indices = modelComponents.transitionMatrix.getRowGroupIndices();
712 for (StateType stateIndex = 0; stateIndex < modelComponents.markovianStates.size(); ++stateIndex) {
713 if (modelComponents.markovianStates[stateIndex]) {
714 modelComponents.exitRates[stateIndex] = modelComponents.transitionMatrix.getRowSum(indices[stateIndex]);
716 modelComponents.exitRates[stateIndex] = storm::utility::zero<ValueType>();
721 std::shared_ptr<storm::models::sparse::MarkovAutomaton<ValueType>> ma;
724 maComponents.rateTransitions =
true;
725 maComponents.markovianStates = modelComponents.markovianStates;
726 maComponents.exitRates = modelComponents.exitRates;
727 ma = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
730 std::move(modelComponents.stateLabeling));
731 maComponents.rateTransitions =
true;
732 maComponents.markovianStates = std::move(modelComponents.markovianStates);
733 maComponents.exitRates = std::move(modelComponents.exitRates);
734 ma = std::make_shared<storm::models::sparse::MarkovAutomaton<ValueType>>(std::move(maComponents));
736 if (ma->hasOnlyTrivialNondeterminism()) {
745 if (model->getNumberOfStates() <= 15) {
746 STORM_LOG_TRACE(
"Transition matrix: \n" << model->getTransitionMatrix());
753template<
typename ValueType,
typename StateType>
756 for (
auto it = skippedStates.begin(); it != skippedStates.end(); ++it) {
757 auto matrixEntry = matrix.
getRow(it->first, 0).
begin();
758 STORM_LOG_ASSERT(matrixEntry->getColumn() == 0,
"Transition has wrong target state.");
759 STORM_LOG_ASSERT(!it->second.first->isPseudoState(),
"State is still pseudo state.");
764 matrixEntry->setValue(getLowerBound(it->second.first));
766 matrixEntry->setValue(getUpperBound(it->second.first));
771template<
typename ValueType,
typename StateType>
772ValueType ExplicitDFTModelBuilder<ValueType, StateType>::getLowerBound(DFTStatePointer
const& state)
const {
774 ValueType lowerBound = storm::utility::zero<ValueType>();
775 STORM_LOG_ASSERT(!state->getFailableElements().hasDependencies(),
"Lower bound should only be computed if dependencies were already handled.");
776 for (
auto it = state->getFailableElements().begin(); it != state->getFailableElements().end(); ++it) {
777 lowerBound += state->getBERate(*it);
779 STORM_LOG_TRACE(
"Lower bound is " << lowerBound <<
" for state " << state->getId());
783template<
typename ValueType,
typename StateType>
784ValueType ExplicitDFTModelBuilder<ValueType, StateType>::getUpperBound(DFTStatePointer
const& state)
const {
785 if (state->hasFailed(dft.getTopLevelIndex())) {
786 return storm::utility::zero<ValueType>();
790 ValueType upperBound = storm::utility::one<ValueType>();
791 ValueType rateSum = storm::utility::zero<ValueType>();
794 for (std::vector<size_t>
const& subtree : subtreeBEs) {
796 std::vector<ValueType> rates;
798 for (
size_t i = 0;
i < subtree.size(); ++
i) {
799 size_t id = subtree[
i];
801 if (state->isOperational(
id)) {
802 auto be = dft.getBasicElement(
id);
803 switch (be->beType()) {
810 if (storm::utility::isZero<ValueType>(rate)) {
812 auto beExp = std::static_pointer_cast<storm::dft::storage::elements::BEExponential<ValueType>
const>(be);
813 rate = beExp->activeFailureRate();
814 STORM_LOG_ASSERT(!storm::utility::isZero<ValueType>(rate),
"Failure rate should not be zero.");
816 coldBEs.set(i,
true);
818 rates.push_back(rate);
823 STORM_LOG_THROW(
false, storm::exceptions::InvalidArgumentException,
"BE of type '" << be->beType() <<
"' is not known.");
831 std::sort(rates.begin(), rates.end());
832 std::vector<size_t> rateCount(rates.size(), 0);
833 size_t lastIndex = 0;
834 for (
size_t i = 0;
i < rates.size(); ++
i) {
835 if (rates[lastIndex] != rates[i]) {
838 ++rateCount[lastIndex];
841 for (
size_t i = 0;
i < rates.size(); ++
i) {
843 if (!coldBEs.get(i) && rateCount[i] > 0) {
844 std::iter_swap(rates.begin() + i, rates.end() - 1);
846 upperBound += rates.back() * rateCount[
i] * computeMTTFAnd(rates, rates.size() - 1);
849 std::iter_swap(rates.begin() + i, rates.end() - 1);
854 STORM_LOG_TRACE(
"Upper bound is " << (rateSum / upperBound) <<
" for state " << state->getId());
857 return rateSum / upperBound;
860template<
typename ValueType,
typename StateType>
861ValueType ExplicitDFTModelBuilder<ValueType, StateType>::computeMTTFAnd(std::vector<ValueType>
const& rates,
size_t size)
const {
862 ValueType result = storm::utility::zero<ValueType>();
894 for (
size_t i1 = 0; i1 < size; ++i1) {
898 for (
size_t i2 = 0; i2 < i1; ++i2) {
901 result -=
one / sum2;
902 for (
size_t i3 = 0; i3 < i2; ++i3) {
904 result +=
one / (sum2 + rates[i3]);
913template<
typename ValueType,
typename StateType>
914StateType ExplicitDFTModelBuilder<ValueType, StateType>::getOrAddStateIndex(DFTStatePointer
const& state) {
916 bool changed =
false;
918 if (stateGenerationInfo->hasSymmetries()) {
921 changed = state->orderBySymmetry();
922 STORM_LOG_TRACE(
"State " << (changed ?
"changed to " :
"did not change") << (changed ? dft.getStateString(state) :
""));
925 if (stateStorage.stateToId.contains(state->status())) {
927 stateId = stateStorage.stateToId.getValue(state->status());
928 STORM_LOG_TRACE(
"State " << dft.getStateString(state) <<
" with id " << stateId <<
" already exists");
932 auto iter = statesNotExplored.find(stateId);
933 if (iter != statesNotExplored.end() && iter->second.first->isPseudoState()) {
935 STORM_LOG_ASSERT(iter->second.first->getId() == stateId,
"Ids do not match.");
936 STORM_LOG_ASSERT(iter->second.first->status() == state->status(),
"Pseudo states do not coincide.");
937 state->setId(stateId);
940 statesNotExplored[stateId] = std::make_pair(state, iter->second.second);
947 STORM_LOG_ASSERT(state->isPseudoState() == changed,
"State type (pseudo/concrete) wrong.");
949 state->setId(newIndex++);
950 stateId = stateStorage.stateToId.findOrAdd(state->status(), state->getId());
953 ExplorationHeuristicPointer nullHeuristic;
954 statesNotExplored[stateId] = std::make_pair(state, nullHeuristic);
956 matrixBuilder.stateRemapping.push_back(0);
957 STORM_LOG_TRACE(
"New " << (state->isPseudoState() ?
"pseudo" :
"concrete") <<
" state: " << dft.getStateString(state));
962template<
typename ValueType,
typename StateType>
963void ExplicitDFTModelBuilder<ValueType, StateType>::setMarkovian(
bool markovian) {
964 if (matrixBuilder.getCurrentRowGroup() > modelComponents.markovianStates.size()) {
966 modelComponents.markovianStates.resize(modelComponents.markovianStates.size() + INITIAL_BITVECTOR_SIZE);
968 modelComponents.markovianStates.set(matrixBuilder.getCurrentRowGroup() - 1, markovian);
971template<
typename ValueType,
typename StateType>
972void ExplicitDFTModelBuilder<ValueType, StateType>::printNotExplored()
const {
973 std::cout <<
"states not explored:\n";
974 for (
auto it : statesNotExplored) {
975 std::cout << it.first <<
" -> " << dft.getStateString(it.second.first) <<
'\n';
980template class ExplicitDFTModelBuilder<double>;
981template 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.
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.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
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)
SettingsType const & getModule()
Get module.
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