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

registry.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  *
00006  *  Contributing authors:
00007  *     Mikael Lagerkvist <lagerkvist@gmail.com>
00008  *
00009  *  Copyright:
00010  *     Guido Tack, 2007
00011  *     Mikael Lagerkvist, 2009
00012  *
00013  *  Last modified:
00014  *     $Date: 2012-03-21 06:25:08 +0100 (Wed, 21 Mar 2012) $ by $Author: tack $
00015  *     $Revision: 12605 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */
00041 
00042 #include <gecode/flatzinc/registry.hh>
00043 #include <gecode/kernel.hh>
00044 #include <gecode/int.hh>
00045 #include <gecode/minimodel.hh>
00046 #ifdef GECODE_HAS_SET_VARS
00047 #include <gecode/set.hh>
00048 #endif
00049 #include <gecode/flatzinc.hh>
00050 
00051 namespace Gecode { namespace FlatZinc {
00052 
00053   Registry& registry(void) {
00054     static Registry r;
00055     return r;
00056   }
00057 
00058   void
00059   Registry::post(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00060     std::map<std::string,poster>::iterator i = r.find(ce.id);
00061     if (i == r.end()) {
00062       throw FlatZinc::Error("Registry",
00063         std::string("Constraint ")+ce.id+" not found");
00064     }
00065     i->second(s, ce, ann);
00066   }
00067 
00068   void
00069   Registry::add(const std::string& id, poster p) {
00070     r[id] = p;
00071   }
00072 
00073   namespace {
00074   
00075     IntConLevel ann2icl(AST::Node* ann) {
00076       if (ann) {
00077         if (ann->hasAtom("val"))
00078           return ICL_VAL;
00079         if (ann->hasAtom("domain"))
00080           return ICL_DOM;
00081         if (ann->hasAtom("bounds") ||
00082             ann->hasAtom("boundsR") ||
00083             ann->hasAtom("boundsD") ||
00084             ann->hasAtom("boundsZ"))
00085           return ICL_BND;
00086       }
00087       return ICL_DEF;
00088     }
00089   
00090     inline IntRelType
00091     swap(IntRelType irt) {
00092       switch (irt) {
00093       case IRT_LQ: return IRT_GQ;
00094       case IRT_LE: return IRT_GR;
00095       case IRT_GQ: return IRT_LQ;
00096       case IRT_GR: return IRT_LE;
00097       default:     return irt;
00098       }
00099     }
00100 
00101     inline IntRelType
00102     neg(IntRelType irt) {
00103       switch (irt) {
00104       case IRT_EQ: return IRT_NQ;
00105       case IRT_NQ: return IRT_EQ;
00106       case IRT_LQ: return IRT_GR;
00107       case IRT_LE: return IRT_GQ;
00108       case IRT_GQ: return IRT_LE;
00109       case IRT_GR:
00110       default:
00111         assert(irt == IRT_GR);
00112       }
00113       return IRT_LQ;
00114     }
00115 
00116     inline IntArgs arg2intargs(AST::Node* arg, int offset = 0) {
00117       AST::Array* a = arg->getArray();
00118       IntArgs ia(a->a.size()+offset);
00119       for (int i=offset; i--;)
00120         ia[i] = 0;
00121       for (int i=a->a.size(); i--;)
00122         ia[i+offset] = a->a[i]->getInt();
00123       return ia;
00124     }
00125 
00126     inline IntArgs arg2boolargs(AST::Node* arg, int offset = 0) {
00127       AST::Array* a = arg->getArray();
00128       IntArgs ia(a->a.size()+offset);
00129       for (int i=offset; i--;)
00130         ia[i] = 0;
00131       for (int i=a->a.size(); i--;)
00132         ia[i+offset] = a->a[i]->getBool();
00133       return ia;
00134     }
00135 
00136     inline IntSet arg2intset(FlatZincSpace& s, AST::Node* n) {
00137       AST::SetLit* sl = n->getSet();
00138       IntSet d;
00139       if (sl->interval) {
00140         d = IntSet(sl->min, sl->max);
00141       } else {
00142         Region re(s);
00143         int* is = re.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
00144         for (int i=sl->s.size(); i--; )
00145           is[i] = sl->s[i];
00146         d = IntSet(is, sl->s.size());
00147       }
00148       return d;
00149     }
00150 
00151     inline IntSetArgs arg2intsetargs(FlatZincSpace& s,
00152                                      AST::Node* arg, int offset = 0) {
00153       AST::Array* a = arg->getArray();
00154       if (a->a.size() == 0) {
00155         IntSetArgs emptyIa(0);
00156         return emptyIa;
00157       }
00158       IntSetArgs ia(a->a.size()+offset);      
00159       for (int i=offset; i--;)
00160         ia[i] = IntSet::empty;
00161       for (int i=a->a.size(); i--;) {
00162         ia[i+offset] = arg2intset(s, a->a[i]);
00163       }
00164       return ia;
00165     }
00166   
00167     inline IntVarArgs arg2intvarargs(FlatZincSpace& s, AST::Node* arg,
00168                                      int offset = 0) {
00169       AST::Array* a = arg->getArray();
00170       if (a->a.size() == 0) {
00171         IntVarArgs emptyIa(0);
00172         return emptyIa;
00173       }
00174       IntVarArgs ia(a->a.size()+offset);
00175       for (int i=offset; i--;)
00176         ia[i] = IntVar(s, 0, 0);
00177       for (int i=a->a.size(); i--;) {
00178         if (a->a[i]->isIntVar()) {
00179           ia[i+offset] = s.iv[a->a[i]->getIntVar()];        
00180         } else {
00181           int value = a->a[i]->getInt();
00182           IntVar iv(s, value, value);
00183           ia[i+offset] = iv;        
00184         }
00185       }
00186       return ia;
00187     }
00188 
00189     inline BoolVarArgs arg2boolvarargs(FlatZincSpace& s, AST::Node* arg,
00190                                        int offset = 0, int siv=-1) {
00191       AST::Array* a = arg->getArray();
00192       if (a->a.size() == 0) {
00193         BoolVarArgs emptyIa(0);
00194         return emptyIa;
00195       }
00196       BoolVarArgs ia(a->a.size()+offset-(siv==-1?0:1));
00197       for (int i=offset; i--;)
00198         ia[i] = BoolVar(s, 0, 0);
00199       for (int i=0; i<static_cast<int>(a->a.size()); i++) {
00200         if (i==siv)
00201           continue;
00202         if (a->a[i]->isBool()) {
00203           bool value = a->a[i]->getBool();
00204           BoolVar iv(s, value, value);
00205           ia[offset++] = iv;
00206         } else if (a->a[i]->isIntVar() &&
00207                    s.aliasBool2Int(a->a[i]->getIntVar()) != -1) {
00208           ia[offset++] = s.bv[s.aliasBool2Int(a->a[i]->getIntVar())];
00209         } else {
00210           ia[offset++] = s.bv[a->a[i]->getBoolVar()];
00211         }
00212       }
00213       return ia;
00214     }
00215 
00216 #ifdef GECODE_HAS_SET_VARS
00217     SetVar getSetVar(FlatZincSpace& s, AST::Node* n) {
00218       SetVar x0;
00219       if (!n->isSetVar()) {
00220         IntSet d = arg2intset(s,n);
00221         x0 = SetVar(s, d, d);        
00222       } else {
00223         x0 = s.sv[n->getSetVar()];
00224       }
00225       return x0;
00226     }
00227 
00228     inline SetVarArgs arg2setvarargs(FlatZincSpace& s, AST::Node* arg,
00229                                      int offset = 0, int doffset = 0,
00230                                      const IntSet& od=IntSet::empty) {
00231       AST::Array* a = arg->getArray();
00232       SetVarArgs ia(a->a.size()+offset);
00233       for (int i=offset; i--;) {
00234         IntSet d = i<doffset ? od : IntSet::empty;
00235         ia[i] = SetVar(s, d, d);
00236       }
00237       for (int i=a->a.size(); i--;) {
00238         ia[i+offset] = getSetVar(s, a->a[i]);
00239       }
00240       return ia;
00241     }
00242 #endif
00243 
00244     BoolVar getBoolVar(FlatZincSpace& s, AST::Node* n) {
00245       BoolVar x0;
00246       if (n->isBool()) {
00247         x0 = BoolVar(s, n->getBool(), n->getBool());
00248       }
00249       else {
00250         x0 = s.bv[n->getBoolVar()];
00251       }
00252       return x0;
00253     }
00254 
00255     IntVar getIntVar(FlatZincSpace& s, AST::Node* n) {
00256       IntVar x0;
00257       if (n->isIntVar()) {
00258         x0 = s.iv[n->getIntVar()];
00259       } else {
00260         x0 = IntVar(s, n->getInt(), n->getInt());            
00261       }
00262       return x0;
00263     }
00264 
00265     bool isBoolArray(FlatZincSpace& s, AST::Node* b, int& singleInt) {
00266       AST::Array* a = b->getArray();
00267       singleInt = -1;
00268       if (a->a.size() == 0)
00269         return true;
00270       for (int i=a->a.size(); i--;) {
00271         if (a->a[i]->isBoolVar() || a->a[i]->isBool()) {
00272         } else if (a->a[i]->isIntVar()) {
00273           if (s.aliasBool2Int(a->a[i]->getIntVar()) == -1) {
00274             if (singleInt != -1) {
00275               return false;
00276             }
00277             singleInt = i;
00278           }
00279         } else {
00280           return false;
00281         }
00282       }
00283       return singleInt==-1 || a->a.size() > 1;
00284     }
00285 
00286     void p_distinct(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00287       IntVarArgs va = arg2intvarargs(s, ce[0]);
00288       IntConLevel icl = ann2icl(ann);
00289       distinct(s, va, icl == ICL_DEF ? ICL_BND : icl);
00290     }
00291     void p_distinctOffset(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00292       IntVarArgs va = arg2intvarargs(s, ce[1]);
00293       AST::Array* offs = ce.args->a[0]->getArray();
00294       IntArgs oa(offs->a.size());
00295       for (int i=offs->a.size(); i--; ) {
00296         oa[i] = offs->a[i]->getInt();    
00297       }
00298       IntConLevel icl = ann2icl(ann);
00299       distinct(s, oa, va, icl == ICL_DEF ? ICL_BND : icl);
00300     }
00301 
00302     void p_all_equal(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00303       IntVarArgs va = arg2intvarargs(s, ce[0]);
00304       rel(s, va, IRT_EQ, ann2icl(ann));
00305     }
00306 
00307     void p_int_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00308                    AST::Node* ann) {
00309       if (ce[0]->isIntVar()) {
00310         if (ce[1]->isIntVar()) {
00311           rel(s, getIntVar(s, ce[0]), irt, getIntVar(s, ce[1]), 
00312               ann2icl(ann));
00313         } else {
00314           rel(s, getIntVar(s, ce[0]), irt, ce[1]->getInt(), ann2icl(ann));
00315         }
00316       } else {
00317         rel(s, getIntVar(s, ce[1]), swap(irt), ce[0]->getInt(), 
00318             ann2icl(ann));
00319       }
00320     }
00321     void p_int_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00322       p_int_CMP(s, IRT_EQ, ce, ann);
00323     }
00324     void p_int_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00325       p_int_CMP(s, IRT_NQ, ce, ann);
00326     }
00327     void p_int_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00328       p_int_CMP(s, IRT_GQ, ce, ann);
00329     }
00330     void p_int_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00331       p_int_CMP(s, IRT_GR, ce, ann);
00332     }
00333     void p_int_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00334       p_int_CMP(s, IRT_LQ, ce, ann);
00335     }
00336     void p_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00337       p_int_CMP(s, IRT_LE, ce, ann);
00338     }
00339     void p_int_CMP_reif(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00340                         AST::Node* ann) {
00341       if (ce[2]->isBool()) {
00342         if (ce[2]->getBool()) {
00343           p_int_CMP(s, irt, ce, ann);
00344         } else {
00345           p_int_CMP(s, neg(irt), ce, ann);
00346         }
00347         return;
00348       }
00349       if (ce[0]->isIntVar()) {
00350         if (ce[1]->isIntVar()) {
00351           rel(s, getIntVar(s, ce[0]), irt, getIntVar(s, ce[1]),
00352                  getBoolVar(s, ce[2]), ann2icl(ann));
00353         } else {
00354           rel(s, getIntVar(s, ce[0]), irt, ce[1]->getInt(),
00355                  getBoolVar(s, ce[2]), ann2icl(ann));
00356         }
00357       } else {
00358         rel(s, getIntVar(s, ce[1]), swap(irt), ce[0]->getInt(),
00359                getBoolVar(s, ce[2]), ann2icl(ann));
00360       }
00361     }
00362 
00363     /* Comparisons */
00364     void p_int_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00365       p_int_CMP_reif(s, IRT_EQ, ce, ann);
00366     }
00367     void p_int_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00368       p_int_CMP_reif(s, IRT_NQ, ce, ann);
00369     }
00370     void p_int_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00371       p_int_CMP_reif(s, IRT_GQ, ce, ann);
00372     }
00373     void p_int_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00374       p_int_CMP_reif(s, IRT_GR, ce, ann);
00375     }
00376     void p_int_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00377       p_int_CMP_reif(s, IRT_LQ, ce, ann);
00378     }
00379     void p_int_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00380       p_int_CMP_reif(s, IRT_LE, ce, ann);
00381     }
00382 
00383     /* linear (in-)equations */
00384     void p_int_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00385                        AST::Node* ann) {
00386       IntArgs ia = arg2intargs(ce[0]);
00387       int singleIntVar;
00388       if (isBoolArray(s,ce[1],singleIntVar)) {
00389         if (singleIntVar != -1) {
00390           if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
00391             IntVar siv = getIntVar(s, ce[1]->getArray()->a[singleIntVar]);
00392             BoolVarArgs iv = arg2boolvarargs(s, ce[1], 0, singleIntVar);
00393             IntArgs ia_tmp(ia.size()-1);
00394             int count = 0;
00395             for (int i=0; i<ia.size(); i++) {
00396               if (i != singleIntVar)
00397                 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
00398             }
00399             IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
00400             linear(s, ia_tmp, iv, t, siv, ann2icl(ann));
00401           } else {
00402             IntVarArgs iv = arg2intvarargs(s, ce[1]);
00403             linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00404           }
00405         } else {
00406           BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00407           linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00408         }
00409       } else {
00410         IntVarArgs iv = arg2intvarargs(s, ce[1]);
00411         linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00412       }
00413     }
00414     void p_int_lin_CMP_reif(FlatZincSpace& s, IntRelType irt,
00415                             const ConExpr& ce, AST::Node* ann) {
00416       if (ce[2]->isBool()) {
00417         if (ce[2]->getBool()) {
00418           p_int_lin_CMP(s, irt, ce, ann);
00419         } else {
00420           p_int_lin_CMP(s, neg(irt), ce, ann);
00421         }
00422         return;
00423       }
00424       IntArgs ia = arg2intargs(ce[0]);
00425       int singleIntVar;
00426       if (isBoolArray(s,ce[1],singleIntVar)) {
00427         if (singleIntVar != -1) {
00428           if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
00429             IntVar siv = getIntVar(s, ce[1]->getArray()->a[singleIntVar]);
00430             BoolVarArgs iv = arg2boolvarargs(s, ce[1], 0, singleIntVar);
00431             IntArgs ia_tmp(ia.size()-1);
00432             int count = 0;
00433             for (int i=0; i<ia.size(); i++) {
00434               if (i != singleIntVar)
00435                 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
00436             }
00437             IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
00438             linear(s, ia_tmp, iv, t, siv, getBoolVar(s, ce[3]), 
00439                    ann2icl(ann));
00440           } else {
00441             IntVarArgs iv = arg2intvarargs(s, ce[1]);
00442             linear(s, ia, iv, irt, ce[2]->getInt(),
00443                    getBoolVar(s, ce[3]), ann2icl(ann));
00444           }
00445         } else {
00446           BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00447           linear(s, ia, iv, irt, ce[2]->getInt(),
00448                  getBoolVar(s, ce[3]), ann2icl(ann));
00449         }
00450       } else {
00451         IntVarArgs iv = arg2intvarargs(s, ce[1]);
00452         linear(s, ia, iv, irt, ce[2]->getInt(), getBoolVar(s, ce[3]), 
00453                ann2icl(ann));
00454       }
00455     }
00456     void p_int_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00457       p_int_lin_CMP(s, IRT_EQ, ce, ann);
00458     }
00459     void p_int_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00460       p_int_lin_CMP_reif(s, IRT_EQ, ce, ann);    
00461     }
00462     void p_int_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00463       p_int_lin_CMP(s, IRT_NQ, ce, ann);
00464     }
00465     void p_int_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00466       p_int_lin_CMP_reif(s, IRT_NQ, ce, ann);    
00467     }
00468     void p_int_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00469       p_int_lin_CMP(s, IRT_LQ, ce, ann);
00470     }
00471     void p_int_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00472       p_int_lin_CMP_reif(s, IRT_LQ, ce, ann);    
00473     }
00474     void p_int_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00475       p_int_lin_CMP(s, IRT_LE, ce, ann);
00476     }
00477     void p_int_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00478       p_int_lin_CMP_reif(s, IRT_LE, ce, ann);    
00479     }
00480     void p_int_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00481       p_int_lin_CMP(s, IRT_GQ, ce, ann);
00482     }
00483     void p_int_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00484       p_int_lin_CMP_reif(s, IRT_GQ, ce, ann);    
00485     }
00486     void p_int_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00487       p_int_lin_CMP(s, IRT_GR, ce, ann);
00488     }
00489     void p_int_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00490       p_int_lin_CMP_reif(s, IRT_GR, ce, ann);    
00491     }
00492 
00493     void p_bool_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00494                         AST::Node* ann) {
00495       IntArgs ia = arg2intargs(ce[0]);
00496       BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00497       if (ce[2]->isIntVar())
00498         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], ann2icl(ann));
00499       else
00500         linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00501     }
00502     void p_bool_lin_CMP_reif(FlatZincSpace& s, IntRelType irt,
00503                             const ConExpr& ce, AST::Node* ann) {
00504       if (ce[2]->isBool()) {
00505         if (ce[2]->getBool()) {
00506           p_bool_lin_CMP(s, irt, ce, ann);
00507         } else {
00508           p_bool_lin_CMP(s, neg(irt), ce, ann);
00509         }
00510         return;
00511       }
00512       IntArgs ia = arg2intargs(ce[0]);
00513       BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00514       if (ce[2]->isIntVar())
00515         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], getBoolVar(s, ce[3]), 
00516                ann2icl(ann));
00517       else
00518         linear(s, ia, iv, irt, ce[2]->getInt(), getBoolVar(s, ce[3]), 
00519                ann2icl(ann));
00520     }
00521     void p_bool_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00522       p_bool_lin_CMP(s, IRT_EQ, ce, ann);
00523     }
00524     void p_bool_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00525     {
00526       p_bool_lin_CMP_reif(s, IRT_EQ, ce, ann);
00527     }
00528     void p_bool_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00529       p_bool_lin_CMP(s, IRT_NQ, ce, ann);
00530     }
00531     void p_bool_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00532     {
00533       p_bool_lin_CMP_reif(s, IRT_NQ, ce, ann);
00534     }
00535     void p_bool_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00536       p_bool_lin_CMP(s, IRT_LQ, ce, ann);
00537     }
00538     void p_bool_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00539     {
00540       p_bool_lin_CMP_reif(s, IRT_LQ, ce, ann);
00541     }
00542     void p_bool_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00543     {
00544       p_bool_lin_CMP(s, IRT_LE, ce, ann);
00545     }
00546     void p_bool_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00547     {
00548       p_bool_lin_CMP_reif(s, IRT_LE, ce, ann);
00549     }
00550     void p_bool_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00551       p_bool_lin_CMP(s, IRT_GQ, ce, ann);
00552     }
00553     void p_bool_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00554     {
00555       p_bool_lin_CMP_reif(s, IRT_GQ, ce, ann);
00556     }
00557     void p_bool_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00558       p_bool_lin_CMP(s, IRT_GR, ce, ann);
00559     }
00560     void p_bool_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00561     {
00562       p_bool_lin_CMP_reif(s, IRT_GR, ce, ann);
00563     }
00564 
00565     /* arithmetic constraints */
00566   
00567     void p_int_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00568       if (!ce[0]->isIntVar()) {
00569         rel(s, ce[0]->getInt() + getIntVar(s, ce[1])
00570                 == getIntVar(s,ce[2]), ann2icl(ann));
00571       } else if (!ce[1]->isIntVar()) {
00572         rel(s, getIntVar(s,ce[0]) + ce[1]->getInt()
00573                 == getIntVar(s,ce[2]), ann2icl(ann));
00574       } else if (!ce[2]->isIntVar()) {
00575         rel(s, getIntVar(s,ce[0]) + getIntVar(s,ce[1]) 
00576                 == ce[2]->getInt(), ann2icl(ann));
00577       } else {
00578         rel(s, getIntVar(s,ce[0]) + getIntVar(s,ce[1]) 
00579                 == getIntVar(s,ce[2]), ann2icl(ann));
00580       }
00581     }
00582 
00583     void p_int_minus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00584       if (!ce[0]->isIntVar()) {
00585         rel(s, ce[0]->getInt() - getIntVar(s, ce[1])
00586                 == getIntVar(s,ce[2]), ann2icl(ann));
00587       } else if (!ce[1]->isIntVar()) {
00588         rel(s, getIntVar(s,ce[0]) - ce[1]->getInt()
00589                 == getIntVar(s,ce[2]), ann2icl(ann));
00590       } else if (!ce[2]->isIntVar()) {
00591         rel(s, getIntVar(s,ce[0]) - getIntVar(s,ce[1]) 
00592                 == ce[2]->getInt(), ann2icl(ann));
00593       } else {
00594         rel(s, getIntVar(s,ce[0]) - getIntVar(s,ce[1]) 
00595                 == getIntVar(s,ce[2]), ann2icl(ann));
00596       }
00597     }
00598 
00599     void p_int_times(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00600       IntVar x0 = getIntVar(s, ce[0]);
00601       IntVar x1 = getIntVar(s, ce[1]);
00602       IntVar x2 = getIntVar(s, ce[2]);
00603       mult(s, x0, x1, x2, ann2icl(ann));    
00604     }
00605     void p_int_div(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00606       IntVar x0 = getIntVar(s, ce[0]);
00607       IntVar x1 = getIntVar(s, ce[1]);
00608       IntVar x2 = getIntVar(s, ce[2]);
00609       div(s,x0,x1,x2, ann2icl(ann));
00610     }
00611     void p_int_mod(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00612       IntVar x0 = getIntVar(s, ce[0]);
00613       IntVar x1 = getIntVar(s, ce[1]);
00614       IntVar x2 = getIntVar(s, ce[2]);
00615       mod(s,x0,x1,x2, ann2icl(ann));
00616     }
00617 
00618     void p_int_min(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00619       IntVar x0 = getIntVar(s, ce[0]);
00620       IntVar x1 = getIntVar(s, ce[1]);
00621       IntVar x2 = getIntVar(s, ce[2]);
00622       min(s, x0, x1, x2, ann2icl(ann));
00623     }
00624     void p_int_max(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00625       IntVar x0 = getIntVar(s, ce[0]);
00626       IntVar x1 = getIntVar(s, ce[1]);
00627       IntVar x2 = getIntVar(s, ce[2]);
00628       max(s, x0, x1, x2, ann2icl(ann));
00629     }
00630     void p_int_negate(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00631       IntVar x0 = getIntVar(s, ce[0]);
00632       IntVar x1 = getIntVar(s, ce[1]);
00633       rel(s, x0 == -x1, ann2icl(ann));
00634     }
00635 
00636     /* Boolean constraints */
00637     void p_bool_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00638                    AST::Node* ann) {
00639       rel(s, getBoolVar(s, ce[0]), irt, getBoolVar(s, ce[1]), 
00640           ann2icl(ann));
00641     }
00642     void p_bool_CMP_reif(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00643                    AST::Node* ann) {
00644       rel(s, getBoolVar(s, ce[0]), irt, getBoolVar(s, ce[1]),
00645           getBoolVar(s, ce[2]), ann2icl(ann));
00646     }
00647     void p_bool_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00648       p_bool_CMP(s, IRT_EQ, ce, ann);
00649     }
00650     void p_bool_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00651       p_bool_CMP_reif(s, IRT_EQ, ce, ann);
00652     }
00653     void p_bool_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00654       p_bool_CMP(s, IRT_NQ, ce, ann);
00655     }
00656     void p_bool_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00657       p_bool_CMP_reif(s, IRT_NQ, ce, ann);
00658     }
00659     void p_bool_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00660       p_bool_CMP(s, IRT_GQ, ce, ann);
00661     }
00662     void p_bool_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00663       p_bool_CMP_reif(s, IRT_GQ, ce, ann);
00664     }
00665     void p_bool_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00666       p_bool_CMP(s, IRT_LQ, ce, ann);
00667     }
00668     void p_bool_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00669       p_bool_CMP_reif(s, IRT_LQ, ce, ann);
00670     }
00671     void p_bool_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00672       p_bool_CMP(s, IRT_GR, ce, ann);
00673     }
00674     void p_bool_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00675       p_bool_CMP_reif(s, IRT_GR, ce, ann);
00676     }
00677     void p_bool_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00678       p_bool_CMP(s, IRT_LE, ce, ann);
00679     }
00680     void p_bool_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00681       p_bool_CMP_reif(s, IRT_LE, ce, ann);
00682     }
00683 
00684 #define BOOL_OP(op) \
00685     BoolVar b0 = getBoolVar(s, ce[0]); \
00686     BoolVar b1 = getBoolVar(s, ce[1]); \
00687     if (ce[2]->isBool()) { \
00688       rel(s, b0, op, b1, ce[2]->getBool(), ann2icl(ann)); \
00689     } else { \
00690       rel(s, b0, op, b1, s.bv[ce[2]->getBoolVar()], ann2icl(ann)); \
00691     }
00692 
00693 #define BOOL_ARRAY_OP(op) \
00694     BoolVarArgs bv = arg2boolvarargs(s, ce[0]); \
00695     if (ce.size()==1) { \
00696       rel(s, op, bv, 1, ann2icl(ann)); \
00697     } else if (ce[1]->isBool()) { \
00698       rel(s, op, bv, ce[1]->getBool(), ann2icl(ann)); \
00699     } else { \
00700       rel(s, op, bv, s.bv[ce[1]->getBoolVar()], ann2icl(ann)); \
00701     }
00702 
00703     void p_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00704       BOOL_OP(BOT_OR);
00705     }
00706     void p_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00707       BOOL_OP(BOT_AND);
00708     }
00709     void p_array_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00710     {
00711       BOOL_ARRAY_OP(BOT_AND);
00712     }
00713     void p_array_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00714     {
00715       BOOL_ARRAY_OP(BOT_OR);
00716     }
00717     void p_array_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00718     {
00719       BOOL_ARRAY_OP(BOT_XOR);
00720     }
00721     void p_array_bool_clause(FlatZincSpace& s, const ConExpr& ce,
00722                              AST::Node* ann) {
00723       BoolVarArgs bvp = arg2boolvarargs(s, ce[0]);
00724       BoolVarArgs bvn = arg2boolvarargs(s, ce[1]);
00725       clause(s, BOT_OR, bvp, bvn, 1, ann2icl(ann));
00726     }
00727     void p_array_bool_clause_reif(FlatZincSpace& s, const ConExpr& ce,
00728                              AST::Node* ann) {
00729       BoolVarArgs bvp = arg2boolvarargs(s, ce[0]);
00730       BoolVarArgs bvn = arg2boolvarargs(s, ce[1]);
00731       BoolVar b0 = getBoolVar(s, ce[2]);
00732       clause(s, BOT_OR, bvp, bvn, b0, ann2icl(ann));
00733     }
00734     void p_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00735       BOOL_OP(BOT_XOR);
00736     }
00737     void p_bool_l_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00738       BoolVar b0 = getBoolVar(s, ce[0]);
00739       BoolVar b1 = getBoolVar(s, ce[1]);
00740       if (ce[2]->isBool()) {
00741         rel(s, b1, BOT_IMP, b0, ce[2]->getBool(), ann2icl(ann));
00742       } else {
00743         rel(s, b1, BOT_IMP, b0, s.bv[ce[2]->getBoolVar()], ann2icl(ann));
00744       }
00745     }
00746     void p_bool_r_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00747       BOOL_OP(BOT_IMP);
00748     }
00749     void p_bool_not(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00750       BoolVar x0 = getBoolVar(s, ce[0]);
00751       BoolVar x1 = getBoolVar(s, ce[1]);
00752       rel(s, x0, BOT_XOR, x1, 1, ann2icl(ann));
00753     }
00754   
00755     /* element constraints */
00756     void p_array_int_element(FlatZincSpace& s, const ConExpr& ce, 
00757                                  AST::Node* ann) {
00758       bool isConstant = true;
00759       AST::Array* a = ce[1]->getArray();
00760       for (int i=a->a.size(); i--;) {
00761         if (!a->a[i]->isInt()) {
00762           isConstant = false;
00763           break;
00764         }
00765       }
00766       IntVar selector = getIntVar(s, ce[0]);
00767       rel(s, selector > 0);
00768       if (isConstant) {
00769         IntArgs ia = arg2intargs(ce[1], 1);
00770         element(s, ia, selector, getIntVar(s, ce[2]), ann2icl(ann));
00771       } else {
00772         IntVarArgs iv = arg2intvarargs(s, ce[1], 1);
00773         element(s, iv, selector, getIntVar(s, ce[2]), ann2icl(ann));
00774       }
00775     }
00776     void p_array_bool_element(FlatZincSpace& s, const ConExpr& ce, 
00777                                   AST::Node* ann) {
00778       bool isConstant = true;
00779       AST::Array* a = ce[1]->getArray();
00780       for (int i=a->a.size(); i--;) {
00781         if (!a->a[i]->isBool()) {
00782           isConstant = false;
00783           break;
00784         }
00785       }
00786       IntVar selector = getIntVar(s, ce[0]);
00787       rel(s, selector > 0);
00788       if (isConstant) {
00789         IntArgs ia = arg2boolargs(ce[1], 1);
00790         element(s, ia, selector, getBoolVar(s, ce[2]), ann2icl(ann));
00791       } else {
00792         BoolVarArgs iv = arg2boolvarargs(s, ce[1], 1);
00793         element(s, iv, selector, getBoolVar(s, ce[2]), ann2icl(ann));
00794       }
00795     }
00796   
00797     /* coercion constraints */
00798     void p_bool2int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00799       BoolVar x0 = getBoolVar(s, ce[0]);
00800       IntVar x1 = getIntVar(s, ce[1]);
00801       if (ce[0]->isBoolVar() && ce[1]->isIntVar()) {
00802         s.aliasBool2Int(ce[1]->getIntVar(), ce[0]->getBoolVar());
00803       }
00804       channel(s, x0, x1, ann2icl(ann));
00805     }
00806 
00807     void p_int_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
00808       IntSet d = arg2intset(s,ce[1]);
00809       if (ce[0]->isBoolVar()) {
00810         IntSetRanges dr(d);
00811         Iter::Ranges::Singleton sr(0,1);
00812         Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
00813         IntSet d01(i);
00814         if (d01.size() == 0) {
00815           s.fail();
00816         } else {
00817           rel(s, getBoolVar(s, ce[0]), IRT_GQ, d01.min());
00818           rel(s, getBoolVar(s, ce[0]), IRT_LQ, d01.max());
00819         }
00820       } else {
00821         dom(s, getIntVar(s, ce[0]), d);
00822       }
00823     }
00824     void p_int_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
00825       IntSet d = arg2intset(s,ce[1]);
00826       if (ce[0]->isBoolVar()) {
00827         IntSetRanges dr(d);
00828         Iter::Ranges::Singleton sr(0,1);
00829         Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
00830         IntSet d01(i);
00831         if (d01.size() == 0) {
00832           rel(s, getBoolVar(s, ce[2]) == 0);
00833         } else if (d01.max() == 0) {
00834           rel(s, getBoolVar(s, ce[2]) == !getBoolVar(s, ce[0]));
00835         } else if (d01.min() == 1) {
00836           rel(s, getBoolVar(s, ce[2]) == getBoolVar(s, ce[0]));
00837         } else {
00838           rel(s, getBoolVar(s, ce[2]) == 1);
00839         }
00840       } else {
00841         std::cerr << "in_in_reif("<<getIntVar(s, ce[0])<<","<<d<<","<<getBoolVar(s, ce[2])<<")\n";
00842         dom(s, getIntVar(s, ce[0]), d, getBoolVar(s, ce[2]));
00843       }
00844     }
00845 
00846     /* constraints from the standard library */
00847   
00848     void p_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00849       IntVar x0 = getIntVar(s, ce[0]);
00850       IntVar x1 = getIntVar(s, ce[1]);
00851       abs(s, x0, x1, ann2icl(ann));
00852     }
00853   
00854     void p_array_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00855       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00856       IntVarArgs iv1 = arg2intvarargs(s, ce[1]);
00857       rel(s, iv0, IRT_LE, iv1, ann2icl(ann));
00858     }
00859 
00860     void p_array_int_lq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00861       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00862       IntVarArgs iv1 = arg2intvarargs(s, ce[1]);
00863       rel(s, iv0, IRT_LQ, iv1, ann2icl(ann));
00864     }
00865   
00866     void p_count(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00867       IntVarArgs iv = arg2intvarargs(s, ce[0]);
00868       if (!ce[1]->isIntVar()) {
00869         if (!ce[2]->isIntVar()) {
00870           count(s, iv, ce[1]->getInt(), IRT_EQ, ce[2]->getInt(), 
00871                 ann2icl(ann));
00872         } else {
00873           count(s, iv, ce[1]->getInt(), IRT_EQ, getIntVar(s, ce[2]), 
00874                 ann2icl(ann));
00875         }
00876       } else if (!ce[2]->isIntVar()) {
00877         count(s, iv, getIntVar(s, ce[1]), IRT_EQ, ce[2]->getInt(), 
00878               ann2icl(ann));
00879       } else {
00880         count(s, iv, getIntVar(s, ce[1]), IRT_EQ, getIntVar(s, ce[2]), 
00881               ann2icl(ann));
00882       }
00883     }
00884 
00885     void count_rel(IntRelType irt,
00886                    FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00887       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00888       count(s, iv, ce[2]->getInt(), irt, ce[0]->getInt(), ann2icl(ann));
00889     }
00890 
00891     void p_at_most(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00892       count_rel(IRT_LQ, s, ce, ann);
00893     }
00894 
00895     void p_at_least(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00896       count_rel(IRT_GQ, s, ce, ann);
00897     }
00898 
00899     void p_bin_packing_load(FlatZincSpace& s, const ConExpr& ce,
00900                             AST::Node* ann) {
00901       int minIdx = ce[3]->getInt();
00902       IntVarArgs load = arg2intvarargs(s, ce[0]);
00903       IntVarArgs l;
00904       IntVarArgs bin = arg2intvarargs(s, ce[1]);
00905       for (int i=bin.size(); i--;)
00906         rel(s, bin[i] >= minIdx);
00907       if (minIdx > 0) {
00908         for (int i=minIdx; i--;)
00909           l << IntVar(s,0,0);
00910       } else if (minIdx < 0) {
00911         IntVarArgs bin2(bin.size());
00912         for (int i=bin.size(); i--;)
00913           bin2[i] = expr(s, bin[i]-minIdx, ann2icl(ann));
00914         bin = bin2;
00915       }
00916       l << load;
00917       IntArgs sizes = arg2intargs(ce[2]);
00918       binpacking(s, l, bin, sizes, ann2icl(ann));
00919     }
00920 
00921     void p_global_cardinality(FlatZincSpace& s, const ConExpr& ce,
00922                               AST::Node* ann) {
00923       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00924       IntArgs cover = arg2intargs(ce[1]);
00925       IntVarArgs iv1 = arg2intvarargs(s, ce[2]);
00926 
00927       Region re(s);
00928       IntSet cover_s(cover);
00929       IntSetRanges cover_r(cover_s);
00930       IntVarRanges* iv0_ri = re.alloc<IntVarRanges>(iv0.size());
00931       for (int i=iv0.size(); i--;)
00932         iv0_ri[i] = IntVarRanges(iv0[i]);
00933       Iter::Ranges::NaryUnion iv0_r(re,iv0_ri,iv0.size());
00934       Iter::Ranges::Diff<Iter::Ranges::NaryUnion,IntSetRanges> 
00935         extra_r(iv0_r,cover_r);
00936       Iter::Ranges::ToValues<Iter::Ranges::Diff<
00937         Iter::Ranges::NaryUnion,IntSetRanges> > extra(extra_r);
00938       for (; extra(); ++extra) {
00939         cover << extra.val();
00940         iv1 << IntVar(s,0,iv0.size());
00941       }
00942       count(s, iv0, iv1, cover, ann2icl(ann));
00943     }
00944 
00945     void p_global_cardinality_closed(FlatZincSpace& s, const ConExpr& ce,
00946                                      AST::Node* ann) {
00947       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00948       IntArgs cover = arg2intargs(ce[1]);
00949       IntVarArgs iv1 = arg2intvarargs(s, ce[2]);
00950       count(s, iv0, iv1, cover, ann2icl(ann));
00951     }
00952 
00953     void p_global_cardinality_low_up(FlatZincSpace& s, const ConExpr& ce,
00954                                      AST::Node* ann) {
00955       IntVarArgs x = arg2intvarargs(s, ce[0]);
00956       IntArgs cover = arg2intargs(ce[1]);
00957 
00958       IntArgs lbound = arg2intargs(ce[2]);
00959       IntArgs ubound = arg2intargs(ce[3]);
00960       IntSetArgs y(cover.size());
00961       for (int i=cover.size(); i--;)
00962         y[i] = IntSet(lbound[i],ubound[i]);
00963 
00964       IntSet cover_s(cover);
00965       Region re(s);
00966       IntVarRanges* xrs = re.alloc<IntVarRanges>(x.size());
00967       for (int i=x.size(); i--;)
00968         xrs[i].init(x[i]);
00969       Iter::Ranges::NaryUnion u(re, xrs, x.size());
00970       Iter::Ranges::ToValues<Iter::Ranges::NaryUnion> uv(u);
00971       for (; uv(); ++uv) {
00972         if (!cover_s.in(uv.val())) {
00973           cover << uv.val();
00974           y << IntSet(0,x.size());
00975         }
00976       }
00977       
00978       count(s, x, y, cover, ann2icl(ann));
00979     }
00980 
00981     void p_global_cardinality_low_up_closed(FlatZincSpace& s,
00982                                             const ConExpr& ce,
00983                                             AST::Node* ann) {
00984       IntVarArgs x = arg2intvarargs(s, ce[0]);
00985       IntArgs cover = arg2intargs(ce[1]);
00986 
00987       IntArgs lbound = arg2intargs(ce[2]);
00988       IntArgs ubound = arg2intargs(ce[3]);
00989       IntSetArgs y(cover.size());
00990       for (int i=cover.size(); i--;)
00991         y[i] = IntSet(lbound[i],ubound[i]);
00992 
00993       count(s, x, y, cover, ann2icl(ann));
00994     }
00995 
00996     void p_minimum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00997       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00998       min(s, iv, getIntVar(s, ce[0]), ann2icl(ann));
00999     }
01000 
01001     void p_maximum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01002       IntVarArgs iv = arg2intvarargs(s, ce[1]);
01003       max(s, iv, getIntVar(s, ce[0]), ann2icl(ann));
01004     }
01005 
01006     void p_regular(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01007       IntVarArgs iv = arg2intvarargs(s, ce[0]);
01008       int q = ce[1]->getInt();
01009       int symbols = ce[2]->getInt();
01010       IntArgs d = arg2intargs(ce[3]);
01011       int q0 = ce[4]->getInt();
01012 
01013       int noOfTrans = 0;
01014       for (int i=1; i<=q; i++) {
01015         for (int j=1; j<=symbols; j++) {
01016           if (d[(i-1)*symbols+(j-1)] > 0)
01017             noOfTrans++;
01018         }
01019       }
01020     
01021       Region re(s);
01022       DFA::Transition* t = re.alloc<DFA::Transition>(noOfTrans+1);
01023       noOfTrans = 0;
01024       for (int i=1; i<=q; i++) {
01025         for (int j=1; j<=symbols; j++) {
01026           if (d[(i-1)*symbols+(j-1)] > 0) {
01027             t[noOfTrans].i_state = i;
01028             t[noOfTrans].symbol  = j;
01029             t[noOfTrans].o_state = d[(i-1)*symbols+(j-1)];
01030             noOfTrans++;
01031           }
01032         }
01033       }
01034       t[noOfTrans].i_state = -1;
01035     
01036       // Final states
01037       AST::SetLit* sl = ce[5]->getSet();
01038       int* f;
01039       if (sl->interval) {
01040         f = static_cast<int*>(malloc(sizeof(int)*(sl->max-sl->min+2)));
01041         for (int i=sl->min; i<=sl->max; i++)
01042           f[i-sl->min] = i;
01043         f[sl->max-sl->min+1] = -1;
01044       } else {
01045         f = static_cast<int*>(malloc(sizeof(int)*(sl->s.size()+1)));
01046         for (int j=sl->s.size(); j--; )
01047           f[j] = sl->s[j];
01048         f[sl->s.size()] = -1;
01049       }
01050         
01051       DFA dfa(q0,t,f);
01052       free(f);
01053       extensional(s, iv, dfa, ann2icl(ann));
01054     }
01055 
01056     void
01057     p_sort(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01058       IntVarArgs x = arg2intvarargs(s, ce[0]);
01059       IntVarArgs y = arg2intvarargs(s, ce[1]);
01060       IntVarArgs xy(x.size()+y.size());
01061       for (int i=x.size(); i--;)
01062         xy[i] = x[i];
01063       for (int i=y.size(); i--;)
01064         xy[i+x.size()] = y[i];
01065       unshare(s, xy);
01066       for (int i=x.size(); i--;)
01067         x[i] = xy[i];
01068       for (int i=y.size(); i--;)
01069         y[i] = xy[i+x.size()];
01070       sorted(s, x, y, ann2icl(ann));
01071     }
01072 
01073     void
01074     p_inverse_offsets(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01075       IntVarArgs x = arg2intvarargs(s, ce[0]);
01076       int xoff = ce[1]->getInt();
01077       IntVarArgs y = arg2intvarargs(s, ce[2]);
01078       int yoff = ce[3]->getInt();
01079       channel(s, x, xoff, y, yoff, ann2icl(ann));
01080     }
01081 
01082     void
01083     p_increasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01084       IntVarArgs x = arg2intvarargs(s, ce[0]);
01085       rel(s,x,IRT_LQ,ann2icl(ann));
01086     }
01087 
01088     void
01089     p_increasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01090       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01091       rel(s,x,IRT_LQ,ann2icl(ann));
01092     }
01093 
01094     void
01095     p_decreasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01096       IntVarArgs x = arg2intvarargs(s, ce[0]);
01097       rel(s,x,IRT_GQ,ann2icl(ann));
01098     }
01099 
01100     void
01101     p_decreasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01102       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01103       rel(s,x,IRT_GQ,ann2icl(ann));
01104     }
01105 
01106     void
01107     p_table_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01108       IntVarArgs x = arg2intvarargs(s, ce[0]);
01109       IntArgs tuples = arg2intargs(ce[1]);
01110       int noOfVars   = x.size();
01111       int noOfTuples = tuples.size()/noOfVars;
01112       TupleSet ts;
01113       for (int i=0; i<noOfTuples; i++) {
01114         IntArgs t(noOfVars);
01115         for (int j=0; j<x.size(); j++) {
01116           t[j] = tuples[i*noOfVars+j];
01117         }
01118         ts.add(t);
01119       }
01120       ts.finalize();
01121       extensional(s,x,ts,EPK_DEF,ann2icl(ann));
01122     }
01123     void
01124     p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01125       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01126       IntArgs tuples = arg2boolargs(ce[1]);
01127       int noOfVars   = x.size();
01128       int noOfTuples = tuples.size()/noOfVars;
01129       TupleSet ts;
01130       for (int i=0; i<noOfTuples; i++) {
01131         IntArgs t(noOfVars);
01132         for (int j=0; j<x.size(); j++) {
01133           t[j] = tuples[i*noOfVars+j];
01134         }
01135         ts.add(t);
01136       }
01137       ts.finalize();
01138       extensional(s,x,ts,EPK_DEF,ann2icl(ann));
01139     }
01140 
01141     void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
01142                       AST::Node* ann) {
01143       IntVarArgs start = arg2intvarargs(s, ce[0]);
01144       IntVarArgs duration = arg2intvarargs(s, ce[1]);
01145       IntVarArgs height = arg2intvarargs(s, ce[2]);
01146       int n = start.size();
01147       IntVar bound = getIntVar(s, ce[3]);
01148 
01149       int minHeight = INT_MAX; int minHeight2 = INT_MAX;
01150       for (int i=n; i--;)
01151         if (height[i].min() < minHeight)
01152           minHeight = height[i].min();
01153         else if (height[i].min() < minHeight2)
01154           minHeight2 = height[i].min();
01155       bool disjunctive =
01156        (minHeight > bound.max()/2) ||
01157        (minHeight2 > bound.max()/2 && minHeight+minHeight2>bound.max());
01158       if (disjunctive) {
01159         rel(s, bound >= max(height));
01160         // Unary
01161         if (duration.assigned()) {
01162           IntArgs durationI(n);
01163           for (int i=n; i--;)
01164             durationI[i] = duration[i].val();
01165           unary(s,start,durationI);
01166         } else {
01167           IntVarArgs end(n);
01168           for (int i=n; i--;)
01169             end[i] = expr(s,start[i]+duration[i]);
01170           unary(s,start,duration,end);
01171         }
01172       } else if (height.assigned()) {
01173         IntArgs heightI(n);
01174         for (int i=n; i--;)
01175           heightI[i] = height[i].val();
01176         if (duration.assigned()) {
01177           IntArgs durationI(n);
01178           for (int i=n; i--;)
01179             durationI[i] = duration[i].val();
01180           cumulative(s, bound, start, durationI, heightI);
01181         } else {
01182           IntVarArgs end(n);
01183           for (int i = n; i--; )
01184             end[i] = expr(s,start[i]+duration[i]);
01185           cumulative(s, bound, start, duration, end, heightI);
01186         }
01187       } else if (bound.assigned()) {
01188         IntArgs machine = IntArgs::create(n,0,0);
01189         IntArgs limit(1, bound.val());
01190         IntVarArgs end(n);
01191         for (int i=n; i--;)
01192           end[i] = expr(s,start[i]+duration[i]);
01193         cumulatives(s, machine, start, duration, end, height, limit, true,
01194                     ann2icl(ann));
01195       } else {
01196         int min = Gecode::Int::Limits::max;
01197         int max = Gecode::Int::Limits::min;
01198         IntVarArgs end(start.size());
01199         for (int i = start.size(); i--; ) {
01200           min = std::min(min, start[i].min());
01201           max = std::max(max, start[i].max() + duration[i].max());
01202           end[i] = expr(s, start[i] + duration[i]);
01203         }
01204         for (int time = min; time < max; ++time) {
01205           IntVarArgs x(start.size());
01206           for (int i = start.size(); i--; ) {
01207             IntVar overlaps = channel(s, expr(s, (start[i] <= time) && 
01208                                                  (time < end[i])));
01209             x[i] = expr(s, overlaps * height[i]);
01210           }
01211           linear(s, x, IRT_LQ, bound);
01212         }
01213       }
01214     }
01215 
01216     void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
01217                          AST::Node* ann) {
01218       IntVarArgs x = arg2intvarargs(s, ce[0]);
01219       IntSet S = arg2intset(s, ce[1]);
01220       int q = ce[2]->getInt();
01221       int l = ce[3]->getInt();
01222       int u = ce[4]->getInt();
01223       sequence(s, x, S, q, l, u, ann2icl(ann));
01224     }
01225 
01226     void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
01227                           AST::Node* ann) {
01228       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01229       bool val = ce[1]->getBool();
01230       int q = ce[2]->getInt();
01231       int l = ce[3]->getInt();
01232       int u = ce[4]->getInt();
01233       IntSet S(val, val);
01234       sequence(s, x, S, q, l, u, ann2icl(ann));
01235     }
01236 
01237     void p_schedule_unary(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01238       IntVarArgs x = arg2intvarargs(s, ce[0]);
01239       IntArgs p = arg2intargs(ce[1]);
01240       unary(s, x, p);
01241     }
01242 
01243     void p_schedule_unary_optional(FlatZincSpace& s, const ConExpr& ce,
01244                                    AST::Node*) {
01245       IntVarArgs x = arg2intvarargs(s, ce[0]);
01246       IntArgs p = arg2intargs(ce[1]);
01247       BoolVarArgs m = arg2boolvarargs(s, ce[2]);
01248       unary(s, x, p, m);
01249     }
01250 
01251     void p_circuit(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01252       IntVarArgs xv = arg2intvarargs(s, ce[0]);
01253       circuit(s,xv,ann2icl(ann));
01254     }
01255     void p_circuit_cost_array(FlatZincSpace& s, const ConExpr& ce,
01256                               AST::Node *ann) {
01257       IntArgs c = arg2intargs(ce[0]);
01258       IntVarArgs xv = arg2intvarargs(s, ce[1]);
01259       IntVarArgs yv = arg2intvarargs(s, ce[2]);
01260       IntVar z = getIntVar(s, ce[3]);
01261       circuit(s,c,xv,yv,z,ann2icl(ann));
01262     }
01263     void p_circuit_cost(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01264       IntArgs c = arg2intargs(ce[0]);
01265       IntVarArgs xv = arg2intvarargs(s, ce[1]);
01266       IntVar z = getIntVar(s, ce[2]);
01267       circuit(s,c,xv,z,ann2icl(ann));
01268     }
01269 
01270     void p_nooverlap(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01271       IntVarArgs x0 = arg2intvarargs(s, ce[0]);
01272       IntVarArgs w = arg2intvarargs(s, ce[1]);
01273       IntVarArgs y0 = arg2intvarargs(s, ce[2]);
01274       IntVarArgs h = arg2intvarargs(s, ce[3]);
01275       IntVarArgs x1(x0.size()), y1(y0.size());
01276       for (int i=x0.size(); i--; )
01277         x1[i] = expr(s, x0[i] + w[i]);
01278       for (int i=y0.size(); i--; )
01279         y1[i] = expr(s, y0[i] + h[i]);
01280       nooverlap(s,x0,w,x1,y0,h,y1,ann2icl(ann));
01281     }
01282 
01283     void p_precede(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01284       IntVarArgs x = arg2intvarargs(s, ce[0]);
01285       IntArgs c = arg2intargs(ce[1]);
01286       precede(s,x,c,ann2icl(ann));
01287     }
01288 
01289     void p_nvalue(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01290       IntVarArgs x = arg2intvarargs(s, ce[1]);
01291       if (ce[0]->isIntVar()) {
01292         IntVar y = getIntVar(s,ce[0]);
01293         nvalues(s,x,IRT_EQ,y,ann2icl(ann));
01294       } else {
01295         nvalues(s,x,IRT_EQ,ce[0]->getInt(),ann2icl(ann));
01296       }
01297     }
01298 
01299     void p_among(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01300       IntVarArgs x = arg2intvarargs(s, ce[1]);
01301       IntSet v = arg2intset(s, ce[2]);
01302       if (ce[0]->isIntVar()) {
01303         IntVar n = getIntVar(s,ce[0]);
01304         std::cerr << "count " << n << std::endl;
01305         count(s,x,v,IRT_EQ,n,ann2icl(ann));
01306       } else {
01307         std::cerr << "count i " << x << " " << v << " " << ce[0]->getInt() << std::endl;
01308         count(s,x,v,IRT_EQ,ce[0]->getInt(),ann2icl(ann));
01309       }
01310     }
01311 
01312     void p_member_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01313       IntVarArgs x = arg2intvarargs(s, ce[0]);
01314       IntVar y = getIntVar(s, ce[1]);
01315       member(s,x,y,ann2icl(ann));
01316     }
01317     void p_member_int_reif(FlatZincSpace& s, const ConExpr& ce,
01318                            AST::Node* ann) {
01319       IntVarArgs x = arg2intvarargs(s, ce[0]);
01320       IntVar y = getIntVar(s, ce[1]);
01321       BoolVar b = getBoolVar(s, ce[2]);
01322       member(s,x,y,b,ann2icl(ann));
01323     }
01324     void p_member_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01325       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01326       BoolVar y = getBoolVar(s, ce[1]);
01327       member(s,x,y,ann2icl(ann));
01328     }
01329     void p_member_bool_reif(FlatZincSpace& s, const ConExpr& ce,
01330                             AST::Node* ann) {
01331       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
01332       BoolVar y = getBoolVar(s, ce[1]);
01333       member(s,x,y,getBoolVar(s, ce[2]),ann2icl(ann));
01334     }
01335 
01336     class IntPoster {
01337     public:
01338       IntPoster(void) {
01339         registry().add("all_different_int", &p_distinct);
01340         registry().add("all_different_offset", &p_distinctOffset);
01341         registry().add("all_equal_int", &p_all_equal);
01342         registry().add("int_eq", &p_int_eq);
01343         registry().add("int_ne", &p_int_ne);
01344         registry().add("int_ge", &p_int_ge);
01345         registry().add("int_gt", &p_int_gt);
01346         registry().add("int_le", &p_int_le);
01347         registry().add("int_lt", &p_int_lt);
01348         registry().add("int_eq_reif", &p_int_eq_reif);
01349         registry().add("int_ne_reif", &p_int_ne_reif);
01350         registry().add("int_ge_reif", &p_int_ge_reif);
01351         registry().add("int_gt_reif", &p_int_gt_reif);
01352         registry().add("int_le_reif", &p_int_le_reif);
01353         registry().add("int_lt_reif", &p_int_lt_reif);
01354         registry().add("int_lin_eq", &p_int_lin_eq);
01355         registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
01356         registry().add("int_lin_ne", &p_int_lin_ne);
01357         registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
01358         registry().add("int_lin_le", &p_int_lin_le);
01359         registry().add("int_lin_le_reif", &p_int_lin_le_reif);
01360         registry().add("int_lin_lt", &p_int_lin_lt);
01361         registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
01362         registry().add("int_lin_ge", &p_int_lin_ge);
01363         registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
01364         registry().add("int_lin_gt", &p_int_lin_gt);
01365         registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
01366         registry().add("int_plus", &p_int_plus);
01367         registry().add("int_minus", &p_int_minus);
01368         registry().add("int_times", &p_int_times);
01369         registry().add("int_div", &p_int_div);
01370         registry().add("int_mod", &p_int_mod);
01371         registry().add("int_min", &p_int_min);
01372         registry().add("int_max", &p_int_max);
01373         registry().add("int_abs", &p_abs);
01374         registry().add("int_negate", &p_int_negate);
01375         registry().add("bool_eq", &p_bool_eq);
01376         registry().add("bool_eq_reif", &p_bool_eq_reif);
01377         registry().add("bool_ne", &p_bool_ne);
01378         registry().add("bool_ne_reif", &p_bool_ne_reif);
01379         registry().add("bool_ge", &p_bool_ge);
01380         registry().add("bool_ge_reif", &p_bool_ge_reif);
01381         registry().add("bool_le", &p_bool_le);
01382         registry().add("bool_le_reif", &p_bool_le_reif);
01383         registry().add("bool_gt", &p_bool_gt);
01384         registry().add("bool_gt_reif", &p_bool_gt_reif);
01385         registry().add("bool_lt", &p_bool_lt);
01386         registry().add("bool_lt_reif", &p_bool_lt_reif);
01387         registry().add("bool_or", &p_bool_or);
01388         registry().add("bool_and", &p_bool_and);
01389         registry().add("bool_xor", &p_bool_xor);
01390         registry().add("array_bool_and", &p_array_bool_and);
01391         registry().add("array_bool_or", &p_array_bool_or);
01392         registry().add("array_bool_xor", &p_array_bool_xor);
01393         registry().add("bool_clause", &p_array_bool_clause);
01394         registry().add("bool_clause_reif", &p_array_bool_clause_reif);
01395         registry().add("bool_left_imp", &p_bool_l_imp);
01396         registry().add("bool_right_imp", &p_bool_r_imp);
01397         registry().add("bool_not", &p_bool_not);
01398         registry().add("array_int_element", &p_array_int_element);
01399         registry().add("array_var_int_element", &p_array_int_element);
01400         registry().add("array_bool_element", &p_array_bool_element);
01401         registry().add("array_var_bool_element", &p_array_bool_element);
01402         registry().add("bool2int", &p_bool2int);
01403         registry().add("int_in", &p_int_in);
01404         registry().add("int_in_reif", &p_int_in_reif);
01405 #ifndef GECODE_HAS_SET_VARS
01406         registry().add("set_in", &p_int_in);
01407         registry().add("set_in_reif", &p_int_in_reif);
01408 #endif
01409       
01410         registry().add("array_int_lt", &p_array_int_lt);
01411         registry().add("array_int_lq", &p_array_int_lq);
01412         registry().add("count", &p_count);
01413         registry().add("at_least_int", &p_at_least);
01414         registry().add("at_most_int", &p_at_most);
01415         registry().add("gecode_bin_packing_load", &p_bin_packing_load);
01416         registry().add("global_cardinality", &p_global_cardinality);
01417         registry().add("global_cardinality_closed",
01418           &p_global_cardinality_closed);
01419         registry().add("global_cardinality_low_up", 
01420           &p_global_cardinality_low_up);
01421         registry().add("global_cardinality_low_up_closed", 
01422           &p_global_cardinality_low_up_closed);
01423         registry().add("minimum_int", &p_minimum);
01424         registry().add("maximum_int", &p_maximum);
01425         registry().add("regular", &p_regular);
01426         registry().add("sort", &p_sort);
01427         registry().add("inverse_offsets", &p_inverse_offsets);
01428         registry().add("increasing_int", &p_increasing_int);
01429         registry().add("increasing_bool", &p_increasing_bool);
01430         registry().add("decreasing_int", &p_decreasing_int);
01431         registry().add("decreasing_bool", &p_decreasing_bool);
01432         registry().add("table_int", &p_table_int);
01433         registry().add("table_bool", &p_table_bool);
01434         registry().add("cumulatives", &p_cumulatives);
01435         registry().add("gecode_among_seq_int", &p_among_seq_int);
01436         registry().add("gecode_among_seq_bool", &p_among_seq_bool);
01437 
01438         registry().add("bool_lin_eq", &p_bool_lin_eq);
01439         registry().add("bool_lin_ne", &p_bool_lin_ne);
01440         registry().add("bool_lin_le", &p_bool_lin_le);
01441         registry().add("bool_lin_lt", &p_bool_lin_lt);
01442         registry().add("bool_lin_ge", &p_bool_lin_ge);
01443         registry().add("bool_lin_gt", &p_bool_lin_gt);
01444 
01445         registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
01446         registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
01447         registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
01448         registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
01449         registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
01450         registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
01451         
01452         registry().add("gecode_schedule_unary", &p_schedule_unary);
01453         registry().add("gecode_schedule_unary_optional", &p_schedule_unary_optional);
01454 
01455         registry().add("gecode_circuit", &p_circuit);
01456         registry().add("gecode_circuit_cost_array", &p_circuit_cost_array);
01457         registry().add("gecode_circuit_cost", &p_circuit_cost);
01458         registry().add("gecode_nooverlap", &p_nooverlap);
01459         registry().add("gecode_precede", &p_precede);
01460         registry().add("nvalue",&p_nvalue);
01461         registry().add("among",&p_among);
01462         registry().add("member_int",&p_member_int);
01463         registry().add("gecode_member_int_reif",&p_member_int_reif);
01464         registry().add("member_bool",&p_member_bool);
01465         registry().add("gecode_member_bool_reif",&p_member_bool_reif);
01466       }
01467     };
01468     IntPoster __int_poster;
01469 
01470 #ifdef GECODE_HAS_SET_VARS
01471     void p_set_OP(FlatZincSpace& s, SetOpType op,
01472                   const ConExpr& ce, AST::Node *) {
01473       rel(s, getSetVar(s, ce[0]), op, getSetVar(s, ce[1]), 
01474           SRT_EQ, getSetVar(s, ce[2]));
01475     }
01476     void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01477       p_set_OP(s, SOT_UNION, ce, ann);
01478     }
01479     void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01480       p_set_OP(s, SOT_INTER, ce, ann);
01481     }
01482     void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01483       p_set_OP(s, SOT_MINUS, ce, ann);
01484     }
01485 
01486     void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01487       SetVar x = getSetVar(s, ce[0]);
01488       SetVar y = getSetVar(s, ce[1]);
01489 
01490       SetVarLubRanges xub(x);
01491       IntSet xubs(xub);
01492       SetVar x_y(s,IntSet::empty,xubs);
01493       rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
01494 
01495       SetVarLubRanges yub(y);
01496       IntSet yubs(yub);
01497       SetVar y_x(s,IntSet::empty,yubs);
01498       rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
01499     
01500       rel(s, x_y, SOT_UNION, y_x, SRT_EQ, getSetVar(s, ce[2]));
01501     }
01502 
01503     void p_array_set_OP(FlatZincSpace& s, SetOpType op,
01504                         const ConExpr& ce, AST::Node *) {
01505       SetVarArgs xs = arg2setvarargs(s, ce[0]);
01506       rel(s, op, xs, getSetVar(s, ce[1]));
01507     }
01508     void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01509       p_array_set_OP(s, SOT_UNION, ce, ann);
01510     }
01511     void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01512       p_array_set_OP(s, SOT_DUNION, ce, ann);
01513     }
01514 
01515 
01516     void p_set_rel(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01517       rel(s, getSetVar(s, ce[0]), srt, getSetVar(s, ce[1]));
01518     }
01519 
01520     void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01521       p_set_rel(s, SRT_EQ, ce);
01522     }
01523     void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01524       p_set_rel(s, SRT_NQ, ce);
01525     }
01526     void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01527       p_set_rel(s, SRT_SUB, ce);
01528     }
01529     void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01530       p_set_rel(s, SRT_SUP, ce);
01531     }
01532     void p_set_le(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01533       p_set_rel(s, SRT_LQ, ce);
01534     }
01535     void p_set_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01536       p_set_rel(s, SRT_LE, ce);
01537     }
01538     void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01539       if (!ce[1]->isIntVar()) {
01540         cardinality(s, getSetVar(s, ce[0]), ce[1]->getInt(), 
01541                     ce[1]->getInt());
01542       } else {
01543         cardinality(s, getSetVar(s, ce[0]), getIntVar(s, ce[1]));
01544       }
01545     }
01546     void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01547       if (!ce[1]->isSetVar()) {
01548         IntSet d = arg2intset(s,ce[1]);
01549         if (ce[0]->isBoolVar()) {
01550           IntSetRanges dr(d);
01551           Iter::Ranges::Singleton sr(0,1);
01552           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01553           IntSet d01(i);
01554           if (d01.size() == 0) {
01555             s.fail();
01556           } else {
01557             rel(s, getBoolVar(s, ce[0]), IRT_GQ, d01.min());
01558             rel(s, getBoolVar(s, ce[0]), IRT_LQ, d01.max());
01559           }
01560         } else {
01561           dom(s, getIntVar(s, ce[0]), d);
01562         }
01563       } else {
01564         if (!ce[0]->isIntVar()) {
01565           dom(s, getSetVar(s, ce[1]), SRT_SUP, ce[0]->getInt());
01566         } else {
01567           rel(s, getSetVar(s, ce[1]), SRT_SUP, getIntVar(s, ce[0]));
01568         }
01569       }
01570     }
01571     void p_set_rel_reif(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01572       rel(s, getSetVar(s, ce[0]), srt, getSetVar(s, ce[1]),
01573           getBoolVar(s, ce[2]));
01574     }
01575 
01576     void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01577       p_set_rel_reif(s,SRT_EQ,ce);
01578     }
01579     void p_set_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01580       p_set_rel_reif(s,SRT_LQ,ce);
01581     }
01582     void p_set_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01583       p_set_rel_reif(s,SRT_LE,ce);
01584     }
01585     void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01586       p_set_rel_reif(s,SRT_NQ,ce);
01587     }
01588     void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
01589                            AST::Node *) {
01590       p_set_rel_reif(s,SRT_SUB,ce);
01591     }
01592     void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
01593                              AST::Node *) {
01594       p_set_rel_reif(s,SRT_SUP,ce);
01595     }
01596     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01597       if (!ce[1]->isSetVar()) {
01598         IntSet d = arg2intset(s,ce[1]);
01599         if (ce[0]->isBoolVar()) {
01600           IntSetRanges dr(d);
01601           Iter::Ranges::Singleton sr(0,1);
01602           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01603           IntSet d01(i);
01604           if (d01.size() == 0) {
01605             rel(s, getBoolVar(s, ce[2]) == 0);
01606           } else if (d01.max() == 0) {
01607             rel(s, getBoolVar(s, ce[2]) == !getBoolVar(s, ce[0]));
01608           } else if (d01.min() == 1) {
01609             rel(s, getBoolVar(s, ce[2]) == getBoolVar(s, ce[0]));
01610           } else {
01611             rel(s, getBoolVar(s, ce[2]) == 1);
01612           }
01613         } else {
01614           dom(s, getIntVar(s, ce[0]), d, getBoolVar(s, ce[2]));
01615         }
01616       } else {
01617         if (!ce[0]->isIntVar()) {
01618           dom(s, getSetVar(s, ce[1]), SRT_SUP, ce[0]->getInt(),
01619               getBoolVar(s, ce[2]));
01620         } else {
01621           rel(s, getSetVar(s, ce[1]), SRT_SUP, getIntVar(s, ce[0]),
01622               getBoolVar(s, ce[2]));
01623         }
01624       }
01625     }
01626     void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01627       rel(s, getSetVar(s, ce[0]), SRT_DISJ, getSetVar(s, ce[1]));
01628     }
01629     
01630     void p_link_set_to_booleans(FlatZincSpace& s, const ConExpr& ce,
01631                                 AST::Node *) {
01632       SetVar x = getSetVar(s, ce[0]);
01633       int idx = ce[2]->getInt();
01634       assert(idx >= 0);
01635       rel(s, x || IntSet(Set::Limits::min,idx-1));
01636       BoolVarArgs y = arg2boolvarargs(s,ce[1],idx);
01637       channel(s, y, x);
01638     }
01639 
01640     void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
01641                              AST::Node*) {
01642       bool isConstant = true;
01643       AST::Array* a = ce[1]->getArray();
01644       for (int i=a->a.size(); i--;) {
01645         if (a->a[i]->isSetVar()) {
01646           isConstant = false;
01647           break;
01648         }
01649       }
01650       IntVar selector = getIntVar(s, ce[0]);
01651       rel(s, selector > 0);
01652       if (isConstant) {
01653         IntSetArgs sv = arg2intsetargs(s,ce[1],1);
01654         element(s, sv, selector, getSetVar(s, ce[2]));
01655       } else {
01656         SetVarArgs sv = arg2setvarargs(s, ce[1], 1);
01657         element(s, sv, selector, getSetVar(s, ce[2]));
01658       }
01659     }
01660 
01661     void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
01662                                 AST::Node*, SetOpType op,
01663                                 const IntSet& universe = 
01664                                 IntSet(Set::Limits::min,Set::Limits::max)) {
01665       bool isConstant = true;
01666       AST::Array* a = ce[1]->getArray();
01667       for (int i=a->a.size(); i--;) {
01668         if (a->a[i]->isSetVar()) {
01669           isConstant = false;
01670           break;
01671         }
01672       }
01673       SetVar selector = getSetVar(s, ce[0]);
01674       dom(s, selector, SRT_DISJ, 0);
01675       if (isConstant) {
01676         IntSetArgs sv = arg2intsetargs(s,ce[1], 1);
01677         element(s, op, sv, selector, getSetVar(s, ce[2]), universe);
01678       } else {
01679         SetVarArgs sv = arg2setvarargs(s, ce[1], 1);
01680         element(s, op, sv, selector, getSetVar(s, ce[2]), universe);
01681       }
01682     }
01683 
01684     void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
01685                                        AST::Node* ann) {
01686       p_array_set_element_op(s, ce, ann, SOT_UNION);
01687     }
01688 
01689     void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
01690                                        AST::Node* ann) {
01691       p_array_set_element_op(s, ce, ann, SOT_INTER);
01692     }
01693 
01694     void p_array_set_element_intersect_in(FlatZincSpace& s,
01695                                               const ConExpr& ce,
01696                                               AST::Node* ann) {
01697       IntSet d = arg2intset(s, ce[3]);
01698       p_array_set_element_op(s, ce, ann, SOT_INTER, d);
01699     }
01700 
01701     void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
01702                                            AST::Node* ann) {
01703       p_array_set_element_op(s, ce, ann, SOT_DUNION);
01704     }
01705 
01706     void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01707       convex(s, getSetVar(s, ce[0]));
01708     }
01709 
01710     void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01711       SetVarArgs sv = arg2setvarargs(s, ce[0]);
01712       sequence(s, sv);
01713     }
01714 
01715     void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
01716                                AST::Node *) {
01717       SetVarArgs sv = arg2setvarargs(s, ce[0]);
01718       sequence(s, sv, getSetVar(s, ce[1]));
01719     }
01720 
01721     void p_int_set_channel(FlatZincSpace& s, const ConExpr& ce,
01722                            AST::Node *) {
01723       int xoff=ce[1]->getInt();
01724       assert(xoff >= 0);
01725       int yoff=ce[3]->getInt();
01726       assert(yoff >= 0);
01727       IntVarArgs xv = arg2intvarargs(s, ce[0], xoff);
01728       SetVarArgs yv = arg2setvarargs(s, ce[2], yoff, 1, IntSet(0, xoff-1));
01729       IntSet xd(yoff,yv.size()-1);
01730       for (int i=xoff; i<xv.size(); i++) {
01731         dom(s, xv[i], xd);
01732       }
01733       IntSet yd(xoff,xv.size()-1);
01734       for (int i=yoff; i<yv.size(); i++) {
01735         dom(s, yv[i], SRT_SUB, yd);
01736       }
01737       channel(s,xv,yv);
01738     }
01739     
01740     void p_range(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01741       int xoff=ce[1]->getInt();
01742       assert(xoff >= 0);
01743       IntVarArgs xv = arg2intvarargs(s,ce[0],xoff);
01744       element(s, SOT_UNION, xv, getSetVar(s,ce[2]), getSetVar(s,ce[3]));
01745     }
01746     
01747     void p_weights(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01748       IntArgs e = arg2intargs(ce[0]);
01749       IntArgs w = arg2intargs(ce[1]);
01750       SetVar x = getSetVar(s,ce[2]);
01751       IntVar y = getIntVar(s,ce[3]);
01752       weights(s,e,w,x,y);
01753     }
01754     
01755     class SetPoster {
01756     public:
01757       SetPoster(void) {
01758         registry().add("set_eq", &p_set_eq);
01759         registry().add("set_le", &p_set_le);
01760         registry().add("set_lt", &p_set_lt);
01761         registry().add("equal", &p_set_eq);
01762         registry().add("set_ne", &p_set_ne);
01763         registry().add("set_union", &p_set_union);
01764         registry().add("array_set_element", &p_array_set_element);
01765         registry().add("array_var_set_element", &p_array_set_element);
01766         registry().add("set_intersect", &p_set_intersect);
01767         registry().add("set_diff", &p_set_diff);
01768         registry().add("set_symdiff", &p_set_symdiff);
01769         registry().add("set_subset", &p_set_subset);
01770         registry().add("set_superset", &p_set_superset);
01771         registry().add("set_card", &p_set_card);
01772         registry().add("set_in", &p_set_in);
01773         registry().add("set_eq_reif", &p_set_eq_reif);
01774         registry().add("set_le_reif", &p_set_le_reif);
01775         registry().add("set_lt_reif", &p_set_lt_reif);
01776         registry().add("equal_reif", &p_set_eq_reif);
01777         registry().add("set_ne_reif", &p_set_ne_reif);
01778         registry().add("set_subset_reif", &p_set_subset_reif);
01779         registry().add("set_superset_reif", &p_set_superset_reif);
01780         registry().add("set_in_reif", &p_set_in_reif);
01781         registry().add("disjoint", &p_set_disjoint);
01782         registry().add("gecode_link_set_to_booleans", 
01783                        &p_link_set_to_booleans);
01784 
01785         registry().add("array_set_union", &p_array_set_union);
01786         registry().add("array_set_partition", &p_array_set_partition);
01787         registry().add("set_convex", &p_set_convex);
01788         registry().add("array_set_seq", &p_array_set_seq);
01789         registry().add("array_set_seq_union", &p_array_set_seq_union);
01790         registry().add("gecode_array_set_element_union", 
01791                        &p_array_set_element_union);
01792         registry().add("gecode_array_set_element_intersect", 
01793                        &p_array_set_element_intersect);
01794         registry().add("gecode_array_set_element_intersect_in", 
01795                        &p_array_set_element_intersect_in);
01796         registry().add("gecode_array_set_element_partition", 
01797                        &p_array_set_element_partition);
01798         registry().add("gecode_int_set_channel", 
01799                        &p_int_set_channel);
01800         registry().add("gecode_range",
01801                        &p_range);
01802         registry().add("gecode_set_weights",
01803                        &p_weights);
01804       }
01805     };
01806     SetPoster __set_poster;
01807 #endif
01808 
01809   }
01810 }}
01811 
01812 // STATISTICS: flatzinc-any