Generated on Mon Aug 25 11:35:33 2008 for Gecode by doxygen 1.5.6

sports-league.cc

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Patrick Pekczynski <pekczynski@ps.uni-sb.de>
00005  *
00006  *  Contributing authors:
00007  *     Christian Schulte <schulte@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Patrick Pekczynski, 2004
00011  *     Christian Schulte, 2007
00012  *
00013  *  Last modified:
00014  *     $Date: 2008-02-01 11:40:25 +0100 (Fri, 01 Feb 2008) $ by $Author: tack $
00015  *     $Revision: 6033 $
00016  *
00017  *  This file is part of Gecode, the generic constraint
00018  *  development environment:
00019  *     http://www.gecode.org
00020  *
00021  *  Permission is hereby granted, free of charge, to any person obtaining
00022  *  a copy of this software and associated documentation files (the
00023  *  "Software"), to deal in the Software without restriction, including
00024  *  without limitation the rights to use, copy, modify, merge, publish,
00025  *  distribute, sublicense, and/or sell copies of the Software, and to
00026  *  permit persons to whom the Software is furnished to do so, subject to
00027  *  the following conditions:
00028  *
00029  *  The above copyright notice and this permission notice shall be
00030  *  included in all copies or substantial portions of the Software.
00031  *
00032  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00033  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00034  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00035  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00036  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00037  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00038  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00039  *
00040  */        
00041 
00042 #include "examples/support.hh"
00043 #include "gecode/minimodel.hh"
00044 
00045 #include <algorithm>
00046 #include <iomanip>
00047 
00049 class Play {
00050 public:
00051   int h; 
00052   int a; 
00053   int g; 
00054 };
00055 
00057 class RRS {
00058 protected:
00060   const int teams;
00062   Play* plays; 
00064   int weeks(void) const {
00065     return teams-1;
00066   }
00068   int periods(void) const {
00069     return teams/2;
00070   }
00072   int gn(int h, int a) const {
00073     return teams*(h-1) + a;
00074   }
00076   Play& play(int p, int w) {
00077     return plays[p*weeks() + w];
00078   }
00079 public:
00105   RRS(int t) : teams(t), plays(new Play[periods()*weeks()])  {
00106     // Initialize array
00107     for (int p=0; p<periods(); p++)
00108       for (int w=0; w<weeks(); w++)
00109         play(p,w).h = play(p,w).a = play(p,w).g = 0;
00110     
00111     // Determine the first game (week 0 period 0)
00112     play(0,0).h = 1;
00113     play(0,0).a = 2;
00114     play(0,0).g = 2;
00115 
00116     // Determine the other games of the first week
00117     for (int p=1; p<periods(); p++) {
00118       play(p,0).h = (p + 1) + 1;
00119       play(p,0).a = teams - (p + 1 - 2);
00120       play(p,0).g = gn(play(p,0).h,play(p,0).a);
00121     }
00122 
00123     // Compute the games for the subsequent weeks
00124     for (int w=1; w<weeks(); w++) {
00125       for (int p=0; p<periods(); p++) {
00126         if (play(p,w-1).h == teams) {
00127           play(p,w).h = 2;
00128         } else if (play(p,w-1).h == 1) {
00129           play(p,w).h = 1;
00130         } else {
00131           play(p,w).h = play(p,w-1).h + 1;
00132         }
00133 
00134         if (play(p,w-1).a == teams) {
00135           play(p,w).a = 2;
00136         } else {
00137           play(p,w).a = play(p,w-1).a + 1;
00138         }
00139 
00140         // maintain symmetry for (h,a): h < a
00141         if (play(p,w).h > play(p,w).a)
00142           std::swap(play(p,w).h,play(p,w).a);
00143 
00144         play(p,w).g = gn(play(p,w).h,play(p,w).a);
00145       }
00146     }
00147 
00148   }
00150   void hag(int w, IntArgs& h, IntArgs& a, IntArgs& g) {
00151     for (int p=0; p<periods(); p++) {
00152       h[p] = play(p,w).h;
00153       a[p] = play(p,w).a;
00154       g[p] = play(p,w).g;
00155     }
00156   }
00158   ~RRS(void) {
00159     delete [] plays;
00160   }
00161 };
00162 
00163 
00164 
00181 class SportsLeague : public Example {
00182 protected:
00183   const int teams;  
00184   IntVarArray home; 
00185   IntVarArray away; 
00186   IntVarArray game; 
00187 
00189   int weeks(void) const {
00190     return teams-1;
00191   }
00193   int periods(void) const {
00194     return teams/2;
00195   }
00197   IntVar& h(int p, int w) {
00198     return home[p*teams + w];
00199   }
00201   IntVar& a(int p, int w) {
00202     return away[p*teams + w];
00203   }
00205   IntVar& g(int p, int w) {
00206     return game[p*weeks() + w];
00207   }
00208 
00209 public:
00211   SportsLeague(const SizeOptions& opt) :
00212     teams(opt.size()),
00213     home(this, periods() * teams, 1, weeks()),
00214     away(this, periods() * teams, 2, weeks()+1),
00215     game(this, weeks()*periods(), 2, teams*weeks())
00216   {
00217     // Initialize round robin schedule
00218     RRS r(teams);
00219 
00220     // Domain for gamenumber of period
00221     for (int w=0; w<weeks(); w++) {
00222       IntArgs rh(periods()), ra(periods()), rg(periods());
00223       IntVarArgs n(periods());
00224 
00225       for (int p=0; p<periods(); p++)
00226         n[p].init(this,0,periods()-1);
00227       distinct(this, n, opt.icl());
00228 
00229       r.hag(w,rh,ra,rg);
00230         
00231       for (int p=0; p<periods(); p++) {
00232         element(this, rh, n[p], h(p,w));
00233         element(this, ra, n[p], a(p,w));
00234         element(this, rg, n[p], g(p,w));
00235       }
00236     }
00237 
00239     for (int p=0; p<periods(); p++)
00240       for (int w=0; w<teams; w++)
00241         rel(this, h(p,w), IRT_LE, a(p,w));
00242 
00243     // Home teams in first week are ordered
00244     for (int p=0; p<periods()-1; p++)
00245       rel(this, h(p,0), IRT_LE, h(p+1,0));
00246 
00247     // Fix first pair
00248     rel(this, h(0,0), IRT_EQ, 1);
00249     rel(this, a(0,0), IRT_EQ, 2);
00250 
00252     for (int w=0; w<teams; w++) {
00253       IntVarArgs c(teams);
00254       for (int p=0; p<periods(); p++) {
00255         c[2*p] = h(p,w); c[2*p+1] = a(p,w);
00256       }
00257       distinct(this, c, opt.icl());
00258     }
00259 
00261     for (int p=0; p<periods(); p++) {
00262       IntVarArgs r(2*teams);
00263       for (int t=0; t<teams; t++) {
00264         r[2*t]   = h(p,t);
00265         r[2*t+1] = a(p,t);
00266       }
00267       IntArgs values(teams);
00268       for (int i=1; i<=teams; i++)
00269         values[i-1] = i;
00270       count(this, r, IntSet(2,2), values, opt.icl());
00271     }
00272 
00273     // Redundant constraint
00274     for (int p=0; p<periods(); p++)
00275       for (int w=0; w<weeks(); w ++)
00276         post(this, teams * h(p,w) + a(p,w) - g(p,w) == teams);
00277 
00278     distinct(this, game, opt.icl());
00279 
00280     branch(this, game, INT_VAR_NONE, INT_VAL_SPLIT_MIN);
00281   }
00283   SportsLeague(bool share, SportsLeague& s)
00284     : Example(share, s), teams(s.teams) {
00285     home.update(this, share, s.home);
00286     away.update(this, share, s.away);
00287     game.update(this, share, s.game);
00288   }
00290   virtual Space*
00291   copy(bool share) {
00292     return new SportsLeague(share, *this);
00293   }
00295   virtual void print(std::ostream& os) {
00296     // print period index
00297     os << "\t       ";
00298     for (int p=0; p<periods(); p++) {
00299       os << "P[";
00300       os.width(2);
00301       os << p << "] ";
00302       }
00303     os << std::endl;
00304     // print entries
00305     for (int w=0; w<weeks(); w++) {
00306       os << "\tW[";
00307       os.width(2);
00308       os << w+1 << "]: ";
00309       for (int p=0; p<periods(); p++) {
00310         os.width(2); 
00311         os << h(p,w).val() << '-';
00312         os.width(2);
00313         os << a(p,w).val() << " ";
00314       }
00315       os << std::endl;
00316     }
00317   }
00318 };
00319 
00320 
00324 int 
00325 main(int argc, char* argv[]) {
00326   SizeOptions opt("Sports League Scheduling");
00327   opt.icl(ICL_DOM);
00328   opt.size(18);
00329   opt.parse(argc,argv);
00330   if (opt.size() < 5) {
00331     std::cerr<< "No Solution for less than 5 teams!" << std::endl;
00332     return 1;
00333   }
00334   if (opt.size() % 2 != 0) {
00335     std::cerr << "Number of teams has to be even!" << std::endl;
00336     return 1;
00337   }
00338   Example::run<SportsLeague, DFS,SizeOptions>(opt);
00339   return 0;
00340 }
00341 
00342 // STATISTICS: example-any