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 * Contributing authors:
7 * Mikael Lagerkvist <lagerkvist@gmail.com>
8 *
9 * Copyright:
10 * Guido Tack, 2007
11 * Mikael Lagerkvist, 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
38#include <gecode/flatzinc/registry.hh>
39#include <gecode/kernel.hh>
40#include <gecode/int.hh>
41#include <gecode/minimodel.hh>
42
43#ifdef GECODE_HAS_SET_VARS
44#include <gecode/set.hh>
45#endif
46#ifdef GECODE_HAS_FLOAT_VARS
47#include <gecode/float.hh>
48#endif
49#include <gecode/flatzinc.hh>
50
51namespace Gecode { namespace FlatZinc {
52
53 Registry& registry(void) {
54 static Registry r;
55 return r;
56 }
57
58 void
59 Registry::post(FlatZincSpace& s, const ConExpr& ce) {
60 std::map<std::string,poster>::iterator i = r.find(ce.id);
61 if (i == r.end()) {
62 throw FlatZinc::Error("Registry",
63 std::string("Constraint ")+ce.id+" not found", ce.ann);
64 }
65 i->second(s, ce, ce.ann);
66 }
67
68 void
69 Registry::add(const std::string& id, poster p) {
70 r[id] = p;
71 r["gecode_" + id] = p;
72 r["fzn_" + id] = p;
73 }
74
75 namespace {
76
77 void p_distinct(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
78 IntVarArgs va = s.arg2intvarargs(ce[0]);
79 IntPropLevel ipl = s.ann2ipl(ann);
80 unshare(s, va);
81 distinct(s, va, ipl == IPL_DEF ? IPL_BND : ipl);
82 }
83
84 void p_distinctOffset(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
85 IntVarArgs va = s.arg2intvarargs(ce[1]);
86 unshare(s, va);
87 AST::Array* offs = ce.args->a[0]->getArray();
88 IntArgs oa(offs->a.size());
89 for (int i=offs->a.size(); i--; ) {
90 oa[i] = offs->a[i]->getInt();
91 }
92 IntPropLevel ipl = s.ann2ipl(ann);
93 distinct(s, oa, va, ipl == IPL_DEF ? IPL_BND : ipl);
94 }
95
96 void p_all_equal(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
97 IntVarArgs va = s.arg2intvarargs(ce[0]);
98 rel(s, va, IRT_EQ, s.ann2ipl(ann));
99 }
100
101 void p_int_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
102 AST::Node* ann) {
103 if (ce[0]->isIntVar()) {
104 if (ce[1]->isIntVar()) {
105 rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
106 s.ann2ipl(ann));
107 } else {
108 rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(), s.ann2ipl(ann));
109 }
110 } else {
111 rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
112 s.ann2ipl(ann));
113 }
114 }
115 void p_int_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
116 p_int_CMP(s, IRT_EQ, ce, ann);
117 }
118 void p_int_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
119 p_int_CMP(s, IRT_NQ, ce, ann);
120 }
121 void p_int_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
122 p_int_CMP(s, IRT_GQ, ce, ann);
123 }
124 void p_int_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
125 p_int_CMP(s, IRT_GR, ce, ann);
126 }
127 void p_int_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
128 p_int_CMP(s, IRT_LQ, ce, ann);
129 }
130 void p_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
131 p_int_CMP(s, IRT_LE, ce, ann);
132 }
133 void p_int_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
134 const ConExpr& ce, AST::Node* ann) {
135 if (rm == RM_EQV && ce[2]->isBool()) {
136 if (ce[2]->getBool()) {
137 p_int_CMP(s, irt, ce, ann);
138 } else {
139 p_int_CMP(s, neg(irt), ce, ann);
140 }
141 return;
142 }
143 if (ce[0]->isIntVar()) {
144 if (ce[1]->isIntVar()) {
145 rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
146 Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
147 } else {
148 rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(),
149 Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
150 }
151 } else {
152 rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
153 Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
154 }
155 }
156
157 /* Comparisons */
158 void p_int_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
159 p_int_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
160 }
161 void p_int_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
162 p_int_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
163 }
164 void p_int_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
165 p_int_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
166 }
167 void p_int_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
168 p_int_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
169 }
170 void p_int_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
171 p_int_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
172 }
173 void p_int_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
174 p_int_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
175 }
176
177 void p_int_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
178 p_int_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
179 }
180 void p_int_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
181 p_int_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
182 }
183 void p_int_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
184 p_int_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
185 }
186 void p_int_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
187 p_int_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
188 }
189 void p_int_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
190 p_int_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
191 }
192 void p_int_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
193 p_int_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
194 }
195
196 /* linear (in-)equations */
197 void p_int_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
198 AST::Node* ann) {
199 IntArgs ia = s.arg2intargs(ce[0]);
200 int singleIntVar;
201 if (s.isBoolArray(ce[1],singleIntVar)) {
202 if (singleIntVar != -1) {
203 if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
204 IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
205 BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
206 IntArgs ia_tmp(ia.size()-1);
207 int count = 0;
208 for (int i=0; i<ia.size(); i++) {
209 if (i != singleIntVar)
210 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
211 }
212 IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
213 linear(s, ia_tmp, iv, t, siv, s.ann2ipl(ann));
214 } else {
215 IntVarArgs iv = s.arg2intvarargs(ce[1]);
216 linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
217 }
218 } else {
219 BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
220 linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
221 }
222 } else {
223 IntVarArgs iv = s.arg2intvarargs(ce[1]);
224 linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
225 }
226 }
227 void p_int_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
228 const ConExpr& ce, AST::Node* ann) {
229 if (rm == RM_EQV && ce[2]->isBool()) {
230 if (ce[2]->getBool()) {
231 p_int_lin_CMP(s, irt, ce, ann);
232 } else {
233 p_int_lin_CMP(s, neg(irt), ce, ann);
234 }
235 return;
236 }
237 IntArgs ia = s.arg2intargs(ce[0]);
238 int singleIntVar;
239 if (s.isBoolArray(ce[1],singleIntVar)) {
240 if (singleIntVar != -1) {
241 if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
242 IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
243 BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
244 IntArgs ia_tmp(ia.size()-1);
245 int count = 0;
246 for (int i=0; i<ia.size(); i++) {
247 if (i != singleIntVar)
248 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
249 }
250 IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
251 linear(s, ia_tmp, iv, t, siv, Reify(s.arg2BoolVar(ce[3]), rm),
252 s.ann2ipl(ann));
253 } else {
254 IntVarArgs iv = s.arg2intvarargs(ce[1]);
255 linear(s, ia, iv, irt, ce[2]->getInt(),
256 Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
257 }
258 } else {
259 BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
260 linear(s, ia, iv, irt, ce[2]->getInt(),
261 Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
262 }
263 } else {
264 IntVarArgs iv = s.arg2intvarargs(ce[1]);
265 linear(s, ia, iv, irt, ce[2]->getInt(),
266 Reify(s.arg2BoolVar(ce[3]), rm),
267 s.ann2ipl(ann));
268 }
269 }
270 void p_int_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
271 p_int_lin_CMP(s, IRT_EQ, ce, ann);
272 }
273 void p_int_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
274 p_int_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
275 }
276 void p_int_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
277 p_int_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
278 }
279 void p_int_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
280 p_int_lin_CMP(s, IRT_NQ, ce, ann);
281 }
282 void p_int_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
283 p_int_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
284 }
285 void p_int_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
286 p_int_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
287 }
288 void p_int_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
289 p_int_lin_CMP(s, IRT_LQ, ce, ann);
290 }
291 void p_int_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
292 p_int_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
293 }
294 void p_int_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
295 p_int_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
296 }
297 void p_int_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
298 p_int_lin_CMP(s, IRT_LE, ce, ann);
299 }
300 void p_int_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
301 p_int_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
302 }
303 void p_int_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
304 p_int_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
305 }
306 void p_int_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
307 p_int_lin_CMP(s, IRT_GQ, ce, ann);
308 }
309 void p_int_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
310 p_int_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
311 }
312 void p_int_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
313 p_int_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
314 }
315 void p_int_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
316 p_int_lin_CMP(s, IRT_GR, ce, ann);
317 }
318 void p_int_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
319 p_int_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
320 }
321 void p_int_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
322 p_int_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
323 }
324
325 void p_bool_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
326 AST::Node* ann) {
327 IntArgs ia = s.arg2intargs(ce[0]);
328 BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
329 if (ce[2]->isIntVar())
330 linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], s.ann2ipl(ann));
331 else
332 linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
333 }
334 void p_bool_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
335 const ConExpr& ce, AST::Node* ann) {
336 if (rm == RM_EQV && ce[2]->isBool()) {
337 if (ce[2]->getBool()) {
338 p_bool_lin_CMP(s, irt, ce, ann);
339 } else {
340 p_bool_lin_CMP(s, neg(irt), ce, ann);
341 }
342 return;
343 }
344 IntArgs ia = s.arg2intargs(ce[0]);
345 BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
346 if (ce[2]->isIntVar())
347 linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()],
348 Reify(s.arg2BoolVar(ce[3]), rm),
349 s.ann2ipl(ann));
350 else
351 linear(s, ia, iv, irt, ce[2]->getInt(),
352 Reify(s.arg2BoolVar(ce[3]), rm),
353 s.ann2ipl(ann));
354 }
355 void p_bool_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
356 p_bool_lin_CMP(s, IRT_EQ, ce, ann);
357 }
358 void p_bool_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
359 {
360 p_bool_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
361 }
362 void p_bool_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
363 {
364 p_bool_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
365 }
366 void p_bool_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
367 p_bool_lin_CMP(s, IRT_NQ, ce, ann);
368 }
369 void p_bool_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
370 {
371 p_bool_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
372 }
373 void p_bool_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
374 {
375 p_bool_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
376 }
377 void p_bool_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
378 p_bool_lin_CMP(s, IRT_LQ, ce, ann);
379 }
380 void p_bool_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
381 {
382 p_bool_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
383 }
384 void p_bool_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
385 {
386 p_bool_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
387 }
388 void p_bool_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
389 {
390 p_bool_lin_CMP(s, IRT_LE, ce, ann);
391 }
392 void p_bool_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
393 {
394 p_bool_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
395 }
396 void p_bool_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
397 {
398 p_bool_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
399 }
400 void p_bool_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
401 p_bool_lin_CMP(s, IRT_GQ, ce, ann);
402 }
403 void p_bool_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
404 {
405 p_bool_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
406 }
407 void p_bool_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
408 {
409 p_bool_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
410 }
411 void p_bool_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
412 p_bool_lin_CMP(s, IRT_GR, ce, ann);
413 }
414 void p_bool_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
415 {
416 p_bool_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
417 }
418 void p_bool_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
419 {
420 p_bool_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
421 }
422
423 /* arithmetic constraints */
424
425 void p_int_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
426 if (!ce[0]->isIntVar()) {
427 rel(s, ce[0]->getInt() + s.arg2IntVar(ce[1])
428 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
429 } else if (!ce[1]->isIntVar()) {
430 rel(s, s.arg2IntVar(ce[0]) + ce[1]->getInt()
431 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
432 } else if (!ce[2]->isIntVar()) {
433 rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
434 == ce[2]->getInt(), s.ann2ipl(ann));
435 } else {
436 rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
437 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
438 }
439 }
440
441 void p_int_minus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
442 if (!ce[0]->isIntVar()) {
443 rel(s, ce[0]->getInt() - s.arg2IntVar(ce[1])
444 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
445 } else if (!ce[1]->isIntVar()) {
446 rel(s, s.arg2IntVar(ce[0]) - ce[1]->getInt()
447 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
448 } else if (!ce[2]->isIntVar()) {
449 rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
450 == ce[2]->getInt(), s.ann2ipl(ann));
451 } else {
452 rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
453 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
454 }
455 }
456
457 void p_int_times(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
458 IntVar x0 = s.arg2IntVar(ce[0]);
459 IntVar x1 = s.arg2IntVar(ce[1]);
460 IntVar x2 = s.arg2IntVar(ce[2]);
461 mult(s, x0, x1, x2, s.ann2ipl(ann));
462 }
463 void p_int_pow(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
464 IntVar x0 = s.arg2IntVar(ce[0]);
465 IntVar x2 = s.arg2IntVar(ce[2]);
466 pow(s, x0, ce[1]->getInt(), x2, s.ann2ipl(ann));
467 }
468 void p_int_div(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
469 IntVar x0 = s.arg2IntVar(ce[0]);
470 IntVar x1 = s.arg2IntVar(ce[1]);
471 IntVar x2 = s.arg2IntVar(ce[2]);
472 div(s,x0,x1,x2, s.ann2ipl(ann));
473 }
474 void p_int_mod(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
475 IntVar x0 = s.arg2IntVar(ce[0]);
476 IntVar x1 = s.arg2IntVar(ce[1]);
477 IntVar x2 = s.arg2IntVar(ce[2]);
478 mod(s,x0,x1,x2, s.ann2ipl(ann));
479 }
480
481 void p_int_min(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
482 IntVar x0 = s.arg2IntVar(ce[0]);
483 IntVar x1 = s.arg2IntVar(ce[1]);
484 IntVar x2 = s.arg2IntVar(ce[2]);
485 min(s, x0, x1, x2, s.ann2ipl(ann));
486 }
487 void p_int_max(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
488 IntVar x0 = s.arg2IntVar(ce[0]);
489 IntVar x1 = s.arg2IntVar(ce[1]);
490 IntVar x2 = s.arg2IntVar(ce[2]);
491 max(s, x0, x1, x2, s.ann2ipl(ann));
492 }
493 void p_int_negate(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
494 IntVar x0 = s.arg2IntVar(ce[0]);
495 IntVar x1 = s.arg2IntVar(ce[1]);
496 rel(s, x0 == -x1, s.ann2ipl(ann));
497 }
498
499 /* Boolean constraints */
500 void p_bool_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
501 AST::Node* ann) {
502 rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
503 s.ann2ipl(ann));
504 }
505 void p_bool_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
506 const ConExpr& ce, AST::Node* ann) {
507 rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
508 Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
509 }
510 void p_bool_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
511 p_bool_CMP(s, IRT_EQ, ce, ann);
512 }
513 void p_bool_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
514 p_bool_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
515 }
516 void p_bool_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
517 p_bool_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
518 }
519 void p_bool_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
520 p_bool_CMP(s, IRT_NQ, ce, ann);
521 }
522 void p_bool_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
523 p_bool_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
524 }
525 void p_bool_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
526 p_bool_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
527 }
528 void p_bool_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
529 p_bool_CMP(s, IRT_GQ, ce, ann);
530 }
531 void p_bool_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
532 p_bool_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
533 }
534 void p_bool_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
535 p_bool_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
536 }
537 void p_bool_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
538 p_bool_CMP(s, IRT_LQ, ce, ann);
539 }
540 void p_bool_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
541 p_bool_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
542 }
543 void p_bool_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
544 p_bool_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
545 }
546 void p_bool_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
547 p_bool_CMP(s, IRT_GR, ce, ann);
548 }
549 void p_bool_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
550 p_bool_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
551 }
552 void p_bool_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
553 p_bool_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
554 }
555 void p_bool_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
556 p_bool_CMP(s, IRT_LE, ce, ann);
557 }
558 void p_bool_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
559 p_bool_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
560 }
561 void p_bool_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
562 p_bool_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
563 }
564
565#define BOOL_OP(op) \
566 BoolVar b0 = s.arg2BoolVar(ce[0]); \
567 BoolVar b1 = s.arg2BoolVar(ce[1]); \
568 if (ce[2]->isBool()) { \
569 rel(s, b0, op, b1, ce[2]->getBool(), s.ann2ipl(ann)); \
570 } else { \
571 rel(s, b0, op, b1, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann)); \
572 }
573
574#define BOOL_ARRAY_OP(op) \
575 BoolVarArgs bv = s.arg2boolvarargs(ce[0]); \
576 if (ce.size()==1) { \
577 rel(s, op, bv, 1, s.ann2ipl(ann)); \
578 } else if (ce[1]->isBool()) { \
579 rel(s, op, bv, ce[1]->getBool(), s.ann2ipl(ann)); \
580 } else { \
581 rel(s, op, bv, s.bv[ce[1]->getBoolVar()], s.ann2ipl(ann)); \
582 }
583
584 void p_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
585 BOOL_OP(BOT_OR);
586 }
587 void p_bool_or_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
588 BoolVar b0 = s.arg2BoolVar(ce[0]);
589 BoolVar b1 = s.arg2BoolVar(ce[1]);
590 BoolVar b2 = s.arg2BoolVar(ce[2]);
591 clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
592 s.ann2ipl(ann));
593 }
594 void p_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
595 BOOL_OP(BOT_AND);
596 }
597 void p_bool_and_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
598 BoolVar b0 = s.arg2BoolVar(ce[0]);
599 BoolVar b1 = s.arg2BoolVar(ce[1]);
600 BoolVar b2 = s.arg2BoolVar(ce[2]);
601 rel(s, b2, BOT_IMP, b0, 1, s.ann2ipl(ann));
602 rel(s, b2, BOT_IMP, b1, 1, s.ann2ipl(ann));
603 }
604 void p_array_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
605 {
606 BOOL_ARRAY_OP(BOT_AND);
607 }
608 void p_array_bool_and_imp(FlatZincSpace& s, const ConExpr& ce,
609 AST::Node* ann)
610 {
611 BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
612 BoolVar b1 = s.arg2BoolVar(ce[1]);
613 for (unsigned int i=bv.size(); i--;)
614 rel(s, b1, BOT_IMP, bv[i], 1, s.ann2ipl(ann));
615 }
616 void p_array_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
617 {
618 BOOL_ARRAY_OP(BOT_OR);
619 }
620 void p_array_bool_or_imp(FlatZincSpace& s, const ConExpr& ce,
621 AST::Node* ann)
622 {
623 BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
624 BoolVar b1 = s.arg2BoolVar(ce[1]);
625 clause(s, BOT_OR, bv, BoolVarArgs()<<b1, 1, s.ann2ipl(ann));
626 }
627 void p_array_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
628 {
629 BOOL_ARRAY_OP(BOT_XOR);
630 }
631 void p_array_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce,
632 AST::Node* ann)
633 {
634 BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
635 BoolVar tmp(s,0,1);
636 rel(s, BOT_XOR, bv, tmp, s.ann2ipl(ann));
637 rel(s, s.arg2BoolVar(ce[1]), BOT_IMP, tmp, 1);
638 }
639 void p_array_bool_clause(FlatZincSpace& s, const ConExpr& ce,
640 AST::Node* ann) {
641 BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
642 BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
643 clause(s, BOT_OR, bvp, bvn, 1, s.ann2ipl(ann));
644 }
645 void p_array_bool_clause_reif(FlatZincSpace& s, const ConExpr& ce,
646 AST::Node* ann) {
647 BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
648 BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
649 BoolVar b0 = s.arg2BoolVar(ce[2]);
650 clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
651 }
652 void p_array_bool_clause_imp(FlatZincSpace& s, const ConExpr& ce,
653 AST::Node* ann) {
654 BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
655 BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
656 BoolVar b0 = s.arg2BoolVar(ce[2]);
657 clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
658 }
659 void p_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
660 BOOL_OP(BOT_XOR);
661 }
662 void p_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
663 BoolVar b0 = s.arg2BoolVar(ce[0]);
664 BoolVar b1 = s.arg2BoolVar(ce[1]);
665 BoolVar b2 = s.arg2BoolVar(ce[2]);
666 clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
667 s.ann2ipl(ann));
668 clause(s, BOT_OR, BoolVarArgs(), BoolVarArgs()<<b0<<b1<<b2, 1,
669 s.ann2ipl(ann));
670 }
671 void p_bool_l_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
672 BoolVar b0 = s.arg2BoolVar(ce[0]);
673 BoolVar b1 = s.arg2BoolVar(ce[1]);
674 if (ce[2]->isBool()) {
675 rel(s, b1, BOT_IMP, b0, ce[2]->getBool(), s.ann2ipl(ann));
676 } else {
677 rel(s, b1, BOT_IMP, b0, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann));
678 }
679 }
680 void p_bool_r_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
681 BOOL_OP(BOT_IMP);
682 }
683 void p_bool_not(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
684 BoolVar x0 = s.arg2BoolVar(ce[0]);
685 BoolVar x1 = s.arg2BoolVar(ce[1]);
686 rel(s, x0, BOT_XOR, x1, 1, s.ann2ipl(ann));
687 }
688
689 /* element constraints */
690 void p_array_int_element(FlatZincSpace& s, const ConExpr& ce,
691 AST::Node* ann) {
692 bool isConstant = true;
693 AST::Array* a = ce[1]->getArray();
694 for (int i=a->a.size(); i--;) {
695 if (!a->a[i]->isInt()) {
696 isConstant = false;
697 break;
698 }
699 }
700 IntVar selector = s.arg2IntVar(ce[0]);
701 rel(s, selector > 0);
702 if (isConstant) {
703 IntSharedArray sia = s.arg2intsharedarray(ce[1]);
704 element(s, sia, selector, -1, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
705 } else {
706 IntVarArgs iv = s.arg2intvarargs(ce[1]);
707 element(s, iv, selector, -1, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
708 }
709 }
710 void p_array_int_element_offset(FlatZincSpace& s, const ConExpr& ce,
711 AST::Node* ann) {
712 bool isConstant = true;
713 AST::Array* a = ce[2]->getArray();
714 for (int i=a->a.size(); i--;) {
715 if (!a->a[i]->isInt()) {
716 isConstant = false;
717 break;
718 }
719 }
720 IntVar selector = s.arg2IntVar(ce[0]);
721 int offset = ce[1]->getInt();
722 rel(s, selector >= offset);
723 if (isConstant) {
724 IntSharedArray sia = s.arg2intsharedarray(ce[2]);
725 element(s, sia, selector, -offset, s.arg2IntVar(ce[3]), s.ann2ipl(ann));
726 } else {
727 IntVarArgs iv = s.arg2intvarargs(ce[2]);
728 element(s, iv, selector, -offset, s.arg2IntVar(ce[3]), s.ann2ipl(ann));
729 }
730 }
731 void p_array_int_element2d(FlatZincSpace& s, const ConExpr& ce,
732 AST::Node* ann) {
733 bool isConstant = true;
734 AST::Array* a = ce[2]->getArray();
735 for (int i=a->a.size(); i--;) {
736 if (!a->a[i]->isInt()) {
737 isConstant = false;
738 break;
739 }
740 }
741 IntVar selector0 = s.arg2IntVar(ce[0]);
742 IntVar selector1 = s.arg2IntVar(ce[1]);
743 IntSet idxset0 = s.arg2intset(ce[3]);
744 IntSet idxset1 = s.arg2intset(ce[4]);
745
746 int w = idxset1.size();
747 int s1off = idxset1.min();
748 int h = idxset0.size();
749 int s0off = idxset0.min();
750
751 if (isConstant) {
752 IntSharedArray sia = s.arg2intsharedarray(ce[2], 0);
753 element(s, sia, selector1, -s1off, w, selector0, -s0off, h, s.arg2IntVar(ce[5]), s.ann2ipl(ann));
754 } else {
755 IntVarArgs iv = s.arg2intvarargs(ce[2], 0);
756 element(s, iv, selector1, -s1off, w, selector0, -s0off, h, s.arg2IntVar(ce[5]), s.ann2ipl(ann));
757 }
758 }
759 void p_array_bool_element(FlatZincSpace& s, const ConExpr& ce,
760 AST::Node* ann) {
761 bool isConstant = true;
762 AST::Array* a = ce[1]->getArray();
763 for (int i=a->a.size(); i--;) {
764 if (!a->a[i]->isBool()) {
765 isConstant = false;
766 break;
767 }
768 }
769 IntVar selector = s.arg2IntVar(ce[0]);
770 rel(s, selector > 0);
771 if (isConstant) {
772 IntSharedArray sia = s.arg2boolsharedarray(ce[1], 1);
773 element(s, sia, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
774 } else {
775 BoolVarArgs iv = s.arg2boolvarargs(ce[1], 1);
776 element(s, iv, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
777 }
778 }
779 void p_array_bool_element_offset(FlatZincSpace& s, const ConExpr& ce,
780 AST::Node* ann) {
781 bool isConstant = true;
782 AST::Array* a = ce[2]->getArray();
783 for (int i=a->a.size(); i--;) {
784 if (!a->a[i]->isBool()) {
785 isConstant = false;
786 break;
787 }
788 }
789 IntVar selector = s.arg2IntVar(ce[0]);
790 int offset = ce[1]->getInt();
791 rel(s, selector >= offset);
792 if (isConstant) {
793 IntSharedArray sia = s.arg2boolsharedarray(ce[2]);
794 element(s, sia, selector, -offset, s.arg2BoolVar(ce[3]), s.ann2ipl(ann));
795 } else {
796 BoolVarArgs iv = s.arg2boolvarargs(ce[2]);
797 element(s, iv, selector, -offset, s.arg2BoolVar(ce[3]), s.ann2ipl(ann));
798 }
799 }
800 void p_array_bool_element2d(FlatZincSpace& s, const ConExpr& ce,
801 AST::Node* ann) {
802 bool isConstant = true;
803 AST::Array* a = ce[2]->getArray();
804 for (int i=a->a.size(); i--;) {
805 if (!a->a[i]->isBool()) {
806 isConstant = false;
807 break;
808 }
809 }
810 IntVar selector0 = s.arg2IntVar(ce[0]);
811 IntVar selector1 = s.arg2IntVar(ce[1]);
812 IntSet idxset0 = s.arg2intset(ce[3]);
813 IntSet idxset1 = s.arg2intset(ce[4]);
814
815 int w = idxset1.size();
816 int s1off = idxset1.min();
817 int h = idxset0.size();
818 int s0off = idxset0.min();
819
820 if (isConstant) {
821 IntSharedArray sia = s.arg2boolsharedarray(ce[2], 0);
822 element(s, sia, selector1, -s1off, w, selector0, -s0off, h, s.arg2BoolVar(ce[5]), s.ann2ipl(ann));
823 } else {
824 BoolVarArgs iv = s.arg2boolvarargs(ce[2], 0);
825 element(s, iv, selector1, -s1off, w, selector0, -s0off, h, s.arg2BoolVar(ce[5]), s.ann2ipl(ann));
826 }
827 }
828
829 /* coercion constraints */
830 void p_bool2int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
831 BoolVar x0 = s.arg2BoolVar(ce[0]);
832 IntVar x1 = s.arg2IntVar(ce[1]);
833 if (ce[0]->isBoolVar() && ce[1]->isIntVar()) {
834 s.aliasBool2Int(ce[1]->getIntVar(), ce[0]->getBoolVar());
835 }
836 channel(s, x0, x1, s.ann2ipl(ann));
837 }
838
839 void p_int_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
840 IntSet d = s.arg2intset(ce[1]);
841 if (ce[0]->isBoolVar()) {
842 IntSetRanges dr(d);
843 Iter::Ranges::Singleton sr(0,1);
844 Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
845 IntSet d01(i);
846 if (d01.size() == 0) {
847 s.fail();
848 } else {
849 rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
850 rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
851 }
852 } else {
853 dom(s, s.arg2IntVar(ce[0]), d);
854 }
855 }
856 void p_int_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
857 IntSet d = s.arg2intset(ce[1]);
858 if (ce[0]->isBoolVar()) {
859 IntSetRanges dr(d);
860 Iter::Ranges::Singleton sr(0,1);
861 Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
862 IntSet d01(i);
863 if (d01.size() == 0) {
864 rel(s, s.arg2BoolVar(ce[2]) == 0);
865 } else if (d01.max() == 0) {
866 rel(s, s.arg2BoolVar(ce[2]) == !s.arg2BoolVar(ce[0]));
867 } else if (d01.min() == 1) {
868 rel(s, s.arg2BoolVar(ce[2]) == s.arg2BoolVar(ce[0]));
869 } else {
870 rel(s, s.arg2BoolVar(ce[2]) == 1);
871 }
872 } else {
873 dom(s, s.arg2IntVar(ce[0]), d, s.arg2BoolVar(ce[2]));
874 }
875 }
876 void p_int_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
877 IntSet d = s.arg2intset(ce[1]);
878 if (ce[0]->isBoolVar()) {
879 IntSetRanges dr(d);
880 Iter::Ranges::Singleton sr(0,1);
881 Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
882 IntSet d01(i);
883 if (d01.size() == 0) {
884 rel(s, s.arg2BoolVar(ce[2]) == 0);
885 } else if (d01.max() == 0) {
886 rel(s, s.arg2BoolVar(ce[2]) >> !s.arg2BoolVar(ce[0]));
887 } else if (d01.min() == 1) {
888 rel(s, s.arg2BoolVar(ce[2]) >> s.arg2BoolVar(ce[0]));
889 }
890 } else {
891 dom(s, s.arg2IntVar(ce[0]), d, Reify(s.arg2BoolVar(ce[2]),RM_IMP));
892 }
893 }
894
895 /* constraints from the standard library */
896
897 void p_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
898 IntVar x0 = s.arg2IntVar(ce[0]);
899 IntVar x1 = s.arg2IntVar(ce[1]);
900 abs(s, x0, x1, s.ann2ipl(ann));
901 }
902
903 void p_array_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
904 IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
905 IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
906 rel(s, iv0, IRT_LE, iv1, s.ann2ipl(ann));
907 }
908
909 void p_array_int_lq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
910 IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
911 IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
912 rel(s, iv0, IRT_LQ, iv1, s.ann2ipl(ann));
913 }
914
915 void p_array_bool_lt(FlatZincSpace& s, const ConExpr& ce,
916 AST::Node* ann) {
917 BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
918 BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
919 rel(s, bv0, IRT_LE, bv1, s.ann2ipl(ann));
920 }
921
922 void p_array_bool_lq(FlatZincSpace& s, const ConExpr& ce,
923 AST::Node* ann) {
924 BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
925 BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
926 rel(s, bv0, IRT_LQ, bv1, s.ann2ipl(ann));
927 }
928
929 void p_count(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
930 IntVarArgs iv = s.arg2intvarargs(ce[0]);
931 if (!ce[1]->isIntVar()) {
932 if (!ce[2]->isIntVar()) {
933 count(s, iv, ce[1]->getInt(), IRT_EQ, ce[2]->getInt(),
934 s.ann2ipl(ann));
935 } else {
936 count(s, iv, ce[1]->getInt(), IRT_EQ, s.arg2IntVar(ce[2]),
937 s.ann2ipl(ann));
938 }
939 } else if (!ce[2]->isIntVar()) {
940 count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, ce[2]->getInt(),
941 s.ann2ipl(ann));
942 } else {
943 count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, s.arg2IntVar(ce[2]),
944 s.ann2ipl(ann));
945 }
946 }
947
948 void p_count_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
949 IntVarArgs iv = s.arg2intvarargs(ce[0]);
950 IntVar x = s.arg2IntVar(ce[1]);
951 IntVar y = s.arg2IntVar(ce[2]);
952 BoolVar b = s.arg2BoolVar(ce[3]);
953 IntVar c(s,0,Int::Limits::max);
954 count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
955 rel(s, b == (c==y));
956 }
957 void p_count_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
958 IntVarArgs iv = s.arg2intvarargs(ce[0]);
959 IntVar x = s.arg2IntVar(ce[1]);
960 IntVar y = s.arg2IntVar(ce[2]);
961 BoolVar b = s.arg2BoolVar(ce[3]);
962 IntVar c(s,0,Int::Limits::max);
963 count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
964 rel(s, b >> (c==y));
965 }
966
967 void count_rel(IntRelType irt,
968 FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
969 IntVarArgs iv = s.arg2intvarargs(ce[1]);
970 count(s, iv, ce[2]->getInt(), irt, ce[0]->getInt(), s.ann2ipl(ann));
971 }
972
973 void p_at_most(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
974 count_rel(IRT_LQ, s, ce, ann);
975 }
976
977 void p_at_least(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
978 count_rel(IRT_GQ, s, ce, ann);
979 }
980
981 void p_bin_packing_load(FlatZincSpace& s, const ConExpr& ce,
982 AST::Node* ann) {
983 int minIdx = ce[3]->getInt();
984 IntVarArgs load = s.arg2intvarargs(ce[0]);
985 IntVarArgs l;
986 IntVarArgs bin = s.arg2intvarargs(ce[1]);
987 for (int i=bin.size(); i--;)
988 rel(s, bin[i] >= minIdx);
989 if (minIdx > 0) {
990 for (int i=minIdx; i--;)
991 l << IntVar(s,0,0);
992 } else if (minIdx < 0) {
993 IntVarArgs bin2(bin.size());
994 for (int i=bin.size(); i--;)
995 bin2[i] = expr(s, bin[i]-minIdx, s.ann2ipl(ann));
996 bin = bin2;
997 }
998 l << load;
999 IntArgs sizes = s.arg2intargs(ce[2]);
1000
1001 IntVarArgs allvars = l + bin;
1002 unshare(s, allvars);
1003 binpacking(s, allvars.slice(0,1,l.size()), allvars.slice(l.size(),1,bin.size()),
1004 sizes, s.ann2ipl(ann));
1005 }
1006
1007 void p_global_cardinality(FlatZincSpace& s, const ConExpr& ce,
1008 AST::Node* ann) {
1009 IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
1010 IntArgs cover = s.arg2intargs(ce[1]);
1011 IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
1012
1013 Region re;
1014 IntSet cover_s(cover);
1015 IntSetRanges cover_r(cover_s);
1016 IntVarRanges* iv0_ri = re.alloc<IntVarRanges>(iv0.size());
1017 for (int i=iv0.size(); i--;)
1018 iv0_ri[i] = IntVarRanges(iv0[i]);
1019 Iter::Ranges::NaryUnion iv0_r(re,iv0_ri,iv0.size());
1020 Iter::Ranges::Diff<Iter::Ranges::NaryUnion,IntSetRanges>
1021 extra_r(iv0_r,cover_r);
1022 Iter::Ranges::ToValues<Iter::Ranges::Diff<
1023 Iter::Ranges::NaryUnion,IntSetRanges> > extra(extra_r);
1024 for (; extra(); ++extra) {
1025 cover << extra.val();
1026 iv1 << IntVar(s,0,iv0.size());
1027 }
1028 IntPropLevel ipl = s.ann2ipl(ann);
1029 if (ipl==IPL_DEF)
1030 ipl=IPL_BND;
1031 if (ipl==IPL_DOM) {
1032 IntVarArgs allvars = iv0+iv1;
1033 unshare(s, allvars);
1034 count(s, allvars.slice(0,1,iv0.size()),
1035 allvars.slice(iv0.size(),1,iv1.size()),
1036 cover, ipl);
1037 } else {
1038 unshare(s, iv0);
1039 count(s, iv0, iv1, cover, ipl);
1040 }
1041 }
1042
1043 void p_global_cardinality_closed(FlatZincSpace& s, const ConExpr& ce,
1044 AST::Node* ann) {
1045 IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
1046 IntArgs cover = s.arg2intargs(ce[1]);
1047 IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
1048 IntPropLevel ipl = s.ann2ipl(ann);
1049 if (ipl==IPL_DEF)
1050 ipl=IPL_BND;
1051 if (ipl==IPL_DOM) {
1052 IntVarArgs allvars = iv0+iv1;
1053 unshare(s, allvars);
1054 count(s, allvars.slice(0,1,iv0.size()),
1055 allvars.slice(iv0.size(),1,iv1.size()),
1056 cover, ipl);
1057 } else {
1058 unshare(s, iv0);
1059 count(s, iv0, iv1, cover, ipl);
1060 }
1061 }
1062
1063 void p_global_cardinality_low_up(FlatZincSpace& s, const ConExpr& ce,
1064 AST::Node* ann) {
1065 IntVarArgs x = s.arg2intvarargs(ce[0]);
1066 IntArgs cover = s.arg2intargs(ce[1]);
1067
1068 IntArgs lbound = s.arg2intargs(ce[2]);
1069 IntArgs ubound = s.arg2intargs(ce[3]);
1070 IntSetArgs y(cover.size());
1071 for (int i=cover.size(); i--;)
1072 y[i] = IntSet(lbound[i],ubound[i]);
1073
1074 IntSet cover_s(cover);
1075 Region re;
1076 IntVarRanges* xrs = re.alloc<IntVarRanges>(x.size());
1077 for (int i=x.size(); i--;)
1078 xrs[i].init(x[i]);
1079 Iter::Ranges::NaryUnion u(re, xrs, x.size());
1080 Iter::Ranges::ToValues<Iter::Ranges::NaryUnion> uv(u);
1081 for (; uv(); ++uv) {
1082 if (!cover_s.in(uv.val())) {
1083 cover << uv.val();
1084 y << IntSet(0,x.size());
1085 }
1086 }
1087 unshare(s, x);
1088 IntPropLevel ipl = s.ann2ipl(ann);
1089 if (ipl==IPL_DEF)
1090 ipl=IPL_BND;
1091 count(s, x, y, cover, ipl);
1092 }
1093
1094 void p_global_cardinality_low_up_closed(FlatZincSpace& s,
1095 const ConExpr& ce,
1096 AST::Node* ann) {
1097 IntVarArgs x = s.arg2intvarargs(ce[0]);
1098 IntArgs cover = s.arg2intargs(ce[1]);
1099
1100 IntArgs lbound = s.arg2intargs(ce[2]);
1101 IntArgs ubound = s.arg2intargs(ce[3]);
1102 IntSetArgs y(cover.size());
1103 for (int i=cover.size(); i--;)
1104 y[i] = IntSet(lbound[i],ubound[i]);
1105 unshare(s, x);
1106 IntPropLevel ipl = s.ann2ipl(ann);
1107 if (ipl==IPL_DEF)
1108 ipl=IPL_BND;
1109 count(s, x, y, cover, ipl);
1110 }
1111
1112 void p_minimum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1113 IntVarArgs iv = s.arg2intvarargs(ce[1]);
1114 min(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
1115 }
1116
1117 void p_maximum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1118 IntVarArgs iv = s.arg2intvarargs(ce[1]);
1119 max(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
1120 }
1121
1122 void p_minimum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1123 IntVarArgs iv = s.arg2intvarargs(ce[0]);
1124 int offset = ce[1]->getInt();
1125 argmin(s, iv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
1126 }
1127
1128 void p_maximum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1129 IntVarArgs iv = s.arg2intvarargs(ce[0]);
1130 int offset = ce[1]->getInt();
1131 argmax(s, iv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
1132 }
1133
1134 void p_minimum_arg_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1135 BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
1136 int offset = ce[1]->getInt();
1137 argmin(s, bv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
1138 }
1139
1140 void p_maximum_arg_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1141 BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
1142 int offset = ce[1]->getInt();
1143 argmax(s, bv, offset, s.arg2IntVar(ce[2]), true, s.ann2ipl(ann));
1144 }
1145
1146 void p_regular(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1147 IntVarArgs iv = s.arg2intvarargs(ce[0]);
1148 int q = ce[1]->getInt();
1149 int symbols = ce[2]->getInt();
1150 IntArgs d = s.arg2intargs(ce[3]);
1151 int q0 = ce[4]->getInt();
1152
1153 int noOfTrans = 0;
1154 for (int i=1; i<=q; i++) {
1155 for (int j=1; j<=symbols; j++) {
1156 if (d[(i-1)*symbols+(j-1)] > 0)
1157 noOfTrans++;
1158 }
1159 }
1160
1161 Region re;
1162 DFA::Transition* t = re.alloc<DFA::Transition>(noOfTrans+1);
1163 noOfTrans = 0;
1164 for (int i=1; i<=q; i++) {
1165 for (int j=1; j<=symbols; j++) {
1166 if (d[(i-1)*symbols+(j-1)] > 0) {
1167 t[noOfTrans].i_state = i;
1168 t[noOfTrans].symbol = j;
1169 t[noOfTrans].o_state = d[(i-1)*symbols+(j-1)];
1170 noOfTrans++;
1171 }
1172 }
1173 }
1174 t[noOfTrans].i_state = -1;
1175
1176 // Final states
1177 AST::SetLit* sl = ce[5]->getSet();
1178 int* f;
1179 if (sl->interval) {
1180 f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->max-sl->min+2)));
1181 for (int i=sl->min; i<=sl->max; i++)
1182 f[i-sl->min] = i;
1183 f[sl->max-sl->min+1] = -1;
1184 } else {
1185 f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->s.size()+1)));
1186 for (int j=sl->s.size(); j--; )
1187 f[j] = sl->s[j];
1188 f[sl->s.size()] = -1;
1189 }
1190
1191 DFA dfa(q0,t,f);
1192 free(f);
1193 unshare(s, iv);
1194 extensional(s, iv, s.getSharedDFA(dfa), s.ann2ipl(ann));
1195 }
1196
1197 void
1198 p_sort(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1199 IntVarArgs x = s.arg2intvarargs(ce[0]);
1200 IntVarArgs y = s.arg2intvarargs(ce[1]);
1201 IntVarArgs xy(x.size()+y.size());
1202 for (int i=x.size(); i--;)
1203 xy[i] = x[i];
1204 for (int i=y.size(); i--;)
1205 xy[i+x.size()] = y[i];
1206 unshare(s, xy);
1207 for (int i=x.size(); i--;)
1208 x[i] = xy[i];
1209 for (int i=y.size(); i--;)
1210 y[i] = xy[i+x.size()];
1211 sorted(s, x, y, s.ann2ipl(ann));
1212 }
1213
1214 void
1215 p_inverse_offsets(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1216 IntVarArgs x = s.arg2intvarargs(ce[0]);
1217 unshare(s, x);
1218 int xoff = ce[1]->getInt();
1219 IntVarArgs y = s.arg2intvarargs(ce[2]);
1220 unshare(s, y);
1221 int yoff = ce[3]->getInt();
1222 channel(s, x, xoff, y, yoff, s.ann2ipl(ann));
1223 }
1224
1225 void
1226 p_increasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1227 IntVarArgs x = s.arg2intvarargs(ce[0]);
1228 rel(s,x,IRT_LQ,s.ann2ipl(ann));
1229 }
1230
1231 void
1232 p_increasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1233 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1234 rel(s,x,IRT_LQ,s.ann2ipl(ann));
1235 }
1236
1237 void
1238 p_decreasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1239 IntVarArgs x = s.arg2intvarargs(ce[0]);
1240 rel(s,x,IRT_GQ,s.ann2ipl(ann));
1241 }
1242
1243 void
1244 p_decreasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1245 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1246 rel(s,x,IRT_GQ,s.ann2ipl(ann));
1247 }
1248
1249 void
1250 p_table_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1251 IntVarArgs x = s.arg2intvarargs(ce[0]);
1252 IntArgs tuples = s.arg2intargs(ce[1]);
1253 TupleSet ts = s.arg2tupleset(tuples,x.size());
1254 extensional(s,x,ts,s.ann2ipl(ann));
1255 }
1256
1257 void
1258 p_table_int_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1259 IntVarArgs x = s.arg2intvarargs(ce[0]);
1260 IntArgs tuples = s.arg2intargs(ce[1]);
1261 TupleSet ts = s.arg2tupleset(tuples,x.size());
1262 extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
1263 }
1264
1265 void
1266 p_table_int_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1267 IntVarArgs x = s.arg2intvarargs(ce[0]);
1268 IntArgs tuples = s.arg2intargs(ce[1]);
1269 TupleSet ts = s.arg2tupleset(tuples,x.size());
1270 extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
1271 }
1272
1273 void
1274 p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1275 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1276 IntArgs tuples = s.arg2boolargs(ce[1]);
1277 TupleSet ts = s.arg2tupleset(tuples,x.size());
1278 extensional(s,x,ts,s.ann2ipl(ann));
1279 }
1280
1281 void
1282 p_table_bool_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1283 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1284 IntArgs tuples = s.arg2boolargs(ce[1]);
1285 TupleSet ts = s.arg2tupleset(tuples,x.size());
1286 extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
1287 }
1288
1289 void
1290 p_table_bool_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1291 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1292 IntArgs tuples = s.arg2boolargs(ce[1]);
1293 TupleSet ts = s.arg2tupleset(tuples,x.size());
1294 extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
1295 }
1296
1297 void p_cumulative_opt(FlatZincSpace& s, const ConExpr& ce,
1298 AST::Node* ann) {
1299 IntVarArgs start = s.arg2intvarargs(ce[0]);
1300 IntArgs duration = s.arg2intargs(ce[1]);
1301 IntArgs height = s.arg2intargs(ce[2]);
1302 BoolVarArgs opt = s.arg2boolvarargs(ce[3]);
1303 int bound = ce[4]->getInt();
1304 unshare(s,start);
1305 cumulative(s,bound,start,duration,height,opt,s.ann2ipl(ann));
1306 }
1307
1308 void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
1309 AST::Node* ann) {
1310 IntVarArgs start = s.arg2intvarargs(ce[0]);
1311 IntVarArgs duration = s.arg2intvarargs(ce[1]);
1312 IntVarArgs height = s.arg2intvarargs(ce[2]);
1313 int n = start.size();
1314 IntVar bound = s.arg2IntVar(ce[3]);
1315
1316 if (n==0)
1317 return;
1318
1319 if (n == 1) {
1320 rel(s, height[0] <= bound);
1321 return;
1322 }
1323
1324 bool nonzeroDuration = true;
1325 for (int i=0; i<n; i++) {
1326 if (duration[i].min() <= 0) {
1327 nonzeroDuration = false;
1328 break;
1329 }
1330 }
1331
1332 int minHeight = std::min(height[0].min(),height[1].min());
1333 int minHeight2 = std::max(height[0].min(),height[1].min());
1334 for (int i=2; i<n; i++) {
1335 if (height[i].min() < minHeight) {
1336 minHeight2 = minHeight;
1337 minHeight = height[i].min();
1338 } else if (height[i].min() < minHeight2) {
1339 minHeight2 = height[i].min();
1340 }
1341 }
1342 bool disjunctive = nonzeroDuration && (
1343 (minHeight > bound.max()/2) ||
1344 (minHeight2 > bound.max()/2 && minHeight+minHeight2>bound.max()));
1345 if (disjunctive) {
1346 rel(s, bound >= max(height));
1347 // Unary
1348 if (duration.assigned()) {
1349 IntArgs durationI(n);
1350 for (int i=n; i--;)
1351 durationI[i] = duration[i].val();
1352 unshare(s,start);
1353 unary(s,start,durationI);
1354 } else {
1355 IntVarArgs end(n);
1356 for (int i=n; i--;)
1357 end[i] = expr(s,start[i]+duration[i]);
1358 unshare(s,start);
1359 unary(s,start,duration,end);
1360 }
1361 } else if (nonzeroDuration && height.assigned()) {
1362 IntArgs heightI(n);
1363 for (int i=n; i--;)
1364 heightI[i] = height[i].val();
1365 if (duration.assigned()) {
1366 IntArgs durationI(n);
1367 for (int i=n; i--;)
1368 durationI[i] = duration[i].val();
1369 cumulative(s, bound, start, durationI, heightI);
1370 } else {
1371 IntVarArgs end(n);
1372 for (int i = n; i--; )
1373 end[i] = expr(s,start[i]+duration[i]);
1374 cumulative(s, bound, start, duration, end, heightI);
1375 }
1376 } else if (nonzeroDuration && bound.assigned()) {
1377 IntArgs machine = IntArgs::create(n,0,0);
1378 IntArgs limit({bound.val()});
1379 IntVarArgs end(n);
1380 for (int i=n; i--;)
1381 end[i] = expr(s,start[i]+duration[i]);
1382 cumulatives(s, machine, start, duration, end, height, limit, true,
1383 s.ann2ipl(ann));
1384 } else {
1385 int min = Gecode::Int::Limits::max;
1386 int max = Gecode::Int::Limits::min;
1387 IntVarArgs end(start.size());
1388 for (int i = start.size(); i--; ) {
1389 min = std::min(min, start[i].min());
1390 max = std::max(max, start[i].max() + duration[i].max());
1391 end[i] = expr(s, start[i] + duration[i]);
1392 }
1393 for (int time = min; time < max; ++time) {
1394 IntVarArgs x(start.size());
1395 for (int i = start.size(); i--; ) {
1396 IntVar overlaps = channel(s, expr(s, (start[i] <= time) &&
1397 (time < end[i])));
1398 x[i] = expr(s, overlaps * height[i]);
1399 }
1400 linear(s, x, IRT_LQ, bound);
1401 }
1402 }
1403 }
1404
1405 void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
1406 AST::Node* ann) {
1407 IntVarArgs x = s.arg2intvarargs(ce[0]);
1408 IntSet S = s.arg2intset(ce[1]);
1409 int q = ce[2]->getInt();
1410 int l = ce[3]->getInt();
1411 int u = ce[4]->getInt();
1412 unshare(s, x);
1413 sequence(s, x, S, q, l, u, s.ann2ipl(ann));
1414 }
1415
1416 void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
1417 AST::Node* ann) {
1418 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1419 bool val = ce[1]->getBool();
1420 int q = ce[2]->getInt();
1421 int l = ce[3]->getInt();
1422 int u = ce[4]->getInt();
1423 IntSet S(val, val);
1424 unshare(s, x);
1425 sequence(s, x, S, q, l, u, s.ann2ipl(ann));
1426 }
1427
1428 void p_schedule_unary(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
1429 IntVarArgs x = s.arg2intvarargs(ce[0]);
1430 IntArgs p = s.arg2intargs(ce[1]);
1431 unshare(s,x);
1432 unary(s, x, p);
1433 }
1434
1435 void p_schedule_unary_optional(FlatZincSpace& s, const ConExpr& ce,
1436 AST::Node*) {
1437 IntVarArgs x = s.arg2intvarargs(ce[0]);
1438 IntArgs p = s.arg2intargs(ce[1]);
1439 BoolVarArgs m = s.arg2boolvarargs(ce[2]);
1440 unshare(s,x);
1441 unary(s, x, p, m);
1442 }
1443
1444 void p_circuit(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1445 int off = ce[0]->getInt();
1446 IntVarArgs xv = s.arg2intvarargs(ce[1]);
1447 unshare(s,xv);
1448 circuit(s,off,xv,s.ann2ipl(ann));
1449 }
1450 void p_circuit_cost_array(FlatZincSpace& s, const ConExpr& ce,
1451 AST::Node *ann) {
1452 IntArgs c = s.arg2intargs(ce[0]);
1453 IntVarArgs xv = s.arg2intvarargs(ce[1]);
1454 IntVarArgs yv = s.arg2intvarargs(ce[2]);
1455 IntVar z = s.arg2IntVar(ce[3]);
1456 unshare(s,xv);
1457 circuit(s,c,xv,yv,z,s.ann2ipl(ann));
1458 }
1459 void p_circuit_cost(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1460 IntArgs c = s.arg2intargs(ce[0]);
1461 IntVarArgs xv = s.arg2intvarargs(ce[1]);
1462 IntVar z = s.arg2IntVar(ce[2]);
1463 unshare(s,xv);
1464 circuit(s,c,xv,z,s.ann2ipl(ann));
1465 }
1466
1467 void p_nooverlap(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1468 IntVarArgs x0 = s.arg2intvarargs(ce[0]);
1469 IntVarArgs w = s.arg2intvarargs(ce[1]);
1470 IntVarArgs y0 = s.arg2intvarargs(ce[2]);
1471 IntVarArgs h = s.arg2intvarargs(ce[3]);
1472 if (w.assigned() && h.assigned()) {
1473 IntArgs iw(w.size());
1474 for (int i=w.size(); i--;)
1475 iw[i] = w[i].val();
1476 IntArgs ih(h.size());
1477 for (int i=h.size(); i--;)
1478 ih[i] = h[i].val();
1479 nooverlap(s,x0,iw,y0,ih,s.ann2ipl(ann));
1480
1481 int miny = y0[0].min();
1482 int maxy = y0[0].max();
1483 int maxdy = ih[0];
1484 for (int i=1; i<y0.size(); i++) {
1485 miny = std::min(miny,y0[i].min());
1486 maxy = std::max(maxy,y0[i].max());
1487 maxdy = std::max(maxdy,ih[i]);
1488 }
1489 int minx = x0[0].min();
1490 int maxx = x0[0].max();
1491 int maxdx = iw[0];
1492 for (int i=1; i<x0.size(); i++) {
1493 minx = std::min(minx,x0[i].min());
1494 maxx = std::max(maxx,x0[i].max());
1495 maxdx = std::max(maxdx,iw[i]);
1496 }
1497 if (miny > Int::Limits::min && maxy < Int::Limits::max) {
1498 cumulative(s,maxdy+maxy-miny,x0,iw,ih);
1499 cumulative(s,maxdx+maxx-minx,y0,ih,iw);
1500 }
1501 } else {
1502 IntVarArgs x1(x0.size()), y1(y0.size());
1503 for (int i=x0.size(); i--; )
1504 x1[i] = expr(s, x0[i] + w[i]);
1505 for (int i=y0.size(); i--; )
1506 y1[i] = expr(s, y0[i] + h[i]);
1507 nooverlap(s,x0,w,x1,y0,h,y1,s.ann2ipl(ann));
1508 }
1509 }
1510
1511 void p_precede(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1512 IntVarArgs x = s.arg2intvarargs(ce[0]);
1513 int p_s = ce[1]->getInt();
1514 int p_t = ce[2]->getInt();
1515 precede(s,x,p_s,p_t,s.ann2ipl(ann));
1516 }
1517
1518 void p_nvalue(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1519 IntVarArgs x = s.arg2intvarargs(ce[1]);
1520 if (ce[0]->isIntVar()) {
1521 IntVar y = s.arg2IntVar(ce[0]);
1522 nvalues(s,x,IRT_EQ,y,s.ann2ipl(ann));
1523 } else {
1524 nvalues(s,x,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
1525 }
1526 }
1527
1528 void p_among(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1529 IntVarArgs x = s.arg2intvarargs(ce[1]);
1530 IntSet v = s.arg2intset(ce[2]);
1531 if (ce[0]->isIntVar()) {
1532 IntVar n = s.arg2IntVar(ce[0]);
1533 unshare(s, x);
1534 count(s,x,v,IRT_EQ,n,s.ann2ipl(ann));
1535 } else {
1536 unshare(s, x);
1537 count(s,x,v,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
1538 }
1539 }
1540
1541 void p_member_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1542 IntVarArgs x = s.arg2intvarargs(ce[0]);
1543 IntVar y = s.arg2IntVar(ce[1]);
1544 member(s,x,y,s.ann2ipl(ann));
1545 }
1546 void p_member_int_reif(FlatZincSpace& s, const ConExpr& ce,
1547 AST::Node* ann) {
1548 IntVarArgs x = s.arg2intvarargs(ce[0]);
1549 IntVar y = s.arg2IntVar(ce[1]);
1550 BoolVar b = s.arg2BoolVar(ce[2]);
1551 member(s,x,y,b,s.ann2ipl(ann));
1552 }
1553 void p_member_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1554 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1555 BoolVar y = s.arg2BoolVar(ce[1]);
1556 member(s,x,y,s.ann2ipl(ann));
1557 }
1558 void p_member_bool_reif(FlatZincSpace& s, const ConExpr& ce,
1559 AST::Node* ann) {
1560 BoolVarArgs x = s.arg2boolvarargs(ce[0]);
1561 BoolVar y = s.arg2BoolVar(ce[1]);
1562 member(s,x,y,s.arg2BoolVar(ce[2]),s.ann2ipl(ann));
1563 }
1564
1565 class IntPoster {
1566 public:
1567 IntPoster(void) {
1568 registry().add("all_different_int", &p_distinct);
1569 registry().add("all_different_offset", &p_distinctOffset);
1570 registry().add("all_equal_int", &p_all_equal);
1571 registry().add("int_eq", &p_int_eq);
1572 registry().add("int_ne", &p_int_ne);
1573 registry().add("int_ge", &p_int_ge);
1574 registry().add("int_gt", &p_int_gt);
1575 registry().add("int_le", &p_int_le);
1576 registry().add("int_lt", &p_int_lt);
1577 registry().add("int_eq_reif", &p_int_eq_reif);
1578 registry().add("int_ne_reif", &p_int_ne_reif);
1579 registry().add("int_ge_reif", &p_int_ge_reif);
1580 registry().add("int_gt_reif", &p_int_gt_reif);
1581 registry().add("int_le_reif", &p_int_le_reif);
1582 registry().add("int_lt_reif", &p_int_lt_reif);
1583 registry().add("int_eq_imp", &p_int_eq_imp);
1584 registry().add("int_ne_imp", &p_int_ne_imp);
1585 registry().add("int_ge_imp", &p_int_ge_imp);
1586 registry().add("int_gt_imp", &p_int_gt_imp);
1587 registry().add("int_le_imp", &p_int_le_imp);
1588 registry().add("int_lt_imp", &p_int_lt_imp);
1589 registry().add("int_lin_eq", &p_int_lin_eq);
1590 registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
1591 registry().add("int_lin_eq_imp", &p_int_lin_eq_imp);
1592 registry().add("int_lin_ne", &p_int_lin_ne);
1593 registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
1594 registry().add("int_lin_ne_imp", &p_int_lin_ne_imp);
1595 registry().add("int_lin_le", &p_int_lin_le);
1596 registry().add("int_lin_le_reif", &p_int_lin_le_reif);
1597 registry().add("int_lin_le_imp", &p_int_lin_le_imp);
1598 registry().add("int_lin_lt", &p_int_lin_lt);
1599 registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
1600 registry().add("int_lin_lt_imp", &p_int_lin_lt_imp);
1601 registry().add("int_lin_ge", &p_int_lin_ge);
1602 registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
1603 registry().add("int_lin_ge_imp", &p_int_lin_ge_imp);
1604 registry().add("int_lin_gt", &p_int_lin_gt);
1605 registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
1606 registry().add("int_lin_gt_imp", &p_int_lin_gt_imp);
1607 registry().add("int_plus", &p_int_plus);
1608 registry().add("int_minus", &p_int_minus);
1609 registry().add("int_times", &p_int_times);
1610 registry().add("gecode_int_pow", &p_int_pow);
1611 registry().add("int_div", &p_int_div);
1612 registry().add("int_mod", &p_int_mod);
1613 registry().add("int_min", &p_int_min);
1614 registry().add("int_max", &p_int_max);
1615 registry().add("int_abs", &p_abs);
1616 registry().add("int_negate", &p_int_negate);
1617 registry().add("bool_eq", &p_bool_eq);
1618 registry().add("bool_eq_reif", &p_bool_eq_reif);
1619 registry().add("bool_eq_imp", &p_bool_eq_imp);
1620 registry().add("bool_ne", &p_bool_ne);
1621 registry().add("bool_ne_reif", &p_bool_ne_reif);
1622 registry().add("bool_ne_imp", &p_bool_ne_imp);
1623 registry().add("bool_ge", &p_bool_ge);
1624 registry().add("bool_ge_reif", &p_bool_ge_reif);
1625 registry().add("bool_ge_imp", &p_bool_ge_imp);
1626 registry().add("bool_le", &p_bool_le);
1627 registry().add("bool_le_reif", &p_bool_le_reif);
1628 registry().add("bool_le_imp", &p_bool_le_imp);
1629 registry().add("bool_gt", &p_bool_gt);
1630 registry().add("bool_gt_reif", &p_bool_gt_reif);
1631 registry().add("bool_gt_imp", &p_bool_gt_imp);
1632 registry().add("bool_lt", &p_bool_lt);
1633 registry().add("bool_lt_reif", &p_bool_lt_reif);
1634 registry().add("bool_lt_imp", &p_bool_lt_imp);
1635 registry().add("bool_or", &p_bool_or);
1636 registry().add("bool_or_imp", &p_bool_or_imp);
1637 registry().add("bool_and", &p_bool_and);
1638 registry().add("bool_and_imp", &p_bool_and_imp);
1639 registry().add("bool_xor", &p_bool_xor);
1640 registry().add("bool_xor_imp", &p_bool_xor_imp);
1641 registry().add("array_bool_and", &p_array_bool_and);
1642 registry().add("array_bool_and_imp", &p_array_bool_and_imp);
1643 registry().add("array_bool_or", &p_array_bool_or);
1644 registry().add("array_bool_or_imp", &p_array_bool_or_imp);
1645 registry().add("array_bool_xor", &p_array_bool_xor);
1646 registry().add("array_bool_xor_imp", &p_array_bool_xor_imp);
1647 registry().add("bool_clause", &p_array_bool_clause);
1648 registry().add("bool_clause_reif", &p_array_bool_clause_reif);
1649 registry().add("bool_clause_imp", &p_array_bool_clause_imp);
1650 registry().add("bool_left_imp", &p_bool_l_imp);
1651 registry().add("bool_right_imp", &p_bool_r_imp);
1652 registry().add("bool_not", &p_bool_not);
1653 registry().add("array_int_element", &p_array_int_element);
1654 registry().add("array_var_int_element", &p_array_int_element);
1655 registry().add("gecode_int_element", &p_array_int_element_offset);
1656 registry().add("gecode_var_int_element", &p_array_int_element_offset);
1657 registry().add("gecode_int_element2d", &p_array_int_element2d);
1658 registry().add("array_bool_element", &p_array_bool_element);
1659 registry().add("array_var_bool_element", &p_array_bool_element);
1660 registry().add("gecode_bool_element", &p_array_bool_element_offset);
1661 registry().add("gecode_var_bool_element", &p_array_bool_element_offset);
1662 registry().add("gecode_bool_element2d", &p_array_bool_element2d);
1663 registry().add("bool2int", &p_bool2int);
1664 registry().add("int_in", &p_int_in);
1665 registry().add("int_in_reif", &p_int_in_reif);
1666 registry().add("int_in_imp", &p_int_in_imp);
1667#ifndef GECODE_HAS_SET_VARS
1668 registry().add("set_in", &p_int_in);
1669 registry().add("set_in_reif", &p_int_in_reif);
1670 registry().add("set_in_imp", &p_int_in_imp);
1671#endif
1672
1673 registry().add("array_int_lt", &p_array_int_lt);
1674 registry().add("array_int_lq", &p_array_int_lq);
1675 registry().add("array_bool_lt", &p_array_bool_lt);
1676 registry().add("array_bool_lq", &p_array_bool_lq);
1677 registry().add("count", &p_count);
1678 registry().add("count_reif", &p_count_reif);
1679 registry().add("count_imp", &p_count_imp);
1680 registry().add("count_eq", &p_count);
1681 registry().add("count_eq_reif", &p_count_reif);
1682 registry().add("count_eq_imp", &p_count_imp);
1683 registry().add("at_least_int", &p_at_least);
1684 registry().add("at_most_int", &p_at_most);
1685 registry().add("gecode_bin_packing_load", &p_bin_packing_load);
1686 registry().add("gecode_global_cardinality", &p_global_cardinality);
1687 registry().add("gecode_global_cardinality_closed",
1688 &p_global_cardinality_closed);
1689 registry().add("global_cardinality_low_up",
1690 &p_global_cardinality_low_up);
1691 registry().add("global_cardinality_low_up_closed",
1692 &p_global_cardinality_low_up_closed);
1693 registry().add("array_int_minimum", &p_minimum);
1694 registry().add("array_int_maximum", &p_maximum);
1695 registry().add("gecode_minimum_arg_int_offset", &p_minimum_arg);
1696 registry().add("gecode_maximum_arg_int_offset", &p_maximum_arg);
1697 registry().add("gecode_minimum_arg_bool_offset", &p_minimum_arg_bool);
1698 registry().add("gecode_maximum_arg_bool_offset", &p_maximum_arg_bool);
1699 registry().add("array_int_maximum", &p_maximum);
1700 registry().add("gecode_regular", &p_regular);
1701 registry().add("sort", &p_sort);
1702 registry().add("inverse_offsets", &p_inverse_offsets);
1703 registry().add("increasing_int", &p_increasing_int);
1704 registry().add("increasing_bool", &p_increasing_bool);
1705 registry().add("decreasing_int", &p_decreasing_int);
1706 registry().add("decreasing_bool", &p_decreasing_bool);
1707 registry().add("gecode_table_int", &p_table_int);
1708 registry().add("gecode_table_int_reif", &p_table_int_reif);
1709 registry().add("gecode_table_int_imp", &p_table_int_imp);
1710 registry().add("gecode_table_bool", &p_table_bool);
1711 registry().add("gecode_table_bool_reif", &p_table_bool_reif);
1712 registry().add("gecode_table_bool_imp", &p_table_bool_imp);
1713 registry().add("cumulatives", &p_cumulatives);
1714 registry().add("gecode_among_seq_int", &p_among_seq_int);
1715 registry().add("gecode_among_seq_bool", &p_among_seq_bool);
1716
1717 registry().add("bool_lin_eq", &p_bool_lin_eq);
1718 registry().add("bool_lin_ne", &p_bool_lin_ne);
1719 registry().add("bool_lin_le", &p_bool_lin_le);
1720 registry().add("bool_lin_lt", &p_bool_lin_lt);
1721 registry().add("bool_lin_ge", &p_bool_lin_ge);
1722 registry().add("bool_lin_gt", &p_bool_lin_gt);
1723
1724 registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
1725 registry().add("bool_lin_eq_imp", &p_bool_lin_eq_imp);
1726 registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
1727 registry().add("bool_lin_ne_imp", &p_bool_lin_ne_imp);
1728 registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
1729 registry().add("bool_lin_le_imp", &p_bool_lin_le_imp);
1730 registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
1731 registry().add("bool_lin_lt_imp", &p_bool_lin_lt_imp);
1732 registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
1733 registry().add("bool_lin_ge_imp", &p_bool_lin_ge_imp);
1734 registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
1735 registry().add("bool_lin_gt_imp", &p_bool_lin_gt_imp);
1736
1737 registry().add("gecode_schedule_unary", &p_schedule_unary);
1738 registry().add("gecode_schedule_unary_optional", &p_schedule_unary_optional);
1739 registry().add("gecode_schedule_cumulative_optional", &p_cumulative_opt);
1740
1741 registry().add("gecode_circuit", &p_circuit);
1742 registry().add("gecode_circuit_cost_array", &p_circuit_cost_array);
1743 registry().add("gecode_circuit_cost", &p_circuit_cost);
1744 registry().add("gecode_nooverlap", &p_nooverlap);
1745 registry().add("gecode_precede", &p_precede);
1746 registry().add("nvalue",&p_nvalue);
1747 registry().add("among",&p_among);
1748 registry().add("member_int",&p_member_int);
1749 registry().add("gecode_member_int_reif",&p_member_int_reif);
1750 registry().add("member_bool",&p_member_bool);
1751 registry().add("gecode_member_bool_reif",&p_member_bool_reif);
1752 }
1753 };
1754 IntPoster __int_poster;
1755
1756#ifdef GECODE_HAS_SET_VARS
1757 void p_set_OP(FlatZincSpace& s, SetOpType op,
1758 const ConExpr& ce, AST::Node *) {
1759 rel(s, s.arg2SetVar(ce[0]), op, s.arg2SetVar(ce[1]),
1760 SRT_EQ, s.arg2SetVar(ce[2]));
1761 }
1762 void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1763 p_set_OP(s, SOT_UNION, ce, ann);
1764 }
1765 void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1766 p_set_OP(s, SOT_INTER, ce, ann);
1767 }
1768 void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1769 p_set_OP(s, SOT_MINUS, ce, ann);
1770 }
1771
1772 void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
1773 SetVar x = s.arg2SetVar(ce[0]);
1774 SetVar y = s.arg2SetVar(ce[1]);
1775
1776 SetVarLubRanges xub(x);
1777 IntSet xubs(xub);
1778 SetVar x_y(s,IntSet::empty,xubs);
1779 rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
1780
1781 SetVarLubRanges yub(y);
1782 IntSet yubs(yub);
1783 SetVar y_x(s,IntSet::empty,yubs);
1784 rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
1785
1786 rel(s, x_y, SOT_UNION, y_x, SRT_EQ, s.arg2SetVar(ce[2]));
1787 }
1788
1789 void p_array_set_OP(FlatZincSpace& s, SetOpType op,
1790 const ConExpr& ce, AST::Node *) {
1791 SetVarArgs xs = s.arg2setvarargs(ce[0]);
1792 rel(s, op, xs, s.arg2SetVar(ce[1]));
1793 }
1794 void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1795 p_array_set_OP(s, SOT_UNION, ce, ann);
1796 }
1797 void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
1798 p_array_set_OP(s, SOT_DUNION, ce, ann);
1799 }
1800
1801
1802 void p_set_rel(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
1803 rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]));
1804 }
1805
1806 void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1807 p_set_rel(s, SRT_EQ, ce);
1808 }
1809 void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1810 p_set_rel(s, SRT_NQ, ce);
1811 }
1812 void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1813 p_set_rel(s, SRT_SUB, ce);
1814 }
1815 void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1816 p_set_rel(s, SRT_SUP, ce);
1817 }
1818 void p_set_le(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1819 p_set_rel(s, SRT_LQ, ce);
1820 }
1821 void p_set_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1822 p_set_rel(s, SRT_LE, ce);
1823 }
1824 void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1825 if (!ce[1]->isIntVar()) {
1826 cardinality(s, s.arg2SetVar(ce[0]), ce[1]->getInt(),
1827 ce[1]->getInt());
1828 } else {
1829 cardinality(s, s.arg2SetVar(ce[0]), s.arg2IntVar(ce[1]));
1830 }
1831 }
1832 void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1833 if (!ce[1]->isSetVar()) {
1834 IntSet d = s.arg2intset(ce[1]);
1835 if (ce[0]->isBoolVar()) {
1836 IntSetRanges dr(d);
1837 Iter::Ranges::Singleton sr(0,1);
1838 Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
1839 IntSet d01(i);
1840 if (d01.size() == 0) {
1841 s.fail();
1842 } else {
1843 rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
1844 rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
1845 }
1846 } else {
1847 dom(s, s.arg2IntVar(ce[0]), d);
1848 }
1849 } else {
1850 if (!ce[0]->isIntVar()) {
1851 dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt());
1852 } else {
1853 rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]));
1854 }
1855 }
1856 }
1857 void p_set_rel_reif(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
1858 rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]),
1859 s.arg2BoolVar(ce[2]));
1860 }
1861
1862 void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1863 p_set_rel_reif(s,SRT_EQ,ce);
1864 }
1865 void p_set_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1866 p_set_rel_reif(s,SRT_LQ,ce);
1867 }
1868 void p_set_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1869 p_set_rel_reif(s,SRT_LE,ce);
1870 }
1871 void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1872 p_set_rel_reif(s,SRT_NQ,ce);
1873 }
1874 void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
1875 AST::Node *) {
1876 p_set_rel_reif(s,SRT_SUB,ce);
1877 }
1878 void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
1879 AST::Node *) {
1880 p_set_rel_reif(s,SRT_SUP,ce);
1881 }
1882 void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann, ReifyMode rm) {
1883 if (!ce[1]->isSetVar()) {
1884 if (rm==RM_EQV) {
1885 p_int_in_reif(s,ce,ann);
1886 } else {
1887 assert(rm==RM_IMP);
1888 p_int_in_imp(s,ce,ann);
1889 }
1890 } else {
1891 if (!ce[0]->isIntVar()) {
1892 dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt(),
1893 Reify(s.arg2BoolVar(ce[2]),rm));
1894 } else {
1895 rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]),
1896 Reify(s.arg2BoolVar(ce[2]),rm));
1897 }
1898 }
1899 }
1900 void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1901 p_set_in_reif(s,ce,ann,RM_EQV);
1902 }
1903 void p_set_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
1904 p_set_in_reif(s,ce,ann,RM_IMP);
1905 }
1906 void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1907 rel(s, s.arg2SetVar(ce[0]), SRT_DISJ, s.arg2SetVar(ce[1]));
1908 }
1909
1910 void p_link_set_to_booleans(FlatZincSpace& s, const ConExpr& ce,
1911 AST::Node *) {
1912 SetVar x = s.arg2SetVar(ce[0]);
1913 int idx = ce[2]->getInt();
1914 assert(idx >= 0);
1915 rel(s, x || IntSet(Set::Limits::min,idx-1));
1916 BoolVarArgs y = s.arg2boolvarargs(ce[1],idx);
1917 unshare(s, y);
1918 channel(s, y, x);
1919 }
1920
1921 void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
1922 AST::Node*) {
1923 bool isConstant = true;
1924 AST::Array* a = ce[1]->getArray();
1925 for (int i=a->a.size(); i--;) {
1926 if (a->a[i]->isSetVar()) {
1927 isConstant = false;
1928 break;
1929 }
1930 }
1931 IntVar selector = s.arg2IntVar(ce[0]);
1932 rel(s, selector > 0);
1933 if (isConstant) {
1934 IntSetArgs sv = s.arg2intsetargs(ce[1],1);
1935 element(s, sv, selector, s.arg2SetVar(ce[2]));
1936 } else {
1937 SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
1938 element(s, sv, selector, s.arg2SetVar(ce[2]));
1939 }
1940 }
1941
1942 void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
1943 AST::Node*, SetOpType op,
1944 const IntSet& universe =
1945 IntSet(Set::Limits::min,Set::Limits::max)) {
1946 bool isConstant = true;
1947 AST::Array* a = ce[1]->getArray();
1948 for (int i=a->a.size(); i--;) {
1949 if (a->a[i]->isSetVar()) {
1950 isConstant = false;
1951 break;
1952 }
1953 }
1954 SetVar selector = s.arg2SetVar(ce[0]);
1955 dom(s, selector, SRT_DISJ, 0);
1956 if (isConstant) {
1957 IntSetArgs sv = s.arg2intsetargs(ce[1], 1);
1958 element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
1959 } else {
1960 SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
1961 element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
1962 }
1963 }
1964
1965 void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
1966 AST::Node* ann) {
1967 p_array_set_element_op(s, ce, ann, SOT_UNION);
1968 }
1969
1970 void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
1971 AST::Node* ann) {
1972 p_array_set_element_op(s, ce, ann, SOT_INTER);
1973 }
1974
1975 void p_array_set_element_intersect_in(FlatZincSpace& s,
1976 const ConExpr& ce,
1977 AST::Node* ann) {
1978 IntSet d = s.arg2intset(ce[3]);
1979 p_array_set_element_op(s, ce, ann, SOT_INTER, d);
1980 }
1981
1982 void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
1983 AST::Node* ann) {
1984 p_array_set_element_op(s, ce, ann, SOT_DUNION);
1985 }
1986
1987 void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1988 convex(s, s.arg2SetVar(ce[0]));
1989 }
1990
1991 void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
1992 SetVarArgs sv = s.arg2setvarargs(ce[0]);
1993 sequence(s, sv);
1994 }
1995
1996 void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
1997 AST::Node *) {
1998 SetVarArgs sv = s.arg2setvarargs(ce[0]);
1999 sequence(s, sv, s.arg2SetVar(ce[1]));
2000 }
2001
2002 void p_int_set_channel(FlatZincSpace& s, const ConExpr& ce,
2003 AST::Node *) {
2004 int xoff=ce[1]->getInt();
2005 assert(xoff >= 0);
2006 int yoff=ce[3]->getInt();
2007 assert(yoff >= 0);
2008 IntVarArgs xv = s.arg2intvarargs(ce[0], xoff);
2009 SetVarArgs yv = s.arg2setvarargs(ce[2], yoff, 1, IntSet(0, xoff-1));
2010 IntSet xd(yoff,yv.size()-1);
2011 for (int i=xoff; i<xv.size(); i++) {
2012 dom(s, xv[i], xd);
2013 }
2014 IntSet yd(xoff,xv.size()-1);
2015 for (int i=yoff; i<yv.size(); i++) {
2016 dom(s, yv[i], SRT_SUB, yd);
2017 }
2018 channel(s,xv,yv);
2019 }
2020
2021 void p_range(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2022 int xoff=ce[1]->getInt();
2023 assert(xoff >= 0);
2024 IntVarArgs xv = s.arg2intvarargs(ce[0],xoff);
2025 element(s, SOT_UNION, xv, s.arg2SetVar(ce[2]), s.arg2SetVar(ce[3]));
2026 }
2027
2028 void p_weights(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2029 IntArgs e = s.arg2intargs(ce[0]);
2030 IntArgs w = s.arg2intargs(ce[1]);
2031 SetVar x = s.arg2SetVar(ce[2]);
2032 IntVar y = s.arg2IntVar(ce[3]);
2033 weights(s,e,w,x,y);
2034 }
2035
2036 void p_inverse_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2037 int xoff = ce[2]->getInt();
2038 int yoff = ce[3]->getInt();
2039 SetVarArgs x = s.arg2setvarargs(ce[0],xoff);
2040 SetVarArgs y = s.arg2setvarargs(ce[1],yoff);
2041 channel(s, x, y);
2042 }
2043
2044 void p_precede_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2045 SetVarArgs x = s.arg2setvarargs(ce[0]);
2046 int p_s = ce[1]->getInt();
2047 int p_t = ce[2]->getInt();
2048 precede(s,x,p_s,p_t);
2049 }
2050
2051 class SetPoster {
2052 public:
2053 SetPoster(void) {
2054 registry().add("set_eq", &p_set_eq);
2055 registry().add("set_le", &p_set_le);
2056 registry().add("set_lt", &p_set_lt);
2057 registry().add("equal", &p_set_eq);
2058 registry().add("set_ne", &p_set_ne);
2059 registry().add("set_union", &p_set_union);
2060 registry().add("array_set_element", &p_array_set_element);
2061 registry().add("array_var_set_element", &p_array_set_element);
2062 registry().add("set_intersect", &p_set_intersect);
2063 registry().add("set_diff", &p_set_diff);
2064 registry().add("set_symdiff", &p_set_symdiff);
2065 registry().add("set_subset", &p_set_subset);
2066 registry().add("set_superset", &p_set_superset);
2067 registry().add("set_card", &p_set_card);
2068 registry().add("set_in", &p_set_in);
2069 registry().add("set_eq_reif", &p_set_eq_reif);
2070 registry().add("set_le_reif", &p_set_le_reif);
2071 registry().add("set_lt_reif", &p_set_lt_reif);
2072 registry().add("equal_reif", &p_set_eq_reif);
2073 registry().add("set_ne_reif", &p_set_ne_reif);
2074 registry().add("set_subset_reif", &p_set_subset_reif);
2075 registry().add("set_superset_reif", &p_set_superset_reif);
2076 registry().add("set_in_reif", &p_set_in_reif);
2077 registry().add("set_in_imp", &p_set_in_imp);
2078 registry().add("disjoint", &p_set_disjoint);
2079 registry().add("gecode_link_set_to_booleans",
2080 &p_link_set_to_booleans);
2081
2082 registry().add("array_set_union", &p_array_set_union);
2083 registry().add("array_set_partition", &p_array_set_partition);
2084 registry().add("set_convex", &p_set_convex);
2085 registry().add("array_set_seq", &p_array_set_seq);
2086 registry().add("array_set_seq_union", &p_array_set_seq_union);
2087 registry().add("gecode_array_set_element_union",
2088 &p_array_set_element_union);
2089 registry().add("gecode_array_set_element_intersect",
2090 &p_array_set_element_intersect);
2091 registry().add("gecode_array_set_element_intersect_in",
2092 &p_array_set_element_intersect_in);
2093 registry().add("gecode_array_set_element_partition",
2094 &p_array_set_element_partition);
2095 registry().add("gecode_int_set_channel",
2096 &p_int_set_channel);
2097 registry().add("gecode_range",
2098 &p_range);
2099 registry().add("gecode_set_weights",
2100 &p_weights);
2101 registry().add("gecode_inverse_set", &p_inverse_set);
2102 registry().add("gecode_precede_set", &p_precede_set);
2103 }
2104 };
2105 SetPoster __set_poster;
2106#endif
2107
2108#ifdef GECODE_HAS_FLOAT_VARS
2109
2110 void p_int2float(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2111 IntVar x0 = s.arg2IntVar(ce[0]);
2112 FloatVar x1 = s.arg2FloatVar(ce[1]);
2113 channel(s, x0, x1);
2114 }
2115
2116 void p_float_lin_cmp(FlatZincSpace& s, FloatRelType frt,
2117 const ConExpr& ce, AST::Node*) {
2118 FloatValArgs fa = s.arg2floatargs(ce[0]);
2119 FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
2120 linear(s, fa, fv, frt, ce[2]->getFloat());
2121 }
2122 void p_float_lin_cmp_reif(FlatZincSpace& s, FloatRelType frt,
2123 const ConExpr& ce, AST::Node*) {
2124 FloatValArgs fa = s.arg2floatargs(ce[0]);
2125 FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
2126 linear(s, fa, fv, frt, ce[2]->getFloat(), s.arg2BoolVar(ce[3]));
2127 }
2128 void p_float_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
2129 p_float_lin_cmp(s,FRT_EQ,ce,ann);
2130 }
2131 void p_float_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce,
2132 AST::Node* ann) {
2133 p_float_lin_cmp_reif(s,FRT_EQ,ce,ann);
2134 }
2135 void p_float_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
2136 p_float_lin_cmp(s,FRT_LQ,ce,ann);
2137 }
2138 void p_float_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
2139 p_float_lin_cmp(s,FRT_LE,ce,ann);
2140 }
2141 void p_float_lin_le_reif(FlatZincSpace& s, const ConExpr& ce,
2142 AST::Node* ann) {
2143 p_float_lin_cmp_reif(s,FRT_LQ,ce,ann);
2144 }
2145 void p_float_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce,
2146 AST::Node* ann) {
2147 p_float_lin_cmp_reif(s,FRT_LE,ce,ann);
2148 }
2149
2150 void p_float_times(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2151 FloatVar x = s.arg2FloatVar(ce[0]);
2152 FloatVar y = s.arg2FloatVar(ce[1]);
2153 FloatVar z = s.arg2FloatVar(ce[2]);
2154 mult(s,x,y,z);
2155 }
2156
2157 void p_float_div(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2158 FloatVar x = s.arg2FloatVar(ce[0]);
2159 FloatVar y = s.arg2FloatVar(ce[1]);
2160 FloatVar z = s.arg2FloatVar(ce[2]);
2161 div(s,x,y,z);
2162 }
2163
2164 void p_float_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2165 FloatVar x = s.arg2FloatVar(ce[0]);
2166 FloatVar y = s.arg2FloatVar(ce[1]);
2167 FloatVar z = s.arg2FloatVar(ce[2]);
2168 rel(s,x+y==z);
2169 }
2170
2171 void p_float_sqrt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2172 FloatVar x = s.arg2FloatVar(ce[0]);
2173 FloatVar y = s.arg2FloatVar(ce[1]);
2174 sqrt(s,x,y);
2175 }
2176
2177 void p_float_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2178 FloatVar x = s.arg2FloatVar(ce[0]);
2179 FloatVar y = s.arg2FloatVar(ce[1]);
2180 abs(s,x,y);
2181 }
2182
2183 void p_float_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2184 FloatVar x = s.arg2FloatVar(ce[0]);
2185 FloatVar y = s.arg2FloatVar(ce[1]);
2186 rel(s,x,FRT_EQ,y);
2187 }
2188 void p_float_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2189 FloatVar x = s.arg2FloatVar(ce[0]);
2190 FloatVar y = s.arg2FloatVar(ce[1]);
2191 BoolVar b = s.arg2BoolVar(ce[2]);
2192 rel(s,x,FRT_EQ,y,b);
2193 }
2194 void p_float_le(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2195 FloatVar x = s.arg2FloatVar(ce[0]);
2196 FloatVar y = s.arg2FloatVar(ce[1]);
2197 rel(s,x,FRT_LQ,y);
2198 }
2199 void p_float_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2200 FloatVar x = s.arg2FloatVar(ce[0]);
2201 FloatVar y = s.arg2FloatVar(ce[1]);
2202 BoolVar b = s.arg2BoolVar(ce[2]);
2203 rel(s,x,FRT_LQ,y,b);
2204 }
2205 void p_float_max(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2206 FloatVar x = s.arg2FloatVar(ce[0]);
2207 FloatVar y = s.arg2FloatVar(ce[1]);
2208 FloatVar z = s.arg2FloatVar(ce[2]);
2209 max(s,x,y,z);
2210 }
2211 void p_float_min(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2212 FloatVar x = s.arg2FloatVar(ce[0]);
2213 FloatVar y = s.arg2FloatVar(ce[1]);
2214 FloatVar z = s.arg2FloatVar(ce[2]);
2215 min(s,x,y,z);
2216 }
2217 void p_float_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2218 FloatVar x = s.arg2FloatVar(ce[0]);
2219 FloatVar y = s.arg2FloatVar(ce[1]);
2220 rel(s, x, FRT_LQ, y);
2221 rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
2222 }
2223
2224 void p_float_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2225 FloatVar x = s.arg2FloatVar(ce[0]);
2226 FloatVar y = s.arg2FloatVar(ce[1]);
2227 BoolVar b = s.arg2BoolVar(ce[2]);
2228 BoolVar b0(s,0,1);
2229 BoolVar b1(s,0,1);
2230 rel(s, b == (b0 && !b1));
2231 rel(s, x, FRT_LQ, y, b0);
2232 rel(s, x, FRT_EQ, y, b1);
2233 }
2234
2235 void p_float_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2236 FloatVar x = s.arg2FloatVar(ce[0]);
2237 FloatVar y = s.arg2FloatVar(ce[1]);
2238 rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
2239 }
2240
2241#ifdef GECODE_HAS_MPFR
2242#define P_FLOAT_OP(Op) \
2243 void p_float_ ## Op (FlatZincSpace& s, const ConExpr& ce, AST::Node*) {\
2244 FloatVar x = s.arg2FloatVar(ce[0]);\
2245 FloatVar y = s.arg2FloatVar(ce[1]);\
2246 Op(s,x,y);\
2247 }
2248 P_FLOAT_OP(acos)
2249 P_FLOAT_OP(asin)
2250 P_FLOAT_OP(atan)
2251 P_FLOAT_OP(cos)
2252 P_FLOAT_OP(exp)
2253 P_FLOAT_OP(sin)
2254 P_FLOAT_OP(tan)
2255 // P_FLOAT_OP(sinh)
2256 // P_FLOAT_OP(tanh)
2257 // P_FLOAT_OP(cosh)
2258#undef P_FLOAT_OP
2259
2260 void p_float_ln(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2261 FloatVar x = s.arg2FloatVar(ce[0]);
2262 FloatVar y = s.arg2FloatVar(ce[1]);
2263 log(s,x,y);
2264 }
2265 void p_float_log10(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2266 FloatVar x = s.arg2FloatVar(ce[0]);
2267 FloatVar y = s.arg2FloatVar(ce[1]);
2268 log(s,10.0,x,y);
2269 }
2270 void p_float_log2(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
2271 FloatVar x = s.arg2FloatVar(ce[0]);
2272 FloatVar y = s.arg2FloatVar(ce[1]);
2273 log(s,2.0,x,y);
2274 }
2275
2276#endif
2277
2278 class FloatPoster {
2279 public:
2280 FloatPoster(void) {
2281 registry().add("int2float",&p_int2float);
2282 registry().add("float_abs",&p_float_abs);
2283 registry().add("float_sqrt",&p_float_sqrt);
2284 registry().add("float_eq",&p_float_eq);
2285 registry().add("float_eq_reif",&p_float_eq_reif);
2286 registry().add("float_le",&p_float_le);
2287 registry().add("float_le_reif",&p_float_le_reif);
2288 registry().add("float_lt",&p_float_lt);
2289 registry().add("float_lt_reif",&p_float_lt_reif);
2290 registry().add("float_ne",&p_float_ne);
2291 registry().add("float_times",&p_float_times);
2292 registry().add("float_div",&p_float_div);
2293 registry().add("float_plus",&p_float_plus);
2294 registry().add("float_max",&p_float_max);
2295 registry().add("float_min",&p_float_min);
2296
2297 registry().add("float_lin_eq",&p_float_lin_eq);
2298 registry().add("float_lin_eq_reif",&p_float_lin_eq_reif);
2299 registry().add("float_lin_le",&p_float_lin_le);
2300 registry().add("float_lin_lt",&p_float_lin_lt);
2301 registry().add("float_lin_le_reif",&p_float_lin_le_reif);
2302 registry().add("float_lin_lt_reif",&p_float_lin_lt_reif);
2303
2304#ifdef GECODE_HAS_MPFR
2305 registry().add("float_acos",&p_float_acos);
2306 registry().add("float_asin",&p_float_asin);
2307 registry().add("float_atan",&p_float_atan);
2308 registry().add("float_cos",&p_float_cos);
2309 // registry().add("float_cosh",&p_float_cosh);
2310 registry().add("float_exp",&p_float_exp);
2311 registry().add("float_ln",&p_float_ln);
2312 registry().add("float_log10",&p_float_log10);
2313 registry().add("float_log2",&p_float_log2);
2314 registry().add("float_sin",&p_float_sin);
2315 // registry().add("float_sinh",&p_float_sinh);
2316 registry().add("float_tan",&p_float_tan);
2317 // registry().add("float_tanh",&p_float_tanh);
2318#endif
2319 }
2320 } __float_poster;
2321#endif
2322
2323 }
2324}}
2325
2326// STATISTICS: flatzinc-any