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