this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * David Rijsman <David.Rijsman@quintiq.com>
5 *
6 * Contributing authors:
7 * Christian Schulte <schulte@gecode.org>
8 *
9 * Copyright:
10 * David Rijsman, 2009
11 * Christian Schulte, 2009
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
38namespace Gecode { namespace Int { namespace Sequence {
39
40 /**
41 * \brief Class for advising the propagator
42 */
43 template<class View>
44 class SupportAdvisor : public Advisor {
45 public:
46 /// Index position
47 int i;
48 /// Initialize
49 SupportAdvisor(Space& home, Propagator& p, Council<SupportAdvisor>& c,
50 int i0);
51 /// Copy during cloning
52 SupportAdvisor(Space& home, SupportAdvisor& a);
53 /// Dispose advisor
54 void dispose(Space& home, Council<SupportAdvisor>& c);
55 };
56
57 template<class View>
58 forceinline
59 SupportAdvisor<View>::SupportAdvisor(Space& home, Propagator& p,
60 Council<SupportAdvisor>& c,int i0)
61 : Advisor(home,p,c), i(i0) {
62 }
63
64 template<class View>
65 forceinline
66 SupportAdvisor<View>::SupportAdvisor(Space& home, SupportAdvisor& a)
67 : Advisor(home,a), i(a.i) {
68 }
69
70 template<class View>
71 forceinline void
72 SupportAdvisor<View>::dispose(Space& home, Council<SupportAdvisor>& c) {
73 Advisor::dispose(home,c);
74 }
75
76 /**
77 * \brief Class for view value support structure
78 */
79 template<class View, class Val, bool iss>
80 class ViewValSupport {
81 public:
82 /// Initialize
83 void init(Space& home, ViewArray<View>& x,Val s, int i, int q);
84 /// Update
85 void update(Space& home, ViewValSupport<View,Val,iss>& vvs, int n0);
86 /// Advise
87 ExecStatus advise(Space& home,ViewArray<View>& a,Val s,int i,int q, int j,const Delta& d);
88 /// Propagate
89 ExecStatus propagate(Space& home,ViewArray<View>& a,Val s,int i,int q,int l,int u);
90 /// Return true if sequence j has been violated
91 bool violated(int j, int q, int l, int u) const;
92 /// Check if retired
93 bool retired(void) const;
94 /// Allocate an instance
95 static ViewValSupport* allocate(Space&,int);
96 private:
97 /// Schedules the invoking support to be concluded (to be shaved)
98 ExecStatus schedule_conclusion(ViewArray<View>& a,Val s,int i);
99 /// Returns true if a conclusion to be made has been scheduled
100 bool conlusion_scheduled(void) const;
101 /// Retires invoking instance
102 void retire(void);
103 /// Return number of forced to s elements in sequence j
104 int values(int j, int q) const;
105 /// Checks if x[i] has been shaved
106 bool shaved(const View& x, Val s, int i) const;
107 /// Push up the cumulative array
108 bool pushup(ViewArray<View>& a,Val s,int i,int q,int idx, int v);
109 /// Make conclusion
110 ExecStatus conclude(Space& home,ViewArray<View>& a,Val s,int i);
111 /// Returns true if a[idx]=s not possible taking into account a[i]=s if iss or a[i]!=s if ! iss
112 bool s_not_possible(ViewArray<View>& a, Val s, int i, int idx) const;
113 /// Returns true if a[idx] can be not s taking into account a[i]=s if iss or a[i]!=s if ! iss
114 bool alternative_not_possible(ViewArray<View>& a,Val s,int i, int idx) const;
115 /// Returns true if there are potential violations marked
116 bool has_potential_violation(void) const;
117 /// Returns next potential violation and removes it
118 int next_potential_violation(void);
119 /// Adds potential violation i
120 void potential_violation(int i);
121 // Sets element idx of cumulative array to v
122 void set(int idx, int v, int q, int n);
123 /// Adds potential violations for location idx in cumulative array
124 void potential_violation(int idx, int q, int n);
125 /// Cumulative array
126 int* y;
127 /// Potential violation set
128 Violations v;
129 };
130
131
132 template<class View, class Val, bool iss>
133 forceinline ViewValSupport<View,Val,iss>*
134 ViewValSupport<View,Val,iss>::allocate(Space& home, int n) {
135 return home.alloc<ViewValSupport<View,Val,iss> >(n);
136 }
137
138 template<class View, class Val, bool iss>
139 forceinline bool
140 ViewValSupport<View,Val,iss>::has_potential_violation(void) const {
141 return !v.empty();
142 }
143
144 template<class View, class Val, bool iss>
145 forceinline int
146 ViewValSupport<View,Val,iss>::next_potential_violation(void) {
147 return static_cast<int>(v.get());
148 }
149
150 template<class View, class Val, bool iss>
151 forceinline void
152 ViewValSupport<View,Val,iss>::potential_violation(int k) {
153 v.add(static_cast<unsigned int>(k));
154 }
155
156
157 template<class View, class Val, bool iss>
158 forceinline bool
159 ViewValSupport<View,Val,iss>::retired(void) const {
160 return nullptr == y;
161 }
162
163 template<class View, class Val, bool iss>
164 forceinline void
165 ViewValSupport<View,Val,iss>::retire(void) {
166 y = nullptr;
167 }
168
169 template<class View,class Val, bool iss>
170 forceinline bool
171 ViewValSupport<View,Val,iss>::alternative_not_possible
172 (ViewArray<View>& a, Val s, int i, int idx) const {
173 (void) i;
174 return includes(a[idx-1],s) || (iss && (idx-1 == i));
175 }
176
177 template<class View, class Val, bool iss>
178 forceinline bool
179 ViewValSupport<View,Val,iss>::s_not_possible
180 (ViewArray<View>& a, Val s, int i, int idx) const {
181 (void) i;
182 return excludes(a[idx-1],s) || (!iss && (i == idx-1));
183 }
184
185
186 template<class View, class Val, bool iss>
187 forceinline void
188 ViewValSupport<View,Val,iss>::init(Space& home, ViewArray<View>& a, Val s,
189 int i, int q) {
190 y = home.alloc<int>(a.size()+1);
191 v.init(home,static_cast<unsigned int>(a.size()));
192 y[0] = 0;
193 for ( int l=0; l<a.size(); l++ ) {
194 if ( alternative_not_possible(a,s,i,l+1) ) {
195 y[l+1] = y[l] + 1;
196 } else {
197 y[l+1] = y[l];
198 }
199 if ( l+1 >= q ) {
200 potential_violation(l+1-q);
201 }
202 if ( l <= a.size() - q ) {
203 potential_violation(l);
204 }
205
206 }
207 }
208
209 template<class View, class Val, bool iss>
210 forceinline void
211 ViewValSupport<View,Val,iss>::update(Space& home,
212 ViewValSupport<View,Val,iss>& vvs,
213 int n0) {
214 y = nullptr;
215 if ( !vvs.retired() ) {
216 y = home.alloc<int>(n0);
217 for ( int l=0; l<n0; l++ ) {
218 y[l] = vvs.y[l];
219 }
220 v.update(home,vvs.v);
221 // = &home.construct<S>(S::key_compare(),S::allocator_type(home));
222 }
223 }
224
225 template<class View,class Val, bool iss>
226 forceinline bool
227 ViewValSupport<View,Val,iss>::shaved(const View& x, Val s, int) const {
228 if (iss)
229 return excludes(x,s);
230 else
231 return includes(x,s);
232 }
233
234 template<class View,class Val, bool iss>
235 forceinline ExecStatus
236 ViewValSupport<View,Val,iss>::schedule_conclusion(ViewArray<View>& a, Val s,
237 int i) {
238 if (!retired()) {
239 if ((iss && includes(a[i],s)) || (!iss && excludes(a[i],s)))
240 return ES_FAILED;
241 y[0] = 1;
242 potential_violation(0);
243 }
244
245 return ES_OK;
246 }
247
248 template<class View,class Val, bool iss>
249 forceinline bool
250 ViewValSupport<View,Val,iss>::conlusion_scheduled(void) const {
251 return !retired() && y[0] > 0;
252 }
253
254 template<class View,class Val, bool iss>
255 forceinline int
256 ViewValSupport<View,Val,iss>::values(int j, int q) const {
257 return y[j+q]-y[j];
258 }
259
260 template<class View,class Val,bool iss>
261 forceinline bool
262 ViewValSupport<View,Val,iss>::violated(int j, int q, int l, int u) const {
263 return values(j,q) < l || values(j,q) > u;
264 }
265
266 template<class View,class Val,bool iss>
267 forceinline ExecStatus
268 ViewValSupport<View,Val,iss>::conclude(Space& home,ViewArray<View>& a,
269 Val s, int i) {
270 if ( iss ) {
271 GECODE_ME_CHECK(exclude(home,a[i],s));
272 } else {
273 GECODE_ME_CHECK(include(home,a[i],s));
274 }
275
276 retire();
277
278 return ES_OK;
279 }
280
281 template<class View,class Val,bool iss>
282 forceinline void
283 ViewValSupport<View,Val,iss>::potential_violation(int idx, int q, int n) {
284 if ( idx >= q ) {
285 potential_violation(idx-q);
286 }
287 if ( idx <= n - q - 1) {
288 potential_violation(idx);
289 }
290 }
291
292 template<class View,class Val,bool iss>
293 forceinline void
294 ViewValSupport<View,Val,iss>::set(int idx, int v, int q, int n) {
295 assert(y[idx]<=v);
296 if ( y[idx] < v ) {
297 y[idx] = v;
298 potential_violation(idx,q,n);
299 }
300 }
301
302 template<class View,class Val,bool iss>
303 forceinline bool
304 ViewValSupport<View,Val,iss>::pushup(ViewArray<View>& a,Val s,int i,int q,int idx, int v) {
305 if ( !retired() ) {
306 int n = a.size() + 1;
307
308 set(idx,y[idx]+v,q,n);
309
310 if ( y[idx] > idx ) {
311 return false;
312 }
313
314 int t = idx;
315
316 // repair y on the left
317 while ( idx > 0 && ((y[idx]-y[idx-1]>1) || ((y[idx]-y[idx-1]==1 && s_not_possible(a,s,i,idx)))) ) {
318 if ( s_not_possible(a,s,i,idx) ) {
319 set(idx-1,y[idx],q,n);
320 } else {
321 set(idx-1,y[idx]-1,q,n);
322 }
323 if ( y[idx-1]>idx-1 ) {
324 return false;
325 }
326 idx -= 1;
327 }
328
329 idx = t;
330
331 // repair y on the right
332 while ( idx < a.size() && ((y[idx]-y[idx+1]>0) || ((y[idx]-y[idx+1]==0) && alternative_not_possible(a,s,i,idx+1))) ) {
333 if ( alternative_not_possible(a,s,i,idx+1) ) {
334 set(idx+1,y[idx]+1,q,n);
335 } else {
336 set(idx+1,y[idx],q,n);
337 }
338 idx += 1;
339 }
340 }
341
342 return true;
343 }
344
345 template<class View,class Val,bool iss>
346 forceinline ExecStatus
347 ViewValSupport<View,Val,iss>::advise(Space&, ViewArray<View>& a,
348 Val s,int i,int q, int j,
349 const Delta&) {
350 ExecStatus status = ES_FIX;
351 if (!retired()) {
352 if ((j == i) && shaved(a[j],s,j)) {
353 retire();
354 } else {
355 switch (takes(a[j],s)) {
356 case TS_YES:
357 if (y[j+1]-y[j] == 0) {
358 if (!pushup(a,s,i,q,j+1,1)) {
359 GECODE_ES_CHECK(schedule_conclusion(a,s,i));
360 }
361 }
362 break;
363 case TS_NO:
364 if (y[j+1]-y[j] > 0) {
365 if (!pushup(a,s,i,q,j,y[j+1]-y[j])) {
366 GECODE_ES_CHECK(schedule_conclusion(a,s,i));
367 }
368 }
369 break;
370 case TS_MAYBE:
371 break;
372 default:
373 GECODE_NEVER;
374 }
375
376 if ( has_potential_violation() )
377 status = ES_NOFIX;
378 }
379 }
380
381 return status;
382 }
383
384 template<class View,class Val,bool iss>
385 forceinline ExecStatus
386 ViewValSupport<View,Val,iss>::propagate(Space& home,ViewArray<View>& a,Val s,int i,int q,int l,int u) {
387 if ( !retired() ) {
388 if ( conlusion_scheduled() ) {
389 return conclude(home,a,s,i);
390 }
391
392 while (has_potential_violation()) {
393 int j = next_potential_violation();
394 if (violated(j,q,l,u)) {
395 int forced_to_s = values(j,q);
396 if (forced_to_s < l) {
397 if (!pushup(a,s,i,q,j+q,l-forced_to_s))
398 return conclude(home,a,s,i);
399 } else {
400 if (!pushup(a,s,i,q,j,forced_to_s-u))
401 return conclude(home,a,s,i);
402 }
403 if (violated(j,q,l,u))
404 return conclude(home,a,s,i);
405 }
406 }
407 }
408 return ES_OK;
409 }
410
411 template<class View,class Val,bool iss>
412 ViewValSupportArray<View,Val,iss>::ViewValSupportArray(void) : xs(nullptr), n(0) {
413 }
414
415 template<class View,class Val,bool iss>
416 ViewValSupportArray<View,Val,iss>::ViewValSupportArray(const ViewValSupportArray<View,Val,iss>& a) {
417 n = a.n; xs = a.xs;
418 }
419
420 template<class View,class Val,bool iss>
421 ViewValSupportArray<View,Val,iss>::ViewValSupportArray(Space& home,ViewArray<View>& x, Val s, int q) : xs(nullptr) {
422 n = x.size();
423 if ( n > 0 ) {
424 xs = ViewValSupport<View,Val,iss>::allocate(home,n);
425 for (int i = n; i--; ) {
426 xs[i].init(home,x,s,i,q);
427 }
428 }
429 }
430
431 template<class View,class Val,bool iss>
432 ViewValSupportArray<View,Val,iss>::ViewValSupportArray(Space& home, int n0) : xs(nullptr) {
433 n = n0;
434 if (n>0) {
435 xs = ViewValSupport<View,Val,iss>::allocate(home,n);
436 }
437 }
438
439 template<class View,class Val,bool iss>
440 forceinline int
441 ViewValSupportArray<View,Val,iss>::size(void) const {
442 return n;
443 }
444
445 template<class View,class Val,bool iss>
446 forceinline ViewValSupport<View,Val,iss>&
447 ViewValSupportArray<View,Val,iss>::operator [](int i) {
448 assert((i >= 0) && (i < size()));
449 return xs[i];
450 }
451
452 template<class View,class Val,bool iss>
453 forceinline const ViewValSupport<View,Val,iss>&
454 ViewValSupportArray<View,Val,iss>::operator [](int i) const {
455 assert((i >= 0) && (i < size()));
456 return xs[i];
457 }
458
459 template<class View,class Val,bool iss>
460 void
461 ViewValSupportArray<View,Val,iss>::update(Space& home, ViewValSupportArray<View,Val,iss>& a) {
462 n = a.size();
463 if (n>0) {
464 xs = ViewValSupport<View,Val,iss>::allocate(home,n);
465 for (int i=n; i--; ) {
466 xs[i].update(home,a[i],n+1);
467 }
468 }
469 }
470
471 template<class View,class Val,bool iss>
472 ExecStatus
473 ViewValSupportArray<View,Val,iss>::propagate(Space& home,ViewArray<View>& a,Val s,int q,int l,int u) {
474 for (int i=n; i--; ) {
475 GECODE_ES_CHECK(xs[i].propagate(home,a,s,i,q,l,u));
476 }
477 return ES_OK;
478 }
479
480 template<class View,class Val,bool iss>
481 ExecStatus
482 ViewValSupportArray<View,Val,iss>::advise(Space& home,ViewArray<View>& a,Val s,int q,int j,const Delta& d) {
483 ExecStatus status = ES_FIX;
484 for (int i=n; i--; ) {
485 if ( ES_NOFIX == xs[i].advise(home,a,s,i,q,j,d) )
486 status = ES_NOFIX;
487 }
488 return status;
489 }
490}}}
491
492
493// STATISTICS: int-prop
494