10namespace bisimulation {
12template<
typename ValueType>
15 std::set<storm::expressions::Variable>
const& stateVariables,
20 ddman(manager.getInternalDdManager().getCuddManager().getManager()),
21 blockVariable(blockVariable),
22 stateVariables(stateVariables),
23 nondeterminismVariables(nondeterminismVariables),
24 nonBlockVariables(nonBlockVariables),
26 nextFreeBlockIndex(0),
27 numberOfRefinements(0),
31 auto const& ddMetaVariable = manager.getMetaVariable(blockVariable);
32 blockDdVariableIndices = ddMetaVariable.getIndices();
35 blockEncoding = std::vector<int>(
static_cast<uint64_t
>(manager.getInternalDdManager().getCuddManager().ReadSize()),
static_cast<int>(2));
38template<
typename ValueType>
41 std::pair<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>, boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>>> newPartitionDds =
43 ++numberOfRefinements;
44 return oldPartition.
replacePartition(newPartitionDds.first, nextFreeBlockIndex, nextFreeBlockIndex, newPartitionDds.second);
47template<
typename ValueType>
49 signatureCache.clear();
50 reuseBlocksCache.clear();
53template<
typename ValueType>
54std::pair<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>, boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>>>
62 std::pair<DdNodePtr, DdNodePtr> result =
64 nondeterminismVariables.getInternalBdd().getCuddDdNode(), nonBlockVariables.getInternalBdd().getCuddDdNode());
68 &manager.getInternalDdManager(), cudd::ADD(manager.getInternalDdManager().getCuddManager(), result.first));
72 boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>> optionalChangedAdd;
75 &manager.getInternalDdManager(), cudd::ADD(manager.getInternalDdManager().getCuddManager(), result.second));
77 optionalChangedAdd = changedAdd;
81 return std::make_pair(newPartitionAdd, optionalChangedAdd);
84template<
typename ValueType>
85DdNodePtr InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::encodeBlock(uint64_t blockIndex) {
86 for (
auto const& blockDdVariableIndex : blockDdVariableIndices) {
87 blockEncoding[blockDdVariableIndex] = blockIndex & 1 ? 1 : 0;
90 DdNodePtr bddEncoding = Cudd_CubeArrayToBdd(ddman, blockEncoding.data());
91 Cudd_Ref(bddEncoding);
92 DdNodePtr result = Cudd_BddToAdd(ddman, bddEncoding);
94 Cudd_RecursiveDeref(ddman, bddEncoding);
99template<
typename ValueType>
100std::pair<DdNodePtr, DdNodePtr> InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::reuseOrRelabel(DdNode* partitionNode,
101 DdNode* nondeterminismVariablesNode,
102 DdNode* nonBlockVariablesNode) {
104 if (partitionNode == Cudd_ReadZero(ddman)) {
105 if (options.createChangedStates) {
106 return std::make_pair(partitionNode, Cudd_ReadZero(ddman));
108 return std::make_pair(partitionNode,
nullptr);
113 auto nodePair = std::make_pair(
nullptr, partitionNode);
115 auto it = signatureCache.find(nodePair);
116 if (it != signatureCache.end()) {
122 if (Cudd_IsConstant(nonBlockVariablesNode)) {
123 if (options.reuseBlockNumbers) {
126 auto& reuseEntry = reuseBlocksCache[partitionNode];
127 if (!reuseEntry.isReused()) {
128 reuseEntry.setReused();
129 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(partitionNode, options.createChangedStates ? Cudd_ReadZero(ddman) : nullptr);
130 signatureCache[nodePair] = result;
135 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(encodeBlock(nextFreeBlockIndex++), options.createChangedStates ? Cudd_ReadOne(ddman) : nullptr);
136 signatureCache[nodePair] = result;
142 DdNode* partitionThen;
143 DdNode* partitionElse;
145 bool isNondeterminismVariable;
146 while (skipped && !Cudd_IsConstant(nonBlockVariablesNode)) {
148 offset = options.shiftStateVariables ? 1 : 0;
149 isNondeterminismVariable =
false;
150 if (!Cudd_IsConstant(nondeterminismVariablesNode) && Cudd_NodeReadIndex(nondeterminismVariablesNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
152 isNondeterminismVariable =
true;
155 if (Cudd_NodeReadIndex(partitionNode) - offset == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
156 partitionThen = Cudd_T(partitionNode);
157 partitionElse = Cudd_E(partitionNode);
160 partitionThen = partitionElse = partitionNode;
166 nonBlockVariablesNode = Cudd_T(nonBlockVariablesNode);
167 if (isNondeterminismVariable) {
168 nondeterminismVariablesNode = Cudd_T(nondeterminismVariablesNode);
174 if (Cudd_IsConstant(nonBlockVariablesNode)) {
175 return reuseOrRelabel(partitionNode, nondeterminismVariablesNode, nonBlockVariablesNode);
178 std::pair<DdNodePtr, DdNodePtr> combinedThenResult = reuseOrRelabel(
179 partitionThen, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode, Cudd_T(nonBlockVariablesNode));
180 DdNodePtr thenResult = combinedThenResult.first;
181 DdNodePtr changedThenResult = combinedThenResult.second;
182 Cudd_Ref(thenResult);
183 if (options.createChangedStates) {
184 Cudd_Ref(changedThenResult);
188 std::pair<DdNodePtr, DdNodePtr> combinedElseResult = reuseOrRelabel(
189 partitionElse, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode, Cudd_T(nonBlockVariablesNode));
190 DdNodePtr elseResult = combinedElseResult.first;
191 DdNodePtr changedElseResult = combinedElseResult.second;
192 Cudd_Ref(elseResult);
193 if (options.createChangedStates) {
194 Cudd_Ref(changedElseResult);
200 if (thenResult == elseResult) {
201 Cudd_Deref(thenResult);
202 Cudd_Deref(elseResult);
206 bool complemented = Cudd_IsComplement(thenResult);
207 result = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(thenResult),
208 complemented ? Cudd_Not(elseResult) : elseResult);
210 result = Cudd_Not(result);
212 Cudd_Deref(thenResult);
213 Cudd_Deref(elseResult);
216 DdNodePtr changedResult =
nullptr;
217 if (options.createChangedStates) {
218 if (changedThenResult == changedElseResult) {
219 Cudd_Deref(changedThenResult);
220 Cudd_Deref(changedElseResult);
221 changedResult = changedThenResult;
224 bool complemented = Cudd_IsComplement(changedThenResult);
225 changedResult = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(changedThenResult),
226 complemented ? Cudd_Not(changedElseResult) : changedElseResult);
228 changedResult = Cudd_Not(changedResult);
230 Cudd_Deref(changedThenResult);
231 Cudd_Deref(changedElseResult);
236 auto pairResult = std::make_pair(result, changedResult);
237 signatureCache[nodePair] = pairResult;
242template<
typename ValueType>
243std::pair<DdNodePtr, DdNodePtr> InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::refine(DdNode* partitionNode, DdNode* signatureNode,
244 DdNode* nondeterminismVariablesNode,
245 DdNode* nonBlockVariablesNode) {
247 if (partitionNode == Cudd_ReadZero(ddman)) {
248 if (options.createChangedStates) {
249 return std::make_pair(partitionNode, Cudd_ReadZero(ddman));
251 return std::make_pair(partitionNode,
nullptr);
253 }
else if (signatureNode == Cudd_ReadZero(ddman)) {
254 std::pair<DdNodePtr, DdNodePtr> result = reuseOrRelabel(partitionNode, nondeterminismVariablesNode, nonBlockVariablesNode);
255 signatureCache[std::make_pair(signatureNode, partitionNode)] = result;
260 auto nodePair = std::make_pair(signatureNode, partitionNode);
262 auto it = signatureCache.find(nodePair);
263 if (it != signatureCache.end()) {
269 if (Cudd_IsConstant(nonBlockVariablesNode)) {
270 if (options.reuseBlockNumbers) {
273 auto& reuseEntry = reuseBlocksCache[partitionNode];
274 if (!reuseEntry.isReused()) {
275 reuseEntry.setReused();
276 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(partitionNode, options.createChangedStates ? Cudd_ReadZero(ddman) : nullptr);
277 signatureCache[nodePair] = result;
282 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(encodeBlock(nextFreeBlockIndex++), options.createChangedStates ? Cudd_ReadOne(ddman) : nullptr);
283 signatureCache[nodePair] = result;
288 bool skippedBoth =
true;
289 DdNode* partitionThen;
290 DdNode* partitionElse;
291 DdNode* signatureThen;
292 DdNode* signatureElse;
294 bool isNondeterminismVariable;
295 while (skippedBoth && !Cudd_IsConstant(nonBlockVariablesNode)) {
297 offset = options.shiftStateVariables ? 1 : 0;
298 isNondeterminismVariable =
false;
299 if (!Cudd_IsConstant(nondeterminismVariablesNode) && Cudd_NodeReadIndex(nondeterminismVariablesNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
301 isNondeterminismVariable =
true;
304 if (Cudd_NodeReadIndex(partitionNode) - offset == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
305 partitionThen = Cudd_T(partitionNode);
306 partitionElse = Cudd_E(partitionNode);
309 partitionThen = partitionElse = partitionNode;
312 if (Cudd_NodeReadIndex(signatureNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
313 signatureThen = Cudd_T(signatureNode);
314 signatureElse = Cudd_E(signatureNode);
317 signatureThen = signatureElse = signatureNode;
323 nonBlockVariablesNode = Cudd_T(nonBlockVariablesNode);
324 if (isNondeterminismVariable) {
325 nondeterminismVariablesNode = Cudd_T(nondeterminismVariablesNode);
331 if (Cudd_IsConstant(nonBlockVariablesNode)) {
332 return refine(partitionNode, signatureNode, nondeterminismVariablesNode, nonBlockVariablesNode);
335 std::pair<DdNodePtr, DdNodePtr> combinedThenResult =
336 refine(partitionThen, signatureThen, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode,
337 Cudd_T(nonBlockVariablesNode));
338 DdNodePtr thenResult = combinedThenResult.first;
339 DdNodePtr changedThenResult = combinedThenResult.second;
340 Cudd_Ref(thenResult);
341 if (options.createChangedStates) {
342 Cudd_Ref(changedThenResult);
346 std::pair<DdNodePtr, DdNodePtr> combinedElseResult =
347 refine(partitionElse, signatureElse, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode,
348 Cudd_T(nonBlockVariablesNode));
349 DdNodePtr elseResult = combinedElseResult.first;
350 DdNodePtr changedElseResult = combinedElseResult.second;
351 Cudd_Ref(elseResult);
352 if (options.createChangedStates) {
353 Cudd_Ref(changedElseResult);
359 if (thenResult == elseResult) {
360 Cudd_Deref(thenResult);
361 Cudd_Deref(elseResult);
365 bool complemented = Cudd_IsComplement(thenResult);
366 result = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(thenResult),
367 complemented ? Cudd_Not(elseResult) : elseResult);
369 result = Cudd_Not(result);
371 Cudd_Deref(thenResult);
372 Cudd_Deref(elseResult);
375 DdNodePtr changedResult =
nullptr;
376 if (options.createChangedStates) {
377 if (changedThenResult == changedElseResult) {
378 Cudd_Deref(changedThenResult);
379 Cudd_Deref(changedElseResult);
380 changedResult = changedThenResult;
383 bool complemented = Cudd_IsComplement(changedThenResult);
384 changedResult = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(changedThenResult),
385 complemented ? Cudd_Not(changedElseResult) : changedElseResult);
387 changedResult = Cudd_Not(changedResult);
389 Cudd_Deref(changedThenResult);
390 Cudd_Deref(changedElseResult);
395 auto pairResult = std::make_pair(result, changedResult);
396 signatureCache[nodePair] = pairResult;
401template class InternalSignatureRefiner<storm::dd::DdType::CUDD, double>;
InternalAdd< LibraryType, ValueType > const & getInternalAdd() const
Retrieves the internal ADD.
std::set< storm::expressions::Variable > const & getContainedMetaVariables() const
Retrieves the set of all meta variables contained in the DD.
DdManager< LibraryType > & getDdManager() const
Retrieves the manager that is responsible for this DD.
uint64_t getNextFreeBlockIndex() const
storm::dd::Add< DdType, ValueType > const & asAdd() const
Partition< DdType, ValueType > replacePartition(storm::dd::Add< DdType, ValueType > const &newPartitionAdd, uint64_t numberOfBlocks, uint64_t nextFreeBlockIndex, boost::optional< storm::dd::Add< DdType, ValueType > > const &changedStates=boost::none) const
storm::dd::Add< DdType, ValueType > const & getSignatureAdd() const
#define STORM_LOG_ASSERT(cond, message)