Generated on Tue May 22 09:39:41 2018 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  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/flatzinc/registry.hh>
00039 #include <gecode/kernel.hh>
00040 #include <gecode/int.hh>
00041 #include <gecode/minimodel.hh>
00042 
00043 #ifdef GECODE_HAS_SET_VARS
00044 #include <gecode/set.hh>
00045 #endif
00046 #ifdef GECODE_HAS_FLOAT_VARS
00047 #include <gecode/float.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) {
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, ce.ann);
00066   }
00067 
00068   void
00069   Registry::add(const std::string& id, poster p) {
00070     r[id] = p;
00071     r["gecode_" + id] = p;
00072   }
00073 
00074   namespace {
00075 
00076     void p_distinct(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00077       IntVarArgs va = s.arg2intvarargs(ce[0]);
00078       IntPropLevel ipl = s.ann2ipl(ann);
00079       unshare(s, va);
00080       distinct(s, va, ipl == IPL_DEF ? IPL_BND : ipl);
00081     }
00082 
00083     void p_distinctOffset(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00084       IntVarArgs va = s.arg2intvarargs(ce[1]);
00085       unshare(s, va);
00086       AST::Array* offs = ce.args->a[0]->getArray();
00087       IntArgs oa(offs->a.size());
00088       for (int i=offs->a.size(); i--; ) {
00089         oa[i] = offs->a[i]->getInt();
00090       }
00091       IntPropLevel ipl = s.ann2ipl(ann);
00092       distinct(s, oa, va, ipl == IPL_DEF ? IPL_BND : ipl);
00093     }
00094 
00095     void p_all_equal(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00096       IntVarArgs va = s.arg2intvarargs(ce[0]);
00097       rel(s, va, IRT_EQ, s.ann2ipl(ann));
00098     }
00099 
00100     void p_int_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00101                    AST::Node* ann) {
00102       if (ce[0]->isIntVar()) {
00103         if (ce[1]->isIntVar()) {
00104           rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
00105               s.ann2ipl(ann));
00106         } else {
00107           rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(), s.ann2ipl(ann));
00108         }
00109       } else {
00110         rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
00111             s.ann2ipl(ann));
00112       }
00113     }
00114     void p_int_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00115       p_int_CMP(s, IRT_EQ, ce, ann);
00116     }
00117     void p_int_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00118       p_int_CMP(s, IRT_NQ, ce, ann);
00119     }
00120     void p_int_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00121       p_int_CMP(s, IRT_GQ, ce, ann);
00122     }
00123     void p_int_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00124       p_int_CMP(s, IRT_GR, ce, ann);
00125     }
00126     void p_int_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00127       p_int_CMP(s, IRT_LQ, ce, ann);
00128     }
00129     void p_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00130       p_int_CMP(s, IRT_LE, ce, ann);
00131     }
00132     void p_int_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
00133                         const ConExpr& ce, AST::Node* ann) {
00134       if (rm == RM_EQV && ce[2]->isBool()) {
00135         if (ce[2]->getBool()) {
00136           p_int_CMP(s, irt, ce, ann);
00137         } else {
00138           p_int_CMP(s, neg(irt), ce, ann);
00139         }
00140         return;
00141       }
00142       if (ce[0]->isIntVar()) {
00143         if (ce[1]->isIntVar()) {
00144           rel(s, s.arg2IntVar(ce[0]), irt, s.arg2IntVar(ce[1]),
00145                  Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
00146         } else {
00147           rel(s, s.arg2IntVar(ce[0]), irt, ce[1]->getInt(),
00148                  Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
00149         }
00150       } else {
00151         rel(s, s.arg2IntVar(ce[1]), swap(irt), ce[0]->getInt(),
00152                Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
00153       }
00154     }
00155 
00156     /* Comparisons */
00157     void p_int_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00158       p_int_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
00159     }
00160     void p_int_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00161       p_int_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
00162     }
00163     void p_int_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00164       p_int_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
00165     }
00166     void p_int_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00167       p_int_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
00168     }
00169     void p_int_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00170       p_int_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
00171     }
00172     void p_int_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00173       p_int_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
00174     }
00175 
00176     void p_int_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00177       p_int_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
00178     }
00179     void p_int_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00180       p_int_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
00181     }
00182     void p_int_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00183       p_int_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
00184     }
00185     void p_int_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00186       p_int_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
00187     }
00188     void p_int_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00189       p_int_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
00190     }
00191     void p_int_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00192       p_int_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
00193     }
00194 
00195     /* linear (in-)equations */
00196     void p_int_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00197                        AST::Node* ann) {
00198       IntArgs ia = s.arg2intargs(ce[0]);
00199       int singleIntVar;
00200       if (s.isBoolArray(ce[1],singleIntVar)) {
00201         if (singleIntVar != -1) {
00202           if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
00203             IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
00204             BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
00205             IntArgs ia_tmp(ia.size()-1);
00206             int count = 0;
00207             for (int i=0; i<ia.size(); i++) {
00208               if (i != singleIntVar)
00209                 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
00210             }
00211             IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
00212             linear(s, ia_tmp, iv, t, siv, s.ann2ipl(ann));
00213           } else {
00214             IntVarArgs iv = s.arg2intvarargs(ce[1]);
00215             linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
00216           }
00217         } else {
00218           BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
00219           linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
00220         }
00221       } else {
00222         IntVarArgs iv = s.arg2intvarargs(ce[1]);
00223         linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
00224       }
00225     }
00226     void p_int_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
00227                             const ConExpr& ce, AST::Node* ann) {
00228       if (rm == RM_EQV && ce[2]->isBool()) {
00229         if (ce[2]->getBool()) {
00230           p_int_lin_CMP(s, irt, ce, ann);
00231         } else {
00232           p_int_lin_CMP(s, neg(irt), ce, ann);
00233         }
00234         return;
00235       }
00236       IntArgs ia = s.arg2intargs(ce[0]);
00237       int singleIntVar;
00238       if (s.isBoolArray(ce[1],singleIntVar)) {
00239         if (singleIntVar != -1) {
00240           if (std::abs(ia[singleIntVar]) == 1 && ce[2]->getInt() == 0) {
00241             IntVar siv = s.arg2IntVar(ce[1]->getArray()->a[singleIntVar]);
00242             BoolVarArgs iv = s.arg2boolvarargs(ce[1], 0, singleIntVar);
00243             IntArgs ia_tmp(ia.size()-1);
00244             int count = 0;
00245             for (int i=0; i<ia.size(); i++) {
00246               if (i != singleIntVar)
00247                 ia_tmp[count++] = ia[singleIntVar] == -1 ? ia[i] : -ia[i];
00248             }
00249             IntRelType t = (ia[singleIntVar] == -1 ? irt : swap(irt));
00250             linear(s, ia_tmp, iv, t, siv, Reify(s.arg2BoolVar(ce[3]), rm),
00251                    s.ann2ipl(ann));
00252           } else {
00253             IntVarArgs iv = s.arg2intvarargs(ce[1]);
00254             linear(s, ia, iv, irt, ce[2]->getInt(),
00255                    Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
00256           }
00257         } else {
00258           BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
00259           linear(s, ia, iv, irt, ce[2]->getInt(),
00260                  Reify(s.arg2BoolVar(ce[3]), rm), s.ann2ipl(ann));
00261         }
00262       } else {
00263         IntVarArgs iv = s.arg2intvarargs(ce[1]);
00264         linear(s, ia, iv, irt, ce[2]->getInt(),
00265                Reify(s.arg2BoolVar(ce[3]), rm),
00266                s.ann2ipl(ann));
00267       }
00268     }
00269     void p_int_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00270       p_int_lin_CMP(s, IRT_EQ, ce, ann);
00271     }
00272     void p_int_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00273       p_int_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
00274     }
00275     void p_int_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00276       p_int_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
00277     }
00278     void p_int_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00279       p_int_lin_CMP(s, IRT_NQ, ce, ann);
00280     }
00281     void p_int_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00282       p_int_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
00283     }
00284     void p_int_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00285       p_int_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
00286     }
00287     void p_int_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00288       p_int_lin_CMP(s, IRT_LQ, ce, ann);
00289     }
00290     void p_int_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00291       p_int_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
00292     }
00293     void p_int_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00294       p_int_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
00295     }
00296     void p_int_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00297       p_int_lin_CMP(s, IRT_LE, ce, ann);
00298     }
00299     void p_int_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00300       p_int_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
00301     }
00302     void p_int_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00303       p_int_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
00304     }
00305     void p_int_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00306       p_int_lin_CMP(s, IRT_GQ, ce, ann);
00307     }
00308     void p_int_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00309       p_int_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
00310     }
00311     void p_int_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00312       p_int_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
00313     }
00314     void p_int_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00315       p_int_lin_CMP(s, IRT_GR, ce, ann);
00316     }
00317     void p_int_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00318       p_int_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
00319     }
00320     void p_int_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00321       p_int_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
00322     }
00323 
00324     void p_bool_lin_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00325                         AST::Node* ann) {
00326       IntArgs ia = s.arg2intargs(ce[0]);
00327       BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
00328       if (ce[2]->isIntVar())
00329         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()], s.ann2ipl(ann));
00330       else
00331         linear(s, ia, iv, irt, ce[2]->getInt(), s.ann2ipl(ann));
00332     }
00333     void p_bool_lin_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
00334                             const ConExpr& ce, AST::Node* ann) {
00335       if (rm == RM_EQV && ce[2]->isBool()) {
00336         if (ce[2]->getBool()) {
00337           p_bool_lin_CMP(s, irt, ce, ann);
00338         } else {
00339           p_bool_lin_CMP(s, neg(irt), ce, ann);
00340         }
00341         return;
00342       }
00343       IntArgs ia = s.arg2intargs(ce[0]);
00344       BoolVarArgs iv = s.arg2boolvarargs(ce[1]);
00345       if (ce[2]->isIntVar())
00346         linear(s, ia, iv, irt, s.iv[ce[2]->getIntVar()],
00347                Reify(s.arg2BoolVar(ce[3]), rm),
00348                s.ann2ipl(ann));
00349       else
00350         linear(s, ia, iv, irt, ce[2]->getInt(),
00351                Reify(s.arg2BoolVar(ce[3]), rm),
00352                s.ann2ipl(ann));
00353     }
00354     void p_bool_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00355       p_bool_lin_CMP(s, IRT_EQ, ce, ann);
00356     }
00357     void p_bool_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00358     {
00359       p_bool_lin_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
00360     }
00361     void p_bool_lin_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00362     {
00363       p_bool_lin_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
00364     }
00365     void p_bool_lin_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00366       p_bool_lin_CMP(s, IRT_NQ, ce, ann);
00367     }
00368     void p_bool_lin_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00369     {
00370       p_bool_lin_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
00371     }
00372     void p_bool_lin_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00373     {
00374       p_bool_lin_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
00375     }
00376     void p_bool_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00377       p_bool_lin_CMP(s, IRT_LQ, ce, ann);
00378     }
00379     void p_bool_lin_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00380     {
00381       p_bool_lin_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
00382     }
00383     void p_bool_lin_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00384     {
00385       p_bool_lin_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
00386     }
00387     void p_bool_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00388     {
00389       p_bool_lin_CMP(s, IRT_LE, ce, ann);
00390     }
00391     void p_bool_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00392     {
00393       p_bool_lin_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
00394     }
00395     void p_bool_lin_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00396     {
00397       p_bool_lin_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
00398     }
00399     void p_bool_lin_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00400       p_bool_lin_CMP(s, IRT_GQ, ce, ann);
00401     }
00402     void p_bool_lin_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00403     {
00404       p_bool_lin_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
00405     }
00406     void p_bool_lin_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00407     {
00408       p_bool_lin_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
00409     }
00410     void p_bool_lin_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00411       p_bool_lin_CMP(s, IRT_GR, ce, ann);
00412     }
00413     void p_bool_lin_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00414     {
00415       p_bool_lin_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
00416     }
00417     void p_bool_lin_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00418     {
00419       p_bool_lin_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
00420     }
00421 
00422     /* arithmetic constraints */
00423 
00424     void p_int_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00425       if (!ce[0]->isIntVar()) {
00426         rel(s, ce[0]->getInt() + s.arg2IntVar(ce[1])
00427                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00428       } else if (!ce[1]->isIntVar()) {
00429         rel(s, s.arg2IntVar(ce[0]) + ce[1]->getInt()
00430                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00431       } else if (!ce[2]->isIntVar()) {
00432         rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
00433                 == ce[2]->getInt(), s.ann2ipl(ann));
00434       } else {
00435         rel(s, s.arg2IntVar(ce[0]) + s.arg2IntVar(ce[1])
00436                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00437       }
00438     }
00439 
00440     void p_int_minus(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00441       if (!ce[0]->isIntVar()) {
00442         rel(s, ce[0]->getInt() - s.arg2IntVar(ce[1])
00443                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00444       } else if (!ce[1]->isIntVar()) {
00445         rel(s, s.arg2IntVar(ce[0]) - ce[1]->getInt()
00446                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00447       } else if (!ce[2]->isIntVar()) {
00448         rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
00449                 == ce[2]->getInt(), s.ann2ipl(ann));
00450       } else {
00451         rel(s, s.arg2IntVar(ce[0]) - s.arg2IntVar(ce[1])
00452                 == s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00453       }
00454     }
00455 
00456     void p_int_times(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00457       IntVar x0 = s.arg2IntVar(ce[0]);
00458       IntVar x1 = s.arg2IntVar(ce[1]);
00459       IntVar x2 = s.arg2IntVar(ce[2]);
00460       mult(s, x0, x1, x2, s.ann2ipl(ann));
00461     }
00462     void p_int_pow(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00463       IntVar x0 = s.arg2IntVar(ce[0]);
00464       IntVar x2 = s.arg2IntVar(ce[2]);
00465       pow(s, x0, ce[1]->getInt(), x2, s.ann2ipl(ann));
00466     }    
00467     void p_int_div(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00468       IntVar x0 = s.arg2IntVar(ce[0]);
00469       IntVar x1 = s.arg2IntVar(ce[1]);
00470       IntVar x2 = s.arg2IntVar(ce[2]);
00471       div(s,x0,x1,x2, s.ann2ipl(ann));
00472     }
00473     void p_int_mod(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00474       IntVar x0 = s.arg2IntVar(ce[0]);
00475       IntVar x1 = s.arg2IntVar(ce[1]);
00476       IntVar x2 = s.arg2IntVar(ce[2]);
00477       mod(s,x0,x1,x2, s.ann2ipl(ann));
00478     }
00479 
00480     void p_int_min(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00481       IntVar x0 = s.arg2IntVar(ce[0]);
00482       IntVar x1 = s.arg2IntVar(ce[1]);
00483       IntVar x2 = s.arg2IntVar(ce[2]);
00484       min(s, x0, x1, x2, s.ann2ipl(ann));
00485     }
00486     void p_int_max(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00487       IntVar x0 = s.arg2IntVar(ce[0]);
00488       IntVar x1 = s.arg2IntVar(ce[1]);
00489       IntVar x2 = s.arg2IntVar(ce[2]);
00490       max(s, x0, x1, x2, s.ann2ipl(ann));
00491     }
00492     void p_int_negate(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00493       IntVar x0 = s.arg2IntVar(ce[0]);
00494       IntVar x1 = s.arg2IntVar(ce[1]);
00495       rel(s, x0 == -x1, s.ann2ipl(ann));
00496     }
00497 
00498     /* Boolean constraints */
00499     void p_bool_CMP(FlatZincSpace& s, IntRelType irt, const ConExpr& ce,
00500                    AST::Node* ann) {
00501       rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
00502           s.ann2ipl(ann));
00503     }
00504     void p_bool_CMP_reif(FlatZincSpace& s, IntRelType irt, ReifyMode rm,
00505                          const ConExpr& ce, AST::Node* ann) {
00506       rel(s, s.arg2BoolVar(ce[0]), irt, s.arg2BoolVar(ce[1]),
00507           Reify(s.arg2BoolVar(ce[2]), rm), s.ann2ipl(ann));
00508     }
00509     void p_bool_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00510       p_bool_CMP(s, IRT_EQ, ce, ann);
00511     }
00512     void p_bool_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00513       p_bool_CMP_reif(s, IRT_EQ, RM_EQV, ce, ann);
00514     }
00515     void p_bool_eq_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00516       p_bool_CMP_reif(s, IRT_EQ, RM_IMP, ce, ann);
00517     }
00518     void p_bool_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00519       p_bool_CMP(s, IRT_NQ, ce, ann);
00520     }
00521     void p_bool_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00522       p_bool_CMP_reif(s, IRT_NQ, RM_EQV, ce, ann);
00523     }
00524     void p_bool_ne_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00525       p_bool_CMP_reif(s, IRT_NQ, RM_IMP, ce, ann);
00526     }
00527     void p_bool_ge(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00528       p_bool_CMP(s, IRT_GQ, ce, ann);
00529     }
00530     void p_bool_ge_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00531       p_bool_CMP_reif(s, IRT_GQ, RM_EQV, ce, ann);
00532     }
00533     void p_bool_ge_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00534       p_bool_CMP_reif(s, IRT_GQ, RM_IMP, ce, ann);
00535     }
00536     void p_bool_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00537       p_bool_CMP(s, IRT_LQ, ce, ann);
00538     }
00539     void p_bool_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00540       p_bool_CMP_reif(s, IRT_LQ, RM_EQV, ce, ann);
00541     }
00542     void p_bool_le_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00543       p_bool_CMP_reif(s, IRT_LQ, RM_IMP, ce, ann);
00544     }
00545     void p_bool_gt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00546       p_bool_CMP(s, IRT_GR, ce, ann);
00547     }
00548     void p_bool_gt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00549       p_bool_CMP_reif(s, IRT_GR, RM_EQV, ce, ann);
00550     }
00551     void p_bool_gt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00552       p_bool_CMP_reif(s, IRT_GR, RM_IMP, ce, ann);
00553     }
00554     void p_bool_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00555       p_bool_CMP(s, IRT_LE, ce, ann);
00556     }
00557     void p_bool_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00558       p_bool_CMP_reif(s, IRT_LE, RM_EQV, ce, ann);
00559     }
00560     void p_bool_lt_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00561       p_bool_CMP_reif(s, IRT_LE, RM_IMP, ce, ann);
00562     }
00563 
00564 #define BOOL_OP(op) \
00565     BoolVar b0 = s.arg2BoolVar(ce[0]); \
00566     BoolVar b1 = s.arg2BoolVar(ce[1]); \
00567     if (ce[2]->isBool()) { \
00568       rel(s, b0, op, b1, ce[2]->getBool(), s.ann2ipl(ann)); \
00569     } else { \
00570       rel(s, b0, op, b1, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann)); \
00571     }
00572 
00573 #define BOOL_ARRAY_OP(op) \
00574     BoolVarArgs bv = s.arg2boolvarargs(ce[0]); \
00575     if (ce.size()==1) { \
00576       rel(s, op, bv, 1, s.ann2ipl(ann)); \
00577     } else if (ce[1]->isBool()) { \
00578       rel(s, op, bv, ce[1]->getBool(), s.ann2ipl(ann)); \
00579     } else { \
00580       rel(s, op, bv, s.bv[ce[1]->getBoolVar()], s.ann2ipl(ann)); \
00581     }
00582 
00583     void p_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00584       BOOL_OP(BOT_OR);
00585     }
00586     void p_bool_or_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00587       BoolVar b0 = s.arg2BoolVar(ce[0]);
00588       BoolVar b1 = s.arg2BoolVar(ce[1]);
00589       BoolVar b2 = s.arg2BoolVar(ce[2]);
00590       clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
00591              s.ann2ipl(ann));
00592     }
00593     void p_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00594       BOOL_OP(BOT_AND);
00595     }
00596     void p_bool_and_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00597       BoolVar b0 = s.arg2BoolVar(ce[0]);
00598       BoolVar b1 = s.arg2BoolVar(ce[1]);
00599       BoolVar b2 = s.arg2BoolVar(ce[2]);
00600       rel(s, b2, BOT_IMP, b0, 1, s.ann2ipl(ann));
00601       rel(s, b2, BOT_IMP, b1, 1, s.ann2ipl(ann));
00602     }
00603     void p_array_bool_and(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00604     {
00605       BOOL_ARRAY_OP(BOT_AND);
00606     }
00607     void p_array_bool_and_imp(FlatZincSpace& s, const ConExpr& ce,
00608                               AST::Node* ann)
00609     {
00610       BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
00611       BoolVar b1 = s.arg2BoolVar(ce[1]);
00612       for (unsigned int i=bv.size(); i--;)
00613         rel(s, b1, BOT_IMP, bv[i], 1, s.ann2ipl(ann));
00614     }
00615     void p_array_bool_or(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00616     {
00617       BOOL_ARRAY_OP(BOT_OR);
00618     }
00619     void p_array_bool_or_imp(FlatZincSpace& s, const ConExpr& ce,
00620                              AST::Node* ann)
00621     {
00622       BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
00623       BoolVar b1 = s.arg2BoolVar(ce[1]);
00624       clause(s, BOT_OR, bv, BoolVarArgs()<<b1, 1, s.ann2ipl(ann));
00625     }
00626     void p_array_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann)
00627     {
00628       BOOL_ARRAY_OP(BOT_XOR);
00629     }
00630     void p_array_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce,
00631                               AST::Node* ann)
00632     {
00633       BoolVarArgs bv = s.arg2boolvarargs(ce[0]);
00634       BoolVar tmp(s,0,1);
00635       rel(s, BOT_XOR, bv, tmp, s.ann2ipl(ann));
00636       rel(s, s.arg2BoolVar(ce[1]), BOT_IMP, tmp, 1);
00637     }
00638     void p_array_bool_clause(FlatZincSpace& s, const ConExpr& ce,
00639                              AST::Node* ann) {
00640       BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
00641       BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
00642       clause(s, BOT_OR, bvp, bvn, 1, s.ann2ipl(ann));
00643     }
00644     void p_array_bool_clause_reif(FlatZincSpace& s, const ConExpr& ce,
00645                              AST::Node* ann) {
00646       BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
00647       BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
00648       BoolVar b0 = s.arg2BoolVar(ce[2]);
00649       clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
00650     }
00651     void p_array_bool_clause_imp(FlatZincSpace& s, const ConExpr& ce,
00652                              AST::Node* ann) {
00653       BoolVarArgs bvp = s.arg2boolvarargs(ce[0]);
00654       BoolVarArgs bvn = s.arg2boolvarargs(ce[1]);
00655       BoolVar b0 = s.arg2BoolVar(ce[2]);
00656       clause(s, BOT_OR, bvp, bvn, b0, s.ann2ipl(ann));
00657     }
00658     void p_bool_xor(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00659       BOOL_OP(BOT_XOR);
00660     }
00661     void p_bool_xor_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00662       BoolVar b0 = s.arg2BoolVar(ce[0]);
00663       BoolVar b1 = s.arg2BoolVar(ce[1]);
00664       BoolVar b2 = s.arg2BoolVar(ce[2]);
00665       clause(s, BOT_OR, BoolVarArgs()<<b0<<b1, BoolVarArgs()<<b2, 1,
00666              s.ann2ipl(ann));
00667       clause(s, BOT_OR, BoolVarArgs(), BoolVarArgs()<<b0<<b1<<b2, 1,
00668              s.ann2ipl(ann));
00669     }
00670     void p_bool_l_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00671       BoolVar b0 = s.arg2BoolVar(ce[0]);
00672       BoolVar b1 = s.arg2BoolVar(ce[1]);
00673       if (ce[2]->isBool()) {
00674         rel(s, b1, BOT_IMP, b0, ce[2]->getBool(), s.ann2ipl(ann));
00675       } else {
00676         rel(s, b1, BOT_IMP, b0, s.bv[ce[2]->getBoolVar()], s.ann2ipl(ann));
00677       }
00678     }
00679     void p_bool_r_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00680       BOOL_OP(BOT_IMP);
00681     }
00682     void p_bool_not(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00683       BoolVar x0 = s.arg2BoolVar(ce[0]);
00684       BoolVar x1 = s.arg2BoolVar(ce[1]);
00685       rel(s, x0, BOT_XOR, x1, 1, s.ann2ipl(ann));
00686     }
00687 
00688     /* element constraints */
00689     void p_array_int_element(FlatZincSpace& s, const ConExpr& ce,
00690                                  AST::Node* ann) {
00691       bool isConstant = true;
00692       AST::Array* a = ce[1]->getArray();
00693       for (int i=a->a.size(); i--;) {
00694         if (!a->a[i]->isInt()) {
00695           isConstant = false;
00696           break;
00697         }
00698       }
00699       IntVar selector = s.arg2IntVar(ce[0]);
00700       rel(s, selector > 0);
00701       if (isConstant) {
00702         IntSharedArray sia = s.arg2intsharedarray(ce[1], 1);
00703         element(s, sia, selector, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00704       } else {
00705         IntVarArgs iv = s.arg2intvarargs(ce[1], 1);
00706         element(s, iv, selector, s.arg2IntVar(ce[2]), s.ann2ipl(ann));
00707       }
00708     }
00709     void p_array_bool_element(FlatZincSpace& s, const ConExpr& ce,
00710                                   AST::Node* ann) {
00711       bool isConstant = true;
00712       AST::Array* a = ce[1]->getArray();
00713       for (int i=a->a.size(); i--;) {
00714         if (!a->a[i]->isBool()) {
00715           isConstant = false;
00716           break;
00717         }
00718       }
00719       IntVar selector = s.arg2IntVar(ce[0]);
00720       rel(s, selector > 0);
00721       if (isConstant) {
00722         IntSharedArray sia = s.arg2boolsharedarray(ce[1], 1);
00723         element(s, sia, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
00724       } else {
00725         BoolVarArgs iv = s.arg2boolvarargs(ce[1], 1);
00726         element(s, iv, selector, s.arg2BoolVar(ce[2]), s.ann2ipl(ann));
00727       }
00728     }
00729 
00730     /* coercion constraints */
00731     void p_bool2int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00732       BoolVar x0 = s.arg2BoolVar(ce[0]);
00733       IntVar x1 = s.arg2IntVar(ce[1]);
00734       if (ce[0]->isBoolVar() && ce[1]->isIntVar()) {
00735         s.aliasBool2Int(ce[1]->getIntVar(), ce[0]->getBoolVar());
00736       }
00737       channel(s, x0, x1, s.ann2ipl(ann));
00738     }
00739 
00740     void p_int_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
00741       IntSet d = s.arg2intset(ce[1]);
00742       if (ce[0]->isBoolVar()) {
00743         IntSetRanges dr(d);
00744         Iter::Ranges::Singleton sr(0,1);
00745         Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
00746         IntSet d01(i);
00747         if (d01.size() == 0) {
00748           s.fail();
00749         } else {
00750           rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
00751           rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
00752         }
00753       } else {
00754         dom(s, s.arg2IntVar(ce[0]), d);
00755       }
00756     }
00757     void p_int_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
00758       IntSet d = s.arg2intset(ce[1]);
00759       if (ce[0]->isBoolVar()) {
00760         IntSetRanges dr(d);
00761         Iter::Ranges::Singleton sr(0,1);
00762         Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
00763         IntSet d01(i);
00764         if (d01.size() == 0) {
00765           rel(s, s.arg2BoolVar(ce[2]) == 0);
00766         } else if (d01.max() == 0) {
00767           rel(s, s.arg2BoolVar(ce[2]) == !s.arg2BoolVar(ce[0]));
00768         } else if (d01.min() == 1) {
00769           rel(s, s.arg2BoolVar(ce[2]) == s.arg2BoolVar(ce[0]));
00770         } else {
00771           rel(s, s.arg2BoolVar(ce[2]) == 1);
00772         }
00773       } else {
00774         dom(s, s.arg2IntVar(ce[0]), d, s.arg2BoolVar(ce[2]));
00775       }
00776     }
00777     void p_int_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
00778       IntSet d = s.arg2intset(ce[1]);
00779       if (ce[0]->isBoolVar()) {
00780         IntSetRanges dr(d);
00781         Iter::Ranges::Singleton sr(0,1);
00782         Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
00783         IntSet d01(i);
00784         if (d01.size() == 0) {
00785           rel(s, s.arg2BoolVar(ce[2]) == 0);
00786         } else if (d01.max() == 0) {
00787           rel(s, s.arg2BoolVar(ce[2]) >> !s.arg2BoolVar(ce[0]));
00788         } else if (d01.min() == 1) {
00789           rel(s, s.arg2BoolVar(ce[2]) >> s.arg2BoolVar(ce[0]));
00790         }
00791       } else {
00792         dom(s, s.arg2IntVar(ce[0]), d, Reify(s.arg2BoolVar(ce[2]),RM_IMP));
00793       }
00794     }
00795 
00796     /* constraints from the standard library */
00797 
00798     void p_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00799       IntVar x0 = s.arg2IntVar(ce[0]);
00800       IntVar x1 = s.arg2IntVar(ce[1]);
00801       abs(s, x0, x1, s.ann2ipl(ann));
00802     }
00803 
00804     void p_array_int_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00805       IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
00806       IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
00807       rel(s, iv0, IRT_LE, iv1, s.ann2ipl(ann));
00808     }
00809 
00810     void p_array_int_lq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00811       IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
00812       IntVarArgs iv1 = s.arg2intvarargs(ce[1]);
00813       rel(s, iv0, IRT_LQ, iv1, s.ann2ipl(ann));
00814     }
00815 
00816     void p_array_bool_lt(FlatZincSpace& s, const ConExpr& ce,
00817                          AST::Node* ann) {
00818       BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
00819       BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
00820       rel(s, bv0, IRT_LE, bv1, s.ann2ipl(ann));
00821     }
00822 
00823     void p_array_bool_lq(FlatZincSpace& s, const ConExpr& ce,
00824                          AST::Node* ann) {
00825       BoolVarArgs bv0 = s.arg2boolvarargs(ce[0]);
00826       BoolVarArgs bv1 = s.arg2boolvarargs(ce[1]);
00827       rel(s, bv0, IRT_LQ, bv1, s.ann2ipl(ann));
00828     }
00829 
00830     void p_count(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00831       IntVarArgs iv = s.arg2intvarargs(ce[0]);
00832       if (!ce[1]->isIntVar()) {
00833         if (!ce[2]->isIntVar()) {
00834           count(s, iv, ce[1]->getInt(), IRT_EQ, ce[2]->getInt(),
00835                 s.ann2ipl(ann));
00836         } else {
00837           count(s, iv, ce[1]->getInt(), IRT_EQ, s.arg2IntVar(ce[2]),
00838                 s.ann2ipl(ann));
00839         }
00840       } else if (!ce[2]->isIntVar()) {
00841         count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, ce[2]->getInt(),
00842               s.ann2ipl(ann));
00843       } else {
00844         count(s, iv, s.arg2IntVar(ce[1]), IRT_EQ, s.arg2IntVar(ce[2]),
00845               s.ann2ipl(ann));
00846       }
00847     }
00848 
00849     void p_count_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00850       IntVarArgs iv = s.arg2intvarargs(ce[0]);
00851       IntVar x = s.arg2IntVar(ce[1]);
00852       IntVar y = s.arg2IntVar(ce[2]);
00853       BoolVar b = s.arg2BoolVar(ce[3]);
00854       IntVar c(s,0,Int::Limits::max);
00855       count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
00856       rel(s, b == (c==y));
00857     }
00858     void p_count_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00859       IntVarArgs iv = s.arg2intvarargs(ce[0]);
00860       IntVar x = s.arg2IntVar(ce[1]);
00861       IntVar y = s.arg2IntVar(ce[2]);
00862       BoolVar b = s.arg2BoolVar(ce[3]);
00863       IntVar c(s,0,Int::Limits::max);
00864       count(s,iv,x,IRT_EQ,c,s.ann2ipl(ann));
00865       rel(s, b >> (c==y));
00866     }
00867 
00868     void count_rel(IntRelType irt,
00869                    FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00870       IntVarArgs iv = s.arg2intvarargs(ce[1]);
00871       count(s, iv, ce[2]->getInt(), irt, ce[0]->getInt(), s.ann2ipl(ann));
00872     }
00873 
00874     void p_at_most(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00875       count_rel(IRT_LQ, s, ce, ann);
00876     }
00877 
00878     void p_at_least(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
00879       count_rel(IRT_GQ, s, ce, ann);
00880     }
00881 
00882     void p_bin_packing_load(FlatZincSpace& s, const ConExpr& ce,
00883                             AST::Node* ann) {
00884       int minIdx = ce[3]->getInt();
00885       IntVarArgs load = s.arg2intvarargs(ce[0]);
00886       IntVarArgs l;
00887       IntVarArgs bin = s.arg2intvarargs(ce[1]);
00888       for (int i=bin.size(); i--;)
00889         rel(s, bin[i] >= minIdx);
00890       if (minIdx > 0) {
00891         for (int i=minIdx; i--;)
00892           l << IntVar(s,0,0);
00893       } else if (minIdx < 0) {
00894         IntVarArgs bin2(bin.size());
00895         for (int i=bin.size(); i--;)
00896           bin2[i] = expr(s, bin[i]-minIdx, s.ann2ipl(ann));
00897         bin = bin2;
00898       }
00899       l << load;
00900       IntArgs sizes = s.arg2intargs(ce[2]);
00901 
00902       IntVarArgs allvars = l + bin;
00903       unshare(s, allvars);
00904       binpacking(s, allvars.slice(0,1,l.size()), allvars.slice(l.size(),1,bin.size()),
00905                  sizes, s.ann2ipl(ann));
00906     }
00907 
00908     void p_global_cardinality(FlatZincSpace& s, const ConExpr& ce,
00909                               AST::Node* ann) {
00910       IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
00911       IntArgs cover = s.arg2intargs(ce[1]);
00912       IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
00913 
00914       Region re;
00915       IntSet cover_s(cover);
00916       IntSetRanges cover_r(cover_s);
00917       IntVarRanges* iv0_ri = re.alloc<IntVarRanges>(iv0.size());
00918       for (int i=iv0.size(); i--;)
00919         iv0_ri[i] = IntVarRanges(iv0[i]);
00920       Iter::Ranges::NaryUnion iv0_r(re,iv0_ri,iv0.size());
00921       Iter::Ranges::Diff<Iter::Ranges::NaryUnion,IntSetRanges>
00922         extra_r(iv0_r,cover_r);
00923       Iter::Ranges::ToValues<Iter::Ranges::Diff<
00924         Iter::Ranges::NaryUnion,IntSetRanges> > extra(extra_r);
00925       for (; extra(); ++extra) {
00926         cover << extra.val();
00927         iv1 << IntVar(s,0,iv0.size());
00928       }
00929       IntPropLevel ipl = s.ann2ipl(ann);
00930       if (ipl==IPL_DEF)
00931         ipl=IPL_BND;
00932       if (ipl==IPL_DOM) {
00933         IntVarArgs allvars = iv0+iv1;
00934         unshare(s, allvars);
00935         count(s, allvars.slice(0,1,iv0.size()),
00936                  allvars.slice(iv0.size(),1,iv1.size()),
00937                  cover, ipl);
00938       } else {
00939         unshare(s, iv0);
00940         count(s, iv0, iv1, cover, ipl);
00941       }
00942     }
00943 
00944     void p_global_cardinality_closed(FlatZincSpace& s, const ConExpr& ce,
00945                                      AST::Node* ann) {
00946       IntVarArgs iv0 = s.arg2intvarargs(ce[0]);
00947       IntArgs cover = s.arg2intargs(ce[1]);
00948       IntVarArgs iv1 = s.arg2intvarargs(ce[2]);
00949       IntPropLevel ipl = s.ann2ipl(ann);
00950       if (ipl==IPL_DEF)
00951         ipl=IPL_BND;
00952       if (ipl==IPL_DOM) {
00953         IntVarArgs allvars = iv0+iv1;
00954         unshare(s, allvars);
00955         count(s, allvars.slice(0,1,iv0.size()),
00956                  allvars.slice(iv0.size(),1,iv1.size()),
00957                  cover, ipl);
00958       } else {
00959         unshare(s, iv0);
00960         count(s, iv0, iv1, cover, ipl);
00961       }
00962     }
00963 
00964     void p_global_cardinality_low_up(FlatZincSpace& s, const ConExpr& ce,
00965                                      AST::Node* ann) {
00966       IntVarArgs x = s.arg2intvarargs(ce[0]);
00967       IntArgs cover = s.arg2intargs(ce[1]);
00968 
00969       IntArgs lbound = s.arg2intargs(ce[2]);
00970       IntArgs ubound = s.arg2intargs(ce[3]);
00971       IntSetArgs y(cover.size());
00972       for (int i=cover.size(); i--;)
00973         y[i] = IntSet(lbound[i],ubound[i]);
00974 
00975       IntSet cover_s(cover);
00976       Region re;
00977       IntVarRanges* xrs = re.alloc<IntVarRanges>(x.size());
00978       for (int i=x.size(); i--;)
00979         xrs[i].init(x[i]);
00980       Iter::Ranges::NaryUnion u(re, xrs, x.size());
00981       Iter::Ranges::ToValues<Iter::Ranges::NaryUnion> uv(u);
00982       for (; uv(); ++uv) {
00983         if (!cover_s.in(uv.val())) {
00984           cover << uv.val();
00985           y << IntSet(0,x.size());
00986         }
00987       }
00988       unshare(s, x);
00989       IntPropLevel ipl = s.ann2ipl(ann);
00990       if (ipl==IPL_DEF)
00991         ipl=IPL_BND;
00992       count(s, x, y, cover, ipl);
00993     }
00994 
00995     void p_global_cardinality_low_up_closed(FlatZincSpace& s,
00996                                             const ConExpr& ce,
00997                                             AST::Node* ann) {
00998       IntVarArgs x = s.arg2intvarargs(ce[0]);
00999       IntArgs cover = s.arg2intargs(ce[1]);
01000 
01001       IntArgs lbound = s.arg2intargs(ce[2]);
01002       IntArgs ubound = s.arg2intargs(ce[3]);
01003       IntSetArgs y(cover.size());
01004       for (int i=cover.size(); i--;)
01005         y[i] = IntSet(lbound[i],ubound[i]);
01006       unshare(s, x);
01007       IntPropLevel ipl = s.ann2ipl(ann);
01008       if (ipl==IPL_DEF)
01009         ipl=IPL_BND;
01010       count(s, x, y, cover, ipl);
01011     }
01012 
01013     void p_minimum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01014       IntVarArgs iv = s.arg2intvarargs(ce[1]);
01015       min(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
01016     }
01017 
01018     void p_maximum(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01019       IntVarArgs iv = s.arg2intvarargs(ce[1]);
01020       max(s, iv, s.arg2IntVar(ce[0]), s.ann2ipl(ann));
01021     }
01022 
01023     void p_minimum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01024       IntVarArgs iv = s.arg2intvarargs(ce[0]);
01025       argmin(s, iv, s.arg2IntVar(ce[1]), true, s.ann2ipl(ann));
01026     }
01027 
01028     void p_maximum_arg(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01029       IntVarArgs iv = s.arg2intvarargs(ce[0]);
01030       argmax(s, iv, s.arg2IntVar(ce[1]), true, s.ann2ipl(ann));
01031     }
01032 
01033     void p_regular(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01034       IntVarArgs iv = s.arg2intvarargs(ce[0]);
01035       int q = ce[1]->getInt();
01036       int symbols = ce[2]->getInt();
01037       IntArgs d = s.arg2intargs(ce[3]);
01038       int q0 = ce[4]->getInt();
01039 
01040       int noOfTrans = 0;
01041       for (int i=1; i<=q; i++) {
01042         for (int j=1; j<=symbols; j++) {
01043           if (d[(i-1)*symbols+(j-1)] > 0)
01044             noOfTrans++;
01045         }
01046       }
01047 
01048       Region re;
01049       DFA::Transition* t = re.alloc<DFA::Transition>(noOfTrans+1);
01050       noOfTrans = 0;
01051       for (int i=1; i<=q; i++) {
01052         for (int j=1; j<=symbols; j++) {
01053           if (d[(i-1)*symbols+(j-1)] > 0) {
01054             t[noOfTrans].i_state = i;
01055             t[noOfTrans].symbol  = j;
01056             t[noOfTrans].o_state = d[(i-1)*symbols+(j-1)];
01057             noOfTrans++;
01058           }
01059         }
01060       }
01061       t[noOfTrans].i_state = -1;
01062 
01063       // Final states
01064       AST::SetLit* sl = ce[5]->getSet();
01065       int* f;
01066       if (sl->interval) {
01067         f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->max-sl->min+2)));
01068         for (int i=sl->min; i<=sl->max; i++)
01069           f[i-sl->min] = i;
01070         f[sl->max-sl->min+1] = -1;
01071       } else {
01072         f = static_cast<int*>(heap.ralloc(sizeof(int)*(sl->s.size()+1)));
01073         for (int j=sl->s.size(); j--; )
01074           f[j] = sl->s[j];
01075         f[sl->s.size()] = -1;
01076       }
01077 
01078       DFA dfa(q0,t,f);
01079       free(f);
01080       unshare(s, iv);
01081       extensional(s, iv, s.getSharedDFA(dfa), s.ann2ipl(ann));
01082     }
01083 
01084     void
01085     p_sort(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01086       IntVarArgs x = s.arg2intvarargs(ce[0]);
01087       IntVarArgs y = s.arg2intvarargs(ce[1]);
01088       IntVarArgs xy(x.size()+y.size());
01089       for (int i=x.size(); i--;)
01090         xy[i] = x[i];
01091       for (int i=y.size(); i--;)
01092         xy[i+x.size()] = y[i];
01093       unshare(s, xy);
01094       for (int i=x.size(); i--;)
01095         x[i] = xy[i];
01096       for (int i=y.size(); i--;)
01097         y[i] = xy[i+x.size()];
01098       sorted(s, x, y, s.ann2ipl(ann));
01099     }
01100 
01101     void
01102     p_inverse_offsets(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01103       IntVarArgs x = s.arg2intvarargs(ce[0]);
01104       unshare(s, x);
01105       int xoff = ce[1]->getInt();
01106       IntVarArgs y = s.arg2intvarargs(ce[2]);
01107       unshare(s, y);
01108       int yoff = ce[3]->getInt();
01109       channel(s, x, xoff, y, yoff, s.ann2ipl(ann));
01110     }
01111 
01112     void
01113     p_increasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01114       IntVarArgs x = s.arg2intvarargs(ce[0]);
01115       rel(s,x,IRT_LQ,s.ann2ipl(ann));
01116     }
01117 
01118     void
01119     p_increasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01120       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01121       rel(s,x,IRT_LQ,s.ann2ipl(ann));
01122     }
01123 
01124     void
01125     p_decreasing_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01126       IntVarArgs x = s.arg2intvarargs(ce[0]);
01127       rel(s,x,IRT_GQ,s.ann2ipl(ann));
01128     }
01129 
01130     void
01131     p_decreasing_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01132       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01133       rel(s,x,IRT_GQ,s.ann2ipl(ann));
01134     }
01135 
01136     void
01137     p_table_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01138       IntVarArgs x = s.arg2intvarargs(ce[0]);
01139       TupleSet ts = s.arg2tupleset(ce[1],x.size());
01140       extensional(s,x,ts,s.ann2ipl(ann));
01141     }
01142     
01143     void
01144     p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01145       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01146       IntArgs tuples = s.arg2boolargs(ce[1]);
01147       int noOfVars   = x.size();
01148       int noOfTuples = tuples.size() == 0 ? 0 : (tuples.size()/noOfVars);
01149       TupleSet ts(noOfVars);
01150       for (int i=0; i<noOfTuples; i++) {
01151         IntArgs t(noOfVars);
01152         for (int j=0; j<x.size(); j++) {
01153           t[j] = tuples[i*noOfVars+j];
01154         }
01155         ts.add(t);
01156       }
01157       ts.finalize();
01158       extensional(s,x,ts,s.ann2ipl(ann));
01159     }
01160 
01161     void p_cumulative_opt(FlatZincSpace& s, const ConExpr& ce,
01162                       AST::Node* ann) {
01163       IntVarArgs start = s.arg2intvarargs(ce[0]);
01164       IntArgs duration = s.arg2intargs(ce[1]);
01165       IntArgs height = s.arg2intargs(ce[2]);
01166       BoolVarArgs opt = s.arg2boolvarargs(ce[3]);
01167       int bound = ce[4]->getInt();
01168       unshare(s,start);
01169       cumulative(s,bound,start,duration,height,opt,s.ann2ipl(ann));
01170     }
01171 
01172     void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
01173                       AST::Node* ann) {
01174       IntVarArgs start = s.arg2intvarargs(ce[0]);
01175       IntVarArgs duration = s.arg2intvarargs(ce[1]);
01176       IntVarArgs height = s.arg2intvarargs(ce[2]);
01177       int n = start.size();
01178       IntVar bound = s.arg2IntVar(ce[3]);
01179 
01180       if (n==0)
01181         return;
01182 
01183       if (n == 1) {
01184         rel(s, height[0] <= bound);
01185         return;
01186       }
01187 
01188       int minHeight = std::min(height[0].min(),height[1].min());
01189       int minHeight2 = std::max(height[0].min(),height[1].min());
01190       for (int i=2; i<n; i++) {
01191         if (height[i].min() < minHeight) {
01192           minHeight2 = minHeight;
01193           minHeight = height[i].min();
01194         } else if (height[i].min() < minHeight2) {
01195           minHeight2 = height[i].min();
01196         }
01197       }
01198       bool disjunctive =
01199        (minHeight > bound.max()/2) ||
01200        (minHeight2 > bound.max()/2 && minHeight+minHeight2>bound.max());
01201       if (disjunctive) {
01202         rel(s, bound >= max(height));
01203         // Unary
01204         if (duration.assigned()) {
01205           IntArgs durationI(n);
01206           for (int i=n; i--;)
01207             durationI[i] = duration[i].val();
01208           unshare(s,start);
01209           unary(s,start,durationI);
01210         } else {
01211           IntVarArgs end(n);
01212           for (int i=n; i--;)
01213             end[i] = expr(s,start[i]+duration[i]);
01214           unshare(s,start);
01215           unary(s,start,duration,end);
01216         }
01217       } else if (height.assigned()) {
01218         IntArgs heightI(n);
01219         for (int i=n; i--;)
01220           heightI[i] = height[i].val();
01221         if (duration.assigned()) {
01222           IntArgs durationI(n);
01223           for (int i=n; i--;)
01224             durationI[i] = duration[i].val();
01225           cumulative(s, bound, start, durationI, heightI);
01226         } else {
01227           IntVarArgs end(n);
01228           for (int i = n; i--; )
01229             end[i] = expr(s,start[i]+duration[i]);
01230           cumulative(s, bound, start, duration, end, heightI);
01231         }
01232       } else if (bound.assigned()) {
01233         IntArgs machine = IntArgs::create(n,0,0);
01234         IntArgs limit(1, bound.val());
01235         IntVarArgs end(n);
01236         for (int i=n; i--;)
01237           end[i] = expr(s,start[i]+duration[i]);
01238         cumulatives(s, machine, start, duration, end, height, limit, true,
01239                     s.ann2ipl(ann));
01240       } else {
01241         int min = Gecode::Int::Limits::max;
01242         int max = Gecode::Int::Limits::min;
01243         IntVarArgs end(start.size());
01244         for (int i = start.size(); i--; ) {
01245           min = std::min(min, start[i].min());
01246           max = std::max(max, start[i].max() + duration[i].max());
01247           end[i] = expr(s, start[i] + duration[i]);
01248         }
01249         for (int time = min; time < max; ++time) {
01250           IntVarArgs x(start.size());
01251           for (int i = start.size(); i--; ) {
01252             IntVar overlaps = channel(s, expr(s, (start[i] <= time) &&
01253                                                  (time < end[i])));
01254             x[i] = expr(s, overlaps * height[i]);
01255           }
01256           linear(s, x, IRT_LQ, bound);
01257         }
01258       }
01259     }
01260 
01261     void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
01262                          AST::Node* ann) {
01263       IntVarArgs x = s.arg2intvarargs(ce[0]);
01264       IntSet S = s.arg2intset(ce[1]);
01265       int q = ce[2]->getInt();
01266       int l = ce[3]->getInt();
01267       int u = ce[4]->getInt();
01268       unshare(s, x);
01269       sequence(s, x, S, q, l, u, s.ann2ipl(ann));
01270     }
01271 
01272     void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
01273                           AST::Node* ann) {
01274       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01275       bool val = ce[1]->getBool();
01276       int q = ce[2]->getInt();
01277       int l = ce[3]->getInt();
01278       int u = ce[4]->getInt();
01279       IntSet S(val, val);
01280       unshare(s, x);
01281       sequence(s, x, S, q, l, u, s.ann2ipl(ann));
01282     }
01283 
01284     void p_schedule_unary(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01285       IntVarArgs x = s.arg2intvarargs(ce[0]);
01286       IntArgs p = s.arg2intargs(ce[1]);
01287       unshare(s,x);
01288       unary(s, x, p);
01289     }
01290 
01291     void p_schedule_unary_optional(FlatZincSpace& s, const ConExpr& ce,
01292                                    AST::Node*) {
01293       IntVarArgs x = s.arg2intvarargs(ce[0]);
01294       IntArgs p = s.arg2intargs(ce[1]);
01295       BoolVarArgs m = s.arg2boolvarargs(ce[2]);
01296       unshare(s,x);
01297       unary(s, x, p, m);
01298     }
01299 
01300     void p_circuit(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01301       int off = ce[0]->getInt();
01302       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01303       unshare(s,xv);
01304       circuit(s,off,xv,s.ann2ipl(ann));
01305     }
01306     void p_circuit_cost_array(FlatZincSpace& s, const ConExpr& ce,
01307                               AST::Node *ann) {
01308       IntArgs c = s.arg2intargs(ce[0]);
01309       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01310       IntVarArgs yv = s.arg2intvarargs(ce[2]);
01311       IntVar z = s.arg2IntVar(ce[3]);
01312       unshare(s,xv);
01313       circuit(s,c,xv,yv,z,s.ann2ipl(ann));
01314     }
01315     void p_circuit_cost(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01316       IntArgs c = s.arg2intargs(ce[0]);
01317       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01318       IntVar z = s.arg2IntVar(ce[2]);
01319       unshare(s,xv);
01320       circuit(s,c,xv,z,s.ann2ipl(ann));
01321     }
01322 
01323     void p_nooverlap(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01324       IntVarArgs x0 = s.arg2intvarargs(ce[0]);
01325       IntVarArgs w = s.arg2intvarargs(ce[1]);
01326       IntVarArgs y0 = s.arg2intvarargs(ce[2]);
01327       IntVarArgs h = s.arg2intvarargs(ce[3]);
01328       if (w.assigned() && h.assigned()) {
01329         IntArgs iw(w.size());
01330         for (int i=w.size(); i--;)
01331           iw[i] = w[i].val();
01332         IntArgs ih(h.size());
01333         for (int i=h.size(); i--;)
01334           ih[i] = h[i].val();
01335         nooverlap(s,x0,iw,y0,ih,s.ann2ipl(ann));
01336 
01337         int miny = y0[0].min();
01338         int maxy = y0[0].max();
01339         int maxdy = ih[0];
01340         for (int i=1; i<y0.size(); i++) {
01341           miny = std::min(miny,y0[i].min());
01342           maxy = std::max(maxy,y0[i].max());
01343           maxdy = std::max(maxdy,ih[i]);
01344         }
01345         int minx = x0[0].min();
01346         int maxx = x0[0].max();
01347         int maxdx = iw[0];
01348         for (int i=1; i<x0.size(); i++) {
01349           minx = std::min(minx,x0[i].min());
01350           maxx = std::max(maxx,x0[i].max());
01351           maxdx = std::max(maxdx,iw[i]);
01352         }
01353         if (miny > Int::Limits::min && maxy < Int::Limits::max) {
01354           cumulative(s,maxdy+maxy-miny,x0,iw,ih);
01355           cumulative(s,maxdx+maxx-minx,y0,ih,iw);
01356         }
01357       } else {
01358         IntVarArgs x1(x0.size()), y1(y0.size());
01359         for (int i=x0.size(); i--; )
01360           x1[i] = expr(s, x0[i] + w[i]);
01361         for (int i=y0.size(); i--; )
01362           y1[i] = expr(s, y0[i] + h[i]);
01363         nooverlap(s,x0,w,x1,y0,h,y1,s.ann2ipl(ann));
01364       }
01365     }
01366 
01367     void p_precede(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01368       IntVarArgs x = s.arg2intvarargs(ce[0]);
01369       int p_s = ce[1]->getInt();
01370       int p_t = ce[2]->getInt();
01371       precede(s,x,p_s,p_t,s.ann2ipl(ann));
01372     }
01373 
01374     void p_nvalue(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01375       IntVarArgs x = s.arg2intvarargs(ce[1]);
01376       if (ce[0]->isIntVar()) {
01377         IntVar y = s.arg2IntVar(ce[0]);
01378         nvalues(s,x,IRT_EQ,y,s.ann2ipl(ann));
01379       } else {
01380         nvalues(s,x,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
01381       }
01382     }
01383 
01384     void p_among(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01385       IntVarArgs x = s.arg2intvarargs(ce[1]);
01386       IntSet v = s.arg2intset(ce[2]);
01387       if (ce[0]->isIntVar()) {
01388         IntVar n = s.arg2IntVar(ce[0]);
01389         unshare(s, x);
01390         count(s,x,v,IRT_EQ,n,s.ann2ipl(ann));
01391       } else {
01392         unshare(s, x);
01393         count(s,x,v,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
01394       }
01395     }
01396 
01397     void p_member_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01398       IntVarArgs x = s.arg2intvarargs(ce[0]);
01399       IntVar y = s.arg2IntVar(ce[1]);
01400       member(s,x,y,s.ann2ipl(ann));
01401     }
01402     void p_member_int_reif(FlatZincSpace& s, const ConExpr& ce,
01403                            AST::Node* ann) {
01404       IntVarArgs x = s.arg2intvarargs(ce[0]);
01405       IntVar y = s.arg2IntVar(ce[1]);
01406       BoolVar b = s.arg2BoolVar(ce[2]);
01407       member(s,x,y,b,s.ann2ipl(ann));
01408     }
01409     void p_member_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01410       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01411       BoolVar y = s.arg2BoolVar(ce[1]);
01412       member(s,x,y,s.ann2ipl(ann));
01413     }
01414     void p_member_bool_reif(FlatZincSpace& s, const ConExpr& ce,
01415                             AST::Node* ann) {
01416       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01417       BoolVar y = s.arg2BoolVar(ce[1]);
01418       member(s,x,y,s.arg2BoolVar(ce[2]),s.ann2ipl(ann));
01419     }
01420 
01421     class IntPoster {
01422     public:
01423       IntPoster(void) {
01424         registry().add("all_different_int", &p_distinct);
01425         registry().add("all_different_offset", &p_distinctOffset);
01426         registry().add("all_equal_int", &p_all_equal);
01427         registry().add("int_eq", &p_int_eq);
01428         registry().add("int_ne", &p_int_ne);
01429         registry().add("int_ge", &p_int_ge);
01430         registry().add("int_gt", &p_int_gt);
01431         registry().add("int_le", &p_int_le);
01432         registry().add("int_lt", &p_int_lt);
01433         registry().add("int_eq_reif", &p_int_eq_reif);
01434         registry().add("int_ne_reif", &p_int_ne_reif);
01435         registry().add("int_ge_reif", &p_int_ge_reif);
01436         registry().add("int_gt_reif", &p_int_gt_reif);
01437         registry().add("int_le_reif", &p_int_le_reif);
01438         registry().add("int_lt_reif", &p_int_lt_reif);
01439         registry().add("int_eq_imp", &p_int_eq_imp);
01440         registry().add("int_ne_imp", &p_int_ne_imp);
01441         registry().add("int_ge_imp", &p_int_ge_imp);
01442         registry().add("int_gt_imp", &p_int_gt_imp);
01443         registry().add("int_le_imp", &p_int_le_imp);
01444         registry().add("int_lt_imp", &p_int_lt_imp);
01445         registry().add("int_lin_eq", &p_int_lin_eq);
01446         registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
01447         registry().add("int_lin_eq_imp", &p_int_lin_eq_imp);
01448         registry().add("int_lin_ne", &p_int_lin_ne);
01449         registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
01450         registry().add("int_lin_ne_imp", &p_int_lin_ne_imp);
01451         registry().add("int_lin_le", &p_int_lin_le);
01452         registry().add("int_lin_le_reif", &p_int_lin_le_reif);
01453         registry().add("int_lin_le_imp", &p_int_lin_le_imp);
01454         registry().add("int_lin_lt", &p_int_lin_lt);
01455         registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
01456         registry().add("int_lin_lt_imp", &p_int_lin_lt_imp);
01457         registry().add("int_lin_ge", &p_int_lin_ge);
01458         registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
01459         registry().add("int_lin_ge_imp", &p_int_lin_ge_imp);
01460         registry().add("int_lin_gt", &p_int_lin_gt);
01461         registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
01462         registry().add("int_lin_gt_imp", &p_int_lin_gt_imp);
01463         registry().add("int_plus", &p_int_plus);
01464         registry().add("int_minus", &p_int_minus);
01465         registry().add("int_times", &p_int_times);
01466         registry().add("gecode_int_pow", &p_int_pow);
01467         registry().add("int_div", &p_int_div);
01468         registry().add("int_mod", &p_int_mod);
01469         registry().add("int_min", &p_int_min);
01470         registry().add("int_max", &p_int_max);
01471         registry().add("int_abs", &p_abs);
01472         registry().add("int_negate", &p_int_negate);
01473         registry().add("bool_eq", &p_bool_eq);
01474         registry().add("bool_eq_reif", &p_bool_eq_reif);
01475         registry().add("bool_eq_imp", &p_bool_eq_imp);
01476         registry().add("bool_ne", &p_bool_ne);
01477         registry().add("bool_ne_reif", &p_bool_ne_reif);
01478         registry().add("bool_ne_imp", &p_bool_ne_imp);
01479         registry().add("bool_ge", &p_bool_ge);
01480         registry().add("bool_ge_reif", &p_bool_ge_reif);
01481         registry().add("bool_ge_imp", &p_bool_ge_imp);
01482         registry().add("bool_le", &p_bool_le);
01483         registry().add("bool_le_reif", &p_bool_le_reif);
01484         registry().add("bool_le_imp", &p_bool_le_imp);
01485         registry().add("bool_gt", &p_bool_gt);
01486         registry().add("bool_gt_reif", &p_bool_gt_reif);
01487         registry().add("bool_gt_imp", &p_bool_gt_imp);
01488         registry().add("bool_lt", &p_bool_lt);
01489         registry().add("bool_lt_reif", &p_bool_lt_reif);
01490         registry().add("bool_lt_imp", &p_bool_lt_imp);
01491         registry().add("bool_or", &p_bool_or);
01492         registry().add("bool_or_imp", &p_bool_or_imp);
01493         registry().add("bool_and", &p_bool_and);
01494         registry().add("bool_and_imp", &p_bool_and_imp);
01495         registry().add("bool_xor", &p_bool_xor);
01496         registry().add("bool_xor_imp", &p_bool_xor_imp);
01497         registry().add("array_bool_and", &p_array_bool_and);
01498         registry().add("array_bool_and_imp", &p_array_bool_and_imp);
01499         registry().add("array_bool_or", &p_array_bool_or);
01500         registry().add("array_bool_or_imp", &p_array_bool_or_imp);
01501         registry().add("array_bool_xor", &p_array_bool_xor);
01502         registry().add("array_bool_xor_imp", &p_array_bool_xor_imp);
01503         registry().add("bool_clause", &p_array_bool_clause);
01504         registry().add("bool_clause_reif", &p_array_bool_clause_reif);
01505         registry().add("bool_clause_imp", &p_array_bool_clause_imp);
01506         registry().add("bool_left_imp", &p_bool_l_imp);
01507         registry().add("bool_right_imp", &p_bool_r_imp);
01508         registry().add("bool_not", &p_bool_not);
01509         registry().add("array_int_element", &p_array_int_element);
01510         registry().add("array_var_int_element", &p_array_int_element);
01511         registry().add("array_bool_element", &p_array_bool_element);
01512         registry().add("array_var_bool_element", &p_array_bool_element);
01513         registry().add("bool2int", &p_bool2int);
01514         registry().add("int_in", &p_int_in);
01515         registry().add("int_in_reif", &p_int_in_reif);
01516         registry().add("int_in_imp", &p_int_in_imp);
01517 #ifndef GECODE_HAS_SET_VARS
01518         registry().add("set_in", &p_int_in);
01519         registry().add("set_in_reif", &p_int_in_reif);
01520         registry().add("set_in_imp", &p_int_in_imp);
01521 #endif
01522 
01523         registry().add("array_int_lt", &p_array_int_lt);
01524         registry().add("array_int_lq", &p_array_int_lq);
01525         registry().add("array_bool_lt", &p_array_bool_lt);
01526         registry().add("array_bool_lq", &p_array_bool_lq);
01527         registry().add("count", &p_count);
01528         registry().add("count_reif", &p_count_reif);
01529         registry().add("count_imp", &p_count_imp);
01530         registry().add("at_least_int", &p_at_least);
01531         registry().add("at_most_int", &p_at_most);
01532         registry().add("gecode_bin_packing_load", &p_bin_packing_load);
01533         registry().add("gecode_global_cardinality", &p_global_cardinality);
01534         registry().add("gecode_global_cardinality_closed",
01535           &p_global_cardinality_closed);
01536         registry().add("global_cardinality_low_up",
01537           &p_global_cardinality_low_up);
01538         registry().add("global_cardinality_low_up_closed",
01539           &p_global_cardinality_low_up_closed);
01540         registry().add("array_int_minimum", &p_minimum);
01541         registry().add("array_int_maximum", &p_maximum);
01542         registry().add("gecode_minimum_arg_int", &p_minimum_arg);
01543         registry().add("gecode_maximum_arg_int", &p_maximum_arg);
01544         registry().add("array_int_maximum", &p_maximum);
01545         registry().add("gecode_regular", &p_regular);
01546         registry().add("sort", &p_sort);
01547         registry().add("inverse_offsets", &p_inverse_offsets);
01548         registry().add("increasing_int", &p_increasing_int);
01549         registry().add("increasing_bool", &p_increasing_bool);
01550         registry().add("decreasing_int", &p_decreasing_int);
01551         registry().add("decreasing_bool", &p_decreasing_bool);
01552         registry().add("gecode_table_int", &p_table_int);
01553         registry().add("gecode_table_bool", &p_table_bool);
01554         registry().add("cumulatives", &p_cumulatives);
01555         registry().add("gecode_among_seq_int", &p_among_seq_int);
01556         registry().add("gecode_among_seq_bool", &p_among_seq_bool);
01557 
01558         registry().add("bool_lin_eq", &p_bool_lin_eq);
01559         registry().add("bool_lin_ne", &p_bool_lin_ne);
01560         registry().add("bool_lin_le", &p_bool_lin_le);
01561         registry().add("bool_lin_lt", &p_bool_lin_lt);
01562         registry().add("bool_lin_ge", &p_bool_lin_ge);
01563         registry().add("bool_lin_gt", &p_bool_lin_gt);
01564 
01565         registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
01566         registry().add("bool_lin_eq_imp", &p_bool_lin_eq_imp);
01567         registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
01568         registry().add("bool_lin_ne_imp", &p_bool_lin_ne_imp);
01569         registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
01570         registry().add("bool_lin_le_imp", &p_bool_lin_le_imp);
01571         registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
01572         registry().add("bool_lin_lt_imp", &p_bool_lin_lt_imp);
01573         registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
01574         registry().add("bool_lin_ge_imp", &p_bool_lin_ge_imp);
01575         registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
01576         registry().add("bool_lin_gt_imp", &p_bool_lin_gt_imp);
01577 
01578         registry().add("gecode_schedule_unary", &p_schedule_unary);
01579         registry().add("gecode_schedule_unary_optional", &p_schedule_unary_optional);
01580         registry().add("gecode_schedule_cumulative_optional", &p_cumulative_opt);
01581 
01582         registry().add("gecode_circuit", &p_circuit);
01583         registry().add("gecode_circuit_cost_array", &p_circuit_cost_array);
01584         registry().add("gecode_circuit_cost", &p_circuit_cost);
01585         registry().add("gecode_nooverlap", &p_nooverlap);
01586         registry().add("gecode_precede", &p_precede);
01587         registry().add("nvalue",&p_nvalue);
01588         registry().add("among",&p_among);
01589         registry().add("member_int",&p_member_int);
01590         registry().add("gecode_member_int_reif",&p_member_int_reif);
01591         registry().add("member_bool",&p_member_bool);
01592         registry().add("gecode_member_bool_reif",&p_member_bool_reif);
01593       }
01594     };
01595     IntPoster __int_poster;
01596 
01597 #ifdef GECODE_HAS_SET_VARS
01598     void p_set_OP(FlatZincSpace& s, SetOpType op,
01599                   const ConExpr& ce, AST::Node *) {
01600       rel(s, s.arg2SetVar(ce[0]), op, s.arg2SetVar(ce[1]),
01601           SRT_EQ, s.arg2SetVar(ce[2]));
01602     }
01603     void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01604       p_set_OP(s, SOT_UNION, ce, ann);
01605     }
01606     void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01607       p_set_OP(s, SOT_INTER, ce, ann);
01608     }
01609     void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01610       p_set_OP(s, SOT_MINUS, ce, ann);
01611     }
01612 
01613     void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01614       SetVar x = s.arg2SetVar(ce[0]);
01615       SetVar y = s.arg2SetVar(ce[1]);
01616 
01617       SetVarLubRanges xub(x);
01618       IntSet xubs(xub);
01619       SetVar x_y(s,IntSet::empty,xubs);
01620       rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
01621 
01622       SetVarLubRanges yub(y);
01623       IntSet yubs(yub);
01624       SetVar y_x(s,IntSet::empty,yubs);
01625       rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
01626 
01627       rel(s, x_y, SOT_UNION, y_x, SRT_EQ, s.arg2SetVar(ce[2]));
01628     }
01629 
01630     void p_array_set_OP(FlatZincSpace& s, SetOpType op,
01631                         const ConExpr& ce, AST::Node *) {
01632       SetVarArgs xs = s.arg2setvarargs(ce[0]);
01633       rel(s, op, xs, s.arg2SetVar(ce[1]));
01634     }
01635     void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01636       p_array_set_OP(s, SOT_UNION, ce, ann);
01637     }
01638     void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01639       p_array_set_OP(s, SOT_DUNION, ce, ann);
01640     }
01641 
01642 
01643     void p_set_rel(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01644       rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]));
01645     }
01646 
01647     void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01648       p_set_rel(s, SRT_EQ, ce);
01649     }
01650     void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01651       p_set_rel(s, SRT_NQ, ce);
01652     }
01653     void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01654       p_set_rel(s, SRT_SUB, ce);
01655     }
01656     void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01657       p_set_rel(s, SRT_SUP, ce);
01658     }
01659     void p_set_le(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01660       p_set_rel(s, SRT_LQ, ce);
01661     }
01662     void p_set_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01663       p_set_rel(s, SRT_LE, ce);
01664     }
01665     void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01666       if (!ce[1]->isIntVar()) {
01667         cardinality(s, s.arg2SetVar(ce[0]), ce[1]->getInt(),
01668                     ce[1]->getInt());
01669       } else {
01670         cardinality(s, s.arg2SetVar(ce[0]), s.arg2IntVar(ce[1]));
01671       }
01672     }
01673     void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01674       if (!ce[1]->isSetVar()) {
01675         IntSet d = s.arg2intset(ce[1]);
01676         if (ce[0]->isBoolVar()) {
01677           IntSetRanges dr(d);
01678           Iter::Ranges::Singleton sr(0,1);
01679           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01680           IntSet d01(i);
01681           if (d01.size() == 0) {
01682             s.fail();
01683           } else {
01684             rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
01685             rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
01686           }
01687         } else {
01688           dom(s, s.arg2IntVar(ce[0]), d);
01689         }
01690       } else {
01691         if (!ce[0]->isIntVar()) {
01692           dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt());
01693         } else {
01694           rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]));
01695         }
01696       }
01697     }
01698     void p_set_rel_reif(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01699       rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]),
01700           s.arg2BoolVar(ce[2]));
01701     }
01702 
01703     void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01704       p_set_rel_reif(s,SRT_EQ,ce);
01705     }
01706     void p_set_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01707       p_set_rel_reif(s,SRT_LQ,ce);
01708     }
01709     void p_set_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01710       p_set_rel_reif(s,SRT_LE,ce);
01711     }
01712     void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01713       p_set_rel_reif(s,SRT_NQ,ce);
01714     }
01715     void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
01716                            AST::Node *) {
01717       p_set_rel_reif(s,SRT_SUB,ce);
01718     }
01719     void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
01720                              AST::Node *) {
01721       p_set_rel_reif(s,SRT_SUP,ce);
01722     }
01723     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann, ReifyMode rm) {
01724       if (!ce[1]->isSetVar()) {
01725         if (rm==RM_EQV) {
01726           p_int_in_reif(s,ce,ann);
01727         } else {
01728           assert(rm==RM_IMP);
01729           p_int_in_imp(s,ce,ann);
01730         }
01731       } else {
01732         if (!ce[0]->isIntVar()) {
01733           dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt(),
01734               Reify(s.arg2BoolVar(ce[2]),rm));
01735         } else {
01736           rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]),
01737               Reify(s.arg2BoolVar(ce[2]),rm));
01738         }
01739       }
01740     }
01741     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01742       p_set_in_reif(s,ce,ann,RM_EQV);
01743     }
01744     void p_set_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01745       p_set_in_reif(s,ce,ann,RM_IMP);
01746     }
01747     void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01748       rel(s, s.arg2SetVar(ce[0]), SRT_DISJ, s.arg2SetVar(ce[1]));
01749     }
01750 
01751     void p_link_set_to_booleans(FlatZincSpace& s, const ConExpr& ce,
01752                                 AST::Node *) {
01753       SetVar x = s.arg2SetVar(ce[0]);
01754       int idx = ce[2]->getInt();
01755       assert(idx >= 0);
01756       rel(s, x || IntSet(Set::Limits::min,idx-1));
01757       BoolVarArgs y = s.arg2boolvarargs(ce[1],idx);
01758       unshare(s, y);
01759       channel(s, y, x);
01760     }
01761 
01762     void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
01763                              AST::Node*) {
01764       bool isConstant = true;
01765       AST::Array* a = ce[1]->getArray();
01766       for (int i=a->a.size(); i--;) {
01767         if (a->a[i]->isSetVar()) {
01768           isConstant = false;
01769           break;
01770         }
01771       }
01772       IntVar selector = s.arg2IntVar(ce[0]);
01773       rel(s, selector > 0);
01774       if (isConstant) {
01775         IntSetArgs sv = s.arg2intsetargs(ce[1],1);
01776         element(s, sv, selector, s.arg2SetVar(ce[2]));
01777       } else {
01778         SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
01779         element(s, sv, selector, s.arg2SetVar(ce[2]));
01780       }
01781     }
01782 
01783     void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
01784                                 AST::Node*, SetOpType op,
01785                                 const IntSet& universe =
01786                                 IntSet(Set::Limits::min,Set::Limits::max)) {
01787       bool isConstant = true;
01788       AST::Array* a = ce[1]->getArray();
01789       for (int i=a->a.size(); i--;) {
01790         if (a->a[i]->isSetVar()) {
01791           isConstant = false;
01792           break;
01793         }
01794       }
01795       SetVar selector = s.arg2SetVar(ce[0]);
01796       dom(s, selector, SRT_DISJ, 0);
01797       if (isConstant) {
01798         IntSetArgs sv = s.arg2intsetargs(ce[1], 1);
01799         element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
01800       } else {
01801         SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
01802         element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
01803       }
01804     }
01805 
01806     void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
01807                                        AST::Node* ann) {
01808       p_array_set_element_op(s, ce, ann, SOT_UNION);
01809     }
01810 
01811     void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
01812                                        AST::Node* ann) {
01813       p_array_set_element_op(s, ce, ann, SOT_INTER);
01814     }
01815 
01816     void p_array_set_element_intersect_in(FlatZincSpace& s,
01817                                               const ConExpr& ce,
01818                                               AST::Node* ann) {
01819       IntSet d = s.arg2intset(ce[3]);
01820       p_array_set_element_op(s, ce, ann, SOT_INTER, d);
01821     }
01822 
01823     void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
01824                                            AST::Node* ann) {
01825       p_array_set_element_op(s, ce, ann, SOT_DUNION);
01826     }
01827 
01828     void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01829       convex(s, s.arg2SetVar(ce[0]));
01830     }
01831 
01832     void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01833       SetVarArgs sv = s.arg2setvarargs(ce[0]);
01834       sequence(s, sv);
01835     }
01836 
01837     void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
01838                                AST::Node *) {
01839       SetVarArgs sv = s.arg2setvarargs(ce[0]);
01840       sequence(s, sv, s.arg2SetVar(ce[1]));
01841     }
01842 
01843     void p_int_set_channel(FlatZincSpace& s, const ConExpr& ce,
01844                            AST::Node *) {
01845       int xoff=ce[1]->getInt();
01846       assert(xoff >= 0);
01847       int yoff=ce[3]->getInt();
01848       assert(yoff >= 0);
01849       IntVarArgs xv = s.arg2intvarargs(ce[0], xoff);
01850       SetVarArgs yv = s.arg2setvarargs(ce[2], yoff, 1, IntSet(0, xoff-1));
01851       IntSet xd(yoff,yv.size()-1);
01852       for (int i=xoff; i<xv.size(); i++) {
01853         dom(s, xv[i], xd);
01854       }
01855       IntSet yd(xoff,xv.size()-1);
01856       for (int i=yoff; i<yv.size(); i++) {
01857         dom(s, yv[i], SRT_SUB, yd);
01858       }
01859       channel(s,xv,yv);
01860     }
01861 
01862     void p_range(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01863       int xoff=ce[1]->getInt();
01864       assert(xoff >= 0);
01865       IntVarArgs xv = s.arg2intvarargs(ce[0],xoff);
01866       element(s, SOT_UNION, xv, s.arg2SetVar(ce[2]), s.arg2SetVar(ce[3]));
01867     }
01868 
01869     void p_weights(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01870       IntArgs e = s.arg2intargs(ce[0]);
01871       IntArgs w = s.arg2intargs(ce[1]);
01872       SetVar x = s.arg2SetVar(ce[2]);
01873       IntVar y = s.arg2IntVar(ce[3]);
01874       weights(s,e,w,x,y);
01875     }
01876 
01877     void p_inverse_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01878       int xoff = ce[2]->getInt();
01879       int yoff = ce[3]->getInt();
01880       SetVarArgs x = s.arg2setvarargs(ce[0],xoff);
01881       SetVarArgs y = s.arg2setvarargs(ce[1],yoff);
01882       channel(s, x, y);
01883     }
01884 
01885     void p_precede_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01886       SetVarArgs x = s.arg2setvarargs(ce[0]);
01887       int p_s = ce[1]->getInt();
01888       int p_t = ce[2]->getInt();
01889       precede(s,x,p_s,p_t);
01890     }
01891 
01892     class SetPoster {
01893     public:
01894       SetPoster(void) {
01895         registry().add("set_eq", &p_set_eq);
01896         registry().add("set_le", &p_set_le);
01897         registry().add("set_lt", &p_set_lt);
01898         registry().add("equal", &p_set_eq);
01899         registry().add("set_ne", &p_set_ne);
01900         registry().add("set_union", &p_set_union);
01901         registry().add("array_set_element", &p_array_set_element);
01902         registry().add("array_var_set_element", &p_array_set_element);
01903         registry().add("set_intersect", &p_set_intersect);
01904         registry().add("set_diff", &p_set_diff);
01905         registry().add("set_symdiff", &p_set_symdiff);
01906         registry().add("set_subset", &p_set_subset);
01907         registry().add("set_superset", &p_set_superset);
01908         registry().add("set_card", &p_set_card);
01909         registry().add("set_in", &p_set_in);
01910         registry().add("set_eq_reif", &p_set_eq_reif);
01911         registry().add("set_le_reif", &p_set_le_reif);
01912         registry().add("set_lt_reif", &p_set_lt_reif);
01913         registry().add("equal_reif", &p_set_eq_reif);
01914         registry().add("set_ne_reif", &p_set_ne_reif);
01915         registry().add("set_subset_reif", &p_set_subset_reif);
01916         registry().add("set_superset_reif", &p_set_superset_reif);
01917         registry().add("set_in_reif", &p_set_in_reif);
01918         registry().add("set_in_imp", &p_set_in_imp);
01919         registry().add("disjoint", &p_set_disjoint);
01920         registry().add("gecode_link_set_to_booleans",
01921                        &p_link_set_to_booleans);
01922 
01923         registry().add("array_set_union", &p_array_set_union);
01924         registry().add("array_set_partition", &p_array_set_partition);
01925         registry().add("set_convex", &p_set_convex);
01926         registry().add("array_set_seq", &p_array_set_seq);
01927         registry().add("array_set_seq_union", &p_array_set_seq_union);
01928         registry().add("gecode_array_set_element_union",
01929                        &p_array_set_element_union);
01930         registry().add("gecode_array_set_element_intersect",
01931                        &p_array_set_element_intersect);
01932         registry().add("gecode_array_set_element_intersect_in",
01933                        &p_array_set_element_intersect_in);
01934         registry().add("gecode_array_set_element_partition",
01935                        &p_array_set_element_partition);
01936         registry().add("gecode_int_set_channel",
01937                        &p_int_set_channel);
01938         registry().add("gecode_range",
01939                        &p_range);
01940         registry().add("gecode_set_weights",
01941                        &p_weights);
01942         registry().add("gecode_inverse_set", &p_inverse_set);
01943         registry().add("gecode_precede_set", &p_precede_set);
01944       }
01945     };
01946     SetPoster __set_poster;
01947 #endif
01948 
01949 #ifdef GECODE_HAS_FLOAT_VARS
01950 
01951     void p_int2float(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01952       IntVar x0 = s.arg2IntVar(ce[0]);
01953       FloatVar x1 = s.arg2FloatVar(ce[1]);
01954       channel(s, x0, x1);
01955     }
01956 
01957     void p_float_lin_cmp(FlatZincSpace& s, FloatRelType frt,
01958                          const ConExpr& ce, AST::Node*) {
01959       FloatValArgs fa = s.arg2floatargs(ce[0]);
01960       FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
01961       linear(s, fa, fv, frt, ce[2]->getFloat());
01962     }
01963     void p_float_lin_cmp_reif(FlatZincSpace& s, FloatRelType frt,
01964                               const ConExpr& ce, AST::Node*) {
01965       FloatValArgs fa = s.arg2floatargs(ce[0]);
01966       FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
01967       linear(s, fa, fv, frt, ce[2]->getFloat(), s.arg2BoolVar(ce[3]));
01968     }
01969     void p_float_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01970       p_float_lin_cmp(s,FRT_EQ,ce,ann);
01971     }
01972     void p_float_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce,
01973                              AST::Node* ann) {
01974       p_float_lin_cmp_reif(s,FRT_EQ,ce,ann);
01975     }
01976     void p_float_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01977       p_float_lin_cmp(s,FRT_LQ,ce,ann);
01978     }
01979     void p_float_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01980       p_float_lin_cmp(s,FRT_LE,ce,ann);
01981     }
01982     void p_float_lin_le_reif(FlatZincSpace& s, const ConExpr& ce,
01983                              AST::Node* ann) {
01984       p_float_lin_cmp_reif(s,FRT_LQ,ce,ann);
01985     }
01986     void p_float_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce,
01987                              AST::Node* ann) {
01988       p_float_lin_cmp_reif(s,FRT_LE,ce,ann);
01989     }
01990 
01991     void p_float_times(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01992       FloatVar x = s.arg2FloatVar(ce[0]);
01993       FloatVar y = s.arg2FloatVar(ce[1]);
01994       FloatVar z = s.arg2FloatVar(ce[2]);
01995       mult(s,x,y,z);
01996     }
01997 
01998     void p_float_div(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01999       FloatVar x = s.arg2FloatVar(ce[0]);
02000       FloatVar y = s.arg2FloatVar(ce[1]);
02001       FloatVar z = s.arg2FloatVar(ce[2]);
02002       div(s,x,y,z);
02003     }
02004 
02005     void p_float_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02006       FloatVar x = s.arg2FloatVar(ce[0]);
02007       FloatVar y = s.arg2FloatVar(ce[1]);
02008       FloatVar z = s.arg2FloatVar(ce[2]);
02009       rel(s,x+y==z);
02010     }
02011 
02012     void p_float_sqrt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02013       FloatVar x = s.arg2FloatVar(ce[0]);
02014       FloatVar y = s.arg2FloatVar(ce[1]);
02015       sqrt(s,x,y);
02016     }
02017 
02018     void p_float_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02019       FloatVar x = s.arg2FloatVar(ce[0]);
02020       FloatVar y = s.arg2FloatVar(ce[1]);
02021       abs(s,x,y);
02022     }
02023 
02024     void p_float_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02025       FloatVar x = s.arg2FloatVar(ce[0]);
02026       FloatVar y = s.arg2FloatVar(ce[1]);
02027       rel(s,x,FRT_EQ,y);
02028     }
02029     void p_float_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02030       FloatVar x = s.arg2FloatVar(ce[0]);
02031       FloatVar y = s.arg2FloatVar(ce[1]);
02032       BoolVar  b = s.arg2BoolVar(ce[2]);
02033       rel(s,x,FRT_EQ,y,b);
02034     }
02035     void p_float_le(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02036       FloatVar x = s.arg2FloatVar(ce[0]);
02037       FloatVar y = s.arg2FloatVar(ce[1]);
02038       rel(s,x,FRT_LQ,y);
02039     }
02040     void p_float_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02041       FloatVar x = s.arg2FloatVar(ce[0]);
02042       FloatVar y = s.arg2FloatVar(ce[1]);
02043       BoolVar  b = s.arg2BoolVar(ce[2]);
02044       rel(s,x,FRT_LQ,y,b);
02045     }
02046     void p_float_max(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02047       FloatVar x = s.arg2FloatVar(ce[0]);
02048       FloatVar y = s.arg2FloatVar(ce[1]);
02049       FloatVar z = s.arg2FloatVar(ce[2]);
02050       max(s,x,y,z);
02051     }
02052     void p_float_min(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02053       FloatVar x = s.arg2FloatVar(ce[0]);
02054       FloatVar y = s.arg2FloatVar(ce[1]);
02055       FloatVar z = s.arg2FloatVar(ce[2]);
02056       min(s,x,y,z);
02057     }
02058     void p_float_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02059       FloatVar x = s.arg2FloatVar(ce[0]);
02060       FloatVar y = s.arg2FloatVar(ce[1]);
02061       rel(s, x, FRT_LQ, y);
02062       rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
02063     }
02064 
02065     void p_float_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02066       FloatVar x = s.arg2FloatVar(ce[0]);
02067       FloatVar y = s.arg2FloatVar(ce[1]);
02068       BoolVar b = s.arg2BoolVar(ce[2]);
02069       BoolVar b0(s,0,1);
02070       BoolVar b1(s,0,1);
02071       rel(s, b == (b0 && !b1));
02072       rel(s, x, FRT_LQ, y, b0);
02073       rel(s, x, FRT_EQ, y, b1);
02074     }
02075 
02076     void p_float_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02077       FloatVar x = s.arg2FloatVar(ce[0]);
02078       FloatVar y = s.arg2FloatVar(ce[1]);
02079       rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
02080     }
02081 
02082 #ifdef GECODE_HAS_MPFR
02083 #define P_FLOAT_OP(Op) \
02084     void p_float_ ## Op (FlatZincSpace& s, const ConExpr& ce, AST::Node*) {\
02085       FloatVar x = s.arg2FloatVar(ce[0]);\
02086       FloatVar y = s.arg2FloatVar(ce[1]);\
02087       Op(s,x,y);\
02088     }
02089     P_FLOAT_OP(acos)
02090     P_FLOAT_OP(asin)
02091     P_FLOAT_OP(atan)
02092     P_FLOAT_OP(cos)
02093     P_FLOAT_OP(exp)
02094     P_FLOAT_OP(sin)
02095     P_FLOAT_OP(tan)
02096     // P_FLOAT_OP(sinh)
02097     // P_FLOAT_OP(tanh)
02098     // P_FLOAT_OP(cosh)
02099 #undef P_FLOAT_OP
02100 
02101     void p_float_ln(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02102       FloatVar x = s.arg2FloatVar(ce[0]);
02103       FloatVar y = s.arg2FloatVar(ce[1]);
02104       log(s,x,y);
02105     }
02106     void p_float_log10(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02107       FloatVar x = s.arg2FloatVar(ce[0]);
02108       FloatVar y = s.arg2FloatVar(ce[1]);
02109       log(s,10.0,x,y);
02110     }
02111     void p_float_log2(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02112       FloatVar x = s.arg2FloatVar(ce[0]);
02113       FloatVar y = s.arg2FloatVar(ce[1]);
02114       log(s,2.0,x,y);
02115     }
02116 
02117 #endif
02118 
02119     class FloatPoster {
02120     public:
02121       FloatPoster(void) {
02122         registry().add("int2float",&p_int2float);
02123         registry().add("float_abs",&p_float_abs);
02124         registry().add("float_sqrt",&p_float_sqrt);
02125         registry().add("float_eq",&p_float_eq);
02126         registry().add("float_eq_reif",&p_float_eq_reif);
02127         registry().add("float_le",&p_float_le);
02128         registry().add("float_le_reif",&p_float_le_reif);
02129         registry().add("float_lt",&p_float_lt);
02130         registry().add("float_lt_reif",&p_float_lt_reif);
02131         registry().add("float_ne",&p_float_ne);
02132         registry().add("float_times",&p_float_times);
02133         registry().add("float_div",&p_float_div);
02134         registry().add("float_plus",&p_float_plus);
02135         registry().add("float_max",&p_float_max);
02136         registry().add("float_min",&p_float_min);
02137 
02138         registry().add("float_lin_eq",&p_float_lin_eq);
02139         registry().add("float_lin_eq_reif",&p_float_lin_eq_reif);
02140         registry().add("float_lin_le",&p_float_lin_le);
02141         registry().add("float_lin_lt",&p_float_lin_lt);
02142         registry().add("float_lin_le_reif",&p_float_lin_le_reif);
02143         registry().add("float_lin_lt_reif",&p_float_lin_lt_reif);
02144 
02145 #ifdef GECODE_HAS_MPFR
02146         registry().add("float_acos",&p_float_acos);
02147         registry().add("float_asin",&p_float_asin);
02148         registry().add("float_atan",&p_float_atan);
02149         registry().add("float_cos",&p_float_cos);
02150         // registry().add("float_cosh",&p_float_cosh);
02151         registry().add("float_exp",&p_float_exp);
02152         registry().add("float_ln",&p_float_ln);
02153         registry().add("float_log10",&p_float_log10);
02154         registry().add("float_log2",&p_float_log2);
02155         registry().add("float_sin",&p_float_sin);
02156         // registry().add("float_sinh",&p_float_sinh);
02157         registry().add("float_tan",&p_float_tan);
02158         // registry().add("float_tanh",&p_float_tanh);
02159 #endif
02160       }
02161     } __float_poster;
02162 #endif
02163 
02164   }
02165 }}
02166 
02167 // STATISTICS: flatzinc-any