12 init(numberOfStates, decomposition);
13 this->numberOfAddedStates = 0;
14 this->onlyBottomTopOrder =
true;
15 for (
auto i : topStates) {
16 this->doneStates.set(i);
17 this->bottom->statesAbove.set(i);
18 this->top->states.insert(i);
20 numberOfAddedStates++;
22 this->statesSorted = statesSorted;
24 for (
auto i : bottomStates) {
25 this->doneStates.set(i);
26 this->bottom->states.insert(i);
27 this->nodes[i] = bottom;
28 numberOfAddedStates++;
30 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates,
"More states were added to the order than it has room for.");
32 "Number of done states does not match the number of given top and bottom states.");
33 if (numberOfAddedStates == numberOfStates) {
34 doneBuilding = doneStates.full();
38Order::Order(uint_fast64_t topState, uint_fast64_t bottomState, uint_fast64_t numberOfStates,
40 init(numberOfStates, decomposition);
42 this->onlyBottomTopOrder =
true;
43 this->doneStates.set(topState);
45 this->bottom->statesAbove.set(topState);
46 this->top->states.insert(topState);
47 this->nodes[topState] = top;
49 this->doneStates.set(bottomState);
51 this->bottom->states.insert(bottomState);
52 this->nodes[bottomState] = bottom;
53 this->numberOfAddedStates = 2;
54 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates,
"More states were added to the order than it has room for.");
56 this->statesSorted = statesSorted;
57 STORM_LOG_ASSERT(doneStates.getNumberOfSetBits() == 2,
"Expected exactly the given top and bottom state to be done.");
58 if (numberOfAddedStates == numberOfStates) {
59 doneBuilding = doneStates.full();
63Order::Order() : invalid(false), doneBuilding(false), onlyBottomTopOrder(false), top(nullptr), bottom(nullptr), numberOfStates(0), numberOfAddedStates(0) {}
66 : invalid(other.invalid),
67 doneBuilding(other.doneBuilding),
68 onlyBottomTopOrder(other.onlyBottomTopOrder),
69 doneStates(other.doneStates),
70 trivialStates(other.trivialStates),
71 nodes(other.numberOfStates, nullptr),
72 statesToHandle(other.statesToHandle),
75 numberOfStates(other.numberOfStates),
76 numberOfAddedStates(other.numberOfAddedStates),
77 statesSorted(other.statesSorted) {
79 for (uint_fast64_t state = 0; state < numberOfStates; ++state) {
80 Node* oldNode = other.nodes.at(state);
81 if (oldNode !=
nullptr && !oldNode->
states.empty() && !seenStates[*oldNode->
states.begin()]) {
82 Node* newNode = allocateNode();
83 if (oldNode == other.top) {
85 }
else if (oldNode == other.bottom) {
89 for (
auto const& i : oldNode->
states) {
98 if (top ==
nullptr && other.top !=
nullptr) {
101 top->states = other.top->
states;
103 if (bottom ==
nullptr && other.bottom !=
nullptr) {
104 bottom = allocateNode();
106 bottom->states = other.bottom->
states;
117 swap(first.invalid, second.invalid);
118 swap(first.doneBuilding, second.doneBuilding);
119 swap(first.onlyBottomTopOrder, second.onlyBottomTopOrder);
120 swap(first.doneStates, second.doneStates);
121 swap(first.trivialStates, second.trivialStates);
122 swap(first.nodes, second.nodes);
123 swap(first.nodeStorage, second.nodeStorage);
124 swap(first.statesToHandle, second.statesToHandle);
125 swap(first.top, second.top);
126 swap(first.bottom, second.bottom);
127 swap(first.numberOfStates, second.numberOfStates);
128 swap(first.numberOfAddedStates, second.numberOfAddedStates);
129 swap(first.statesSorted, second.statesSorted);
133 nodeStorage.push_back(std::make_unique<Node>());
134 return nodeStorage.back().get();
140 STORM_LOG_ASSERT(nodes[state] ==
nullptr,
"State " << state <<
" is already in the order.");
148 STORM_LOG_ASSERT(nodes[state] ==
nullptr,
"State " << state <<
" is already in the order.");
149 Node* newNode = allocateNode();
150 nodes[state] = newNode;
152 newNode->
states.insert(state);
154 for (
auto const& state : top->states) {
158 numberOfAddedStates++;
159 onlyBottomTopOrder =
false;
160 if (numberOfAddedStates == numberOfStates) {
161 doneBuilding = doneStates.full();
168 STORM_LOG_ASSERT(nodes[state] ==
nullptr,
"State " << state <<
" is already in the order.");
169 Node* newNode = allocateNode();
170 nodes[state] = newNode;
171 newNode->
states.insert(state);
173 for (
auto statesAbove : node->
states) {
176 bottom->statesAbove.set(state);
177 numberOfAddedStates++;
178 onlyBottomTopOrder =
false;
179 if (numberOfAddedStates == numberOfStates) {
180 doneBuilding = doneStates.full();
182 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates,
"More states were added to the order than it has room for.");
186 STORM_LOG_INFO(
"Add " << state <<
" between (above) " << *above->states.begin() <<
" and " << *below->
states.begin() <<
'\n');
189 STORM_LOG_ASSERT(above !=
nullptr && below !=
nullptr,
"Both nodes must exist.");
190 if (nodes[state] ==
nullptr) {
192 Node* newNode = allocateNode();
193 nodes[state] = newNode;
195 newNode->
states.insert(state);
197 for (
auto aboveStates : above->states) {
201 numberOfAddedStates++;
202 onlyBottomTopOrder =
false;
203 if (numberOfAddedStates == numberOfStates) {
204 doneBuilding = doneStates.full();
206 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates,
"More states were added to the order than it has room for.");
229 STORM_LOG_INFO(
"Add relation between (above) " << *above->states.begin() <<
" and " << *below->
states.begin() <<
'\n');
238 for (
auto const& state : above->states) {
247 if (nodes[state] ==
nullptr) {
249 node->
states.insert(state);
251 numberOfAddedStates++;
252 if (numberOfAddedStates == numberOfStates) {
253 doneBuilding = doneStates.full();
255 STORM_LOG_ASSERT(numberOfAddedStates <= numberOfStates,
"More states were added to the order than it has room for.");
272 for (
auto const& i : node2->
states) {
276 for (
auto const& node : nodes) {
277 if (node !=
nullptr) {
278 for (
auto state2 : node2->
states) {
279 if (node->statesAbove[state2]) {
280 for (
auto state1 : node1->
states) {
281 node->statesAbove.set(state1);
288 for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
289 if (nodes[i] ==
nullptr) {
292 for (uint_fast64_t j = i + 1; j < numberOfStates; ++j) {
293 if (nodes[j] ==
nullptr) {
299 (comp1 ==
SAME && comp2 ==
SAME))) {
324 if (node1 !=
nullptr && node2 !=
nullptr) {
325 if (node1 == node2) {
329 if ((hypothesis ==
UNKNOWN || hypothesis ==
ABOVE) && ((node1 == top || node2 == bottom) || aboveFast(node1, node2))) {
333 if ((hypothesis ==
UNKNOWN || hypothesis ==
BELOW) && ((node2 == top || node1 == bottom) || aboveFast(node2, node1))) {
336 }
else if (node1 == top || node2 == bottom) {
338 }
else if (node2 == top || node1 == bottom) {
345 if (node1 !=
nullptr && node2 !=
nullptr) {
350 if ((hypothesis ==
UNKNOWN || hypothesis ==
ABOVE) && above(node1, node2)) {
357 if ((hypothesis ==
UNKNOWN || hypothesis ==
BELOW) && above(node2, node1)) {
360 }
else if (node1 == top || node2 == bottom) {
362 }
else if (node2 == top || node1 == bottom) {
369 return state < numberOfStates && nodes[state] !=
nullptr;
377 STORM_LOG_ASSERT(!doneStates.full() || numberOfAddedStates == numberOfStates,
378 "All states are marked done, but not all states have been added to the order.");
379 return doneStates.full();
383 return doneStates.getNextSetIndex(state + 1);
387 assert(stateNumber < numberOfStates);
388 return nodes[stateNumber];
404 return numberOfAddedStates;
408 return numberOfStates;
412 auto states = bottom->
states;
413 return states.find(state) != states.end();
417 auto states = top->states;
418 return states.find(state) != states.end();
422 return onlyBottomTopOrder;
427 uint_fast64_t numberOfStatesToSort = states->size();
428 std::vector<uint_fast64_t> result;
430 for (
auto state : *states) {
431 bool unknown =
false;
432 if (result.size() == 0) {
433 result.push_back(state);
436 for (
auto itr = result.begin(); itr != result.end(); ++itr) {
437 auto compareRes =
compare(state, (*itr));
438 if (compareRes ==
ABOVE || compareRes ==
SAME) {
440 result.insert(itr, state);
443 }
else if (compareRes ==
UNKNOWN) {
452 result.push_back(state);
456 while (result.size() < numberOfStatesToSort) {
457 result.push_back(numberOfStates);
459 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort,
"Not all states could be sorted (or padded with the sentinel value).");
464 std::vector<uint_fast64_t>
const& states) {
465 std::vector<uint_fast64_t> statesSorted;
466 statesSorted.push_back(currentState);
468 bool oneUnknown =
false;
469 bool unknown =
false;
470 uint_fast64_t s1 = numberOfStates;
471 uint_fast64_t s2 = numberOfStates;
472 for (
auto& state : states) {
475 for (
auto itr = statesSorted.begin(); itr != statesSorted.end(); ++itr) {
476 auto compareRes =
compare(state, (*itr));
477 if (compareRes ==
ABOVE || compareRes ==
SAME) {
483 statesSorted.insert(itr, state);
485 }
else if (compareRes ==
UNKNOWN && !oneUnknown) {
492 }
else if (compareRes ==
UNKNOWN && oneUnknown) {
500 statesSorted.push_back(state);
502 if (unknown && oneUnknown) {
506 if (!unknown && oneUnknown) {
507 STORM_LOG_ASSERT(statesSorted.size() == states.size(),
"Expected all but the single unresolved state to have been sorted.");
510 STORM_LOG_ASSERT(s1 == numberOfStates || (s1 != numberOfStates && s2 == numberOfStates && statesSorted.size() == states.size()) ||
511 (s1 != numberOfStates && s2 != numberOfStates && statesSorted.size() < states.size()),
512 "Inconsistent result: (s1, s2) and the number of sorted states must agree on how far sorting got.");
514 return {{s1, s2}, statesSorted};
519 [[maybe_unused]] uint_fast64_t numberOfStatesToSort = states->size();
520 std::vector<uint_fast64_t> result;
522 for (
auto state : *states) {
523 bool unknown =
false;
524 if (result.size() == 0) {
525 result.push_back(state);
528 for (
auto itr = result.begin(); itr != result.end(); ++itr) {
529 auto compareRes =
compare(state, (*itr));
530 if (compareRes ==
ABOVE || compareRes ==
SAME) {
532 result.insert(itr, state);
535 }
else if (compareRes ==
UNKNOWN) {
536 return {{(*itr), state}, std::move(result)};
543 result.push_back(state);
548 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort,
"Not all states could be sorted.");
549 return {{numberOfStates, numberOfStates}, std::move(result)};
554 std::vector<uint_fast64_t> result;
556 for (
auto state : *states) {
557 bool unknown =
false;
558 if (result.size() == 0) {
559 result.push_back(state);
562 for (
auto itr = result.begin(); itr != result.end(); ++itr) {
563 auto compareRes =
compare(state, (*itr));
564 if (compareRes ==
ABOVE || compareRes ==
SAME) {
566 result.insert(itr, state);
569 }
else if (compareRes ==
UNKNOWN) {
578 result.push_back(state);
582 while (result.size() < numberOfStatesToSort) {
583 result.push_back(numberOfStates);
585 STORM_LOG_ASSERT(result.size() == numberOfStatesToSort,
"Not all states could be sorted (or padded with the sentinel value).");
593 return std::make_shared<Order>(*
this);
598 doneStates.set(stateNumber);
605 std::cout <<
"Dot Output:\n"
606 <<
"digraph model {\n";
610 for (uint_fast64_t i = 0; i < numberOfStates; ++i) {
611 if (nodes[i] !=
nullptr) {
612 stateCoverage.
set(i);
616 for (uint_fast64_t j = i + 1; j < numberOfStates; j++) {
618 stateCoverage.
set(j,
false);
621 std::cout <<
"\t" << nodeName(*
getNode(i)) <<
" [ label = \"" << nodeLabel(*
getNode(i)) <<
"\" ];\n";
628 for (uint_fast64_t s1 :
getNode(i)->statesAbove) {
632 std::set<Node*> seenNodes;
633 for (uint_fast64_t state : currentNode->
statesAbove) {
635 if (std::find(seenNodes.begin(), seenNodes.end(), n) == seenNodes.end()) {
638 std::cout <<
"\t" << nodeName(*currentNode) <<
" -> " << nodeName(*
getNode(state)) <<
";\n";
649 dotOutfile <<
"Dot Output:\n"
650 <<
"digraph model {\n";
658 for (uint_fast64_t j = i + 1; j < numberOfStates; j++) {
660 stateCoverage.
set(j,
false);
664 dotOutfile <<
"\t" << nodeName(*
getNode(i)) <<
" [ label = \"" << nodeLabel(*
getNode(i)) <<
"\" ];\n";
671 if (currentNode ==
nullptr) {
675 for (uint_fast64_t s1 :
getNode(i)->statesAbove) {
679 std::set<Node*> seenNodes;
680 for (uint_fast64_t state : currentNode->
statesAbove) {
682 if (std::find(seenNodes.begin(), seenNodes.end(), n) == seenNodes.end()) {
685 dotOutfile <<
"\t" << nodeName(*currentNode) <<
" -> " << nodeName(*
getNode(state)) <<
";\n";
698 this->numberOfStates = numberOfStates;
699 this->invalid =
false;
700 this->nodes = std::vector<Node*>(numberOfStates,
nullptr);
703 if (decomposition.
size() == 0) {
707 for (
auto& scc : decomposition) {
708 if (scc.size() == 1) {
709 trivialStates.
set(*(scc.begin()));
713 this->top = allocateNode();
714 this->bottom = allocateNode();
715 this->top->statesAbove = storm::storage::BitVector(numberOfStates,
false);
716 this->bottom->statesAbove = storm::storage::BitVector(numberOfStates,
false);
717 this->doneBuilding = doneBuilding;
720bool Order::aboveFast(Node* node1, Node* node2)
const {
722 for (
auto const& state : node1->states) {
723 found = ((node2->statesAbove))[state];
731bool Order::above(Node* node1, Node* node2) {
732 assert(!aboveFast(node1, node2));
736 if (!trivialStates.full() || !doneBuilding) {
739 storm::storage::BitVector statesSeen((node2->statesAbove));
740 std::queue<uint_fast64_t> statesToHandle;
741 for (
auto state : statesSeen) {
742 statesToHandle.push(state);
744 while (!above && !statesToHandle.empty()) {
746 auto state = statesToHandle.front();
747 statesToHandle.pop();
749 if (aboveFast(node1, node)) {
753 for (
auto newState : node->statesAbove) {
754 if (!statesSeen[newState]) {
755 statesToHandle.push(newState);
756 statesSeen.set(newState);
762 for (
auto state : node1->states) {
763 node2->statesAbove.set(state);
769std::string Order::nodeName(Node n)
const {
770 auto itr = n.states.begin();
771 std::string name =
"n" + std::to_string(*itr);
775std::string Order::nodeLabel(Node n)
const {
776 if (n.states == top->states) {
779 if (n.states == bottom->states) {
782 auto itr = n.states.begin();
783 std::string label =
"s" + std::to_string(*itr);
785 if (itr != n.states.end()) {
786 label =
"[" + label +
"]";
792 return !doneStates.full();
796 return trivialStates[state];
800 while (!statesSorted.empty()) {
801 auto state = statesSorted.back();
802 statesSorted.pop_back();
803 if (!doneStates[state]) {
804 return {state,
true};
807 return {numberOfStates,
true};
812 auto state = statesToHandle.back();
813 statesToHandle.pop_back();
814 return {state,
false};
818 while (!statesToHandle.empty() && doneStates[statesToHandle.back()]) {
819 statesToHandle.pop_back();
821 return !statesToHandle.empty();
825 if (!doneStates[state]) {
826 statesToHandle.push_back(state);
831 statesSorted.push_back(state);
835 auto allAbove =
true;
836 auto allBelow =
true;
837 for (
auto& checkState : states) {
838 auto comp =
compare(checkState, state);
839 allAbove &= (comp ==
ABOVE || comp ==
SAME);
840 allBelow &= (comp ==
BELOW || comp ==
SAME);
842 return {allAbove, allBelow};
846 return doneStates.getNumberOfSetBits();
uint_fast64_t getNumberOfDoneStates() const
void addAbove(uint_fast64_t state, Node *node)
Adds a node with the given state above the given node.
bool isTrivial(uint_fast64_t state)
void addStateSorted(uint_fast64_t state)
Node * getBottom() const
Retrieves the bottom node of the order.
bool contains(uint_fast64_t state) const
Check if state is already contained in order.
Order::NodeComparison compareFast(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis=UNKNOWN) const
bool existsStateToHandle()
Order::NodeComparison compare(uint_fast64_t state1, uint_fast64_t state2, NodeComparison hypothesis=UNKNOWN)
Compares the level of the nodes of the states.
std::pair< uint_fast64_t, bool > getStateToHandle()
std::vector< uint_fast64_t > & getStatesSorted()
friend void swap(Order &first, Order &second) noexcept
std::vector< uint_fast64_t > sortStates(std::vector< uint_fast64_t > *states)
Sorts the given states if possible.
NodeComparison
Constants for comparison of nodes/states.
Order()
Constructs a new Order.
void toDotOutput() const
Prints the dot output to stdout.
void dotOutputToFile(std::ofstream &dotOutfile) const
Writes dotoutput to the given file.
Order(storm::storage::BitVector const &topStates, storm::storage::BitVector const &bottomStates, uint_fast64_t numberOfStates, storage::Decomposition< storage::StronglyConnectedComponent > sccsSorted, std::vector< uint_fast64_t > statesSorted)
Constructs an order with the given top and bottom states.
void addRelation(uint_fast64_t above, uint_fast64_t below, bool allowMerge=false)
Adds a new relation between two states to the order.
Node * getNode(uint_fast64_t state) const
Retrieves the pointer to a Node at which the state occurs.
bool merge(uint_fast64_t var1, uint_fast64_t var2)
Merges node of var2 into node of var1.
std::vector< Node * > getNodes() const
Returns the vector with the nodes of the order.
bool mergeNodes(Node *node1, Node *node2)
Merges node2 into node1.
std::pair< bool, bool > allAboveBelow(std::vector< uint_fast64_t > const states, uint_fast64_t state)
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...
bool getDoneBuilding() const
Returns true if done building the order.
void addToNode(uint_fast64_t state, Node *node)
Adds state to the states of the given node.
bool isTopState(uint_fast64_t) const
Checks if the given state is a top state.
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.
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.
void addStateToHandle(uint_fast64_t state)
void addBetween(uint_fast64_t state, Node *node1, Node *node2)
Adds a node with the given state below node1 and above node2.
Order & operator=(Order other)
uint_fast64_t getNumberOfStates() const
Returns the number of possible states in the order.
void addBelow(uint_fast64_t state, Node *node)
Adds a node with the given state below the given node.
void setDoneState(uint_fast64_t sccNumber)
std::pair< uint_fast64_t, bool > getNextStateNumber()
std::shared_ptr< Order > copy() const
Creates a copy of the calling Order.
bool isOnlyBottomTopOrder() const
Returns if the order only consists of bottom and top states (so no in-between nodes).
uint_fast64_t getNumberOfAddedStates() const
Returns the number of added states.
bool isBottomState(uint_fast64_t) const
Checks if the given state is a bottom state.
Node * getTop() const
Retrieves the top node of the order.
void add(uint_fast64_t state)
Adds state between the top and bottom node of the order.
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.
A bit vector that is internally represented as a vector of 64-bit values.
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.
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)
#define STORM_LOG_ASSERT(cond, message)
void swap(Order &first, Order &second) noexcept
Nodes of the Reachability Order.
boost::container::flat_set< uint_fast64_t > states
storm::storage::BitVector statesAbove