Storm 1.14.0.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Order.cpp
Go to the documentation of this file.
2
3#include <iostream>
4#include <queue>
5
7
8namespace storm {
9namespace analysis {
10Order::Order(storm::storage::BitVector const& topStates, storm::storage::BitVector const& bottomStates, uint_fast64_t numberOfStates,
11 storage::Decomposition<storage::StronglyConnectedComponent> decomposition, std::vector<uint_fast64_t> statesSorted) {
12 init(numberOfStates, decomposition);
13 this->numberOfAddedStates = 0;
14 this->onlyBottomTopOrder = true;
15 for (uint64_t i : topStates) {
16 this->doneStates.set(i);
17 this->bottom->statesAbove.set(i);
18 this->top->states.insert(i);
19 this->nodes[i] = top;
20 numberOfAddedStates++;
21 }
22 this->statesSorted = statesSorted;
23
24 for (uint64_t i : bottomStates) {
25 this->doneStates.set(i);
26 this->bottom->states.insert(i);
27 this->nodes[i] = bottom;
28 numberOfAddedStates++;
29 }
30 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates, "Number of added states exceeds total states.");
31 STORM_LOG_ASSERT(doneStates.getNumberOfSetBits() == (topStates.getNumberOfSetBits() + bottomStates.getNumberOfSetBits()), "Done states bits mismatch.");
32 if (numberOfAddedStates == numberOfStates) {
33 doneBuilding = doneStates.full();
34 }
35}
36
37Order::Order(uint_fast64_t topState, uint_fast64_t bottomState, uint_fast64_t numberOfStates,
38 storage::Decomposition<storage::StronglyConnectedComponent> decomposition, std::vector<uint_fast64_t> statesSorted) {
39 init(numberOfStates, decomposition);
40
41 this->onlyBottomTopOrder = true;
42 this->doneStates.set(topState);
43
44 this->bottom->statesAbove.set(topState);
45 this->top->states.insert(topState);
46 this->nodes[topState] = top;
47
48 this->doneStates.set(bottomState);
49
50 this->bottom->states.insert(bottomState);
51 this->nodes[bottomState] = bottom;
52 this->numberOfAddedStates = 2;
53 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates, "Number of added states exceeds total states.");
54
55 this->statesSorted = statesSorted;
56 STORM_LOG_ASSERT(doneStates.getNumberOfSetBits() == 2, "Done states bits should be 2.");
57 if (numberOfAddedStates == numberOfStates) {
58 doneBuilding = doneStates.full();
59 }
60}
61
63 this->invalid = false;
64}
65
66/*** Modifying the order ***/
67
68void Order::add(uint_fast64_t state) {
69 STORM_LOG_ASSERT(nodes[state] == nullptr, "State already has a node.");
70 addBetween(state, top, bottom);
71 addStateToHandle(state);
72}
73
74void Order::addAbove(uint_fast64_t state, Node* node) {
75 STORM_LOG_INFO("Add " << state << " above " << *node->states.begin() << '\n');
76
77 STORM_LOG_ASSERT(nodes[state] == nullptr, "State already has a node.");
78 Node* newNode = new Node();
79 nodes[state] = newNode;
80
81 newNode->states.insert(state);
82 newNode->statesAbove = storm::storage::BitVector(numberOfStates, false);
83 for (auto const& state : top->states) {
84 newNode->statesAbove.set(state);
85 }
86 node->statesAbove.set(state);
87 numberOfAddedStates++;
88 onlyBottomTopOrder = false;
89 if (numberOfAddedStates == numberOfStates) {
90 doneBuilding = doneStates.full();
91 }
92}
93
94void Order::addBelow(uint_fast64_t state, Node* node) {
95 STORM_LOG_INFO("Add " << state << " below " << *node->states.begin() << '\n');
96
97 STORM_LOG_ASSERT(nodes[state] == nullptr, "State already has a node.");
98 Node* newNode = new Node();
99 nodes[state] = newNode;
100 newNode->states.insert(state);
102 for (auto statesAbove : node->states) {
103 newNode->statesAbove.set(statesAbove);
104 }
105 bottom->statesAbove.set(state);
106 numberOfAddedStates++;
107 onlyBottomTopOrder = false;
108 if (numberOfAddedStates == numberOfStates) {
109 doneBuilding = doneStates.full();
110 }
111 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates, "Number of added states exceeds total states.");
112}
113
114void Order::addBetween(uint_fast64_t state, Node* above, Node* below) {
115 STORM_LOG_INFO("Add " << state << " between (above) " << *above->states.begin() << " and " << *below->states.begin() << '\n');
116
117 STORM_LOG_ASSERT(compare(above, below) == ABOVE, "Comparison result is not ABOVE");
118 STORM_LOG_ASSERT(above != nullptr && below != nullptr, "Above or below is null.");
119 if (nodes[state] == nullptr) {
120 // State is not in the order yet
121 Node* newNode = new Node();
122 nodes[state] = newNode;
123
124 newNode->states.insert(state);
125 newNode->statesAbove = storm::storage::BitVector(above->statesAbove);
126 for (auto aboveStates : above->states) {
127 newNode->statesAbove.set(aboveStates);
128 }
129 below->statesAbove.set(state);
130 numberOfAddedStates++;
131 onlyBottomTopOrder = false;
132 if (numberOfAddedStates == numberOfStates) {
133 doneBuilding = doneStates.full();
134 }
135 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates, "Number of added states exceeds total states.");
136 } else {
137 // State is in the order already, so we add the new relations
138 addRelationNodes(above, nodes[state]);
139 addRelationNodes(nodes[state], below);
140 }
141}
142
143void Order::addBetween(uint_fast64_t state, uint_fast64_t above, uint_fast64_t below) {
144 STORM_LOG_ASSERT(compare(above, below) == ABOVE, "Comparison result is not ABOVE");
145 STORM_LOG_ASSERT(getNode(below)->states.find(below) != getNode(below)->states.end(), "Below state not found in its node.");
146 STORM_LOG_ASSERT(getNode(above)->states.find(above) != getNode(above)->states.end(), "Above state not found in its node.");
147
148 addBetween(state, getNode(above), getNode(below));
149}
150
151void Order::addRelation(uint_fast64_t above, uint_fast64_t below, bool allowMerge) {
152 STORM_LOG_ASSERT(getNode(above) != nullptr && getNode(below) != nullptr, "Above or below node is null.");
153 addRelationNodes(getNode(above), getNode(below), allowMerge);
154}
155
156void Order::addRelationNodes(Order::Node* above, Order::Node* below, bool allowMerge) {
157 STORM_LOG_ASSERT(allowMerge || compare(above, below) != BELOW, "Merge not allowed and comparison is BELOW");
158
159 STORM_LOG_INFO("Add relation between (above) " << *above->states.begin() << " and " << *below->states.begin() << '\n');
160
161 if (allowMerge) {
162 if (compare(below, above) == ABOVE) {
163 mergeNodes(above, below);
164 return;
165 }
166 }
167 below->statesAbove |= ((above->statesAbove));
168 for (auto const& state : above->states) {
169 below->statesAbove.set(state);
170 }
171 STORM_LOG_ASSERT(compare(above, below) == ABOVE, "Comparison result is not ABOVE");
172}
173
174void Order::addToNode(uint_fast64_t state, Node* node) {
175 STORM_LOG_INFO("Add " << state << " to between (above) " << *node->states.begin() << '\n');
176
177 if (nodes[state] == nullptr) {
178 // State is not in the order yet
179 node->states.insert(state);
180 nodes[state] = node;
181 numberOfAddedStates++;
182 if (numberOfAddedStates == numberOfStates) {
183 doneBuilding = doneStates.full();
184 }
185 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates, "Number of added states exceeds total states.");
186
187 } else {
188 // State is in the order already, so we merge the nodes
189 mergeNodes(nodes[state], node);
190 }
191}
192
194 STORM_LOG_INFO("Merge " << *node1->states.begin() << " and " << *node2->states.begin() << '\n');
195
196 // Merges node2 into node 1
197 // everything above n2 also above n1
198 node1->statesAbove |= ((node2->statesAbove));
199 // add states of node 2 to node 1
200 node1->states.insert(node2->states.begin(), node2->states.end());
201
202 for (auto const& i : node2->states) {
203 nodes[i] = node1;
204 }
205
206 for (auto const& node : nodes) {
207 if (node != nullptr) {
208 for (auto state2 : node2->states) {
209 if (node->statesAbove[state2]) {
210 for (auto state1 : node1->states) {
211 node->statesAbove.set(state1);
212 }
213 break;
214 }
215 }
216 }
217 }
218 for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
219 for (uint_fast64_t j = i + 1; j < numberOfStates; ++j) {
220 auto comp1 = compare(i, j);
221 auto comp2 = compare(j, i);
222 if (!((comp1 == BELOW && comp2 == ABOVE) || (comp1 == ABOVE && comp2 == BELOW) || (comp1 == UNKNOWN && comp2 == UNKNOWN) ||
223 (comp1 == SAME && comp2 == SAME))) {
224 invalid = true;
225 return false;
226 }
227 }
228 }
229 return !invalid;
230}
231
232bool Order::merge(uint_fast64_t var1, uint_fast64_t var2) {
233 return mergeNodes(getNode(var1), getNode(var2));
234}
235
236/*** Checking on the order ***/
237
238Order::NodeComparison Order::compare(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis) {
239 return compare(getNode(state1), getNode(state2), hypothesis);
240}
241
242Order::NodeComparison Order::compareFast(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis) const {
243 auto res = compareFast(getNode(state1), getNode(state2), hypothesis);
244 return res;
245}
246
248 if (node1 != nullptr && node2 != nullptr) {
249 if (node1 == node2) {
250 return SAME;
251 }
252
253 if ((hypothesis == UNKNOWN || hypothesis == ABOVE) && ((node1 == top || node2 == bottom) || aboveFast(node1, node2))) {
254 return ABOVE;
255 }
256
257 if ((hypothesis == UNKNOWN || hypothesis == BELOW) && ((node2 == top || node1 == bottom) || aboveFast(node2, node1))) {
258 return BELOW;
259 }
260 } else if (node1 == top || node2 == bottom) {
261 return ABOVE;
262 } else if (node2 == top || node1 == bottom) {
263 return BELOW;
264 }
265 return UNKNOWN;
266}
267
269 if (node1 != nullptr && node2 != nullptr) {
270 auto comp = compareFast(node1, node2, hypothesis);
271 if (comp != UNKNOWN) {
272 return comp;
273 }
274 if ((hypothesis == UNKNOWN || hypothesis == ABOVE) && above(node1, node2)) {
275 STORM_LOG_ASSERT(!above(node2, node1), "Above relation is not strict");
276 return ABOVE;
277 }
278
279 if ((hypothesis == UNKNOWN || hypothesis == BELOW) && above(node2, node1)) {
280 return BELOW;
281 }
282 } else if (node1 == top || node2 == bottom) {
283 return ABOVE;
284 } else if (node2 == top || node1 == bottom) {
285 return BELOW;
286 }
287 return UNKNOWN;
288}
289
290bool Order::contains(uint_fast64_t state) const {
291 return state < numberOfStates && nodes[state] != nullptr;
292}
293
295 return bottom;
296}
297
299 STORM_LOG_ASSERT(!doneStates.full() || numberOfAddedStates == numberOfStates, "Done states full but not all states added.");
300 return doneStates.full();
301}
302
303uint_fast64_t Order::getNextDoneState(uint_fast64_t state) const {
304 return doneStates.getNextSetIndex(state + 1);
305}
306
307Order::Node* Order::getNode(uint_fast64_t stateNumber) const {
308 STORM_LOG_ASSERT(stateNumber < numberOfStates, "State number exceeds total states.");
309 return nodes[stateNumber];
310}
311
312std::vector<Order::Node*> Order::getNodes() const {
313 return nodes;
314}
315
316std::vector<uint_fast64_t>& Order::getStatesSorted() {
317 return statesSorted;
318}
319
321 return top;
322}
323
324uint_fast64_t Order::getNumberOfAddedStates() const {
325 return numberOfAddedStates;
326}
327
328uint_fast64_t Order::getNumberOfStates() const {
329 return numberOfStates;
330}
331
332bool Order::isBottomState(uint_fast64_t state) const {
333 auto states = bottom->states;
334 return states.find(state) != states.end();
335}
336
337bool Order::isTopState(uint_fast64_t state) const {
338 auto states = top->states;
339 return states.find(state) != states.end();
340}
341
343 return onlyBottomTopOrder;
344}
345
346std::vector<uint_fast64_t> Order::sortStates(std::vector<uint_fast64_t>* states) {
347 STORM_LOG_ASSERT(states != nullptr, "States pointer is null.");
348 uint_fast64_t numberOfStatesToSort = states->size();
349 std::vector<uint_fast64_t> result;
350 // Go over all states
351 for (auto state : *states) {
352 bool unknown = false;
353 if (result.size() == 0) {
354 result.push_back(state);
355 } else {
356 bool added = false;
357 for (auto itr = result.begin(); itr != result.end(); ++itr) {
358 auto compareRes = compare(state, (*itr));
359 if (compareRes == ABOVE || compareRes == SAME) {
360 // insert at current pointer (while keeping other values)
361 result.insert(itr, state);
362 added = true;
363 break;
364 } else if (compareRes == UNKNOWN) {
365 unknown = true;
366 break;
367 }
368 }
369 if (unknown) {
370 break;
371 }
372 if (!added) {
373 result.push_back(state);
374 }
375 }
376 }
377 while (result.size() < numberOfStatesToSort) {
378 result.push_back(numberOfStates);
379 }
380 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort, "Result size mismatch.");
381 return result;
382}
383
384std::pair<std::pair<uint_fast64_t, uint_fast64_t>, std::vector<uint_fast64_t>> Order::sortStatesForForward(uint_fast64_t currentState,
385 std::vector<uint_fast64_t> const& states) {
386 std::vector<uint_fast64_t> statesSorted;
387 statesSorted.push_back(currentState);
388 // Go over all states
389 bool oneUnknown = false;
390 bool unknown = false;
391 uint_fast64_t s1 = numberOfStates;
392 uint_fast64_t s2 = numberOfStates;
393 for (auto& state : states) {
394 unknown = false;
395 bool added = false;
396 for (auto itr = statesSorted.begin(); itr != statesSorted.end(); ++itr) {
397 auto compareRes = compare(state, (*itr));
398 if (compareRes == ABOVE || compareRes == SAME) {
399 if (!contains(state) && compareRes == ABOVE) {
400 add(state);
401 }
402 added = true;
403 // insert at current pointer (while keeping other values)
404 statesSorted.insert(itr, state);
405 break;
406 } else if (compareRes == UNKNOWN && !oneUnknown) {
407 // We miss state in the result.
408 s1 = state;
409 s2 = *itr;
410 oneUnknown = true;
411 added = true;
412 break;
413 } else if (compareRes == UNKNOWN && oneUnknown) {
414 unknown = true;
415 added = true;
416 break;
417 }
418 }
419 if (!added) {
420 // State will be last in the list
421 statesSorted.push_back(state);
422 }
423 if (unknown && oneUnknown) {
424 break;
425 }
426 }
427 if (!unknown && oneUnknown) {
428 STORM_LOG_ASSERT(statesSorted.size() == states.size(), "States sorted size mismatch.");
429 s2 = numberOfStates;
430 }
431 STORM_LOG_ASSERT(s1 == numberOfStates || (s1 != numberOfStates && s2 == numberOfStates && statesSorted.size() == states.size()) ||
432 (s1 != numberOfStates && s2 != numberOfStates && statesSorted.size() < states.size()),
433 "States are not sorted.");
434
435 return {{s1, s2}, statesSorted};
436}
437
438std::pair<std::pair<uint_fast64_t, uint_fast64_t>, std::vector<uint_fast64_t>> Order::sortStatesUnorderedPair(const std::vector<uint_fast64_t>* states) {
439 STORM_LOG_ASSERT(states != nullptr, "States pointer is null.");
440 [[maybe_unused]] uint_fast64_t numberOfStatesToSort = states->size();
441 std::vector<uint_fast64_t> result;
442 // Go over all states
443 for (auto state : *states) {
444 bool unknown = false;
445 if (result.size() == 0) {
446 result.push_back(state);
447 } else {
448 bool added = false;
449 for (auto itr = result.begin(); itr != result.end(); ++itr) {
450 auto compareRes = compare(state, (*itr));
451 if (compareRes == ABOVE || compareRes == SAME) {
452 // insert at current pointer (while keeping other values)
453 result.insert(itr, state);
454 added = true;
455 break;
456 } else if (compareRes == UNKNOWN) {
457 return {{(*itr), state}, std::move(result)};
458 }
459 }
460 if (unknown) {
461 break;
462 }
463 if (!added) {
464 result.push_back(state);
465 }
466 }
467 }
468
469 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort, "Result size mismatch.");
470 return {{numberOfStates, numberOfStates}, std::move(result)};
471}
472
473std::vector<uint_fast64_t> Order::sortStates(storm::storage::BitVector* states) {
474 uint_fast64_t numberOfStatesToSort = states->getNumberOfSetBits();
475 std::vector<uint_fast64_t> result;
476 // Go over all states
477 for (uint64_t state : *states) {
478 bool unknown = false;
479 if (result.size() == 0) {
480 result.push_back(state);
481 } else {
482 bool added = false;
483 for (auto itr = result.begin(); itr != result.end(); ++itr) {
484 auto compareRes = compare(state, (*itr));
485 if (compareRes == ABOVE || compareRes == SAME) {
486 // insert at current pointer (while keeping other values)
487 result.insert(itr, state);
488 added = true;
489 break;
490 } else if (compareRes == UNKNOWN) {
491 unknown = true;
492 break;
493 }
494 }
495 if (unknown) {
496 break;
497 }
498 if (!added) {
499 result.push_back(state);
500 }
501 }
502 }
503 while (result.size() < numberOfStatesToSort) {
504 result.push_back(numberOfStates);
505 }
506 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort, "Result size mismatch.");
507 return result;
508}
509
510/*** Checking on helpfunctionality for building of order ***/
511
512std::shared_ptr<Order> Order::copy() const {
513 STORM_LOG_ASSERT(!isInvalid(), "Order is invalid.");
514 std::shared_ptr<Order> copiedOrder = std::make_shared<Order>();
515 copiedOrder->nodes = std::vector<Node*>(numberOfStates, nullptr);
516 copiedOrder->onlyBottomTopOrder = this->isOnlyBottomTopOrder();
517 copiedOrder->numberOfStates = this->getNumberOfStates();
518 copiedOrder->statesSorted = std::vector<uint_fast64_t>(this->statesSorted);
519 copiedOrder->statesToHandle = std::vector<uint_fast64_t>(this->statesToHandle);
520 copiedOrder->trivialStates = storm::storage::BitVector(trivialStates);
521 copiedOrder->doneStates = storm::storage::BitVector(doneStates);
522 copiedOrder->numberOfAddedStates = this->numberOfAddedStates;
523 copiedOrder->doneBuilding = this->doneBuilding;
524
525 auto seenStates = storm::storage::BitVector(numberOfStates, false);
526 // copy nodes
527 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
528 Node* oldNode = nodes.at(state);
529 if (oldNode != nullptr) {
530 if (!seenStates[*(oldNode->states.begin())]) {
531 Node* newNode = new Node();
532 if (oldNode == this->getTop()) {
533 copiedOrder->top = newNode;
534 } else if (oldNode == this->getBottom()) {
535 copiedOrder->bottom = newNode;
536 }
538 for (size_t i = 0; i < oldNode->statesAbove.size(); ++i) {
539 STORM_LOG_ASSERT(newNode->statesAbove[i] == oldNode->statesAbove[i], "StatesAbove mismatch during copy.");
540 }
541 for (auto const& i : oldNode->states) {
542 STORM_LOG_ASSERT(!seenStates[i], "State already seen during copy.");
543 newNode->states.insert(i);
544 seenStates.set(i);
545 copiedOrder->nodes[i] = newNode;
546 }
547 }
548 } else {
549 STORM_LOG_ASSERT(copiedOrder->nodes[state] == nullptr, "Copied order node already exists.");
550 }
551 }
552
553 return copiedOrder;
554}
555
556/*** Setters ***/
557void Order::setDoneState(uint_fast64_t stateNumber) {
558 doneStates.set(stateNumber);
559}
560
561/*** Output ***/
562
563void Order::toDotOutput() const {
564 // This emits a Graphviz DOT document to stdout for external consumption, not a log message.
565 // Graphviz Output start
566 std::cout << "Dot Output:\n"
567 << "digraph model {\n";
568
569 // Vertices of the digraph
570 storm::storage::BitVector stateCoverage = storm::storage::BitVector(doneStates);
571 for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
572 if (nodes[i] != nullptr) {
573 stateCoverage.set(i);
574 }
575 }
576 for (uint_fast64_t i = stateCoverage.getNextSetIndex(0); i != numberOfStates; i = stateCoverage.getNextSetIndex(i + 1)) {
577 for (uint_fast64_t j = i + 1; j < numberOfStates; j++) {
578 if (getNode(j) == getNode(i)) {
579 stateCoverage.set(j, false);
580 }
581 }
582 std::cout << "\t" << nodeName(*getNode(i)) << " [ label = \"" << nodeLabel(*getNode(i)) << "\" ];\n";
583 }
584
585 // Edges of the digraph
586 for (uint_fast64_t i = stateCoverage.getNextSetIndex(0); i != numberOfStates; i = stateCoverage.getNextSetIndex(i + 1)) {
587 storm::storage::BitVector v = storm::storage::BitVector(numberOfStates, false);
588 Node* currentNode = getNode(i);
589 for (uint_fast64_t s1 : getNode(i)->statesAbove) {
590 v |= (currentNode->statesAbove & getNode(s1)->statesAbove);
591 }
592
593 std::set<Node*> seenNodes;
594 for (uint_fast64_t state : currentNode->statesAbove) {
595 Node* n = getNode(state);
596 if (std::find(seenNodes.begin(), seenNodes.end(), n) == seenNodes.end()) {
597 seenNodes.insert(n);
598 if (!v[state]) {
599 std::cout << "\t" << nodeName(*currentNode) << " -> " << nodeName(*getNode(state)) << ";\n";
600 }
601 }
602 }
603 }
604 // Graphviz Output end
605 std::cout << "}\n";
606}
607
608void Order::dotOutputToFile(std::ofstream& dotOutfile) const {
609 // Graphviz Output start
610 dotOutfile << "Dot Output:\n"
611 << "digraph model {\n";
612
613 // Vertices of the digraph
614 storm::storage::BitVector stateCoverage = storm::storage::BitVector(numberOfStates, true);
615 for (uint_fast64_t i = stateCoverage.getNextSetIndex(0); i != numberOfStates; i = stateCoverage.getNextSetIndex(i + 1)) {
616 if (getNode(i) == nullptr) {
617 continue;
618 }
619 for (uint_fast64_t j = i + 1; j < numberOfStates; j++) {
620 if (getNode(j) == getNode(i)) {
621 stateCoverage.set(j, false);
622 }
623 }
624
625 dotOutfile << "\t" << nodeName(*getNode(i)) << " [ label = \"" << nodeLabel(*getNode(i)) << "\" ];\n";
626 }
627
628 // Edges of the digraph
629 for (uint_fast64_t i = stateCoverage.getNextSetIndex(0); i != numberOfStates; i = stateCoverage.getNextSetIndex(i + 1)) {
630 storm::storage::BitVector v = storm::storage::BitVector(numberOfStates, false);
631 Node* currentNode = getNode(i);
632 if (currentNode == nullptr) {
633 continue;
634 }
635
636 for (uint_fast64_t s1 : getNode(i)->statesAbove) {
637 v |= (currentNode->statesAbove & getNode(s1)->statesAbove);
638 }
639
640 std::set<Node*> seenNodes;
641 for (uint_fast64_t state : currentNode->statesAbove) {
642 Node* n = getNode(state);
643 if (std::find(seenNodes.begin(), seenNodes.end(), n) == seenNodes.end()) {
644 seenNodes.insert(n);
645 if (!v[state]) {
646 dotOutfile << "\t" << nodeName(*currentNode) << " -> " << nodeName(*getNode(state)) << ";\n";
647 }
648 }
649 }
650 }
651
652 // Graphviz Output end
653 dotOutfile << "}\n";
654}
655
656/*** Private methods ***/
657
658void Order::init(uint_fast64_t numberOfStates, storage::Decomposition<storage::StronglyConnectedComponent> decomposition, bool doneBuilding) {
659 this->numberOfStates = numberOfStates;
660 this->invalid = false;
661 this->nodes = std::vector<Node*>(numberOfStates, nullptr);
662 this->doneStates = storm::storage::BitVector(numberOfStates, false);
663 STORM_LOG_ASSERT(doneStates.getNumberOfSetBits() == 0, "Done states should be empty initially.");
664 if (decomposition.size() == 0) {
665 this->trivialStates = storm::storage::BitVector(numberOfStates, true);
666 } else {
667 this->trivialStates = storm::storage::BitVector(numberOfStates, false);
668 for (auto& scc : decomposition) {
669 if (scc.size() == 1) {
670 trivialStates.set(*(scc.begin()));
671 }
672 }
673 }
674 this->top = new Node();
675 this->bottom = new Node();
676 this->top->statesAbove = storm::storage::BitVector(numberOfStates, false);
677 this->bottom->statesAbove = storm::storage::BitVector(numberOfStates, false);
678 this->doneBuilding = doneBuilding;
679}
680
681bool Order::aboveFast(Node* node1, Node* node2) const {
682 bool found = false;
683 for (auto const& state : node1->states) {
684 found = ((node2->statesAbove))[state];
685 if (found) {
686 break;
687 }
688 }
689 return found;
690}
691
692bool Order::above(Node* node1, Node* node2) {
693 STORM_LOG_ASSERT(!aboveFast(node1, node2), "AboveFast already true");
694 // Check whether node1 is above node2 by going over all states that are above state 2
695 bool above = false;
696 // Only do this when we have to deal with forward reasoning or we are not yet done with the building of the order
697 if (!trivialStates.full() || !doneBuilding) {
698 // First gather all states that are above node 2;
699
700 storm::storage::BitVector statesSeen((node2->statesAbove));
701 std::queue<uint_fast64_t> statesToHandle;
702 for (uint64_t state : statesSeen) {
703 statesToHandle.push(state);
704 }
705 while (!above && !statesToHandle.empty()) {
706 // Get first item from the queue
707 auto state = statesToHandle.front();
708 statesToHandle.pop();
709 auto node = getNode(state);
710 if (aboveFast(node1, node)) {
711 above = true;
712 continue;
713 }
714 for (uint64_t newState : node->statesAbove) {
715 if (!statesSeen[newState]) {
716 statesToHandle.push(newState);
717 statesSeen.set(newState);
718 }
719 }
720 }
721 }
722 if (above) {
723 for (auto state : node1->states) {
724 node2->statesAbove.set(state);
725 }
726 }
727 return above;
728}
729
730std::string Order::nodeName(Node n) const {
731 auto itr = n.states.begin();
732 std::string name = "n" + std::to_string(*itr);
733 return name;
734}
735
736std::string Order::nodeLabel(Node n) const {
737 if (n.states == top->states) {
738 return "=)";
739 }
740 if (n.states == bottom->states) {
741 return "=(";
742 }
743 auto itr = n.states.begin();
744 std::string label = "s" + std::to_string(*itr);
745 ++itr;
746 if (itr != n.states.end()) {
747 label = "[" + label + "]";
748 }
749 return label;
750}
751
753 return !doneStates.full();
754}
755
756bool Order::isTrivial(uint_fast64_t state) {
757 return trivialStates[state];
758}
759
760std::pair<uint_fast64_t, bool> Order::getNextStateNumber() {
761 while (!statesSorted.empty()) {
762 auto state = statesSorted.back();
763 statesSorted.pop_back();
764 if (!doneStates[state]) {
765 return {state, true};
766 }
767 }
768 return {numberOfStates, true};
769}
770
771std::pair<uint_fast64_t, bool> Order::getStateToHandle() {
772 STORM_LOG_ASSERT(existsStateToHandle(), "No state to handle.");
773 auto state = statesToHandle.back();
774 statesToHandle.pop_back();
775 return {state, false};
776}
777
779 while (!statesToHandle.empty() && doneStates[statesToHandle.back()]) {
780 statesToHandle.pop_back();
781 }
782 return !statesToHandle.empty();
783}
784
785void Order::addStateToHandle(uint_fast64_t state) {
786 if (!doneStates[state]) {
787 statesToHandle.push_back(state);
788 }
789}
790
791void Order::addStateSorted(uint_fast64_t state) {
792 statesSorted.push_back(state);
793}
794
795std::pair<bool, bool> Order::allAboveBelow(std::vector<uint_fast64_t> const states, uint_fast64_t state) {
796 auto allAbove = true;
797 auto allBelow = true;
798 for (auto& checkState : states) {
799 auto comp = compare(checkState, state);
800 allAbove &= (comp == ABOVE || comp == SAME);
801 allBelow &= (comp == BELOW || comp == SAME);
802 }
803 return {allAbove, allBelow};
804}
805
806uint_fast64_t Order::getNumberOfDoneStates() const {
807 return doneStates.getNumberOfSetBits();
808}
809
810bool Order::isInvalid() const {
811 return invalid;
812}
813} // namespace analysis
814} // namespace storm
uint_fast64_t getNumberOfDoneStates() const
Definition Order.cpp:806
void addAbove(uint_fast64_t state, Node *node)
Adds a node with the given state above the given node.
Definition Order.cpp:74
bool isTrivial(uint_fast64_t state)
Definition Order.cpp:756
void addStateSorted(uint_fast64_t state)
Definition Order.cpp:791
Node * getBottom() const
Retrieves the bottom node of the order.
Definition Order.cpp:294
bool contains(uint_fast64_t state) const
Check if state is already contained in order.
Definition Order.cpp:290
bool isInvalid() const
Definition Order.cpp:810
Order::NodeComparison compareFast(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis=UNKNOWN) const
Definition Order.cpp:242
Order::NodeComparison compare(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis=UNKNOWN)
Compares the level of the nodes of the states.
Definition Order.cpp:238
std::pair< uint_fast64_t, bool > getStateToHandle()
Definition Order.cpp:771
std::vector< uint_fast64_t > & getStatesSorted()
Definition Order.cpp:316
std::vector< uint_fast64_t > sortStates(std::vector< uint_fast64_t > *states)
Sorts the given states if possible.
Definition Order.cpp:346
NodeComparison
Constants for comparison of nodes/states.
Definition Order.h:18
Order()
Constructs a new Order.
Definition Order.cpp:62
void toDotOutput() const
Prints the dot output to stdout.
Definition Order.cpp:563
void dotOutputToFile(std::ofstream &dotOutfile) const
Writes dotoutput to the given file.
Definition Order.cpp:608
void addRelation(uint_fast64_t above, uint_fast64_t below, bool allowMerge=false)
Adds a new relation between two states to the order.
Definition Order.cpp:151
Node * getNode(uint_fast64_t state) const
Retrieves the pointer to a Node at which the state occurs.
Definition Order.cpp:307
bool merge(uint_fast64_t var1, uint_fast64_t var2)
Merges node of var2 into node of var1.
Definition Order.cpp:232
std::vector< Node * > getNodes() const
Returns the vector with the nodes of the order.
Definition Order.cpp:312
bool mergeNodes(Node *node1, Node *node2)
Merges node2 into node1.
Definition Order.cpp:193
std::pair< bool, bool > allAboveBelow(std::vector< uint_fast64_t > const states, uint_fast64_t state)
Definition Order.cpp:795
uint_fast64_t getNextDoneState(uint_fast64_t state) const
Returns the next done state of the order, returns the number of state if end of done states is reache...
Definition Order.cpp:303
bool getDoneBuilding() const
Returns true if done building the order.
Definition Order.cpp:298
void addToNode(uint_fast64_t state, Node *node)
Adds state to the states of the given node.
Definition Order.cpp:174
bool isTopState(uint_fast64_t) const
Checks if the given state is a top state.
Definition Order.cpp:337
std::pair< std::pair< uint_fast64_t, uint_fast64_t >, std::vector< uint_fast64_t > > sortStatesForForward(uint_fast64_t currentState, std::vector< uint_fast64_t > const &successors)
Sorts the given states if possible.
Definition Order.cpp:384
std::pair< std::pair< uint_fast64_t, uint_fast64_t >, std::vector< uint_fast64_t > > sortStatesUnorderedPair(const std::vector< uint_fast64_t > *states)
Sorts the given states if possible.
Definition Order.cpp:438
void addStateToHandle(uint_fast64_t state)
Definition Order.cpp:785
void addBetween(uint_fast64_t state, Node *node1, Node *node2)
Adds a node with the given state below node1 and above node2.
Definition Order.cpp:114
uint_fast64_t getNumberOfStates() const
Returns the number of possible states in the order.
Definition Order.cpp:328
void addBelow(uint_fast64_t state, Node *node)
Adds a node with the given state below the given node.
Definition Order.cpp:94
void setDoneState(uint_fast64_t sccNumber)
Definition Order.cpp:557
std::pair< uint_fast64_t, bool > getNextStateNumber()
Definition Order.cpp:760
std::shared_ptr< Order > copy() const
Creates a copy of the calling Order.
Definition Order.cpp:512
bool isOnlyBottomTopOrder() const
Returns if the order only consists of bottom and top states (so no in-between nodes).
Definition Order.cpp:342
uint_fast64_t getNumberOfAddedStates() const
Returns the number of added states.
Definition Order.cpp:324
bool isBottomState(uint_fast64_t) const
Checks if the given state is a bottom state.
Definition Order.cpp:332
Node * getTop() const
Retrieves the top node of the order.
Definition Order.cpp:320
void add(uint_fast64_t state)
Adds state between the top and bottom node of the order.
Definition Order.cpp:68
void addRelationNodes(storm::analysis::Order::Node *above, storm::analysis::Order::Node *below, bool allowMerge=false)
Adds a new relation between two nodes to the order.
Definition Order.cpp:156
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.
uint64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
This class represents the decomposition of a model into blocks which are of the template type.
std::size_t size() const
Retrieves the number of blocks of this decomposition.
#define STORM_LOG_INFO(message)
Definition logging.h:27
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:9
Nodes of the Reachability Order.
Definition Order.h:28
boost::container::flat_set< uint_fast64_t > states
Definition Order.h:29
storm::storage::BitVector statesAbove
Definition Order.h:30