Generated on Mon Nov 30 11:16:08 2009 for Gecode by doxygen 1.5.5

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: 2009-11-27 20:52:10 +0100 (Fri, 27 Nov 2009) $ by $Author: tack $
00011  *     $Revision: 10138 $
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 
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           int k=vars->a.size();
00313           for (int i=vars->a.size(); i--;)
00314             if (vars->a[i]->isInt())
00315               k--;
00316           IntVarArgs va(k);
00317           k=0;
00318           for (unsigned int i=0; i<vars->a.size(); i++) {
00319             if (vars->a[i]->isInt())
00320               continue;
00321             va[k++] = iv[vars->a[i]->getIntVar()];
00322           }
00323           branch(*this, va, ann2ivarsel(args->a[1]), ann2ivalsel(args->a[2]));
00324           hadSearchAnnotation = true;
00325         } catch (AST::TypeError& e) {
00326           (void) e;
00327           try {
00328             AST::Call *call = flatAnn[i]->getCall("bool_search");
00329             AST::Array *args = call->getArgs(4);
00330             AST::Array *vars = args->a[0]->getArray();
00331             int k=vars->a.size();
00332             for (int i=vars->a.size(); i--;)
00333               if (vars->a[i]->isBool())
00334                 k--;
00335             BoolVarArgs va(k);
00336             k=0;
00337             for (unsigned int i=0; i<vars->a.size(); i++) {
00338               if (vars->a[i]->isBool())
00339                 continue;
00340               va[k++] = bv[vars->a[i]->getBoolVar()];
00341             }
00342             branch(*this, va, ann2ivarsel(args->a[1]), 
00343                    ann2ivalsel(args->a[2]));        
00344             hadSearchAnnotation = true;
00345           } catch (AST::TypeError& e) {
00346             (void) e;
00347 #ifdef GECODE_HAS_SET_VARS
00348             try {
00349               AST::Call *call = flatAnn[i]->getCall("set_search");
00350               AST::Array *args = call->getArgs(4);
00351               AST::Array *vars = args->a[0]->getArray();
00352               int k=vars->a.size();
00353               for (int i=vars->a.size(); i--;)
00354                 if (vars->a[i]->isSet())
00355                   k--;
00356               SetVarArgs va(k);
00357               k=0;
00358               for (unsigned int i=0; i<vars->a.size(); i++) {
00359                 if (vars->a[i]->isSet())
00360                   continue;
00361                 va[k++] = sv[vars->a[i]->getSetVar()];
00362               }
00363               branch(*this, va, ann2svarsel(args->a[1]), 
00364                                ann2svalsel(args->a[2]));        
00365               hadSearchAnnotation = true;
00366             } catch (AST::TypeError& e) {
00367               (void) e;
00368               std::cerr << "Warning, ignored search annotation: ";
00369               flatAnn[i]->print(std::cerr);
00370               std::cerr << std::endl;
00371             }
00372 #else
00373             std::cerr << "Warning, ignored search annotation: ";
00374             flatAnn[i]->print(std::cerr);
00375             std::cerr << std::endl;
00376 #endif
00377           }
00378         }
00379       }
00380     }
00381     if (!hadSearchAnnotation) {
00382       int countUp = 0;
00383       int countDown = iv.size()-1;
00384       IntVarArgs iva(iv.size());
00385       for (int i=0; i<iv.size(); i++)
00386         if (iv_introduced[i])
00387           iva[countDown--] = iv[i];
00388         else
00389           iva[countUp++] = iv[i];
00390       countUp = 0;
00391       countDown = bv.size()-1;
00392       BoolVarArgs bva(bv.size());
00393       for (int i=0; i<bv.size(); i++)
00394         if (bv_introduced[i])
00395           bva[countDown--] = bv[i];
00396         else
00397           bva[countUp++] = bv[i];
00398       branch(*this, iva, INT_VAR_NONE, INT_VAL_MIN);
00399       branch(*this, bva, INT_VAR_NONE, INT_VAL_MIN);
00400 #ifdef GECODE_HAS_SET_VARS
00401       countUp = 0;
00402       countDown = sv.size()-1;
00403       SetVarArgs sva(sv.size());
00404       for (int i=0; i<sv.size(); i++)
00405         if (sv_introduced[i])
00406           sva[countDown--] = sv[i];
00407         else
00408           sva[countUp++] = sv[i];
00409       branch(*this, sva, SET_VAR_NONE, SET_VAL_MIN_INC);
00410 #endif
00411     }
00412   }
00413 
00414   void
00415   FlatZincSpace::solve(AST::Array* ann) {
00416     _method = SAT;
00417     parseSolveAnn(ann);
00418   }
00419 
00420   void
00421   FlatZincSpace::minimize(int var, AST::Array* ann) {
00422     _method = MIN;
00423     _optVar = var;
00424     parseSolveAnn(ann);
00425     // Branch on optimization variable to ensure that it is given a value.
00426     IntVarArgs optVar(1);
00427     optVar[0] = iv[_optVar];
00428     branch(*this, optVar, INT_VAR_NONE, INT_VAL_MIN);
00429   }
00430 
00431   void
00432   FlatZincSpace::maximize(int var, AST::Array* ann) {
00433     _method = MAX;
00434     _optVar = var;
00435     parseSolveAnn(ann);
00436     // Branch on optimization variable to ensure that it is given a value.
00437     IntVarArgs optVar(1);
00438     optVar[0] = iv[_optVar];
00439     branch(*this, optVar, INT_VAR_NONE, INT_VAL_MAX);
00440   }
00441 
00442 #ifdef GECODE_HAS_GIST
00443 
00447   template<class Engine>
00448   class GistEngine {
00449   };
00450 
00452   template<typename S>
00453   class GistEngine<DFS<S> > {
00454   public:
00455     static void explore(S* root, Gist::Inspector* i) {
00456       Gecode::Gist::Options o; o.inspect.click(i);
00457       (void) Gecode::Gist::dfs(root, o);
00458     }
00459   };
00460 
00462   template<typename S>
00463   class GistEngine<LDS<S> > {
00464   public:
00465     static void explore(S* root, Gist::Inspector* i) {
00466       Gecode::Gist::Options o; o.inspect.click(i);
00467       (void) Gecode::Gist::dfs(root, o);
00468     }
00469   };
00470 
00472   template<typename S>
00473   class GistEngine<BAB<S> > {
00474   public:
00475     static void explore(S* root, Gist::Inspector* i) {
00476       Gecode::Gist::Options o; o.inspect.click(i);
00477       (void) Gecode::Gist::bab(root, o);
00478     }
00479   };
00480 
00482   template<typename S>
00483   class GistEngine<Restart<S> > {
00484   public:
00485     static void explore(S* root, Gist::Inspector* i) {
00486       Gecode::Gist::Options o; o.inspect.click = i;
00487       (void) Gecode::Gist::bab(root, o);
00488     }
00489   };
00490 
00492   template<class S>
00493   class FZPrintingInspector : public Gecode::Gist::TextInspector {
00494   private:
00495     const Printer& p;
00496   public:
00498     FZPrintingInspector(const Printer& p0);
00500     virtual void inspect(const Space& node);
00501   };
00502 
00503   template<class S>
00504   FZPrintingInspector<S>::FZPrintingInspector(const Printer& p0)
00505   : TextInspector("Gecode/FlatZinc"), p(p0) {}
00506 
00507   template<class S>
00508   void
00509   FZPrintingInspector<S>::inspect(const Space& node) {
00510     init();
00511     dynamic_cast<const S&>(node).print(getStream(), p);
00512     getStream() << std::endl;
00513   }
00514 
00515 #endif
00516 
00517   template<template<class> class Engine>
00518   void
00519   FlatZincSpace::runEngine(std::ostream& out, const Printer& p,
00520                             const FlatZincOptions& opt, Support::Timer& t_total) {
00521 #ifdef GECODE_HAS_GIST
00522     if (opt.mode() == SM_GIST) {
00523       FZPrintingInspector<FlatZincSpace> pi(p);
00524       (void) GistEngine<Engine<FlatZincSpace> >::explore(this,&pi);
00525       return;
00526     }
00527 #endif
00528     StatusStatistics sstat;
00529     unsigned int n_p = 0;
00530     Support::Timer t_solve;
00531     t_solve.start();
00532     if (status(sstat) != SS_FAILED) {
00533       n_p = propagators();
00534     }
00535     Search::Options o;
00536     o.stop = Driver::Cutoff::create(opt.node(), opt.fail(), opt.time());
00537     o.c_d = opt.c_d();
00538     o.a_d = opt.a_d();
00539     o.threads = opt.threads();
00540     Engine<FlatZincSpace> se(this,o);
00541     int noOfSolutions = _method == SAT ? opt.solutions() : 0;
00542     int findSol = noOfSolutions;
00543     while (FlatZincSpace* sol = se.next()) {
00544       sol->print(out, p);
00545       out << "----------" << std::endl;
00546       delete sol;
00547       if (--findSol==0)
00548         goto stopped;
00549     }
00550     if (!se.stopped())
00551       out << "==========" << endl;
00552     stopped:
00553     if (opt.mode() == SM_STAT) {
00554       Gecode::Search::Statistics stat = se.statistics();
00555       out << endl
00556            << "%%  runtime:       ";
00557       Driver::stop(t_total,out);
00558       out << endl
00559            << "%%  solvetime:     ";
00560       Driver::stop(t_solve,out);
00561       out << endl
00562            << "%%  solutions:     " 
00563            << std::abs(noOfSolutions - findSol) << endl
00564            << "%%  variables:     " 
00565            << (intVarCount + boolVarCount + setVarCount) << endl
00566            << "%%  propagators:   " << n_p << endl
00567            << "%%  propagations:  " << sstat.propagate+stat.propagate << endl
00568            << "%%  nodes:         " << stat.node << endl
00569            << "%%  failures:      " << stat.fail << endl
00570            << "%%  peak depth:    " << stat.depth << endl
00571            << "%%  peak memory:   "
00572            << static_cast<int>((stat.memory+1023) / 1024) << " KB"
00573            << endl;
00574     }
00575   }
00576 
00577   void
00578   FlatZincSpace::run(std::ostream& out, const Printer& p,
00579                       const FlatZincOptions& opt, Support::Timer& t_total) {
00580     switch (_method) {
00581     case MIN:
00582     case MAX:
00583       runEngine<BAB>(out,p,opt,t_total);
00584       break;
00585     case SAT:
00586       runEngine<DFS>(out,p,opt,t_total);
00587       break;
00588     }
00589   }
00590 
00591   void
00592   FlatZincSpace::constrain(const Space& s) {
00593     if (_method == MIN)
00594       rel(*this, iv[_optVar], IRT_LE, 
00595                  static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00596     else
00597       rel(*this, iv[_optVar], IRT_GR,
00598                  static_cast<const FlatZincSpace*>(&s)->iv[_optVar].val());
00599   }
00600 
00601   Space*
00602   FlatZincSpace::copy(bool share) {
00603     return new FlatZincSpace(share, *this);
00604   }
00605 
00606   FlatZincSpace::Meth
00607   FlatZincSpace::method(void) {
00608     return _method;
00609   }
00610 
00611   void
00612   FlatZincSpace::print(std::ostream& out, const Printer& p) const {
00613     p.print(out, iv, bv
00614 #ifdef GECODE_HAS_SET_VARS
00615     , sv
00616 #endif
00617     );
00618   }
00619 
00620   void
00621   Printer::init(AST::Array* output) {
00622     _output = output;
00623   }
00624 
00625   void
00626   Printer::printElem(std::ostream& out,
00627                        AST::Node* ai,
00628                        const Gecode::IntVarArray& iv,
00629                        const Gecode::BoolVarArray& bv
00630 #ifdef GECODE_HAS_SET_VARS
00631                        , const Gecode::SetVarArray& sv
00632 #endif
00633                        ) const {
00634     int k;
00635     if (ai->isInt(k)) {
00636       out << k;
00637     } else if (ai->isIntVar()) {
00638       out << iv[ai->getIntVar()];
00639     } else if (ai->isBoolVar()) {
00640       if (bv[ai->getBoolVar()].min() == 1) {
00641         out << "true";
00642       } else if (bv[ai->getBoolVar()].max() == 0) {
00643         out << "false";
00644       } else {
00645         out << "false..true";
00646       }
00647 #ifdef GECODE_HAS_SET_VARS
00648     } else if (ai->isSetVar()) {
00649       if (!sv[ai->getSetVar()].assigned()) {
00650         out << sv[ai->getSetVar()];
00651         return;
00652       }
00653       SetVarGlbRanges svr(sv[ai->getSetVar()]);
00654       if (!svr()) {
00655         out << "{}";
00656         return;
00657       }
00658       int min = svr.min();
00659       int max = svr.max();
00660       ++svr;
00661       if (svr()) {
00662         SetVarGlbValues svv(sv[ai->getSetVar()]);
00663         int i = svv.val();
00664         out << "{" << i;
00665         ++svv;
00666         for (; svv(); ++svv)
00667           out << ", " << svv.val();
00668         out << "}";
00669       } else {
00670         out << min << ".." << max;
00671       }
00672 #endif
00673     } else if (ai->isBool()) {
00674       out << (ai->getBool() ? "true" : "false");
00675     } else if (ai->isSet()) {
00676       AST::SetLit* s = ai->getSet();
00677       if (s->interval) {
00678         out << s->min << ".." << s->max;
00679       } else {
00680         out << "{";
00681         for (unsigned int i=0; i<s->s.size(); i++) {
00682           out << s->s[i] << (i < s->s.size()-1 ? ", " : "}");
00683         }
00684       }
00685     } else if (ai->isString()) {
00686       std::string s = ai->getString();
00687       for (unsigned int i=0; i<s.size(); i++) {
00688         if (s[i] == '\\' && i<s.size()-1) {
00689           switch (s[i+1]) {
00690           case 'n': out << "\n"; break;
00691           case '\\': out << "\\"; break;
00692           case 't': out << "\t"; break;
00693           default: out << "\\" << s[i+1];
00694           }
00695           i++;
00696         } else {
00697           out << s[i];
00698         }
00699       }
00700     }
00701   }
00702 
00703   void
00704   Printer::print(std::ostream& out,
00705                    const Gecode::IntVarArray& iv,
00706                    const Gecode::BoolVarArray& bv
00707 #ifdef GECODE_HAS_SET_VARS
00708                    ,
00709                    const Gecode::SetVarArray& sv
00710 #endif
00711                    ) const {
00712     if (_output == NULL)
00713       return;
00714     for (unsigned int i=0; i< _output->a.size(); i++) {
00715       AST::Node* ai = _output->a[i];
00716       if (ai->isArray()) {
00717         AST::Array* aia = ai->getArray();
00718         int size = aia->a.size();
00719         out << "[";
00720         for (int j=0; j<size; j++) {
00721           printElem(out,aia->a[j],iv,bv
00722 #ifdef GECODE_HAS_SET_VARS
00723           ,sv
00724 #endif
00725           );
00726           if (j<size-1)
00727             out << ", ";
00728         }
00729         out << "]";
00730       } else if (ai->isCall("ifthenelse")) {
00731         AST::Array* aia = ai->getCall("ifthenelse")->getArgs(3);
00732         if (aia->a[0]->isBool()) {
00733           if (aia->a[0]->getBool())
00734             printElem(out, aia->a[1], iv,bv
00735 #ifdef GECODE_HAS_SET_VARS
00736             ,sv
00737 #endif
00738             );
00739           else
00740             printElem(out, aia->a[2], iv,bv
00741 #ifdef GECODE_HAS_SET_VARS
00742             ,sv
00743 #endif
00744             );
00745         } else if (aia->a[0]->isBoolVar()) {
00746           BoolVar b = bv[aia->a[0]->getBoolVar()];
00747           if (b.one())
00748             printElem(out, aia->a[1], iv,bv
00749 #ifdef GECODE_HAS_SET_VARS
00750             ,sv
00751 #endif
00752             );
00753           else if (b.zero())
00754             printElem(out, aia->a[2], iv,bv
00755 #ifdef GECODE_HAS_SET_VARS
00756             ,sv
00757 #endif
00758             );
00759           else
00760             std::cerr << "Error: Condition not fixed." << std::endl;
00761         } else {
00762           std::cerr << "Error: Condition not Boolean." << std::endl;        
00763         }
00764       } else {
00765         printElem(out,ai,iv,bv
00766 #ifdef GECODE_HAS_SET_VARS
00767         ,sv
00768 #endif
00769         );
00770       }
00771     }
00772   }
00773 
00774   Printer::~Printer(void) {
00775     delete _output;
00776   }
00777 
00778 }}
00779 
00780 // STATISTICS: flatzinc-any