32namespace modelchecker {
36template<
typename SparseDtmcModelType>
42template<
typename SparseDtmcModelType>
53template<
typename SparseDtmcModelType>
57 std::unique_ptr<CheckResult> subResultPointer = this->check(stateFormula);
61 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
62 if (psiStates.
empty()) {
63 return std::unique_ptr<CheckResult>(
66 if (psiStates.
full()) {
67 return std::unique_ptr<CheckResult>(
73 "Input model is required to have exactly one initial state.");
75 "Cannot compute long-run probabilities for all states.");
81 std::vector<ValueType> result(transitionMatrix.
getRowCount(), storm::utility::zero<ValueType>());
84 bool furtherComputationNeeded =
true;
86 STORM_LOG_DEBUG(
"The long-run probability for all initial states was found in a preprocessing step.");
87 furtherComputationNeeded =
false;
89 if (maybeStates.
empty()) {
90 STORM_LOG_DEBUG(
"The long-run probability for all states was found in a preprocessing step.");
91 furtherComputationNeeded =
false;
94 if (furtherComputationNeeded) {
101 maybeStates &= reachableStates;
104 std::vector<ValueType> stateValues(maybeStates.
size(), storm::utility::zero<ValueType>());
120template<
typename SparseDtmcModelType>
125 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
129 "Input model is required to have exactly one initial state.");
131 "Cannot compute long-run probabilities for all states.");
134 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
137 std::vector<ValueType> stateRewardValues = rewardModel.getTotalRewardVector(this->getModel().getTransitionMatrix());
140 uint_fast64_t index = 0;
141 for (
auto const& value : stateRewardValues) {
142 if (value != storm::utility::zero<ValueType>()) {
143 maybeStates.
set(index,
true);
153 std::vector<ValueType> result(numberOfStates, storm::utility::zero<ValueType>());
156 bool furtherComputationNeeded =
true;
158 furtherComputationNeeded =
false;
161 if (furtherComputationNeeded) {
168 maybeStates &= reachableStates;
185template<
typename SparseDtmcModelType>
186std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
191 bool computeResultsForInitialStatesOnly, std::vector<ValueType>& stateValues) {
192 std::chrono::high_resolution_clock::time_point totalTimeStart = std::chrono::high_resolution_clock::now();
195 std::chrono::high_resolution_clock::time_point sccDecompositionStart = std::chrono::high_resolution_clock::now();
198 auto sccDecompositionEnd = std::chrono::high_resolution_clock::now();
200 std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now();
204 flexibleMatrix.filterEntries(maybeStates, maybeStates);
206 flexibleBackwardTransitions.filterEntries(maybeStates, maybeStates);
207 auto conversionEnd = std::chrono::high_resolution_clock::now();
209 std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now();
213 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
219 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
223 std::vector<storm::storage::sparse::state_type> bsccRepresentatives;
224 uint_fast64_t currentIndex = 0;
225 for (
auto const& bscc : bsccDecomposition) {
228 if (maybeStates.
get(*bscc.cbegin())) {
229 relevantBsccs.set(currentIndex);
230 bsccRepresentatives.push_back(*bscc.cbegin());
231 bsccRepresentativesAsBitVector.set(*bscc.cbegin(),
true);
232 for (
auto const& state : bscc) {
233 regularStatesInBsccs.set(state,
true);
238 regularStatesInBsccs &= ~bsccRepresentativesAsBitVector;
241 std::vector<ValueType> averageTimeInStates(stateValues.size(), storm::utility::one<ValueType>());
244 std::shared_ptr<StatePriorityQueue> priorityQueue =
245 createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
247 stateValues, averageTimeInStates);
249 while (priorityQueue->hasNext()) {
251 stateEliminator.eliminateState(state,
true);
253 STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions),
"The forward and backward transition matrices became inconsistent.");
259 auto representativeIt = bsccRepresentatives.begin();
260 for (
auto sccIndex : relevantBsccs) {
263 ValueType bsccValue = stateValues[*representativeIt] / averageTimeInStates[*representativeIt];
264 auto const& bscc = bsccDecomposition[sccIndex];
265 if (!computeResultsForInitialStatesOnly) {
266 for (
auto const& state : bscc) {
267 stateValues[state] = bsccValue;
270 for (
auto const& state : bscc) {
271 stateValues[state] = storm::utility::zero<ValueType>();
273 stateValues[*representativeIt] = bsccValue;
276 FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt);
277 representativeForwardRow.clear();
278 representativeForwardRow.shrink_to_fit();
280 FlexibleRowType& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt);
281 auto it = representativeBackwardRow.begin(),
ite = representativeBackwardRow.end();
282 for (; it !=
ite; ++it) {
283 if (it->getColumn() == *representativeIt) {
287 representativeBackwardRow.erase(it);
298 for (
auto state : remainingStates) {
299 if (!bsccRepresentativesAsBitVector.get(state)) {
300 stateValues[state] = storm::utility::zero<ValueType>();
306 if (!relevantBsccs.empty()) {
307 performOrdinaryStateElimination(flexibleMatrix, flexibleBackwardTransitions, remainingStates, initialStates, computeResultsForInitialStatesOnly,
308 stateValues, distanceBasedPriorities);
311 std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now();
312 std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now();
315 std::chrono::high_resolution_clock::duration sccDecompositionTime = sccDecompositionEnd - sccDecompositionStart;
316 std::chrono::milliseconds sccDecompositionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(sccDecompositionTime);
317 std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart;
318 std::chrono::milliseconds conversionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(conversionTime);
319 std::chrono::high_resolution_clock::duration modelCheckingTime = modelCheckingEnd - modelCheckingStart;
320 std::chrono::milliseconds modelCheckingTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(modelCheckingTime);
321 std::chrono::high_resolution_clock::duration totalTime = totalTimeEnd - totalTimeStart;
322 std::chrono::milliseconds totalTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(totalTime);
326 STORM_PRINT_AND_LOG(
" * time for SCC decomposition: " << sccDecompositionTimeInMilliseconds.count() <<
"ms\n");
327 STORM_PRINT_AND_LOG(
" * time for conversion: " << conversionTimeInMilliseconds.count() <<
"ms\n");
328 STORM_PRINT_AND_LOG(
" * time for checking: " << modelCheckingTimeInMilliseconds.count() <<
"ms\n");
335 for (
auto& value : stateValues) {
341template<
typename SparseDtmcModelType>
347 "Formula needs to have single upper time bound.");
351 std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.
getLeftSubformula());
352 std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.
getRightSubformula());
353 storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
354 storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
359 this->getModel().getBackwardTransitions(), phiStates, psiStates,
true, pathFormula.
getUpperBound<uint64_t>());
360 statesWithProbabilityGreater0 &= ~psiStates;
363 bool furtherComputationNeeded =
true;
365 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
366 furtherComputationNeeded =
false;
367 }
else if (statesWithProbabilityGreater0.
empty()) {
368 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
369 furtherComputationNeeded =
false;
375 std::vector<ValueType> result(transitionMatrix.
getRowCount(), storm::utility::zero<ValueType>());
377 if (furtherComputationNeeded) {
378 uint_fast64_t timeBound = pathFormula.
getUpperBound<uint64_t>();
386 statesWithProbabilityGreater0 &= reachableStates;
391 transitionMatrix.
getSubmatrix(
true, statesWithProbabilityGreater0, statesWithProbabilityGreater0,
true);
393 std::vector<uint_fast64_t> distancesFromInitialStates;
410 std::vector<ValueType> subresult(b);
411 std::vector<ValueType> tmp(subresult.size());
417 for (uint_fast64_t timeStep = 0; timeStep < timeBound; ++timeStep) {
425 for (
auto state : relevantStates) {
426 if (distancesFromInitialStates[state] > (timeBound - timeStep)) {
427 for (
auto& element : submatrix.
getRow(state)) {
428 element.setValue(storm::utility::zero<ValueType>());
430 b[state] = storm::utility::zero<ValueType>();
431 relevantStates.
set(state,
false);
440 storm::utility::vector::setVectorValues<ValueType>(result, psiStates, storm::utility::one<ValueType>());
452template<
typename SparseDtmcModelType>
458 std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.
getLeftSubformula());
459 std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.
getRightSubformula());
460 storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
461 storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
463 return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(),
467template<
typename SparseDtmcModelType>
471 bool computeForInitialStatesOnly) {
473 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
480 bool furtherComputationNeeded =
true;
481 if (computeForInitialStatesOnly && initialStates.
isDisjointFrom(maybeStates)) {
482 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
483 furtherComputationNeeded =
false;
484 }
else if (maybeStates.
empty()) {
485 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
486 furtherComputationNeeded =
false;
489 std::vector<ValueType> result(maybeStates.
size());
490 if (furtherComputationNeeded) {
493 if (computeForInitialStatesOnly) {
499 maybeStates &= reachableStates;
503 std::vector<ValueType> oneStepProbabilities = probabilityMatrix.
getConstrainedRowSumVector(maybeStates, statesWithProbability1);
512 std::vector<ValueType> subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates,
513 computeForInitialStatesOnly, oneStepProbabilities);
514 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
518 storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability0, storm::utility::zero<ValueType>());
519 storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability1, storm::utility::one<ValueType>());
521 if (computeForInitialStatesOnly) {
524 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
525 for (
auto state : ~maybeStates | initialStates) {
526 (*checkResult)[state] = result[state];
528 return std::move(checkResult);
530 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
533template<
typename SparseDtmcModelType>
539 std::unique_ptr<CheckResult> subResultPointer = this->check(eventuallyFormula.
getSubformula());
541 storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
546 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
547 return computeReachabilityRewards(
548 this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates,
550 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
555template<
typename SparseDtmcModelType>
559 bool computeForInitialStatesOnly) {
560 return computeReachabilityRewards(
561 probabilityMatrix, backwardTransitions, initialStates, targetStates,
563 std::vector<ValueType> result(numberOfRows);
567 computeForInitialStatesOnly);
570template<
typename SparseDtmcModelType>
575 totalStateRewardVectorGetter,
576 bool computeForInitialStatesOnly) {
577 uint_fast64_t numberOfStates = probabilityMatrix.
getRowCount();
586 bool furtherComputationNeeded =
true;
587 if (computeForInitialStatesOnly) {
588 if (initialStates.
isSubsetOf(infinityStates)) {
589 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
590 furtherComputationNeeded =
false;
593 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
594 furtherComputationNeeded =
false;
598 std::vector<ValueType> result(maybeStates.
size());
599 if (furtherComputationNeeded) {
602 if (computeForInitialStatesOnly) {
607 maybeStates &= reachableStates;
618 std::vector<ValueType> stateRewardValues = totalStateRewardVectorGetter(submatrix.
getRowCount(), probabilityMatrix, maybeStates);
620 std::vector<ValueType> subresult =
621 computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly,
623 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
627 storm::utility::vector::setVectorValues<ValueType>(result, infinityStates, storm::utility::infinity<ValueType>());
628 storm::utility::vector::setVectorValues<ValueType>(result, targetStates, storm::utility::zero<ValueType>());
629 if (computeForInitialStatesOnly) {
632 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
633 for (
auto state : ~maybeStates | initialStates) {
634 (*checkResult)[state] = result[state];
636 return std::move(checkResult);
638 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
641template<
typename SparseDtmcModelType>
649 "Expected 'eventually' formula.");
661 STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException,
662 "Input model is required to have exactly one initial state.");
664 "Cannot compute conditional probabilities for all states.");
673 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
678 STORM_LOG_THROW(this->getModel().getInitialStates().isSubsetOf(statesWithProbabilityGreater0), storm::exceptions::InvalidPropertyException,
679 "The condition of the conditional probability has zero probability.");
682 if (this->getModel().getInitialStates().isSubsetOf(statesWithProbability1)) {
683 STORM_LOG_INFO(
"The condition holds with probability 1, so the regular reachability probability is computed.");
684 std::shared_ptr<storm::logic::BooleanLiteralFormula> trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(
true);
685 std::shared_ptr<storm::logic::UntilFormula> untilFormula =
687 return this->computeUntilProbabilities(env, *untilFormula);
704 std::vector<ValueType> oneStepProbabilities(maybeStates.
getNumberOfSetBits(), storm::utility::zero<ValueType>());
711 phiStates = phiStates % maybeStates;
714 if (phiStates.
empty()) {
718 psiStates = psiStates % maybeStates;
721 maybeStates = phiStates | psiStates;
727 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
738 std::shared_ptr<StatePriorityQueue> statePriorities =
739 createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
742 uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
743 STORM_LOG_INFO(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
744 performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(),
752 if (!flexibleBackwardTransitions.
getRow(*newInitialStates.
begin()).empty()) {
758 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
759 auto initialStateSuccessor = trans1.getColumn();
761 STORM_LOG_TRACE(
"Exploring successor " << initialStateSuccessor <<
" of the initial state.");
763 if (phiStates.
get(initialStateSuccessor)) {
767 if (psiStates.
get(initialStateSuccessor)) {
774 bool hasNonPsiSuccessor =
true;
775 while (hasNonPsiSuccessor) {
777 hasNonPsiSuccessor =
false;
780 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
781 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
782 for (
auto const& element : currentRow) {
784 if (!psiStates.
get(element.getColumn())) {
787 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
788 STORM_LOG_TRACE(
"Found non-psi successor " << element.getColumn() <<
" that needs to be eliminated.");
790 hasNonPsiSuccessor =
true;
794 STORM_LOG_ASSERT(!flexibleMatrix.
getRow(initialStateSuccessor).empty(),
"(1) New transitions expected to be non-empty.");
806 bool hasNonPhiSuccessor =
true;
807 while (hasNonPhiSuccessor) {
809 hasNonPhiSuccessor =
false;
812 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
813 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
814 for (
auto const& element : currentRow) {
816 if (!phiStates.
get(element.getColumn())) {
818 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
819 STORM_LOG_TRACE(
"Found non-phi successor " << element.getColumn() <<
" that needs to be eliminated.");
821 hasNonPhiSuccessor =
true;
831 ValueType numerator = storm::utility::zero<ValueType>();
832 ValueType denominator = storm::utility::zero<ValueType>();
834 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
835 auto initialStateSuccessor = trans1.getColumn();
836 if (phiStates.
get(initialStateSuccessor)) {
837 if (psiStates.
get(initialStateSuccessor)) {
838 numerator += trans1.getValue();
839 denominator += trans1.getValue();
841 ValueType additiveTerm = storm::utility::zero<ValueType>();
842 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
843 if (psiStates.
get(trans2.getColumn())) {
844 additiveTerm += trans2.getValue();
847 additiveTerm *= trans1.getValue();
848 numerator += additiveTerm;
849 denominator += additiveTerm;
853 denominator += trans1.getValue();
854 ValueType additiveTerm = storm::utility::zero<ValueType>();
855 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
856 if (phiStates.
get(trans2.getColumn())) {
857 additiveTerm += trans2.getValue();
860 numerator += trans1.getValue() * additiveTerm;
867template<
typename SparseDtmcModelType>
871 bool computeResultsForInitialStatesOnly) {
874 while (priorityQueue->hasNext()) {
876 bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.
get(state);
877 stateEliminator.eliminateState(state, removeForwardTransitions);
878 if (removeForwardTransitions) {
879 values[state] = storm::utility::zero<ValueType>();
882 STORM_LOG_ASSERT(checkConsistent(transitionMatrix, backwardTransitions),
"The forward and backward transition matrices became inconsistent.");
887template<
typename SparseDtmcModelType>
888void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(
891 std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
892 std::shared_ptr<StatePriorityQueue> statePriorities =
895 std::size_t numberOfStatesToEliminate = statePriorities->size();
896 STORM_LOG_DEBUG(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
897 performPrioritizedStateElimination(statePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
898 STORM_LOG_DEBUG(
"Eliminated " << numberOfStatesToEliminate <<
" states.\n");
901template<
typename SparseDtmcModelType>
902uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performHybridStateElimination(
906 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
908 std::vector<storm::storage::sparse::state_type> entryStateQueue;
909 STORM_LOG_DEBUG(
"Eliminating " << subsystem.
size() <<
" states using the hybrid elimination technique.\n");
910 uint_fast64_t maximalDepth = treatScc(transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions,
false, 0,
912 computeResultsForInitialStatesOnly, distanceBasedPriorities);
916 STORM_LOG_DEBUG(
"Eliminating " << entryStateQueue.size() <<
" entry states as a last step.");
917 std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
918 std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
919 performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
925template<
typename SparseDtmcModelType>
926std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
928 std::vector<ValueType>& values,
931 bool computeResultsForInitialStatesOnly,
932 std::vector<ValueType>
const& oneStepProbabilitiesToTarget) {
939 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
941 distanceBasedPriorities =
getDistanceBasedPriorities(transitionMatrix, backwardTransitions, initialStates, oneStepProbabilitiesToTarget,
950 performOrdinaryStateElimination(flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values,
951 distanceBasedPriorities);
954 uint64_t maximalDepth = performHybridStateElimination(transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates,
955 computeResultsForInitialStatesOnly, values, distanceBasedPriorities);
956 STORM_LOG_TRACE(
"Maximal depth of decomposition was " << maximalDepth <<
".");
959 STORM_LOG_ASSERT(flexibleMatrix.empty(),
"Not all transitions were eliminated.");
960 STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(),
"Not all transitions were eliminated.");
964 for (
auto& value : values) {
970template<
typename SparseDtmcModelType>
971uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::treatScc(
975 std::vector<storm::storage::sparse::state_type>& entryStateQueue,
bool computeResultsForInitialStatesOnly,
976 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
977 uint_fast64_t maximalDepth = level;
987 STORM_LOG_TRACE(
"Decomposed SCC into " << decomposition.size() <<
" sub-SCCs.");
995 for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) {
999 statesInTrivialSccs.
set(*scc.
begin(),
true);
1000 remainingSccs.set(sccIndex,
false);
1004 std::shared_ptr<StatePriorityQueue> statePriorities =
1006 STORM_LOG_TRACE(
"Eliminating " << statePriorities->size() <<
" trivial SCCs.");
1007 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1011 STORM_LOG_TRACE(
"Eliminating " << remainingSccs.getNumberOfSetBits() <<
" remaining SCCs on level " << level <<
".");
1012 for (
auto sccIndex : remainingSccs) {
1020 for (
auto const& state : newScc) {
1021 for (
auto const& predecessor : backwardTransitions.getRow(state)) {
1022 if (predecessor.getValue() != storm::utility::zero<ValueType>() && !newSccAsBitVector.get(predecessor.getColumn())) {
1023 entryStates.
set(state);
1029 uint_fast64_t depth =
1030 treatScc(matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions,
1032 level + 1, maximalSccSize, entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
1033 maximalDepth = std::max(maximalDepth, depth);
1037 STORM_LOG_TRACE(
"SCC of size " << scc.getNumberOfSetBits() <<
" is small enough to be eliminated directly.");
1038 std::shared_ptr<StatePriorityQueue> statePriorities =
1040 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1045 if (eliminateEntryStates) {
1048 performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1052 for (
auto state : entryStates) {
1053 entryStateQueue.push_back(state);
1057 return maximalDepth;
1060template<
typename SparseDtmcModelType>
1063 for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.
getRowCount(); ++forwardIndex) {
1064 for (
auto const& forwardEntry : transitionMatrix.getRow(forwardIndex)) {
1065 if (forwardEntry.getColumn() == forwardIndex) {
1069 bool foundCorrespondingElement =
false;
1070 for (
auto const& backwardEntry : backwardTransitions.getRow(forwardEntry.getColumn())) {
1071 if (backwardEntry.getColumn() == forwardIndex) {
1072 foundCorrespondingElement =
true;
1076 if (!foundCorrespondingElement) {
1084template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>>;
1086#ifdef STORM_HAVE_CARL
1087template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<storm::RationalNumber>>;
1088template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<storm::RationalFunction>>;
FragmentSpecification & setOnlyEventuallyFormuluasInConditionalFormulasAllowed(bool newValue)
FragmentSpecification & setCumulativeRewardFormulasAllowed(bool newValue)
FragmentSpecification & setConditionalProbabilityFormulasAllowed(bool newValue)
FragmentSpecification & setLongRunAverageProbabilitiesAllowed(bool newValue)
FragmentSpecification & setInstantaneousFormulasAllowed(bool newValue)
FragmentSpecification & setNestedOperatorsAllowed(bool newValue)
bool isRewardModelSet() const
Retrieves whether a reward model was set.
std::string const & getRewardModel() const
Retrieves the reward model over which to perform the checking (if set).
FormulaType const & getFormula() const
Retrieves the formula from this task.
bool isOnlyInitialStatesRelevantSet() const
Retrieves whether only the initial states are relevant in the computation.
virtual std::unique_ptr< CheckResult > computeBoundedUntilProbabilities(Environment const &env, CheckTask< storm::logic::BoundedUntilFormula, ValueType > const &checkTask) override
SparseDtmcModelType::ValueType ValueType
virtual std::unique_ptr< CheckResult > computeUntilProbabilities(Environment const &env, CheckTask< storm::logic::UntilFormula, ValueType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeLongRunAverageRewards(Environment const &env, CheckTask< storm::logic::LongRunAverageRewardFormula, ValueType > const &checkTask) override
SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc< ValueType > const &model)
Creates an elimination-based model checker for the given model.
virtual std::unique_ptr< CheckResult > computeLongRunAverageProbabilities(Environment const &env, CheckTask< storm::logic::StateFormula, ValueType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeReachabilityRewards(Environment const &env, CheckTask< storm::logic::EventuallyFormula, ValueType > const &checkTask) override
storm::storage::FlexibleSparseMatrix< ValueType >::row_type FlexibleRowType
virtual std::unique_ptr< CheckResult > computeConditionalProbabilities(Environment const &env, CheckTask< storm::logic::ConditionalFormula, ValueType > const &checkTask) override
virtual bool canHandle(CheckTask< storm::logic::Formula, ValueType > const &checkTask) const override
SparseDtmcModelType::RewardModelType RewardModelType
This class represents a discrete-time Markov chain.
EliminationOrder
An enum that contains all available state elimination orders.
void eliminateState(storm::storage::sparse::state_type state, bool removeForwardTransitions)
A bit vector that is internally represented as a vector of 64-bit values.
void complement()
Negates all bits in the bit vector.
bool isDisjointFrom(BitVector const &other) const
Checks whether none of the bits that are set in the current bit vector are also set in the given bit ...
bool full() const
Retrieves whether all bits are set in this bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
bool isSubsetOf(BitVector const &other) const
Checks whether all bits that are set in the current bit vector are also set in the given bit vector.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
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.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
The flexible sparse matrix is used during state elimination.
row_type & getRow(index_type)
Returns an object representing the given row.
index_type getRowCount() const
Returns the number of rows of the matrix.
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.
void multiplyWithVector(std::vector< value_type > const &vector, std::vector< value_type > &result, std::vector< value_type > const *summand=nullptr) const
Multiplies the matrix with the given vector and writes the result to the given result vector.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
std::vector< value_type > getConstrainedRowSumVector(storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint) const
Computes a vector whose i-th entry is the sum of the entries in the i-th selected row where only thos...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
iterator begin()
Returns an iterator to the states in this SCC.
iterator end()
Returns an iterator that points one past the end of the states in this SCC.
This class represents the decomposition of a graph-like structure into its strongly connected compone...
This class represents a strongly connected component, i.e., a set of states such that every state can...
bool isTrivial() const
Retrieves whether this SCC is trivial.
#define STORM_LOG_INFO(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
#define STORM_PRINT_AND_LOG(message)
SFTBDDChecker::ValueType ValueType
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
FragmentSpecification prctl()
SettingsType const & getModule()
Get module.
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01(storm::models::sparse::DeterministicModel< T > const &model, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 or 1, respectively, of satisfying phi until psi i...
storm::storage::BitVector getReachableStates(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, storm::storage::BitVector const &constraintStates, storm::storage::BitVector const &targetStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceFilter)
Performs a forward depth-first search through the underlying graph structure to identify the states t...
storm::storage::BitVector performProbGreater0(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Performs a backward depth-first search trough the underlying graph structure of the given model to de...
storm::storage::BitVector performProb1(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &, storm::storage::BitVector const &psiStates, storm::storage::BitVector const &statesWithProbabilityGreater0)
Computes the set of states of the given model for which all paths lead to the given set of target sta...
std::vector< uint_fast64_t > getDistances(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates, boost::optional< storm::storage::BitVector > const &subsystem)
Performs a breadth-first search through the underlying graph structure to compute the distance from a...
std::shared_ptr< StatePriorityQueue > createStatePriorityQueue(boost::optional< std::vector< uint_fast64_t > > const &distanceBasedStatePriorities, storm::storage::FlexibleSparseMatrix< ValueType > const &transitionMatrix, storm::storage::FlexibleSparseMatrix< ValueType > const &backwardTransitions, std::vector< ValueType > const &oneStepProbabilities, storm::storage::BitVector const &states)
bool eliminationOrderNeedsForwardDistances(storm::settings::modules::EliminationSettings::EliminationOrder const &order)
bool eliminationOrderNeedsDistances(storm::settings::modules::EliminationSettings::EliminationOrder const &order)
std::vector< uint_fast64_t > getDistanceBasedPriorities(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &transitionMatrixTransposed, storm::storage::BitVector const &initialStates, std::vector< ValueType > const &oneStepProbabilities, bool forward, bool reverse)
bool eliminationOrderNeedsReversedDistances(storm::settings::modules::EliminationSettings::EliminationOrder const &order)
void addVectors(std::vector< InValueType1 > const &firstOperand, std::vector< InValueType2 > const &secondOperand, std::vector< OutValueType > &target)
Adds the two given vectors and writes the result to the target vector.
void setVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Sets the provided values at the provided positions in the given vector.
void selectVectorValues(std::vector< T > &vector, storm::storage::BitVector const &positions, std::vector< T > const &values)
Selects the elements from a vector at the specified positions and writes them consecutively into anot...
ValueType simplify(ValueType value)