Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
Partition.cpp
Go to the documentation of this file.
2
3#include <iostream>
4
6
9
10namespace storm {
11namespace storage {
12namespace bisimulation {
13template<typename DataType>
14Partition<DataType>::Partition(std::size_t numberOfStates) : stateToBlockMapping(numberOfStates), states(numberOfStates), positions(numberOfStates) {
15 blocks.emplace_back(new Block<DataType>(0, numberOfStates, nullptr, nullptr, blocks.size()));
16
17 // Set up the different parts of the internal structure.
18 for (storm::storage::sparse::state_type state = 0; state < numberOfStates; ++state) {
19 states[state] = state;
20 positions[state] = state;
21 stateToBlockMapping[state] = blocks.back().get();
22 }
23}
25template<typename DataType>
26Partition<DataType>::Partition(std::size_t numberOfStates, storm::storage::BitVector const& prob0States, storm::storage::BitVector const& prob1States,
27 boost::optional<storm::storage::sparse::state_type> representativeProb1State)
28 : stateToBlockMapping(numberOfStates), states(numberOfStates), positions(numberOfStates) {
30 Block<DataType>* firstBlock = nullptr;
31 Block<DataType>* secondBlock = nullptr;
32 Block<DataType>* thirdBlock = nullptr;
33 if (!prob0States.empty()) {
34 blocks.emplace_back(new Block<DataType>(0, prob0States.getNumberOfSetBits(), nullptr, nullptr, blocks.size()));
35 firstBlock = blocks.front().get();
36
37 for (auto state : prob0States) {
38 states[position] = state;
39 positions[state] = position;
40 stateToBlockMapping[state] = firstBlock;
41 ++position;
42 }
43 firstBlock->data().setAbsorbing(true);
44 }
45
46 if (!prob1States.empty()) {
47 blocks.emplace_back(new Block<DataType>(position, position + prob1States.getNumberOfSetBits(), firstBlock, nullptr, blocks.size()));
48 secondBlock = blocks.back().get();
49
50 for (auto state : prob1States) {
51 states[position] = state;
52 positions[state] = position;
53 stateToBlockMapping[state] = secondBlock;
54 ++position;
55 }
56 secondBlock->data().setAbsorbing(true);
57 secondBlock->data().setRepresentativeState(representativeProb1State.get());
58 }
60 storm::storage::BitVector otherStates = ~(prob0States | prob1States);
61 if (!otherStates.empty()) {
62 blocks.emplace_back(new Block<DataType>(position, numberOfStates, secondBlock, nullptr, blocks.size()));
63 thirdBlock = blocks.back().get();
64
65 for (auto state : otherStates) {
66 states[position] = state;
67 positions[state] = position;
68 stateToBlockMapping[state] = thirdBlock;
69 ++position;
70 }
71 }
72}
74template<typename DataType>
76 std::swap(this->states[this->positions[state1]], this->states[this->positions[state2]]);
77 std::swap(this->positions[state1], this->positions[state2]);
79
80template<typename DataType>
82 storm::storage::sparse::state_type state1 = this->states[position1];
83 storm::storage::sparse::state_type state2 = this->states[position2];
84 std::swap(this->states[position1], this->states[position2]);
85 this->positions[state1] = position2;
86 this->positions[state2] = position1;
87}
88
89template<typename DataType>
91 return this->positions[state];
92}
93
94template<typename DataType>
98
99template<typename DataType>
100void Partition<DataType>::mapStatesToBlock(Block<DataType>& block, std::vector<storm::storage::sparse::state_type>::iterator first,
101 std::vector<storm::storage::sparse::state_type>::iterator last) {
102 for (; first != last; ++first) {
103 this->stateToBlockMapping[*first] = &block;
104 }
105}
107template<typename DataType>
108void Partition<DataType>::mapStatesToPositions(std::vector<storm::storage::sparse::state_type>::const_iterator first,
109 std::vector<storm::storage::sparse::state_type>::const_iterator last) {
110 storm::storage::sparse::state_type position = std::distance(this->states.cbegin(), first);
111 for (; first != last; ++first, ++position) {
112 this->positions[*first] = position;
113 }
114}
116template<typename DataType>
118 mapStatesToPositions(this->begin(block), this->end(block));
119}
120
121template<typename DataType>
123 return *this->stateToBlockMapping[state];
125
126template<typename DataType>
128 return *this->stateToBlockMapping[state];
129}
131template<typename DataType>
132std::vector<storm::storage::sparse::state_type>::iterator Partition<DataType>::begin(Block<DataType> const& block) {
133 auto it = this->states.begin();
134 std::advance(it, block.getBeginIndex());
135 return it;
137
138template<typename DataType>
139std::vector<storm::storage::sparse::state_type>::const_iterator Partition<DataType>::begin(Block<DataType> const& block) const {
140 auto it = this->states.begin();
141 std::advance(it, block.getBeginIndex());
142 return it;
143}
144
145template<typename DataType>
146std::vector<storm::storage::sparse::state_type>::iterator Partition<DataType>::end(Block<DataType> const& block) {
147 auto it = this->states.begin();
148 std::advance(it, block.getEndIndex());
149 return it;
150}
152template<typename DataType>
153std::vector<storm::storage::sparse::state_type>::const_iterator Partition<DataType>::end(Block<DataType> const& block) const {
154 auto it = this->states.begin();
155 std::advance(it, block.getEndIndex());
156 return it;
157}
159template<typename DataType>
160std::vector<storm::storage::sparse::state_type>::iterator Partition<DataType>::begin() {
161 return this->states.begin();
163
164template<typename DataType>
165std::vector<storm::storage::sparse::state_type>::const_iterator Partition<DataType>::begin() const {
166 return this->states.begin();
167}
168
169template<typename DataType>
170std::vector<storm::storage::sparse::state_type>::iterator Partition<DataType>::end() {
171 return this->states.end();
172}
173
174template<typename DataType>
175std::vector<storm::storage::sparse::state_type>::const_iterator Partition<DataType>::end() const {
176 return this->states.end();
177}
178
179template<typename DataType>
182 bool updatePositions) {
183 // FIXME, TODO: Wrapping less argument in a lambda here, as clang and the GCC stdlib do not play nicely
184 // Pass 'less' directly to std::sort when this has been resolved (problem with clang 3.7, gcc 5.1)
185 std::sort(this->states.begin() + beginIndex, this->states.begin() + endIndex,
186 [&](const storm::storage::sparse::state_type& a, storm::storage::sparse::state_type& b) { return less(a, b); });
187
188 if (updatePositions) {
189 mapStatesToPositions(this->states.begin() + beginIndex, this->states.begin() + endIndex);
190 }
191}
192
193template<typename DataType>
196 bool updatePositions) {
197 sortRange(block.getBeginIndex(), block.getEndIndex(), less, updatePositions);
198}
199
200template<typename DataType>
202 uint_fast64_t startIndex, uint_fast64_t endIndex, std::function<bool(storm::storage::sparse::state_type, storm::storage::sparse::state_type)> const& less) {
203 auto it = this->states.cbegin() + startIndex;
204 auto ite = this->states.cbegin() + endIndex;
205
206 std::vector<storm::storage::sparse::state_type>::const_iterator upperBound;
207 std::vector<uint_fast64_t> result;
208 result.push_back(startIndex);
209 do {
210 upperBound = std::upper_bound(it, ite, *it, less);
211 result.push_back(std::distance(this->states.cbegin(), upperBound));
212 it = upperBound;
213 } while (upperBound != ite);
214
215 return result;
216}
217
218template<typename DataType>
219std::pair<typename std::vector<std::unique_ptr<Block<DataType>>>::iterator, bool> Partition<DataType>::splitBlock(Block<DataType>& block,
221 STORM_LOG_ASSERT(position >= block.getBeginIndex() && position <= block.getEndIndex(), "Cannot split block at illegal position.");
222 STORM_LOG_TRACE("Splitting " << block.getId() << " at position " << position << " (begin was " << block.getBeginIndex() << ").");
223
224 // In case one of the resulting blocks would be empty, we simply return the current block and do not create
225 // a new one.
226 if (position == block.getBeginIndex() || position == block.getEndIndex()) {
227 auto it = blocks.begin();
228 std::advance(it, block.getId());
229 return std::make_pair(it, false);
230 }
231
232 // Actually create the new block.
233 blocks.emplace_back(new Block<DataType>(block.getBeginIndex(), position, block.getPreviousBlockPointer(), &block, blocks.size()));
234 auto newBlockIt = std::prev(blocks.end());
235
236 // Resize the current block appropriately.
237 block.setBeginIndex(position);
238
239 // Update the mapping of the states in the newly created block.
240 this->mapStatesToBlock(**newBlockIt, this->begin(**newBlockIt), this->end(**newBlockIt));
241
242 return std::make_pair(newBlockIt, true);
243}
244
245template<typename DataType>
248 std::function<void(Block<DataType>&)> const& newBlockCallback) {
249 // Sort the block, but leave the positions untouched.
250 this->sortBlock(block, less, false);
251
252 auto originalBegin = block.getBeginIndex();
253 auto originalEnd = block.getEndIndex();
254
255 auto it = this->states.cbegin() + block.getBeginIndex();
256 auto ite = this->states.cbegin() + block.getEndIndex();
257
258 bool wasSplit = false;
259 std::vector<storm::storage::sparse::state_type>::const_iterator upperBound;
260 do {
261 upperBound = std::upper_bound(it, ite, *it, less);
262
263 if (upperBound != ite) {
264 wasSplit = true;
265 auto result = this->splitBlock(block, std::distance(this->states.cbegin(), upperBound));
266 newBlockCallback(**result.first);
267 }
268 it = upperBound;
269 } while (upperBound != ite);
270
271 // Finally, repair the positions mapping.
272 mapStatesToPositions(this->states.begin() + originalBegin, this->states.begin() + originalEnd);
273
274 return wasSplit;
275}
276
277// Splits the block by sorting the states according to the given function and then identifying the split
278// points.
279template<typename DataType>
282 return this->splitBlock(block, less, [](Block<DataType>&) {});
283}
284
285template<typename DataType>
287 std::function<void(Block<DataType>&)> const& newBlockCallback) {
288 bool result = false;
289 // Since the underlying storage of the blocks may change during iteration, we remember the current size
290 // and iterate over indices. This assumes that new blocks will be added at the end of the blocks vector.
291 std::size_t currentSize = this->size();
292 for (uint_fast64_t index = 0; index < currentSize; ++index) {
293 result |= splitBlock(*blocks[index], less, newBlockCallback);
294 }
295 return result;
296}
297
298template<typename DataType>
300 return this->split(less, [](Block<DataType>&) {});
301}
302
303template<typename DataType>
305 this->splitBlock(
306 block, [&states](storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { return states.get(a) && !states.get(b); });
307}
308
309template<typename DataType>
311 this->split(
312 [&states](storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { return states.get(a) && !states.get(b); });
313}
314
315template<typename DataType>
317 std::sort(this->begin(block), this->end(block),
318 [](storm::storage::sparse::state_type const& a, storm::storage::sparse::state_type const& b) { return a < b; });
319 mapStatesToPositions(block);
320}
321
322template<typename DataType>
323std::vector<std::unique_ptr<Block<DataType>>> const& Partition<DataType>::getBlocks() const {
324 return this->blocks;
325}
326
327template<typename DataType>
328std::vector<std::unique_ptr<Block<DataType>>>& Partition<DataType>::getBlocks() {
329 return this->blocks;
330}
331
332template<typename DataType>
334 for (uint_fast64_t state = 0; state < this->positions.size(); ++state) {
335 STORM_LOG_ASSERT(this->states[this->positions[state]] == state, "Position mapping corrupted.");
336 }
337 for (auto const& blockPtr : this->blocks) {
338 STORM_LOG_ASSERT(blockPtr->check(), "Block corrupted.");
339 for (auto stateIt = this->begin(*blockPtr), stateIte = this->end(*blockPtr); stateIt != stateIte; ++stateIt) {
340 STORM_LOG_ASSERT(this->stateToBlockMapping[*stateIt] == blockPtr.get(), "Block mapping corrupted.");
341 }
342 }
343 return true;
344}
345
346template<typename DataType>
348 for (auto const& block : this->blocks) {
349 block->print(*this);
350 }
351 std::cout << "states in partition\n";
352 for (auto const& state : states) {
353 std::cout << state << " ";
354 }
355 std::cout << "\npositions: \n";
356 for (auto const& index : positions) {
357 std::cout << index << " ";
358 }
359 std::cout << "\nstate to block mapping: \n";
360 for (auto const& block : stateToBlockMapping) {
361 std::cout << block << "[" << block->getId() << "] ";
362 }
363 std::cout << "\nsize: " << blocks.size() << '\n';
364 STORM_LOG_ASSERT(this->check(), "Partition corrupted.");
365}
366
367template<typename DataType>
368std::size_t Partition<DataType>::size() const {
369 return blocks.size();
370}
371
373
374} // namespace bisimulation
375} // namespace storage
376} // namespace storm
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
bool empty() const
Retrieves whether no bits are set to true in this bit vector.
uint_fast64_t getNumberOfSetBits() const
Returns the number of bits that are set to true in this bit vector.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
storm::storage::sparse::state_type getEndIndex() const
Definition Block.cpp:74
void print(Partition< DataType > const &partition) const
Definition Block.cpp:40
storm::storage::sparse::state_type getBeginIndex() const
Definition Block.cpp:69
std::size_t getId() const
Definition Block.cpp:64
void sortRange(storm::storage::sparse::state_type beginIndex, storm::storage::sparse::state_type endIndex, std::function< bool(storm::storage::sparse::state_type, storm::storage::sparse::state_type)> const &less, bool updatePositions=true)
storm::storage::sparse::state_type const & getPosition(storm::storage::sparse::state_type state) const
Definition Partition.cpp:90
std::pair< typename std::vector< std::unique_ptr< Block< DataType > > >::iterator, bool > splitBlock(Block< DataType > &block, storm::storage::sparse::state_type position)
Block< DataType > & getBlock(storm::storage::sparse::state_type state)
storm::storage::sparse::state_type const & getState(storm::storage::sparse::state_type position) const
Definition Partition.cpp:95
void sortBlock(Block< DataType > &block, std::function< bool(storm::storage::sparse::state_type, storm::storage::sparse::state_type)> const &less, bool updatePositions=true)
void splitStates(Block< DataType > &block, storm::storage::BitVector const &states)
std::vector< storm::storage::sparse::state_type >::iterator end(Block< DataType > const &block)
void mapStatesToPositions(Block< DataType > const &block)
void swapStates(storm::storage::sparse::state_type state1, storm::storage::sparse::state_type state2)
Definition Partition.cpp:75
std::vector< std::unique_ptr< Block< DataType > > > const & getBlocks() const
bool split(std::function< bool(storm::storage::sparse::state_type, storm::storage::sparse::state_type)> const &less, std::function< void(Block< DataType > &)> const &newBlockCallback)
std::vector< storm::storage::sparse::state_type >::iterator begin()
void mapStatesToBlock(Block< DataType > &block, std::vector< storm::storage::sparse::state_type >::iterator first, std::vector< storm::storage::sparse::state_type >::iterator last)
void swapStatesAtPositions(storm::storage::sparse::state_type position1, storm::storage::sparse::state_type position2)
Definition Partition.cpp:81
std::vector< storm::storage::sparse::state_type >::iterator end()
std::vector< uint_fast64_t > computeRangesOfEqualValue(uint_fast64_t startIndex, uint_fast64_t endIndex, std::function< bool(storm::storage::sparse::state_type, storm::storage::sparse::state_type)> const &less)
#define STORM_LOG_TRACE(message)
Definition logging.h:17
#define STORM_LOG_ASSERT(cond, message)
Definition macros.h:11
LabParser.cpp.
Definition cli.cpp:18