Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Add.cpp
Go to the documentation of this file.
2
3#include <boost/algorithm/string/join.hpp>
4
15
16namespace storm {
17namespace dd {
18template<DdType LibraryType, typename ValueType>
19Add<LibraryType, ValueType>::Add(DdManager<LibraryType> const& ddManager, InternalAdd<LibraryType, ValueType> const& internalAdd,
20 std::set<storm::expressions::Variable> const& containedMetaVariables)
21 : Dd<LibraryType>(ddManager, containedMetaVariables), internalAdd(internalAdd) {
22 // Intentionally left empty.
23}
24
25template<DdType LibraryType, typename ValueType>
27 return internalAdd == other.internalAdd;
28}
29
30template<DdType LibraryType, typename ValueType>
32 return internalAdd != other.internalAdd;
33}
34
35template<DdType LibraryType, typename ValueType>
37 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd + other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
38}
39
40template<DdType LibraryType, typename ValueType>
42 this->addMetaVariables(other.getContainedMetaVariables());
43 internalAdd += other.internalAdd;
44 return *this;
45}
46
47template<DdType LibraryType, typename ValueType>
49 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd * other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
50}
51
52template<DdType LibraryType, typename ValueType>
54 this->addMetaVariables(other.getContainedMetaVariables());
55 internalAdd *= other.internalAdd;
56 return *this;
57}
58
59template<DdType LibraryType, typename ValueType>
61 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd - other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
62}
63
64template<DdType LibraryType, typename ValueType>
66 return this->getDdManager().template getAddZero<ValueType>() - *this;
67}
68
69template<DdType LibraryType, typename ValueType>
71 this->addMetaVariables(other.getContainedMetaVariables());
72 internalAdd -= other.internalAdd;
73 return *this;
74}
75
76template<DdType LibraryType, typename ValueType>
78 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd / other.internalAdd, Dd<LibraryType>::joinMetaVariables(*this, other));
79}
80
81template<DdType LibraryType, typename ValueType>
83 this->addMetaVariables(other.getContainedMetaVariables());
84 internalAdd /= other.internalAdd;
85 return *this;
86}
87
88template<DdType LibraryType, typename ValueType>
90 return Bdd<LibraryType>(this->getDdManager(), internalAdd.equals(other), Dd<LibraryType>::joinMetaVariables(*this, other));
91}
92
93template<DdType LibraryType, typename ValueType>
95 return Bdd<LibraryType>(this->getDdManager(), internalAdd.notEquals(other), Dd<LibraryType>::joinMetaVariables(*this, other));
96}
98template<DdType LibraryType, typename ValueType>
100 return Bdd<LibraryType>(this->getDdManager(), internalAdd.less(other), Dd<LibraryType>::joinMetaVariables(*this, other));
101}
102
103template<DdType LibraryType, typename ValueType>
105 return Bdd<LibraryType>(this->getDdManager(), internalAdd.lessOrEqual(other), Dd<LibraryType>::joinMetaVariables(*this, other));
106}
107
108template<DdType LibraryType, typename ValueType>
110 return Bdd<LibraryType>(this->getDdManager(), internalAdd.greater(other), Dd<LibraryType>::joinMetaVariables(*this, other));
111}
112
113template<DdType LibraryType, typename ValueType>
115 return Bdd<LibraryType>(this->getDdManager(), internalAdd.greaterOrEqual(other), Dd<LibraryType>::joinMetaVariables(*this, other));
116}
117
118template<DdType LibraryType, typename ValueType>
120 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.pow(other), Dd<LibraryType>::joinMetaVariables(*this, other));
121}
122
123template<DdType LibraryType, typename ValueType>
125 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.mod(other), Dd<LibraryType>::joinMetaVariables(*this, other));
126}
127
128template<DdType LibraryType, typename ValueType>
130 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.logxy(other), Dd<LibraryType>::joinMetaVariables(*this, other));
131}
132
133template<DdType LibraryType, typename ValueType>
135 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.floor(), this->getContainedMetaVariables());
137
138template<DdType LibraryType, typename ValueType>
140 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.ceil(), this->getContainedMetaVariables());
141}
142
143template<DdType LibraryType, typename ValueType>
145 STORM_LOG_THROW(false, storm::exceptions::NotSupportedException, "Operation not supported.");
146}
147
148template<>
150 return Add<storm::dd::DdType::Sylvan, storm::RationalNumber>(this->getDdManager(), internalAdd.sharpenKwekMehlhorn(static_cast<std::size_t>(precision)),
151 this->getContainedMetaVariables());
153
154template<>
156 return Add<storm::dd::DdType::Sylvan, storm::RationalNumber>(this->getDdManager(), internalAdd.sharpenKwekMehlhorn(static_cast<std::size_t>(precision)),
157 this->getContainedMetaVariables());
158}
159
160template<DdType LibraryType, typename ValueType>
162 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.minimum(other), Dd<LibraryType>::joinMetaVariables(*this, other));
163}
164
165template<DdType LibraryType, typename ValueType>
167 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.maximum(other), Dd<LibraryType>::joinMetaVariables(*this, other));
168}
170template<DdType LibraryType, typename ValueType>
171Add<LibraryType, ValueType> Add<LibraryType, ValueType>::sumAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
172 Bdd<LibraryType> cube = Bdd<LibraryType>::getCube(this->getDdManager(), metaVariables);
173 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.sumAbstract(cube.getInternalBdd()),
175}
176
177template<DdType LibraryType, typename ValueType>
178Add<LibraryType, ValueType> Add<LibraryType, ValueType>::minAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
179 Bdd<LibraryType> cube = Bdd<LibraryType>::getCube(this->getDdManager(), metaVariables);
180 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.minAbstract(cube.getInternalBdd()),
182}
183
184template<DdType LibraryType, typename ValueType>
185Bdd<LibraryType> Add<LibraryType, ValueType>::minAbstractRepresentative(std::set<storm::expressions::Variable> const& metaVariables) const {
186 Bdd<LibraryType> cube = Bdd<LibraryType>::getCube(this->getDdManager(), metaVariables);
187 return Bdd<LibraryType>(this->getDdManager(), internalAdd.minAbstractRepresentative(cube.getInternalBdd()), this->getContainedMetaVariables());
188}
189
190template<DdType LibraryType, typename ValueType>
191Add<LibraryType, ValueType> Add<LibraryType, ValueType>::maxAbstract(std::set<storm::expressions::Variable> const& metaVariables) const {
192 Bdd<LibraryType> cube = Bdd<LibraryType>::getCube(this->getDdManager(), metaVariables);
193 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.maxAbstract(cube.getInternalBdd()),
195}
197template<DdType LibraryType, typename ValueType>
198Bdd<LibraryType> Add<LibraryType, ValueType>::maxAbstractRepresentative(std::set<storm::expressions::Variable> const& metaVariables) const {
199 Bdd<LibraryType> cube = Bdd<LibraryType>::getCube(this->getDdManager(), metaVariables);
200 return Bdd<LibraryType>(this->getDdManager(), internalAdd.maxAbstractRepresentative(cube.getInternalBdd()), this->getContainedMetaVariables());
201}
202
203template<DdType LibraryType, typename ValueType>
204bool Add<LibraryType, ValueType>::equalModuloPrecision(Add<LibraryType, ValueType> const& other, ValueType const& precision, bool relative) const {
205 return internalAdd.equalModuloPrecision(other, precision, relative);
206}
207
208template<DdType LibraryType, typename ValueType>
209Add<LibraryType, ValueType> Add<LibraryType, ValueType>::renameVariables(std::set<storm::expressions::Variable> const& from,
210 std::set<storm::expressions::Variable> const& to) const {
211 std::vector<InternalBdd<LibraryType>> fromBdds;
212 std::vector<InternalBdd<LibraryType>> toBdds;
213
214 for (auto const& metaVariable : from) {
215 STORM_LOG_THROW(this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException,
216 "Cannot rename variable '" << metaVariable.getName() << "' that is not present.");
217 DdMetaVariable<LibraryType> const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable);
218 for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
219 fromBdds.push_back(ddVariable.getInternalBdd());
220 }
222 for (auto const& metaVariable : to) {
223 STORM_LOG_THROW(!this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException,
224 "Cannot rename to variable '" << metaVariable.getName() << "' that is already present.");
225 DdMetaVariable<LibraryType> const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable);
226 for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
227 toBdds.push_back(ddVariable.getInternalBdd());
229 }
230
231 std::set<storm::expressions::Variable> newContainedMetaVariables = to;
232 std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), from.begin(), from.end(),
233 std::inserter(newContainedMetaVariables, newContainedMetaVariables.begin()));
234
235 STORM_LOG_THROW(fromBdds.size() == toBdds.size(), storm::exceptions::InvalidArgumentException, "Unable to rename mismatching meta variables.");
236 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.swapVariables(fromBdds, toBdds), newContainedMetaVariables);
237}
238
239template<DdType LibraryType, typename ValueType>
241 std::set<storm::expressions::Variable> const& to) const {
242 std::vector<InternalBdd<LibraryType>> fromBdds;
243 std::vector<InternalBdd<LibraryType>> toBdds;
244
245 for (auto const& metaVariable : from) {
246 STORM_LOG_THROW(this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException,
247 "Cannot rename variable '" << metaVariable.getName() << "' that is not present.");
248 DdMetaVariable<LibraryType> const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable);
249 for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
250 fromBdds.push_back(ddVariable.getInternalBdd());
251 }
252 }
253 std::sort(fromBdds.begin(), fromBdds.end(),
254 [](InternalBdd<LibraryType> const& a, InternalBdd<LibraryType> const& b) { return a.getLevel() < b.getLevel(); });
255 for (auto const& metaVariable : to) {
256 STORM_LOG_THROW(!this->containsMetaVariable(metaVariable), storm::exceptions::InvalidOperationException,
257 "Cannot rename to variable '" << metaVariable.getName() << "' that is already present.");
258 DdMetaVariable<LibraryType> const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable);
259 for (auto const& ddVariable : ddMetaVariable.getDdVariables()) {
260 toBdds.push_back(ddVariable.getInternalBdd());
261 }
262 }
263 std::sort(toBdds.begin(), toBdds.end(), [](InternalBdd<LibraryType> const& a, InternalBdd<LibraryType> const& b) { return a.getLevel() < b.getLevel(); });
264
265 std::set<storm::expressions::Variable> newContainedMetaVariables = to;
266 std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), from.begin(), from.end(),
267 std::inserter(newContainedMetaVariables, newContainedMetaVariables.begin()));
269 STORM_LOG_ASSERT(fromBdds.size() >= toBdds.size(), "Unable to perform rename-abstract with mismatching sizes.");
270
271 if (fromBdds.size() == toBdds.size()) {
272 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.permuteVariables(fromBdds, toBdds), newContainedMetaVariables);
273 } else {
274 InternalBdd<LibraryType> cube = this->getDdManager().getBddOne().getInternalBdd();
275 for (uint64_t index = toBdds.size(); index < fromBdds.size(); ++index) {
276 cube &= fromBdds[index];
277 }
278 fromBdds.resize(toBdds.size());
279
280 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.sumAbstract(cube).permuteVariables(fromBdds, toBdds), newContainedMetaVariables);
281 }
283
284template<DdType LibraryType, typename ValueType>
286 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) const {
287 std::set<storm::expressions::Variable> newContainedMetaVariables;
288 std::set<storm::expressions::Variable> deletedMetaVariables;
289 std::vector<InternalBdd<LibraryType>> from;
290 std::vector<InternalBdd<LibraryType>> to;
291 for (auto const& metaVariablePair : metaVariablePairs) {
292 DdMetaVariable<LibraryType> const& variable1 = this->getDdManager().getMetaVariable(metaVariablePair.first);
293 DdMetaVariable<LibraryType> const& variable2 = this->getDdManager().getMetaVariable(metaVariablePair.second);
294
295 // Keep track of the contained meta variables in the DD.
296 if (this->containsMetaVariable(metaVariablePair.first)) {
297 if (this->containsMetaVariable(metaVariablePair.second)) {
298 // Nothing to do here.
299 } else {
300 newContainedMetaVariables.insert(metaVariablePair.second);
301 deletedMetaVariables.insert(metaVariablePair.first);
302 }
303 } else {
304 if (!this->containsMetaVariable(metaVariablePair.second)) {
305 // Nothing to do here.
306 } else {
307 newContainedMetaVariables.insert(metaVariablePair.first);
308 deletedMetaVariables.insert(metaVariablePair.second);
309 }
310 }
311 for (auto const& ddVariable : variable1.getDdVariables()) {
312 from.push_back(ddVariable.getInternalBdd());
313 }
314 for (auto const& ddVariable : variable2.getDdVariables()) {
315 to.push_back(ddVariable.getInternalBdd());
316 }
317 }
319 std::set<storm::expressions::Variable> tmp;
320 std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), deletedMetaVariables.begin(),
321 deletedMetaVariables.end(), std::inserter(tmp, tmp.begin()));
322 std::set<storm::expressions::Variable> containedMetaVariables;
323 std::set_union(tmp.begin(), tmp.end(), newContainedMetaVariables.begin(), newContainedMetaVariables.end(),
324 std::inserter(containedMetaVariables, containedMetaVariables.begin()));
325 STORM_LOG_THROW(from.size() == to.size(), storm::exceptions::InvalidArgumentException, "Unable to swap mismatching meta variables.");
326 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.swapVariables(from, to), containedMetaVariables);
327}
328
329template<DdType LibraryType, typename ValueType>
331 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> const& metaVariablePairs) const {
332 std::set<storm::expressions::Variable> newContainedMetaVariables;
333 std::set<storm::expressions::Variable> deletedMetaVariables;
334 std::vector<InternalBdd<LibraryType>> from;
335 std::vector<InternalBdd<LibraryType>> to;
336 for (auto const& metaVariablePair : metaVariablePairs) {
337 DdMetaVariable<LibraryType> const& variable1 = this->getDdManager().getMetaVariable(metaVariablePair.first);
338 DdMetaVariable<LibraryType> const& variable2 = this->getDdManager().getMetaVariable(metaVariablePair.second);
339
340 // Keep track of the contained meta variables in the DD.
341 if (this->containsMetaVariable(metaVariablePair.first)) {
342 deletedMetaVariables.insert(metaVariablePair.first);
343 newContainedMetaVariables.insert(metaVariablePair.second);
344 }
345
346 for (auto const& ddVariable : variable1.getDdVariables()) {
347 from.push_back(ddVariable.getInternalBdd());
348 }
349 for (auto const& ddVariable : variable2.getDdVariables()) {
350 to.push_back(ddVariable.getInternalBdd());
351 }
353
354 std::set<storm::expressions::Variable> tmp;
355 std::set_difference(this->getContainedMetaVariables().begin(), this->getContainedMetaVariables().end(), deletedMetaVariables.begin(),
356 deletedMetaVariables.end(), std::inserter(tmp, tmp.begin()));
357 std::set<storm::expressions::Variable> containedMetaVariables;
358 std::set_union(tmp.begin(), tmp.end(), newContainedMetaVariables.begin(), newContainedMetaVariables.end(),
359 std::inserter(containedMetaVariables, containedMetaVariables.begin()));
360 STORM_LOG_THROW(from.size() == to.size(), storm::exceptions::InvalidArgumentException, "Unable to swap mismatching meta variables.");
361 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.permuteVariables(from, to), containedMetaVariables);
363
364template<DdType LibraryType, typename ValueType>
366 std::set<storm::expressions::Variable> const& summationMetaVariables) const {
367 // Create the summation variables.
368 std::vector<InternalBdd<LibraryType>> summationDdVariables;
369 for (auto const& metaVariable : summationMetaVariables) {
370 for (auto const& ddVariable : this->getDdManager().getMetaVariable(metaVariable).getDdVariables()) {
371 summationDdVariables.push_back(ddVariable.getInternalBdd());
372 }
374
375 std::set<storm::expressions::Variable> unionOfMetaVariables = Dd<LibraryType>::joinMetaVariables(*this, otherMatrix);
376 std::set<storm::expressions::Variable> containedMetaVariables;
377 std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), summationMetaVariables.begin(), summationMetaVariables.end(),
378 std::inserter(containedMetaVariables, containedMetaVariables.begin()));
379
380 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.multiplyMatrix(otherMatrix, summationDdVariables), containedMetaVariables);
381}
382
383template<DdType LibraryType, typename ValueType>
385 std::set<storm::expressions::Variable> const& summationMetaVariables) const {
386 // Create the summation variables.
387 std::vector<InternalBdd<LibraryType>> summationDdVariables;
388 for (auto const& metaVariable : summationMetaVariables) {
389 for (auto const& ddVariable : this->getDdManager().getMetaVariable(metaVariable).getDdVariables()) {
390 summationDdVariables.push_back(ddVariable.getInternalBdd());
391 }
392 }
394 std::set<storm::expressions::Variable> unionOfMetaVariables = Dd<LibraryType>::joinMetaVariables(*this, otherMatrix);
395 std::set<storm::expressions::Variable> containedMetaVariables;
396 std::set_difference(unionOfMetaVariables.begin(), unionOfMetaVariables.end(), summationMetaVariables.begin(), summationMetaVariables.end(),
397 std::inserter(containedMetaVariables, containedMetaVariables.begin()));
398
399 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.multiplyMatrix(otherMatrix.getInternalBdd(), summationDdVariables),
400 containedMetaVariables);
401}
403template<DdType LibraryType, typename ValueType>
405 return Bdd<LibraryType>(this->getDdManager(), internalAdd.greater(value), this->getContainedMetaVariables());
406}
407
408template<DdType LibraryType, typename ValueType>
410 return Bdd<LibraryType>(this->getDdManager(), internalAdd.greaterOrEqual(value), this->getContainedMetaVariables());
412
413template<DdType LibraryType, typename ValueType>
415 return Bdd<LibraryType>(this->getDdManager(), internalAdd.less(value), this->getContainedMetaVariables());
416}
417
418template<DdType LibraryType, typename ValueType>
420 return Bdd<LibraryType>(this->getDdManager(), internalAdd.lessOrEqual(value), this->getContainedMetaVariables());
421}
422
423template<DdType LibraryType, typename ValueType>
425 return Bdd<LibraryType>(this->getDdManager(), internalAdd.notZero(), this->getContainedMetaVariables());
426}
427
428template<DdType LibraryType, typename ValueType>
430 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.constrain(constraint), Dd<LibraryType>::joinMetaVariables(*this, constraint));
431}
432
433template<DdType LibraryType, typename ValueType>
435 return Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.restrict(constraint), Dd<LibraryType>::joinMetaVariables(*this, constraint));
436}
437
438template<DdType LibraryType, typename ValueType>
440 return Bdd<LibraryType>(this->getDdManager(), internalAdd.getSupport(), this->getContainedMetaVariables());
441}
442
443template<DdType LibraryType, typename ValueType>
445 std::size_t numberOfDdVariables = 0;
446 for (auto const& metaVariable : this->getContainedMetaVariables()) {
447 numberOfDdVariables += this->getDdManager().getMetaVariable(metaVariable).getNumberOfDdVariables();
449 return internalAdd.getNonZeroCount(numberOfDdVariables);
450}
451
452template<DdType LibraryType, typename ValueType>
454 return internalAdd.getLeafCount();
456
457template<DdType LibraryType, typename ValueType>
459 return internalAdd.getNodeCount();
460}
461
462template<DdType LibraryType, typename ValueType>
464 return internalAdd.getMin();
465}
466
467template<DdType LibraryType, typename ValueType>
469 return internalAdd.getMax();
470}
471
472template<DdType LibraryType, typename ValueType>
473void Add<LibraryType, ValueType>::setValue(storm::expressions::Variable const& metaVariable, int_fast64_t variableValue, ValueType const& targetValue) {
474 std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
475 metaVariableToValueMap.emplace(metaVariable, variableValue);
476 this->setValue(metaVariableToValueMap, targetValue);
477}
478
479template<DdType LibraryType, typename ValueType>
480void Add<LibraryType, ValueType>::setValue(storm::expressions::Variable const& metaVariable1, int_fast64_t variableValue1,
481 storm::expressions::Variable const& metaVariable2, int_fast64_t variableValue2, ValueType const& targetValue) {
482 std::map<storm::expressions::Variable, int_fast64_t> metaVariableToValueMap;
483 metaVariableToValueMap.emplace(metaVariable1, variableValue1);
484 metaVariableToValueMap.emplace(metaVariable2, variableValue2);
485 this->setValue(metaVariableToValueMap, targetValue);
486}
487
488template<DdType LibraryType, typename ValueType>
489void Add<LibraryType, ValueType>::setValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap, ValueType const& targetValue) {
490 Bdd<LibraryType> valueEncoding = this->getDdManager().getBddOne();
491 for (auto const& nameValuePair : metaVariableToValueMap) {
492 valueEncoding &= this->getDdManager().getEncoding(nameValuePair.first, nameValuePair.second);
493 // Also record that the DD now contains the meta variable.
494 this->addMetaVariable(nameValuePair.first);
495 }
496
497 internalAdd = valueEncoding.ite(this->getDdManager().getConstant(targetValue), *this);
498}
499
500template<DdType LibraryType, typename ValueType>
501ValueType Add<LibraryType, ValueType>::getValue(std::map<storm::expressions::Variable, int_fast64_t> const& metaVariableToValueMap) const {
502 std::set<storm::expressions::Variable> remainingMetaVariables(this->getContainedMetaVariables());
503 Bdd<LibraryType> valueEncoding = this->getDdManager().getBddOne();
504 for (auto const& nameValuePair : metaVariableToValueMap) {
505 valueEncoding &= this->getDdManager().getEncoding(nameValuePair.first, nameValuePair.second);
506 if (this->containsMetaVariable(nameValuePair.first)) {
507 remainingMetaVariables.erase(nameValuePair.first);
508 }
509 }
510
511 STORM_LOG_THROW(remainingMetaVariables.empty(), storm::exceptions::InvalidArgumentException,
512 "Cannot evaluate function for which not all inputs were given.");
513
514 Add<LibraryType, ValueType> value = *this * valueEncoding.template toAdd<ValueType>();
515 value = value.sumAbstract(this->getContainedMetaVariables());
516 return value.internalAdd.getValue();
518
519template<DdType LibraryType, typename ValueType>
521 return internalAdd.isOne();
522}
523
524template<DdType LibraryType, typename ValueType>
526 return internalAdd.isZero();
527}
529template<DdType LibraryType, typename ValueType>
531 return internalAdd.isConstant();
532}
533
534template<DdType LibraryType, typename ValueType>
536 return internalAdd.getIndex();
537}
539template<DdType LibraryType, typename ValueType>
541 return internalAdd.getLevel();
542}
543
544template<DdType LibraryType, typename ValueType>
545std::vector<ValueType> Add<LibraryType, ValueType>::toVector() const {
546 return this->toVector(this->createOdd());
547}
548
549template<DdType LibraryType, typename ValueType>
550std::vector<ValueType> Add<LibraryType, ValueType>::toVector(Odd const& rowOdd) const {
551 std::vector<ValueType> result(rowOdd.getTotalOffset());
552 std::vector<uint_fast64_t> ddVariableIndices = this->getSortedVariableIndices();
553 internalAdd.composeWithExplicitVector(rowOdd, ddVariableIndices, result, std::plus<ValueType>());
554 return result;
555}
556
557template<DdType LibraryType, typename ValueType>
559 std::vector<uint_fast64_t> const& rowGroupIndices,
560 std::set<storm::expressions::Variable> const& rowMetaVariables,
561 std::set<storm::expressions::Variable> const& columnMetaVariables,
562 std::set<storm::expressions::Variable> const& groupMetaVariables,
563 storm::dd::Odd const& rowOdd) const {
564 std::vector<uint_fast64_t> ddRowVariableIndices;
565 std::vector<uint_fast64_t> ddColumnVariableIndices;
566 std::vector<uint_fast64_t> ddGroupVariableIndices;
567 std::set<storm::expressions::Variable> rowAndColumnMetaVariables;
568
569 for (auto const& variable : rowMetaVariables) {
570 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
571 for (auto const& ddVariable : metaVariable.getDdVariables()) {
572 ddRowVariableIndices.push_back(ddVariable.getIndex());
573 }
574 rowAndColumnMetaVariables.insert(variable);
575 }
576 std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
577 for (auto const& variable : columnMetaVariables) {
578 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
579 for (auto const& ddVariable : metaVariable.getDdVariables()) {
580 ddColumnVariableIndices.push_back(ddVariable.getIndex());
581 }
582 rowAndColumnMetaVariables.insert(variable);
583 }
584 std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
585 for (auto const& variable : groupMetaVariables) {
586 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
587 for (auto const& ddVariable : metaVariable.getDdVariables()) {
588 ddGroupVariableIndices.push_back(ddVariable.getIndex());
589 }
590 }
591 std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end());
592
593 Bdd<LibraryType> columnVariableCube = Bdd<LibraryType>::getCube(this->getDdManager(), columnMetaVariables);
594
595 // Copy the row group indices so we can modify them.
596 std::vector<uint_fast64_t> mutableRowGroupIndices = rowGroupIndices;
597
598 // Create the explicit vector we need to fill later.
599 std::vector<ValueType> explicitVector(mutableRowGroupIndices.back());
601 // Next, we split the matrix into one for each group. Note that this only works if the group variables are at the very top.
602 std::vector<std::pair<InternalAdd<LibraryType, ValueType>, InternalAdd<LibraryType, ValueType>>> internalAddGroups =
603 matrix.internalAdd.splitIntoGroups(*this, ddGroupVariableIndices);
604 std::vector<std::pair<Add<LibraryType, ValueType>, Add<LibraryType, ValueType>>> groups;
605 for (auto const& internalAdd : internalAddGroups) {
606 groups.push_back(std::make_pair(Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.first, rowAndColumnMetaVariables),
607 Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.second, rowMetaVariables)));
608 }
609
610 std::vector<InternalAdd<LibraryType, uint_fast64_t>> statesWithGroupEnabled(groups.size());
611 for (uint_fast64_t i = 0; i < groups.size(); ++i) {
612 std::pair<Add<LibraryType, ValueType>, Add<LibraryType, ValueType>> const& ddPair = groups[i];
613 Bdd<LibraryType> matrixDdNotZero = ddPair.first.notZero();
614 Bdd<LibraryType> vectorDdNotZero = ddPair.second.notZero();
615
616 ddPair.second.internalAdd.composeWithExplicitVector(rowOdd, ddRowVariableIndices, mutableRowGroupIndices, explicitVector, std::plus<ValueType>());
617
618 InternalAdd<LibraryType, uint_fast64_t> statesWithGroupEnabled =
619 (matrixDdNotZero.existsAbstract(columnMetaVariables) || vectorDdNotZero).template toAdd<uint_fast64_t>();
620 statesWithGroupEnabled.composeWithExplicitVector(rowOdd, ddRowVariableIndices, mutableRowGroupIndices, std::plus<uint_fast64_t>());
621 }
623 return explicitVector;
624}
625
626template<DdType LibraryType, typename ValueType>
628 std::set<storm::expressions::Variable> rowVariables;
629 std::set<storm::expressions::Variable> columnVariables;
630
631 for (auto const& variable : this->getContainedMetaVariables()) {
632 if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
633 columnVariables.insert(variable);
634 } else {
635 rowVariables.insert(variable);
636 }
637 }
638
639 return toMatrix(rowVariables, columnVariables, this->sumAbstract(rowVariables).createOdd(), this->sumAbstract(columnVariables).createOdd());
640}
641
642template<DdType LibraryType, typename ValueType>
644 std::set<storm::expressions::Variable> rowMetaVariables;
645 std::set<storm::expressions::Variable> columnMetaVariables;
646
647 for (auto const& variable : this->getContainedMetaVariables()) {
648 if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
649 columnMetaVariables.insert(variable);
650 } else {
651 rowMetaVariables.insert(variable);
652 }
653 }
654
655 return toMatrix(rowMetaVariables, columnMetaVariables, rowOdd, columnOdd);
656}
657
658template<DdType LibraryType, typename ValueType>
659storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(std::set<storm::expressions::Variable> const& rowMetaVariables,
660 std::set<storm::expressions::Variable> const& columnMetaVariables,
661 storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
662 std::vector<uint_fast64_t> ddRowVariableIndices;
663 std::vector<uint_fast64_t> ddColumnVariableIndices;
664
665 for (auto const& variable : rowMetaVariables) {
666 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
667 for (auto const& ddVariable : metaVariable.getDdVariables()) {
668 ddRowVariableIndices.push_back(ddVariable.getIndex());
669 }
670 }
671 std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
672
673 for (auto const& variable : columnMetaVariables) {
674 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
675 for (auto const& ddVariable : metaVariable.getDdVariables()) {
676 ddColumnVariableIndices.push_back(ddVariable.getIndex());
677 }
678 }
679 std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
680
681 // Prepare the vectors that represent the matrix.
682 std::vector<uint_fast64_t> rowIndications(rowOdd.getTotalOffset() + 1);
683 std::vector<storm::storage::MatrixEntry<uint_fast64_t, ValueType>> columnsAndValues(this->getNonZeroCount());
684
685 // Create a trivial row grouping.
686 std::vector<uint_fast64_t> trivialRowGroupIndices(rowIndications.size());
687 uint_fast64_t i = 0;
688 for (auto& entry : trivialRowGroupIndices) {
689 entry = i;
690 ++i;
691 }
692
693 // Count the number of elements in the rows.
694 rowIndications = this->notZero().template toAdd<uint_fast64_t>().sumAbstract(columnMetaVariables).toVector(rowOdd);
695 rowIndications.emplace_back();
696
697 // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
698 uint_fast64_t tmp = 0;
699 uint_fast64_t tmp2 = 0;
700 for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
701 tmp2 = rowIndications[i];
702 rowIndications[i] = rowIndications[i - 1] + tmp;
703 std::swap(tmp, tmp2);
704 }
705 rowIndications[0] = 0;
706
707 // Now actually fill the entry vector.
708 internalAdd.toMatrixComponents(trivialRowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices,
709 true);
710
711 // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
712 for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
713 rowIndications[i] = rowIndications[i - 1];
714 }
715 rowIndications[0] = 0;
716
717 // Construct matrix and return result.
718 return storm::storage::SparseMatrix<ValueType>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), boost::none);
719}
720
721template<DdType LibraryType, typename ValueType>
722storm::storage::SparseMatrix<ValueType> Add<LibraryType, ValueType>::toMatrix(std::set<storm::expressions::Variable> const& groupMetaVariables,
723 storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
724 std::set<storm::expressions::Variable> rowMetaVariables;
725 std::set<storm::expressions::Variable> columnMetaVariables;
727 for (auto const& variable : this->getContainedMetaVariables()) {
728 // If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables.
729 if (groupMetaVariables.contains(variable)) {
730 continue;
731 }
732
733 if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
734 columnMetaVariables.insert(variable);
735 } else {
736 rowMetaVariables.insert(variable);
737 }
739
740 // Create the canonical row group sizes and build the matrix.
741 return toLabeledMatrix(rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd).matrix;
742}
743
744template<DdType LibraryType, typename ValueType>
746 std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables,
747 std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd,
748 std::vector<std::set<storm::expressions::Variable>> const& labelMetaVariables) const {
749 std::vector<uint_fast64_t> ddRowVariableIndices;
750 std::vector<uint_fast64_t> ddColumnVariableIndices;
751 std::vector<uint_fast64_t> ddGroupVariableIndices;
752 std::vector<storm::storage::BitVector> ddLabelVariableIndicesVector;
753 std::set<storm::expressions::Variable> rowAndColumnMetaVariables;
754 bool buildLabeling = !labelMetaVariables.empty();
755 MatrixAndLabeling result;
756
757 for (auto const& variable : rowMetaVariables) {
758 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
759 for (auto const& ddVariable : metaVariable.getDdVariables()) {
760 ddRowVariableIndices.push_back(ddVariable.getIndex());
761 }
762 rowAndColumnMetaVariables.insert(variable);
763 }
764 std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
765 for (auto const& variable : columnMetaVariables) {
766 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
767 for (auto const& ddVariable : metaVariable.getDdVariables()) {
768 ddColumnVariableIndices.push_back(ddVariable.getIndex());
769 }
770 rowAndColumnMetaVariables.insert(variable);
771 }
772 std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
773 for (auto const& variable : groupMetaVariables) {
774 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
775 for (auto const& ddVariable : metaVariable.getDdVariables()) {
776 ddGroupVariableIndices.push_back(ddVariable.getIndex());
778 }
779 std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end());
780 if (buildLabeling) {
781 for (auto const& labelMetaVariableSet : labelMetaVariables) {
782 std::set<uint64_t> ddLabelVariableIndicesSet;
783 for (auto const& variable : labelMetaVariableSet) {
784 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
785 for (auto const& ddVariable : metaVariable.getDdVariables()) {
786 ddLabelVariableIndicesSet.insert(ddVariable.getIndex());
787 }
788 }
789
790 ddLabelVariableIndicesVector.emplace_back(ddGroupVariableIndices.size());
791 uint64_t position = 0;
792 for (auto const& index : ddGroupVariableIndices) {
793 if (ddLabelVariableIndicesSet.contains(index)) {
794 ddLabelVariableIndicesVector.back().set(position);
795 }
796 ++position;
797 }
798 }
799 }
800
801 Bdd<LibraryType> columnVariableCube = Bdd<LibraryType>::getCube(this->getDdManager(), columnMetaVariables);
802
803 // Start by computing the offsets (in terms of rows) for each row group.
804 Add<LibraryType, uint_fast64_t> stateToNumberOfChoices =
805 this->notZero().existsAbstract(columnMetaVariables).template toAdd<uint_fast64_t>().sumAbstract(groupMetaVariables);
806 std::vector<uint_fast64_t> rowGroupIndices = stateToNumberOfChoices.toVector(rowOdd);
807 rowGroupIndices.resize(rowGroupIndices.size() + 1);
808 uint_fast64_t tmp = 0;
809 uint_fast64_t tmp2 = 0;
810 for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) {
811 tmp2 = rowGroupIndices[i];
812 rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp;
813 std::swap(tmp, tmp2);
814 }
815 rowGroupIndices[0] = 0;
816
817 // Next, we split the matrix into one for each group. Note that this only works if the group variables are
818 // at the very top.
819 std::vector<InternalAdd<LibraryType, ValueType>> internalAddGroups = internalAdd.splitIntoGroups(ddGroupVariableIndices);
820 std::vector<Add<LibraryType, ValueType>> groups;
821 for (auto const& internalAdd : internalAddGroups) {
822 groups.push_back(Add<LibraryType, ValueType>(this->getDdManager(), internalAdd, rowAndColumnMetaVariables));
823 }
824
825 // Create the group labelings if requested.
826 std::vector<std::vector<uint64_t>> groupLabelings;
827 if (buildLabeling) {
828 for (auto const& ddLabelVariableIndices : ddLabelVariableIndicesVector) {
829 groupLabelings.emplace_back(internalAdd.decodeGroupLabels(ddGroupVariableIndices, ddLabelVariableIndices));
830 STORM_LOG_ASSERT(groupLabelings.back().size() == groups.size(), "Mismatching label sizes.");
831 }
832 }
833
834 // Create the actual storage for the non-zero entries.
835 std::vector<storm::storage::MatrixEntry<uint_fast64_t, ValueType>> columnsAndValues(this->getNonZeroCount());
836
837 // Now compute the indices at which the individual rows start.
838 std::vector<uint_fast64_t> rowIndications(rowGroupIndices.back() + 1);
839
840 if (buildLabeling) {
841 for (uint64_t i = 0; i < labelMetaVariables.size(); ++i) {
842 result.labelings.emplace_back(rowGroupIndices.back());
843 }
844 }
845
846 std::vector<InternalAdd<LibraryType, uint_fast64_t>> statesWithGroupEnabled(groups.size());
847 InternalAdd<LibraryType, uint_fast64_t> stateToRowGroupCount = this->getDdManager().template getAddZero<uint_fast64_t>();
848 for (uint_fast64_t i = 0; i < groups.size(); ++i) {
849 auto const& group = groups[i];
850 auto groupNotZero = group.notZero();
851
852 std::vector<uint64_t> tmpRowIndications = groupNotZero.template toAdd<uint_fast64_t>().sumAbstract(columnMetaVariables).toVector(rowOdd);
853 for (uint64_t offset = 0; offset < tmpRowIndications.size(); ++offset) {
854 rowIndications[rowGroupIndices[offset]] += tmpRowIndications[offset];
855 }
856
857 statesWithGroupEnabled[i] = groupNotZero.existsAbstract(columnMetaVariables).template toAdd<uint_fast64_t>();
858 if (buildLabeling) {
859 for (uint64_t j = 0; j < labelMetaVariables.size(); ++j) {
860 uint64_t currentLabel = groupLabelings[j][i];
861 statesWithGroupEnabled[i].forEach(rowOdd, ddRowVariableIndices,
862 [currentLabel, &rowGroupIndices, &result, j](uint64_t const& offset, uint_fast64_t const& value) {
863 result.labelings[j][rowGroupIndices[offset]] = currentLabel;
864 });
865 }
866 }
867 statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
868 }
869
870 // Since we modified the rowGroupIndices, we need to restore the correct values.
871 stateToNumberOfChoices.internalAdd.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus<uint_fast64_t>());
872
873 // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
874 tmp = 0;
875 tmp2 = 0;
876 for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
877 tmp2 = rowIndications[i];
878 rowIndications[i] = rowIndications[i - 1] + tmp;
879 std::swap(tmp, tmp2);
880 }
881 rowIndications[0] = 0;
882
883 // Now actually fill the entry vector.
884 for (uint_fast64_t i = 0; i < groups.size(); ++i) {
885 auto const& group = groups[i];
886
887 group.internalAdd.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices,
888 ddColumnVariableIndices, true);
889
890 statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
891 }
892
893 // Since we modified the rowGroupIndices, we need to restore the correct values.
894 stateToNumberOfChoices.internalAdd.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus<uint_fast64_t>());
895
896 // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
897 for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
898 rowIndications[i] = rowIndications[i - 1];
899 }
900 rowIndications[0] = 0;
901
902 // Move-construct matrix and return.
903 result.matrix =
904 storm::storage::SparseMatrix<ValueType>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices));
905 return result;
906}
907
908template<DdType LibraryType, typename ValueType>
909std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> Add<LibraryType, ValueType>::toMatrixVector(
910 storm::dd::Add<LibraryType, ValueType> const& vector, std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd const& rowOdd,
911 storm::dd::Odd const& columnOdd) const {
912 std::set<storm::expressions::Variable> rowMetaVariables;
913 std::set<storm::expressions::Variable> columnMetaVariables;
914
915 for (auto const& variable : this->getContainedMetaVariables()) {
916 // If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables.
917 if (groupMetaVariables.contains(variable)) {
918 continue;
919 }
920
921 if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
922 columnMetaVariables.insert(variable);
923 } else {
924 rowMetaVariables.insert(variable);
925 }
926 }
927
928 // Create the canonical row group sizes and build the matrix.
929 return toMatrixVector(vector, rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
930}
931
932template<DdType LibraryType, typename ValueType>
933std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> Add<LibraryType, ValueType>::toMatrixVector(
934 storm::dd::Add<LibraryType, ValueType> const& vector, std::set<storm::expressions::Variable> const& rowMetaVariables,
935 std::set<storm::expressions::Variable> const& columnMetaVariables, std::set<storm::expressions::Variable> const& groupMetaVariables,
936 storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
937 // Count how many choices each row group has.
938 std::vector<uint_fast64_t> rowGroupIndices = (this->notZero().existsAbstract(columnMetaVariables) || vector.notZero())
939 .template toAdd<uint_fast64_t>()
940 .sumAbstract(groupMetaVariables)
941 .toVector(rowOdd);
942 return toMatrixVector(std::move(rowGroupIndices), vector, rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
943}
944
945template<DdType LibraryType, typename ValueType>
946std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<ValueType>> Add<LibraryType, ValueType>::toMatrixVector(
947 std::vector<uint_fast64_t>&& rowGroupIndices, storm::dd::Add<LibraryType, ValueType> const& vector,
948 std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables,
949 std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
950 auto resultAsVector = toMatrixVectors(std::move(rowGroupIndices), {vector}, rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
951 return std::make_pair(resultAsVector.first, resultAsVector.second.front());
952}
953
954template<DdType LibraryType, typename ValueType>
955std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<std::vector<ValueType>>> Add<LibraryType, ValueType>::toMatrixVectors(
956 std::vector<storm::dd::Add<LibraryType, ValueType>> const& vectors, std::set<storm::expressions::Variable> const& groupMetaVariables,
957 storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
958 std::set<storm::expressions::Variable> rowMetaVariables;
959 std::set<storm::expressions::Variable> columnMetaVariables;
960
961 for (auto const& variable : this->getContainedMetaVariables()) {
962 // If the meta variable is a group meta variable, we do not insert it into the set of row/column meta variables.
963 if (groupMetaVariables.contains(variable)) {
964 continue;
965 }
966
967 if (variable.getName().size() > 0 && variable.getName().back() == '\'') {
968 columnMetaVariables.insert(variable);
969 } else {
970 rowMetaVariables.insert(variable);
971 }
972 }
973 // Count how many choices each row group has.
974 Bdd<LibraryType> vectorsNotZero = this->getDdManager().getBddZero();
975 for (auto const& v : vectors) {
976 vectorsNotZero |= v.notZero();
977 }
978 std::vector<uint_fast64_t> rowGroupIndices = (this->notZero().existsAbstract(columnMetaVariables) || vectorsNotZero)
979 .template toAdd<uint_fast64_t>()
980 .sumAbstract(groupMetaVariables)
981 .toVector(rowOdd);
982 return toMatrixVectors(std::move(rowGroupIndices), vectors, rowMetaVariables, columnMetaVariables, groupMetaVariables, rowOdd, columnOdd);
983}
984
985template<DdType LibraryType, typename ValueType>
986std::pair<storm::storage::SparseMatrix<ValueType>, std::vector<std::vector<ValueType>>> Add<LibraryType, ValueType>::toMatrixVectors(
987 std::vector<uint_fast64_t>&& rowGroupIndices, std::vector<storm::dd::Add<LibraryType, ValueType>> const& vectors,
988 std::set<storm::expressions::Variable> const& rowMetaVariables, std::set<storm::expressions::Variable> const& columnMetaVariables,
989 std::set<storm::expressions::Variable> const& groupMetaVariables, storm::dd::Odd const& rowOdd, storm::dd::Odd const& columnOdd) const {
990 std::vector<uint_fast64_t> ddRowVariableIndices;
991 std::vector<uint_fast64_t> ddColumnVariableIndices;
992 std::vector<uint_fast64_t> ddGroupVariableIndices;
993 std::set<storm::expressions::Variable> rowAndColumnMetaVariables;
994
995 for (auto const& variable : rowMetaVariables) {
996 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
997 for (auto const& ddVariable : metaVariable.getDdVariables()) {
998 ddRowVariableIndices.push_back(ddVariable.getIndex());
999 }
1000 rowAndColumnMetaVariables.insert(variable);
1001 }
1002 std::sort(ddRowVariableIndices.begin(), ddRowVariableIndices.end());
1003 for (auto const& variable : columnMetaVariables) {
1004 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
1005 for (auto const& ddVariable : metaVariable.getDdVariables()) {
1006 ddColumnVariableIndices.push_back(ddVariable.getIndex());
1007 }
1008 rowAndColumnMetaVariables.insert(variable);
1009 }
1010 std::sort(ddColumnVariableIndices.begin(), ddColumnVariableIndices.end());
1011 for (auto const& variable : groupMetaVariables) {
1012 DdMetaVariable<LibraryType> const& metaVariable = this->getDdManager().getMetaVariable(variable);
1013 for (auto const& ddVariable : metaVariable.getDdVariables()) {
1014 ddGroupVariableIndices.push_back(ddVariable.getIndex());
1015 }
1016 }
1017 std::sort(ddGroupVariableIndices.begin(), ddGroupVariableIndices.end());
1018
1019 Bdd<LibraryType> columnVariableCube = Bdd<LibraryType>::getCube(this->getDdManager(), columnMetaVariables);
1020
1021 // Transform the row group sizes to the actual row group indices.
1022 rowGroupIndices.resize(rowGroupIndices.size() + 1);
1023 uint_fast64_t tmp = 0;
1024 uint_fast64_t tmp2 = 0;
1025 for (uint_fast64_t i = 1; i < rowGroupIndices.size(); ++i) {
1026 tmp2 = rowGroupIndices[i];
1027 rowGroupIndices[i] = rowGroupIndices[i - 1] + tmp;
1028 std::swap(tmp, tmp2);
1029 }
1030 rowGroupIndices[0] = 0;
1031
1032 // Create the explicit vectors we need to fill later.
1033 std::vector<std::vector<ValueType>> explicitVectors(vectors.size());
1034 for (auto& v : explicitVectors) {
1035 v.resize(rowGroupIndices.back());
1036 }
1037
1038 // Next, we split the matrix into one for each group. Note that this only works if the group variables are at the very top.
1039 std::vector<std::vector<Add<LibraryType, ValueType>>> groups;
1040 if (vectors.size() == 1) {
1041 // This version potentially has slightly reduced overhead
1042 std::vector<std::pair<InternalAdd<LibraryType, ValueType>, InternalAdd<LibraryType, ValueType>>> internalAddGroups =
1043 internalAdd.splitIntoGroups(vectors.front(), ddGroupVariableIndices);
1044 for (auto const& internalAdd : internalAddGroups) {
1045 groups.push_back({Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.second, rowMetaVariables),
1046 Add<LibraryType, ValueType>(this->getDdManager(), internalAdd.first, rowAndColumnMetaVariables)});
1047 }
1048 } else {
1049 std::vector<InternalAdd<LibraryType, ValueType>> internalVectors;
1050 for (Add<LibraryType, ValueType> const& v : vectors) {
1051 internalVectors.push_back(v.getInternalAdd());
1052 }
1053 std::vector<std::vector<InternalAdd<LibraryType, ValueType>>> internalAddGroups = internalAdd.splitIntoGroups(internalVectors, ddGroupVariableIndices);
1054 for (auto const& internalAddGroup : internalAddGroups) {
1055 STORM_LOG_ASSERT(internalAddGroup.size() == vectors.size() + 1, "Unexpected group size.");
1056 std::vector<Add<LibraryType, ValueType>> group;
1057 for (uint64_t vectorIndex = 0; vectorIndex < vectors.size(); ++vectorIndex) {
1058 group.push_back(Add<LibraryType, ValueType>(this->getDdManager(), internalAddGroup[vectorIndex], rowMetaVariables));
1059 }
1060 // The last group member corresponds to the matrix.
1061 group.push_back(Add<LibraryType, ValueType>(this->getDdManager(), internalAddGroup.back(), rowAndColumnMetaVariables));
1062 groups.push_back(std::move(group));
1063 }
1064 }
1065
1066 // Create the actual storage for the non-zero entries.
1067 std::vector<storm::storage::MatrixEntry<uint_fast64_t, ValueType>> columnsAndValues(this->getNonZeroCount());
1068
1069 // Now compute the indices at which the individual rows start.
1070 std::vector<uint_fast64_t> rowIndications(rowGroupIndices.back() + 1);
1071
1072 std::vector<InternalAdd<LibraryType, uint_fast64_t>> statesWithGroupEnabled(groups.size());
1073 InternalAdd<LibraryType, uint_fast64_t> stateToRowGroupCount = this->getDdManager().template getAddZero<uint_fast64_t>();
1074 for (uint_fast64_t i = 0; i < groups.size(); ++i) {
1075 std::vector<Add<LibraryType, ValueType>> const& group = groups[i];
1076 Bdd<LibraryType> matrixDdNotZero = group.back().notZero();
1077
1078 std::vector<uint64_t> tmpRowIndications = matrixDdNotZero.template toAdd<uint_fast64_t>().sumAbstract(columnMetaVariables).toVector(rowOdd);
1079 for (uint64_t offset = 0; offset < tmpRowIndications.size(); ++offset) {
1080 rowIndications[rowGroupIndices[offset]] += tmpRowIndications[offset];
1081 }
1082
1083 Bdd<LibraryType> vectorDdNotZero = this->getDdManager().getBddZero();
1084 for (uint64_t vectorIndex = 0; vectorIndex < vectors.size(); ++vectorIndex) {
1085 vectorDdNotZero |= group[vectorIndex].notZero();
1086 group[vectorIndex].internalAdd.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, explicitVectors[vectorIndex],
1087 std::plus<ValueType>());
1088 }
1089
1090 statesWithGroupEnabled[i] = (matrixDdNotZero.existsAbstract(columnMetaVariables) || vectorDdNotZero).template toAdd<uint_fast64_t>();
1091 stateToRowGroupCount += statesWithGroupEnabled[i];
1092 statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
1093 }
1094
1095 // Since we modified the rowGroupIndices, we need to restore the correct values.
1096 stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus<uint_fast64_t>());
1097
1098 // Now that we computed the number of entries in each row, compute the corresponding offsets in the entry vector.
1099 tmp = 0;
1100 tmp2 = 0;
1101 for (uint_fast64_t i = 1; i < rowIndications.size(); ++i) {
1102 tmp2 = rowIndications[i];
1103 rowIndications[i] = rowIndications[i - 1] + tmp;
1104 std::swap(tmp, tmp2);
1105 }
1106 rowIndications[0] = 0;
1107
1108 // Now actually fill the entry vector.
1109 for (uint_fast64_t i = 0; i < groups.size(); ++i) {
1110 auto const& dd = groups[i].back();
1111
1112 dd.internalAdd.toMatrixComponents(rowGroupIndices, rowIndications, columnsAndValues, rowOdd, columnOdd, ddRowVariableIndices, ddColumnVariableIndices,
1113 true);
1114 statesWithGroupEnabled[i].composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::plus<uint_fast64_t>());
1115 }
1116
1117 // Since we modified the rowGroupIndices, we need to restore the correct values.
1118 stateToRowGroupCount.composeWithExplicitVector(rowOdd, ddRowVariableIndices, rowGroupIndices, std::minus<uint_fast64_t>());
1119
1120 // Since the last call to toMatrixRec modified the rowIndications, we need to restore the correct values.
1121 for (uint_fast64_t i = rowIndications.size() - 1; i > 0; --i) {
1122 rowIndications[i] = rowIndications[i - 1];
1123 }
1124 rowIndications[0] = 0;
1125
1126 return std::make_pair(
1127 storm::storage::SparseMatrix<ValueType>(columnOdd.getTotalOffset(), std::move(rowIndications), std::move(columnsAndValues), std::move(rowGroupIndices)),
1128 std::move(explicitVectors));
1129}
1130
1131template<DdType LibraryType, typename ValueType>
1132void Add<LibraryType, ValueType>::exportToDot(std::string const& filename, bool showVariablesIfPossible) const {
1133 internalAdd.exportToDot(filename, this->getDdManager().getDdVariableNames(), showVariablesIfPossible);
1134}
1135
1136template<DdType LibraryType, typename ValueType>
1137void Add<LibraryType, ValueType>::exportToText(std::string const& filename) const {
1138 internalAdd.exportToText(filename);
1139}
1140
1141template<DdType LibraryType, typename ValueType>
1143 uint_fast64_t numberOfDdVariables = 0;
1144 for (auto const& metaVariable : this->getContainedMetaVariables()) {
1145 auto const& ddMetaVariable = this->getDdManager().getMetaVariable(metaVariable);
1146 numberOfDdVariables += ddMetaVariable.getNumberOfDdVariables();
1147 }
1148
1149 return internalAdd.begin(this->getDdManager(), Bdd<LibraryType>::getCube(this->getDdManager(), this->getContainedMetaVariables()).getInternalBdd(),
1150 numberOfDdVariables, this->getContainedMetaVariables(), enumerateDontCareMetaVariables);
1151}
1152
1153template<DdType LibraryType, typename ValueType>
1155 return internalAdd.end(this->getDdManager());
1156}
1157
1158template<DdType LibraryType, typename ValueType>
1159std::ostream& operator<<(std::ostream& out, Add<LibraryType, ValueType> const& add) {
1160 out << "ADD [" << add.getInternalAdd().getStringId() << "] with " << add.getNonZeroCount() << " nnz, " << add.getNodeCount() << " nodes, "
1161 << add.getLeafCount() << " leaves\n";
1162 std::vector<std::string> variableNames;
1163 for (auto const& variable : add.getContainedMetaVariables()) {
1164 variableNames.push_back(variable.getName());
1165 }
1166 out << "contained variables: " << boost::algorithm::join(variableNames, ", ") << '\n';
1167 return out;
1168}
1169
1170template<DdType LibraryType, typename ValueType>
1172 Odd const& odd, std::set<storm::expressions::Variable> const& metaVariables) {
1173 return Add<LibraryType, ValueType>(ddManager,
1174 InternalAdd<LibraryType, ValueType>::fromVector(ddManager.getInternalDdManagerPointer(), values, odd,
1175 ddManager.getSortedVariableIndices(metaVariables)),
1176 metaVariables);
1177}
1178
1179template<DdType LibraryType, typename ValueType>
1181 return this->notZero();
1182}
1183
1184template<DdType LibraryType, typename ValueType>
1186 return internalAdd.createOdd(this->getSortedVariableIndices());
1187}
1188
1189template<DdType LibraryType, typename ValueType>
1193
1194template<DdType LibraryType, typename ValueType>
1198
1199template<DdType LibraryType, typename ValueType>
1201 return internalAdd;
1202}
1203
1204template<DdType LibraryType, typename ValueType>
1205template<typename TargetValueType>
1206std::enable_if_t<std::is_same_v<TargetValueType, ValueType>, Add<LibraryType, TargetValueType>> Add<LibraryType, ValueType>::toValueType() const {
1207 return *this;
1208}
1209
1210template<DdType LibraryType, typename ValueType>
1211template<typename TargetValueType>
1212std::enable_if_t<!std::is_same_v<TargetValueType, ValueType>, Add<LibraryType, TargetValueType>> Add<LibraryType, ValueType>::toValueType() const {
1213 return Add<LibraryType, TargetValueType>(this->getDdManager(), internalAdd.template toValueType<TargetValueType>(), this->getContainedMetaVariables());
1214}
1215
1217template std::ostream& operator<<(std::ostream& out, Add<storm::dd::DdType::CUDD, double> const& add);
1219
1221template std::ostream& operator<<(std::ostream& out, Add<storm::dd::DdType::Sylvan, double> const& add);
1223
1225template std::ostream& operator<<(std::ostream& out, Add<storm::dd::DdType::CUDD, storm::RationalNumber> const& add);
1226
1228template std::ostream& operator<<(std::ostream& out, Add<storm::dd::DdType::Sylvan, storm::RationalNumber> const& add);
1230
1234
1236 const;
1240} // namespace dd
1241} // namespace storm
Definition DdTest.cpp:38
friend class Add
Definition Add.h:36
bool isOne() const
Retrieves whether this ADD represents the constant one function.
Definition Add.cpp:520
ValueType getMax() const
Retrieves the highest function value of any encoding.
Definition Add.cpp:468
void exportToDot(std::string const &filename, bool showVariablesIfPossible=true) const override
Exports the DD to the given file in the dot format.
Definition Add.cpp:1132
InternalAdd< LibraryType, ValueType > const & getInternalAdd() const
Retrieves the internal ADD.
Definition Add.cpp:1190
virtual uint_fast64_t getLevel() const override
Retrieves the level of the topmost variable in the DD.
Definition Add.cpp:540
ValueType getMin() const
Retrieves the lowest function value of any encoding.
Definition Add.cpp:463
InternalDdManager< LibraryType > const & getInternalDdManager() const
Retrieves the internal ADD.
Definition Add.cpp:1195
virtual uint_fast64_t getNonZeroCount() const override
Retrieves the number of encodings that are mapped to a non-zero value.
Definition Add.cpp:444
Add< LibraryType, ValueType > sumAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Sum-abstracts from the given meta variables.
Definition Add.cpp:171
virtual uint_fast64_t getNodeCount() const override
Retrieves the number of nodes necessary to represent the DD.
Definition Add.cpp:458
Odd createOdd() const
Creates an ODD based on the current ADD.
Definition Add.cpp:1185
AddIterator< LibraryType, ValueType > end() const
Retrieves an iterator that points past the end of the container.
Definition Add.cpp:1154
virtual uint_fast64_t getIndex() const override
Retrieves the index of the topmost variable in the DD.
Definition Add.cpp:535
bool isZero() const
Retrieves whether this ADD represents the constant zero function.
Definition Add.cpp:525
virtual uint_fast64_t getLeafCount() const override
Retrieves the number of leaves of the ADD.
Definition Add.cpp:453
bool isConstant() const
Retrieves whether this ADD represents a constant function.
Definition Add.cpp:530
bool equalModuloPrecision(Add< LibraryType, ValueType > const &other, ValueType const &precision, bool relative=true) const
Checks whether the current and the given ADD represent the same function modulo some given precision.
Definition Add.cpp:204
virtual void exportToText(std::string const &filename) const override
Exports the DD to the given file in the dot format.
Definition Add.cpp:1137
Bdd< LibraryType > notZero() const
Computes a BDD that represents the function in which all assignments with a function value unequal to...
Definition Add.cpp:424
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
Definition Bdd.cpp:172
static Bdd< LibraryType > getEncoding(DdManager< LibraryType > const &ddManager, uint64_t targetOffset, storm::dd::Odd const &odd, std::set< storm::expressions::Variable > const &metaVariables)
Constructs the BDD representation of the encoding with the given offset.
Definition Bdd.cpp:88
storm::storage::BitVector toVector(storm::dd::Odd const &rowOdd) const
Converts the BDD to a bit vector.
Definition Bdd.cpp:491
Bdd< LibraryType > ite(Bdd< LibraryType > const &thenBdd, Bdd< LibraryType > const &elseBdd) const
Performs an if-then-else with the given operands, i.e.
Definition Bdd.cpp:107
InternalBdd< LibraryType > const & getInternalBdd() const
Retrieves the internal BDD.
Definition Bdd.cpp:570
std::set< storm::expressions::Variable > const & getContainedMetaVariables() const
Retrieves the set of all meta variables contained in the DD.
Definition Dd.cpp:28
std::vector< uint_fast64_t > getSortedVariableIndices() const
Retrieves the (sorted) list of the variable indices of the DD variables given by the meta variable se...
std::size_t getNumberOfDdVariables() const
Retrieves the number of DD variables for this meta variable.
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
Definition Odd.cpp:44
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
Converts the ADD to a row-grouped (sparse) matrix.
Definition Add.h:668