this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Christian Schulte <schulte@gecode.org>
5 *
6 * Contributing authors:
7 * Mikael Lagerkvist <lagerkvist@gecode.org>
8 *
9 * Copyright:
10 * Christian Schulte, 2006
11 * Mikael Lagerkvist, 2006
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 Channel {
39
40 /**
41 * \brief Combine view with information for domain propagation
42 *
43 */
44 template<class View, class Offset>
45 class DomInfo {
46 public:
47 /// The view
48 View view;
49 /// Last propagated size
50 unsigned int size;
51 /// Last propagated minimum
52 int min;
53 /// Last propagated maximum
54 int max;
55 /// Initialize
56 void init(View x, int n);
57 /// Update during cloning
58 void update(Space& home, DomInfo<View,Offset>& vcb);
59 /// Check whether propagation for assignment is to be done
60 bool doval(void) const;
61 /// Check whether propagation for domain is to be done
62 bool dodom(void) const;
63 /// Record that view got assigned
64 void assigned(void);
65 /// Record that one value got removed
66 void removed(int i);
67 /// Update the size and bounds information after pruning
68 void done(Offset& o);
69 };
70
71 template<class View, class Offset>
72 forceinline void
73 DomInfo<View,Offset>::init(View x, int n) {
74 view = x;
75 size = static_cast<unsigned int>(n);
76 min = 0;
77 max = n-1;
78 }
79
80 template<class View, class Offset>
81 forceinline void
82 DomInfo<View,Offset>::update(Space& home, DomInfo<View,Offset>& di) {
83 view.update(home,di.view);
84 size = di.size;
85 min = di.min;
86 max = di.max;
87 }
88
89 template<class View, class Offset>
90 forceinline bool
91 DomInfo<View,Offset>::doval(void) const {
92 return (size != 1) && view.assigned();
93 }
94
95 template<class View, class Offset>
96 forceinline bool
97 DomInfo<View,Offset>::dodom(void) const {
98 return size != view.size();
99 }
100
101 template<class View, class Offset>
102 forceinline void
103 DomInfo<View,Offset>::assigned(void) {
104 size = 1;
105 }
106
107 template<class View, class Offset>
108 forceinline void
109 DomInfo<View,Offset>::removed(int i) {
110 size--;
111 if (i == min)
112 min++;
113 else if (i == max)
114 max--;
115 }
116
117 template<class View, class Offset>
118 forceinline void
119 DomInfo<View,Offset>::done(Offset& o) {
120 size = view.size();
121 min = o(view).min();
122 max = o(view).max();
123 }
124
125 // Propagate domain information from x to y
126 template<class View, class Offset>
127 ExecStatus
128 prop_dom(Space& home, int n, DomInfo<View,Offset>* x, Offset& ox,
129 DomInfo<View,Offset>* y, Offset& oy, ProcessStack& ya) {
130 for (int i=0; i<n; i++)
131 // Only views with not yet propagated missing values
132 if (x[i].dodom()) {
133 // Iterate the values in the complement of x[i]
134 ViewRanges<typename Offset::ViewType>
135 xir(ox(x[i].view));
136 Iter::Ranges::ComplVal<ViewRanges<typename Offset::ViewType> >
137 xirc(x[i].min,x[i].max,xir);
138 Iter::Ranges::ToValues<Iter::Ranges::ComplVal<
139 ViewRanges<typename Offset::ViewType> > > jv(xirc);
140 while (jv()) {
141 // j is not in the domain of x[i], so prune i from y[j]
142 int j = jv.val();
143 ModEvent me = oy(y[j].view).nq(home,i);
144 if (me_failed(me))
145 return ES_FAILED;
146 if (me_modified(me)) {
147 if (me == ME_INT_VAL) {
148 // Record that y[j] has been assigned and must be propagated
149 ya.push(j);
150 } else {
151 // Obvious as x[i] is different from j
152 y[j].removed(i);
153 }
154 }
155 ++jv;
156 }
157 // Update which values have been propagated and what are the new bounds
158 x[i].done(ox);
159 }
160 return ES_OK;
161 }
162
163 /*
164 * The actual propagator
165 *
166 */
167 template<class View, class Offset, bool shared>
168 forceinline
169 Dom<View,Offset,shared>::Dom(Home home, int n, DomInfo<View,Offset>* xy,
170 Offset& ox, Offset& oy)
171 : Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,n,xy,ox,oy) {}
172
173 template<class View, class Offset, bool shared>
174 forceinline
175 Dom<View,Offset,shared>::Dom(Space& home, Dom<View,Offset,shared>& p)
176 : Base<DomInfo<View,Offset>,Offset,PC_INT_DOM>(home,p) {}
177
178 template<class View, class Offset, bool shared>
179 Actor*
180 Dom<View,Offset,shared>::copy(Space& home) {
181 return new (home) Dom<View,Offset,shared>(home,*this);
182 }
183
184 template<class View, class Offset, bool shared>
185 PropCost
186 Dom<View,Offset,shared>::cost(const Space&,
187 const ModEventDelta& med) const {
188 if (View::me(med) == ME_INT_VAL)
189 return PropCost::quadratic(PropCost::LO, 2*n);
190 else
191 return PropCost::quadratic(PropCost::HI, 2*n);
192 }
193
194 template<class View, class Offset, bool shared>
195 ExecStatus
196 Dom<View,Offset,shared>::propagate(Space& home, const ModEventDelta& med) {
197 // MSVC in non-permissive mode needs this, no idea why...
198 const int n = this->n;
199 Region r;
200 ProcessStack xa(r,n);
201 ProcessStack ya(r,n);
202
203 DomInfo<View,Offset>* x = xy;
204 DomInfo<View,Offset>* y = xy+n;
205
206 if (View::me(med) == ME_INT_VAL) {
207 // Scan x and y for assigned but not yet propagated views
208 for (int i=0; i<n; i++) {
209 if (x[i].doval()) xa.push(i);
210 if (y[i].doval()) ya.push(i);
211 }
212
213 if (shared) {
214 do {
215 // Propagate assigned views for x
216 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
217 (home,n,x,ox,y,oy,n_na,xa,ya)));
218 // Propagate assigned views for y
219 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
220 (home,n,y,oy,x,ox,n_na,ya,xa)));
221 assert(ya.empty());
222 } while (!xa.empty() || !ya.empty());
223 return home.ES_NOFIX_PARTIAL(*this,View::med(ME_INT_DOM));
224 } else {
225 do {
226 // Propagate assigned views for x
227 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
228 (home,n,x,ox,y,oy,n_na,xa,ya)));
229 // Propagate assigned views for y
230 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
231 (home,n,y,oy,x,ox,n_na,ya,xa)));
232 assert(ya.empty());
233 } while (!xa.empty());
234 return home.ES_FIX_PARTIAL(*this,View::med(ME_INT_DOM));
235 }
236 }
237
238 // Process changed views for y
239 // This propagates from y to x and possibly records xs that
240 // got assigned
241 GECODE_ES_CHECK(prop_dom(home,n,y,oy,x,ox,xa));
242
243 // Process assigned views for x
244 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
245 (home,n,x,ox,y,oy,n_na,xa,ya)));
246
247 // Perform domain consistent propagation for distinct on the x views
248 if (dc.available()) {
249 GECODE_ES_CHECK(dc.sync());
250 } else {
251 ViewArray<View> xv(r,n);
252 for (int i=0; i<n; i++)
253 xv[i] = x[i].view;
254 GECODE_ES_CHECK(dc.init(home,xv));
255 }
256 bool assigned;
257 GECODE_ES_CHECK(dc.propagate(home,assigned));
258 if (assigned) {
259 // This has assigned some more views in x which goes unnoticed
260 // (that is, not recorded in xa). This must be checked and propagated
261 // to the y views, however the distinctness on x is already
262 // propagated.
263 for (int i=0; i<n; i++)
264 if (x[i].doval()) {
265 int j = ox(x[i].view).val();
266 // Assign the y variable to i (or test if already assigned!)
267 ModEvent me = oy(y[j].view).eq(home,i);
268 if (me_failed(me))
269 return ES_FAILED;
270 if (me_modified(me)) {
271 // Record that y[j] has been assigned and must be propagated
272 assert(me == ME_INT_VAL);
273 // Otherwise the modification event would not be ME_INT_VAL
274 ya.push(j);
275 }
276 x[i].assigned(); n_na--;
277 }
278 }
279
280 // Process changed views for x
281 // This propagates from x to y and possibly records ys that
282 // got assigned
283 GECODE_ES_CHECK(prop_dom(home,n,x,ox,y,oy,ya));
284
285 // Process assigned view again (some might have been found above)
286 while (!xa.empty() || !ya.empty()) {
287 // Process assigned views for x
288 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
289 (home,n,x,ox,y,oy,n_na,xa,ya)));
290 // Process assigned views for y
291 GECODE_ES_CHECK((prop_val<View,Offset,DomInfo<View,Offset> >
292 (home,n,y,oy,x,ox,n_na,ya,xa)));
293 };
294
295 if (shared) {
296 for (int i=0; i<2*n; i++)
297 if (!xy[i].view.assigned())
298 return ES_NOFIX;
299 return home.ES_SUBSUMED(*this);
300 } else {
301 return (n_na == 0) ? home.ES_SUBSUMED(*this) : ES_FIX;
302 }
303 }
304
305 template<class View, class Offset, bool shared>
306 ExecStatus
307 Dom<View,Offset,shared>::post(Home home, int n, DomInfo<View,Offset>* xy,
308 Offset& ox, Offset& oy) {
309 assert(n > 0);
310 if (n == 1) {
311 GECODE_ME_CHECK(ox(xy[0].view).eq(home,0));
312 GECODE_ME_CHECK(oy(xy[1].view).eq(home,0));
313 return ES_OK;
314 }
315 for (int i=0; i<n; i++) {
316 GECODE_ME_CHECK(ox(xy[i ].view).gq(home,0));
317 GECODE_ME_CHECK(ox(xy[i ].view).le(home,n));
318 GECODE_ME_CHECK(oy(xy[i+n].view).gq(home,0));
319 GECODE_ME_CHECK(oy(xy[i+n].view).le(home,n));
320 }
321 (void) new (home) Dom<View,Offset,shared>(home,n,xy,ox,oy);
322 return ES_OK;
323 }
324
325}}}
326
327// STATISTICS: int-prop
328