Generated on Tue Apr 18 10:21:28 2017 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: 2016-10-25 12:52:26 +0200 (Tue, 25 Oct 2016) $ by $Author: schulte $
00013  *     $Revision: 15233 $
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              IntPropLevel) {
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     GECODE_POST;
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              IntPropLevel) {
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     PostInfo pi(home);
00096 
00097     // Capacity constraint for each dimension
00098     for (int k=d; k--; )
00099       for (int j=m; j--; ) {
00100         IntView li(l[j*d+k]);
00101         if (me_failed(li.lq(home,c[k]))) {
00102           home.fail();
00103           return IntSet::empty;
00104         }
00105       }
00106 
00107     // Post a binpacking constraint for each dimension
00108     for (int k=d; k--; ) {
00109       ViewArray<OffsetView> lv(home,m);
00110       for (int j=m; j--; )
00111         lv[j] = OffsetView(l[j*d+k],0);
00112 
00113       ViewArray<BinPacking::Item> bv(home,n);
00114       for (int i=n; i--; )
00115         bv[i] = BinPacking::Item(b[i],s[i*d+k]);
00116 
00117       if (Int::BinPacking::Pack::post(home,lv,bv) == ES_FAILED) {
00118         home.fail();
00119         return IntSet::empty;
00120       }
00121     }
00122 
00123 
00124     // Clique Finding and distinct posting
00125     {
00126       // First construct the conflict graph
00127       Region r(home);
00128       BinPacking::ConflictGraph cg(home,r,b,m);
00129 
00130       for (int i=0; i<n-1; i++) {
00131         for (int j=i+1; j<n; j++) {
00132           unsigned int nl = 0;
00133           unsigned int ds = 0;
00134           IntVarValues ii(b[i]), jj(b[j]);
00135           while (ii() && jj()) {
00136             if (ii.val() < jj.val()) {
00137               ++ii;
00138             } else if (ii.val() > jj.val()) {
00139               ++jj;
00140             } else {
00141               ds++;
00142               for (int k=d; k--; )
00143                 if (s[i*d+k] + s[j*d+k] > c[k]) {
00144                   nl++;
00145                   break;
00146                 }
00147               ++ii; ++jj;
00148             }
00149           }
00150           if (nl >= ds)
00151             cg.edge(i,j);
00152         }
00153       }
00154 
00155       if (cg.post() == ES_FAILED)
00156         home.fail();
00157 
00158       // The clique can be computed even if home is failed
00159       return cg.maxclique();
00160     }
00161   }
00162 
00163 }
00164 
00165 // STATISTICS: int-post