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