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