1 |
|
/****************************************************************************** |
2 |
|
* Top contributors (to current version): |
3 |
|
* Tim King, Dejan Jovanovic, Mathias Preiner |
4 |
|
* |
5 |
|
* This file is part of the cvc5 project. |
6 |
|
* |
7 |
|
* Copyright (c) 2009-2021 by the authors listed in the file AUTHORS |
8 |
|
* in the top-level source directory and their institutional affiliations. |
9 |
|
* All rights reserved. See the file COPYING in the top-level source |
10 |
|
* directory for licensing information. |
11 |
|
* **************************************************************************** |
12 |
|
* |
13 |
|
* This is an abstraction of a Map from unsigned integers to elements |
14 |
|
* of type T. |
15 |
|
* |
16 |
|
* This is an abstraction of a Map from an unsigned integer to elements of |
17 |
|
* type T. |
18 |
|
* This class is designed to provide constant time insertion, deletion, |
19 |
|
* element_of, and fast iteration. This is done by storing backing vectors of |
20 |
|
* size greater than the maximum key. |
21 |
|
* This datastructure is appropriate for heavy use datastructures where the |
22 |
|
* Keys are a dense set of integers. |
23 |
|
* |
24 |
|
* T must support T(), and operator=(). |
25 |
|
* |
26 |
|
* The derived utility classes DenseSet and DenseMultiset are also defined. |
27 |
|
*/ |
28 |
|
|
29 |
|
#include "cvc5_private.h" |
30 |
|
|
31 |
|
#pragma once |
32 |
|
|
33 |
|
#include <limits> |
34 |
|
#include <vector> |
35 |
|
|
36 |
|
#include "base/check.h" |
37 |
|
#include "util/index.h" |
38 |
|
|
39 |
|
namespace cvc5 { |
40 |
|
|
41 |
|
template <class T> |
42 |
288173 |
class DenseMap { |
43 |
|
public: |
44 |
|
typedef Index Key; |
45 |
|
typedef std::vector<Key> KeyList; |
46 |
|
typedef KeyList::const_iterator const_iterator; |
47 |
|
|
48 |
|
private: |
49 |
|
//List of the keys in the dense map. |
50 |
|
KeyList d_list; |
51 |
|
|
52 |
|
typedef Index Position; |
53 |
|
typedef std::vector<Position> PositionMap; |
54 |
|
static const Position POSITION_SENTINEL = |
55 |
|
std::numeric_limits<Position>::max(); |
56 |
|
|
57 |
|
//Each Key in the set is mapped to its position in d_list. |
58 |
|
//Each Key not in the set is mapped to KEY_SENTINEL |
59 |
|
PositionMap d_posVector; |
60 |
|
|
61 |
|
typedef std::vector<T> ImageMap; |
62 |
|
//d_image : Key |-> T |
63 |
|
ImageMap d_image; |
64 |
|
|
65 |
|
public: |
66 |
|
|
67 |
288260 |
DenseMap() : d_list(), d_posVector(), d_image() {} |
68 |
|
|
69 |
|
/** Returns the number of elements in the set. */ |
70 |
30072255 |
size_t size() const { |
71 |
30072255 |
return d_list.size(); |
72 |
|
} |
73 |
|
|
74 |
|
/** Returns true if the map is empty(). */ |
75 |
92757815 |
bool empty() const { |
76 |
92757815 |
return d_list.empty(); |
77 |
|
} |
78 |
|
|
79 |
|
/** |
80 |
|
* Similar to a std::vector::clear(). |
81 |
|
* |
82 |
|
* Invalidates iterators. |
83 |
|
*/ |
84 |
|
void clear() { |
85 |
|
d_list.clear(); |
86 |
|
d_posVector.clear(); |
87 |
|
d_image.clear(); |
88 |
|
Assert(empty()); |
89 |
|
} |
90 |
|
|
91 |
|
/** |
92 |
|
* Similar to a clear(), but the datastructures are not reset in size. |
93 |
|
* Invalidates iterators. |
94 |
|
*/ |
95 |
12570027 |
void purge() { |
96 |
21052473 |
while(!empty()){ |
97 |
8482446 |
pop_back(); |
98 |
|
} |
99 |
4087581 |
Assert(empty()); |
100 |
4087581 |
} |
101 |
|
|
102 |
|
/** Returns true if k is a key of this datastructure. */ |
103 |
2994182951 |
bool isKey(Key x) const{ |
104 |
2994182951 |
if( x >= allocated()){ |
105 |
1935885 |
return false; |
106 |
|
}else{ |
107 |
2992247066 |
Assert(x < allocated()); |
108 |
2992247066 |
return d_posVector[x] != +POSITION_SENTINEL; |
109 |
|
} |
110 |
|
} |
111 |
|
|
112 |
|
/** |
113 |
|
* Maps the key to value in the map. |
114 |
|
* Invalidates iterators. |
115 |
|
*/ |
116 |
32868962 |
void set(Key key, const T& value){ |
117 |
32868962 |
if( key >= allocated()){ |
118 |
860672 |
increaseSize(key); |
119 |
|
} |
120 |
|
|
121 |
32868962 |
if(!isKey(key)){ |
122 |
28106712 |
d_posVector[key] = size(); |
123 |
28106712 |
d_list.push_back(key); |
124 |
|
} |
125 |
32868962 |
d_image[key] = value; |
126 |
32868962 |
} |
127 |
|
|
128 |
|
/** Returns a mutable reference to the element mapped by key. */ |
129 |
178857790 |
T& get(Key key){ |
130 |
178857790 |
Assert(isKey(key)); |
131 |
178857790 |
return d_image[key]; |
132 |
|
} |
133 |
|
|
134 |
|
/** Returns a const reference to the element mapped by key.*/ |
135 |
2336279776 |
const T& operator[](Key key) const { |
136 |
2336279776 |
Assert(isKey(key)); |
137 |
2336279776 |
return d_image[key]; |
138 |
|
} |
139 |
|
|
140 |
|
/** Returns an iterator over the keys of the map. */ |
141 |
7922542 |
const_iterator begin() const{ return d_list.begin(); } |
142 |
29375573 |
const_iterator end() const{ return d_list.end(); } |
143 |
|
|
144 |
|
const KeyList& getKeys() const{ |
145 |
|
return d_list; |
146 |
|
} |
147 |
|
|
148 |
|
/** |
149 |
|
* Removes the mapping associated with key. |
150 |
|
* This changes the order of the keys. |
151 |
|
* |
152 |
|
* Invalidates iterators. |
153 |
|
*/ |
154 |
532743 |
void remove(Key x){ |
155 |
532743 |
Assert(isKey(x)); |
156 |
532743 |
swapToBack(x); |
157 |
532743 |
Assert(d_list.back() == x); |
158 |
532743 |
pop_back(); |
159 |
532743 |
} |
160 |
|
|
161 |
|
/** Returns the key at the back of a non-empty list.*/ |
162 |
46401970 |
Key back() const { |
163 |
46401970 |
return d_list.back(); |
164 |
|
} |
165 |
|
|
166 |
|
/** Removes the element associated with the last Key from the map. */ |
167 |
27442208 |
void pop_back() { |
168 |
27442208 |
Assert(!empty()); |
169 |
27442208 |
Key atBack = back(); |
170 |
27442208 |
d_posVector[atBack] = +POSITION_SENTINEL; |
171 |
27442208 |
d_image[atBack] = T(); |
172 |
27442208 |
d_list.pop_back(); |
173 |
27442208 |
} |
174 |
|
|
175 |
|
|
176 |
|
/** Adds at least a constant fraction of the elements in the current map to another map. */ |
177 |
|
void splitInto(DenseMap<T>& target){ |
178 |
|
uint32_t targetSize = size()/2; |
179 |
|
while(size() > targetSize){ |
180 |
|
Key key = back(); |
181 |
|
target.set(key, get(key)); |
182 |
|
pop_back(); |
183 |
|
} |
184 |
|
} |
185 |
|
|
186 |
|
/** Adds the current target map to the current map.*/ |
187 |
|
void addAll(const DenseMap<T>& target){ |
188 |
|
for(const_iterator i = target.begin(), e = target.end(); i != e; ++i){ |
189 |
|
Key k = *i; |
190 |
|
set(k, target[k]); |
191 |
|
} |
192 |
|
} |
193 |
|
|
194 |
|
|
195 |
|
|
196 |
|
private: |
197 |
|
|
198 |
6020159651 |
size_t allocated() const { |
199 |
6020159651 |
Assert(d_posVector.size() == d_image.size()); |
200 |
6020159651 |
return d_posVector.size(); |
201 |
|
} |
202 |
|
|
203 |
860672 |
void increaseSize(Key max){ |
204 |
860672 |
Assert(max >= allocated()); |
205 |
860672 |
d_posVector.resize(max+1, +POSITION_SENTINEL); |
206 |
860672 |
d_image.resize(max+1); |
207 |
860672 |
} |
208 |
|
|
209 |
|
/** Swaps a member x to the back of d_list. */ |
210 |
532743 |
void swapToBack(Key x){ |
211 |
532743 |
Assert(isKey(x)); |
212 |
|
|
213 |
532743 |
Position currentPos = d_posVector[x]; |
214 |
532743 |
Key atBack = back(); |
215 |
|
|
216 |
532743 |
d_list[currentPos] = atBack; |
217 |
532743 |
d_posVector[atBack] = currentPos; |
218 |
|
|
219 |
532743 |
Position last = size() - 1; |
220 |
|
|
221 |
532743 |
d_list[last] = x; |
222 |
532743 |
d_posVector[x] = last; |
223 |
532743 |
} |
224 |
|
}; /* class DenseMap<T> */ |
225 |
|
|
226 |
|
/** |
227 |
|
* This provides an abstraction for a set of unsigned integers with similar capabilities |
228 |
|
* as DenseMap. This is implemented as a light wrapper for DenseMap<bool> with an |
229 |
|
* interface designed for use as a set instead of a map. |
230 |
|
*/ |
231 |
218647 |
class DenseSet { |
232 |
|
private: |
233 |
|
typedef DenseMap<bool> BackingMap; |
234 |
|
BackingMap d_map; |
235 |
|
public: |
236 |
|
typedef BackingMap::const_iterator const_iterator; |
237 |
|
typedef BackingMap::Key Element; |
238 |
|
|
239 |
|
size_t size() const { return d_map.size(); } |
240 |
22070838 |
bool empty() const { return d_map.empty(); } |
241 |
|
|
242 |
|
/** See DenseMap's documentation. */ |
243 |
2921804 |
void purge() { d_map.purge(); } |
244 |
|
void clear() { d_map.clear(); } |
245 |
|
|
246 |
7158066 |
bool isMember(Element x) const{ return d_map.isKey(x); } |
247 |
|
|
248 |
|
/** |
249 |
|
* Adds an element that is not a member of the set to the set. |
250 |
|
*/ |
251 |
130731 |
void add(Element x){ |
252 |
130731 |
Assert(!isMember(x)); |
253 |
130731 |
d_map.set(x, true); |
254 |
130731 |
} |
255 |
|
|
256 |
|
/** Adds an element to the set even if it is already an element of the set. */ |
257 |
17138264 |
void softAdd(Element x){ d_map.set(x, true); } |
258 |
|
|
259 |
|
/** Removes an element from the set. */ |
260 |
|
void remove(Element x){ d_map.remove(x); } |
261 |
|
|
262 |
1110618 |
const_iterator begin() const{ return d_map.begin(); } |
263 |
1110618 |
const_iterator end() const{ return d_map.end(); } |
264 |
|
|
265 |
9839492 |
Element back() { return d_map.back(); } |
266 |
9839492 |
void pop_back() { d_map.pop_back(); } |
267 |
|
}; /* class DenseSet */ |
268 |
|
|
269 |
|
/** |
270 |
|
* This provides an abstraction for a multiset of unsigned integers with similar |
271 |
|
* capabilities as DenseMap. |
272 |
|
* This is implemented as a light wrapper for DenseMap<bool> with an |
273 |
|
* interface designed for use as a set instead of a map. |
274 |
|
*/ |
275 |
19874 |
class DenseMultiset { |
276 |
|
public: |
277 |
|
typedef uint32_t CountType; |
278 |
|
|
279 |
|
private: |
280 |
|
typedef DenseMap<CountType> BackingMap; |
281 |
|
BackingMap d_map; |
282 |
|
|
283 |
|
public: |
284 |
|
typedef BackingMap::const_iterator const_iterator; |
285 |
|
typedef BackingMap::Key Element; |
286 |
|
|
287 |
19880 |
DenseMultiset() : d_map() {} |
288 |
|
|
289 |
|
size_t size() const { return d_map.size(); } |
290 |
|
bool empty() const { return d_map.empty(); } |
291 |
|
|
292 |
95653 |
void purge() { d_map.purge(); } |
293 |
|
void clear() { d_map.clear(); } |
294 |
|
|
295 |
|
bool isMember(Element x) const{ return d_map.isKey(x); } |
296 |
|
|
297 |
209978 |
void add(Element x, CountType c = 1u){ |
298 |
209978 |
Assert(c > 0); |
299 |
209978 |
if(d_map.isKey(x)){ |
300 |
1672 |
d_map.set(x, d_map.get(x)+c); |
301 |
|
}else{ |
302 |
208306 |
d_map.set(x,c); |
303 |
|
} |
304 |
209978 |
} |
305 |
|
|
306 |
|
void setCount(Element x, CountType c){ |
307 |
|
d_map.set(x, c); |
308 |
|
} |
309 |
|
|
310 |
|
void removeAll(Element x){ return d_map.remove(x); } |
311 |
|
|
312 |
|
void removeOne(Element x){ |
313 |
|
CountType c = count(x); |
314 |
|
switch(c){ |
315 |
|
case 0: break; // do nothing |
316 |
|
case 1: removeAll(x); break; // remove |
317 |
|
default: d_map.set(x, c-1); break; // decrease |
318 |
|
} |
319 |
|
} |
320 |
|
|
321 |
|
void removeOneOfEverything(){ |
322 |
|
BackingMap::KeyList keys(d_map.begin(), d_map.end()); |
323 |
|
for(BackingMap::const_iterator i=keys.begin(), i_end = keys.end(); i != i_end; ++i){ |
324 |
|
removeOne(*i); |
325 |
|
} |
326 |
|
} |
327 |
|
|
328 |
420188 |
CountType count(Element x) const { |
329 |
420188 |
if(d_map.isKey(x)){ |
330 |
211882 |
return d_map[x]; |
331 |
|
}else { |
332 |
208306 |
return 0; |
333 |
|
} |
334 |
|
} |
335 |
|
|
336 |
|
const_iterator begin() const{ return d_map.begin(); } |
337 |
|
const_iterator end() const{ return d_map.end(); } |
338 |
|
Element back() { return d_map.back(); } |
339 |
|
void pop_back() { d_map.pop_back(); } |
340 |
|
}; /* class DenseMultiset */ |
341 |
|
|
342 |
|
} // namespace cvc5 |