30template<
typename SparseDtmcModelType>
36template<
typename SparseDtmcModelType>
47template<
typename SparseDtmcModelType>
51 std::unique_ptr<CheckResult> subResultPointer = this->
check(stateFormula);
52 storm::storage::BitVector const& psiStates = subResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
55 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
56 if (psiStates.
empty()) {
57 return std::unique_ptr<CheckResult>(
60 if (psiStates.
full()) {
61 return std::unique_ptr<CheckResult>(
67 "Input model is required to have exactly one initial state.");
69 "Cannot compute long-run probabilities for all states.");
78 bool furtherComputationNeeded =
true;
80 STORM_LOG_DEBUG(
"The long-run probability for all initial states was found in a preprocessing step.");
81 furtherComputationNeeded =
false;
83 if (maybeStates.
empty()) {
84 STORM_LOG_DEBUG(
"The long-run probability for all states was found in a preprocessing step.");
85 furtherComputationNeeded =
false;
88 if (furtherComputationNeeded) {
95 maybeStates &= reachableStates;
114template<
typename SparseDtmcModelType>
119 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
123 "Input model is required to have exactly one initial state.");
125 "Cannot compute long-run probabilities for all states.");
128 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
131 std::vector<ValueType> stateRewardValues = rewardModel.getTotalRewardVector(this->
getModel().getTransitionMatrix());
134 uint_fast64_t index = 0;
135 for (
auto const& value : stateRewardValues) {
137 maybeStates.
set(index,
true);
150 bool furtherComputationNeeded =
true;
152 furtherComputationNeeded =
false;
155 if (furtherComputationNeeded) {
162 maybeStates &= reachableStates;
179template<
typename SparseDtmcModelType>
180std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::SolutionType>
181SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeLongRunValues(
Environment const& env,
186 bool computeResultsForInitialStatesOnly, std::vector<ValueType>& stateValues) {
187 std::chrono::high_resolution_clock::time_point totalTimeStart = std::chrono::high_resolution_clock::now();
190 std::chrono::high_resolution_clock::time_point sccDecompositionStart = std::chrono::high_resolution_clock::now();
193 auto sccDecompositionEnd = std::chrono::high_resolution_clock::now();
195 std::chrono::high_resolution_clock::time_point conversionStart = std::chrono::high_resolution_clock::now();
199 flexibleMatrix.filterEntries(maybeStates, maybeStates);
201 flexibleBackwardTransitions.filterEntries(maybeStates, maybeStates);
202 auto conversionEnd = std::chrono::high_resolution_clock::now();
204 std::chrono::high_resolution_clock::time_point modelCheckingStart = std::chrono::high_resolution_clock::now();
207 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
209 distanceBasedPriorities =
getDistanceBasedPriorities(order, transitionMatrix, backwardTransitions, initialStates, stateValues,
213 uint_fast64_t numberOfStates = transitionMatrix.
getRowCount();
217 std::vector<storm::storage::sparse::state_type> bsccRepresentatives;
218 uint_fast64_t currentIndex = 0;
219 for (
auto const& bscc : bsccDecomposition) {
222 if (maybeStates.
get(*bscc.cbegin())) {
223 relevantBsccs.set(currentIndex);
224 bsccRepresentatives.push_back(*bscc.cbegin());
225 bsccRepresentativesAsBitVector.set(*bscc.cbegin(),
true);
226 for (
auto const& state : bscc) {
227 regularStatesInBsccs.set(state,
true);
232 regularStatesInBsccs &= ~bsccRepresentativesAsBitVector;
238 std::shared_ptr<StatePriorityQueue> priorityQueue =
239 createStatePriorityQueue(order, distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, stateValues, regularStatesInBsccs);
240 storm::solver::stateelimination::MultiValueStateEliminator<ValueType> stateEliminator(flexibleMatrix, flexibleBackwardTransitions, priorityQueue,
241 stateValues, averageTimeInStates);
243 while (priorityQueue->hasNext()) {
245 stateEliminator.eliminateState(state,
true);
250 auto representativeIt = bsccRepresentatives.begin();
251 for (uint64_t sccIndex : relevantBsccs) {
254 ValueType bsccValue = stateValues[*representativeIt] / averageTimeInStates[*representativeIt];
255 auto const& bscc = bsccDecomposition[sccIndex];
256 if (!computeResultsForInitialStatesOnly) {
257 for (
auto const& state : bscc) {
258 stateValues[state] = bsccValue;
261 for (
auto const& state : bscc) {
264 stateValues[*representativeIt] = bsccValue;
267 FlexibleRowType& representativeForwardRow = flexibleMatrix.getRow(*representativeIt);
268 representativeForwardRow.clear();
269 representativeForwardRow.shrink_to_fit();
271 FlexibleRowType& representativeBackwardRow = flexibleBackwardTransitions.getRow(*representativeIt);
272 auto it = representativeBackwardRow.begin(),
ite = representativeBackwardRow.end();
273 for (; it !=
ite; ++it) {
274 if (it->getColumn() == *representativeIt) {
278 representativeBackwardRow.erase(it);
284 storm::storage::BitVector remainingStates = maybeStates & ~regularStatesInBsccs;
289 for (uint64_t state : remainingStates) {
290 if (!bsccRepresentativesAsBitVector.get(state)) {
297 if (!relevantBsccs.empty()) {
298 performOrdinaryStateElimination(env, flexibleMatrix, flexibleBackwardTransitions, remainingStates, initialStates, computeResultsForInitialStatesOnly,
299 stateValues, distanceBasedPriorities);
302 std::chrono::high_resolution_clock::time_point modelCheckingEnd = std::chrono::high_resolution_clock::now();
303 std::chrono::high_resolution_clock::time_point totalTimeEnd = std::chrono::high_resolution_clock::now();
306 std::chrono::high_resolution_clock::duration sccDecompositionTime = sccDecompositionEnd - sccDecompositionStart;
307 std::chrono::milliseconds sccDecompositionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(sccDecompositionTime);
308 std::chrono::high_resolution_clock::duration conversionTime = conversionEnd - conversionStart;
309 std::chrono::milliseconds conversionTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(conversionTime);
310 std::chrono::high_resolution_clock::duration modelCheckingTime = modelCheckingEnd - modelCheckingStart;
311 std::chrono::milliseconds modelCheckingTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(modelCheckingTime);
312 std::chrono::high_resolution_clock::duration totalTime = totalTimeEnd - totalTimeStart;
313 std::chrono::milliseconds totalTimeInMilliseconds = std::chrono::duration_cast<std::chrono::milliseconds>(totalTime);
317 STORM_LOG_STATISTICS(
" * time for SCC decomposition: " << sccDecompositionTimeInMilliseconds.count() <<
"ms\n");
318 STORM_LOG_STATISTICS(
" * time for conversion: " << conversionTimeInMilliseconds.count() <<
"ms\n");
319 STORM_LOG_STATISTICS(
" * time for checking: " << modelCheckingTimeInMilliseconds.count() <<
"ms\n");
326 for (
auto& value : stateValues) {
332template<
typename SparseDtmcModelType>
338 "Formula needs to have single upper time bound.");
344 storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
345 storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
350 this->
getModel().getBackwardTransitions(), phiStates, psiStates,
true, pathFormula.
getUpperBound<uint64_t>());
351 statesWithProbabilityGreater0 &= ~psiStates;
354 bool furtherComputationNeeded =
true;
356 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
357 furtherComputationNeeded =
false;
358 }
else if (statesWithProbabilityGreater0.
empty()) {
359 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
360 furtherComputationNeeded =
false;
368 if (furtherComputationNeeded) {
369 uint_fast64_t timeBound = pathFormula.
getUpperBound<uint64_t>();
377 statesWithProbabilityGreater0 &= reachableStates;
382 transitionMatrix.
getSubmatrix(
true, statesWithProbabilityGreater0, statesWithProbabilityGreater0,
true);
384 std::vector<uint_fast64_t> distancesFromInitialStates;
401 std::vector<ValueType> subresult(b);
402 std::vector<ValueType> tmp(subresult.size());
408 for (uint_fast64_t timeStep = 0; timeStep < timeBound; ++timeStep) {
416 for (uint64_t state : relevantStates) {
417 if (distancesFromInitialStates[state] > (timeBound - timeStep)) {
418 for (
auto& element : submatrix.
getRow(state)) {
422 relevantStates.set(state,
false);
443template<
typename SparseDtmcModelType>
451 storm::storage::BitVector const& phiStates = leftResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
452 storm::storage::BitVector const& psiStates = rightResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
458template<
typename SparseDtmcModelType>
464 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
471 bool furtherComputationNeeded =
true;
472 if (computeForInitialStatesOnly && initialStates.
isDisjointFrom(maybeStates)) {
473 STORM_LOG_DEBUG(
"The probability for all initial states was found in a preprocessing step.");
474 furtherComputationNeeded =
false;
475 }
else if (maybeStates.
empty()) {
476 STORM_LOG_DEBUG(
"The probability for all states was found in a preprocessing step.");
477 furtherComputationNeeded =
false;
480 std::vector<ValueType> result(maybeStates.
size());
481 if (furtherComputationNeeded) {
484 if (computeForInitialStatesOnly) {
490 maybeStates &= reachableStates;
494 std::vector<ValueType> oneStepProbabilities = probabilityMatrix.
getConstrainedRowSumVector(maybeStates, statesWithProbability1);
503 std::vector<ValueType> subresult = computeReachabilityValues(env, submatrix, oneStepProbabilities, submatrixTransposed, newInitialStates,
504 computeForInitialStatesOnly, oneStepProbabilities);
512 if (computeForInitialStatesOnly) {
515 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
516 for (uint64_t state : ~maybeStates | initialStates) {
517 (*checkResult)[state] = result[state];
519 return std::move(checkResult);
521 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
524template<
typename SparseDtmcModelType>
530 std::unique_ptr<CheckResult> subResultPointer = this->
check(eventuallyFormula.
getSubformula());
532 storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
537 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
539 env, this->
getModel().getTransitionMatrix(), this->
getModel().getBackwardTransitions(), this->
getModel().getInitialStates(), targetStates,
541 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
546template<
typename SparseDtmcModelType>
550 storm::storage::BitVector const& targetStates, std::vector<ValueType>& stateRewardValues,
bool computeForInitialStatesOnly) {
552 env, probabilityMatrix, backwardTransitions, initialStates, targetStates,
554 std::vector<ValueType> result(numberOfRows);
558 computeForInitialStatesOnly);
561template<
typename SparseDtmcModelType>
567 totalStateRewardVectorGetter,
568 bool computeForInitialStatesOnly) {
569 uint_fast64_t numberOfStates = probabilityMatrix.
getRowCount();
578 bool furtherComputationNeeded =
true;
579 if (computeForInitialStatesOnly) {
580 if (initialStates.
isSubsetOf(infinityStates)) {
581 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
582 furtherComputationNeeded =
false;
585 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
586 furtherComputationNeeded =
false;
590 std::vector<ValueType> result(maybeStates.
size());
591 if (furtherComputationNeeded) {
594 if (computeForInitialStatesOnly) {
599 maybeStates &= reachableStates;
603 storm::storage::BitVector newInitialStates = initialStates % maybeStates;
606 storm::storage::SparseMatrix<ValueType> submatrix = probabilityMatrix.
getSubmatrix(
false, maybeStates, maybeStates);
607 storm::storage::SparseMatrix<ValueType> submatrixTransposed = submatrix.
transpose();
610 std::vector<ValueType> stateRewardValues = totalStateRewardVectorGetter(submatrix.
getRowCount(), probabilityMatrix, maybeStates);
612 std::vector<ValueType> subresult =
613 computeReachabilityValues(env, submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly,
621 if (computeForInitialStatesOnly) {
624 std::unique_ptr<ExplicitQuantitativeCheckResult<ValueType>> checkResult = std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>();
625 for (uint64_t state : ~maybeStates | initialStates) {
626 (*checkResult)[state] = result[state];
628 return std::move(checkResult);
630 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
633template<
typename SparseDtmcModelType>
641 "Expected 'eventually' formula.");
645 storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
646 storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
649 STORM_LOG_THROW(this->
getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException,
650 "Input model is required to have exactly one initial state.");
652 "Cannot compute conditional probabilities for all states.");
661 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
666 STORM_LOG_THROW(this->
getModel().getInitialStates().isSubsetOf(statesWithProbabilityGreater0), storm::exceptions::InvalidPropertyException,
667 "The condition of the conditional probability has zero probability.");
670 if (this->
getModel().getInitialStates().isSubsetOf(statesWithProbability1)) {
671 STORM_LOG_INFO(
"The condition holds with probability 1, so the regular reachability probability is computed.");
672 std::shared_ptr<storm::logic::BooleanLiteralFormula> trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(
true);
673 std::shared_ptr<storm::logic::UntilFormula> untilFormula =
699 phiStates = phiStates % maybeStates;
702 if (phiStates.
empty()) {
706 psiStates = psiStates % maybeStates;
709 maybeStates = phiStates | psiStates;
715 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
718 distanceBasedPriorities =
getDistanceBasedPriorities(order, submatrix, submatrixTransposed, newInitialStates, oneStepProbabilities,
725 std::shared_ptr<StatePriorityQueue> statePriorities =
726 createStatePriorityQueue(order, distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
729 uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
730 STORM_LOG_INFO(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
731 performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->
getModel().getInitialStates(),
739 if (!flexibleBackwardTransitions.
getRow(*newInitialStates.
begin()).empty()) {
745 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
746 auto initialStateSuccessor = trans1.getColumn();
748 STORM_LOG_TRACE(
"Exploring successor " << initialStateSuccessor <<
" of the initial state.");
750 if (phiStates.
get(initialStateSuccessor)) {
754 if (psiStates.
get(initialStateSuccessor)) {
761 bool hasNonPsiSuccessor =
true;
762 while (hasNonPsiSuccessor) {
764 hasNonPsiSuccessor =
false;
767 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
768 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
769 for (
auto const& element : currentRow) {
771 if (!psiStates.
get(element.getColumn())) {
774 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
775 STORM_LOG_TRACE(
"Found non-psi successor " << element.getColumn() <<
" that needs to be eliminated.");
777 hasNonPsiSuccessor =
true;
781 STORM_LOG_ASSERT(!flexibleMatrix.
getRow(initialStateSuccessor).empty(),
"Expected new transitions to be non-empty (1).");
793 bool hasNonPhiSuccessor =
true;
794 while (hasNonPhiSuccessor) {
796 hasNonPhiSuccessor =
false;
799 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
800 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
801 for (
auto const& element : currentRow) {
803 if (!phiStates.
get(element.getColumn())) {
805 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
806 STORM_LOG_TRACE(
"Found non-phi successor " << element.getColumn() <<
" that needs to be eliminated.");
808 hasNonPhiSuccessor =
true;
821 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
822 auto initialStateSuccessor = trans1.getColumn();
823 if (phiStates.
get(initialStateSuccessor)) {
824 if (psiStates.
get(initialStateSuccessor)) {
825 numerator += trans1.getValue();
826 denominator += trans1.getValue();
829 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
830 if (psiStates.
get(trans2.getColumn())) {
831 additiveTerm += trans2.getValue();
834 additiveTerm *= trans1.getValue();
835 numerator += additiveTerm;
836 denominator += additiveTerm;
840 denominator += trans1.getValue();
842 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
843 if (phiStates.
get(trans2.getColumn())) {
844 additiveTerm += trans2.getValue();
847 numerator += trans1.getValue() * additiveTerm;
854template<
typename SparseDtmcModelType>
855void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(
858 bool computeResultsForInitialStatesOnly) {
861 while (priorityQueue->hasNext()) {
863 bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.
get(state);
864 stateEliminator.eliminateState(state, removeForwardTransitions);
865 if (removeForwardTransitions) {
871template<
typename SparseDtmcModelType>
872void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(
873 Environment
const& env, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix,
874 storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector
const& subsystem,
875 storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values,
876 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
877 std::shared_ptr<StatePriorityQueue> statePriorities =
878 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
880 std::size_t numberOfStatesToEliminate = statePriorities->size();
881 STORM_LOG_DEBUG(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
882 performPrioritizedStateElimination(statePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
883 STORM_LOG_DEBUG(
"Eliminated " << numberOfStatesToEliminate <<
" states.\n");
886template<
typename SparseDtmcModelType>
887uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performHybridStateElimination(
888 Environment
const& env, storm::storage::SparseMatrix<ValueType>
const& forwardTransitions,
889 storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions,
890 storm::storage::BitVector
const& subsystem, storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly,
891 std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
893 std::vector<storm::storage::sparse::state_type> entryStateQueue;
894 STORM_LOG_DEBUG(
"Eliminating " << subsystem.
size() <<
" states using the hybrid elimination technique.\n");
895 uint_fast64_t maximalDepth =
896 treatScc(env, transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions,
false, 0,
897 env.solver().elimination().getMaximalSccSize(), entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
900 if (env.solver().elimination().isEliminateEntryStatesLastSet()) {
901 STORM_LOG_DEBUG(
"Eliminating " << entryStateQueue.size() <<
" entry states as a last step.");
902 std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
903 std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
904 performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
910template<
typename SparseDtmcModelType>
911std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
912SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeReachabilityValues(
913 Environment
const& env, storm::storage::SparseMatrix<ValueType>
const& transitionMatrix, std::vector<ValueType>& values,
914 storm::storage::SparseMatrix<ValueType>
const& backwardTransitions, storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly,
915 std::vector<ValueType>
const& oneStepProbabilitiesToTarget) {
917 storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(transitionMatrix);
918 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(backwardTransitions);
921 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
923 distanceBasedPriorities =
getDistanceBasedPriorities(order, transitionMatrix, backwardTransitions, initialStates, oneStepProbabilitiesToTarget,
928 storm::storage::BitVector subsystem = storm::storage::BitVector(transitionMatrix.
getRowCount(),
true);
930 if (env.solver().elimination().getMethod() == EliminationMethod::State) {
931 performOrdinaryStateElimination(env, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values,
932 distanceBasedPriorities);
933 }
else if (env.solver().elimination().getMethod() == EliminationMethod::Hybrid) {
934 uint64_t maximalDepth = performHybridStateElimination(env, transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates,
935 computeResultsForInitialStatesOnly, values, distanceBasedPriorities);
936 STORM_LOG_TRACE(
"Maximal depth of decomposition was " << maximalDepth <<
".");
939 STORM_LOG_ASSERT(flexibleMatrix.empty(),
"Not all transitions were eliminated.");
940 STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(),
"Not all transitions were eliminated.");
944 for (
auto& value : values) {
950template<
typename SparseDtmcModelType>
951uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::treatScc(
952 Environment
const& env, storm::storage::FlexibleSparseMatrix<ValueType>& matrix, std::vector<ValueType>& values,
953 storm::storage::BitVector
const& entryStates, storm::storage::BitVector
const& scc, storm::storage::BitVector
const& initialStates,
954 storm::storage::SparseMatrix<ValueType>
const& forwardTransitions, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions,
955 bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector<storm::storage::sparse::state_type>& entryStateQueue,
956 bool computeResultsForInitialStatesOnly, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
957 uint_fast64_t maximalDepth = level;
964 storm::storage::BitVector nonEntrySccStates = scc & ~entryStates;
965 storm::storage::StronglyConnectedComponentDecomposition<ValueType> decomposition(
966 forwardTransitions, storm::storage::StronglyConnectedComponentDecompositionOptions().subsystem(nonEntrySccStates));
967 STORM_LOG_TRACE(
"Decomposed SCC into " << decomposition.size() <<
" sub-SCCs.");
971 storm::storage::BitVector remainingSccs(decomposition.size(),
true);
974 storm::storage::BitVector statesInTrivialSccs(matrix.
getRowCount());
975 for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) {
976 storm::storage::StronglyConnectedComponent
const& scc = decomposition.getBlock(sccIndex);
979 statesInTrivialSccs.set(*scc.
begin(),
true);
980 remainingSccs.set(sccIndex,
false);
984 std::shared_ptr<StatePriorityQueue> statePriorities =
985 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
986 STORM_LOG_TRACE(
"Eliminating " << statePriorities->size() <<
" trivial SCCs.");
987 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
991 STORM_LOG_TRACE(
"Eliminating " << remainingSccs.getNumberOfSetBits() <<
" remaining SCCs on level " << level <<
".");
992 for (uint64_t sccIndex : remainingSccs) {
993 storm::storage::StronglyConnectedComponent
const& newScc = decomposition.getBlock(sccIndex);
996 storm::storage::BitVector newSccAsBitVector(forwardTransitions.
getRowCount(), newScc.
begin(), newScc.
end());
999 storm::storage::BitVector entryStates(forwardTransitions.
getRowCount());
1000 for (
auto const& state : newScc) {
1001 for (
auto const& predecessor : backwardTransitions.
getRow(state)) {
1003 entryStates.
set(state);
1009 uint_fast64_t depth = treatScc(env, matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions,
1010 eliminateEntryStates || !env.solver().elimination().isEliminateEntryStatesLastSet(), level + 1, maximalSccSize,
1011 entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
1012 maximalDepth = std::max(maximalDepth, depth);
1016 STORM_LOG_TRACE(
"SCC of size " << scc.getNumberOfSetBits() <<
" is small enough to be eliminated directly.");
1017 std::shared_ptr<StatePriorityQueue> statePriorities =
1018 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
1019 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1024 if (eliminateEntryStates) {
1027 performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1031 for (uint64_t state : entryStates) {
1032 entryStateQueue.push_back(state);
1036 return maximalDepth;
storm::solver::stateelimination::EliminationOrder const & getOrder() const
SolverEnvironment & solver()
EliminationSolverEnvironment & elimination()
FragmentSpecification & setOnlyEventuallyFormuluasInConditionalFormulasAllowed(bool newValue)
FragmentSpecification & setCumulativeRewardFormulasAllowed(bool newValue)
FragmentSpecification & setConditionalProbabilityFormulasAllowed(bool newValue)
FragmentSpecification & setLongRunAverageProbabilitiesAllowed(bool newValue)
FragmentSpecification & setInstantaneousFormulasAllowed(bool newValue)
FragmentSpecification & setNestedOperatorsAllowed(bool newValue)
virtual std::unique_ptr< CheckResult > check(Environment const &env, CheckTask< storm::logic::Formula, SolutionType > const &checkTask)
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.
SparseDtmcModelType::ValueType ValueType
virtual bool canHandle(CheckTask< storm::logic::Formula, SolutionType > const &checkTask) const override
SparseDtmcEliminationModelChecker(storm::models::sparse::Dtmc< ValueType > const &model)
Creates an elimination-based model checker for the given model.
virtual std::unique_ptr< CheckResult > computeReachabilityRewards(Environment const &env, CheckTask< storm::logic::EventuallyFormula, SolutionType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeUntilProbabilities(Environment const &env, CheckTask< storm::logic::UntilFormula, SolutionType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeLongRunAverageProbabilities(Environment const &env, CheckTask< storm::logic::StateFormula, SolutionType > const &checkTask) override
storm::storage::FlexibleSparseMatrix< ValueType >::row_type FlexibleRowType
virtual std::unique_ptr< CheckResult > computeBoundedUntilProbabilities(Environment const &env, CheckTask< storm::logic::BoundedUntilFormula, SolutionType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeLongRunAverageRewards(Environment const &env, CheckTask< storm::logic::LongRunAverageRewardFormula, SolutionType > const &checkTask) override
virtual std::unique_ptr< CheckResult > computeConditionalProbabilities(Environment const &env, CheckTask< storm::logic::ConditionalFormula, SolutionType > const &checkTask) override
SparseDtmcModelType::RewardModelType RewardModelType
SparsePropositionalModelChecker(SparseDtmcModelType const &model)
SparseDtmcModelType const & getModel() const
This class represents a discrete-time Markov chain.
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...
bool isTrivial() const
Retrieves whether this SCC is trivial.
#define STORM_LOG_INFO(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_STATISTICS(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)
FragmentSpecification prctl()
bool eliminationOrderNeedsReversedDistances(EliminationOrder const &order)
bool eliminationOrderNeedsForwardDistances(EliminationOrder const &order)
std::shared_ptr< StatePriorityQueue > createStatePriorityQueue(EliminationOrder const &order, 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 eliminationOrderNeedsDistances(EliminationOrder const &order)
EliminationOrder
An enum that contains all available state elimination orders.
std::vector< uint_fast64_t > getDistanceBasedPriorities(EliminationOrder const &order, 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)
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...
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)