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

flatzinc.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  *     Gabriel Hjort Blindell <gabriel.hjort.blindell@gmail.com>
00008  *
00009  *  Copyright:
00010  *     Guido Tack, 2007-2012
00011  *     Gabriel Hjort Blindell, 2012
00012  *
00013  *  Last modified:
00014  *     $Date: 2015-03-19 11:47:57 +0100 (Thu, 19 Mar 2015) $ by $Author: tack $
00015  *     $Revision: 14463 $
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.hh>
00043 #include <gecode/flatzinc/registry.hh>
00044 #include <gecode/flatzinc/plugin.hh>
00045 
00046 #include <gecode/search.hh>
00047 
00048 #include <vector>
00049 #include <string>
00050 #include <sstream>
00051 #include <limits>
00052 using namespace std;
00053 
00054 namespace Gecode { namespace FlatZinc {
00055 
00068   class AuxVarBrancher : public Brancher {
00069   protected:
00071     bool done;
00073     AuxVarBrancher(Home home, TieBreak<IntVarBranch> int_varsel0,
00074                    IntValBranch int_valsel0,
00075                    TieBreak<IntVarBranch> bool_varsel0,
00076                    IntValBranch bool_valsel0
00077 #ifdef GECODE_HAS_SET_VARS
00078                    ,
00079                    SetVarBranch set_varsel0,
00080                    SetValBranch set_valsel0
00081 #endif
00082 #ifdef GECODE_HAS_FLOAT_VARS
00083                    ,
00084                    TieBreak<FloatVarBranch> float_varsel0,
00085                    FloatValBranch float_valsel0
00086 #endif
00087                    )
00088       : Brancher(home), done(false),
00089         int_varsel(int_varsel0), int_valsel(int_valsel0),
00090         bool_varsel(bool_varsel0), bool_valsel(bool_valsel0)
00091 #ifdef GECODE_HAS_SET_VARS
00092         , set_varsel(set_varsel0), set_valsel(set_valsel0)
00093 #endif
00094 #ifdef GECODE_HAS_FLOAT_VARS
00095         , float_varsel(float_varsel0), float_valsel(float_valsel0)
00096 #endif
00097         {}
00099     AuxVarBrancher(Space& home, bool share, AuxVarBrancher& b)
00100       : Brancher(home, share, b), done(b.done) {}
00101 
00103     class Choice : public Gecode::Choice {
00104     public:
00106       bool fail;
00108       Choice(const Brancher& b, bool fail0)
00109         : Gecode::Choice(b,1), fail(fail0) {}
00111       virtual size_t size(void) const {
00112         return sizeof(Choice);
00113       }
00115       virtual void archive(Archive& e) const {
00116         Gecode::Choice::archive(e);
00117         e.put(fail);
00118       }
00119     };
00120 
00121     TieBreak<IntVarBranch> int_varsel;
00122     IntValBranch int_valsel;
00123     TieBreak<IntVarBranch> bool_varsel;
00124     IntValBranch bool_valsel;
00125 #ifdef GECODE_HAS_SET_VARS
00126     SetVarBranch set_varsel;
00127     SetValBranch set_valsel;
00128 #endif
00129 #ifdef GECODE_HAS_FLOAT_VARS
00130     TieBreak<FloatVarBranch> float_varsel;
00131     FloatValBranch float_valsel;
00132 #endif
00133 
00134   public:
00136     virtual bool status(const Space& _home) const {
00137       if (done) return false;
00138       const FlatZincSpace& home = static_cast<const FlatZincSpace&>(_home);
00139       for (int i=0; i<home.iv_aux.size(); i++)
00140         if (!home.iv_aux[i].assigned()) return true;
00141       for (int i=0; i<home.bv_aux.size(); i++)
00142         if (!home.bv_aux[i].assigned()) return true;
00143 #ifdef GECODE_HAS_SET_VARS
00144       for (int i=0; i<home.sv_aux.size(); i++)
00145         if (!home.sv_aux[i].assigned()) return true;
00146 #endif
00147 #ifdef GECODE_HAS_FLOAT_VARS
00148       for (int i=0; i<home.fv_aux.size(); i++)
00149         if (!home.fv_aux[i].assigned()) return true;
00150 #endif
00151       // No non-assigned variables left
00152       return false;
00153     }
00155     virtual Choice* choice(Space& home) {
00156       done = true;
00157       FlatZincSpace& fzs = static_cast<FlatZincSpace&>(*home.clone());
00158       fzs.needAuxVars = false;
00159       branch(fzs,fzs.iv_aux,int_varsel,int_valsel);
00160       branch(fzs,fzs.bv_aux,bool_varsel,bool_valsel);
00161 #ifdef GECODE_HAS_SET_VARS
00162       branch(fzs,fzs.sv_aux,set_varsel,set_valsel);
00163 #endif
00164 #ifdef GECODE_HAS_FLOAT_VARS
00165       branch(fzs,fzs.fv_aux,float_varsel,float_valsel);
00166 #endif
00167       Search::Options opt; opt.clone = false;
00168       FlatZincSpace* sol = dfs(&fzs, opt);
00169       if (sol) {
00170         delete sol;
00171         return new Choice(*this,false);
00172       } else {
00173         return new Choice(*this,true);
00174       }
00175     }
00177     virtual Choice* choice(const Space&, Archive& e) {
00178       bool fail; e >> fail;
00179       return new Choice(*this, fail);
00180     }
00182     virtual ExecStatus commit(Space&, const Gecode::Choice& c, unsigned int) {
00183       return static_cast<const Choice&>(c).fail ? ES_FAILED : ES_OK;
00184     }
00186     virtual void print(const Space&, const Gecode::Choice& c, 
00187                        unsigned int,
00188                        std::ostream& o) const {
00189       o << "FlatZinc(" 
00190         << (static_cast<const Choice&>(c).fail ? "fail" : "ok")
00191         << ")";
00192     }
00194     virtual Actor* copy(Space& home, bool share) {
00195       return new (home) AuxVarBrancher(home, share, *this);
00196     }
00198     static void post(Home home,
00199                      TieBreak<IntVarBranch> int_varsel,
00200                      IntValBranch int_valsel,
00201                      TieBreak<IntVarBranch> bool_varsel,
00202                      IntValBranch bool_valsel
00203 #ifdef GECODE_HAS_SET_VARS
00204                      ,
00205                      SetVarBranch set_varsel,
00206                      SetValBranch set_valsel
00207 #endif
00208 #ifdef GECODE_HAS_FLOAT_VARS
00209                      ,
00210                      TieBreak<FloatVarBranch> float_varsel,
00211                      FloatValBranch float_valsel
00212 #endif
00213                    ) {
00214       (void) new (home) AuxVarBrancher(home, int_varsel, int_valsel,
00215                                        bool_varsel, bool_valsel
00216 #ifdef GECODE_HAS_SET_VARS
00217                                        , set_varsel, set_valsel
00218 #endif
00219 #ifdef GECODE_HAS_FLOAT_VARS
00220                                        , float_varsel, float_valsel
00221 #endif
00222                                        );
00223     }
00225     virtual size_t dispose(Space&) {
00226       return sizeof(*this);
00227     }      
00228   };
00229 
00230   class BranchInformationO : public SharedHandle::Object {
00231   private:
00232     struct BI {
00233       string r0;
00234       string r1;
00235       vector<string> n;
00236       BI(void) : r0(""), r1(""), n(0) {}
00237       BI(const string& r00, const string& r10, const vector<string>& n0)
00238         : r0(r00), r1(r10), n(n0) {}
00239     };
00240     vector<BI> v;
00241     BranchInformationO(vector<BI> v0) : v(v0) {}
00242   public:
00243     BranchInformationO(void) {}
00244     virtual ~BranchInformationO(void) {}
00245     virtual SharedHandle::Object* copy(void) const {
00246       return new BranchInformationO(v);
00247     }
00249     void add(const BrancherHandle& bh,
00250              const string& rel0,
00251              const string& rel1,
00252              const vector<string>& n) {
00253       v.resize(std::max(static_cast<unsigned int>(v.size()),bh.id()+1));
00254       v[bh.id()] = BI(rel0,rel1,n);
00255     }
00257     void print(const BrancherHandle& bh,
00258                int a, int i, int n, ostream& o) const {
00259       const BI& bi = v[bh.id()];
00260       o << bi.n[i] << " " << (a==0 ? bi.r0 : bi.r1) << " " << n;
00261     }
00262 #ifdef GECODE_HAS_FLOAT_VARS
00263     void print(const BrancherHandle& bh,
00264                int a, int i, const FloatNumBranch& nl, ostream& o) const {
00265       const BI& bi = v[bh.id()];
00266       o << bi.n[i] << " "
00267         << (((a == 0) == nl.l) ? "<=" : ">=") << nl.n;
00268     }
00269 #endif
00270   };
00271   
00272   BranchInformation::BranchInformation(void)
00273     : SharedHandle(NULL) {}
00274 
00275   BranchInformation::BranchInformation(const BranchInformation& bi)
00276     : SharedHandle(bi) {}
00277 
00278   void
00279   BranchInformation::init(void) {
00280     assert(object() == NULL);
00281     object(new BranchInformationO());
00282   }
00283 
00284   void
00285   BranchInformation::add(const BrancherHandle& bh,
00286                          const std::string& rel0,
00287                          const std::string& rel1,
00288                          const std::vector<std::string>& n) {
00289     static_cast<BranchInformationO*>(object())->add(bh,rel0,rel1,n);
00290   }
00291   void
00292   BranchInformation::print(const BrancherHandle& bh, int a, int i,
00293                            int n, std::ostream& o) const {
00294     static_cast<const BranchInformationO*>(object())->print(bh,a,i,n,o);
00295   }
00296 #ifdef GECODE_HAS_FLOAT_VARS
00297   void
00298   BranchInformation::print(const BrancherHandle& bh, int a, int i,
00299                            const FloatNumBranch& nl, std::ostream& o) const {
00300     static_cast<const BranchInformationO*>(object())->print(bh,a,i,nl,o);
00301   }
00302 #endif
00303   template<class Var>
00304   void varValPrint(const Space &home, const BrancherHandle& bh,
00305                    unsigned int a,
00306                    Var, int i, const int& n,
00307                    std::ostream& o) {
00308     static_cast<const FlatZincSpace&>(home).branchInfo.print(bh,a,i,n,o);
00309   }
00310 
00311 #ifdef GECODE_HAS_FLOAT_VARS
00312   void varValPrintF(const Space &home, const BrancherHandle& bh,
00313                     unsigned int a,
00314                     FloatVar, int i, const FloatNumBranch& nl,
00315                     std::ostream& o) {
00316     static_cast<const FlatZincSpace&>(home).branchInfo.print(bh,a,i,nl,o);
00317   }
00318 #endif
00319 
00320   FznRnd::FznRnd(unsigned int s) : random(s) {}
00321   
00322   unsigned int
00323   FznRnd::operator ()(unsigned int n) {
00324     Support::Lock lock(mutex);
00325     return random(n);
00326   }
00327 
00328   IntSet vs2is(IntVarSpec* vs) {
00329     if (vs->assigned) {
00330       return IntSet(vs->i,vs->i);
00331     }
00332     if (vs->domain()) {
00333       AST::SetLit* sl = vs->domain.some();
00334       if (sl->interval) {
00335         return IntSet(sl->min, sl->max);
00336       } else {
00337         int* newdom = heap.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
00338         for (int i=sl->s.size(); i--;)
00339           newdom[i] = sl->s[i];
00340         IntSet ret(newdom, sl->s.size());
00341         heap.free(newdom, static_cast<unsigned long int>(sl->s.size()));
00342         return ret;
00343       }
00344     }
00345     return IntSet(Int::Limits::min, Int::Limits::max);
00346   }
00347 
00348   int vs2bsl(BoolVarSpec* bs) {
00349     if (bs->assigned) {
00350       return bs->i;
00351     }
00352     if (bs->domain()) {
00353       AST::SetLit* sl = bs->domain.some();
00354       assert(sl->interval);
00355       return std::min(1, std::max(0, sl->min));
00356     }
00357     return 0;
00358   }
00359 
00360   int vs2bsh(BoolVarSpec* bs) {
00361     if (bs->assigned) {
00362       return bs->i;
00363     }
00364     if (bs->domain()) {
00365       AST::SetLit* sl = bs->domain.some();
00366       assert(sl->interval);
00367       return std::max(0, std::min(1, sl->max));
00368     }
00369     return 1;
00370   }
00371 
00372   TieBreak<IntVarBranch> ann2ivarsel(AST::Node* ann, Rnd rnd, double decay) {
00373     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00374       if (s->id == "input_order")
00375         return TieBreak<IntVarBranch>(INT_VAR_NONE());
00376       if (s->id == "first_fail")
00377         return TieBreak<IntVarBranch>(INT_VAR_SIZE_MIN());
00378       if (s->id == "anti_first_fail")
00379         return TieBreak<IntVarBranch>(INT_VAR_SIZE_MAX());
00380       if (s->id == "smallest")
00381         return TieBreak<IntVarBranch>(INT_VAR_MIN_MIN());
00382       if (s->id == "largest")
00383         return TieBreak<IntVarBranch>(INT_VAR_MAX_MAX());
00384       if (s->id == "occurrence")
00385         return TieBreak<IntVarBranch>(INT_VAR_DEGREE_MAX());
00386       if (s->id == "max_regret")
00387         return TieBreak<IntVarBranch>(INT_VAR_REGRET_MIN_MAX());
00388       if (s->id == "most_constrained")
00389         return TieBreak<IntVarBranch>(INT_VAR_SIZE_MIN(),
00390                                       INT_VAR_DEGREE_MAX());
00391       if (s->id == "random") {
00392         return TieBreak<IntVarBranch>(INT_VAR_RND(rnd));
00393       }
00394       if (s->id == "dom_w_deg") {
00395         return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MAX(decay));
00396       }
00397       if (s->id == "afc_min")
00398         return TieBreak<IntVarBranch>(INT_VAR_AFC_MIN(decay));
00399       if (s->id == "afc_max")
00400         return TieBreak<IntVarBranch>(INT_VAR_AFC_MAX(decay));
00401       if (s->id == "afc_size_min")
00402         return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MIN(decay));
00403       if (s->id == "afc_size_max") {
00404         return TieBreak<IntVarBranch>(INT_VAR_AFC_SIZE_MAX(decay));
00405       }
00406       if (s->id == "activity_min")
00407         return TieBreak<IntVarBranch>(INT_VAR_ACTIVITY_MIN(decay));
00408       if (s->id == "activity_max")
00409         return TieBreak<IntVarBranch>(INT_VAR_ACTIVITY_MAX(decay));
00410       if (s->id == "activity_size_min")
00411         return TieBreak<IntVarBranch>(INT_VAR_ACTIVITY_SIZE_MIN(decay));
00412       if (s->id == "activity_size_max")
00413         return TieBreak<IntVarBranch>(INT_VAR_ACTIVITY_SIZE_MAX(decay));
00414     }
00415     std::cerr << "Warning, ignored search annotation: ";
00416     ann->print(std::cerr);
00417     std::cerr << std::endl;
00418     return TieBreak<IntVarBranch>(INT_VAR_NONE());
00419   }
00420 
00421   IntValBranch ann2ivalsel(AST::Node* ann, std::string& r0, std::string& r1,
00422                            Rnd rnd) {
00423     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00424       if (s->id == "indomain_min") {
00425         r0 = "="; r1 = "!=";
00426         return INT_VAL_MIN();
00427       }
00428       if (s->id == "indomain_max") {
00429         r0 = "="; r1 = "!=";
00430         return INT_VAL_MAX();
00431       }
00432       if (s->id == "indomain_median") {
00433         r0 = "="; r1 = "!=";
00434         return INT_VAL_MED();
00435       }
00436       if (s->id == "indomain_split") {
00437         r0 = "<="; r1 = ">";
00438         return INT_VAL_SPLIT_MIN();
00439       }
00440       if (s->id == "indomain_reverse_split") {
00441         r0 = ">"; r1 = "<=";
00442         return INT_VAL_SPLIT_MAX();
00443       }
00444       if (s->id == "indomain_random") {
00445         r0 = "="; r1 = "!=";
00446         return INT_VAL_RND(rnd);
00447       }
00448       if (s->id == "indomain") {
00449         r0 = "="; r1 = "=";
00450         return INT_VALUES_MIN();
00451       }
00452       if (s->id == "indomain_middle") {
00453         std::cerr << "Warning, replacing unsupported annotation "
00454                   << "indomain_middle with indomain_median" << std::endl;
00455         r0 = "="; r1 = "!=";
00456         return INT_VAL_MED();
00457       }
00458       if (s->id == "indomain_interval") {
00459         std::cerr << "Warning, replacing unsupported annotation "
00460                   << "indomain_interval with indomain_split" << std::endl;
00461         r0 = "<="; r1 = ">";
00462         return INT_VAL_SPLIT_MIN();
00463       }
00464     }
00465     std::cerr << "Warning, ignored search annotation: ";
00466     ann->print(std::cerr);
00467     std::cerr << std::endl;
00468     r0 = "="; r1 = "!=";
00469     return INT_VAL_MIN();
00470   }
00471 
00472   IntAssign ann2asnivalsel(AST::Node* ann, Rnd rnd) {
00473     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00474       if (s->id == "indomain_min")
00475         return INT_ASSIGN_MIN();
00476       if (s->id == "indomain_max")
00477         return INT_ASSIGN_MAX();
00478       if (s->id == "indomain_median")
00479         return INT_ASSIGN_MED();
00480       if (s->id == "indomain_random") {
00481         return INT_ASSIGN_RND(rnd);
00482       }
00483     }
00484     std::cerr << "Warning, ignored search annotation: ";
00485     ann->print(std::cerr);
00486     std::cerr << std::endl;
00487     return INT_ASSIGN_MIN();
00488   }
00489 
00490 #ifdef GECODE_HAS_SET_VARS
00491   SetVarBranch ann2svarsel(AST::Node* ann, Rnd rnd, double decay) {
00492     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00493       if (s->id == "input_order")
00494         return SET_VAR_NONE();
00495       if (s->id == "first_fail")
00496         return SET_VAR_SIZE_MIN();
00497       if (s->id == "anti_first_fail")
00498         return SET_VAR_SIZE_MAX();
00499       if (s->id == "smallest")
00500         return SET_VAR_MIN_MIN();
00501       if (s->id == "largest")
00502         return SET_VAR_MAX_MAX();
00503       if (s->id == "afc_min")
00504         return SET_VAR_AFC_MIN(decay);
00505       if (s->id == "afc_max")
00506         return SET_VAR_AFC_MAX(decay);
00507       if (s->id == "afc_size_min")
00508         return SET_VAR_AFC_SIZE_MIN(decay);
00509       if (s->id == "afc_size_max")
00510         return SET_VAR_AFC_SIZE_MAX(decay);
00511       if (s->id == "activity_min")
00512         return SET_VAR_ACTIVITY_MIN(decay);
00513       if (s->id == "activity_max")
00514         return SET_VAR_ACTIVITY_MAX(decay);
00515       if (s->id == "activity_size_min")
00516         return SET_VAR_ACTIVITY_SIZE_MIN(decay);
00517       if (s->id == "activity_size_max")
00518         return SET_VAR_ACTIVITY_SIZE_MAX(decay);
00519       if (s->id == "random") {
00520         return SET_VAR_RND(rnd);
00521       }
00522     }
00523     std::cerr << "Warning, ignored search annotation: ";
00524     ann->print(std::cerr);
00525     std::cerr << std::endl;
00526     return SET_VAR_NONE();
00527   }
00528 
00529   SetValBranch ann2svalsel(AST::Node* ann, std::string r0, std::string r1,
00530                            Rnd rnd) {
00531     (void) rnd;
00532     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00533       if (s->id == "indomain_min") {
00534         r0 = "in"; r1 = "not in";
00535         return SET_VAL_MIN_INC();
00536       }
00537       if (s->id == "indomain_max") {
00538         r0 = "in"; r1 = "not in";
00539         return SET_VAL_MAX_INC();
00540       }
00541       if (s->id == "outdomain_min") {
00542         r1 = "in"; r0 = "not in";
00543         return SET_VAL_MIN_EXC();
00544       }
00545       if (s->id == "outdomain_max") {
00546         r1 = "in"; r0 = "not in";
00547         return SET_VAL_MAX_EXC();
00548       }
00549     }
00550     std::cerr << "Warning, ignored search annotation: ";
00551     ann->print(std::cerr);
00552     std::cerr << std::endl;
00553     r0 = "in"; r1 = "not in";
00554     return SET_VAL_MIN_INC();
00555   }
00556 #endif
00557 
00558 #ifdef GECODE_HAS_FLOAT_VARS
00559   TieBreak<FloatVarBranch> ann2fvarsel(AST::Node* ann, Rnd rnd,
00560                                        double decay) {
00561     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00562       if (s->id == "input_order")
00563         return TieBreak<FloatVarBranch>(FLOAT_VAR_NONE());
00564       if (s->id == "first_fail")
00565         return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MIN());
00566       if (s->id == "anti_first_fail")
00567         return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MAX());
00568       if (s->id == "smallest")
00569         return TieBreak<FloatVarBranch>(FLOAT_VAR_MIN_MIN());
00570       if (s->id == "largest")
00571         return TieBreak<FloatVarBranch>(FLOAT_VAR_MAX_MAX());
00572       if (s->id == "occurrence")
00573         return TieBreak<FloatVarBranch>(FLOAT_VAR_DEGREE_MAX());
00574       if (s->id == "most_constrained")
00575         return TieBreak<FloatVarBranch>(FLOAT_VAR_SIZE_MIN(),
00576                                         FLOAT_VAR_DEGREE_MAX());
00577       if (s->id == "random") {
00578         return TieBreak<FloatVarBranch>(FLOAT_VAR_RND(rnd));
00579       }
00580       if (s->id == "afc_min")
00581         return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_MIN(decay));
00582       if (s->id == "afc_max")
00583         return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_MAX(decay));
00584       if (s->id == "afc_size_min")
00585         return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_SIZE_MIN(decay));
00586       if (s->id == "afc_size_max")
00587         return TieBreak<FloatVarBranch>(FLOAT_VAR_AFC_SIZE_MAX(decay));
00588       if (s->id == "activity_min")
00589         return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTIVITY_MIN(decay));
00590       if (s->id == "activity_max")
00591         return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTIVITY_MAX(decay));
00592       if (s->id == "activity_size_min")
00593         return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTIVITY_SIZE_MIN(decay));
00594       if (s->id == "activity_size_max")
00595         return TieBreak<FloatVarBranch>(FLOAT_VAR_ACTIVITY_SIZE_MAX(decay));
00596     }
00597     std::cerr << "Warning, ignored search annotation: ";
00598     ann->print(std::cerr);
00599     std::cerr << std::endl;
00600     return TieBreak<FloatVarBranch>(FLOAT_VAR_NONE());
00601   }
00602 
00603   FloatValBranch ann2fvalsel(AST::Node* ann, std::string r0, std::string r1) {
00604     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00605       if (s->id == "indomain_split") {
00606         r0 = "<="; r1 = ">";
00607         return FLOAT_VAL_SPLIT_MIN();
00608       }
00609       if (s->id == "indomain_reverse_split") {
00610         r1 = "<="; r0 = ">";
00611         return FLOAT_VAL_SPLIT_MAX();
00612       }
00613     }
00614     std::cerr << "Warning, ignored search annotation: ";
00615     ann->print(std::cerr);
00616     std::cerr << std::endl;
00617     r0 = "<="; r1 = ">";
00618     return FLOAT_VAL_SPLIT_MIN();
00619   }
00620 
00621 #endif
00622 
00623   FlatZincSpace::FlatZincSpace(bool share, FlatZincSpace& f)
00624     : Space(share, f), _random(f._random),
00625       _solveAnnotations(NULL), iv_boolalias(NULL),
00626 #ifdef GECODE_HAS_FLOAT_VARS
00627       step(f.step),
00628 #endif
00629       needAuxVars(f.needAuxVars) {
00630       _optVar = f._optVar;
00631       _optVarIsInt = f._optVarIsInt;
00632       _method = f._method;
00633       _lns = f._lns;
00634       branchInfo.update(*this, share, f.branchInfo);
00635       iv.update(*this, share, f.iv);
00636       iv_lns.update(*this, share, f.iv_lns);
00637       intVarCount = f.intVarCount;
00638       
00639       if (needAuxVars) {
00640         IntVarArgs iva;
00641         for (int i=0; i<f.iv_aux.size(); i++) {
00642           if (!f.iv_aux[i].assigned()) {
00643             iva << IntVar();
00644             iva[iva.size()-1].update(*this, share, f.iv_aux[i]);
00645           }
00646         }
00647         iv_aux = IntVarArray(*this, iva);
00648       }
00649       
00650       bv.update(*this, share, f.bv);
00651       boolVarCount = f.boolVarCount;
00652       if (needAuxVars) {
00653         BoolVarArgs bva;
00654         for (int i=0; i<f.bv_aux.size(); i++) {
00655           if (!f.bv_aux[i].assigned()) {
00656             bva << BoolVar();
00657             bva[bva.size()-1].update(*this, share, f.bv_aux[i]);
00658           }
00659         }
00660         bv_aux = BoolVarArray(*this, bva);
00661       }
00662 
00663 #ifdef GECODE_HAS_SET_VARS
00664       sv.update(*this, share, f.sv);
00665       setVarCount = f.setVarCount;
00666       if (needAuxVars) {
00667         SetVarArgs sva;
00668         for (int i=0; i<f.sv_aux.size(); i++) {
00669           if (!f.sv_aux[i].assigned()) {
00670             sva << SetVar();
00671             sva[sva.size()-1].update(*this, share, f.sv_aux[i]);
00672           }
00673         }
00674         sv_aux = SetVarArray(*this, sva);
00675       }
00676 #endif
00677 #ifdef GECODE_HAS_FLOAT_VARS
00678       fv.update(*this, share, f.fv);
00679       floatVarCount = f.floatVarCount;
00680       if (needAuxVars) {
00681         FloatVarArgs fva;
00682         for (int i=0; i<f.fv_aux.size(); i++) {
00683           if (!f.fv_aux[i].assigned()) {
00684             fva << FloatVar();
00685             fva[fva.size()-1].update(*this, share, f.fv_aux[i]);
00686           }
00687         }
00688         fv_aux = FloatVarArray(*this, fva);
00689       }
00690 #endif
00691     }
00692   
00693   FlatZincSpace::FlatZincSpace(FznRnd* random)
00694   : intVarCount(-1), boolVarCount(-1), floatVarCount(-1), setVarCount(-1),
00695     _optVar(-1), _optVarIsInt(true), _lns(0), _random(random),
00696     _solveAnnotations(NULL), needAuxVars(true) {
00697     branchInfo.init();
00698   }
00699 
00700   void
00701   FlatZincSpace::init(int intVars, int boolVars,
00702                       int setVars, int floatVars) {
00703     (void) setVars;
00704     (void) floatVars;
00705 
00706     intVarCount = 0;
00707     iv = IntVarArray(*this, intVars);
00708     iv_introduced = std::vector<bool>(2*intVars);
00709     iv_boolalias = alloc<int>(intVars+(intVars==0?1:0));
00710     boolVarCount = 0;
00711     bv = BoolVarArray(*this, boolVars);
00712     bv_introduced = std::vector<bool>(2*boolVars);
00713 #ifdef GECODE_HAS_SET_VARS
00714     setVarCount = 0;
00715     sv = SetVarArray(*this, setVars);
00716     sv_introduced = std::vector<bool>(2*setVars);
00717 #endif
00718 #ifdef GECODE_HAS_FLOAT_VARS
00719     floatVarCount = 0;
00720     fv = FloatVarArray(*this, floatVars);
00721     fv_introduced = std::vector<bool>(2*floatVars);
00722 #endif
00723   }
00724 
00725   void
00726   FlatZincSpace::newIntVar(IntVarSpec* vs) {
00727     if (vs->alias) {
00728       iv[intVarCount++] = iv[vs->i];
00729     } else {
00730       IntSet dom(vs2is(vs));
00731       if (dom.size()==0) {
00732         fail();
00733         return;
00734       } else {
00735         iv[intVarCount++] = IntVar(*this, dom);
00736       }
00737     }
00738     iv_introduced[2*(intVarCount-1)] = vs->introduced;
00739     iv_introduced[2*(intVarCount-1)+1] = vs->funcDep;
00740     iv_boolalias[intVarCount-1] = -1;
00741   }
00742 
00743   void
00744   FlatZincSpace::aliasBool2Int(int iv, int bv) {
00745     iv_boolalias[iv] = bv;
00746   }
00747   int
00748   FlatZincSpace::aliasBool2Int(int iv) {
00749     return iv_boolalias[iv];
00750   }
00751 
00752   void
00753   FlatZincSpace::newBoolVar(BoolVarSpec* vs) {
00754     if (vs->alias) {
00755       bv[boolVarCount++] = bv[vs->i];
00756     } else {
00757       bv[boolVarCount++] = BoolVar(*this, vs2bsl(vs), vs2bsh(vs));
00758     }
00759     bv_introduced[2*(boolVarCount-1)] = vs->introduced;
00760     bv_introduced[2*(boolVarCount-1)+1] = vs->funcDep;
00761   }
00762 
00763 #ifdef GECODE_HAS_SET_VARS
00764   void
00765   FlatZincSpace::newSetVar(SetVarSpec* vs) {
00766     if (vs->alias) {
00767       sv[setVarCount++] = sv[vs->i];
00768     } else if (vs->assigned) {
00769       assert(vs->upperBound());
00770       AST::SetLit* vsv = vs->upperBound.some();
00771       if (vsv->interval) {
00772         IntSet d(vsv->min, vsv->max);
00773         sv[setVarCount++] = SetVar(*this, d, d);
00774       } else {
00775         int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00776         for (int i=vsv->s.size(); i--; )
00777           is[i] = vsv->s[i];
00778         IntSet d(is, vsv->s.size());
00779         heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00780         sv[setVarCount++] = SetVar(*this, d, d);
00781       }
00782     } else if (vs->upperBound()) {
00783       AST::SetLit* vsv = vs->upperBound.some();
00784       if (vsv->interval) {
00785         IntSet d(vsv->min, vsv->max);
00786         sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00787       } else {
00788         int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00789         for (int i=vsv->s.size(); i--; )
00790           is[i] = vsv->s[i];
00791         IntSet d(is, vsv->s.size());
00792         heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00793         sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00794       }
00795     } else {
00796       sv[setVarCount++] = SetVar(*this, IntSet::empty,
00797                                  IntSet(Set::Limits::min, 
00798                                         Set::Limits::max));
00799     }
00800     sv_introduced[2*(setVarCount-1)] = vs->introduced;
00801     sv_introduced[2*(setVarCount-1)+1] = vs->funcDep;
00802   }
00803 #else
00804   void
00805   FlatZincSpace::newSetVar(SetVarSpec*) {
00806     throw FlatZinc::Error("Gecode", "set variables not supported");
00807   }
00808 #endif
00809 
00810 #ifdef GECODE_HAS_FLOAT_VARS
00811   void
00812   FlatZincSpace::newFloatVar(FloatVarSpec* vs) {
00813     if (vs->alias) {
00814       fv[floatVarCount++] = fv[vs->i];
00815     } else {
00816       double dmin, dmax;
00817       if (vs->domain()) {
00818         dmin = vs->domain.some().first;
00819         dmax = vs->domain.some().second;
00820         if (dmin > dmax) {
00821           fail();
00822           return;
00823         }
00824       } else {
00825         dmin = Float::Limits::min;
00826         dmax = Float::Limits::max;
00827       }
00828       fv[floatVarCount++] = FloatVar(*this, dmin, dmax);
00829     }
00830     fv_introduced[2*(floatVarCount-1)] = vs->introduced;
00831     fv_introduced[2*(floatVarCount-1)+1] = vs->funcDep;
00832   }
00833 #else
00834   void
00835   FlatZincSpace::newFloatVar(FloatVarSpec*) {
00836     throw FlatZinc::Error("Gecode", "float variables not supported");
00837   }
00838 #endif
00839 
00840   namespace {
00841     struct ConExprOrder {
00842       bool operator() (ConExpr* ce0, ConExpr* ce1) {
00843         return ce0->args->a.size() < ce1->args->a.size();
00844       }
00845     };
00846   }
00847 
00848   void
00849   FlatZincSpace::postConstraints(std::vector<ConExpr*>& ces) {
00850     ConExprOrder ceo;
00851     std::sort(ces.begin(), ces.end(), ceo);
00852     
00853     for (unsigned int i=0; i<ces.size(); i++) {
00854       const ConExpr& ce = *ces[i];
00855       try {
00856         registry().post(*this, ce);
00857       } catch (Gecode::Exception& e) {
00858         throw FlatZinc::Error("Gecode", e.what());
00859       } catch (AST::TypeError& e) {
00860         throw FlatZinc::Error("Type error", e.what());
00861       }
00862       delete ces[i];
00863       ces[i] = NULL;
00864     }
00865   }
00866 
00867   void flattenAnnotations(AST::Array* ann, std::vector<AST::Node*>& out) {
00868       for (unsigned int i=0; i<ann->a.size(); i++) {
00869         if (ann->a[i]->isCall("seq_search")) {
00870           AST::Call* c = ann->a[i]->getCall();
00871           if (c->args->isArray())
00872             flattenAnnotations(c->args->getArray(), out);
00873           else
00874             out.push_back(c->args);
00875         } else {
00876           out.push_back(ann->a[i]);
00877         }
00878       }
00879   }
00880 
00881   void
00882   FlatZincSpace::createBranchers(AST::Node* ann, int seed, double decay,
00883                                  bool ignoreUnknown,
00884                                  std::ostream& err) {
00885     Rnd rnd(static_cast<unsigned int>(seed));
00886     TieBreak<IntVarBranch> def_int_varsel = INT_VAR_AFC_SIZE_MAX(0.99);
00887     IntValBranch def_int_valsel = INT_VAL_MIN();
00888     TieBreak<IntVarBranch> def_bool_varsel = INT_VAR_AFC_MAX(0.99);
00889     IntValBranch def_bool_valsel = INT_VAL_MIN();
00890 #ifdef GECODE_HAS_SET_VARS
00891     SetVarBranch def_set_varsel = SET_VAR_AFC_SIZE_MAX(0.99);
00892     SetValBranch def_set_valsel = SET_VAL_MIN_INC();
00893 #endif
00894 #ifdef GECODE_HAS_FLOAT_VARS
00895     TieBreak<FloatVarBranch> def_float_varsel = FLOAT_VAR_SIZE_MIN();
00896     FloatValBranch def_float_valsel = FLOAT_VAL_SPLIT_MIN();
00897 #endif
00898 
00899     std::vector<bool> iv_searched(iv.size());
00900     for (unsigned int i=iv.size(); i--;)
00901       iv_searched[i] = false;
00902     std::vector<bool> bv_searched(bv.size());
00903     for (unsigned int i=bv.size(); i--;)
00904       bv_searched[i] = false;
00905 #ifdef GECODE_HAS_SET_VARS
00906     std::vector<bool> sv_searched(sv.size());
00907     for (unsigned int i=sv.size(); i--;)
00908       sv_searched[i] = false;
00909 #endif
00910 #ifdef GECODE_HAS_FLOAT_VARS
00911     std::vector<bool> fv_searched(fv.size());
00912     for (unsigned int i=fv.size(); i--;)
00913       fv_searched[i] = false;
00914 #endif
00915 
00916     _lns = 0;
00917     if (ann) {
00918       std::vector<AST::Node*> flatAnn;
00919       if (ann->isArray()) {
00920         flattenAnnotations(ann->getArray()  , flatAnn);
00921       } else {
00922         flatAnn.push_back(ann);
00923       }
00924 
00925       for (unsigned int i=0; i<flatAnn.size(); i++) {
00926         if (flatAnn[i]->isCall("relax_and_reconstruct")) {
00927           if (_lns != 0)
00928             throw FlatZinc::Error("FlatZinc",
00929             "Only one relax_and_reconstruct annotation allowed");
00930           AST::Call *call = flatAnn[i]->getCall("relax_and_reconstruct");
00931           AST::Array *args = call->getArgs(2);
00932           _lns = args->a[1]->getInt();
00933           AST::Array *vars = args->a[0]->getArray();
00934           int k=vars->a.size();
00935           for (int i=vars->a.size(); i--;)
00936             if (vars->a[i]->isInt())
00937               k--;
00938           iv_lns = IntVarArray(*this, k);
00939           k = 0;
00940           for (unsigned int i=0; i<vars->a.size(); i++) {
00941             if (vars->a[i]->isInt())
00942               continue;
00943             iv_lns[k++] = iv[vars->a[i]->getIntVar()];
00944           }
00945         } else if (flatAnn[i]->isCall("gecode_search")) {
00946           AST::Call* c = flatAnn[i]->getCall();
00947           branchWithPlugin(c->args);
00948         } else if (flatAnn[i]->isCall("int_search")) {
00949           AST::Call *call = flatAnn[i]->getCall("int_search");
00950           AST::Array *args = call->getArgs(4);
00951           AST::Array *vars = args->a[0]->getArray();
00952           int k=vars->a.size();
00953           for (int i=vars->a.size(); i--;)
00954             if (vars->a[i]->isInt())
00955               k--;
00956           IntVarArgs va(k);
00957           vector<string> names;
00958           k=0;
00959           for (unsigned int i=0; i<vars->a.size(); i++) {
00960             if (vars->a[i]->isInt())
00961               continue;
00962             va[k++] = iv[vars->a[i]->getIntVar()];
00963             iv_searched[vars->a[i]->getIntVar()] = true;
00964             names.push_back(vars->a[i]->getVarName());
00965           }
00966           std::string r0, r1;
00967           BrancherHandle bh = branch(*this, va, 
00968             ann2ivarsel(args->a[1],rnd,decay), 
00969             ann2ivalsel(args->a[2],r0,r1,rnd),
00970             NULL,
00971             &varValPrint<IntVar>);
00972           branchInfo.add(bh,r0,r1,names);
00973         } else if (flatAnn[i]->isCall("int_assign")) {
00974           AST::Call *call = flatAnn[i]->getCall("int_assign");
00975           AST::Array *args = call->getArgs(2);
00976           AST::Array *vars = args->a[0]->getArray();
00977           int k=vars->a.size();
00978           for (int i=vars->a.size(); i--;)
00979             if (vars->a[i]->isInt())
00980               k--;
00981           IntVarArgs va(k);
00982           k=0;
00983           for (unsigned int i=0; i<vars->a.size(); i++) {
00984             if (vars->a[i]->isInt())
00985               continue;
00986             va[k++] = iv[vars->a[i]->getIntVar()];
00987             iv_searched[vars->a[i]->getIntVar()] = true;
00988           }
00989           assign(*this, va, ann2asnivalsel(args->a[1],rnd), NULL,
00990                 &varValPrint<IntVar>);
00991         } else if (flatAnn[i]->isCall("bool_search")) {
00992           AST::Call *call = flatAnn[i]->getCall("bool_search");
00993           AST::Array *args = call->getArgs(4);
00994           AST::Array *vars = args->a[0]->getArray();
00995           int k=vars->a.size();
00996           for (int i=vars->a.size(); i--;)
00997             if (vars->a[i]->isBool())
00998               k--;
00999           BoolVarArgs va(k);
01000           k=0;
01001           vector<string> names;
01002           for (unsigned int i=0; i<vars->a.size(); i++) {
01003             if (vars->a[i]->isBool())
01004               continue;
01005             va[k++] = bv[vars->a[i]->getBoolVar()];
01006             bv_searched[vars->a[i]->getBoolVar()] = true;
01007             names.push_back(vars->a[i]->getVarName());
01008           }
01009           
01010           std::string r0, r1;
01011           BrancherHandle bh = branch(*this, va, 
01012             ann2ivarsel(args->a[1],rnd,decay), 
01013             ann2ivalsel(args->a[2],r0,r1,rnd), NULL,
01014             &varValPrint<BoolVar>);
01015           branchInfo.add(bh,r0,r1,names);
01016         } else if (flatAnn[i]->isCall("int_default_search")) {
01017           AST::Call *call = flatAnn[i]->getCall("int_default_search");
01018           AST::Array *args = call->getArgs(2);
01019           def_int_varsel = ann2ivarsel(args->a[0],rnd,decay);
01020           std::string r0;
01021           def_int_valsel = ann2ivalsel(args->a[1],r0,r0,rnd);
01022         } else if (flatAnn[i]->isCall("bool_default_search")) {
01023           AST::Call *call = flatAnn[i]->getCall("bool_default_search");
01024           AST::Array *args = call->getArgs(2);
01025           def_bool_varsel = ann2ivarsel(args->a[0],rnd,decay);
01026           std::string r0;
01027           def_bool_valsel = ann2ivalsel(args->a[1],r0,r0,rnd);
01028         } else if (flatAnn[i]->isCall("set_search")) {
01029 #ifdef GECODE_HAS_SET_VARS
01030           AST::Call *call = flatAnn[i]->getCall("set_search");
01031           AST::Array *args = call->getArgs(4);
01032           AST::Array *vars = args->a[0]->getArray();
01033           int k=vars->a.size();
01034           for (int i=vars->a.size(); i--;)
01035             if (vars->a[i]->isSet())
01036               k--;
01037           SetVarArgs va(k);
01038           k=0;
01039           vector<string> names;
01040           for (unsigned int i=0; i<vars->a.size(); i++) {
01041             if (vars->a[i]->isSet())
01042               continue;
01043             va[k++] = sv[vars->a[i]->getSetVar()];
01044             sv_searched[vars->a[i]->getSetVar()] = true;
01045             names.push_back(vars->a[i]->getVarName());
01046           }
01047           std::string r0, r1;
01048           BrancherHandle bh = branch(*this, va, 
01049             ann2svarsel(args->a[1],rnd,decay), 
01050             ann2svalsel(args->a[2],r0,r1,rnd),
01051             NULL,
01052             &varValPrint<SetVar>);
01053           branchInfo.add(bh,r0,r1,names);
01054 #else
01055           if (!ignoreUnknown) {
01056             err << "Warning, ignored search annotation: ";
01057             flatAnn[i]->print(err);
01058             err << std::endl;
01059           }
01060 #endif
01061         } else if (flatAnn[i]->isCall("set_default_search")) {
01062 #ifdef GECODE_HAS_SET_VARS
01063           AST::Call *call = flatAnn[i]->getCall("set_default_search");
01064           AST::Array *args = call->getArgs(2);
01065           def_set_varsel = ann2svarsel(args->a[0],rnd,decay);
01066           std::string r0;
01067           def_set_valsel = ann2svalsel(args->a[1],r0,r0,rnd);
01068 #else
01069           if (!ignoreUnknown) {
01070             err << "Warning, ignored search annotation: ";
01071             flatAnn[i]->print(err);
01072             err << std::endl;
01073           }
01074 #endif
01075         } else if (flatAnn[i]->isCall("float_default_search")) {
01076 #ifdef GECODE_HAS_FLOAT_VARS
01077           AST::Call *call = flatAnn[i]->getCall("float_default_search");
01078           AST::Array *args = call->getArgs(2);
01079           def_float_varsel = ann2fvarsel(args->a[0],rnd,decay);
01080           std::string r0;
01081           def_float_valsel = ann2fvalsel(args->a[1],r0,r0);
01082 #else
01083           if (!ignoreUnknown) {
01084             err << "Warning, ignored search annotation: ";
01085             flatAnn[i]->print(err);
01086             err << std::endl;
01087           }
01088 #endif
01089         } else if (flatAnn[i]->isCall("float_search")) {
01090 #ifdef GECODE_HAS_FLOAT_VARS
01091           AST::Call *call = flatAnn[i]->getCall("float_search");
01092           AST::Array *args = call->getArgs(5);
01093           AST::Array *vars = args->a[0]->getArray();
01094           int k=vars->a.size();
01095           for (int i=vars->a.size(); i--;)
01096             if (vars->a[i]->isFloat())
01097               k--;
01098           FloatVarArgs va(k);
01099           k=0;
01100           vector<string> names;
01101           for (unsigned int i=0; i<vars->a.size(); i++) {
01102             if (vars->a[i]->isFloat())
01103               continue;
01104             va[k++] = fv[vars->a[i]->getFloatVar()];
01105             fv_searched[vars->a[i]->getFloatVar()] = true;
01106             names.push_back(vars->a[i]->getVarName());
01107           }
01108           std::string r0, r1;
01109           BrancherHandle bh = branch(*this, va,
01110             ann2fvarsel(args->a[2],rnd,decay), 
01111             ann2fvalsel(args->a[3],r0,r1),
01112             NULL,
01113             &varValPrintF);
01114           branchInfo.add(bh,r0,r1,names);
01115 #else
01116           if (!ignoreUnknown) {
01117             err << "Warning, ignored search annotation: ";
01118             flatAnn[i]->print(err);
01119             err << std::endl;
01120           }
01121 #endif
01122         } else {
01123           if (!ignoreUnknown) {
01124             err << "Warning, ignored search annotation: ";
01125             flatAnn[i]->print(err);
01126             err << std::endl;
01127           }
01128         }
01129       }
01130     }
01131     int introduced = 0;
01132     int funcdep = 0;
01133     int searched = 0;
01134     for (int i=iv.size(); i--;) {
01135       if (iv_searched[i] || (_method != SAT && _optVarIsInt && _optVar==i)) {
01136         searched++;
01137       } else if (iv_introduced[2*i]) {
01138         if (iv_introduced[2*i+1]) {
01139           funcdep++;
01140         } else {
01141           introduced++;
01142         }
01143       }
01144     }
01145     IntVarArgs iv_sol(iv.size()-(introduced+funcdep+searched));
01146     IntVarArgs iv_tmp(introduced);
01147     for (int i=iv.size(), j=0, k=0; i--;) {
01148       if (iv_searched[i] || (_method != SAT && _optVarIsInt && _optVar==i))
01149         continue;
01150       if (iv_introduced[2*i]) {
01151         if (!iv_introduced[2*i+1]) {
01152           iv_tmp[j++] = iv[i];
01153         }
01154       } else {
01155         iv_sol[k++] = iv[i];
01156       }
01157     }
01158 
01159     introduced = 0;
01160     funcdep = 0;
01161     searched = 0;
01162     for (int i=bv.size(); i--;) {
01163       if (bv_searched[i]) {
01164         searched++;
01165       } else if (bv_introduced[2*i]) {
01166         if (bv_introduced[2*i+1]) {
01167           funcdep++;
01168         } else {
01169           introduced++;
01170         }
01171       }
01172     }
01173     BoolVarArgs bv_sol(bv.size()-(introduced+funcdep+searched));
01174     BoolVarArgs bv_tmp(introduced);
01175     for (int i=bv.size(), j=0, k=0; i--;) {
01176       if (bv_searched[i])
01177         continue;
01178       if (bv_introduced[2*i]) {
01179         if (!bv_introduced[2*i+1]) {
01180           bv_tmp[j++] = bv[i];
01181         }
01182       } else {
01183         bv_sol[k++] = bv[i];
01184       }
01185     }
01186 
01187     if (iv_sol.size() > 0) {
01188       branch(*this, iv_sol, def_int_varsel, def_int_valsel);
01189     }
01190     if (bv_sol.size() > 0)
01191       branch(*this, bv_sol, def_bool_varsel, def_bool_valsel);
01192 #ifdef GECODE_HAS_FLOAT_VARS
01193     introduced = 0;
01194     funcdep = 0;
01195     searched = 0;
01196     for (int i=fv.size(); i--;) {
01197       if (fv_searched[i] || (_method != SAT && !_optVarIsInt && _optVar==i)) {
01198         searched++;
01199       } else if (fv_introduced[2*i]) {
01200         if (fv_introduced[2*i+1]) {
01201           funcdep++;
01202         } else {
01203           introduced++;
01204         }
01205       }
01206     }
01207     FloatVarArgs fv_sol(fv.size()-(introduced+funcdep+searched));
01208     FloatVarArgs fv_tmp(introduced);
01209     for (int i=fv.size(), j=0, k=0; i--;) {
01210       if (fv_searched[i] || (_method != SAT && !_optVarIsInt && _optVar==i))
01211         continue;
01212       if (fv_introduced[2*i]) {
01213         if (!fv_introduced[2*i+1]) {
01214           fv_tmp[j++] = fv[i];
01215         }
01216       } else {
01217         fv_sol[k++] = fv[i];
01218       }
01219     }
01220 
01221     if (fv_sol.size() > 0)
01222       branch(*this, fv_sol, def_float_varsel, def_float_valsel);
01223 #endif
01224 #ifdef GECODE_HAS_SET_VARS
01225     introduced = 0;
01226     funcdep = 0;
01227     searched = 0;
01228     for (int i=sv.size(); i--;) {
01229       if (sv_searched[i]) {
01230         searched++;
01231       } else if (sv_introduced[2*i]) {
01232         if (sv_introduced[2*i+1]) {
01233           funcdep++;
01234         } else {
01235           introduced++;
01236         }
01237       }
01238     }
01239     SetVarArgs sv_sol(sv.size()-(introduced+funcdep+searched));
01240     SetVarArgs sv_tmp(introduced);
01241     for (int i=sv.size(), j=0, k=0; i--;) {
01242       if (sv_searched[i])
01243         continue;
01244       if (sv_introduced[2*i]) {
01245         if (!sv_introduced[2*i+1]) {
01246           sv_tmp[j++] = sv[i];
01247         }
01248       } else {
01249         sv_sol[k++] = sv[i];
01250       }
01251     }
01252 
01253     if (sv_sol.size() > 0)
01254       branch(*this, sv_sol, def_set_varsel, def_set_valsel);
01255 #endif
01256     iv_aux = IntVarArray(*this, iv_tmp);
01257     bv_aux = BoolVarArray(*this, bv_tmp);
01258     int n_aux = iv_aux.size() + bv_aux.size();
01259 #ifdef GECODE_HAS_SET_VARS
01260     sv_aux = SetVarArray(*this, sv_tmp);
01261     n_aux += sv_aux.size();
01262 #endif
01263 #ifdef GECODE_HAS_FLOAT_VARS
01264     fv_aux = FloatVarArray(*this, fv_tmp);
01265     n_aux += fv_aux.size();
01266 #endif
01267 
01268     if (_method == MIN) {
01269       if (_optVarIsInt) {
01270         branch(*this, iv[_optVar], INT_VAL_MIN());
01271       } else {
01272 #ifdef GECODE_HAS_FLOAT_VARS
01273         branch(*this, fv[_optVar], FLOAT_VAL_SPLIT_MIN());
01274 #endif
01275       }
01276     } else if (_method == MAX) {
01277       if (_optVarIsInt) {
01278         branch(*this, iv[_optVar], INT_VAL_MAX());
01279       } else {
01280 #ifdef GECODE_HAS_FLOAT_VARS
01281         branch(*this, fv[_optVar], FLOAT_VAL_SPLIT_MAX());
01282 #endif
01283       }
01284     }
01285 
01286     if (n_aux > 0) {
01287       if (_method == SAT) {
01288         AuxVarBrancher::post(*this, def_int_varsel, def_int_valsel,
01289                              def_bool_varsel, def_bool_valsel
01290 #ifdef GECODE_HAS_SET_VARS
01291                              , def_set_varsel, def_set_valsel
01292 #endif
01293 #ifdef GECODE_HAS_FLOAT_VARS
01294                              , def_float_varsel, def_float_valsel
01295 #endif
01296                              );
01297       } else {
01298         branch(*this,iv_aux,def_int_varsel,def_int_valsel);
01299         branch(*this,bv_aux,def_bool_varsel,def_bool_valsel);
01300   #ifdef GECODE_HAS_SET_VARS
01301         branch(*this,sv_aux,def_set_varsel,def_set_valsel);
01302   #endif
01303   #ifdef GECODE_HAS_FLOAT_VARS
01304         branch(*this,fv_aux,def_float_varsel,def_float_valsel);
01305   #endif
01306         
01307       }
01308     }
01309   }
01310 
01311   AST::Array*
01312   FlatZincSpace::solveAnnotations(void) const {
01313     return _solveAnnotations;
01314   }
01315 
01316   void
01317   FlatZincSpace::solve(AST::Array* ann) {
01318     _method = SAT;
01319     _solveAnnotations = ann;
01320   }
01321 
01322   void
01323   FlatZincSpace::minimize(int var, bool isInt, AST::Array* ann) {
01324     _method = MIN;
01325     _optVar = var;
01326     _optVarIsInt = isInt;
01327     _solveAnnotations = ann;
01328   }
01329 
01330   void
01331   FlatZincSpace::maximize(int var, bool isInt, AST::Array* ann) {
01332     _method = MAX;
01333     _optVar = var;
01334     _optVarIsInt = isInt;
01335     _solveAnnotations = ann;
01336   }
01337 
01338   FlatZincSpace::~FlatZincSpace(void) {
01339     delete _solveAnnotations;
01340   }
01341 
01342 #ifdef GECODE_HAS_GIST
01343 
01347   template<class Engine>
01348   class GistEngine {
01349   };
01350 
01352   template<typename S>
01353   class GistEngine<DFS<S> > {
01354   public:
01355     static void explore(S* root, const FlatZincOptions& opt,
01356                         Gist::Inspector* i, Gist::Comparator* c) {
01357       Gecode::Gist::Options o;
01358       o.c_d = opt.c_d(); o.a_d = opt.a_d();
01359       o.inspect.click(i);
01360       o.inspect.compare(c);
01361       (void) Gecode::Gist::dfs(root, o);
01362     }
01363   };
01364 
01366   template<typename S>
01367   class GistEngine<BAB<S> > {
01368   public:
01369     static void explore(S* root, const FlatZincOptions& opt,
01370                         Gist::Inspector* i, Gist::Comparator* c) {
01371       Gecode::Gist::Options o;
01372       o.c_d = opt.c_d(); o.a_d = opt.a_d();
01373       o.inspect.click(i);
01374       o.inspect.compare(c);
01375       (void) Gecode::Gist::bab(root, o);
01376     }
01377   };
01378 
01380   template<class S>
01381   class FZPrintingInspector
01382    : public Gecode::Gist::TextOutput, public Gecode::Gist::Inspector {
01383   private:
01384     const Printer& p;
01385   public:
01387     FZPrintingInspector(const Printer& p0);
01389     virtual void inspect(const Space& node);
01391     virtual void finalize(void);
01392   };
01393 
01394   template<class S>
01395   FZPrintingInspector<S>::FZPrintingInspector(const Printer& p0)
01396   : TextOutput("Gecode/FlatZinc"), p(p0) {}
01397 
01398   template<class S>
01399   void
01400   FZPrintingInspector<S>::inspect(const Space& node) {
01401     init();
01402     dynamic_cast<const S&>(node).print(getStream(), p);
01403     getStream() << std::endl;
01404   }
01405 
01406   template<class S>
01407   void
01408   FZPrintingInspector<S>::finalize(void) {
01409     Gecode::Gist::TextOutput::finalize();
01410   }
01411 
01412   template<class S>
01413   class FZPrintingComparator
01414   : public Gecode::Gist::VarComparator<S> {
01415   private:
01416     const Printer& p;
01417   public:
01419     FZPrintingComparator(const Printer& p0);
01420 
01422     virtual void compare(const Space& s0, const Space& s1);
01423   };
01424 
01425   template<class S>
01426   FZPrintingComparator<S>::FZPrintingComparator(const Printer& p0)
01427   : Gecode::Gist::VarComparator<S>("Gecode/FlatZinc"), p(p0) {}
01428 
01429   template<class S>
01430   void
01431   FZPrintingComparator<S>::compare(const Space& s0, const Space& s1) {
01432     this->init();
01433     try {
01434       dynamic_cast<const S&>(s0).compare(dynamic_cast<const S&>(s1),
01435                                          this->getStream(), p);
01436     } catch (Exception& e) {
01437       this->getStream() << "Exception: " << e.what();
01438     }
01439     this->getStream() << std::endl;
01440   }
01441 
01442 #endif
01443 
01444 
01445   template<template<class> class Engine>
01446   void
01447   FlatZincSpace::runEngine(std::ostream& out, const Printer& p,
01448                            const FlatZincOptions& opt, Support::Timer& t_total) {
01449     if (opt.restart()==RM_NONE) {
01450       runMeta<Engine,Driver::EngineToMeta>(out,p,opt,t_total);
01451     } else {
01452       runMeta<Engine,RBS>(out,p,opt,t_total);
01453     }
01454   }
01455 
01456   template<template<class> class Engine,
01457            template<template<class> class,class> class Meta>
01458   void
01459   FlatZincSpace::runMeta(std::ostream& out, const Printer& p,
01460                          const FlatZincOptions& opt, Support::Timer& t_total) {
01461 #ifdef GECODE_HAS_GIST
01462     if (opt.mode() == SM_GIST) {
01463       FZPrintingInspector<FlatZincSpace> pi(p);
01464       FZPrintingComparator<FlatZincSpace> pc(p);
01465       (void) GistEngine<Engine<FlatZincSpace> >::explore(this,opt,&pi,&pc);
01466       return;
01467     }
01468 #endif
01469     StatusStatistics sstat;
01470     unsigned int n_p = 0;
01471     Support::Timer t_solve;
01472     t_solve.start();
01473     if (status(sstat) != SS_FAILED) {
01474       n_p = propagators();
01475     }
01476     Search::Options o;
01477     o.stop = Driver::CombinedStop::create(opt.node(), opt.fail(), opt.time(), 
01478                                           true);
01479     o.c_d = opt.c_d();
01480     o.a_d = opt.a_d();
01481 #ifdef GECODE_HAS_FLOAT_VARS    
01482     step = opt.step();
01483 #endif
01484     o.threads = opt.threads();
01485     o.nogoods_limit = opt.nogoods() ? opt.nogoods_limit() : 0;
01486     o.cutoff  = Driver::createCutoff(opt);
01487     if (opt.interrupt())
01488       Driver::CombinedStop::installCtrlHandler(true);
01489     Meta<Engine,FlatZincSpace> se(this,o);
01490     int noOfSolutions = opt.solutions();
01491     if (noOfSolutions == -1) {
01492       noOfSolutions = (_method == SAT) ? 1 : 0;
01493     }
01494     bool printAll = _method == SAT || opt.allSolutions() || noOfSolutions != 0;
01495     int findSol = noOfSolutions;
01496     FlatZincSpace* sol = NULL;
01497     while (FlatZincSpace* next_sol = se.next()) {
01498       delete sol;
01499       sol = next_sol;
01500       if (printAll) {
01501         sol->print(out, p);
01502         out << "----------" << std::endl;
01503       }
01504       if (--findSol==0)
01505         goto stopped;
01506     }
01507     if (sol && !printAll) {
01508       sol->print(out, p);
01509       out << "----------" << std::endl;
01510     }
01511     if (!se.stopped()) {
01512       if (sol) {
01513         out << "==========" << endl;
01514       } else {
01515         out << "=====UNSATISFIABLE=====" << endl;
01516       }
01517     } else if (!sol) {
01518         out << "=====UNKNOWN=====" << endl;
01519     }
01520     delete sol;
01521     stopped:
01522     if (opt.interrupt())
01523       Driver::CombinedStop::installCtrlHandler(false);
01524     if (opt.mode() == SM_STAT) {
01525       Gecode::Search::Statistics stat = se.statistics();
01526       out << endl
01527            << "%%  runtime:       ";
01528       Driver::stop(t_total,out);
01529       out << endl
01530            << "%%  solvetime:     ";
01531       Driver::stop(t_solve,out);
01532       out << endl
01533            << "%%  solutions:     " 
01534            << std::abs(noOfSolutions - findSol) << endl
01535            << "%%  variables:     " 
01536            << (intVarCount + boolVarCount + setVarCount) << endl
01537            << "%%  propagators:   " << n_p << endl
01538            << "%%  propagations:  " << sstat.propagate+stat.propagate << endl
01539            << "%%  nodes:         " << stat.node << endl
01540            << "%%  failures:      " << stat.fail << endl
01541            << "%%  restarts:      " << stat.restart << endl
01542            << "%%  peak depth:    " << stat.depth << endl
01543            << endl;
01544     }
01545     delete o.stop;
01546   }
01547 
01548 #ifdef GECODE_HAS_QT
01549   void
01550   FlatZincSpace::branchWithPlugin(AST::Node* ann) {
01551     if (AST::Call* c = dynamic_cast<AST::Call*>(ann)) {
01552       QString pluginName(c->id.c_str());
01553       if (QLibrary::isLibrary(pluginName+".dll")) {
01554         pluginName += ".dll";
01555       } else if (QLibrary::isLibrary(pluginName+".dylib")) {
01556         pluginName = "lib" + pluginName + ".dylib";
01557       } else if (QLibrary::isLibrary(pluginName+".so")) {
01558         // Must check .so after .dylib so that Mac OS uses .dylib
01559         pluginName = "lib" + pluginName + ".so";
01560       }
01561       QPluginLoader pl(pluginName);
01562       QObject* plugin_o = pl.instance();
01563       if (!plugin_o) {
01564         throw FlatZinc::Error("FlatZinc",
01565           "Error loading plugin "+pluginName.toStdString()+
01566           ": "+pl.errorString().toStdString());
01567       }
01568       BranchPlugin* pb = qobject_cast<BranchPlugin*>(plugin_o);
01569       if (!pb) {
01570         throw FlatZinc::Error("FlatZinc",
01571         "Error loading plugin "+pluginName.toStdString()+
01572         ": does not contain valid PluginBrancher");
01573       }
01574       pb->branch(*this, c);
01575     }
01576   }
01577 #else
01578   void
01579   FlatZincSpace::branchWithPlugin(AST::Node*) {
01580     throw FlatZinc::Error("FlatZinc",
01581       "Branching with plugins not supported (requires Qt support)");
01582   }
01583 #endif
01584 
01585   void
01586   FlatZincSpace::run(std::ostream& out, const Printer& p,
01587                       const FlatZincOptions& opt, Support::Timer& t_total) {
01588     switch (_method) {
01589     case MIN:
01590     case MAX:
01591       runEngine<BAB>(out,p,opt,t_total);
01592       break;
01593     case SAT:
01594       runEngine<DFS>(out,p,opt,t_total);
01595       break;
01596     }
01597   }
01598 
01599   void
01600   FlatZincSpace::constrain(const Space& s) {
01601     if (_optVarIsInt) {
01602       if (_method == MIN)
01603         rel(*this, iv[_optVar], IRT_LE, 
01604                    static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
01605       else if (_method == MAX)
01606         rel(*this, iv[_optVar], IRT_GR,
01607                    static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
01608     } else {
01609 #ifdef GECODE_HAS_FLOAT_VARS
01610       if (_method == MIN)
01611         rel(*this, fv[_optVar], FRT_LE, 
01612                    static_cast<const FlatZincSpace*>(&s)->fv[_optVar].val()-step);
01613       else if (_method == MAX)
01614         rel(*this, fv[_optVar], FRT_GR,
01615                    static_cast<const FlatZincSpace*>(&s)->fv[_optVar].val()+step);
01616 #endif
01617     }
01618   }
01619 
01620   bool
01621   FlatZincSpace::slave(const CRI& cri) {
01622     if (cri.restart() != 0 && _lns > 0 && cri.last()) {
01623       const FlatZincSpace& last = static_cast<const FlatZincSpace&>(*cri.last());
01624       for (unsigned int i=iv_lns.size(); i--;) {
01625         if ((*_random)(99) <= _lns) {
01626           rel(*this, iv_lns[i], IRT_EQ, last.iv_lns[i]);
01627         }
01628       }
01629       return false;
01630     }
01631     return true;
01632   }
01633 
01634   Space*
01635   FlatZincSpace::copy(bool share) {
01636     return new FlatZincSpace(share, *this);
01637   }
01638 
01639   FlatZincSpace::Meth
01640   FlatZincSpace::method(void) const {
01641     return _method;
01642   }
01643 
01644   int
01645   FlatZincSpace::optVar(void) const {
01646     return _optVar;
01647   }
01648 
01649   bool
01650   FlatZincSpace::optVarIsInt(void) const {
01651     return _optVarIsInt;
01652   }
01653 
01654   void
01655   FlatZincSpace::print(std::ostream& out, const Printer& p) const {
01656     p.print(out, iv, bv
01657 #ifdef GECODE_HAS_SET_VARS
01658     , sv
01659 #endif
01660 #ifdef GECODE_HAS_FLOAT_VARS
01661     , fv
01662 #endif
01663     );
01664   }
01665 
01666   void
01667   FlatZincSpace::compare(const Space& s, std::ostream& out) const {
01668     (void) s; (void) out;
01669 #ifdef GECODE_HAS_GIST
01670     const FlatZincSpace& fs = dynamic_cast<const FlatZincSpace&>(s);
01671     for (int i = 0; i < iv.size(); ++i) {
01672       std::stringstream ss;
01673       ss << "iv[" << i << "]";
01674       std::string result(Gecode::Gist::Comparator::compare(ss.str(), iv[i],
01675                                                            fs.iv[i]));
01676       if (result.length() > 0) out << result << std::endl;
01677     }
01678     for (int i = 0; i < bv.size(); ++i) {
01679       std::stringstream ss;
01680       ss << "bv[" << i << "]";
01681       std::string result(Gecode::Gist::Comparator::compare(ss.str(), bv[i],
01682                                                            fs.bv[i]));
01683       if (result.length() > 0) out << result << std::endl;
01684     }
01685 #ifdef GECODE_HAS_SET_VARS
01686     for (int i = 0; i < sv.size(); ++i) {
01687       std::stringstream ss;
01688       ss << "sv[" << i << "]";
01689       std::string result(Gecode::Gist::Comparator::compare(ss.str(), sv[i],
01690                                                            fs.sv[i]));
01691       if (result.length() > 0) out << result << std::endl;
01692     }
01693 #endif
01694 #ifdef GECODE_HAS_FLOAT_VARS
01695     for (int i = 0; i < fv.size(); ++i) {
01696       std::stringstream ss;
01697       ss << "fv[" << i << "]";
01698       std::string result(Gecode::Gist::Comparator::compare(ss.str(), fv[i],
01699                                                            fs.fv[i]));
01700       if (result.length() > 0) out << result << std::endl;
01701     }
01702 #endif
01703 #endif
01704   }
01705 
01706   void
01707   FlatZincSpace::compare(const FlatZincSpace& s, std::ostream& out,
01708                          const Printer& p) const {
01709     p.printDiff(out, iv, s.iv, bv, s.bv
01710 #ifdef GECODE_HAS_SET_VARS
01711      , sv, s.sv
01712 #endif
01713 #ifdef GECODE_HAS_FLOAT_VARS
01714      , fv, s.fv
01715 #endif
01716     );
01717   }
01718 
01719   void
01720   FlatZincSpace::shrinkArrays(Printer& p) {
01721     p.shrinkArrays(*this, _optVar, _optVarIsInt, iv, bv
01722 #ifdef GECODE_HAS_SET_VARS
01723     , sv
01724 #endif
01725 #ifdef GECODE_HAS_FLOAT_VARS
01726     , fv
01727 #endif
01728     );
01729   }
01730 
01731   IntArgs
01732   FlatZincSpace::arg2intargs(AST::Node* arg, int offset) {
01733     AST::Array* a = arg->getArray();
01734     IntArgs ia(a->a.size()+offset);
01735     for (int i=offset; i--;)
01736       ia[i] = 0;
01737     for (int i=a->a.size(); i--;)
01738       ia[i+offset] = a->a[i]->getInt();
01739     return ia;
01740   }
01741   IntArgs
01742   FlatZincSpace::arg2boolargs(AST::Node* arg, int offset) {
01743     AST::Array* a = arg->getArray();
01744     IntArgs ia(a->a.size()+offset);
01745     for (int i=offset; i--;)
01746       ia[i] = 0;
01747     for (int i=a->a.size(); i--;)
01748       ia[i+offset] = a->a[i]->getBool();
01749     return ia;
01750   }
01751   IntSet
01752   FlatZincSpace::arg2intset(AST::Node* n) {
01753     AST::SetLit* sl = n->getSet();
01754     IntSet d;
01755     if (sl->interval) {
01756       d = IntSet(sl->min, sl->max);
01757     } else {
01758       Region re(*this);
01759       int* is = re.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
01760       for (int i=sl->s.size(); i--; )
01761         is[i] = sl->s[i];
01762       d = IntSet(is, sl->s.size());
01763     }
01764     return d;
01765   }
01766   IntSetArgs
01767   FlatZincSpace::arg2intsetargs(AST::Node* arg, int offset) {
01768     AST::Array* a = arg->getArray();
01769     if (a->a.size() == 0) {
01770       IntSetArgs emptyIa(0);
01771       return emptyIa;
01772     }
01773     IntSetArgs ia(a->a.size()+offset);      
01774     for (int i=offset; i--;)
01775       ia[i] = IntSet::empty;
01776     for (int i=a->a.size(); i--;) {
01777       ia[i+offset] = arg2intset(a->a[i]);
01778     }
01779     return ia;
01780   }
01781   IntVarArgs
01782   FlatZincSpace::arg2intvarargs(AST::Node* arg, int offset) {
01783     AST::Array* a = arg->getArray();
01784     if (a->a.size() == 0) {
01785       IntVarArgs emptyIa(0);
01786       return emptyIa;
01787     }
01788     IntVarArgs ia(a->a.size()+offset);
01789     for (int i=offset; i--;)
01790       ia[i] = IntVar(*this, 0, 0);
01791     for (int i=a->a.size(); i--;) {
01792       if (a->a[i]->isIntVar()) {
01793         ia[i+offset] = iv[a->a[i]->getIntVar()];        
01794       } else {
01795         int value = a->a[i]->getInt();
01796         IntVar iv(*this, value, value);
01797         ia[i+offset] = iv;        
01798       }
01799     }
01800     return ia;
01801   }
01802   BoolVarArgs
01803   FlatZincSpace::arg2boolvarargs(AST::Node* arg, int offset, int siv) {
01804     AST::Array* a = arg->getArray();
01805     if (a->a.size() == 0) {
01806       BoolVarArgs emptyIa(0);
01807       return emptyIa;
01808     }
01809     BoolVarArgs ia(a->a.size()+offset-(siv==-1?0:1));
01810     for (int i=offset; i--;)
01811       ia[i] = BoolVar(*this, 0, 0);
01812     for (int i=0; i<static_cast<int>(a->a.size()); i++) {
01813       if (i==siv)
01814         continue;
01815       if (a->a[i]->isBool()) {
01816         bool value = a->a[i]->getBool();
01817         BoolVar iv(*this, value, value);
01818         ia[offset++] = iv;
01819       } else if (a->a[i]->isIntVar() &&
01820                  aliasBool2Int(a->a[i]->getIntVar()) != -1) {
01821         ia[offset++] = bv[aliasBool2Int(a->a[i]->getIntVar())];
01822       } else {
01823         ia[offset++] = bv[a->a[i]->getBoolVar()];
01824       }
01825     }
01826     return ia;
01827   }
01828   BoolVar
01829   FlatZincSpace::arg2BoolVar(AST::Node* n) {
01830     BoolVar x0;
01831     if (n->isBool()) {
01832       x0 = BoolVar(*this, n->getBool(), n->getBool());
01833     }
01834     else {
01835       x0 = bv[n->getBoolVar()];
01836     }
01837     return x0;
01838   }
01839   IntVar
01840   FlatZincSpace::arg2IntVar(AST::Node* n) {
01841     IntVar x0;
01842     if (n->isIntVar()) {
01843       x0 = iv[n->getIntVar()];
01844     } else {
01845       x0 = IntVar(*this, n->getInt(), n->getInt());            
01846     }
01847     return x0;
01848   }
01849   bool
01850   FlatZincSpace::isBoolArray(AST::Node* b, int& singleInt) {
01851     AST::Array* a = b->getArray();
01852     singleInt = -1;
01853     if (a->a.size() == 0)
01854       return true;
01855     for (int i=a->a.size(); i--;) {
01856       if (a->a[i]->isBoolVar() || a->a[i]->isBool()) {
01857       } else if (a->a[i]->isIntVar()) {
01858         if (aliasBool2Int(a->a[i]->getIntVar()) == -1) {
01859           if (singleInt != -1) {
01860             return false;
01861           }
01862           singleInt = i;
01863         }
01864       } else {
01865         return false;
01866       }
01867     }
01868     return singleInt==-1 || a->a.size() > 1;
01869   }
01870 #ifdef GECODE_HAS_SET_VARS
01871   SetVar
01872   FlatZincSpace::arg2SetVar(AST::Node* n) {
01873     SetVar x0;
01874     if (!n->isSetVar()) {
01875       IntSet d = arg2intset(n);
01876       x0 = SetVar(*this, d, d);
01877     } else {
01878       x0 = sv[n->getSetVar()];
01879     }
01880     return x0;
01881   }
01882   SetVarArgs
01883   FlatZincSpace::arg2setvarargs(AST::Node* arg, int offset, int doffset,
01884                                 const IntSet& od) {
01885     AST::Array* a = arg->getArray();
01886     SetVarArgs ia(a->a.size()+offset);
01887     for (int i=offset; i--;) {
01888       IntSet d = i<doffset ? od : IntSet::empty;
01889       ia[i] = SetVar(*this, d, d);
01890     }
01891     for (int i=a->a.size(); i--;) {
01892       ia[i+offset] = arg2SetVar(a->a[i]);
01893     }
01894     return ia;
01895   }
01896 #endif
01897 #ifdef GECODE_HAS_FLOAT_VARS
01898   FloatValArgs
01899   FlatZincSpace::arg2floatargs(AST::Node* arg, int offset) {
01900     AST::Array* a = arg->getArray();
01901     FloatValArgs fa(a->a.size()+offset);
01902     for (int i=offset; i--;)
01903       fa[i] = 0.0;
01904     for (int i=a->a.size(); i--;)
01905       fa[i+offset] = a->a[i]->getFloat();
01906     return fa;
01907   }
01908   FloatVarArgs
01909   FlatZincSpace::arg2floatvarargs(AST::Node* arg, int offset) {
01910     AST::Array* a = arg->getArray();
01911     if (a->a.size() == 0) {
01912       FloatVarArgs emptyFa(0);
01913       return emptyFa;
01914     }
01915     FloatVarArgs fa(a->a.size()+offset);
01916     for (int i=offset; i--;)
01917       fa[i] = FloatVar(*this, 0.0, 0.0);
01918     for (int i=a->a.size(); i--;) {
01919       if (a->a[i]->isFloatVar()) {
01920         fa[i+offset] = fv[a->a[i]->getFloatVar()];        
01921       } else {
01922         double value = a->a[i]->getFloat();
01923         FloatVar fv(*this, value, value);
01924         fa[i+offset] = fv;
01925       }
01926     }
01927     return fa;
01928   }
01929   FloatVar
01930   FlatZincSpace::arg2FloatVar(AST::Node* n) {
01931     FloatVar x0;
01932     if (n->isFloatVar()) {
01933       x0 = fv[n->getFloatVar()];
01934     } else {
01935       x0 = FloatVar(*this, n->getFloat(), n->getFloat());
01936     }
01937     return x0;
01938   }
01939 #endif
01940   IntConLevel
01941   FlatZincSpace::ann2icl(AST::Node* ann) {
01942     if (ann) {
01943       if (ann->hasAtom("val"))
01944         return ICL_VAL;
01945       if (ann->hasAtom("domain"))
01946         return ICL_DOM;
01947       if (ann->hasAtom("bounds") ||
01948           ann->hasAtom("boundsR") ||
01949           ann->hasAtom("boundsD") ||
01950           ann->hasAtom("boundsZ"))
01951         return ICL_BND;
01952     }
01953     return ICL_DEF;
01954   }
01955 
01956 
01957   void
01958   Printer::init(AST::Array* output) {
01959     _output = output;
01960   }
01961 
01962   void
01963   Printer::printElem(std::ostream& out,
01964                        AST::Node* ai,
01965                        const Gecode::IntVarArray& iv,
01966                        const Gecode::BoolVarArray& bv
01967 #ifdef GECODE_HAS_SET_VARS
01968                        , const Gecode::SetVarArray& sv
01969 #endif
01970 #ifdef GECODE_HAS_FLOAT_VARS
01971                        ,
01972                        const Gecode::FloatVarArray& fv
01973 #endif
01974                        ) const {
01975     int k;
01976     if (ai->isInt(k)) {
01977       out << k;
01978     } else if (ai->isIntVar()) {
01979       out << iv[ai->getIntVar()];
01980     } else if (ai->isBoolVar()) {
01981       if (bv[ai->getBoolVar()].min() == 1) {
01982         out << "true";
01983       } else if (bv[ai->getBoolVar()].max() == 0) {
01984         out << "false";
01985       } else {
01986         out << "false..true";
01987       }
01988 #ifdef GECODE_HAS_SET_VARS
01989     } else if (ai->isSetVar()) {
01990       if (!sv[ai->getSetVar()].assigned()) {
01991         out << sv[ai->getSetVar()];
01992         return;
01993       }
01994       SetVarGlbRanges svr(sv[ai->getSetVar()]);
01995       if (!svr()) {
01996         out << "{}";
01997         return;
01998       }
01999       int min = svr.min();
02000       int max = svr.max();
02001       ++svr;
02002       if (svr()) {
02003         SetVarGlbValues svv(sv[ai->getSetVar()]);
02004         int i = svv.val();
02005         out << "{" << i;
02006         ++svv;
02007         for (; svv(); ++svv)
02008           out << ", " << svv.val();
02009         out << "}";
02010       } else {
02011         out << min << ".." << max;
02012       }
02013 #endif
02014 #ifdef GECODE_HAS_FLOAT_VARS
02015     } else if (ai->isFloatVar()) {
02016       if (fv[ai->getFloatVar()].assigned()) {
02017         FloatVal vv = fv[ai->getFloatVar()].val();
02018         FloatNum v;
02019         if (vv.singleton())
02020           v = vv.min();
02021         else if (vv < 0.0)
02022           v = vv.max();
02023         else
02024           v = vv.min();
02025         std::ostringstream oss;
02026         // oss << std::scientific;
02027         oss << std::setprecision(std::numeric_limits<double>::digits10);
02028         oss << v;
02029         if (oss.str().find(".") == std::string::npos)
02030           oss << ".0";
02031         out << oss.str();
02032       } else {
02033         out << fv[ai->getFloatVar()];
02034       }
02035 #endif
02036     } else if (ai->isBool()) {
02037       out << (ai->getBool() ? "true" : "false");
02038     } else if (ai->isSet()) {
02039       AST::SetLit* s = ai->getSet();
02040       if (s->interval) {
02041         out << s->min << ".." << s->max;
02042       } else {
02043         out << "{";
02044         for (unsigned int i=0; i<s->s.size(); i++) {
02045           out << s->s[i] << (i < s->s.size()-1 ? ", " : "}");
02046         }
02047       }
02048     } else if (ai->isString()) {
02049       std::string s = ai->getString();
02050       for (unsigned int i=0; i<s.size(); i++) {
02051         if (s[i] == '\\' && i<s.size()-1) {
02052           switch (s[i+1]) {
02053           case 'n': out << "\n"; break;
02054           case '\\': out << "\\"; break;
02055           case 't': out << "\t"; break;
02056           default: out << "\\" << s[i+1];
02057           }
02058           i++;
02059         } else {
02060           out << s[i];
02061         }
02062       }
02063     }
02064   }
02065 
02066   void
02067   Printer::printElemDiff(std::ostream& out,
02068                        AST::Node* ai,
02069                        const Gecode::IntVarArray& iv1,
02070                        const Gecode::IntVarArray& iv2,
02071                        const Gecode::BoolVarArray& bv1,
02072                        const Gecode::BoolVarArray& bv2
02073 #ifdef GECODE_HAS_SET_VARS
02074                        , const Gecode::SetVarArray& sv1,
02075                        const Gecode::SetVarArray& sv2
02076 #endif
02077 #ifdef GECODE_HAS_FLOAT_VARS
02078                        , const Gecode::FloatVarArray& fv1,
02079                        const Gecode::FloatVarArray& fv2
02080 #endif
02081                        ) const {
02082 #ifdef GECODE_HAS_GIST
02083     using namespace Gecode::Gist;
02084     int k;
02085     if (ai->isInt(k)) {
02086       out << k;
02087     } else if (ai->isIntVar()) {
02088       std::string res(Comparator::compare("",iv1[ai->getIntVar()],
02089                                           iv2[ai->getIntVar()]));
02090       if (res.length() > 0) {
02091         res.erase(0, 1); // Remove '='
02092         out << res;
02093       } else {
02094         out << iv1[ai->getIntVar()];
02095       }
02096     } else if (ai->isBoolVar()) {
02097       std::string res(Comparator::compare("",bv1[ai->getBoolVar()],
02098                                           bv2[ai->getBoolVar()]));
02099       if (res.length() > 0) {
02100         res.erase(0, 1); // Remove '='
02101         out << res;
02102       } else {
02103         out << bv1[ai->getBoolVar()];
02104       }
02105 #ifdef GECODE_HAS_SET_VARS
02106     } else if (ai->isSetVar()) {
02107       std::string res(Comparator::compare("",sv1[ai->getSetVar()],
02108                                           sv2[ai->getSetVar()]));
02109       if (res.length() > 0) {
02110         res.erase(0, 1); // Remove '='
02111         out << res;
02112       } else {
02113         out << sv1[ai->getSetVar()];
02114       }
02115 #endif
02116 #ifdef GECODE_HAS_FLOAT_VARS
02117     } else if (ai->isFloatVar()) {
02118       std::string res(Comparator::compare("",fv1[ai->getFloatVar()],
02119                                           fv2[ai->getFloatVar()]));
02120       if (res.length() > 0) {
02121         res.erase(0, 1); // Remove '='
02122         out << res;
02123       } else {
02124         out << fv1[ai->getFloatVar()];
02125       }
02126 #endif
02127     } else if (ai->isBool()) {
02128       out << (ai->getBool() ? "true" : "false");
02129     } else if (ai->isSet()) {
02130       AST::SetLit* s = ai->getSet();
02131       if (s->interval) {
02132         out << s->min << ".." << s->max;
02133       } else {
02134         out << "{";
02135         for (unsigned int i=0; i<s->s.size(); i++) {
02136           out << s->s[i] << (i < s->s.size()-1 ? ", " : "}");
02137         }
02138       }
02139     } else if (ai->isString()) {
02140       std::string s = ai->getString();
02141       for (unsigned int i=0; i<s.size(); i++) {
02142         if (s[i] == '\\' && i<s.size()-1) {
02143           switch (s[i+1]) {
02144           case 'n': out << "\n"; break;
02145           case '\\': out << "\\"; break;
02146           case 't': out << "\t"; break;
02147           default: out << "\\" << s[i+1];
02148           }
02149           i++;
02150         } else {
02151           out << s[i];
02152         }
02153       }
02154     }
02155 #else
02156     (void) out;
02157     (void) ai;
02158     (void) iv1;
02159     (void) iv2;
02160     (void) bv1;
02161     (void) bv2;
02162 #ifdef GECODE_HAS_SET_VARS
02163     (void) sv1;
02164     (void) sv2;
02165 #endif
02166 #ifdef GECODE_HAS_FLOAT_VARS
02167     (void) fv1;
02168     (void) fv2;
02169 #endif
02170     
02171 #endif
02172   }
02173 
02174   void
02175   Printer::print(std::ostream& out,
02176                    const Gecode::IntVarArray& iv,
02177                    const Gecode::BoolVarArray& bv
02178 #ifdef GECODE_HAS_SET_VARS
02179                    ,
02180                    const Gecode::SetVarArray& sv
02181 #endif
02182 #ifdef GECODE_HAS_FLOAT_VARS
02183                    ,
02184                    const Gecode::FloatVarArray& fv
02185 #endif
02186                    ) const {
02187     if (_output == NULL)
02188       return;
02189     for (unsigned int i=0; i< _output->a.size(); i++) {
02190       AST::Node* ai = _output->a[i];
02191       if (ai->isArray()) {
02192         AST::Array* aia = ai->getArray();
02193         int size = aia->a.size();
02194         out << "[";
02195         for (int j=0; j<size; j++) {
02196           printElem(out,aia->a[j],iv,bv
02197 #ifdef GECODE_HAS_SET_VARS
02198           ,sv
02199 #endif
02200 #ifdef GECODE_HAS_FLOAT_VARS
02201           ,fv
02202 #endif
02203           );
02204           if (j<size-1)
02205             out << ", ";
02206         }
02207         out << "]";
02208       } else {
02209         printElem(out,ai,iv,bv
02210 #ifdef GECODE_HAS_SET_VARS
02211         ,sv
02212 #endif
02213 #ifdef GECODE_HAS_FLOAT_VARS
02214           ,fv
02215 #endif
02216         );
02217       }
02218     }
02219   }
02220 
02221   void
02222   Printer::printDiff(std::ostream& out,
02223                    const Gecode::IntVarArray& iv1,
02224                    const Gecode::IntVarArray& iv2,
02225                    const Gecode::BoolVarArray& bv1,
02226                    const Gecode::BoolVarArray& bv2
02227 #ifdef GECODE_HAS_SET_VARS
02228                    ,
02229                    const Gecode::SetVarArray& sv1,
02230                    const Gecode::SetVarArray& sv2
02231 #endif
02232 #ifdef GECODE_HAS_FLOAT_VARS
02233                    ,
02234                    const Gecode::FloatVarArray& fv1,
02235                    const Gecode::FloatVarArray& fv2
02236 #endif
02237                    ) const {
02238     if (_output == NULL)
02239       return;
02240     for (unsigned int i=0; i< _output->a.size(); i++) {
02241       AST::Node* ai = _output->a[i];
02242       if (ai->isArray()) {
02243         AST::Array* aia = ai->getArray();
02244         int size = aia->a.size();
02245         out << "[";
02246         for (int j=0; j<size; j++) {
02247           printElemDiff(out,aia->a[j],iv1,iv2,bv1,bv2
02248 #ifdef GECODE_HAS_SET_VARS
02249             ,sv1,sv2
02250 #endif
02251 #ifdef GECODE_HAS_FLOAT_VARS
02252             ,fv1,fv2
02253 #endif
02254           );
02255           if (j<size-1)
02256             out << ", ";
02257         }
02258         out << "]";
02259       } else {
02260         printElemDiff(out,ai,iv1,iv2,bv1,bv2
02261 #ifdef GECODE_HAS_SET_VARS
02262           ,sv1,sv2
02263 #endif
02264 #ifdef GECODE_HAS_FLOAT_VARS
02265             ,fv1,fv2
02266 #endif
02267         );
02268       }
02269     }
02270   }
02271 
02272   void
02273   Printer::shrinkElement(AST::Node* node,
02274                          std::map<int,int>& iv, std::map<int,int>& bv, 
02275                          std::map<int,int>& sv, std::map<int,int>& fv) {
02276     if (node->isIntVar()) {
02277       AST::IntVar* x = static_cast<AST::IntVar*>(node);
02278       if (iv.find(x->i) == iv.end()) {
02279         int newi = iv.size();
02280         iv[x->i] = newi;
02281       }
02282       x->i = iv[x->i];
02283     } else if (node->isBoolVar()) {
02284       AST::BoolVar* x = static_cast<AST::BoolVar*>(node);
02285       if (bv.find(x->i) == bv.end()) {
02286         int newi = bv.size();
02287         bv[x->i] = newi;
02288       }
02289       x->i = bv[x->i];
02290     } else if (node->isSetVar()) {
02291       AST::SetVar* x = static_cast<AST::SetVar*>(node);
02292       if (sv.find(x->i) == sv.end()) {
02293         int newi = sv.size();
02294         sv[x->i] = newi;
02295       }
02296       x->i = sv[x->i];      
02297     } else if (node->isFloatVar()) {
02298       AST::FloatVar* x = static_cast<AST::FloatVar*>(node);
02299       if (fv.find(x->i) == fv.end()) {
02300         int newi = fv.size();
02301         fv[x->i] = newi;
02302       }
02303       x->i = fv[x->i];      
02304     }
02305   }
02306 
02307   void
02308   Printer::shrinkArrays(Space& home,
02309                         int& optVar, bool optVarIsInt,
02310                         Gecode::IntVarArray& iv,
02311                         Gecode::BoolVarArray& bv
02312 #ifdef GECODE_HAS_SET_VARS
02313                         ,
02314                         Gecode::SetVarArray& sv
02315 #endif
02316 #ifdef GECODE_HAS_FLOAT_VARS
02317                         ,
02318                         Gecode::FloatVarArray& fv
02319 #endif
02320                        ) {
02321     if (_output == NULL) {
02322       if (optVarIsInt && optVar != -1) {
02323         IntVar ov = iv[optVar];
02324         iv = IntVarArray(home, 1);
02325         iv[0] = ov;
02326         optVar = 0;
02327       } else {
02328         iv = IntVarArray(home, 0);
02329       }
02330       bv = BoolVarArray(home, 0);
02331 #ifdef GECODE_HAS_SET_VARS
02332       sv = SetVarArray(home, 0);
02333 #endif
02334 #ifdef GECODE_HAS_FLOAT_VARS
02335       if (!optVarIsInt && optVar != -1) {
02336         FloatVar ov = fv[optVar];
02337         fv = FloatVarArray(home, 1);
02338         fv[0] = ov;
02339         optVar = 0;
02340       } else {
02341         fv = FloatVarArray(home,0);
02342       }
02343 #endif
02344       return;
02345     }
02346     std::map<int,int> iv_new;
02347     std::map<int,int> bv_new;
02348     std::map<int,int> sv_new;
02349     std::map<int,int> fv_new;
02350 
02351     if (optVar != -1) {
02352       if (optVarIsInt)
02353         iv_new[optVar] = 0;
02354       else
02355         fv_new[optVar] = 0;
02356       optVar = 0;
02357     }
02358 
02359     for (unsigned int i=0; i< _output->a.size(); i++) {
02360       AST::Node* ai = _output->a[i];
02361       if (ai->isArray()) {
02362         AST::Array* aia = ai->getArray();
02363         for (unsigned int j=0; j<aia->a.size(); j++) {
02364           shrinkElement(aia->a[j],iv_new,bv_new,sv_new,fv_new);
02365         }
02366       } else {
02367         shrinkElement(ai,iv_new,bv_new,sv_new,fv_new);
02368       }
02369     }
02370 
02371     IntVarArgs iva(iv_new.size());
02372     for (map<int,int>::iterator i=iv_new.begin(); i != iv_new.end(); ++i) {
02373       iva[(*i).second] = iv[(*i).first];
02374     }
02375     iv = IntVarArray(home, iva);
02376 
02377     BoolVarArgs bva(bv_new.size());
02378     for (map<int,int>::iterator i=bv_new.begin(); i != bv_new.end(); ++i) {
02379       bva[(*i).second] = bv[(*i).first];
02380     }
02381     bv = BoolVarArray(home, bva);
02382 
02383 #ifdef GECODE_HAS_SET_VARS
02384     SetVarArgs sva(sv_new.size());
02385     for (map<int,int>::iterator i=sv_new.begin(); i != sv_new.end(); ++i) {
02386       sva[(*i).second] = sv[(*i).first];
02387     }
02388     sv = SetVarArray(home, sva);
02389 #endif
02390 
02391 #ifdef GECODE_HAS_FLOAT_VARS
02392     FloatVarArgs fva(fv_new.size());
02393     for (map<int,int>::iterator i=fv_new.begin(); i != fv_new.end(); ++i) {
02394       fva[(*i).second] = fv[(*i).first];
02395     }
02396     fv = FloatVarArray(home, fva);
02397 #endif
02398   }
02399 
02400   Printer::~Printer(void) {
02401     delete _output;
02402   }
02403 
02404 }}
02405 
02406 // STATISTICS: flatzinc-any