Storm 1.11.1.1
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
CuddAddIterator.cpp
Go to the documentation of this file.
2
3#include <cmath>
4
11
12namespace storm {
13namespace dd {
14
15#ifdef STORM_HAVE_CUDD
16template<typename ValueType>
17AddIterator<DdType::CUDD, ValueType>::AddIterator()
18 : ddManager(),
19 generator(),
20 cube(),
21 valueAsDouble(),
22 isAtEnd(),
23 metaVariables(),
24 enumerateDontCareMetaVariables(),
25 cubeCounter(),
26 relevantDontCareDdVariables(),
27 currentValuation() {
28 // Intentionally left empty.
29}
30
31template<typename ValueType>
32AddIterator<DdType::CUDD, ValueType>::AddIterator(DdManager<DdType::CUDD> const& ddManager, DdGen* generator, int* cube, ValueType const& value, bool isAtEnd,
33 std::set<storm::expressions::Variable> const* metaVariables, bool enumerateDontCareMetaVariables)
34 : ddManager(&ddManager),
35 generator(generator),
36 cube(cube),
37 valueAsDouble(storm::utility::convertNumber<double>(value)),
38 isAtEnd(isAtEnd),
39 metaVariables(metaVariables),
40 enumerateDontCareMetaVariables(enumerateDontCareMetaVariables),
41 cubeCounter(),
42 relevantDontCareDdVariables(),
43 currentValuation(ddManager.getExpressionManager().getSharedPointer()) {
44 // If the given generator is not yet at its end, we need to create the current valuation from the cube from
45 // scratch.
46 if (!this->isAtEnd) {
47 // And then get ready for treating the first cube.
48 this->treatNewCube();
49 }
50}
51
52template<typename ValueType>
53AddIterator<DdType::CUDD, ValueType>::AddIterator(AddIterator<DdType::CUDD, ValueType>&& other)
54 : ddManager(other.ddManager),
55 generator(other.generator),
56 cube(other.cube),
57 valueAsDouble(other.valueAsDouble),
58 isAtEnd(other.isAtEnd),
59 metaVariables(other.metaVariables),
60 cubeCounter(other.cubeCounter),
61 relevantDontCareDdVariables(other.relevantDontCareDdVariables),
62 currentValuation(other.currentValuation) {
63 // Null-out the pointers of which we took possession.
64 other.cube = nullptr;
65 other.generator = nullptr;
66}
67
68template<typename ValueType>
69AddIterator<DdType::CUDD, ValueType>& AddIterator<DdType::CUDD, ValueType>::operator=(AddIterator<DdType::CUDD, ValueType>&& other) {
70 if (this != &other) {
71 this->ddManager = other.ddManager;
72 this->generator = other.generator;
73 this->cube = other.cube;
74 this->valueAsDouble = other.valueAsDouble;
75 this->isAtEnd = other.isAtEnd;
76 this->metaVariables = other.metaVariables;
77 this->cubeCounter = other.cubeCounter;
78 this->relevantDontCareDdVariables = other.relevantDontCareDdVariables;
79 this->currentValuation = other.currentValuation;
80
81 // Null-out the pointers of which we took possession.
82 other.cube = nullptr;
83 other.generator = nullptr;
84 }
85 return *this;
86}
87
88template<typename ValueType>
89AddIterator<DdType::CUDD, ValueType>::~AddIterator() {
90 // We free the pointers sind Cudd allocates them using malloc rather than new/delete.
91 free(this->cube);
92 free(this->generator);
93}
94
95template<typename ValueType>
96AddIterator<DdType::CUDD, ValueType>& AddIterator<DdType::CUDD, ValueType>::operator++() {
97 STORM_LOG_ASSERT(!this->isAtEnd, "Illegally incrementing iterator that is already at its end.");
98
99 // If there were no (relevant) don't cares or we have enumerated all combination, we need to eliminate the
100 // found solutions and get the next "first" cube.
101 if (this->relevantDontCareDdVariables.empty() || this->cubeCounter >= std::pow(2, this->relevantDontCareDdVariables.size()) - 1) {
102 // Get the next cube and check for emptiness.
103 cudd::ABDD::NextCube(generator, &cube, &valueAsDouble);
104 this->isAtEnd = (Cudd_IsGenEmpty(generator) != 0);
105
106 // In case we are not done yet, we get ready to treat the next cube.
107 if (!this->isAtEnd) {
108 this->treatNewCube();
109 }
110 } else {
111 // Treat the next solution of the cube.
112 this->treatNextInCube();
113 }
114
115 return *this;
116}
117
118template<typename ValueType>
119void AddIterator<DdType::CUDD, ValueType>::treatNextInCube() {
120 // Start by increasing the counter and check which bits we need to set/unset in the new valuation.
121 ++this->cubeCounter;
122
123 for (uint_fast64_t index = 0; index < this->relevantDontCareDdVariables.size(); ++index) {
124 auto const& ddMetaVariable = this->ddManager->getMetaVariable(std::get<0>(this->relevantDontCareDdVariables[index]));
125 if (ddMetaVariable.getType() == MetaVariableType::Bool) {
126 if ((this->cubeCounter & (1ull << index)) != 0) {
127 currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), true);
128 } else {
129 currentValuation.setBooleanValue(std::get<0>(this->relevantDontCareDdVariables[index]), false);
130 }
131 } else {
132 storm::expressions::Variable const& metaVariable = std::get<0>(this->relevantDontCareDdVariables[index]);
133 if ((this->cubeCounter & (1ull << index)) != 0) {
134 currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) |
135 (1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) +
136 ddMetaVariable.getLow());
137 } else {
138 currentValuation.setBitVectorValue(metaVariable, ((currentValuation.getBitVectorValue(metaVariable) - ddMetaVariable.getLow()) &
139 ~(1ull << std::get<1>(this->relevantDontCareDdVariables[index]))) +
140 ddMetaVariable.getLow());
141 }
142 }
143 }
144}
145
146template<typename ValueType>
147void AddIterator<DdType::CUDD, ValueType>::treatNewCube() {
148 this->relevantDontCareDdVariables.clear();
149
150 // Now loop through the bits of all meta variables and check whether they need to be set, not set or are
151 // don't cares. In the latter case, we add them to a special list, so we can iterate over their concrete
152 // valuations later.
153 for (auto const& metaVariable : *this->metaVariables) {
154 bool metaVariableAppearsInCube = false;
155 std::vector<std::tuple<storm::expressions::Variable, uint_fast64_t>> localRelevantDontCareDdVariables;
156 auto const& ddMetaVariable = this->ddManager->getMetaVariable(metaVariable);
157 if (ddMetaVariable.getType() == MetaVariableType::Bool) {
158 if (this->cube[ddMetaVariable.getDdVariables().front().getIndex()] == 0) {
159 metaVariableAppearsInCube = true;
160 currentValuation.setBooleanValue(metaVariable, false);
161 } else if (this->cube[ddMetaVariable.getDdVariables().front().getIndex()] == 1) {
162 metaVariableAppearsInCube = true;
163 currentValuation.setBooleanValue(metaVariable, true);
164 } else {
165 currentValuation.setBooleanValue(metaVariable, false);
166 localRelevantDontCareDdVariables.push_back(std::make_tuple(metaVariable, 0));
167 }
168 } else {
169 int_fast64_t intValue = 0;
170 for (uint_fast64_t bitIndex = 0; bitIndex < ddMetaVariable.getNumberOfDdVariables(); ++bitIndex) {
171 if (cube[ddMetaVariable.getDdVariables()[bitIndex].getIndex()] == 0) {
172 // Leave bit unset.
173 metaVariableAppearsInCube = true;
174 } else if (cube[ddMetaVariable.getDdVariables()[bitIndex].getIndex()] == 1) {
175 intValue |= 1ull << (ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1);
176 metaVariableAppearsInCube = true;
177 } else {
178 // Temporarily leave bit unset so we can iterate trough the other option later.
179 // Add the bit to the relevant don't care bits.
180 localRelevantDontCareDdVariables.push_back(std::make_tuple(metaVariable, ddMetaVariable.getNumberOfDdVariables() - bitIndex - 1));
181 }
182 }
183 if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
184 currentValuation.setBitVectorValue(metaVariable, intValue + ddMetaVariable.getLow());
185 }
186 }
187
188 // If all meta variables are to be enumerated or the meta variable appeared in the cube, we register the
189 // missing bits to later enumerate all possible valuations.
190 if (this->enumerateDontCareMetaVariables || metaVariableAppearsInCube) {
191 relevantDontCareDdVariables.insert(relevantDontCareDdVariables.end(), localRelevantDontCareDdVariables.begin(),
192 localRelevantDontCareDdVariables.end());
193 }
194 }
195
196 // Finally, reset the cube counter.
197 this->cubeCounter = 0;
198}
199
200template<typename ValueType>
201bool AddIterator<DdType::CUDD, ValueType>::operator==(AddIterator<DdType::CUDD, ValueType> const& other) const {
202 if (this->isAtEnd && other.isAtEnd) {
203 return true;
204 } else {
205 return this->ddManager == other.ddManager && this->generator == other.generator && this->cube == other.cube &&
206 this->valueAsDouble == other.valueAsDouble && this->isAtEnd == other.isAtEnd && this->metaVariables == other.metaVariables &&
207 this->cubeCounter == other.cubeCounter && this->relevantDontCareDdVariables == other.relevantDontCareDdVariables &&
208 this->currentValuation == other.currentValuation;
209 }
210}
211
212template<typename ValueType>
213bool AddIterator<DdType::CUDD, ValueType>::operator!=(AddIterator<DdType::CUDD, ValueType> const& other) const {
214 return !(*this == other);
215}
216
217template<typename ValueType>
218std::pair<storm::expressions::SimpleValuation, ValueType> AddIterator<DdType::CUDD, ValueType>::operator*() const {
219 return std::make_pair(currentValuation, storm::utility::convertNumber<ValueType>(valueAsDouble));
220}
221
222#else
223template<typename ValueType>
225 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
226 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
227 "of Storm with CUDD support.");
228}
229
230template<typename ValueType>
232 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
233 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
234 "of Storm with CUDD support.");
235}
236
237template<typename ValueType>
239 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
240 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
241 "of Storm with CUDD support.");
242}
243
244template<typename ValueType>
246
247template<typename ValueType>
249 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
250 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
251 "of Storm with CUDD support.");
252}
253
254template<typename ValueType>
256 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
257 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
258 "of Storm with CUDD support.");
259}
260
261template<typename ValueType>
263 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
264 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
265 "of Storm with CUDD support.");
266}
267
268template<typename ValueType>
269std::pair<storm::expressions::SimpleValuation, ValueType> AddIterator<DdType::CUDD, ValueType>::operator*() const {
270 STORM_LOG_THROW(false, storm::exceptions::MissingLibraryException,
271 "This version of Storm was compiled without support for CUDD. Yet, a method was called that requires this support. Please choose a version "
272 "of Storm with CUDD support.");
273}
274#endif
275
279
280} // namespace dd
281} // namespace storm
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
#define STORM_LOG_THROW(cond, exception, message)
Definition macros.h:30
TargetType convertNumber(SourceType const &number)