Storm
A Modern Probabilistic Model Checker
Loading...
Searching...
No Matches
BitVectorHashMap.cpp
Go to the documentation of this file.
2
3#include <algorithm>
4#include <iostream>
5
8
9namespace storm {
10namespace storage {
11template<class ValueType, class Hash>
13 : map(map), indexIt(indexIt) {
14 // Intentionally left empty.
15}
16
17template<class ValueType, class Hash>
19 return &map == &other.map && *indexIt == *other.indexIt;
20}
21
22template<class ValueType, class Hash>
26
27template<class ValueType, class Hash>
29 ++indexIt;
30 return *this;
31}
33template<class ValueType, class Hash>
35 ++indexIt;
36 return *this;
38
39template<class ValueType, class Hash>
40std::pair<storm::storage::BitVector, ValueType> BitVectorHashMap<ValueType, Hash>::BitVectorHashMapIterator::operator*() const {
41 return map.getBucketAndValue(*indexIt);
42}
43
44template<class ValueType, class Hash>
45BitVectorHashMap<ValueType, Hash>::BitVectorHashMap(uint64_t bucketSize, uint64_t initialSize, double loadFactor)
46 : loadFactor(loadFactor), bucketSize(bucketSize), currentSize(1), numberOfElements(0) {
47 STORM_LOG_ASSERT(bucketSize % 64 == 0, "Bucket size must be a multiple of 64.");
48
49 while (initialSize > 0) {
50 ++currentSize;
51 initialSize >>= 1;
52 }
53
54 // Create the underlying containers.
55 buckets = storm::storage::BitVector(bucketSize * (1ull << currentSize));
56 occupied = storm::storage::BitVector(1ull << currentSize);
57 values = std::vector<ValueType>(1ull << currentSize);
58}
59
60template<class ValueType, class Hash>
61bool BitVectorHashMap<ValueType, Hash>::isBucketOccupied(uint_fast64_t bucket) const {
62 return occupied.get(bucket);
63}
64
65template<class ValueType, class Hash>
67 return numberOfElements;
68}
69
70template<class ValueType, class Hash>
72 return 1ull << currentSize;
73}
74
75template<class ValueType, class Hash>
77 ++currentSize;
78 STORM_LOG_TRACE("Increasing size of hash map from " << (1ull << (currentSize - 1)) << " to " << (1ull << currentSize) << ".");
79
80 // Create new containers and swap them with the old ones.
81 storm::storage::BitVector oldBuckets(bucketSize * (1ull << currentSize));
82 std::swap(oldBuckets, buckets);
83 storm::storage::BitVector oldOccupied = storm::storage::BitVector(1ull << currentSize);
84 std::swap(oldOccupied, occupied);
85 std::vector<ValueType> oldValues = std::vector<ValueType>(1ull << currentSize);
86 std::swap(oldValues, values);
88 // Now iterate through the elements and reinsert them in the new storage.
89 [[maybe_unused]] uint64_t oldSize = numberOfElements;
90 numberOfElements = 0;
91 for (auto bucketIndex : oldOccupied) {
92 findOrAddAndGetBucket(oldBuckets.get(bucketIndex * bucketSize, bucketSize), oldValues[bucketIndex]);
93 }
94 STORM_LOG_ASSERT(oldSize == numberOfElements, "Size mismatch in rehashing. Size before was " << oldSize << " and new size is " << numberOfElements << ".");
96
97template<class ValueType, class Hash>
98ValueType BitVectorHashMap<ValueType, Hash>::findOrAdd(storm::storage::BitVector const& key, ValueType const& value) {
99 return findOrAddAndGetBucket(key, value).first;
100}
101
102template<class ValueType, class Hash>
103std::pair<ValueType, uint64_t> BitVectorHashMap<ValueType, Hash>::findOrAddAndGetBucket(storm::storage::BitVector const& key, ValueType const& value) {
104 checkIncreaseSize();
105
106 std::pair<bool, uint64_t> flagAndBucket = this->findBucket(key);
107 if (flagAndBucket.first) {
108 return std::make_pair(values[flagAndBucket.second], flagAndBucket.second);
109 } else {
110 // Insert the new bits into the bucket.
111 buckets.set(flagAndBucket.second * bucketSize, key);
112 occupied.set(flagAndBucket.second);
113 values[flagAndBucket.second] = value;
114 ++numberOfElements;
115 return std::make_pair(value, flagAndBucket.second);
116 }
117}
119template<class ValueType, class Hash>
121 // If the load of the map is too high, we increase the size.
122 if (numberOfElements >= loadFactor * (1ull << currentSize)) {
123 this->increaseSize();
124 return true;
126 return false;
127}
128
129template<class ValueType, class Hash>
131 std::pair<bool, uint64_t> flagBucketPair = this->findBucket(key);
132 STORM_LOG_ASSERT(flagBucketPair.first, "Unknown key.");
133 return values[flagBucketPair.second];
134}
135
136template<class ValueType, class Hash>
137ValueType BitVectorHashMap<ValueType, Hash>::getValue(uint64_t bucket) const {
138 return values[bucket];
140
141template<class ValueType, class Hash>
143 return findBucket(key).first;
144}
145
146template<class ValueType, class Hash>
150
151template<class ValueType, class Hash>
153 return const_iterator(*this, occupied.end());
154}
155
156template<class ValueType, class Hash>
158 return (sizeof(decltype(hasher(storm::storage::BitVector()))) * 8 - currentSize);
159}
160
161template<class ValueType, class Hash>
162std::pair<bool, uint64_t> BitVectorHashMap<ValueType, Hash>::findBucket(storm::storage::BitVector const& key) const {
163 STORM_LOG_ASSERT(key.size() == bucketSize, "Size of bit vector and size of buckets do not match");
164 uint64_t bucket = hasher(key) >> this->getCurrentShiftWidth();
165
166 while (isBucketOccupied(bucket)) {
167 if (buckets.matches(bucket * bucketSize, key)) {
168 return std::make_pair(true, bucket);
169 }
170 ++bucket;
171 if (bucket == (1ull << currentSize)) {
172 bucket = 0;
173 }
174 }
175
176 return std::make_pair(false, bucket);
177}
178
179template<class ValueType, class Hash>
180std::pair<storm::storage::BitVector, ValueType> BitVectorHashMap<ValueType, Hash>::getBucketAndValue(uint64_t bucket) const {
181 return std::make_pair(buckets.get(bucket * bucketSize, bucketSize), values[bucket]);
182}
183
184template<class ValueType, class Hash>
185void BitVectorHashMap<ValueType, Hash>::remap(std::function<ValueType(ValueType const&)> const& remapping) {
186 for (auto pos : occupied) {
187 values[pos] = remapping(values[pos]);
188 }
189}
190
191template class BitVectorHashMap<uint64_t>;
192template class BitVectorHashMap<uint32_t>;
193// These instantiations allow you to "group" states in a BitVectorHashMap. I.e.,
194// if you want to look at a state and know what "group" it is in (with groups
195// controlled by an 8 bit group index) you can instantiate a BitVectorHashMap<uint8_t>
196// which looks up your state and returns a group inded
197//
198// For example, the STAMINA project (built on STORM) uses this for thread indecies
199// in its multithreading implementation.
202} // namespace storage
203} // namespace storm
A class that enables iterating over the indices of the bit vector whose corresponding bits are set to...
Definition BitVector.h:25
bool operator==(BitVectorHashMapIterator const &other)
std::pair< storm::storage::BitVector, ValueType > operator*() const
bool operator!=(BitVectorHashMapIterator const &other)
BitVectorHashMapIterator(BitVectorHashMap const &map, BitVector::const_iterator indexIt)
Creates an iterator that points to the bucket with the given index in the given map.
This class represents a hash-map whose keys are bit vectors.
std::pair< ValueType, uint64_t > findOrAddAndGetBucket(storm::storage::BitVector const &key, ValueType const &value)
Searches for the given key in the map.
ValueType findOrAdd(storm::storage::BitVector const &key, ValueType const &value)
Searches for the given key in the map.
std::pair< storm::storage::BitVector, ValueType > getBucketAndValue(uint64_t bucket) const
Retrieves the key stored in the given bucket (if any) and the value it is mapped to.
BitVectorHashMap(uint64_t bucketSize, uint64_t initialSize=1000, double loadFactor=0.75)
Creates a new hash map with the given bucket size and initial size.
ValueType getValue(storm::storage::BitVector const &key) const
Retrieves the value associated with the given key (if any).
const_iterator begin() const
Retrieves an iterator to the elements of the map.
uint64_t capacity() const
Retrieves the capacity of the underlying container.
const_iterator end() const
Retrieves an iterator that points one past the elements of the map.
bool contains(storm::storage::BitVector const &key) const
Checks if the given key is already contained in the map.
void remap(std::function< ValueType(ValueType const &)> const &remapping)
Performs a remapping of all values stored by applying the given remapping.
uint64_t size() const
Retrieves the size of the map in terms of the number of key-value pairs it stores.
A bit vector that is internally represented as a vector of 64-bit values.
Definition BitVector.h:18
size_t size() const
Retrieves the number of bits this bit vector can store.
bool get(uint_fast64_t index) const
Retrieves the truth value of the bit at the given index and performs a bound check.
#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