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
00041 #include <gecode/search.hh>
00042
00043 #include <vector>
00044 #include <string>
00045 using namespace std;
00046
00047 namespace Gecode { namespace FlatZinc {
00048
00049 IntSet vs2is(IntVarSpec* vs) {
00050 if (vs->assigned) {
00051 return IntSet(vs->i,vs->i);
00052 }
00053 if (vs->domain()) {
00054 AST::SetLit* sl = vs->domain.some();
00055 if (sl->interval) {
00056 return IntSet(sl->min, sl->max);
00057 } else {
00058 int* newdom = heap.alloc<int>(static_cast<unsigned long int>(sl->s.size()));
00059 for (int i=sl->s.size(); i--;)
00060 newdom[i] = sl->s[i];
00061 IntSet ret(newdom, sl->s.size());
00062 heap.free(newdom, static_cast<unsigned long int>(sl->s.size()));
00063 return ret;
00064 }
00065 }
00066 return IntSet(Int::Limits::min, Int::Limits::max);
00067 }
00068
00069 int vs2bsl(BoolVarSpec* bs) {
00070 if (bs->assigned) {
00071 return bs->i;
00072 }
00073 if (bs->domain()) {
00074 AST::SetLit* sl = bs->domain.some();
00075 assert(sl->interval);
00076 return std::min(1, std::max(0, sl->min));
00077 }
00078 return 0;
00079 }
00080
00081 int vs2bsh(BoolVarSpec* bs) {
00082 if (bs->assigned) {
00083 return bs->i;
00084 }
00085 if (bs->domain()) {
00086 AST::SetLit* sl = bs->domain.some();
00087 assert(sl->interval);
00088 return std::max(0, std::min(1, sl->max));
00089 }
00090 return 1;
00091 }
00092
00093 TieBreakVarBranch<IntVarBranch> ann2ivarsel(AST::Node* ann) {
00094 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00095 if (s->id == "input_order")
00096 return TieBreakVarBranch<IntVarBranch>(INT_VAR_NONE);
00097 if (s->id == "first_fail")
00098 return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MIN);
00099 if (s->id == "anti_first_fail")
00100 return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MAX);
00101 if (s->id == "smallest")
00102 return TieBreakVarBranch<IntVarBranch>(INT_VAR_MIN_MIN);
00103 if (s->id == "largest")
00104 return TieBreakVarBranch<IntVarBranch>(INT_VAR_MAX_MAX);
00105 if (s->id == "occurrence")
00106 return TieBreakVarBranch<IntVarBranch>(INT_VAR_DEGREE_MAX);
00107 if (s->id == "max_regret")
00108 return TieBreakVarBranch<IntVarBranch>(INT_VAR_REGRET_MIN_MAX);
00109 if (s->id == "most_constrained")
00110 return TieBreakVarBranch<IntVarBranch>(INT_VAR_SIZE_MIN,
00111 INT_VAR_DEGREE_MAX);
00112 if (s->id == "random")
00113 return TieBreakVarBranch<IntVarBranch>(INT_VAR_RND);
00114 }
00115 std::cerr << "Warning, ignored search annotation: ";
00116 ann->print(std::cerr);
00117 std::cerr << std::endl;
00118 return TieBreakVarBranch<IntVarBranch>(INT_VAR_NONE);
00119 }
00120
00121 IntValBranch ann2ivalsel(AST::Node* ann) {
00122 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00123 if (s->id == "indomain_min")
00124 return INT_VAL_MIN;
00125 if (s->id == "indomain_max")
00126 return INT_VAL_MAX;
00127 if (s->id == "indomain_median")
00128 return INT_VAL_MED;
00129 if (s->id == "indomain_split")
00130 return INT_VAL_SPLIT_MIN;
00131 if (s->id == "indomain_reverse_split")
00132 return INT_VAL_SPLIT_MAX;
00133 if (s->id == "indomain_random")
00134 return INT_VAL_RND;
00135 if (s->id == "indomain")
00136 return INT_VALUES_MIN;
00137 }
00138 std::cerr << "Warning, ignored search annotation: ";
00139 ann->print(std::cerr);
00140 std::cerr << std::endl;
00141 return INT_VAL_MIN;
00142 }
00143
00144 #ifdef GECODE_HAS_SET_VARS
00145 SetVarBranch ann2svarsel(AST::Node* ann) {
00146 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00147 if (s->id == "input_order")
00148 return SET_VAR_NONE;
00149 if (s->id == "first_fail")
00150 return SET_VAR_SIZE_MIN;
00151 if (s->id == "anti_first_fail")
00152 return SET_VAR_SIZE_MAX;
00153 if (s->id == "smallest")
00154 return SET_VAR_MIN_MIN;
00155 if (s->id == "largest")
00156 return SET_VAR_MIN_MAX;
00157 }
00158 std::cerr << "Warning, ignored search annotation: ";
00159 ann->print(std::cerr);
00160 std::cerr << std::endl;
00161 return SET_VAR_NONE;
00162 }
00163
00164 SetValBranch ann2svalsel(AST::Node* ann) {
00165 if (AST::Atom* s = dynamic_cast<AST::Atom*>(ann)) {
00166 if (s->id == "indomain_min")
00167 return SET_VAL_MIN_INC;
00168 if (s->id == "indomain_max")
00169 return SET_VAL_MAX_INC;
00170 if (s->id == "outdomain_min")
00171 return SET_VAL_MIN_EXC;
00172 if (s->id == "outdomain_max")
00173 return SET_VAL_MAX_EXC;
00174 }
00175 std::cerr << "Warning, ignored search annotation: ";
00176 ann->print(std::cerr);
00177 std::cerr << std::endl;
00178 return SET_VAL_MIN_INC;
00179 }
00180 #endif
00181
00182 FlatZincSpace::FlatZincSpace(bool share, FlatZincSpace& f)
00183 : Space(share, f) {
00184 _optVar = f._optVar;
00185 _method = f._method;
00186 iv.update(*this, share, f.iv);
00187 bv.update(*this, share, f.bv);
00188 #ifdef GECODE_HAS_SET_VARS
00189 sv.update(*this, share, f.sv);
00190 #endif
00191 }
00192
00193 FlatZincSpace::FlatZincSpace(int intVars,
00194 int boolVars,
00195 #ifdef GECODE_HAS_SET_VARS
00196 int setVars)
00197 #else
00198 int)
00199 #endif
00200 : intVarCount(0), boolVarCount(0), setVarCount(0),
00201 iv(*this, intVars), iv_introduced(intVars),
00202 bv(*this, boolVars), bv_introduced(boolVars)
00203 #ifdef GECODE_HAS_SET_VARS
00204 , sv(*this, setVars),
00205 sv_introduced(setVars)
00206 #endif
00207 {}
00208
00209 void
00210 FlatZincSpace::newIntVar(IntVarSpec* vs) {
00211 if (vs->alias) {
00212 iv[intVarCount++] = iv[vs->i];
00213 } else {
00214 iv[intVarCount++] = IntVar(*this, vs2is(vs));
00215 }
00216 iv_introduced[intVarCount-1] = vs->introduced;
00217 }
00218
00219 void
00220 FlatZincSpace::newBoolVar(BoolVarSpec* vs) {
00221 if (vs->alias) {
00222 bv[boolVarCount++] = bv[vs->i];
00223 } else {
00224 bv[boolVarCount++] = BoolVar(*this, vs2bsl(vs), vs2bsh(vs));
00225 }
00226 bv_introduced[boolVarCount-1] = vs->introduced;
00227 }
00228
00229 #ifdef GECODE_HAS_SET_VARS
00230 void
00231 FlatZincSpace::newSetVar(SetVarSpec* vs) {
00232 if (vs->alias) {
00233 sv[setVarCount++] = sv[vs->i];
00234 } else if (vs->assigned) {
00235 assert(vs->upperBound());
00236 AST::SetLit* vsv = vs->upperBound.some();
00237 if (vsv->interval) {
00238 IntSet d(vsv->min, vsv->max);
00239 sv[setVarCount++] = SetVar(*this, d, d);
00240 } else {
00241 int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00242 for (int i=vsv->s.size(); i--; )
00243 is[i] = vsv->s[i];
00244 IntSet d(is, vsv->s.size());
00245 heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00246 sv[setVarCount++] = SetVar(*this, d, d);
00247 }
00248 } else if (vs->upperBound()) {
00249 AST::SetLit* vsv = vs->upperBound.some();
00250 if (vsv->interval) {
00251 IntSet d(vsv->min, vsv->max);
00252 sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00253 } else {
00254 int* is = heap.alloc<int>(static_cast<unsigned long int>(vsv->s.size()));
00255 for (int i=vsv->s.size(); i--; )
00256 is[i] = vsv->s[i];
00257 IntSet d(is, vsv->s.size());
00258 heap.free(is,static_cast<unsigned long int>(vsv->s.size()));
00259 sv[setVarCount++] = SetVar(*this, IntSet::empty, d);
00260 }
00261 } else {
00262 sv[setVarCount++] = SetVar(*this, IntSet::empty,
00263 IntSet(Set::Limits::min,
00264 Set::Limits::max));
00265 }
00266 sv_introduced[setVarCount-1] = vs->introduced;
00267 }
00268 #else
00269 void
00270 FlatZincSpace::newSetVar(SetVarSpec*) {
00271 throw FlatZinc::Error("Gecode", "set variables not supported");
00272 }
00273 #endif
00274
00275 void
00276 FlatZincSpace::postConstraint(const ConExpr& ce, AST::Node* ann) {
00277 try {
00278 registry().post(*this, ce, ann);
00279 } catch (Gecode::Exception& e) {
00280 throw FlatZinc::Error("Gecode", e.what());
00281 } catch (AST::TypeError& e) {
00282 throw FlatZinc::Error("Type error", e.what());
00283 }
00284 }
00285
00286 void flattenAnnotations(AST::Array* ann, std::vector<AST::Node*>& out) {
00287 for (unsigned int i=0; i<ann->a.size(); i++) {
00288 if (ann->a[i]->isCall("seq_search")) {
00289 AST::Call* c = ann->a[i]->getCall();
00290 if (c->args->isArray())
00291 flattenAnnotations(c->args->getArray(), out);
00292 else
00293 out.push_back(c->args);
00294 } else {
00295 out.push_back(ann->a[i]);
00296 }
00297 }
00298 }
00299
00300 void
00301 FlatZincSpace::parseSolveAnn(AST::Array* ann) {
00302 bool hadSearchAnnotation = false;
00303 if (ann) {
00304 std::vector<AST::Node*> flatAnn;
00305 flattenAnnotations(ann, flatAnn);
00306
00307 for (unsigned int i=0; i<flatAnn.size(); i++) {
00308 try {
00309 AST::Call *call = flatAnn[i]->getCall("int_search");
00310 AST::Array *args = call->getArgs(4);
00311 AST::Array *vars = args->a[0]->getArray();
00312 IntVarArgs va(vars->a.size());
00313 for (int i=vars->a.size(); i--; )
00314 va[i] = iv[vars->a[i]->getIntVar()];
00315 branch(*this, va, ann2ivarsel(args->a[1]), ann2ivalsel(args->a[2]));
00316 hadSearchAnnotation = true;
00317 } catch (AST::TypeError& e) {
00318 (void) e;
00319 try {
00320 AST::Call *call = flatAnn[i]->getCall("bool_search");
00321 AST::Array *args = call->getArgs(4);
00322 AST::Array *vars = args->a[0]->getArray();
00323 BoolVarArgs va(vars->a.size());
00324 for (int i=vars->a.size(); i--; )
00325 va[i] = bv[vars->a[i]->getBoolVar()];
00326 branch(*this, va, ann2ivarsel(args->a[1]),
00327 ann2ivalsel(args->a[2]));
00328 hadSearchAnnotation = true;
00329 } catch (AST::TypeError& e) {
00330 (void) e;
00331 #ifdef GECODE_HAS_SET_VARS
00332 try {
00333 AST::Call *call = flatAnn[i]->getCall("set_search");
00334 AST::Array *args = call->getArgs(4);
00335 AST::Array *vars = args->a[0]->getArray();
00336 SetVarArgs va(vars->a.size());
00337 for (int i=vars->a.size(); i--; )
00338 va[i] = sv[vars->a[i]->getSetVar()];
00339 branch(*this, va, ann2svarsel(args->a[1]),
00340 ann2svalsel(args->a[2]));
00341 hadSearchAnnotation = true;
00342 } catch (AST::TypeError& e) {
00343 (void) e;
00344 std::cerr << "Warning, ignored search annotation: ";
00345 flatAnn[i]->print(std::cerr);
00346 std::cerr << std::endl;
00347 }
00348 #else
00349 std::cerr << "Warning, ignored search annotation: ";
00350 flatAnn[i]->print(std::cerr);
00351 std::cerr << std::endl;
00352 #endif
00353 }
00354 }
00355 }
00356 }
00357 if (!hadSearchAnnotation) {
00358 int countUp = 0;
00359 int countDown = iv.size()-1;
00360 IntVarArgs iva(iv.size());
00361 for (int i=0; i<iv.size(); i++)
00362 if (iv_introduced[i])
00363 iva[countDown--] = iv[i];
00364 else
00365 iva[countUp++] = iv[i];
00366 countUp = 0;
00367 countDown = bv.size()-1;
00368 BoolVarArgs bva(bv.size());
00369 for (int i=0; i<bv.size(); i++)
00370 if (bv_introduced[i])
00371 bva[countDown--] = bv[i];
00372 else
00373 bva[countUp++] = bv[i];
00374 branch(*this, iva, INT_VAR_NONE, INT_VAL_MIN);
00375 branch(*this, bva, INT_VAR_NONE, INT_VAL_MIN);
00376 #ifdef GECODE_HAS_SET_VARS
00377 countUp = 0;
00378 countDown = sv.size()-1;
00379 SetVarArgs sva(sv.size());
00380 for (int i=0; i<sv.size(); i++)
00381 if (sv_introduced[i])
00382 sva[countDown--] = sv[i];
00383 else
00384 sva[countUp++] = sv[i];
00385 branch(*this, sva, SET_VAR_NONE, SET_VAL_MIN_INC);
00386 #endif
00387 }
00388 }
00389
00390 void
00391 FlatZincSpace::solve(AST::Array* ann) {
00392 _method = SAT;
00393 parseSolveAnn(ann);
00394 }
00395
00396 void
00397 FlatZincSpace::minimize(int var, AST::Array* ann) {
00398 _method = MIN;
00399 _optVar = var;
00400 parseSolveAnn(ann);
00401
00402 IntVarArgs optVar(1);
00403 optVar[0] = iv[_optVar];
00404 branch(*this, optVar, INT_VAR_NONE, INT_VAL_MIN);
00405 }
00406
00407 void
00408 FlatZincSpace::maximize(int var, AST::Array* ann) {
00409 _method = MAX;
00410 _optVar = var;
00411 parseSolveAnn(ann);
00412
00413 IntVarArgs optVar(1);
00414 optVar[0] = iv[_optVar];
00415 branch(*this, optVar, INT_VAR_NONE, INT_VAL_MAX);
00416 }
00417
00418 #ifdef GECODE_HAS_GIST
00419
00423 template<class Engine>
00424 class GistEngine {
00425 };
00426
00428 template<typename S>
00429 class GistEngine<DFS<S> > {
00430 public:
00431 static void explore(S* root, Gist::Inspector* i) {
00432 Gecode::Gist::Options o; o.inspect.click(i);
00433 (void) Gecode::Gist::dfs(root, o);
00434 }
00435 };
00436
00438 template<typename S>
00439 class GistEngine<LDS<S> > {
00440 public:
00441 static void explore(S* root, Gist::Inspector* i) {
00442 Gecode::Gist::Options o; o.inspect.click(i);
00443 (void) Gecode::Gist::dfs(root, o);
00444 }
00445 };
00446
00448 template<typename S>
00449 class GistEngine<BAB<S> > {
00450 public:
00451 static void explore(S* root, Gist::Inspector* i) {
00452 Gecode::Gist::Options o; o.inspect.click(i);
00453 (void) Gecode::Gist::bab(root, o);
00454 }
00455 };
00456
00458 template<typename S>
00459 class GistEngine<Restart<S> > {
00460 public:
00461 static void explore(S* root, Gist::Inspector* i) {
00462 Gecode::Gist::Options o; o.inspect.click = i;
00463 (void) Gecode::Gist::bab(root, o);
00464 }
00465 };
00466
00468 template<class S>
00469 class FZPrintingInspector : public Gecode::Gist::TextInspector {
00470 private:
00471 const Printer& p;
00472 public:
00474 FZPrintingInspector(const Printer& p0);
00476 virtual void inspect(const Space& node);
00477 };
00478
00479 template<class S>
00480 FZPrintingInspector<S>::FZPrintingInspector(const Printer& p0)
00481 : TextInspector("Gecode/FlatZinc"), p(p0) {}
00482
00483 template<class S>
00484 void
00485 FZPrintingInspector<S>::inspect(const Space& node) {
00486 init();
00487 dynamic_cast<const S&>(node).print(getStream(), p);
00488 getStream() << std::endl;
00489 }
00490
00491 #endif
00492
00493 template<template<class> class Engine>
00494 void
00495 FlatZincSpace::runEngine(std::ostream& out, const Printer& p,
00496 const FlatZincOptions& opt, Support::Timer& t_total) {
00497 #ifdef GECODE_HAS_GIST
00498 if (opt.mode() == SM_GIST) {
00499 FZPrintingInspector<FlatZincSpace> pi(p);
00500 (void) GistEngine<Engine<FlatZincSpace> >::explore(this,&pi);
00501 return;
00502 }
00503 #endif
00504 StatusStatistics sstat;
00505 unsigned int n_p = 0;
00506 Support::Timer t_solve;
00507 t_solve.start();
00508 if (status(sstat) != SS_FAILED) {
00509 n_p = propagators();
00510 }
00511 Search::Options o;
00512 o.stop = Driver::Cutoff::create(opt.node(), opt.fail(), opt.time());
00513 o.c_d = opt.c_d();
00514 o.a_d = opt.a_d();
00515 o.threads = opt.threads();
00516 Engine<FlatZincSpace> se(this,o);
00517 int noOfSolutions = _method == SAT ? opt.solutions() : 0;
00518 int findSol = noOfSolutions;
00519 while (FlatZincSpace* sol = se.next()) {
00520 sol->print(out, p);
00521 out << "----------" << std::endl;
00522 delete sol;
00523 if (--findSol==0)
00524 goto stopped;
00525 }
00526 if (!se.stopped())
00527 out << "==========" << endl;
00528 stopped:
00529 if (opt.mode() == SM_STAT) {
00530 Gecode::Search::Statistics stat = se.statistics();
00531 out << endl
00532 << "%% runtime: ";
00533 Driver::stop(t_total,out);
00534 out << endl
00535 << "%% solvetime: ";
00536 Driver::stop(t_solve,out);
00537 out << endl
00538 << "%% solutions: "
00539 << std::abs(noOfSolutions - findSol) << endl
00540 << "%% variables: "
00541 << (intVarCount + boolVarCount + setVarCount) << endl
00542 << "%% propagators: " << n_p << endl
00543 << "%% propagations: " << sstat.propagate+stat.propagate << endl
00544 << "%% nodes: " << stat.node << endl
00545 << "%% failures: " << stat.fail << endl
00546 << "%% peak depth: " << stat.depth << endl
00547 << "%% peak memory: "
00548 << static_cast<int>((stat.memory+1023) / 1024) << " KB"
00549 << endl;
00550 }
00551 }
00552
00553 void
00554 FlatZincSpace::run(std::ostream& out, const Printer& p,
00555 const FlatZincOptions& opt, Support::Timer& t_total) {
00556 switch (_method) {
00557 case MIN:
00558 case MAX:
00559 runEngine<BAB>(out,p,opt,t_total);
00560 break;
00561 case SAT:
00562 runEngine<DFS>(out,p,opt,t_total);
00563 break;
00564 }
00565 }
00566
00567 void
00568 FlatZincSpace::constrain(const Space& s) {
00569 if (_method == MIN)
00570 rel(*this, iv[_optVar], IRT_LE,
00571 static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00572 else
00573 rel(*this, iv[_optVar], IRT_GR,
00574 static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00575 }
00576
00577 Space*
00578 FlatZincSpace::copy(bool share) {
00579 return new FlatZincSpace(share, *this);
00580 }
00581
00582 FlatZincSpace::Meth
00583 FlatZincSpace::method(void) {
00584 return _method;
00585 }
00586
00587 void
00588 FlatZincSpace::print(std::ostream& out, const Printer& p) const {
00589 p.print(out, iv, bv
00590 #ifdef GECODE_HAS_SET_VARS
00591 , sv
00592 #endif
00593 );
00594 }
00595
00596 void
00597 Printer::init(AST::Array* output) {
00598 _output = output;
00599 }
00600
00601 void
00602 Printer::printElem(std::ostream& out,
00603 AST::Node* ai,
00604 const Gecode::IntVarArray& iv,
00605 const Gecode::BoolVarArray& bv
00606 #ifdef GECODE_HAS_SET_VARS
00607 , const Gecode::SetVarArray& sv
00608 #endif
00609 ) const {
00610 int k;
00611 if (ai->isInt(k)) {
00612 out << k;
00613 } else if (ai->isIntVar()) {
00614 out << iv[ai->getIntVar()];
00615 } else if (ai->isBoolVar()) {
00616 if (bv[ai->getBoolVar()].min() == 1) {
00617 out << "true";
00618 } else if (bv[ai->getBoolVar()].max() == 0) {
00619 out << "false";
00620 } else {
00621 out << "false..true";
00622 }
00623 #ifdef GECODE_HAS_SET_VARS
00624 } else if (ai->isSetVar()) {
00625 if (!sv[ai->getSetVar()].assigned()) {
00626 out << sv[ai->getSetVar()];
00627 return;
00628 }
00629 SetVarGlbRanges svr(sv[ai->getSetVar()]);
00630 if (!svr()) {
00631 out << "{}";
00632 return;
00633 }
00634 int min = svr.min();
00635 int max = svr.max();
00636 ++svr;
00637 if (svr()) {
00638 SetVarGlbValues svv(sv[ai->getSetVar()]);
00639 int i = svv.val();
00640 out << "{" << i;
00641 ++svv;
00642 for (; svv(); ++svv)
00643 out << ", " << svv.val();
00644 out << "}";
00645 } else {
00646 out << min << ".." << max;
00647 }
00648 #endif
00649 } else if (ai->isBool()) {
00650 out << (ai->getBool() ? "true" : "false");
00651 } else if (ai->isSet()) {
00652 AST::SetLit* s = ai->getSet();
00653 if (s->interval) {
00654 out << s->min << ".." << s->max;
00655 } else {
00656 out << "{";
00657 for (unsigned int i=0; i<s->s.size(); i++) {
00658 out << s->s[i] << (i < s->s.size()-1 ? ", " : "}");
00659 }
00660 }
00661 } else if (ai->isString()) {
00662 std::string s = ai->getString();
00663 for (unsigned int i=0; i<s.size(); i++) {
00664 if (s[i] == '\\' && i<s.size()-1) {
00665 switch (s[i+1]) {
00666 case 'n': out << "\n"; break;
00667 case '\\': out << "\\"; break;
00668 case 't': out << "\t"; break;
00669 default: out << "\\" << s[i+1];
00670 }
00671 i++;
00672 } else {
00673 out << s[i];
00674 }
00675 }
00676 }
00677 }
00678
00679 void
00680 Printer::print(std::ostream& out,
00681 const Gecode::IntVarArray& iv,
00682 const Gecode::BoolVarArray& bv
00683 #ifdef GECODE_HAS_SET_VARS
00684 ,
00685 const Gecode::SetVarArray& sv
00686 #endif
00687 ) const {
00688 if (_output == NULL)
00689 return;
00690 for (unsigned int i=0; i< _output->a.size(); i++) {
00691 AST::Node* ai = _output->a[i];
00692 if (ai->isArray()) {
00693 AST::Array* aia = ai->getArray();
00694 int size = aia->a.size();
00695 out << "[";
00696 for (int j=0; j<size; j++) {
00697 printElem(out,aia->a[j],iv,bv
00698 #ifdef GECODE_HAS_SET_VARS
00699 ,sv
00700 #endif
00701 );
00702 if (j<size-1)
00703 out << ", ";
00704 }
00705 out << "]";
00706 } else if (ai->isCall("ifthenelse")) {
00707 AST::Array* aia = ai->getCall("ifthenelse")->getArgs(3);
00708 if (aia->a[0]->isBool()) {
00709 if (aia->a[0]->getBool())
00710 printElem(out, aia->a[1], iv,bv
00711 #ifdef GECODE_HAS_SET_VARS
00712 ,sv
00713 #endif
00714 );
00715 else
00716 printElem(out, aia->a[2], iv,bv
00717 #ifdef GECODE_HAS_SET_VARS
00718 ,sv
00719 #endif
00720 );
00721 } else if (aia->a[0]->isBoolVar()) {
00722 BoolVar b = bv[aia->a[0]->getBoolVar()];
00723 if (b.one())
00724 printElem(out, aia->a[1], iv,bv
00725 #ifdef GECODE_HAS_SET_VARS
00726 ,sv
00727 #endif
00728 );
00729 else if (b.zero())
00730 printElem(out, aia->a[2], iv,bv
00731 #ifdef GECODE_HAS_SET_VARS
00732 ,sv
00733 #endif
00734 );
00735 else
00736 std::cerr << "Error: Condition not fixed." << std::endl;
00737 } else {
00738 std::cerr << "Error: Condition not Boolean." << std::endl;
00739 }
00740 } else {
00741 printElem(out,ai,iv,bv
00742 #ifdef GECODE_HAS_SET_VARS
00743 ,sv
00744 #endif
00745 );
00746 }
00747 }
00748 }
00749
00750 Printer::~Printer(void) {
00751 delete _output;
00752 }
00753
00754 }}
00755
00756