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