Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
BigStep.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <functional>
5#include <map>
6#include <memory>
7#include <numeric>
8#include <queue>
9#include <set>
10#include <stack>
11#include <string>
12#include <unordered_map>
13#include <utility>
14#include <vector>
15
24#include "storm/utility/graph.h"
27
28#define WRITE_DTMCS 0
29
30namespace storm {
31namespace transformer {
32
34
36 auto multivariatePol = storm::RawPolynomial(uniPoly);
37 auto multiNominator = carl::FactorizedPolynomial<storm::RawPolynomial>(multivariatePol, rawPolynomialCache);
38 return RationalFunction(multiNominator);
39}
40
41bool UniPolyCompare::operator()(const UniPoly& lhs, const UniPoly& rhs) const {
42 if (lhs.degree() != rhs.degree()) {
43 return lhs.degree() < rhs.degree();
44 }
45
46 for (uint64_t i = 0; i < lhs.coefficients().size(); i++) {
47 if (lhs.coefficients()[i] != rhs.coefficients()[i]) {
48 return lhs.coefficients()[i] < rhs.coefficients()[i];
49 }
50 }
51
52 return false;
53}
54
56 auto& container = (*this)[p];
57
58 auto it = container.first.find(f);
59 if (it != container.first.end()) {
60 return it->second;
61 }
62
63 uint64_t newIndex = container.second.size();
64 container.first[f] = newIndex;
65 container.second.push_back(f);
66
67 return newIndex;
68}
69
70UniPoly PolynomialCache::polynomialFromFactorization(std::vector<uint64_t> const& factorization, RationalFunctionVariable const& p) const {
71 static std::map<std::pair<std::vector<uint64_t>, RationalFunctionVariable>, UniPoly> localCache;
72 auto key = std::make_pair(factorization, p);
73 if (localCache.count(key)) {
74 return localCache.at(key);
75 }
76 UniPoly polynomial = UniPoly(p);
77 polynomial = polynomial.one();
78 for (uint64_t i = 0; i < factorization.size(); i++) {
79 for (uint64_t j = 0; j < factorization[i]; j++) {
80 polynomial *= this->at(p).second[i];
81 }
82 }
83 localCache.emplace(key, polynomial);
84 return polynomial;
85}
86
87Annotation::Annotation(RationalFunctionVariable parameter, std::shared_ptr<PolynomialCache> polynomialCache)
88 : parameter(parameter), polynomialCache(polynomialCache) {
89 // Intentionally left empty
90}
91
93 STORM_LOG_ASSERT(other.parameter == this->parameter, "Can only add annotations with equal parameters.");
94 for (auto const& [factors, number] : other) {
95 if (this->count(factors)) {
96 this->at(factors) += number;
97 } else {
98 this->emplace(factors, number);
99 }
100 }
101}
102
103void Annotation::operator*=(RationalFunctionCoefficient n) {
104 for (auto& [factors, number] : *this) {
105 number *= n;
106 }
107}
108
109Annotation Annotation::operator*(RationalFunctionCoefficient n) const {
110 Annotation annotationCopy(*this);
111 annotationCopy *= n;
112 return annotationCopy;
113}
114
115void Annotation::addAnnotationTimesConstant(Annotation const& other, RationalFunctionCoefficient timesConstant) {
116 for (auto const& [info, constant] : other) {
117 if (!this->count(info)) {
118 this->emplace(info, utility::zero<RationalFunctionCoefficient>());
119 }
120 this->at(info) += constant * timesConstant;
121 }
122}
123
125 for (auto const& [info, constant] : other) {
126 // Copy array
127 auto newCounter = info;
128
129 // Write new polynomial into array
130 auto const cacheNum = this->polynomialCache->lookUpInCache(polynomial, parameter);
131 while (newCounter.size() <= cacheNum) {
132 newCounter.push_back(0);
133 }
134 newCounter[cacheNum]++;
135
136 if (!this->count(newCounter)) {
137 this->emplace(newCounter, constant);
138 } else {
139 this->at(newCounter) += constant;
140 }
141 }
142}
143
145 for (auto const& [info1, constant1] : anno1) {
146 for (auto const& [info2, constant2] : anno2) {
147 std::vector<uint64_t> newCounter(std::max(info1.size(), info2.size()), 0);
148
149 for (uint64_t i = 0; i < newCounter.size(); i++) {
150 if (i < info1.size()) {
151 newCounter[i] += info1[i];
152 }
153 if (i < info2.size()) {
154 newCounter[i] += info2[i];
155 }
156 }
157
158 if (!this->count(newCounter)) {
159 this->emplace(newCounter, constant1 * constant2);
160 } else {
161 this->at(newCounter) += constant1 * constant2;
162 }
163 }
164 }
165}
166
168 UniPoly prob = UniPoly(parameter); // Creates a zero polynomial
169 for (auto const& [info, constant] : *this) {
170 prob += polynomialCache->polynomialFromFactorization(info, parameter) * constant;
171 }
172 return prob;
173}
174
175std::vector<UniPoly> Annotation::getTerms() const {
176 std::vector<UniPoly> terms;
177 for (auto const& [info, constant] : *this) {
178 terms.push_back(polynomialCache->polynomialFromFactorization(info, parameter) * constant);
179 }
180 return terms;
181}
182
184 if (!derivativeOfThis) {
185 return evaluate<Interval>(input);
186 } else {
187 Interval boundDerivative = derivativeOfThis->evaluateOnIntervalMidpointTheorem(input, higherOrderBounds);
188 double maxSlope = utility::max(utility::abs(boundDerivative.lower()), utility::abs(boundDerivative.upper()));
189 double fMid = evaluate<double>(input.center());
190 double fMin = fMid - (input.diameter() / 2) * maxSlope;
191 double fMax = fMid + (input.diameter() / 2) * maxSlope;
192 if (higherOrderBounds) {
193 Interval boundsHere = evaluate<Interval>(input);
194 return Interval(utility::max(fMin, boundsHere.lower()), utility::min(fMax, boundsHere.upper()));
195 } else {
196 return Interval(fMin, fMax);
197 }
198 }
199}
200
202 return parameter;
203}
204
206 if (nth == 0 || derivativeOfThis) {
207 return;
208 }
209 derivativeOfThis = std::make_shared<Annotation>(this->parameter, this->polynomialCache);
210 for (auto const& [info, constant] : *this) {
211 // Product rule
212 for (uint64_t i = 0; i < info.size(); i++) {
213 if (info[i] == 0) {
214 continue;
215 }
216
217 RationalFunctionCoefficient newConstant = constant * utility::convertNumber<RationalFunctionCoefficient>(info[i]);
218
219 std::vector<uint64_t> insert(info);
220 insert[i]--;
221 // Delete trailing zeroes from insert
222 while (!insert.empty() && insert.back() == 0) {
223 insert.pop_back();
224 }
225
226 auto polynomial = polynomialCache->at(parameter).second.at(i);
227 auto derivative = polynomial.derivative();
228 if (derivative.isConstant()) {
229 newConstant *= derivative.constantPart();
230 } else {
231 uint64_t derivativeIndex = this->polynomialCache->lookUpInCache(derivative, parameter);
232 while (insert.size() < derivativeIndex) {
233 insert.push_back(0);
234 }
235 insert[derivativeIndex]++;
236 }
237 if (derivativeOfThis->count(insert)) {
238 derivativeOfThis->at(insert) += newConstant;
239 } else {
240 derivativeOfThis->emplace(insert, newConstant);
241 }
242 }
243 }
244 derivativeOfThis->computeDerivative(nth - 1);
245}
246
247uint64_t Annotation::maxDegree() const {
248 uint64_t maxDegree = 0;
249 for (auto const& [info, constant] : *this) {
250 if (!info.empty()) {
251 maxDegree = std::max(maxDegree, *std::max_element(info.begin(), info.end()));
252 }
253 }
254 return maxDegree;
255}
256
257std::shared_ptr<Annotation> Annotation::derivative() {
259 return derivativeOfThis;
260}
261
262// Annotation operator<< implementation
263std::ostream& operator<<(std::ostream& os, const Annotation& annotation) {
264 auto iterator = annotation.begin();
265 while (iterator != annotation.end()) {
266 auto const& factors = iterator->first;
267 auto const& constant = iterator->second;
268 os << constant << " * (";
269 bool alreadyPrintedFactor = false;
270 for (uint64_t i = 0; i < factors.size(); i++) {
271 if (factors[i] > 0) {
272 if (alreadyPrintedFactor) {
273 os << "*";
274 } else {
275 alreadyPrintedFactor = true;
276 }
277 os << "(" << annotation.polynomialCache->at(annotation.parameter).second[i] << ")"
278 << "^" << factors[i];
279 }
280 }
281 if (factors.empty()) {
282 os << "1";
283 }
284 os << ")";
285 iterator++;
286 if (iterator != annotation.end()) {
287 os << " + ";
288 }
289 }
290 return os;
291}
292
293std::pair<std::map<uint64_t, std::set<uint64_t>>, std::set<uint64_t>> findSubgraph(
294 const storm::storage::FlexibleSparseMatrix<RationalFunction>& transitionMatrix, const uint64_t root,
295 const std::map<RationalFunctionVariable, std::map<uint64_t, std::set<uint64_t>>>& treeStates,
296 const boost::optional<std::vector<RationalFunction>>& stateRewardVector, const RationalFunctionVariable parameter) {
297 std::map<uint64_t, std::set<uint64_t>> subgraph;
298 std::set<uint64_t> bottomStates;
299
300 std::set<uint64_t> acyclicStates;
301
302 std::vector<uint64_t> dfsStack = {root};
303 while (!dfsStack.empty()) {
304 uint64_t state = dfsStack.back();
305 // Is it a new state that we see for the first time or one we've already visited?
306 if (!subgraph.count(state)) {
307 subgraph[state] = {};
308
309 std::vector<uint64_t> tmpStack;
310 bool isAcyclic = true;
311
312 // First we find out whether the state is acyclic
313 for (auto const& entry : transitionMatrix.getRow(state)) {
314 if (!storm::utility::isZero(entry.getValue())) {
315 if (subgraph.count(entry.getColumn()) && !acyclicStates.count(entry.getColumn()) && !bottomStates.count(entry.getColumn())) {
316 // The state has been visited before but is not known to be acyclic.
317 isAcyclic = false;
318 break;
319 }
320 }
321 }
322
323 if (!isAcyclic) {
324 bottomStates.emplace(state);
325 continue;
326 }
327
328 for (auto const& entry : transitionMatrix.getRow(state)) {
329 if (!storm::utility::isZero(entry.getValue())) {
330 STORM_LOG_ASSERT(entry.getValue().isConstant() ||
331 (entry.getValue().gatherVariables().size() == 1 && *entry.getValue().gatherVariables().begin() == parameter),
332 "Called findSubgraph with incorrect parameter.");
333 // Add this edge to the subgraph
334 subgraph.at(state).emplace(entry.getColumn());
335 // If we haven't explored the node we are going to, we will need to figure out if it is a leaf or not
336 if (!subgraph.count(entry.getColumn())) {
337 bool continueSearching = treeStates.at(parameter).count(entry.getColumn()) && !treeStates.at(parameter).at(entry.getColumn()).empty();
338
339 if (!entry.getValue().isConstant()) {
340 // We are only interested in transitions that are constant or have the parameter
341 // We can skip transitions that have other parameters
342 continueSearching &= entry.getValue().gatherVariables().size() == 1 && *entry.getValue().gatherVariables().begin() == parameter;
343 }
344
345 // Also continue searching if there is only a transition with a one coming up, we can skip that
346 // This is nice because we can possibly combine more transitions later
347 bool onlyHasOne = transitionMatrix.getRow(entry.getColumn()).size() == 1 &&
348 transitionMatrix.getRow(entry.getColumn()).begin()->getValue() == utility::one<RationalFunction>();
349 continueSearching |= onlyHasOne;
350
351 // Don't mess with rewards
352 continueSearching &= !(stateRewardVector && !stateRewardVector->at(entry.getColumn()).isZero());
353
354 if (continueSearching) {
355 // We are setting this state to explored once we pop it from the stack, not yet
356 // Just push it to the stack
357 tmpStack.push_back(entry.getColumn());
358 } else {
359 // This state is a leaf
360 subgraph[entry.getColumn()] = {};
361 bottomStates.emplace(entry.getColumn());
362
363 acyclicStates.emplace(entry.getColumn());
364 }
365 }
366 }
367 }
368
369 for (auto const& entry : tmpStack) {
370 dfsStack.push_back(entry);
371 }
372 } else {
373 // Go back over the states backwards - we know these are not acyclic
374 acyclicStates.emplace(state);
375 dfsStack.pop_back();
376 }
377 }
378 return std::make_pair(subgraph, bottomStates);
379}
380
381std::pair<models::sparse::Dtmc<RationalFunction>, std::map<UniPoly, Annotation>> BigStep::bigStep(
385
386 STORM_LOG_ASSERT(transitionMatrix.isProbabilistic(storm::utility::zero<RationalFunction>()), "Gave big-step a nonprobabilistic transition matrix.");
387
388 uint64_t initialState = dtmc.getInitialStates().getNextSetIndex(0);
389
390 uint64_t originalNumStates = dtmc.getNumberOfStates();
391
392 auto allParameters = storm::models::sparse::getAllParameters(dtmc);
393
394 std::set<std::string> labelsInFormula;
395 for (auto const& atomicLabelFormula : checkTask.getFormula().getAtomicLabelFormulas()) {
396 labelsInFormula.emplace(atomicLabelFormula->getLabel());
397 }
398
399 models::sparse::StateLabeling runningLabeling(dtmc.getStateLabeling());
400 models::sparse::StateLabeling runningLabelingTreeStates(dtmc.getStateLabeling());
401 for (auto const& label : labelsInFormula) {
402 runningLabelingTreeStates.removeLabel(label);
403 }
404
405 // Check the reward model - do not touch states with rewards
406 boost::optional<std::vector<RationalFunction>> stateRewardVector;
407 boost::optional<std::string> stateRewardName;
408 if (checkTask.getFormula().isRewardOperatorFormula()) {
409 if (checkTask.isRewardModelSet()) {
411 stateRewardVector = dtmc.getRewardModel(checkTask.getRewardModel()).getStateRewardVector();
412 stateRewardName = checkTask.getRewardModel();
413 } else {
415 stateRewardVector = dtmc.getRewardModel("").getStateRewardVector();
416 stateRewardName = dtmc.getUniqueRewardModelName();
417 }
418 }
419
420 auto topologicalOrdering = utility::graph::getTopologicalSort<RationalFunction>(transitionMatrix, {initialState});
421
422 auto flexibleMatrix = storage::FlexibleSparseMatrix<RationalFunction>(transitionMatrix);
423 auto backwardsTransitions = storage::FlexibleSparseMatrix<RationalFunction>(transitionMatrix.transpose());
424
425 // Initialize counting
426 // Tree states: parameter p -> state s -> set of reachable states from s by constant transition that have a p-transition
427 std::map<RationalFunctionVariable, std::map<uint64_t, std::set<uint64_t>>> treeStates;
428 // Tree states need updating for these sets and variables
429 std::map<RationalFunctionVariable, std::set<uint64_t>> treeStatesNeedUpdate;
430
431 // Initialize treeStates and treeStatesNeedUpdate
432 for (uint64_t row = 0; row < flexibleMatrix.getRowCount(); row++) {
433 for (auto const& entry : flexibleMatrix.getRow(row)) {
434 if (!entry.getValue().isConstant()) {
435 if (!this->rawPolynomialCache) {
436 // So we can create new FactorizedPolynomials later
437 this->rawPolynomialCache = entry.getValue().nominator().pCache();
438 }
439 for (auto const& parameter : entry.getValue().gatherVariables()) {
440 treeStatesNeedUpdate[parameter].emplace(row);
441 treeStates[parameter][row].emplace(row);
442 }
443 }
444 }
445 }
446 updateTreeStates(treeStates, treeStatesNeedUpdate, flexibleMatrix, backwardsTransitions, allParameters, stateRewardVector, runningLabelingTreeStates);
447
448 // To prevent infinite unrolling of parametric loops:
449 // We have already reordered with these as leaves, don't reorder with these as leaves again
450 std::map<RationalFunctionVariable, std::set<std::set<uint64_t>>> alreadyTimeTravelledToThis;
451
452 // We will traverse the model according to the topological ordering
453 std::stack<uint64_t> topologicalOrderingStack;
454 topologicalOrdering = utility::graph::getTopologicalSort<RationalFunction>(transitionMatrix, {initialState});
455 for (auto rit = topologicalOrdering.begin(); rit != topologicalOrdering.end(); ++rit) {
456 topologicalOrderingStack.push(*rit);
457 }
458
459 // Identify reachable states - not reachable states do not have do be big-stepped
460 const storage::BitVector trueVector(transitionMatrix.getRowCount(), true);
461 const storage::BitVector falseVector(transitionMatrix.getRowCount(), false);
462 storage::BitVector initialStates(transitionMatrix.getRowCount(), false);
463 initialStates.set(initialState, true);
464
465 // We will compute the reachable states once in the beginning but update them dynamically
466 storage::BitVector reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, trueVector, falseVector);
467
468 // We will return these stored annotations to help find the zeroes
469 std::map<UniPoly, Annotation> storedAnnotations;
470
471 std::map<RationalFunctionVariable, std::set<uint64_t>> bottomStatesSeen;
472
473#if WRITE_DTMCS
474 uint64_t writeDtmcCounter = 0;
475#endif
476
477 while (!topologicalOrderingStack.empty()) {
478 auto state = topologicalOrderingStack.top();
479 topologicalOrderingStack.pop();
480
481 if (!reachableStates.get(state)) {
482 continue;
483 }
484
485 std::set<RationalFunctionVariable> parametersInState;
486 for (auto const& entry : flexibleMatrix.getRow(state)) {
487 for (auto const& parameter : entry.getValue().gatherVariables()) {
488 parametersInState.emplace(parameter);
489 }
490 }
491
492 std::set<RationalFunctionVariable> bigStepParameters;
493 for (auto const& parameter : allParameters) {
494 if (treeStates[parameter].count(state)) {
495 // Parallel parameters
496 if (treeStates.at(parameter).at(state).size() > 1) {
497 bigStepParameters.emplace(parameter);
498 continue;
499 }
500 // Sequential parameters
501 if (parametersInState.count(parameter)) {
502 for (auto const& treeState : treeStates[parameter][state]) {
503 for (auto const& successor : flexibleMatrix.getRow(treeState)) {
504 if (treeStates[parameter].count(successor.getColumn())) {
505 bigStepParameters.emplace(parameter);
506 break;
507 }
508 }
509 }
510 }
511 }
512 }
513
514 // Do big-step lifting from here
515 // Follow the treeStates and eliminate transitions
516 for (auto const& parameter : bigStepParameters) {
517 // Find the paths along which we eliminate the transitions into one transition along with their probabilities.
518 auto const [bottomAnnotations, visitedStatesAndSubtree] =
519 bigStepBFS(state, parameter, flexibleMatrix, backwardsTransitions, treeStates, stateRewardVector, storedAnnotations);
520 auto const [visitedStates, subtree] = visitedStatesAndSubtree;
521
522 // Check the following:
523 // There exists a state s in visitedStates s.t. all predecessors of s are in the subtree
524 // If not, we are not eliminating any states with this big-step which baaaad and leads to the world-famous "grid issue"
525 bool existsEliminableState = false;
526 for (auto const& s : visitedStates) {
527 bool allPredecessorsInVisitedStates = true;
528 for (auto const& predecessor : backwardsTransitions.getRow(s)) {
529 if (predecessor.getValue().isZero()) {
530 continue;
531 }
532 if (!reachableStates.get(predecessor.getColumn())) {
533 continue;
534 }
535 // is the predecessor not in the subtree? then this state won't get eliminated
536 // is the predcessor in the subtree but the edge isn't? then this state won't get eliminated
537 if (!subtree.count(predecessor.getColumn()) || !subtree.at(predecessor.getColumn()).count(s)) {
538 allPredecessorsInVisitedStates = false;
539 break;
540 }
541 }
542 if (allPredecessorsInVisitedStates) {
543 existsEliminableState = true;
544 break;
545 }
546 }
547 // If we will not eliminate any states, do not perfom big-step
548 if (!existsEliminableState) {
549 continue;
550 }
551
552 uint64_t oldMatrixSize = flexibleMatrix.getRowCount();
553
554 std::vector<std::pair<uint64_t, Annotation>> transitions = findBigStep(bottomAnnotations, parameter, flexibleMatrix, backwardsTransitions,
555 alreadyTimeTravelledToThis, treeStatesNeedUpdate, state, originalNumStates);
556
557 // Put paths into matrix
558 auto newStoredAnnotations =
559 replaceWithNewTransitions(state, transitions, flexibleMatrix, backwardsTransitions, reachableStates, treeStatesNeedUpdate);
560 for (auto const& entry : newStoredAnnotations) {
561 storedAnnotations.emplace(entry);
562 }
563
564 // Dynamically update unreachable states
565 updateUnreachableStates(reachableStates, visitedStates, backwardsTransitions, initialState);
566
567 uint64_t newMatrixSize = flexibleMatrix.getRowCount();
568 if (newMatrixSize > oldMatrixSize) {
569 // Extend labeling to more states
570 runningLabeling = extendStateLabeling(runningLabeling, oldMatrixSize, newMatrixSize, state, labelsInFormula);
571 runningLabelingTreeStates = extendStateLabeling(runningLabelingTreeStates, oldMatrixSize, newMatrixSize, state, labelsInFormula);
572
573 // Extend reachableStates
574 reachableStates.resize(newMatrixSize, true);
575
576 for (uint64_t i = oldMatrixSize; i < newMatrixSize; i++) {
577 topologicalOrderingStack.push(i);
578 for (auto& [_parameter, updateStates] : treeStatesNeedUpdate) {
579 updateStates.emplace(i);
580 }
581 // New states have zero reward
582 if (stateRewardVector) {
583 stateRewardVector->push_back(storm::utility::zero<RationalFunction>());
584 }
585 }
586 updateTreeStates(treeStates, treeStatesNeedUpdate, flexibleMatrix, backwardsTransitions, allParameters, stateRewardVector,
587 runningLabelingTreeStates);
588 }
589 // We continue the loop through the bigStepParameters if we don't do big-step.
590 // If we reach here, then we did indeed to big-step, so we will break.
591 break;
592 }
593
594#if WRITE_DTMCS
595 models::sparse::Dtmc<RationalFunction> newnewnewDTMC(flexibleMatrix.createSparseMatrix(), runningLabeling);
596 if (stateRewardVector) {
597 models::sparse::StandardRewardModel<RationalFunction> newRewardModel(*stateRewardVector);
598 newnewnewDTMC.addRewardModel(*stateRewardName, newRewardModel);
599 }
600 std::ofstream file2;
601 storm::io::openFile("dots/travel_" + std::to_string(flexibleMatrix.getRowCount()) + ".dot", file2);
602 newnewnewDTMC.writeDotToStream(file2);
604#endif
605 }
606
607 transitionMatrix = flexibleMatrix.createSparseMatrix();
608
609 // Delete states
610 {
611 storage::BitVector trueVector(transitionMatrix.getRowCount(), true);
612 storage::BitVector falseVector(transitionMatrix.getRowCount(), false);
613 storage::BitVector initialStates(transitionMatrix.getRowCount(), false);
614 initialStates.set(initialState, true);
615 storage::BitVector reachableStates = storm::utility::graph::getReachableStates(transitionMatrix, initialStates, trueVector, falseVector);
616
617 transitionMatrix = transitionMatrix.getSubmatrix(false, reachableStates, reachableStates);
618 runningLabeling = runningLabeling.getSubLabeling(reachableStates);
619 uint_fast64_t newInitialState = 0;
620 for (uint_fast64_t i = 0; i < initialState; i++) {
621 if (reachableStates.get(i)) {
622 newInitialState++;
623 }
624 }
625 initialState = newInitialState;
626 if (stateRewardVector) {
627 std::vector<RationalFunction> newStateRewardVector;
628 for (uint_fast64_t i = 0; i < stateRewardVector->size(); i++) {
629 if (reachableStates.get(i)) {
630 newStateRewardVector.push_back(stateRewardVector->at(i));
631 } else {
632 STORM_LOG_ERROR_COND(stateRewardVector->at(i).isZero(), "Deleted non-zero reward.");
633 }
634 }
635 stateRewardVector = newStateRewardVector;
636 }
637 }
638
639 models::sparse::Dtmc<RationalFunction> newDTMC(transitionMatrix, runningLabeling);
640
641 storage::BitVector newInitialStates(transitionMatrix.getRowCount());
642 newInitialStates.set(initialState, true);
643 newDTMC.setInitialStates(newInitialStates);
644
645 if (stateRewardVector) {
646 models::sparse::StandardRewardModel<RationalFunction> newRewardModel(*stateRewardVector);
647 newDTMC.addRewardModel(*stateRewardName, newRewardModel);
648 }
649
651 "Internal error: resulting matrix not probabilistic!");
652
653 lastSavedAnnotations.clear();
654 for (auto const& entry : storedAnnotations) {
655 lastSavedAnnotations.emplace(std::make_pair(uniPolyToRationalFunction(entry.first), entry.second));
656 }
657
658 return std::make_pair(newDTMC, storedAnnotations);
659}
660
661std::pair<std::map<uint64_t, Annotation>, std::pair<std::vector<uint64_t>, std::map<uint64_t, std::set<uint64_t>>>> BigStep::bigStepBFS(
662 uint64_t start, const RationalFunctionVariable& parameter, const storage::FlexibleSparseMatrix<RationalFunction>& flexibleMatrix,
663 const storage::FlexibleSparseMatrix<RationalFunction>& backwardsFlexibleMatrix,
664 const std::map<RationalFunctionVariable, std::map<uint64_t, std::set<uint64_t>>>& treeStates,
665 const boost::optional<std::vector<RationalFunction>>& stateRewardVector, const std::map<UniPoly, Annotation>& storedAnnotations) {
666 // Find the subgraph we will work on using DFS, following the treeStates, stopping before cycles
667 auto const [subtree, bottomStates] = findSubgraph(flexibleMatrix, start, treeStates, stateRewardVector, parameter);
668
669 // We need this to later determine which states are now unreachable
670 std::vector<uint64_t> visitedStatesInBFSOrder;
671
672 std::set<std::pair<uint64_t, uint64_t>> visitedEdges;
673
674 // We iterate over these annotations
675 std::map<uint64_t, Annotation> annotations;
676
677 // Set of active states in BFS
678 std::queue<uint64_t> activeStates;
679 activeStates.push(start);
680
681 annotations.emplace(start, Annotation(parameter, polynomialCache));
682 // We go with probability one from the start to the start
683 annotations.at(start)[std::vector<uint64_t>()] = utility::one<RationalFunctionCoefficient>();
684
685 while (!activeStates.empty()) {
686 auto state = activeStates.front();
687 activeStates.pop();
688 visitedStatesInBFSOrder.push_back(state);
689 for (auto const& entry : flexibleMatrix.getRow(state)) {
690 auto const goToState = entry.getColumn();
691 if (!subtree.count(goToState) || !subtree.at(state).count(goToState)) {
692 continue;
693 }
694 visitedEdges.emplace(std::make_pair(state, goToState));
695 // Check if all of the backwards states have been visited
696 bool allBackwardsStatesVisited = true;
697 for (auto const& backwardsEntry : backwardsFlexibleMatrix.getRow(goToState)) {
698 if (!subtree.count(backwardsEntry.getColumn()) || !subtree.at(backwardsEntry.getColumn()).count(goToState)) {
699 // We don't consider this edge for one of two reasons:
700 // (1) The node is not in the subtree.
701 // (2) The edge is not in the subtree. This can happen if to states are in the subtree for unrelated reasons
702 continue;
703 }
704 if (!visitedEdges.count(std::make_pair(backwardsEntry.getColumn(), goToState))) {
705 allBackwardsStatesVisited = false;
706 break;
707 }
708 }
709 if (!allBackwardsStatesVisited) {
710 continue;
711 }
712
713 // Update the annotation of the target state
714 annotations.emplace(goToState, Annotation(parameter, polynomialCache));
715
716 // Value-iteration style
717 for (auto const& backwardsEntry : backwardsFlexibleMatrix.getRow(goToState)) {
718 if (!subtree.count(backwardsEntry.getColumn()) || !subtree.at(backwardsEntry.getColumn()).count(goToState)) {
719 // We don't consider this edge for one of two reasons:
720 // (1) The node is not in the subtree.
721 // (2) The edge is not in the subtree. This can happen if to states are in the subtree for unrelated reasons
722 continue;
723 }
724 auto const transition = backwardsEntry.getValue();
725
726 // We add stuff to this annotation
727 auto& targetAnnotation = annotations.at(goToState);
728
729 // The core of this big-step algorithm: "value-iterating" on our annotation.
730 if (transition.isConstant()) {
731 targetAnnotation.addAnnotationTimesConstant(annotations.at(backwardsEntry.getColumn()), transition.constantPart());
732 } else {
733 // Read transition from DTMC, convert to univariate polynomial
734 STORM_LOG_ERROR_COND(transition.denominator().isConstant(), "Only transitions with constant denominator supported but this has "
735 << transition.denominator() << " in transition " << transition);
736 auto nominator = transition.nominator();
737 UniPoly nominatorAsUnivariate = transition.nominator().toUnivariatePolynomial();
738 // Constant denominator is now distributed in the factors, not in the denominator of the rational function
739 nominatorAsUnivariate /= transition.denominator().coefficient();
740 if (storedAnnotations.count(nominatorAsUnivariate)) {
741 targetAnnotation.addAnnotationTimesAnnotation(annotations.at(backwardsEntry.getColumn()), storedAnnotations.at(nominatorAsUnivariate));
742 } else {
743 targetAnnotation.addAnnotationTimesPolynomial(annotations.at(backwardsEntry.getColumn()), std::move(nominatorAsUnivariate));
744 }
745 }
746
747 // Check if we have visited all forward edges of this annotation, if so, erase it
748 bool allForwardEdgesVisited = true;
749 for (auto const& entry : flexibleMatrix.getRow(backwardsEntry.getColumn())) {
750 if (!subtree.at(backwardsEntry.getColumn()).count(entry.getColumn())) {
751 // We don't consider this edge for one of two reasons:
752 // (1) The node is not in the subtree.
753 // (2) The edge is not in the subtree. This can happen if to states are in the subtree for unrelated reasons
754 continue;
755 }
756 if (!annotations.count(entry.getColumn())) {
757 allForwardEdgesVisited = false;
758 break;
759 }
760 }
761 if (allForwardEdgesVisited) {
762 annotations.erase(backwardsEntry.getColumn());
763 }
764 }
765 activeStates.push(goToState);
766 }
767 }
768 // Delete annotations that are not bottom states
769 for (auto const& [state, _successors] : subtree) {
770 if (!bottomStates.count(state)) {
771 annotations.erase(state);
772 }
773 }
774 return std::make_pair(annotations, std::make_pair(visitedStatesInBFSOrder, subtree));
775}
776
777std::vector<std::pair<uint64_t, Annotation>> BigStep::findBigStep(const std::map<uint64_t, Annotation> bigStepAnnotations,
778 const RationalFunctionVariable& parameter,
779 storage::FlexibleSparseMatrix<RationalFunction>& flexibleMatrix,
780 storage::FlexibleSparseMatrix<RationalFunction>& backwardsFlexibleMatrix,
781 std::map<RationalFunctionVariable, std::set<std::set<uint64_t>>>& alreadyTimeTravelledToThis,
782 std::map<RationalFunctionVariable, std::set<uint64_t>>& treeStatesNeedUpdate, uint64_t root,
783 uint64_t originalNumStates) {
784 STORM_LOG_INFO("Find time travelling called with root " << root << " and parameter " << parameter);
785
786 // Time Travelling: For transitions that divide into constants, join them into one transition leading into new state
787 std::map<std::vector<uint64_t>, std::map<uint64_t, RationalFunctionCoefficient>> parametricTransitions;
788
789 for (auto const& [state, annotation] : bigStepAnnotations) {
790 for (auto const& [info, constant] : annotation) {
791 if (!parametricTransitions.count(info)) {
792 parametricTransitions[info] = std::map<uint64_t, RationalFunctionCoefficient>();
793 }
794 STORM_LOG_ASSERT(!parametricTransitions.at(info).count(state), "State already exists.");
795 parametricTransitions.at(info)[state] = constant;
796 }
797 }
798
799 // These are the transitions that we are actually going to insert (that the function will return).
800 std::vector<std::pair<uint64_t, Annotation>> insertTransitions;
801
802 // State affected by big-step
803 std::unordered_set<uint64_t> affectedStates;
804
805 std::set<std::set<uint64_t>> targetSetStates;
806
807 for (auto const& [factors, transitions] : parametricTransitions) {
808 if (transitions.size() > 1) {
809 // STORM_LOG_ERROR_COND(!factors.empty(), "Empty factors!");
810 STORM_LOG_INFO("Time-travelling from root " << root);
811 // The set of target states of the paths that we maybe want to time-travel
812 std::set<uint64_t> targetStates;
813
814 // All of these states are affected by time-travelling
815 for (auto const& [state, info] : transitions) {
816 affectedStates.emplace(state);
817 if (state < originalNumStates) {
818 targetStates.emplace(state);
819 }
820 }
821
822 if (alreadyTimeTravelledToThis[parameter].count(targetStates)) {
823 for (auto const& [state, probability] : transitions) {
824 Annotation newAnnotation(parameter, polynomialCache);
825 newAnnotation[factors] = probability;
826
827 insertTransitions.emplace_back(state, newAnnotation);
828 }
829 continue;
830 }
831 targetSetStates.emplace(targetStates);
832
833 Annotation newAnnotation(parameter, polynomialCache);
834
835 RationalFunctionCoefficient constantPart = utility::zero<RationalFunctionCoefficient>();
836 for (auto const& [state, transition] : transitions) {
837 constantPart += transition;
838 }
839 newAnnotation[factors] = constantPart;
840
841 STORM_LOG_INFO("Time travellable transitions with " << newAnnotation);
842
843 // Create the new state that our parametric transitions will start in
844 uint64_t newRow = flexibleMatrix.insertNewRowsAtEnd(1);
845 [[maybe_unused]] uint64_t newRowBackwards = backwardsFlexibleMatrix.insertNewRowsAtEnd(1);
846 STORM_LOG_ASSERT(newRow == newRowBackwards, "Internal error: Drifting matrix and backwardsTransitions.");
847
848 // Sum of parametric transitions goes to new row
849 insertTransitions.emplace_back(newRow, newAnnotation);
850
851 // Write outgoing transitions from new row directly into the flexible matrix
852 for (auto const& [state, thisProb] : transitions) {
853 const RationalFunction probAsFunction = RationalFunction(thisProb) / constantPart;
854 // Forward
855 flexibleMatrix.getRow(newRow).push_back(storage::MatrixEntry<uint_fast64_t, RationalFunction>(state, probAsFunction));
856 // Backward
857 backwardsFlexibleMatrix.getRow(state).push_back(storage::MatrixEntry<uint_fast64_t, RationalFunction>(newRow, probAsFunction));
858 // Update tree-states here
859 for (auto& entry : treeStatesNeedUpdate) {
860 entry.second.emplace(state);
861 }
862 STORM_LOG_INFO("With: " << probAsFunction << " to " << state);
863 // Join duplicate transitions backwards (need to do this for all rows we come from)
864 backwardsFlexibleMatrix.getRow(state) = joinDuplicateTransitions(backwardsFlexibleMatrix.getRow(state));
865 }
866 // Join duplicate transitions forwards (only need to do this for row we go to)
867 flexibleMatrix.getRow(newRow) = joinDuplicateTransitions(flexibleMatrix.getRow(newRow));
868 } else {
869 auto const [state, probability] = *transitions.begin();
870
871 Annotation newAnnotation(parameter, polynomialCache);
872 newAnnotation[factors] = probability;
873
874 insertTransitions.emplace_back(state, newAnnotation);
875 }
876 }
877
878 // Add everything to alreadyTimeTravelledToThis
879 for (auto const& targetSet : targetSetStates) {
880 alreadyTimeTravelledToThis[parameter].emplace(targetSet);
881 }
882
883 return insertTransitions;
884}
885
886std::map<UniPoly, Annotation> BigStep::replaceWithNewTransitions(uint64_t state, const std::vector<std::pair<uint64_t, Annotation>> transitions,
887 storage::FlexibleSparseMatrix<RationalFunction>& flexibleMatrix,
888 storage::FlexibleSparseMatrix<RationalFunction>& backwardsFlexibleMatrix,
889 storage::BitVector& reachableStates,
890 std::map<RationalFunctionVariable, std::set<uint64_t>>& treeStatesNeedUpdate) {
891 std::map<UniPoly, Annotation> storedAnnotations;
892
893 // STORM_LOG_ASSERT(flexibleMatrix.createSparseMatrix().transpose() == backwardsFlexibleMatrix.createSparseMatrix(), "");
894 // Delete old transitions - backwards
895 for (auto const& deletingTransition : flexibleMatrix.getRow(state)) {
896 auto& row = backwardsFlexibleMatrix.getRow(deletingTransition.getColumn());
897 auto it = row.begin();
898 while (it != row.end()) {
899 if (it->getColumn() == state) {
900 it = row.erase(it);
901 } else {
902 it++;
903 }
904 }
905 }
906 // Delete old transitions - forwards
907 flexibleMatrix.getRow(state) = std::vector<storage::MatrixEntry<uint_fast64_t, RationalFunction>>();
908 // STORM_LOG_ASSERT(flexibleMatrix.createSparseMatrix().transpose() == backwardsFlexibleMatrix.createSparseMatrix().transpose().transpose(), "");
909
910 // Insert new transitions
911 std::map<uint64_t, Annotation> insertThese;
912 for (auto const& [target, probability] : transitions) {
913 for (auto& entry : treeStatesNeedUpdate) {
914 entry.second.emplace(target);
915 }
916 if (insertThese.count(target)) {
917 insertThese.at(target) += probability;
918 } else {
919 insertThese.emplace(target, probability);
920 }
921 }
922 for (auto const& [state2, annotation] : insertThese) {
923 auto uniProbability = annotation.getProbability();
924 storedAnnotations.emplace(uniProbability, std::move(annotation));
925 auto probability = uniPolyToRationalFunction(uniProbability);
926
927 // We know that neither no transition state <-> entry.first exist because we've erased them
928 flexibleMatrix.getRow(state).push_back(storm::storage::MatrixEntry<uint_fast64_t, RationalFunction>(state2, probability));
929 backwardsFlexibleMatrix.getRow(state2).push_back(storm::storage::MatrixEntry<uint_fast64_t, RationalFunction>(state, probability));
930 }
931 // STORM_LOG_ASSERT(flexibleMatrix.createSparseMatrix().transpose() == backwardsFlexibleMatrix.createSparseMatrix(), "");
932 return storedAnnotations;
933}
934
935void BigStep::updateUnreachableStates(storage::BitVector& reachableStates, std::vector<uint64_t> const& statesMaybeUnreachable,
936 storage::FlexibleSparseMatrix<RationalFunction> const& backwardsFlexibleMatrix, uint64_t initialState) {
937 if (backwardsFlexibleMatrix.getRowCount() > reachableStates.size()) {
938 reachableStates.resize(backwardsFlexibleMatrix.getRowCount(), true);
939 }
940 // Look if one of our visitedStates has become unreachable
941 // i.e. all of its predecessors are unreachable
942 for (auto const& visitedState : statesMaybeUnreachable) {
943 if (visitedState == initialState) {
944 continue;
945 }
946 bool isUnreachable = true;
947 for (auto const& entry : backwardsFlexibleMatrix.getRow(visitedState)) {
948 if (reachableStates.get(entry.getColumn())) {
949 isUnreachable = false;
950 break;
951 }
952 }
953 if (isUnreachable) {
954 reachableStates.set(visitedState, false);
955 }
956 }
957}
958
959std::vector<storm::storage::MatrixEntry<uint64_t, RationalFunction>> BigStep::joinDuplicateTransitions(
960 std::vector<storm::storage::MatrixEntry<uint64_t, RationalFunction>> const& entries) {
961 std::vector<uint64_t> keyOrder;
962 std::map<uint64_t, storm::storage::MatrixEntry<uint64_t, RationalFunction>> existingEntries;
963 for (auto const& entry : entries) {
964 if (existingEntries.count(entry.getColumn())) {
965 existingEntries.at(entry.getColumn()).setValue(existingEntries.at(entry.getColumn()).getValue() + entry.getValue());
966 } else {
967 existingEntries[entry.getColumn()] = entry;
968 keyOrder.push_back(entry.getColumn());
969 }
970 }
971 std::vector<storm::storage::MatrixEntry<uint64_t, RationalFunction>> newEntries;
972 for (uint64_t key : keyOrder) {
973 newEntries.push_back(existingEntries.at(key));
974 }
975 return newEntries;
976}
977
978models::sparse::StateLabeling BigStep::extendStateLabeling(models::sparse::StateLabeling const& oldLabeling, uint64_t oldSize, uint64_t newSize,
979 uint64_t stateWithLabels, const std::set<std::string>& labelsInFormula) {
980 models::sparse::StateLabeling newLabels(newSize);
981 for (auto const& label : oldLabeling.getLabels()) {
982 newLabels.addLabel(label);
983 }
984 for (uint64_t state = 0; state < oldSize; state++) {
985 for (auto const& label : oldLabeling.getLabelsOfState(state)) {
986 newLabels.addLabelToState(label, state);
987 }
988 }
989 for (uint64_t i = oldSize; i < newSize; i++) {
990 // We assume that everything that we time-travel has the same labels for now.
991 for (auto const& label : oldLabeling.getLabelsOfState(stateWithLabels)) {
992 if (labelsInFormula.count(label)) {
993 newLabels.addLabelToState(label, i);
994 }
995 }
996 }
997 return newLabels;
998}
999
1000void BigStep::updateTreeStates(std::map<RationalFunctionVariable, std::map<uint64_t, std::set<uint64_t>>>& treeStates,
1001 std::map<RationalFunctionVariable, std::set<uint64_t>>& workingSets,
1002 const storage::FlexibleSparseMatrix<RationalFunction>& flexibleMatrix,
1003 const storage::FlexibleSparseMatrix<RationalFunction>& backwardsTransitions,
1004 const std::set<RationalFunctionVariable>& allParameters, const boost::optional<std::vector<RationalFunction>>& stateRewardVector,
1005 const models::sparse::StateLabeling stateLabeling) {
1006 for (auto const& parameter : allParameters) {
1007 std::set<uint64_t>& workingSet = workingSets[parameter];
1008 while (!workingSet.empty()) {
1009 std::set<uint64_t> newWorkingSet;
1010 for (uint64_t row : workingSet) {
1011 if (stateRewardVector && !stateRewardVector->at(row).isZero()) {
1012 continue;
1013 }
1014 for (auto const& entry : backwardsTransitions.getRow(row)) {
1015 if (entry.getValue().isConstant()) {
1016 // If the set of tree states at the current position is a subset of the set of
1017 // tree states of the parent state, we've reached some loop. Then we can stop.
1018 bool isSubset = true;
1019 for (auto const& state : treeStates.at(parameter)[row]) {
1020 if (!treeStates.at(parameter)[entry.getColumn()].count(state)) {
1021 isSubset = false;
1022 break;
1023 }
1024 }
1025 if (isSubset) {
1026 continue;
1027 }
1028 for (auto const& state : treeStates.at(parameter).at(row)) {
1029 treeStates.at(parameter).at(entry.getColumn()).emplace(state);
1030 }
1031 if (stateLabeling.getLabelsOfState(entry.getColumn()) == stateLabeling.getLabelsOfState(row)) {
1032 newWorkingSet.emplace(entry.getColumn());
1033 }
1034 }
1035 }
1036 }
1037 workingSet = newWorkingSet;
1038 }
1039 }
1040}
1041
1042} // namespace transformer
1043} // namespace storm
bool isRewardModelSet() const
Retrieves whether a reward model was set.
Definition CheckTask.h:191
std::string const & getRewardModel() const
Retrieves the reward model over which to perform the checking (if set).
Definition CheckTask.h:198
FormulaType const & getFormula() const
Retrieves the formula from this task.
Definition CheckTask.h:141
virtual void writeDotToStream(std::ostream &outStream, size_t maxWidthLabel=30, bool includeLabeling=true, storm::storage::BitVector const *subsystem=nullptr, std::vector< ValueType > const *firstValue=nullptr, std::vector< ValueType > const *secondValue=nullptr, std::vector< uint_fast64_t > const *stateColoring=nullptr, std::vector< std::string > const *colors=nullptr, std::vector< uint_fast64_t > *scheduler=nullptr, bool finalizeOutput=true) const override
This class represents a discrete-time Markov chain.
Definition Dtmc.h:13
virtual void reduceToStateBasedRewards() override
Converts the transition rewards of all reward models to state-based rewards.
Definition Dtmc.cpp:41
void removeLabel(std::string const &label)
Removes a label from the labelings.
storm::storage::SparseMatrix< ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
Definition Model.cpp:198
void setInitialStates(storm::storage::BitVector const &states)
Overwrites the initial states of the model.
Definition Model.cpp:183
void addRewardModel(std::string const &rewardModelName, RewardModelType const &rewModel)
Adds a reward model to the model.
Definition Model.cpp:255
storm::models::sparse::StateLabeling const & getStateLabeling() const
Returns the state labeling associated with this model.
Definition Model.cpp:320
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
Definition Model.cpp:163
RewardModelType const & getRewardModel(std::string const &rewardModelName) const
Retrieves the reward model with the given name, if one exists.
Definition Model.cpp:219
virtual std::string const & getUniqueRewardModelName() const override
Retrieves the name of the unique reward model, if there exists exactly one.
Definition Model.cpp:293
storm::storage::BitVector const & getInitialStates() const
Retrieves the initial states of the model.
Definition Model.cpp:178
This class manages the labeling of the state space with a number of (atomic) labels.
StateLabeling getSubLabeling(storm::storage::BitVector const &states) const
Retrieves the sub labeling that represents the same labeling as the current one for all selected stat...
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
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.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
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.
The flexible sparse matrix is used during state elimination.
row_type & getRow(index_type)
Returns an object representing the given row.
A class that holds a possibly non-square matrix in the compressed row storage format.
bool isProbabilistic(ValueType const &tolerance, storm::OptionalRef< std::string > reason={}) const
Checks for each row whether (i) each entry is between zero and one and (ii) all entries sum to one.
SparseMatrix getSubmatrix(bool useGroups, storm::storage::BitVector const &rowConstraint, storm::storage::BitVector const &columnConstraint, bool insertDiagonalEntries=false, storm::storage::BitVector const &makeZeroColumns=storm::storage::BitVector()) const
Creates a submatrix of the current matrix by dropping all rows and columns whose bits are not set to ...
storm::storage::SparseMatrix< value_type > transpose(bool joinGroups=false, bool keepZeros=false) const
Transposes the matrix.
index_type getRowCount() const
Returns the number of rows of the matrix.
UniPoly getProbability() const
Get the probability of this annotation as a univariate polynomial (which isn't factorized).
Definition BigStep.cpp:167
void addAnnotationTimesPolynomial(Annotation const &other, UniPoly &&polynomial)
Adds another annotation times a polynomial to this annotation.
Definition BigStep.cpp:124
void addAnnotationTimesConstant(Annotation const &other, RationalFunctionCoefficient timesConstant)
Adds another annotation times a constant to this annotation.
Definition BigStep.cpp:115
std::vector< UniPoly > getTerms() const
Get all of the terms of the UniPoly.
Definition BigStep.cpp:175
void computeDerivative(uint64_t nth)
Definition BigStep.cpp:205
Annotation(RationalFunctionVariable parameter, std::shared_ptr< PolynomialCache > polynomialCache)
Definition BigStep.cpp:87
void operator*=(RationalFunctionCoefficient n)
Multiply this annotation with a rational number.
Definition BigStep.cpp:103
std::shared_ptr< Annotation > derivative()
Definition BigStep.cpp:257
Interval evaluateOnIntervalMidpointTheorem(Interval input, bool higherOrderBounds=false) const
Definition BigStep.cpp:183
void operator+=(const Annotation other)
Add another annotation to this annotation.
Definition BigStep.cpp:92
void addAnnotationTimesAnnotation(Annotation const &anno1, Annotation const &anno2)
Adds another annotation times an annotation to this annotation.
Definition BigStep.cpp:144
ConstantType evaluate(ConstantType input) const
Definition BigStep.h:127
RationalFunctionVariable getParameter() const
Definition BigStep.cpp:201
Annotation operator*(RationalFunctionCoefficient n) const
Multiply this annotation with a rational number to get a new annotation.
Definition BigStep.cpp:109
std::pair< models::sparse::Dtmc< RationalFunction >, std::map< UniPoly, Annotation > > bigStep(models::sparse::Dtmc< RationalFunction > const &model, modelchecker::CheckTask< logic::Formula, RationalFunction > const &checkTask)
Perform big-step on the given model and the given checkTask.
Definition BigStep.cpp:381
static std::unordered_map< RationalFunction, Annotation > lastSavedAnnotations
Definition BigStep.h:198
RationalFunction uniPolyToRationalFunction(UniPoly poly)
Definition BigStep.cpp:35
#define STORM_LOG_INFO(message)
Definition logging.h:27
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
#define STORM_LOG_ERROR_COND(cond, message)
Definition macros.h:50
void closeFile(std::ofstream &stream)
Close the given file after writing.
Definition file.h:47
void openFile(std::string const &filepath, std::ofstream &filestream, bool append=false, bool silent=false)
Open the given file for writing.
Definition file.h:18
std::set< storm::RationalFunctionVariable > getAllParameters(Model< storm::RationalFunction > const &model)
Get all parameters (probability, rewards, and rates) occurring in the model.
Definition Model.cpp:719
std::pair< storm::RationalNumber, storm::RationalNumber > count(std::vector< storm::storage::BitVector > const &origSets, std::vector< storm::storage::BitVector > const &intersects, std::vector< storm::storage::BitVector > const &intersectsInfo, storm::RationalNumber val, bool plus, uint64_t remdepth)
std::ostream & operator<<(std::ostream &os, const Annotation &annotation)
Definition BigStep.cpp:263
carl::UnivariatePolynomial< RationalFunctionCoefficient > UniPoly
Definition BigStep.cpp:33
std::pair< std::map< uint64_t, std::set< uint64_t > >, std::set< uint64_t > > findSubgraph(const storm::storage::FlexibleSparseMatrix< RationalFunction > &transitionMatrix, const uint64_t root, const std::map< RationalFunctionVariable, std::map< uint64_t, std::set< uint64_t > > > &treeStates, const boost::optional< std::vector< RationalFunction > > &stateRewardVector, const RationalFunctionVariable parameter)
Definition BigStep.cpp:293
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:1845
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:41
ValueType max(ValueType const &first, ValueType const &second)
ValueType min(ValueType const &first, ValueType const &second)
bool isZero(ValueType const &a)
Definition constants.cpp:42
ValueType abs(ValueType const &number)
ValueType zero()
Definition constants.cpp:24
ValueType one()
Definition constants.cpp:19
TargetType convertNumber(SourceType const &number)
carl::Interval< double > Interval
Interval type.
carl::Variable RationalFunctionVariable
carl::RationalFunction< Polynomial, true > RationalFunction
carl::MultivariatePolynomial< RationalFunctionCoefficient > RawPolynomial
uint64_t lookUpInCache(UniPoly const &f, RationalFunctionVariable const &p)
Look up the index of this polynomial in the cache.
Definition BigStep.cpp:55
UniPoly polynomialFromFactorization(std::vector< uint64_t > const &factorization, RationalFunctionVariable const &p) const
Computes a univariate polynomial from a factorization.
Definition BigStep.cpp:70
bool operator()(const UniPoly &lhs, const UniPoly &rhs) const
Definition BigStep.cpp:41