Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
SylvanAddIterator.cpp
Go to the documentation of this file.
2
3#include <cmath>
4
10
11namespace storm {
12namespace dd {
13
14#ifdef STORM_HAVE_SYLVAN
15template<typename ValueType>
16AddIterator<DdType::Sylvan, ValueType>::AddIterator() {
17 // Intentionally left empty.
18}
19
20template<typename ValueType>
21AddIterator<DdType::Sylvan, ValueType>::AddIterator(DdManager<DdType::Sylvan> const& ddManager, sylvan::Mtbdd mtbdd, sylvan::Bdd variables,
22 uint_fast64_t numberOfDdVariables, bool isAtEnd,
23 std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables)
24 : ddManager(&ddManager),
25 mtbdd(mtbdd),
26 variables(variables),
27 cube(numberOfDdVariables),
28 leaf(),
29 isAtEnd(isAtEnd),
30 metaVariables(metaVariables),
31 enumerateDontCareMetaVariables(enumerateDontCareMetaVariables),
32 cubeCounter(0),
33 relevantDontCareDdVariables(),
34 currentValuation(ddManager.getExpressionManager().getSharedPointer()) {
35 // If the given generator is not yet at its end, we need to create the current valuation from the cube from
36 // scratch.
37 if (!this->isAtEnd) {
38 this->createGlobalToLocalIndexMapping();
39
40 // And then get ready for treating the first cube.
41 leaf = mtbdd_enum_first(mtbdd.GetMTBDD(), variables.GetBDD(), cube.data(), &mtbdd_isnonzero);
42
43 if (leaf != mtbdd_false) {
44 this->treatNewCube();
45 } else {
46 this->isAtEnd = true;
47 }
48 }
49}
50
51template<typename ValueType>
52void AddIterator<DdType::Sylvan, ValueType>::createGlobalToLocalIndexMapping() {
53 // Create the global to local index mapping.
54 std::vector<uint_fast64_t> globalIndices;
55 for (auto const& metaVariable : *this->metaVariables) {
56 auto const& ddMetaVariable = this->ddManager->getMetaVariable(metaVariable);
57
58 for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
59 globalIndices.push_back(ddVariable.getIndex());
60 }
61 }
62
63 std::sort(globalIndices.begin(), globalIndices.end());
64
65 for (auto it = globalIndices.begin(), ite = globalIndices.end(); it != ite; ++it) {
66 globalToLocalIndexMap[*it] = std::distance(globalIndices.begin(), it);
67 }
68}
69
70template<typename ValueType>
71AddIterator<DdType::Sylvan, ValueType> AddIterator<DdType::Sylvan, ValueType>::createBeginIterator(DdManager<DdType::Sylvan> const& ddManager,
72 sylvan::Mtbdd mtbdd, sylvan::Bdd variables,
73 uint_fast64_t numberOfDdVariables,
74 std::set<storm::expressions::Variable> const* metaVariables,
75 bool enumerateDontCareMetaVariables) {
76 return AddIterator<DdType::Sylvan, ValueType>(ddManager, mtbdd, variables, numberOfDdVariables, false, metaVariables, enumerateDontCareMetaVariables);
77}
78
79template<typename ValueType>
80AddIterator<DdType::Sylvan, ValueType> AddIterator<DdType::Sylvan, ValueType>::createEndIterator(DdManager<DdType::Sylvan> const& ddManager) {
81 return AddIterator<DdType::Sylvan, ValueType>(ddManager, sylvan::Mtbdd(), sylvan::Bdd(), 0, true, nullptr, false);
82}
83
84template<typename ValueType>
85AddIterator<DdType::Sylvan, ValueType>& AddIterator<DdType::Sylvan, ValueType>::operator++() {
86 STORM_LOG_ASSERT(!this->isAtEnd, "Illegally incrementing iterator that is already at its end.");
87
88 // If there were no (relevant) don't cares or we have enumerated all combination, we need to eliminate the
89 // found solutions and get the next "first" cube.
90 if (this->relevantDontCareDdVariables.empty() || this->cubeCounter >= std::pow(2, this->relevantDontCareDdVariables.size()) - 1) {
91 leaf = mtbdd_enum_next(mtbdd.GetMTBDD(), variables.GetBDD(), cube.data(), &mtbdd_isnonzero);
92
93 if (leaf != mtbdd_false) {
94 this->treatNewCube();
95 } else {
96 this->isAtEnd = true;
97 }
98 } else {
99 // Treat the next solution of the cube.
100 this->treatNextInCube();
101 }
102
103 return *this;
104}
105
106template<typename ValueType>
107bool AddIterator<DdType::Sylvan, ValueType>::operator==(AddIterator<DdType::Sylvan, ValueType> const& other) const {
108 if (this->isAtEnd && other.isAtEnd) {
109 return true;
110 } else {
111 return this->ddManager == other.ddManager && this->mtbdd == other.mtbdd && this->variables == other.variables && this->cube == other.cube &&
112 this->leaf == other.leaf && this->isAtEnd == other.isAtEnd && this->metaVariables == other.metaVariables &&
113 this->cubeCounter == other.cubeCounter && this->relevantDontCareDdVariables == other.relevantDontCareDdVariables &&
114 this->currentValuation == other.currentValuation;
115 }
116}
117
118template<typename ValueType>
119bool AddIterator<DdType::Sylvan, ValueType>::operator!=(AddIterator<DdType::Sylvan, ValueType> const& other) const {
120 return !(*this == other);
121}
122
123template<typename ValueType>
124std::pair<storm::expressions::SimpleValuation, ValueType> AddIterator<DdType::Sylvan, ValueType>::operator*() const {
125 return std::make_pair(currentValuation, static_cast<ValueType>(InternalAdd<DdType::Sylvan, ValueType>::getValue(leaf)));
126}
127
128template<typename ValueType>
129void AddIterator<DdType::Sylvan, ValueType>::treatNewCube() {
130 this->relevantDontCareDdVariables.clear();
131
132 // Now loop through the bits of all meta variables and check whether they need to be set, not set or are
133 // don't cares. In the latter case, we add them to a special list, so we can iterate over their concrete
134 // valuations later.
135 for (auto const& metaVariable : *this->metaVariables) {
136 bool metaVariableAppearsInCube = false;
137 std::vector<std::tuple<storm::expressions::Variable, uint_fast64_t>> localRelenvantDontCareDdVariables;
138 auto const& ddMetaVariable = this->ddManager->getMetaVariable(metaVariable);
139 if (ddMetaVariable.getType() == MetaVariableType::Bool) {
140 if (this->cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables().front().getIndex())] == 0) {
141 metaVariableAppearsInCube = true;
142 currentValuation.setBooleanValue(metaVariable, false);
143 } else if (this->cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables().front().getIndex())] == 1) {
144 metaVariableAppearsInCube = true;
145 currentValuation.setBooleanValue(metaVariable, true);
146 } else {
147 localRelenvantDontCareDdVariables.push_back(std::make_tuple(metaVariable, 0));
148 }
149 } else {
150 int_fast64_t intValue = 0;
151 for (uint_fast64_t bitIndex = 0; bitIndex < ddMetaVariable.getNumberOfDdVariables(); ++bitIndex) {
152 if (cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables()[bitIndex].getIndex())] == 0) {
153 // Leave bit unset.
154 metaVariableAppearsInCube = true;
155 } else if (cube[globalToLocalIndexMap.at(ddMetaVariable.getDdVariables()[bitIndex].getIndex())] == 1) {
156 intValue |= 1ull << (ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1);
157 metaVariableAppearsInCube = true;
158 } else {
159 // Temporarily leave bit unset so we can iterate trough the other option later.
160 // Add the bit to the relevant don't care bits.
161 localRelenvantDontCareDdVariables.push_back(std::make_tuple(metaVariable, ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1));
162 }
163 }
164 if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
165 currentValuation.setBitVectorValue(metaVariable, intValue + ddMetaVariable.getLow());
166 }
167 }
168
169 // If all meta variables are to be enumerated or the meta variable appeared in the cube, we register the
170 // missing bits to later enumerate all possible valuations.
171 if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
172 relevantDontCareDdVariables.insert(relevantDontCareDdVariables.end(), localRelenvantDontCareDdVariables.begin(),
173 localRelenvantDontCareDdVariables.end());
174 }
175 }
176
177 // Finally, reset the cube counter.
178 this->cubeCounter = 0;
179}
180
181template<typename ValueType>
182void AddIterator<DdType::Sylvan, ValueType>::treatNextInCube() {
183 // Start by increasing the counter and check which bits we need to set/unset in the new valuation.
184 ++this->cubeCounter;
185
186 for (uint_fast64_t index = 0; index < this->relevantDontCareDdVariables.size(); ++index) {
187 auto const& ddMetaVariable = this->ddManager->getMetaVariable(std::get<0>(this->relevantDontCareDdVariables[index]));
188 if (ddMetaVariable.getType() == MetaVariableType::Bool) {
189 if ((this->cubeCounter & (1ull << index)) != 0) {
190 currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), true);
191 } else {
192 currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), false);
193 }
194 } else {
195 storm::expressions::Variable const& metaVariable = std::get<0>(this->relevantDontCareDdVariables[index]);
196 if ((this->cubeCounter & (1ull << index)) != 0) {
197 currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) |
198 (1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) +
199 ddMetaVariable.getLow());
200 } else {
201 currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) &
202 ~(1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) +
203 ddMetaVariable.getLow());
204 }
205 }
206 }
207}
208#else
209template<typename ValueType>
211 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
212 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
213 "version of Storm with Sylvan support.");
214}
215
216template<typename ValueType>
218 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
219 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
220 "version of Storm with Sylvan support.");
221}
222
223template<typename ValueType>
225 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
226 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
227 "version of Storm with Sylvan support.");
228}
229
230template<typename ValueType>
232 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
233 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
234 "version of Storm with Sylvan support.");
235}
236
237template<typename ValueType>
238std::pair<storm::expressions::SimpleValuation, ValueType> AddIterator<DdType::Sylvan, ValueType>::operator*() const {
239 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
240 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
241 "version of Storm with Sylvan support.");
242}
243#endif
244
249} // namespace dd
250} // namespace storm
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
SFTBDDChecker::ValueType ValueType
Expression ite(Expression const &condition, Expression const &thenExpression, Expression const &elseExpression)