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