10namespace bisimulation {
13template<
typename ValueType>
16 std::set<storm::expressions::Variable>
const& stateVariables,
19 InternalSignatureRefinerOptions
const& options)
21 ddman(
manager.getInternalDdManager().getCuddManager().getManager()),
22 blockVariable(blockVariable),
23 stateVariables(stateVariables),
24 nondeterminismVariables(nondeterminismVariables),
25 nonBlockVariables(nonBlockVariables),
27 nextFreeBlockIndex(0),
28 numberOfRefinements(0),
32 auto const& ddMetaVariable =
manager.getMetaVariable(blockVariable);
33 blockDdVariableIndices = ddMetaVariable.getIndices();
36 blockEncoding = std::vector<int>(
static_cast<uint64_t
>(
manager.getInternalDdManager().getCuddManager().ReadSize()),
static_cast<int>(2));
39template<
typename ValueType>
40Partition<storm::dd::DdType::CUDD, ValueType> InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::refine(
41 Partition<storm::dd::DdType::CUDD, ValueType>
const& oldPartition, Signature<storm::dd::DdType::CUDD, ValueType>
const& signature) {
42 std::pair<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>, boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>>> newPartitionDds =
43 refine(oldPartition, signature.getSignatureAdd());
44 ++numberOfRefinements;
45 return oldPartition.replacePartition(newPartitionDds.first, nextFreeBlockIndex, nextFreeBlockIndex, newPartitionDds.second);
48template<
typename ValueType>
49void InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::clearCaches() {
50 signatureCache.clear();
51 reuseBlocksCache.clear();
54template<
typename ValueType>
55std::pair<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>, boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>>>
56InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::refine(Partition<storm::dd::DdType::CUDD, ValueType>
const& oldPartition,
58 STORM_LOG_ASSERT(oldPartition.storedAsAdd(),
"Expecting partition to be stored as ADD for CUDD.");
60 nextFreeBlockIndex = options.reuseBlockNumbers ? oldPartition.getNextFreeBlockIndex() : 0;
63 std::pair<DdNodePtr, DdNodePtr> result =
64 refine(oldPartition.asAdd().getInternalAdd().getCuddDdNode(), signatureAdd.
getInternalAdd().getCuddDdNode(),
69 &
manager.getInternalDdManager(), cudd::ADD(
manager.getInternalDdManager().getCuddManager(), result.first));
71 oldPartition.asAdd().getContainedMetaVariables());
73 boost::optional<storm::dd::Add<storm::dd::DdType::CUDD, ValueType>> optionalChangedAdd;
76 &
manager.getInternalDdManager(), cudd::ADD(
manager.getInternalDdManager().getCuddManager(), result.second));
78 optionalChangedAdd = changedAdd;
82 return std::make_pair(newPartitionAdd, optionalChangedAdd);
85template<
typename ValueType>
86DdNodePtr InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::encodeBlock(uint64_t blockIndex) {
87 for (
auto const& blockDdVariableIndex : blockDdVariableIndices) {
88 blockEncoding[blockDdVariableIndex] = blockIndex & 1 ? 1 : 0;
91 DdNodePtr bddEncoding = Cudd_CubeArrayToBdd(ddman, blockEncoding.data());
92 Cudd_Ref(bddEncoding);
93 DdNodePtr result = Cudd_BddToAdd(ddman, bddEncoding);
95 Cudd_RecursiveDeref(ddman, bddEncoding);
100template<
typename ValueType>
101std::pair<DdNodePtr, DdNodePtr> InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::reuseOrRelabel(DdNode* partitionNode,
102 DdNode* nondeterminismVariablesNode,
103 DdNode* nonBlockVariablesNode) {
105 if (partitionNode == Cudd_ReadZero(ddman)) {
106 if (options.createChangedStates) {
107 return std::make_pair(partitionNode, Cudd_ReadZero(ddman));
109 return std::make_pair(partitionNode,
nullptr);
114 auto nodePair = std::make_pair(
nullptr, partitionNode);
116 auto it = signatureCache.find(nodePair);
117 if (it != signatureCache.end()) {
123 if (Cudd_IsConstant(nonBlockVariablesNode)) {
124 if (options.reuseBlockNumbers) {
127 auto& reuseEntry = reuseBlocksCache[partitionNode];
128 if (!reuseEntry.isReused()) {
129 reuseEntry.setReused();
130 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(partitionNode, options.createChangedStates ? Cudd_ReadZero(ddman) : nullptr);
131 signatureCache[nodePair] = result;
136 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(encodeBlock(nextFreeBlockIndex++), options.createChangedStates ? Cudd_ReadOne(ddman) : nullptr);
137 signatureCache[nodePair] = result;
143 DdNode* partitionThen;
144 DdNode* partitionElse;
146 bool isNondeterminismVariable;
147 while (skipped && !Cudd_IsConstant(nonBlockVariablesNode)) {
149 offset = options.shiftStateVariables ? 1 : 0;
150 isNondeterminismVariable =
false;
151 if (!Cudd_IsConstant(nondeterminismVariablesNode) && Cudd_NodeReadIndex(nondeterminismVariablesNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
153 isNondeterminismVariable =
true;
156 if (Cudd_NodeReadIndex(partitionNode) - offset == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
157 partitionThen = Cudd_T(partitionNode);
158 partitionElse = Cudd_E(partitionNode);
161 partitionThen = partitionElse = partitionNode;
167 nonBlockVariablesNode = Cudd_T(nonBlockVariablesNode);
168 if (isNondeterminismVariable) {
169 nondeterminismVariablesNode = Cudd_T(nondeterminismVariablesNode);
175 if (Cudd_IsConstant(nonBlockVariablesNode)) {
176 return reuseOrRelabel(partitionNode, nondeterminismVariablesNode, nonBlockVariablesNode);
179 std::pair<DdNodePtr, DdNodePtr> combinedThenResult = reuseOrRelabel(
180 partitionThen, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode, Cudd_T(nonBlockVariablesNode));
181 DdNodePtr thenResult = combinedThenResult.first;
182 DdNodePtr changedThenResult = combinedThenResult.second;
183 Cudd_Ref(thenResult);
184 if (options.createChangedStates) {
185 Cudd_Ref(changedThenResult);
189 std::pair<DdNodePtr, DdNodePtr> combinedElseResult = reuseOrRelabel(
190 partitionElse, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode, Cudd_T(nonBlockVariablesNode));
191 DdNodePtr elseResult = combinedElseResult.first;
192 DdNodePtr changedElseResult = combinedElseResult.second;
193 Cudd_Ref(elseResult);
194 if (options.createChangedStates) {
195 Cudd_Ref(changedElseResult);
201 if (thenResult == elseResult) {
202 Cudd_Deref(thenResult);
203 Cudd_Deref(elseResult);
207 bool complemented = Cudd_IsComplement(thenResult);
208 result = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(thenResult),
209 complemented ? Cudd_Not(elseResult) : elseResult);
211 result = Cudd_Not(result);
213 Cudd_Deref(thenResult);
214 Cudd_Deref(elseResult);
217 DdNodePtr changedResult =
nullptr;
218 if (options.createChangedStates) {
219 if (changedThenResult == changedElseResult) {
220 Cudd_Deref(changedThenResult);
221 Cudd_Deref(changedElseResult);
222 changedResult = changedThenResult;
225 bool complemented = Cudd_IsComplement(changedThenResult);
226 changedResult = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(changedThenResult),
227 complemented ? Cudd_Not(changedElseResult) : changedElseResult);
229 changedResult = Cudd_Not(changedResult);
231 Cudd_Deref(changedThenResult);
232 Cudd_Deref(changedElseResult);
237 auto pairResult = std::make_pair(result, changedResult);
238 signatureCache[nodePair] = pairResult;
243template<
typename ValueType>
244std::pair<DdNodePtr, DdNodePtr> InternalSignatureRefiner<storm::dd::DdType::CUDD, ValueType>::refine(DdNode* partitionNode, DdNode* signatureNode,
245 DdNode* nondeterminismVariablesNode,
246 DdNode* nonBlockVariablesNode) {
248 if (partitionNode == Cudd_ReadZero(ddman)) {
249 if (options.createChangedStates) {
250 return std::make_pair(partitionNode, Cudd_ReadZero(ddman));
252 return std::make_pair(partitionNode,
nullptr);
254 }
else if (signatureNode == Cudd_ReadZero(ddman)) {
255 std::pair<DdNodePtr, DdNodePtr> result = reuseOrRelabel(partitionNode, nondeterminismVariablesNode, nonBlockVariablesNode);
256 signatureCache[std::make_pair(signatureNode, partitionNode)] = result;
261 auto nodePair = std::make_pair(signatureNode, partitionNode);
263 auto it = signatureCache.find(nodePair);
264 if (it != signatureCache.end()) {
270 if (Cudd_IsConstant(nonBlockVariablesNode)) {
271 if (options.reuseBlockNumbers) {
274 auto& reuseEntry = reuseBlocksCache[partitionNode];
275 if (!reuseEntry.isReused()) {
276 reuseEntry.setReused();
277 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(partitionNode, options.createChangedStates ? Cudd_ReadZero(ddman) : nullptr);
278 signatureCache[nodePair] = result;
283 std::pair<DdNodePtr, DdNodePtr> result = std::make_pair(encodeBlock(nextFreeBlockIndex++), options.createChangedStates ? Cudd_ReadOne(ddman) : nullptr);
284 signatureCache[nodePair] = result;
289 bool skippedBoth =
true;
290 DdNode* partitionThen;
291 DdNode* partitionElse;
292 DdNode* signatureThen;
293 DdNode* signatureElse;
295 bool isNondeterminismVariable;
296 while (skippedBoth && !Cudd_IsConstant(nonBlockVariablesNode)) {
298 offset = options.shiftStateVariables ? 1 : 0;
299 isNondeterminismVariable =
false;
300 if (!Cudd_IsConstant(nondeterminismVariablesNode) && Cudd_NodeReadIndex(nondeterminismVariablesNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
302 isNondeterminismVariable =
true;
305 if (Cudd_NodeReadIndex(partitionNode) - offset == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
306 partitionThen = Cudd_T(partitionNode);
307 partitionElse = Cudd_E(partitionNode);
310 partitionThen = partitionElse = partitionNode;
313 if (Cudd_NodeReadIndex(signatureNode) == Cudd_NodeReadIndex(nonBlockVariablesNode)) {
314 signatureThen = Cudd_T(signatureNode);
315 signatureElse = Cudd_E(signatureNode);
318 signatureThen = signatureElse = signatureNode;
324 nonBlockVariablesNode = Cudd_T(nonBlockVariablesNode);
325 if (isNondeterminismVariable) {
326 nondeterminismVariablesNode = Cudd_T(nondeterminismVariablesNode);
332 if (Cudd_IsConstant(nonBlockVariablesNode)) {
333 return refine(partitionNode, signatureNode, nondeterminismVariablesNode, nonBlockVariablesNode);
336 std::pair<DdNodePtr, DdNodePtr> combinedThenResult =
337 refine(partitionThen, signatureThen, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode,
338 Cudd_T(nonBlockVariablesNode));
339 DdNodePtr thenResult = combinedThenResult.first;
340 DdNodePtr changedThenResult = combinedThenResult.second;
341 Cudd_Ref(thenResult);
342 if (options.createChangedStates) {
343 Cudd_Ref(changedThenResult);
347 std::pair<DdNodePtr, DdNodePtr> combinedElseResult =
348 refine(partitionElse, signatureElse, isNondeterminismVariable ? Cudd_T(nondeterminismVariablesNode) : nondeterminismVariablesNode,
349 Cudd_T(nonBlockVariablesNode));
350 DdNodePtr elseResult = combinedElseResult.first;
351 DdNodePtr changedElseResult = combinedElseResult.second;
352 Cudd_Ref(elseResult);
353 if (options.createChangedStates) {
354 Cudd_Ref(changedElseResult);
360 if (thenResult == elseResult) {
361 Cudd_Deref(thenResult);
362 Cudd_Deref(elseResult);
366 bool complemented = Cudd_IsComplement(thenResult);
367 result = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(thenResult),
368 complemented ? Cudd_Not(elseResult) : elseResult);
370 result = Cudd_Not(result);
372 Cudd_Deref(thenResult);
373 Cudd_Deref(elseResult);
376 DdNodePtr changedResult =
nullptr;
377 if (options.createChangedStates) {
378 if (changedThenResult == changedElseResult) {
379 Cudd_Deref(changedThenResult);
380 Cudd_Deref(changedElseResult);
381 changedResult = changedThenResult;
384 bool complemented = Cudd_IsComplement(changedThenResult);
385 changedResult = cuddUniqueInter(ddman, Cudd_NodeReadIndex(nonBlockVariablesNode) + offset, Cudd_Regular(changedThenResult),
386 complemented ? Cudd_Not(changedElseResult) : changedElseResult);
388 changedResult = Cudd_Not(changedResult);
390 Cudd_Deref(changedThenResult);
391 Cudd_Deref(changedElseResult);
396 auto pairResult = std::make_pair(result, changedResult);
397 signatureCache[nodePair] = pairResult;
402template<
typename ValueType>
405 std::set<storm::expressions::Variable>
const& stateVariables,
410 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
411 "of Storm with CUDD support.");
414template<
typename ValueType>
418 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
419 "of Storm with CUDD support.");
InternalAdd< LibraryType, ValueType > const & getInternalAdd() const
Retrieves the internal ADD.
InternalBdd< LibraryType > const & getInternalBdd() const
Retrieves the internal BDD.
#define STORM_LOG_ASSERT(cond, message)
#define STORM_LOG_THROW(cond, exception, message)
SettingsManager const & manager()
Retrieves the settings manager.