Generated on for Gecode by doxygen 1.17.0
bit-set.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Linnea Ingmar <linnea.ingmar@hotmail.com>
5 *
6 * Contributing authors:
7 * Christian Schulte <schulte@gecode.dev>
8 *
9 * Copyright:
10 * Linnea Ingmar, 2017
11 * Christian Schulte, 2017
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.dev
16 *
17 * Permission is hereby granted, free of charge, to any person obtaining
18 * a copy of this software and associated documentation files (the
19 * "Software"), to deal in the Software without restriction, including
20 * without limitation the rights to use, copy, modify, merge, publish,
21 * distribute, sublicense, and/or sell copies of the Software, and to
22 * permit persons to whom the Software is furnished to do so, subject to
23 * the following conditions:
24 *
25 * The above copyright notice and this permission notice shall be
26 * included in all copies or substantial portions of the Software.
27 *
28 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
29 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
30 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
31 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
32 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
33 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
34 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 *
36 */
37
38namespace Gecode { namespace Int { namespace Extensional {
39
40 forceinline
42 : b(nullptr), e(nullptr) {}
43
44 forceinline
48
49 forceinline const TupleSet::CSupportWord*
51 return b;
52 }
53
54 forceinline const TupleSet::CSupportWord*
56 return e;
57 }
58
59 forceinline bool
61 return (b == nullptr) || (b >= e);
62 }
63
64 forceinline const TupleSet::BitSetData*
65 find_support_word(const CompressedSupport& s, unsigned int widx) {
66 const TupleSet::CSupportWord* b = s.begin();
67 const TupleSet::CSupportWord* e = s.end();
68 while (b < e) {
69 const TupleSet::CSupportWord* m = b + ((e-b) >> 1);
70 if (widx < m->widx) {
71 e = m;
72 } else if (widx > m->widx) {
73 b = m+1;
74 } else {
75 return &m->bits;
76 }
77 }
78 return nullptr;
79 }
80
81 template<class IndexType>
82 forceinline unsigned int
84 return static_cast<unsigned int>(_active_words);
85 }
86
87 template<class IndexType>
88 forceinline bool
90 return _active_words == 0U;
91 }
92
93 template<class IndexType>
94 forceinline unsigned int
96 return static_cast<unsigned int>(_active_words);
97 }
98
99 template<class IndexType>
100 forceinline unsigned int
102 return words();
103 }
104
105 template<class IndexType>
106 forceinline unsigned int
108 assert(!empty());
109 IndexType width = _word_index[0];
110 for (IndexType i=1; i<_active_words; i++)
111 width = std::max(width,_word_index[i]);
112 assert(static_cast<unsigned int>(width+1U) >= words());
113 return static_cast<unsigned int>(width+1U);
114 }
115
116 template<class IndexType>
117 forceinline
118 BitSet<IndexType>::BitSet(Space& home, unsigned int n,
119 bool track_positions)
120 : _active_words(static_cast<IndexType>(n)),
121 _word_capacity(static_cast<IndexType>(n)),
122 _word_index(home.alloc<IndexType>(n)),
123 _word_bits(home.alloc<BitSetData>(n)),
124 _active_position(track_positions ? home.alloc<IndexType>(n) : nullptr) {
125 // Set all bits in all words (including the last)
126 for (IndexType i=0; i<_active_words; i++) {
127 _word_bits[i].init(true);
128 _word_index[i] = i;
129 if (_active_position != nullptr)
130 _active_position[i] = i+1;
131 }
132 }
133
134 template<class IndexType>
135 template<class OldIndexType>
136 forceinline
138 const BitSet<OldIndexType>& bs)
139 : _active_words(static_cast<IndexType>(bs._active_words)),
140 _word_capacity(static_cast<IndexType>(
141 bs.empty() ? 0U : bs.width())),
143 home.alloc<IndexType>(_active_words) : nullptr),
145 home.alloc<BitSetData>(_active_words) : nullptr),
146 _active_position(((bs._active_position != nullptr) &&
147 (_word_capacity > 0U)) ?
148 home.alloc<IndexType>(_word_capacity) : nullptr) {
149 for (IndexType i=0; i<_active_words; i++) {
150 _word_bits[i] = bs._word_bits[i];
151 _word_index[i] = static_cast<IndexType>(bs._word_index[i]);
152 }
153 if (_active_position != nullptr) {
154 for (IndexType i=0; i<_word_capacity; i++)
155 _active_position[i] = 0;
156 for (IndexType i=0; i<_active_words; i++)
158 }
159 }
160
161 template<class IndexType>
162 forceinline void
164 _active_words = 0U;
165 assert(empty());
166 }
167
168 template<class IndexType>
169 forceinline
174 template<class IndexType>
175 forceinline
180 template<class IndexType>
181 forceinline
186 template<class IndexType>
187 forceinline
192
193 template<class IndexType>
194 forceinline void
196 BitSetData word) {
197 assert(_active_words > 0U);
198 BitSetData old_word = _word_bits[active_pos];
199 if (word != old_word) {
200 _word_bits[active_pos] = word;
201 if (word.none()) {
202 assert(_word_bits[active_pos].none());
203 const IndexType removed_word_index = _word_index[active_pos];
205 const IndexType moved_word_index = _word_index[_active_words];
206 _word_bits[active_pos] = _word_bits[_active_words];
207 _word_index[active_pos] = moved_word_index;
208 if (_active_position != nullptr) {
209 _active_position[removed_word_index] = 0;
210 if (active_pos < _active_words)
211 _active_position[moved_word_index] = active_pos+1;
212 }
213 }
214 }
215 }
216
217 template<class IndexType>
218 forceinline void
220 assert(_active_words > 0U);
221 for (IndexType i=0; i<_active_words; i++) {
222 mask[i].init(false);
223 assert(mask[i].none());
224 }
225 }
226
227 template<class IndexType>
228 forceinline void
230 BitSetData* mask) const {
231 assert(_active_words > 0U);
232 for (IndexType i=0; i<_active_words; i++)
233 mask[i] = BitSetData::o(mask[i],support[_word_index[i]]);
234 }
235
236 template<class IndexType>
237 forceinline void
239 BitSetData* mask) const {
240 if ((_active_words == 0U) || support.empty())
241 return;
242 if (_active_position == nullptr) {
243 for (IndexType i=0; i<_active_words; i++) {
244 const BitSetData* support_word =
245 find_support_word(support,_word_index[i]);
246 if (support_word != nullptr)
247 mask[i] = BitSetData::o(mask[i],*support_word);
248 }
249 return;
250 }
251 for (const TupleSet::CSupportWord* s=support.begin();
252 s<support.end(); ++s) {
253 if (s->widx >= static_cast<unsigned int>(_word_capacity))
254 continue;
255 const IndexType active_pos = _active_position[s->widx];
256 if (active_pos == 0U)
257 continue;
258 mask[active_pos-1] = BitSetData::o(mask[active_pos-1],s->bits);
259 }
260 }
261
262 template<class IndexType>
263 template<bool sparse>
264 forceinline void
266 assert(_active_words > 0U);
267 if (sparse) {
268 for (IndexType i = _active_words; i--; ) {
269 assert(!_word_bits[i].none());
270 BitSetData old_word = _word_bits[i];
271 BitSetData new_word = BitSetData::a(old_word, mask[_word_index[i]]);
272 replace_and_decrease(i,new_word);
273 assert(i == _active_words || !_word_bits[i].none());
274 }
275 } else { // The same except different _word_indexing in mask
276 for (IndexType i = _active_words; i--; ) {
277 assert(!_word_bits[i].none());
278 BitSetData old_word = _word_bits[i];
279 BitSetData new_word = BitSetData::a(old_word, mask[i]);
280 replace_and_decrease(i,new_word);
281 assert(i == _active_words || !_word_bits[i].none());
282 }
283 }
284 }
285
286 template<class IndexType>
287 forceinline void
289 if (_active_words == 0U)
290 return;
291 for (IndexType i = _active_words; i--; ) {
292 assert(!_word_bits[i].none());
293 const BitSetData* support_word =
294 find_support_word(support,_word_index[i]);
295 BitSetData new_word;
296 if (support_word == nullptr) {
297 new_word.init(false);
298 } else {
299 new_word = BitSetData::a(_word_bits[i],*support_word);
300 }
301 replace_and_decrease(i,new_word);
302 assert(i == _active_words || !_word_bits[i].none());
303 }
304 }
305
306 template<class IndexType>
307 forceinline void
309 const BitSetData* b) {
310 assert(_active_words > 0U);
311 for (IndexType i = _active_words; i--; ) {
312 assert(!_word_bits[i].none());
313 BitSetData old_word = _word_bits[i];
314 IndexType offset = _word_index[i];
315 BitSetData union_word = BitSetData::o(a[offset], b[offset]);
316 BitSetData new_word = BitSetData::a(old_word,union_word);
317 replace_and_decrease(i,new_word);
318 assert(i == _active_words || !_word_bits[i].none());
319 }
320 }
321
322 template<class IndexType>
323 forceinline void
325 const CompressedSupport& b) {
326 if (_active_words == 0U)
327 return;
328 for (IndexType i = _active_words; i--; ) {
329 assert(!_word_bits[i].none());
330 const BitSetData* first_support_word =
332 const BitSetData* second_support_word =
334 BitSetData union_word;
335 if (first_support_word != nullptr) {
336 union_word = *first_support_word;
337 } else {
338 union_word.init(false);
339 }
340 if (second_support_word != nullptr)
341 union_word = BitSetData::o(union_word,*second_support_word);
342 BitSetData new_word = BitSetData::a(_word_bits[i],union_word);
343 replace_and_decrease(i,new_word);
344 assert(i == _active_words || !_word_bits[i].none());
345 }
346 }
347
348 template<class IndexType>
349 forceinline void
351 assert(_active_words > 0U);
352 for (IndexType i = _active_words; i--; ) {
353 assert(!_word_bits[i].none());
354 BitSetData new_word =
355 BitSetData::a(_word_bits[i],~(mask[_word_index[i]]));
356 replace_and_decrease(i,new_word);
357 assert(i == _active_words || !_word_bits[i].none());
358 }
359 }
360
361 template<class IndexType>
362 forceinline void
364 if ((_active_words == 0U) || support.empty())
365 return;
366 if (_active_position == nullptr) {
367 for (IndexType i = _active_words; i--; ) {
368 assert(!_word_bits[i].none());
369 const BitSetData* support_word =
370 find_support_word(support,_word_index[i]);
371 if (support_word != nullptr) {
372 BitSetData new_word = BitSetData::a(_word_bits[i],~(*support_word));
373 replace_and_decrease(i,new_word);
374 assert(i == _active_words || !_word_bits[i].none());
375 }
376 }
377 return;
378 }
379 for (const TupleSet::CSupportWord* s=support.begin();
380 s<support.end(); ++s) {
381 if (s->widx >= static_cast<unsigned int>(_word_capacity))
382 continue;
383 const IndexType active_pos = _active_position[s->widx];
384 if (active_pos == 0U)
385 continue;
386 const IndexType i = active_pos-1;
387 BitSetData new_word = BitSetData::a(_word_bits[i],~(s->bits));
388 replace_and_decrease(i,new_word);
389 }
390 }
391
392 template<class IndexType>
393 forceinline bool
395 for (IndexType i=0; i<_active_words; i++)
396 if (!BitSetData::a(_word_bits[i],mask[_word_index[i]]).none())
397 return true;
398 return false;
399 }
400
401 template<class IndexType>
402 forceinline bool
404 if ((_active_words == 0U) || support.empty())
405 return false;
406 if (_active_position == nullptr) {
407 for (IndexType i=0; i<_active_words; i++) {
408 const BitSetData* support_word =
409 find_support_word(support,_word_index[i]);
410 if ((support_word != nullptr) &&
411 !BitSetData::a(_word_bits[i],*support_word).none())
412 return true;
413 }
414 return false;
415 }
416 for (const TupleSet::CSupportWord* s=support.begin();
417 s<support.end(); ++s) {
418 if (s->widx >= static_cast<unsigned int>(_word_capacity))
419 continue;
420 const IndexType active_pos = _active_position[s->widx];
421 if ((active_pos != 0U) &&
422 !BitSetData::a(_word_bits[active_pos-1],s->bits).none())
423 return true;
424 }
425 return false;
426 }
427
428 template<class IndexType>
429 forceinline unsigned long long int
431 unsigned long long int count = 0U;
432 for (IndexType i=0; i<_active_words; i++)
433 count += static_cast<unsigned long long int>
434 (BitSetData::a(_word_bits[i],mask[_word_index[i]]).ones());
435 return count;
436 }
437
438 template<class IndexType>
439 forceinline unsigned long long int
441 unsigned long long int count = 0U;
442 if ((_active_words == 0U) || support.empty())
443 return 0U;
444 if (_active_position == nullptr) {
445 for (IndexType i=0; i<_active_words; i++) {
446 const BitSetData* support_word =
447 find_support_word(support,_word_index[i]);
448 if (support_word != nullptr)
449 count += static_cast<unsigned long long int>
450 (BitSetData::a(_word_bits[i],*support_word).ones());
451 }
452 return count;
453 }
454 for (const TupleSet::CSupportWord* s=support.begin();
455 s<support.end(); ++s) {
456 if (s->widx >= static_cast<unsigned int>(_word_capacity))
457 continue;
458 const IndexType active_pos = _active_position[s->widx];
459 if (active_pos == 0U)
460 continue;
461 count += static_cast<unsigned long long int>
462 (BitSetData::a(_word_bits[active_pos-1],s->bits).ones());
463 }
464 return count;
465 }
466
467 template<class IndexType>
468 forceinline unsigned long long int
470 unsigned long long int count = 0U;
471 for (IndexType i=0; i<_active_words; i++)
472 count += static_cast<unsigned long long int>(_word_bits[i].ones());
473 return count;
474 }
475
476 template<class IndexType>
477 forceinline unsigned long long int
479 return (static_cast<unsigned long long int>(_active_words) *
480 static_cast<unsigned long long int>(BitSetData::bpb));
481 }
482
483}}}
484
485// STATISTICS: int-prop
BitSetData * _word_bits
Active word data.
unsigned long long int bits(void) const
Return an upper bound on the number of bits.
Definition bit-set.hpp:478
void add_to_mask(const BitSetData *support, BitSetData *mask) const
Add support to mask.
Definition bit-set.hpp:229
bool intersects(const BitSetData *mask) const
Check if has a non-empty intersection with the set.
Definition bit-set.hpp:394
void intersect_with_mask(const BitSetData *mask)
Intersect with mask, sparse mask if sparse is true.
Definition bit-set.hpp:265
unsigned int width(void) const
Return the highest active index.
Definition bit-set.hpp:107
IndexType _word_capacity
Number of addressable word slots.
unsigned long long int ones(void) const
Return the number of ones.
Definition bit-set.hpp:469
IndexType _active_words
Number of active words.
void intersect_with_masks(const BitSetData *a, const BitSetData *b)
Intersect with the "or" of a and b.
Definition bit-set.hpp:308
IndexType * _word_index
Original word index for each active word position.
unsigned int size(void) const
Return the number of required bit set words.
Definition bit-set.hpp:101
unsigned int limit(void) const
Get the number of active words.
Definition bit-set.hpp:83
void replace_and_decrease(IndexType active_pos, BitSetData word)
Replace active word active_pos, dropping it if word is zero.
Definition bit-set.hpp:195
void clear_mask(BitSetData *mask) const
Clear all active words in mask.
Definition bit-set.hpp:219
bool empty(void) const
Check whether the set is empty.
Definition bit-set.hpp:89
unsigned int words(void) const
Return the number of required bit set words.
Definition bit-set.hpp:95
IndexType * _active_position
Reverse map from word index to active position+1 (optional).
void flush(void)
Make the set empty.
Definition bit-set.hpp:163
void nand_with_mask(const BitSetData *mask)
Perform "nand" with mask.
Definition bit-set.hpp:350
Compressed tuple-word support list.
const TupleSet::CSupportWord * end(void) const
Return one past last support word.
Definition bit-set.hpp:55
const TupleSet::CSupportWord * begin(void) const
Return first support word.
Definition bit-set.hpp:50
bool empty(void) const
Whether support list is empty.
Definition bit-set.hpp:60
const TupleSet::CSupportWord * e
One past last support word.
const TupleSet::CSupportWord * b
First support word.
CompressedSupport(void)
Initialize as empty support list.
Definition bit-set.hpp:41
Computation spaces.
Definition core.hpp:1775
static const unsigned int bpb
Bits per base.
void init(bool setbits=false)
Initialize with all bits set if setbits.
void a(BitSetData a)
Perform "and" with a.
bool none(void) const
Whether no bits are set.
void o(BitSetData a)
Perform "or" with a.
Compressed support data for one tuple-word block.
Definition int.hh:2393
unsigned int widx
Word index in tuple-word array.
Definition int.hh:2395
BitSetData bits
Support bits in that word.
Definition int.hh:2396
Gecode::Support::BitSetData BitSetData
Import bit set data type.
Definition int.hh:2391
Extensional propagators
Definition int.hh:2335
const TupleSet::BitSetData * find_support_word(const CompressedSupport &s, unsigned int widx)
Definition bit-set.hpp:65
Gecode::Support::BitSetData BitSetData
Import type.
Finite domain integers.
Definition lastval.hh:52
Gecode toplevel namespace
void count(Home home, const IntVarArgs &x, int n, IntRelType irt, int m, IntPropLevel ipl=IPL_DEF)
Post propagator for .
#define GECODE_NEVER
Assert that this command is never executed.
Definition macros.hpp:56