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
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
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
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
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
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