Generated on Fri Oct 19 11:24:51 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       IntArgs tuples = s.arg2intargs(ce[1]);
01140       TupleSet ts = s.arg2tupleset(tuples,x.size());
01141       extensional(s,x,ts,s.ann2ipl(ann));
01142     }
01143 
01144     void
01145     p_table_int_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01146       IntVarArgs x = s.arg2intvarargs(ce[0]);
01147       IntArgs tuples = s.arg2intargs(ce[1]);
01148       TupleSet ts = s.arg2tupleset(tuples,x.size());
01149       extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
01150     }
01151 
01152     void
01153     p_table_int_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01154       IntVarArgs x = s.arg2intvarargs(ce[0]);
01155       IntArgs tuples = s.arg2intargs(ce[1]);
01156       TupleSet ts = s.arg2tupleset(tuples,x.size());
01157       extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
01158     }
01159     
01160     void
01161     p_table_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01162       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01163       IntArgs tuples = s.arg2boolargs(ce[1]);
01164       TupleSet ts = s.arg2tupleset(tuples,x.size());
01165       extensional(s,x,ts,s.ann2ipl(ann));
01166     }
01167 
01168     void
01169     p_table_bool_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01170       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01171       IntArgs tuples = s.arg2boolargs(ce[1]);
01172       TupleSet ts = s.arg2tupleset(tuples,x.size());
01173       extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_EQV),s.ann2ipl(ann));
01174     }
01175 
01176     void
01177     p_table_bool_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01178       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01179       IntArgs tuples = s.arg2boolargs(ce[1]);
01180       TupleSet ts = s.arg2tupleset(tuples,x.size());
01181       extensional(s,x,ts,Reify(s.arg2BoolVar(ce[2]),RM_IMP),s.ann2ipl(ann));
01182     }
01183 
01184     void p_cumulative_opt(FlatZincSpace& s, const ConExpr& ce,
01185                       AST::Node* ann) {
01186       IntVarArgs start = s.arg2intvarargs(ce[0]);
01187       IntArgs duration = s.arg2intargs(ce[1]);
01188       IntArgs height = s.arg2intargs(ce[2]);
01189       BoolVarArgs opt = s.arg2boolvarargs(ce[3]);
01190       int bound = ce[4]->getInt();
01191       unshare(s,start);
01192       cumulative(s,bound,start,duration,height,opt,s.ann2ipl(ann));
01193     }
01194 
01195     void p_cumulatives(FlatZincSpace& s, const ConExpr& ce,
01196                       AST::Node* ann) {
01197       IntVarArgs start = s.arg2intvarargs(ce[0]);
01198       IntVarArgs duration = s.arg2intvarargs(ce[1]);
01199       IntVarArgs height = s.arg2intvarargs(ce[2]);
01200       int n = start.size();
01201       IntVar bound = s.arg2IntVar(ce[3]);
01202 
01203       if (n==0)
01204         return;
01205 
01206       if (n == 1) {
01207         rel(s, height[0] <= bound);
01208         return;
01209       }
01210 
01211       int minHeight = std::min(height[0].min(),height[1].min());
01212       int minHeight2 = std::max(height[0].min(),height[1].min());
01213       for (int i=2; i<n; i++) {
01214         if (height[i].min() < minHeight) {
01215           minHeight2 = minHeight;
01216           minHeight = height[i].min();
01217         } else if (height[i].min() < minHeight2) {
01218           minHeight2 = height[i].min();
01219         }
01220       }
01221       bool disjunctive =
01222        (minHeight > bound.max()/2) ||
01223        (minHeight2 > bound.max()/2 && minHeight+minHeight2>bound.max());
01224       if (disjunctive) {
01225         rel(s, bound >= max(height));
01226         // Unary
01227         if (duration.assigned()) {
01228           IntArgs durationI(n);
01229           for (int i=n; i--;)
01230             durationI[i] = duration[i].val();
01231           unshare(s,start);
01232           unary(s,start,durationI);
01233         } else {
01234           IntVarArgs end(n);
01235           for (int i=n; i--;)
01236             end[i] = expr(s,start[i]+duration[i]);
01237           unshare(s,start);
01238           unary(s,start,duration,end);
01239         }
01240       } else if (height.assigned()) {
01241         IntArgs heightI(n);
01242         for (int i=n; i--;)
01243           heightI[i] = height[i].val();
01244         if (duration.assigned()) {
01245           IntArgs durationI(n);
01246           for (int i=n; i--;)
01247             durationI[i] = duration[i].val();
01248           cumulative(s, bound, start, durationI, heightI);
01249         } else {
01250           IntVarArgs end(n);
01251           for (int i = n; i--; )
01252             end[i] = expr(s,start[i]+duration[i]);
01253           cumulative(s, bound, start, duration, end, heightI);
01254         }
01255       } else if (bound.assigned()) {
01256         IntArgs machine = IntArgs::create(n,0,0);
01257         IntArgs limit({bound.val()});
01258         IntVarArgs end(n);
01259         for (int i=n; i--;)
01260           end[i] = expr(s,start[i]+duration[i]);
01261         cumulatives(s, machine, start, duration, end, height, limit, true,
01262                     s.ann2ipl(ann));
01263       } else {
01264         int min = Gecode::Int::Limits::max;
01265         int max = Gecode::Int::Limits::min;
01266         IntVarArgs end(start.size());
01267         for (int i = start.size(); i--; ) {
01268           min = std::min(min, start[i].min());
01269           max = std::max(max, start[i].max() + duration[i].max());
01270           end[i] = expr(s, start[i] + duration[i]);
01271         }
01272         for (int time = min; time < max; ++time) {
01273           IntVarArgs x(start.size());
01274           for (int i = start.size(); i--; ) {
01275             IntVar overlaps = channel(s, expr(s, (start[i] <= time) &&
01276                                                  (time < end[i])));
01277             x[i] = expr(s, overlaps * height[i]);
01278           }
01279           linear(s, x, IRT_LQ, bound);
01280         }
01281       }
01282     }
01283 
01284     void p_among_seq_int(FlatZincSpace& s, const ConExpr& ce,
01285                          AST::Node* ann) {
01286       IntVarArgs x = s.arg2intvarargs(ce[0]);
01287       IntSet S = s.arg2intset(ce[1]);
01288       int q = ce[2]->getInt();
01289       int l = ce[3]->getInt();
01290       int u = ce[4]->getInt();
01291       unshare(s, x);
01292       sequence(s, x, S, q, l, u, s.ann2ipl(ann));
01293     }
01294 
01295     void p_among_seq_bool(FlatZincSpace& s, const ConExpr& ce,
01296                           AST::Node* ann) {
01297       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01298       bool val = ce[1]->getBool();
01299       int q = ce[2]->getInt();
01300       int l = ce[3]->getInt();
01301       int u = ce[4]->getInt();
01302       IntSet S(val, val);
01303       unshare(s, x);
01304       sequence(s, x, S, q, l, u, s.ann2ipl(ann));
01305     }
01306 
01307     void p_schedule_unary(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01308       IntVarArgs x = s.arg2intvarargs(ce[0]);
01309       IntArgs p = s.arg2intargs(ce[1]);
01310       unshare(s,x);
01311       unary(s, x, p);
01312     }
01313 
01314     void p_schedule_unary_optional(FlatZincSpace& s, const ConExpr& ce,
01315                                    AST::Node*) {
01316       IntVarArgs x = s.arg2intvarargs(ce[0]);
01317       IntArgs p = s.arg2intargs(ce[1]);
01318       BoolVarArgs m = s.arg2boolvarargs(ce[2]);
01319       unshare(s,x);
01320       unary(s, x, p, m);
01321     }
01322 
01323     void p_circuit(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01324       int off = ce[0]->getInt();
01325       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01326       unshare(s,xv);
01327       circuit(s,off,xv,s.ann2ipl(ann));
01328     }
01329     void p_circuit_cost_array(FlatZincSpace& s, const ConExpr& ce,
01330                               AST::Node *ann) {
01331       IntArgs c = s.arg2intargs(ce[0]);
01332       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01333       IntVarArgs yv = s.arg2intvarargs(ce[2]);
01334       IntVar z = s.arg2IntVar(ce[3]);
01335       unshare(s,xv);
01336       circuit(s,c,xv,yv,z,s.ann2ipl(ann));
01337     }
01338     void p_circuit_cost(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01339       IntArgs c = s.arg2intargs(ce[0]);
01340       IntVarArgs xv = s.arg2intvarargs(ce[1]);
01341       IntVar z = s.arg2IntVar(ce[2]);
01342       unshare(s,xv);
01343       circuit(s,c,xv,z,s.ann2ipl(ann));
01344     }
01345 
01346     void p_nooverlap(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01347       IntVarArgs x0 = s.arg2intvarargs(ce[0]);
01348       IntVarArgs w = s.arg2intvarargs(ce[1]);
01349       IntVarArgs y0 = s.arg2intvarargs(ce[2]);
01350       IntVarArgs h = s.arg2intvarargs(ce[3]);
01351       if (w.assigned() && h.assigned()) {
01352         IntArgs iw(w.size());
01353         for (int i=w.size(); i--;)
01354           iw[i] = w[i].val();
01355         IntArgs ih(h.size());
01356         for (int i=h.size(); i--;)
01357           ih[i] = h[i].val();
01358         nooverlap(s,x0,iw,y0,ih,s.ann2ipl(ann));
01359 
01360         int miny = y0[0].min();
01361         int maxy = y0[0].max();
01362         int maxdy = ih[0];
01363         for (int i=1; i<y0.size(); i++) {
01364           miny = std::min(miny,y0[i].min());
01365           maxy = std::max(maxy,y0[i].max());
01366           maxdy = std::max(maxdy,ih[i]);
01367         }
01368         int minx = x0[0].min();
01369         int maxx = x0[0].max();
01370         int maxdx = iw[0];
01371         for (int i=1; i<x0.size(); i++) {
01372           minx = std::min(minx,x0[i].min());
01373           maxx = std::max(maxx,x0[i].max());
01374           maxdx = std::max(maxdx,iw[i]);
01375         }
01376         if (miny > Int::Limits::min && maxy < Int::Limits::max) {
01377           cumulative(s,maxdy+maxy-miny,x0,iw,ih);
01378           cumulative(s,maxdx+maxx-minx,y0,ih,iw);
01379         }
01380       } else {
01381         IntVarArgs x1(x0.size()), y1(y0.size());
01382         for (int i=x0.size(); i--; )
01383           x1[i] = expr(s, x0[i] + w[i]);
01384         for (int i=y0.size(); i--; )
01385           y1[i] = expr(s, y0[i] + h[i]);
01386         nooverlap(s,x0,w,x1,y0,h,y1,s.ann2ipl(ann));
01387       }
01388     }
01389 
01390     void p_precede(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01391       IntVarArgs x = s.arg2intvarargs(ce[0]);
01392       int p_s = ce[1]->getInt();
01393       int p_t = ce[2]->getInt();
01394       precede(s,x,p_s,p_t,s.ann2ipl(ann));
01395     }
01396 
01397     void p_nvalue(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01398       IntVarArgs x = s.arg2intvarargs(ce[1]);
01399       if (ce[0]->isIntVar()) {
01400         IntVar y = s.arg2IntVar(ce[0]);
01401         nvalues(s,x,IRT_EQ,y,s.ann2ipl(ann));
01402       } else {
01403         nvalues(s,x,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
01404       }
01405     }
01406 
01407     void p_among(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01408       IntVarArgs x = s.arg2intvarargs(ce[1]);
01409       IntSet v = s.arg2intset(ce[2]);
01410       if (ce[0]->isIntVar()) {
01411         IntVar n = s.arg2IntVar(ce[0]);
01412         unshare(s, x);
01413         count(s,x,v,IRT_EQ,n,s.ann2ipl(ann));
01414       } else {
01415         unshare(s, x);
01416         count(s,x,v,IRT_EQ,ce[0]->getInt(),s.ann2ipl(ann));
01417       }
01418     }
01419 
01420     void p_member_int(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01421       IntVarArgs x = s.arg2intvarargs(ce[0]);
01422       IntVar y = s.arg2IntVar(ce[1]);
01423       member(s,x,y,s.ann2ipl(ann));
01424     }
01425     void p_member_int_reif(FlatZincSpace& s, const ConExpr& ce,
01426                            AST::Node* ann) {
01427       IntVarArgs x = s.arg2intvarargs(ce[0]);
01428       IntVar y = s.arg2IntVar(ce[1]);
01429       BoolVar b = s.arg2BoolVar(ce[2]);
01430       member(s,x,y,b,s.ann2ipl(ann));
01431     }
01432     void p_member_bool(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01433       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01434       BoolVar y = s.arg2BoolVar(ce[1]);
01435       member(s,x,y,s.ann2ipl(ann));
01436     }
01437     void p_member_bool_reif(FlatZincSpace& s, const ConExpr& ce,
01438                             AST::Node* ann) {
01439       BoolVarArgs x = s.arg2boolvarargs(ce[0]);
01440       BoolVar y = s.arg2BoolVar(ce[1]);
01441       member(s,x,y,s.arg2BoolVar(ce[2]),s.ann2ipl(ann));
01442     }
01443 
01444     class IntPoster {
01445     public:
01446       IntPoster(void) {
01447         registry().add("all_different_int", &p_distinct);
01448         registry().add("all_different_offset", &p_distinctOffset);
01449         registry().add("all_equal_int", &p_all_equal);
01450         registry().add("int_eq", &p_int_eq);
01451         registry().add("int_ne", &p_int_ne);
01452         registry().add("int_ge", &p_int_ge);
01453         registry().add("int_gt", &p_int_gt);
01454         registry().add("int_le", &p_int_le);
01455         registry().add("int_lt", &p_int_lt);
01456         registry().add("int_eq_reif", &p_int_eq_reif);
01457         registry().add("int_ne_reif", &p_int_ne_reif);
01458         registry().add("int_ge_reif", &p_int_ge_reif);
01459         registry().add("int_gt_reif", &p_int_gt_reif);
01460         registry().add("int_le_reif", &p_int_le_reif);
01461         registry().add("int_lt_reif", &p_int_lt_reif);
01462         registry().add("int_eq_imp", &p_int_eq_imp);
01463         registry().add("int_ne_imp", &p_int_ne_imp);
01464         registry().add("int_ge_imp", &p_int_ge_imp);
01465         registry().add("int_gt_imp", &p_int_gt_imp);
01466         registry().add("int_le_imp", &p_int_le_imp);
01467         registry().add("int_lt_imp", &p_int_lt_imp);
01468         registry().add("int_lin_eq", &p_int_lin_eq);
01469         registry().add("int_lin_eq_reif", &p_int_lin_eq_reif);
01470         registry().add("int_lin_eq_imp", &p_int_lin_eq_imp);
01471         registry().add("int_lin_ne", &p_int_lin_ne);
01472         registry().add("int_lin_ne_reif", &p_int_lin_ne_reif);
01473         registry().add("int_lin_ne_imp", &p_int_lin_ne_imp);
01474         registry().add("int_lin_le", &p_int_lin_le);
01475         registry().add("int_lin_le_reif", &p_int_lin_le_reif);
01476         registry().add("int_lin_le_imp", &p_int_lin_le_imp);
01477         registry().add("int_lin_lt", &p_int_lin_lt);
01478         registry().add("int_lin_lt_reif", &p_int_lin_lt_reif);
01479         registry().add("int_lin_lt_imp", &p_int_lin_lt_imp);
01480         registry().add("int_lin_ge", &p_int_lin_ge);
01481         registry().add("int_lin_ge_reif", &p_int_lin_ge_reif);
01482         registry().add("int_lin_ge_imp", &p_int_lin_ge_imp);
01483         registry().add("int_lin_gt", &p_int_lin_gt);
01484         registry().add("int_lin_gt_reif", &p_int_lin_gt_reif);
01485         registry().add("int_lin_gt_imp", &p_int_lin_gt_imp);
01486         registry().add("int_plus", &p_int_plus);
01487         registry().add("int_minus", &p_int_minus);
01488         registry().add("int_times", &p_int_times);
01489         registry().add("gecode_int_pow", &p_int_pow);
01490         registry().add("int_div", &p_int_div);
01491         registry().add("int_mod", &p_int_mod);
01492         registry().add("int_min", &p_int_min);
01493         registry().add("int_max", &p_int_max);
01494         registry().add("int_abs", &p_abs);
01495         registry().add("int_negate", &p_int_negate);
01496         registry().add("bool_eq", &p_bool_eq);
01497         registry().add("bool_eq_reif", &p_bool_eq_reif);
01498         registry().add("bool_eq_imp", &p_bool_eq_imp);
01499         registry().add("bool_ne", &p_bool_ne);
01500         registry().add("bool_ne_reif", &p_bool_ne_reif);
01501         registry().add("bool_ne_imp", &p_bool_ne_imp);
01502         registry().add("bool_ge", &p_bool_ge);
01503         registry().add("bool_ge_reif", &p_bool_ge_reif);
01504         registry().add("bool_ge_imp", &p_bool_ge_imp);
01505         registry().add("bool_le", &p_bool_le);
01506         registry().add("bool_le_reif", &p_bool_le_reif);
01507         registry().add("bool_le_imp", &p_bool_le_imp);
01508         registry().add("bool_gt", &p_bool_gt);
01509         registry().add("bool_gt_reif", &p_bool_gt_reif);
01510         registry().add("bool_gt_imp", &p_bool_gt_imp);
01511         registry().add("bool_lt", &p_bool_lt);
01512         registry().add("bool_lt_reif", &p_bool_lt_reif);
01513         registry().add("bool_lt_imp", &p_bool_lt_imp);
01514         registry().add("bool_or", &p_bool_or);
01515         registry().add("bool_or_imp", &p_bool_or_imp);
01516         registry().add("bool_and", &p_bool_and);
01517         registry().add("bool_and_imp", &p_bool_and_imp);
01518         registry().add("bool_xor", &p_bool_xor);
01519         registry().add("bool_xor_imp", &p_bool_xor_imp);
01520         registry().add("array_bool_and", &p_array_bool_and);
01521         registry().add("array_bool_and_imp", &p_array_bool_and_imp);
01522         registry().add("array_bool_or", &p_array_bool_or);
01523         registry().add("array_bool_or_imp", &p_array_bool_or_imp);
01524         registry().add("array_bool_xor", &p_array_bool_xor);
01525         registry().add("array_bool_xor_imp", &p_array_bool_xor_imp);
01526         registry().add("bool_clause", &p_array_bool_clause);
01527         registry().add("bool_clause_reif", &p_array_bool_clause_reif);
01528         registry().add("bool_clause_imp", &p_array_bool_clause_imp);
01529         registry().add("bool_left_imp", &p_bool_l_imp);
01530         registry().add("bool_right_imp", &p_bool_r_imp);
01531         registry().add("bool_not", &p_bool_not);
01532         registry().add("array_int_element", &p_array_int_element);
01533         registry().add("array_var_int_element", &p_array_int_element);
01534         registry().add("array_bool_element", &p_array_bool_element);
01535         registry().add("array_var_bool_element", &p_array_bool_element);
01536         registry().add("bool2int", &p_bool2int);
01537         registry().add("int_in", &p_int_in);
01538         registry().add("int_in_reif", &p_int_in_reif);
01539         registry().add("int_in_imp", &p_int_in_imp);
01540 #ifndef GECODE_HAS_SET_VARS
01541         registry().add("set_in", &p_int_in);
01542         registry().add("set_in_reif", &p_int_in_reif);
01543         registry().add("set_in_imp", &p_int_in_imp);
01544 #endif
01545 
01546         registry().add("array_int_lt", &p_array_int_lt);
01547         registry().add("array_int_lq", &p_array_int_lq);
01548         registry().add("array_bool_lt", &p_array_bool_lt);
01549         registry().add("array_bool_lq", &p_array_bool_lq);
01550         registry().add("count", &p_count);
01551         registry().add("count_reif", &p_count_reif);
01552         registry().add("count_imp", &p_count_imp);
01553         registry().add("at_least_int", &p_at_least);
01554         registry().add("at_most_int", &p_at_most);
01555         registry().add("gecode_bin_packing_load", &p_bin_packing_load);
01556         registry().add("gecode_global_cardinality", &p_global_cardinality);
01557         registry().add("gecode_global_cardinality_closed",
01558           &p_global_cardinality_closed);
01559         registry().add("global_cardinality_low_up",
01560           &p_global_cardinality_low_up);
01561         registry().add("global_cardinality_low_up_closed",
01562           &p_global_cardinality_low_up_closed);
01563         registry().add("array_int_minimum", &p_minimum);
01564         registry().add("array_int_maximum", &p_maximum);
01565         registry().add("gecode_minimum_arg_int", &p_minimum_arg);
01566         registry().add("gecode_maximum_arg_int", &p_maximum_arg);
01567         registry().add("array_int_maximum", &p_maximum);
01568         registry().add("gecode_regular", &p_regular);
01569         registry().add("sort", &p_sort);
01570         registry().add("inverse_offsets", &p_inverse_offsets);
01571         registry().add("increasing_int", &p_increasing_int);
01572         registry().add("increasing_bool", &p_increasing_bool);
01573         registry().add("decreasing_int", &p_decreasing_int);
01574         registry().add("decreasing_bool", &p_decreasing_bool);
01575         registry().add("gecode_table_int", &p_table_int);
01576         registry().add("gecode_table_int_reif", &p_table_int_reif);
01577         registry().add("gecode_table_int_imp", &p_table_int_imp);
01578         registry().add("gecode_table_bool", &p_table_bool);
01579         registry().add("gecode_table_bool_reif", &p_table_bool_reif);
01580         registry().add("gecode_table_bool_imp", &p_table_bool_imp);
01581         registry().add("cumulatives", &p_cumulatives);
01582         registry().add("gecode_among_seq_int", &p_among_seq_int);
01583         registry().add("gecode_among_seq_bool", &p_among_seq_bool);
01584 
01585         registry().add("bool_lin_eq", &p_bool_lin_eq);
01586         registry().add("bool_lin_ne", &p_bool_lin_ne);
01587         registry().add("bool_lin_le", &p_bool_lin_le);
01588         registry().add("bool_lin_lt", &p_bool_lin_lt);
01589         registry().add("bool_lin_ge", &p_bool_lin_ge);
01590         registry().add("bool_lin_gt", &p_bool_lin_gt);
01591 
01592         registry().add("bool_lin_eq_reif", &p_bool_lin_eq_reif);
01593         registry().add("bool_lin_eq_imp", &p_bool_lin_eq_imp);
01594         registry().add("bool_lin_ne_reif", &p_bool_lin_ne_reif);
01595         registry().add("bool_lin_ne_imp", &p_bool_lin_ne_imp);
01596         registry().add("bool_lin_le_reif", &p_bool_lin_le_reif);
01597         registry().add("bool_lin_le_imp", &p_bool_lin_le_imp);
01598         registry().add("bool_lin_lt_reif", &p_bool_lin_lt_reif);
01599         registry().add("bool_lin_lt_imp", &p_bool_lin_lt_imp);
01600         registry().add("bool_lin_ge_reif", &p_bool_lin_ge_reif);
01601         registry().add("bool_lin_ge_imp", &p_bool_lin_ge_imp);
01602         registry().add("bool_lin_gt_reif", &p_bool_lin_gt_reif);
01603         registry().add("bool_lin_gt_imp", &p_bool_lin_gt_imp);
01604 
01605         registry().add("gecode_schedule_unary", &p_schedule_unary);
01606         registry().add("gecode_schedule_unary_optional", &p_schedule_unary_optional);
01607         registry().add("gecode_schedule_cumulative_optional", &p_cumulative_opt);
01608 
01609         registry().add("gecode_circuit", &p_circuit);
01610         registry().add("gecode_circuit_cost_array", &p_circuit_cost_array);
01611         registry().add("gecode_circuit_cost", &p_circuit_cost);
01612         registry().add("gecode_nooverlap", &p_nooverlap);
01613         registry().add("gecode_precede", &p_precede);
01614         registry().add("nvalue",&p_nvalue);
01615         registry().add("among",&p_among);
01616         registry().add("member_int",&p_member_int);
01617         registry().add("gecode_member_int_reif",&p_member_int_reif);
01618         registry().add("member_bool",&p_member_bool);
01619         registry().add("gecode_member_bool_reif",&p_member_bool_reif);
01620       }
01621     };
01622     IntPoster __int_poster;
01623 
01624 #ifdef GECODE_HAS_SET_VARS
01625     void p_set_OP(FlatZincSpace& s, SetOpType op,
01626                   const ConExpr& ce, AST::Node *) {
01627       rel(s, s.arg2SetVar(ce[0]), op, s.arg2SetVar(ce[1]),
01628           SRT_EQ, s.arg2SetVar(ce[2]));
01629     }
01630     void p_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01631       p_set_OP(s, SOT_UNION, ce, ann);
01632     }
01633     void p_set_intersect(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01634       p_set_OP(s, SOT_INTER, ce, ann);
01635     }
01636     void p_set_diff(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01637       p_set_OP(s, SOT_MINUS, ce, ann);
01638     }
01639 
01640     void p_set_symdiff(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01641       SetVar x = s.arg2SetVar(ce[0]);
01642       SetVar y = s.arg2SetVar(ce[1]);
01643 
01644       SetVarLubRanges xub(x);
01645       IntSet xubs(xub);
01646       SetVar x_y(s,IntSet::empty,xubs);
01647       rel(s, x, SOT_MINUS, y, SRT_EQ, x_y);
01648 
01649       SetVarLubRanges yub(y);
01650       IntSet yubs(yub);
01651       SetVar y_x(s,IntSet::empty,yubs);
01652       rel(s, y, SOT_MINUS, x, SRT_EQ, y_x);
01653 
01654       rel(s, x_y, SOT_UNION, y_x, SRT_EQ, s.arg2SetVar(ce[2]));
01655     }
01656 
01657     void p_array_set_OP(FlatZincSpace& s, SetOpType op,
01658                         const ConExpr& ce, AST::Node *) {
01659       SetVarArgs xs = s.arg2setvarargs(ce[0]);
01660       rel(s, op, xs, s.arg2SetVar(ce[1]));
01661     }
01662     void p_array_set_union(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01663       p_array_set_OP(s, SOT_UNION, ce, ann);
01664     }
01665     void p_array_set_partition(FlatZincSpace& s, const ConExpr& ce, AST::Node *ann) {
01666       p_array_set_OP(s, SOT_DUNION, ce, ann);
01667     }
01668 
01669 
01670     void p_set_rel(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01671       rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]));
01672     }
01673 
01674     void p_set_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01675       p_set_rel(s, SRT_EQ, ce);
01676     }
01677     void p_set_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01678       p_set_rel(s, SRT_NQ, ce);
01679     }
01680     void p_set_subset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01681       p_set_rel(s, SRT_SUB, ce);
01682     }
01683     void p_set_superset(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01684       p_set_rel(s, SRT_SUP, ce);
01685     }
01686     void p_set_le(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01687       p_set_rel(s, SRT_LQ, ce);
01688     }
01689     void p_set_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01690       p_set_rel(s, SRT_LE, ce);
01691     }
01692     void p_set_card(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01693       if (!ce[1]->isIntVar()) {
01694         cardinality(s, s.arg2SetVar(ce[0]), ce[1]->getInt(),
01695                     ce[1]->getInt());
01696       } else {
01697         cardinality(s, s.arg2SetVar(ce[0]), s.arg2IntVar(ce[1]));
01698       }
01699     }
01700     void p_set_in(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01701       if (!ce[1]->isSetVar()) {
01702         IntSet d = s.arg2intset(ce[1]);
01703         if (ce[0]->isBoolVar()) {
01704           IntSetRanges dr(d);
01705           Iter::Ranges::Singleton sr(0,1);
01706           Iter::Ranges::Inter<IntSetRanges,Iter::Ranges::Singleton> i(dr,sr);
01707           IntSet d01(i);
01708           if (d01.size() == 0) {
01709             s.fail();
01710           } else {
01711             rel(s, s.arg2BoolVar(ce[0]), IRT_GQ, d01.min());
01712             rel(s, s.arg2BoolVar(ce[0]), IRT_LQ, d01.max());
01713           }
01714         } else {
01715           dom(s, s.arg2IntVar(ce[0]), d);
01716         }
01717       } else {
01718         if (!ce[0]->isIntVar()) {
01719           dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt());
01720         } else {
01721           rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]));
01722         }
01723       }
01724     }
01725     void p_set_rel_reif(FlatZincSpace& s, SetRelType srt, const ConExpr& ce) {
01726       rel(s, s.arg2SetVar(ce[0]), srt, s.arg2SetVar(ce[1]),
01727           s.arg2BoolVar(ce[2]));
01728     }
01729 
01730     void p_set_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01731       p_set_rel_reif(s,SRT_EQ,ce);
01732     }
01733     void p_set_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01734       p_set_rel_reif(s,SRT_LQ,ce);
01735     }
01736     void p_set_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01737       p_set_rel_reif(s,SRT_LE,ce);
01738     }
01739     void p_set_ne_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01740       p_set_rel_reif(s,SRT_NQ,ce);
01741     }
01742     void p_set_subset_reif(FlatZincSpace& s, const ConExpr& ce,
01743                            AST::Node *) {
01744       p_set_rel_reif(s,SRT_SUB,ce);
01745     }
01746     void p_set_superset_reif(FlatZincSpace& s, const ConExpr& ce,
01747                              AST::Node *) {
01748       p_set_rel_reif(s,SRT_SUP,ce);
01749     }
01750     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann, ReifyMode rm) {
01751       if (!ce[1]->isSetVar()) {
01752         if (rm==RM_EQV) {
01753           p_int_in_reif(s,ce,ann);
01754         } else {
01755           assert(rm==RM_IMP);
01756           p_int_in_imp(s,ce,ann);
01757         }
01758       } else {
01759         if (!ce[0]->isIntVar()) {
01760           dom(s, s.arg2SetVar(ce[1]), SRT_SUP, ce[0]->getInt(),
01761               Reify(s.arg2BoolVar(ce[2]),rm));
01762         } else {
01763           rel(s, s.arg2SetVar(ce[1]), SRT_SUP, s.arg2IntVar(ce[0]),
01764               Reify(s.arg2BoolVar(ce[2]),rm));
01765         }
01766       }
01767     }
01768     void p_set_in_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01769       p_set_in_reif(s,ce,ann,RM_EQV);
01770     }
01771     void p_set_in_imp(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01772       p_set_in_reif(s,ce,ann,RM_IMP);
01773     }
01774     void p_set_disjoint(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01775       rel(s, s.arg2SetVar(ce[0]), SRT_DISJ, s.arg2SetVar(ce[1]));
01776     }
01777 
01778     void p_link_set_to_booleans(FlatZincSpace& s, const ConExpr& ce,
01779                                 AST::Node *) {
01780       SetVar x = s.arg2SetVar(ce[0]);
01781       int idx = ce[2]->getInt();
01782       assert(idx >= 0);
01783       rel(s, x || IntSet(Set::Limits::min,idx-1));
01784       BoolVarArgs y = s.arg2boolvarargs(ce[1],idx);
01785       unshare(s, y);
01786       channel(s, y, x);
01787     }
01788 
01789     void p_array_set_element(FlatZincSpace& s, const ConExpr& ce,
01790                              AST::Node*) {
01791       bool isConstant = true;
01792       AST::Array* a = ce[1]->getArray();
01793       for (int i=a->a.size(); i--;) {
01794         if (a->a[i]->isSetVar()) {
01795           isConstant = false;
01796           break;
01797         }
01798       }
01799       IntVar selector = s.arg2IntVar(ce[0]);
01800       rel(s, selector > 0);
01801       if (isConstant) {
01802         IntSetArgs sv = s.arg2intsetargs(ce[1],1);
01803         element(s, sv, selector, s.arg2SetVar(ce[2]));
01804       } else {
01805         SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
01806         element(s, sv, selector, s.arg2SetVar(ce[2]));
01807       }
01808     }
01809 
01810     void p_array_set_element_op(FlatZincSpace& s, const ConExpr& ce,
01811                                 AST::Node*, SetOpType op,
01812                                 const IntSet& universe =
01813                                 IntSet(Set::Limits::min,Set::Limits::max)) {
01814       bool isConstant = true;
01815       AST::Array* a = ce[1]->getArray();
01816       for (int i=a->a.size(); i--;) {
01817         if (a->a[i]->isSetVar()) {
01818           isConstant = false;
01819           break;
01820         }
01821       }
01822       SetVar selector = s.arg2SetVar(ce[0]);
01823       dom(s, selector, SRT_DISJ, 0);
01824       if (isConstant) {
01825         IntSetArgs sv = s.arg2intsetargs(ce[1], 1);
01826         element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
01827       } else {
01828         SetVarArgs sv = s.arg2setvarargs(ce[1], 1);
01829         element(s, op, sv, selector, s.arg2SetVar(ce[2]), universe);
01830       }
01831     }
01832 
01833     void p_array_set_element_union(FlatZincSpace& s, const ConExpr& ce,
01834                                        AST::Node* ann) {
01835       p_array_set_element_op(s, ce, ann, SOT_UNION);
01836     }
01837 
01838     void p_array_set_element_intersect(FlatZincSpace& s, const ConExpr& ce,
01839                                        AST::Node* ann) {
01840       p_array_set_element_op(s, ce, ann, SOT_INTER);
01841     }
01842 
01843     void p_array_set_element_intersect_in(FlatZincSpace& s,
01844                                               const ConExpr& ce,
01845                                               AST::Node* ann) {
01846       IntSet d = s.arg2intset(ce[3]);
01847       p_array_set_element_op(s, ce, ann, SOT_INTER, d);
01848     }
01849 
01850     void p_array_set_element_partition(FlatZincSpace& s, const ConExpr& ce,
01851                                            AST::Node* ann) {
01852       p_array_set_element_op(s, ce, ann, SOT_DUNION);
01853     }
01854 
01855     void p_set_convex(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01856       convex(s, s.arg2SetVar(ce[0]));
01857     }
01858 
01859     void p_array_set_seq(FlatZincSpace& s, const ConExpr& ce, AST::Node *) {
01860       SetVarArgs sv = s.arg2setvarargs(ce[0]);
01861       sequence(s, sv);
01862     }
01863 
01864     void p_array_set_seq_union(FlatZincSpace& s, const ConExpr& ce,
01865                                AST::Node *) {
01866       SetVarArgs sv = s.arg2setvarargs(ce[0]);
01867       sequence(s, sv, s.arg2SetVar(ce[1]));
01868     }
01869 
01870     void p_int_set_channel(FlatZincSpace& s, const ConExpr& ce,
01871                            AST::Node *) {
01872       int xoff=ce[1]->getInt();
01873       assert(xoff >= 0);
01874       int yoff=ce[3]->getInt();
01875       assert(yoff >= 0);
01876       IntVarArgs xv = s.arg2intvarargs(ce[0], xoff);
01877       SetVarArgs yv = s.arg2setvarargs(ce[2], yoff, 1, IntSet(0, xoff-1));
01878       IntSet xd(yoff,yv.size()-1);
01879       for (int i=xoff; i<xv.size(); i++) {
01880         dom(s, xv[i], xd);
01881       }
01882       IntSet yd(xoff,xv.size()-1);
01883       for (int i=yoff; i<yv.size(); i++) {
01884         dom(s, yv[i], SRT_SUB, yd);
01885       }
01886       channel(s,xv,yv);
01887     }
01888 
01889     void p_range(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01890       int xoff=ce[1]->getInt();
01891       assert(xoff >= 0);
01892       IntVarArgs xv = s.arg2intvarargs(ce[0],xoff);
01893       element(s, SOT_UNION, xv, s.arg2SetVar(ce[2]), s.arg2SetVar(ce[3]));
01894     }
01895 
01896     void p_weights(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01897       IntArgs e = s.arg2intargs(ce[0]);
01898       IntArgs w = s.arg2intargs(ce[1]);
01899       SetVar x = s.arg2SetVar(ce[2]);
01900       IntVar y = s.arg2IntVar(ce[3]);
01901       weights(s,e,w,x,y);
01902     }
01903 
01904     void p_inverse_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01905       int xoff = ce[2]->getInt();
01906       int yoff = ce[3]->getInt();
01907       SetVarArgs x = s.arg2setvarargs(ce[0],xoff);
01908       SetVarArgs y = s.arg2setvarargs(ce[1],yoff);
01909       channel(s, x, y);
01910     }
01911 
01912     void p_precede_set(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01913       SetVarArgs x = s.arg2setvarargs(ce[0]);
01914       int p_s = ce[1]->getInt();
01915       int p_t = ce[2]->getInt();
01916       precede(s,x,p_s,p_t);
01917     }
01918 
01919     class SetPoster {
01920     public:
01921       SetPoster(void) {
01922         registry().add("set_eq", &p_set_eq);
01923         registry().add("set_le", &p_set_le);
01924         registry().add("set_lt", &p_set_lt);
01925         registry().add("equal", &p_set_eq);
01926         registry().add("set_ne", &p_set_ne);
01927         registry().add("set_union", &p_set_union);
01928         registry().add("array_set_element", &p_array_set_element);
01929         registry().add("array_var_set_element", &p_array_set_element);
01930         registry().add("set_intersect", &p_set_intersect);
01931         registry().add("set_diff", &p_set_diff);
01932         registry().add("set_symdiff", &p_set_symdiff);
01933         registry().add("set_subset", &p_set_subset);
01934         registry().add("set_superset", &p_set_superset);
01935         registry().add("set_card", &p_set_card);
01936         registry().add("set_in", &p_set_in);
01937         registry().add("set_eq_reif", &p_set_eq_reif);
01938         registry().add("set_le_reif", &p_set_le_reif);
01939         registry().add("set_lt_reif", &p_set_lt_reif);
01940         registry().add("equal_reif", &p_set_eq_reif);
01941         registry().add("set_ne_reif", &p_set_ne_reif);
01942         registry().add("set_subset_reif", &p_set_subset_reif);
01943         registry().add("set_superset_reif", &p_set_superset_reif);
01944         registry().add("set_in_reif", &p_set_in_reif);
01945         registry().add("set_in_imp", &p_set_in_imp);
01946         registry().add("disjoint", &p_set_disjoint);
01947         registry().add("gecode_link_set_to_booleans",
01948                        &p_link_set_to_booleans);
01949 
01950         registry().add("array_set_union", &p_array_set_union);
01951         registry().add("array_set_partition", &p_array_set_partition);
01952         registry().add("set_convex", &p_set_convex);
01953         registry().add("array_set_seq", &p_array_set_seq);
01954         registry().add("array_set_seq_union", &p_array_set_seq_union);
01955         registry().add("gecode_array_set_element_union",
01956                        &p_array_set_element_union);
01957         registry().add("gecode_array_set_element_intersect",
01958                        &p_array_set_element_intersect);
01959         registry().add("gecode_array_set_element_intersect_in",
01960                        &p_array_set_element_intersect_in);
01961         registry().add("gecode_array_set_element_partition",
01962                        &p_array_set_element_partition);
01963         registry().add("gecode_int_set_channel",
01964                        &p_int_set_channel);
01965         registry().add("gecode_range",
01966                        &p_range);
01967         registry().add("gecode_set_weights",
01968                        &p_weights);
01969         registry().add("gecode_inverse_set", &p_inverse_set);
01970         registry().add("gecode_precede_set", &p_precede_set);
01971       }
01972     };
01973     SetPoster __set_poster;
01974 #endif
01975 
01976 #ifdef GECODE_HAS_FLOAT_VARS
01977 
01978     void p_int2float(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
01979       IntVar x0 = s.arg2IntVar(ce[0]);
01980       FloatVar x1 = s.arg2FloatVar(ce[1]);
01981       channel(s, x0, x1);
01982     }
01983 
01984     void p_float_lin_cmp(FlatZincSpace& s, FloatRelType frt,
01985                          const ConExpr& ce, AST::Node*) {
01986       FloatValArgs fa = s.arg2floatargs(ce[0]);
01987       FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
01988       linear(s, fa, fv, frt, ce[2]->getFloat());
01989     }
01990     void p_float_lin_cmp_reif(FlatZincSpace& s, FloatRelType frt,
01991                               const ConExpr& ce, AST::Node*) {
01992       FloatValArgs fa = s.arg2floatargs(ce[0]);
01993       FloatVarArgs fv = s.arg2floatvarargs(ce[1]);
01994       linear(s, fa, fv, frt, ce[2]->getFloat(), s.arg2BoolVar(ce[3]));
01995     }
01996     void p_float_lin_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
01997       p_float_lin_cmp(s,FRT_EQ,ce,ann);
01998     }
01999     void p_float_lin_eq_reif(FlatZincSpace& s, const ConExpr& ce,
02000                              AST::Node* ann) {
02001       p_float_lin_cmp_reif(s,FRT_EQ,ce,ann);
02002     }
02003     void p_float_lin_le(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
02004       p_float_lin_cmp(s,FRT_LQ,ce,ann);
02005     }
02006     void p_float_lin_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node* ann) {
02007       p_float_lin_cmp(s,FRT_LE,ce,ann);
02008     }
02009     void p_float_lin_le_reif(FlatZincSpace& s, const ConExpr& ce,
02010                              AST::Node* ann) {
02011       p_float_lin_cmp_reif(s,FRT_LQ,ce,ann);
02012     }
02013     void p_float_lin_lt_reif(FlatZincSpace& s, const ConExpr& ce,
02014                              AST::Node* ann) {
02015       p_float_lin_cmp_reif(s,FRT_LE,ce,ann);
02016     }
02017 
02018     void p_float_times(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02019       FloatVar x = s.arg2FloatVar(ce[0]);
02020       FloatVar y = s.arg2FloatVar(ce[1]);
02021       FloatVar z = s.arg2FloatVar(ce[2]);
02022       mult(s,x,y,z);
02023     }
02024 
02025     void p_float_div(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02026       FloatVar x = s.arg2FloatVar(ce[0]);
02027       FloatVar y = s.arg2FloatVar(ce[1]);
02028       FloatVar z = s.arg2FloatVar(ce[2]);
02029       div(s,x,y,z);
02030     }
02031 
02032     void p_float_plus(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02033       FloatVar x = s.arg2FloatVar(ce[0]);
02034       FloatVar y = s.arg2FloatVar(ce[1]);
02035       FloatVar z = s.arg2FloatVar(ce[2]);
02036       rel(s,x+y==z);
02037     }
02038 
02039     void p_float_sqrt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02040       FloatVar x = s.arg2FloatVar(ce[0]);
02041       FloatVar y = s.arg2FloatVar(ce[1]);
02042       sqrt(s,x,y);
02043     }
02044 
02045     void p_float_abs(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02046       FloatVar x = s.arg2FloatVar(ce[0]);
02047       FloatVar y = s.arg2FloatVar(ce[1]);
02048       abs(s,x,y);
02049     }
02050 
02051     void p_float_eq(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02052       FloatVar x = s.arg2FloatVar(ce[0]);
02053       FloatVar y = s.arg2FloatVar(ce[1]);
02054       rel(s,x,FRT_EQ,y);
02055     }
02056     void p_float_eq_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02057       FloatVar x = s.arg2FloatVar(ce[0]);
02058       FloatVar y = s.arg2FloatVar(ce[1]);
02059       BoolVar  b = s.arg2BoolVar(ce[2]);
02060       rel(s,x,FRT_EQ,y,b);
02061     }
02062     void p_float_le(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02063       FloatVar x = s.arg2FloatVar(ce[0]);
02064       FloatVar y = s.arg2FloatVar(ce[1]);
02065       rel(s,x,FRT_LQ,y);
02066     }
02067     void p_float_le_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02068       FloatVar x = s.arg2FloatVar(ce[0]);
02069       FloatVar y = s.arg2FloatVar(ce[1]);
02070       BoolVar  b = s.arg2BoolVar(ce[2]);
02071       rel(s,x,FRT_LQ,y,b);
02072     }
02073     void p_float_max(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02074       FloatVar x = s.arg2FloatVar(ce[0]);
02075       FloatVar y = s.arg2FloatVar(ce[1]);
02076       FloatVar z = s.arg2FloatVar(ce[2]);
02077       max(s,x,y,z);
02078     }
02079     void p_float_min(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02080       FloatVar x = s.arg2FloatVar(ce[0]);
02081       FloatVar y = s.arg2FloatVar(ce[1]);
02082       FloatVar z = s.arg2FloatVar(ce[2]);
02083       min(s,x,y,z);
02084     }
02085     void p_float_lt(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02086       FloatVar x = s.arg2FloatVar(ce[0]);
02087       FloatVar y = s.arg2FloatVar(ce[1]);
02088       rel(s, x, FRT_LQ, y);
02089       rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
02090     }
02091 
02092     void p_float_lt_reif(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02093       FloatVar x = s.arg2FloatVar(ce[0]);
02094       FloatVar y = s.arg2FloatVar(ce[1]);
02095       BoolVar b = s.arg2BoolVar(ce[2]);
02096       BoolVar b0(s,0,1);
02097       BoolVar b1(s,0,1);
02098       rel(s, b == (b0 && !b1));
02099       rel(s, x, FRT_LQ, y, b0);
02100       rel(s, x, FRT_EQ, y, b1);
02101     }
02102 
02103     void p_float_ne(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02104       FloatVar x = s.arg2FloatVar(ce[0]);
02105       FloatVar y = s.arg2FloatVar(ce[1]);
02106       rel(s, x, FRT_EQ, y, BoolVar(s,0,0));
02107     }
02108 
02109 #ifdef GECODE_HAS_MPFR
02110 #define P_FLOAT_OP(Op) \
02111     void p_float_ ## Op (FlatZincSpace& s, const ConExpr& ce, AST::Node*) {\
02112       FloatVar x = s.arg2FloatVar(ce[0]);\
02113       FloatVar y = s.arg2FloatVar(ce[1]);\
02114       Op(s,x,y);\
02115     }
02116     P_FLOAT_OP(acos)
02117     P_FLOAT_OP(asin)
02118     P_FLOAT_OP(atan)
02119     P_FLOAT_OP(cos)
02120     P_FLOAT_OP(exp)
02121     P_FLOAT_OP(sin)
02122     P_FLOAT_OP(tan)
02123     // P_FLOAT_OP(sinh)
02124     // P_FLOAT_OP(tanh)
02125     // P_FLOAT_OP(cosh)
02126 #undef P_FLOAT_OP
02127 
02128     void p_float_ln(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02129       FloatVar x = s.arg2FloatVar(ce[0]);
02130       FloatVar y = s.arg2FloatVar(ce[1]);
02131       log(s,x,y);
02132     }
02133     void p_float_log10(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02134       FloatVar x = s.arg2FloatVar(ce[0]);
02135       FloatVar y = s.arg2FloatVar(ce[1]);
02136       log(s,10.0,x,y);
02137     }
02138     void p_float_log2(FlatZincSpace& s, const ConExpr& ce, AST::Node*) {
02139       FloatVar x = s.arg2FloatVar(ce[0]);
02140       FloatVar y = s.arg2FloatVar(ce[1]);
02141       log(s,2.0,x,y);
02142     }
02143 
02144 #endif
02145 
02146     class FloatPoster {
02147     public:
02148       FloatPoster(void) {
02149         registry().add("int2float",&p_int2float);
02150         registry().add("float_abs",&p_float_abs);
02151         registry().add("float_sqrt",&p_float_sqrt);
02152         registry().add("float_eq",&p_float_eq);
02153         registry().add("float_eq_reif",&p_float_eq_reif);
02154         registry().add("float_le",&p_float_le);
02155         registry().add("float_le_reif",&p_float_le_reif);
02156         registry().add("float_lt",&p_float_lt);
02157         registry().add("float_lt_reif",&p_float_lt_reif);
02158         registry().add("float_ne",&p_float_ne);
02159         registry().add("float_times",&p_float_times);
02160         registry().add("float_div",&p_float_div);
02161         registry().add("float_plus",&p_float_plus);
02162         registry().add("float_max",&p_float_max);
02163         registry().add("float_min",&p_float_min);
02164 
02165         registry().add("float_lin_eq",&p_float_lin_eq);
02166         registry().add("float_lin_eq_reif",&p_float_lin_eq_reif);
02167         registry().add("float_lin_le",&p_float_lin_le);
02168         registry().add("float_lin_lt",&p_float_lin_lt);
02169         registry().add("float_lin_le_reif",&p_float_lin_le_reif);
02170         registry().add("float_lin_lt_reif",&p_float_lin_lt_reif);
02171 
02172 #ifdef GECODE_HAS_MPFR
02173         registry().add("float_acos",&p_float_acos);
02174         registry().add("float_asin",&p_float_asin);
02175         registry().add("float_atan",&p_float_atan);
02176         registry().add("float_cos",&p_float_cos);
02177         // registry().add("float_cosh",&p_float_cosh);
02178         registry().add("float_exp",&p_float_exp);
02179         registry().add("float_ln",&p_float_ln);
02180         registry().add("float_log10",&p_float_log10);
02181         registry().add("float_log2",&p_float_log2);
02182         registry().add("float_sin",&p_float_sin);
02183         // registry().add("float_sinh",&p_float_sinh);
02184         registry().add("float_tan",&p_float_tan);
02185         // registry().add("float_tanh",&p_float_tanh);
02186 #endif
02187       }
02188     } __float_poster;
02189 #endif
02190 
02191   }
02192 }}
02193 
02194 // STATISTICS: flatzinc-any