3#pragma GCC diagnostic push
4#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
5#include <parallel_hashmap/phmap.h>
6#pragma GCC diagnostic pop
30namespace bisimulation {
32template<storm::dd::DdType DdType>
35template<storm::dd::DdType DdType>
67 this->ddman = this->internalDdManager->getCuddManager().getManager();
70 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a "
71 "version of Storm with CUDD support.");
80 this->internalDdManager,
81 cudd::BDD(this->internalDdManager->getCuddManager(), this->getRepresentativesRec(this->partitionBdd.getInternalBdd().getCuddDdNode(),
82 this->rowVariablesCube.getInternalBdd().getCuddDdNode()))),
86 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a "
87 "version of Storm with CUDD support.");
93 DdNodePtr getRepresentativesRec(DdNodePtr partitionNode, DdNodePtr stateVariablesCube) {
94 if (partitionNode == Cudd_ReadLogicZero(ddman)) {
99 if (visitedNodes.find(partitionNode) != visitedNodes.end()) {
100 return Cudd_ReadLogicZero(ddman);
104 if (Cudd_IsConstant(stateVariablesCube)) {
105 visitedNodes.emplace(partitionNode,
true);
106 return Cudd_ReadOne(ddman);
108 bool skipped =
false;
109 DdNodePtr elsePartitionNode;
110 DdNodePtr thenPartitionNode;
111 if (Cudd_NodeReadIndex(partitionNode) == Cudd_NodeReadIndex(stateVariablesCube)) {
112 elsePartitionNode = Cudd_E(partitionNode);
113 thenPartitionNode = Cudd_T(partitionNode);
115 if (Cudd_IsComplement(partitionNode)) {
116 elsePartitionNode = Cudd_Not(elsePartitionNode);
117 thenPartitionNode = Cudd_Not(thenPartitionNode);
120 elsePartitionNode = thenPartitionNode = partitionNode;
125 visitedNodes.emplace(partitionNode,
true);
129 DdNodePtr elseResult = getRepresentativesRec(elsePartitionNode, Cudd_T(stateVariablesCube));
130 Cudd_Ref(elseResult);
132 DdNodePtr thenResult =
nullptr;
134 thenResult = getRepresentativesRec(thenPartitionNode, Cudd_T(stateVariablesCube));
135 Cudd_Ref(thenResult);
137 if (thenResult == elseResult) {
138 Cudd_Deref(elseResult);
139 Cudd_Deref(thenResult);
142 bool complement = Cudd_IsComplement(thenResult);
143 auto result = cuddUniqueInter(ddman, Cudd_NodeReadIndex(stateVariablesCube), Cudd_Regular(thenResult),
144 complement ? Cudd_Not(elseResult) : elseResult);
145 Cudd_Deref(elseResult);
146 Cudd_Deref(thenResult);
147 return complement ? Cudd_Not(result) : result;
151 if (elseResult == Cudd_ReadLogicZero(ddman)) {
154 result = Cudd_Not(cuddUniqueInter(ddman, Cudd_NodeReadIndex(stateVariablesCube), Cudd_ReadOne(ddman), Cudd_Not(elseResult)));
156 Cudd_Deref(elseResult);
163 phmap::flat_hash_map<DdNode const*, bool> visitedNodes;
172#ifndef STORM_HAVE_SYLVAN
174 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
175 "version of Storm with Sylvan support.");
181#ifdef STORM_HAVE_SYLVAN
185 this->internalDdManager, sylvan::Bdd(this->getRepresentativesRec(this->partitionBdd.getInternalBdd().getSylvanBdd().GetBDD(),
186 this->rowVariablesCube.getInternalBdd().getSylvanBdd().GetBDD()))),
190 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
191 "version of Storm with Sylvan support.");
196#ifdef STORM_HAVE_SYLVAN
197 BDD getRepresentativesRec(BDD partitionNode, BDD stateVariablesCube) {
198 if (partitionNode == sylvan_false) {
203 if (visitedNodes.find(partitionNode) != visitedNodes.end()) {
208 if (sylvan_isconst(stateVariablesCube)) {
209 visitedNodes.emplace(partitionNode,
true);
212 bool skipped =
false;
213 BDD elsePartitionNode;
214 BDD thenPartitionNode;
215 if (sylvan_bdd_matches_variable_index(partitionNode, sylvan_var(stateVariablesCube))) {
216 elsePartitionNode = sylvan_low(partitionNode);
217 thenPartitionNode = sylvan_high(partitionNode);
219 elsePartitionNode = thenPartitionNode = partitionNode;
224 visitedNodes.emplace(partitionNode,
true);
228 BDD elseResult = getRepresentativesRec(elsePartitionNode, sylvan_high(stateVariablesCube));
229 mtbdd_refs_push(elseResult);
233 thenResult = getRepresentativesRec(thenPartitionNode, sylvan_high(stateVariablesCube));
234 mtbdd_refs_push(thenResult);
236 if (thenResult == elseResult) {
240 auto result = sylvan_makenode(sylvan_var(stateVariablesCube), elseResult, thenResult);
246 if (elseResult == sylvan_false) {
249 result = sylvan_makenode(sylvan_var(stateVariablesCube), elseResult, sylvan_false);
257 phmap::flat_hash_map<BDD, bool> visitedNodes;
261template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType = ValueType>
264template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType = ValueType>
325 std::vector<ExportValueType> reorderedValues(valueVector.size());
326 for (uint64_t pos = 0; pos < valueVector.size(); ++pos) {
329 return reorderedValues;
340 .toVector(this->
odd);
351 std::sort(row.begin(), row.end(),
360 [
this](uint64_t first, uint64_t second) { return this->rowToState[first] < this->rowToState[second]; });
363 uint64_t rowCounter = 0;
377 for (
auto const& entry : row) {
378 builder.
addNextValue(rowCounter, entry.getColumn(), entry.getValue());
393 return builder.
build();
396 void addMatrixEntry(uint64_t row, uint64_t column, ExportValueType
const& value) {
443 std::vector<std::vector<storm::storage::MatrixEntry<uint_fast64_t, ExportValueType>>>
matrixEntries;
452template<
typename ValueType>
455#ifdef STORM_HAVE_CUDD
460 ddman(this->manager.getInternalDdManager().getCuddManager().getManager()) {
461 this->createBlockToOffsetMapping();
469 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a "
470 "version of Storm with CUDD support.");
476#ifdef STORM_HAVE_CUDD
478 this->createMatrixEntryStorage();
479 extractTransitionMatrixRec(matrix.
getInternalAdd().getCuddDdNode(), this->isNondeterministic ? this->nondeterminismOdd : this->odd, 0,
480 this->partitionBdd.getInternalBdd().getCuddDdNode(), this->representatives.getInternalBdd().getCuddDdNode(),
481 this->allSourceVariablesCube.getInternalBdd().getCuddDdNode(),
482 this->nondeterminismVariablesCube.getInternalBdd().getCuddDdNode(), this->isNondeterministic ? &this->odd : nullptr, 0);
483 return this->createMatrixFromEntries();
486 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a "
487 "version of Storm with CUDD support.");
493#ifdef STORM_HAVE_CUDD
495 extractVectorRec(vector.
getInternalAdd().getCuddDdNode(), this->representatives.getInternalBdd().getCuddDdNode(),
500 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a "
501 "version of Storm with CUDD support.");
504#ifdef STORM_HAVE_CUDD
505 void createBlockToOffsetMapping() {
506 this->createBlockToOffsetMappingRec(this->partitionBdd.
getInternalBdd().getCuddDdNode(), this->representatives.getInternalBdd().getCuddDdNode(),
507 this->rowVariablesCube.getInternalBdd().getCuddDdNode(), this->odd, 0);
509 "Mismatching block-to-offset mapping: " << blockToOffset.size() <<
" vs. " << this->numberOfBlocks <<
".");
512 void createBlockToOffsetMappingRec(DdNodePtr partitionNode, DdNodePtr representativesNode, DdNodePtr variables,
storm::dd::Odd const& odd,
514 STORM_LOG_ASSERT(partitionNode != Cudd_ReadLogicZero(ddman) || representativesNode == Cudd_ReadLogicZero(ddman),
515 "Expected representative to be zero if the partition is zero.");
516 if (representativesNode == Cudd_ReadLogicZero(ddman) || partitionNode == Cudd_ReadLogicZero(ddman)) {
520 if (Cudd_IsConstant(variables)) {
522 STORM_LOG_ASSERT(blockToOffset.find(partitionNode) == blockToOffset.end(),
"Duplicate entry.");
523 blockToOffset[partitionNode] = offset;
526 DdNodePtr partitionT;
527 DdNodePtr partitionE;
528 if (Cudd_NodeReadIndex(partitionNode) == Cudd_NodeReadIndex(variables)) {
529 partitionT = Cudd_T(partitionNode);
530 partitionE = Cudd_E(partitionNode);
532 if (Cudd_IsComplement(partitionNode)) {
533 partitionE = Cudd_Not(partitionE);
534 partitionT = Cudd_Not(partitionT);
537 partitionT = partitionE = partitionNode;
540 DdNodePtr representativesT;
541 DdNodePtr representativesE;
542 if (Cudd_NodeReadIndex(representativesNode) == Cudd_NodeReadIndex(variables)) {
543 representativesT = Cudd_T(representativesNode);
544 representativesE = Cudd_E(representativesNode);
546 if (Cudd_IsComplement(representativesNode)) {
547 representativesE = Cudd_Not(representativesE);
548 representativesT = Cudd_Not(representativesT);
551 representativesT = representativesE = representativesNode;
554 createBlockToOffsetMappingRec(partitionE, representativesE, Cudd_T(variables), odd.
getElseSuccessor(), offset);
559 void extractVectorRec(DdNodePtr vector, DdNodePtr representativesNode, DdNodePtr variables,
storm::dd::Odd const& odd, uint64_t offset,
560 std::vector<ValueType>& result) {
561 if (representativesNode == Cudd_ReadLogicZero(ddman) || vector == Cudd_ReadZero(ddman)) {
565 if (Cudd_IsConstant(variables)) {
566 result[offset] = Cudd_V(vector);
570 if (Cudd_NodeReadIndex(vector) == Cudd_NodeReadIndex(variables)) {
571 vectorT = Cudd_T(vector);
572 vectorE = Cudd_E(vector);
574 vectorT = vectorE = vector;
577 DdNodePtr representativesT;
578 DdNodePtr representativesE;
579 if (Cudd_NodeReadIndex(representativesNode) == Cudd_NodeReadIndex(variables)) {
580 representativesT = Cudd_T(representativesNode);
581 representativesE = Cudd_E(representativesNode);
583 if (Cudd_IsComplement(representativesNode)) {
584 representativesT = Cudd_Not(representativesT);
585 representativesE = Cudd_Not(representativesE);
588 representativesT = representativesE = representativesNode;
591 extractVectorRec(vectorE, representativesE, Cudd_T(variables), odd.
getElseSuccessor(), offset, result);
596 void extractTransitionMatrixRec(DdNodePtr transitionMatrixNode,
storm::dd::Odd const& sourceOdd, uint64_t sourceOffset, DdNodePtr targetPartitionNode,
597 DdNodePtr representativesNode, DdNodePtr variables, DdNodePtr nondeterminismVariables,
storm::dd::Odd const* stateOdd,
598 uint64_t stateOffset) {
601 if (transitionMatrixNode == Cudd_ReadZero(ddman) || representativesNode == Cudd_ReadLogicZero(ddman)) {
606 if (Cudd_IsConstant(variables)) {
607 STORM_LOG_ASSERT(Cudd_IsConstant(transitionMatrixNode),
"Expected constant node.");
608 this->addMatrixEntry(sourceOffset, blockToOffset.at(targetPartitionNode), Cudd_V(transitionMatrixNode));
610 this->assignRowToState(sourceOffset, stateOffset);
614 bool nextVariableIsNondeterminismVariable =
615 !Cudd_IsConstant(nondeterminismVariables) && Cudd_NodeReadIndex(nondeterminismVariables) == Cudd_NodeReadIndex(variables);
617 if (nextVariableIsNondeterminismVariable) {
622 if (Cudd_NodeReadIndex(transitionMatrixNode) == Cudd_NodeReadIndex(variables)) {
623 t = Cudd_T(transitionMatrixNode);
624 e = Cudd_E(transitionMatrixNode);
626 t = e = transitionMatrixNode;
630 extractTransitionMatrixRec(e, sourceOdd.
getElseSuccessor(), sourceOffset, targetPartitionNode, representativesNode, Cudd_T(variables),
631 Cudd_T(nondeterminismVariables), stateOdd, stateOffset);
632 extractTransitionMatrixRec(t, sourceOdd.
getThenSuccessor(), sourceOffset + sourceOdd.
getElseOffset(), targetPartitionNode, representativesNode,
633 Cudd_T(variables), Cudd_T(nondeterminismVariables), stateOdd, stateOffset);
641 if (Cudd_NodeReadIndex(transitionMatrixNode) == Cudd_NodeReadIndex(variables)) {
643 t = Cudd_T(transitionMatrixNode);
644 e = Cudd_E(transitionMatrixNode);
646 t = e = transitionMatrixNode;
649 if (Cudd_NodeReadIndex(t) == Cudd_NodeReadIndex(variables) + 1) {
658 if (Cudd_NodeReadIndex(e) == Cudd_NodeReadIndex(variables) + 1) {
673 if (Cudd_NodeReadIndex(targetPartitionNode) == Cudd_NodeReadIndex(variables)) {
675 targetT = Cudd_T(targetPartitionNode);
676 targetE = Cudd_E(targetPartitionNode);
678 if (Cudd_IsComplement(targetPartitionNode)) {
679 targetT = Cudd_Not(targetT);
680 targetE = Cudd_Not(targetE);
684 targetT = targetE = targetPartitionNode;
687 DdNodePtr representativesT;
688 DdNodePtr representativesE;
689 if (Cudd_NodeReadIndex(representativesNode) == Cudd_NodeReadIndex(variables)) {
691 representativesT = Cudd_T(representativesNode);
692 representativesE = Cudd_E(representativesNode);
695 representativesT = representativesE = representativesNode;
698 if (representativesT != representativesE && Cudd_IsComplement(representativesNode)) {
699 representativesT = Cudd_Not(representativesT);
700 representativesE = Cudd_Not(representativesE);
703 extractTransitionMatrixRec(ee, sourceOdd.
getElseSuccessor(), sourceOffset, targetE, representativesE, Cudd_T(variables),
704 nondeterminismVariables, stateOdd ? &stateOdd->
getElseSuccessor() : stateOdd, stateOffset);
705 extractTransitionMatrixRec(et, sourceOdd.
getElseSuccessor(), sourceOffset, targetT, representativesE, Cudd_T(variables),
706 nondeterminismVariables, stateOdd ? &stateOdd->
getElseSuccessor() : stateOdd, stateOffset);
708 Cudd_T(variables), nondeterminismVariables, stateOdd ? &stateOdd->
getThenSuccessor() : stateOdd,
709 stateOffset + (stateOdd ? stateOdd->getElseOffset() : 0));
711 Cudd_T(variables), nondeterminismVariables, stateOdd ? &stateOdd->
getThenSuccessor() : stateOdd,
712 stateOffset + (stateOdd ? stateOdd->getElseOffset() : 0));
720 phmap::flat_hash_map<DdNode const*, uint64_t> blockToOffset;
724template<
typename ValueType,
typename ExportValueType>
733#ifdef STORM_HAVE_SYLVAN
734 this->createBlockToOffsetMapping();
737 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
738 "version of Storm with Sylvan support.");
744#ifdef STORM_HAVE_SYLVAN
745 this->createMatrixEntryStorage();
746 extractTransitionMatrixRec(matrix.
getInternalAdd().getSylvanMtbdd().GetMTBDD(), this->isNondeterministic ? this->nondeterminismOdd : this->odd, 0,
747 this->partitionBdd.getInternalBdd().getSylvanBdd().GetBDD(), this->representatives.getInternalBdd().getSylvanBdd().GetBDD(),
748 this->allSourceVariablesCube.getInternalBdd().getSylvanBdd().GetBDD(),
749 this->nondeterminismVariablesCube.getInternalBdd().getSylvanBdd().GetBDD(), this->isNondeterministic ? &this->odd : nullptr,
751 return this->createMatrixFromEntries();
754 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
755 "version of Storm with Sylvan support.");
762#ifdef STORM_HAVE_SYLVAN
764 extractVectorRec(vector.
getInternalAdd().getSylvanMtbdd().GetMTBDD(), this->representatives.getInternalBdd().getSylvanBdd().GetBDD(),
765 variablesCube.
getInternalBdd().getSylvanBdd().GetBDD(), odd, 0, result);
769 "This version of Storm was compiled without support for Sylvan. Yet, a method was called that requires this support. Please choose a "
770 "version of Storm with Sylvan support.");
774#ifdef STORM_HAVE_SYLVAN
775 void extractVectorRec(MTBDD vector, BDD representativesNode, BDD variables,
storm::dd::Odd const& odd, uint64_t offset,
776 std::vector<ExportValueType>& result) {
777 if (representativesNode == sylvan_false || mtbdd_iszero(vector)) {
781 if (sylvan_isconst(variables)) {
786 if (sylvan_mtbdd_matches_variable_index(vector, sylvan_var(variables))) {
787 vectorT = sylvan_high(vector);
788 vectorE = sylvan_low(vector);
790 vectorT = vectorE = vector;
793 BDD representativesT;
794 BDD representativesE;
795 if (sylvan_bdd_matches_variable_index(representativesNode, sylvan_var(variables))) {
796 representativesT = sylvan_high(representativesNode);
797 representativesE = sylvan_low(representativesNode);
799 representativesT = representativesE = representativesNode;
802 extractVectorRec(vectorE, representativesE, sylvan_high(variables), odd.
getElseSuccessor(), offset, result);
807 void createBlockToOffsetMapping() {
808 this->createBlockToOffsetMappingRec(this->partitionBdd.
getInternalBdd().getSylvanBdd().GetBDD(),
809 this->representatives.getInternalBdd().getSylvanBdd().GetBDD(),
810 this->rowVariablesCube.getInternalBdd().getSylvanBdd().GetBDD(), this->odd, 0);
812 "Mismatching block-to-offset mapping: " << blockToOffset.size() <<
" vs. " << this->numberOfBlocks <<
".");
815 void createBlockToOffsetMappingRec(BDD partitionNode, BDD representativesNode, BDD variables,
storm::dd::Odd const& odd, uint64_t offset) {
816 STORM_LOG_ASSERT(partitionNode != sylvan_false || representativesNode == sylvan_false,
"Expected representative to be zero if the partition is zero.");
817 if (representativesNode == sylvan_false || partitionNode == sylvan_false) {
821 if (sylvan_isconst(variables)) {
823 STORM_LOG_ASSERT(blockToOffset.find(partitionNode) == blockToOffset.end(),
"Duplicate entry.");
824 blockToOffset[partitionNode] = offset;
829 if (sylvan_bdd_matches_variable_index(partitionNode, sylvan_var(variables))) {
830 partitionT = sylvan_high(partitionNode);
831 partitionE = sylvan_low(partitionNode);
833 partitionT = partitionE = partitionNode;
836 BDD representativesT;
837 BDD representativesE;
838 if (sylvan_bdd_matches_variable_index(representativesNode, sylvan_var(variables))) {
839 representativesT = sylvan_high(representativesNode);
840 representativesE = sylvan_low(representativesNode);
842 representativesT = representativesE = representativesNode;
845 createBlockToOffsetMappingRec(partitionE, representativesE, sylvan_high(variables), odd.
getElseSuccessor(), offset);
850 void extractTransitionMatrixRec(MTBDD transitionMatrixNode,
storm::dd::Odd const& sourceOdd, uint64_t sourceOffset, BDD targetPartitionNode,
851 BDD representativesNode, BDD variables, BDD nondeterminismVariables,
storm::dd::Odd const* stateOdd, uint64_t stateOffset) {
854 if (mtbdd_iszero(transitionMatrixNode) || representativesNode == sylvan_false) {
859 if (sylvan_isconst(variables)) {
860 STORM_LOG_ASSERT(mtbdd_isleaf(transitionMatrixNode),
"Expected constant node.");
861 this->addMatrixEntry(
862 sourceOffset, blockToOffset.at(targetPartitionNode),
865 this->assignRowToState(sourceOffset, stateOffset);
869 bool nextVariableIsNondeterminismVariable =
870 !sylvan_isconst(nondeterminismVariables) && sylvan_var(nondeterminismVariables) == sylvan_var(variables);
872 if (nextVariableIsNondeterminismVariable) {
877 if (sylvan_mtbdd_matches_variable_index(transitionMatrixNode, sylvan_var(variables))) {
878 t = sylvan_high(transitionMatrixNode);
879 e = sylvan_low(transitionMatrixNode);
881 t = e = transitionMatrixNode;
885 extractTransitionMatrixRec(e, sourceOdd.
getElseSuccessor(), sourceOffset, targetPartitionNode, representativesNode, sylvan_high(variables),
886 sylvan_high(nondeterminismVariables), stateOdd, stateOffset);
887 extractTransitionMatrixRec(t, sourceOdd.
getThenSuccessor(), sourceOffset + sourceOdd.
getElseOffset(), targetPartitionNode, representativesNode,
888 sylvan_high(variables), sylvan_high(nondeterminismVariables), stateOdd, stateOffset);
896 if (sylvan_mtbdd_matches_variable_index(transitionMatrixNode, sylvan_var(variables))) {
898 t = sylvan_high(transitionMatrixNode);
899 e = sylvan_low(transitionMatrixNode);
901 t = e = transitionMatrixNode;
904 if (sylvan_mtbdd_matches_variable_index(t, sylvan_var(variables) + 1)) {
913 if (sylvan_mtbdd_matches_variable_index(e, sylvan_var(variables) + 1)) {
928 if (sylvan_bdd_matches_variable_index(targetPartitionNode, sylvan_var(variables))) {
930 targetT = sylvan_high(targetPartitionNode);
931 targetE = sylvan_low(targetPartitionNode);
934 targetT = targetE = targetPartitionNode;
937 BDD representativesT;
938 BDD representativesE;
939 if (sylvan_bdd_matches_variable_index(representativesNode, sylvan_var(variables))) {
941 representativesT = sylvan_high(representativesNode);
942 representativesE = sylvan_low(representativesNode);
945 representativesT = representativesE = representativesNode;
948 extractTransitionMatrixRec(ee, sourceOdd.
getElseSuccessor(), sourceOffset, targetE, representativesE, sylvan_high(variables),
949 nondeterminismVariables, stateOdd ? &stateOdd->
getElseSuccessor() : stateOdd, stateOffset);
950 extractTransitionMatrixRec(et, sourceOdd.
getElseSuccessor(), sourceOffset, targetT, representativesE, sylvan_high(variables),
951 nondeterminismVariables, stateOdd ? &stateOdd->
getElseSuccessor() : stateOdd, stateOffset);
953 sylvan_high(variables), nondeterminismVariables, stateOdd ? &stateOdd->
getThenSuccessor() : stateOdd,
954 stateOffset + (stateOdd ? stateOdd->getElseOffset() : 0));
956 sylvan_high(variables), nondeterminismVariables, stateOdd ? &stateOdd->
getThenSuccessor() : stateOdd,
957 stateOffset + (stateOdd ? stateOdd->getElseOffset() : 0));
963 phmap::flat_hash_map<BDD, uint64_t> blockToOffset;
967template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
969 : useRepresentatives(false), quotientFormat(quotientFormat) {
970 auto const& settings = storm::settings::getModule<storm::settings::modules::BisimulationSettings>();
971 this->useRepresentatives = settings.isUseRepresentativesSet();
972 this->useOriginalVariables = settings.isUseOriginalVariablesSet();
975template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
979 auto start = std::chrono::high_resolution_clock::now();
980 std::shared_ptr<storm::models::Model<ExportValueType>> result;
982 result = extractSparseQuotient(model, partition, preservationInformation);
984 result = extractDdQuotient(model, partition, preservationInformation);
986 auto end = std::chrono::high_resolution_clock::now();
987 STORM_LOG_INFO(
"Quotient extraction completed in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
989 STORM_LOG_THROW(result, storm::exceptions::NotSupportedException,
"Quotient could not be extracted.");
994template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
1003 auto start = std::chrono::high_resolution_clock::now();
1009 "Representatives do not cover all blocks.");
1013 auto end = std::chrono::high_resolution_clock::now();
1014 STORM_LOG_INFO(
"Quotient transition matrix extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() <<
"ms.");
1016 start = std::chrono::high_resolution_clock::now();
1018 quotientStateLabeling.addLabel(
"init", sparseExtractor.extractSetExists(model.
getInitialStates()));
1019 quotientStateLabeling.addLabel(
"deadlock", sparseExtractor.extractSetExists(model.
getDeadlockStates()));
1021 for (
auto const& label : preservationInformation.getLabels()) {
1022 quotientStateLabeling.addLabel(label, sparseExtractor.extractSetAll(model.
getStates(label)));
1024 for (
auto const& expression : preservationInformation.getExpressions()) {
1025 std::stringstream stream;
1026 stream << expression;
1027 std::string expressionAsString = stream.str();
1029 if (quotientStateLabeling.containsLabel(expressionAsString)) {
1030 STORM_LOG_WARN(
"Duplicate label '" << expressionAsString <<
"', dropping second label definition.");
1032 quotientStateLabeling.addLabel(stream.str(), sparseExtractor.extractSetAll(model.
getStates(expression)));
1035 end = std::chrono::high_resolution_clock::now();
1036 STORM_LOG_INFO(
"Quotient labels extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1038 start = std::chrono::high_resolution_clock::now();
1039 std::unordered_map<std::string, storm::models::sparse::StandardRewardModel<ExportValueType>> quotientRewardModels;
1040 for (
auto const& rewardModelName : preservationInformation.getRewardModelNames()) {
1043 std::optional<std::vector<ExportValueType>> quotientStateRewards;
1044 if (rewardModel.hasStateRewards()) {
1045 quotientStateRewards = sparseExtractor.extractStateVector(rewardModel.getStateRewardVector());
1048 std::optional<std::vector<ExportValueType>> quotientStateActionRewards;
1049 if (rewardModel.hasStateActionRewards()) {
1050 quotientStateActionRewards = sparseExtractor.extractStateActionVector(rewardModel.getStateActionRewardVector());
1054 std::move(quotientStateRewards), std::move(quotientStateActionRewards), std::nullopt));
1056 end = std::chrono::high_resolution_clock::now();
1057 STORM_LOG_INFO(
"Reward models extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1059 std::shared_ptr<storm::models::sparse::Model<ExportValueType>> result;
1061 result = std::make_shared<storm::models::sparse::Dtmc<ExportValueType>>(std::move(quotientTransitionMatrix), std::move(quotientStateLabeling),
1062 std::move(quotientRewardModels));
1064 result = std::make_shared<storm::models::sparse::Ctmc<ExportValueType>>(std::move(quotientTransitionMatrix), std::move(quotientStateLabeling),
1065 std::move(quotientRewardModels));
1067 result = std::make_shared<storm::models::sparse::Mdp<ExportValueType>>(std::move(quotientTransitionMatrix), std::move(quotientStateLabeling),
1068 std::move(quotientRewardModels));
1071 *model.template as<storm::models::symbolic::MarkovAutomaton<DdType, ValueType>>();
1073 boost::optional<storm::storage::BitVector> markovianStates = sparseExtractor.extractSetExists(markovAutomaton.
getMarkovianStates());
1075 std::move(quotientRewardModels),
false, std::move(markovianStates));
1076 modelComponents.exitRates = sparseExtractor.extractStateVector(markovAutomaton.
getExitRateVector());
1078 result = std::make_shared<storm::models::sparse::MarkovAutomaton<ExportValueType>>(std::move(modelComponents));
1084template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
1085std::shared_ptr<storm::models::symbolic::Model<DdType, ExportValueType>> QuotientExtractor<DdType, ValueType, ExportValueType>::extractDdQuotient(
1087 PreservationInformation<DdType, ValueType>
const& preservationInformation) {
1088 if (this->useOriginalVariables) {
1089 return extractQuotientUsingOriginalVariables(model, partition, preservationInformation);
1091 return extractQuotientUsingBlockVariables(model, partition, preservationInformation);
1095template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
1096std::shared_ptr<storm::models::symbolic::Model<DdType, ExportValueType>>
1097QuotientExtractor<DdType, ValueType, ExportValueType>::extractQuotientUsingBlockVariables(
1099 PreservationInformation<DdType, ValueType>
const& preservationInformation) {
1100 auto modelType = model.
getType();
1102 bool useRepresentativesForThisExtraction = this->useRepresentatives;
1108 "Mismatching partition.");
1110 std::set<storm::expressions::Variable> blockVariableSet = {partition.getBlockVariable()};
1111 std::set<storm::expressions::Variable> blockPrimeVariableSet = {partition.getPrimedBlockVariable()};
1112 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> blockMetaVariablePairs = {
1113 std::make_pair(partition.getBlockVariable(), partition.getPrimedBlockVariable())};
1115 auto start = std::chrono::high_resolution_clock::now();
1118 storm::dd::Bdd<DdType> partitionAsBdd = partition.storedAsBdd() ? partition.asBdd() : partition.asAdd().notZero();
1120 auto representatives = InternalRepresentativeComputer<DdType>(partitionAsBdd, model.
getRowVariables()).getRepresentatives();
1122 if (useRepresentativesForThisExtraction) {
1125 (representatives && partitionAsBddOverPrimedBlockVariables).renameVariablesConcretize(model.
getRowVariables(), blockVariableSet);
1126 partitionAsBdd = (tmp && partitionAsBddOverPrimedBlockVariables).existsAbstract(blockPrimeVariableSet);
1132 std::map<std::string, storm::dd::Bdd<DdType>> preservedLabelBdds;
1133 for (
auto const& label : preservationInformation.getLabels()) {
1134 preservedLabelBdds.emplace(label, (model.
getStates(label) && partitionAsBdd).existsAbstract(model.
getRowVariables()));
1136 for (
auto const& expression : preservationInformation.getExpressions()) {
1137 std::stringstream stream;
1138 stream << expression;
1139 std::string expressionAsString = stream.str();
1141 auto it = preservedLabelBdds.find(expressionAsString);
1142 if (it != preservedLabelBdds.end()) {
1143 STORM_LOG_WARN(
"Duplicate label '" << expressionAsString <<
"', dropping second label definition.");
1145 preservedLabelBdds.emplace(stream.str(), (model.
getStates(expression) && partitionAsBdd).existsAbstract(model.
getRowVariables()));
1148 auto end = std::chrono::high_resolution_clock::now();
1149 STORM_LOG_INFO(
"Quotient labels extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1151 start = std::chrono::high_resolution_clock::now();
1152 std::set<storm::expressions::Variable> blockAndRowVariables;
1154 std::inserter(blockAndRowVariables, blockAndRowVariables.end()));
1155 std::set<storm::expressions::Variable> blockPrimeAndColumnVariables;
1157 std::inserter(blockPrimeAndColumnVariables, blockPrimeAndColumnVariables.end()));
1163 partitionAsBdd &= representatives;
1164 partitionAsAdd *= partitionAsBdd.template toAdd<ValueType>();
1167 end = std::chrono::high_resolution_clock::now();
1170 if (std::is_same<ValueType, storm::RationalNumber>::value) {
1171 STORM_LOG_ASSERT(quotientTransitionMatrix.
greater(storm::utility::one<ValueType>()).isZero(),
"Illegal entries in quotient matrix.");
1172 }
else if (std::is_same<ValueType, storm::RationalFunction>::value) {
1175 STORM_LOG_ASSERT(quotientTransitionMatrix.
greater(storm::utility::one<ValueType>() + storm::utility::convertNumber<ValueType>(1e-6)).isZero(),
1176 "Illegal entries in quotient matrix.");
1179 .equalModuloPrecision(quotientTransitionMatrix.
notZero().existsAbstract(blockPrimeVariableSet).template toAdd<ValueType>(),
1180 storm::utility::convertNumber<ValueType>(1e-6)),
1181 "Illegal non-probabilistic matrix.");
1183 STORM_LOG_INFO(
"Quotient transition matrix extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1188 blockPrimeAndNondeterminismVariables.insert(blockPrimeVariableSet.begin(), blockPrimeVariableSet.end());
1191 start = std::chrono::high_resolution_clock::now();
1192 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<DdType, ValueType>> quotientRewardModels;
1193 for (
auto const& rewardModelName : preservationInformation.getRewardModelNames()) {
1196 boost::optional<storm::dd::Add<DdType, ValueType>> quotientStateRewards;
1197 if (rewardModel.hasStateRewards()) {
1201 boost::optional<storm::dd::Add<DdType, ValueType>> quotientStateActionRewards;
1202 if (rewardModel.hasStateActionRewards()) {
1203 quotientStateActionRewards = rewardModel.getStateActionRewardVector().multiplyMatrix(partitionAsAdd, model.
getRowVariables());
1207 quotientStateRewards, quotientStateActionRewards, boost::none));
1209 end = std::chrono::high_resolution_clock::now();
1210 STORM_LOG_INFO(
"Reward models extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1212 std::shared_ptr<storm::models::symbolic::Model<DdType, ValueType>> result;
1215 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, blockVariableSet,
1216 blockPrimeVariableSet, blockMetaVariablePairs, preservedLabelBdds, quotientRewardModels));
1219 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, blockVariableSet,
1220 blockPrimeVariableSet, blockMetaVariablePairs, preservedLabelBdds, quotientRewardModels));
1223 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, blockVariableSet,
1224 blockPrimeVariableSet, blockMetaVariablePairs, model.
getNondeterminismVariables(), preservedLabelBdds, quotientRewardModels));
1230 deadlockStates, quotientTransitionMatrix, blockVariableSet, blockPrimeVariableSet, blockMetaVariablePairs,
1234 return result->template toValueType<ExportValueType>();
1236 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Cannot extract quotient for this model type.");
1240template<storm::dd::DdType DdType,
typename ValueType,
typename ExportValueType>
1241std::shared_ptr<storm::models::symbolic::Model<DdType, ExportValueType>>
1242QuotientExtractor<DdType, ValueType, ExportValueType>::extractQuotientUsingOriginalVariables(
1244 PreservationInformation<DdType, ValueType>
const& preservationInformation) {
1245 auto modelType = model.
getType();
1247 bool useRepresentativesForThisExtraction = this->useRepresentatives;
1250 STORM_LOG_WARN_COND(!this->useRepresentatives,
"Using representatives is unsupported for this extraction, falling back to regular extraction.");
1255 "Mismatching partition.");
1257 std::set<storm::expressions::Variable> blockVariableSet = {partition.getBlockVariable()};
1258 std::set<storm::expressions::Variable> blockPrimeVariableSet = {partition.getPrimedBlockVariable()};
1259 std::vector<std::pair<storm::expressions::Variable, storm::expressions::Variable>> blockMetaVariablePairs = {
1260 std::make_pair(partition.getBlockVariable(), partition.getPrimedBlockVariable())};
1262 auto start = std::chrono::high_resolution_clock::now();
1265 storm::dd::Bdd<DdType> partitionAsBdd = partition.storedAsBdd() ? partition.asBdd() : partition.asAdd().notZero();
1267 auto representatives = InternalRepresentativeComputer<DdType>(partitionAsBdd, model.
getRowVariables()).getRepresentatives();
1269 if (useRepresentativesForThisExtraction) {
1272 (representatives && partitionAsBddOverPrimedBlockVariables).renameVariablesConcretize(model.
getRowVariables(), blockVariableSet);
1273 partitionAsBdd = (tmp && partitionAsBddOverPrimedBlockVariables).existsAbstract(blockPrimeVariableSet);
1282 std::map<std::string, storm::dd::Bdd<DdType>> preservedLabelBdds;
1283 for (
auto const& label : preservationInformation.getLabels()) {
1284 preservedLabelBdds.emplace(label, (model.
getStates(label) && partitionAsBdd)
1288 for (
auto const& expression : preservationInformation.getExpressions()) {
1289 std::stringstream stream;
1290 stream << expression;
1291 std::string expressionAsString = stream.str();
1293 auto it = preservedLabelBdds.find(expressionAsString);
1294 if (it != preservedLabelBdds.end()) {
1295 STORM_LOG_WARN(
"Duplicate label '" << expressionAsString <<
"', dropping second label definition.");
1297 preservedLabelBdds.emplace(stream.str(), (model.
getStates(expression) && partitionAsBdd)
1302 auto end = std::chrono::high_resolution_clock::now();
1303 STORM_LOG_INFO(
"Quotient labels extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1305 start = std::chrono::high_resolution_clock::now();
1306 std::set<storm::expressions::Variable> blockAndRowVariables;
1308 std::inserter(blockAndRowVariables, blockAndRowVariables.end()));
1309 std::set<storm::expressions::Variable> blockPrimeAndColumnVariables;
1311 std::inserter(blockPrimeAndColumnVariables, blockPrimeAndColumnVariables.end()));
1319 partitionAsBdd &= representatives;
1320 partitionAsAdd = partitionAsBdd.template toAdd<ValueType>();
1324 quotientTransitionMatrix = (quotientTransitionMatrix * partitionAsAdd)
1331 end = std::chrono::high_resolution_clock::now();
1334 if (std::is_same<ValueType, storm::RationalNumber>::value) {
1335 STORM_LOG_ASSERT(quotientTransitionMatrix.
greater(storm::utility::one<ValueType>()).isZero(),
"Illegal entries in quotient matrix.");
1337 STORM_LOG_ASSERT(quotientTransitionMatrix.
greater(storm::utility::one<ValueType>() + storm::utility::convertNumber<ValueType>(1e-6)).isZero(),
1338 "Illegal entries in quotient matrix.");
1341 .equalModuloPrecision(quotientTransitionMatrix.
notZero().existsAbstract(model.
getColumnVariables()).template toAdd<ValueType>(),
1342 storm::utility::convertNumber<ValueType>(1e-6)),
1343 "Illegal probabilistic matrix.");
1345 STORM_LOG_INFO(
"Quotient transition matrix extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1349 std::set<storm::expressions::Variable> columnAndNondeterminismVariables = model.
getColumnVariables();
1353 start = std::chrono::high_resolution_clock::now();
1354 std::unordered_map<std::string, storm::models::symbolic::StandardRewardModel<DdType, ValueType>> quotientRewardModels;
1355 for (
auto const& rewardModelName : preservationInformation.getRewardModelNames()) {
1358 boost::optional<storm::dd::Add<DdType, ValueType>> quotientStateRewards;
1359 if (rewardModel.hasStateRewards()) {
1365 boost::optional<storm::dd::Add<DdType, ValueType>> quotientStateActionRewards;
1366 if (rewardModel.hasStateActionRewards()) {
1367 quotientStateActionRewards = rewardModel.getStateActionRewardVector()
1373 quotientStateRewards, quotientStateActionRewards, boost::none));
1375 end = std::chrono::high_resolution_clock::now();
1376 STORM_LOG_INFO(
"Reward models extracted in " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).
count() <<
"ms.");
1378 std::shared_ptr<storm::models::symbolic::Model<DdType, ValueType>> result;
1381 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, model.
getRowVariables(),
1385 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, model.
getRowVariables(),
1389 model.
getManager().asSharedPointer(), reachableStates, initialStates, deadlockStates, quotientTransitionMatrix, model.
getRowVariables(),
1391 quotientRewardModels));
1401 return result->template toValueType<ExportValueType>();
1403 STORM_LOG_THROW(
false, storm::exceptions::NotSupportedException,
"Cannot extract quotient for this model type.");
1407template class QuotientExtractor<storm::dd::DdType::CUDD, double>;
1409template class QuotientExtractor<storm::dd::DdType::Sylvan, double>;
1410template class QuotientExtractor<storm::dd::DdType::Sylvan, storm::RationalNumber>;
1411template class QuotientExtractor<storm::dd::DdType::Sylvan, storm::RationalNumber, double>;
1412template class QuotientExtractor<storm::dd::DdType::Sylvan, storm::RationalFunction>;
InternalAdd< LibraryType, ValueType > const & getInternalAdd() const
Retrieves the internal ADD.
Bdd< LibraryType > greater(Add< LibraryType, ValueType > const &other) const
Retrieves the function that maps all evaluations to one whose function value in the first ADD are gre...
Add< LibraryType, ValueType > renameVariables(std::set< storm::expressions::Variable > const &from, std::set< storm::expressions::Variable > const &to) const
Renames the given meta variables in the ADD.
Add< LibraryType, ValueType > sumAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Sum-abstracts from the given meta variables.
Add< LibraryType, ValueType > multiplyMatrix(Add< LibraryType, ValueType > const &otherMatrix, std::set< storm::expressions::Variable > const &summationMetaVariables) const
Multiplies the current ADD (representing a matrix) with the given matrix by summing over the given me...
Bdd< LibraryType > toBdd() const
Converts the ADD to a BDD by mapping all values unequal to zero to 1.
Bdd< LibraryType > notZero() const
Computes a BDD that represents the function in which all assignments with a function value unequal to...
Bdd< LibraryType > existsAbstract(std::set< storm::expressions::Variable > const &metaVariables) const
Existentially abstracts from the given meta variables.
virtual uint_fast64_t getNonZeroCount() const override
Retrieves the number of encodings that are mapped to a non-zero value.
Bdd< LibraryType > swapVariables(std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const &metaVariablePairs) const
Swaps the given pairs of meta variables in the BDD.
Odd createOdd() const
Creates an ODD based on the current BDD.
static Bdd< LibraryType > getCube(DdManager< LibraryType > const &manager, std::set< storm::expressions::Variable > const &metaVariables)
Retrieves the cube of all given meta variables.
Bdd< LibraryType > renameVariables(std::set< storm::expressions::Variable > const &from, std::set< storm::expressions::Variable > const &to) const
Renames the given meta variables in the BDD.
bool isOne() const
Retrieves whether this DD represents the constant one function.
InternalBdd< LibraryType > const & getInternalBdd() const
Retrieves the internal BDD.
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
storm::expressions::Variable getMetaVariable(std::string const &variableName) const
Retrieves the given meta variable by name.
InternalDdManager< LibraryType > & getInternalDdManager()
Retrieves the internal DD manager.
Bdd< LibraryType > getBddOne() const
Retrieves a BDD representing the constant one function.
Odd const & getThenSuccessor() const
Retrieves the then-successor of this ODD node.
uint_fast64_t getTotalOffset() const
Retrieves the total offset, i.e., the sum of the then- and else-offset.
uint_fast64_t getElseOffset() const
Retrieves the else-offset of this ODD node.
bool isTerminalNode() const
Checks whether the given ODD node is a terminal node, i.e.
Odd const & getElseSuccessor() const
Retrieves the else-successor of this ODD node.
InternalRepresentativeComputer(storm::dd::Bdd< storm::dd::DdType::CUDD > const &partitionBdd, std::set< storm::expressions::Variable > const &rowVariables)
storm::dd::Bdd< storm::dd::DdType::CUDD > getRepresentatives()
storm::dd::Bdd< storm::dd::DdType::Sylvan > getRepresentatives()
InternalRepresentativeComputer(storm::dd::Bdd< storm::dd::DdType::Sylvan > const &partitionBdd, std::set< storm::expressions::Variable > const &rowVariables)
std::set< storm::expressions::Variable > const & rowVariables
storm::dd::Bdd< DdType > partitionBdd
storm::dd::InternalDdManager< DdType > const * internalDdManager
storm::dd::Bdd< DdType > rowVariablesCube
storm::dd::DdManager< DdType > const * ddManager
InternalRepresentativeComputerBase(storm::dd::Bdd< DdType > const &partitionBdd, std::set< storm::expressions::Variable > const &rowVariables)
storm::expressions::Variable const & getBlockVariable() const
storm::dd::Bdd< DdType > const & asBdd() const
uint64_t getNumberOfBlocks() const
storm::dd::Bdd< DdType > getStates() const
storm::dd::Add< DdType, ValueType > const & asAdd() const
virtual ModelType getType() const
Return the actual type of the model.
This class manages the labeling of the state space with a number of (atomic) labels.
This class represents a continuous-time Markov chain.
This class represents a discrete-time Markov chain.
This class represents a discrete-time Markov decision process.
storm::dd::Bdd< Type > const & getMarkovianStates() const
storm::dd::Bdd< Type > const & getMarkovianMarker() const
storm::dd::Add< Type, ValueType > const & getExitRateVector() const
This class represents a discrete-time Markov decision process.
Base class for all symbolic models.
storm::dd::DdManager< Type > & getManager() const
Retrieves the manager responsible for the DDs that represent this model.
RewardModelType const & getRewardModel(std::string const &rewardModelName) const
Retrieves the reward model with the given name, if one exists.
storm::dd::Add< Type, ValueType > const & getTransitionMatrix() const
Retrieves the matrix representing the transitions of the model.
storm::dd::Bdd< Type > const & getDeadlockStates() const
virtual storm::dd::Bdd< Type > getQualitativeTransitionMatrix(bool keepNondeterminism=true) const
Retrieves the matrix qualitatively (i.e.
std::set< storm::expressions::Variable > const & getColumnVariables() const
Retrieves the meta variables used to encode the columns of the transition matrix and the vector indic...
storm::dd::Bdd< Type > const & getInitialStates() const
Retrieves the initial states of the model.
virtual std::set< storm::expressions::Variable > const & getNondeterminismVariables() const
Retrieves all meta variables used to encode the nondeterminism.
std::vector< std::pair< storm::expressions::Variable, storm::expressions::Variable > > const & getRowColumnMetaVariablePairs() const
Retrieves the pairs of row and column meta variables.
std::set< storm::expressions::Variable > const & getRowVariables() const
Retrieves the meta variables used to encode the rows of the transition matrix and the vector indices.
virtual storm::dd::Bdd< Type > getStates(std::string const &label) const
Returns the sets of states labeled with the given label.
storm::dd::Bdd< Type > const & getReachableStates() const
Retrieves the reachable states of the model.
virtual uint_fast64_t getNumberOfStates() const override
Returns the number of states of the model.
storm::dd::Add< Type, ValueType > const & getStateRewardVector() const
Retrieves the state rewards of the reward model.
A bit vector that is internally represented as a vector of 64-bit values.
A class that can be used to build a sparse matrix by adding value by value.
void addNextValue(index_type row, index_type column, value_type const &value)
Sets the matrix entry at the given row and column to the given value.
void newRowGroup(index_type startingRow)
Starts a new row group in the matrix.
SparseMatrix< value_type > build(index_type overriddenRowCount=0, index_type overriddenColumnCount=0, index_type overriddenRowGroupCount=0)
A class that holds a possibly non-square matrix in the compressed row storage format.
#define STORM_LOG_INFO(message)
#define STORM_LOG_WARN(message)
#define STORM_LOG_TRACE(message)
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_WARN_COND(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
std::pair< storm::RationalNumber, storm::RationalNumber > count(std::vector< storm::storage::BitVector > const &origSets, std::vector< storm::storage::BitVector > const &intersects, std::vector< storm::storage::BitVector > const &intersectsInfo, storm::RationalNumber val, bool plus, uint64_t remdepth)