Generated on for Gecode by doxygen 1.17.0
propagate.hpp
Go to the documentation of this file.
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.dev>
5 *
6 * Contributing authors:
7 * Fabio Tardivo <ftardivo@nmsu.edu>
8 *
9 * Copyright:
10 * Fabio Tardivo, 2024
11 * Christian Schulte, 2010
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 BinPacking {
39
40 /*
41 * Item
42 *
43 */
44 forceinline
46 : s(0) {}
47 forceinline
49 : DerivedView<IntView>(b), s(s0) {}
50
51 forceinline IntView
52 Item::bin(void) const {
53 return x;
54 }
55 forceinline
57 x = b;
58 }
59 forceinline int
60 Item::size(void) const {
61 return s;
62 }
63 forceinline void
64 Item::size(int s0) {
65 s = s0;
66 }
67
68 forceinline void
69 Item::update(Space& home, Item& i) {
70 x.update(home,i.x);
71 s = i.s;
72 }
73
74
75 forceinline bool
76 operator ==(const Item& i, const Item& j) {
77 return (i.bin() == j.bin()) && (i.size() == j.size());
78 }
79 forceinline bool
80 operator !=(const Item& i, const Item& j) {
81 return !(i == j);
82 }
83
85 forceinline bool
86 operator <(const Item& i, const Item& j) {
87 return i.size() > j.size();
88 }
89
90
91 /*
92 * Size set
93 *
94 */
95 forceinline
97 forceinline
98 SizeSet::SizeSet(Region& region, int n_max)
99 : n(0), t(0), s(region.alloc<int>(n_max)) {}
100 forceinline void
101 SizeSet::add(int s0) {
102 t += s0; s[n++] = s0;
103 }
104 forceinline int
105 SizeSet::card(void) const {
106 return n;
107 }
108 forceinline int
109 SizeSet::total(void) const {
110 return t;
111 }
112 forceinline int
113 SizeSet::operator [](int i) const {
114 return s[i];
115 }
116
117 forceinline
119 forceinline
121 : SizeSet(region,n_max), p(-1) {}
122 forceinline void
124 // This rests on the fact that items are removed in order
125 do
126 p++;
127 while (s[p] > s0);
128 assert(p < n);
129 }
130 forceinline int
132 assert(p >= 0);
133 return n - 1;
134 }
135 forceinline int
137 assert(p >= 0);
138 return t - s[p];
139 }
140 forceinline int
142 assert(p >= 0);
143 return s[(i < p) ? i : i+1];
144 }
145
146
147
148 /*
149 * Packing propagator
150 *
151 */
152
153 forceinline
155 IntPropLevel ipl0)
156 : Propagator(home), l(l0), bs(bs0),
157 ipl(ba(ipl0) == IPL_DEF ? IPL_ADVANCED : ipl0), t(0) {
158 l.subscribe(home,*this,PC_INT_BND);
159 bs.subscribe(home,*this,PC_INT_DOM);
160 for (int i=0; i<bs.size(); i++)
161 t += bs[i].size();
162 }
163
164 forceinline
166 : Propagator(home,p), ipl(p.ipl), t(p.t) {
167 l.update(home,p.l);
168 bs.update(home,p.bs);
169 }
170
171 forceinline size_t
173 l.cancel(home,*this,PC_INT_BND);
174 bs.cancel(home,*this,PC_INT_DOM);
175 (void) Propagator::dispose(home);
176 return sizeof(*this);
177 }
178
179 template<class SizeSet>
180 forceinline bool
181 Pack::nosum(const SizeSet& s, int a, int b, int& ap, int& bp) {
182 if ((a <= 0) || (b >= s.total()))
183 return false;
184 int n=s.card()-1;
185 int sc=0;
186 int kp=0;
187 while (sc + s[n-kp] < a) {
188 sc += s[n-kp];
189 kp++;
190 }
191 int k=0;
192 int sa=0, sb = s[n-kp];
193 while ((sa < a) && (sb <= b)) {
194 sa += s[k++];
195 if (sa < a) {
196 kp--;
197 sb += s[n-kp];
198 sc -= s[n-kp];
199 while (sa + sc >= a) {
200 kp--;
201 sc -= s[n-kp];
202 sb += s[n-kp] - s[n-kp-k-1];
203 }
204 }
205 }
206 ap = sa + sc; bp = sb;
207 return sa < a;
208 }
209
210 template<class SizeSet>
211 forceinline bool
212 Pack::nosum(const SizeSet& s, int a, int b) {
213 int ap, bp;
214 return nosum(s, a, b, ap, bp);
215 }
216
217 forceinline int
218 Pack::f_ccm1(int w, int l, int c) {
219 // Conditions
220 int const c0 = w > c - w; // x > c / 2
221 int const c1 = w == c - w; // x == c / 2
222 int const c2 = w < c - w; // x < c / 2
223
224 // Values
225 int const v0 = 2 * ((c / l) - ((c - w) / l));
226 int const v1 = c / l;
227 int const v2 = 2 * (w / l);
228
229 return (c0 * v0) + (c1 * v1) + (c2 * v2);
230 }
231
232 forceinline int
233 Pack::f_mt(int w, int l, int c) {
234 // Conditions
235 int const c0 = w < l;
236 int const c1 = (l <= w) && (w <= c - l);
237 int const c2 = c - l < w;
238
239 // Values
240 int const v0 = 0;
241 int const v1 = w;
242 int const v2 = c;
243
244 return (c0 * v0) + (c1 * v1) + (c2 * v2);
245 }
246
247 forceinline int
248 Pack::f_bj1(int w, int l, int c) {
249 // Auxiliary values
250 int const p = l - (c % l);
251
252 // Conditions
253 int const c0 = w % l <= c % l;
254 int const c1 = w % l > c % l;
255
256 // Values
257 int const v0 = (w / l) * p;
258 int const v1 = (w / l) * p + (w % l) - (c % l);
259
260 return (c0 * v0) + (c1 * v1);
261 }
262
263 forceinline int
264 Pack::f_vb2_base(int w, int l, int c) {
265 int v = ceil_div_pp(l * w, c);
266 return v > 0 ? v - 1 : 0;
267 }
268
269 forceinline int
270 Pack::f_vb2(int w, int l, int c) {
271 int const c0 = w > c - w;
272 int const c1 = w == c - w;
273 int const c2 = w < c - w;
274
275 int const t0 = f_vb2_base(c, l, c);
276 int const t1 = f_vb2_base(w, l, c);
277 int const t2 = f_vb2_base(c - w, l, c);
278
279 int const v0 = 2 * t0 - 2 * t2;
280 int const v1 = t0;
281 int const v2 = 2 * t1;
282
283 return (c0 * v0) + (c1 * v1) + (c2 * v2);
284 }
285
286 forceinline int
287 Pack::f_fs1(int w, int l, int c) {
288 // Conditions
289 int const c0 = w * (l + 1) % c == 0;
290 int const c1 = w * (l + 1) % c != 0;
291
292 // Values
293 int const v0 = w * l;
294 int const v1 = ((w * (l + 1)) / c) * c;
295
296 return (c0 * v0) + (c1 * v1);
297 }
298
299 forceinline int
300 Pack::f_rad2_base(int w, int l, int c) {
301 // Conditions
302 int const c0 = w < l;
303 int const c1 = (l <= w) && (w <= c - 2 * l);
304 int const c2 = (c - 2 * l < w) && (w < 2 * l);
305
306 // Values
307 int const v0 = 0;
308 int const v1 = c / 3;
309 int const v2 = c / 2;
310
311 return (c0 * v0) + (c1 * v1) + (c2 * v2);
312 }
313
314 forceinline int
315 Pack::f_rad2(int w, int l, int c) {
316 // Conditions
317 int const c0 = w < 2 * l;
318 int const c1 = 2 * l <= w;
319
320 // Values
321 int const v0 = f_rad2_base(w, l, c);
322 int const v1 = c - f_rad2_base(c - w, l, c);
323
324 return (c0 * v0) + (c1 * v1);
325 }
326
327 forceinline LambdaRange
329 return {1, c / 2};
330 }
331
332 forceinline LambdaRange
333 Pack::l_mt(int c) {
334 return {0, c / 2};
335 }
336
337 forceinline LambdaRange
338 Pack::l_bj1(int c) {
339 return {1, c};
340 }
341
342 forceinline LambdaRange
343 Pack::l_vb2(int c) {
344 return {2, c};
345 }
346
347 forceinline LambdaRange
349 return {1, 100};
350 }
351
352 forceinline LambdaRange
354 return {c / 4 + 1, c / 3};
355 }
356
357 forceinline LambdaRange
359 int n_not_zero_weights, int max_weight) {
360 long long int n = static_cast<long long int>(n_not_zero_weights) *
361 static_cast<long long int>(max_weight);
362 if (n != 0) {
363 int l_max =
364 std::min(static_cast<int>(std::numeric_limits<int>::max() / n),
365 lambda_range.max);
366 return {lambda_range.min, l_max};
367 } else {
368 return {0, -1};
369 }
370 }
371
372 template<int f(int,int,int)>
373 forceinline int
375 int capacity, int lambda) {
376 // Transform and sum the weights
377 long long int sum_transformed_weights = 0;
378 for (int w_idx = 0; w_idx < n_weights; w_idx += 1)
379 sum_transformed_weights += f(weights[w_idx], lambda, capacity);
380
381 // Transform the capacity
382 int transformed_capacity = f(capacity, lambda, capacity);
383
384 // Lower bound
385 return static_cast<int>
386 (ceil_div_pp(sum_transformed_weights,
387 static_cast<long long int>(transformed_capacity)));
388 }
389
390 template<int f(int,int,int), LambdaRange l(int)>
391 forceinline int
392 Pack::calc_dff_lower_bound(const int* weights, int n_weights,
393 int capacity, int n_not_zero_weights,
394 int max_weight, bool sanitize) {
395 LambdaRange lambda_range = l(capacity);
396 lambda_range =
397 sanitize ? sanitize_lambda_range(lambda_range, n_not_zero_weights,
398 max_weight) :
399 lambda_range;
400 if (lambda_range.min >= lambda_range.max)
401 return 0;
402
403 int lower_bound = 0;
404 int l_step =
405 ceil_div_pp(lambda_range.max - lambda_range.min + 1,
406 n_lambda_samples + 1);
407 for (int lambda = lambda_range.min + l_step;
408 lambda < lambda_range.max; ) {
409 int cur_lower_bound =
411 capacity, lambda);
412 lower_bound = std::max(lower_bound, cur_lower_bound);
413 if (lambda > lambda_range.max - l_step)
414 break;
415 lambda += l_step;
416 }
417 return lower_bound;
418 }
419
420}}}
421
422// STATISTICS: int-prop
virtual size_t dispose(Space &home)
Delete actor and return its size.
Definition core.hpp:3358
Home class for posting propagators
Definition core.hpp:863
Item combining bin and size information.
IntView bin(void) const
Return bin of item.
Definition propagate.hpp:52
void update(Space &home, Item &i)
Update item during cloning.
Definition propagate.hpp:69
Item(void)
Default constructor.
Definition propagate.hpp:45
int size(void) const
Return size of item.
Definition propagate.hpp:60
static LambdaRange l_rad2(int c)
static int f_bj1(int w, int l, int c)
ViewArray< OffsetView > l
Views for load of bins.
static int calc_dff_lower_bound(const int *weights, int n_weights, int capacity, int n_not_zero_weights, int max_weight, bool sanitize=false)
IntPropLevel ipl
Propagation level.
static LambdaRange sanitize_lambda_range(LambdaRange lambda, int n_weights, int max_weight)
static int f_mt(int w, int l, int c)
ViewArray< Item > bs
Items with bin and size.
int t
Total size of all items.
static int f_rad2(int w, int l, int c)
static int calc_dff_lower_bound_single_lambda(const int *weights, int n_weights, int capacity, int lambda)
Lower bound.
static int const n_lambda_samples
static LambdaRange l_ccm1(int c)
static int f_ccm1(int w, int l, int c)
Dual Feasible Functions.
static LambdaRange l_bj1(int c)
bool nosum(const SizeSet &s, int a, int b, int &ap, int &bp)
Detect non-existence of sums in a .. b.
static int f_vb2(int w, int l, int c)
static LambdaRange l_mt(int c)
static int f_vb2_base(int w, int l, int c)
static LambdaRange l_vb2(int c)
Pack(Home home, ViewArray< OffsetView > &l, ViewArray< Item > &bs, IntPropLevel ipl)
Constructor for posting.
static int f_rad2_base(int w, int l, int c)
static LambdaRange l_fs1(int c)
static int f_fs1(int w, int l, int c)
virtual size_t dispose(Space &home)
Destructor.
int operator[](int i) const
Return size of item i.
void minus(int s)
Discard size s.
SizeSetMinusOne(void)
Default constructor.
int p
Position of discarded item.
int total(void) const
Return total size.
int card(void) const
Return cardinality of set (number of entries).
int t
Total size of the set.
SizeSet(void)
Default constructor.
Definition propagate.hpp:96
void add(int s)
Add new size s.
int total(void) const
Return total size.
int operator[](int i) const
Return size of item i.
int n
Number of size entries in the set.
int * s
Array of sizes (will have more elements).
int card(void) const
Return cardinality of set (number of entries).
Integer view for integer variables.
Definition view.hpp:129
friend class Space
Definition core.hpp:1075
Propagator(Home home)
Constructor for posting.
Definition core.hpp:3607
Handle to region.
Definition region.hpp:55
Computation spaces.
Definition core.hpp:1775
View arrays.
Definition array.hpp:255
IntPropLevel
Propagation levels for integer propagators.
Definition int.hh:1008
@ IPL_ADVANCED
Use advanced propagation algorithm.
Definition int.hh:1016
@ IPL_DEF
Simple propagation levels.
Definition int.hh:1010
void weights(Home home, IntSharedArray elements, IntSharedArray weights, SetVar x, IntVar y)
Post propagator for .
Bin-packing propagators
bool operator<(const Item &i, const Item &j)
Order, also for sorting according to size.
Definition propagate.hpp:86
bool operator!=(const Item &i, const Item &j)
Whether two items are not the same.
Definition propagate.hpp:80
bool operator==(const Item &i, const Item &j)
Whether two items are the same.
Definition propagate.hpp:76
Finite domain integers.
Definition lastval.hh:52
IntType ceil_div_pp(IntType x, IntType y)
Compute where x and y are non-negative.
Definition div.hpp:38
const Gecode::PropCond PC_INT_BND
Propagate when minimum or maximum of a view changes.
Definition var-type.hpp:99
const Gecode::PropCond PC_INT_DOM
Propagate when domain changes.
Definition var-type.hpp:108
Gecode toplevel namespace
IntPropLevel ba(IntPropLevel ipl)
Extract basic or advanced from propagation level.
Definition ipl.hpp:43
const int capacity[n_warehouses]
Capacity of a single warehouse.