Generated on Tue Apr 18 10:21:31 2017 for Gecode by doxygen 1.6.3

options.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2004
00008  *
00009  *  Last modified:
00010  *     $Date: 2017-03-17 23:04:57 +0100 (Fri, 17 Mar 2017) $ by $Author: schulte $
00011  *     $Revision: 15597 $
00012  *
00013  *  This file is part of Gecode, the generic constraint
00014  *  development environment:
00015  *     http://www.gecode.org
00016  *
00017  *
00018  *  Permission is hereby granted, free of charge, to any person obtaining
00019  *  a copy of this software and associated documentation files (the
00020  *  "Software"), to deal in the Software without restriction, including
00021  *  without limitation the rights to use, copy, modify, merge, publish,
00022  *  distribute, sublicense, and/or sell copies of the Software, and to
00023  *  permit persons to whom the Software is furnished to do so, subject to
00024  *  the following conditions:
00025  *
00026  *  The above copyright notice and this permission notice shall be
00027  *  included in all copies or substantial portions of the Software.
00028  *
00029  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00030  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00031  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00032  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00033  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00034  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00035  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00036  *
00037  */
00038 
00039 #include <gecode/driver.hh>
00040 
00041 #include <iostream>
00042 #include <iomanip>
00043 
00044 #include <cstdlib>
00045 #include <cstring>
00046 
00047 namespace Gecode {
00048 
00049   namespace Driver {
00050 
00051     /*
00052      * Option baseclass
00053      *
00054      */
00055     char*
00056     BaseOption::strdup(const char* s) {
00057       if (s == NULL)
00058         return NULL;
00059       char* d = heap.alloc<char>(static_cast<unsigned long int>(strlen(s)+1));
00060       (void) strcpy(d,s);
00061       return d;
00062     }
00063 
00064     void
00065     BaseOption::strdel(const char* s) {
00066       if (s == NULL)
00067         return;
00068       heap.rfree(const_cast<char*>(s));
00069     }
00070 
00071     char*
00072     BaseOption::argument(int argc, char* argv[]) const {
00073       if ((argc < 2) || strcmp(argv[1],opt))
00074         return NULL;
00075       if (argc == 2) {
00076         std::cerr << "Missing argument for option \"" << opt << "\""
00077                   << std::endl;
00078         exit(EXIT_FAILURE);
00079       }
00080       return argv[2];
00081     }
00082 
00083     BaseOption::BaseOption(const char* o, const char* e)
00084       : opt(strdup(o)), exp(strdup(e)) {}
00085 
00086     BaseOption::~BaseOption(void) {
00087       strdel(opt);
00088       strdel(exp);
00089     }
00090 
00091 
00092     StringValueOption::StringValueOption(const char* o, const char* e,
00093                                          const char* v)
00094       : BaseOption(o,e), cur(strdup(v)) {}
00095     void
00096     StringValueOption::value(const char* v) {
00097       strdel(cur);
00098       cur = strdup(v);
00099     }
00100     int
00101     StringValueOption::parse(int argc, char* argv[]) {
00102       if (char* a = argument(argc,argv)) {
00103         cur = strdup(a);
00104         return 2;
00105       }
00106       return 0;
00107     }
00108     void
00109     StringValueOption::help(void) {
00110       std::cerr << '\t' << opt << " (string) default: "
00111                 << ((cur == NULL) ? "NONE" : cur) << std::endl
00112                 << "\t\t" << exp << std::endl;
00113     }
00114     StringValueOption::~StringValueOption(void) {
00115       strdel(cur);
00116     }
00117 
00118 
00119 
00120     void
00121     StringOption::add(int v, const char* o, const char* h) {
00122       Value* n = new Value;
00123       n->val  = v;
00124       n->opt  = strdup(o);
00125       n->help = strdup(h);
00126       n->next = NULL;
00127       if (fst == NULL) {
00128         fst = n;
00129       } else {
00130         lst->next = n;
00131       }
00132       lst = n;
00133     }
00134     int
00135     StringOption::parse(int argc, char* argv[]) {
00136       if (char* a = argument(argc,argv)) {
00137         for (Value* v = fst; v != NULL; v = v->next)
00138           if (!strcmp(a,v->opt)) {
00139             cur = v->val;
00140             return 2;
00141           }
00142         std::cerr << "Wrong argument \"" << a
00143                   << "\" for option \"" << opt << "\""
00144                   << std::endl;
00145         exit(EXIT_FAILURE);
00146       }
00147       return 0;
00148     }
00149     void
00150     StringOption::help(void) {
00151       if (fst == NULL)
00152         return;
00153       std::cerr << '\t' << opt << " (";
00154       const char* d = NULL;
00155       for (Value* v = fst; v != NULL; v = v->next) {
00156         std::cerr << v->opt << ((v->next != NULL) ? ", " : "");
00157         if (v->val == cur)
00158           d = v->opt;
00159       }
00160       std::cerr << ")";
00161       if (d != NULL)
00162         std::cerr << " default: " << d;
00163       std::cerr << std::endl << "\t\t" << exp << std::endl;
00164       for (Value* v = fst; v != NULL; v = v->next)
00165         if (v->help != NULL)
00166           std::cerr << "\t\t  " << v->opt << ": " << v->help << std::endl;
00167     }
00168 
00169     StringOption::~StringOption(void) {
00170       Value* v = fst;
00171       while (v != NULL) {
00172         strdel(v->opt);
00173         strdel(v->help);
00174         Value* n = v->next;
00175         delete v;
00176         v = n;
00177       }
00178     }
00179 
00180 
00181     int
00182     IntOption::parse(int argc, char* argv[]) {
00183       if (char* a = argument(argc,argv)) {
00184         cur = atoi(a);
00185         return 2;
00186       }
00187       return 0;
00188     }
00189 
00190     void
00191     IntOption::help(void) {
00192       std::cerr << '\t' << opt << " (int) default: " << cur << std::endl
00193                 << "\t\t" << exp << std::endl;
00194     }
00195 
00196 
00197     int
00198     UnsignedIntOption::parse(int argc, char* argv[]) {
00199       if (char* a = argument(argc,argv)) {
00200         cur = static_cast<unsigned int>(atoi(a));
00201         return 2;
00202       }
00203       return 0;
00204     }
00205 
00206     void
00207     UnsignedIntOption::help(void) {
00208       std::cerr << '\t' << opt << " (unsigned int) default: "
00209                 << cur << std::endl
00210                 << "\t\t" << exp << std::endl;
00211     }
00212 
00213 
00214     int
00215     DoubleOption::parse(int argc, char* argv[]) {
00216       if (char* a = argument(argc,argv)) {
00217         cur = atof(a);
00218         return 2;
00219       }
00220       return 0;
00221     }
00222 
00223     void
00224     DoubleOption::help(void) {
00225       using namespace std;
00226       cerr << '\t' << opt << " (double) default: " << cur << endl
00227            << "\t\t" << exp << endl;
00228     }
00229 
00230 
00231     int
00232     BoolOption::parse(int argc, char* argv[]) {
00233       if ((argc < 2) || strcmp(argv[1],opt))
00234         return 0;
00235       if (argc == 2) {
00236         // Option without argument
00237         cur = true;
00238         return 1;
00239       } else if (!strcmp(argv[2],"true") || !strcmp(argv[2],"1")) {
00240         cur = true;
00241         return 2;
00242       } else if (!strcmp(argv[2],"false") || !strcmp(argv[2],"0")) {
00243         cur = false;
00244         return 2;
00245       } else {
00246         // Option without argument
00247         cur = true;
00248         return 1;
00249       }
00250       return 0;
00251     }
00252 
00253     void
00254     BoolOption::help(void) {
00255       using namespace std;
00256       cerr << '\t' << opt << " (optional: false, 0, true, 1) default: "
00257            << (cur ? "true" : "false") << endl
00258            << "\t\t" << exp << endl;
00259     }
00260 
00261     /*
00262      * Integer propagation level option
00263      *
00264      */
00265     IplOption::IplOption(IntPropLevel ipl)
00266       : BaseOption("-ipl","integer propagation level (comma-separated list)"),
00267         cur(ipl) {}
00268 
00269     int
00270     IplOption::parse(int argc, char* argv[]) {
00271       if (char* a = argument(argc,argv)) {
00272         int b = IPL_DEF;
00273         int m = IPL_DEF;
00274         do {
00275           // Search for a comma
00276           char* c = a;
00277           while ((*c != ',') && (*c != 0))
00278             c++;
00279           unsigned int e = static_cast<unsigned int>(c-a);
00280           if      (!strncmp("def",a,e))      { b = IPL_DEF; }
00281           else if (!strncmp("val",a,e))      { b = IPL_VAL; }
00282           else if (!strncmp("bnd",a,e))      { b = IPL_BND; }
00283           else if (!strncmp("dom",a,e))      { b = IPL_DOM; }
00284           else if (!strncmp("speed",a,e))    { m |= IPL_SPEED; }
00285           else if (!strncmp("memory",a,e))   { m |= IPL_MEMORY; }
00286           else if (!strncmp("basic",a,e))    { m |= IPL_BASIC; }
00287           else if (!strncmp("advanced",a,e)) { m |= IPL_ADVANCED; }
00288           else {
00289             std::cerr << "Wrong argument \"" << a
00290                       << "\" for option \"" << opt << "\""
00291                       << std::endl;
00292             exit(EXIT_FAILURE);
00293           }
00294 
00295           if (*c == ',') a = c+1; else a = c;
00296 
00297         } while (*a != 0);
00298 
00299         cur = static_cast<IntPropLevel>(b | m);
00300         return 2;
00301       }
00302       return 0;
00303     }
00304 
00305     void
00306     IplOption::help(void) {
00307       using namespace std;
00308       cerr << '\t' << opt
00309            << " (def,val,bnd,dom,speed,memory,basic,advanced)" << endl
00310            << "\t\tdefault: ";
00311       switch (vbd(cur)) {
00312       case IPL_DEF: cerr << "def"; break;
00313       case IPL_VAL: cerr << "val"; break;
00314       case IPL_BND: cerr << "bnd"; break;
00315       case IPL_DOM: cerr << "dom"; break;
00316       default: GECODE_NEVER;
00317       }
00318       if (cur & IPL_SPEED)    cerr << ",speed";
00319       if (cur & IPL_MEMORY)   cerr << ",memory";
00320       if (cur & IPL_BASIC)    cerr << ",basic";
00321       if (cur & IPL_ADVANCED) cerr << ",advanced";
00322       cerr << endl << "\t\t" << exp << endl;
00323     }
00324 
00325 
00326     /*
00327      * Trace flag option
00328      *
00329      */
00330     TraceOption::TraceOption(int f)
00331       : BaseOption("-trace","trace flags (comma-separated list)"),
00332         cur(f) {}
00333 
00334     int
00335     TraceOption::parse(int argc, char* argv[]) {
00336       if (char* a = argument(argc,argv)) {
00337         cur = 0;
00338         do {
00339           // Search for a comma
00340           char* c = a;
00341           while ((*c != ',') && (*c != 0))
00342             c++;
00343           unsigned int e = static_cast<unsigned int>(c-a);
00344           if      (!strncmp("init",a,e))      { cur |= TE_INIT; }
00345           else if (!strncmp("prune",a,e))     { cur |= TE_PRUNE; }
00346           else if (!strncmp("fix",a,e))       { cur |= TE_FIX; }
00347           else if (!strncmp("fail",a,e))      { cur |= TE_FAIL; }
00348           else if (!strncmp("done",a,e))      { cur |= TE_DONE ; }
00349           else if (!strncmp("propagate",a,e)) { cur |= TE_PROPAGATE; }
00350           else if (!strncmp("commit",a,e))    { cur |= TE_COMMIT; }
00351           else if (!strncmp("none",a,e) ||
00352                    !strncmp("false",a,e) ||
00353                    !strncmp("0",a,e))         { cur = 0; }
00354           else if (!strncmp("all",a,e) ||
00355                    !strncmp("1",a,e))         { cur = (TE_INIT |
00356                                                        TE_PRUNE |
00357                                                        TE_FIX |
00358                                                        TE_FAIL |
00359                                                        TE_DONE |
00360                                                        TE_PROPAGATE |
00361                                                        TE_COMMIT); }
00362           else if (!strncmp("variable",a,e))  { cur = (TE_INIT |
00363                                                        TE_PRUNE |
00364                                                        TE_FIX |
00365                                                        TE_FAIL |
00366                                                        TE_DONE); }
00367           else if (!strncmp("general",a,e))   { cur = (TE_PROPAGATE |
00368                                                        TE_COMMIT); }
00369           else {
00370             std::cerr << "Wrong argument \"" << a
00371                       << "\" for option \"" << opt << "\""
00372                       << std::endl;
00373             exit(EXIT_FAILURE);
00374           }
00375 
00376           if (*c == ',') a = c+1; else a = c;
00377 
00378         } while (*a != 0);
00379 
00380         return 2;
00381       }
00382       return 0;
00383     }
00384 
00385     void
00386     TraceOption::help(void) {
00387       using namespace std;
00388       cerr << '\t' << opt
00389            << " (init,prune,fix,fail,done,propagate,commit,none,all,variable,general)"
00390            << " default: ";
00391       if (cur == 0) {
00392         cerr << "none";
00393       } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE |
00394                          TE_PROPAGATE | TE_COMMIT)) {
00395         cerr << "all";
00396       } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE)) {
00397         cerr << "variable";
00398       } else if (cur == (TE_PROPAGATE | TE_COMMIT)) {
00399         cerr << "general";
00400       } else {
00401         int f = cur;
00402         if ((f & TE_INIT) != 0) {
00403           cerr << "init";
00404           f -= TE_INIT;
00405           if (f != 0) cerr << ',';
00406         }
00407         if ((f & TE_PRUNE) != 0) {
00408           cerr << "prune";
00409           f -= TE_PRUNE;
00410           if (f != 0) cerr << ',';
00411         }
00412         if ((f & TE_FIX) != 0) {
00413           cerr << "fix";
00414           f -= TE_FIX;
00415           if (f != 0) cerr << ',';
00416         }
00417         if ((f & TE_FAIL) != 0) {
00418           cerr << "fail";
00419           f -= TE_FAIL;
00420           if (f != 0) cerr << ',';
00421         }
00422         if ((f & TE_DONE) != 0) {
00423           cerr << "done";
00424           f -= TE_DONE;
00425           if (f != 0) cerr << ',';
00426         }
00427         if ((f & TE_PROPAGATE) != 0) {
00428           cerr << "propagate";
00429           f -= TE_PROPAGATE;
00430           if (f != 0) cerr << ',';
00431         }
00432         if ((f & TE_COMMIT) != 0) {
00433           cerr << "commit";
00434         }
00435       }
00436       cerr << endl << "\t\t" << exp << endl;
00437     }
00438 
00439 
00440   }
00441 
00442   void
00443   BaseOptions::add(Driver::BaseOption& o) {
00444     o.next = NULL;
00445     if (fst == NULL) {
00446       fst=&o;
00447     } else {
00448       lst->next=&o;
00449     }
00450     lst=&o;
00451   }
00452   BaseOptions::BaseOptions(const char* n)
00453     : fst(NULL), lst(NULL),
00454       _name(Driver::BaseOption::strdup(n)) {}
00455 
00456   void
00457   BaseOptions::name(const char* n) {
00458     Driver::BaseOption::strdel(_name);
00459     _name = Driver::BaseOption::strdup(n);
00460   }
00461 
00462   void
00463   BaseOptions::help(void) {
00464     std::cerr << "Gecode configuration information:" << std::endl
00465               << " - Version: " << GECODE_VERSION << std::endl
00466               << " - Variable types: ";
00467 #ifdef GECODE_HAS_INT_VARS
00468     std::cerr << "BoolVar IntVar ";
00469 #endif
00470 #ifdef GECODE_HAS_SET_VARS
00471     std::cerr << "SetVar ";
00472 #endif
00473 #ifdef GECODE_HAS_FLOAT_VARS
00474     std::cerr << "FloatVar "
00475               << std::endl
00476               << " - Trigonometric and transcendental float constraints: ";
00477 #ifdef GECODE_HAS_MPFR
00478     std::cerr  << "enabled";
00479 #else
00480     std::cerr << "disabled";
00481 #endif
00482 #endif
00483     std::cerr << std::endl;
00484     std::cerr << " - Thread support: ";
00485 #ifdef GECODE_HAS_THREADS
00486     if (Support::Thread::npu() == 1)
00487       std::cerr << "enabled (1 processing unit)";
00488     else
00489       std::cerr << "enabled (" << Support::Thread::npu()
00490                 << " processing units)";
00491 #else
00492     std::cerr << "disabled";
00493 #endif
00494     std::cerr << std::endl
00495               << " - Gist support: ";
00496 #ifdef GECODE_HAS_GIST
00497     std::cerr << "enabled";
00498 #else
00499     std::cerr << "disabled";
00500 #endif
00501     std::cerr << std::endl << std::endl
00502               << "Options for " << name() << ":" << std::endl
00503               << "\t-help, --help, -?" << std::endl
00504               << "\t\tprint this help message" << std::endl;
00505     for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00506       o->help();
00507   }
00508 
00509   void
00510   BaseOptions::parse(int& argc, char* argv[]) {
00511     int c = argc;
00512     char** v = argv;
00513   next:
00514     for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00515       if (int a = o->parse(c,v)) {
00516         c -= a; v += a;
00517         goto next;
00518       }
00519     if (c >= 2) {
00520       if (!strcmp(v[1],"-help") || !strcmp(v[1],"--help") ||
00521           !strcmp(v[1],"-?")) {
00522         help();
00523         exit(EXIT_SUCCESS);
00524       }
00525     }
00526     // Copy remaining arguments
00527     argc = c;
00528     for (int i=1; i<argc; i++)
00529       argv[i] = v[i];
00530     return;
00531   }
00532 
00533   BaseOptions::~BaseOptions(void) {
00534     Driver::BaseOption::strdel(_name);
00535   }
00536 
00537 
00538   Options::Options(const char* n)
00539     : BaseOptions(n),
00540 
00541       _model("-model","model variants"),
00542       _symmetry("-symmetry","symmetry variants"),
00543       _propagation("-propagation","propagation variants"),
00544       _branching("-branching","branching variants"),
00545       _decay("-decay","decay factor",1.0),
00546       _seed("-seed","random number generator seed",1U),
00547       _step("-step","step distance for float optimization",0.0),
00548 
00549       _search("-search","search engine variants"),
00550       _solutions("-solutions","number of solutions (0 = all)",1),
00551       _threads("-threads","number of threads (0 = #processing units)",
00552                Search::Config::threads),
00553       _c_d("-c-d","recomputation commit distance",Search::Config::c_d),
00554       _a_d("-a-d","recomputation adaptation distance",Search::Config::a_d),
00555       _d_l("-d-l","discrepancy limit for LDS",Search::Config::d_l),
00556       _node("-node","node cutoff (0 = none, solution mode)"),
00557       _fail("-fail","failure cutoff (0 = none, solution mode)"),
00558       _time("-time","time (in ms) cutoff (0 = none, solution mode)"),
00559       _assets("-assets","#portfolio assets (#engines)",0),
00560       _slice("-slice","portfolio slice (in #failures)",Search::Config::slice),
00561       _restart("-restart","restart sequence type",RM_NONE),
00562       _r_base("-restart-base","base for geometric restart sequence",
00563               Search::Config::base),
00564       _r_scale("-restart-scale","scale factor for restart sequence",
00565                Search::Config::slice),
00566       _nogoods("-nogoods","whether to use no-goods from restarts",false),
00567       _nogoods_limit("-nogoods-limit","depth limit for no-good extraction",
00568                      Search::Config::nogoods_limit),
00569       _relax("-relax","probability for relaxing variable", 0.0),
00570       _interrupt("-interrupt","whether to catch Ctrl-C (true) or not (false)",
00571                  true),
00572 
00573       _mode("-mode","how to execute script",SM_SOLUTION),
00574       _samples("-samples","how many samples (time mode)",1),
00575       _iterations("-iterations","iterations per sample (time mode)",1),
00576       _print_last("-print-last",
00577                   "whether to only print the last solution (solution mode)",
00578                   false),
00579       _out_file("-file-sol", "where to print solutions "
00580                 "(supports stdout, stdlog, stderr)","stdout"),
00581       _log_file("-file-stat", "where to print statistics "
00582                 "(supports stdout, stdlog, stderr)","stdout"),
00583       _trace(0)
00584   {
00585 
00586     _mode.add(SM_SOLUTION, "solution");
00587     _mode.add(SM_TIME, "time");
00588     _mode.add(SM_STAT, "stat");
00589     _mode.add(SM_GIST, "gist");
00590 
00591     _restart.add(RM_NONE,"none");
00592     _restart.add(RM_CONSTANT,"constant");
00593     _restart.add(RM_LINEAR,"linear");
00594     _restart.add(RM_LUBY,"luby");
00595     _restart.add(RM_GEOMETRIC,"geometric");
00596 
00597     add(_model); add(_symmetry); add(_propagation); add(_ipl);
00598     add(_branching); add(_decay); add(_seed); add(_step);
00599     add(_search); add(_solutions); add(_threads); add(_c_d); add(_a_d);
00600     add(_d_l);
00601     add(_node); add(_fail); add(_time); add(_interrupt);
00602     add(_assets); add(_slice);
00603     add(_restart); add(_r_base); add(_r_scale);
00604     add(_nogoods); add(_nogoods_limit);
00605     add(_relax);
00606     add(_mode); add(_iterations); add(_samples); add(_print_last);
00607     add(_out_file); add(_log_file); add(_trace);
00608   }
00609 
00610 
00611   SizeOptions::SizeOptions(const char* e)
00612     : Options(e), _size(0) {}
00613 
00614   void
00615   SizeOptions::help(void) {
00616     Options::help();
00617     std::cerr << "\t(unsigned int) default: " << size() << std::endl
00618               << "\t\twhich version/size for script" << std::endl;
00619   }
00620 
00621   void
00622   SizeOptions::parse(int& argc, char* argv[]) {
00623     Options::parse(argc,argv);
00624     if (argc < 2)
00625       return;
00626     size(static_cast<unsigned int>(atoi(argv[1])));
00627   }
00628 
00629 
00630 
00631   InstanceOptions::InstanceOptions(const char* e)
00632     : Options(e), _inst(NULL) {}
00633 
00634   void
00635   InstanceOptions::instance(const char* s) {
00636     Driver::BaseOption::strdel(_inst);
00637     _inst = Driver::BaseOption::strdup(s);
00638   }
00639 
00640   void
00641   InstanceOptions::help(void) {
00642     Options::help();
00643     std::cerr << "\t(string) default: " << instance() << std::endl
00644               << "\t\twhich instance for script" << std::endl;
00645   }
00646 
00647   void
00648   InstanceOptions::parse(int& argc, char* argv[]) {
00649     Options::parse(argc,argv);
00650     if (argc < 2)
00651       return;
00652     instance(argv[1]);
00653   }
00654 
00655   InstanceOptions::~InstanceOptions(void) {
00656     Driver::BaseOption::strdel(_inst);
00657   }
00658 
00659 }
00660 
00661 // STATISTICS: driver-any