Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Odd.cpp
Go to the documentation of this file.
2
3#include <boost/algorithm/string/join.hpp>
4#include <fstream>
5#include <set>
6
10#include "storm/io/file.h"
13
14namespace storm {
15namespace dd {
16Odd::Odd(std::shared_ptr<Odd> elseNode, uint_fast64_t elseOffset, std::shared_ptr<Odd> thenNode, uint_fast64_t thenOffset)
17 : elseNode(elseNode), thenNode(thenNode), elseOffset(elseOffset), thenOffset(thenOffset) {
18 STORM_LOG_ASSERT(this != elseNode.get() && this != thenNode.get(), "Cyclic ODD.");
19}
20
21Odd const& Odd::getThenSuccessor() const {
22 return *this->thenNode;
23}
24
25Odd const& Odd::getElseSuccessor() const {
26 return *this->elseNode;
27}
28
29uint_fast64_t Odd::getElseOffset() const {
30 return this->elseOffset;
31}
32
33void Odd::setElseOffset(uint_fast64_t newOffset) {
34 this->elseOffset = newOffset;
35}
36
37uint_fast64_t Odd::getThenOffset() const {
38 return this->thenOffset;
39}
40
41void Odd::setThenOffset(uint_fast64_t newOffset) {
42 this->thenOffset = newOffset;
43}
44
45uint_fast64_t Odd::getTotalOffset() const {
46 return this->elseOffset + this->thenOffset;
47}
48
49uint_fast64_t Odd::getNodeCount() const {
50 // If the ODD contains a constant (and thus has no children), the size is 1.
51 if (this->elseNode == nullptr && this->thenNode == nullptr) {
52 return 1;
53 }
54
55 // If the two successors are actually the same, we need to count the subnodes only once.
56 if (this->elseNode == this->thenNode) {
57 return this->elseNode->getNodeCount();
58 } else {
59 return this->elseNode->getNodeCount() + this->thenNode->getNodeCount();
60 }
61}
62
63uint_fast64_t Odd::getHeight() const {
64 if (this->isTerminalNode()) {
65 return 1;
66 } else {
67 // Since both subtrees have the same height, we only count the height of the else-tree.
68 return 1 + this->getElseSuccessor().getHeight();
69 }
70}
71
72bool Odd::isTerminalNode() const {
73 return this->elseNode == nullptr && this->thenNode == nullptr;
74}
75
76template<typename ValueType>
77void Odd::expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<ValueType> const& oldValues, std::vector<ValueType>& newValues) const {
78 expandValuesToVectorRec(0, *this, oldValues, 0, newOdd, newValues);
79}
80
81template<typename ValueType>
82void Odd::expandValuesToVectorRec(uint_fast64_t oldOffset, storm::dd::Odd const& oldOdd, std::vector<ValueType> const& oldValues, uint_fast64_t newOffset,
83 storm::dd::Odd const& newOdd, std::vector<ValueType>& newValues) {
84 if (oldOdd.isTerminalNode()) {
85 STORM_LOG_THROW(newOdd.isTerminalNode(), storm::exceptions::InvalidArgumentException, "The ODDs for the translation must have the same height.");
86 if (oldOdd.getThenOffset() != 0) {
87 newValues[newOffset] += oldValues[oldOffset];
88 }
89 } else {
90 expandValuesToVectorRec(oldOffset, oldOdd.getElseSuccessor(), oldValues, newOffset, newOdd.getElseSuccessor(), newValues);
91 expandValuesToVectorRec(oldOffset + oldOdd.getElseOffset(), oldOdd.getThenSuccessor(), oldValues, newOffset + newOdd.getElseOffset(),
92 newOdd.getThenSuccessor(), newValues);
93 }
94}
95
96void Odd::oldToNewIndex(storm::dd::Odd const& newOdd, std::function<void(uint64_t oldOffset, uint64_t newOffset)> const& callback) const {
97 STORM_LOG_ASSERT(this->getHeight() < newOdd.getHeight(), "Expected increase in height.");
98 oldToNewIndexRec(0, *this, 0, newOdd, callback);
99}
100
101void Odd::oldToNewIndexRec(uint_fast64_t oldOffset, storm::dd::Odd const& oldOdd, uint_fast64_t newOffset, storm::dd::Odd const& newOdd,
102 std::function<void(uint64_t oldOffset, uint64_t newOffset)> const& callback) {
103 if (oldOdd.getTotalOffset() == 0 || newOdd.getTotalOffset() == 0) {
104 return;
105 }
106
107 if (oldOdd.isTerminalNode()) {
108 if (oldOdd.getThenOffset() != 0) {
109 if (newOdd.isTerminalNode()) {
110 if (newOdd.getThenOffset() != 0) {
111 callback(oldOffset, newOffset);
112 }
113 } else {
114 oldToNewIndexRec(oldOffset, oldOdd, newOffset, newOdd.getElseSuccessor(), callback);
115 oldToNewIndexRec(oldOffset, oldOdd, newOffset + newOdd.getElseOffset(), newOdd.getThenSuccessor(), callback);
116 }
117 }
118 } else {
119 oldToNewIndexRec(oldOffset, oldOdd.getElseSuccessor(), newOffset, newOdd.getElseSuccessor(), callback);
120 oldToNewIndexRec(oldOffset + oldOdd.getElseOffset(), oldOdd.getThenSuccessor(), newOffset + newOdd.getElseOffset(), newOdd.getThenSuccessor(),
121 callback);
122 }
123}
124
125void Odd::exportToDot(std::string const& filename) const {
126 std::ofstream dotFile;
127 storm::io::openFile(filename, dotFile);
128
129 // Print header.
130 dotFile << "digraph \"ODD\" {\n"
131 << "center=true;\n"
132 << "edge [dir = none];\n";
133
134 // Print levels as ranks.
135 dotFile << "{ node [shape = plaintext];\n"
136 << "edge [style = invis];\n";
137 std::vector<std::string> levelNames;
138 for (uint_fast64_t level = 0; level < this->getHeight(); ++level) {
139 levelNames.push_back("\"" + std::to_string(level) + "\"");
140 }
141 dotFile << boost::join(levelNames, " -> ") << ";";
142 dotFile << "}\n";
143
144 std::map<uint_fast64_t, std::unordered_set<storm::dd::Odd const*>> levelToOddNodesMap;
145 this->addToLevelToOddNodesMap(levelToOddNodesMap);
146
147 for (auto const& levelNodes : levelToOddNodesMap) {
148 dotFile << "{ rank = same; \"" << levelNodes.first << "\"\n";
149 for (auto const& node : levelNodes.second) {
150 dotFile << "\"" << node << "\";\n";
151 }
152 dotFile << "}\n";
153 }
154
155 for (auto const& levelNodes : levelToOddNodesMap) {
156 for (auto const& node : levelNodes.second) {
157 dotFile << "\"" << node << "\" [label=\"" << node->getTotalOffset() << "\"];\n";
158 if (!node->isTerminalNode()) {
159 dotFile << "\"" << node << "\" -> \"" << &node->getElseSuccessor() << "\" [style=dashed, label=\"0\"];\n";
160 dotFile << "\"" << node << "\" -> \"" << &node->getThenSuccessor() << "\" [style=solid, label=\"" << node->getElseOffset() << "\"];\n";
161 }
162 }
163 }
164
165 dotFile << "}\n";
166 storm::io::closeFile(dotFile);
167}
168
169void Odd::exportToText(std::string const& filename) const {
170 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation not supported");
171}
172
173void getEncodingRec(Odd const& odd, uint64_t index, uint64_t offset, storm::storage::BitVector& result) {
174 if (odd.isTerminalNode()) {
175 return;
176 }
177
178 bool thenPath = false;
179 if (odd.getElseOffset() <= offset) {
180 thenPath = true;
181 offset -= odd.getElseOffset();
182 result.set(index);
183 }
184 getEncodingRec(thenPath ? odd.getThenSuccessor() : odd.getElseSuccessor(), index + 1, offset, result);
185}
186
187storm::storage::BitVector Odd::getEncoding(uint64_t offset, uint64_t variableCount) const {
188 storm::storage::BitVector result(variableCount > 0 ? variableCount : this->getHeight());
189 getEncodingRec(*this, 0, offset, result);
190 return result;
191}
192
193void Odd::addToLevelToOddNodesMap(std::map<uint_fast64_t, std::unordered_set<storm::dd::Odd const*>>& levelToOddNodesMap, uint_fast64_t level) const {
194 levelToOddNodesMap[level].emplace(this);
195 if (!this->isTerminalNode()) {
196 this->getElseSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1);
197 if (this->thenNode != this->elseNode) {
198 this->getThenSuccessor().addToLevelToOddNodesMap(levelToOddNodesMap, level + 1);
199 }
200 }
201}
202
203template void Odd::expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<double> const& oldValues, std::vector<double>& newValues) const;
204template void Odd::expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<storm::RationalNumber> const& oldValues,
205 std::vector<storm::RationalNumber>& newValues) const;
206template void Odd::expandExplicitVector(storm::dd::Odd const& newOdd, std::vector<storm::RationalFunction> const& oldValues,
207 std::vector<storm::RationalFunction>& newValues) const;
208} // namespace dd
209} // namespace storm
Odd const & getThenSuccessor() const
Retrieves the then-successor of this ODD node.
Definition Odd.cpp:21
void expandExplicitVector(storm::dd::Odd const &newOdd, std::vector< ValueType > const &oldValues, std::vector< ValueType > &newValues) const
Adds the old values to the new values.
Definition Odd.cpp:77
void exportToText(std::string const &filename) const
Exports the ODD in the text format to the given file.
Definition Odd.cpp:169
uint_fast64_t getNodeCount() const
Retrieves the size of the ODD.
Definition Odd.cpp:49
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
Definition Odd.cpp:45
uint_fast64_t getElseOffset() const
Retrieves the else-offset of this ODD node.
Definition Odd.cpp:29
void oldToNewIndex(storm::dd::Odd const &newOdd, std::function< void(uint64_t oldOffset, uint64_t newOffset)> const &callback) const
Translates the indices of the old ODD to that of the new ODD by calling the callback for each old-new...
Definition Odd.cpp:96
void setElseOffset(uint_fast64_t newOffset)
Sets the else-offset of this ODD node.
Definition Odd.cpp:33
uint_fast64_t getHeight() const
Retrieves the height of the ODD.
Definition Odd.cpp:63
bool isTerminalNode() const
Checks whether the given ODD node is a terminal node, i.e.
Definition Odd.cpp:72
void setThenOffset(uint_fast64_t newOffset)
Sets the then-offset of this ODD node.
Definition Odd.cpp:41
storm::storage::BitVector getEncoding(uint64_t offset, uint64_t variableCount=0) const
Retrieves the encoding for the given offset.
Definition Odd.cpp:187
Odd const & getElseSuccessor() const
Retrieves the else-successor of this ODD node.
Definition Odd.cpp:25
void exportToDot(std::string const &filename) const
Exports the ODD in the dot format to the given file.
Definition Odd.cpp:125
Odd()=default
uint_fast64_t getThenOffset() const
Retrieves the then-offset of this ODD node.
Definition Odd.cpp:37
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:16
void set(uint64_t index, bool value=true)
Sets the given truth value at the given index.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
void getEncodingRec(Odd const &odd, uint64_t index, uint64_t offset, storm::storage::BitVector &result)
Definition Odd.cpp:173
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