29namespace modelchecker {
33template<
typename SparseDtmcModelType>
39template<
typename SparseDtmcModelType>
50template<
typename SparseDtmcModelType>
54 std::unique_ptr<CheckResult> subResultPointer = this->check(stateFormula);
58 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
59 if (psiStates.
empty()) {
60 return std::unique_ptr<CheckResult>(
63 if (psiStates.
full()) {
64 return std::unique_ptr<CheckResult>(
70 "Input model is required to have exactly one initial state.");
72 "Cannot compute long-run probabilities for all states.");
78 std::vector<ValueType> result(transitionMatrix.
getRowCount(), storm::utility::zero<ValueType>());
81 bool furtherComputationNeeded =
true;
83 STORM_LOG_DEBUG(
"The long-run probability for all initial states was found in a preprocessing step.");
84 furtherComputationNeeded =
false;
86 if (maybeStates.
empty()) {
87 STORM_LOG_DEBUG(
"The long-run probability for all states was found in a preprocessing step.");
88 furtherComputationNeeded =
false;
91 if (furtherComputationNeeded) {
98 maybeStates &= reachableStates;
101 std::vector<ValueType> stateValues(maybeStates.
size(), storm::utility::zero<ValueType>());
117template<
typename SparseDtmcModelType>
122 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
126 "Input model is required to have exactly one initial state.");
128 "Cannot compute long-run probabilities for all states.");
131 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
134 std::vector<ValueType> stateRewardValues = rewardModel.getTotalRewardVector(this->getModel().getTransitionMatrix());
137 uint_fast64_t index = 0;
138 for (
auto const& value : stateRewardValues) {
139 if (value != storm::utility::zero<ValueType>()) {
140 maybeStates.
set(index,
true);
150 std::vector<ValueType> result(numberOfStates, storm::utility::zero<ValueType>());
153 bool furtherComputationNeeded =
true;
155 furtherComputationNeeded =
false;
158 if (furtherComputationNeeded) {
165 maybeStates &= reachableStates;
182template<
typename SparseDtmcModelType>
183std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
188 bool computeResultsForInitialStatesOnly, std::vector<ValueType>& stateValues) {
189 std::chrono::high_resolution_clock::time_point totalTimeStart = std::chrono::high_resolution_clock::now();
192 std::chrono::high_resolution_clock::time_point sccDecompositionStart = std::chrono::high_resolution_clock::now();
195 auto sccDecompositionEnd = std::chrono::high_resolution_clock::now();
197 std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now();
201 flexibleMatrix.filterEntries(maybeStates, maybeStates);
203 flexibleBackwardTransitions.filterEntries(maybeStates, maybeStates);
204 auto conversionEnd = std::chrono::high_resolution_clock::now();
206 std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now();
209 storm::settings::getModule<storm::settings::modules::EliminationSettings>().getEliminationOrder();
210 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
216 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
220 std::vector<storm::storage::sparse::state_type> bsccRepresentatives;
221 uint_fast64_t currentIndex = 0;
222 for (
auto const& bscc : bsccDecomposition) {
225 if (maybeStates.
get(*bscc.cbegin())) {
226 relevantBsccs.set(currentIndex);
227 bsccRepresentatives.push_back(*bscc.cbegin());
228 bsccRepresentativesAsBitVector.set(*bscc.cbegin(),
true);
229 for (
auto const& state : bscc) {
230 regularStatesInBsccs.set(state,
true);
235 regularStatesInBsccs &= ~bsccRepresentativesAsBitVector;
238 std::vector<ValueType> averageTimeInStates(stateValues.size(), storm::utility::one<ValueType>());
241 std::shared_ptr<StatePriorityQueue> priorityQueue =
242 createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
244 stateValues, averageTimeInStates);
246 while (priorityQueue->hasNext()) {
248 stateEliminator.eliminateState(state,
true);
250 STORM_LOG_ASSERT(checkConsistent(flexibleMatrix, flexibleBackwardTransitions),
"The forward and backward transition matrices became inconsistent.");
256 auto representativeIt = bsccRepresentatives.begin();
257 for (
auto sccIndex : relevantBsccs) {
260 ValueType bsccValue = stateValues[*representativeIt] / averageTimeInStates[*representativeIt];
261 auto const& bscc = bsccDecomposition[sccIndex];
262 if (!computeResultsForInitialStatesOnly) {
263 for (
auto const& state : bscc) {
264 stateValues[state] = bsccValue;
267 for (
auto const& state : bscc) {
268 stateValues[state] = storm::utility::zero<ValueType>();
270 stateValues[*representativeIt] = bsccValue;
273 FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt);
274 representativeForwardRow.clear();
275 representativeForwardRow.shrink_to_fit();
277 FlexibleRowType& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt);
278 auto it = representativeBackwardRow.begin(),
ite = representativeBackwardRow.end();
279 for (; it !=
ite; ++it) {
280 if (it->getColumn() == *representativeIt) {
284 representativeBackwardRow.erase(it);
295 for (
auto state : remainingStates) {
296 if (!bsccRepresentativesAsBitVector.get(state)) {
297 stateValues[state] = storm::utility::zero<ValueType>();
303 if (!relevantBsccs.empty()) {
304 performOrdinaryStateElimination(flexibleMatrix, flexibleBackwardTransitions, remainingStates, initialStates, computeResultsForInitialStatesOnly,
305 stateValues, distanceBasedPriorities);
308 std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now();
309 std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now();
311 if (storm::settings::getModule<storm::settings::modules::CoreSettings>().isShowStatisticsSet()) {
312 std::chrono::high_resolution_clock::duration sccDecompositionTime = sccDecompositionEnd - sccDecompositionStart;
313 std::chrono::milliseconds sccDecompositionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(sccDecompositionTime);
314 std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart;
315 std::chrono::milliseconds conversionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(conversionTime);
316 std::chrono::high_resolution_clock::duration modelCheckingTime = modelCheckingEnd - modelCheckingStart;
317 std::chrono::milliseconds modelCheckingTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(modelCheckingTime);
318 std::chrono::high_resolution_clock::duration totalTime = totalTimeEnd - totalTimeStart;
319 std::chrono::milliseconds totalTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(totalTime);
323 STORM_PRINT_AND_LOG(
" * time for SCC decomposition: " << sccDecompositionTimeInMilliseconds.count() <<
"ms\n");
324 STORM_PRINT_AND_LOG(
" * time for conversion: " << conversionTimeInMilliseconds.count() <<
"ms\n");
325 STORM_PRINT_AND_LOG(
" * time for checking: " << modelCheckingTimeInMilliseconds.count() <<
"ms\n");
332 for (
auto& value : stateValues) {
338template<
typename SparseDtmcModelType>
344 "Formula needs to have single upper time bound.");
348 std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.
getLeftSubformula());
349 std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.
getRightSubformula());
350 storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
351 storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
356 this->getModel().getBackwardTransitions(), phiStates, psiStates,
true, pathFormula.
getUpperBound<uint64_t>());
357 statesWithProbabilityGreater0 &= ~psiStates;
360 bool furtherComputationNeeded =
true;
362 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
363 furtherComputationNeeded =
false;
364 }
else if (statesWithProbabilityGreater0.
empty()) {
365 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
366 furtherComputationNeeded =
false;
372 std::vector<ValueType> result(transitionMatrix.
getRowCount(), storm::utility::zero<ValueType>());
374 if (furtherComputationNeeded) {
375 uint_fast64_t timeBound = pathFormula.
getUpperBound<uint64_t>();
383 statesWithProbabilityGreater0 &= reachableStates;
388 transitionMatrix.
getSubmatrix(
true, statesWithProbabilityGreater0, statesWithProbabilityGreater0,
true);
390 std::vector<uint_fast64_t> distancesFromInitialStates;
407 std::vector<ValueType> subresult(b);
408 std::vector<ValueType> tmp(subresult.size());
414 for (uint_fast64_t timeStep = 0; timeStep < timeBound; ++timeStep) {
422 for (
auto state : relevantStates) {
423 if (distancesFromInitialStates[state] > (timeBound - timeStep)) {
424 for (
auto& element : submatrix.
getRow(state)) {
425 element.setValue(storm::utility::zero<ValueType>());
427 b[state] = storm::utility::zero<ValueType>();
428 relevantStates.
set(state,
false);
437 storm::utility::vector::setVectorValues<ValueType>(result, psiStates, storm::utility::one<ValueType>());
449template<
typename SparseDtmcModelType>
455 std::unique_ptr<CheckResult> leftResultPointer = this->check(pathFormula.
getLeftSubformula());
456 std::unique_ptr<CheckResult> rightResultPointer = this->check(pathFormula.
getRightSubformula());
457 storm::storage::BitVector const& phiStates = leftResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
458 storm::storage::BitVector const& psiStates = rightResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
460 return computeUntilProbabilities(this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(),
464template<
typename SparseDtmcModelType>
468 bool computeForInitialStatesOnly) {
470 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
477 bool furtherComputationNeeded =
true;
478 if (computeForInitialStatesOnly && initialStates.
isDisjointFrom(maybeStates)) {
479 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
480 furtherComputationNeeded =
false;
481 }
else if (maybeStates.
empty()) {
482 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
483 furtherComputationNeeded =
false;
486 std::vector<ValueType> result(maybeStates.
size());
487 if (furtherComputationNeeded) {
490 if (computeForInitialStatesOnly) {
496 maybeStates &= reachableStates;
500 std::vector<ValueType> oneStepProbabilities = probabilityMatrix.
getConstrainedRowSumVector(maybeStates, statesWithProbability1);
509 std::vector<ValueType> subresult = computeReachabilityValues(submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates,
510 computeForInitialStatesOnly, oneStepProbabilities);
511 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
515 storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability0, storm::utility::zero<ValueType>());
516 storm::utility::vector::setVectorValues<ValueType>(result, statesWithProbability1, storm::utility::one<ValueType>());
518 if (computeForInitialStatesOnly) {
521 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
522 for (
auto state : ~maybeStates | initialStates) {
523 (*checkResult)[state] = result[state];
525 return std::move(checkResult);
527 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
530template<
typename SparseDtmcModelType>
536 std::unique_ptr<CheckResult> subResultPointer = this->check(eventuallyFormula.
getSubformula());
538 storm::storage::BitVector const& targetStates = subResultPointer->asExplicitQualitativeCheckResult().getTruthValuesVector();
543 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
544 return computeReachabilityRewards(
545 this->getModel().getTransitionMatrix(), this->getModel().getBackwardTransitions(), this->getModel().getInitialStates(), targetStates,
547 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
552template<
typename SparseDtmcModelType>
556 bool computeForInitialStatesOnly) {
557 return computeReachabilityRewards(
558 probabilityMatrix, backwardTransitions, initialStates, targetStates,
560 std::vector<ValueType> result(numberOfRows);
564 computeForInitialStatesOnly);
567template<
typename SparseDtmcModelType>
572 totalStateRewardVectorGetter,
573 bool computeForInitialStatesOnly) {
574 uint_fast64_t numberOfStates = probabilityMatrix.
getRowCount();
583 bool furtherComputationNeeded =
true;
584 if (computeForInitialStatesOnly) {
585 if (initialStates.
isSubsetOf(infinityStates)) {
586 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
587 furtherComputationNeeded =
false;
590 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
591 furtherComputationNeeded =
false;
595 std::vector<ValueType> result(maybeStates.
size());
596 if (furtherComputationNeeded) {
599 if (computeForInitialStatesOnly) {
604 maybeStates &= reachableStates;
615 std::vector<ValueType> stateRewardValues = totalStateRewardVectorGetter(submatrix.
getRowCount(), probabilityMatrix, maybeStates);
617 std::vector<ValueType> subresult =
618 computeReachabilityValues(submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly,
620 storm::utility::vector::setVectorValues<ValueType>(result, maybeStates, subresult);
624 storm::utility::vector::setVectorValues<ValueType>(result, infinityStates, storm::utility::infinity<ValueType>());
625 storm::utility::vector::setVectorValues<ValueType>(result, targetStates, storm::utility::zero<ValueType>());
626 if (computeForInitialStatesOnly) {
629 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
630 for (
auto state : ~maybeStates | initialStates) {
631 (*checkResult)[state] = result[state];
633 return std::move(checkResult);
635 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
638template<
typename SparseDtmcModelType>
646 "Expected 'eventually' formula.");
658 STORM_LOG_THROW(this->getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException,
659 "Input model is required to have exactly one initial state.");
661 "Cannot compute conditional probabilities for all states.");
670 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
675 STORM_LOG_THROW(this->getModel().getInitialStates().isSubsetOf(statesWithProbabilityGreater0), storm::exceptions::InvalidPropertyException,
676 "The condition of the conditional probability has zero probability.");
679 if (this->getModel().getInitialStates().isSubsetOf(statesWithProbability1)) {
680 STORM_LOG_INFO(
"The condition holds with probability 1, so the regular reachability probability is computed.");
681 std::shared_ptr<storm::logic::BooleanLiteralFormula> trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(
true);
682 std::shared_ptr<storm::logic::UntilFormula> untilFormula =
684 return this->computeUntilProbabilities(env, *untilFormula);
701 std::vector<ValueType> oneStepProbabilities(maybeStates.
getNumberOfSetBits(), storm::utility::zero<ValueType>());
708 phiStates = phiStates % maybeStates;
711 if (phiStates.
empty()) {
715 psiStates = psiStates % maybeStates;
718 maybeStates = phiStates | psiStates;
724 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
726 storm::settings::getModule<storm::settings::modules::EliminationSettings>().getEliminationOrder();
735 std::shared_ptr<StatePriorityQueue> statePriorities =
736 createStatePriorityQueue(distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
739 uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
740 STORM_LOG_INFO(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
741 performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->getModel().getInitialStates(),
749 if (!flexibleBackwardTransitions.
getRow(*newInitialStates.
begin()).empty()) {
755 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
756 auto initialStateSuccessor = trans1.getColumn();
758 STORM_LOG_TRACE(
"Exploring successor " << initialStateSuccessor <<
" of the initial state.");
760 if (phiStates.
get(initialStateSuccessor)) {
764 if (psiStates.
get(initialStateSuccessor)) {
771 bool hasNonPsiSuccessor =
true;
772 while (hasNonPsiSuccessor) {
774 hasNonPsiSuccessor =
false;
777 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
778 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
779 for (
auto const& element : currentRow) {
781 if (!psiStates.
get(element.getColumn())) {
784 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
785 STORM_LOG_TRACE(
"Found non-psi successor " << element.getColumn() <<
" that needs to be eliminated.");
787 hasNonPsiSuccessor =
true;
791 STORM_LOG_ASSERT(!flexibleMatrix.
getRow(initialStateSuccessor).empty(),
"(1) New transitions expected to be non-empty.");
803 bool hasNonPhiSuccessor =
true;
804 while (hasNonPhiSuccessor) {
806 hasNonPhiSuccessor =
false;
809 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
810 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
811 for (
auto const& element : currentRow) {
813 if (!phiStates.
get(element.getColumn())) {
815 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
816 STORM_LOG_TRACE(
"Found non-phi successor " << element.getColumn() <<
" that needs to be eliminated.");
818 hasNonPhiSuccessor =
true;
828 ValueType numerator = storm::utility::zero<ValueType>();
829 ValueType denominator = storm::utility::zero<ValueType>();
831 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
832 auto initialStateSuccessor = trans1.getColumn();
833 if (phiStates.
get(initialStateSuccessor)) {
834 if (psiStates.
get(initialStateSuccessor)) {
835 numerator += trans1.getValue();
836 denominator += trans1.getValue();
838 ValueType additiveTerm = storm::utility::zero<ValueType>();
839 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
840 if (psiStates.
get(trans2.getColumn())) {
841 additiveTerm += trans2.getValue();
844 additiveTerm *= trans1.getValue();
845 numerator += additiveTerm;
846 denominator += additiveTerm;
850 denominator += trans1.getValue();
851 ValueType additiveTerm = storm::utility::zero<ValueType>();
852 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
853 if (phiStates.
get(trans2.getColumn())) {
854 additiveTerm += trans2.getValue();
857 numerator += trans1.getValue() * additiveTerm;
864template<
typename SparseDtmcModelType>
868 bool computeResultsForInitialStatesOnly) {
871 while (priorityQueue->hasNext()) {
873 bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.
get(state);
874 stateEliminator.eliminateState(state, removeForwardTransitions);
875 if (removeForwardTransitions) {
876 values[state] = storm::utility::zero<ValueType>();
879 STORM_LOG_ASSERT(checkConsistent(transitionMatrix, backwardTransitions),
"The forward and backward transition matrices became inconsistent.");
884template<
typename SparseDtmcModelType>
885void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(
888 std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
889 std::shared_ptr<StatePriorityQueue> statePriorities =
892 std::size_t numberOfStatesToEliminate = statePriorities->size();
893 STORM_LOG_DEBUG(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
894 performPrioritizedStateElimination(statePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
895 STORM_LOG_DEBUG(
"Eliminated " << numberOfStatesToEliminate <<
" states.\n");
898template<
typename SparseDtmcModelType>
899uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performHybridStateElimination(
903 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
905 std::vector<storm::storage::sparse::state_type> entryStateQueue;
906 STORM_LOG_DEBUG(
"Eliminating " << subsystem.
size() <<
" states using the hybrid elimination technique.\n");
907 uint_fast64_t maximalDepth = treatScc(transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions,
false, 0,
908 storm::settings::getModule<storm::settings::modules::EliminationSettings>().getMaximalSccSize(), entryStateQueue,
909 computeResultsForInitialStatesOnly, distanceBasedPriorities);
912 if (storm::settings::getModule<storm::settings::modules::EliminationSettings>().isEliminateEntryStatesLastSet()) {
913 STORM_LOG_DEBUG(
"Eliminating " << entryStateQueue.size() <<
" entry states as a last step.");
914 std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
915 std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
916 performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
922template<
typename SparseDtmcModelType>
923std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
925 std::vector<ValueType>& values,
928 bool computeResultsForInitialStatesOnly,
929 std::vector<ValueType>
const& oneStepProbabilitiesToTarget) {
935 storm::settings::getModule<storm::settings::modules::EliminationSettings>().getEliminationOrder();
936 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
938 distanceBasedPriorities =
getDistanceBasedPriorities(transitionMatrix, backwardTransitions, initialStates, oneStepProbabilitiesToTarget,
945 if (storm::settings::getModule<storm::settings::modules::EliminationSettings>().getEliminationMethod() ==
947 performOrdinaryStateElimination(flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values,
948 distanceBasedPriorities);
949 }
else if (storm::settings::getModule<storm::settings::modules::EliminationSettings>().getEliminationMethod() ==
951 uint64_t maximalDepth = performHybridStateElimination(transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates,
952 computeResultsForInitialStatesOnly, values, distanceBasedPriorities);
953 STORM_LOG_TRACE(
"Maximal depth of decomposition was " << maximalDepth <<
".");
956 STORM_LOG_ASSERT(flexibleMatrix.empty(),
"Not all transitions were eliminated.");
957 STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(),
"Not all transitions were eliminated.");
961 for (
auto& value : values) {
967template<
typename SparseDtmcModelType>
968uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::treatScc(
972 std::vector<storm::storage::sparse::state_type>& entryStateQueue,
bool computeResultsForInitialStatesOnly,
973 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
974 uint_fast64_t maximalDepth = level;
984 STORM_LOG_TRACE(
"Decomposed SCC into " << decomposition.size() <<
" sub-SCCs.");
992 for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) {
996 statesInTrivialSccs.
set(*scc.
begin(),
true);
997 remainingSccs.set(sccIndex,
false);
1001 std::shared_ptr<StatePriorityQueue> statePriorities =
1003 STORM_LOG_TRACE(
"Eliminating " << statePriorities->size() <<
" trivial SCCs.");
1004 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1008 STORM_LOG_TRACE(
"Eliminating " << remainingSccs.getNumberOfSetBits() <<
" remaining SCCs on level " << level <<
".");
1009 for (
auto sccIndex : remainingSccs) {
1017 for (
auto const& state : newScc) {
1018 for (
auto const& predecessor : backwardTransitions.getRow(state)) {
1019 if (predecessor.getValue() != storm::utility::zero<ValueType>() && !newSccAsBitVector.get(predecessor.getColumn())) {
1020 entryStates.
set(state);
1026 uint_fast64_t depth =
1027 treatScc(matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions,
1028 eliminateEntryStates || !storm::settings::getModule<storm::settings::modules::EliminationSettings>().isEliminateEntryStatesLastSet(),
1029 level + 1, maximalSccSize, entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
1030 maximalDepth = std::max(maximalDepth, depth);
1034 STORM_LOG_TRACE(
"SCC of size " << scc.getNumberOfSetBits() <<
" is small enough to be eliminated directly.");
1035 std::shared_ptr<StatePriorityQueue> statePriorities =
1037 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1042 if (eliminateEntryStates) {
1045 performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1049 for (
auto state : entryStates) {
1050 entryStateQueue.push_back(state);
1054 return maximalDepth;
1057template<
typename SparseDtmcModelType>
1060 for (uint_fast64_t forwardIndex = 0; forwardIndex < transitionMatrix.
getRowCount(); ++forwardIndex) {
1061 for (
auto const& forwardEntry : transitionMatrix.getRow(forwardIndex)) {
1062 if (forwardEntry.getColumn() == forwardIndex) {
1066 bool foundCorrespondingElement =
false;
1067 for (
auto const& backwardEntry : backwardTransitions.getRow(forwardEntry.getColumn())) {
1068 if (backwardEntry.getColumn() == forwardIndex) {
1069 foundCorrespondingElement =
true;
1073 if (!foundCorrespondingElement) {
1081template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<double>>;
1083template class SparseDtmcEliminationModelChecker<storm::models::sparse::Dtmc<storm::RationalNumber>>;
1084template 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.
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.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint64_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()
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)