Generated on Fri Mar 20 15:55:56 2015 for Gecode by doxygen 1.6.3

registry.cpp

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