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

golf.cc

Go to the documentation of this file.
00001 /*
00002  *  Main authors:
00003  *     Christian Schulte <schulte@gecode.org>
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Copyright:
00007  *     Christian Schulte, 2004
00008  *     Guido Tack, 2004
00009  *
00010  *  Last modified:
00011  *     $Date: 2006-08-04 16:06:52 +0200 (Fri, 04 Aug 2006) $ by $Author: schulte $
00012  *     $Revision: 3517 $
00013  *
00014  *  This file is part of Gecode, the generic constraint
00015  *  development environment:
00016  *     http://www.gecode.org
00017  *
00018  *  See the file "LICENSE" for information on usage and
00019  *  redistribution of this file, and for a
00020  *     DISCLAIMER OF ALL WARRANTIES.
00021  *
00022  */
00023 
00024 #include "gecode/set.hh"
00025 #include "examples/support.hh"
00026 
00033 
00034 struct Tournament {
00036   int groups;
00038   int playersInGroup;
00040   int weeks;
00041 };
00043 static const Tournament t[]=
00044   { {8,4,9},
00045     {5,3,7},
00046     {4,3,2}
00047   };
00049 static const unsigned int n_examples = sizeof(t) / sizeof(Tournament);
00051 
00060 class Golf : public Example {
00061 public:
00062   int groups;
00063   int playersInGroup;
00064   int weeks;
00065   int players;
00066 
00067   SetVarArray groupsS;
00068   IntVarArray groupsSInv;
00069 
00070   SetVar& group(int w, int g) {
00071     return groupsS[w*groups+g];
00072   }
00073   IntVar& groupInv(int w, int p) {
00074     return groupsSInv[w*players+p];
00075   }
00076 
00077   Golf(const Options& o) :
00078     groups(t[o.size].groups),
00079     playersInGroup(t[o.size].playersInGroup),
00080     weeks(t[o.size].weeks),
00081     players(groups*playersInGroup),
00082     groupsS(this,groups*weeks,IntSet::empty,0,players-1,
00083             playersInGroup,playersInGroup),
00084     groupsSInv(this, weeks*players, 0, groups-1) {
00085 
00086     SetVar allPlayers(this, 0, players-1, 0, players-1);
00087 
00088     // Groups in one week must be disjoint
00089     for (int w=0; w<weeks; w++) {
00090       SetVarArgs p(groups);
00091       for (int g=0; g < groups; g++)
00092         p[g] = group(w,g);
00093 
00094       rel(this,SOT_DUNION,p,allPlayers);
00095     }
00096 
00097     // No two golfers play in the same group more than once
00098     for (int w=0; w<weeks; w++) {
00099       for (int g=0; g<groups; g++) {
00100         SetVar v = group(w,g);
00101         for (int i=(w+1)*groups; i<weeks*groups; i++) {
00102           SetVar atMostOne(this,IntSet::empty,0,players-1,0,1);
00103           rel(this, v, SOT_INTER, groupsS[i], SRT_EQ, atMostOne);
00104         }
00105       }
00106     }
00107 
00108     if (!o.naive) {
00109 
00110       //      atmostOne(this, groupsS, playersInGroup);
00111 
00112       /*
00113        * Redundant constraints and static symmetry breaking from
00114        * "Solving Kirkman's Schoolgirl Problem in a Few Seconds"
00115        * Nicolas Barnier, Pascal Brisset, Constraints, 10, 7-21, 2005
00116        *
00117        */
00118 
00119       // Redundant constraint:
00120       // in each week, one player plays in only one group
00121       for (int w=0; w < weeks; w++) {
00122         for (int p=0; p < players; p++) {
00123           BoolVarArgs bs(groups);
00124           for (int g=0; g<groups; g++) {
00125             BoolVar b(this,0,1);
00126             dom(this, group(w,g), SRT_SUP, p, b);
00127             bs[g] = b;
00128           }
00129           linear(this, bs, IRT_EQ, 1);
00130         }
00131        }
00132 
00133       // Redundant constraint:
00134       // any two groups has at most one player in common
00135       atmostOne(this, groupsS, playersInGroup);
00136 
00137       // Symmetry breaking: order groups
00138       for (int w=0; w<weeks; w++) {
00139         for (int g=0; g<groups-1; g++) {
00140           IntVar minG1(this, 0, players-1);
00141           IntVar minG2(this, 0, players-1);
00142           SetVar g1 = group(w,g);
00143           SetVar g2 = group(w,g+1);
00144           min(this, g1, minG1);
00145           min(this, g2, minG2);
00146           rel(this, minG1, IRT_LE, minG2);
00147         }
00148       }
00149 
00150       // Symmetry breaking: order weeks
00151       // minElem(group(w,0)\{0}) < minElem(group(w+1,0)\{0})
00152       for (int w=0; w<weeks-1; w++) {
00153         SetVar g1(this, IntSet::empty, 1, players-1);
00154         SetVar g2(this, IntSet::empty, 1, players-1);
00155         SetVar zero1(this, IntSet::empty,0,0);
00156         SetVar zero2(this, IntSet::empty,0,0);
00157         rel(this, g1, SOT_DUNION, zero1, SRT_EQ, group(w,0));
00158         rel(this, g2, SOT_DUNION, zero2, SRT_EQ, group(w+1,0));
00159         IntVar minG1(this, 0, players-1);
00160         IntVar minG2(this, 0, players-1);
00161         min(this, g1, minG1);
00162         min(this, g2, minG2);
00163         rel(this, minG1, IRT_LE, minG2);
00164       }
00165 
00166       // Initialize the dual variables:
00167       // groupInv(w,p) is player p's group in week w
00168       for (int w=0; w<weeks; w++) {
00169         for (int p=0; p<players; p++) {
00170           SetVar thisPlayer(this, p,p, 0, players-1);
00171           SetVarArgs thisWeek(groups);
00172           for (int g=0; g<groups; g++)
00173             thisWeek[g] = group(w,g);
00174           selectSet(this, thisWeek, groupInv(w,p), thisPlayer);
00175         }
00176       }
00177 
00178       // Symmetry breaking: order players
00179       // For all p<groups : groupInv(w,p) <= p
00180       for (int w=0; w<weeks; w++) {
00181         for (int p=0; p<groups; p++) {
00182           rel(this, groupInv(w,p), IRT_LQ, p);
00183         }
00184       }
00185 
00186     }
00187 
00188     branch(this, groupsS, SETBVAR_MIN_UNKNOWN_ELEM, SETBVAL_MIN);
00189   }
00190 
00191   Golf(bool share, Golf& s) : Example(share,s),
00192       groups(s.groups), playersInGroup(s.playersInGroup),
00193       weeks(s.weeks), players(s.players) {
00194     groupsS.update(this, share, s.groupsS);
00195   }
00196 
00197   virtual Space*
00198   copy(bool share) {
00199     return new Golf(share,*this);
00200   }
00201 
00202   virtual void
00203   print(void) {
00204 
00205     std::cout << "Tournament plan" << std::endl;
00206 
00207     for (int w=0; w<weeks; w++) {
00208       std::cout << "Week " << w << ": " << std::endl << "    ";
00209       for (int g=0; g<groups; g++) {
00210         SetVarGlbValues glb(group(w,g));
00211         std::cout << "(" << glb.val();
00212         ++glb;
00213         while(glb()) {
00214           std::cout << " " << glb.val();
00215           ++glb;
00216         }
00217         std::cout << ")";
00218         if (g < groups-1) std::cout << " ";
00219         if (g > 0 && g % 4 == 0) std::cout << std::endl << "    ";
00220       }
00221       std::cout << std::endl;
00222     }
00223 
00224   }
00225 };
00226 
00227 int
00228 main(int argc, char** argv) {
00229   Options o("Golf");
00230   o.parse(argc,argv);
00231   o.solutions  = 1;
00232   if (o.size >= n_examples) {
00233     std::cerr << "Error: size must be between 0 and " << n_examples - 1
00234               << std::endl;
00235     return 1;
00236   }
00237   Example::run<Golf,DFS>(o);
00238   return 0;
00239 }
00240 
00241 // STATISTICS: example-any
00242