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 #include <gecode/driver.hh>
00039 #include <gecode/int.hh>
00040 #include <gecode/minimodel.hh>
00041
00042 #include <fstream>
00043
00044 using namespace Gecode;
00045
00052 typedef int (*order_t)[2];
00053 extern const int order_weight;
00054 extern const int order_color;
00055
00056
00062 extern int csplib_capacities[];
00063 extern unsigned int csplib_ncapacities;
00064 extern unsigned int csplib_maxcapacity;
00065 extern int csplib_loss[];
00066 extern int csplib_orders[][2];
00067 extern unsigned int csplib_ncolors;
00068 extern unsigned int csplib_norders;
00069
00070
00071
00077 class SteelMillOptions : public Options {
00078 private:
00079 unsigned int _size;
00080 int* _capacities;
00081 int _ncapacities;
00082 int _maxcapacity;
00083 int* _loss;
00084 order_t _orders;
00085 int _ncolors;
00086 unsigned int _norders;
00087 public:
00089 SteelMillOptions(const char* n)
00090 : Options(n), _size(csplib_norders),
00091 _capacities(csplib_capacities), _ncapacities(csplib_ncapacities),
00092 _maxcapacity(csplib_maxcapacity),
00093 _loss(csplib_loss), _orders(&(csplib_orders[0])), _ncolors(csplib_ncolors),
00094 _norders(csplib_norders) {}
00096 virtual void help(void);
00098 bool parse(int& argc, char* argv[]);
00099
00101 unsigned int size(void) const { return _size; }
00103 int* capacities(void) const { return _capacities; }
00105 int ncapacities(void) const { return _ncapacities; }
00107 int maxcapacity(void) const { return _maxcapacity; }
00109 int* loss(void) const { return _loss; }
00111 order_t orders(void) const { return _orders; }
00113 int ncolors(void) const { return _ncolors; }
00115 int norders(void) const { return _norders; }
00116 };
00117
00118
00147 class SteelMill : public MinimizeScript {
00148 protected:
00152 int* capacities;
00153 int ncapacities;
00154 int maxcapacity;
00155 int* loss;
00156 int ncolors;
00157 order_t orders;
00158 unsigned int norders;
00159 unsigned int nslabs;
00160
00161
00165 IntVarArray slab,
00166 slabload,
00167 slabcost;
00168 IntVar total_cost;
00169
00170
00171 public:
00173 enum {
00174 BRANCHING_NAIVE,
00175 BRANCHING_SYMMETRY
00176 };
00177
00179 SteelMill(const SteelMillOptions& opt)
00180 :
00181 capacities(opt.capacities()), ncapacities(opt.ncapacities()),
00182 maxcapacity(opt.maxcapacity()), loss(opt.loss()),
00183 ncolors(opt.ncolors()), orders(opt.orders()),
00184 norders(opt.size()), nslabs(opt.size()),
00185
00186 slab(*this, norders, 0,nslabs-1),
00187 slabload(*this, nslabs, 0,45),
00188 slabcost(*this, nslabs, 0, Int::Limits::max),
00189 total_cost(*this, 0, Int::Limits::max)
00190 {
00191
00192 BoolVarArgs boolslab(norders*nslabs);
00193 for (unsigned int i = 0; i < norders; ++i) {
00194 BoolVarArgs tmp(nslabs);
00195 for (int j = nslabs; j--; ) {
00196 boolslab[j + i*nslabs] = tmp[j] = BoolVar(*this, 0, 1);
00197 }
00198 channel(*this, tmp, slab[i]);
00199 }
00200
00201
00202 for (unsigned int s = 0; s < nslabs; ++s) {
00203 IntArgs c(norders);
00204 BoolVarArgs x(norders);
00205 for (int i = norders; i--; ) {
00206 c[i] = orders[i][order_weight];
00207 x[i] = boolslab[s + i*nslabs];
00208 }
00209 linear(*this, c, x, IRT_EQ, slabload[s]);
00210 }
00211
00212 int totalweight = 0;
00213 for (unsigned int i = norders; i-- ; )
00214 totalweight += orders[i][order_weight] ;
00215 linear(*this, slabload, IRT_EQ, totalweight);
00216
00217
00218
00219 IntArgs nofcolor(ncolors);
00220 for (int c = ncolors; c--; ) {
00221 nofcolor[c] = 0;
00222 for (int o = norders; o--; ) {
00223 if (orders[o][order_color] == c) nofcolor[c] += 1;
00224 }
00225 }
00226 BoolVar f(*this, 0, 0);
00227 for (unsigned int s = 0; s < nslabs; ++s) {
00228 BoolVarArgs hascolor(ncolors);
00229 for (int c = ncolors; c--; ) {
00230 if (nofcolor[c]) {
00231 BoolVarArgs hasc(nofcolor[c]);
00232 int pos = 0;
00233 for (int o = norders; o--; ) {
00234 if (orders[o][order_color] == c)
00235 hasc[pos++] = boolslab[s + o*nslabs];
00236 }
00237 assert(pos == nofcolor[c]);
00238 hascolor[c] = BoolVar(*this, 0, 1);
00239 rel(*this, BOT_OR, hasc, hascolor[c]);
00240 } else {
00241 hascolor[c] = f;
00242 }
00243 }
00244 linear(*this, hascolor, IRT_LQ, 2);
00245 }
00246
00247
00248 IntArgs l(maxcapacity, loss);
00249 for (int s = nslabs; s--; ) {
00250 element(*this, l, slabload[s], slabcost[s]);
00251 }
00252 linear(*this, slabcost, IRT_EQ, total_cost);
00253
00254
00255 if (opt.branching() == BRANCHING_SYMMETRY) {
00256
00257 SteelMillBranch::post(*this);
00258 } else {
00259 branch(*this, slab, INT_VAR_MAX_MIN, INT_VAL_MIN);
00260 }
00261 }
00262
00264 virtual void
00265 print(std::ostream& os) const {
00266 os << "What slab=" << slab << std::endl;
00267 os << "Slab load=" << slabload << std::endl;
00268 os << "Slab cost=" << slabcost << std::endl;
00269 os << "Total cost=" << total_cost << std::endl;
00270 int nslabsused = 0;
00271 int nslabscost = 0;
00272 bool unassigned = false;
00273 for (int i = nslabs; i--; ) {
00274 if (!slabload[i].assigned() || !slabcost[i].assigned()) {
00275 unassigned = true;
00276 break;
00277 }
00278 if (slabload[i].min()>0) ++nslabsused;
00279 if (slabcost[i].min()>0) ++nslabscost;
00280 }
00281 if (!unassigned)
00282 os << "Number of slabs used=" << nslabsused
00283 << ", slabs with cost=" << nslabscost
00284 << std::endl;
00285 os << std::endl;
00286 }
00287
00289 SteelMill(bool share, SteelMill& s)
00290 : MinimizeScript(share,s),
00291 capacities(s.capacities), ncapacities(s.ncapacities),
00292 maxcapacity(s.maxcapacity), loss(s.loss),
00293 ncolors(s.ncolors), orders(s.orders),
00294 norders(s.norders), nslabs(s.nslabs) {
00295 slab.update(*this, share, s.slab);
00296 slabload.update(*this, share, s.slabload);
00297 slabcost.update(*this, share, s.slabcost);
00298 total_cost.update(*this, share, s.total_cost);
00299 }
00301 virtual Space*
00302 copy(bool share) {
00303 return new SteelMill(share,*this);
00304 }
00306 virtual IntVar cost(void) const {
00307 return total_cost;
00308 }
00309
00310
00319 class SteelMillBranch : Branching {
00321 mutable int start;
00323 class Description : public BranchingDesc {
00324 public:
00326 int pos;
00328 int val;
00332 Description(const Branching& b, unsigned int a, int pos0, int val0)
00333 : BranchingDesc(b,a), pos(pos0), val(val0) {}
00335 virtual size_t size(void) const {
00336 return sizeof(Description);
00337 }
00338 };
00339
00341 SteelMillBranch(Space& home)
00342 : Branching(home), start(0) {}
00344 SteelMillBranch(Space& home, bool share, SteelMillBranch& b)
00345 : Branching(home, share, b), start(b.start) {
00346 }
00347
00348 public:
00350 virtual bool status(const Space& home) const {
00351 const SteelMill& sm = static_cast<const SteelMill&>(home);
00352 for (unsigned int i = start; i < sm.norders; ++i)
00353 if (!sm.slab[i].assigned()) {
00354 start = i;
00355 return true;
00356 }
00357
00358 return false;
00359 }
00361 virtual BranchingDesc* description(Space& home) {
00362 SteelMill& sm = static_cast<SteelMill&>(home);
00363 assert(!sm.slab[start].assigned());
00364
00365 unsigned int size = sm.norders;
00366 int weight = 0;
00367 unsigned int pos = start;
00368 for (unsigned int i = start; i<sm.norders; ++i) {
00369 if (!sm.slab[i].assigned()) {
00370 if (sm.slab[i].size() == size &&
00371 sm.orders[i][order_weight] > weight) {
00372 weight = sm.orders[i][order_weight];
00373 pos = i;
00374 } else if (sm.slab[i].size() < size) {
00375 size = sm.slab[i].size();
00376 weight = sm.orders[i][order_weight];
00377 pos = i;
00378 }
00379 }
00380 }
00381 unsigned int val = sm.slab[pos].min();
00382
00383 unsigned int firstzero = 0;
00384 while (firstzero < sm.nslabs && sm.slabload[firstzero].min() > 0)
00385 ++firstzero;
00386 assert(pos < sm.nslabs &&
00387 val < sm.norders);
00388 return new Description(*this, val<firstzero ? 2 : 1, pos, val);
00389 }
00391 virtual ExecStatus commit(Space& home, const BranchingDesc& d,
00392 unsigned int a) {
00393 SteelMill& sm = static_cast<SteelMill&>(home);
00394 const Description& desc =
00395 static_cast<const Description&>(d);
00396 if (a)
00397 return me_failed(Int::IntView(sm.slab[desc.pos]).nq(home, desc.val))
00398 ? ES_FAILED : ES_OK;
00399 else
00400 return me_failed(Int::IntView(sm.slab[desc.pos]).eq(home, desc.val))
00401 ? ES_FAILED : ES_OK;
00402 }
00404 virtual Actor* copy(Space& home, bool share) {
00405 return new (home) SteelMillBranch(home, share, *this);
00406 }
00408 static void post(Space& home) {
00409 (void) new (home) SteelMillBranch(home);
00410 }
00411 };
00412 };
00413
00417 int
00418 main(int argc, char* argv[]) {
00419 SteelMillOptions opt("Steel Mill Slab design");
00420 opt.branching(SteelMill::BRANCHING_SYMMETRY);
00421 opt.branching(SteelMill::BRANCHING_NAIVE,"naive");
00422 opt.branching(SteelMill::BRANCHING_SYMMETRY,"symmetry");
00423 opt.solutions(0);
00424 if (!opt.parse(argc,argv))
00425 return 1;
00426 Script::run<SteelMill,BAB,SteelMillOptions>(opt);
00427 return 0;
00428 }
00429
00430
00431 void
00432 SteelMillOptions::help(void) {
00433 Options::help();
00434 std::cerr << "\t(string), optional" << std::endl
00435 << "\t\tBenchmark to load." << std::endl
00436 << "\t\tIf none is given, the standard CSPLib instance is used."
00437 << std::endl;
00438 std::cerr << "\t(unsigned int), optional" << std::endl
00439 << "\t\tNumber of orders to use, in the interval [0..norders]."
00440 << std::endl
00441 << "\t\tIf none is given, all orders are used." << std::endl;
00442 }
00443
00444 bool
00445 SteelMillOptions::parse(int& argc, char* argv[]) {
00446 Options::parse(argc,argv);
00447
00448 if (argc >= 4) {
00449 std::cerr << "Too many arguments given, max two allowed (given={";
00450 for (int i = 1; i < argc; ++i) {
00451 std::cerr << "\"" << argv[i] << "\"";
00452 if (i < argc-1) std::cerr << ",";
00453 }
00454 std::cerr << "})." << std::endl;
00455 return false;
00456 }
00457
00458 while (argc >= 2) {
00459 bool issize = true;
00460 for (int i = strlen(argv[argc-1]); i-- && issize; )
00461 issize &= (isdigit(argv[argc-1][i]) != 0);
00462 if (issize) {
00463 _size = atoi(argv[argc-1]);
00464 } else {
00465 std::ifstream instance(argv[argc-1]);
00466 if (instance.fail()) {
00467 std::cerr << "Argument \"" << argv[argc-1]
00468 << "\" is neither an integer nor a readable file"
00469 << std::endl;
00470 return false;
00471 }
00472
00473 instance >> _ncapacities;
00474 _capacities = new int[_ncapacities];
00475 _maxcapacity = -1;
00476 for (int i = 0; i < _ncapacities; ++i) {
00477 instance >> _capacities[i];
00478 _maxcapacity = std::max(_maxcapacity, _capacities[i]);
00479 }
00480 instance >> _ncolors >> _norders;
00481 _orders = new int[_norders][2];
00482 for (unsigned int i = 0; i < _norders; ++i) {
00483 instance >> _orders[i][order_weight] >> _orders[i][order_color];
00484 }
00485 }
00486
00487 --argc;
00488 }
00489
00490 {
00491 _loss = new int[_maxcapacity+1];
00492 _loss[0] = 0;
00493 int currcap = 0;
00494 for (int c = 1; c < _maxcapacity; ++c) {
00495 if (c > _capacities[currcap]) ++currcap;
00496 _loss[c] = _capacities[currcap] - c;
00497 }
00498 }
00499
00500 if (_size == 0) {
00501 _size = _norders;
00502 }
00503
00504 if (_size == 0 || _size > _norders) {
00505 std::cerr << "Size must be between 1 and " << _norders << std::endl;
00506 return false;
00507 }
00508 return true;
00509 }
00510
00511
00512 const int order_weight = 0;
00513 const int order_color = 1;
00514
00515
00516 int csplib_capacities[] =
00517 {12, 14, 17, 18, 19,
00518 20, 23, 24, 25, 26,
00519 27, 28, 29, 30, 32,
00520 35, 39, 42, 43, 44};
00521 unsigned int csplib_ncapacities = 20;
00522 unsigned int csplib_maxcapacity = 44;
00523 int csplib_loss[45];
00524 unsigned int csplib_ncolors = 89;
00525 unsigned int csplib_norders = 111;
00526 int csplib_orders[][2] = {
00527 {4, 1},
00528 {22, 2},
00529 {9, 3},
00530 {5, 4},
00531 {8, 5},
00532 {3, 6},
00533 {3, 4},
00534 {4, 7},
00535 {7, 4},
00536 {7, 8},
00537 {3, 6},
00538 {2, 6},
00539 {2, 4},
00540 {8, 9},
00541 {5, 10},
00542 {7, 11},
00543 {4, 7},
00544 {7, 11},
00545 {5, 10},
00546 {7, 11},
00547 {8, 9},
00548 {3, 1},
00549 {25, 12},
00550 {14, 13},
00551 {3, 6},
00552 {22, 14},
00553 {19, 15},
00554 {19, 15},
00555 {22, 16},
00556 {22, 17},
00557 {22, 18},
00558 {20, 19},
00559 {22, 20},
00560 {5, 21},
00561 {4, 22},
00562 {10, 23},
00563 {26, 24},
00564 {17, 25},
00565 {20, 26},
00566 {16, 27},
00567 {10, 28},
00568 {19, 29},
00569 {10, 30},
00570 {10, 31},
00571 {23, 32},
00572 {22, 33},
00573 {26, 34},
00574 {27, 35},
00575 {22, 36},
00576 {27, 37},
00577 {22, 38},
00578 {22, 39},
00579 {13, 40},
00580 {14, 41},
00581 {16, 27},
00582 {26, 34},
00583 {26, 42},
00584 {27, 35},
00585 {22, 36},
00586 {20, 43},
00587 {26, 24},
00588 {22, 44},
00589 {13, 45},
00590 {19, 46},
00591 {20, 47},
00592 {16, 48},
00593 {15, 49},
00594 {17, 50},
00595 {10, 28},
00596 {20, 51},
00597 {5, 52},
00598 {26, 24},
00599 {19, 53},
00600 {15, 54},
00601 {10, 55},
00602 {10, 56},
00603 {13, 57},
00604 {13, 58},
00605 {13, 59},
00606 {12, 60},
00607 {12, 61},
00608 {18, 62},
00609 {10, 63},
00610 {18, 64},
00611 {16, 65},
00612 {20, 66},
00613 {12, 67},
00614 {6, 68},
00615 {6, 68},
00616 {15, 69},
00617 {15, 70},
00618 {15, 70},
00619 {21, 71},
00620 {30, 72},
00621 {30, 73},
00622 {30, 74},
00623 {30, 75},
00624 {23, 76},
00625 {15, 77},
00626 {15, 78},
00627 {27, 79},
00628 {27, 80},
00629 {27, 81},
00630 {27, 82},
00631 {27, 83},
00632 {27, 84},
00633 {27, 79},
00634 {27, 85},
00635 {27, 86},
00636 {10, 87},
00637 {3, 88}
00638 };
00639
00640