Generated on Wed Nov 1 15:04:28 2006 for Gecode by doxygen 1.4.5

sports-league.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Patrick Pekczynski <pekczynski@ps.uni-sb.de>
00004  *
00005  *  Copyright:
00006  *     Patrick Pekczynski, 2004
00007  *
00008  *  Last modified:
00009  *     $Date: 2006-08-04 16:06:52 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00010  *     $Revision: 3517 $
00011  *
00012  *  This file is part of Gecode, the generic constraint
00013  *  development environment:
00014  *     http://www.gecode.org
00015  *
00016  *  See the file "LICENSE" for information on usage and
00017  *  redistribution of this file, and for a
00018  *     DISCLAIMER OF ALL WARRANTIES.
00019  *
00020  */     
00021 
00022 #include "examples/support.hh"
00023 #include "gecode/minimodel.hh"
00024 
00031 struct Play {
00033   int h;
00035   int a;
00037   int g;
00038 };
00039 
00040 typedef PrimArgArray<Play> RRSArray;
00041 
00059 class SportsLeague : public Example {
00060 private:
00063   int t;
00065   int weeks;
00067   int eweeks;
00069   int periods;
00071   int season;
00073   int value;
00075   IntVarArray home;
00077   IntVarArray away;
00079   IntVarArray game;
00081   RRSArray rrs_array;
00082 protected:
00083   // return the number of digits of n
00084   int digit(int n) {
00085     int f = n;
00086     int fdigit = 0;
00087     while (f / 10) {
00088       fdigit++;
00089       f = f / 10;
00090     }
00091     return fdigit;
00092   }
00093 
00094   // printing function that makes the schedule more readable
00095   void blank(int n) {
00096     for (int d = digit(t) - digit(n); d--; ) {
00097       std::cout << " ";
00098     }
00099     std::cout << n;
00100   }
00101 
00102   void blankv(int n) {
00103     for (int d = digit(value) - digit(n); d--; ) {
00104       std::cout << " ";
00105     }
00106     std::cout << n;
00107   }
00108 
00109   void blank_only(int n) {
00110     for (int i = digit(n); i--; ) {
00111       std::cout << " ";
00112     }
00113   }
00114 
00115 public:
00117   IntVar& h (int p, int w) {
00118     return home[p * eweeks + w];
00119   }
00120 
00122   IntVar& a (int p, int w) {
00123     return away[p * eweeks + w];
00124   }
00125 
00130   IntVar& g (int p, int w) {
00131     return game[p * weeks + w];
00132   }
00133 
00138   Play& rrs(int p, int w) {
00139     return rrs_array[p * weeks + w];
00140   }
00141 
00151   int gn(int h, int a) {
00152     return (t * (h - 1) + a);
00153   }
00154 
00181   void init_rrs(void) {
00182 
00183     // Initialize the array
00184     for(int p = 0; p < periods; p++)
00185       for (int w = 0; w < weeks; w++) {
00186         rrs(p, w).h = 0;
00187         rrs(p, w).a = 0;
00188         rrs(p, w).g = 0;
00189       }
00190 
00191     // Determine the first game (week 0 period 0)
00192     rrs(0, 0).h = 1;
00193     rrs(0, 0).a = 2;
00194     rrs(0, 0).g = 2;
00195 
00196     // Determine the other games of the first week
00197     for(int p = 1; p < periods; p++){
00198       rrs(p, 0).h = (p + 1) + 1;
00199       rrs(p, 0).a = t - (p + 1 - 2);
00200       rrs(p, 0).g = gn(rrs(p, 0).h, rrs(p, 0).a);
00201     }
00202 
00203     // Compute the games for the subsequent weeks
00204     for (int w = 1; w < weeks; w++) {
00205       for (int p = 0; p < periods; p++) {
00206         if (rrs(p, w - 1).h == t) {
00207           rrs(p, w).h = 2;
00208         } else {
00209           if (rrs(p, w - 1).h == 1) {
00210             rrs(p, w).h = 1;
00211           } else {
00212             rrs(p, w).h = rrs(p, w - 1).h + 1;
00213           }
00214         }
00215         if (rrs(p, w - 1).a == t) {
00216           rrs(p, w).a = 2;
00217         } else {
00218           rrs(p, w).a = rrs(p, w - 1).a + 1;
00219         }
00220 
00221         // maintain symmetry for (h, a): h < a
00222         if (rrs(p, w).h > rrs(p, w).a) {
00223           int buffer  = rrs(p, w).h;
00224           rrs(p, w).h = rrs(p, w).a;
00225           rrs(p, w).a = buffer;
00226         }
00227         rrs(p, w).g = gn(rrs(p, w).h, rrs(p, w).a);
00228       }
00229     }
00230   }
00231 
00232   SportsLeague(const Options& op) :
00233     t       (op.size),
00234     weeks   (t - 1),
00235     eweeks  (t),
00236     periods (t / 2),
00237     season  (weeks * periods),
00238     value   (t * (t - 2) + t),
00239     home    (this, periods * eweeks),
00240     away    (this, periods * eweeks),
00241     game    (this, season),
00242     rrs_array     (periods * weeks){
00243 
00244     IntSet dom_all   (1, t);
00245     IntSet dom_game  (2, value);
00246     IntSet dom_home  (1, t - 1);
00247     IntSet dom_away  (2, t);
00248     IntSet dom_index (0, periods - 1);
00249 
00250     for (int i = eweeks * periods; i--; ) {
00251       home[i].init(this, dom_home);
00252       away[i].init(this, dom_away);
00253     }
00254     for (int i = season; i--; ) {
00255       game[i].init(this, dom_game);
00256     }
00257 
00258 
00259     // Initialize the round robin schedule
00260     init_rrs();
00261 
00262     //    domain for the gamenumber of period
00263     for (int w = 0; w < weeks; w++) {
00264       IntArgs gamenum(periods);
00265       IntArgs fst(periods);
00266       IntArgs snd(periods);
00267 
00268       for(int p = 0; p < periods; p++){
00269         gamenum[p] = rrs(p, w).g;
00270         fst[p]     = rrs(p, w).h;
00271         snd[p]     = rrs(p, w).a;
00272       }
00273 
00274       IntVarArray n(this, periods, 0, periods - 1);
00275       distinct(this, n, ICL_DOM);
00276         
00277       for(int p = 0; p < periods; p++){
00278         element(this, gamenum, n[p], g(p, w), op.icl);
00279         element(this, fst,     n[p], h(p, w), op.icl);
00280         element(this, snd,     n[p], a(p, w), op.icl);
00281       }
00282     }
00283 
00284 
00291     // fix the first pair
00292     rel(this, h(0,0), IRT_EQ, 1);
00293     rel(this, a(0,0), IRT_EQ, 2);
00294 
00295     for (int p = 0; p < periods; p++) {
00296       for (int w = 0; w < eweeks; w++) {
00297         rel(this, h(p, w), IRT_LE, a(p, w));
00298       }
00299     }
00300 
00301     // home teams in the first week are ordered
00302     for (int p = 0; p < periods - 1; p++) {
00303       rel(this, h(p, 0), IRT_LE, h(p + 1, 0));
00304     }
00305 
00312     for(int w = 0; w < eweeks; w++ ) {
00313       IntVarArray col(this, t);
00314       int k = 0;
00315       for( int p = 0; p < periods; p++ ) {
00316         col[k] = h(p, w);
00317         k++;
00318         col[k] = a(p, w);
00319         k++;
00320       }
00321       distinct(this, col, ICL_DOM);
00322     }
00323 
00332     for(int p = 0; p < periods; p++) {
00333       IntVarArray row(this, 2 * eweeks);
00334       for (int w = 0; w < 2 * eweeks; w +=2) {
00335         row[w]     = h(p, w / 2);
00336         row[w + 1] = a(p, w / 2);
00337       }
00338       gcc(this, row, 2, op.icl); // cardvars
00339     }
00340 
00341 
00342 
00343     for(int p = 0; p < periods; p++) {
00344       for(int w = 0; w < weeks; w ++) {
00345         post(this, t * h(p, w) + 1 * a(p, w) - 1* g(p, w) == t);
00346       }
00347     }
00348 
00349     distinct(this, game, ICL_DOM);
00350 
00351     branch(this, game, BVAR_NONE, BVAL_MIN);
00352 
00353   }
00354 
00355   SportsLeague(bool share, SportsLeague& s)
00356     : Example(share, s),
00357       t(s.t), weeks(s.weeks), eweeks(s.eweeks),
00358       periods(s.periods), season(s.season),
00359       value(s.value), rrs_array(s.rrs_array) {
00360     home.update(this, share, s.home);
00361     away.update(this, share, s.away);
00362     game.update(this, share, s.game);
00363   }
00364 
00365   virtual Space*
00366   copy(bool share) {
00367     return new SportsLeague(share, *this);
00368   }
00369 
00370   virtual void print(void){
00371     // print feasible schedule
00372     // t is the number of the greatest game
00373     std::cout << "\nSchedule for " << t << " teams"
00374               << " and "<< weeks << " weeks:" << std::endl;
00375     // print period index
00376     std::cout << " ";
00377     blank_only(t);
00378     std::cout << "     ";
00379     for (int p = 0; p < periods; p++) {
00380       blank_only(t);
00381       std::cout << "P[";
00382       blank(p);
00383       std::cout <<"]";
00384       blank_only(t);
00385     }
00386     std::cout <<"\n";
00387 
00388     // print entries
00389     for(int w = 0; w < weeks; w++){
00390       std::cout << "W[";
00391       blank(w + 1);
00392       std::cout <<"]: ";
00393       for(int p = 0; p < periods; p++){
00394         if (h(p, w).assigned() && a(p, w).assigned()) {
00395           std::cout <<" ";
00396           blank(h(p, w).val());
00397           std::cout <<",";
00398           blank(a(p, w).val());
00399           std::cout <<" ";
00400         } else {
00401           blank_only(t);
00402           std::cout << " x ";
00403           blank_only(t);
00404         }
00405       }
00406       std::cout << "\n";
00407     }
00408     std::cout << "\n";
00409 
00410     //print gamenumbers
00411     std::cout << "\nUnique game numbers:\n";
00412     std::cout <<"\n";
00413     for(int p = 0; p < periods; p++){
00414       std::cout << "Period[";
00415       blank(p + 1);
00416       std::cout <<"]: " ;
00417       for(int w = 0; w < weeks; w++){
00418         if (g(p, w).assigned()) {
00419           blankv(g(p, w).val());
00420           std::cout << " ";
00421         } else {
00422           for (int i = digit(value); i--; ) {
00423             std::cout << " ";
00424           }
00425           std::cout << " ";
00426         }
00427       }
00428       std::cout << "\n";
00429     }
00430     std::cout << "\n";
00431 
00432   }
00433 };
00434 
00435 
00436 int main(int argc, char** argv){
00437   Options o("Sports League Scheduling ");
00438   o.solutions = 1;
00439   o.size      = 18;
00440   o.parse(argc, argv);
00441   if (o.size == 4) {
00442     std::cerr<< "No Solution for t = 4!\n";
00443     return -1;
00444   }
00445   if (o.size % 2 != 0) {
00446     std::cerr << "Number of t has to be even!\n";
00447     return -1;
00448   }
00449   Example::run<SportsLeague, DFS>(o);
00450   return 0;
00451 }
00452 
00453 // STATISTICS: example-any
00454