Generated on Fri Mar 20 15:55:53 2015 for Gecode by doxygen 1.6.3

bin-packing.cpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Stefano Gualandi <stefano.gualandi@gmail.com>
00005  *     Christian Schulte <schulte@gecode.org>
00006  *
00007  *  Copyright:
00008  *     Stefano Gualandi, 2013
00009  *     Christian Schulte, 2010
00010  *
00011  *  Last modified:
00012  *     $Date: 2014-07-30 14:16:57 +0200 (Wed, 30 Jul 2014) $ by $Author: schulte $
00013  *     $Revision: 14181 $
00014  *
00015  *  This file is part of Gecode, the generic constraint
00016  *  development environment:
00017  *     http://www.gecode.org
00018  *
00019  *  Permission is hereby granted, free of charge, to any person obtaining
00020  *  a copy of this software and associated documentation files (the
00021  *  "Software"), to deal in the Software without restriction, including
00022  *  without limitation the rights to use, copy, modify, merge, publish,
00023  *  distribute, sublicense, and/or sell copies of the Software, and to
00024  *  permit persons to whom the Software is furnished to do so, subject to
00025  *  the following conditions:
00026  *
00027  *  The above copyright notice and this permission notice shall be
00028  *  included in all copies or substantial portions of the Software.
00029  *
00030  *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00031  *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00032  *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00033  *  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
00034  *  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
00035  *  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
00036  *  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00037  *
00038  */
00039 
00040 #include <gecode/int/bin-packing.hh>
00041 
00042 namespace Gecode {
00043 
00044   void
00045   binpacking(Home home, 
00046              const IntVarArgs& l, 
00047              const IntVarArgs& b, const IntArgs& s,
00048              IntConLevel) {
00049     using namespace Int;
00050     if (l.same(home,b))
00051       throw ArgumentSame("Int::binpacking");
00052     if (b.size() != s.size())
00053       throw ArgumentSizeMismatch("Int::binpacking");      
00054     for (int i=s.size(); i--; )
00055       Limits::nonnegative(s[i],"Int::binpacking");
00056     if (home.failed()) return;
00057 
00058     ViewArray<OffsetView> lv(home,l.size());
00059     for (int i=l.size(); i--; )
00060       lv[i] = OffsetView(l[i],0);
00061 
00062     ViewArray<BinPacking::Item> bs(home,b.size());
00063     for (int i=bs.size(); i--; )
00064       bs[i] = BinPacking::Item(b[i],s[i]);
00065 
00066     GECODE_ES_FAIL(Int::BinPacking::Pack::post(home,lv,bs));
00067   }
00068 
00069   IntSet
00070   binpacking(Home home, int d,
00071              const IntVarArgs& l, const IntVarArgs& b, 
00072              const IntArgs& s, const IntArgs& c,
00073              IntConLevel) {
00074     using namespace Int;
00075 
00076     if (l.same(home,b))
00077       throw ArgumentSame("Int::binpacking");
00078 
00079     // The number of items
00080     int n = b.size();
00081     // The number of bins
00082     int m = l.size() / d;
00083 
00084     // Check input sizes
00085     if ((n*d != s.size()) || (m*d != l.size()) || (d != c.size()))
00086       throw ArgumentSizeMismatch("Int::binpacking");      
00087     for (int i=s.size(); i--; )
00088       Limits::nonnegative(s[i],"Int::binpacking");
00089     for (int i=c.size(); i--; )
00090       Limits::nonnegative(c[i],"Int::binpacking");
00091 
00092     if (home.failed()) 
00093       return IntSet::empty;
00094 
00095     // Capacity constraint for each dimension
00096     for (int k=d; k--; )
00097       for (int j=m; j--; ) {
00098         IntView li(l[j*d+k]);
00099         if (me_failed(li.lq(home,c[k]))) {
00100           home.fail();
00101           return IntSet::empty;
00102         }
00103       }
00104 
00105     // Post a binpacking constraint for each dimension
00106     for (int k=d; k--; ) {
00107       ViewArray<OffsetView> lv(home,m);
00108       for (int j=m; j--; )
00109         lv[j] = OffsetView(l[j*d+k],0);
00110       
00111       ViewArray<BinPacking::Item> bv(home,n);
00112       for (int i=n; i--; )
00113         bv[i] = BinPacking::Item(b[i],s[i*d+k]);
00114       
00115       if (Int::BinPacking::Pack::post(home,lv,bv) == ES_FAILED) {
00116         home.fail();
00117         return IntSet::empty;
00118       }
00119     }
00120 
00121 
00122     // Clique Finding and distinct posting
00123     {
00124       // First construct the conflict graph
00125       Region r(home);
00126       BinPacking::ConflictGraph cg(home,r,b,m);
00127 
00128       for (int i=0; i<n-1; i++) {
00129         for (int j=i+1; j<n; j++) {
00130           unsigned int nl = 0;
00131           unsigned int ds = 0;
00132           IntVarValues ii(b[i]), jj(b[j]);
00133           while (ii() && jj()) {
00134             if (ii.val() < jj.val()) {
00135               ++ii;
00136             } else if (ii.val() > jj.val()) {
00137               ++jj;
00138             } else {
00139               ds++;
00140               for (int k=d; k--; )
00141                 if (s[i*d+k] + s[j*d+k] > c[k]) {
00142                   nl++;
00143                   break;
00144                 }
00145               ++ii; ++jj;
00146             }
00147           }
00148           if (nl >= ds)
00149             cg.edge(i,j);
00150         }
00151       }
00152 
00153       if (cg.post() == ES_FAILED)
00154         home.fail();
00155 
00156       // The clique can be computed even if home is failed
00157       return cg.maxclique();
00158     }
00159   }
00160   
00161 }
00162 
00163 // STATISTICS: int-post