Generated on Tue Apr 18 10:21:47 2017 for Gecode by doxygen 1.6.3

conflict-graph.hpp

Go to the documentation of this file.
00001 /* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */
00002 /*
00003  *  Main authors:
00004  *     Christian Schulte <schulte@gecode.org>
00005  *     Stefano Gualandi <stefano.gualandi@gmail.com>
00006  *
00007  *  Copyright:
00008  *     Stefano Gualandi, 2013
00009  *     Christian Schulte, 2014
00010  *
00011  *  Last modified:
00012  *     $Date: 2016-11-08 17:23:24 +0100 (Tue, 08 Nov 2016) $ by $Author: schulte $
00013  *     $Revision: 15253 $
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/rel.hh>
00041 #include <gecode/int/distinct.hh>
00042 
00043 namespace Gecode { namespace Int { namespace BinPacking {
00044 
00045   forceinline int
00046   ConflictGraph::nodes(void) const {
00047     return b.size();
00048   }
00049 
00050   forceinline
00051   ConflictGraph::NodeSet::NodeSet(void) {}
00052   forceinline
00053   ConflictGraph::NodeSet::NodeSet(Region& r, int n)
00054     : Support::RawBitSetBase(r,static_cast<unsigned int>(n)) {}
00055   forceinline
00056   ConflictGraph::NodeSet::NodeSet(Region& r, int n,
00057                                   const NodeSet& ns)
00058     : Support::RawBitSetBase(r,static_cast<unsigned int>(n),ns) {}
00059   forceinline void
00060   ConflictGraph::NodeSet::allocate(Region& r, int n) {
00061     Support::RawBitSetBase::allocate(r,static_cast<unsigned int>(n));
00062   }
00063   forceinline void
00064   ConflictGraph::NodeSet::init(Region& r, int n) {
00065     Support::RawBitSetBase::init(r,static_cast<unsigned int>(n));
00066   }
00067   forceinline bool
00068   ConflictGraph::NodeSet::in(int i) const {
00069     return RawBitSetBase::get(static_cast<unsigned int>(i));
00070   }
00071   forceinline void
00072   ConflictGraph::NodeSet::incl(int i) {
00073     RawBitSetBase::set(static_cast<unsigned int>(i));
00074   }
00075   forceinline void
00076   ConflictGraph::NodeSet::excl(int i) {
00077     RawBitSetBase::clear(static_cast<unsigned int>(i));
00078   }
00079   forceinline void
00080   ConflictGraph::NodeSet::copy(int n, const NodeSet& ns) {
00081     RawBitSetBase::copy(static_cast<unsigned int>(n),ns);
00082   }
00083   forceinline void
00084   ConflictGraph::NodeSet::empty(int n) {
00085     RawBitSetBase::clearall(static_cast<unsigned int>(n));
00086   }
00087   forceinline bool
00088   ConflictGraph::NodeSet::iwn(NodeSet& cwa, const NodeSet& a,
00089                               NodeSet& cwb, const NodeSet& b,
00090                               const NodeSet& c, int _n) {
00091     unsigned int n = static_cast<unsigned int>(_n);
00092     // This excludes the sentinel bit
00093     unsigned int pos = n / bpb;
00094     unsigned int bits = n % bpb;
00095 
00096     // Whether any bit is set
00097     Support::BitSetData abc; abc.init();
00098     for (unsigned int i=0; i<pos; i++) {
00099       cwa.data[i] = Support::BitSetData::a(a.data[i],c.data[i]);
00100       cwb.data[i] = Support::BitSetData::a(b.data[i],c.data[i]);
00101       abc.o(cwa.data[i]);
00102       abc.o(cwb.data[i]);
00103     }
00104     // Note that the sentinel bit is copied as well
00105     cwa.data[pos] = Support::BitSetData::a(a.data[pos],c.data[pos]);
00106     cwb.data[pos] = Support::BitSetData::a(b.data[pos],c.data[pos]);
00107     abc.o(cwa.data[pos],bits);
00108     abc.o(cwb.data[pos],bits);
00109 
00110     assert(cwa.get(n) && cwb.get(n));
00111     return abc.none();
00112   }
00113 
00114 
00115   forceinline
00116   ConflictGraph::Node::Node(void) {}
00117 
00118   forceinline
00119   ConflictGraph::Nodes::Nodes(const NodeSet& ns0)
00120     : ns(ns0), c(ns.next(0)) {}
00121   forceinline void
00122   ConflictGraph::Nodes::operator ++(void) {
00123     c = ns.next(c+1);
00124   }
00125   forceinline int
00126   ConflictGraph::Nodes::operator ()(void) const {
00127     return static_cast<int>(c);
00128   }
00129 
00130   forceinline
00131   ConflictGraph::Clique::Clique(Region& r, int m)
00132     : n(r,m), c(0), w(0) {}
00133   forceinline void
00134   ConflictGraph::Clique::incl(int i, unsigned int wi) {
00135     n.incl(i); c++; w += wi;
00136   }
00137   forceinline void
00138   ConflictGraph::Clique::excl(int i, unsigned int wi) {
00139     n.excl(i); c--; w -= wi;
00140   }
00141 
00142   forceinline
00143   ConflictGraph::ConflictGraph(Home& h, Region& reg,
00144                                const IntVarArgs& b0, int m)
00145     : home(h), b(b0),
00146       bins(static_cast<unsigned int>(m)),
00147       node(reg.alloc<Node>(nodes())),
00148       cur(reg,nodes()), max(reg,nodes()) {
00149     for (int i=nodes(); i--; ) {
00150       node[i].n.init(reg,nodes());
00151       node[i].d=node[i].w=0;
00152     }
00153   }
00154 
00155   forceinline
00156   ConflictGraph::~ConflictGraph(void) {
00157   }
00158 
00159   forceinline void
00160   ConflictGraph::edge(int i, int j, bool add) {
00161     if (add) {
00162       assert(!node[i].n.in(j) && !node[j].n.in(i));
00163       node[i].n.incl(j); node[i].d++; node[i].w++;
00164       node[j].n.incl(i); node[j].d++; node[j].w++;
00165     } else {
00166       assert(node[i].n.in(j) && node[j].n.in(i));
00167       node[i].n.excl(j); node[i].d--;
00168       node[j].n.excl(i); node[j].d--;
00169     }
00170   }
00171 
00172   forceinline bool
00173   ConflictGraph::adjacent(int i, int j) const {
00174     assert(node[i].n.in(j) == node[j].n.in(i));
00175     return node[i].n.in(j);
00176   }
00177 
00178   forceinline int
00179   ConflictGraph::pivot(const NodeSet& a, const NodeSet& b) const {
00180     Nodes i(a), j(b);
00181     assert((i() < nodes()) || (j() < nodes()));
00182     int p;
00183     if (i() < nodes()) {
00184       p = i(); ++i;
00185     } else {
00186       p = j(); ++j;
00187     }
00188     unsigned int m = node[p].d;
00189     while (i() < nodes()) {
00190       if (node[i()].d > m) {
00191         p=i(); m=node[p].d;
00192       }
00193       ++i;
00194     }
00195     while (j() < nodes()) {
00196       if (node[j()].d > m) {
00197         p=j(); m=node[p].d;
00198       }
00199       ++j;
00200     }
00201     return p;
00202   }
00203 
00204   forceinline ExecStatus
00205   ConflictGraph::clique(void) {
00206     // Remember clique
00207     if ((cur.c > max.c) || ((cur.c == max.c) && (cur.w > max.w))) {
00208       max.n.copy(nodes(),cur.n); max.c=cur.c; max.w=cur.w;
00209       if (max.c > bins)
00210         return ES_FAILED;
00211     }
00212     // Compute corresponding variables
00213     ViewArray<IntView> bv(home,static_cast<int>(cur.c));
00214     int i=0;
00215     for (Nodes c(cur.n); c() < nodes(); ++c)
00216       bv[i++] = b[c()];
00217     assert(i == static_cast<int>(cur.c));
00218     return Distinct::Dom<IntView>::post(home,bv);
00219   }
00220 
00221   forceinline ExecStatus
00222   ConflictGraph::clique(int i) {
00223     if (1 > max.c) {
00224       assert(max.n.none(nodes()));
00225       max.n.incl(i); max.c=1; max.w=0;
00226     }
00227     return ES_OK;
00228   }
00229 
00230   forceinline ExecStatus
00231   ConflictGraph::clique(int i, int j) {
00232     unsigned int w = node[i].w + node[j].w;
00233     if ((2 > max.c) || ((2 == max.c) && (cur.w > max.w))) {
00234       max.n.empty(nodes());
00235       max.n.incl(i); max.n.incl(j);
00236       max.c=2; max.w=w;
00237       if (max.c > bins)
00238         return ES_FAILED;
00239     }
00240     return Rel::Nq<IntView,IntView>::post(home,b[i],b[j]);
00241   }
00242 
00243   forceinline ExecStatus
00244   ConflictGraph::clique(int i, int j, int k) {
00245     unsigned int w = node[i].w + node[j].w + node[k].w;
00246     if ((3 > max.c) || ((3 == max.c) && (cur.w > max.w))) {
00247       max.n.empty(nodes());
00248       max.n.incl(i); max.n.incl(j); max.n.incl(k);
00249       max.c=3; max.w=w;
00250       if (max.c > bins)
00251         return ES_FAILED;
00252     }
00253     // Compute corresponding variables
00254     ViewArray<IntView> bv(home,3);
00255     bv[0]=b[i]; bv[1]=b[j]; bv[2]=b[k];
00256     return Distinct::Dom<IntView>::post(home,bv);
00257   }
00258 
00259   forceinline ExecStatus
00260   ConflictGraph::post(void) {
00261     // Find some simple cliques of sizes 2 and 3.
00262     {
00263       Region reg(home);
00264       // Nodes can be entered twice (for degree 2 and later for degree 1)
00265       Support::StaticStack<int,Region> n(reg,2*nodes());
00266       // Make a copy of the degree information to be used as weights
00267       // and record all nodes of degree 1 and 2.
00268       for (int i=nodes(); i--; ) {
00269         if ((node[i].d == 1) || (node[i].d == 2))
00270           n.push(i);
00271       }
00272       while (!n.empty()) {
00273         int i = n.pop();
00274         switch (node[i].d) {
00275         case 0:
00276           // Might happen as the edges have already been removed
00277           break;
00278         case 1: {
00279           Nodes ii(node[i].n);
00280           int j=ii();
00281           GECODE_ES_CHECK(clique(i,j));
00282           // Remove edge
00283           edge(i,j,false);
00284           if ((node[j].d == 1) || (node[j].d == 2))
00285             n.push(j);
00286           break;
00287         }
00288         case 2: {
00289           Nodes ii(node[i].n);
00290           int j=ii(); ++ii;
00291           int k=ii();
00292           if (adjacent(j,k)) {
00293             GECODE_ES_CHECK(clique(i,j,k));
00294             // Can the edge j-k still be member of another clique?
00295             if ((node[j].d == 2) || (node[k].d == 2))
00296               edge(j,k,false);
00297           } else {
00298             GECODE_ES_CHECK(clique(i,j));
00299             GECODE_ES_CHECK(clique(i,k));
00300           }
00301           edge(i,j,false);
00302           edge(i,k,false);
00303           if ((node[j].d == 1) || (node[j].d == 2))
00304             n.push(j);
00305           if ((node[k].d == 1) || (node[k].d == 2))
00306             n.push(k);
00307           break;
00308         }
00309         default: GECODE_NEVER;
00310         }
00311       }
00312     }
00313     // Initialize for Bron-Kerbosch
00314     {
00315       Region reg(home);
00316       NodeSet p(reg,nodes()), x(reg,nodes());
00317       bool empty = true;
00318       for (int i=nodes(); i--; )
00319         if (node[i].d > 0) {
00320           p.incl(i); empty = false;
00321         } else {
00322           // Report clique of size 1
00323           GECODE_ES_CHECK(clique(i));
00324         }
00325       if (empty)
00326         return ES_OK;
00327       GECODE_ES_CHECK(bk(p,x));
00328     }
00329     return ES_OK;
00330   }
00331 
00332   inline IntSet
00333   ConflictGraph::maxclique(void) const {
00334     Region reg(home);
00335     int* n=reg.alloc<int>(max.c);
00336     int j=0;
00337     for (Nodes i(max.n); i() < nodes(); ++i)
00338       n[j++]=i();
00339     assert(j == static_cast<int>(max.c));
00340     IntSet s(n,static_cast<int>(max.c));
00341     return s;
00342   }
00343 
00344 }}}
00345 
00346 // STATISTICS: int-prop
00347