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