77 for (
int i=0; i<arity; i++)
123 for (
int a=0; a<
arity; a++) {
126 vd[a].base =
nullptr;
138 case EPK_DENSE_COMPRESSED:
149 bool sparse_possible,
bool compressed_possible,
150 bool support_bits_sparse,
unsigned long long dense_bytes)
const {
151 const unsigned long long dense_small_threshold =
152 2ULL * 1024ULL * 1024ULL;
155 if (dense_possible &&
156 ((dense_bytes <= dense_small_threshold) || !support_bits_sparse))
158 if (compressed_possible)
171 case EPK_DENSE_COMPRESSED:
172 if (compressed_possible)
193 class FinalizeGuard {
198 FinalizeGuard(
Data& d0) : d(d0), committed(
false) {}
199 ~FinalizeGuard(
void) {
209 void commit(
State selected) {
221 guard.commit(selected);
232 TupleCompare tc(
arity);
237 for (
int a=0; a<
arity; a++)
251 const unsigned long long n_tcells64 =
252 static_cast<unsigned long long>(
n_tuples) *
253 static_cast<unsigned long long>(
arity);
254 if (n_tcells64 >
static_cast<unsigned long long>
255 (std::numeric_limits<unsigned long>::max()))
257 const unsigned long n_tcells =
static_cast<unsigned long>(n_tcells64);
259 for (
int a=0; a<
arity; a++)
262 int* new_td =
heap.alloc<
int>(n_tcells);
264 for (
int a=0; a<
arity; a++) {
265 new_td[
static_cast<unsigned long>(t) *
266 static_cast<unsigned long>(
arity) +
267 static_cast<unsigned long>(a)] =
tuples[t][a];
270 tuples[t] = new_td +
static_cast<unsigned long>(t) *
271 static_cast<unsigned long>(
arity);
287 unsigned long long n_vals64 = 0ULL;
289 unsigned long long n_ranges64 = 0ULL;
290 for (
int a=0; a<
arity; a++) {
296 int last_value=
tuples[0][a];
297 n_vals64++; n_ranges64++;
300 if (last_value+1 ==
tuples[i][a]) {
303 }
else if (last_value+1 <
tuples[i][a]) {
304 n_vals64++; n_ranges64++;
307 assert(last_value ==
tuples[i][a]);
312 const unsigned long long max_u64 =
313 std::numeric_limits<unsigned long long>::max();
314 const bool support_entries_overflow =
316 (n_vals64 > max_u64 /
static_cast<unsigned long long>(
n_words));
317 const unsigned long long n_support_entries64 =
318 support_entries_overflow ? max_u64 :
319 static_cast<unsigned long long>(
n_words) * n_vals64;
320 const unsigned long long n_tcells64 =
321 static_cast<unsigned long long>(
n_tuples) *
322 static_cast<unsigned long long>(
arity);
323 const unsigned long long sparse_support_cells_per_entry =
325 const bool support_bits_sparse =
326 support_entries_overflow ||
327 (n_support_entries64 > max_u64 / sparse_support_cells_per_entry) ||
329 n_support_entries64 * sparse_support_cells_per_entry);
330 const bool dense_possible = !support_entries_overflow &&
331 (n_support_entries64 <= static_cast<unsigned long long>
332 (std::numeric_limits<unsigned int>::max()));
333 unsigned int n_offsets = 0U;
334 const bool support_offsets_possible =
335 support_offsets_size(n_vals64,n_offsets);
336 const bool sparse_possible =
338 static_cast<unsigned long long>(std::numeric_limits<unsigned int>::max())) &&
339 support_offsets_possible;
340 const bool compressed_possible = sparse_possible;
341 const unsigned long long dense_bytes =
342 (support_entries_overflow ||
343 (n_support_entries64 > max_u64 /
sizeof(
BitSetData))) ? max_u64 :
344 n_support_entries64 *
static_cast<unsigned long long>(
sizeof(
BitSetData));
349 selected =
select_state(epk,dense_possible,sparse_possible,
350 compressed_possible,support_bits_sparse,
352 const bool build_dense = (selected ==
TS_DENSE);
353 const bool build_sparse = (selected ==
TS_SPARSE);
355 if ((n_vals64 >
static_cast<unsigned long long>
356 (std::numeric_limits<unsigned int>::max())) ||
357 (n_ranges64 >
static_cast<unsigned long long>
358 (std::numeric_limits<unsigned int>::max())))
360 const unsigned int n_vals =
static_cast<unsigned int>(n_vals64);
361 const unsigned int n_ranges =
static_cast<unsigned int>(n_ranges64);
377 unsigned int n_support_entries_u32 = 0U;
380 (n_vals <= std::numeric_limits<unsigned int>::max() /
n_words));
381 n_support_entries_u32 =
n_words * n_vals;
383 for (
unsigned int i=0; i<n_support_entries_u32; i++)
384 support_cursor[i].
init();
386 for (
int a=0; a<
arity; a++) {
388 vd[a].r = range_cursor;
389 vd[a].base =
nullptr;
405 j++;
vd[a].r[j].min=
vd[a].r[j].max=
tuples[i][a];
411 range_cursor += j+1U;
414 for (
unsigned int i=0U; i<
vd[a].n; i++) {
415 vd[a].r[i].s = support_cursor;
417 support_cursor +=
n_words *
vd[a].r[i].width();
430 if (build_sparse || build_compressed) {
431 assert(support_offsets_possible);
433 static_cast<unsigned long long>
434 (std::numeric_limits<unsigned int>::max()));
435 const unsigned int n_tcells =
static_cast<unsigned int>(n_tcells64);
437 heap.alloc<
unsigned int>(n_ranges) :
nullptr;
439 unsigned int first_support_id = 0U;
440 for (
int a=0; a<
arity; a++) {
441 vd[a].base = base_cursor;
442 for (
unsigned int i=0U; i<
vd[a].n; i++) {
443 vd[a].base[i] = first_support_id;
444 first_support_id +=
vd[a].r[i].width();
446 base_cursor +=
vd[a].n;
448 assert(first_support_id == n_vals);
449 assert((n_ranges == 0U) ||
452 unsigned int* support_offsets;
457 heap.alloc<
unsigned int>(n_tcells) :
nullptr;
460 support_offsets = region.
alloc<
unsigned int>(n_offsets);
462 for (
unsigned int i=0U; i<n_offsets; i++)
463 support_offsets[i] = 0U;
464 for (
unsigned int tid=0U;
465 tid<static_cast<unsigned int>(
n_tuples); tid++) {
467 for (
int a=0; a<
arity; a++) {
468 const unsigned int range_index =
vd[a].start(t[a]);
469 const unsigned int support_id =
470 vd[a].base[range_index] +
471 static_cast<unsigned int>
472 (t[a] -
vd[a].r[range_index].min);
475 support_offsets[support_id+1U]++;
479 for (
unsigned int i=1U; i<n_offsets; i++)
480 support_offsets[i] += support_offsets[i-1U];
484 heap.alloc<
unsigned int>(n_tcells) :
nullptr;
485 unsigned int* next_support = (n_vals > 0U) ?
486 region.
alloc<
unsigned int>(n_vals) :
nullptr;
487 for (
unsigned int i=0U; i<n_vals; i++)
489 for (
unsigned int tid=0U;
490 tid<static_cast<unsigned int>(
n_tuples); tid++) {
491 for (
int a=0; a<
arity; a++) {
497 unsigned int* tuples_by_support = (n_tcells > 0U) ?
498 region.
alloc<
unsigned int>(n_tcells) :
nullptr;
499 unsigned int* next_support = (n_vals > 0U) ?
500 region.
alloc<
unsigned int>(n_vals) :
nullptr;
501 for (
unsigned int i=0U; i<n_vals; i++)
502 next_support[i] = support_offsets[i];
505 for (
unsigned int tid=0U;
506 tid<static_cast<unsigned int>(
n_tuples); tid++) {
508 for (
int a=0; a<
arity; a++) {
509 const unsigned int range_index =
vd[a].start(t[a]);
510 const unsigned int support_id =
511 vd[a].base[range_index] +
512 static_cast<unsigned int>
513 (t[a] -
vd[a].r[range_index].min);
514 tuples_by_support[next_support[support_id]++] = tid;
520 unsigned long long entries64 = 0ULL;
521 for (
unsigned int gid=0U; gid<n_vals; gid++) {
522 unsigned int count = 0U;
523 unsigned int last_widx = std::numeric_limits<unsigned int>::max();
524 for (
unsigned int p=support_offsets[gid];
525 p<support_offsets[gid+1U]; p++) {
526 const unsigned int tid = tuples_by_support[p];
528 if (widx != last_widx) {
533 entries64 +=
static_cast<unsigned long long>(
count);
535 static_cast<unsigned long long>(std::numeric_limits<unsigned int>::max()))
543 unsigned int out = 0U;
544 for (
unsigned int gid=0U; gid<n_vals; gid++) {
545 unsigned int current_widx = std::numeric_limits<unsigned int>::max();
548 const unsigned int begin = support_offsets[gid];
549 const unsigned int end = support_offsets[gid+1U];
550 for (
unsigned int p=begin; p<end; p++) {
551 const unsigned int tid = tuples_by_support[p];
553 if (widx != current_widx) {
554 if (current_widx != std::numeric_limits<unsigned int>::max()) {
564 if (current_widx != std::numeric_limits<unsigned int>::max()) {
575 assert(support_cursor ==
support + n_support_entries_u32);
576 assert(range_cursor ==
range + n_ranges);
580 guard.commit(selected);
587 int n =
static_cast<int>(1+
n_tuples*1.5);
613 (void) SharedHandle::operator =(ts);
653 Layer* layers = r.alloc<Layer>(a+1);
654 State* states = r.alloc<State>(max_states*(a+1));
656 for (
int i=0; i<max_states*(a+1); i++) {
657 states[i].i_deg = 0; states[i].o_deg = 0;
658 states[i].n_tuples = 0;
659 states[i].tuples =
nullptr;
661 for (
int i=0; i<a+1; i++) {
662 layers[i].states = states + i*max_states;
663 layers[i].n_supports = 0;
667 layers[0].states[0].i_deg = 1;
668 layers[0].states[0].n_tuples = 1;
669 layers[0].states[0].tuples = r.alloc<
int>(1);
670 assert(layers[0].states[0].
tuples !=
nullptr);
673 Edge* edges = r.alloc<Edge>(dfa.
max_degree());
677 for (
int i=0; i<a; i++) {
682 if (layers[i].states[t.i_state()].i_deg != 0) {
684 edges[n_edges].i_state = t.i_state();
685 edges[n_edges].o_state = t.o_state();
688 layers[i].states[t.i_state()].o_deg++;
689 layers[i+1].states[t.o_state()].i_deg++;
691 layers[i+1].states[t.o_state()].n_tuples
692 += layers[i].states[t.i_state()].n_tuples;
694 assert(
static_cast<unsigned int>(n_edges) <= dfa.
max_degree());
698 Support& support = supports[n_supports++];
699 support.val = s.val();
700 support.n_edges = n_edges;
701 support.edges =
Heap::copy(r.alloc<Edge>(n_edges),edges,n_edges);
705 if (n_supports > 0) {
708 layers[i].n_supports = n_supports;
717 if (layers[a].states[s].i_deg != 0U)
718 layers[a].states[s].o_deg = 1U;
722 for (
int i=a; i--; ) {
723 for (
int j = layers[i].n_supports; j--; ) {
724 Support& s = layers[i].supports[j];
725 for (
int k = s.n_edges; k--; ) {
726 int i_state = s.edges[k].i_state;
727 int o_state = s.edges[k].o_state;
729 if (layers[i+1].states[o_state].o_deg == 0) {
731 --layers[i+1].states[o_state].i_deg;
732 --layers[i].states[i_state].o_deg;
734 assert(s.n_edges > 0);
735 s.edges[k] = s.edges[--s.n_edges];
740 layers[i].supports[j] = layers[i].supports[--layers[i].n_supports];
742 if (layers[i].n_supports == 0U) {
749 for (
int i=0; i<a; i++) {
750 for (
int j = layers[i].n_supports; j--; ) {
751 Support& s = layers[i].supports[j];
752 for (
int k = s.n_edges; k--; ) {
753 int i_state = s.edges[k].i_state;
754 int o_state = s.edges[k].o_state;
756 if (layers[i+1].states[o_state].
tuples ==
nullptr) {
757 int n_tuples = layers[i+1].states[o_state].n_tuples;
758 layers[i+1].states[o_state].tuples = r.alloc<
int>((i+1)*n_tuples);
759 layers[i+1].states[o_state].n_tuples = 0;
761 int n = layers[i+1].states[o_state].n_tuples;
763 for (
int t=0; t < layers[i].states[i_state].n_tuples; t++) {
766 &layers[i].states[i_state].
tuples[t*i], i);
768 layers[i+1].states[o_state].tuples[n*(i+1)+t*(i+1)+i] = s.val;
770 layers[i+1].states[o_state].n_tuples
771 += layers[i].states[i_state].n_tuples;
778 for (
int i=0; i<layers[a].states[s].n_tuples; i++) {
779 int* tuple = &layers[a].states[s].tuples[i*a];
793 for (
int i=0; i<
tuples(); i++)
794 for (
int j=0; j<
arity(); j++)
795 if ((*
this)[i][j] != t[i][j])
804 if (
raw().terminal())
809 for (
int i=0; i<t.
size(); i++)
int size(void) const
Return size of array (number of elements).
Iterator for DFA symbols.
Iterator for DFA transitions (sorted by symbols).
Deterministic finite automaton (DFA).
unsigned int max_degree(void) const
Return maximal degree (in-degree and out-degree) of any state.
int n_states(void) const
Return the number of states.
int final_lst(void) const
Return the number of the last final state.
unsigned int n_symbols(void) const
Return the number of symbols.
int final_fst(void) const
Return the number of the first final state.
static T * copy(T *d, const T *s, long unsigned int n)
Copy n objects starting at s to d.
Passing integer arguments.
int min(int i) const
Return minimum of range at position i.
int max(int i) const
Return maximum of range at position i.
Exception: Tuple set already finalized
Exception: Arguments are of different size
PosCompare(int p)
Initialize with position p.
bool operator()(const Tuple &a, const Tuple &b)
Comparison of tuples a and b.
TupleCompare(int a)
Initialize with arity a.
bool operator()(const Tuple &a, const Tuple &b)
Comparison of tuples a and b.
Exception: Value out of limits
Exception: uninitialized tuple set
T * alloc(long unsigned int n)
Allocate block of n objects of type T from region.
SharedHandle(void)
Create shared handle with no object pointing to.
SharedHandle::Object * object(void) const
Access to the shared object.
static const unsigned int bpb
Bits per base.
void init(bool setbits=false)
Initialize with all bits set if setbits.
static unsigned int data(unsigned int s)
Get number of data elements for s bits.
void set(unsigned int i)
Set bit i.
Compressed support data for one tuple-word block.
void clear_support(void)
Release partially or fully constructed support data.
unsigned int compressed_n_entries
Number of compressed support entries.
int n_free
Number of free tuple entries of arity.
bool terminal(void) const
Is datastructure no longer mutable.
unsigned int * sparse_tuples
Sparse support tuple ids (size arity*n_tuples).
void resize(void)
Resize tuple data.
BitSetData * support
Pointer to all support data.
Data(int a)
Initialize as empty tuple set with arity a.
unsigned int * compressed_offsets
Compressed support offsets (size n_vals+1).
unsigned int n_words
Number of words for support.
State empty_state(ExtensionalPropKind epk) const
Select the state for an empty finalized tuple set.
static void set(BitSetData *d, unsigned int n)
Set bit n in bitset data d.
virtual ~Data(void)
Delete implementation.
unsigned int * sparse_offsets
Sparse support offsets (size sparse_n_vals+1).
void finalize(void)
Finalize datastructure (disallows additions of more Tuples).
int n_tuples
Number of Tuples.
unsigned int sparse_n_vals
Number of sparse support values.
unsigned int * sparse_tv
Tuple cell to sparse support id map (size arity*n_tuples).
State state
Tuple set lifecycle state and finalized representation.
CSupportWord * compressed_words
Compressed support words (size compressed_n_entries).
unsigned int tuple2idx(Tuple t) const
Map tuple address to index.
State
Tuple set lifecycle state and finalized representation.
Range * range
Pointer to all ranges.
State select_state(ExtensionalPropKind epk, bool dense_possible, bool sparse_possible, bool compressed_possible, bool support_bits_sparse, unsigned long long dense_bytes) const
Select the finalized state for the computed table layout.
ValueData * vd
Value data.
Tuple add(void)
Return newly added tuple.
unsigned int * range_base
Pointer to all range support ids.
Class representing a set of tuples.
TupleSet(void)
Construct an uninitialized tuple set.
void _add(const IntArgs &t)
Add tuple t to tuple set.
int tuples(void) const
Number of tuples.
int max(void) const
Return maximal value in all tuples.
bool finalized(void) const
Is tuple set successfully finalized.
TupleSet & add(const IntArgs &t)
Add tuple t to tuple set.
TupleSet & operator=(const TupleSet &t)
Assignment operator.
int * Tuple
Type of a tuple.
void finalize(void)
Finalize tuple set with dense support data.
bool equal(const TupleSet &t) const
Test whether tuple set is equal to t.
int min(void) const
Return minimal value in all tuples.
Data & raw(void) const
Get raw data (must be initialized).
Gecode::Support::BitSetData BitSetData
Import bit set data type.
void init(int a)
Initialize an uninitialized tuple set.
int arity(void) const
Arity of tuple set.
Heap heap
The single global heap.
ExtensionalPropKind
Support representation selection for extensional tuple sets.
TupleSet::Tuple Tuple
Tuple type.
const int min
Smallest allowed integer value.
bool valid(int n)
Return whether n is in range.
const int max
Largest allowed integer value.
Support algorithms and datastructures
void quicksort(Type *l, Type *r, Less &less)
Standard quick sort.
Gecode toplevel namespace
void count(Home home, const IntVarArgs &x, int n, IntRelType irt, int m, IntPropLevel ipl=IPL_DEF)
Post propagator for .
void cmb_hash(std::size_t &seed, const T h)
Combine hash value h into seed.
bool same(VarArgArray< Var > x, VarArgArray< Var > y)
#define GECODE_NEVER
Assert that this command is never executed.