diff --git a/src/storm-counterexamples/api/counterexamples.cpp b/src/storm-counterexamples/api/counterexamples.cpp index f0927c869..0230595e1 100644 --- a/src/storm-counterexamples/api/counterexamples.cpp +++ b/src/storm-counterexamples/api/counterexamples.cpp @@ -6,22 +6,22 @@ namespace storm { namespace api { - std::shared_ptr - computeHighLevelCounterexampleMilp(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr> mdp, - std::shared_ptr const& formula) { + std::shared_ptr computeHighLevelCounterexampleMilp(storm::storage::SymbolicModelDescription const& symbolicModel, + std::shared_ptr> mdp, + std::shared_ptr const& formula) { Environment env; return storm::counterexamples::MILPMinimalLabelSetGenerator::computeCounterexample(env, symbolicModel, *mdp, formula); } - std::shared_ptr - computeHighLevelCounterexampleMaxSmt(storm::storage::SymbolicModelDescription const& symbolicModel, std::shared_ptr> model, - std::shared_ptr const& formula) { + std::shared_ptr computeHighLevelCounterexampleMaxSmt(storm::storage::SymbolicModelDescription const& symbolicModel, + std::shared_ptr > model, + std::shared_ptr const& formula) { Environment env; return storm::counterexamples::SMTMinimalLabelSetGenerator::computeCounterexample(env, symbolicModel, *model, formula); } - std::shared_ptr - computeKShortestPathCounterexample(std::shared_ptr> model, std::shared_ptr const& formula, size_t maxK) { + std::shared_ptr computeKShortestPathCounterexample(std::shared_ptr> model, + std::shared_ptr const& formula, size_t maxK) { // Only accept formulas of the form "P isProbabilityOperatorFormula(), storm::exceptions::InvalidPropertyException, "Counterexample generation does not support this kind of formula. Expecting a probability operator as the outermost formula element."); @@ -33,7 +33,10 @@ namespace storm { storm::logic::Formula const& subformula = formula->asOperatorFormula().getSubformula(); STORM_LOG_THROW(subformula.isEventuallyFormula(), storm::exceptions::InvalidPropertyException, "Path formula is required to be of the form 'F psi' for counterexample generation."); - bool strictBound = (probabilityOperator.getComparisonType() == storm::logic::ComparisonType::Greater); + bool strictBound = (probabilityOperator.getComparisonType() == storm::logic::ComparisonType::Less); + STORM_LOG_THROW(model->getInitialStates().getNumberOfSetBits() == 1, storm::exceptions::NotSupportedException, + "k-shortest paths is only supported for models with a unique initial state."); + size_t initialState = *(model->getInitialStates().begin()); // Perform model checking to get target states Environment env; @@ -43,6 +46,16 @@ namespace storm { std::unique_ptr subResult = modelchecker.check(env, eventuallyFormula.getSubformula()); storm::modelchecker::ExplicitQualitativeCheckResult const& subQualitativeResult = subResult->asExplicitQualitativeCheckResult(); + // Check if counterexample is even possible + storm::storage::BitVector phiStates(model->getNumberOfStates(), true); + auto results = storm::modelchecker::helper::SparseDtmcPrctlHelper::computeUntilProbabilities(env, false, model->getTransitionMatrix(), + model->getBackwardTransitions(), phiStates, + subQualitativeResult.getTruthValuesVector(), true); + double reachProb = results.at(initialState); + STORM_LOG_THROW((reachProb > threshold) || (strictBound && reachProb >= threshold), storm::exceptions::InvalidArgumentException, + "Given probability threshold " << threshold << " cannot be " << (strictBound ? "achieved" : "exceeded") + << " in model with maximal reachability probability of " << reachProb << "."); + auto generator = storm::utility::ksp::ShortestPathsGenerator(*model, subQualitativeResult.getTruthValuesVector()); storm::counterexamples::PathCounterexample cex(model); double probability = 0; @@ -51,7 +64,7 @@ namespace storm { cex.addPath(generator.getPathAsList(k), k); probability += generator.getDistance(k); // Check if accumulated probability mass is already enough - if ((probability >= threshold && !strictBound) || (probability > threshold)) { + if ((probability > threshold) || (strictBound && probability >= threshold && strictBound)) { thresholdExceeded = true; break; }