Generated on Thu Mar 22 10:39:30 2012 for Gecode by doxygen 1.6.3

bacp.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Guido Tack <tack@gecode.org>
00005  *
00006  *  Contributing authors:
00007  *     Mikael Lagerkvist <lagerkvist@gecode.org>
00008  *
00009  *  Copyright:
00010  *     Guido Tack, 2006
00011  *     Mikael Lagerkvist, 2010
00012  *
00013  *  Last modified:
00014  *     $Date: 2011-09-19 14:02:26 +0200 (Mon, 19 Sep 2011) $ by $Author: schulte $
00015  *     $Revision: 12400 $
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 <gecode/driver.hh>
00043 #include <gecode/int.hh>
00044 #include <gecode/minimodel.hh>
00045 #include <gecode/int/branch.hh>
00046 
00047 #include <map>
00048 #include <string>
00049 #include <list>
00050 #include <vector>
00051 
00052 using namespace Gecode;
00053 
00055 class Course {
00056 public:
00057   const char* name; 
00058   int credit;       
00059 };
00060 
00062 class Curriculum {
00063 public:
00065   int p;
00067   int a;
00069   int b;
00071   int c;
00073   int d;
00074 
00076   const Course *courses;
00078   const char **prereqs;
00079 };
00080 
00081 namespace {
00082 
00083   extern const Curriculum curriculum[];
00084   extern const unsigned int n_examples;
00085 
00086 }
00087 
00100 class BACP : public MinimizeScript {
00101 protected:
00103   const Curriculum curr;
00104 
00106   IntVarArray l;
00108   IntVar u;
00110   IntVarArray q;
00111 
00113   IntVarArray x;
00114 public:
00116   enum {
00117     BRANCHING_NAIVE,    
00118     BRANCHING_LOAD,     
00119     BRANCHING_LOAD_REV, 
00120   };
00121 
00123   BACP(const SizeOptions& opt) : curr(curriculum[opt.size()]) {
00124     std::map<std::string, int> courseMap; // Map names to course numbers
00125     int maxCredit = 0;
00126     int numberOfCourses = 0;
00127     for (const Course* co=curr.courses; co->name != 0; co++) {
00128       courseMap[co->name] = numberOfCourses++;
00129       maxCredit += co->credit;
00130     }
00131 
00132     int p = curr.p;
00133     int a = curr.a;
00134     int b = curr.b;
00135     int c = curr.c;
00136     int d = curr.d;
00137 
00138     l = IntVarArray(*this, p, a, b);
00139     u = IntVar(*this, 0, maxCredit);
00140     q = IntVarArray(*this, p, c, d);
00141     x = IntVarArray(*this, numberOfCourses, 0, p-1);
00142 
00143     for (int j=0; j<p; j++) {
00144       BoolVarArgs xij(*this, numberOfCourses, 0, 1);
00145       IntArgs t(numberOfCourses);
00146       for (int i=0; i<numberOfCourses; i++) {
00147         rel(*this, (x[i]==j) == xij[i]);
00148         t[i] = curr.courses[i].credit;
00149       }
00150       // sum over all t*(xi==j) is load of period i
00151       linear(*this, t, xij, IRT_EQ, l[j]);
00152       // sum over all (xi==j) is number of courses in period i
00153       linear(*this, xij, IRT_EQ, q[j]);
00154     }
00155 
00156     // Precedence
00157     for (const char** prereq = curr.prereqs; *prereq != 0; prereq+=2)
00158       rel(*this, x[courseMap[*prereq]] < x[courseMap[*(prereq+1)]]);
00159 
00160     // Optimization criterion: minimize u
00161     max(*this, l, u);
00162 
00163     // Redundant constraints
00164     linear(*this, l, IRT_EQ, maxCredit);
00165     linear(*this, q, IRT_EQ, numberOfCourses);
00166 
00167     if (opt.branching() == BRANCHING_NAIVE) {
00168       branch(*this, x, INT_VAR_SIZE_MIN, INT_VAL_MIN);
00169     } else {
00170       Int::Branch::BySizeMin varsel(*this, VarBranchOptions::def);
00171       ViewArray<Int::IntView> xv(*this, IntVarArgs(x));
00172       if (opt.branching() == BRANCHING_LOAD) {
00173         ValBestLoad<true> valsel(*this, ValBranchOptions::def);
00174         ViewValBrancher<Int::Branch::BySizeMin, ValBestLoad<true> >
00175           ::post(*this,xv,varsel,valsel);
00176       } else { 
00177         ValBestLoad<false> valsel(*this, ValBranchOptions::def);
00178         ViewValBrancher<Int::Branch::BySizeMin, ValBestLoad<false> >
00179           ::post(*this,xv,varsel,valsel);
00180       }
00181     }
00182   }
00183     
00185   BACP(bool share, BACP& bacp) : MinimizeScript(share,bacp),
00186     curr(bacp.curr) {
00187     l.update(*this, share, bacp.l);
00188     u.update(*this, share, bacp.u);
00189     x.update(*this, share, bacp.x);
00190   }
00192   virtual Space*
00193   copy(bool share) {
00194     return new BACP(share,*this);
00195   }
00197   virtual IntVar cost(void) const {
00198     return u;
00199   }
00201   virtual void
00202   print(std::ostream& os) const {
00203     std::vector<std::list<int> > period(curr.p);
00204     for (int i=x.size(); i--;)
00205       period[x[i].val()].push_back(i);
00206 
00207     os << "Solution with load " << u.val() << ":" << std::endl;
00208     for (int i=0; i<curr.p; i++) {
00209       os << "\tPeriod "<<i+1<<": ";
00210       for (std::list<int>::iterator v=period[i].begin();
00211            v != period[i].end(); ++v) {
00212         os << curr.courses[*v].name << " ";
00213       }
00214       os << std::endl;
00215     }
00216     os << std::endl;
00217   }
00218 
00225   template <bool minimize>
00226   class ValBestLoad : public ValSelBase<Int::IntView,int> {
00227   public:
00229     ValBestLoad(void) {}
00230 
00232     ValBestLoad(Space& home, const ValBranchOptions& vbo)
00233       : ValSelBase<Int::IntView,int>(home,vbo) {}
00234 
00236     int val(Space& home, Int::IntView x) const {
00237       BACP& b = static_cast<BACP&>(home);
00238       Int::ViewValues<Int::IntView> values(x);
00239       int val = -1;
00240       int best = minimize ? Int::Limits::max+1 : Int::Limits::min-1;
00241       while (values()) {
00242         if (minimize 
00243             ? b.l[values.val()].min() < best
00244             : b.l[values.val()].min() > best) {
00245           val  = values.val();
00246           best = b.l[val].min();
00247         }
00248         ++values;
00249       }
00250       assert(val != -1);
00251       return val;
00252     }
00253 
00255     ModEvent tell(Space& home, unsigned int a, Int::IntView x, int n) {
00256       return (a == 0) ? x.eq(home,n) : x.gr(home,n);
00257     }
00258   };
00259 };
00260 
00264 int
00265 main(int argc, char* argv[]) {
00266   SizeOptions opt("BACP");
00267   opt.branching(BACP::BRANCHING_NAIVE);
00268   opt.branching(BACP::BRANCHING_NAIVE,"naive");
00269   opt.branching(BACP::BRANCHING_LOAD,"load");
00270   opt.branching(BACP::BRANCHING_LOAD_REV,"load-reverse");
00271   opt.size(2);
00272   opt.solutions(0);
00273   opt.iterations(20);
00274   opt.parse(argc,argv);
00275   if (opt.size() >= n_examples) {
00276     std::cerr << "Error: size must be between 0 and " << n_examples - 1
00277               << std::endl;
00278     return 1;
00279   }
00280   MinimizeScript::run<BACP,BAB,SizeOptions>(opt);
00281   return 0;
00282 }
00283 
00284 namespace {
00290 
00291   const Course courses8[] =
00292     {
00293       {"dew100", 1},
00294       {"fis100", 3},
00295       {"hcw310", 1},{"iwg101", 2},{"mat190", 4},{"mat192", 4},{"dew101", 1},
00296       {"fis101", 5},{"iwi131", 3},{"mat191", 4},{"mat193", 4},{"fis102", 5},{"hxwxx1", 1},
00297       {"iei134", 3},{"iei141", 3},{"mat194", 4},
00298       {"dewxx0", 1},{"hcw311", 1},{"iei132", 3},{"iei133", 3},{"iei142", 3},{"iei162", 3},
00299       {"iwn170", 3},{"mat195", 3},{"hxwxx2", 1},{"iei231", 4},{"iei241", 4},{"iei271", 3},{"iei281", 3},{"iwn261", 3},
00300       {"hfw120", 2},{"iei233", 4},{"iei238", 3},{"iei261", 3},{"iei272", 3},{"iei273", 3},{"iei161", 3},{"iei232", 3},
00301       {"iei262", 3},{"iei274", 3},{"iwi365", 3},{"iwn270", 3},{"hrw130", 2},{"iei218", 3},{"iei219", 3},{"iei248", 3},
00302       {0,0}
00303     };
00304 
00306   const char* prereqs8[] =
00307     {
00308     "dew101","dew100",
00309     "fis101","fis100",
00310     "fis101","mat192",
00311     "mat191","mat190",
00312     "mat193","mat190",
00313     "mat193","mat192",
00314     "fis102","fis101",
00315     "fis102","mat193",
00316     "iei134","iwi131",
00317     "iei141","iwi131",
00318     "mat194","mat191 ",
00319     "mat194","mat193",
00320     "dewxx0","dew101",
00321     "hcw311","hcw310",
00322     "iei132","iei134",
00323     "iei133","iei134",
00324     "iei142","iei141",
00325     "mat195","mat194",
00326     "iei231","iei134",
00327     "iei241","iei142",
00328     "iei271","iei162",
00329     "iei281","mat195",
00330     "iei233","iei231",
00331     "iei238","iei231",
00332     "iei261","iwn261",
00333     "iei272","iei271",
00334     "iei273","iei271",
00335     "iei273","iei271",
00336     "iei161","iwn261",
00337     "iei161","iwn261",
00338     "iei232","iei273",
00339     "iei232","iei273",
00340     "iei262","iwn261",
00341     "iei274","iei273",
00342     "iei274","iei273",
00343     "iei219","iei232",
00344     "iei248","iei233",
00345     "iei248","iei233",
00346     0,0
00347     };
00348 
00350   const Course courses10[] = {
00351   {"dew100",1},
00352   {"fis100",3},
00353   {"hrwxx1",2},
00354   {"iwg101",2},
00355   {"mat021",5},
00356   {"qui010",3},
00357   {"dew101",1},
00358   {"fis110",5},
00359   {"hrwxx2",2},
00360   {"iwi131",3},
00361   {"mat022",5},
00362   {"dewxx0",1},
00363   {"fis120",4},
00364   {"hcw310",1},
00365   {"hrwxx3",2},
00366   {"ili134",4},
00367   {"ili151",3},
00368   {"mat023",4},
00369   {"hcw311",1},
00370   {"ili135",4},
00371   {"ili153",3},
00372   {"ili260",3},
00373   {"iwn261",3},
00374   {"mat024",4},
00375   {"fis130",4},
00376   {"ili239",4},
00377   {"ili245",4},
00378   {"ili253",4},
00379   {"fis140",4},
00380   {"ili236",4},
00381   {"ili243",4},
00382   {"ili270",3},
00383   {"ili280",4},
00384   {"ici344",4},
00385   {"ili263",3},
00386   {"ili332",4},
00387   {"ili355",4},
00388   {"iwn170",3},
00389   {"icdxx1",3},
00390   {"ili362",3},
00391   {"iwn270",3},
00392   {"icdxx2",3},
00393   {0,0}
00394   };
00395 
00397   const char* prereqs10[] = {
00398   "dew101","dew100",
00399   "fis110","fis100",
00400   "fis110","mat021",
00401   "mat022","mat021",
00402   "dewxx0","dew101",
00403   "fis120","fis110",
00404   "fis120","mat022",
00405   "ili134","iwi131",
00406   "ili151","iwi131",
00407   "mat023","mat022",
00408   "hcw311","hcw310",
00409   "ili135","ili134",
00410   "ili153","ili134",
00411   "ili153","ili151",
00412   "mat024","mat023",
00413   "fis130","fis110",
00414   "fis130","mat022",
00415   "ili239","ili135",
00416   "ili245","ili153",
00417   "ili253","ili153",
00418   "fis140","fis120",
00419   "fis140","fis130",
00420   "ili236","ili239",
00421   "ili243","ili245",
00422   "ili270","ili260",
00423   "ili270","iwn261",
00424   "ili280","mat024",
00425   "ici344","ili243",
00426   "ili263","ili260",
00427   "ili263","iwn261",
00428   "ili332","ili236",
00429   "ili355","ili153",
00430   "ili355","ili280",
00431   "ili362","ili263",
00432   0,0
00433   };
00434 
00436   const Course courses12[] = {
00437   {"dew100",1},
00438   {"fis100",3},
00439   {"hcw310",1},
00440   {"iwg101",2},
00441   {"mat111",4},
00442   {"mat121",4},
00443   {"dew101",1},
00444   {"fis110",5},
00445   {"iwi131",3},
00446   {"mat112",4},
00447   {"mat122",4},
00448   {"dewxx0",1},
00449   {"fis120",4},
00450   {"hcw311",1},
00451   {"hxwxx1",1},
00452   {"ili142",4},
00453   {"mat113",4},
00454   {"mat123",4},
00455   {"fis130",4},
00456   {"ili134",4},
00457   {"ili151",3},
00458   {"iwm185",3},
00459   {"mat124",4},
00460   {"fis140",4},
00461   {"hxwxx2",1},
00462   {"ile260",3},
00463   {"ili260",3},
00464   {"iwn170",3},
00465   {"qui104",3},
00466   {"ili231",3},
00467   {"ili243",4},
00468   {"ili252",4},
00469   {"ili273",3},
00470   {"mat210",4},
00471   {"mat260",4},
00472   {"ild208",3},
00473   {"ili221",4},
00474   {"ili274",3},
00475   {"ili281",3},
00476   {"iwn270",3},
00477   {"mat270",4},
00478   {"hrw150",2},
00479   {"ili238",4},
00480   {"ili242",3},
00481   {"ili275",3},
00482   {"ili355",4},
00483   {"hrw110",2},
00484   {"ici393",4},
00485   {"ili237",4},
00486   {"ili334",4},
00487   {"ili363",3},
00488   {"iwn261",3},
00489   {"hrw100",2},
00490   {"ici382",4},
00491   {"ili331",4},
00492   {"ili362",3},
00493   {"ili381",3},
00494   {"iln230",3},
00495   {"ici313",2},
00496   {"ici315",2},
00497   {"ici332",3},
00498   {"ici344",4},
00499   {"icn336",3},
00500   {"iwi365",3},
00501   {"ici314",2},
00502   {"ici367",2},
00503   {0,0}
00504   };
00505 
00507   const char* prereqs12[] = {
00508   "dew101","dew100",
00509   "fis110","fis100",
00510   "fis110","mat121",
00511   "mat112","mat111",
00512   "mat122","mat111",
00513   "mat122","mat121",
00514   "dewxx0","dew101",
00515   "fis120","fis110",
00516   "fis120","mat122",
00517   "hcw311","hcw310",
00518   "ili142","iwi131",
00519   "mat113","mat112",
00520   "mat113","mat122",
00521   "mat123","mat112",
00522   "mat123","mat122",
00523   "fis130","fis110",
00524   "fis130","mat122",
00525   "ili134","iwi131",
00526   "ili151","mat112",
00527   "mat124","mat113",
00528   "mat124","mat123",
00529   "fis140","fis120",
00530   "fis140","fis130",
00531   "ile260","fis120",
00532   "ile260","mat124",
00533   "ili231","iwi131",
00534   "ili252","iwi131",
00535   "ili273","ili260",
00536   "mat210","mat113",
00537   "mat260","iwi131",
00538   "mat260","mat113",
00539   "mat260","mat123",
00540   "ili221","ili134",
00541   "ili221","ili231",
00542   "ili221","mat260",
00543   "ili274","ili273",
00544   "ili281","mat260",
00545   "mat270","iwi131",
00546   "mat270","mat113",
00547   "mat270","mat123",
00548   "ili238","ili134",
00549   "ili242","ili142",
00550   "ili275","ili274",
00551   "ili355","ili221",
00552   "hrw110","hrw150",
00553   "ici393","mat210",
00554   "ici393","mat260",
00555   "ili237","ili231",
00556   "ili237","ili252",
00557   "ili334","ili238",
00558   "ili363","ili273",
00559   "hrw100","hrw110",
00560   "ici382","ili334",
00561   "ili331","ili238",
00562   "ili331","ili274",
00563   "ili362","ili363",
00564   "ili381","ili281",
00565   "ili381","mat210",
00566   "iln230","iwn170",
00567   "ici313","ili331",
00568   "ici332","ici393",
00569   "ici332","ili331",
00570   "ici344","ili243",
00571   "icn336","ici393",
00572   "ici314","ici313",
00573   0,0
00574   };
00575 
00577   const Curriculum curriculum[]=
00578     { { 8, 10, 24, 2, 10,
00579         courses8, prereqs8
00580       },
00581       { 10, 10, 24, 2, 10,
00582         courses10, prereqs10
00583       },
00584       { 12, 10, 24, 2, 10,
00585         courses12, prereqs12
00586       }
00587     };
00588 
00590   const unsigned int n_examples = sizeof(curriculum) / sizeof(Curriculum);
00591 
00593 }
00594 
00595 // STATISTICS: example-any
00596