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 * Christian Schulte <schulte@gecode.org>
6 *
7 * Copyright:
8 * Guido Tack, 2010
9 * Christian Schulte, 2004
10 *
11 * This file is part of Gecode, the generic constraint
12 * development environment:
13 * http://www.gecode.org
14 *
15 * Permission is hereby granted, free of charge, to any person obtaining
16 * a copy of this software and associated documentation files (the
17 * "Software"), to deal in the Software without restriction, including
18 * without limitation the rights to use, copy, modify, merge, publish,
19 * distribute, sublicense, and/or sell copies of the Software, and to
20 * permit persons to whom the Software is furnished to do so, subject to
21 * the following conditions:
22 *
23 * The above copyright notice and this permission notice shall be
24 * included in all copies or substantial portions of the Software.
25 *
26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 *
34 */
35
36#include <gecode/minimodel.hh>
37
38#ifdef GECODE_HAS_SET_VARS
39
40namespace Gecode {
41
42 namespace {
43 /// Check if types agree
44 static bool same(SetExpr::NodeType t0, SetExpr::NodeType t1) {
45 return (t0==t1) || (t1==SetExpr::NT_VAR) ||
46 (t1==SetExpr::NT_CONST) || (t1==SetExpr::NT_LEXP);
47 }
48 }
49
50 /// %Node for set expression
51 class SetExpr::Node {
52 public:
53 /// Nodes are reference counted
54 unsigned int use;
55 /// Number of variables in subtree with same type (for INTER and UNION)
56 int same;
57 /// Type of expression
58 NodeType t;
59 /// Subexpressions
60 Node *l, *r;
61 /// Possibly a variable
62 SetVar x;
63 /// Possibly a constant
64 IntSet s;
65 /// Possibly a linear expression
66 LinIntExpr e;
67
68 /// Default constructor
69 Node(void);
70 /// Decrement reference count and possibly free memory
71 GECODE_MINIMODEL_EXPORT
72 bool decrement(void);
73 /// Memory management
74 static void* operator new(size_t size);
75 /// Memory management
76 static void operator delete(void* p, size_t size);
77 };
78
79 /*
80 * Operations for nodes
81 *
82 */
83 SetExpr::Node::Node(void) : use(1) {}
84
85 void*
86 SetExpr::Node::operator new(size_t size) {
87 return heap.ralloc(size);
88 }
89 void
90 SetExpr::Node::operator delete(void* p, size_t) {
91 heap.rfree(p);
92 }
93
94 bool
95 SetExpr::Node::decrement(void) {
96 if (--use == 0) {
97 if ((l != nullptr) && l->decrement())
98 delete l;
99 if ((r != nullptr) && r->decrement())
100 delete r;
101 return true;
102 }
103 return false;
104 }
105
106 namespace {
107 /// %Node for negation normalform (%NNF)
108 class NNF {
109 public:
110 typedef SetExpr::NodeType NodeType;
111 typedef SetExpr::Node Node;
112 /// Type of node
113 NodeType t;
114 /// Number of positive literals for node type
115 int p;
116 /// Number of negative literals for node type
117 int n;
118 /// Union depending on nodetype \a t
119 union {
120 /// For binary nodes (and, or, eqv)
121 struct {
122 /// Left subtree
123 NNF* l;
124 /// Right subtree
125 NNF* r;
126 } b;
127 /// For atomic nodes
128 struct {
129 /// Pointer to corresponding Boolean expression node
130 Node* x;
131 } a;
132 } u;
133 /// Is formula negative
134 bool neg;
135 /// Create negation normalform
136 static NNF* nnf(Region& r, Node* n, bool neg);
137 /// Post propagators for nested conjunctive and disjunctive expression
138 void post(Home home, NodeType t, SetVarArgs& b, int& i) const;
139 /// Post propagators for expression
140 void post(Home home, SetRelType srt, SetVar s) const;
141 /// Post propagators for reified expression
142 void post(Home home, SetRelType srt, SetVar s, BoolVar b) const;
143 /// Post propagators for relation
144 void post(Home home, SetRelType srt, const NNF* n) const;
145 /// Post reified propagators for relation (or negated relation if \a t is false)
146 void post(Home home, BoolVar b, bool t, SetRelType srt,
147 const NNF* n) const;
148 /// Allocate memory from region
149 static void* operator new(size_t s, Region& r);
150 /// No-op (for exceptions)
151 static void operator delete(void*);
152 /// No-op
153 static void operator delete(void*, Region&);
154 };
155
156 /*
157 * Operations for negation normalform
158 *
159 */
160 forceinline void
161 NNF::operator delete(void*) {}
162
163 forceinline void
164 NNF::operator delete(void*, Region&) {}
165
166 forceinline void*
167 NNF::operator new(size_t s, Region& r) {
168 return r.ralloc(s);
169 }
170
171 void
172 NNF::post(Home home, SetRelType srt, SetVar s) const {
173 switch (t) {
174 case SetExpr::NT_VAR:
175 if (neg) {
176 switch (srt) {
177 case SRT_EQ:
178 rel(home, u.a.x->x, SRT_CMPL, s);
179 break;
180 case SRT_CMPL:
181 rel(home, u.a.x->x, SRT_EQ, s);
182 break;
183 default:
184 SetVar bc(home,IntSet::empty,
185 IntSet(Set::Limits::min,Set::Limits::max));
186 rel(home, s, SRT_CMPL, bc);
187 rel(home, u.a.x->x, srt, bc);
188 break;
189 }
190 } else
191 rel(home, u.a.x->x, srt, s);
192 break;
193 case SetExpr::NT_CONST:
194 {
195 IntSet ss;
196 if (neg) {
197 IntSetRanges sr(u.a.x->s);
198 Set::RangesCompl<IntSetRanges> src(sr);
199 ss = IntSet(src);
200 } else {
201 ss = u.a.x->s;
202 }
203 switch (srt) {
204 case SRT_SUB: srt = SRT_SUP; break;
205 case SRT_SUP: srt = SRT_SUB; break;
206 default: break;
207 }
208 dom(home, s, srt, ss);
209 }
210 break;
211 case SetExpr::NT_LEXP:
212 {
213 IntVar iv = u.a.x->e.post(home,IntPropLevels::def);
214 if (neg) {
215 SetVar ic(home,IntSet::empty,
216 IntSet(Set::Limits::min,Set::Limits::max));
217 rel(home, iv, SRT_CMPL, ic);
218 rel(home,ic,srt,s);
219 } else {
220 rel(home,iv,srt,s);
221 }
222 }
223 break;
224 case SetExpr::NT_INTER:
225 {
226 SetVarArgs bs(p+n);
227 int i=0;
228 post(home, SetExpr::NT_INTER, bs, i);
229 if (i == 2) {
230 rel(home, bs[0], SOT_INTER, bs[1], srt, s);
231 } else {
232 if (srt == SRT_EQ)
233 rel(home, SOT_INTER, bs, s);
234 else {
235 SetVar bc(home,IntSet::empty,
236 IntSet(Set::Limits::min,Set::Limits::max));
237 rel(home, SOT_INTER, bs, bc);
238 rel(home, bc, srt, s);
239 }
240 }
241 }
242 break;
243 case SetExpr::NT_UNION:
244 {
245 SetVarArgs bs(p+n);
246 int i=0;
247 post(home, SetExpr::NT_UNION, bs, i);
248 if (i == 2) {
249 rel(home, bs[0], SOT_UNION, bs[1], srt, s);
250 } else {
251 if (srt == SRT_EQ)
252 rel(home, SOT_UNION, bs, s);
253 else {
254 SetVar bc(home,IntSet::empty,
255 IntSet(Set::Limits::min,Set::Limits::max));
256 rel(home, SOT_UNION, bs, bc);
257 rel(home, bc, srt, s);
258 }
259 }
260 }
261 break;
262 case SetExpr::NT_DUNION:
263 {
264 SetVarArgs bs(p+n);
265 int i=0;
266 post(home, SetExpr::NT_DUNION, bs, i);
267
268 if (i == 2) {
269 if (neg) {
270 if (srt == SRT_CMPL) {
271 rel(home, bs[0], SOT_DUNION, bs[1], srt, s);
272 } else {
273 SetVar bc(home,IntSet::empty,
274 IntSet(Set::Limits::min,Set::Limits::max));
275 rel(home,s,SRT_CMPL,bc);
276 rel(home, bs[0], SOT_DUNION, bs[1], srt, bc);
277 }
278 } else {
279 rel(home, bs[0], SOT_DUNION, bs[1], srt, s);
280 }
281 } else {
282 if (neg) {
283 if (srt == SRT_CMPL) {
284 rel(home, SOT_DUNION, bs, s);
285 } else {
286 SetVar br(home,IntSet::empty,
287 IntSet(Set::Limits::min,Set::Limits::max));
288 rel(home, SOT_DUNION, bs, br);
289 if (srt == SRT_EQ)
290 rel(home, br, SRT_CMPL, s);
291 else {
292 SetVar bc(home,IntSet::empty,
293 IntSet(Set::Limits::min,Set::Limits::max));
294 rel(home, br, srt, bc);
295 rel(home, bc, SRT_CMPL, s);
296 }
297 }
298 } else {
299 if (srt == SRT_EQ)
300 rel(home, SOT_DUNION, bs, s);
301 else {
302 SetVar br(home,IntSet::empty,
303 IntSet(Set::Limits::min,Set::Limits::max));
304 rel(home, SOT_DUNION, bs, br);
305 rel(home, br, srt, s);
306 }
307 }
308 }
309 }
310 break;
311 default:
312 GECODE_NEVER;
313 }
314 }
315
316 void
317 NNF::post(Home home, SetRelType srt, SetVar s, BoolVar b) const {
318 switch (t) {
319 case SetExpr::NT_VAR:
320 if (neg) {
321 switch (srt) {
322 case SRT_EQ:
323 rel(home, u.a.x->x, SRT_CMPL, s, b);
324 break;
325 case SRT_CMPL:
326 rel(home, u.a.x->x, SRT_EQ, s, b);
327 break;
328 default:
329 SetVar bc(home,IntSet::empty,
330 IntSet(Set::Limits::min,Set::Limits::max));
331 rel(home, s, SRT_CMPL, bc);
332 rel(home, u.a.x->x, srt, bc, b);
333 break;
334 }
335 } else
336 rel(home, u.a.x->x, srt, s, b);
337 break;
338 case SetExpr::NT_CONST:
339 {
340 IntSet ss;
341 if (neg) {
342 IntSetRanges sr(u.a.x->s);
343 Set::RangesCompl<IntSetRanges> src(sr);
344 ss = IntSet(src);
345 } else {
346 ss = u.a.x->s;
347 }
348 SetRelType invsrt;
349 switch (srt) {
350 case SRT_SUB: invsrt = SRT_SUP; break;
351 case SRT_SUP: invsrt = SRT_SUB; break;
352 case SRT_LQ: invsrt = SRT_GQ; break;
353 case SRT_LE: invsrt = SRT_GR; break;
354 case SRT_GQ: invsrt = SRT_LQ; break;
355 case SRT_GR: invsrt = SRT_LE; break;
356 case SRT_EQ:
357 case SRT_NQ:
358 case SRT_DISJ:
359 case SRT_CMPL:
360 invsrt = srt;
361 break;
362 default:
363 invsrt = srt;
364 GECODE_NEVER;
365 }
366 dom(home, s, invsrt, ss, b);
367 }
368 break;
369 case SetExpr::NT_LEXP:
370 {
371 IntVar iv = u.a.x->e.post(home,IntPropLevels::def);
372 if (neg) {
373 SetVar ic(home,IntSet::empty,
374 IntSet(Set::Limits::min,Set::Limits::max));
375 rel(home, iv, SRT_CMPL, ic);
376 rel(home,ic,srt,s,b);
377 } else {
378 rel(home,iv,srt,s,b);
379 }
380 }
381 break;
382 case SetExpr::NT_INTER:
383 {
384 SetVarArgs bs(p+n);
385 int i=0;
386 post(home, SetExpr::NT_INTER, bs, i);
387 SetVar br(home,IntSet::empty,
388 IntSet(Set::Limits::min,Set::Limits::max));
389 rel(home, SOT_INTER, bs, br);
390 rel(home, br, srt, s, b);
391 }
392 break;
393 case SetExpr::NT_UNION:
394 {
395 SetVarArgs bs(p+n);
396 int i=0;
397 post(home, SetExpr::NT_UNION, bs, i);
398 SetVar br(home,IntSet::empty,
399 IntSet(Set::Limits::min,Set::Limits::max));
400 rel(home, SOT_UNION, bs, br);
401 rel(home, br, srt, s, b);
402 }
403 break;
404 case SetExpr::NT_DUNION:
405 {
406 SetVarArgs bs(p+n);
407 int i=0;
408 post(home, SetExpr::NT_DUNION, bs, i);
409
410 if (neg) {
411 SetVar br(home,IntSet::empty,
412 IntSet(Set::Limits::min,Set::Limits::max));
413 rel(home, SOT_DUNION, bs, br);
414 if (srt == SRT_CMPL)
415 rel(home, br, SRT_EQ, s, b);
416 else if (srt == SRT_EQ)
417 rel(home, br, SRT_CMPL, s, b);
418 else {
419 SetVar bc(home,IntSet::empty,
420 IntSet(Set::Limits::min,Set::Limits::max));
421 rel(home, br, srt, bc);
422 rel(home, bc, SRT_CMPL, s, b);
423 }
424 } else {
425 SetVar br(home,IntSet::empty,
426 IntSet(Set::Limits::min,Set::Limits::max));
427 rel(home, SOT_DUNION, bs, br);
428 rel(home, br, srt, s, b);
429 }
430 }
431 break;
432 default:
433 GECODE_NEVER;
434 }
435 }
436
437 void
438 NNF::post(Home home, NodeType t, SetVarArgs& b, int& i) const {
439 if (this->t != t) {
440 switch (this->t) {
441 case SetExpr::NT_VAR:
442 if (neg) {
443 SetVar xc(home,IntSet::empty,
444 IntSet(Set::Limits::min,Set::Limits::max));
445 rel(home, xc, SRT_CMPL, u.a.x->x);
446 b[i++]=xc;
447 } else {
448 b[i++]=u.a.x->x;
449 }
450 break;
451 default:
452 {
453 SetVar s(home,IntSet::empty,
454 IntSet(Set::Limits::min,Set::Limits::max));
455 post(home,SRT_EQ,s);
456 b[i++] = s;
457 }
458 break;
459 }
460 } else {
461 u.b.l->post(home, t, b, i);
462 u.b.r->post(home, t, b, i);
463 }
464 }
465
466 void
467 NNF::post(Home home, SetRelType srt, const NNF* n) const {
468 if (n->t == SetExpr::NT_VAR && !n->neg) {
469 post(home,srt,n->u.a.x->x);
470 } else if (t == SetExpr::NT_VAR && !neg) {
471 SetRelType n_srt;
472 switch (srt) {
473 case SRT_SUB: n_srt = SRT_SUP; break;
474 case SRT_SUP: n_srt = SRT_SUB; break;
475 default: n_srt = srt;
476 }
477 n->post(home,n_srt,this);
478 } else {
479 SetVar nx(home,IntSet::empty,
480 IntSet(Set::Limits::min,Set::Limits::max));
481 n->post(home,SRT_EQ,nx);
482 post(home,srt,nx);
483 }
484 }
485
486 void
487 NNF::post(Home home, BoolVar b, bool pt,
488 SetRelType srt, const NNF* n) const {
489 if (pt) {
490 if (n->t == SetExpr::NT_VAR && !n->neg) {
491 post(home,srt,n->u.a.x->x,b);
492 } else if (t == SetExpr::NT_VAR && !neg) {
493 SetRelType n_srt;
494 switch (srt) {
495 case SRT_SUB: n_srt = SRT_SUP; break;
496 case SRT_SUP: n_srt = SRT_SUB; break;
497 default: n_srt = srt;
498 }
499 n->post(home,b,true,n_srt,this);
500 } else {
501 SetVar nx(home,IntSet::empty,
502 IntSet(Set::Limits::min,Set::Limits::max));
503 n->post(home,SRT_EQ,nx);
504 post(home,srt,nx,b);
505 }
506 } else if (srt == SRT_EQ) {
507 post(home,b,true,SRT_NQ,n);
508 } else if (srt == SRT_NQ) {
509 post(home,b,true,SRT_EQ,n);
510 } else {
511 BoolVar nb(home,0,1);
512 rel(home,b,IRT_NQ,nb);
513 post(home,nb,true,srt,n);
514 }
515 }
516
517 NNF*
518 NNF::nnf(Region& r, Node* n, bool neg) {
519 switch (n->t) {
520 case SetExpr::NT_VAR:
521 case SetExpr::NT_CONST:
522 case SetExpr::NT_LEXP:
523 {
524 NNF* x = new (r) NNF;
525 x->t = n->t; x->neg = neg; x->u.a.x = n;
526 if (neg) {
527 x->p = 0; x->n = 1;
528 } else {
529 x->p = 1; x->n = 0;
530 }
531 return x;
532 }
533 case SetExpr::NT_CMPL:
534 return nnf(r,n->l,!neg);
535 case SetExpr::NT_INTER:
536 case SetExpr::NT_UNION:
537 case SetExpr::NT_DUNION:
538 {
539 NodeType t; bool xneg;
540 if (n->t == SetExpr::NT_DUNION) {
541 t = n->t; xneg = neg; neg = false;
542 } else {
543 t = ((n->t == SetExpr::NT_INTER) == neg) ?
544 SetExpr::NT_UNION : SetExpr::NT_INTER;
545 xneg = false;
546 }
547 NNF* x = new (r) NNF;
548 x->neg = xneg;
549 x->t = t;
550 x->u.b.l = nnf(r,n->l,neg);
551 x->u.b.r = nnf(r,n->r,neg);
552 int p_l, n_l;
553 if ((x->u.b.l->t == t) || (x->u.b.l->t == SetExpr::NT_VAR)) {
554 p_l=x->u.b.l->p; n_l=x->u.b.l->n;
555 } else {
556 p_l=1; n_l=0;
557 }
558 int p_r, n_r;
559 if ((x->u.b.r->t == t) || (x->u.b.r->t == SetExpr::NT_VAR)) {
560 p_r=x->u.b.r->p; n_r=x->u.b.r->n;
561 } else {
562 p_r=1; n_r=0;
563 }
564 x->p = p_l+p_r;
565 x->n = n_l+n_r;
566 return x;
567 }
568 default:
569 GECODE_NEVER;
570 }
571 GECODE_NEVER;
572 return nullptr;
573 }
574 }
575
576 SetExpr::SetExpr(const SetVar& x) : n(new Node) {
577 n->same = 1;
578 n->t = NT_VAR;
579 n->l = nullptr;
580 n->r = nullptr;
581 n->x = x;
582 }
583
584 SetExpr::SetExpr(const IntSet& s) : n(new Node) {
585 n->same = 1;
586 n->t = NT_CONST;
587 n->l = nullptr;
588 n->r = nullptr;
589 n->s = s;
590 }
591
592 SetExpr::SetExpr(const LinIntExpr& e) : n(new Node) {
593 n->same = 1;
594 n->t = NT_LEXP;
595 n->l = nullptr;
596 n->r = nullptr;
597 n->e = e;
598 }
599
600 SetExpr::SetExpr(const SetExpr& l, NodeType t, const SetExpr& r)
601 : n(new Node) {
602 int ls = same(t,l.n->t) ? l.n->same : 1;
603 int rs = same(t,r.n->t) ? r.n->same : 1;
604 n->same = ls+rs;
605 n->t = t;
606 n->l = l.n;
607 n->l->use++;
608 n->r = r.n;
609 n->r->use++;
610 }
611
612 SetExpr::SetExpr(const SetExpr& l, NodeType t) {
613 (void) t;
614 assert(t == NT_CMPL);
615 if (l.n->t == NT_CMPL) {
616 n = l.n->l;
617 n->use++;
618 } else {
619 n = new Node;
620 n->same = 1;
621 n->t = NT_CMPL;
622 n->l = l.n;
623 n->l->use++;
624 n->r = nullptr;
625 }
626 }
627
628 const SetExpr&
629 SetExpr::operator =(const SetExpr& e) {
630 if (this != &e) {
631 if (n != nullptr && n->decrement())
632 delete n;
633 n = e.n;
634 n->use++;
635 }
636 return *this;
637 }
638
639 SetExpr::~SetExpr(void) {
640 if (n != nullptr && n->decrement())
641 delete n;
642 }
643
644 SetExpr::SetExpr(const SetExpr& e) : n(e.n) {
645 n->use++;
646 }
647
648 SetVar
649 SetExpr::post(Home home) const {
650 Region r;
651 SetVar s(home,IntSet::empty,
652 IntSet(Set::Limits::min,Set::Limits::max));
653 NNF::nnf(r,n,false)->post(home,SRT_EQ,s);
654 return s;
655 }
656
657 void
658 SetExpr::post(Home home, SetRelType srt, const SetExpr& e) const {
659 Region r;
660 return NNF::nnf(r,n,false)->post(home,srt,NNF::nnf(r,e.n,false));
661 }
662 void
663 SetExpr::post(Home home, BoolVar b, bool t,
664 SetRelType srt, const SetExpr& e) const {
665 Region r;
666 return NNF::nnf(r,n,false)->post(home,b,t,srt,
667 NNF::nnf(r,e.n,false));
668 }
669
670 SetExpr
671 operator &(const SetExpr& l, const SetExpr& r) {
672 return SetExpr(l,SetExpr::NT_INTER,r);
673 }
674 SetExpr
675 operator |(const SetExpr& l, const SetExpr& r) {
676 return SetExpr(l,SetExpr::NT_UNION,r);
677 }
678 SetExpr
679 operator +(const SetExpr& l, const SetExpr& r) {
680 return SetExpr(l,SetExpr::NT_DUNION,r);
681 }
682 SetExpr
683 operator -(const SetExpr& e) {
684 return SetExpr(e,SetExpr::NT_CMPL);
685 }
686 SetExpr
687 operator -(const SetExpr& l, const SetExpr& r) {
688 return SetExpr(l,SetExpr::NT_INTER,-r);
689 }
690 SetExpr
691 singleton(const LinIntExpr& e) {
692 return SetExpr(e);
693 }
694
695 SetExpr
696 inter(const SetVarArgs& x) {
697 if (x.size() == 0)
698 return SetExpr(IntSet(Set::Limits::min,Set::Limits::max));
699 SetExpr r(x[0]);
700 for (int i=1; i<x.size(); i++)
701 r = (r & x[i]);
702 return r;
703 }
704 SetExpr
705 setunion(const SetVarArgs& x) {
706 if (x.size() == 0)
707 return SetExpr(IntSet::empty);
708 SetExpr r(x[0]);
709 for (int i=1; i<x.size(); i++)
710 r = (r | x[i]);
711 return r;
712 }
713 SetExpr
714 setdunion(const SetVarArgs& x) {
715 if (x.size() == 0)
716 return SetExpr(IntSet::empty);
717 SetExpr r(x[0]);
718 for (int i=1; i<x.size(); i++)
719 r = (r + x[i]);
720 return r;
721 }
722
723 namespace MiniModel {
724 /// Integer valued set expressions
725 class GECODE_MINIMODEL_EXPORT SetNonLinIntExpr : public NonLinIntExpr {
726 public:
727 /// The expression type
728 enum SetNonLinIntExprType {
729 SNLE_CARD, ///< Cardinality expression
730 SNLE_MIN, ///< Minimum element expression
731 SNLE_MAX ///< Maximum element expression
732 } t;
733 /// The expression
734 SetExpr e;
735 /// Constructor
736 SetNonLinIntExpr(const SetExpr& e0, SetNonLinIntExprType t0)
737 : t(t0), e(e0) {}
738 /// Post expression
739 virtual IntVar post(Home home, IntVar* ret,
740 const IntPropLevels&) const {
741 IntVar m = result(home,ret);
742 switch (t) {
743 case SNLE_CARD:
744 cardinality(home, e.post(home), m);
745 break;
746 case SNLE_MIN:
747 min(home, e.post(home), m);
748 break;
749 case SNLE_MAX:
750 max(home, e.post(home), m);
751 break;
752 default:
753 GECODE_NEVER;
754 break;
755 }
756 return m;
757 }
758 virtual void post(Home home, IntRelType irt, int c,
759 const IntPropLevels& ipls) const {
760 if (t==SNLE_CARD && irt!=IRT_NQ) {
761 switch (irt) {
762 case IRT_LQ:
763 cardinality(home, e.post(home),
764 0U,
765 static_cast<unsigned int>(c));
766 break;
767 case IRT_LE:
768 cardinality(home, e.post(home),
769 0U,
770 static_cast<unsigned int>(c-1));
771 break;
772 case IRT_GQ:
773 cardinality(home, e.post(home),
774 static_cast<unsigned int>(c),
775 Set::Limits::card);
776 break;
777 case IRT_GR:
778 cardinality(home, e.post(home),
779 static_cast<unsigned int>(c+1),
780 Set::Limits::card);
781 break;
782 case IRT_EQ:
783 cardinality(home, e.post(home),
784 static_cast<unsigned int>(c),
785 static_cast<unsigned int>(c));
786 break;
787 default:
788 GECODE_NEVER;
789 }
790 } else if (t==SNLE_MIN && (irt==IRT_GR || irt==IRT_GQ)) {
791 c = (irt==IRT_GQ ? c : c+1);
792 dom(home, e.post(home), SRT_SUB, c, Set::Limits::max);
793 } else if (t==SNLE_MAX && (irt==IRT_LE || irt==IRT_LQ)) {
794 c = (irt==IRT_LQ ? c : c-1);
795 dom(home, e.post(home), SRT_SUB, Set::Limits::min, c);
796 } else {
797 rel(home, post(home,nullptr,ipls), irt, c);
798 }
799 }
800 virtual void post(Home home, IntRelType irt, int c,
801 BoolVar b,
802 const IntPropLevels& ipls) const {
803 if (t==SNLE_MIN && (irt==IRT_GR || irt==IRT_GQ)) {
804 c = (irt==IRT_GQ ? c : c+1);
805 dom(home, e.post(home), SRT_SUB, c, Set::Limits::max, b);
806 } else if (t==SNLE_MAX && (irt==IRT_LE || irt==IRT_LQ)) {
807 c = (irt==IRT_LQ ? c : c-1);
808 dom(home, e.post(home), SRT_SUB, Set::Limits::min, c, b);
809 } else {
810 rel(home, post(home,nullptr,ipls), irt, c, b);
811 }
812 }
813 };
814 }
815
816 LinIntExpr
817 cardinality(const SetExpr& e) {
818 return LinIntExpr(new MiniModel::SetNonLinIntExpr(e,
819 MiniModel::SetNonLinIntExpr::SNLE_CARD));
820 }
821 LinIntExpr
822 min(const SetExpr& e) {
823 return LinIntExpr(new MiniModel::SetNonLinIntExpr(e,
824 MiniModel::SetNonLinIntExpr::SNLE_MIN));
825 }
826 LinIntExpr
827 max(const SetExpr& e) {
828 return LinIntExpr(new MiniModel::SetNonLinIntExpr(e,
829 MiniModel::SetNonLinIntExpr::SNLE_MAX));
830 }
831
832 /*
833 * Posting set expressions
834 *
835 */
836 SetVar
837 expr(Home home, const SetExpr& e) {
838 PostInfo pi(home);
839 if (!home.failed())
840 return e.post(home);
841 SetVar x(home,IntSet::empty,IntSet::empty);
842 return x;
843 }
844
845}
846
847#endif
848
849// STATISTICS: minimodel-any