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