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 #include <gecode/driver.hh>
00036
00037 #include <iostream>
00038 #include <iomanip>
00039
00040 #include <cstdlib>
00041 #include <cstring>
00042
00043 namespace Gecode {
00044
00045 namespace Driver {
00046
00047
00048
00049
00050
00051 char*
00052 BaseOption::strdup(const char* s) {
00053 if (s == NULL)
00054 return NULL;
00055 char* d = heap.alloc<char>(static_cast<unsigned long int>(strlen(s)+1));
00056 (void) strcpy(d,s);
00057 return d;
00058 }
00059
00060 char*
00061 BaseOption::stredup(const char* s) {
00062 if (s == NULL)
00063 return NULL;
00064 char* d = heap.alloc<char>(static_cast<unsigned long int>(strlen(s)+2));
00065 d[0] = '-';
00066 (void) strcpy(d+1,s);
00067 return d;
00068 }
00069
00070 void
00071 BaseOption::strdel(const char* s) {
00072 if (s == NULL)
00073 return;
00074 heap.rfree(const_cast<char*>(s));
00075 }
00076
00077 char*
00078 BaseOption::argument(int argc, char* argv[]) const {
00079 if (argc < 2)
00080 return NULL;
00081 const char* s = argv[1];
00082 if (s[0] == '-') {
00083 s++;
00084 if (s[0] == '-')
00085 s++;
00086 } else {
00087 return NULL;
00088 }
00089 if (strcmp(s,eopt))
00090 return NULL;
00091 if (argc == 2) {
00092 std::cerr << "Missing argument for option \"" << iopt << "\""
00093 << std::endl;
00094 exit(EXIT_FAILURE);
00095 }
00096 return argv[2];
00097 }
00098
00099 BaseOption::BaseOption(const char* o, const char* e)
00100 : eopt(strdup(o)), iopt(stredup(o)), exp(strdup(e)) {}
00101
00102 BaseOption::~BaseOption(void) {
00103 strdel(eopt);
00104 strdel(iopt);
00105 strdel(exp);
00106 }
00107
00108
00109 StringValueOption::StringValueOption(const char* o, const char* e,
00110 const char* v)
00111 : BaseOption(o,e), cur(strdup(v)) {}
00112 void
00113 StringValueOption::value(const char* v) {
00114 strdel(cur);
00115 cur = strdup(v);
00116 }
00117 int
00118 StringValueOption::parse(int argc, char* argv[]) {
00119 if (char* a = argument(argc,argv)) {
00120 cur = strdup(a);
00121 return 2;
00122 }
00123 return 0;
00124 }
00125 void
00126 StringValueOption::help(void) {
00127 std::cerr << '\t' << iopt << " (string) default: "
00128 << ((cur == NULL) ? "NONE" : cur) << std::endl
00129 << "\t\t" << exp << std::endl;
00130 }
00131 StringValueOption::~StringValueOption(void) {
00132 strdel(cur);
00133 }
00134
00135
00136
00137 void
00138 StringOption::add(int v, const char* o, const char* h) {
00139 Value* n = new Value;
00140 n->val = v;
00141 n->opt = strdup(o);
00142 n->help = strdup(h);
00143 n->next = NULL;
00144 if (fst == NULL) {
00145 fst = n;
00146 } else {
00147 lst->next = n;
00148 }
00149 lst = n;
00150 }
00151 int
00152 StringOption::parse(int argc, char* argv[]) {
00153 if (char* a = argument(argc,argv)) {
00154 for (Value* v = fst; v != NULL; v = v->next)
00155 if (!strcmp(a,v->opt)) {
00156 cur = v->val;
00157 return 2;
00158 }
00159 std::cerr << "Wrong argument \"" << a
00160 << "\" for option \"" << iopt << "\""
00161 << std::endl;
00162 exit(EXIT_FAILURE);
00163 }
00164 return 0;
00165 }
00166 void
00167 StringOption::help(void) {
00168 if (fst == NULL)
00169 return;
00170 std::cerr << '\t' << iopt << " (";
00171 const char* d = NULL;
00172 for (Value* v = fst; v != NULL; v = v->next) {
00173 std::cerr << v->opt << ((v->next != NULL) ? ", " : "");
00174 if (v->val == cur)
00175 d = v->opt;
00176 }
00177 std::cerr << ")";
00178 if (d != NULL)
00179 std::cerr << " default: " << d;
00180 std::cerr << std::endl << "\t\t" << exp << std::endl;
00181 for (Value* v = fst; v != NULL; v = v->next)
00182 if (v->help != NULL)
00183 std::cerr << "\t\t " << v->opt << ": " << v->help << std::endl;
00184 }
00185
00186 StringOption::~StringOption(void) {
00187 Value* v = fst;
00188 while (v != NULL) {
00189 strdel(v->opt);
00190 strdel(v->help);
00191 Value* n = v->next;
00192 delete v;
00193 v = n;
00194 }
00195 }
00196
00197
00198 int
00199 IntOption::parse(int argc, char* argv[]) {
00200 if (char* a = argument(argc,argv)) {
00201 cur = atoi(a);
00202 return 2;
00203 }
00204 return 0;
00205 }
00206
00207 void
00208 IntOption::help(void) {
00209 std::cerr << '\t' << iopt << " (int) default: " << cur << std::endl
00210 << "\t\t" << exp << std::endl;
00211 }
00212
00213
00214 int
00215 UnsignedIntOption::parse(int argc, char* argv[]) {
00216 if (char* a = argument(argc,argv)) {
00217 cur = static_cast<unsigned int>(atoi(a));
00218 return 2;
00219 }
00220 return 0;
00221 }
00222
00223 void
00224 UnsignedIntOption::help(void) {
00225 std::cerr << '\t' << iopt << " (unsigned int) default: "
00226 << cur << std::endl
00227 << "\t\t" << exp << std::endl;
00228 }
00229
00230
00231 int
00232 DoubleOption::parse(int argc, char* argv[]) {
00233 if (char* a = argument(argc,argv)) {
00234 cur = atof(a);
00235 return 2;
00236 }
00237 return 0;
00238 }
00239
00240 void
00241 DoubleOption::help(void) {
00242 using namespace std;
00243 cerr << '\t' << iopt << " (double) default: " << cur << endl
00244 << "\t\t" << exp << endl;
00245 }
00246
00247
00248 int
00249 BoolOption::parse(int argc, char* argv[]) {
00250 if (argc < 2)
00251 return 0;
00252 const char* s = argv[1];
00253 if (s[0] == '-') {
00254 s++;
00255 if (s[0] == '-')
00256 s++;
00257 } else {
00258 return 0;
00259 }
00260 if (strcmp(s,eopt))
00261 return 0;
00262 if (argc == 2) {
00263
00264 cur = true;
00265 return 1;
00266 } else if (!strcmp(argv[2],"true") || !strcmp(argv[2],"1")) {
00267 cur = true;
00268 return 2;
00269 } else if (!strcmp(argv[2],"false") || !strcmp(argv[2],"0")) {
00270 cur = false;
00271 return 2;
00272 } else {
00273
00274 cur = true;
00275 return 1;
00276 }
00277 return 0;
00278 }
00279
00280 void
00281 BoolOption::help(void) {
00282 using namespace std;
00283 cerr << '\t' << iopt << " (optional: false, 0, true, 1) default: "
00284 << (cur ? "true" : "false") << endl
00285 << "\t\t" << exp << endl;
00286 }
00287
00288
00289
00290
00291
00292 IplOption::IplOption(IntPropLevel ipl)
00293 : BaseOption("ipl","integer propagation level (comma-separated list)"),
00294 cur(ipl) {}
00295
00296 int
00297 IplOption::parse(int argc, char* argv[]) {
00298 if (char* a = argument(argc,argv)) {
00299 int b = IPL_DEF;
00300 int m = IPL_DEF;
00301 do {
00302
00303 char* c = a;
00304 while ((*c != ',') && (*c != 0))
00305 c++;
00306 unsigned int e = static_cast<unsigned int>(c-a);
00307 if (!strncmp("def",a,e)) { b = IPL_DEF; }
00308 else if (!strncmp("val",a,e)) { b = IPL_VAL; }
00309 else if (!strncmp("bnd",a,e)) { b = IPL_BND; }
00310 else if (!strncmp("dom",a,e)) { b = IPL_DOM; }
00311 else if (!strncmp("basic",a,e)) { m |= IPL_BASIC; }
00312 else if (!strncmp("advanced",a,e)) { m |= IPL_ADVANCED; }
00313 else {
00314 std::cerr << "Wrong argument \"" << a
00315 << "\" for option \"" << iopt << "\""
00316 << std::endl;
00317 exit(EXIT_FAILURE);
00318 }
00319
00320 if (*c == ',') a = c+1; else a = c;
00321
00322 } while (*a != 0);
00323
00324 cur = static_cast<IntPropLevel>(b | m);
00325 return 2;
00326 }
00327 return 0;
00328 }
00329
00330 void
00331 IplOption::help(void) {
00332 using namespace std;
00333 cerr << '\t' << iopt
00334 << " (def,val,bnd,dom,basic,advanced)" << endl
00335 << "\t\tdefault: ";
00336 switch (vbd(cur)) {
00337 case IPL_DEF: cerr << "def"; break;
00338 case IPL_VAL: cerr << "val"; break;
00339 case IPL_BND: cerr << "bnd"; break;
00340 case IPL_DOM: cerr << "dom"; break;
00341 default: GECODE_NEVER;
00342 }
00343 if (cur & IPL_BASIC) cerr << ",basic";
00344 if (cur & IPL_ADVANCED) cerr << ",advanced";
00345 cerr << endl << "\t\t" << exp << endl;
00346 }
00347
00348
00349
00350
00351
00352
00353 TraceOption::TraceOption(int f)
00354 : BaseOption("trace","trace flags (comma-separated list)"),
00355 cur(f) {}
00356
00357 int
00358 TraceOption::parse(int argc, char* argv[]) {
00359 if (char* a = argument(argc,argv)) {
00360 cur = 0;
00361 do {
00362
00363 char* c = a;
00364 while ((*c != ',') && (*c != 0))
00365 c++;
00366 unsigned int e = static_cast<unsigned int>(c-a);
00367 if (!strncmp("init",a,e)) { cur |= TE_INIT; }
00368 else if (!strncmp("prune",a,e)) { cur |= TE_PRUNE; }
00369 else if (!strncmp("fix",a,e)) { cur |= TE_FIX; }
00370 else if (!strncmp("fail",a,e)) { cur |= TE_FAIL; }
00371 else if (!strncmp("done",a,e)) { cur |= TE_DONE ; }
00372 else if (!strncmp("propagate",a,e)) { cur |= TE_PROPAGATE; }
00373 else if (!strncmp("commit",a,e)) { cur |= TE_COMMIT; }
00374 else if (!strncmp("none",a,e) ||
00375 !strncmp("false",a,e) ||
00376 !strncmp("0",a,e)) { cur = 0; }
00377 else if (!strncmp("all",a,e) ||
00378 !strncmp("1",a,e)) { cur = (TE_INIT |
00379 TE_PRUNE |
00380 TE_FIX |
00381 TE_FAIL |
00382 TE_DONE |
00383 TE_PROPAGATE |
00384 TE_COMMIT); }
00385 else if (!strncmp("variable",a,e)) { cur = (TE_INIT |
00386 TE_PRUNE |
00387 TE_FIX |
00388 TE_FAIL |
00389 TE_DONE); }
00390 else if (!strncmp("general",a,e)) { cur = (TE_PROPAGATE |
00391 TE_COMMIT); }
00392 else {
00393 std::cerr << "Wrong argument \"" << a
00394 << "\" for option \"" << iopt << "\""
00395 << std::endl;
00396 exit(EXIT_FAILURE);
00397 }
00398
00399 if (*c == ',') a = c+1; else a = c;
00400
00401 } while (*a != 0);
00402
00403 return 2;
00404 }
00405 return 0;
00406 }
00407
00408 void
00409 TraceOption::help(void) {
00410 using namespace std;
00411 cerr << '\t' << iopt
00412 << " (init,prune,fix,fail,done,propagate,commit,none,all,variable,general)"
00413 << " default: ";
00414 if (cur == 0) {
00415 cerr << "none";
00416 } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE |
00417 TE_PROPAGATE | TE_COMMIT)) {
00418 cerr << "all";
00419 } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE)) {
00420 cerr << "variable";
00421 } else if (cur == (TE_PROPAGATE | TE_COMMIT)) {
00422 cerr << "general";
00423 } else {
00424 int f = cur;
00425 if ((f & TE_INIT) != 0) {
00426 cerr << "init";
00427 f -= TE_INIT;
00428 if (f != 0) cerr << ',';
00429 }
00430 if ((f & TE_PRUNE) != 0) {
00431 cerr << "prune";
00432 f -= TE_PRUNE;
00433 if (f != 0) cerr << ',';
00434 }
00435 if ((f & TE_FIX) != 0) {
00436 cerr << "fix";
00437 f -= TE_FIX;
00438 if (f != 0) cerr << ',';
00439 }
00440 if ((f & TE_FAIL) != 0) {
00441 cerr << "fail";
00442 f -= TE_FAIL;
00443 if (f != 0) cerr << ',';
00444 }
00445 if ((f & TE_DONE) != 0) {
00446 cerr << "done";
00447 f -= TE_DONE;
00448 if (f != 0) cerr << ',';
00449 }
00450 if ((f & TE_PROPAGATE) != 0) {
00451 cerr << "propagate";
00452 f -= TE_PROPAGATE;
00453 if (f != 0) cerr << ',';
00454 }
00455 if ((f & TE_COMMIT) != 0) {
00456 cerr << "commit";
00457 }
00458 }
00459 cerr << endl << "\t\t" << exp << endl;
00460 }
00461
00462
00463 }
00464
00465 void
00466 BaseOptions::add(Driver::BaseOption& o) {
00467 o.next = NULL;
00468 if (fst == NULL) {
00469 fst=&o;
00470 } else {
00471 lst->next=&o;
00472 }
00473 lst=&o;
00474 }
00475 BaseOptions::BaseOptions(const char* n)
00476 : fst(NULL), lst(NULL),
00477 _name(Driver::BaseOption::strdup(n)) {}
00478
00479 void
00480 BaseOptions::name(const char* n) {
00481 Driver::BaseOption::strdel(_name);
00482 _name = Driver::BaseOption::strdup(n);
00483 }
00484
00485 void
00486 BaseOptions::help(void) {
00487 std::cerr << "Gecode configuration information:" << std::endl
00488 << " - Version: " << GECODE_VERSION << std::endl
00489 << " - Variable types: ";
00490 #ifdef GECODE_HAS_INT_VARS
00491 std::cerr << "BoolVar IntVar ";
00492 #endif
00493 #ifdef GECODE_HAS_SET_VARS
00494 std::cerr << "SetVar ";
00495 #endif
00496 #ifdef GECODE_HAS_FLOAT_VARS
00497 std::cerr << "FloatVar "
00498 << std::endl
00499 << " - Trigonometric and transcendental float constraints: ";
00500 #ifdef GECODE_HAS_MPFR
00501 std::cerr << "enabled";
00502 #else
00503 std::cerr << "disabled";
00504 #endif
00505 #endif
00506 std::cerr << std::endl;
00507 std::cerr << " - Thread support: ";
00508 #ifdef GECODE_HAS_THREADS
00509 if (Support::Thread::npu() == 1)
00510 std::cerr << "enabled (1 processing unit)";
00511 else
00512 std::cerr << "enabled (" << Support::Thread::npu()
00513 << " processing units)";
00514 #else
00515 std::cerr << "disabled";
00516 #endif
00517 std::cerr << std::endl
00518 << " - Gist support: ";
00519 #ifdef GECODE_HAS_GIST
00520 std::cerr << "enabled";
00521 #else
00522 std::cerr << "disabled";
00523 #endif
00524 std::cerr << std::endl
00525 << " - CPProfiler support: ";
00526 #ifdef GECODE_HAS_CPPROFILER
00527 std::cerr << "enabled";
00528 #else
00529 std::cerr << "disabled";
00530 #endif
00531 std::cerr << std::endl << std::endl
00532 << "Options for " << name() << ":" << std::endl
00533 << "\t-help, --help, -?" << std::endl
00534 << "\t\tprint this help message" << std::endl;
00535 for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00536 o->help();
00537 }
00538
00539 void
00540 BaseOptions::parse(int& argc, char* argv[]) {
00541 int c = argc;
00542 char** v = argv;
00543 next:
00544 for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00545 if (int a = o->parse(c,v)) {
00546 c -= a; v += a;
00547 goto next;
00548 }
00549 if (c >= 2) {
00550 if (!strcmp(v[1],"-help") || !strcmp(v[1],"--help") ||
00551 !strcmp(v[1],"-?")) {
00552 help();
00553 exit(EXIT_SUCCESS);
00554 }
00555 }
00556
00557 argc = c;
00558 for (int i=1; i<argc; i++)
00559 argv[i] = v[i];
00560 return;
00561 }
00562
00563 BaseOptions::~BaseOptions(void) {
00564 Driver::BaseOption::strdel(_name);
00565 }
00566
00567
00568 Options::Options(const char* n)
00569 : BaseOptions(n),
00570
00571 _model("model","model variants"),
00572 _symmetry("symmetry","symmetry variants"),
00573 _propagation("propagation","propagation variants"),
00574 _branching("branching","branching variants"),
00575 _decay("decay","decay factor",1.0),
00576 _seed("seed","random number generator seed",1U),
00577 _step("step","step distance for float optimization",0.0),
00578
00579 _search("search","search engine variants"),
00580 _solutions("solutions","number of solutions (0 = all)",1),
00581 _threads("threads","number of threads (0 = #processing units)",
00582 Search::Config::threads),
00583 _c_d("c-d","recomputation commit distance",Search::Config::c_d),
00584 _a_d("a-d","recomputation adaptation distance",Search::Config::a_d),
00585 _d_l("d-l","discrepancy limit for LDS",Search::Config::d_l),
00586 _node("node","node cutoff (0 = none, solution mode)"),
00587 _fail("fail","failure cutoff (0 = none, solution mode)"),
00588 _time("time","time (in ms) cutoff (0 = none, solution mode)"),
00589 _assets("assets","#portfolio assets (#engines)",0),
00590 _slice("slice","portfolio slice (in #failures)",Search::Config::slice),
00591 _restart("restart","restart sequence type",RM_NONE),
00592 _r_base("restart-base","base for geometric restart sequence",
00593 Search::Config::base),
00594 _r_scale("restart-scale","scale factor for restart sequence",
00595 Search::Config::slice),
00596 _nogoods("nogoods","whether to use no-goods from restarts",false),
00597 _nogoods_limit("nogoods-limit","depth limit for no-good extraction",
00598 Search::Config::nogoods_limit),
00599 _relax("relax","probability for relaxing variable", 0.0),
00600 _interrupt("interrupt","whether to catch Ctrl-C (true) or not (false)",
00601 true),
00602
00603 _mode("mode","how to execute script",SM_SOLUTION),
00604 _samples("samples","how many samples (time mode)",1),
00605 _iterations("iterations","iterations per sample (time mode)",1),
00606 _print_last("print-last",
00607 "whether to only print the last solution (solution mode)",
00608 false),
00609 _out_file("file-sol", "where to print solutions "
00610 "(supports stdout, stdlog, stderr)","stdout"),
00611 _log_file("file-stat", "where to print statistics "
00612 "(supports stdout, stdlog, stderr)","stdout"),
00613 _trace(0)
00614
00615 #ifdef GECODE_HAS_CPPROFILER
00616 ,
00617 _profiler_id("cpprofiler-id", "use this execution id with CP-profiler", 0),
00618 _profiler_port("cpprofiler-port", "connect to CP-profiler on this port",
00619 Search::Config::cpprofiler_port),
00620 _profiler_info("cpprofiler-info", "send solution information to CP-profiler", false)
00621 #endif
00622 {
00623
00624 _mode.add(SM_SOLUTION, "solution");
00625 _mode.add(SM_TIME, "time");
00626 _mode.add(SM_STAT, "stat");
00627 _mode.add(SM_GIST, "gist");
00628 _mode.add(SM_CPPROFILER, "cpprofiler");
00629
00630 _restart.add(RM_NONE,"none");
00631 _restart.add(RM_CONSTANT,"constant");
00632 _restart.add(RM_LINEAR,"linear");
00633 _restart.add(RM_LUBY,"luby");
00634 _restart.add(RM_GEOMETRIC,"geometric");
00635
00636 add(_model); add(_symmetry); add(_propagation); add(_ipl);
00637 add(_branching); add(_decay); add(_seed); add(_step);
00638 add(_search); add(_solutions); add(_threads); add(_c_d); add(_a_d);
00639 add(_d_l);
00640 add(_node); add(_fail); add(_time); add(_interrupt);
00641 add(_assets); add(_slice);
00642 add(_restart); add(_r_base); add(_r_scale);
00643 add(_nogoods); add(_nogoods_limit);
00644 add(_relax);
00645 add(_mode); add(_iterations); add(_samples); add(_print_last);
00646 add(_out_file); add(_log_file); add(_trace);
00647 #ifdef GECODE_HAS_CPPROFILER
00648 add(_profiler_id);
00649 add(_profiler_port);
00650 add(_profiler_info);
00651 #endif
00652 }
00653
00654
00655 SizeOptions::SizeOptions(const char* e)
00656 : Options(e), _size(0) {}
00657
00658 void
00659 SizeOptions::help(void) {
00660 Options::help();
00661 std::cerr << "\t(unsigned int) default: " << size() << std::endl
00662 << "\t\twhich version/size for script" << std::endl;
00663 }
00664
00665 void
00666 SizeOptions::parse(int& argc, char* argv[]) {
00667 Options::parse(argc,argv);
00668 if (argc < 2)
00669 return;
00670 size(static_cast<unsigned int>(atoi(argv[1])));
00671 }
00672
00673
00674
00675 InstanceOptions::InstanceOptions(const char* e)
00676 : Options(e), _inst(NULL) {}
00677
00678 void
00679 InstanceOptions::instance(const char* s) {
00680 Driver::BaseOption::strdel(_inst);
00681 _inst = Driver::BaseOption::strdup(s);
00682 }
00683
00684 void
00685 InstanceOptions::help(void) {
00686 Options::help();
00687 std::cerr << "\t(string) default: " << instance() << std::endl
00688 << "\t\twhich instance for script" << std::endl;
00689 }
00690
00691 void
00692 InstanceOptions::parse(int& argc, char* argv[]) {
00693 Options::parse(argc,argv);
00694 if (argc < 2)
00695 return;
00696 instance(argv[1]);
00697 }
00698
00699 InstanceOptions::~InstanceOptions(void) {
00700 Driver::BaseOption::strdel(_inst);
00701 }
00702
00703 }
00704
00705