this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
2/*
3 * Main authors:
4 * Guido Tack <tack@gecode.org>
5 *
6 * Copyright:
7 * Guido Tack, 2008
8 *
9 * This file is part of Gecode, the generic constraint
10 * development environment:
11 * http://www.gecode.org
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining
14 * a copy of this software and associated documentation files (the
15 * "Software"), to deal in the Software without restriction, including
16 * without limitation the rights to use, copy, modify, merge, publish,
17 * distribute, sublicense, and/or sell copies of the Software, and to
18 * permit persons to whom the Software is furnished to do so, subject to
19 * the following conditions:
20 *
21 * The above copyright notice and this permission notice shall be
22 * included in all copies or substantial portions of the Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 *
32 */
33
34#include <gecode/int/linear.hh>
35
36namespace Gecode { namespace Int { namespace Arithmetic {
37
38 /*
39 * Positive bounds consistent division
40 *
41 */
42
43 template<class VA, class VB, class VC>
44 forceinline
45 DivPlusBnd<VA,VB,VC>::DivPlusBnd(Home home, VA x0, VB x1, VC x2)
46 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
47 (home,x0,x1,x2) {}
48
49 template<class VA, class VB, class VC>
50 forceinline
51 DivPlusBnd<VA,VB,VC>::DivPlusBnd(Space& home, DivPlusBnd<VA,VB,VC>& p)
52 : MixTernaryPropagator<VA,PC_INT_BND,VB,PC_INT_BND,VC,PC_INT_BND>
53 (home,p) {}
54
55 template<class VA, class VB, class VC>
56 Actor*
57 DivPlusBnd<VA,VB,VC>::copy(Space& home) {
58 return new (home) DivPlusBnd<VA,VB,VC>(home,*this);
59 }
60
61 template<class VA, class VB, class VC>
62 ExecStatus
63 DivPlusBnd<VA,VB,VC>::propagate(Space& home, const ModEventDelta&) {
64 assert(pos(x0) && pos(x1) && !neg(x2));
65 bool mod;
66 do {
67 mod = false;
68 GECODE_ME_CHECK_MODIFIED(mod,x2.lq(home,
69 floor_div_pp(x0.max(),x1.min())));
70 GECODE_ME_CHECK_MODIFIED(mod,x2.gq(home,
71 floor_div_px(x0.min(),x1.max())));
72 GECODE_ME_CHECK_MODIFIED(mod,x0.le(home,mll(x1.max(),ill(x2.max()))));
73 GECODE_ME_CHECK_MODIFIED(mod,x0.gq(home,mll(x1.min(),x2.min())));
74 if (x2.min() > 0) {
75 GECODE_ME_CHECK_MODIFIED(mod,
76 x1.lq(home,floor_div_pp(x0.max(),x2.min())));
77 }
78 GECODE_ME_CHECK_MODIFIED(mod,x1.gq(home,ceil_div_pp(ll(x0.min()),
79 ill(x2.max()))));
80 } while (mod);
81 return x0.assigned() && x1.assigned() ?
82 home.ES_SUBSUMED(*this) : ES_FIX;
83 }
84
85 template<class VA, class VB, class VC>
86 forceinline ExecStatus
87 DivPlusBnd<VA,VB,VC>::post(Home home, VA x0, VB x1, VC x2) {
88 GECODE_ME_CHECK(x0.gr(home,0));
89 GECODE_ME_CHECK(x1.gr(home,0));
90 GECODE_ME_CHECK(x2.gq(home,floor_div_pp(x0.min(),x1.max())));
91 (void) new (home) DivPlusBnd<VA,VB,VC>(home,x0,x1,x2);
92 return ES_OK;
93 }
94
95
96 /*
97 * Bounds consistent division
98 *
99 */
100 template<class View>
101 forceinline
102 DivBnd<View>::DivBnd(Home home, View x0, View x1, View x2)
103 : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
104
105 template<class View>
106 forceinline
107 DivBnd<View>::DivBnd(Space& home, DivBnd<View>& p)
108 : TernaryPropagator<View,PC_INT_BND>(home,p) {}
109
110 template<class View>
111 Actor*
112 DivBnd<View>::copy(Space& home) {
113 return new (home) DivBnd<View>(home,*this);
114 }
115
116 template<class View>
117 ExecStatus
118 DivBnd<View>::propagate(Space& home, const ModEventDelta&) {
119 if (pos(x1)) {
120 if (pos(x2) || pos(x0)) goto rewrite_ppp;
121 if (neg(x2) || neg(x0)) goto rewrite_npn;
122 goto prop_xpx;
123 }
124 if (neg(x1)) {
125 if (neg(x2) || pos(x0)) goto rewrite_pnn;
126 if (pos(x2) || neg(x0)) goto rewrite_nnp;
127 goto prop_xnx;
128 }
129 if (pos(x2)) {
130 if (pos(x0)) goto rewrite_ppp;
131 if (neg(x0)) goto rewrite_nnp;
132 goto prop_xxp;
133 }
134 if (neg(x2)) {
135 if (pos(x0)) goto rewrite_pnn;
136 if (neg(x0)) goto rewrite_npn;
137 goto prop_xxn;
138 }
139 assert(any(x1) && any(x2));
140 GECODE_ME_CHECK(x0.lq(home,std::max(mll(x1.max(),ill(x2.max()))-1,
141 mll(x1.min(),dll(x2.min()))-1)));
142 GECODE_ME_CHECK(x0.gq(home,std::min(mll(x1.min(),ill(x2.max())),
143 mll(x1.max(),dll(x2.min())))));
144 return ES_NOFIX;
145
146 prop_xxp:
147 assert(any(x0) && any(x1) && pos(x2));
148
149 GECODE_ME_CHECK(x0.le(home, mll(x1.max(),ill(x2.max()))));
150 GECODE_ME_CHECK(x0.gq(home, mll(x1.min(),ill(x2.max()))));
151
152 if (pos(x0)) goto rewrite_ppp;
153 if (neg(x0)) goto rewrite_nnp;
154
155 GECODE_ME_CHECK(x1.lq(home,floor_div_pp(x0.max(),x2.min())));
156 GECODE_ME_CHECK(x1.gq(home,ceil_div_xp(x0.min(),x2.min())));
157
158 if (x0.assigned() && x1.assigned())
159 goto subsumed;
160 return ES_NOFIX;
161
162 prop_xpx:
163 assert(any(x0) && pos(x1) && any(x2));
164
165 GECODE_ME_CHECK(x0.le(home, mll(x1.max(),ill(x2.max()))));
166 GECODE_ME_CHECK(x0.gq(home, mll(x1.max(),dll(x2.min()))));
167
168 if (pos(x0)) goto rewrite_ppp;
169 if (neg(x0)) goto rewrite_npn;
170
171 GECODE_ME_CHECK(x2.lq(home,floor_div_xp(x0.max(),x1.min())));
172 GECODE_ME_CHECK(x2.gq(home,floor_div_xp(x0.min(),x1.min())));
173
174 if (x0.assigned() && x1.assigned())
175 goto subsumed;
176 return ES_NOFIX;
177
178 prop_xxn:
179 assert(any(x0) && any(x1) && neg(x2));
180
181 GECODE_ME_CHECK(x0.lq(home, mll(x1.min(),dll(x2.min()))));
182 GECODE_ME_CHECK(x0.gq(home, mll(x1.max(),dll(x2.min()))));
183
184 if (pos(x0)) goto rewrite_pnn;
185 if (neg(x0)) goto rewrite_npn;
186
187 if (x2.max() != -1)
188 GECODE_ME_CHECK(x1.lq(home,ceil_div_xx(ll(x0.min()),ill(x2.max()))));
189 if (x2.max() != -1)
190 GECODE_ME_CHECK(x1.gq(home,ceil_div_xx(ll(x0.max()),ill(x2.max()))));
191
192 if (x0.assigned() && x1.assigned())
193 goto subsumed;
194 return ES_NOFIX;
195
196 prop_xnx:
197 assert(any(x0) && neg(x1) && any(x2));
198
199 GECODE_ME_CHECK(x0.lq(home, mll(x1.min(),dll(x2.min()))));
200 GECODE_ME_CHECK(x0.gq(home, mll(x1.min(),ill(x2.max()))));
201
202 if (pos(x0)) goto rewrite_pnn;
203 if (neg(x0)) goto rewrite_nnp;
204
205 GECODE_ME_CHECK(x2.lq(home,floor_div_xx(x0.min(),x1.max())));
206 GECODE_ME_CHECK(x2.gq(home,floor_div_xx(x0.max(),x1.max())));
207
208 if (x0.assigned() && x1.assigned())
209 goto subsumed;
210 return ES_NOFIX;
211
212 rewrite_ppp:
213 GECODE_REWRITE(*this,(DivPlusBnd<IntView,IntView,IntView>
214 ::post(home(*this),x0,x1,x2)));
215 rewrite_nnp:
216 GECODE_REWRITE(*this,(DivPlusBnd<MinusView,MinusView,IntView>
217 ::post(home(*this),MinusView(x0),MinusView(x1),x2)));
218 rewrite_pnn:
219 GECODE_REWRITE(*this,(DivPlusBnd<IntView,MinusView,MinusView>
220 ::post(home(*this),x0,MinusView(x1),MinusView(x2))));
221 rewrite_npn:
222 GECODE_REWRITE(*this,(DivPlusBnd<MinusView,IntView,MinusView>
223 ::post(home(*this),MinusView(x0),x1,MinusView(x2))));
224 subsumed:
225 assert(x0.assigned() && x1.assigned());
226 int result = std::abs(x0.val()) / std::abs(x1.val());
227 if (x0.val()/x1.val() < 0)
228 result = -result;
229 GECODE_ME_CHECK(x2.eq(home,result));
230 return home.ES_SUBSUMED(*this);
231 }
232
233 template<class View>
234 ExecStatus
235 DivBnd<View>::post(Home home, View x0, View x1, View x2) {
236 GECODE_ME_CHECK(x1.nq(home, 0));
237 if (pos(x0)) {
238 if (pos(x1) || pos(x2)) goto post_ppp;
239 if (neg(x1) || neg(x2)) goto post_pnn;
240 } else if (neg(x0)) {
241 if (neg(x1) || pos(x2)) goto post_nnp;
242 if (pos(x1) || neg(x2)) goto post_npn;
243 } else if (pos(x1)) {
244 if (pos(x2)) goto post_ppp;
245 if (neg(x2)) goto post_npn;
246 } else if (neg(x1)) {
247 if (pos(x2)) goto post_nnp;
248 if (neg(x2)) goto post_pnn;
249 }
250 (void) new (home) DivBnd<View>(home,x0,x1,x2);
251 return ES_OK;
252
253 post_ppp:
254 return DivPlusBnd<IntView,IntView,IntView>
255 ::post(home,x0,x1,x2);
256 post_nnp:
257 return DivPlusBnd<MinusView,MinusView,IntView>
258 ::post(home,MinusView(x0),MinusView(x1),x2);
259 post_pnn:
260 return DivPlusBnd<IntView,MinusView,MinusView>
261 ::post(home,x0,MinusView(x1),MinusView(x2));
262 post_npn:
263 return DivPlusBnd<MinusView,IntView,MinusView>
264 ::post(home,MinusView(x0),x1,MinusView(x2));
265 }
266
267
268 /*
269 * Propagator for x0 != 0 /\ (x1 != 0 => x0*x1>0) /\ abs(x1)<abs(x0)
270 *
271 */
272
273 template<class View>
274 forceinline
275 DivMod<View>::DivMod(Home home, View x0, View x1, View x2)
276 : TernaryPropagator<View,PC_INT_BND>(home,x0,x1,x2) {}
277
278 template<class View>
279 forceinline ExecStatus
280 DivMod<View>::post(Home home, View x0, View x1, View x2) {
281 GECODE_ME_CHECK(x1.nq(home,0));
282 (void) new (home) DivMod<View>(home,x0,x1,x2);
283 return ES_OK;
284 }
285
286 template<class View>
287 forceinline
288 DivMod<View>::DivMod(Space& home, DivMod<View>& p)
289 : TernaryPropagator<View,PC_INT_BND>(home,p) {}
290
291 template<class View>
292 Actor*
293 DivMod<View>::copy(Space& home) {
294 return new (home) DivMod<View>(home,*this);
295 }
296
297 template<class View>
298 ExecStatus
299 DivMod<View>::propagate(Space& home, const ModEventDelta&) {
300 bool signIsSame;
301 do {
302 signIsSame = true;
303 // The sign of x0 and x2 is the same
304 if (x0.min() >= 0) {
305 GECODE_ME_CHECK(x2.gq(home, 0));
306 } else if (x0.max() <= 0) {
307 GECODE_ME_CHECK(x2.lq(home, 0));
308 } else if (x2.min() > 0) {
309 GECODE_ME_CHECK(x0.gq(home, 0));
310 } else if (x2.max() < 0) {
311 GECODE_ME_CHECK(x0.lq(home, 0));
312 } else {
313 signIsSame = false;
314 }
315
316 // abs(x2) is less than abs(x1)
317 int x1max = std::max(x1.max(),std::max(-x1.max(),
318 std::max(x1.min(),-x1.min())));
319 GECODE_ME_CHECK(x2.le(home, x1max));
320 GECODE_ME_CHECK(x2.gr(home, -x1max));
321
322 int x2absmin = any(x2) ? 0 : (pos(x2) ? x2.min() : -x2.max());
323 Iter::Ranges::Singleton sr(-x2absmin,x2absmin);
324 GECODE_ME_CHECK(x1.minus_r(home,sr,false));
325 } while (!signIsSame &&
326 (x0.min() > 0 || x0.max() < 0 || x2.min() > 0 || x2.max() < 0));
327
328 if (signIsSame) {
329 int x2max = std::max(x2.max(),std::max(-x2.max(),
330 std::max(x2.min(),-x2.min())));
331 int x1absmin = any(x1) ? 0 : (pos(x1) ? x1.min() : -x1.max());
332 if (x2max < x1absmin)
333 return home.ES_SUBSUMED(*this);
334 }
335 return ES_FIX;
336 }
337
338}}}
339
340// STATISTICS: int-prop