|
|
@ -197,6 +197,9 @@ namespace storm { |
|
|
|
storm::storage::SparseMatrix<ValueType> extractTransitionMatrix(storm::dd::Add<storm::dd::DdType::CUDD, ValueType> const& transitionMatrix, Partition<storm::dd::DdType::CUDD, ValueType> const& partition) { |
|
|
|
STORM_LOG_ASSERT(partition.storedAsAdd(), "Expected partition stored as ADD."); |
|
|
|
|
|
|
|
transitionMatrix.exportToDot("trans.dot"); |
|
|
|
partition.asAdd().exportToDot("part.dot"); |
|
|
|
|
|
|
|
// Create the number of rows necessary for the matrix.
|
|
|
|
this->reserveMatrixEntries(partition.getNumberOfBlocks()); |
|
|
|
STORM_LOG_TRACE("Partition has " << partition.getNumberOfStates() << " states in " << partition.getNumberOfBlocks() << " blocks."); |
|
|
@ -291,7 +294,7 @@ namespace storm { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void extractTransitionMatrixRec(DdNode* transitionMatrixNode, DdNode* sourcePartitionNode, DdNode* targetPartitionNode, uint64_t sourceStateEncodingIndex, storm::storage::BitVector& sourceStateEncoding, storm::storage::BitVector const& nondeterminismEncoding, ValueType factor = 1) { |
|
|
|
void extractTransitionMatrixRec(DdNode* transitionMatrixNode, DdNode* sourcePartitionNode, DdNode* targetPartitionNode, uint64_t sourceStateEncodingIndex, storm::storage::BitVector& sourceStateEncoding, storm::storage::BitVector const& nondeterminismEncoding, ValueType const& factor = 1) { |
|
|
|
// For the empty DD, we do not need to add any entries. Note that the partition nodes cannot be zero
|
|
|
|
// as all states of the model have to be contained.
|
|
|
|
if (transitionMatrixNode == Cudd_ReadZero(ddman)) { |
|
|
@ -322,6 +325,9 @@ namespace storm { |
|
|
|
uint64_t targetPartitionVariable = Cudd_NodeReadIndex(targetPartitionNode) - 1; |
|
|
|
|
|
|
|
// Move through transition matrix.
|
|
|
|
bool skippedSourceInMatrix = false; |
|
|
|
bool skippedTargetTInMatrix = false; |
|
|
|
bool skippedTargetEInMatrix = false; |
|
|
|
DdNode* tt = transitionMatrixNode; |
|
|
|
DdNode* te = transitionMatrixNode; |
|
|
|
DdNode* et = transitionMatrixNode; |
|
|
@ -335,6 +341,7 @@ namespace storm { |
|
|
|
te = Cudd_E(t); |
|
|
|
} else { |
|
|
|
tt = te = t; |
|
|
|
skippedTargetTInMatrix = true; |
|
|
|
} |
|
|
|
|
|
|
|
DdNode* e = Cudd_E(transitionMatrixNode); |
|
|
@ -344,13 +351,16 @@ namespace storm { |
|
|
|
ee = Cudd_E(e); |
|
|
|
} else { |
|
|
|
et = ee = e; |
|
|
|
skippedTargetEInMatrix = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
skippedSourceInMatrix = true; |
|
|
|
if (transitionMatrixVariable == this->sourceVariablesIndicesAndLevels[sourceStateEncodingIndex].first + 1) { |
|
|
|
tt = et = Cudd_T(transitionMatrixNode); |
|
|
|
te = ee = Cudd_E(transitionMatrixNode); |
|
|
|
} else { |
|
|
|
tt = te = et = ee = transitionMatrixNode; |
|
|
|
skippedTargetTInMatrix = skippedTargetEInMatrix = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -383,8 +393,10 @@ namespace storm { |
|
|
|
// If we skipped the variable in the source partition, we only have to choose one of the two representatives.
|
|
|
|
if (!skippedInSourcePartition) { |
|
|
|
sourceStateEncoding.set(sourceStateEncodingIndex, true); |
|
|
|
extractTransitionMatrixRec(tt, sourceT, targetT, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, factor); |
|
|
|
extractTransitionMatrixRec(te, sourceT, targetE, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, factor); |
|
|
|
if (!skippedInTargetPartition) { |
|
|
|
extractTransitionMatrixRec(tt, sourceT, targetT, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, factor); |
|
|
|
} |
|
|
|
extractTransitionMatrixRec(te, sourceT, targetE, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, skippedTargetTInMatrix && skippedInTargetPartition ? 2 * factor : factor); |
|
|
|
} |
|
|
|
|
|
|
|
sourceStateEncoding.set(sourceStateEncodingIndex, false); |
|
|
@ -392,7 +404,7 @@ namespace storm { |
|
|
|
if (!skippedInTargetPartition) { |
|
|
|
extractTransitionMatrixRec(et, sourceE, targetT, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, factor); |
|
|
|
} |
|
|
|
extractTransitionMatrixRec(ee, sourceE, targetE, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, skippedInTargetPartition ? 2 * factor : factor); |
|
|
|
extractTransitionMatrixRec(ee, sourceE, targetE, sourceStateEncodingIndex + 1, sourceStateEncoding, nondeterminismEncoding, skippedTargetEInMatrix && skippedInTargetPartition ? 2 * factor : factor); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@ -497,7 +509,7 @@ namespace storm { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void extractTransitionMatrixRec(MTBDD transitionMatrixNode, BDD sourcePartitionNode, BDD targetPartitionNode, uint64_t currentIndex, storm::storage::BitVector& sourceState, storm::storage::BitVector const& nondeterminismEncoding) { |
|
|
|
void extractTransitionMatrixRec(MTBDD transitionMatrixNode, BDD sourcePartitionNode, BDD targetPartitionNode, uint64_t currentIndex, storm::storage::BitVector& sourceState, storm::storage::BitVector const& nondeterminismEncoding, ValueType const& factor = storm::utility::one<ValueType>()) { |
|
|
|
// For the empty DD, we do not need to add any entries. Note that the partition nodes cannot be zero
|
|
|
|
// as all states of the model have to be contained.
|
|
|
|
if (mtbdd_iszero(transitionMatrixNode)) { |
|
|
@ -518,10 +530,9 @@ namespace storm { |
|
|
|
// Otherwise, we record the new representative.
|
|
|
|
sourceRepresentative.reset(new storm::storage::BitVector(sourceState)); |
|
|
|
|
|
|
|
// Decode the target block.
|
|
|
|
// Decode the target block and add matrix entry.
|
|
|
|
uint64_t targetBlockIndex = decodeBlockIndex(targetPartitionNode); |
|
|
|
|
|
|
|
this->addMatrixEntry(nondeterminismEncoding, sourceBlockIndex, targetBlockIndex, storm::dd::InternalAdd<storm::dd::DdType::Sylvan, ValueType>::getValue(transitionMatrixNode)); |
|
|
|
this->addMatrixEntry(nondeterminismEncoding, sourceBlockIndex, targetBlockIndex, factor * storm::dd::InternalAdd<storm::dd::DdType::Sylvan, ValueType>::getValue(transitionMatrixNode)); |
|
|
|
} else { |
|
|
|
// Determine the levels in the DDs.
|
|
|
|
uint64_t transitionMatrixVariable = sylvan_isconst(transitionMatrixNode) ? 0xffffffff : sylvan_var(transitionMatrixNode); |
|
|
@ -529,6 +540,9 @@ namespace storm { |
|
|
|
uint64_t targetPartitionVariable = sylvan_var(targetPartitionNode) - 1; |
|
|
|
|
|
|
|
// Move through transition matrix.
|
|
|
|
bool skippedSourceInMatrix = false; |
|
|
|
bool skippedTargetTInMatrix = false; |
|
|
|
bool skippedTargetEInMatrix = false; |
|
|
|
MTBDD tt = transitionMatrixNode; |
|
|
|
MTBDD te = transitionMatrixNode; |
|
|
|
MTBDD et = transitionMatrixNode; |
|
|
@ -543,6 +557,7 @@ namespace storm { |
|
|
|
te = sylvan_low(t); |
|
|
|
} else { |
|
|
|
tt = te = t; |
|
|
|
skippedTargetTInMatrix = true; |
|
|
|
} |
|
|
|
|
|
|
|
uint64_t eVariable = sylvan_isconst(e) ? 0xffffffff : sylvan_var(e); |
|
|
@ -551,17 +566,21 @@ namespace storm { |
|
|
|
ee = sylvan_low(e); |
|
|
|
} else { |
|
|
|
et = ee = e; |
|
|
|
skippedTargetEInMatrix = true; |
|
|
|
} |
|
|
|
} else { |
|
|
|
skippedSourceInMatrix = true; |
|
|
|
if (transitionMatrixVariable == this->sourceVariablesIndicesAndLevels[currentIndex].first + 1) { |
|
|
|
tt = et = sylvan_high(transitionMatrixNode); |
|
|
|
te = ee = sylvan_low(transitionMatrixNode); |
|
|
|
} else { |
|
|
|
tt = te = et = ee = transitionMatrixNode; |
|
|
|
skippedTargetTInMatrix = skippedTargetEInMatrix = true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
// Move through partition (for source state).
|
|
|
|
bool skippedInSourcePartition = false; |
|
|
|
MTBDD sourceT; |
|
|
|
MTBDD sourceE; |
|
|
|
if (sourcePartitionVariable == this->sourceVariablesIndicesAndLevels[currentIndex].first) { |
|
|
@ -569,9 +588,11 @@ namespace storm { |
|
|
|
sourceE = sylvan_low(sourcePartitionNode); |
|
|
|
} else { |
|
|
|
sourceT = sourceE = sourcePartitionNode; |
|
|
|
skippedInSourcePartition = true; |
|
|
|
} |
|
|
|
|
|
|
|
// Move through partition (for target state).
|
|
|
|
bool skippedInTargetPartition = false; |
|
|
|
MTBDD targetT; |
|
|
|
MTBDD targetE; |
|
|
|
if (targetPartitionVariable == this->sourceVariablesIndicesAndLevels[currentIndex].first) { |
|
|
@ -579,15 +600,25 @@ namespace storm { |
|
|
|
targetE = sylvan_low(targetPartitionNode); |
|
|
|
} else { |
|
|
|
targetT = targetE = targetPartitionNode; |
|
|
|
skippedInTargetPartition = true; |
|
|
|
} |
|
|
|
|
|
|
|
sourceState.set(currentIndex, true); |
|
|
|
extractTransitionMatrixRec(tt, sourceT, targetT, currentIndex + 1, sourceState, nondeterminismEncoding); |
|
|
|
extractTransitionMatrixRec(te, sourceT, targetE, currentIndex + 1, sourceState, nondeterminismEncoding); |
|
|
|
// If we skipped the variable in the source partition, we only have to choose one of the two representatives.
|
|
|
|
if (!skippedInSourcePartition) { |
|
|
|
sourceState.set(currentIndex, true); |
|
|
|
// If we skipped the variable in the target partition, just count the one representative twice.
|
|
|
|
if (!skippedInTargetPartition) { |
|
|
|
extractTransitionMatrixRec(tt, sourceT, targetT, currentIndex + 1, sourceState, nondeterminismEncoding, factor); |
|
|
|
} |
|
|
|
extractTransitionMatrixRec(te, sourceT, targetE, currentIndex + 1, sourceState, nondeterminismEncoding, skippedTargetTInMatrix && skippedInTargetPartition ? 2 * factor : factor); |
|
|
|
} |
|
|
|
|
|
|
|
sourceState.set(currentIndex, false); |
|
|
|
extractTransitionMatrixRec(et, sourceE, targetT, currentIndex + 1, sourceState, nondeterminismEncoding); |
|
|
|
extractTransitionMatrixRec(ee, sourceE, targetE, currentIndex + 1, sourceState, nondeterminismEncoding); |
|
|
|
// If we skipped the variable in the target partition, just count the one representative twice.
|
|
|
|
if (!skippedInTargetPartition) { |
|
|
|
extractTransitionMatrixRec(et, sourceE, targetT, currentIndex + 1, sourceState, nondeterminismEncoding, factor); |
|
|
|
} |
|
|
|
extractTransitionMatrixRec(ee, sourceE, targetE, currentIndex + 1, sourceState, nondeterminismEncoding, skippedTargetEInMatrix && skippedInTargetPartition ? 2 * factor : factor); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|