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