Generated on Thu Mar 22 10:39:43 2012 for Gecode by doxygen 1.6.3

set-expr.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Guido Tack, 2010
00009  *     Christian Schulte, 2004
00010  *
00011  *  Last modified:
00012  *     $Date: 2011-01-21 16:01:14 +0100 (Fri, 21 Jan 2011) $ by $Author: schulte $
00013  *     $Revision: 11553 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <gecode/minimodel.hh>
00041 
00042 #ifdef GECODE_HAS_SET_VARS
00043 
00044 namespace Gecode {
00045 
00046   /*
00047    * Operations for nodes
00048    *
00049    */
00050   bool
00051   SetExpr::Node::decrement(void) {
00052     if (--use == 0) {
00053       if ((l != NULL) && l->decrement())
00054         delete l;
00055       if ((r != NULL) && r->decrement())
00056         delete r;
00057       return true;
00058     }
00059     return false;
00060   }
00061 
00062 
00063   SetExpr::SetExpr(const SetVar& x) : n(new Node) {
00064     n->same = 1;
00065     n->t    = NT_VAR;
00066     n->l    = NULL;
00067     n->r    = NULL;
00068     n->x    = x;
00069   }
00070 
00071   SetExpr::SetExpr(const IntSet& s) : n(new Node) {
00072     n->same = 1;
00073     n->t    = NT_CONST;
00074     n->l    = NULL;
00075     n->r    = NULL;
00076     n->s    = s;
00077   }
00078 
00079   SetExpr::SetExpr(const LinExpr& e) : n(new Node) {
00080     n->same = 1;
00081     n->t    = NT_LEXP;
00082     n->l    = NULL;
00083     n->r    = NULL;
00084     n->e    = e;
00085   }
00086   
00087   SetExpr::SetExpr(const SetExpr& l, NodeType t, const SetExpr& r)
00088     : n(new Node) {
00089     int ls = same(t,l.n->t) ? l.n->same : 1;
00090     int rs = same(t,r.n->t) ? r.n->same : 1;
00091     n->same = ls+rs;
00092     n->t    = t;
00093     n->l    = l.n;
00094     n->l->use++;
00095     n->r    = r.n;
00096     n->r->use++;
00097   }
00098 
00099   SetExpr::SetExpr(const SetExpr& l, NodeType t) {
00100     (void) t;
00101     assert(t == NT_CMPL);
00102     if (l.n->t == NT_CMPL) {
00103       n = l.n->l;
00104       n->use++;
00105     } else {
00106       n = new Node;
00107       n->same = 1;
00108       n->t    = NT_CMPL;
00109       n->l    = l.n;
00110       n->l->use++;
00111       n->r    = NULL;
00112     }
00113   }
00114 
00115   const SetExpr&
00116   SetExpr::operator =(const SetExpr& e) {
00117     if (this != &e) {
00118       if (n != NULL && n->decrement())
00119         delete n;
00120       n = e.n;
00121       n->use++;
00122     }
00123     return *this;
00124   }
00125 
00126   SetExpr::~SetExpr(void) {
00127     if (n != NULL && n->decrement())
00128       delete n;
00129   }
00130 
00131   /*
00132    * Operations for negation normalform
00133    *
00134    */
00135   forceinline void
00136   SetExpr::NNF::operator delete(void*) {}
00137 
00138   forceinline void
00139   SetExpr::NNF::operator delete(void*, Region&) {}
00140 
00141   forceinline void*
00142   SetExpr::NNF::operator new(size_t s, Region& r) {
00143     return r.ralloc(s);
00144   }
00145 
00146   void
00147   SetExpr::NNF::post(Home home, SetRelType srt, SetVar s) const {
00148     switch (t) {
00149     case NT_VAR:
00150       if (neg) {
00151         switch (srt) {
00152         case SRT_EQ:
00153           rel(home, u.a.x->x, SRT_CMPL, s);
00154           break;
00155         case SRT_CMPL:
00156           rel(home, u.a.x->x, SRT_EQ, s);
00157           break;
00158         default:
00159           SetVar bc(home,IntSet::empty,
00160                     IntSet(Set::Limits::min,Set::Limits::max));
00161           rel(home, s, SRT_CMPL, bc);
00162           rel(home, u.a.x->x, srt, bc);
00163           break;
00164         }
00165       } else
00166         rel(home, u.a.x->x, srt, s);
00167       break;
00168     case NT_CONST:
00169       {
00170         IntSet ss;
00171         if (neg) {
00172           IntSetRanges sr(u.a.x->s);
00173           Set::RangesCompl<IntSetRanges> src(sr);
00174           ss = IntSet(src);
00175         } else {
00176           ss = u.a.x->s;
00177         }
00178         switch (srt) {
00179         case SRT_SUB: srt = SRT_SUP; break;
00180         case SRT_SUP: srt = SRT_SUB; break;
00181         default: break;
00182         }
00183         dom(home, s, srt, ss);
00184       }
00185       break;
00186     case NT_LEXP:
00187       {
00188         IntVar iv = u.a.x->e.post(home,ICL_DEF);
00189         if (neg) {
00190           SetVar ic(home,IntSet::empty,
00191                     IntSet(Set::Limits::min,Set::Limits::max));
00192           rel(home, iv, SRT_CMPL, ic);
00193           rel(home,ic,srt,s);
00194         } else {
00195           rel(home,iv,srt,s);
00196         }
00197       }
00198       break;
00199     case NT_INTER:
00200       {
00201         SetVarArgs bs(p+n);
00202         int i=0;
00203         post(home, NT_INTER, bs, i);
00204         if (i == 2) {
00205           rel(home, bs[0], SOT_INTER, bs[1], srt, s);
00206         } else {
00207           if (srt == SRT_EQ)
00208             rel(home, SOT_INTER, bs, s);
00209           else {
00210             SetVar bc(home,IntSet::empty,
00211                       IntSet(Set::Limits::min,Set::Limits::max));
00212             rel(home, SOT_INTER, bs, bc);
00213             rel(home, bc, srt, s);
00214           }
00215         }
00216       }
00217       break;
00218     case NT_UNION:
00219       {
00220         SetVarArgs bs(p+n);
00221         int i=0;
00222         post(home, NT_UNION, bs, i);
00223         if (i == 2) {
00224           rel(home, bs[0], SOT_UNION, bs[1], srt, s);
00225         } else {
00226           if (srt == SRT_EQ)
00227             rel(home, SOT_UNION, bs, s);
00228           else {
00229             SetVar bc(home,IntSet::empty,
00230                       IntSet(Set::Limits::min,Set::Limits::max));
00231             rel(home, SOT_UNION, bs, bc);
00232             rel(home, bc, srt, s);
00233           }
00234         }
00235       }
00236       break;
00237     case NT_DUNION:
00238       {
00239         SetVarArgs bs(p+n);
00240         int i=0;
00241         post(home, NT_DUNION, bs, i);
00242 
00243         if (i == 2) {
00244           if (neg) {
00245             if (srt == SRT_CMPL) {
00246               rel(home, bs[0], SOT_DUNION, bs[1], srt, s);
00247             } else {
00248               SetVar bc(home,IntSet::empty,
00249                 IntSet(Set::Limits::min,Set::Limits::max));
00250               rel(home,s,SRT_CMPL,bc);
00251               rel(home, bs[0], SOT_DUNION, bs[1], srt, bc);
00252             }
00253           } else {
00254             rel(home, bs[0], SOT_DUNION, bs[1], srt, s);
00255           }
00256         } else {
00257           if (neg) {
00258             if (srt == SRT_CMPL) {
00259               rel(home, SOT_DUNION, bs, s);
00260             } else {
00261               SetVar br(home,IntSet::empty,
00262                         IntSet(Set::Limits::min,Set::Limits::max));
00263               rel(home, SOT_DUNION, bs, br);
00264               if (srt == SRT_EQ)
00265                 rel(home, br, SRT_CMPL, s);
00266               else {
00267                 SetVar bc(home,IntSet::empty,
00268                           IntSet(Set::Limits::min,Set::Limits::max));
00269                 rel(home, br, srt, bc);
00270                 rel(home, bc, SRT_CMPL, s);
00271               }
00272             }
00273           } else {
00274             if (srt == SRT_EQ)
00275               rel(home, SOT_DUNION, bs, s);
00276             else {
00277               SetVar br(home,IntSet::empty,
00278                         IntSet(Set::Limits::min,Set::Limits::max));
00279               rel(home, SOT_DUNION, bs, br);
00280               rel(home, br, srt, s);
00281             }
00282           }
00283         }
00284       }
00285       break;
00286     default:
00287       GECODE_NEVER;
00288     }
00289   }
00290 
00291   void
00292   SetExpr::NNF::post(Home home, SetRelType srt, SetVar s, BoolVar b) const {
00293     switch (t) {
00294     case NT_VAR:
00295       if (neg) {
00296         switch (srt) {
00297         case SRT_EQ:
00298           rel(home, u.a.x->x, SRT_CMPL, s, b);
00299           break;
00300         case SRT_CMPL:
00301           rel(home, u.a.x->x, SRT_EQ, s, b);
00302           break;
00303         default:
00304           SetVar bc(home,IntSet::empty,
00305                     IntSet(Set::Limits::min,Set::Limits::max));
00306           rel(home, s, SRT_CMPL, bc);
00307           rel(home, u.a.x->x, srt, bc, b);
00308           break;
00309         }
00310       } else
00311         rel(home, u.a.x->x, srt, s, b);
00312       break;
00313     case NT_CONST:
00314       {
00315         IntSet ss;
00316         if (neg) {
00317           IntSetRanges sr(u.a.x->s);
00318           Set::RangesCompl<IntSetRanges> src(sr);
00319           ss = IntSet(src);
00320         } else {
00321           ss = u.a.x->s;
00322         }
00323         dom(home, s, srt, ss, b);
00324       }
00325       break;
00326     case NT_LEXP:
00327       {
00328         IntVar iv = u.a.x->e.post(home,ICL_DEF);
00329         if (neg) {
00330           SetVar ic(home,IntSet::empty,
00331                     IntSet(Set::Limits::min,Set::Limits::max));
00332           rel(home, iv, SRT_CMPL, ic);
00333           rel(home,ic,srt,s,b);
00334         } else {
00335           rel(home,iv,srt,s,b);
00336         }
00337       }
00338     case NT_INTER:
00339       {
00340         SetVarArgs bs(p+n);
00341         int i=0;
00342         post(home, NT_INTER, bs, i);
00343         SetVar br(home,IntSet::empty,
00344                   IntSet(Set::Limits::min,Set::Limits::max));
00345         rel(home, SOT_INTER, bs, br);
00346         rel(home, br, srt, s, b);
00347       }
00348       break;
00349     case NT_UNION:
00350       {
00351         SetVarArgs bs(p+n);
00352         int i=0;
00353         post(home, NT_UNION, bs, i);
00354         SetVar br(home,IntSet::empty,
00355                   IntSet(Set::Limits::min,Set::Limits::max));
00356         rel(home, SOT_UNION, bs, br);
00357         rel(home, br, srt, s, b);
00358       }
00359       break;
00360     case NT_DUNION:
00361       {
00362         SetVarArgs bs(p+n);
00363         int i=0;
00364         post(home, NT_DUNION, bs, i);
00365 
00366         if (neg) {
00367           SetVar br(home,IntSet::empty,
00368                     IntSet(Set::Limits::min,Set::Limits::max));
00369           rel(home, SOT_DUNION, bs, br);
00370           if (srt == SRT_CMPL)
00371             rel(home, br, SRT_EQ, s, b);
00372           else if (srt == SRT_EQ)
00373             rel(home, br, SRT_CMPL, s, b);
00374           else {
00375             SetVar bc(home,IntSet::empty,
00376                       IntSet(Set::Limits::min,Set::Limits::max));
00377             rel(home, br, srt, bc);
00378             rel(home, bc, SRT_CMPL, s, b);
00379           }
00380         } else {
00381           SetVar br(home,IntSet::empty,
00382                     IntSet(Set::Limits::min,Set::Limits::max));
00383           rel(home, SOT_DUNION, bs, br);
00384           rel(home, br, srt, s, b);
00385         }
00386       }
00387       break;
00388     default:
00389       GECODE_NEVER;
00390     }
00391   }
00392 
00393   void
00394   SetExpr::NNF::post(Home home, NodeType t,
00395                      SetVarArgs& b, int& i) const {
00396     if (this->t != t) {
00397       switch (this->t) {
00398       case NT_VAR:
00399         if (neg) {
00400           SetVar xc(home,IntSet::empty,
00401                     IntSet(Set::Limits::min,Set::Limits::max));
00402           rel(home, xc, SRT_CMPL, u.a.x->x);
00403           b[i++]=xc;
00404         } else {
00405           b[i++]=u.a.x->x;
00406         }
00407         break;
00408       default:
00409         {
00410           SetVar s(home,IntSet::empty,
00411                    IntSet(Set::Limits::min,Set::Limits::max));
00412           post(home,SRT_EQ,s);
00413           b[i++] = s;
00414         }
00415         break;
00416       }
00417     } else {
00418       u.b.l->post(home, t, b, i);
00419       u.b.r->post(home, t, b, i);
00420     }
00421   }
00422 
00423   void
00424   SetExpr::NNF::post(Home home, SetRelType srt, const NNF* n) const {
00425     if (n->t == NT_VAR && !n->neg) {
00426       post(home,srt,n->u.a.x->x);
00427     } else if (t == NT_VAR && !neg) {
00428       SetRelType n_srt;
00429       switch (srt) {
00430       case SRT_SUB: n_srt = SRT_SUP; break;
00431       case SRT_SUP: n_srt = SRT_SUB; break;
00432       default: n_srt = srt;
00433       }
00434       n->post(home,n_srt,this);
00435     } else {
00436       SetVar nx(home,IntSet::empty,
00437                 IntSet(Set::Limits::min,Set::Limits::max));
00438       n->post(home,SRT_EQ,nx);
00439       post(home,srt,nx);
00440     }
00441   }
00442 
00443   void
00444   SetExpr::NNF::post(Home home, BoolVar b, bool t,
00445                      SetRelType srt, const NNF* n) const {
00446     if (t) {
00447       if (n->t == NT_VAR && !n->neg) {
00448         post(home,srt,n->u.a.x->x,b);
00449       } else if (t == NT_VAR && !neg) {
00450         SetRelType n_srt;
00451         switch (srt) {
00452         case SRT_SUB: n_srt = SRT_SUP; break;
00453         case SRT_SUP: n_srt = SRT_SUB; break;
00454         default: n_srt = srt;
00455         }
00456         n->post(home,b,true,n_srt,this);
00457       } else {
00458         SetVar nx(home,IntSet::empty,
00459                   IntSet(Set::Limits::min,Set::Limits::max));
00460         n->post(home,SRT_EQ,nx);
00461         post(home,srt,nx,b);
00462       }
00463     } else if (srt == SRT_EQ) {
00464       post(home,b,true,SRT_NQ,n);
00465     } else if (srt == SRT_NQ) {
00466       post(home,b,true,SRT_EQ,n);
00467     } else {
00468       BoolVar nb(home,0,1);
00469       rel(home,b,IRT_NQ,nb);
00470       post(home,nb,true,srt,n);
00471     }
00472   }
00473 
00474   SetExpr::NNF*
00475   SetExpr::NNF::nnf(Region& r, Node* n, bool neg) {
00476     switch (n->t) {
00477     case NT_VAR: case NT_CONST: case NT_LEXP:
00478       {
00479         NNF* x = new (r) NNF;
00480         x->t = n->t; x->neg = neg; x->u.a.x = n;
00481         if (neg) {
00482           x->p = 0; x->n = 1;
00483         } else {
00484           x->p = 1; x->n = 0;
00485         }
00486         return x;
00487       }
00488     case NT_CMPL:
00489       return nnf(r,n->l,!neg);
00490     case NT_INTER: case NT_UNION: case NT_DUNION:
00491       {
00492         NodeType t; bool xneg;
00493         if (n->t == NT_DUNION) {
00494           t = n->t; xneg = neg; neg = false;
00495         } else {
00496           t = ((n->t == NT_INTER) == neg) ? NT_UNION : NT_INTER;
00497           xneg = false;
00498         }
00499         NNF* x = new (r) NNF;
00500         x->neg = xneg;
00501         x->t = t;
00502         x->u.b.l = nnf(r,n->l,neg);
00503         x->u.b.r = nnf(r,n->r,neg);
00504         int p_l, n_l;
00505         if ((x->u.b.l->t == t) || (x->u.b.l->t == NT_VAR)) {
00506           p_l=x->u.b.l->p; n_l=x->u.b.l->n;
00507         } else {
00508           p_l=1; n_l=0;
00509         }
00510         int p_r, n_r;
00511         if ((x->u.b.r->t == t) || (x->u.b.r->t == NT_VAR)) {
00512           p_r=x->u.b.r->p; n_r=x->u.b.r->n;
00513         } else {
00514           p_r=1; n_r=0;
00515         }
00516         x->p = p_l+p_r;
00517         x->n = n_l+n_r;
00518         return x;
00519       }
00520     default:
00521       GECODE_NEVER;
00522     }
00523     GECODE_NEVER;
00524     return NULL;
00525   }
00526 
00527 
00528   SetExpr
00529   operator &(const SetExpr& l, const SetExpr& r) {
00530     return SetExpr(l,SetExpr::NT_INTER,r);
00531   }
00532   SetExpr
00533   operator |(const SetExpr& l, const SetExpr& r) {
00534     return SetExpr(l,SetExpr::NT_UNION,r);
00535   }
00536   SetExpr
00537   operator +(const SetExpr& l, const SetExpr& r) {
00538     return SetExpr(l,SetExpr::NT_DUNION,r);
00539   }
00540   SetExpr
00541   operator -(const SetExpr& e) {
00542     return SetExpr(e,SetExpr::NT_CMPL);
00543   }
00544   SetExpr
00545   operator -(const SetExpr& l, const SetExpr& r) {
00546     return SetExpr(l,SetExpr::NT_INTER,-r);
00547   }
00548   SetExpr
00549   singleton(const LinExpr& e) {
00550     return SetExpr(e);
00551   }
00552 
00553   SetExpr
00554   inter(const SetVarArgs& x) {
00555     if (x.size() == 0)
00556       return SetExpr(IntSet(Set::Limits::min,Set::Limits::max));
00557     SetExpr r(x[0]);
00558     for (int i=1; i<x.size(); i++)
00559       r = (r & x[i]);
00560     return r;
00561   }
00562   SetExpr
00563   setunion(const SetVarArgs& x) {
00564     if (x.size() == 0)
00565       return SetExpr(IntSet::empty);
00566     SetExpr r(x[0]);
00567     for (int i=1; i<x.size(); i++)
00568       r = (r | x[i]);
00569     return r;    
00570   }
00571   SetExpr
00572   setdunion(const SetVarArgs& x) {
00573     if (x.size() == 0)
00574       return SetExpr(IntSet::empty);
00575     SetExpr r(x[0]);
00576     for (int i=1; i<x.size(); i++)
00577       r = (r + x[i]);
00578     return r;    
00579   }
00580 
00581   namespace MiniModel {
00583     class GECODE_MINIMODEL_EXPORT SetNonLinExpr : public NonLinExpr {
00584     public:
00586       enum SetNonLinExprType {
00587         SNLE_CARD, 
00588         SNLE_MIN,  
00589         SNLE_MAX   
00590       } t;
00592       SetExpr e;
00594       SetNonLinExpr(const SetExpr& e0, SetNonLinExprType t0)
00595         : t(t0), e(e0) {}
00597       virtual IntVar post(Home home, IntVar* ret, IntConLevel) const {
00598         IntVar m = result(home,ret);
00599         switch (t) {
00600         case SNLE_CARD:
00601           cardinality(home, e.post(home), m);
00602           break;
00603         case SNLE_MIN:
00604           min(home, e.post(home), m);
00605           break;
00606         case SNLE_MAX:
00607           max(home, e.post(home), m);
00608           break;
00609         default:
00610           GECODE_NEVER;
00611           break;
00612         }
00613         return m;
00614       }
00615       virtual void post(Home home, IntRelType irt, int c,
00616                         IntConLevel icl) const {
00617         if (t==SNLE_CARD && irt!=IRT_NQ) {
00618           switch (irt) {
00619           case IRT_LQ:
00620             cardinality(home, e.post(home), 
00621                         0U, 
00622                         static_cast<unsigned int>(c));
00623             break;
00624           case IRT_LE:
00625             cardinality(home, e.post(home), 
00626                         0U, 
00627                         static_cast<unsigned int>(c-1));
00628             break;
00629           case IRT_GQ:
00630             cardinality(home, e.post(home), 
00631                         static_cast<unsigned int>(c), 
00632                         Set::Limits::card);
00633             break;
00634           case IRT_GR:
00635             cardinality(home, e.post(home), 
00636                         static_cast<unsigned int>(c+1), 
00637                         Set::Limits::card);
00638             break;
00639           case IRT_EQ:
00640             cardinality(home, e.post(home), 
00641                         static_cast<unsigned int>(c),
00642                         static_cast<unsigned int>(c));
00643             break;
00644           default:
00645             GECODE_NEVER;
00646           }
00647         } else if (t==SNLE_MIN && (irt==IRT_GR || irt==IRT_GQ)) {
00648           c = (irt==IRT_GQ ? c : c+1);
00649           dom(home, e.post(home), SRT_SUB, c, Set::Limits::max);
00650         } else if (t==SNLE_MAX && (irt==IRT_LE || irt==IRT_LQ)) {
00651           c = (irt==IRT_LQ ? c : c-1);
00652           dom(home, e.post(home), SRT_SUB, Set::Limits::min, c);
00653         } else {
00654           rel(home, post(home,NULL,icl), irt, c);
00655         }
00656       }
00657       virtual void post(Home home, IntRelType irt, int c,
00658                         BoolVar b, IntConLevel icl) const {
00659         if (t==SNLE_MIN && (irt==IRT_GR || irt==IRT_GQ)) {
00660           c = (irt==IRT_GQ ? c : c+1);
00661           dom(home, e.post(home), SRT_SUB, c, Set::Limits::max, b);
00662         } else if (t==SNLE_MAX && (irt==IRT_LE || irt==IRT_LQ)) {
00663           c = (irt==IRT_LQ ? c : c-1);
00664           dom(home, e.post(home), SRT_SUB, Set::Limits::min, c, b);
00665         } else {
00666           rel(home, post(home,NULL,icl), irt, c, b);
00667         }
00668       }
00669     };
00670   }
00671 
00672   LinExpr
00673   cardinality(const SetExpr& e) {
00674     return LinExpr(new MiniModel::SetNonLinExpr(e,
00675       MiniModel::SetNonLinExpr::SNLE_CARD));
00676   }
00677   LinExpr
00678   min(const SetExpr& e) {
00679     return LinExpr(new MiniModel::SetNonLinExpr(e,
00680       MiniModel::SetNonLinExpr::SNLE_MIN));
00681   }
00682   LinExpr
00683   max(const SetExpr& e) {
00684     return LinExpr(new MiniModel::SetNonLinExpr(e,
00685       MiniModel::SetNonLinExpr::SNLE_MAX));
00686   }
00687 
00688   /*
00689    * Posting set expressions
00690    *
00691    */
00692   SetVar
00693   expr(Home home, const SetExpr& e) {
00694     if (!home.failed())
00695       return e.post(home);
00696     SetVar x(home,IntSet::empty,IntSet::empty);
00697     return x;
00698   }
00699 
00700 }
00701 
00702 #endif
00703 
00704 // STATISTICS: minimodel-any