Generated on Thu Mar 22 10:39:32 2012 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  *  Copyright:
00007  *     Guido Tack, 2007
00008  *
00009  *  Last modified:
00010  *     $Date: 2012-03-21 06:25:08 +0100 (Wed, 21 Mar 2012) $ by $Author: tack $
00011  *     $Revision: 12605 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *  Permission is hereby granted, free of charge, to any person obtaining
00018  *  a copy of this software and associated documentation files (the
00019  *  "Software"), to deal in the Software without restriction, including
00020  *  without limitation the rights to use, copy, modify, merge, publish,
00021  *  distribute, sublicense, and/or sell copies of the Software, and to
00022  *  permit persons to whom the Software is furnished to do so, subject to
00023  *  the following conditions:
00024  *
00025  *  The above copyright notice and this permission notice shall be
00026  *  included in all copies or substantial portions of the Software.
00027  *
00028  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00029  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00030  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00031  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00032  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00033  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00034  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00035  *
00036  */
00037 
00038 #include <gecode/flatzinc.hh>
00039 #include <gecode/flatzinc/registry.hh>
00040 #include <gecode/flatzinc/plugin.hh>
00041 
00042 #include <gecode/search.hh>
00043 
00044 #include <vector>
00045 #include <string>
00046 using namespace std;
00047 
00048 namespace Gecode { namespace FlatZinc {
00049 
00050   IntSet vs2is(IntVarSpec* vs) {
00051     if (vs->assigned) {
00052       return IntSet(vs->i,vs->i);
00053     }
00054     if (vs->domain()) {
00055       AST::SetLit* sl = vs->domain.some();
00056       if (sl->interval) {
00057         return IntSet(sl->min, sl->max);
00058       } else {
00059         int* newdom = heap.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
00060         for (int i=sl->s.size(); i--;)
00061           newdom[i] = sl->s[i];
00062         IntSet ret(newdom, sl->s.size());
00063         heap.free(newdom, static_cast<unsigned long int>(sl->s.size()));
00064         return ret;
00065       }
00066     }
00067     return IntSet(Int::Limits::min, Int::Limits::max);
00068   }
00069 
00070   int vs2bsl(BoolVarSpec* bs) {
00071     if (bs->assigned) {
00072       return bs->i;
00073     }
00074     if (bs->domain()) {
00075       AST::SetLit* sl = bs->domain.some();
00076       assert(sl->interval);
00077       return std::min(1, std::max(0, sl->min));
00078     }
00079     return 0;
00080   }
00081 
00082   int vs2bsh(BoolVarSpec* bs) {
00083     if (bs->assigned) {
00084       return bs->i;
00085     }
00086     if (bs->domain()) {
00087       AST::SetLit* sl = bs->domain.some();
00088       assert(sl->interval);
00089       return std::max(0, std::min(1, sl->max));
00090     }
00091     return 1;
00092   }
00093 
00094   TieBreakVarBranch<IntVarBranch> ann2ivarsel(AST::Node* ann) {
00095     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00096       if (s->id == "input_order")
00097         return TieBreakVarBranch<IntVarBranch>(INT_VAR_NONE);
00098       if (s->id == "first_fail")
00099         return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MIN);
00100       if (s->id == "anti_first_fail")
00101         return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MAX);
00102       if (s->id == "smallest")
00103         return TieBreakVarBranch<IntVarBranch>(INT_VAR_MIN_MIN);
00104       if (s->id == "largest")
00105         return TieBreakVarBranch<IntVarBranch>(INT_VAR_MAX_MAX);
00106       if (s->id == "occurrence")
00107         return TieBreakVarBranch<IntVarBranch>(INT_VAR_DEGREE_MAX);
00108       if (s->id == "max_regret")
00109         return TieBreakVarBranch<IntVarBranch>(INT_VAR_REGRET_MIN_MAX);
00110       if (s->id == "most_constrained")
00111         return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MIN,
00112           INT_VAR_DEGREE_MAX);
00113       if (s->id == "random")
00114         return TieBreakVarBranch<IntVarBranch>(INT_VAR_RND);
00115       if (s->id == "afc_min")
00116         return TieBreakVarBranch<IntVarBranch>(INT_VAR_AFC_MIN);
00117       if (s->id == "afc_max")
00118         return TieBreakVarBranch<IntVarBranch>(INT_VAR_AFC_MAX);
00119       if (s->id == "size_afc_min")
00120         return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_AFC_MIN);
00121       if (s->id == "size_afc_max")
00122         return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_AFC_MAX);
00123     }
00124     std::cerr << "Warning, ignored search annotation: ";
00125     ann->print(std::cerr);
00126     std::cerr << std::endl;
00127     return TieBreakVarBranch<IntVarBranch>(INT_VAR_NONE);
00128   }
00129 
00130   IntValBranch ann2ivalsel(AST::Node* ann) {
00131     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00132       if (s->id == "indomain_min")
00133         return INT_VAL_MIN;
00134       if (s->id == "indomain_max")
00135         return INT_VAL_MAX;
00136       if (s->id == "indomain_median")
00137         return INT_VAL_MED;
00138       if (s->id == "indomain_split")
00139         return INT_VAL_SPLIT_MIN;
00140       if (s->id == "indomain_reverse_split")
00141         return INT_VAL_SPLIT_MAX;
00142       if (s->id == "indomain_random")
00143         return INT_VAL_RND;
00144       if (s->id == "indomain")
00145         return INT_VALUES_MIN;
00146       if (s->id == "indomain_middle") {
00147         std::cerr << "Warning, replacing unsupported annotation "
00148                   << "indomain_middle with indomain_median" << std::endl;
00149         return INT_VAL_MED;
00150       }
00151       if (s->id == "indomain_interval") {
00152         std::cerr << "Warning, replacing unsupported annotation "
00153                   << "indomain_interval with indomain_split" << std::endl;
00154         return INT_VAL_SPLIT_MIN;
00155       }
00156     }
00157     std::cerr << "Warning, ignored search annotation: ";
00158     ann->print(std::cerr);
00159     std::cerr << std::endl;
00160     return INT_VAL_MIN;
00161   }
00162 
00163   IntAssign ann2asnivalsel(AST::Node* ann) {
00164     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00165       if (s->id == "indomain_min")
00166         return INT_ASSIGN_MIN;
00167       if (s->id == "indomain_max")
00168         return INT_ASSIGN_MAX;
00169       if (s->id == "indomain_median")
00170         return INT_ASSIGN_MED;
00171       if (s->id == "indomain_random")
00172         return INT_ASSIGN_RND;
00173     }
00174     std::cerr << "Warning, ignored search annotation: ";
00175     ann->print(std::cerr);
00176     std::cerr << std::endl;
00177     return INT_ASSIGN_MIN;
00178   }
00179 
00180 #ifdef GECODE_HAS_SET_VARS
00181   SetVarBranch ann2svarsel(AST::Node* ann) {
00182     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00183       if (s->id == "input_order")
00184         return SET_VAR_NONE;
00185       if (s->id == "first_fail")
00186         return SET_VAR_SIZE_MIN;
00187       if (s->id == "anti_first_fail")
00188         return SET_VAR_SIZE_MAX;
00189       if (s->id == "smallest")
00190         return SET_VAR_MIN_MIN;
00191       if (s->id == "largest")
00192         return SET_VAR_MAX_MAX;
00193     }
00194     std::cerr << "Warning, ignored search annotation: ";
00195     ann->print(std::cerr);
00196     std::cerr << std::endl;
00197     return SET_VAR_NONE;
00198   }
00199 
00200   SetValBranch ann2svalsel(AST::Node* ann) {
00201     if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00202       if (s->id == "indomain_min")
00203         return SET_VAL_MIN_INC;
00204       if (s->id == "indomain_max")
00205         return SET_VAL_MAX_INC;
00206       if (s->id == "outdomain_min")
00207         return SET_VAL_MIN_EXC;
00208       if (s->id == "outdomain_max")
00209         return SET_VAL_MAX_EXC;
00210     }
00211     std::cerr << "Warning, ignored search annotation: ";
00212     ann->print(std::cerr);
00213     std::cerr << std::endl;
00214     return SET_VAL_MIN_INC;
00215   }
00216 #endif
00217 
00218   FlatZincSpace::FlatZincSpace(bool share, FlatZincSpace& f)
00219     : Space(share, f), _solveAnnotations(NULL), iv_boolalias(NULL) {
00220       _optVar = f._optVar;
00221       _method = f._method;
00222       iv.update(*this, share, f.iv);
00223       intVarCount = f.intVarCount;
00224       bv.update(*this, share, f.bv);
00225       boolVarCount = f.boolVarCount;
00226 #ifdef GECODE_HAS_SET_VARS
00227       sv.update(*this, share, f.sv);
00228       setVarCount = f.setVarCount;
00229 #endif
00230     }
00231   
00232   FlatZincSpace::FlatZincSpace(void)
00233   : intVarCount(-1), boolVarCount(-1), setVarCount(-1), _optVar(-1),
00234     _solveAnnotations(NULL) {}
00235 
00236   void
00237   FlatZincSpace::init(int intVars, int boolVars,
00238 #ifdef GECODE_HAS_SET_VARS
00239                                  int setVars) {
00240 #else
00241                                  int) {
00242 #endif
00243     intVarCount = 0;
00244     iv = IntVarArray(*this, intVars);
00245     iv_introduced = std::vector<bool>(intVars);
00246     iv_boolalias = alloc<int>(intVars+(intVars==0?1:0));
00247     boolVarCount = 0;
00248     bv = BoolVarArray(*this, boolVars);
00249     bv_introduced = std::vector<bool>(boolVars);
00250 #ifdef GECODE_HAS_SET_VARS
00251     setVarCount = 0;
00252     sv = SetVarArray(*this, setVars);
00253     sv_introduced = std::vector<bool>(setVars);
00254 #endif
00255   }
00256 
00257   void
00258   FlatZincSpace::newIntVar(IntVarSpec* vs) {
00259     if (vs->alias) {
00260       iv[intVarCount++] = iv[vs->i];
00261     } else {
00262       IntSet dom(vs2is(vs));
00263       if (dom.size()==0) {
00264         fail();
00265         return;
00266       } else {
00267         iv[intVarCount++] = IntVar(*this, dom);
00268       }
00269     }
00270     iv_introduced[intVarCount-1] = vs->introduced;
00271     iv_boolalias[intVarCount-1] = -1;
00272   }
00273 
00274   void
00275   FlatZincSpace::aliasBool2Int(int iv, int bv) {
00276     iv_boolalias[iv] = bv;
00277   }
00278   int
00279   FlatZincSpace::aliasBool2Int(int iv) {
00280     return iv_boolalias[iv];
00281   }
00282 
00283   void
00284   FlatZincSpace::newBoolVar(BoolVarSpec* vs) {
00285     if (vs->alias) {
00286       bv[boolVarCount++] = bv[vs->i];
00287     } else {
00288       bv[boolVarCount++] = BoolVar(*this, vs2bsl(vs), vs2bsh(vs));
00289     }
00290     bv_introduced[boolVarCount-1] = vs->introduced;
00291   }
00292 
00293 #ifdef GECODE_HAS_SET_VARS
00294   void
00295   FlatZincSpace::newSetVar(SetVarSpec* vs) {
00296     if (vs->alias) {
00297       sv[setVarCount++] = sv[vs->i];
00298     } else if (vs->assigned) {
00299       assert(vs->upperBound());
00300       AST::SetLit* vsv = vs->upperBound.some();
00301       if (vsv->interval) {
00302         IntSet d(vsv->min, vsv->max);
00303         sv[setVarCount++] = SetVar(*this, d, d);
00304       } else {
00305         int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00306         for (int i=vsv->s.size(); i--; )
00307           is[i] = vsv->s[i];
00308         IntSet d(is, vsv->s.size());
00309         heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00310         sv[setVarCount++] = SetVar(*this, d, d);
00311       }
00312     } else if (vs->upperBound()) {
00313       AST::SetLit* vsv = vs->upperBound.some();
00314       if (vsv->interval) {
00315         IntSet d(vsv->min, vsv->max);
00316         sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00317       } else {
00318         int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00319         for (int i=vsv->s.size(); i--; )
00320           is[i] = vsv->s[i];
00321         IntSet d(is, vsv->s.size());
00322         heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00323         sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00324       }
00325     } else {
00326       sv[setVarCount++] = SetVar(*this, IntSet::empty,
00327                                  IntSet(Set::Limits::min, 
00328                                         Set::Limits::max));
00329     }
00330     sv_introduced[setVarCount-1] = vs->introduced;
00331   }
00332 #else
00333   void
00334   FlatZincSpace::newSetVar(SetVarSpec*) {
00335     throw FlatZinc::Error("Gecode", "set variables not supported");
00336   }
00337 #endif
00338 
00339   void
00340   FlatZincSpace::postConstraint(const ConExpr& ce, AST::Node* ann) {
00341     try {
00342       registry().post(*this, ce, ann);
00343     } catch (Gecode::Exception& e) {
00344       throw FlatZinc::Error("Gecode", e.what());
00345     } catch (AST::TypeError& e) {
00346       throw FlatZinc::Error("Type error", e.what());
00347     }
00348   }
00349 
00350   void flattenAnnotations(AST::Array* ann, std::vector<AST::Node*>& out) {
00351       for (unsigned int i=0; i<ann->a.size(); i++) {
00352         if (ann->a[i]->isCall("seq_search")) {
00353           AST::Call* c = ann->a[i]->getCall();
00354           if (c->args->isArray())
00355             flattenAnnotations(c->args->getArray(), out);
00356           else
00357             out.push_back(c->args);
00358         } else {
00359           out.push_back(ann->a[i]);
00360         }
00361       }
00362   }
00363 
00364   void
00365   FlatZincSpace::createBranchers(AST::Node* ann, int seed,
00366                                  bool ignoreUnknown,
00367                                  std::ostream& err) {
00368     VarBranchOptions varbo;
00369     varbo.seed = seed;
00370     ValBranchOptions valbo;
00371     valbo.seed = seed;
00372     if (ann) {
00373       std::vector<AST::Node*> flatAnn;
00374       if (ann->isArray()) {
00375         flattenAnnotations(ann->getArray()  , flatAnn);
00376       } else {
00377         flatAnn.push_back(ann);
00378       }
00379 
00380       for (unsigned int i=0; i<flatAnn.size(); i++) {
00381         if (flatAnn[i]->isCall("gecode_search")) {
00382           AST::Call* c = flatAnn[i]->getCall();
00383           branchWithPlugin(c->args);
00384         } else try {
00385           AST::Call *call = flatAnn[i]->getCall("int_search");
00386           AST::Array *args = call->getArgs(4);
00387           AST::Array *vars = args->a[0]->getArray();
00388           int k=vars->a.size();
00389           for (int i=vars->a.size(); i--;)
00390             if (vars->a[i]->isInt())
00391               k--;
00392           IntVarArgs va(k);
00393           k=0;
00394           for (unsigned int i=0; i<vars->a.size(); i++) {
00395             if (vars->a[i]->isInt())
00396               continue;
00397             va[k++] = iv[vars->a[i]->getIntVar()];
00398           }
00399           branch(*this, va, ann2ivarsel(args->a[1]), ann2ivalsel(args->a[2]),
00400                  varbo,valbo);
00401         } catch (AST::TypeError& e) {
00402         try {
00403           AST::Call *call = flatAnn[i]->getCall("int_assign");
00404           AST::Array *args = call->getArgs(2);
00405           AST::Array *vars = args->a[0]->getArray();
00406           int k=vars->a.size();
00407           for (int i=vars->a.size(); i--;)
00408             if (vars->a[i]->isInt())
00409               k--;
00410           IntVarArgs va(k);
00411           k=0;
00412           for (unsigned int i=0; i<vars->a.size(); i++) {
00413             if (vars->a[i]->isInt())
00414               continue;
00415             va[k++] = iv[vars->a[i]->getIntVar()];
00416           }
00417           assign(*this, va, ann2asnivalsel(args->a[1]));
00418         } catch (AST::TypeError& e) {
00419           (void) e;
00420           try {
00421             AST::Call *call = flatAnn[i]->getCall("bool_search");
00422             AST::Array *args = call->getArgs(4);
00423             AST::Array *vars = args->a[0]->getArray();
00424             int k=vars->a.size();
00425             for (int i=vars->a.size(); i--;)
00426               if (vars->a[i]->isBool())
00427                 k--;
00428             BoolVarArgs va(k);
00429             k=0;
00430             for (unsigned int i=0; i<vars->a.size(); i++) {
00431               if (vars->a[i]->isBool())
00432                 continue;
00433               va[k++] = bv[vars->a[i]->getBoolVar()];
00434             }
00435             branch(*this, va, ann2ivarsel(args->a[1]), 
00436                    ann2ivalsel(args->a[2]), varbo, valbo);
00437           } catch (AST::TypeError& e) {
00438             (void) e;
00439 #ifdef GECODE_HAS_SET_VARS
00440             try {
00441               AST::Call *call = flatAnn[i]->getCall("set_search");
00442               AST::Array *args = call->getArgs(4);
00443               AST::Array *vars = args->a[0]->getArray();
00444               int k=vars->a.size();
00445               for (int i=vars->a.size(); i--;)
00446                 if (vars->a[i]->isSet())
00447                   k--;
00448               SetVarArgs va(k);
00449               k=0;
00450               for (unsigned int i=0; i<vars->a.size(); i++) {
00451                 if (vars->a[i]->isSet())
00452                   continue;
00453                 va[k++] = sv[vars->a[i]->getSetVar()];
00454               }
00455               branch(*this, va, ann2svarsel(args->a[1]), 
00456                      ann2svalsel(args->a[2]), varbo, valbo);
00457             } catch (AST::TypeError& e) {
00458               (void) e;
00459               if (!ignoreUnknown) {
00460                 err << "Warning, ignored search annotation: ";
00461                 flatAnn[i]->print(err);
00462                 err << std::endl;
00463               }
00464             }
00465 #else
00466             if (!ignoreUnknown) {
00467               err << "Warning, ignored search annotation: ";
00468               flatAnn[i]->print(err);
00469               err << std::endl;
00470             }
00471 #endif
00472           }
00473         }
00474         }
00475       }
00476     }
00477     int introduced = 0;
00478     for (int i=iv.size(); i--;)
00479       if (iv_introduced[i])
00480         introduced++;
00481     IntVarArgs iv_sol(iv.size()-introduced);
00482     IntVarArgs iv_tmp(introduced);
00483     for (int i=iv.size(), j=0, k=0; i--;)
00484       if (iv_introduced[i])
00485         iv_tmp[j++] = iv[i];
00486       else
00487         iv_sol[k++] = iv[i];
00488 
00489     introduced = 0;
00490     for (int i=bv.size(); i--;)
00491       if (bv_introduced[i])
00492         introduced++;
00493     BoolVarArgs bv_sol(bv.size()-introduced);
00494     BoolVarArgs bv_tmp(introduced);
00495     for (int i=bv.size(), j=0, k=0; i--;)
00496       if (bv_introduced[i])
00497         bv_tmp[j++] = bv[i];
00498       else
00499         bv_sol[k++] = bv[i];
00500 
00501     branch(*this, iv_sol, INT_VAR_SIZE_AFC_MIN, INT_VAL_MIN);
00502     branch(*this, bv_sol, INT_VAR_AFC_MAX, INT_VAL_MIN);
00503 #ifdef GECODE_HAS_SET_VARS
00504     introduced = 0;
00505     for (int i=sv.size(); i--;)
00506       if (sv_introduced[i])
00507         introduced++;
00508     SetVarArgs sv_sol(sv.size()-introduced);
00509     SetVarArgs sv_tmp(introduced);
00510     for (int i=sv.size(), j=0, k=0; i--;)
00511       if (sv_introduced[i])
00512         sv_tmp[j++] = sv[i];
00513       else
00514         sv_sol[k++] = sv[i];
00515     branch(*this, sv_sol, SET_VAR_SIZE_AFC_MIN, SET_VAL_MIN_INC);
00516 #endif
00517     branch(*this, iv_tmp, INT_VAR_SIZE_AFC_MIN, INT_VAL_MIN);
00518     branch(*this, bv_tmp, INT_VAR_AFC_MAX, INT_VAL_MIN);
00519 #ifdef GECODE_HAS_SET_VARS
00520     branch(*this, sv_tmp, SET_VAR_SIZE_AFC_MIN, SET_VAL_MIN_INC);
00521 #endif
00522   }
00523 
00524   AST::Array*
00525   FlatZincSpace::solveAnnotations(void) const {
00526     return _solveAnnotations;
00527   }
00528 
00529   void
00530   FlatZincSpace::solve(AST::Array* ann) {
00531     _method = SAT;
00532     _solveAnnotations = ann;
00533   }
00534 
00535   void
00536   FlatZincSpace::minimize(int var, AST::Array* ann) {
00537     _method = MIN;
00538     _optVar = var;
00539     _solveAnnotations = ann;
00540     // Branch on optimization variable to ensure that it is given a value.
00541     AST::Array* args = new AST::Array(4);
00542     args->a[0] = new AST::Array(new AST::IntVar(_optVar));
00543     args->a[1] = new AST::Atom("input_order");
00544     args->a[2] = new AST::Atom("indomain_min");
00545     args->a[3] = new AST::Atom("complete");
00546     AST::Call* c = new AST::Call("int_search", args);
00547     if (!ann)
00548       ann = new AST::Array(c);
00549     else
00550       ann->a.push_back(c);
00551   }
00552 
00553   void
00554   FlatZincSpace::maximize(int var, AST::Array* ann) {
00555     _method = MAX;
00556     _optVar = var;
00557     _solveAnnotations = ann;
00558     // Branch on optimization variable to ensure that it is given a value.
00559     AST::Array* args = new AST::Array(4);
00560     args->a[0] = new AST::Array(new AST::IntVar(_optVar));
00561     args->a[1] = new AST::Atom("input_order");
00562     args->a[2] = new AST::Atom("indomain_min");
00563     args->a[3] = new AST::Atom("complete");
00564     AST::Call* c = new AST::Call("int_search", args);
00565     if (!ann)
00566       ann = new AST::Array(c);
00567     else
00568       ann->a.push_back(c);
00569   }
00570 
00571   FlatZincSpace::~FlatZincSpace(void) {
00572     delete _solveAnnotations;
00573   }
00574 
00575 #ifdef GECODE_HAS_GIST
00576 
00580   template<class Engine>
00581   class GistEngine {
00582   };
00583 
00585   template<typename S>
00586   class GistEngine<DFS<S> > {
00587   public:
00588     static void explore(S* root, const FlatZincOptions& opt,
00589                         Gist::Inspector* i) {
00590       Gecode::Gist::Options o;
00591       o.c_d = opt.c_d(); o.a_d = opt.a_d();
00592       o.inspect.click(i);
00593       (void) Gecode::Gist::dfs(root, o);
00594     }
00595   };
00596 
00598   template<typename S>
00599   class GistEngine<BAB<S> > {
00600   public:
00601     static void explore(S* root, const FlatZincOptions& opt,
00602                         Gist::Inspector* i) {
00603       Gecode::Gist::Options o;
00604       o.c_d = opt.c_d(); o.a_d = opt.a_d();
00605       o.inspect.click(i);
00606       (void) Gecode::Gist::bab(root, o);
00607     }
00608   };
00609 
00611   template<typename S>
00612   class GistEngine<Restart<S> > {
00613   public:
00614     static void explore(S* root, const FlatZincOptions& opt,
00615                         Gist::Inspector* i) {
00616       Gecode::Gist::Options o;
00617       o.c_d = opt.c_d(); o.a_d = opt.a_d();
00618       o.inspect.click(i);
00619       (void) Gecode::Gist::bab(root, o);
00620     }
00621   };
00622 
00624   template<class S>
00625   class FZPrintingInspector
00626    : public Gecode::Gist::TextOutput, public Gecode::Gist::Inspector {
00627   private:
00628     const Printer& p;
00629   public:
00631     FZPrintingInspector(const Printer& p0);
00633     virtual void inspect(const Space& node);
00635     virtual void finalize(void);
00636   };
00637 
00638   template<class S>
00639   FZPrintingInspector<S>::FZPrintingInspector(const Printer& p0)
00640   : TextOutput("Gecode/FlatZinc"), p(p0) {}
00641 
00642   template<class S>
00643   void
00644   FZPrintingInspector<S>::inspect(const Space& node) {
00645     init();
00646     dynamic_cast<const S&>(node).print(getStream(), p);
00647     getStream() << std::endl;
00648   }
00649 
00650   template<class S>
00651   void
00652   FZPrintingInspector<S>::finalize(void) {
00653     Gecode::Gist::TextOutput::finalize();
00654   }
00655 
00656 #endif
00657 
00658   template<template<class> class Engine>
00659   void
00660   FlatZincSpace::runEngine(std::ostream& out, const Printer& p,
00661                             const FlatZincOptions& opt, Support::Timer& t_total) {
00662 #ifdef GECODE_HAS_GIST
00663     if (opt.mode() == SM_GIST) {
00664       FZPrintingInspector<FlatZincSpace> pi(p);
00665       (void) GistEngine<Engine<FlatZincSpace> >::explore(this,opt,&pi);
00666       return;
00667     }
00668 #endif
00669     StatusStatistics sstat;
00670     unsigned int n_p = 0;
00671     Support::Timer t_solve;
00672     t_solve.start();
00673     if (status(sstat) != SS_FAILED) {
00674       n_p = propagators();
00675     }
00676     Search::Options o;
00677     o.stop = Driver::Cutoff::create(opt.node(), opt.fail(), opt.time(), 
00678                                     true);
00679     o.c_d = opt.c_d();
00680     o.a_d = opt.a_d();
00681     o.threads = opt.threads();
00682     Driver::Cutoff::installCtrlHandler(true);
00683     Engine<FlatZincSpace> se(this,o);
00684     int noOfSolutions = _method == SAT ? opt.solutions() : 0;
00685     bool printAll = _method == SAT || opt.allSolutions();
00686     int findSol = noOfSolutions;
00687     FlatZincSpace* sol = NULL;
00688     while (FlatZincSpace* next_sol = se.next()) {
00689       delete sol;
00690       sol = next_sol;
00691       if (printAll) {
00692         sol->print(out, p);
00693         out << "----------" << std::endl;
00694       }
00695       if (--findSol==0)
00696         goto stopped;
00697     }
00698     if (sol && !printAll) {
00699       sol->print(out, p);
00700       out << "----------" << std::endl;
00701     }
00702     if (!se.stopped()) {
00703       if (sol) {
00704         out << "==========" << endl;
00705       } else {
00706         out << "=====UNSATISFIABLE=====" << endl;
00707       }
00708     } else if (!sol) {
00709         out << "=====UNKNOWN=====" << endl;
00710     }
00711     delete sol;
00712     stopped:
00713     Driver::Cutoff::installCtrlHandler(false);
00714     if (opt.mode() == SM_STAT) {
00715       Gecode::Search::Statistics stat = se.statistics();
00716       out << endl
00717            << "%%  runtime:       ";
00718       Driver::stop(t_total,out);
00719       out << endl
00720            << "%%  solvetime:     ";
00721       Driver::stop(t_solve,out);
00722       out << endl
00723            << "%%  solutions:     " 
00724            << std::abs(noOfSolutions - findSol) << endl
00725            << "%%  variables:     " 
00726            << (intVarCount + boolVarCount + setVarCount) << endl
00727            << "%%  propagators:   " << n_p << endl
00728            << "%%  propagations:  " << sstat.propagate+stat.propagate << endl
00729            << "%%  nodes:         " << stat.node << endl
00730            << "%%  failures:      " << stat.fail << endl
00731            << "%%  peak depth:    " << stat.depth << endl
00732            << "%%  peak memory:   "
00733            << static_cast<int>((stat.memory+1023) / 1024) << " KB"
00734            << endl;
00735     }
00736   }
00737 
00738 #ifdef GECODE_HAS_QT
00739   void
00740   FlatZincSpace::branchWithPlugin(AST::Node* ann) {
00741     if (AST::Call* c = dynamic_cast<AST::Call*>(ann)) {
00742       QString pluginName(c->id.c_str());
00743       if (QLibrary::isLibrary(pluginName+".dll")) {
00744         pluginName += ".dll";
00745       } else if (QLibrary::isLibrary(pluginName+".dylib")) {
00746         pluginName = "lib" + pluginName + ".dylib";
00747       } else if (QLibrary::isLibrary(pluginName+".so")) {
00748         // Must check .so after .dylib so that Mac OS uses .dylib
00749         pluginName = "lib" + pluginName + ".so";
00750       }
00751       QPluginLoader pl(pluginName);
00752       QObject* plugin_o = pl.instance();
00753       if (!plugin_o) {
00754         throw FlatZinc::Error("FlatZinc",
00755           "Error loading plugin "+pluginName.toStdString()+
00756           ": "+pl.errorString().toStdString());
00757       }
00758       BranchPlugin* pb = qobject_cast<BranchPlugin*>(plugin_o);
00759       if (!pb) {
00760         throw FlatZinc::Error("FlatZinc",
00761         "Error loading plugin "+pluginName.toStdString()+
00762         ": does not contain valid PluginBrancher");
00763       }
00764       pb->branch(*this, c);
00765     }
00766   }
00767 #else
00768   void
00769   FlatZincSpace::branchWithPlugin(AST::Node* ann) {
00770     throw FlatZinc::Error("FlatZinc",
00771       "Branching with plugins not supported (requires Qt support)");
00772   }
00773 #endif
00774 
00775   void
00776   FlatZincSpace::run(std::ostream& out, const Printer& p,
00777                       const FlatZincOptions& opt, Support::Timer& t_total) {
00778     switch (_method) {
00779     case MIN:
00780     case MAX:
00781       if (opt.search() == FlatZincOptions::FZ_SEARCH_BAB)
00782         runEngine<BAB>(out,p,opt,t_total);
00783       else
00784         runEngine<Restart>(out,p,opt,t_total);
00785       break;
00786     case SAT:
00787       runEngine<DFS>(out,p,opt,t_total);
00788       break;
00789     }
00790   }
00791 
00792   void
00793   FlatZincSpace::constrain(const Space& s) {
00794     if (_method == MIN)
00795       rel(*this, iv[_optVar], IRT_LE, 
00796                  static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00797     else if (_method == MAX)
00798       rel(*this, iv[_optVar], IRT_GR,
00799                  static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00800   }
00801 
00802   Space*
00803   FlatZincSpace::copy(bool share) {
00804     return new FlatZincSpace(share, *this);
00805   }
00806 
00807   FlatZincSpace::Meth
00808   FlatZincSpace::method(void) const {
00809     return _method;
00810   }
00811 
00812   int
00813   FlatZincSpace::optVar(void) const {
00814     return _optVar;
00815   }
00816 
00817   void
00818   FlatZincSpace::print(std::ostream& out, const Printer& p) const {
00819     p.print(out, iv, bv
00820 #ifdef GECODE_HAS_SET_VARS
00821     , sv
00822 #endif
00823     );
00824   }
00825 
00826   void
00827   FlatZincSpace::shrinkArrays(Printer& p) {
00828     p.shrinkArrays(*this, _optVar, iv, bv
00829 #ifdef GECODE_HAS_SET_VARS
00830     , sv
00831 #endif
00832     );
00833   }
00834 
00835   void
00836   Printer::init(AST::Array* output) {
00837     _output = output;
00838   }
00839 
00840   void
00841   Printer::printElem(std::ostream& out,
00842                        AST::Node* ai,
00843                        const Gecode::IntVarArray& iv,
00844                        const Gecode::BoolVarArray& bv
00845 #ifdef GECODE_HAS_SET_VARS
00846                        , const Gecode::SetVarArray& sv
00847 #endif
00848                        ) const {
00849     int k;
00850     if (ai->isInt(k)) {
00851       out << k;
00852     } else if (ai->isIntVar()) {
00853       out << iv[ai->getIntVar()];
00854     } else if (ai->isBoolVar()) {
00855       if (bv[ai->getBoolVar()].min() == 1) {
00856         out << "true";
00857       } else if (bv[ai->getBoolVar()].max() == 0) {
00858         out << "false";
00859       } else {
00860         out << "false..true";
00861       }
00862 #ifdef GECODE_HAS_SET_VARS
00863     } else if (ai->isSetVar()) {
00864       if (!sv[ai->getSetVar()].assigned()) {
00865         out << sv[ai->getSetVar()];
00866         return;
00867       }
00868       SetVarGlbRanges svr(sv[ai->getSetVar()]);
00869       if (!svr()) {
00870         out << "{}";
00871         return;
00872       }
00873       int min = svr.min();
00874       int max = svr.max();
00875       ++svr;
00876       if (svr()) {
00877         SetVarGlbValues svv(sv[ai->getSetVar()]);
00878         int i = svv.val();
00879         out << "{" << i;
00880         ++svv;
00881         for (; svv(); ++svv)
00882           out << ", " << svv.val();
00883         out << "}";
00884       } else {
00885         out << min << ".." << max;
00886       }
00887 #endif
00888     } else if (ai->isBool()) {
00889       out << (ai->getBool() ? "true" : "false");
00890     } else if (ai->isSet()) {
00891       AST::SetLit* s = ai->getSet();
00892       if (s->interval) {
00893         out << s->min << ".." << s->max;
00894       } else {
00895         out << "{";
00896         for (unsigned int i=0; i<s->s.size(); i++) {
00897           out << s->s[i] << (i < s->s.size()-1 ? ", " : "}");
00898         }
00899       }
00900     } else if (ai->isString()) {
00901       std::string s = ai->getString();
00902       for (unsigned int i=0; i<s.size(); i++) {
00903         if (s[i] == '\\' && i<s.size()-1) {
00904           switch (s[i+1]) {
00905           case 'n': out << "\n"; break;
00906           case '\\': out << "\\"; break;
00907           case 't': out << "\t"; break;
00908           default: out << "\\" << s[i+1];
00909           }
00910           i++;
00911         } else {
00912           out << s[i];
00913         }
00914       }
00915     }
00916   }
00917 
00918   void
00919   Printer::print(std::ostream& out,
00920                    const Gecode::IntVarArray& iv,
00921                    const Gecode::BoolVarArray& bv
00922 #ifdef GECODE_HAS_SET_VARS
00923                    ,
00924                    const Gecode::SetVarArray& sv
00925 #endif
00926                    ) const {
00927     if (_output == NULL)
00928       return;
00929     for (unsigned int i=0; i< _output->a.size(); i++) {
00930       AST::Node* ai = _output->a[i];
00931       if (ai->isArray()) {
00932         AST::Array* aia = ai->getArray();
00933         int size = aia->a.size();
00934         out << "[";
00935         for (int j=0; j<size; j++) {
00936           printElem(out,aia->a[j],iv,bv
00937 #ifdef GECODE_HAS_SET_VARS
00938           ,sv
00939 #endif
00940           );
00941           if (j<size-1)
00942             out << ", ";
00943         }
00944         out << "]";
00945       } else {
00946         printElem(out,ai,iv,bv
00947 #ifdef GECODE_HAS_SET_VARS
00948         ,sv
00949 #endif
00950         );
00951       }
00952     }
00953   }
00954 
00955   void
00956   Printer::shrinkElement(AST::Node* node,
00957                          std::map<int,int>& iv, std::map<int,int>& bv, 
00958                          std::map<int,int>& sv) {
00959     if (node->isIntVar()) {
00960       AST::IntVar* x = static_cast<AST::IntVar*>(node);
00961       if (iv.find(x->i) == iv.end()) {
00962         int newi = iv.size();
00963         iv[x->i] = newi;
00964       }
00965       x->i = iv[x->i];
00966     } else if (node->isBoolVar()) {
00967       AST::BoolVar* x = static_cast<AST::BoolVar*>(node);
00968       if (bv.find(x->i) == bv.end()) {
00969         int newi = bv.size();
00970         bv[x->i] = newi;
00971       }
00972       x->i = bv[x->i];
00973     } else if (node->isSetVar()) {
00974       AST::SetVar* x = static_cast<AST::SetVar*>(node);
00975       if (sv.find(x->i) == sv.end()) {
00976         int newi = sv.size();
00977         sv[x->i] = newi;
00978       }
00979       x->i = sv[x->i];      
00980     }
00981   }
00982 
00983   void
00984   Printer::shrinkArrays(Space& home,
00985                         int& optVar,
00986                         Gecode::IntVarArray& iv,
00987                         Gecode::BoolVarArray& bv
00988 #ifdef GECODE_HAS_SET_VARS
00989                         ,
00990                         Gecode::SetVarArray& sv
00991 #endif
00992                        ) {
00993     if (_output == NULL) {
00994       if (optVar == -1) {
00995         iv = IntVarArray(home, 0);
00996       } else {
00997         IntVar ov = iv[optVar];
00998         iv = IntVarArray(home, 1);
00999         iv[0] = ov;
01000         optVar = 0;
01001       }
01002       bv = BoolVarArray(home, 0);
01003 #ifdef GECODE_HAS_SET_VARS
01004       sv = SetVarArray(home, 0);
01005 #endif
01006       return;
01007     }
01008     std::map<int,int> iv_new;
01009     std::map<int,int> bv_new;
01010     std::map<int,int> sv_new;
01011 
01012     if (optVar != -1) {
01013       iv_new[optVar] = 0;
01014       optVar = 0;
01015     }
01016 
01017     for (unsigned int i=0; i< _output->a.size(); i++) {
01018       AST::Node* ai = _output->a[i];
01019       if (ai->isArray()) {
01020         AST::Array* aia = ai->getArray();
01021         for (unsigned int j=0; j<aia->a.size(); j++) {
01022           shrinkElement(aia->a[j],iv_new,bv_new,sv_new);
01023         }
01024       } else {
01025         shrinkElement(ai,iv_new,bv_new,sv_new);
01026       }
01027     }
01028 
01029     IntVarArgs iva(iv_new.size());
01030     for (map<int,int>::iterator i=iv_new.begin(); i != iv_new.end(); ++i) {
01031       iva[(*i).second] = iv[(*i).first];
01032     }
01033     iv = IntVarArray(home, iva);
01034 
01035     BoolVarArgs bva(bv_new.size());
01036     for (map<int,int>::iterator i=bv_new.begin(); i != bv_new.end(); ++i) {
01037       bva[(*i).second] = bv[(*i).first];
01038     }
01039     bv = BoolVarArray(home, bva);
01040 
01041 #ifdef GECODE_HAS_SET_VARS
01042     SetVarArgs sva(sv_new.size());
01043     for (map<int,int>::iterator i=sv_new.begin(); i != sv_new.end(); ++i) {
01044       sva[(*i).second] = sv[(*i).first];
01045     }
01046     sv = SetVarArray(home, sva);
01047 #endif
01048   }
01049 
01050   Printer::~Printer(void) {
01051     delete _output;
01052   }
01053 
01054 }}
01055 
01056 // STATISTICS: flatzinc-any