21namespace modelchecker {
24template<
typename ValueType,
bool Nondeterministic>
26 : _transitionMatrix(transitionMatrix) {
30template<
typename ValueType,
bool Nondeterministic>
33 STORM_LOG_ASSERT(this->isProduceSchedulerSet(),
"Trying to get the produced optimal choices although no scheduler was requested.");
35 "Trying to get the produced optimal choices but none were available. Was there a computation call before?");
37 return this->_schedulerHelper.get().extractScheduler(model, this->hasRelevantStates());
40template<
typename ValueType,
bool Nondeterministic>
49 auto apSets = computeApSets(extracted, formulaChecker);
51 STORM_LOG_INFO(
"Computing LTL probabilities for formula with " << apSets.size() <<
" atomic proposition(s).");
54 return computeLTLProbabilities(env, ltlFormula->asPathFormula(), apSets);
57template<
typename ValueType,
bool Nondeterministic>
59 std::map<std::string, std::shared_ptr<storm::logic::Formula const>>
const& extracted,
CheckFormulaCallback const& formulaChecker) {
60 std::map<std::string, storm::storage::BitVector> apSets;
61 for (
auto& p : extracted) {
62 STORM_LOG_DEBUG(
" Computing satisfaction set for atomic proposition \"" << p.first <<
"\" <=> " << *p.second <<
"...");
63 apSets[p.first] = formulaChecker(*p.second);
68template<
typename ValueType,
bool Nondeterministic>
75 STORM_LOG_INFO(
" TRUE -> all states accepting (assumes no deadlock in the model)");
82 std::vector<std::vector<automata::AcceptanceCondition::acceptance_expr::ptr>> dnf = acceptance.
extractFromDNF();
86 std::size_t accMECs = 0;
87 std::size_t allMECs = 0;
93 std::vector<uint64_t> stateToMec(transitionMatrix.
getRowGroupCount(), std::numeric_limits<uint64_t>::max());
96 for (uint64_t mec_counter = 0;
auto const& mec : mecs) {
97 for (
auto const& [state, _] : mec) {
98 stateToMec[state] = mec_counter;
99 mecStates.set(state,
true);
104 for (
auto const& conjunction : dnf) {
108 if (allowed.
empty()) {
113 if (literal->isTRUE()) {
115 }
else if (literal->isFALSE()) {
118 }
else if (literal->isAtom()) {
119 const cpphoafparser::AtomAcceptance& atom = literal->getAtom();
120 if (atom.getType() == cpphoafparser::AtomAcceptance::TEMPORAL_FIN) {
123 if (atom.isNegated()) {
134 if (allowed.
empty()) {
141 allMECs += allowedECs.size();
142 for (
const auto& ec : allowedECs) {
143 auto const representativeEcState = ec.begin()->first;
144 if (acceptingStates.get(representativeEcState)) {
149 bool accepting =
true;
151 if (literal->isTRUE()) {
154 }
else if (literal->isFALSE()) {
157 }
else if (literal->isAtom()) {
158 const cpphoafparser::AtomAcceptance& atom = literal->getAtom();
160 if (atom.getType() == cpphoafparser::AtomAcceptance::TEMPORAL_INF) {
161 if (atom.isNegated()) {
162 if (!ec.containsAnyState(~accSet)) {
167 if (!ec.containsAnyState(accSet)) {
173 }
else if (atom.getType() == cpphoafparser::AtomAcceptance::TEMPORAL_FIN) {
175 STORM_LOG_ASSERT(atom.isNegated() ? !ec.containsAnyState(~accSet) : !ec.containsAnyState(accSet),
176 "EC contains Fin-states, which should have been removed");
185 auto const mec_index = stateToMec[representativeEcState];
187 auto const& mec = mecs[mec_index];
190 for (
auto const& [state, _] : mec) {
191 acceptingStates.set(state);
194 if (this->isProduceSchedulerSet()) {
196 this->_schedulerHelper.get().saveProductEcChoices(acceptance, ec, mec, conjunction, product);
202 STORM_LOG_INFO(
"Found " << acceptingStates.getNumberOfSetBits() <<
" states in " << accMECs <<
" accepting MECs (considered " << allMECs <<
" MECs).");
204 return acceptingStates;
207template<
typename ValueType,
bool Nondeterministic>
208storm::storage::BitVector SparseLTLHelper<ValueType, Nondeterministic>::computeAcceptingBCCs(automata::AcceptanceCondition
const& acceptance,
211 transitionMatrix, storage::StronglyConnectedComponentDecompositionOptions().onlyBottomSccs().dropNaiveSccs());
214 std::size_t checkedBSCCs = 0, acceptingBSCCs = 0, acceptingBSCCStates = 0;
215 for (
auto& scc : bottomSccs) {
217 if (acceptance.isAccepting(scc)) {
219 for (
auto& state : scc) {
220 acceptingStates.set(state);
221 acceptingBSCCStates++;
225 STORM_LOG_INFO(
"BSCC analysis: " << acceptingBSCCs <<
" of " << checkedBSCCs <<
" BSCCs were acceptingStates (" << acceptingBSCCStates
226 <<
" states in acceptingStates BSCCs).");
227 return acceptingStates;
230template<
typename ValueType,
bool Nondeterministic>
235 std::vector<storm::storage::BitVector> statesForAP;
236 for (
const std::string& ap : apSet.
getAPs()) {
237 auto it = apSatSets.find(ap);
238 STORM_LOG_THROW(it != apSatSets.end(), storm::exceptions::InvalidOperationException,
239 "Deterministic automaton has AP " << ap <<
", does not appear in formula");
241 statesForAP.push_back(std::move(it->second));
246 if (this->hasRelevantStates()) {
247 statesOfInterest = this->getRelevantStates();
253 STORM_LOG_INFO(
"Building " + (Nondeterministic ? std::string(
"MDP-DA") : std::string(
"DTMC-DA")) +
" product with deterministic automaton, starting from "
257 auto product = productBuilder.build<
productModelType>(this->_transitionMatrix, statesOfInterest);
259 STORM_LOG_INFO(
"Product " + (Nondeterministic ? std::string(
"MDP-DA") : std::string(
"DTMC-DA")) +
" has "
264 if (this->isProduceSchedulerSet()) {
265 STORM_LOG_THROW(Nondeterministic, storm::exceptions::InvalidOperationException,
"Scheduler export only supported for nondeterministic models.");
266 this->_schedulerHelper.emplace(product->
getProductModel().getNumberOfStates());
271 if (Nondeterministic) {
281 if (acceptingStates.
empty()) {
282 STORM_LOG_INFO(
"No accepting states, skipping probability computation.");
283 if (this->isProduceSchedulerSet()) {
284 this->_schedulerHelper.get().setRandom();
286 std::vector<ValueType> numericResult(this->_transitionMatrix.getRowGroupCount(), storm::utility::zero<ValueType>());
287 return numericResult;
290 STORM_LOG_INFO(
"Computing probabilities for reaching accepting components...");
297 if (this->isValueThresholdSet()) {
299 this->getValueThresholdValue(), std::move(soiProduct));
305 std::vector<ValueType> prodNumericResult;
307 if (Nondeterministic) {
311 acceptingStates, this->isQualitativeSet(),
312 this->isProduceSchedulerSet()
314 prodNumericResult = std::move(prodCheckResult.
values);
316 if (this->isProduceSchedulerSet()) {
317 this->_schedulerHelper.get().prepareScheduler(da.
getNumberOfStates(), acceptingStates, std::move(prodCheckResult.
scheduler), productBuilder,
318 product, statesOfInterest, this->_transitionMatrix);
324 acceptingStates, this->isQualitativeSet());
327 std::vector<ValueType> numericResult = product->
projectToOriginalModel(this->_transitionMatrix.getRowGroupCount(), prodNumericResult);
329 return numericResult;
332template<
typename ValueType,
bool Nondeterministic>
334 std::map<std::string, storm::storage::BitVector>& apSatSets) {
335 std::shared_ptr<storm::logic::Formula const> ltlFormula;
336 STORM_LOG_THROW((!Nondeterministic) || this->isOptimizationDirectionSet(), storm::exceptions::InvalidPropertyException,
337 "Formula needs to specify whether minimal or maximal values are to be computed on nondeterministic model.");
338 if (Nondeterministic && this->getOptimizationDirection() == OptimizationDirection::Minimize) {
341 STORM_LOG_INFO(
"Computing Pmin, proceeding with negated LTL formula.");
346 STORM_LOG_INFO(
"Resulting LTL path formula: " << ltlFormula->toString());
347 STORM_LOG_INFO(
" in prefix format: " << ltlFormula->toPrefixString());
350 std::shared_ptr<storm::automata::DeterministicAutomaton> da;
360 STORM_LOG_INFO(
"Deterministic automaton for LTL formula has " << da->getNumberOfStates() <<
" states, " << da->getAPSet().size()
361 <<
" atomic propositions and " << *da->getAcceptance()->getAcceptanceExpression()
362 <<
" as acceptance condition.\n");
364 std::vector<ValueType> numericResult = computeDAProductProbabilities(env, *da, apSatSets);
366 if (Nondeterministic && this->getOptimizationDirection() == OptimizationDirection::Minimize) {
368 for (
auto& value : numericResult) {
369 value = storm::utility::one<ValueType>() - value;
373 return numericResult;
379#ifdef STORM_HAVE_CARL
ModelCheckerEnvironment & modelchecker()
bool isLtl2daToolSet() const
std::string const & getLtl2daTool() const
const std::vector< std::string > & getAPs() const
storm::storage::BitVector & getAcceptanceSet(unsigned int index)
std::vector< std::vector< acceptance_expr::ptr > > extractFromDNF() const
acceptance_expr::ptr getAcceptanceExpression() const
const APSet & getAPSet() const
std::size_t getNumberOfStates() const
static std::shared_ptr< DeterministicAutomaton > ltl2daExternalTool(storm::logic::Formula const &f, std::string ltl2daTool)
Converts an LTL formula into a deterministic omega-automaton using an external LTL2DA tool.
static std::shared_ptr< DeterministicAutomaton > ltl2daSpot(storm::logic::Formula const &f, bool dnf)
Converts an LTL formula into a deterministic omega-automaton using the internal LTL2DA tool "Spot".
static std::vector< ValueType > computeUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool qualitative, ModelCheckerHint const &hint=ModelCheckerHint())
Helper class for LTL model checking.
std::function< storm::storage::BitVector(storm::logic::Formula const &)> CheckFormulaCallback
std::vector< ValueType > computeLTLProbabilities(Environment const &env, storm::logic::PathFormula const &formula, CheckFormulaCallback const &formulaChecker)
Computes the LTL probabilities.
SparseLTLHelper(storm::storage::SparseMatrix< ValueType > const &transitionMatrix)
Initializes the helper for a discrete time model (i.e.
static std::map< std::string, storm::storage::BitVector > computeApSets(std::map< std::string, std::shared_ptr< storm::logic::Formula const > > const &extracted, CheckFormulaCallback const &formulaChecker)
Computes the states that are satisfying the AP.
std::vector< ValueType > computeDAProductProbabilities(Environment const &env, storm::automata::DeterministicAutomaton const &da, std::map< std::string, storm::storage::BitVector > &apSatSets)
Computes the (maximizing) probabilities for the constructed DA product.
typename std::conditional< Nondeterministic, storm::models::sparse::Mdp< ValueType >, storm::models::sparse::Dtmc< ValueType > >::type productModelType
The type of the product model (DTMC or MDP) that is used during the computation.
static MDPSparseModelCheckingHelperReturnType< SolutionType > computeUntilProbabilities(Environment const &env, storm::solver::SolveGoal< ValueType, SolutionType > &&goal, storm::storage::SparseMatrix< ValueType > const &transitionMatrix, storm::storage::SparseMatrix< ValueType > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool qualitative, bool produceScheduler, ModelCheckerHint const &hint=ModelCheckerHint())
Base class for all sparse models.
void setRelevantValues(storm::storage::BitVector &&values)
A bit vector that is internally represented as a vector of 64-bit values.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
void clear()
Removes all set bits from the bit vector.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
This class represents the decomposition of a nondeterministic model into its maximal end components.
This class defines which action is chosen in a particular state of a non-deterministic model.
A class that holds a possibly non-square matrix in the compressed row storage format.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
This class represents the decomposition of a graph-like structure into its strongly connected compone...
#define STORM_LOG_INFO(message)
#define STORM_LOG_DEBUG(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
Expression conjunction(std::vector< storm::expressions::Expression > const &expressions)
std::unique_ptr< storm::storage::Scheduler< ValueType > > scheduler
std::vector< ValueType > values