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 // or, equivalently, the states satisfying Pmin=0 [ F !"rewInfStates"].
603 auto trapStates = performProb0E(transitionMatrix, transitionMatrix.getRowGroupIndices(), backwardTransitions, rewInfStates, ~rewInfStates);
604 // Also set a corresponding choice for all those states
605 computeSchedulerProb0E(trapStates, transitionMatrix, scheduler);
606
607 // All remaining rewInfStates must reach a trapState with positive probability
608 auto remainingStates = rewInfStates & ~trapStates;
609 if (!remainingStates.empty()) {
610 computeSchedulerProbGreater0E(transitionMatrix, backwardTransitions, remainingStates, trapStates, scheduler);
611 }
612}
613
614template<typename T, typename SchedulerValueType>
616 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
618 boost::optional<storm::storage::BitVector> const& rowFilter) {
619 // set an arbitrary (valid) choice for the psi states.
620 for (auto psiState : psiStates) {
621 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
622 if (!scheduler.getChoice(psiState, memState).isDefined()) {
623 scheduler.setChoice(0, psiState, memState);
624 }
625 }
626 }
627
628 // Now perform a backwards search from the psi states and store choices with prob. 1
629 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices = transitionMatrix.getRowGroupIndices();
630 std::vector<uint_fast64_t> stack;
631 storm::storage::BitVector currentStates(psiStates);
632 stack.insert(stack.end(), currentStates.begin(), currentStates.end());
633 uint_fast64_t currentState = 0;
634
635 while (!stack.empty()) {
636 currentState = stack.back();
637 stack.pop_back();
638
639 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
640 predecessorEntryIte = backwardTransitions.end(currentState);
641 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
642 if (phiStates.get(predecessorEntryIt->getColumn()) && !currentStates.get(predecessorEntryIt->getColumn())) {
643 // Check whether the predecessor has only successors in the prob1E state set for one of the
644 // nondeterminstic choices.
645 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
646 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
647 if (!rowFilter || rowFilter.get().get(row)) {
648 bool allSuccessorsInProb1EStates = true;
649 bool hasSuccessorInCurrentStates = false;
650 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
651 successorEntryIte = transitionMatrix.end(row);
652 successorEntryIt != successorEntryIte; ++successorEntryIt) {
653 if (!prob1EStates.get(successorEntryIt->getColumn())) {
654 allSuccessorsInProb1EStates = false;
655 break;
656 } else if (currentStates.get(successorEntryIt->getColumn())) {
657 hasSuccessorInCurrentStates = true;
658 }
659 }
660
661 // If all successors for a given nondeterministic choice are in the prob1E state set, we
662 // perform a backward search from that state.
663 if (allSuccessorsInProb1EStates && hasSuccessorInCurrentStates) {
664 for (uint_fast64_t memState = 0; memState < scheduler.getNumberOfMemoryStates(); ++memState) {
665 scheduler.setChoice(row - nondeterministicChoiceIndices[predecessorEntryIt->getColumn()], predecessorEntryIt->getColumn(),
666 memState);
667 }
668 currentStates.set(predecessorEntryIt->getColumn(), true);
669 stack.push_back(predecessorEntryIt->getColumn());
670 break;
671 }
672 }
673 }
674 }
675 }
676 }
677}
678
679template<typename T>
681 storm::storage::BitVector const& psiStates, bool useStepBound, uint_fast64_t maximalSteps) {
682 size_t numberOfStates = phiStates.size();
683
684 // Prepare resulting bit vector.
685 storm::storage::BitVector statesWithProbabilityGreater0(numberOfStates);
686
687 // Add all psi states as the already satisfy the condition.
688 statesWithProbabilityGreater0 |= psiStates;
689
690 // Initialize the stack used for the DFS with the states
691 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
692
693 // Initialize the stack for the step bound, if the number of steps is bounded.
694 std::vector<uint_fast64_t> stepStack;
695 std::vector<uint_fast64_t> remainingSteps;
696 if (useStepBound) {
697 stepStack.reserve(numberOfStates);
698 stepStack.insert(stepStack.begin(), psiStates.getNumberOfSetBits(), maximalSteps);
699 remainingSteps.resize(numberOfStates);
700 for (auto state : psiStates) {
701 remainingSteps[state] = maximalSteps;
702 }
703 }
704
705 // Perform the actual DFS.
706 uint_fast64_t currentState, currentStepBound;
707 while (!stack.empty()) {
708 currentState = stack.back();
709 stack.pop_back();
710
711 if (useStepBound) {
712 currentStepBound = stepStack.back();
713 stepStack.pop_back();
714 if (currentStepBound == 0) {
715 continue;
716 }
717 }
718
719 for (typename storm::storage::SparseMatrix<T>::const_iterator entryIt = backwardTransitions.begin(currentState),
720 entryIte = backwardTransitions.end(currentState);
721 entryIt != entryIte; ++entryIt) {
722 if (phiStates.get(entryIt->getColumn()) &&
723 (!statesWithProbabilityGreater0.get(entryIt->getColumn()) || (useStepBound && remainingSteps[entryIt->getColumn()] < currentStepBound - 1))) {
724 // If we don't have a bound on the number of steps to take, just add the state to the stack.
725 if (useStepBound) {
726 // If there is at least one more step to go, we need to push the state and the new number of steps.
727 remainingSteps[entryIt->getColumn()] = currentStepBound - 1;
728 stepStack.push_back(currentStepBound - 1);
729 }
730 statesWithProbabilityGreater0.set(entryIt->getColumn(), true);
731 stack.push_back(entryIt->getColumn());
732 }
733 }
734 }
735
736 return statesWithProbabilityGreater0;
737}
738
739template<typename T>
741 storm::storage::BitVector const& psiStates) {
742 storm::storage::BitVector statesWithProbability0 = performProbGreater0E(backwardTransitions, phiStates, psiStates);
743 statesWithProbability0.complement();
744 return statesWithProbability0;
745}
746
747template<typename T>
749 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
750 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
751 storm::storage::BitVector const& psiStates, boost::optional<storm::storage::BitVector> const& choiceConstraint) {
752 size_t numberOfStates = phiStates.size();
753
754 // Initialize the environment for the iterative algorithm.
755 storm::storage::BitVector currentStates(numberOfStates, true);
756 std::vector<uint_fast64_t> stack;
757 stack.reserve(numberOfStates);
758
759 // Perform the loop as long as the set of states gets larger.
760 bool done = false;
761 uint_fast64_t currentState;
762 while (!done) {
763 stack.clear();
764 storm::storage::BitVector nextStates(psiStates);
765 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
766
767 while (!stack.empty()) {
768 currentState = stack.back();
769 stack.pop_back();
770
771 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
772 predecessorEntryIte = backwardTransitions.end(currentState);
773 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
774 if (phiStates.get(predecessorEntryIt->getColumn()) && !nextStates.get(predecessorEntryIt->getColumn())) {
775 // Check whether the predecessor has only successors in the current state set for one of the
776 // nondeterminstic choices.
777 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
778 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
779 if (!choiceConstraint || choiceConstraint.get().get(row)) {
780 bool allSuccessorsInCurrentStates = true;
781 bool hasNextStateSuccessor = false;
782 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
783 successorEntryIte = transitionMatrix.end(row);
784 successorEntryIt != successorEntryIte; ++successorEntryIt) {
785 if (!currentStates.get(successorEntryIt->getColumn())) {
786 allSuccessorsInCurrentStates = false;
787 break;
788 } else if (nextStates.get(successorEntryIt->getColumn())) {
789 hasNextStateSuccessor = true;
790 }
791 }
792
793 // If all successors for a given nondeterministic choice are in the current state set, we
794 // add it to the set of states for the next iteration and perform a backward search from
795 // that state.
796 if (allSuccessorsInCurrentStates && hasNextStateSuccessor) {
797 nextStates.set(predecessorEntryIt->getColumn(), true);
798 stack.push_back(predecessorEntryIt->getColumn());
799 break;
800 }
801 }
802 }
803 }
804 }
805 }
806
807 // Check whether we need to perform an additional iteration.
808 if (currentStates == nextStates) {
809 done = true;
810 } else {
811 currentStates = std::move(nextStates);
812 }
813 }
814
815 return currentStates;
816}
817
818template<typename T, typename RM>
820 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
821 storm::storage::BitVector const& psiStates) {
822 return performProb1E(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
823}
824
825template<typename T>
826std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::storage::SparseMatrix<T> const& transitionMatrix,
827 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
828 storm::storage::SparseMatrix<T> const& backwardTransitions,
829 storm::storage::BitVector const& phiStates,
830 storm::storage::BitVector const& psiStates) {
831 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
832
833 result.first = performProb0A(backwardTransitions, phiStates, psiStates);
834
835 result.second = performProb1E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
836 return result;
837}
838
839template<typename T, typename RM>
840std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::models::sparse::NondeterministicModel<T, RM> const& model,
841 storm::storage::BitVector const& phiStates,
842 storm::storage::BitVector const& psiStates) {
843 return performProb01Max(model.getTransitionMatrix(), model.getTransitionMatrix().getRowGroupIndices(), model.getBackwardTransitions(), phiStates,
844 psiStates);
845}
846
847template<typename T>
849 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
850 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
851 storm::storage::BitVector const& psiStates, bool useStepBound, uint_fast64_t maximalSteps,
852 boost::optional<storm::storage::BitVector> const& choiceConstraint) {
853 size_t numberOfStates = phiStates.size();
854
855 // Prepare resulting bit vector.
856 storm::storage::BitVector statesWithProbabilityGreater0(numberOfStates);
857
858 // Add all psi states as the already satisfy the condition.
859 statesWithProbabilityGreater0 |= psiStates;
860
861 // Initialize the stack used for the DFS with the states
862 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
863
864 // Initialize the stack for the step bound, if the number of steps is bounded.
865 std::vector<uint_fast64_t> stepStack;
866 std::vector<uint_fast64_t> remainingSteps;
867 if (useStepBound) {
868 stepStack.reserve(numberOfStates);
869 stepStack.insert(stepStack.begin(), psiStates.getNumberOfSetBits(), maximalSteps);
870 remainingSteps.resize(numberOfStates);
871 for (auto state : psiStates) {
872 remainingSteps[state] = maximalSteps;
873 }
874 }
875
876 // Perform the actual DFS.
877 uint_fast64_t currentState, currentStepBound;
878 while (!stack.empty()) {
879 currentState = stack.back();
880 stack.pop_back();
881
882 if (useStepBound) {
883 currentStepBound = stepStack.back();
884 stepStack.pop_back();
885 if (currentStepBound == 0) {
886 continue;
887 }
888 }
889
890 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
891 predecessorEntryIte = backwardTransitions.end(currentState);
892 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
893 if (phiStates.get(predecessorEntryIt->getColumn())) {
894 if (!statesWithProbabilityGreater0.get(predecessorEntryIt->getColumn())) {
895 // Check whether the predecessor has at least one successor in the current state set for every
896 // nondeterministic choice within the possibly given choiceConstraint.
897
898 // Note: The backwards edge might be induced by a choice that violates the choiceConstraint.
899 // However this is not problematic as long as there is at least one enabled choice for the predecessor.
900 uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
901 uint_fast64_t const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
902 if (!choiceConstraint || choiceConstraint->getNextSetIndex(row) < endOfGroup) {
903 bool addToStatesWithProbabilityGreater0 = true;
904 for (; row < endOfGroup; ++row) {
905 if (!choiceConstraint || choiceConstraint->get(row)) {
906 bool hasAtLeastOneSuccessorWithProbabilityGreater0 = false;
907 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
908 successorEntryIte = transitionMatrix.end(row);
909 successorEntryIt != successorEntryIte; ++successorEntryIt) {
910 if (statesWithProbabilityGreater0.get(successorEntryIt->getColumn())) {
911 hasAtLeastOneSuccessorWithProbabilityGreater0 = true;
912 break;
913 }
914 }
915
916 if (!hasAtLeastOneSuccessorWithProbabilityGreater0) {
917 addToStatesWithProbabilityGreater0 = false;
918 break;
919 }
920 }
921 }
922
923 // If we need to add the state, then actually add it and perform further search from the state.
924 if (addToStatesWithProbabilityGreater0) {
925 // If we don't have a bound on the number of steps to take, just add the state to the stack.
926 if (useStepBound) {
927 // If there is at least one more step to go, we need to push the state and the new number of steps.
928 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
929 stepStack.push_back(currentStepBound - 1);
930 }
931 statesWithProbabilityGreater0.set(predecessorEntryIt->getColumn(), true);
932 stack.push_back(predecessorEntryIt->getColumn());
933 }
934 }
935
936 } else if (useStepBound && remainingSteps[predecessorEntryIt->getColumn()] < currentStepBound - 1) {
937 // We have found a shorter path to the predecessor. Hence, we need to explore it again.
938 // If there is a choiceConstraint, we still need to check whether the backwards edge was induced by a valid action
939 bool predecessorIsValid = true;
940 if (choiceConstraint) {
941 predecessorIsValid = false;
942 uint_fast64_t row = choiceConstraint->getNextSetIndex(nondeterministicChoiceIndices[predecessorEntryIt->getColumn()]);
943 uint_fast64_t const& endOfGroup = nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1];
944 for (; row < endOfGroup && !predecessorIsValid; row = choiceConstraint->getNextSetIndex(row + 1)) {
945 for (auto const& entry : transitionMatrix.getRow(row)) {
946 if (entry.getColumn() == currentState) {
947 predecessorIsValid = true;
948 break;
949 }
950 }
951 }
952 }
953 if (predecessorIsValid) {
954 remainingSteps[predecessorEntryIt->getColumn()] = currentStepBound - 1;
955 stepStack.push_back(currentStepBound - 1);
956 stack.push_back(predecessorEntryIt->getColumn());
957 }
958 }
959 }
960 }
961 }
962
963 return statesWithProbabilityGreater0;
964}
965
966template<typename T, typename RM>
968 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
969 storm::storage::BitVector const& psiStates) {
970 storm::storage::BitVector statesWithProbability0 =
971 performProbGreater0A(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
972 statesWithProbability0.complement();
973 return statesWithProbability0;
974}
975
976template<typename T>
978 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
979 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
980 storm::storage::BitVector const& psiStates) {
981 storm::storage::BitVector statesWithProbability0 =
982 performProbGreater0A(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
983 statesWithProbability0.complement();
984 return statesWithProbability0;
985}
986
987template<typename T, typename RM>
989 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
990 storm::storage::BitVector const& psiStates) {
991 return performProb1A(model.getTransitionMatrix(), model.getNondeterministicChoiceIndices(), backwardTransitions, phiStates, psiStates);
992}
993
994template<typename T>
996 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
997 storm::storage::SparseMatrix<T> const& backwardTransitions, storm::storage::BitVector const& phiStates,
998 storm::storage::BitVector const& psiStates) {
999 size_t numberOfStates = phiStates.size();
1000
1001 // Initialize the environment for the iterative algorithm.
1002 storm::storage::BitVector currentStates(numberOfStates, true);
1003 std::vector<uint_fast64_t> stack;
1004 stack.reserve(numberOfStates);
1005
1006 // Perform the loop as long as the set of states gets smaller.
1007 bool done = false;
1008 uint_fast64_t currentState;
1009 while (!done) {
1010 stack.clear();
1011 storm::storage::BitVector nextStates(psiStates);
1012 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
1013
1014 while (!stack.empty()) {
1015 currentState = stack.back();
1016 stack.pop_back();
1017
1018 for (typename storm::storage::SparseMatrix<T>::const_iterator predecessorEntryIt = backwardTransitions.begin(currentState),
1019 predecessorEntryIte = backwardTransitions.end(currentState);
1020 predecessorEntryIt != predecessorEntryIte; ++predecessorEntryIt) {
1021 if (phiStates.get(predecessorEntryIt->getColumn()) && !nextStates.get(predecessorEntryIt->getColumn())) {
1022 // Check whether the predecessor has only successors in the current state set for all of the
1023 // nondeterminstic choices and that for each choice there exists a successor that is already
1024 // in the next states.
1025 bool addToStatesWithProbability1 = true;
1026 for (uint_fast64_t row = nondeterministicChoiceIndices[predecessorEntryIt->getColumn()];
1027 row < nondeterministicChoiceIndices[predecessorEntryIt->getColumn() + 1]; ++row) {
1028 bool hasAtLeastOneSuccessorWithProbability1 = false;
1029 for (typename storm::storage::SparseMatrix<T>::const_iterator successorEntryIt = transitionMatrix.begin(row),
1030 successorEntryIte = transitionMatrix.end(row);
1031 successorEntryIt != successorEntryIte; ++successorEntryIt) {
1032 if (!currentStates.get(successorEntryIt->getColumn())) {
1033 addToStatesWithProbability1 = false;
1034 goto afterCheckLoop;
1035 }
1036 if (nextStates.get(successorEntryIt->getColumn())) {
1037 hasAtLeastOneSuccessorWithProbability1 = true;
1038 }
1039 }
1040
1041 if (!hasAtLeastOneSuccessorWithProbability1) {
1042 addToStatesWithProbability1 = false;
1043 break;
1044 }
1045 }
1046
1047 afterCheckLoop:
1048 // If all successors for all nondeterministic choices are in the current state set, we
1049 // add it to the set of states for the next iteration and perform a backward search from
1050 // that state.
1051 if (addToStatesWithProbability1) {
1052 nextStates.set(predecessorEntryIt->getColumn(), true);
1053 stack.push_back(predecessorEntryIt->getColumn());
1054 }
1055 }
1056 }
1057 }
1058
1059 // Check whether we need to perform an additional iteration.
1060 if (currentStates == nextStates) {
1061 done = true;
1062 } else {
1063 currentStates = std::move(nextStates);
1064 }
1065 }
1066 return currentStates;
1067}
1068
1069template<typename T>
1070std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::storage::SparseMatrix<T> const& transitionMatrix,
1071 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1072 storm::storage::SparseMatrix<T> const& backwardTransitions,
1073 storm::storage::BitVector const& phiStates,
1074 storm::storage::BitVector const& psiStates) {
1075 std::pair<storm::storage::BitVector, storm::storage::BitVector> result;
1076 result.first = performProb0E(transitionMatrix, nondeterministicChoiceIndices, backwardTransitions, phiStates, psiStates);
1077 // Instead of calling performProb1A, we call the (more easier) performProb0A on the Prob0E states.
1078 // This is valid because, when minimizing probabilities, states that have prob1 cannot reach a state with prob 0 (and will eventually reach a psiState).
1079 // States that do not have prob1 will eventually reach a state with prob0.
1080 result.second = performProb0A(backwardTransitions, ~psiStates, result.first);
1081 return result;
1082}
1083
1084template<typename T, typename RM>
1085std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::models::sparse::NondeterministicModel<T, RM> const& model,
1086 storm::storage::BitVector const& phiStates,
1087 storm::storage::BitVector const& psiStates) {
1088 return performProb01Min(model.getTransitionMatrix(), model.getTransitionMatrix().getRowGroupIndices(), model.getBackwardTransitions(), phiStates,
1089 psiStates);
1090}
1091
1092template<storm::dd::DdType Type, typename ValueType>
1094 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1095 storm::dd::Bdd<Type> const& psiStates) {
1096 // Initialize environment for backward search.
1097 storm::dd::DdManager<Type> const& manager = model.getManager();
1098 storm::dd::Bdd<Type> statesWithProbabilityGreater0E = manager.getBddZero();
1099 storm::dd::Bdd<Type> frontier = psiStates;
1100 storm::dd::Bdd<Type> scheduler = manager.getBddZero();
1101
1102 while (!frontier.isZero()) {
1103 storm::dd::Bdd<Type> statesAndChoicesWithProbabilityGreater0E =
1104 frontier.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1105 frontier = phiStates && statesAndChoicesWithProbabilityGreater0E.existsAbstract(model.getNondeterminismVariables()) && !statesWithProbabilityGreater0E;
1106 scheduler = scheduler || (frontier && statesAndChoicesWithProbabilityGreater0E).existsAbstractRepresentative(model.getNondeterminismVariables());
1107 statesWithProbabilityGreater0E |= frontier;
1108 }
1109
1110 return scheduler;
1111}
1112
1113template<storm::dd::DdType Type, typename ValueType>
1115 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1116 storm::dd::Bdd<Type> const& psiStates) {
1117 // Initialize environment for backward search.
1118 storm::dd::DdManager<Type> const& manager = model.getManager();
1119 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1120 storm::dd::Bdd<Type> statesWithProbabilityGreater0E = psiStates;
1121
1122 storm::dd::Bdd<Type> abstractedTransitionMatrix = transitionMatrix.existsAbstract(model.getNondeterminismVariables());
1123 while (lastIterationStates != statesWithProbabilityGreater0E) {
1124 lastIterationStates = statesWithProbabilityGreater0E;
1125 statesWithProbabilityGreater0E =
1126 statesWithProbabilityGreater0E.inverseRelationalProduct(abstractedTransitionMatrix, model.getRowVariables(), model.getColumnVariables());
1127 statesWithProbabilityGreater0E &= phiStates;
1128 statesWithProbabilityGreater0E |= lastIterationStates;
1129 }
1130
1131 return statesWithProbabilityGreater0E;
1132}
1133
1134template<storm::dd::DdType Type, typename ValueType>
1136 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1137 return !performProbGreater0E(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
1138}
1139
1140template<storm::dd::DdType Type, typename ValueType>
1142 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1143 storm::dd::Bdd<Type> const& psiStates) {
1144 // Initialize environment for backward search.
1145 storm::dd::DdManager<Type> const& manager = model.getManager();
1146 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1147 storm::dd::Bdd<Type> statesWithProbabilityGreater0A = psiStates;
1148
1149 while (lastIterationStates != statesWithProbabilityGreater0A) {
1150 lastIterationStates = statesWithProbabilityGreater0A;
1151 statesWithProbabilityGreater0A =
1152 statesWithProbabilityGreater0A.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1153 statesWithProbabilityGreater0A |= model.getIllegalMask();
1154 statesWithProbabilityGreater0A = statesWithProbabilityGreater0A.universalAbstract(model.getNondeterminismVariables());
1155 statesWithProbabilityGreater0A &= phiStates;
1156 statesWithProbabilityGreater0A |= psiStates;
1157 }
1158
1159 return statesWithProbabilityGreater0A;
1160}
1161
1162template<storm::dd::DdType Type, typename ValueType>
1164 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1165 return !performProbGreater0A(model, transitionMatrix, phiStates, psiStates) && model.getReachableStates();
1166}
1167
1168template<storm::dd::DdType Type, typename ValueType>
1170 storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbabilityGreater0A) {
1171 // Initialize environment for backward search.
1172 storm::dd::DdManager<Type> const& manager = model.getManager();
1173 storm::dd::Bdd<Type> lastIterationStates = manager.getBddZero();
1174 storm::dd::Bdd<Type> statesWithProbability1A = psiStates || statesWithProbabilityGreater0A;
1175
1176 while (lastIterationStates != statesWithProbability1A) {
1177 lastIterationStates = statesWithProbability1A;
1178 statesWithProbability1A = statesWithProbability1A.swapVariables(model.getRowColumnMetaVariablePairs());
1179 statesWithProbability1A = transitionMatrix.implies(statesWithProbability1A).universalAbstract(model.getColumnVariables());
1180 statesWithProbability1A |= model.getIllegalMask();
1181 statesWithProbability1A = statesWithProbability1A.universalAbstract(model.getNondeterminismVariables());
1182 statesWithProbability1A &= statesWithProbabilityGreater0A;
1183 statesWithProbability1A |= psiStates;
1184 }
1185
1186 return statesWithProbability1A;
1187}
1188
1189template<storm::dd::DdType Type, typename ValueType>
1191 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates,
1192 storm::dd::Bdd<Type> const& statesWithProbabilityGreater0E) {
1193 // Initialize environment for backward search.
1194 storm::dd::DdManager<Type> const& manager = model.getManager();
1195 storm::dd::Bdd<Type> statesWithProbability1E = statesWithProbabilityGreater0E;
1196
1197 bool outerLoopDone = false;
1198 while (!outerLoopDone) {
1199 storm::dd::Bdd<Type> innerStates = manager.getBddZero();
1200
1201 bool innerLoopDone = false;
1202 while (!innerLoopDone) {
1203 storm::dd::Bdd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
1204 temporary = transitionMatrix.implies(temporary).universalAbstract(model.getColumnVariables());
1205
1206 storm::dd::Bdd<Type> temporary2 =
1207 innerStates.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1208
1209 temporary = temporary.andExists(temporary2, model.getNondeterminismVariables());
1210 temporary &= phiStates;
1211 temporary |= psiStates;
1212
1213 if (innerStates == temporary) {
1214 innerLoopDone = true;
1215 } else {
1216 innerStates = temporary;
1217 }
1218 }
1219
1220 if (statesWithProbability1E == innerStates) {
1221 outerLoopDone = true;
1222 } else {
1223 statesWithProbability1E = innerStates;
1224 }
1225 }
1226
1227 return statesWithProbability1E;
1228}
1229
1230template<storm::dd::DdType Type, typename ValueType>
1232 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1233 storm::dd::Bdd<Type> const& psiStates, storm::dd::Bdd<Type> const& statesWithProbability1E) {
1234 // Initialize environment for backward search.
1235 storm::dd::DdManager<Type> const& manager = model.getManager();
1236 storm::dd::Bdd<Type> scheduler = manager.getBddZero();
1237
1238 storm::dd::Bdd<Type> innerStates = manager.getBddZero();
1239
1240 bool innerLoopDone = false;
1241 while (!innerLoopDone) {
1242 storm::dd::Bdd<Type> temporary = statesWithProbability1E.swapVariables(model.getRowColumnMetaVariablePairs());
1243 temporary = transitionMatrix.implies(temporary).universalAbstract(model.getColumnVariables());
1244
1245 storm::dd::Bdd<Type> temporary2 =
1246 innerStates.inverseRelationalProductWithExtendedRelation(transitionMatrix, model.getRowVariables(), model.getColumnVariables());
1247 temporary &= temporary2;
1248 temporary &= phiStates;
1249
1250 // Extend the scheduler for those states that have not been seen as inner states before.
1251 scheduler |= (temporary && !innerStates).existsAbstractRepresentative(model.getNondeterminismVariables());
1252
1253 temporary = temporary.existsAbstract(model.getNondeterminismVariables());
1254 temporary |= psiStates;
1255
1256 if (innerStates == temporary) {
1257 innerLoopDone = true;
1258 } else {
1259 innerStates = temporary;
1260 }
1261 }
1262
1263 return scheduler;
1264}
1265
1266template<storm::dd::DdType Type, typename ValueType>
1268 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1269 return performProb01Max(model, model.getTransitionMatrix().notZero(), phiStates, psiStates);
1270}
1271
1272template<storm::dd::DdType Type, typename ValueType>
1274 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1275 storm::dd::Bdd<Type> const& psiStates) {
1276 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
1277 result.first = performProb0A(model, transitionMatrix, phiStates, psiStates);
1278 result.second = performProb1E(model, transitionMatrix, phiStates, psiStates, !result.first && model.getReachableStates());
1279 return result;
1280}
1281
1282template<storm::dd::DdType Type, typename ValueType>
1284 storm::dd::Bdd<Type> const& phiStates, storm::dd::Bdd<Type> const& psiStates) {
1285 return performProb01Min(model, model.getTransitionMatrix().notZero(), phiStates, psiStates);
1286}
1287
1288template<storm::dd::DdType Type, typename ValueType>
1290 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1291 storm::dd::Bdd<Type> const& psiStates) {
1292 std::pair<storm::dd::Bdd<Type>, storm::dd::Bdd<Type>> result;
1293 result.first = performProb0E(model, transitionMatrix, phiStates, psiStates);
1294 result.second = performProb1A(model, transitionMatrix, psiStates, !result.first && model.getReachableStates());
1295 return result;
1296}
1297
1298template<typename ValueType>
1299ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<uint64_t> const& player1Groups,
1300 storm::storage::SparseMatrix<ValueType> const& player1BackwardTransitions,
1301 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
1302 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
1303 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair) {
1304 ExplicitGameProb01Result result(psiStates, storm::storage::BitVector(transitionMatrix.getRowGroupCount()));
1305
1306 // Initialize the stack used for the DFS with the states
1307 std::vector<uint_fast64_t> stack(psiStates.begin(), psiStates.end());
1308
1309 // Perform the actual DFS.
1310 uint_fast64_t currentState;
1311 while (!stack.empty()) {
1312 currentState = stack.back();
1313 stack.pop_back();
1314
1315 // Check which player 2 predecessors of the current player 1 state to add.
1316 for (auto const& player2PredecessorEntry : player1BackwardTransitions.getRow(currentState)) {
1317 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1318 if (!result.player2States.get(player2Predecessor)) {
1319 bool addPlayer2State = false;
1320 if (player2Direction == OptimizationDirection::Minimize) {
1321 bool allChoicesHavePlayer1State = true;
1322 for (uint64_t row = transitionMatrix.getRowGroupIndices()[player2Predecessor];
1323 row < transitionMatrix.getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1324 bool choiceHasPlayer1State = false;
1325 for (auto const& entry : transitionMatrix.getRow(row)) {
1326 if (result.player1States.get(entry.getColumn())) {
1327 choiceHasPlayer1State = true;
1328 break;
1329 }
1330 }
1331 if (!choiceHasPlayer1State) {
1332 allChoicesHavePlayer1State = false;
1333 }
1334 }
1335 if (allChoicesHavePlayer1State) {
1336 addPlayer2State = true;
1337 }
1338 } else {
1339 addPlayer2State = true;
1340 }
1341
1342 if (addPlayer2State) {
1343 result.player2States.set(player2Predecessor);
1344
1345 // Now check whether adding the player 2 state changes something with respect to the
1346 // (single) player 1 predecessor.
1347 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1348
1349 if (!result.player1States.get(player1Predecessor)) {
1350 bool addPlayer1State = false;
1351 if (player1Direction == OptimizationDirection::Minimize) {
1352 bool allPlayer2Successors = true;
1353 for (uint64_t player2State = player1Groups[player1Predecessor]; player2State < player1Groups[player1Predecessor + 1];
1354 ++player2State) {
1355 if (!result.player2States.get(player2State)) {
1356 allPlayer2Successors = false;
1357 break;
1358 }
1359 }
1360 if (allPlayer2Successors) {
1361 addPlayer1State = true;
1362 }
1363 } else {
1364 addPlayer1State = true;
1365 }
1366
1367 if (addPlayer1State) {
1368 result.player1States.set(player1Predecessor);
1369 stack.emplace_back(player1Predecessor);
1370 }
1371 }
1372 }
1373 }
1374 }
1375 }
1376
1377 // Since we have determined the complements of the desired sets, we need to complement it now.
1378 result.player1States.complement();
1379 result.player2States.complement();
1380
1381 // Generate player 1 strategy if required.
1382 if (strategyPair) {
1383 for (auto player1State : result.player1States) {
1384 if (player1Direction == storm::OptimizationDirection::Minimize) {
1385 // At least one player 2 successor is a state with probability 0, find it.
1386 [[maybe_unused]] bool foundProb0Successor = false;
1387 uint64_t player2State;
1388 for (player2State = player1Groups[player1State]; player2State < player1Groups[player1State + 1]; ++player2State) {
1389 if (result.player2States.get(player2State)) {
1390 foundProb0Successor = true;
1391 break;
1392 }
1393 }
1394 STORM_LOG_ASSERT(foundProb0Successor, "Expected at least one state 2 successor with probability 0.");
1395 strategyPair->getPlayer1Strategy().setChoice(player1State, player2State);
1396 } else {
1397 // Since all player 2 successors are states with probability 0, just pick any.
1398 strategyPair->getPlayer1Strategy().setChoice(player1State, player1Groups[player1State]);
1399 }
1400 }
1401 }
1402
1403 // Generate player 2 strategy if required.
1404 if (strategyPair) {
1405 for (auto player2State : result.player2States) {
1406 if (player2Direction == storm::OptimizationDirection::Minimize) {
1407 // At least one distribution only has successors with probability 0, find it.
1408 [[maybe_unused]] bool foundProb0SuccessorDistribution = false;
1409
1410 uint64_t row;
1411 for (row = transitionMatrix.getRowGroupIndices()[player2State]; row < transitionMatrix.getRowGroupIndices()[player2State + 1]; ++row) {
1412 bool distributionHasOnlyProb0Successors = true;
1413 for (auto const& player1SuccessorEntry : transitionMatrix.getRow(row)) {
1414 if (!result.player1States.get(player1SuccessorEntry.getColumn())) {
1415 distributionHasOnlyProb0Successors = false;
1416 break;
1417 }
1418 }
1419 if (distributionHasOnlyProb0Successors) {
1420 foundProb0SuccessorDistribution = true;
1421 break;
1422 }
1423 }
1424
1425 STORM_LOG_ASSERT(foundProb0SuccessorDistribution, "Expected at least one distribution with only successors with probability 0.");
1426 strategyPair->getPlayer2Strategy().setChoice(player2State, row);
1427 } else {
1428 // Since all player 1 successors are states with probability 0, just pick any.
1429 strategyPair->getPlayer2Strategy().setChoice(player2State, transitionMatrix.getRowGroupIndices()[player2State]);
1430 }
1431 }
1432 }
1433
1434 return result;
1435}
1436
1437template<storm::dd::DdType Type, typename ValueType>
1439 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1440 storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy,
1441 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy) {
1442 // The solution sets.
1443 storm::dd::Bdd<Type> player1States = psiStates;
1444 storm::dd::Bdd<Type> player2States = model.getManager().getBddZero();
1445
1446 bool done = false;
1447 while (!done) {
1449 (transitionMatrix && player1States.swapVariables(model.getRowColumnMetaVariablePairs())).existsAbstract(model.getColumnVariables()) && phiStates;
1450
1451 if (player2Strategy == OptimizationDirection::Minimize) {
1452 tmp = (tmp || model.getIllegalPlayer2Mask()).universalAbstract(model.getPlayer2Variables());
1453 } else {
1454 tmp = tmp.existsAbstract(model.getPlayer2Variables());
1455 }
1456 player2States |= tmp;
1457
1458 if (player1Strategy == OptimizationDirection::Minimize) {
1459 tmp = (tmp || model.getIllegalPlayer1Mask()).universalAbstract(model.getPlayer1Variables());
1460 } else {
1461 tmp = tmp.existsAbstract(model.getPlayer1Variables());
1462 }
1463
1464 // Re-add all previous player 1 states.
1465 tmp |= player1States;
1466
1467 if (tmp == player1States) {
1468 done = true;
1469 }
1470
1471 player1States = tmp;
1472 }
1473
1474 // Since we have determined the complements of the desired sets, we need to complement it now.
1475 player1States = !player1States && model.getReachableStates();
1476
1477 std::set<storm::expressions::Variable> variablesToAbstract(model.getColumnVariables());
1478 variablesToAbstract.insert(model.getPlayer2Variables().begin(), model.getPlayer2Variables().end());
1479 player2States = !player2States && transitionMatrix.existsAbstract(variablesToAbstract);
1480
1481 // Determine all transitions between prob0 states.
1482 storm::dd::Bdd<Type> transitionsBetweenProb0States =
1483 player2States && (transitionMatrix && player1States.swapVariables(model.getRowColumnMetaVariablePairs()));
1484
1485 // Determine the distributions that have only successors that are prob0 states.
1486 storm::dd::Bdd<Type> onlyProb0Successors = (transitionsBetweenProb0States || model.getIllegalSuccessorMask()).universalAbstract(model.getColumnVariables());
1487
1488 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1489 if (producePlayer2Strategy) {
1490 // Pick a distribution that has only prob0 successors.
1491 player2StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer2Variables());
1492 }
1493
1494 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1495 if (producePlayer1Strategy) {
1496 // Move from player 2 choices with only prob0 successors to player 1 choices with only prob 0 successors.
1497 onlyProb0Successors = (player1States && onlyProb0Successors).existsAbstract(model.getPlayer2Variables());
1498
1499 // Pick a prob0 player 2 state.
1500 player1StrategyBdd = onlyProb0Successors.existsAbstractRepresentative(model.getPlayer1Variables());
1501 }
1502
1503 return SymbolicGameProb01Result<Type>(player1States, player2States, player1StrategyBdd, player2StrategyBdd);
1504}
1505
1506template<typename ValueType>
1507ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<ValueType> const& transitionMatrix, std::vector<uint64_t> const& player1Groups,
1508 storm::storage::SparseMatrix<ValueType> const& player1BackwardTransitions,
1509 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
1510 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
1511 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
1512 boost::optional<storm::storage::BitVector> const& player1Candidates) {
1513 // During the execution, the two state sets in the result hold the potential player 1/2 states.
1515 if (player1Candidates) {
1516 result = ExplicitGameProb01Result(player1Candidates.get(), storm::storage::BitVector(transitionMatrix.getRowGroupCount()));
1517 } else {
1519 }
1520
1521 // A flag that governs whether strategies are produced in the current iteration.
1522 bool produceStrategiesInIteration = false;
1523
1524 // Initialize the stack used for the DFS with the states
1525 std::vector<uint_fast64_t> stack;
1526 bool maybeStatesDone = false;
1527 while (!maybeStatesDone || produceStrategiesInIteration) {
1528 storm::storage::BitVector player1Solution = psiStates;
1529 storm::storage::BitVector player2Solution(result.player2States.size());
1530
1531 stack.clear();
1532 stack.insert(stack.end(), psiStates.begin(), psiStates.end());
1533
1534 // Perform the actual DFS.
1535 uint_fast64_t currentState;
1536 while (!stack.empty()) {
1537 currentState = stack.back();
1538 stack.pop_back();
1539
1540 for (auto player2PredecessorEntry : player1BackwardTransitions.getRow(currentState)) {
1541 uint64_t player2Predecessor = player2PredecessorEntry.getColumn();
1542 if (!player2Solution.get(player2PredecessorEntry.getColumn())) {
1543 bool addPlayer2State = player2Direction == storm::OptimizationDirection::Minimize ? true : false;
1544
1545 uint64_t validChoice = transitionMatrix.getRowGroupIndices()[player2Predecessor];
1546 for (uint64_t row = validChoice; row < transitionMatrix.getRowGroupIndices()[player2Predecessor + 1]; ++row) {
1547 bool choiceHasSolutionSuccessor = false;
1548 bool choiceStaysInMaybeStates = true;
1549 for (auto const& entry : transitionMatrix.getRow(row)) {
1550 if (player1Solution.get(entry.getColumn())) {
1551 choiceHasSolutionSuccessor = true;
1552 }
1553 if (!result.player1States.get(entry.getColumn())) {
1554 choiceStaysInMaybeStates = false;
1555 break;
1556 }
1557 }
1558
1559 if (choiceHasSolutionSuccessor && choiceStaysInMaybeStates) {
1560 if (player2Direction == storm::OptimizationDirection::Maximize) {
1561 validChoice = row;
1562 addPlayer2State = true;
1563 break;
1564 }
1565 } else if (player2Direction == storm::OptimizationDirection::Minimize) {
1566 addPlayer2State = false;
1567 break;
1568 }
1569 }
1570
1571 if (addPlayer2State) {
1572 player2Solution.set(player2Predecessor);
1573 if (produceStrategiesInIteration) {
1574 strategyPair->getPlayer2Strategy().setChoice(player2Predecessor, validChoice);
1575 }
1576
1577 // Check whether the addition of the player 2 state changes the state of the (single)
1578 // player 1 predecessor.
1579 uint64_t player1Predecessor = player2BackwardTransitions[player2Predecessor];
1580
1581 if (!player1Solution.get(player1Predecessor)) {
1582 bool addPlayer1State = player1Direction == storm::OptimizationDirection::Minimize ? true : false;
1583
1584 validChoice = player1Groups[player1Predecessor];
1585 for (uint64_t player2Successor = validChoice; player2Successor < player1Groups[player1Predecessor + 1]; ++player2Successor) {
1586 if (player2Solution.get(player2Successor)) {
1587 if (player1Direction == storm::OptimizationDirection::Maximize) {
1588 validChoice = player2Successor;
1589 addPlayer1State = true;
1590 break;
1591 }
1592 } else if (player1Direction == storm::OptimizationDirection::Minimize) {
1593 addPlayer1State = false;
1594 break;
1595 }
1596 }
1597
1598 if (addPlayer1State) {
1599 player1Solution.set(player1Predecessor);
1600
1601 if (produceStrategiesInIteration) {
1602 strategyPair->getPlayer1Strategy().setChoice(player1Predecessor, validChoice);
1603 }
1604
1605 stack.emplace_back(player1Predecessor);
1606 }
1607 }
1608 }
1609 }
1610 }
1611 }
1612
1613 if (result.player1States == player1Solution) {
1614 maybeStatesDone = true;
1615 result.player2States = player2Solution;
1616
1617 // If we were asked to produce strategies, we propagate that by triggering another iteration.
1618 // We only do this if at least one strategy will be produced.
1619 produceStrategiesInIteration = !produceStrategiesInIteration && strategyPair;
1620 } else {
1621 result.player1States = player1Solution;
1622 result.player2States = player2Solution;
1623 }
1624 }
1625
1626 return result;
1627}
1628
1629template<storm::dd::DdType Type, typename ValueType>
1631 storm::dd::Bdd<Type> const& transitionMatrix, storm::dd::Bdd<Type> const& phiStates,
1632 storm::dd::Bdd<Type> const& psiStates, storm::OptimizationDirection const& player1Strategy,
1633 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
1634 boost::optional<storm::dd::Bdd<Type>> const& player1Candidates) {
1635 // Create the potential prob1 states of player 1.
1636 storm::dd::Bdd<Type> maybePlayer1States = model.getReachableStates();
1637 if (player1Candidates) {
1638 maybePlayer1States &= player1Candidates.get();
1639 }
1640
1641 // Initialize potential prob1 states of player 2.
1642 storm::dd::Bdd<Type> maybePlayer2States = model.getManager().getBddZero();
1643
1644 // A flag that governs whether strategies are produced in the current iteration.
1645 bool produceStrategiesInIteration = false;
1646 boost::optional<storm::dd::Bdd<Type>> player1StrategyBdd;
1647 boost::optional<storm::dd::Bdd<Type>> consideredPlayer1States;
1648 boost::optional<storm::dd::Bdd<Type>> player2StrategyBdd;
1649 boost::optional<storm::dd::Bdd<Type>> consideredPlayer2States;
1650
1651 bool maybeStatesDone = false;
1652 while (!maybeStatesDone || produceStrategiesInIteration) {
1653 bool solutionStatesDone = false;
1654
1655 // If we are to produce strategies in this iteration, we prepare some storage.
1656 if (produceStrategiesInIteration) {
1657 if (player1Strategy == storm::OptimizationDirection::Maximize) {
1658 player1StrategyBdd = model.getManager().getBddZero();
1659 consideredPlayer1States = model.getManager().getBddZero();
1660 }
1661 if (player2Strategy == storm::OptimizationDirection::Maximize) {
1662 player2StrategyBdd = model.getManager().getBddZero();
1663 consideredPlayer2States = model.getManager().getBddZero();
1664 }
1665 }
1666
1667 storm::dd::Bdd<Type> player1Solution = psiStates;
1668 storm::dd::Bdd<Type> player2Solution = model.getManager().getBddZero();
1669 while (!solutionStatesDone) {
1670 // Start by computing the transitions that have only maybe states as successors. Note that at
1671 // this point, there may be illegal transitions.
1672 storm::dd::Bdd<Type> distributionsStayingInMaybe =
1673 (!transitionMatrix || maybePlayer1States.swapVariables(model.getRowColumnMetaVariablePairs())).universalAbstract(model.getColumnVariables());
1674
1675 // Then, determine all distributions that have at least one successor in the states that have
1676 // probability 1.
1677 storm::dd::Bdd<Type> distributionsWithProb1Successor =
1678 (transitionMatrix && player1Solution.swapVariables(model.getRowColumnMetaVariablePairs())).existsAbstract(model.getColumnVariables());
1679
1680 // The valid distributions are then those that emanate from phi states, stay completely in the
1681 // maybe states and have at least one successor with probability 1.
1682 storm::dd::Bdd<Type> valid = phiStates && distributionsStayingInMaybe && distributionsWithProb1Successor;
1683
1684 // Depending on the strategy of player 2, we need to check whether all choices are valid or
1685 // there exists a valid choice.
1686 if (player2Strategy == OptimizationDirection::Minimize) {
1687 valid = (valid || model.getIllegalPlayer2Mask()).universalAbstract(model.getPlayer2Variables());
1688 } else {
1689 if (produceStrategiesInIteration) {
1690 storm::dd::Bdd<Type> newValidDistributions = valid && !consideredPlayer2States.get();
1691 player2StrategyBdd.get() = player2StrategyBdd.get() || newValidDistributions.existsAbstractRepresentative(model.getPlayer2Variables());
1692 }
1693
1694 valid = valid.existsAbstract(model.getPlayer2Variables());
1695
1696 if (produceStrategiesInIteration) {
1697 consideredPlayer2States.get() |= valid;
1698 }
1699 }
1700
1701 player2Solution |= valid;
1702
1703 // And do the same for player 1.
1704 if (player1Strategy == OptimizationDirection::Minimize) {
1705 valid = (valid || model.getIllegalPlayer1Mask()).universalAbstract(model.getPlayer1Variables());
1706 } else {
1707 if (produceStrategiesInIteration) {
1708 storm::dd::Bdd<Type> newValidDistributions = valid && !consideredPlayer1States.get();
1709 player1StrategyBdd.get() = player1StrategyBdd.get() || newValidDistributions.existsAbstractRepresentative(model.getPlayer1Variables());
1710 }
1711
1712 valid = valid.existsAbstract(model.getPlayer1Variables());
1713
1714 if (produceStrategiesInIteration) {
1715 consideredPlayer1States.get() |= valid;
1716 }
1717 }
1718
1719 // Explicitly add psi states to result since they may have transitions going to some state that
1720 // does not have a reachability probability of 1.
1721 valid |= psiStates;
1722
1723 // If no new states were added, we have found the current hypothesis for the states with
1724 // probability 1.
1725 if (valid == player1Solution) {
1726 solutionStatesDone = true;
1727 } else {
1728 player1Solution = valid;
1729 }
1730 }
1731
1732 // If the states with probability 1 and the potential probability 1 states coincide, we have found
1733 // the solution.
1734 if (player1Solution == maybePlayer1States) {
1735 maybePlayer2States = player2Solution;
1736 maybeStatesDone = true;
1737
1738 // If we were asked to produce strategies, we propagate that by triggering another iteration.
1739 // We only do this if at least one strategy will be produced.
1740 produceStrategiesInIteration = !produceStrategiesInIteration && ((producePlayer1Strategy && player1Strategy == OptimizationDirection::Maximize) ||
1741 (producePlayer2Strategy && player2Strategy == OptimizationDirection::Maximize));
1742 } else {
1743 // Otherwise, we use the current hypothesis for the states with probability 1 as the new maybe
1744 // state set.
1745 maybePlayer1States = player1Solution;
1746 }
1747 }
1748
1749 // From now on, the solution is stored in maybeStates (as it coincides with the previous solution).
1750
1751 // If we were asked to produce strategies that do not need to pick a certain successor but are
1752 // 'arbitrary', do so now.
1753 bool strategiesToCompute = (producePlayer1Strategy && !player1StrategyBdd) || (producePlayer2Strategy && !player2StrategyBdd);
1754 if (strategiesToCompute) {
1755 storm::dd::Bdd<Type> relevantStates = (transitionMatrix && maybePlayer2States).existsAbstract(model.getColumnVariables());
1756 if (producePlayer2Strategy && !player2StrategyBdd) {
1757 player2StrategyBdd = relevantStates.existsAbstractRepresentative(model.getPlayer2Variables());
1758 }
1759 if (producePlayer1Strategy && !player1StrategyBdd) {
1760 relevantStates = (maybePlayer1States && relevantStates).existsAbstract(model.getPlayer2Variables());
1761 player1StrategyBdd = relevantStates.existsAbstractRepresentative(model.getPlayer1Variables());
1762 }
1763 }
1764
1765 return SymbolicGameProb01Result<Type>(maybePlayer1States, maybePlayer2States, player1StrategyBdd, player2StrategyBdd);
1766}
1767
1768template<typename T>
1769void topologicalSortHelper(storm::storage::SparseMatrix<T> const& matrix, uint64_t state, std::vector<uint_fast64_t>& topologicalSort,
1770 std::vector<uint_fast64_t>& recursionStack,
1771 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator>& iteratorRecursionStack,
1772 storm::storage::BitVector& visitedStates) {
1773 if (!visitedStates.get(state)) {
1774 recursionStack.push_back(state);
1775 iteratorRecursionStack.push_back(matrix.begin(state));
1776
1777 recursionStepForward:
1778 while (!recursionStack.empty()) {
1779 uint_fast64_t currentState = recursionStack.back();
1780 typename storm::storage::SparseMatrix<T>::const_iterator successorIterator = iteratorRecursionStack.back();
1781
1782 visitedStates.set(currentState, true);
1783
1784 recursionStepBackward:
1785 for (; successorIterator != matrix.end(currentState); ++successorIterator) {
1786 if (!visitedStates.get(successorIterator->getColumn())) {
1787 // Put unvisited successor on top of our recursion stack and remember that.
1788 recursionStack.push_back(successorIterator->getColumn());
1789
1790 // Also, put initial value for iterator on corresponding recursion stack.
1791 iteratorRecursionStack.push_back(matrix.begin(successorIterator->getColumn()));
1792
1793 goto recursionStepForward;
1794 }
1795 }
1796
1797 topologicalSort.push_back(currentState);
1798
1799 // If we reach this point, we have completed the recursive descent for the current state.
1800 // That is, we need to pop it from the recursion stacks.
1801 recursionStack.pop_back();
1802 iteratorRecursionStack.pop_back();
1803
1804 // If there is at least one state under the current one in our recursion stack, we need
1805 // to restore the topmost state as the current state and jump to the part after the
1806 // original recursive call.
1807 if (recursionStack.size() > 0) {
1808 currentState = recursionStack.back();
1809 successorIterator = iteratorRecursionStack.back();
1810
1811 goto recursionStepBackward;
1812 }
1813 }
1814 }
1815}
1816
1817template<typename T>
1818std::vector<uint_fast64_t> getBFSSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint_fast64_t> const& firstStates) {
1819 storm::storage::BitVector seenStates(matrix.getRowGroupCount());
1820
1821 std::vector<uint_fast64_t> stateQueue;
1822 stateQueue.reserve(matrix.getRowGroupCount());
1823 std::vector<uint_fast64_t> result;
1824 result.reserve(matrix.getRowGroupCount());
1825
1826 // storm::storage::sparse::state_type currentPosition = 0;
1827 auto count = matrix.getRowGroupCount() - 1;
1828 for (auto const& state : firstStates) {
1829 stateQueue.push_back(state);
1830 result[count] = state;
1831 count--;
1832 }
1833
1834 // Perform a BFS.
1835 while (!stateQueue.empty()) {
1836 auto state = stateQueue.back();
1837 stateQueue.pop_back();
1838 seenStates.set(state);
1839 for (auto const& successorEntry : matrix.getRowGroup(state)) {
1840 auto succ = successorEntry.geColumn();
1841 if (!seenStates[succ]) {
1842 result[count] = succ;
1843 count--;
1844 stateQueue.insert(stateQueue.begin(), succ);
1845 }
1846 }
1847 }
1848 return result;
1849}
1850
1851template<typename T>
1852std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<T> const& matrix, std::vector<uint64_t> const& firstStates) {
1853 if (matrix.getRowCount() != matrix.getColumnCount()) {
1854 STORM_LOG_ERROR("Provided matrix is required to be square.");
1855 throw storm::exceptions::InvalidArgumentException() << "Provided matrix is required to be square.";
1856 }
1857
1858 uint_fast64_t numberOfStates = matrix.getRowCount();
1859
1860 // Prepare the result. This relies on the matrix being square.
1861 std::vector<uint_fast64_t> topologicalSort;
1862 topologicalSort.reserve(numberOfStates);
1863
1864 // Prepare the stacks needed for recursion.
1865 std::vector<uint_fast64_t> recursionStack;
1866 recursionStack.reserve(matrix.getRowCount());
1867 std::vector<typename storm::storage::SparseMatrix<T>::const_iterator> iteratorRecursionStack;
1868 iteratorRecursionStack.reserve(numberOfStates);
1869
1870 // Perform a depth-first search over the given transitions and record states in the reverse order they were visited.
1871 storm::storage::BitVector visitedStates(numberOfStates);
1872 for (auto const state : firstStates) {
1873 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1874 }
1875 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
1876 topologicalSortHelper<T>(matrix, state, topologicalSort, recursionStack, iteratorRecursionStack, visitedStates);
1877 }
1878
1879 return topologicalSort;
1880}
1881
1883 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
1884 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
1885 boost::optional<storm::storage::BitVector> const& choiceFilter);
1886
1888
1889template bool hasCycle(storm::storage::SparseMatrix<double> const& transitionMatrix, boost::optional<storm::storage::BitVector> const& subsystem);
1890
1892 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& subsystem,
1893 storm::storage::BitVector const& choices);
1894
1895template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<double> const& transitionMatrix, storm::storage::BitVector const& initialStates,
1896 boost::optional<storm::storage::BitVector> const& subsystem);
1897
1899 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1900 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
1901
1903 storm::storage::BitVector const& psiStates, storm::storage::BitVector const& statesWithProbabilityGreater0);
1904
1906 storm::storage::BitVector const& psiStates);
1907
1908template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::sparse::DeterministicModel<double> const& model,
1909 storm::storage::BitVector const& phiStates,
1910 storm::storage::BitVector const& psiStates);
1911
1912template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::storage::SparseMatrix<double> const& backwardTransitions,
1913 storm::storage::BitVector const& phiStates,
1914 storm::storage::BitVector const& psiStates);
1915
1917 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1919 boost::optional<storm::storage::BitVector> const& rowFilter);
1920
1921template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1923
1924template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1925 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::Scheduler<double>& scheduler);
1926
1927template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<double> const& transitionMatrix,
1928 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1930 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
1931
1933 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1934 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
1935
1937 storm::storage::BitVector const& psiStates);
1938
1940 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1941 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1942 storm::storage::BitVector const& psiStates,
1943 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
1944
1947 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1948
1949template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(storm::storage::SparseMatrix<double> const& transitionMatrix,
1950 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1951 storm::storage::SparseMatrix<double> const& backwardTransitions,
1952 storm::storage::BitVector const& phiStates,
1953 storm::storage::BitVector const& psiStates);
1954
1955template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
1957 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1958
1960 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1961 storm::storage::SparseMatrix<double> const& backwardTransitions,
1962 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
1963 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
1964 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
1965
1968 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1969#ifdef STORM_HAVE_CARL
1972 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1973#endif
1975 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1976 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1977 storm::storage::BitVector const& psiStates);
1978
1981 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1982#ifdef STORM_HAVE_CARL
1985 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
1986#endif
1988 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1989 storm::storage::SparseMatrix<double> const& backwardTransitions, storm::storage::BitVector const& phiStates,
1990 storm::storage::BitVector const& psiStates);
1991
1992template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(storm::storage::SparseMatrix<double> const& transitionMatrix,
1993 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
1994 storm::storage::SparseMatrix<double> const& backwardTransitions,
1995 storm::storage::BitVector const& phiStates,
1996 storm::storage::BitVector const& psiStates);
1997
1998template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2000 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2001#ifdef STORM_HAVE_CARL
2002template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2004 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2005#endif
2006
2007template ExplicitGameProb01Result performProb0(storm::storage::SparseMatrix<double> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping,
2008 storm::storage::SparseMatrix<double> const& player1BackwardTransitions,
2009 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2010 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2011 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2012
2013template ExplicitGameProb01Result performProb1(storm::storage::SparseMatrix<double> const& transitionMatrix, std::vector<uint64_t> const& player1RowGrouping,
2014 storm::storage::SparseMatrix<double> const& player1BackwardTransitions,
2015 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2016 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2017 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2018 boost::optional<storm::storage::BitVector> const& player1Candidates);
2019
2020template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<double> const& matrix, std::vector<uint64_t> const& firstStates);
2021
2022// Instantiations for storm::RationalNumber.
2023#ifdef STORM_HAVE_CARL
2025 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2026 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2027 boost::optional<storm::storage::BitVector> const& choiceFilter);
2028
2030
2031template bool hasCycle(storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2032 boost::optional<storm::storage::BitVector> const& subsystem);
2033
2035 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2036 storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices);
2037
2038template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2039 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2040
2042 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2043 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2044
2046 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2047 storm::storage::BitVector const& statesWithProbabilityGreater0);
2048
2050 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2051
2052template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2054 storm::storage::BitVector const& psiStates);
2055
2056template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2057 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2058 storm::storage::BitVector const& psiStates);
2059
2061 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2062 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2064 boost::optional<storm::storage::BitVector> const& rowFilter);
2065
2066template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2068
2069template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2070 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2072
2073template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix,
2074 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2076 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2077
2079 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2080 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2081
2083 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2084
2086 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2087 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2088 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2089 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2090
2092 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2093 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2094
2095template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2096 storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2097 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2098 storm::storage::BitVector const& psiStates);
2099
2100template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2102 storm::storage::BitVector const& psiStates);
2103
2105 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2106 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2107 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2108 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2109 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2110
2112 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2113 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2114
2116 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2117 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2118 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2119
2121 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2122 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions,
2123 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2124
2125template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2126 storm::storage::SparseMatrix<storm::RationalNumber> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2127 storm::storage::SparseMatrix<storm::RationalNumber> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2128 storm::storage::BitVector const& psiStates);
2129
2130template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2132 storm::storage::BitVector const& psiStates);
2133
2135 std::vector<uint64_t> const& player1RowGrouping,
2136 storm::storage::SparseMatrix<storm::RationalNumber> const& player1BackwardTransitions,
2137 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2138 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2139 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2140
2142 std::vector<uint64_t> const& player1RowGrouping,
2143 storm::storage::SparseMatrix<storm::RationalNumber> const& player1BackwardTransitions,
2144 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2145 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2146 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2147 boost::optional<storm::storage::BitVector> const& player1Candidates);
2148
2149template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalNumber> const& matrix,
2150 std::vector<uint64_t> const& firstStates);
2151// End of instantiations for storm::RationalNumber.
2152// Instantiations for storm::interval
2153
2155 storm::storage::BitVector const& initialStates);
2156
2158 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2159 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2160 boost::optional<storm::storage::BitVector> const& choiceFilter);
2161
2163
2164template bool hasCycle(storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, boost::optional<storm::storage::BitVector> const& subsystem);
2165
2167 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& subsystem,
2168 storm::storage::BitVector const& choices);
2169
2170template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2171 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2172
2174 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2175 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2176
2178 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2179 storm::storage::BitVector const& statesWithProbabilityGreater0);
2180
2182 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2183
2184template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::models::sparse::DeterministicModel<storm::Interval> const& model,
2185 storm::storage::BitVector const& phiStates,
2186 storm::storage::BitVector const& psiStates);
2187
2188template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2189 storm::storage::BitVector const& phiStates,
2190 storm::storage::BitVector const& psiStates);
2191
2193 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2194 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2195 storm::storage::Scheduler<double>& scheduler, boost::optional<storm::storage::BitVector> const& rowFilter);
2196
2197template void computeSchedulerProb0E(storm::storage::BitVector const& prob0EStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2199
2200template void computeSchedulerRewInf(storm::storage::BitVector const& rewInfStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2202
2203template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates, storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix,
2204 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2206 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2207
2209 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2210 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2211
2213 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2214
2216 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2217 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2218 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2219 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2220
2222 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2223 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2224
2225template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2226 storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2227 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2228 storm::storage::BitVector const& psiStates);
2229
2230template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2232 storm::storage::BitVector const& psiStates);
2233
2235 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2236 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2237 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2238 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2239 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2240
2242 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2243 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2244
2246 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2247 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2248 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2249
2251 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2252 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions,
2253 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2254
2255template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2256 storm::storage::SparseMatrix<storm::Interval> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2257 storm::storage::SparseMatrix<storm::Interval> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2258 storm::storage::BitVector const& psiStates);
2259
2260template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2262 storm::storage::BitVector const& psiStates);
2263
2265 std::vector<uint64_t> const& player1RowGrouping,
2266 storm::storage::SparseMatrix<storm::Interval> const& player1BackwardTransitions,
2267 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2268 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2269 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair);
2270
2272 std::vector<uint64_t> const& player1RowGrouping,
2273 storm::storage::SparseMatrix<storm::Interval> const& player1BackwardTransitions,
2274 std::vector<uint64_t> const& player2BackwardTransitions, storm::storage::BitVector const& phiStates,
2275 storm::storage::BitVector const& psiStates, storm::OptimizationDirection const& player1Direction,
2276 storm::OptimizationDirection const& player2Direction, storm::storage::ExplicitGameStrategyPair* strategyPair,
2277 boost::optional<storm::storage::BitVector> const& player1Candidates);
2278
2279template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::Interval> const& matrix, std::vector<uint64_t> const& firstStates);
2280// End storm::interval
2281
2283 storm::storage::BitVector const& initialStates, storm::storage::BitVector const& constraintStates,
2284 storm::storage::BitVector const& targetStates, bool useStepBound, uint_fast64_t maximalSteps,
2285 boost::optional<storm::storage::BitVector> const& choiceFilter);
2286
2288
2289template bool hasCycle(storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix,
2290 boost::optional<storm::storage::BitVector> const& subsystem);
2291
2294 storm::storage::BitVector const& subsystem, storm::storage::BitVector const& choices);
2295
2296template std::vector<uint_fast64_t> getDistances(storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix,
2297 storm::storage::BitVector const& initialStates, boost::optional<storm::storage::BitVector> const& subsystem);
2298
2300 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2301 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2302
2304 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2305 storm::storage::BitVector const& statesWithProbabilityGreater0);
2306
2308 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2309
2310template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2312 storm::storage::BitVector const& psiStates);
2313
2314template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01(
2315 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2316 storm::storage::BitVector const& psiStates);
2317
2318template void computeSchedulerProb1E(storm::storage::BitVector const& prob1EStates,
2321 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2323 boost::optional<storm::storage::BitVector> const& rowFilter = boost::none);
2324
2326 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2327 bool useStepBound = false, uint_fast64_t maximalSteps = 0);
2328
2330 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2331
2333 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2335 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2336 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2337
2340 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2341
2342template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2343 storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2344 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2345 storm::storage::BitVector const& psiStates);
2346
2347template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Max(
2349 storm::storage::BitVector const& psiStates);
2350
2352 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2354 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates,
2355 bool useStepBound = false, uint_fast64_t maximalSteps = 0,
2356 boost::optional<storm::storage::BitVector> const& choiceConstraint = boost::none);
2357
2360 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2362 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2364 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2365
2368 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2370 std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2372 storm::storage::BitVector const& phiStates, storm::storage::BitVector const& psiStates);
2373
2374template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2375 storm::storage::SparseMatrix<storm::RationalFunction> const& transitionMatrix, std::vector<uint_fast64_t> const& nondeterministicChoiceIndices,
2376 storm::storage::SparseMatrix<storm::RationalFunction> const& backwardTransitions, storm::storage::BitVector const& phiStates,
2377 storm::storage::BitVector const& psiStates);
2378
2379template std::pair<storm::storage::BitVector, storm::storage::BitVector> performProb01Min(
2381 storm::storage::BitVector const& psiStates);
2382
2383template std::vector<uint_fast64_t> getTopologicalSort(storm::storage::SparseMatrix<storm::RationalFunction> const& matrix,
2384 std::vector<uint64_t> const& firstStates);
2385#endif
2386
2387// Instantiations for CUDD.
2388
2390 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2393 boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2394
2396 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2399 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0);
2400
2402 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2405
2406template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01(
2409
2410template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01(
2413
2418
2423
2425 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2428
2433
2435 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2438
2440 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2442 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0A);
2443
2445 storm::dd::Bdd<storm::dd::DdType::CUDD> const& transitionMatrix,
2448 storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbabilityGreater0E);
2449
2453 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::dd::Bdd<storm::dd::DdType::CUDD> const& statesWithProbability1E);
2454
2455template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Max(
2458
2459template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Max(
2463
2464template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(
2467
2468template std::pair<storm::dd::Bdd<storm::dd::DdType::CUDD>, storm::dd::Bdd<storm::dd::DdType::CUDD>> performProb01Min(
2472
2476 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2477 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
2478
2482 storm::dd::Bdd<storm::dd::DdType::CUDD> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2483 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
2484 boost::optional<storm::dd::Bdd<storm::dd::DdType::CUDD>> const& player1Candidates);
2485
2486// Instantiations for Sylvan (double).
2487
2489 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2492 boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2493
2495 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2498 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2499
2501 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2504
2505template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2508
2509template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2512
2517
2522
2524 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2527
2532
2534 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2537
2539 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2541 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2542
2544 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2547 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2548
2552 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2553
2554template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2557
2558template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2562
2563template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2566
2567template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2571
2575 storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy,
2576 bool producePlayer2Strategy);
2577
2581 storm::OptimizationDirection const& player1Strategy, storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy,
2582 bool producePlayer2Strategy, boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
2583
2584// Instantiations for Sylvan (rational number).
2585
2589 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2590
2592 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2595 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2596
2598 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2601
2602template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2605
2606template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2610
2615
2620
2625
2630
2635
2639 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2640
2644 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2645
2649 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2650
2651template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2654
2655template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2659
2660template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2663
2664template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2668
2672 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2673 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy);
2674
2678 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::OptimizationDirection const& player1Strategy,
2679 storm::OptimizationDirection const& player2Strategy, bool producePlayer1Strategy, bool producePlayer2Strategy,
2680 boost::optional<storm::dd::Bdd<storm::dd::DdType::Sylvan>> const& player1Candidates);
2681
2682// Instantiations for Sylvan (rational function).
2683
2687 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, boost::optional<uint_fast64_t> const& stepBound = boost::optional<uint_fast64_t>());
2688
2690 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2693 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0);
2694
2696 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& transitionMatrix,
2699
2700template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2703
2704template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01(
2708
2713
2718
2723
2728
2733
2737 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0A);
2738
2742 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbabilityGreater0E);
2743
2747 storm::dd::Bdd<storm::dd::DdType::Sylvan> const& psiStates, storm::dd::Bdd<storm::dd::DdType::Sylvan> const& statesWithProbability1E);
2748
2749template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2752
2753template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Max(
2757
2758template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2761
2762template std::pair<storm::dd::Bdd<storm::dd::DdType::Sylvan>, storm::dd::Bdd<storm::dd::DdType::Sylvan>> performProb01Min(
2766
2767} // namespace graph
2768} // namespace utility
2769} // 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:826
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:1769
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:1299
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:1852
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:1818
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:848
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:615
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:988
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:680
storm::storage::BitVector performProb0A(storm::storage::SparseMatrix< T > const &backwardTransitions, storm::storage::BitVector const &phiStates, storm::storage::BitVector const &psiStates)
Definition graph.cpp:740
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:967
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:1070
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:748
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