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 =
44 ++numberOfRefinements;
45 return oldPartition.
replacePartition(newPartitionDds.first, nextFreeBlockIndex, nextFreeBlockIndex, newPartitionDds.second);
48template<
typename ValueType>
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>>>
63 std::pair<DdNodePtr, DdNodePtr> result =
65 nondeterminismVariables.getInternalBdd().getCuddDdNode(), nonBlockVariables.getInternalBdd().getCuddDdNode());
69 &manager.getInternalDdManager(), cudd::ADD(manager.getInternalDdManager().getCuddManager(), result.first));
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 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.
Partition< storm::dd::DdType::CUDD, ValueType > refine(Partition< storm::dd::DdType::CUDD, ValueType > const &oldPartition, Signature< storm::dd::DdType::CUDD, ValueType > const &signature)
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)