Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
graph.cpp
Go to the documentation of this file.
1#include "graph.h"
2#include <algorithm>
3
4#include "storm-config.h"
6
8
13
16
24
28
29#include <queue>
30
31namespace storm {
32namespace utility {
33namespace graph {
34
35template<typename T>
37 storm::storage::BitVector result{initialStates.size()};
38 for (uint64_t currentState : initialStates) {
39 for (auto const& successor : transitionMatrix.getRowGroup(currentState)) {
40 STORM_LOG_ASSERT(!storm::utility::isZero(successor.getValue()), "Matrix should not have zero entries.");
41 result.set(successor.getColumn());
42 }
43 }
44 return result;
45}
46
47template<typename T>
49 storm::storage::BitVector const& constraintStates, storm::storage::BitVector const& targetStates,
50 bool useStepBound, uint_fast64_t maximalSteps, boost::optional<storm::storage::BitVector> const& choiceFilter) {
51 storm::storage::BitVector reachableStates(initialStates);
52
53 uint_fast64_t numberOfStates = transitionMatrix.getRowGroupCount();
54
55 // Initialize the stack used for the DFS with the states.
56 std::vector<uint_fast64_t> stack;
57 stack.reserve(initialStates.size());
58 for (auto state : initialStates) {
59 if (constraintStates.get(state)) {
60 stack.push_back(state);
61 }
62 }
63
64 // Initialize the stack for the step bound, if the number of steps is bounded.
65 std::vector<uint_fast64_t> stepStack;
66 std::vector<uint_fast64_t> remainingSteps;
67 if (useStepBound) {
68 stepStack.reserve(numberOfStates);
69 stepStack.insert(stepStack.begin(), stack.size(), maximalSteps);
70 remainingSteps.resize(numberOfStates);
71 for (auto state : stack) {
72 remainingSteps[state] = maximalSteps;
73 }
74 }
75
76 // Perform the actual DFS.
77 uint_fast64_t currentState = 0, currentStepBound = 0;
78 while (!stack.empty()) {
79 currentState = stack.back();
80 stack.pop_back();
81
82 if (useStepBound) {
83 currentStepBound = stepStack.back();
84 stepStack.pop_back();
85
86 if (currentStepBound == 0) {
87 continue;
88 }
89 }
90
91 uint64_t row = transitionMatrix.getRowGroupIndices()[currentState];
92 if (choiceFilter) {
93 row = choiceFilter->getNextSetIndex(row);
94 }
95 uint64_t const rowGroupEnd = transitionMatrix.getRowGroupIndices()[currentState + 1];
96 while (row < rowGroupEnd) {
97 for (auto const& successor : transitionMatrix.getRow(row)) {
98 // Only explore the state if the transition was actually there and the successor has not yet
99 // been visited.
100 if (!storm::utility::isZero(successor.getValue()) &&
101 (!reachableStates.get(successor.getColumn()) || (useStepBound && remainingSteps[successor.getColumn()] < currentStepBound - 1))) {
102 // If the successor is one of the target states, we need to include it, but must not explore
103 // it further.
104 if (targetStates.get(successor.getColumn())) {
105 reachableStates.set(successor.getColumn());
106 } else if (constraintStates.get(successor.getColumn())) {
107 // However, if the state is in the constrained set of states, we potentially need to follow it.
108 if (useStepBound) {
109 // As there is at least one more step to go, we need to push the state and the new number of steps.
110 remainingSteps[successor.getColumn()] = currentStepBound - 1;
111 stepStack.push_back(currentStepBound - 1);
112 }
113 reachableStates.set(successor.getColumn());
114 stack.push_back(successor.getColumn());
115 }
116 }
117 }
118 ++row;
119 if (choiceFilter) {
120 row = choiceFilter->getNextSetIndex(row);
121 }
122 }
123 }
124
125 return reachableStates;
126}
127
128template<typename T>
130 storm::storage::BitVector result(transitionMatrix.getRowGroupCount());
133
134 // Take the first state out of each BSCC.
135 for (auto const& scc : decomposition) {
136 result.set(*scc.begin());
137 }
138
139 return result;
140}
141
142template<typename T>
143bool hasCycle(storm::storage::SparseMatrix<T> const& transitionMatrix, boost::optional<storm::storage::BitVector> const& subsystem) {
144 storm::storage::BitVector unexploredStates; // States that have not been visited yet
145 storm::storage::BitVector acyclicStates; // States that are known to not lie on a cycle consisting of subsystem states
146 if (subsystem) {
147 unexploredStates = subsystem.get();
148 acyclicStates = ~subsystem.get();
149 } else {
150 unexploredStates.resize(transitionMatrix.getRowGroupCount(), true);
151 acyclicStates.resize(transitionMatrix.getRowGroupCount(), false);
152 }
153 std::vector<uint64_t> dfsStack;
154 for (uint64_t start = unexploredStates.getNextSetIndex(0); start < unexploredStates.size(); start = unexploredStates.getNextSetIndex(start + 1)) {
155 dfsStack.push_back(start);
156 while (!dfsStack.empty()) {
157 uint64_t state = dfsStack.back();
158 if (unexploredStates.get(state)) {
159 unexploredStates.set(state, false);
160 for (auto const& entry : transitionMatrix.getRowGroup(state)) {
161 if (!storm::utility::isZero(entry.getValue())) {
162 if (unexploredStates.get(entry.getColumn())) {
163 dfsStack.push_back(entry.getColumn());
164 } else {
165 if (!acyclicStates.get(entry.getColumn())) {
166 // The state has been visited before but is not known to be acyclic.
167 return true;
168 }
169 }
170 }
171 }
172 } else {
173 acyclicStates.set(state, true);
174 dfsStack.pop_back();
175 }
176 }
177 }
178 return false;
179}
180
181template<typename T>
183 storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices) {
184 STORM_LOG_THROW(subsystem.size() == transitionMatrix.getRowGroupCount(), storm::exceptions::InvalidArgumentException, "Invalid size of subsystem");
185 STORM_LOG_THROW(choices.size() == transitionMatrix.getRowCount(), storm::exceptions::InvalidArgumentException, "Invalid size of choice vector");
186
187 if (subsystem.empty() || choices.empty()) {
188 return false;
189 }
190
191 storm::storage::BitVector statesWithChoice(transitionMatrix.getRowGroupCount(), false);
192 uint_fast64_t state = 0;
193 for (auto choice : choices) {
194 // Get the correct state
195 while (choice >= transitionMatrix.getRowGroupIndices()[state + 1]) {
196 ++state;
197 }
198 assert(choice >= transitionMatrix.getRowGroupIndices()[state]);
199 // make sure that the choice originates from the subsystem and also stays within the subsystem
200 if (subsystem.get(state)) {
201 bool choiceStaysInSubsys = true;
202 for (auto const& entry : transitionMatrix.getRow(choice)) {
203 if (!subsystem.get(entry.getColumn())) {
204 choiceStaysInSubsys = false;
205 break;
206 }
207 }
208 if (choiceStaysInSubsys) {
209 statesWithChoice.set(state, true);
210 }
211 }
212 }
213
214 // Initialize candidate states that satisfy some necessary conditions for being part of an EC with a specified choice:
215
216 // Get the states for which a policy can enforce that a choice is reached while staying inside the subsystem
217 storm::storage::BitVector candidateStates =
218 storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, subsystem, statesWithChoice);
219
220 // Only keep the states that can stay in the set of candidates forever
221 candidateStates =
222 storm::utility::graph::performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, candidateStates, ~candidateStates);
223
224 // Only keep the states that can be reached after performing one of the specified choices
225 statesWithChoice &= candidateStates;
226 storm::storage::BitVector choiceTargets(transitionMatrix.getRowGroupCount(), false);
227 for (auto state : statesWithChoice) {
228 for (uint_fast64_t choice = choices.getNextSetIndex(transitionMatrix.getRowGroupIndices()[state]);
229 choice < transitionMatrix.getRowGroupIndices()[state + 1]; choice = choices.getNextSetIndex(choice + 1)) {
230 bool choiceStaysInCandidateSet = true;
231 for (auto const& entry : transitionMatrix.getRow(choice)) {
232 if (!candidateStates.get(entry.getColumn())) {
233 choiceStaysInCandidateSet = false;
234 break;
235 }
236 }
237 if (choiceStaysInCandidateSet) {
238 for (auto const& entry : transitionMatrix.getRow(choice)) {
239 choiceTargets.set(entry.getColumn(), true);
240 }
241 }
242 }
243 }
244 candidateStates =
245 storm::utility::graph::getReachableStates(transitionMatrix, choiceTargets, candidateStates, storm::storage::BitVector(candidateStates.size(), false));
246
247 // At this point we know that every candidate state can reach a state with a choice without leaving the set of candidate states.
248 // We now compute the states that can reach a choice at least twice, three times, four times, ... until a fixpoint is reached.
249 while (!candidateStates.empty()) {
250 // Update the states with a choice that stays within the set of candidates
251 statesWithChoice &= candidateStates;
252 for (auto state : statesWithChoice) {
253 bool stateHasChoice = false;
254 for (uint_fast64_t choice = choices.getNextSetIndex(transitionMatrix.getRowGroupIndices()[state]);
255 choice < transitionMatrix.getRowGroupIndices()[state + 1]; choice = choices.getNextSetIndex(choice + 1)) {
256 bool choiceStaysInCandidateSet = true;
257 for (auto const& entry : transitionMatrix.getRow(choice)) {
258 if (!candidateStates.get(entry.getColumn())) {
259 choiceStaysInCandidateSet = false;
260 break;
261 }
262 }
263 if (choiceStaysInCandidateSet) {
264 stateHasChoice = true;
265 break;
266 }
267 }
268 if (!stateHasChoice) {
269 statesWithChoice.set(state, false);
270 }
271 }
272
273 // Update the candidates
274 storm::storage::BitVector newCandidates = storm::utility::graph::performProb1E(transitionMatrix, transitionMatrix.getRowGroupIndices(),
275 backwardTransitions, candidateStates, statesWithChoice);
276
277 // Check if converged
278 if (newCandidates == candidateStates) {
279 assert(!candidateStates.empty());
280 return true;
281 }
282 candidateStates = std::move(newCandidates);
283 }
284 return false;
285}
286
287template<typename T>
288std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<T> const& transitionMatrix, storm::storage::BitVector const& initialStates,
289 boost::optional<storm::storage::BitVector> const& subsystem) {
290 std::vector<uint_fast64_t> distances(transitionMatrix.getRowGroupCount());
291
292 std::vector<std::pair<storm::storage::sparse::state_type, uint_fast64_t>> stateQueue;
293 stateQueue.reserve(transitionMatrix.getRowGroupCount());
294 storm::storage::BitVector statesInQueue(transitionMatrix.getRowGroupCount());
295
296 storm::storage::sparse::state_type currentPosition = 0;
297 for (auto initialState : initialStates) {
298 stateQueue.emplace_back(initialState, 0);
299 statesInQueue.set(initialState);
300 }
301
302 // Perform a BFS.
303 while (currentPosition < stateQueue.size()) {
304 std::pair<storm::storage::sparse::state_type, std::size_t> const& stateDistancePair = stateQueue[currentPosition];
305 distances[stateDistancePair.first] = stateDistancePair.second;
306
307 for (auto const& successorEntry : transitionMatrix.getRowGroup(stateDistancePair.first)) {
308 if (!statesInQueue.get(successorEntry.getColumn())) {
309 if (!subsystem || subsystem.get()[successorEntry.getColumn()]) {
310 stateQueue.emplace_back(successorEntry.getColumn(), stateDistancePair.second + 1);
311 statesInQueue.set(successorEntry.getColumn());
312 }
313 }
314 }
315 ++currentPosition;
316 }
317
318 return distances;
319}
320
321template<typename T>
323 storm::storage::BitVector const& psiStates, bool useStepBound, uint_fast64_t maximalSteps) {
324 // Prepare the resulting bit vector.
325 uint_fast64_t numberOfStates = phiStates.size();
326 storm::storage::BitVector statesWithProbabilityGreater0(numberOfStates);
327
328 // Add all psi states as they already satisfy the condition.
329 statesWithProbabilityGreater0 |= psiStates;
330
331 // Initialize the stack used for the DFS with the states.
332 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
333
334 // Initialize the stack for the step bound, if the number of steps is bounded.
335 std::vector<uint_fast64_t> stepStack;
336 std::vector<uint_fast64_t> remainingSteps;
337 if (useStepBound) {
338 stepStack.reserve(numberOfStates);
339 stepStack.insert(stepStack.begin(), psiStates.getNumberOfSetBits(), maximalSteps);
340 remainingSteps.resize(numberOfStates);
341 for (auto state : psiStates) {
342 remainingSteps[state] = maximalSteps;
343 }
344 }
345
346 // Perform the actual DFS.
347 uint_fast64_t currentState, currentStepBound;
348 while (!stack.empty()) {
349 currentState = stack.back();
350 stack.pop_back();
351
352 if (useStepBound) {
353 currentStepBound = stepStack.back();
354 stepStack.pop_back();
355 if (currentStepBound == 0) {
356 continue;
357 }
358 }
359
360 for (typename storm::storage::SparseMatrix<T>::const_iterator entryIt = backwardTransitions.begin(currentState),
361 entryIte = backwardTransitions.end(currentState);
362 entryIt != entryIte; ++entryIt) {
363 if (phiStates[entryIt->getColumn()] &&
364 (!statesWithProbabilityGreater0.get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
365 statesWithProbabilityGreater0.set(entryIt->getColumn(), true);
366
367 // If we don't have a bound on the number of steps to take, just add the state to the stack.
368 if (useStepBound) {
369 // As there is at least one more step to go, we need to push the state and the new number of steps.
370 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
371 stepStack.push_back(currentStepBound - 1);
372 }
373 stack.push_back(entryIt->getColumn());
374 }
375 }
376 }
377
378 // Return result.
379 return statesWithProbabilityGreater0;
380}
381
382template<typename T>
384 storm::storage::BitVector const& psiStates, storm::storage::BitVector const& statesWithProbabilityGreater0) {
385 storm::storage::BitVector statesWithProbability1 = performProbGreater0(backwardTransitions, ~psiStates, ~statesWithProbabilityGreater0);
386 statesWithProbability1.complement();
387 return statesWithProbability1;
388}
389
390template<typename T>
392 storm::storage::BitVector const& psiStates) {
393 storm::storage::BitVector statesWithProbabilityGreater0 = performProbGreater0(backwardTransitions, phiStates, psiStates);
394 storm::storage::BitVector statesWithProbability1 = performProbGreater0(backwardTransitions, ~psiStates, ~(statesWithProbabilityGreater0));
395 statesWithProbability1.complement();
396 return statesWithProbability1;
397}
398
399template<typename T>
400std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::sparse::DeterministicModel<T> const& model,
401 storm::storage::BitVector const& phiStates,
402 storm::storage::BitVector const& psiStates) {
403 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
404 storm::storage::SparseMatrix<T> backwardTransitions = model.getBackwardTransitions();
405 result.first = performProbGreater0(backwardTransitions, phiStates, psiStates);
406 result.second = performProb1(backwardTransitions, phiStates, psiStates, result.first);
407 result.first.complement();
408 return result;
409}
410
411template<typename T>
412std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::storage::SparseMatrix<T> const& backwardTransitions,
413 storm::storage::BitVector const& phiStates,
414 storm::storage::BitVector const& psiStates) {
415 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
416 result.first = performProbGreater0(backwardTransitions, phiStates, psiStates);
417 result.second = performProb1(backwardTransitions, phiStates, psiStates, result.first);
418 result.first.complement();
419 return result;
420}
421
422template<storm::dd::DdType Type, typename ValueType>
424 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates,
425 boost::optional<uint_fast64_t> const& stepBound) {
426 // Initialize environment for backward search.
427 storm::dd::DdManager<Type> const& manager = model.getManager();
428 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
429 storm::dd::Bdd<Type> statesWithProbabilityGreater0 = psiStates;
430
431 uint_fast64_t iterations = 0;
432 while (lastIterationStates != statesWithProbabilityGreater0) {
433 if (stepBound && iterations >= stepBound.get()) {
434 break;
435 }
436
437 lastIterationStates = statesWithProbabilityGreater0;
438 statesWithProbabilityGreater0 =
439 statesWithProbabilityGreater0.inverseRelationalProduct(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
440 statesWithProbabilityGreater0 &= phiStates;
441 statesWithProbabilityGreater0 |= lastIterationStates;
442 ++iterations;
443 }
444
445 return statesWithProbabilityGreater0;
446}
447
448template<storm::dd::DdType Type, typename ValueType>
450 storm::dd::Bdd<Type> const&, storm::dd::Bdd<Type> const& psiStates,
451 storm::dd::Bdd<Type> const& statesWithProbabilityGreater0) {
452 storm::dd::Bdd<Type> statesWithProbability1 =
453 performProbGreater0(model, transitionMatrix, !psiStates && model.getReachableStates(), !statesWithProbabilityGreater0 && model.getReachableStates());
454 statesWithProbability1 = !statesWithProbability1 && model.getReachableStates();
455 return statesWithProbability1;
456}
457
458template<storm::dd::DdType Type, typename ValueType>
460 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
461 storm::dd::Bdd<Type> statesWithProbabilityGreater0 = performProbGreater0(model, transitionMatrix, phiStates, psiStates);
462 return performProb1(model, transitionMatrix, phiStates, psiStates, statesWithProbabilityGreater0);
463}
464
465template<storm::dd::DdType Type, typename ValueType>
467 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
468 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
469 storm::dd::Bdd<Type> transitionMatrix = model.getTransitionMatrix().notZero();
470 result.first = performProbGreater0(model, transitionMatrix, phiStates, psiStates);
471 result.second = !performProbGreater0(model, transitionMatrix, !psiStates && model.getReachableStates(), !result.first && model.getReachableStates()) &&
472 model.getReachableStates();
473 result.first = !result.first && model.getReachableStates();
474 return result;
475}
476
477template<storm::dd::DdType Type, typename ValueType>
479 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
480 storm::dd::Bdd<Type> const& psiStates) {
481 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
482 result.first = performProbGreater0(model, transitionMatrix, phiStates, psiStates);
483 result.second = !performProbGreater0(model, transitionMatrix, !psiStates && model.getReachableStates(), !result.first && model.getReachableStates()) &&
484 model.getReachableStates();
485 result.first = !result.first && model.getReachableStates();
486 return result;
487}
488
489template<typename T, typename SchedulerValueType>
491 storm::storage::Scheduler<SchedulerValueType>& scheduler, boost::optional<storm::storage::BitVector> const& rowFilter) {
492 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
493
494 for (auto state : states) {
495 [[maybe_unused]] bool setValue{false};
496 for (auto choice : transitionMatrix.getRowGroupIndices(state)) {
497 if (rowFilter && !rowFilter->get(choice)) {
498 continue;
499 }
500 auto const row = transitionMatrix.getRow(choice);
501 bool const allSuccessorsInStates = std::all_of(row.begin(), row.end(), [&states](auto const& entry) { return states.get(entry.getColumn()); });
502 if (allSuccessorsInStates) {
503 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
504 scheduler.setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
505 }
506 setValue = true;
507 break;
508 }
509 }
510 STORM_LOG_ASSERT(setValue, "Expected that at least one action for state " << state << " stays within the selected state");
511 }
512}
513
514template<typename T, typename SchedulerValueType>
517 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
518
519 for (auto state : states) {
520 [[maybe_unused]] bool setValue = false;
521 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
522 bool oneSuccessorInStates = false;
523 for (auto const& element : transitionMatrix.getRow(choice)) {
524 if (states.get(element.getColumn())) {
525 oneSuccessorInStates = true;
526 break;
527 }
528 }
529 if (oneSuccessorInStates) {
530 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
531 scheduler.setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
532 }
533 setValue = true;
534 break;
535 }
536 }
537 STORM_LOG_ASSERT(setValue, "Expected that at least one action for state " << state << " leads with positive probability to the selected state");
538 }
539}
540
541template<typename T, typename SchedulerValueType>
543 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
544 storm::storage::Scheduler<SchedulerValueType>& scheduler, boost::optional<storm::storage::BitVector> const& rowFilter) {
545 // Perform backwards DFS from psiStates and find a valid choice for each visited state.
546
547 std::vector<uint_fast64_t> stack;
548 storm::storage::BitVector currentStates(psiStates); // the states that are either psiStates or for which we have found a valid choice.
549 stack.insert(stack.end(), currentStates.begin(), currentStates.end());
550 uint_fast64_t currentState = 0;
551
552 while (!stack.empty()) {
553 currentState = stack.back();
554 stack.pop_back();
555
556 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
557 predecessorEntryIte = backwardTransitions.end(currentState);
558 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
559 uint_fast64_t const& predecessor = predecessorEntryIt->getColumn();
560 if (phiStates.get(predecessor) && !currentStates.get(predecessor)) {
561 // The predecessor is a probGreater0E state that has not been considered yet. Let's find the right choice that leads to a state in
562 // currentStates.
563 bool foundValidChoice = false;
564 for (uint_fast64_t row = transitionMatrix.getRowGroupIndices()[predecessor]; row < transitionMatrix.getRowGroupIndices()[predecessor + 1];
565 ++row) {
566 if (rowFilter && !rowFilter->get(row)) {
567 continue;
568 }
569 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
570 successorEntryIte = transitionMatrix.end(row);
571 successorEntryIt != successorEntryIte; ++successorEntryIt) {
572 if (currentStates.get(successorEntryIt->getColumn())) {
573 foundValidChoice = true;
574 break;
575 }
576 }
577 if (foundValidChoice) {
578 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
579 scheduler.setChoice(row - transitionMatrix.getRowGroupIndices()[predecessor], predecessor, memState);
580 }
581 currentStates.set(predecessor, true);
582 stack.push_back(predecessor);
583 break;
584 }
585 }
586 STORM_LOG_INFO_COND(foundValidChoice, "Could not find a valid choice for ProbGreater0E state " << predecessor << ".");
587 }
588 }
589 }
590}
591
592template<typename T, typename SchedulerValueType>
595 computeSchedulerStayingInStates(prob0EStates, transitionMatrix, scheduler);
596}
597
598template<typename T, typename SchedulerValueType>
601 // Get the states from which we can never exit the rewInfStates, i.e. the states satisfying Pmax=1 [ G "rewInfStates"]
602 // Also set a corresponding choice for all those states
603 storm::storage::BitVector trapStates(rewInfStates.size(), false);
604 auto const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
605 for (auto state : rewInfStates) {
606 STORM_LOG_ASSERT(nondeterministicChoiceIndices[state + 1] - nondeterministicChoiceIndices[state] > 0,
607 "Expected at least one action enabled in state " << state);
608 for (uint_fast64_t choice = nondeterministicChoiceIndices[state]; choice < nondeterministicChoiceIndices[state + 1]; ++choice) {
609 auto const& row = transitionMatrix.getRow(choice);
610 if (std::all_of(row.begin(), row.end(), [&rewInfStates](auto const& entry) { return rewInfStates.get(entry.getColumn()); })) {
611 trapStates.set(state, true);
612 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
613 scheduler.setChoice(choice - nondeterministicChoiceIndices[state], state, memState);
614 }
615 break;
616 }
617 }
618 }
619 // All remaining rewInfStates must reach a trapState with positive probability
620 computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, rewInfStates, trapStates, scheduler);
621}
622
623template<typename T, typename SchedulerValueType>
625 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
627 boost::optional<storm::storage::BitVector> const& rowFilter) {
628 // set an arbitrary (valid) choice for the psi states.
629 for (auto psiState : psiStates) {
630 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
631 if (!scheduler.getChoice(psiState, memState).isDefined()) {
632 scheduler.setChoice(0, psiState, memState);
633 }
634 }
635 }
636
637 // Now perform a backwards search from the psi states and store choices with prob. 1
638 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
639 std::vector<uint_fast64_t> stack;
640 storm::storage::BitVector currentStates(psiStates);
641 stack.insert(stack.end(), currentStates.begin(), currentStates.end());
642 uint_fast64_t currentState = 0;
643
644 while (!stack.empty()) {
645 currentState = stack.back();
646 stack.pop_back();
647
648 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
649 predecessorEntryIte = backwardTransitions.end(currentState);
650 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
651 if (phiStates.get(predecessorEntryIt->getColumn()) && !currentStates.get(predecessorEntryIt->getColumn())) {
652 // Check whether the predecessor has only successors in the prob1E state set for one of the
653 // nondeterminstic choices.
654 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
655 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
656 if (!rowFilter || rowFilter.get().get(row)) {
657 bool allSuccessorsInProb1EStates = true;
658 bool hasSuccessorInCurrentStates = false;
659 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
660 successorEntryIte = transitionMatrix.end(row);
661 successorEntryIt != successorEntryIte; ++successorEntryIt) {
662 if (!prob1EStates.get(successorEntryIt->getColumn())) {
663 allSuccessorsInProb1EStates = false;
664 break;
665 } else if (currentStates.get(successorEntryIt->getColumn())) {
666 hasSuccessorInCurrentStates = true;
667 }
668 }
669
670 // If all successors for a given nondeterministic choice are in the prob1E state set, we
671 // perform a backward search from that state.
672 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
673 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
674 scheduler.setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
675 memState);
676 }
677 currentStates.set(predecessorEntryIt->getColumn(), true);
678 stack.push_back(predecessorEntryIt->getColumn());
679 break;
680 }
681 }
682 }
683 }
684 }
685 }
686}
687
688template<typename T>
690 storm::storage::BitVector const& psiStates, bool useStepBound, uint_fast64_t maximalSteps) {
691 size_t numberOfStates = phiStates.size();
692
693 // Prepare resulting bit vector.
694 storm::storage::BitVector statesWithProbabilityGreater0(numberOfStates);
695
696 // Add all psi states as the already satisfy the condition.
697 statesWithProbabilityGreater0 |= psiStates;
698
699 // Initialize the stack used for the DFS with the states
700 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
701
702 // Initialize the stack for the step bound, if the number of steps is bounded.
703 std::vector<uint_fast64_t> stepStack;
704 std::vector<uint_fast64_t> remainingSteps;
705 if (useStepBound) {
706 stepStack.reserve(numberOfStates);
707 stepStack.insert(stepStack.begin(), psiStates.getNumberOfSetBits(), maximalSteps);
708 remainingSteps.resize(numberOfStates);
709 for (auto state : psiStates) {
710 remainingSteps[state] = maximalSteps;
711 }
712 }
713
714 // Perform the actual DFS.
715 uint_fast64_t currentState, currentStepBound;
716 while (!stack.empty()) {
717 currentState = stack.back();
718 stack.pop_back();
719
720 if (useStepBound) {
721 currentStepBound = stepStack.back();
722 stepStack.pop_back();
723 if (currentStepBound == 0) {
724 continue;
725 }
726 }
727
728 for (typename storm::storage::SparseMatrix<T>::const_iterator entryIt = backwardTransitions.begin(currentState),
729 entryIte = backwardTransitions.end(currentState);
730 entryIt != entryIte; ++entryIt) {
731 if (phiStates.get(entryIt->getColumn()) &&
732 (!statesWithProbabilityGreater0.get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
733 // If we don't have a bound on the number of steps to take, just add the state to the stack.
734 if (useStepBound) {
735 // If there is at least one more step to go, we need to push the state and the new number of steps.
736 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
737 stepStack.push_back(currentStepBound - 1);
738 }
739 statesWithProbabilityGreater0.set(entryIt->getColumn(), true);
740 stack.push_back(entryIt->getColumn());
741 }
742 }
743 }
744
745 return statesWithProbabilityGreater0;
746}
747
748template<typename T>
750 storm::storage::BitVector const& psiStates) {
751 storm::storage::BitVector statesWithProbability0 = performProbGreater0E(backwardTransitions, phiStates, psiStates);
752 statesWithProbability0.complement();
753 return statesWithProbability0;
754}
755
756template<typename T>
758 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
759 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
760 storm::storage::BitVector const& psiStates, boost::optional<storm::storage::BitVector> const& choiceConstraint) {
761 size_t numberOfStates = phiStates.size();
762
763 // Initialize the environment for the iterative algorithm.
764 storm::storage::BitVector currentStates(numberOfStates, true);
765 std::vector<uint_fast64_t> stack;
766 stack.reserve(numberOfStates);
767
768 // Perform the loop as long as the set of states gets larger.
769 bool done = false;
770 uint_fast64_t currentState;
771 while (!done) {
772 stack.clear();
773 storm::storage::BitVector nextStates(psiStates);
774 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
775
776 while (!stack.empty()) {
777 currentState = stack.back();
778 stack.pop_back();
779
780 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
781 predecessorEntryIte = backwardTransitions.end(currentState);
782 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
783 if (phiStates.get(predecessorEntryIt->getColumn()) && !nextStates.get(predecessorEntryIt->getColumn())) {
784 // Check whether the predecessor has only successors in the current state set for one of the
785 // nondeterminstic choices.
786 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
787 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
788 if (!choiceConstraint || choiceConstraint.get().get(row)) {
789 bool allSuccessorsInCurrentStates = true;
790 bool hasNextStateSuccessor = false;
791 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
792 successorEntryIte = transitionMatrix.end(row);
793 successorEntryIt != successorEntryIte; ++successorEntryIt) {
794 if (!currentStates.get(successorEntryIt->getColumn())) {
795 allSuccessorsInCurrentStates = false;
796 break;
797 } else if (nextStates.get(successorEntryIt->getColumn())) {
798 hasNextStateSuccessor = true;
799 }
800 }
801
802 // If all successors for a given nondeterministic choice are in the current state set, we
803 // add it to the set of states for the next iteration and perform a backward search from
804 // that state.
805 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
806 nextStates.set(predecessorEntryIt->getColumn(), true);
807 stack.push_back(predecessorEntryIt->getColumn());
808 break;
809 }
810 }
811 }
812 }
813 }
814 }
815
816 // Check whether we need to perform an additional iteration.
817 if (currentStates == nextStates) {
818 done = true;
819 } else {
820 currentStates = std::move(nextStates);
821 }
822 }
823
824 return currentStates;
825}
826
827template<typename T, typename RM>
829 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
830 storm::storage::BitVector const& psiStates) {
831 return performProb1E(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
832}
833
834template<typename T>
835std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::storage::SparseMatrix<T> const& transitionMatrix,
836 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
837 storm::storage::SparseMatrix<T> const& backwardTransitions,
838 storm::storage::BitVector const& phiStates,
839 storm::storage::BitVector const& psiStates) {
840 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
841
842 result.first = performProb0A(backwardTransitions, phiStates, psiStates);
843
844 result.second = performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
845 return result;
846}
847
848template<typename T, typename RM>
849std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::models::sparse::NondeterministicModel<T, RM> const& model,
850 storm::storage::BitVector const& phiStates,
851 storm::storage::BitVector const& psiStates) {
852 return performProb01Max(model.getTransitionMatrix(), model.getTransitionMatrix().getRowGroupIndices(), model.getBackwardTransitions(), phiStates,
853 psiStates);
854}
855
856template<typename T>
858 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
859 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
860 storm::storage::BitVector const& psiStates, bool useStepBound, uint_fast64_t maximalSteps,
861 boost::optional<storm::storage::BitVector> const& choiceConstraint) {
862 size_t numberOfStates = phiStates.size();
863
864 // Prepare resulting bit vector.
865 storm::storage::BitVector statesWithProbabilityGreater0(numberOfStates);
866
867 // Add all psi states as the already satisfy the condition.
868 statesWithProbabilityGreater0 |= psiStates;
869
870 // Initialize the stack used for the DFS with the states
871 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
872
873 // Initialize the stack for the step bound, if the number of steps is bounded.
874 std::vector<uint_fast64_t> stepStack;
875 std::vector<uint_fast64_t> remainingSteps;
876 if (useStepBound) {
877 stepStack.reserve(numberOfStates);
878 stepStack.insert(stepStack.begin(), psiStates.getNumberOfSetBits(), maximalSteps);
879 remainingSteps.resize(numberOfStates);
880 for (auto state : psiStates) {
881 remainingSteps[state] = maximalSteps;
882 }
883 }
884
885 // Perform the actual DFS.
886 uint_fast64_t currentState, currentStepBound;
887 while (!stack.empty()) {
888 currentState = stack.back();
889 stack.pop_back();
890
891 if (useStepBound) {
892 currentStepBound = stepStack.back();
893 stepStack.pop_back();
894 if (currentStepBound == 0) {
895 continue;
896 }
897 }
898
899 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
900 predecessorEntryIte = backwardTransitions.end(currentState);
901 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
902 if (phiStates.get(predecessorEntryIt->getColumn())) {
903 if (!statesWithProbabilityGreater0.get(predecessorEntryIt->getColumn())) {
904 // Check whether the predecessor has at least one successor in the current state set for every
905 // nondeterministic choice within the possibly given choiceConstraint.
906
907 // Note: The backwards edge might be induced by a choice that violates the choiceConstraint.
908 // However this is not problematic as long as there is at least one enabled choice for the predecessor.
909 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
910 uint_fast64_t const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
911 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
912 bool addToStatesWithProbabilityGreater0 = true;
913 for (; row < endOfGroup; ++row) {
914 if (!choiceConstraint || choiceConstraint->get(row)) {
915 bool hasAtLeastOneSuccessorWithProbabilityGreater0 = false;
916 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
917 successorEntryIte = transitionMatrix.end(row);
918 successorEntryIt != successorEntryIte; ++successorEntryIt) {
919 if (statesWithProbabilityGreater0.get(successorEntryIt->getColumn())) {
920 hasAtLeastOneSuccessorWithProbabilityGreater0 = true;
921 break;
922 }
923 }
924
925 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
926 addToStatesWithProbabilityGreater0 = false;
927 break;
928 }
929 }
930 }
931
932 // If we need to add the state, then actually add it and perform further search from the state.
933 if (addToStatesWithProbabilityGreater0) {
934 // If we don't have a bound on the number of steps to take, just add the state to the stack.
935 if (useStepBound) {
936 // If there is at least one more step to go, we need to push the state and the new number of steps.
937 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
938 stepStack.push_back(currentStepBound - 1);
939 }
940 statesWithProbabilityGreater0.set(predecessorEntryIt->getColumn(), true);
941 stack.push_back(predecessorEntryIt->getColumn());
942 }
943 }
944
945 } else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
946 // We have found a shorter path to the predecessor. Hence, we need to explore it again.
947 // If there is a choiceConstraint, we still need to check whether the backwards edge was induced by a valid action
948 bool predecessorIsValid = true;
949 if (choiceConstraint) {
950 predecessorIsValid = false;
951 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
952 uint_fast64_t const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
953 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
954 for (auto const& entry : transitionMatrix.getRow(row)) {
955 if (entry.getColumn() == currentState) {
956 predecessorIsValid = true;
957 break;
958 }
959 }
960 }
961 }
962 if (predecessorIsValid) {
963 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
964 stepStack.push_back(currentStepBound - 1);
965 stack.push_back(predecessorEntryIt->getColumn());
966 }
967 }
968 }
969 }
970 }
971
972 return statesWithProbabilityGreater0;
973}
974
975template<typename T, typename RM>
977 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
978 storm::storage::BitVector const& psiStates) {
979 storm::storage::BitVector statesWithProbability0 =
980 performProbGreater0A(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
981 statesWithProbability0.complement();
982 return statesWithProbability0;
983}
984
985template<typename T>
987 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
988 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
989 storm::storage::BitVector const& psiStates) {
990 storm::storage::BitVector statesWithProbability0 =
991 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
992 statesWithProbability0.complement();
993 return statesWithProbability0;
994}
995
996template<typename T, typename RM>
998 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
999 storm::storage::BitVector const& psiStates) {
1000 return performProb1A(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
1001}
1002
1003template<typename T>
1005 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1006 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1007 storm::storage::BitVector const& psiStates) {
1008 size_t numberOfStates = phiStates.size();
1009
1010 // Initialize the environment for the iterative algorithm.
1011 storm::storage::BitVector currentStates(numberOfStates, true);
1012 std::vector<uint_fast64_t> stack;
1013 stack.reserve(numberOfStates);
1014
1015 // Perform the loop as long as the set of states gets smaller.
1016 bool done = false;
1017 uint_fast64_t currentState;
1018 while (!done) {
1019 stack.clear();
1020 storm::storage::BitVector nextStates(psiStates);
1021 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
1022
1023 while (!stack.empty()) {
1024 currentState = stack.back();
1025 stack.pop_back();
1026
1027 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
1028 predecessorEntryIte = backwardTransitions.end(currentState);
1029 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1030 if (phiStates.get(predecessorEntryIt->getColumn()) && !nextStates.get(predecessorEntryIt->getColumn())) {
1031 // Check whether the predecessor has only successors in the current state set for all of the
1032 // nondeterminstic choices and that for each choice there exists a successor that is already
1033 // in the next states.
1034 bool addToStatesWithProbability1 = true;
1035 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1036 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1037 bool hasAtLeastOneSuccessorWithProbability1 = false;
1038 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
1039 successorEntryIte = transitionMatrix.end(row);
1040 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1041 if (!currentStates.get(successorEntryIt->getColumn())) {
1042 addToStatesWithProbability1 = false;
1043 goto afterCheckLoop;
1044 }
1045 if (nextStates.get(successorEntryIt->getColumn())) {
1046 hasAtLeastOneSuccessorWithProbability1 = true;
1047 }
1048 }
1049
1050 if (!hasAtLeastOneSuccessorWithProbability1) {
1051 addToStatesWithProbability1 = false;
1052 break;
1053 }
1054 }
1055
1056 afterCheckLoop:
1057 // If all successors for all nondeterministic choices are in the current state set, we
1058 // add it to the set of states for the next iteration and perform a backward search from
1059 // that state.
1060 if (addToStatesWithProbability1) {
1061 nextStates.set(predecessorEntryIt->getColumn(), true);
1062 stack.push_back(predecessorEntryIt->getColumn());
1063 }
1064 }
1065 }
1066 }
1067
1068 // Check whether we need to perform an additional iteration.
1069 if (currentStates == nextStates) {
1070 done = true;
1071 } else {
1072 currentStates = std::move(nextStates);
1073 }
1074 }
1075 return currentStates;
1076}
1077
1078template<typename T>
1079std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::storage::SparseMatrix<T> const& transitionMatrix,
1080 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1081 storm::storage::SparseMatrix<T> const& backwardTransitions,
1082 storm::storage::BitVector const& phiStates,
1083 storm::storage::BitVector const& psiStates) {
1084 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1085 result.first = performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1086 // Instead of calling performProb1A, we call the (more easier) performProb0A on the Prob0E states.
1087 // This is valid because, when minimizing probabilities, states that have prob1 cannot reach a state with prob 0 (and will eventually reach a psiState).
1088 // States that do not have prob1 will eventually reach a state with prob0.
1089 result.second = performProb0A(backwardTransitions, ~psiStates, result.first);
1090 return result;
1091}
1092
1093template<typename T, typename RM>
1094std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::models::sparse::NondeterministicModel<T, RM> const& model,
1095 storm::storage::BitVector const& phiStates,
1096 storm::storage::BitVector const& psiStates) {
1097 return performProb01Min(model.getTransitionMatrix(), model.getTransitionMatrix().getRowGroupIndices(), model.getBackwardTransitions(), phiStates,
1098 psiStates);
1099}
1100
1101template<storm::dd::DdType Type, typename ValueType>
1103 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1104 storm::dd::Bdd<Type> const& psiStates) {
1105 // Initialize environment for backward search.
1106 storm::dd::DdManager<Type> const& manager = model.getManager();
1107 storm::dd::Bdd<Type> statesWithProbabilityGreater0E = manager.getBddZero();
1108 storm::dd::Bdd<Type> frontier = psiStates;
1109 storm::dd::Bdd<Type> scheduler = manager.getBddZero();
1110
1111 while (!frontier.isZero()) {
1112 storm::dd::Bdd<Type> statesAndChoicesWithProbabilityGreater0E =
1113 frontier.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1114 frontier = phiStates && statesAndChoicesWithProbabilityGreater0E.existsAbstract(model.getNondeterminismVariables()) && !statesWithProbabilityGreater0E;
1115 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.getNondeterminismVariables());
1116 statesWithProbabilityGreater0E |= frontier;
1117 }
1118
1119 return scheduler;
1120}
1121
1122template<storm::dd::DdType Type, typename ValueType>
1124 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1125 storm::dd::Bdd<Type> const& psiStates) {
1126 // Initialize environment for backward search.
1127 storm::dd::DdManager<Type> const& manager = model.getManager();
1128 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1129 storm::dd::Bdd<Type> statesWithProbabilityGreater0E = psiStates;
1130
1131 storm::dd::Bdd<Type> abstractedTransitionMatrix = transitionMatrix.existsAbstract(model.getNondeterminismVariables());
1132 while (lastIterationStates != statesWithProbabilityGreater0E) {
1133 lastIterationStates = statesWithProbabilityGreater0E;
1134 statesWithProbabilityGreater0E =
1135 statesWithProbabilityGreater0E.inverseRelationalProduct(abstractedTransitionMatrix, model.getRowVariables(), model.getColumnVariables());
1136 statesWithProbabilityGreater0E &= phiStates;
1137 statesWithProbabilityGreater0E |= lastIterationStates;
1138 }
1139
1140 return statesWithProbabilityGreater0E;
1141}
1142
1143template<storm::dd::DdType Type, typename ValueType>
1145 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1146 return !performProbGreater0E(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
1147}
1148
1149template<storm::dd::DdType Type, typename ValueType>
1151 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1152 storm::dd::Bdd<Type> const& psiStates) {
1153 // Initialize environment for backward search.
1154 storm::dd::DdManager<Type> const& manager = model.getManager();
1155 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1156 storm::dd::Bdd<Type> statesWithProbabilityGreater0A = psiStates;
1157
1158 while (lastIterationStates != statesWithProbabilityGreater0A) {
1159 lastIterationStates = statesWithProbabilityGreater0A;
1160 statesWithProbabilityGreater0A =
1161 statesWithProbabilityGreater0A.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1162 statesWithProbabilityGreater0A |= model.getIllegalMask();
1163 statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.universalAbstract(model.getNondeterminismVariables());
1164 statesWithProbabilityGreater0A &= phiStates;
1165 statesWithProbabilityGreater0A |= psiStates;
1166 }
1167
1168 return statesWithProbabilityGreater0A;
1169}
1170
1171template<storm::dd::DdType Type, typename ValueType>
1173 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1174 return !performProbGreater0A(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
1175}
1176
1177template<storm::dd::DdType Type, typename ValueType>
1179 storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0A) {
1180 // Initialize environment for backward search.
1181 storm::dd::DdManager<Type> const& manager = model.getManager();
1182 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1183 storm::dd::Bdd<Type> statesWithProbability1A = psiStates || statesWithProbabilityGreater0A;
1184
1185 while (lastIterationStates != statesWithProbability1A) {
1186 lastIterationStates = statesWithProbability1A;
1187 statesWithProbability1A = statesWithProbability1A.swapVariables(model.getRowColumnMetaVariablePairs());
1188 statesWithProbability1A = transitionMatrix.implies(statesWithProbability1A).universalAbstract(model.getColumnVariables());
1189 statesWithProbability1A |= model.getIllegalMask();
1190 statesWithProbability1A = statesWithProbability1A.universalAbstract(model.getNondeterminismVariables());
1191 statesWithProbability1A &= statesWithProbabilityGreater0A;
1192 statesWithProbability1A |= psiStates;
1193 }
1194
1195 return statesWithProbability1A;
1196}
1197
1198template<storm::dd::DdType Type, typename ValueType>
1200 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates,
1201 storm::dd::Bdd<Type> const& statesWithProbabilityGreater0E) {
1202 // Initialize environment for backward search.
1203 storm::dd::DdManager<Type> const& manager = model.getManager();
1204 storm::dd::Bdd<Type> statesWithProbability1E = statesWithProbabilityGreater0E;
1205
1206 bool outerLoopDone = false;
1207 while (!outerLoopDone) {
1208 storm::dd::Bdd<Type> innerStates = manager.getBddZero();
1209
1210 bool innerLoopDone = false;
1211 while (!innerLoopDone) {
1212 storm::dd::Bdd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
1213 temporary = transitionMatrix.implies(temporary).universalAbstract(model.getColumnVariables());
1214
1215 storm::dd::Bdd<Type> temporary2 =
1216 innerStates.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1217
1218 temporary = temporary.andExists(temporary2, model.getNondeterminismVariables());
1219 temporary &= phiStates;
1220 temporary |= psiStates;
1221
1222 if (innerStates == temporary) {
1223 innerLoopDone = true;
1224 } else {
1225 innerStates = temporary;
1226 }
1227 }
1228
1229 if (statesWithProbability1E == innerStates) {
1230 outerLoopDone = true;
1231 } else {
1232 statesWithProbability1E = innerStates;
1233 }
1234 }
1235
1236 return statesWithProbability1E;
1237}
1238
1239template<storm::dd::DdType Type, typename ValueType>
1241 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1242 storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbability1E) {
1243 // Initialize environment for backward search.
1244 storm::dd::DdManager<Type> const& manager = model.getManager();
1245 storm::dd::Bdd<Type> scheduler = manager.getBddZero();
1246
1247 storm::dd::Bdd<Type> innerStates = manager.getBddZero();
1248
1249 bool innerLoopDone = false;
1250 while (!innerLoopDone) {
1251 storm::dd::Bdd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
1252 temporary = transitionMatrix.implies(temporary).universalAbstract(model.getColumnVariables());
1253
1254 storm::dd::Bdd<Type> temporary2 =
1255 innerStates.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1256 temporary &= temporary2;
1257 temporary &= phiStates;
1258
1259 // Extend the scheduler for those states that have not been seen as inner states before.
1260 scheduler |= (temporary && !innerStates).existsAbstractRepresentative(model.getNondeterminismVariables());
1261
1262 temporary = temporary.existsAbstract(model.getNondeterminismVariables());
1263 temporary |= psiStates;
1264
1265 if (innerStates == temporary) {
1266 innerLoopDone = true;
1267 } else {
1268 innerStates = temporary;
1269 }
1270 }
1271
1272 return scheduler;
1273}
1274
1275template<storm::dd::DdType Type, typename ValueType>
1277 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1278 return performProb01Max(model, model.getTransitionMatrix().notZero(), phiStates, psiStates);
1279}
1280
1281template<storm::dd::DdType Type, typename ValueType>
1283 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1284 storm::dd::Bdd<Type> const& psiStates) {
1285 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
1286 result.first = performProb0A(model, transitionMatrix, phiStates, psiStates);
1287 result.second = performProb1E(model, transitionMatrix, phiStates, psiStates, !result.first && model.getReachableStates());
1288 return result;
1289}
1290
1291template<storm::dd::DdType Type, typename ValueType>
1293 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1294 return performProb01Min(model, model.getTransitionMatrix().notZero(), phiStates, psiStates);
1295}
1296
1297template<storm::dd::DdType Type, typename ValueType>
1299 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1300 storm::dd::Bdd<Type> const& psiStates) {
1301 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
1302 result.first = performProb0E(model, transitionMatrix, phiStates, psiStates);
1303 result.second = performProb1A(model, transitionMatrix, psiStates, !result.first && model.getReachableStates());
1304 return result;
1305}
1306
1307template<typename ValueType>
1308ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<uint64_t> const& player1Groups,
1309 storm::storage::SparseMatrix<ValueType> const& player1BackwardTransitions,
1310 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
1311 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
1312 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair) {
1313 ExplicitGameProb01Result result(psiStates, storm::storage::BitVector(transitionMatrix.getRowGroupCount()));
1314
1315 // Initialize the stack used for the DFS with the states
1316 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
1317
1318 // Perform the actual DFS.
1319 uint_fast64_t currentState;
1320 while (!stack.empty()) {
1321 currentState = stack.back();
1322 stack.pop_back();
1323
1324 // Check which player 2 predecessors of the current player 1 state to add.
1325 for (auto const& player2PredecessorEntry : player1BackwardTransitions.getRow(currentState)) {
1326 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1327 if (!result.player2States.get(player2Predecessor)) {
1328 bool addPlayer2State = false;
1329 if (player2Direction == OptimizationDirection::Minimize) {
1330 bool allChoicesHavePlayer1State = true;
1331 for (uint64_t row = transitionMatrix.getRowGroupIndices()[player2Predecessor];
1332 row < transitionMatrix.getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1333 bool choiceHasPlayer1State = false;
1334 for (auto const& entry : transitionMatrix.getRow(row)) {
1335 if (result.player1States.get(entry.getColumn())) {
1336 choiceHasPlayer1State = true;
1337 break;
1338 }
1339 }
1340 if (!choiceHasPlayer1State) {
1341 allChoicesHavePlayer1State = false;
1342 }
1343 }
1344 if (allChoicesHavePlayer1State) {
1345 addPlayer2State = true;
1346 }
1347 } else {
1348 addPlayer2State = true;
1349 }
1350
1351 if (addPlayer2State) {
1352 result.player2States.set(player2Predecessor);
1353
1354 // Now check whether adding the player 2 state changes something with respect to the
1355 // (single) player 1 predecessor.
1356 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1357
1358 if (!result.player1States.get(player1Predecessor)) {
1359 bool addPlayer1State = false;
1360 if (player1Direction == OptimizationDirection::Minimize) {
1361 bool allPlayer2Successors = true;
1362 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1363 ++player2State) {
1364 if (!result.player2States.get(player2State)) {
1365 allPlayer2Successors = false;
1366 break;
1367 }
1368 }
1369 if (allPlayer2Successors) {
1370 addPlayer1State = true;
1371 }
1372 } else {
1373 addPlayer1State = true;
1374 }
1375
1376 if (addPlayer1State) {
1377 result.player1States.set(player1Predecessor);
1378 stack.emplace_back(player1Predecessor);
1379 }
1380 }
1381 }
1382 }
1383 }
1384 }
1385
1386 // Since we have determined the complements of the desired sets, we need to complement it now.
1387 result.player1States.complement();
1388 result.player2States.complement();
1389
1390 // Generate player 1 strategy if required.
1391 if (strategyPair) {
1392 for (auto player1State : result.player1States) {
1393 if (player1Direction == storm::OptimizationDirection::Minimize) {
1394 // At least one player 2 successor is a state with probability 0, find it.
1395 [[maybe_unused]] bool foundProb0Successor = false;
1396 uint64_t player2State;
1397 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1398 if (result.player2States.get(player2State)) {
1399 foundProb0Successor = true;
1400 break;
1401 }
1402 }
1403 STORM_LOG_ASSERT(foundProb0Successor, "Expected at least one state 2 successor with probability 0.");
1404 strategyPair->getPlayer1Strategy().setChoice(player1State, player2State);
1405 } else {
1406 // Since all player 2 successors are states with probability 0, just pick any.
1407 strategyPair->getPlayer1Strategy().setChoice(player1State, player1Groups[player1State]);
1408 }
1409 }
1410 }
1411
1412 // Generate player 2 strategy if required.
1413 if (strategyPair) {
1414 for (auto player2State : result.player2States) {
1415 if (player2Direction == storm::OptimizationDirection::Minimize) {
1416 // At least one distribution only has successors with probability 0, find it.
1417 [[maybe_unused]] bool foundProb0SuccessorDistribution = false;
1418
1419 uint64_t row;
1420 for (row = transitionMatrix.getRowGroupIndices()[player2State]; row < transitionMatrix.getRowGroupIndices()[player2State + 1]; ++row) {
1421 bool distributionHasOnlyProb0Successors = true;
1422 for (auto const& player1SuccessorEntry : transitionMatrix.getRow(row)) {
1423 if (!result.player1States.get(player1SuccessorEntry.getColumn())) {
1424 distributionHasOnlyProb0Successors = false;
1425 break;
1426 }
1427 }
1428 if (distributionHasOnlyProb0Successors) {
1429 foundProb0SuccessorDistribution = true;
1430 break;
1431 }
1432 }
1433
1434 STORM_LOG_ASSERT(foundProb0SuccessorDistribution, "Expected at least one distribution with only successors with probability 0.");
1435 strategyPair->getPlayer2Strategy().setChoice(player2State, row);
1436 } else {
1437 // Since all player 1 successors are states with probability 0, just pick any.
1438 strategyPair->getPlayer2Strategy().setChoice(player2State, transitionMatrix.getRowGroupIndices()[player2State]);
1439 }
1440 }
1441 }
1442
1443 return result;
1444}
1445
1446template<storm::dd::DdType Type, typename ValueType>
1448 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1449 storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy,
1450 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy) {
1451 // The solution sets.
1452 storm::dd::Bdd<Type> player1States = psiStates;
1453 storm::dd::Bdd<Type> player2States = model.getManager().getBddZero();
1454
1455 bool done = false;
1456 while (!done) {
1458 (transitionMatrix && player1States.swapVariables(model.getRowColumnMetaVariablePairs())).existsAbstract(model.getColumnVariables()) && phiStates;
1459
1460 if (player2Strategy == OptimizationDirection::Minimize) {
1461 tmp = (tmp || model.getIllegalPlayer2Mask()).universalAbstract(model.getPlayer2Variables());
1462 } else {
1463 tmp = tmp.existsAbstract(model.getPlayer2Variables());
1464 }
1465 player2States |= tmp;
1466
1467 if (player1Strategy == OptimizationDirection::Minimize) {
1468 tmp = (tmp || model.getIllegalPlayer1Mask()).universalAbstract(model.getPlayer1Variables());
1469 } else {
1470 tmp = tmp.existsAbstract(model.getPlayer1Variables());
1471 }
1472
1473 // Re-add all previous player 1 states.
1474 tmp |= player1States;
1475
1476 if (tmp == player1States) {
1477 done = true;
1478 }
1479
1480 player1States = tmp;
1481 }
1482
1483 // Since we have determined the complements of the desired sets, we need to complement it now.
1484 player1States = !player1States && model.getReachableStates();
1485
1486 std::set<storm::expressions::Variable> variablesToAbstract(model.getColumnVariables());
1487 variablesToAbstract.insert(model.getPlayer2Variables().begin(), model.getPlayer2Variables().end());
1488 player2States = !player2States && transitionMatrix.existsAbstract(variablesToAbstract);
1489
1490 // Determine all transitions between prob0 states.
1491 storm::dd::Bdd<Type> transitionsBetweenProb0States =
1492 player2States && (transitionMatrix && player1States.swapVariables(model.getRowColumnMetaVariablePairs()));
1493
1494 // Determine the distributions that have only successors that are prob0 states.
1495 storm::dd::Bdd<Type> onlyProb0Successors = (transitionsBetweenProb0States || model.getIllegalSuccessorMask()).universalAbstract(model.getColumnVariables());
1496
1497 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1498 if (producePlayer2Strategy) {
1499 // Pick a distribution that has only prob0 successors.
1500 player2StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer2Variables());
1501 }
1502
1503 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1504 if (producePlayer1Strategy) {
1505 // Move from player 2 choices with only prob0 successors to player 1 choices with only prob 0 successors.
1506 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.getPlayer2Variables());
1507
1508 // Pick a prob0 player 2 state.
1509 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables());
1510 }
1511
1512 return SymbolicGameProb01Result<Type>(player1States, player2States, player1StrategyBdd, player2StrategyBdd);
1513}
1514
1515template<typename ValueType>
1516ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<uint64_t> const& player1Groups,
1517 storm::storage::SparseMatrix<ValueType> const& player1BackwardTransitions,
1518 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
1519 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
1520 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
1521 boost::optional<storm::storage::BitVector> const& player1Candidates) {
1522 // During the execution, the two state sets in the result hold the potential player 1/2 states.
1524 if (player1Candidates) {
1525 result = ExplicitGameProb01Result(player1Candidates.get(), storm::storage::BitVector(transitionMatrix.getRowGroupCount()));
1526 } else {
1528 }
1529
1530 // A flag that governs whether strategies are produced in the current iteration.
1531 bool produceStrategiesInIteration = false;
1532
1533 // Initialize the stack used for the DFS with the states
1534 std::vector<uint_fast64_t> stack;
1535 bool maybeStatesDone = false;
1536 while (!maybeStatesDone || produceStrategiesInIteration) {
1537 storm::storage::BitVector player1Solution = psiStates;
1538 storm::storage::BitVector player2Solution(result.player2States.size());
1539
1540 stack.clear();
1541 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
1542
1543 // Perform the actual DFS.
1544 uint_fast64_t currentState;
1545 while (!stack.empty()) {
1546 currentState = stack.back();
1547 stack.pop_back();
1548
1549 for (auto player2PredecessorEntry : player1BackwardTransitions.getRow(currentState)) {
1550 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1551 if (!player2Solution.get(player2PredecessorEntry.getColumn())) {
1552 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true : false;
1553
1554 uint64_t validChoice = transitionMatrix.getRowGroupIndices()[player2Predecessor];
1555 for (uint64_t row = validChoice; row < transitionMatrix.getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1556 bool choiceHasSolutionSuccessor = false;
1557 bool choiceStaysInMaybeStates = true;
1558 for (auto const& entry : transitionMatrix.getRow(row)) {
1559 if (player1Solution.get(entry.getColumn())) {
1560 choiceHasSolutionSuccessor = true;
1561 }
1562 if (!result.player1States.get(entry.getColumn())) {
1563 choiceStaysInMaybeStates = false;
1564 break;
1565 }
1566 }
1567
1568 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1569 if (player2Direction == storm::OptimizationDirection::Maximize) {
1570 validChoice = row;
1571 addPlayer2State = true;
1572 break;
1573 }
1574 } else if (player2Direction == storm::OptimizationDirection::Minimize) {
1575 addPlayer2State = false;
1576 break;
1577 }
1578 }
1579
1580 if (addPlayer2State) {
1581 player2Solution.set(player2Predecessor);
1582 if (produceStrategiesInIteration) {
1583 strategyPair->getPlayer2Strategy().setChoice(player2Predecessor, validChoice);
1584 }
1585
1586 // Check whether the addition of the player 2 state changes the state of the (single)
1587 // player 1 predecessor.
1588 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1589
1590 if (!player1Solution.get(player1Predecessor)) {
1591 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true : false;
1592
1593 validChoice = player1Groups[player1Predecessor];
1594 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1595 if (player2Solution.get(player2Successor)) {
1596 if (player1Direction == storm::OptimizationDirection::Maximize) {
1597 validChoice = player2Successor;
1598 addPlayer1State = true;
1599 break;
1600 }
1601 } else if (player1Direction == storm::OptimizationDirection::Minimize) {
1602 addPlayer1State = false;
1603 break;
1604 }
1605 }
1606
1607 if (addPlayer1State) {
1608 player1Solution.set(player1Predecessor);
1609
1610 if (produceStrategiesInIteration) {
1611 strategyPair->getPlayer1Strategy().setChoice(player1Predecessor, validChoice);
1612 }
1613
1614 stack.emplace_back(player1Predecessor);
1615 }
1616 }
1617 }
1618 }
1619 }
1620 }
1621
1622 if (result.player1States == player1Solution) {
1623 maybeStatesDone = true;
1624 result.player2States = player2Solution;
1625
1626 // If we were asked to produce strategies, we propagate that by triggering another iteration.
1627 // We only do this if at least one strategy will be produced.
1628 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1629 } else {
1630 result.player1States = player1Solution;
1631 result.player2States = player2Solution;
1632 }
1633 }
1634
1635 return result;
1636}
1637
1638template<storm::dd::DdType Type, typename ValueType>
1640 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1641 storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy,
1642 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
1643 boost::optional<storm::dd::Bdd<Type>> const& player1Candidates) {
1644 // Create the potential prob1 states of player 1.
1645 storm::dd::Bdd<Type> maybePlayer1States = model.getReachableStates();
1646 if (player1Candidates) {
1647 maybePlayer1States &= player1Candidates.get();
1648 }
1649
1650 // Initialize potential prob1 states of player 2.
1651 storm::dd::Bdd<Type> maybePlayer2States = model.getManager().getBddZero();
1652
1653 // A flag that governs whether strategies are produced in the current iteration.
1654 bool produceStrategiesInIteration = false;
1655 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1656 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1657 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1658 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1659
1660 bool maybeStatesDone = false;
1661 while (!maybeStatesDone || produceStrategiesInIteration) {
1662 bool solutionStatesDone = false;
1663
1664 // If we are to produce strategies in this iteration, we prepare some storage.
1665 if (produceStrategiesInIteration) {
1666 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1667 player1StrategyBdd = model.getManager().getBddZero();
1668 consideredPlayer1States = model.getManager().getBddZero();
1669 }
1670 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1671 player2StrategyBdd = model.getManager().getBddZero();
1672 consideredPlayer2States = model.getManager().getBddZero();
1673 }
1674 }
1675
1676 storm::dd::Bdd<Type> player1Solution = psiStates;
1677 storm::dd::Bdd<Type> player2Solution = model.getManager().getBddZero();
1678 while (!solutionStatesDone) {
1679 // Start by computing the transitions that have only maybe states as successors. Note that at
1680 // this point, there may be illegal transitions.
1681 storm::dd::Bdd<Type> distributionsStayingInMaybe =
1682 (!transitionMatrix || maybePlayer1States.swapVariables(model.getRowColumnMetaVariablePairs())).universalAbstract(model.getColumnVariables());
1683
1684 // Then, determine all distributions that have at least one successor in the states that have
1685 // probability 1.
1686 storm::dd::Bdd<Type> distributionsWithProb1Successor =
1687 (transitionMatrix && player1Solution.swapVariables(model.getRowColumnMetaVariablePairs())).existsAbstract(model.getColumnVariables());
1688
1689 // The valid distributions are then those that emanate from phi states, stay completely in the
1690 // maybe states and have at least one successor with probability 1.
1691 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1692
1693 // Depending on the strategy of player 2, we need to check whether all choices are valid or
1694 // there exists a valid choice.
1695 if (player2Strategy == OptimizationDirection::Minimize) {
1696 valid = (valid || model.getIllegalPlayer2Mask()).universalAbstract(model.getPlayer2Variables());
1697 } else {
1698 if (produceStrategiesInIteration) {
1699 storm::dd::Bdd<Type> newValidDistributions = valid && !consideredPlayer2States.get();
1700 player2StrategyBdd.get() = player2StrategyBdd.get() || newValidDistributions.existsAbstractRepresentative(model.getPlayer2Variables());
1701 }
1702
1703 valid = valid.existsAbstract(model.getPlayer2Variables());
1704
1705 if (produceStrategiesInIteration) {
1706 consideredPlayer2States.get() |= valid;
1707 }
1708 }
1709
1710 player2Solution |= valid;
1711
1712 // And do the same for player 1.
1713 if (player1Strategy == OptimizationDirection::Minimize) {
1714 valid = (valid || model.getIllegalPlayer1Mask()).universalAbstract(model.getPlayer1Variables());
1715 } else {
1716 if (produceStrategiesInIteration) {
1717 storm::dd::Bdd<Type> newValidDistributions = valid && !consideredPlayer1States.get();
1718 player1StrategyBdd.get() = player1StrategyBdd.get() || newValidDistributions.existsAbstractRepresentative(model.getPlayer1Variables());
1719 }
1720
1721 valid = valid.existsAbstract(model.getPlayer1Variables());
1722
1723 if (produceStrategiesInIteration) {
1724 consideredPlayer1States.get() |= valid;
1725 }
1726 }
1727
1728 // Explicitly add psi states to result since they may have transitions going to some state that
1729 // does not have a reachability probability of 1.
1730 valid |= psiStates;
1731
1732 // If no new states were added, we have found the current hypothesis for the states with
1733 // probability 1.
1734 if (valid == player1Solution) {
1735 solutionStatesDone = true;
1736 } else {
1737 player1Solution = valid;
1738 }
1739 }
1740
1741 // If the states with probability 1 and the potential probability 1 states coincide, we have found
1742 // the solution.
1743 if (player1Solution == maybePlayer1States) {
1744 maybePlayer2States = player2Solution;
1745 maybeStatesDone = true;
1746
1747 // If we were asked to produce strategies, we propagate that by triggering another iteration.
1748 // We only do this if at least one strategy will be produced.
1749 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1750 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1751 } else {
1752 // Otherwise, we use the current hypothesis for the states with probability 1 as the new maybe
1753 // state set.
1754 maybePlayer1States = player1Solution;
1755 }
1756 }
1757
1758 // From now on, the solution is stored in maybeStates (as it coincides with the previous solution).
1759
1760 // If we were asked to produce strategies that do not need to pick a certain successor but are
1761 // 'arbitrary', do so now.
1762 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1763 if (strategiesToCompute) {
1764 storm::dd::Bdd<Type> relevantStates = (transitionMatrix && maybePlayer2States).existsAbstract(model.getColumnVariables());
1765 if (producePlayer2Strategy && !player2StrategyBdd) {
1766 player2StrategyBdd = relevantStates.existsAbstractRepresentative(model.getPlayer2Variables());
1767 }
1768 if (producePlayer1Strategy && !player1StrategyBdd) {
1769 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.getPlayer2Variables());
1770 player1StrategyBdd = relevantStates.existsAbstractRepresentative(model.getPlayer1Variables());
1771 }
1772 }
1773
1774 return SymbolicGameProb01Result<Type>(maybePlayer1States, maybePlayer2States, player1StrategyBdd, player2StrategyBdd);
1775}
1776
1777template<typename T>
1778void topologicalSortHelper(storm::storage::SparseMatrix<T> const& matrix, uint64_t state, std::vector<uint_fast64_t>& topologicalSort,
1779 std::vector<uint_fast64_t>& recursionStack,
1780 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator>& iteratorRecursionStack,
1781 storm::storage::BitVector& visitedStates) {
1782 if (!visitedStates.get(state)) {
1783 recursionStack.push_back(state);
1784 iteratorRecursionStack.push_back(matrix.begin(state));
1785
1786 recursionStepForward:
1787 while (!recursionStack.empty()) {
1788 uint_fast64_t currentState = recursionStack.back();
1789 typename storm::storage::SparseMatrix<T>::const_iterator successorIterator = iteratorRecursionStack.back();
1790
1791 visitedStates.set(currentState, true);
1792
1793 recursionStepBackward:
1794 for (; successorIterator != matrix.end(currentState); ++successorIterator) {
1795 if (!visitedStates.get(successorIterator->getColumn())) {
1796 // Put unvisited successor on top of our recursion stack and remember that.
1797 recursionStack.push_back(successorIterator->getColumn());
1798
1799 // Also, put initial value for iterator on corresponding recursion stack.
1800 iteratorRecursionStack.push_back(matrix.begin(successorIterator->getColumn()));
1801
1802 goto recursionStepForward;
1803 }
1804 }
1805
1806 topologicalSort.push_back(currentState);
1807
1808 // If we reach this point, we have completed the recursive descent for the current state.
1809 // That is, we need to pop it from the recursion stacks.
1810 recursionStack.pop_back();
1811 iteratorRecursionStack.pop_back();
1812
1813 // If there is at least one state under the current one in our recursion stack, we need
1814 // to restore the topmost state as the current state and jump to the part after the
1815 // original recursive call.
1816 if (recursionStack.size() > 0) {
1817 currentState = recursionStack.back();
1818 successorIterator = iteratorRecursionStack.back();
1819
1820 goto recursionStepBackward;
1821 }
1822 }
1823 }
1824}
1825
1826template<typename T>
1827std::vector<uint_fast64_t> getBFSSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint_fast64_t> const& firstStates) {
1828 storm::storage::BitVector seenStates(matrix.getRowGroupCount());
1829
1830 std::vector<uint_fast64_t> stateQueue;
1831 stateQueue.reserve(matrix.getRowGroupCount());
1832 std::vector<uint_fast64_t> result;
1833 result.reserve(matrix.getRowGroupCount());
1834
1835 // storm::storage::sparse::state_type currentPosition = 0;
1836 auto count = matrix.getRowGroupCount() - 1;
1837 for (auto const& state : firstStates) {
1838 stateQueue.push_back(state);
1839 result[count] = state;
1840 count--;
1841 }
1842
1843 // Perform a BFS.
1844 while (!stateQueue.empty()) {
1845 auto state = stateQueue.back();
1846 stateQueue.pop_back();
1847 seenStates.set(state);
1848 for (auto const& successorEntry : matrix.getRowGroup(state)) {
1849 auto succ = successorEntry.geColumn();
1850 if (!seenStates[succ]) {
1851 result[count] = succ;
1852 count--;
1853 stateQueue.insert(stateQueue.begin(), succ);
1854 }
1855 }
1856 }
1857 return result;
1858}
1859
1860template<typename T>
1861std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint64_t> const& firstStates) {
1862 if (matrix.getRowCount() != matrix.getColumnCount()) {
1863 STORM_LOG_ERROR("Provided matrix is required to be square.");
1864 throw storm::exceptions::InvalidArgumentException() << "Provided matrix is required to be square.";
1865 }
1866
1867 uint_fast64_t numberOfStates = matrix.getRowCount();
1868
1869 // Prepare the result. This relies on the matrix being square.
1870 std::vector<uint_fast64_t> topologicalSort;
1871 topologicalSort.reserve(numberOfStates);
1872
1873 // Prepare the stacks needed for recursion.
1874 std::vector<uint_fast64_t> recursionStack;
1875 recursionStack.reserve(matrix.getRowCount());
1876 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1877 iteratorRecursionStack.reserve(numberOfStates);
1878
1879 // Perform a depth-first search over the given transitions and record states in the reverse order they were visited.
1880 storm::storage::BitVector visitedStates(numberOfStates);
1881 for (auto const state : firstStates) {
1882 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1883 }
1884 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1885 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1886 }
1887
1888 return topologicalSort;
1889}
1890
1892 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
1893 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
1894 boost::optional<storm::storage::BitVector> const& choiceFilter);
1895
1897
1898template bool hasCycle(storm::storage::SparseMatrix<double> const& transitionMatrix, boost::optional<storm::storage::BitVector> const& subsystem);
1899
1901 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& subsystem,
1902 storm::storage::BitVector const& choices);
1903
1904template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<double> const& transitionMatrix, storm::storage::BitVector const& initialStates,
1905 boost::optional<storm::storage::BitVector> const& subsystem);
1906
1908 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1909 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
1910
1912 storm::storage::BitVector const& psiStates, storm::storage::BitVector const& statesWithProbabilityGreater0);
1913
1915 storm::storage::BitVector const& psiStates);
1916
1917template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::sparse::DeterministicModel<double> const& model,
1918 storm::storage::BitVector const& phiStates,
1919 storm::storage::BitVector const& psiStates);
1920
1921template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::storage::SparseMatrix<double> const& backwardTransitions,
1922 storm::storage::BitVector const& phiStates,
1923 storm::storage::BitVector const& psiStates);
1924
1926 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1928 boost::optional<storm::storage::BitVector> const& rowFilter);
1929
1930template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1932
1933template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1934 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::Scheduler<double>& scheduler);
1935
1936template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1937 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1939 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
1940
1942 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1943 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
1944
1946 storm::storage::BitVector const& psiStates);
1947
1949 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1950 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1951 storm::storage::BitVector const& psiStates,
1952 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
1953
1956 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1957
1958template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::storage::SparseMatrix<double> const& transitionMatrix,
1959 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1960 storm::storage::SparseMatrix<double> const& backwardTransitions,
1961 storm::storage::BitVector const& phiStates,
1962 storm::storage::BitVector const& psiStates);
1963
1964template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
1966 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1967
1969 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1970 storm::storage::SparseMatrix<double> const& backwardTransitions,
1971 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1972 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
1973 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
1974
1977 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1978#ifdef STORM_HAVE_CARL
1981 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1982#endif
1984 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1985 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1986 storm::storage::BitVector const& psiStates);
1987
1990 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1991#ifdef STORM_HAVE_CARL
1994 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1995#endif
1997 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1998 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1999 storm::storage::BitVector const& psiStates);
2000
2001template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::storage::SparseMatrix<double> const& transitionMatrix,
2002 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2003 storm::storage::SparseMatrix<double> const& backwardTransitions,
2004 storm::storage::BitVector const& phiStates,
2005 storm::storage::BitVector const& psiStates);
2006
2007template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2009 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2010#ifdef STORM_HAVE_CARL
2011template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2013 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2014#endif
2015
2016template ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix<double> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping,
2017 storm::storage::SparseMatrix<double> const& player1BackwardTransitions,
2018 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2019 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2020 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2021
2022template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<double> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping,
2023 storm::storage::SparseMatrix<double> const& player1BackwardTransitions,
2024 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2025 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2026 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2027 boost::optional<storm::storage::BitVector> const& player1Candidates);
2028
2029template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<double> const& matrix, std::vector<uint64_t> const& firstStates);
2030
2031// Instantiations for storm::RationalNumber.
2032#ifdef STORM_HAVE_CARL
2034 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2035 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2036 boost::optional<storm::storage::BitVector> const& choiceFilter);
2037
2039
2040template bool hasCycle(storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2041 boost::optional<storm::storage::BitVector> const& subsystem);
2042
2044 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2045 storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices);
2046
2047template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2048 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2049
2051 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2052 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2053
2055 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2056 storm::storage::BitVector const& statesWithProbabilityGreater0);
2057
2059 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2060
2061template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2063 storm::storage::BitVector const& psiStates);
2064
2065template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2066 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2067 storm::storage::BitVector const& psiStates);
2068
2070 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2071 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2073 boost::optional<storm::storage::BitVector> const& rowFilter);
2074
2075template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2077
2078template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2079 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2081
2082template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2083 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2085 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2086
2088 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2089 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2090
2092 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2093
2095 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2096 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2097 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2098 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2099
2101 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2102 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2103
2104template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2105 storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2106 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2107 storm::storage::BitVector const& psiStates);
2108
2109template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2111 storm::storage::BitVector const& psiStates);
2112
2114 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2115 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2116 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2117 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2118 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2119
2121 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2122 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2123
2125 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2126 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2127 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2128
2130 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2131 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2132 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2133
2134template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2135 storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2136 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2137 storm::storage::BitVector const& psiStates);
2138
2139template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2141 storm::storage::BitVector const& psiStates);
2142
2144 std::vector<uint64_t> const& player1RowGrouping,
2145 storm::storage::SparseMatrix<storm::RationalNumber> const& player1BackwardTransitions,
2146 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2147 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2148 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2149
2151 std::vector<uint64_t> const& player1RowGrouping,
2152 storm::storage::SparseMatrix<storm::RationalNumber> const& player1BackwardTransitions,
2153 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2154 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2155 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2156 boost::optional<storm::storage::BitVector> const& player1Candidates);
2157
2158template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalNumber> const& matrix,
2159 std::vector<uint64_t> const& firstStates);
2160// End of instantiations for storm::RationalNumber.
2161// Instantiations for storm::interval
2162
2164 storm::storage::BitVector const& initialStates);
2165
2167 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2168 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2169 boost::optional<storm::storage::BitVector> const& choiceFilter);
2170
2172
2173template bool hasCycle(storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, boost::optional<storm::storage::BitVector> const& subsystem);
2174
2176 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& subsystem,
2177 storm::storage::BitVector const& choices);
2178
2179template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2180 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2181
2183 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2184 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2185
2187 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2188 storm::storage::BitVector const& statesWithProbabilityGreater0);
2189
2191 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2192
2193template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::sparse::DeterministicModel<storm::Interval> const& model,
2194 storm::storage::BitVector const& phiStates,
2195 storm::storage::BitVector const& psiStates);
2196
2197template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2198 storm::storage::BitVector const& phiStates,
2199 storm::storage::BitVector const& psiStates);
2200
2202 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2203 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2204 storm::storage::Scheduler<double>& scheduler, boost::optional<storm::storage::BitVector> const& rowFilter);
2205
2206template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2208
2209template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2211
2212template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2213 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2215 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2216
2218 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2219 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2220
2222 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2223
2225 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2226 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2227 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2228 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2229
2231 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2232 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2233
2234template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2235 storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2236 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2237 storm::storage::BitVector const& psiStates);
2238
2239template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2241 storm::storage::BitVector const& psiStates);
2242
2244 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2245 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2246 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2247 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2248 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2249
2251 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2252 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2253
2255 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2256 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2257 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2258
2260 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2261 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2262 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2263
2264template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2265 storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2266 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2267 storm::storage::BitVector const& psiStates);
2268
2269template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2271 storm::storage::BitVector const& psiStates);
2272
2274 std::vector<uint64_t> const& player1RowGrouping,
2275 storm::storage::SparseMatrix<storm::Interval> const& player1BackwardTransitions,
2276 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2277 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2278 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2279
2281 std::vector<uint64_t> const& player1RowGrouping,
2282 storm::storage::SparseMatrix<storm::Interval> const& player1BackwardTransitions,
2283 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2284 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2285 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2286 boost::optional<storm::storage::BitVector> const& player1Candidates);
2287
2288template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::Interval> const& matrix, std::vector<uint64_t> const& firstStates);
2289// End storm::interval
2290
2292 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2293 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2294 boost::optional<storm::storage::BitVector> const& choiceFilter);
2295
2297
2298template bool hasCycle(storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix,
2299 boost::optional<storm::storage::BitVector> const& subsystem);
2300
2303 storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices);
2304
2305template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix,
2306 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2307
2309 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2310 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2311
2313 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2314 storm::storage::BitVector const& statesWithProbabilityGreater0);
2315
2317 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2318
2319template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2321 storm::storage::BitVector const& psiStates);
2322
2323template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2324 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2325 storm::storage::BitVector const& psiStates);
2326
2327template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates,
2330 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2332 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2333
2335 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2336 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2337
2339 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2340
2342 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2344 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2345 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2346
2349 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2350
2351template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2352 storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2353 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2354 storm::storage::BitVector const& psiStates);
2355
2356template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2358 storm::storage::BitVector const& psiStates);
2359
2361 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2363 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2364 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2365 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2366
2369 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2371 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2373 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2374
2377 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2379 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2381 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2382
2383template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2384 storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2385 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2386 storm::storage::BitVector const& psiStates);
2387
2388template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2390 storm::storage::BitVector const& psiStates);
2391
2392template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalFunction> const& matrix,
2393 std::vector<uint64_t> const& firstStates);
2394#endif
2395
2396// Instantiations for CUDD.
2397
2399 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2402 boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2403
2405 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2408 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0);
2409
2411 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2414
2415template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01(
2418
2419template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01(
2422
2427
2432
2434 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2437
2442
2444 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2447
2449 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2451 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0A);
2452
2454 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2457 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0E);
2458
2462 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbability1E);
2463
2464template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Max(
2467
2468template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Max(
2472
2473template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(
2476
2477template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(
2481
2485 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2486 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
2487
2491 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2492 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
2493 boost::optional<storm::dd::Bdd<storm::dd::DdType::CUDD>> const& player1Candidates);
2494
2495// Instantiations for Sylvan (double).
2496
2498 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2501 boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2502
2504 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2507 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2508
2510 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2513
2514template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2517
2518template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2521
2526
2531
2533 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2536
2541
2543 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2546
2548 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2550 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2551
2553 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2556 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2557
2561 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2562
2563template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2566
2567template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2571
2572template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2575
2576template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2580
2584 storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy,
2585 bool producePlayer2Strategy);
2586
2590 storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy,
2591 bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
2592
2593// Instantiations for Sylvan (rational number).
2594
2598 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2599
2601 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2604 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2605
2607 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2610
2611template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2614
2615template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2619
2624
2629
2634
2639
2644
2648 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2649
2653 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2654
2658 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2659
2660template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2663
2664template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2668
2669template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2672
2673template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2677
2681 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2682 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
2683
2687 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2688 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
2689 boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
2690
2691// Instantiations for Sylvan (rational function).
2692
2696 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2697
2699 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2702 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2703
2705 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2708
2709template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2712
2713template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2717
2722
2727
2732
2737
2742
2746 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2747
2751 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2752
2756 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2757
2758template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2761
2762template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2766
2767template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2770
2771template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2775
2776} // namespace graph
2777} // namespace utility
2778} // namespace storm
Bdd< LibraryType > notZero() const
Computes a BDD that represents the function in which all assignments with a function value unequal to...
Definition Add.cpp:431
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
Definition Bdd.cpp:178
Bdd< LibraryType > inverseRelationalProduct(Bdd< LibraryType > const &relation, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables) const
Computes the inverse relational product of the current BDD and the given BDD representing a relation.
Definition Bdd.cpp:246
bool isZero() const
Retrieves whether this DD represents the constant zero function.
Definition Bdd.cpp:547
Bdd< LibraryType > andExists(Bdd< LibraryType > const &other, std::set< storm::expressions::Variable > const &existentialVariables) const
Computes the logical and of the current and the given BDD and existentially abstracts from the given ...
Definition Bdd.cpp:196
Bdd< LibraryType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the BDD.
Definition Bdd.cpp:302
Bdd< LibraryType > existsAbstractRepresentative(std::set< storm::expressions::Variable > const &metaVariables) const
Similar to existsAbstract, but does not abstract from the variables but rather picks a valuation of e...
Definition Bdd.cpp:184
Bdd< LibraryType > universalAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Universally abstracts from the given meta variables.
Definition Bdd.cpp:190
Bdd< LibraryType > inverseRelationalProductWithExtendedRelation(Bdd< LibraryType > const &relation, std::set< storm::expressions::Variable > const &rowMetaVariables, std::set< storm::expressions::Variable > const &columnMetaVariables) const
Computes the inverse relational product of the current BDD and the given BDD representing a relation ...
Definition Bdd.cpp:273
Bdd< LibraryType > implies(Bdd< LibraryType > const &other) const
Performs a logical implication of the current and the given BDD.
Definition Bdd.cpp:162
The base class of all sparse deterministic models.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:197
storm::storage::SparseMatrix< ValueType > getBackwardTransitions() const
Retrieves the backward transition relation of the model, i.e.
Definition Model.cpp:152
The base class of sparse nondeterministic models.
std::vector< uint_fast64_t > const & getNondeterministicChoiceIndices() const
Retrieves the vector indicating which matrix rows represent non-deterministic choices of a certain st...
Base class for all deterministic symbolic models.
Base class for all symbolic models.
Definition Model.h:46
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
Definition Model.cpp:92
storm::dd::Add< Type, ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:177
std::set< storm::expressions::Variable > const & getColumnVariables() const
Retrieves the meta variables used to encode the columns of the transition matrix and the vector indic...
Definition Model.cpp:197
std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const & getRowColumnMetaVariablePairs() const
Retrieves the pairs of row and column meta variables.
Definition Model.cpp:223
std::set< storm::expressions::Variable > const & getRowVariables() const
Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.
Definition Model.cpp:192
storm::dd::Bdd< Type > const & getReachableStates() const
Retrieves the reachable states of the model.
Definition Model.cpp:102
Base class for all nondeterministic symbolic models.
virtual std::set< storm::expressions::Variable > const & getNondeterminismVariables() const override
Retrieves the meta variables used to encode the nondeterminism in the model.
storm::dd::Bdd< Type > const & getIllegalMask() const
Retrieves a BDD characterizing all illegal nondeterminism encodings in the model.
storm::dd::Bdd< Type > getIllegalSuccessorMask() const
Retrieves a BDD characterizing the illegal successors for each choice.
This class represents a discrete-time stochastic two-player game.
std::set< storm::expressions::Variable > const & getPlayer1Variables() const
Retrieeves the set of meta variables used to encode the nondeterministic choices of player 1.
std::set< storm::expressions::Variable > const & getPlayer2Variables() const
Retrieeves the set of meta variables used to encode the nondeterministic choices of player 2.
storm::dd::Bdd< Type > getIllegalPlayer1Mask() const
Retrieves a BDD characterizing all illegal player 1 choice encodings in the model.
storm::dd::Bdd< Type > getIllegalPlayer2Mask() const
Retrieves a BDD characterizing all illegal player 2 choice encodings in the model.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
void complement()
Negates all bits in the bit vector.
const_iterator end() const
Returns an iterator pointing at the element past the back of the bit vector.
uint_fast64_t getNextSetIndex(uint_fast64_t startingIndex) const
Retrieves the index of the bit that is the next bit set to true in the bit vector.
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
void resize(uint_fast64_t newLength, bool init=false)
Resizes the bit vector to hold the given new number of bits.
const_iterator begin() const
Returns an iterator to the indices of the set bits in the bit vector.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
void setChoice(uint64_t state, uint64_t choice)
This class defines which action is chosen in a particular state of a non-deterministic model.
Definition Scheduler.h:18
SchedulerChoice< ValueType > const & getChoice(uint_fast64_t modelState, uint_fast64_t memoryState=0) const
Gets the choice defined by the scheduler for the given model and memory state.
Definition Scheduler.cpp:86
void setChoice(SchedulerChoice< ValueType > const &choice, uint_fast64_t modelState, uint_fast64_t memoryState=0)
Sets the choice defined by the scheduler for the given state.
Definition Scheduler.cpp:37
uint_fast64_t getNumberOfMemoryStates() const
Retrieves the number of memory states this scheduler considers.
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.
const_iterator begin(index_type row) const
Retrieves an iterator that points to the beginning of the given row.
const_rows getRowGroup(index_type rowGroup) const
Returns an object representing the given row group.
const_iterator end(index_type row) const
Retrieves an iterator that points past the end of the given row.
index_type getRowGroupCount() const
Returns the number of row groups in the matrix.
index_type getColumnCount() const
Returns the number of columns of the matrix.
std::vector< MatrixEntry< index_type, value_type > >::const_iterator const_iterator
std::vector< index_type > const & getRowGroupIndices() const
Returns the grouping of rows of this matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
This class represents the decomposition of a graph-like structure into its strongly connected compone...
#define STORM_LOG_ERROR(message)
Definition logging.h:31
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
#define STORM_LOG_INFO_COND(cond, message)
Definition macros.h:45
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...
Definition graph.cpp:400
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Max(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:835
void topologicalSortHelper(storm::storage::SparseMatrix< T > const &matrix, uint64_t state, std::vector< uint_fast64_t > &topologicalSort, std::vector< uint_fast64_t > &recursionStack, std::vector< typename storm::storage::SparseMatrix< T >::const_iterator > &iteratorRecursionStack, storm::storage::BitVector &visitedStates)
Definition graph.cpp:1778
void computeSchedulerStayingInStates(storm::storage::BitVector const &states, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the given states that chooses an action that stays completely in the very sa...
Definition graph.cpp:490
ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix< ValueType > const &transitionMatrix, std::vector< uint64_t > const &player1Groups, storm::storage::SparseMatrix< ValueType > const &player1BackwardTransitions, std::vector< uint64_t > const &player2BackwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::OptimizationDirection const &player1Direction, storm::OptimizationDirection const &player2Direction, storm::storage::ExplicitGameStrategyPair *strategyPair)
Computes the set of states that have probability 0 given the strategies of the two players.
Definition graph.cpp:1308
std::vector< uint_fast64_t > getTopologicalSort(storm::storage::SparseMatrix< T > const &matrix, std::vector< uint64_t > const &firstStates)
Performs a topological sort of the states of the system according to the given transitions.
Definition graph.cpp:1861
void computeSchedulerProbGreater0E(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the ProbGreater0E-States such that in the induced system the given psiStates...
Definition graph.cpp:542
std::vector< uint_fast64_t > getBFSSort(storm::storage::SparseMatrix< T > const &matrix, std::vector< uint_fast64_t > const &firstStates)
Definition graph.cpp:1827
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...
Definition graph.cpp:48
storm::storage::BitVector getReachableOneStep(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::BitVector const &initialStates)
Computes the states reachable in one step from the states indicated by the bitvector.
Definition graph.cpp:36
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...
Definition graph.cpp:322
void computeSchedulerWithOneSuccessorInStates(storm::storage::BitVector const &states, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::Scheduler< SchedulerValueType > &scheduler)
Definition graph.cpp:515
storm::storage::BitVector performProbGreater0A(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under any pos...
Definition graph.cpp:857
void computeSchedulerProb1E(storm::storage::BitVector const &prob1EStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, storm::storage::Scheduler< SchedulerValueType > &scheduler, boost::optional< storm::storage::BitVector > const &rowFilter)
Computes a scheduler for the given prob1EStates such that in the induced system the given psiStates a...
Definition graph.cpp:624
bool hasCycle(storm::storage::SparseMatrix< T > const &transitionMatrix, boost::optional< storm::storage::BitVector > const &subsystem)
Returns true if the graph represented by the given matrix has a cycle.
Definition graph.cpp:143
storm::storage::BitVector performProb1A(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 1 of satisfying phi until psi under all possible re...
Definition graph.cpp:997
storm::storage::BitVector performProbGreater0E(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, bool useStepBound, uint_fast64_t maximalSteps)
Computes the sets of states that have probability greater 0 of satisfying phi until psi under at leas...
Definition graph.cpp:689
storm::storage::BitVector performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:749
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...
Definition graph.cpp:383
bool checkIfECWithChoiceExists(storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &subsystem, storm::storage::BitVector const &choices)
Checks whether there is an End Component that.
Definition graph.cpp:182
storm::storage::BitVector performProb0E(storm::models::sparse::NondeterministicModel< T, RM > const &model, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Computes the sets of states that have probability 0 of satisfying phi until psi under at least one po...
Definition graph.cpp:976
storm::storage::BitVector getBsccCover(storm::storage::SparseMatrix< T > const &transitionMatrix)
Retrieves a set of states that covers als BSCCs of the system in the sense that for every BSCC exactl...
Definition graph.cpp:129
void computeSchedulerProb0E(storm::storage::BitVector const &prob0EStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::Scheduler< SchedulerValueType > &scheduler)
Computes a scheduler for the given states that have a scheduler that has a probability 0.
Definition graph.cpp:593
std::pair< storm::storage::BitVector, storm::storage::BitVector > performProb01Min(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:1079
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...
Definition graph.cpp:288
storm::storage::BitVector performProb1E(storm::storage::SparseMatrix< T > const &transitionMatrix, std::vector< uint_fast64_t > const &nondeterministicChoiceIndices, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates, boost::optional< storm::storage::BitVector > const &choiceConstraint)
Computes the sets of states that have probability 1 of satisfying phi until psi under at least one po...
Definition graph.cpp:757
void computeSchedulerRewInf(storm::storage::BitVector const &rewInfStates, storm::storage::SparseMatrix< T > const &transitionMatrix, storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::Scheduler< SchedulerValueType > &scheduler)
Computes a scheduler for the given states that have a scheduler that has a reward infinity.
Definition graph.cpp:599
bool isZero(ValueType const &a)
Definition constants.cpp:41
LabParser.cpp.
Definition cli.cpp:18
storm::storage::BitVector player2States
Definition graph.h:769
storm::storage::BitVector player1States
Definition graph.h:768