18#include "storm-config.h"
22template<
typename ValueType>
27template<
typename ValueType>
29 : ddManager(ddManager), sylvanMtbdd(sylvanMtbdd) {
33template<
typename ValueType>
35 STORM_LOG_ASSERT(mtbdd_isleaf(node),
"Expected leaf, but got variable " << mtbdd_getvar(node) <<
".");
37 bool negated = mtbdd_hascomp(node);
38 MTBDD n = mtbdd_regular(node);
40 if (std::is_same<ValueType, double>::value) {
42 return negated ? -mtbdd_getdouble(n) : mtbdd_getdouble(n);
43 }
else if (std::is_same<ValueType, uint_fast64_t>::value) {
45 return negated ? -mtbdd_getint64(node) : mtbdd_getint64(node);
48 else if (std::is_same<ValueType, storm::RationalFunction>::value) {
49 STORM_LOG_ASSERT(
false,
"Non-specialized version of getValue() called for storm::RationalFunction value.");
59 STORM_LOG_ASSERT(mtbdd_isleaf(node),
"Expected leaf, but got variable " << mtbdd_getvar(node) <<
".");
61 bool negated = mtbdd_hascomp(node);
63 STORM_LOG_ASSERT(mtbdd_gettype(node) == sylvan_storm_rational_number_get_type(),
"Expected a storm::RationalNumber value.");
64 storm_rational_number_ptr ptr = (storm_rational_number_ptr)mtbdd_getstorm_rational_number_ptr(node);
65 storm::RationalNumber* rationalNumber = (storm::RationalNumber*)(ptr);
67 return negated ? -(*rationalNumber) : (*rationalNumber);
73 STORM_LOG_ASSERT(mtbdd_isleaf(node),
"Expected leaf, but got variable " << mtbdd_getvar(node) <<
".");
75 bool negated = mtbdd_hascomp(node);
77 STORM_LOG_ASSERT(mtbdd_gettype(node) == sylvan_storm_rational_function_get_type(),
"Expected a storm::RationalFunction value.");
78 uint64_t value = mtbdd_getvalue(node);
79 storm_rational_function_ptr ptr = (storm_rational_function_ptr)value;
83 return negated ? -(*rationalFunction) : (*rationalFunction);
87template<
typename ValueType>
89 return this->sylvanMtbdd == other.sylvanMtbdd;
92template<
typename ValueType>
94 return this->sylvanMtbdd != other.sylvanMtbdd;
97template<
typename ValueType>
108#ifdef STORM_HAVE_CARL
116template<
typename ValueType>
118 this->sylvanMtbdd = this->sylvanMtbdd.Plus(other.sylvanMtbdd);
125 this->sylvanMtbdd = this->sylvanMtbdd.PlusRN(other.sylvanMtbdd);
129#ifdef STORM_HAVE_CARL
133 this->sylvanMtbdd = this->sylvanMtbdd.PlusRF(other.sylvanMtbdd);
138template<
typename ValueType>
149#ifdef STORM_HAVE_CARL
157template<
typename ValueType>
159 this->sylvanMtbdd = this->sylvanMtbdd.Times(other.sylvanMtbdd);
166 this->sylvanMtbdd = this->sylvanMtbdd.TimesRN(other.sylvanMtbdd);
170#ifdef STORM_HAVE_CARL
174 this->sylvanMtbdd = this->sylvanMtbdd.TimesRF(other.sylvanMtbdd);
179template<
typename ValueType>
190#ifdef STORM_HAVE_CARL
198template<
typename ValueType>
200 this->sylvanMtbdd = this->sylvanMtbdd.Minus(other.sylvanMtbdd);
207 this->sylvanMtbdd = this->sylvanMtbdd.MinusRN(other.sylvanMtbdd);
211#ifdef STORM_HAVE_CARL
215 this->sylvanMtbdd = this->sylvanMtbdd.MinusRF(other.sylvanMtbdd);
220template<
typename ValueType>
231#ifdef STORM_HAVE_CARL
239template<
typename ValueType>
241 this->sylvanMtbdd = this->sylvanMtbdd.Divide(other.sylvanMtbdd);
248 this->sylvanMtbdd = this->sylvanMtbdd.DivideRN(other.sylvanMtbdd);
252#ifdef STORM_HAVE_CARL
256 this->sylvanMtbdd = this->sylvanMtbdd.DivideRF(other.sylvanMtbdd);
261template<
typename ValueType>
271#ifdef STORM_HAVE_CARL
279template<
typename ValueType>
281 return !this->equals(other);
284template<
typename ValueType>
294#ifdef STORM_HAVE_CARL
302template<
typename ValueType>
313#ifdef STORM_HAVE_CARL
321template<
typename ValueType>
323 return !this->lessOrEqual(other);
326template<
typename ValueType>
328 return !this->less(other);
331template<
typename ValueType>
342#ifdef STORM_HAVE_CARL
350template<
typename ValueType>
361#ifdef STORM_HAVE_CARL
365 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Operation (mod) not supported by rational functions.");
369template<
typename ValueType>
377 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Operation (logxy) not supported by rational numbers.");
380#ifdef STORM_HAVE_CARL
384 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Operation (logxy) not supported by rational functions.");
388template<
typename ValueType>
398#ifdef STORM_HAVE_CARL
405template<
typename ValueType>
415#ifdef STORM_HAVE_CARL
422template<
typename ValueType>
427#ifdef STORM_HAVE_CARL
430 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Operation not supported.");
434template<
typename ValueType>
445#ifdef STORM_HAVE_CARL
453template<
typename ValueType>
464#ifdef STORM_HAVE_CARL
472template<
typename ValueType>
473template<
typename TargetValueType>
475 if (std::is_same<TargetValueType, ValueType>::value) {
478 STORM_LOG_THROW(
false, storm::exceptions::InvalidOperationException,
"Cannot convert this ADD to the target type.");
493#ifdef STORM_HAVE_CARL
501template<
typename ValueType>
512#ifdef STORM_HAVE_CARL
520template<
typename ValueType>
525template<
typename ValueType>
541#ifdef STORM_HAVE_CARL
549template<
typename ValueType>
554template<
typename ValueType>
570#ifdef STORM_HAVE_CARL
578template<
typename ValueType>
580 bool relative)
const {
582 return this->sylvanMtbdd.EqualNormRel(other.sylvanMtbdd, precision);
584 return this->sylvanMtbdd.EqualNorm(other.sylvanMtbdd, precision);
588#ifdef STORM_HAVE_CARL
591 storm::RationalNumber
const& precision,
bool relative)
const {
593 return this->sylvanMtbdd.EqualNormRelRN(other.sylvanMtbdd, precision);
595 return this->sylvanMtbdd.EqualNormRN(other.sylvanMtbdd, precision);
603 return this->sylvanMtbdd.EqualNormRelRF(other.sylvanMtbdd, precision);
605 return this->sylvanMtbdd.EqualNormRF(other.sylvanMtbdd, precision);
610template<
typename ValueType>
613 std::vector<uint32_t> fromIndices;
614 std::vector<uint32_t> toIndices;
615 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
616 fromIndices.push_back(it1->getIndex());
617 fromIndices.push_back(it2->getIndex());
618 toIndices.push_back(it2->getIndex());
619 toIndices.push_back(it1->getIndex());
624template<
typename ValueType>
627 std::vector<uint32_t> fromIndices;
628 std::vector<uint32_t> toIndices;
629 for (
auto it1 = from.begin(), ite1 = from.end(), it2 = to.begin(); it1 != ite1; ++it1, ++it2) {
630 fromIndices.push_back(it1->getIndex());
631 toIndices.push_back(it2->getIndex());
636template<
typename ValueType>
640 for (
auto const& ddVariable : summationDdVariables) {
641 summationVariables &= ddVariable;
647#ifdef STORM_HAVE_CARL
652 for (
auto const& ddVariable : summationDdVariables) {
653 summationVariables &= ddVariable;
656 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(ddManager,
657 this->sylvanMtbdd.AndExistsRF(otherMatrix.sylvanMtbdd, summationVariables.getSylvanBdd()));
665 for (
auto const& ddVariable : summationDdVariables) {
666 summationVariables &= ddVariable;
670 this->sylvanMtbdd.AndExistsRN(otherMatrix.sylvanMtbdd, summationVariables.getSylvanBdd()));
673template<
typename ValueType>
677 for (
auto const& ddVariable : summationDdVariables) {
678 summationVariables &= ddVariable;
682 ddManager, this->sylvanMtbdd.AndExists(sylvan::Bdd(otherMatrix.getSylvanBdd().GetBDD()), summationVariables.getSylvanBdd()));
685#ifdef STORM_HAVE_CARL
690 for (
auto const& ddVariable : summationDdVariables) {
691 summationVariables &= ddVariable;
694 return InternalAdd<DdType::Sylvan, storm::RationalFunction>(
695 ddManager, this->sylvanMtbdd.AndExistsRF(sylvan::Bdd(otherMatrix.getSylvanBdd().GetBDD()), summationVariables.getSylvanBdd()));
703 for (
auto const& ddVariable : summationDdVariables) {
704 summationVariables &= ddVariable;
708 ddManager, this->sylvanMtbdd.AndExistsRN(sylvan::Bdd(otherMatrix.getSylvanBdd().GetBDD()), summationVariables.getSylvanBdd()));
711template<
typename ValueType>
721#ifdef STORM_HAVE_CARL
728template<
typename ValueType>
738#ifdef STORM_HAVE_CARL
745template<
typename ValueType>
747 return !this->greaterOrEqual(value);
750template<
typename ValueType>
752 return !this->greater(value);
755template<
typename ValueType>
760template<
typename ValueType>
762 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Operation (constrain) not yet implemented.");
765template<
typename ValueType>
767 STORM_LOG_THROW(
false, storm::exceptions::NotImplementedException,
"Operation (restrict) not yet implemented.");
770template<
typename ValueType>
775template<
typename ValueType>
777 if (numberOfDdVariables == 0) {
780 return static_cast<uint_fast64_t
>(this->sylvanMtbdd.NonZeroCount(numberOfDdVariables));
783template<
typename ValueType>
785 return static_cast<uint_fast64_t
>(this->sylvanMtbdd.CountLeaves());
788template<
typename ValueType>
790 return static_cast<uint_fast64_t
>(this->sylvanMtbdd.NodeCount());
793template<
typename ValueType>
795 return getValue(this->sylvanMtbdd.Minimum().GetMTBDD());
800 return getValue(this->sylvanMtbdd.MinimumRN().GetMTBDD());
803#ifdef STORM_HAVE_CARL
806 return getValue(this->sylvanMtbdd.MinimumRF().GetMTBDD());
810template<
typename ValueType>
812 return getValue(this->sylvanMtbdd.Maximum().GetMTBDD());
817 return getValue(this->sylvanMtbdd.MaximumRN().GetMTBDD());
820#ifdef STORM_HAVE_CARL
823 return getValue(this->sylvanMtbdd.MaximumRF().GetMTBDD());
827template<
typename ValueType>
829 return getValue(this->sylvanMtbdd.GetMTBDD());
832template<
typename ValueType>
834 return *
this == ddManager->getAddOne<ValueType>();
837template<
typename ValueType>
839 return *
this == ddManager->getAddZero<ValueType>();
842template<
typename ValueType>
844 return this->sylvanMtbdd.isTerminal();
847template<
typename ValueType>
849 return static_cast<uint_fast64_t
>(this->sylvanMtbdd.TopVar());
852template<
typename ValueType>
854 return this->getIndex();
857template<
typename ValueType>
860 FILE* filePointer = fopen(filename.c_str(),
"a+");
862 if (filePointer ==
nullptr) {
865 this->sylvanMtbdd.PrintDot(filePointer);
870template<
typename ValueType>
873 FILE* filePointer = fopen(filename.c_str(),
"a+");
875 if (filePointer ==
nullptr) {
878 this->sylvanMtbdd.PrintText(filePointer);
883template<
typename ValueType>
886 uint_fast64_t numberOfDdVariables,
887 std::set<storm::expressions::Variable>
const& metaVariables,
888 bool enumerateDontCareMetaVariables)
const {
890 &metaVariables, enumerateDontCareMetaVariables);
893template<
typename ValueType>
898template<
typename ValueType>
901 std::vector<std::unordered_map<BDD, std::shared_ptr<Odd>>> uniqueTableForLevels(ddVariableIndices.size() + 1);
904 std::shared_ptr<Odd> rootOdd =
905 createOddRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), 0, ddVariableIndices.size(), ddVariableIndices, uniqueTableForLevels);
908 return Odd(*rootOdd);
911template<
typename ValueType>
913 std::vector<uint_fast64_t>
const& ddVariableIndices,
914 std::vector<std::unordered_map<BDD, std::shared_ptr<Odd>>>& uniqueTableForLevels) {
916 auto const& iterator = uniqueTableForLevels[currentLevel].find(dd);
917 if (iterator != uniqueTableForLevels[currentLevel].end()) {
918 return iterator->second;
924 if (currentLevel == maxLevel) {
925 uint_fast64_t elseOffset = 0;
926 uint_fast64_t thenOffset = 0;
931 if (!mtbdd_iszero(dd)) {
935 auto oddNode = std::make_shared<Odd>(
nullptr, elseOffset,
nullptr, thenOffset);
936 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
938 }
else if (mtbdd_isleaf(dd) || ddVariableIndices[currentLevel] < mtbdd_getvar(dd)) {
941 std::shared_ptr<Odd> elseNode = createOddRec(dd, currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
942 std::shared_ptr<Odd> thenNode = elseNode;
943 auto oddNode = std::make_shared<Odd>(elseNode, elseNode->getElseOffset() + elseNode->getThenOffset(), thenNode,
944 thenNode->getElseOffset() + thenNode->getThenOffset());
945 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
949 std::shared_ptr<Odd> elseNode = createOddRec(mtbdd_regular(mtbdd_getlow(dd)), currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
950 std::shared_ptr<Odd> thenNode = createOddRec(mtbdd_regular(mtbdd_gethigh(dd)), currentLevel + 1, maxLevel, ddVariableIndices, uniqueTableForLevels);
952 uint_fast64_t totalElseOffset = elseNode->getElseOffset() + elseNode->getThenOffset();
953 uint_fast64_t totalThenOffset = thenNode->getElseOffset() + thenNode->getThenOffset();
955 auto oddNode = std::make_shared<Odd>(elseNode, totalElseOffset, thenNode, totalThenOffset);
956 uniqueTableForLevels[currentLevel].emplace(dd, oddNode);
962template<
typename ValueType>
967template<
typename ValueType>
969 std::vector<ValueType>& targetVector,
970 std::function<ValueType(ValueType
const&, ValueType
const&)>
const& function)
const {
971 forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices,
972 [&function, &targetVector](uint64_t
const& offset, ValueType
const& value) { targetVector[offset] = function(targetVector[offset], value); });
975template<
typename ValueType>
977 std::vector<uint_fast64_t>
const& offsets, std::vector<ValueType>& targetVector,
978 std::function<ValueType(ValueType
const&, ValueType
const&)>
const& function)
const {
979 forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices,
980 [&function, &targetVector, &offsets](uint64_t
const& offset, ValueType
const& value) {
981 ValueType& targetValue = targetVector[offsets[offset]];
982 targetValue = function(targetValue, value);
986template<
typename ValueType>
988 std::function<
void(uint64_t
const&, ValueType
const&)>
const& function)
const {
989 forEachRec(this->getSylvanMtbdd().GetMTBDD(), 0, ddVariableIndices.size(), 0, odd, ddVariableIndices, function);
992template<
typename ValueType>
994 Odd const& odd, std::vector<uint_fast64_t>
const& ddVariableIndices,
995 std::function<
void(uint64_t
const&, ValueType
const&)>
const& function)
const {
997 if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) {
1002 if (currentLevel == maxLevel) {
1003 function(currentOffset, getValue(dd));
1004 }
else if (mtbdd_isleaf(dd) || ddVariableIndices[currentLevel] < mtbdd_getvar(dd)) {
1007 forEachRec(dd, currentLevel + 1, maxLevel, currentOffset, odd.
getElseSuccessor(), ddVariableIndices, function);
1011 MTBDD thenNode = mtbdd_gethigh(dd);
1012 MTBDD elseNode = mtbdd_getlow(dd);
1014 forEachRec(elseNode, currentLevel + 1, maxLevel, currentOffset, odd.
getElseSuccessor(), ddVariableIndices, function);
1019template<
typename ValueType>
1022 std::vector<uint64_t> result;
1023 decodeGroupLabelsRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), result, ddGroupVariableIndices, ddLabelVariableIndices, 0,
1024 ddGroupVariableIndices.
size(), 0);
1028template<
typename ValueType>
1030 std::vector<uint_fast64_t>
const& ddGroupVariableIndices,
1032 uint_fast64_t maxLevel, uint64_t label)
const {
1034 if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) {
1038 if (currentLevel == maxLevel) {
1039 labels.push_back(label);
1041 uint64_t elseLabel = label;
1042 uint64_t thenLabel = label;
1044 if (ddLabelVariableIndices.
get(currentLevel)) {
1046 thenLabel = (thenLabel << 1) | 1;
1049 if (mtbdd_isleaf(dd) || ddGroupVariableIndices[currentLevel] < mtbdd_getvar(dd)) {
1050 decodeGroupLabelsRec(dd, labels, ddGroupVariableIndices, ddLabelVariableIndices, currentLevel + 1, maxLevel, elseLabel);
1051 decodeGroupLabelsRec(dd, labels, ddGroupVariableIndices, ddLabelVariableIndices, currentLevel + 1, maxLevel, thenLabel);
1054 MTBDD thenDdNode = mtbdd_gethigh(dd);
1055 MTBDD elseDdNode = mtbdd_getlow(dd);
1057 decodeGroupLabelsRec(mtbdd_regular(elseDdNode), labels, ddGroupVariableIndices, ddLabelVariableIndices, currentLevel + 1, maxLevel, elseLabel);
1058 decodeGroupLabelsRec(mtbdd_regular(thenDdNode), labels, ddGroupVariableIndices, ddLabelVariableIndices, currentLevel + 1, maxLevel, thenLabel);
1063template<
typename ValueType>
1065 std::vector<uint_fast64_t>
const& ddGroupVariableIndices)
const {
1066 std::vector<InternalAdd<DdType::Sylvan, ValueType>> result;
1067 splitIntoGroupsRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()), result, ddGroupVariableIndices, 0,
1068 ddGroupVariableIndices.size());
1072template<
typename ValueType>
1076 splitIntoGroupsRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()),
1077 mtbdd_regular(vector.getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(vector.getSylvanMtbdd().GetMTBDD()), result, ddGroupVariableIndices, 0,
1078 ddGroupVariableIndices.size());
1082template<
typename ValueType>
1085 std::vector<std::vector<InternalAdd<DdType::Sylvan, ValueType>>> result;
1086 std::vector<MTBDD> dds;
1088 for (
auto const& vector : vectors) {
1089 negatedDds.
set(dds.size(), mtbdd_hascomp(vector.getSylvanMtbdd().GetMTBDD()));
1090 dds.push_back(mtbdd_regular(vector.getSylvanMtbdd().GetMTBDD()));
1092 dds.push_back(this->getSylvanMtbdd().GetMTBDD());
1093 negatedDds.
set(vectors.size(), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()));
1095 splitIntoGroupsRec(dds, negatedDds, result, ddGroupVariableIndices, 0, ddGroupVariableIndices.
size());
1099template<
typename ValueType>
1101 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
1102 uint_fast64_t maxLevel)
const {
1104 if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) {
1108 if (currentLevel == maxLevel) {
1109 groups.push_back(InternalAdd<DdType::Sylvan, ValueType>(ddManager, negated ? sylvan::Mtbdd(dd).Negate() : sylvan::Mtbdd(dd)));
1110 }
else if (mtbdd_isleaf(dd) || ddGroupVariableIndices[currentLevel] < mtbdd_getvar(dd)) {
1111 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1112 splitIntoGroupsRec(dd, negated, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1115 MTBDD thenDdNode = mtbdd_gethigh(dd);
1116 MTBDD elseDdNode = mtbdd_getlow(dd);
1119 bool elseComplemented = mtbdd_hascomp(elseDdNode) ^ negated;
1120 bool thenComplemented = mtbdd_hascomp(thenDdNode) ^ negated;
1124 splitIntoGroupsRec(mtbdd_regular(elseDdNode), elseComplemented, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1125 splitIntoGroupsRec(mtbdd_regular(thenDdNode), thenComplemented, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1129template<
typename ValueType>
1130void InternalAdd<DdType::Sylvan, ValueType>::splitIntoGroupsRec(
1131 MTBDD dd1,
bool negated1, MTBDD dd2,
bool negated2,
1132 std::vector<std::pair<InternalAdd<DdType::Sylvan, ValueType>, InternalAdd<DdType::Sylvan, ValueType>>>& groups,
1133 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel, uint_fast64_t maxLevel)
const {
1135 if (mtbdd_isleaf(dd1) && mtbdd_isleaf(dd2) && mtbdd_iszero(dd1) && mtbdd_iszero(dd2)) {
1139 if (currentLevel == maxLevel) {
1140 groups.push_back(std::make_pair(InternalAdd<DdType::Sylvan, ValueType>(ddManager, negated1 ? sylvan::Mtbdd(dd1).Negate() : sylvan::Mtbdd(dd1)),
1141 InternalAdd<
DdType::
Sylvan,
ValueType>(ddManager, negated2 ? sylvan::Mtbdd(dd2).Negate() : sylvan::Mtbdd(dd2))));
1142 }
else if (mtbdd_isleaf(dd1) || ddGroupVariableIndices[currentLevel] < mtbdd_getvar(dd1)) {
1143 if (mtbdd_isleaf(dd2) || ddGroupVariableIndices[currentLevel] < mtbdd_getvar(dd2)) {
1144 splitIntoGroupsRec(dd1, negated1, dd2, negated2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1145 splitIntoGroupsRec(dd1, negated1, dd2, negated2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1147 MTBDD dd2ThenNode = mtbdd_gethigh(dd2);
1148 MTBDD dd2ElseNode = mtbdd_getlow(dd2);
1151 bool elseComplemented = mtbdd_hascomp(dd2ElseNode) ^ negated2;
1152 bool thenComplemented = mtbdd_hascomp(dd2ThenNode) ^ negated2;
1154 splitIntoGroupsRec(dd1, negated1, mtbdd_regular(dd2ThenNode), thenComplemented, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1155 splitIntoGroupsRec(dd1, negated1, mtbdd_regular(dd2ElseNode), elseComplemented, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1157 }
else if (mtbdd_isleaf(dd2) || ddGroupVariableIndices[currentLevel] < mtbdd_getvar(dd2)) {
1158 MTBDD dd1ThenNode = mtbdd_gethigh(dd1);
1159 MTBDD dd1ElseNode = mtbdd_getlow(dd1);
1162 bool elseComplemented = mtbdd_hascomp(dd1ElseNode) ^ negated1;
1163 bool thenComplemented = mtbdd_hascomp(dd1ThenNode) ^ negated1;
1165 splitIntoGroupsRec(mtbdd_regular(dd1ThenNode), thenComplemented, dd2, negated2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1166 splitIntoGroupsRec(mtbdd_regular(dd1ElseNode), elseComplemented, dd2, negated2, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1168 MTBDD dd1ThenNode = mtbdd_gethigh(dd1);
1169 MTBDD dd1ElseNode = mtbdd_getlow(dd1);
1170 MTBDD dd2ThenNode = mtbdd_gethigh(dd2);
1171 MTBDD dd2ElseNode = mtbdd_getlow(dd2);
1174 bool dd1ElseComplemented = mtbdd_hascomp(dd1ElseNode) ^ negated1;
1175 bool dd1ThenComplemented = mtbdd_hascomp(dd1ThenNode) ^ negated1;
1176 bool dd2ElseComplemented = mtbdd_hascomp(dd2ElseNode) ^ negated2;
1177 bool dd2ThenComplemented = mtbdd_hascomp(dd2ThenNode) ^ negated2;
1179 splitIntoGroupsRec(mtbdd_regular(dd1ThenNode), dd1ThenComplemented, mtbdd_regular(dd2ThenNode), dd2ThenComplemented, groups, ddGroupVariableIndices,
1180 currentLevel + 1, maxLevel);
1181 splitIntoGroupsRec(mtbdd_regular(dd1ElseNode), dd1ElseComplemented, mtbdd_regular(dd2ElseNode), dd2ElseComplemented, groups, ddGroupVariableIndices,
1182 currentLevel + 1, maxLevel);
1186template<
typename ValueType>
1187void InternalAdd<DdType::Sylvan, ValueType>::splitIntoGroupsRec(std::vector<MTBDD>
const& dds,
storm::storage::BitVector const& negatedDds,
1188 std::vector<std::vector<InternalAdd<DdType::Sylvan, ValueType>>>& groups,
1189 std::vector<uint_fast64_t>
const& ddGroupVariableIndices, uint_fast64_t currentLevel,
1190 uint_fast64_t maxLevel)
const {
1193 bool emptyDd =
true;
1194 for (
auto const& dd : dds) {
1195 if (!(mtbdd_isleaf(dd) && mtbdd_iszero(dd))) {
1205 if (currentLevel == maxLevel) {
1206 std::vector<InternalAdd<DdType::Sylvan, ValueType>> newGroup;
1207 for (uint64_t ddIndex = 0; ddIndex < dds.size(); ++ddIndex) {
1208 newGroup.emplace_back(ddManager, negatedDds.
get(ddIndex) ? sylvan::Mtbdd(dds[ddIndex]).Negate() : sylvan::Mtbdd(dds[ddIndex]));
1210 groups.push_back(std::move(newGroup));
1212 std::vector<MTBDD> thenSubDds(dds), elseSubDds(dds);
1214 for (uint64_t ddIndex = 0; ddIndex < dds.size(); ++ddIndex) {
1215 auto const& dd = dds[ddIndex];
1216 if (!mtbdd_isleaf(dd) && ddGroupVariableIndices[currentLevel] == mtbdd_getvar(dd)) {
1217 MTBDD ddThenNode = mtbdd_gethigh(dd);
1218 MTBDD ddElseNode = mtbdd_getlow(dd);
1219 thenSubDds[ddIndex] = mtbdd_regular(ddThenNode);
1220 elseSubDds[ddIndex] = mtbdd_regular(ddElseNode);
1222 thenNegatedSubDds.set(ddIndex, mtbdd_hascomp(ddThenNode) ^ negatedDds.
get(ddIndex));
1223 elseNegatedSubDds.set(ddIndex, mtbdd_hascomp(ddElseNode) ^ negatedDds.
get(ddIndex));
1226 splitIntoGroupsRec(thenSubDds, thenNegatedSubDds, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1227 splitIntoGroupsRec(elseSubDds, elseNegatedSubDds, groups, ddGroupVariableIndices, currentLevel + 1, maxLevel);
1231template<
typename ValueType>
1234 Odd const& rowOdd,
Odd const& columnOdd, std::vector<uint_fast64_t>
const& ddRowVariableIndices,
1235 std::vector<uint_fast64_t>
const& ddColumnVariableIndices,
bool writeValues)
const {
1236 return toMatrixComponentsRec(mtbdd_regular(this->getSylvanMtbdd().GetMTBDD()), mtbdd_hascomp(this->getSylvanMtbdd().GetMTBDD()), rowGroupIndices,
1237 rowIndications, columnsAndValues, rowOdd, columnOdd, 0, 0, ddRowVariableIndices.size() + ddColumnVariableIndices.size(), 0, 0,
1238 ddRowVariableIndices, ddColumnVariableIndices, writeValues);
1241template<
typename ValueType>
1243 std::vector<uint_fast64_t>& rowIndications,
1245 Odd const& rowOdd,
Odd const& columnOdd, uint_fast64_t currentRowLevel,
1246 uint_fast64_t currentColumnLevel, uint_fast64_t maxLevel, uint_fast64_t currentRowOffset,
1247 uint_fast64_t currentColumnOffset, std::vector<uint_fast64_t>
const& ddRowVariableIndices,
1248 std::vector<uint_fast64_t>
const& ddColumnVariableIndices,
bool generateValues)
const {
1250 if (mtbdd_isleaf(dd) && mtbdd_iszero(dd)) {
1255 if (currentRowLevel + currentColumnLevel == maxLevel) {
1256 if (generateValues) {
1257 columnsAndValues[rowIndications[rowGroupOffsets[currentRowOffset]]] =
1260 ++rowIndications[rowGroupOffsets[currentRowOffset]];
1267 if (mtbdd_isleaf(dd) || ddColumnVariableIndices[currentColumnLevel] < mtbdd_getvar(dd)) {
1268 elseElse = elseThen = thenElse = thenThen = dd;
1269 }
else if (ddRowVariableIndices[currentColumnLevel] < mtbdd_getvar(dd)) {
1270 elseElse = thenElse = mtbdd_getlow(dd);
1271 elseThen = thenThen = mtbdd_gethigh(dd);
1273 MTBDD elseNode = mtbdd_getlow(dd);
1274 if (mtbdd_isleaf(elseNode) || ddColumnVariableIndices[currentColumnLevel] < mtbdd_getvar(elseNode)) {
1275 elseElse = elseThen = elseNode;
1277 elseElse = mtbdd_getlow(elseNode);
1278 elseThen = mtbdd_gethigh(elseNode);
1281 MTBDD thenNode = mtbdd_gethigh(dd);
1282 if (mtbdd_isleaf(thenNode) || ddColumnVariableIndices[currentColumnLevel] < mtbdd_getvar(thenNode)) {
1283 thenElse = thenThen = thenNode;
1285 thenElse = mtbdd_getlow(thenNode);
1286 thenThen = mtbdd_gethigh(thenNode);
1291 toMatrixComponentsRec(mtbdd_regular(elseElse), mtbdd_hascomp(elseElse) ^ negated, rowGroupOffsets, rowIndications, columnsAndValues,
1293 currentColumnOffset, ddRowVariableIndices, ddColumnVariableIndices, generateValues);
1295 toMatrixComponentsRec(mtbdd_regular(elseThen), mtbdd_hascomp(elseThen) ^ negated, rowGroupOffsets, rowIndications, columnsAndValues,
1297 currentColumnOffset + columnOdd.
getElseOffset(), ddRowVariableIndices, ddColumnVariableIndices, generateValues);
1299 toMatrixComponentsRec(mtbdd_regular(thenElse), mtbdd_hascomp(thenElse) ^ negated, rowGroupOffsets, rowIndications, columnsAndValues,
1301 currentRowOffset + rowOdd.
getElseOffset(), currentColumnOffset, ddRowVariableIndices, ddColumnVariableIndices, generateValues);
1303 toMatrixComponentsRec(mtbdd_regular(thenThen), mtbdd_hascomp(thenThen) ^ negated, rowGroupOffsets, rowIndications, columnsAndValues,
1306 ddColumnVariableIndices, generateValues);
1310template<
typename ValueType>
1313 std::vector<uint_fast64_t>
const& ddVariableIndices) {
1314 uint_fast64_t offset = 0;
1318template<
typename ValueType>
1320 std::vector<ValueType>
const& values,
Odd const& odd,
1321 std::vector<uint_fast64_t>
const& ddVariableIndices) {
1322 if (currentLevel == maxLevel) {
1327 return getLeaf(values[currentOffset++]);
1329 return getLeaf(storm::utility::zero<ValueType>());
1334 return getLeaf(storm::utility::zero<ValueType>());
1338 MTBDD elseSuccessor;
1340 elseSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, values, odd.
getElseSuccessor(), ddVariableIndices);
1342 elseSuccessor = getLeaf(storm::utility::zero<ValueType>());
1344 mtbdd_refs_push(elseSuccessor);
1347 MTBDD thenSuccessor;
1349 thenSuccessor = fromVectorRec(currentOffset, currentLevel + 1, maxLevel, values, odd.
getThenSuccessor(), ddVariableIndices);
1351 thenSuccessor = getLeaf(storm::utility::zero<ValueType>());
1353 mtbdd_refs_push(thenSuccessor);
1356 MTBDD currentVar = mtbdd_makenode(ddVariableIndices[currentLevel], mtbdd_false, mtbdd_true);
1357 mtbdd_refs_push(thenSuccessor);
1358 MTBDD result = mtbdd_ite(currentVar, thenSuccessor, elseSuccessor);
1367template<
typename ValueType>
1368MTBDD InternalAdd<DdType::Sylvan, ValueType>::getLeaf(
double value) {
1369 return mtbdd_double(value);
1372template<
typename ValueType>
1373MTBDD InternalAdd<DdType::Sylvan, ValueType>::getLeaf(uint_fast64_t value) {
1374 return mtbdd_int64(value);
1377template<
typename ValueType>
1379 storm_rational_function_ptr ptr = (storm_rational_function_ptr)(&value);
1380 return mtbdd_storm_rational_function(ptr);
1383template<
typename ValueType>
1384MTBDD InternalAdd<DdType::Sylvan, ValueType>::getLeaf(storm::RationalNumber
const& value) {
1385 storm_rational_function_ptr ptr = (storm_rational_number_ptr)(&value);
1386 return mtbdd_storm_rational_number(ptr);
1389template<
typename ValueType>
1394template<
typename ValueType>
1396 std::stringstream ss;
1397 ss << this->getSylvanMtbdd().GetMTBDD();
1406#ifdef STORM_HAVE_CARL
InternalAdd< DdType::Sylvan, double > toValueType() const
InternalAdd< DdType::Sylvan, storm::RationalNumber > operator+(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > multiplyMatrix(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &otherMatrix, std::vector< InternalBdd< DdType::Sylvan > > const &summationDdVariables) const
storm::RationalNumber getValue(MTBDD const &node)
InternalBdd< DdType::CUDD > lessOrEqual(storm::RationalNumber const &value) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > maximum(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
storm::RationalNumber getMin() const
InternalAdd< DdType::Sylvan, storm::RationalNumber > & operator+=(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other)
InternalAdd< DdType::Sylvan, storm::RationalNumber > & operator-=(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other)
InternalAdd< DdType::Sylvan, storm::RationalNumber > operator*(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > & operator/=(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other)
InternalBdd< DdType::CUDD > greaterOrEqual(storm::RationalNumber const &value) const
InternalBdd< DdType::Sylvan > maxAbstractRepresentative(InternalBdd< DdType::Sylvan > const &cube) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > & operator*=(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other)
InternalBdd< DdType::Sylvan > equals(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
storm::RationalNumber getMax() const
InternalBdd< DdType::Sylvan > minAbstractRepresentative(InternalBdd< DdType::Sylvan > const &cube) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > operator-(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > ceil() const
InternalAdd< DdType::Sylvan, storm::RationalNumber > sumAbstract(InternalBdd< DdType::Sylvan > const &cube) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > floor() const
InternalAdd< DdType::Sylvan, storm::RationalNumber > pow(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
bool equalModuloPrecision(InternalAdd< DdType::CUDD, storm::RationalNumber > const &, storm::RationalNumber const &, bool) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > maxAbstract(InternalBdd< DdType::Sylvan > const &cube) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > minAbstract(InternalBdd< DdType::Sylvan > const &cube) const
InternalBdd< DdType::CUDD > less(storm::RationalNumber const &value) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > logxy(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &) const
DdNode * fromVectorRec(::DdManager *manager, uint_fast64_t ¤tOffset, uint_fast64_t currentLevel, uint_fast64_t maxLevel, std::vector< storm::RationalNumber > const &values, Odd const &odd, std::vector< uint_fast64_t > const &ddVariableIndices)
InternalAdd< DdType::Sylvan, storm::RationalNumber > operator/(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > minimum(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalAdd< DdType::Sylvan, storm::RationalNumber > mod(InternalAdd< DdType::Sylvan, storm::RationalNumber > const &other) const
InternalBdd< DdType::CUDD > greater(storm::RationalNumber const &value) const
Odd const & getThenSuccessor() const
Retrieves the then-successor of this ODD node.
uint_fast64_t getElseOffset() const
Retrieves the else-offset of this ODD node.
Odd const & getElseSuccessor() const
Retrieves the else-successor of this ODD node.
uint_fast64_t getThenOffset() const
Retrieves the then-offset of this ODD node.
A bit vector that is internally represented as a vector of 64-bit values.
void set(uint_fast64_t index, bool value=true)
Sets the given truth value at the given index.
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
#define STORM_LOG_ERROR(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SFTBDDChecker::ValueType ValueType