this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Linnea Ingmar <linnea.ingmar@hotmail.com>
5 * Mikael Lagerkvist <lagerkvist@gecode.org>
6 * Christian Schulte <schulte@gecode.org>
7 *
8 * Copyright:
9 * Linnea Ingmar, 2017
10 * Mikael Lagerkvist, 2007
11 * Christian Schulte, 2017
12 *
13 * This file is part of Gecode, the generic constraint
14 * development environment:
15 * http://www.gecode.org
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
38#include <gecode/int.hh>
39#include <algorithm>
40
41namespace Gecode { namespace Int { namespace Extensional {
42
43 /// Import tuple type
44 typedef ::Gecode::TupleSet::Tuple Tuple;
45
46 /// Tuple comparison
47 class TupleCompare {
48 private:
49 /// The arity of the tuples to compare
50 int arity;
51 public:
52 /// Initialize with arity \a a
53 TupleCompare(int a);
54 /// Comparison of tuples \a a and \a b
55 bool operator ()(const Tuple& a, const Tuple& b);
56 };
57
58 /// Tuple comparison by position
59 class PosCompare {
60 private:
61 /// The position of the tuples to compare
62 int p;
63 public:
64 /// Initialize with position \a p
65 PosCompare(int p);
66 /// Comparison of tuples \a a and \a b
67 bool operator ()(const Tuple& a, const Tuple& b);
68 };
69
70
71 forceinline
72 TupleCompare::TupleCompare(int a) : arity(a) {}
73
74 forceinline bool
75 TupleCompare::operator ()(const Tuple& a, const Tuple& b) {
76 for (int i=0; i<arity; i++)
77 if (a[i] < b[i])
78 return true;
79 else if (a[i] > b[i])
80 return false;
81 return false;
82 }
83
84
85 forceinline
86 PosCompare::PosCompare(int p0) : p(p0) {}
87
88 forceinline bool
89 PosCompare::operator ()(const Tuple& a, const Tuple& b) {
90 return a[p] < b[p];
91 }
92
93
94}}}
95
96namespace Gecode {
97
98 /*
99 * Tuple set data
100 *
101 */
102 void
103 TupleSet::Data::finalize(void) {
104 using namespace Int::Extensional;
105 assert(!finalized());
106 // Mark as finalized
107 n_free = -1;
108
109 // Initialization
110 if (n_tuples == 0) {
111 heap.rfree(td);
112 td=nullptr;
113 return;
114 }
115
116 // Compact and copy data
117 Region r;
118 // Set up tuple pointers
119 Tuple* tuple = r.alloc<Tuple>(n_tuples);
120 {
121 for (int t=0; t<n_tuples; t++)
122 tuple[t] = td + t*arity;
123 TupleCompare tc(arity);
124 Support::quicksort(tuple, n_tuples, tc);
125 // Remove duplicates
126 int j=1;
127 for (int t=1; t<n_tuples; t++) {
128 for (int a=0; a<arity; a++)
129 if (tuple[t-1][a] != tuple[t][a])
130 goto notsame;
131 goto same;
132 notsame: ;
133 tuple[j++] = tuple[t];
134 same: ;
135 }
136 assert(j <= n_tuples);
137 n_tuples=j;
138 // Initialize hash key
139 key = static_cast<std::size_t>(n_tuples);
140 cmb_hash(key, arity);
141 // Copy into now possibly smaller area
142 int* new_td = heap.alloc<int>(n_tuples*arity);
143 for (int t=0; t<n_tuples; t++) {
144 for (int a=0; a<arity; a++) {
145 new_td[t*arity+a] = tuple[t][a];
146 cmb_hash(key,tuple[t][a]);
147 }
148 tuple[t] = new_td + t*arity;
149 }
150 heap.rfree(td);
151 td = new_td;
152 }
153
154 // Only now compute how many tuples are needed!
155 n_words = BitSetData::data(static_cast<unsigned int>(n_tuples));
156
157 // Compute range information
158 {
159 /*
160 * Pass one: compute how many values and ranges are needed
161 */
162 // How many values
163 unsigned int n_vals = 0U;
164 // How many ranges
165 unsigned int n_ranges = 0U;
166 for (int a=0; a<arity; a++) {
167 // Sort tuple according to position
168 PosCompare pc(a);
169 Support::quicksort(tuple, n_tuples, pc);
170 // Scan values
171 {
172 int max=tuple[0][a];
173 n_vals++; n_ranges++;
174 for (int i=1; i<n_tuples; i++) {
175 assert(tuple[i-1][a] <= tuple[i][a]);
176 if (max+1 == tuple[i][a]) {
177 n_vals++;
178 max=tuple[i][a];
179 } else if (max+1 < tuple[i][a]) {
180 n_vals++; n_ranges++;
181 max=tuple[i][a];
182 } else {
183 assert(max == tuple[i][a]);
184 }
185 }
186 }
187 }
188 /*
189 * Pass 2: allocate memory and fill data structures
190 */
191 // Allocate memory for ranges
192 Range* cr = range = heap.alloc<Range>(n_ranges);
193 // Allocate and initialize memory for supports
194 BitSetData* cs = support = heap.alloc<BitSetData>(n_words * n_vals);
195 for (unsigned int i=0; i<n_vals * n_words; i++)
196 cs[i].init();
197 for (int a=0; a<arity; a++) {
198 // Set range pointer
199 vd[a].r = cr;
200 // Sort tuple according to position
201 PosCompare pc(a);
202 Support::quicksort(tuple, n_tuples, pc);
203 // Update min and max
204 min = std::min(min,tuple[0][a]);
205 max = std::max(max,tuple[n_tuples-1][a]);
206 // Compress into non-overlapping ranges
207 {
208 unsigned int j=0U;
209 vd[a].r[0].max=vd[a].r[0].min=tuple[0][a];
210 for (int i=1; i<n_tuples; i++) {
211 assert(tuple[i-1][a] <= tuple[i][a]);
212 if (vd[a].r[j].max+1 == tuple[i][a]) {
213 vd[a].r[j].max=tuple[i][a];
214 } else if (vd[a].r[j].max+1 < tuple[i][a]) {
215 j++; vd[a].r[j].min=vd[a].r[j].max=tuple[i][a];
216 } else {
217 assert(vd[a].r[j].max == tuple[i][a]);
218 }
219 }
220 vd[a].n = j+1U;
221 cr += j+1U;
222 }
223 // Set support pointer and set bits
224 for (unsigned int i=0U; i<vd[a].n; i++) {
225 vd[a].r[i].s = cs;
226 cs += n_words * vd[a].r[i].width();
227 }
228 {
229 int j=0;
230 for (int i=0; i<n_tuples; i++) {
231 while (tuple[i][a] > vd[a].r[j].max)
232 j++;
233 set(const_cast<BitSetData*>
234 (vd[a].r[j].supports(n_words,tuple[i][a])),
235 tuple2idx(tuple[i]));
236 }
237 }
238 }
239 assert(cs == support + n_words * n_vals);
240 assert(cr == range + n_ranges);
241 }
242 if ((min < Int::Limits::min) || (max > Int::Limits::max))
243 throw Int::OutOfLimits("TupleSet::finalize()");
244 assert(finalized());
245 }
246
247 void
248 TupleSet::Data::resize(void) {
249 assert(n_free == 0);
250 int n = static_cast<int>(1+n_tuples*1.5);
251 td = heap.realloc<int>(td, n_tuples * arity, n * arity);
252 n_free = n - n_tuples;
253 }
254
255 TupleSet::Data::~Data(void) {
256 heap.rfree(td);
257 heap.rfree(vd);
258 heap.rfree(range);
259 heap.rfree(support);
260 }
261
262
263 /*
264 * Tuple set
265 *
266 */
267 TupleSet::TupleSet(int a)
268 : SharedHandle(new Data(a)) {}
269 void
270 TupleSet::init(int a) {
271 object(new Data(a));
272 }
273 TupleSet::TupleSet(const TupleSet& ts)
274 : SharedHandle(ts) {}
275 TupleSet&
276 TupleSet::operator =(const TupleSet& ts) {
277 (void) SharedHandle::operator =(ts);
278 return *this;
279 }
280
281 TupleSet::TupleSet(int a, const Gecode::DFA& dfa) {
282 /// Edges in layered graph
283 struct Edge {
284 int i_state; ///< Number of in-state
285 int o_state; ///< Number of out-state
286 };
287 /// State in layered graph
288 struct State {
289 int i_deg; ///< In-degree (number of incoming arcs)
290 int o_deg; ///< Out-degree (number of outgoing arcs)
291 int n_tuples; ///< Number of tuples
292 int* tuples; ///< The tuples
293 };
294 /// Support for a value
295 struct Support {
296 int val; ///< Supported value
297 int n_edges; ///< Number of supporting edges
298 Edge* edges; ///< Supporting edges
299 };
300 /// Layer in layered graph
301 struct Layer {
302 State* states; ///< States
303 Support* supports; ///< Supported values
304 int n_supports; ///< Number of supported values
305 };
306 // Initialize
307 object(new Data(a));
308
309 Region r;
310 // Number of states
311 int max_states = dfa.n_states();
312 // Allocate memory for all layers and states
313 Layer* layers = r.alloc<Layer>(a+1);
314 State* states = r.alloc<State>(max_states*(a+1));
315
316 for (int i=0; i<max_states*(a+1); i++) {
317 states[i].i_deg = 0; states[i].o_deg = 0;
318 states[i].n_tuples = 0;
319 states[i].tuples = nullptr;
320 }
321 for (int i=0; i<a+1; i++) {
322 layers[i].states = states + i*max_states;
323 layers[i].n_supports = 0;
324 }
325
326 // Mark initial state as being reachable
327 layers[0].states[0].i_deg = 1;
328 layers[0].states[0].n_tuples = 1;
329 layers[0].states[0].tuples = r.alloc<int>(1);
330 assert(layers[0].states[0].tuples != nullptr);
331
332 // Allocate temporary memory for edges and supports
333 Edge* edges = r.alloc<Edge>(dfa.max_degree());
334 Support* supports = r.alloc<Support>(dfa.n_symbols());
335
336 // Forward pass: accumulate
337 for (int i=0; i<a; i++) {
338 int n_supports=0;
339 for (DFA::Symbols s(dfa); s(); ++s) {
340 int n_edges=0;
341 for (DFA::Transitions t(dfa,s.val()); t(); ++t) {
342 if (layers[i].states[t.i_state()].i_deg != 0) {
343 // Create edge
344 edges[n_edges].i_state = t.i_state();
345 edges[n_edges].o_state = t.o_state();
346 n_edges++;
347 // Adjust degrees
348 layers[i].states[t.i_state()].o_deg++;
349 layers[i+1].states[t.o_state()].i_deg++;
350 // Adjust number of tuples
351 layers[i+1].states[t.o_state()].n_tuples
352 += layers[i].states[t.i_state()].n_tuples;
353 }
354 assert(static_cast<unsigned int>(n_edges) <= dfa.max_degree());
355 }
356 // Found a support for the value
357 if (n_edges > 0) {
358 Support& support = supports[n_supports++];
359 support.val = s.val();
360 support.n_edges = n_edges;
361 support.edges = Heap::copy(r.alloc<Edge>(n_edges),edges,n_edges);
362 }
363 }
364 // Create supports
365 if (n_supports > 0) {
366 layers[i].supports =
367 Heap::copy(r.alloc<Support>(n_supports),supports,n_supports);
368 layers[i].n_supports = n_supports;
369 } else {
370 finalize();
371 return;
372 }
373 }
374
375 // Mark final states as being reachable
376 for (int s=dfa.final_fst(); s<dfa.final_lst(); s++) {
377 if (layers[a].states[s].i_deg != 0U)
378 layers[a].states[s].o_deg = 1U;
379 }
380
381 // Backward pass: validate
382 for (int i=a; i--; ) {
383 for (int j = layers[i].n_supports; j--; ) {
384 Support& s = layers[i].supports[j];
385 for (int k = s.n_edges; k--; ) {
386 int i_state = s.edges[k].i_state;
387 int o_state = s.edges[k].o_state;
388 // State is unreachable
389 if (layers[i+1].states[o_state].o_deg == 0) {
390 // Adjust degree
391 --layers[i+1].states[o_state].i_deg;
392 --layers[i].states[i_state].o_deg;
393 // Remove edge
394 assert(s.n_edges > 0);
395 s.edges[k] = s.edges[--s.n_edges];
396 }
397 }
398 // Lost support
399 if (s.n_edges == 0)
400 layers[i].supports[j] = layers[i].supports[--layers[i].n_supports];
401 }
402 if (layers[i].n_supports == 0U) {
403 finalize();
404 return;
405 }
406 }
407
408 // Generate tuples
409 for (int i=0; i<a; i++) {
410 for (int j = layers[i].n_supports; j--; ) {
411 Support& s = layers[i].supports[j];
412 for (int k = s.n_edges; k--; ) {
413 int i_state = s.edges[k].i_state;
414 int o_state = s.edges[k].o_state;
415 // Allocate memory for tuples if not done
416 if (layers[i+1].states[o_state].tuples == nullptr) {
417 int n_tuples = layers[i+1].states[o_state].n_tuples;
418 layers[i+1].states[o_state].tuples = r.alloc<int>((i+1)*n_tuples);
419 layers[i+1].states[o_state].n_tuples = 0;
420 }
421 int n = layers[i+1].states[o_state].n_tuples;
422 // Write tuples
423 for (int t=0; t < layers[i].states[i_state].n_tuples; t++) {
424 // Copy the first i number of digits from the previous layer
425 Heap::copy(&layers[i+1].states[o_state].tuples[n*(i+1)+t*(i+1)],
426 &layers[i].states[i_state].tuples[t*i], i);
427 // Write the last digit
428 layers[i+1].states[o_state].tuples[n*(i+1)+t*(i+1)+i] = s.val;
429 }
430 layers[i+1].states[o_state].n_tuples
431 += layers[i].states[i_state].n_tuples;
432 }
433 }
434 }
435
436 // Add tuples to tuple set
437 for (int s = dfa.final_fst(); s < dfa.final_lst(); s++) {
438 for (int i=0; i<layers[a].states[s].n_tuples; i++) {
439 int* tuple = &layers[a].states[s].tuples[i*a];
440 add(IntArgs(a,tuple));
441 }
442 }
443
444 finalize();
445 }
446
447 bool
448 TupleSet::equal(const TupleSet& t) const {
449 assert(tuples() == t.tuples());
450 assert(arity() == t.arity());
451 assert(min() == t.min());
452 assert(max() == t.max());
453 for (int i=0; i<tuples(); i++)
454 for (int j=0; j<arity(); j++)
455 if ((*this)[i][j] != t[i][j])
456 return false;
457 return true;
458 }
459
460 void
461 TupleSet::_add(const IntArgs& t) {
462 if (!*this)
463 throw Int::UninitializedTupleSet("TupleSet::add()");
464 if (raw().finalized())
465 throw Int::AlreadyFinalized("TupleSet::add()");
466 if (t.size() != raw().arity)
467 throw Int::ArgumentSizeMismatch("TupleSet::add()");
468 Tuple a = raw().add();
469 for (int i=0; i<t.size(); i++)
470 a[i]=t[i];
471 }
472
473}
474
475// STATISTICS: int-prop
476