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("post",a,e)) { cur |= TE_POST; }
00375 else if (!strncmp("none",a,e) ||
00376 !strncmp("false",a,e) ||
00377 !strncmp("0",a,e)) { cur = 0; }
00378 else if (!strncmp("all",a,e) ||
00379 !strncmp("1",a,e)) { cur = (TE_INIT |
00380 TE_PRUNE |
00381 TE_FIX |
00382 TE_FAIL |
00383 TE_DONE |
00384 TE_PROPAGATE |
00385 TE_COMMIT |
00386 TE_POST); }
00387 else if (!strncmp("variable",a,e)) { cur = (TE_INIT |
00388 TE_PRUNE |
00389 TE_FIX |
00390 TE_FAIL |
00391 TE_DONE); }
00392 else if (!strncmp("general",a,e)) { cur = (TE_PROPAGATE |
00393 TE_COMMIT |
00394 TE_POST); }
00395 else {
00396 std::cerr << "Wrong argument \"" << a
00397 << "\" for option \"" << iopt << "\""
00398 << std::endl;
00399 exit(EXIT_FAILURE);
00400 }
00401
00402 if (*c == ',') a = c+1; else a = c;
00403
00404 } while (*a != 0);
00405
00406 return 2;
00407 }
00408 return 0;
00409 }
00410
00411 void
00412 TraceOption::help(void) {
00413 using namespace std;
00414 cerr << '\t' << iopt
00415 << " (init,prune,fix,fail,done,propagate,commit,post,none,all,variable,general)"
00416 << " default: ";
00417 if (cur == 0) {
00418 cerr << "none";
00419 } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE |
00420 TE_PROPAGATE | TE_COMMIT | TE_POST)) {
00421 cerr << "all";
00422 } else if (cur == (TE_INIT | TE_PRUNE | TE_FIX | TE_FAIL | TE_DONE)) {
00423 cerr << "variable";
00424 } else if (cur == (TE_PROPAGATE | TE_COMMIT | TE_POST)) {
00425 cerr << "general";
00426 } else {
00427 int f = cur;
00428 if ((f & TE_INIT) != 0) {
00429 cerr << "init";
00430 f -= TE_INIT;
00431 if (f != 0) cerr << ',';
00432 }
00433 if ((f & TE_PRUNE) != 0) {
00434 cerr << "prune";
00435 f -= TE_PRUNE;
00436 if (f != 0) cerr << ',';
00437 }
00438 if ((f & TE_FIX) != 0) {
00439 cerr << "fix";
00440 f -= TE_FIX;
00441 if (f != 0) cerr << ',';
00442 }
00443 if ((f & TE_FAIL) != 0) {
00444 cerr << "fail";
00445 f -= TE_FAIL;
00446 if (f != 0) cerr << ',';
00447 }
00448 if ((f & TE_DONE) != 0) {
00449 cerr << "done";
00450 f -= TE_DONE;
00451 if (f != 0) cerr << ',';
00452 }
00453 if ((f & TE_PROPAGATE) != 0) {
00454 cerr << "propagate";
00455 f -= TE_PROPAGATE;
00456 if (f != 0) cerr << ',';
00457 }
00458 if ((f & TE_COMMIT) != 0) {
00459 cerr << "commit";
00460 f -= TE_COMMIT;
00461 if (f != 0) cerr << ',';
00462 }
00463 if ((f & TE_POST) != 0) {
00464 cerr << "post";
00465 }
00466 }
00467 cerr << endl << "\t\t" << exp << endl;
00468 }
00469
00470
00471 }
00472
00473 void
00474 BaseOptions::add(Driver::BaseOption& o) {
00475 o.next = NULL;
00476 if (fst == NULL) {
00477 fst=&o;
00478 } else {
00479 lst->next=&o;
00480 }
00481 lst=&o;
00482 }
00483 BaseOptions::BaseOptions(const char* n)
00484 : fst(NULL), lst(NULL),
00485 _name(Driver::BaseOption::strdup(n)) {}
00486
00487 void
00488 BaseOptions::name(const char* n) {
00489 Driver::BaseOption::strdel(_name);
00490 _name = Driver::BaseOption::strdup(n);
00491 }
00492
00493 void
00494 BaseOptions::help(void) {
00495 std::cerr << "Gecode configuration information:" << std::endl
00496 << " - Version: " << GECODE_VERSION << std::endl
00497 << " - Variable types: ";
00498 #ifdef GECODE_HAS_INT_VARS
00499 std::cerr << "BoolVar IntVar ";
00500 #endif
00501 #ifdef GECODE_HAS_SET_VARS
00502 std::cerr << "SetVar ";
00503 #endif
00504 #ifdef GECODE_HAS_FLOAT_VARS
00505 std::cerr << "FloatVar "
00506 << std::endl
00507 << " - Trigonometric and transcendental float constraints: ";
00508 #ifdef GECODE_HAS_MPFR
00509 std::cerr << "enabled";
00510 #else
00511 std::cerr << "disabled";
00512 #endif
00513 #endif
00514 std::cerr << std::endl;
00515 std::cerr << " - Thread support: ";
00516 #ifdef GECODE_HAS_THREADS
00517 if (Support::Thread::npu() == 1)
00518 std::cerr << "enabled (1 processing unit)";
00519 else
00520 std::cerr << "enabled (" << Support::Thread::npu()
00521 << " processing units)";
00522 #else
00523 std::cerr << "disabled";
00524 #endif
00525 std::cerr << std::endl
00526 << " - Gist support: ";
00527 #ifdef GECODE_HAS_GIST
00528 std::cerr << "enabled";
00529 #else
00530 std::cerr << "disabled";
00531 #endif
00532 std::cerr << std::endl
00533 << " - CPProfiler support: ";
00534 #ifdef GECODE_HAS_CPPROFILER
00535 std::cerr << "enabled";
00536 #else
00537 std::cerr << "disabled";
00538 #endif
00539 std::cerr << std::endl << std::endl
00540 << "Options for " << name() << ":" << std::endl
00541 << "\t-help, --help, -?" << std::endl
00542 << "\t\tprint this help message" << std::endl;
00543 for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00544 o->help();
00545 }
00546
00547 void
00548 BaseOptions::parse(int& argc, char* argv[]) {
00549 int c = argc;
00550 char** v = argv;
00551 next:
00552 for (Driver::BaseOption* o = fst; o != NULL; o = o->next)
00553 if (int a = o->parse(c,v)) {
00554 c -= a; v += a;
00555 goto next;
00556 }
00557 if (c >= 2) {
00558 if (!strcmp(v[1],"-help") || !strcmp(v[1],"--help") ||
00559 !strcmp(v[1],"-?")) {
00560 help();
00561 exit(EXIT_SUCCESS);
00562 }
00563 }
00564
00565 argc = c;
00566 for (int i=1; i<argc; i++)
00567 argv[i] = v[i];
00568 return;
00569 }
00570
00571 BaseOptions::~BaseOptions(void) {
00572 Driver::BaseOption::strdel(_name);
00573 }
00574
00575
00576 Options::Options(const char* n)
00577 : BaseOptions(n),
00578
00579 _model("model","model variants"),
00580 _symmetry("symmetry","symmetry variants"),
00581 _propagation("propagation","propagation variants"),
00582 _branching("branching","branching variants"),
00583 _decay("decay","decay factor",1.0),
00584 _seed("seed","random number generator seed",1U),
00585 _step("step","step distance for float optimization",0.0),
00586
00587 _search("search","search engine variants"),
00588 _solutions("solutions","number of solutions (0 = all)",1),
00589 _threads("threads","number of threads (0 = #processing units)",
00590 Search::Config::threads),
00591 _c_d("c-d","recomputation commit distance",Search::Config::c_d),
00592 _a_d("a-d","recomputation adaptation distance",Search::Config::a_d),
00593 _d_l("d-l","discrepancy limit for LDS",Search::Config::d_l),
00594 _node("node","node cutoff (0 = none, solution mode)"),
00595 _fail("fail","failure cutoff (0 = none, solution mode)"),
00596 _time("time","time (in ms) cutoff (0 = none, solution mode)"),
00597 _assets("assets","#portfolio assets (#engines)",0),
00598 _slice("slice","portfolio slice (in #failures)",Search::Config::slice),
00599 _restart("restart","restart sequence type",RM_NONE),
00600 _r_base("restart-base","base for geometric restart sequence",
00601 Search::Config::base),
00602 _r_scale("restart-scale","scale factor for restart sequence",
00603 Search::Config::slice),
00604 _nogoods("nogoods","whether to use no-goods from restarts",false),
00605 _nogoods_limit("nogoods-limit","depth limit for no-good extraction",
00606 Search::Config::nogoods_limit),
00607 _relax("relax","probability for relaxing variable", 0.0),
00608 _interrupt("interrupt","whether to catch Ctrl-C (true) or not (false)",
00609 true),
00610
00611 _mode("mode","how to execute script",SM_SOLUTION),
00612 _samples("samples","how many samples (time mode)",1),
00613 _iterations("iterations","iterations per sample (time mode)",1),
00614 _print_last("print-last",
00615 "whether to only print the last solution (solution mode)",
00616 false),
00617 _out_file("file-sol", "where to print solutions "
00618 "(supports stdout, stdlog, stderr)","stdout"),
00619 _log_file("file-stat", "where to print statistics "
00620 "(supports stdout, stdlog, stderr)","stdout"),
00621 _trace(0)
00622
00623 #ifdef GECODE_HAS_CPPROFILER
00624 ,
00625 _profiler_id("cpprofiler-id", "use this execution id with CP-profiler", 0),
00626 _profiler_port("cpprofiler-port", "connect to CP-profiler on this port",
00627 Search::Config::cpprofiler_port),
00628 _profiler_info("cpprofiler-info", "send solution information to CP-profiler", false)
00629 #endif
00630 {
00631
00632 _mode.add(SM_SOLUTION, "solution");
00633 _mode.add(SM_TIME, "time");
00634 _mode.add(SM_STAT, "stat");
00635 _mode.add(SM_GIST, "gist");
00636 _mode.add(SM_CPPROFILER, "cpprofiler");
00637
00638 _restart.add(RM_NONE,"none");
00639 _restart.add(RM_CONSTANT,"constant");
00640 _restart.add(RM_LINEAR,"linear");
00641 _restart.add(RM_LUBY,"luby");
00642 _restart.add(RM_GEOMETRIC,"geometric");
00643
00644 add(_model); add(_symmetry); add(_propagation); add(_ipl);
00645 add(_branching); add(_decay); add(_seed); add(_step);
00646 add(_search); add(_solutions); add(_threads); add(_c_d); add(_a_d);
00647 add(_d_l);
00648 add(_node); add(_fail); add(_time); add(_interrupt);
00649 add(_assets); add(_slice);
00650 add(_restart); add(_r_base); add(_r_scale);
00651 add(_nogoods); add(_nogoods_limit);
00652 add(_relax);
00653 add(_mode); add(_iterations); add(_samples); add(_print_last);
00654 add(_out_file); add(_log_file); add(_trace);
00655 #ifdef GECODE_HAS_CPPROFILER
00656 add(_profiler_id);
00657 add(_profiler_port);
00658 add(_profiler_info);
00659 #endif
00660 }
00661
00662
00663 SizeOptions::SizeOptions(const char* e)
00664 : Options(e), _size(0) {}
00665
00666 void
00667 SizeOptions::help(void) {
00668 Options::help();
00669 std::cerr << "\t(unsigned int) default: " << size() << std::endl
00670 << "\t\twhich version/size for script" << std::endl;
00671 }
00672
00673 void
00674 SizeOptions::parse(int& argc, char* argv[]) {
00675 Options::parse(argc,argv);
00676 if (argc < 2)
00677 return;
00678 size(static_cast<unsigned int>(atoi(argv[1])));
00679 }
00680
00681
00682
00683 InstanceOptions::InstanceOptions(const char* e)
00684 : Options(e), _inst(NULL) {}
00685
00686 void
00687 InstanceOptions::instance(const char* s) {
00688 Driver::BaseOption::strdel(_inst);
00689 _inst = Driver::BaseOption::strdup(s);
00690 }
00691
00692 void
00693 InstanceOptions::help(void) {
00694 Options::help();
00695 std::cerr << "\t(string) default: " << instance() << std::endl
00696 << "\t\twhich instance for script" << std::endl;
00697 }
00698
00699 void
00700 InstanceOptions::parse(int& argc, char* argv[]) {
00701 Options::parse(argc,argv);
00702 if (argc < 2)
00703 return;
00704 instance(argv[1]);
00705 }
00706
00707 InstanceOptions::~InstanceOptions(void) {
00708 Driver::BaseOption::strdel(_inst);
00709 }
00710
00711 }
00712
00713