Generated on Mon Nov 30 11:16:08 2009 for Gecode by doxygen 1.5.5

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: 2009-11-27 19:25:12 +0100 (Fri, 27 Nov 2009) $ by $Author: tack $
00015  *     $Revision: 10137 $
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/scheduling.hh>
00046 #include <gecode/minimodel.hh>
00047 #ifdef GECODE_HAS_SET_VARS
00048 #include <gecode/set.hh>
00049 #endif
00050 #include <gecode/flatzinc.hh>
00051 
00052 namespace Gecode { namespace FlatZinc {
00053 
00054   Registry& registry(void) {
00055     static Registry r;
00056     return r;
00057   }
00058 
00059   void
00060   Registry::post(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00061     std::map<std::string,poster>::iterator i = r.find(ce.id);
00062     if (i == r.end()) {
00063       throw FlatZinc::Error("Registry",
00064         std::string("Constraint ")+ce.id+" not found");
00065     }
00066     i->second(s, ce, ann);
00067   }
00068 
00069   void
00070   Registry::add(const std::string& id, poster p) {
00071     r[id] = p;
00072   }
00073 
00074   namespace {
00075   
00076     IntConLevel ann2icl(AST::Node* ann) {
00077       if (ann) {
00078         if (ann->hasAtom("val"))
00079           return ICL_VAL;
00080         if (ann->hasAtom("domain"))
00081           return ICL_DOM;
00082         if (ann->hasAtom("bounds") ||
00083             ann->hasAtom("boundsR") ||
00084             ann->hasAtom("boundsD") ||
00085             ann->hasAtom("boundsZ"))
00086           return ICL_BND;
00087       }
00088       return ICL_DEF;
00089     }
00090   
00091     inline IntRelType
00092     swap(IntRelType irt) {
00093       switch (irt) {
00094       case IRT_LQ: return IRT_GQ;
00095       case IRT_LE: return IRT_GR;
00096       case IRT_GQ: return IRT_LQ;
00097       case IRT_GR: return IRT_LE;
00098       default:     return irt;
00099       }
00100     }
00101 
00102     inline IntRelType
00103     neg(IntRelType irt) {
00104       switch (irt) {
00105       case IRT_EQ: return IRT_NQ;
00106       case IRT_NQ: return IRT_EQ;
00107       case IRT_LQ: return IRT_GR;
00108       case IRT_LE: return IRT_GQ;
00109       case IRT_GQ: return IRT_LE;
00110       case IRT_GR:
00111       default:
00112         assert(irt == IRT_GR);
00113       }
00114       return IRT_LQ;
00115     }
00116 
00117     inline IntArgs arg2intargs(AST::Node* arg, int offset = 0) {
00118       AST::Array* a = arg->getArray();
00119       IntArgs ia(a->a.size()+offset);
00120       for (int i=offset; i--;)
00121         ia[i] = 0;
00122       for (int i=a->a.size(); i--;)
00123         ia[i+offset] = a->a[i]->getInt();
00124       return ia;
00125     }
00126 
00127     inline IntArgs arg2boolargs(AST::Node* arg, int offset = 0) {
00128       AST::Array* a = arg->getArray();
00129       IntArgs ia(a->a.size()+offset);
00130       for (int i=offset; i--;)
00131         ia[i] = 0;
00132       for (int i=a->a.size(); i--;)
00133         ia[i+offset] = a->a[i]->getBool();
00134       return ia;
00135     }
00136 
00137     inline IntSet arg2intset(FlatZincSpace& s, AST::Node* n) {
00138       AST::SetLit* sl = n->getSet();
00139       IntSet d;
00140       if (sl->interval) {
00141         d = IntSet(sl->min, sl->max);
00142       } else {
00143         Region re(s);
00144         int* is = re.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
00145         for (int i=sl->s.size(); i--; )
00146           is[i] = sl->s[i];
00147         d = IntSet(is, sl->s.size());
00148       }
00149       return d;
00150     }
00151 
00152     inline IntSetArgs arg2intsetargs(FlatZincSpace& s,
00153                                      AST::Node* arg, int offset = 0) {
00154       AST::Array* a = arg->getArray();
00155       if (a->a.size() == 0) {
00156         IntSetArgs emptyIa(0);
00157         return emptyIa;
00158       }
00159       IntSetArgs ia(a->a.size()+offset);      
00160       for (int i=offset; i--;)
00161         ia[i] = IntSet::empty;
00162       for (int i=a->a.size(); i--;) {
00163         ia[i+offset] = arg2intset(s, a->a[i]);
00164       }
00165       return ia;
00166     }
00167   
00168     inline IntVarArgs arg2intvarargs(FlatZincSpace& s, AST::Node* arg,
00169                                      int offset = 0) {
00170       AST::Array* a = arg->getArray();
00171       if (a->a.size() == 0) {
00172         IntVarArgs emptyIa(0);
00173         return emptyIa;
00174       }
00175       IntVarArgs ia(a->a.size()+offset);
00176       for (int i=offset; i--;)
00177         ia[i] = IntVar(s, 0, 0);
00178       for (int i=a->a.size(); i--;) {
00179         if (a->a[i]->isIntVar()) {
00180           ia[i+offset] = s.iv[a->a[i]->getIntVar()];        
00181         } else {
00182           int value = a->a[i]->getInt();
00183           IntVar iv(s, value, value);
00184           ia[i+offset] = iv;        
00185         }
00186       }
00187       return ia;
00188     }
00189 
00190     inline BoolVarArgs arg2boolvarargs(FlatZincSpace& s, AST::Node* arg,
00191                                        int offset = 0) {
00192       AST::Array* a = arg->getArray();
00193       if (a->a.size() == 0) {
00194         BoolVarArgs emptyIa(0);
00195         return emptyIa;
00196       }
00197       BoolVarArgs ia(a->a.size()+offset);
00198       for (int i=offset; i--;)
00199         ia[i] = BoolVar(s, 0, 0);
00200       for (int i=a->a.size(); i--;) {
00201         if (a->a[i]->isBool()) {
00202           bool value = a->a[i]->getBool();
00203           BoolVar iv(s, value, value);
00204           ia[i+offset] = iv;
00205         } else {
00206           ia[i+offset] = s.bv[a->a[i]->getBoolVar()];
00207         }
00208       }
00209       return ia;
00210     }
00211 
00212 #ifdef GECODE_HAS_SET_VARS
00213     SetVar getSetVar(FlatZincSpace& s, AST::Node* n) {
00214       SetVar x0;
00215       if (!n->isSetVar()) {
00216         IntSet d = arg2intset(s,n);
00217         x0 = SetVar(s, d, d);        
00218       } else {
00219         x0 = s.sv[n->getSetVar()];
00220       }
00221       return x0;
00222     }
00223 
00224     inline SetVarArgs arg2setvarargs(FlatZincSpace& s, AST::Node* arg,
00225                                      int offset = 0) {
00226       AST::Array* a = arg->getArray();
00227       if (a->a.size() == 0) {
00228         SetVarArgs emptyIa(0);
00229         return emptyIa;
00230       }
00231       SetVarArgs ia(a->a.size()+offset);
00232       for (int i=offset; i--;)
00233         ia[i] = SetVar(s, IntSet::empty, IntSet::empty);
00234       for (int i=a->a.size(); i--;) {
00235         ia[i+offset] = getSetVar(s, a->a[i]);
00236       }
00237       return ia;
00238     }
00239 #endif
00240 
00241     BoolVar getBoolVar(FlatZincSpace& s, AST::Node* n) {
00242       BoolVar x0;
00243       if (n->isBool()) {
00244         x0 = BoolVar(s, n->getBool(), n->getBool());
00245       }
00246       else {
00247         x0 = s.bv[n->getBoolVar()];
00248       }
00249       return x0;
00250     }
00251 
00252     IntVar getIntVar(FlatZincSpace& s, AST::Node* n) {
00253       IntVar x0;
00254       if (n->isIntVar()) {
00255         x0 = s.iv[n->getIntVar()];
00256       } else {
00257         x0 = IntVar(s, n->getInt(), n->getInt());            
00258       }
00259       return x0;
00260     }
00261 
00262     void p_distinct(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00263       IntVarArgs va = arg2intvarargs(s, ce[0]);
00264       distinct(s, va, ann2icl(ann));    
00265     }
00266     void p_distinctOffset(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00267       IntVarArgs va = arg2intvarargs(s, ce[1]);
00268       AST::Array* offs = ce.args->a[0]->getArray();
00269       IntArgs oa(offs->a.size());
00270       for (int i=offs->a.size(); i--; ) {
00271         oa[i] = offs->a[i]->getInt();    
00272       }
00273       distinct(s, oa, va, ann2icl(ann));
00274     }
00275 
00276     void p_int_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00277                    AST::Node* ann) {
00278       if (ce[0]->isIntVar()) {
00279         if (ce[1]->isIntVar()) {
00280           rel(s, getIntVar(s, ce[0]), irt, getIntVar(s, ce[1]), 
00281               ann2icl(ann));
00282         } else {
00283           rel(s, getIntVar(s, ce[0]), irt, ce[1]->getInt(), ann2icl(ann));
00284         }
00285       } else {
00286         rel(s, getIntVar(s, ce[1]), swap(irt), ce[0]->getInt(), 
00287             ann2icl(ann));
00288       }
00289     }
00290     void p_int_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00291       p_int_CMP(s, IRT_EQ, ce, ann);
00292     }
00293     void p_int_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00294       p_int_CMP(s, IRT_NQ, ce, ann);
00295     }
00296     void p_int_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00297       p_int_CMP(s, IRT_GQ, ce, ann);
00298     }
00299     void p_int_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00300       p_int_CMP(s, IRT_GR, ce, ann);
00301     }
00302     void p_int_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00303       p_int_CMP(s, IRT_LQ, ce, ann);
00304     }
00305     void p_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00306       p_int_CMP(s, IRT_LE, ce, ann);
00307     }
00308     void p_int_CMP_reif(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00309                         AST::Node* ann) {
00310       if (ce[2]->isBool()) {
00311         if (ce[2]->getBool()) {
00312           p_int_CMP(s, irt, ce, ann);
00313         } else {
00314           p_int_CMP(s, neg(irt), ce, ann);
00315         }
00316         return;
00317       }
00318       if (ce[0]->isIntVar()) {
00319         if (ce[1]->isIntVar()) {
00320           rel(s, getIntVar(s, ce[0]), irt, getIntVar(s, ce[1]),
00321                  getBoolVar(s, ce[2]), ann2icl(ann));
00322         } else {
00323           rel(s, getIntVar(s, ce[0]), irt, ce[1]->getInt(),
00324                  getBoolVar(s, ce[2]), ann2icl(ann));
00325         }
00326       } else {
00327         rel(s, getIntVar(s, ce[1]), swap(irt), ce[0]->getInt(),
00328                getBoolVar(s, ce[2]), ann2icl(ann));
00329       }
00330     }
00331 
00332     /* Comparisons */
00333     void p_int_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00334       p_int_CMP_reif(s, IRT_EQ, ce, ann);
00335     }
00336     void p_int_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00337       p_int_CMP_reif(s, IRT_NQ, ce, ann);
00338     }
00339     void p_int_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00340       p_int_CMP_reif(s, IRT_GQ, ce, ann);
00341     }
00342     void p_int_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00343       p_int_CMP_reif(s, IRT_GR, ce, ann);
00344     }
00345     void p_int_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00346       p_int_CMP_reif(s, IRT_LQ, ce, ann);
00347     }
00348     void p_int_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00349       p_int_CMP_reif(s, IRT_LE, ce, ann);
00350     }
00351 
00352     /* linear (in-)equations */
00353     void p_int_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00354                        AST::Node* ann) {
00355       IntArgs ia = arg2intargs(ce[0]);
00356       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00357       linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00358     }
00359     void p_int_lin_CMP_reif(FlatZincSpace& s, IntRelType irt,
00360                             const ConExpr& ce, AST::Node* ann) {
00361       if (ce[2]->isBool()) {
00362         if (ce[2]->getBool()) {
00363           p_int_lin_CMP(s, irt, ce, ann);
00364         } else {
00365           p_int_lin_CMP(s, neg(irt), ce, ann);
00366         }
00367         return;
00368       }
00369       IntArgs ia = arg2intargs(ce[0]);
00370       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00371       linear(s, ia, iv, irt, ce[2]->getInt(), getBoolVar(s, ce[3]), 
00372              ann2icl(ann));
00373     }
00374     void p_int_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00375       p_int_lin_CMP(s, IRT_EQ, ce, ann);
00376     }
00377     void p_int_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00378       p_int_lin_CMP_reif(s, IRT_EQ, ce, ann);    
00379     }
00380     void p_int_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00381       p_int_lin_CMP(s, IRT_NQ, ce, ann);
00382     }
00383     void p_int_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00384       p_int_lin_CMP_reif(s, IRT_NQ, ce, ann);    
00385     }
00386     void p_int_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00387       p_int_lin_CMP(s, IRT_LQ, ce, ann);
00388     }
00389     void p_int_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00390       p_int_lin_CMP_reif(s, IRT_LQ, ce, ann);    
00391     }
00392     void p_int_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00393       p_int_lin_CMP(s, IRT_LE, ce, ann);
00394     }
00395     void p_int_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00396       p_int_lin_CMP_reif(s, IRT_LE, ce, ann);    
00397     }
00398     void p_int_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00399       p_int_lin_CMP(s, IRT_GQ, ce, ann);
00400     }
00401     void p_int_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00402       p_int_lin_CMP_reif(s, IRT_GQ, ce, ann);    
00403     }
00404     void p_int_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00405       p_int_lin_CMP(s, IRT_GR, ce, ann);
00406     }
00407     void p_int_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00408       p_int_lin_CMP_reif(s, IRT_GR, ce, ann);    
00409     }
00410 
00411     void p_bool_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00412                         AST::Node* ann) {
00413       IntArgs ia = arg2intargs(ce[0]);
00414       BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00415       if (ce[2]->isIntVar())
00416         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], ann2icl(ann));
00417       else
00418         linear(s, ia, iv, irt, ce[2]->getInt(), ann2icl(ann));
00419     }
00420     void p_bool_lin_CMP_reif(FlatZincSpace& s, IntRelType irt,
00421                             const ConExpr& ce, AST::Node* ann) {
00422       if (ce[2]->isBool()) {
00423         if (ce[2]->getBool()) {
00424           p_bool_lin_CMP(s, irt, ce, ann);
00425         } else {
00426           p_bool_lin_CMP(s, neg(irt), ce, ann);
00427         }
00428         return;
00429       }
00430       IntArgs ia = arg2intargs(ce[0]);
00431       BoolVarArgs iv = arg2boolvarargs(s, ce[1]);
00432       if (ce[2]->isIntVar())
00433         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], getBoolVar(s, ce[3]), 
00434                ann2icl(ann));
00435       else
00436         linear(s, ia, iv, irt, ce[2]->getInt(), getBoolVar(s, ce[3]), 
00437                ann2icl(ann));
00438     }
00439     void p_bool_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00440       p_bool_lin_CMP(s, IRT_EQ, ce, ann);
00441     }
00442     void p_bool_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00443     {
00444       p_bool_lin_CMP_reif(s, IRT_EQ, ce, ann);
00445     }
00446     void p_bool_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00447       p_bool_lin_CMP(s, IRT_NQ, ce, ann);
00448     }
00449     void p_bool_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00450     {
00451       p_bool_lin_CMP_reif(s, IRT_NQ, ce, ann);
00452     }
00453     void p_bool_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00454       p_bool_lin_CMP(s, IRT_LQ, ce, ann);
00455     }
00456     void p_bool_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00457     {
00458       p_bool_lin_CMP_reif(s, IRT_LQ, ce, ann);
00459     }
00460     void p_bool_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00461     {
00462       p_bool_lin_CMP(s, IRT_LE, ce, ann);
00463     }
00464     void p_bool_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00465     {
00466       p_bool_lin_CMP_reif(s, IRT_LE, ce, ann);
00467     }
00468     void p_bool_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00469       p_bool_lin_CMP(s, IRT_GQ, ce, ann);
00470     }
00471     void p_bool_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00472     {
00473       p_bool_lin_CMP_reif(s, IRT_GQ, ce, ann);
00474     }
00475     void p_bool_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00476       p_bool_lin_CMP(s, IRT_GR, ce, ann);
00477     }
00478     void p_bool_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) 
00479     {
00480       p_bool_lin_CMP_reif(s, IRT_GR, ce, ann);
00481     }
00482 
00483     /* arithmetic constraints */
00484   
00485     void p_int_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00486       if (!ce[0]->isIntVar()) {
00487         post(s, ce[0]->getInt() + getIntVar(s, ce[1])
00488                 == getIntVar(s,ce[2]), ann2icl(ann));
00489       } else if (!ce[1]->isIntVar()) {
00490         post(s, getIntVar(s,ce[0]) + ce[1]->getInt()
00491                 == getIntVar(s,ce[2]), ann2icl(ann));
00492       } else if (!ce[2]->isIntVar()) {
00493         post(s, getIntVar(s,ce[0]) + getIntVar(s,ce[1]) 
00494                 == ce[2]->getInt(), ann2icl(ann));
00495       } else {
00496         post(s, getIntVar(s,ce[0]) + getIntVar(s,ce[1]) 
00497                 == getIntVar(s,ce[2]), ann2icl(ann));
00498       }
00499     }
00500 
00501     void p_int_minus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00502       if (!ce[0]->isIntVar()) {
00503         post(s, ce[0]->getInt() - getIntVar(s, ce[1])
00504                 == getIntVar(s,ce[2]), ann2icl(ann));
00505       } else if (!ce[1]->isIntVar()) {
00506         post(s, getIntVar(s,ce[0]) - ce[1]->getInt()
00507                 == getIntVar(s,ce[2]), ann2icl(ann));
00508       } else if (!ce[2]->isIntVar()) {
00509         post(s, getIntVar(s,ce[0]) - getIntVar(s,ce[1]) 
00510                 == ce[2]->getInt(), ann2icl(ann));
00511       } else {
00512         post(s, getIntVar(s,ce[0]) - getIntVar(s,ce[1]) 
00513                 == getIntVar(s,ce[2]), ann2icl(ann));
00514       }
00515     }
00516 
00517     void p_int_times(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00518       IntVar x0 = getIntVar(s, ce[0]);
00519       IntVar x1 = getIntVar(s, ce[1]);
00520       IntVar x2 = getIntVar(s, ce[2]);
00521       mult(s, x0, x1, x2, ann2icl(ann));    
00522     }
00523     void p_int_div(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00524       IntVar x0 = getIntVar(s, ce[0]);
00525       IntVar x1 = getIntVar(s, ce[1]);
00526       IntVar x2 = getIntVar(s, ce[2]);
00527       div(s,x0,x1,x2, ann2icl(ann));
00528     }
00529     void p_int_mod(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00530       IntVar x0 = getIntVar(s, ce[0]);
00531       IntVar x1 = getIntVar(s, ce[1]);
00532       IntVar x2 = getIntVar(s, ce[2]);
00533       mod(s,x0,x1,x2, ann2icl(ann));
00534     }
00535 
00536     void p_int_min(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00537       IntVar x0 = getIntVar(s, ce[0]);
00538       IntVar x1 = getIntVar(s, ce[1]);
00539       IntVar x2 = getIntVar(s, ce[2]);
00540       min(s, x0, x1, x2, ann2icl(ann));
00541     }
00542     void p_int_max(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00543       IntVar x0 = getIntVar(s, ce[0]);
00544       IntVar x1 = getIntVar(s, ce[1]);
00545       IntVar x2 = getIntVar(s, ce[2]);
00546       max(s, x0, x1, x2, ann2icl(ann));
00547     }
00548     void p_int_negate(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00549       IntVar x0 = getIntVar(s, ce[0]);
00550       IntVar x1 = getIntVar(s, ce[1]);
00551       post(s, x0 == -x1, ann2icl(ann));
00552     }
00553 
00554     /* Boolean constraints */
00555     void p_bool_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00556                    AST::Node* ann) {
00557       if (ce[0]->isBoolVar()) {
00558         if (ce[1]->isBoolVar()) {
00559           rel(s, getBoolVar(s, ce[0]), irt, getBoolVar(s, ce[1]), 
00560               ann2icl(ann));
00561         } else {
00562           rel(s, getBoolVar(s, ce[0]), irt, ce[1]->getBool(), ann2icl(ann));
00563         }
00564       } else {
00565         rel(s, getBoolVar(s, ce[1]), swap(irt), ce[0]->getBool(), 
00566             ann2icl(ann));
00567       }
00568     }
00569     void p_bool_CMP_reif(FlatZincSpace& s, IntRelType irt, const ConExpr& ce, 
00570                    AST::Node* ann) {
00571       rel(s, getBoolVar(s, ce[0]), irt, getBoolVar(s, ce[1]),
00572             getBoolVar(s, ce[2]), ann2icl(ann));
00573     }
00574     void p_bool_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00575       p_bool_CMP(s, IRT_EQ, ce, ann);
00576     }
00577     void p_bool_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00578       p_bool_CMP_reif(s, IRT_EQ, ce, ann);
00579     }
00580     void p_bool_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00581       p_bool_CMP(s, IRT_NQ, ce, ann);
00582     }
00583     void p_bool_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00584       p_bool_CMP_reif(s, IRT_NQ, ce, ann);
00585     }
00586     void p_bool_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00587       p_bool_CMP(s, IRT_GQ, ce, ann);
00588     }
00589     void p_bool_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00590       p_bool_CMP_reif(s, IRT_GQ, ce, ann);
00591     }
00592     void p_bool_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00593       p_bool_CMP(s, IRT_LQ, ce, ann);
00594     }
00595     void p_bool_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00596       p_bool_CMP_reif(s, IRT_LQ, ce, ann);
00597     }
00598     void p_bool_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00599       p_bool_CMP(s, IRT_GR, ce, ann);
00600     }
00601     void p_bool_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00602       p_bool_CMP_reif(s, IRT_GR, ce, ann);
00603     }
00604     void p_bool_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00605       p_bool_CMP(s, IRT_LE, ce, ann);
00606     }
00607     void p_bool_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00608       p_bool_CMP_reif(s, IRT_LE, ce, ann);
00609     }
00610 
00611 #define BOOL_OP(op) \
00612     BoolVar b0 = getBoolVar(s, ce[0]); \
00613     BoolVar b1 = getBoolVar(s, ce[1]); \
00614     if (ce[2]->isBool()) { \
00615       rel(s, b0, op, b1, ce[2]->getBool(), ann2icl(ann)); \
00616     } else { \
00617       rel(s, b0, op, b1, s.bv[ce[2]->getBoolVar()], ann2icl(ann)); \
00618     }
00619 
00620 #define BOOL_ARRAY_OP(op) \
00621     BoolVarArgs bv = arg2boolvarargs(s, ce[0]); \
00622     if (ce[1]->isBool()) { \
00623       rel(s, op, bv, ce[1]->getBool(), ann2icl(ann)); \
00624     } else { \
00625       rel(s, op, bv, s.bv[ce[1]->getBoolVar()], ann2icl(ann)); \
00626     }
00627 
00628     void p_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00629       BOOL_OP(BOT_OR);
00630     }
00631     void p_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00632       BOOL_OP(BOT_AND);
00633     }
00634     void p_array_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00635     {
00636       BOOL_ARRAY_OP(BOT_AND);
00637     }
00638     void p_array_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00639     {
00640       BOOL_ARRAY_OP(BOT_OR);
00641     }
00642     void p_array_bool_clause(FlatZincSpace& s, const ConExpr& ce,
00643                              AST::Node* ann) {
00644       BoolVarArgs bvp = arg2boolvarargs(s, ce[0]);
00645       BoolVarArgs bvn = arg2boolvarargs(s, ce[1]);
00646       clause(s, BOT_OR, bvp, bvn, 1, ann2icl(ann));
00647     }
00648     void p_array_bool_clause_reif(FlatZincSpace& s, const ConExpr& ce,
00649                              AST::Node* ann) {
00650       BoolVarArgs bvp = arg2boolvarargs(s, ce[0]);
00651       BoolVarArgs bvn = arg2boolvarargs(s, ce[1]);
00652       BoolVar b0 = getBoolVar(s, ce[2]);
00653       clause(s, BOT_OR, bvp, bvn, b0, ann2icl(ann));
00654     }
00655     void p_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00656       BOOL_OP(BOT_XOR);
00657     }
00658     void p_bool_l_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00659       BoolVar b0 = getBoolVar(s, ce[0]);
00660       BoolVar b1 = getBoolVar(s, ce[1]);
00661       if (ce[2]->isBool()) {
00662         rel(s, b1, BOT_IMP, b0, ce[2]->getBool(), ann2icl(ann));
00663       } else {
00664         rel(s, b1, BOT_IMP, b0, s.bv[ce[2]->getBoolVar()], ann2icl(ann));
00665       }
00666     }
00667     void p_bool_r_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00668       BOOL_OP(BOT_IMP);
00669     }
00670     void p_bool_not(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00671       BoolVar x0 = getBoolVar(s, ce[0]);
00672       BoolVar x1 = getBoolVar(s, ce[1]);
00673       rel(s, x0, BOT_XOR, x1, 1, ann2icl(ann));
00674     }
00675   
00676     /* element constraints */
00677     void p_array_int_element(FlatZincSpace& s, const ConExpr& ce, 
00678                                  AST::Node* ann) {
00679       bool isConstant = true;
00680       AST::Array* a = ce[1]->getArray();
00681       for (int i=a->a.size(); i--;) {
00682         if (!a->a[i]->isInt()) {
00683           isConstant = false;
00684           break;
00685         }
00686       }
00687       IntVar selector = getIntVar(s, ce[0]);
00688       post(s, selector > 0);
00689       if (isConstant) {
00690         IntArgs ia = arg2intargs(ce[1], 1);
00691         element(s, ia, selector, getIntVar(s, ce[2]), ann2icl(ann));
00692       } else {
00693         IntVarArgs iv = arg2intvarargs(s, ce[1], 1);
00694         element(s, iv, selector, getIntVar(s, ce[2]), ann2icl(ann));
00695       }
00696     }
00697     void p_array_bool_element(FlatZincSpace& s, const ConExpr& ce, 
00698                                   AST::Node* ann) {
00699       bool isConstant = true;
00700       AST::Array* a = ce[1]->getArray();
00701       for (int i=a->a.size(); i--;) {
00702         if (!a->a[i]->isBool()) {
00703           isConstant = false;
00704           break;
00705         }
00706       }
00707       IntVar selector = getIntVar(s, ce[0]);
00708       post(s, selector > 0);
00709       if (isConstant) {
00710         IntArgs ia = arg2boolargs(ce[1], 1);
00711         element(s, ia, selector, getBoolVar(s, ce[2]), ann2icl(ann));
00712       } else {
00713         BoolVarArgs iv = arg2boolvarargs(s, ce[1], 1);
00714         element(s, iv, selector, getBoolVar(s, ce[2]), ann2icl(ann));
00715       }
00716     }
00717   
00718     /* coercion constraints */
00719     void p_bool2int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00720       BoolVar x0 = getBoolVar(s, ce[0]);
00721       IntVar x1 = getIntVar(s, ce[1]);
00722       channel(s, x0, x1, ann2icl(ann));
00723     }
00724 
00725     /* constraints from the standard library */
00726   
00727     void p_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00728       IntVar x0 = getIntVar(s, ce[0]);
00729       IntVar x1 = getIntVar(s, ce[1]);
00730       abs(s, x0, x1, ann2icl(ann));
00731     }
00732   
00733     void p_array_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00734       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00735       IntVarArgs iv1 = arg2intvarargs(s, ce[1]);
00736       rel(s, iv0, IRT_LE, iv1, ann2icl(ann));
00737     }
00738 
00739     void p_array_int_lq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00740       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00741       IntVarArgs iv1 = arg2intvarargs(s, ce[1]);
00742       rel(s, iv0, IRT_LQ, iv1, ann2icl(ann));
00743     }
00744   
00745     void p_count(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00746       IntVarArgs iv = arg2intvarargs(s, ce[0]);
00747       if (!ce[1]->isIntVar()) {
00748         if (!ce[2]->isIntVar()) {
00749           count(s, iv, ce[1]->getInt(), IRT_EQ, ce[2]->getInt(), 
00750                 ann2icl(ann));
00751         } else {
00752           count(s, iv, ce[1]->getInt(), IRT_EQ, getIntVar(s, ce[2]), 
00753                 ann2icl(ann));
00754         }
00755       } else if (!ce[2]->isIntVar()) {
00756         count(s, iv, getIntVar(s, ce[1]), IRT_EQ, ce[2]->getInt(), 
00757               ann2icl(ann));
00758       } else {
00759         count(s, iv, getIntVar(s, ce[1]), IRT_EQ, getIntVar(s, ce[2]), 
00760               ann2icl(ann));
00761       }
00762     }
00763 
00764     void count_rel(IntRelType irt,
00765                    FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00766       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00767       count(s, iv, ce[2]->getInt(), irt, ce[0]->getInt(), ann2icl(ann));
00768     }
00769 
00770     void p_at_most(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00771       count_rel(IRT_LQ, s, ce, ann);
00772     }
00773 
00774     void p_at_least(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00775       count_rel(IRT_GQ, s, ce, ann);
00776     }
00777 
00778     void p_global_cardinality(FlatZincSpace& s, const ConExpr& ce,
00779                               AST::Node* ann) {
00780       IntVarArgs iv0 = arg2intvarargs(s, ce[0]);
00781       IntVarArgs iv1 = arg2intvarargs(s, ce[1]);
00782       int cmin = ce[2]->getInt();
00783 
00784       int smallest = cmin;
00785       int largest = iv1.size()-1;
00786       for (int i=iv0.size(); i--;) {
00787         smallest = std::min(smallest, iv0[i].min());
00788         largest = std::max(largest, iv0[i].max());
00789       }
00790       
00791 
00792       if (cmin == 0 && smallest == 0 && largest == iv1.size()-1) {
00793         count(s, iv0, iv1, ann2icl(ann));      
00794       } else {
00795         IntArgs values(largest - smallest + 1);
00796         for (int i=largest-smallest+1; i--;)
00797           values[i] = i+smallest;
00798         IntVarArgs iv1tmp(largest-smallest+1);
00799         int k = 0;
00800         for (int i=cmin-smallest; i--;) {
00801           iv1tmp[k++] = IntVar(s, 0, iv0.size());
00802         }
00803         for (int i=0; i<iv1.size(); i++)
00804           iv1tmp[k++] = iv1[i];
00805         for (int i=k; i<iv1tmp.size(); i++) {
00806           iv1tmp[i] = IntVar(s, 0, iv0.size());
00807         }
00808         count(s, iv0, iv1tmp, values, ann2icl(ann));
00809       }
00810     }
00811 
00812     void p_minimum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00813       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00814       min(s, iv, getIntVar(s, ce[0]), ann2icl(ann));
00815     }
00816 
00817     void p_maximum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00818       IntVarArgs iv = arg2intvarargs(s, ce[1]);
00819       max(s, iv, getIntVar(s, ce[0]), ann2icl(ann));
00820     }
00821 
00822     void p_regular(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00823       IntVarArgs iv = arg2intvarargs(s, ce[0]);
00824       int q = ce[1]->getInt();
00825       int symbols = ce[2]->getInt();
00826       IntArgs d = arg2intargs(ce[3]);
00827       int q0 = ce[4]->getInt();
00828 
00829       int noOfTrans = 0;
00830       for (int i=1; i<=q; i++) {
00831         for (int j=1; j<=symbols; j++) {
00832           if (d[(i-1)*symbols+(j-1)] > 0)
00833             noOfTrans++;
00834         }
00835       }
00836     
00837       Region re(s);
00838       DFA::Transition* t = re.alloc<DFA::Transition>(noOfTrans+1);
00839       noOfTrans = 0;
00840       for (int i=1; i<=q; i++) {
00841         for (int j=1; j<=symbols; j++) {
00842           if (d[(i-1)*symbols+(j-1)] > 0) {
00843             t[noOfTrans].i_state = i;
00844             t[noOfTrans].symbol  = j;
00845             t[noOfTrans].o_state = d[(i-1)*symbols+(j-1)];
00846             noOfTrans++;
00847           }
00848         }
00849       }
00850       t[noOfTrans].i_state = -1;
00851     
00852       // Final states
00853       AST::SetLit* sl = ce[5]->getSet();
00854       int* f;
00855       if (sl->interval) {
00856         f = static_cast<int*>(malloc(sizeof(int)*(sl->max-sl->min+2)));
00857         for (int i=sl->min; i<=sl->max; i++)
00858           f[i-sl->min] = i;
00859         f[sl->max-sl->min+1] = -1;
00860       } else {
00861         f = static_cast<int*>(malloc(sizeof(int)*(sl->s.size()+1)));
00862         for (int j=sl->s.size(); j--; )
00863           f[j] = sl->s[j];
00864         f[sl->s.size()] = -1;
00865       }
00866         
00867       DFA dfa(q0,t,f);
00868       free(f);
00869       extensional(s, iv, dfa, ann2icl(ann));
00870     }
00871 
00872     void
00873     p_sort(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00874       IntVarArgs x = arg2intvarargs(s, ce[0]);
00875       IntVarArgs y = arg2intvarargs(s, ce[1]);
00876       IntVarArgs xy(x.size()+y.size());
00877       for (int i=x.size(); i--;)
00878         xy[i] = x[i];
00879       for (int i=y.size(); i--;)
00880         xy[i+x.size()] = y[i];
00881       unshare(s, xy);
00882       for (int i=x.size(); i--;)
00883         x[i] = xy[i];
00884       for (int i=y.size(); i--;)
00885         y[i] = xy[i+x.size()];
00886       sorted(s, x, y, ann2icl(ann));
00887     }
00888 
00889     void
00890     p_inverse_offsets(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00891       IntVarArgs x = arg2intvarargs(s, ce[0]);
00892       int xoff = ce[1]->getInt();
00893       IntVarArgs y = arg2intvarargs(s, ce[2]);
00894       int yoff = ce[3]->getInt();
00895       channel(s, x, xoff, y, yoff, ann2icl(ann));
00896     }
00897 
00898     void
00899     p_increasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00900       IntVarArgs x = arg2intvarargs(s, ce[0]);
00901       rel(s,x,IRT_LQ,ann2icl(ann));
00902     }
00903 
00904     void
00905     p_increasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00906       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
00907       rel(s,x,IRT_LQ,ann2icl(ann));
00908     }
00909 
00910     void
00911     p_table_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00912       IntVarArgs x = arg2intvarargs(s, ce[0]);
00913       IntArgs tuples = arg2intargs(ce[1]);
00914       int noOfVars   = x.size();
00915       int noOfTuples = tuples.size()/noOfVars;
00916       TupleSet ts;
00917       for (int i=0; i<noOfTuples; i++) {
00918         IntArgs t(noOfVars);
00919         for (int j=0; j<x.size(); j++) {
00920           t[j] = tuples[i*noOfVars+j];
00921         }
00922         ts.add(t);
00923       }
00924       ts.finalize();
00925       extensional(s,x,ts,EPK_DEF,ann2icl(ann));
00926     }
00927     void
00928     p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00929       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
00930       IntArgs tuples = arg2boolargs(ce[1]);
00931       int noOfVars   = x.size();
00932       int noOfTuples = tuples.size()/noOfVars;
00933       TupleSet ts;
00934       for (int i=0; i<noOfTuples; i++) {
00935         IntArgs t(noOfVars);
00936         for (int j=0; j<x.size(); j++) {
00937           t[j] = tuples[i*noOfVars+j];
00938         }
00939         ts.add(t);
00940       }
00941       ts.finalize();
00942       extensional(s,x,ts,EPK_DEF,ann2icl(ann));
00943     }
00944 
00945     void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
00946                       AST::Node* ann) {
00947       IntVarArgs start = arg2intvarargs(s, ce[0]);
00948       IntVarArgs duration = arg2intvarargs(s, ce[1]);
00949       IntVarArgs height = arg2intvarargs(s, ce[2]);
00950       int n = start.size();
00951       IntVar bound = getIntVar(s, ce[3]);
00952 
00953       if (bound.assigned()) {
00954         IntArgs machine(n);
00955         for (int i = n; i--; ) machine[i] = 0;
00956         IntArgs limit(1, bound.val());
00957         IntVarArgs end(n);
00958         for (int i = n; i--; ) end[i] = IntVar(s, 0, Int::Limits::max);
00959         cumulatives(s, machine, start, duration, end, height, limit, true,
00960                     ann2icl(ann));
00961       } else {
00962         int min = Gecode::Int::Limits::max;
00963         int max = Gecode::Int::Limits::min;
00964         IntVarArgs end(start.size());
00965         for (int i = start.size(); i--; ) {
00966           min = std::min(min, start[i].min());
00967           max = std::max(max, start[i].max() + duration[i].max());
00968           end[i] = post(s, start[i] + duration[i]);
00969         }
00970         for (int time = min; time < max; ++time) {
00971           IntVarArgs x(start.size());
00972           for (int i = start.size(); i--; ) {
00973             IntVar overlaps = channel(s, post(s, (~(start[i] <= time) && 
00974                                                   ~(time < end[i]))));
00975             x[i] = mult(s, overlaps, height[i]);
00976           }
00977           linear(s, x, IRT_LQ, bound);
00978         }
00979       }
00980     }
00981 
00982     void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
00983                          AST::Node* ann) {
00984       IntVarArgs x = arg2intvarargs(s, ce[0]);
00985       IntSet S = arg2intset(s, ce[1]);
00986       int q = ce[2]->getInt();
00987       int l = ce[3]->getInt();
00988       int u = ce[4]->getInt();
00989       sequence(s, x, S, q, l, u, ann2icl(ann));
00990     }
00991 
00992     void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
00993                           AST::Node* ann) {
00994       BoolVarArgs x = arg2boolvarargs(s, ce[0]);
00995       bool val = ce[1]->getBool();
00996       int q = ce[2]->getInt();
00997       int l = ce[3]->getInt();
00998       int u = ce[4]->getInt();
00999       IntSet S(val, val);
01000       sequence(s, x, S, q, l, u, ann2icl(ann));
01001     }
01002 
01003     class IntPoster {
01004     public:
01005       IntPoster(void) {
01006         registry().add("all_different_int", &p_distinct);
01007         registry().add("all_different_offset", &p_distinctOffset);
01008         registry().add("int_eq", &p_int_eq);
01009         registry().add("int_ne", &p_int_ne);
01010         registry().add("int_ge", &p_int_ge);
01011         registry().add("int_gt", &p_int_gt);
01012         registry().add("int_le", &p_int_le);
01013         registry().add("int_lt", &p_int_lt);
01014         registry().add("int_eq_reif", &p_int_eq_reif);
01015         registry().add("int_ne_reif", &p_int_ne_reif);
01016         registry().add("int_ge_reif", &p_int_ge_reif);
01017         registry().add("int_gt_reif", &p_int_gt_reif);
01018         registry().add("int_le_reif", &p_int_le_reif);
01019         registry().add("int_lt_reif", &p_int_lt_reif);
01020         registry().add("int_lin_eq", &p_int_lin_eq);
01021         registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
01022         registry().add("int_lin_ne", &p_int_lin_ne);
01023         registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
01024         registry().add("int_lin_le", &p_int_lin_le);
01025         registry().add("int_lin_le_reif", &p_int_lin_le_reif);
01026         registry().add("int_lin_lt", &p_int_lin_lt);
01027         registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
01028         registry().add("int_lin_ge", &p_int_lin_ge);
01029         registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
01030         registry().add("int_lin_gt", &p_int_lin_gt);
01031         registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
01032         registry().add("int_plus", &p_int_plus);
01033         registry().add("int_minus", &p_int_minus);
01034         registry().add("int_times", &p_int_times);
01035         registry().add("int_div", &p_int_div);
01036         registry().add("int_mod", &p_int_mod);
01037         registry().add("int_min", &p_int_min);
01038         registry().add("int_max", &p_int_max);
01039         registry().add("int_abs", &p_abs);
01040         registry().add("int_negate", &p_int_negate);
01041         registry().add("bool_eq", &p_bool_eq);
01042         registry().add("bool_eq_reif", &p_bool_eq_reif);
01043         registry().add("bool_ne", &p_bool_ne);
01044         registry().add("bool_ne_reif", &p_bool_ne_reif);
01045         registry().add("bool_ge", &p_bool_ge);
01046         registry().add("bool_ge_reif", &p_bool_ge_reif);
01047         registry().add("bool_le", &p_bool_le);
01048         registry().add("bool_le_reif", &p_bool_le_reif);
01049         registry().add("bool_gt", &p_bool_gt);
01050         registry().add("bool_gt_reif", &p_bool_gt_reif);
01051         registry().add("bool_lt", &p_bool_lt);
01052         registry().add("bool_lt_reif", &p_bool_lt_reif);
01053         registry().add("bool_or", &p_bool_or);
01054         registry().add("bool_and", &p_bool_and);
01055         registry().add("bool_xor", &p_bool_xor);
01056         registry().add("array_bool_and", &p_array_bool_and);
01057         registry().add("array_bool_or", &p_array_bool_or);
01058         registry().add("bool_clause", &p_array_bool_clause);
01059         registry().add("bool_clause_reif", &p_array_bool_clause_reif);
01060         registry().add("bool_left_imp", &p_bool_l_imp);
01061         registry().add("bool_right_imp", &p_bool_r_imp);
01062         registry().add("bool_not", &p_bool_not);
01063         registry().add("array_int_element", &p_array_int_element);
01064         registry().add("array_var_int_element", &p_array_int_element);
01065         registry().add("array_bool_element", &p_array_bool_element);
01066         registry().add("array_var_bool_element", &p_array_bool_element);
01067         registry().add("bool2int", &p_bool2int);
01068       
01069         registry().add("array_int_lt", &p_array_int_lt);
01070         registry().add("array_int_lq", &p_array_int_lq);
01071         registry().add("count", &p_count);
01072         registry().add("at_least_int", &p_at_least);      
01073         registry().add("at_most_int", &p_at_most);
01074         registry().add("global_cardinality_gecode", &p_global_cardinality);
01075         registry().add("minimum_int", &p_minimum);
01076         registry().add("maximum_int", &p_maximum);
01077         registry().add("regular", &p_regular);
01078         registry().add("sort", &p_sort);
01079         registry().add("inverse_offsets", &p_inverse_offsets);
01080         registry().add("increasing_int", &p_increasing_int);
01081         registry().add("increasing_bool", &p_increasing_bool);
01082         registry().add("table_int", &p_table_int);
01083         registry().add("table_bool", &p_table_bool);
01084         registry().add("cumulatives", &p_cumulatives);
01085         registry().add("among_seq_int", &p_among_seq_int);
01086         registry().add("among_seq_bool", &p_among_seq_bool);
01087 
01088         registry().add("bool_lin_eq", &p_bool_lin_eq);
01089         registry().add("bool_lin_ne", &p_bool_lin_ne);
01090         registry().add("bool_lin_le", &p_bool_lin_le);
01091         registry().add("bool_lin_lt", &p_bool_lin_lt);
01092         registry().add("bool_lin_ge", &p_bool_lin_ge);
01093         registry().add("bool_lin_gt", &p_bool_lin_gt);
01094 
01095         registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
01096         registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
01097         registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
01098         registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
01099         registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
01100         registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
01101       }
01102     };
01103     IntPoster __int_poster;
01104 
01105 #ifdef GECODE_HAS_SET_VARS
01106     void p_set_OP(FlatZincSpace& s, SetOpType op,
01107                   const ConExpr& ce, AST::Node *) {
01108       rel(s, getSetVar(s, ce[0]), op, getSetVar(s, ce[1]), 
01109           SRT_EQ, getSetVar(s, ce[2]));
01110     }
01111     void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01112       p_set_OP(s, SOT_UNION, ce, ann);
01113     }
01114     void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01115       p_set_OP(s, SOT_INTER, ce, ann);
01116     }
01117     void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01118       p_set_OP(s, SOT_MINUS, ce, ann);
01119     }
01120 
01121     void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01122       SetVar x = getSetVar(s, ce[0]);
01123       SetVar y = getSetVar(s, ce[1]);
01124 
01125       SetVarLubRanges xub(x);
01126       IntSet xubs(xub);
01127       SetVar x_y(s,IntSet::empty,xubs);
01128       rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
01129 
01130       SetVarLubRanges yub(y);
01131       IntSet yubs(yub);
01132       SetVar y_x(s,IntSet::empty,yubs);
01133       rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
01134     
01135       rel(s, x_y, SOT_UNION, y_x, SRT_EQ, getSetVar(s, ce[2]));
01136     }
01137 
01138     void p_array_set_OP(FlatZincSpace& s, SetOpType op,
01139                         const ConExpr& ce, AST::Node *) {
01140       SetVarArgs xs = arg2setvarargs(s, ce[0]);
01141       rel(s, op, xs, getSetVar(s, ce[1]));
01142     }
01143     void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01144       p_array_set_OP(s, SOT_UNION, ce, ann);
01145     }
01146     void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01147       p_array_set_OP(s, SOT_DUNION, ce, ann);
01148     }
01149 
01150 
01151     void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01152       rel(s, getSetVar(s, ce[0]), SRT_EQ, getSetVar(s, ce[1]));
01153     }
01154     void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01155       rel(s, getSetVar(s, ce[0]), SRT_NQ, getSetVar(s, ce[1]));
01156     }
01157     void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01158       rel(s, getSetVar(s, ce[0]), SRT_SUB, getSetVar(s, ce[1]));
01159     }
01160     void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01161       rel(s, getSetVar(s, ce[0]), SRT_SUP, getSetVar(s, ce[1]));
01162     }
01163     void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01164       if (!ce[1]->isIntVar()) {
01165         cardinality(s, getSetVar(s, ce[0]), ce[1]->getInt(), 
01166                     ce[1]->getInt());
01167       } else {
01168         cardinality(s, getSetVar(s, ce[0]), getIntVar(s, ce[1]));
01169       }
01170     }
01171     void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01172       if (!ce[1]->isSetVar()) {
01173         IntSet d = arg2intset(s,ce[1]);
01174         if (ce[0]->isBoolVar()) {
01175           IntSetRanges dr(d);
01176           Iter::Ranges::Singleton sr(0,1);
01177           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01178           IntSet d01(i);
01179           if (d01.size() == 0) {
01180             s.fail();
01181           } else {
01182             rel(s, getBoolVar(s, ce[0]), IRT_GQ, d01.min());
01183             rel(s, getBoolVar(s, ce[0]), IRT_LQ, d01.max());
01184           }
01185         } else {
01186           dom(s, getIntVar(s, ce[0]), d);
01187         }
01188       } else {
01189         if (!ce[0]->isIntVar()) {
01190           dom(s, getSetVar(s, ce[1]), SRT_SUP, ce[0]->getInt());
01191         } else {
01192           rel(s, getSetVar(s, ce[1]), SRT_SUP, getIntVar(s, ce[0]));
01193         }
01194       }
01195     }
01196     void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01197       rel(s, getSetVar(s, ce[0]), SRT_EQ, getSetVar(s, ce[1]),
01198           getBoolVar(s, ce[2]));
01199     }
01200     void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01201       rel(s, getSetVar(s, ce[0]), SRT_NQ, getSetVar(s, ce[1]),
01202           getBoolVar(s, ce[2]));
01203     }
01204     void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
01205                            AST::Node *) {
01206       rel(s, getSetVar(s, ce[0]), SRT_SUB, getSetVar(s, ce[1]),
01207           getBoolVar(s, ce[2]));
01208     }
01209     void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
01210                              AST::Node *) {
01211       rel(s, getSetVar(s, ce[0]), SRT_SUP, getSetVar(s, ce[1]),
01212           getBoolVar(s, ce[2]));
01213     }
01214     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01215       if (!ce[1]->isSetVar()) {
01216         IntSet d = arg2intset(s,ce[1]);
01217         if (ce[0]->isBoolVar()) {
01218           IntSetRanges dr(d);
01219           Iter::Ranges::Singleton sr(0,1);
01220           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01221           IntSet d01(i);
01222           if (d01.size() == 0) {
01223             post(s, getBoolVar(s, ce[2]) == 0);
01224           } else if (d01.max() == 0) {
01225             post(s, tt(eqv(getBoolVar(s, ce[2]), !getBoolVar(s, ce[0]))));
01226           } else if (d01.min() == 1) {
01227             post(s, getBoolVar(s, ce[2]) == getBoolVar(s, ce[0]));
01228           } else {
01229             post(s, getBoolVar(s, ce[2]) == 1);
01230           }
01231         } else {
01232           dom(s, getIntVar(s, ce[0]), d, getBoolVar(s, ce[2]));
01233         }
01234       } else {
01235         if (!ce[0]->isIntVar()) {
01236           dom(s, getSetVar(s, ce[1]), SRT_SUP, ce[0]->getInt(),
01237               getBoolVar(s, ce[2]));
01238         } else {
01239           rel(s, getSetVar(s, ce[1]), SRT_SUP, getIntVar(s, ce[0]),
01240               getBoolVar(s, ce[2]));
01241         }
01242       }
01243     }
01244     void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01245       rel(s, getSetVar(s, ce[0]), SRT_DISJ, getSetVar(s, ce[1]));
01246     }
01247 
01248     void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
01249                              AST::Node*) {
01250       bool isConstant = true;
01251       AST::Array* a = ce[1]->getArray();
01252       for (int i=a->a.size(); i--;) {
01253         if (a->a[i]->isSetVar()) {
01254           isConstant = false;
01255           break;
01256         }
01257       }
01258       IntVar selector = getIntVar(s, ce[0]);
01259       post(s, selector > 0);
01260       if (isConstant) {
01261         IntSetArgs sv = arg2intsetargs(s,ce[1],1);
01262         element(s, sv, selector, getSetVar(s, ce[2]));
01263       } else {
01264         SetVarArgs sv = arg2setvarargs(s, ce[1], 1);
01265         element(s, sv, selector, getSetVar(s, ce[2]));
01266       }
01267     }
01268 
01269     void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
01270                                 AST::Node*, SetOpType op,
01271                                 const IntSet& universe = 
01272                                 IntSet(Set::Limits::min,Set::Limits::max)) {
01273       bool isConstant = true;
01274       AST::Array* a = ce[1]->getArray();
01275       for (int i=a->a.size(); i--;) {
01276         if (a->a[i]->isSetVar()) {
01277           isConstant = false;
01278           break;
01279         }
01280       }
01281       SetVar selector = getSetVar(s, ce[0]);
01282       dom(s, selector, SRT_DISJ, 0);
01283       if (isConstant) {
01284         IntSetArgs sv = arg2intsetargs(s,ce[1], 1);
01285         element(s, op, sv, selector, getSetVar(s, ce[2]), universe);
01286       } else {
01287         SetVarArgs sv = arg2setvarargs(s, ce[1], 1);
01288         element(s, op, sv, selector, getSetVar(s, ce[2]), universe);
01289       }
01290     }
01291 
01292     void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
01293                                        AST::Node* ann) {
01294       p_array_set_element_op(s, ce, ann, SOT_UNION);
01295     }
01296 
01297     void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
01298                                        AST::Node* ann) {
01299       p_array_set_element_op(s, ce, ann, SOT_INTER);
01300     }
01301 
01302     void p_array_set_element_intersect_in(FlatZincSpace& s,
01303                                               const ConExpr& ce,
01304                                               AST::Node* ann) {
01305       IntSet d = arg2intset(s, ce[3]);
01306       p_array_set_element_op(s, ce, ann, SOT_INTER, d);
01307     }
01308 
01309     void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
01310                                            AST::Node* ann) {
01311       p_array_set_element_op(s, ce, ann, SOT_DUNION);
01312     }
01313 
01314     void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01315       convex(s, getSetVar(s, ce[0]));
01316     }
01317 
01318     void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01319       SetVarArgs sv = arg2setvarargs(s, ce[0]);
01320       sequence(s, sv);
01321     }
01322 
01323     void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
01324                                AST::Node *) {
01325       SetVarArgs sv = arg2setvarargs(s, ce[0]);
01326       sequence(s, sv, getSetVar(s, ce[1]));
01327     }
01328 
01329     class SetPoster {
01330     public:
01331       SetPoster(void) {
01332         registry().add("set_eq", &p_set_eq);
01333         registry().add("equal", &p_set_eq);
01334         registry().add("set_ne", &p_set_ne);
01335         registry().add("set_union", &p_set_union);
01336         registry().add("array_set_element", &p_array_set_element);
01337         registry().add("array_var_set_element", &p_array_set_element);
01338         registry().add("set_intersect", &p_set_intersect);
01339         registry().add("set_diff", &p_set_diff);
01340         registry().add("set_symdiff", &p_set_symdiff);
01341         registry().add("set_subset", &p_set_subset);
01342         registry().add("set_superset", &p_set_superset);
01343         registry().add("set_card", &p_set_card);
01344         registry().add("set_in", &p_set_in);
01345         registry().add("set_eq_reif", &p_set_eq_reif);
01346         registry().add("equal_reif", &p_set_eq_reif);
01347         registry().add("set_ne_reif", &p_set_ne_reif);
01348         registry().add("set_subset_reif", &p_set_subset_reif);
01349         registry().add("set_superset_reif", &p_set_superset_reif);
01350         registry().add("set_in_reif", &p_set_in_reif);
01351         registry().add("disjoint", &p_set_disjoint);
01352 
01353         registry().add("array_set_union", &p_array_set_union);
01354         registry().add("array_set_partition", &p_array_set_partition);
01355         registry().add("set_convex", &p_set_convex);
01356         registry().add("array_set_seq", &p_array_set_seq);
01357         registry().add("array_set_seq_union", &p_array_set_seq_union);
01358         registry().add("array_set_element_union", 
01359                        &p_array_set_element_union);
01360         registry().add("array_set_element_intersect", 
01361                        &p_array_set_element_intersect);
01362         registry().add("array_set_element_intersect_in", 
01363                        &p_array_set_element_intersect_in);
01364         registry().add("array_set_element_partition", 
01365                        &p_array_set_element_partition);
01366       }
01367     };
01368     SetPoster __set_poster;
01369 #endif
01370 
01371   }
01372 }}
01373 
01374 // STATISTICS: flatzinc-any