Generated on Fri Mar 20 15:55:55 2015 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: 2015-03-17 16:09:10 +0100 (Tue, 17 Mar 2015) $ by $Author: schulte $
00011  *     $Revision: 14446 $
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     int
00231     BoolOption::parse(int argc, char* argv[]) {
00232       if ((argc < 2) || strcmp(argv[1],opt))
00233         return 0;
00234       if (argc == 2) {
00235         // Option without argument
00236         cur = true;
00237         return 1;
00238       } else if (!strcmp(argv[2],"true") || !strcmp(argv[2],"1")) {
00239         cur = true;
00240         return 2;
00241       } else if (!strcmp(argv[2],"false") || !strcmp(argv[2],"0")) {
00242         cur = false;
00243         return 2;
00244       } else {
00245         // Option without argument
00246         cur = true;
00247         return 1;
00248       }
00249       return 0;
00250     }
00251 
00252     void 
00253     BoolOption::help(void) {
00254       using namespace std;
00255       cerr << '\t' << opt << " (optional: false, 0, true, 1) default: " 
00256            << (cur ? "true" : "false") << endl 
00257            << "\t\t" << exp << endl;
00258     }
00259 
00260   
00261   }
00262 
00263   void
00264   BaseOptions::add(Driver::BaseOption& o) {
00265     o.next = NULL;
00266     if (fst == NULL) {
00267       fst=&o;
00268     } else {
00269       lst->next=&o;
00270     }
00271     lst=&o;
00272   }
00273   BaseOptions::BaseOptions(const char* n)
00274     : fst(NULL), lst(NULL), 
00275       _name(Driver::BaseOption::strdup(n)) {}
00276 
00277   void
00278   BaseOptions::name(const char* n) {
00279     Driver::BaseOption::strdel(_name);
00280     _name = Driver::BaseOption::strdup(n);
00281   }
00282 
00283   void
00284   BaseOptions::help(void) {
00285     std::cerr << "Gecode configuration information:" << std::endl
00286               << " - Version: " << GECODE_VERSION << std::endl
00287               << " - Variable types: ";
00288 #ifdef GECODE_HAS_INT_VARS
00289     std::cerr << "BoolVar IntVar ";
00290 #endif
00291 #ifdef GECODE_HAS_SET_VARS
00292     std::cerr << "SetVar ";
00293 #endif
00294 #ifdef GECODE_HAS_FLOAT_VARS
00295     std::cerr << "FloatVar "
00296               << std::endl
00297               << " - Trigonometric and transcendental float constraints: ";
00298 #ifdef GECODE_HAS_MPFR
00299     std::cerr  << "enabled";
00300 #else
00301     std::cerr << "disabled";
00302 #endif
00303 #endif
00304     std::cerr << std::endl;
00305     std::cerr << " - Thread support: ";
00306 #ifdef GECODE_HAS_THREADS
00307     if (Support::Thread::npu() == 1)
00308       std::cerr << "enabled (1 processing unit)";
00309     else
00310       std::cerr << "enabled (" << Support::Thread::npu() 
00311                 << " processing units)";
00312 #else
00313     std::cerr << "disabled";
00314 #endif
00315     std::cerr << std::endl
00316               << " - Gist support: ";
00317 #ifdef GECODE_HAS_GIST
00318     std::cerr << "enabled";
00319 #else
00320     std::cerr << "disabled";
00321 #endif
00322     std::cerr << std::endl << std::endl
00323               << "Options for " << name() << ":" << std::endl
00324               << "\t-help, --help, -?" << std::endl
00325               << "\t\tprint this help message" << std::endl;
00326     for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00327       o->help();
00328   }
00329 
00330   void
00331   BaseOptions::parse(int& argc, char* argv[]) {
00332     int c = argc;
00333     char** v = argv;
00334   next:
00335     for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00336       if (int a = o->parse(c,v)) {
00337         c -= a; v += a;
00338         goto next;
00339       }
00340     if (c >= 2) {
00341       if (!strcmp(v[1],"-help") || !strcmp(v[1],"--help") ||
00342           !strcmp(v[1],"-?")) {
00343         help();
00344         exit(EXIT_SUCCESS);
00345       }
00346     }
00347     // Copy remaining arguments
00348     argc = c;
00349     for (int i=1; i<argc; i++)
00350       argv[i] = v[i];
00351     return;
00352   }
00353   
00354   BaseOptions::~BaseOptions(void) {
00355     Driver::BaseOption::strdel(_name);
00356   }
00357 
00358 
00359   Options::Options(const char* n)
00360     : BaseOptions(n),
00361       
00362       _model("-model","model variants"),
00363       _symmetry("-symmetry","symmetry variants"),
00364       _propagation("-propagation","propagation variants"),
00365       _icl("-icl","integer consistency level",ICL_DEF),
00366       _branching("-branching","branching variants"),
00367       _decay("-decay","decay factor",1.0),
00368       _seed("-seed","random number generator seed",1U),
00369       _step("-step","step distance for float optimization",0.0),
00370       
00371       _search("-search","search engine variants"),
00372       _solutions("-solutions","number of solutions (0 = all)",1),
00373       _threads("-threads","number of threads (0 = #processing units)",
00374                Search::Config::threads),
00375       _c_d("-c-d","recomputation commit distance",Search::Config::c_d),
00376       _a_d("-a-d","recomputation adaptation distance",Search::Config::a_d),
00377       _node("-node","node cutoff (0 = none, solution mode)"),
00378       _fail("-fail","failure cutoff (0 = none, solution mode)"),
00379       _time("-time","time (in ms) cutoff (0 = none, solution mode)"),
00380       _restart("-restart","restart sequence type",RM_NONE),
00381       _r_base("-restart-base","base for geometric restart sequence",1.5),
00382       _r_scale("-restart-scale","scale factor for restart sequence",250),
00383       _nogoods("-nogoods","whether to use no-goods from restarts",false),
00384       _nogoods_limit("-nogoods-limit","depth limit for no-good extraction",
00385                      Search::Config::nogoods_limit),
00386       _interrupt("-interrupt","whether to catch Ctrl-C (true) or not (false)",
00387                  true),
00388       
00389       _mode("-mode","how to execute script",SM_SOLUTION),
00390       _samples("-samples","how many samples (time mode)",1),
00391       _iterations("-iterations","iterations per sample (time mode)",1),
00392       _print_last("-print-last",
00393                   "whether to only print the last solution (solution mode)",
00394                   false),
00395       _out_file("-file-sol", "where to print solutions "
00396                 "(supports stdout, stdlog, stderr)","stdout"),
00397       _log_file("-file-stat", "where to print statistics "
00398                 "(supports stdout, stdlog, stderr)","stdout")
00399   {
00400     
00401     _icl.add(ICL_DEF, "def"); _icl.add(ICL_VAL, "val");
00402     _icl.add(ICL_BND, "bnd"); _icl.add(ICL_DOM, "dom");
00403     
00404     _mode.add(SM_SOLUTION, "solution");
00405     _mode.add(SM_TIME, "time");
00406     _mode.add(SM_STAT, "stat");
00407     _mode.add(SM_GIST, "gist");
00408     
00409     _restart.add(RM_NONE,"none");
00410     _restart.add(RM_CONSTANT,"constant");
00411     _restart.add(RM_LINEAR,"linear");
00412     _restart.add(RM_LUBY,"luby");
00413     _restart.add(RM_GEOMETRIC,"geometric");
00414     
00415     add(_model); add(_symmetry); add(_propagation); add(_icl); 
00416     add(_branching); add(_decay); add(_seed); add(_step);
00417     add(_search); add(_solutions); add(_threads); add(_c_d); add(_a_d);
00418     add(_node); add(_fail); add(_time); add(_interrupt);
00419     add(_restart); add(_r_base); add(_r_scale); 
00420     add(_nogoods); add(_nogoods_limit);
00421     add(_mode); add(_iterations); add(_samples); add(_print_last);
00422     add(_out_file); add(_log_file);
00423   }
00424 
00425   
00426   SizeOptions::SizeOptions(const char* e)
00427     : Options(e), _size(0) {}
00428   
00429   void
00430   SizeOptions::help(void) {
00431     Options::help();
00432     std::cerr << "\t(unsigned int) default: " << size() << std::endl
00433               << "\t\twhich version/size for script" << std::endl;
00434   }
00435 
00436   void
00437   SizeOptions::parse(int& argc, char* argv[]) {
00438     Options::parse(argc,argv);
00439     if (argc < 2)
00440       return;
00441     size(static_cast<unsigned int>(atoi(argv[1])));
00442   }
00443 
00444 
00445 
00446   InstanceOptions::InstanceOptions(const char* e)
00447     : Options(e), _inst(NULL) {}
00448   
00449   void
00450   InstanceOptions::instance(const char* s) {
00451     Driver::BaseOption::strdel(_inst);
00452     _inst = Driver::BaseOption::strdup(s);
00453   }
00454 
00455   void
00456   InstanceOptions::help(void) {
00457     Options::help();
00458     std::cerr << "\t(string) default: " << instance() << std::endl
00459               << "\t\twhich instance for script" << std::endl;
00460   }
00461 
00462   void
00463   InstanceOptions::parse(int& argc, char* argv[]) {
00464     Options::parse(argc,argv);
00465     if (argc < 2)
00466       return;
00467     instance(argv[1]);
00468   }
00469 
00470   InstanceOptions::~InstanceOptions(void) {
00471     Driver::BaseOption::strdel(_inst);
00472   }
00473 
00474 }
00475 
00476 // STATISTICS: driver-any