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) {
517 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(std::move(relevantStates), std::move(relevantValues));
519 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
522template<
typename SparseDtmcModelType>
528 std::unique_ptr<CheckResult> subResultPointer = this->
check(eventuallyFormula.
getSubformula());
530 storm::storage::BitVector const& targetStates = subResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
535 STORM_LOG_THROW(!rewardModel.empty(), storm::exceptions::IllegalArgumentException,
"Input model does not have a reward model.");
537 env, this->
getModel().getTransitionMatrix(), this->
getModel().getBackwardTransitions(), this->
getModel().getInitialStates(), targetStates,
539 return rewardModel.getTotalRewardVector(numberOfRows, transitionMatrix, maybeStates);
544template<
typename SparseDtmcModelType>
548 storm::storage::BitVector const& targetStates, std::vector<ValueType>& stateRewardValues,
bool computeForInitialStatesOnly) {
550 env, probabilityMatrix, backwardTransitions, initialStates, targetStates,
552 std::vector<ValueType> result(numberOfRows);
556 computeForInitialStatesOnly);
559template<
typename SparseDtmcModelType>
565 totalStateRewardVectorGetter,
566 bool computeForInitialStatesOnly) {
567 uint_fast64_t numberOfStates = probabilityMatrix.
getRowCount();
576 bool furtherComputationNeeded =
true;
577 if (computeForInitialStatesOnly) {
578 if (initialStates.
isSubsetOf(infinityStates)) {
579 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
580 furtherComputationNeeded =
false;
583 STORM_LOG_DEBUG(
"The reward of all initial states was found in a preprocessing step.");
584 furtherComputationNeeded =
false;
588 std::vector<storm::utility::ExtendedValueType<ValueType>> result(maybeStates.
size());
589 if (furtherComputationNeeded) {
592 if (computeForInitialStatesOnly) {
597 maybeStates &= reachableStates;
601 storm::storage::BitVector newInitialStates = initialStates % maybeStates;
604 storm::storage::SparseMatrix<ValueType> submatrix = probabilityMatrix.
getSubmatrix(
false, maybeStates, maybeStates);
605 storm::storage::SparseMatrix<ValueType> submatrixTransposed = submatrix.
transpose();
608 std::vector<ValueType> stateRewardValues = totalStateRewardVectorGetter(submatrix.
getRowCount(), probabilityMatrix, maybeStates);
610 std::vector<ValueType> subresult =
611 computeReachabilityValues(env, submatrix, stateRewardValues, submatrixTransposed, newInitialStates, computeForInitialStatesOnly,
619 if (computeForInitialStatesOnly) {
622 storm::storage::BitVector relevantStates = ~maybeStates | initialStates;
624 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(std::move(relevantStates), std::move(relevantValues));
626 return std::make_unique<ExplicitQuantitativeCheckResult<ValueType>>(result);
633#pragma GCC diagnostic push
634#pragma GCC diagnostic ignored "-Wfree-nonheap-object"
635template<
typename SparseDtmcModelType>
643 "Expected 'eventually' formula.");
647 storm::storage::BitVector phiStates = leftResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
648 storm::storage::BitVector psiStates = rightResultPointer->template asExplicitQualitativeCheckResult<ValueType>().getTruthValuesVector();
651 STORM_LOG_THROW(this->
getModel().getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::IllegalArgumentException,
652 "Input model is required to have exactly one initial state.");
654 "Cannot compute conditional probabilities for all states.");
663 std::pair<storm::storage::BitVector, storm::storage::BitVector> statesWithProbability01 =
668 STORM_LOG_THROW(this->
getModel().getInitialStates().isSubsetOf(statesWithProbabilityGreater0), storm::exceptions::InvalidPropertyException,
669 "The condition of the conditional probability has zero probability.");
672 if (this->
getModel().getInitialStates().isSubsetOf(statesWithProbability1)) {
673 STORM_LOG_INFO(
"The condition holds with probability 1, so the regular reachability probability is computed.");
674 std::shared_ptr<storm::logic::BooleanLiteralFormula> trueFormula = std::make_shared<storm::logic::BooleanLiteralFormula>(
true);
675 std::shared_ptr<storm::logic::UntilFormula> untilFormula =
701 phiStates = phiStates % maybeStates;
704 if (phiStates.
empty()) {
708 psiStates = psiStates % maybeStates;
711 maybeStates = phiStates | psiStates;
717 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
720 distanceBasedPriorities =
getDistanceBasedPriorities(order, submatrix, submatrixTransposed, newInitialStates, oneStepProbabilities,
727 std::shared_ptr<StatePriorityQueue> statePriorities =
728 createStatePriorityQueue(order, distanceBasedPriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, statesToEliminate);
731 uint_fast64_t numberOfStatesToEliminate = statePriorities->size();
732 STORM_LOG_INFO(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
733 performPrioritizedStateElimination(statePriorities, flexibleMatrix, flexibleBackwardTransitions, oneStepProbabilities, this->
getModel().getInitialStates(),
741 if (!flexibleBackwardTransitions.
getRow(*newInitialStates.
begin()).empty()) {
747 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
748 auto initialStateSuccessor = trans1.getColumn();
750 STORM_LOG_TRACE(
"Exploring successor " << initialStateSuccessor <<
" of the initial state.");
752 if (phiStates.
get(initialStateSuccessor)) {
756 if (psiStates.
get(initialStateSuccessor)) {
763 bool hasNonPsiSuccessor =
true;
764 while (hasNonPsiSuccessor) {
766 hasNonPsiSuccessor =
false;
769 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
770 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
771 for (
auto const& element : currentRow) {
773 if (!psiStates.
get(element.getColumn())) {
776 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
777 STORM_LOG_TRACE(
"Found non-psi successor " << element.getColumn() <<
" that needs to be eliminated.");
779 hasNonPsiSuccessor =
true;
783 STORM_LOG_ASSERT(!flexibleMatrix.
getRow(initialStateSuccessor).empty(),
"Expected new transitions to be non-empty (1).");
795 bool hasNonPhiSuccessor =
true;
796 while (hasNonPhiSuccessor) {
798 hasNonPhiSuccessor =
false;
801 auto const currentRow = flexibleMatrix.
getRow(initialStateSuccessor);
802 if (currentRow.size() > 1 || (!currentRow.empty() && currentRow.front().getColumn() != initialStateSuccessor)) {
803 for (
auto const& element : currentRow) {
805 if (!phiStates.
get(element.getColumn())) {
807 if (successorRow.size() > 1 || (!successorRow.empty() && successorRow.front().getColumn() != element.getColumn())) {
808 STORM_LOG_TRACE(
"Found non-phi successor " << element.getColumn() <<
" that needs to be eliminated.");
810 hasNonPhiSuccessor =
true;
823 for (
auto const& trans1 : flexibleMatrix.
getRow(*newInitialStates.
begin())) {
824 auto initialStateSuccessor = trans1.getColumn();
825 if (phiStates.
get(initialStateSuccessor)) {
826 if (psiStates.
get(initialStateSuccessor)) {
827 numerator += trans1.getValue();
828 denominator += trans1.getValue();
831 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
832 if (psiStates.
get(trans2.getColumn())) {
833 additiveTerm += trans2.getValue();
836 additiveTerm *= trans1.getValue();
837 numerator += additiveTerm;
838 denominator += additiveTerm;
842 denominator += trans1.getValue();
844 for (
auto const& trans2 : flexibleMatrix.
getRow(initialStateSuccessor)) {
845 if (phiStates.
get(trans2.getColumn())) {
846 additiveTerm += trans2.getValue();
849 numerator += trans1.getValue() * additiveTerm;
856template<
typename SparseDtmcModelType>
857void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performPrioritizedStateElimination(
860 bool computeResultsForInitialStatesOnly) {
863 while (priorityQueue->hasNext()) {
865 bool removeForwardTransitions = computeResultsForInitialStatesOnly && !initialStates.
get(state);
866 stateEliminator.eliminateState(state, removeForwardTransitions);
867 if (removeForwardTransitions) {
872#pragma GCC diagnostic pop
874template<
typename SparseDtmcModelType>
875void SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performOrdinaryStateElimination(
876 Environment
const& env, storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix,
877 storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions, storm::storage::BitVector
const& subsystem,
878 storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly, std::vector<ValueType>& values,
879 boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
880 std::shared_ptr<StatePriorityQueue> statePriorities =
881 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, transitionMatrix, backwardTransitions, values, subsystem);
883 std::size_t numberOfStatesToEliminate = statePriorities->size();
884 STORM_LOG_DEBUG(
"Eliminating " << numberOfStatesToEliminate <<
" states using the state elimination technique.\n");
885 performPrioritizedStateElimination(statePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
886 STORM_LOG_DEBUG(
"Eliminated " << numberOfStatesToEliminate <<
" states.\n");
889template<
typename SparseDtmcModelType>
890uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::performHybridStateElimination(
891 Environment
const& env, storm::storage::SparseMatrix<ValueType>
const& forwardTransitions,
892 storm::storage::FlexibleSparseMatrix<ValueType>& transitionMatrix, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions,
893 storm::storage::BitVector
const& subsystem, storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly,
894 std::vector<ValueType>& values, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
896 std::vector<storm::storage::sparse::state_type> entryStateQueue;
897 STORM_LOG_DEBUG(
"Eliminating " << subsystem.
size() <<
" states using the hybrid elimination technique.\n");
898 uint_fast64_t maximalDepth =
899 treatScc(env, transitionMatrix, values, initialStates, subsystem, initialStates, forwardTransitions, backwardTransitions,
false, 0,
900 env.solver().elimination().getMaximalSccSize(), entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
903 if (env.solver().elimination().isEliminateEntryStatesLastSet()) {
904 STORM_LOG_DEBUG(
"Eliminating " << entryStateQueue.size() <<
" entry states as a last step.");
905 std::vector<storm::storage::sparse::state_type> sortedStates(entryStateQueue.begin(), entryStateQueue.end());
906 std::shared_ptr<StatePriorityQueue> queuePriorities = std::make_shared<StaticStatePriorityQueue>(sortedStates);
907 performPrioritizedStateElimination(queuePriorities, transitionMatrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
913template<
typename SparseDtmcModelType>
914std::vector<typename SparseDtmcEliminationModelChecker<SparseDtmcModelType>::ValueType>
915SparseDtmcEliminationModelChecker<SparseDtmcModelType>::computeReachabilityValues(
916 Environment
const& env, storm::storage::SparseMatrix<ValueType>
const& transitionMatrix, std::vector<ValueType>& values,
917 storm::storage::SparseMatrix<ValueType>
const& backwardTransitions, storm::storage::BitVector
const& initialStates,
bool computeResultsForInitialStatesOnly,
918 std::vector<ValueType>
const& oneStepProbabilitiesToTarget) {
920 storm::storage::FlexibleSparseMatrix<ValueType> flexibleMatrix(transitionMatrix);
921 storm::storage::FlexibleSparseMatrix<ValueType> flexibleBackwardTransitions(backwardTransitions);
924 boost::optional<std::vector<uint_fast64_t>> distanceBasedPriorities;
926 distanceBasedPriorities =
getDistanceBasedPriorities(order, transitionMatrix, backwardTransitions, initialStates, oneStepProbabilitiesToTarget,
931 storm::storage::BitVector subsystem = storm::storage::BitVector(transitionMatrix.
getRowCount(),
true);
933 if (env.solver().elimination().getMethod() == EliminationMethod::State) {
934 performOrdinaryStateElimination(env, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates, computeResultsForInitialStatesOnly, values,
935 distanceBasedPriorities);
936 }
else if (env.solver().elimination().getMethod() == EliminationMethod::Hybrid) {
937 uint64_t maximalDepth = performHybridStateElimination(env, transitionMatrix, flexibleMatrix, flexibleBackwardTransitions, subsystem, initialStates,
938 computeResultsForInitialStatesOnly, values, distanceBasedPriorities);
939 STORM_LOG_TRACE(
"Maximal depth of decomposition was " << maximalDepth <<
".");
942 STORM_LOG_ASSERT(flexibleMatrix.empty(),
"Not all transitions were eliminated.");
943 STORM_LOG_ASSERT(flexibleBackwardTransitions.empty(),
"Not all transitions were eliminated.");
947 for (
auto& value : values) {
953template<
typename SparseDtmcModelType>
954uint_fast64_t SparseDtmcEliminationModelChecker<SparseDtmcModelType>::treatScc(
955 Environment
const& env, storm::storage::FlexibleSparseMatrix<ValueType>& matrix, std::vector<ValueType>& values,
956 storm::storage::BitVector
const& entryStates, storm::storage::BitVector
const& scc, storm::storage::BitVector
const& initialStates,
957 storm::storage::SparseMatrix<ValueType>
const& forwardTransitions, storm::storage::FlexibleSparseMatrix<ValueType>& backwardTransitions,
958 bool eliminateEntryStates, uint_fast64_t level, uint_fast64_t maximalSccSize, std::vector<storm::storage::sparse::state_type>& entryStateQueue,
959 bool computeResultsForInitialStatesOnly, boost::optional<std::vector<uint_fast64_t>>
const& distanceBasedPriorities) {
960 uint_fast64_t maximalDepth = level;
967 storm::storage::BitVector nonEntrySccStates = scc & ~entryStates;
968 storm::storage::StronglyConnectedComponentDecomposition<ValueType> decomposition(
969 forwardTransitions, storm::storage::StronglyConnectedComponentDecompositionOptions().subsystem(nonEntrySccStates));
970 STORM_LOG_TRACE(
"Decomposed SCC into " << decomposition.size() <<
" sub-SCCs.");
974 storm::storage::BitVector remainingSccs(decomposition.size(),
true);
977 storm::storage::BitVector statesInTrivialSccs(matrix.
getRowCount());
978 for (uint_fast64_t sccIndex = 0; sccIndex < decomposition.size(); ++sccIndex) {
979 storm::storage::StronglyConnectedComponent
const& scc = decomposition.getBlock(sccIndex);
982 statesInTrivialSccs.set(*scc.
begin(),
true);
983 remainingSccs.set(sccIndex,
false);
987 std::shared_ptr<StatePriorityQueue> statePriorities =
988 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, matrix, backwardTransitions, values, statesInTrivialSccs);
989 STORM_LOG_TRACE(
"Eliminating " << statePriorities->size() <<
" trivial SCCs.");
990 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
994 STORM_LOG_TRACE(
"Eliminating " << remainingSccs.getNumberOfSetBits() <<
" remaining SCCs on level " << level <<
".");
995 for (uint64_t sccIndex : remainingSccs) {
996 storm::storage::StronglyConnectedComponent
const& newScc = decomposition.getBlock(sccIndex);
999 storm::storage::BitVector newSccAsBitVector(forwardTransitions.
getRowCount(), newScc.
begin(), newScc.
end());
1002 storm::storage::BitVector entryStates(forwardTransitions.
getRowCount());
1003 for (
auto const& state : newScc) {
1004 for (
auto const& predecessor : backwardTransitions.
getRow(state)) {
1006 entryStates.
set(state);
1012 uint_fast64_t depth = treatScc(env, matrix, values, entryStates, newSccAsBitVector, initialStates, forwardTransitions, backwardTransitions,
1013 eliminateEntryStates || !env.solver().elimination().isEliminateEntryStatesLastSet(), level + 1, maximalSccSize,
1014 entryStateQueue, computeResultsForInitialStatesOnly, distanceBasedPriorities);
1015 maximalDepth = std::max(maximalDepth, depth);
1019 STORM_LOG_TRACE(
"SCC of size " << scc.getNumberOfSetBits() <<
" is small enough to be eliminated directly.");
1020 std::shared_ptr<StatePriorityQueue> statePriorities =
1021 createStatePriorityQueue(env.solver().elimination().getOrder(), distanceBasedPriorities, matrix, backwardTransitions, values, scc & ~entryStates);
1022 performPrioritizedStateElimination(statePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1027 if (eliminateEntryStates) {
1030 performPrioritizedStateElimination(naivePriorities, matrix, backwardTransitions, values, initialStates, computeResultsForInitialStatesOnly);
1034 for (uint64_t state : entryStates) {
1035 entryStateQueue.push_back(state);
1039 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.
A qualitative check result over the states of a sparse model.
A quantitative check result over the states of a sparse model.
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< S > 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...
std::vector< Type > filterVector(std::vector< Type > const &in, storm::storage::BitVector const &filter)
ExtendedValueType< ValueType > positiveInfinity()
ValueType simplify(ValueType value)