00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
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
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
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
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