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