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