this repo has no description
1/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ 2/* 3 * Main authors: 4 * Christian Schulte <schulte@gecode.org> 5 * Stefano Gualandi <stefano.gualandi@gmail.com> 6 * 7 * Copyright: 8 * Stefano Gualandi, 2013 9 * Christian Schulte, 2014 10 * 11 * This file is part of Gecode, the generic constraint 12 * development environment: 13 * http://www.gecode.org 14 * 15 * Permission is hereby granted, free of charge, to any person obtaining 16 * a copy of this software and associated documentation files (the 17 * "Software"), to deal in the Software without restriction, including 18 * without limitation the rights to use, copy, modify, merge, publish, 19 * distribute, sublicense, and/or sell copies of the Software, and to 20 * permit persons to whom the Software is furnished to do so, subject to 21 * the following conditions: 22 * 23 * The above copyright notice and this permission notice shall be 24 * included in all copies or substantial portions of the Software. 25 * 26 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 27 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 28 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 29 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 30 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 31 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 32 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 33 * 34 */ 35 36#include <gecode/int/rel.hh> 37#include <gecode/int/distinct.hh> 38 39namespace Gecode { namespace Int { namespace BinPacking { 40 41 forceinline int 42 ConflictGraph::nodes(void) const { 43 return b.size(); 44 } 45 46 forceinline 47 ConflictGraph::NodeSet::NodeSet(void) {} 48 forceinline 49 ConflictGraph::NodeSet::NodeSet(Region& r, int n) 50 : Support::RawBitSetBase(r,static_cast<unsigned int>(n)) {} 51 forceinline 52 ConflictGraph::NodeSet::NodeSet(Region& r, int n, 53 const NodeSet& ns) 54 : Support::RawBitSetBase(r,static_cast<unsigned int>(n),ns) {} 55 forceinline void 56 ConflictGraph::NodeSet::allocate(Region& r, int n) { 57 Support::RawBitSetBase::allocate(r,static_cast<unsigned int>(n)); 58 } 59 forceinline void 60 ConflictGraph::NodeSet::init(Region& r, int n) { 61 Support::RawBitSetBase::init(r,static_cast<unsigned int>(n)); 62 } 63 forceinline bool 64 ConflictGraph::NodeSet::in(int i) const { 65 return RawBitSetBase::get(static_cast<unsigned int>(i)); 66 } 67 forceinline void 68 ConflictGraph::NodeSet::incl(int i) { 69 RawBitSetBase::set(static_cast<unsigned int>(i)); 70 } 71 forceinline void 72 ConflictGraph::NodeSet::excl(int i) { 73 RawBitSetBase::clear(static_cast<unsigned int>(i)); 74 } 75 forceinline void 76 ConflictGraph::NodeSet::copy(int n, const NodeSet& ns) { 77 RawBitSetBase::copy(static_cast<unsigned int>(n),ns); 78 } 79 forceinline void 80 ConflictGraph::NodeSet::empty(int n) { 81 RawBitSetBase::clearall(static_cast<unsigned int>(n)); 82 } 83 forceinline bool 84 ConflictGraph::NodeSet::iwn(NodeSet& cwa, const NodeSet& a, 85 NodeSet& cwb, const NodeSet& b, 86 const NodeSet& c, int _n) { 87 unsigned int n = static_cast<unsigned int>(_n); 88 // This excludes the sentinel bit 89 unsigned int pos = n / bpb; 90 unsigned int bits = n % bpb; 91 92 // Whether any bit is set 93 Support::BitSetData abc; abc.init(); 94 for (unsigned int i=0; i<pos; i++) { 95 cwa.data[i] = Support::BitSetData::a(a.data[i],c.data[i]); 96 cwb.data[i] = Support::BitSetData::a(b.data[i],c.data[i]); 97 abc.o(cwa.data[i]); 98 abc.o(cwb.data[i]); 99 } 100 // Note that the sentinel bit is copied as well 101 cwa.data[pos] = Support::BitSetData::a(a.data[pos],c.data[pos]); 102 cwb.data[pos] = Support::BitSetData::a(b.data[pos],c.data[pos]); 103 abc.o(cwa.data[pos],bits); 104 abc.o(cwb.data[pos],bits); 105 106 assert(cwa.get(n) && cwb.get(n)); 107 return abc.none(); 108 } 109 110 111 forceinline 112 ConflictGraph::Node::Node(void) {} 113 114 forceinline 115 ConflictGraph::Nodes::Nodes(const NodeSet& ns0) 116 : ns(ns0), c(ns.next(0)) {} 117 forceinline void 118 ConflictGraph::Nodes::operator ++(void) { 119 c = ns.next(c+1); 120 } 121 forceinline int 122 ConflictGraph::Nodes::operator ()(void) const { 123 return static_cast<int>(c); 124 } 125 126 forceinline 127 ConflictGraph::Clique::Clique(Region& r, int m) 128 : n(r,m), c(0), w(0) {} 129 forceinline void 130 ConflictGraph::Clique::incl(int i, unsigned int wi) { 131 n.incl(i); c++; w += wi; 132 } 133 forceinline void 134 ConflictGraph::Clique::excl(int i, unsigned int wi) { 135 n.excl(i); c--; w -= wi; 136 } 137 138 forceinline 139 ConflictGraph::ConflictGraph(Home& h, Region& reg, 140 const IntVarArgs& b0, int m) 141 : home(h), b(b0), 142 bins(static_cast<unsigned int>(m)), 143 node(reg.alloc<Node>(nodes())), 144 cur(reg,nodes()), max(reg,nodes()) { 145 for (int i=0; i<nodes(); i++) { 146 node[i].n.init(reg,nodes()); 147 node[i].d=node[i].w=0; 148 } 149 } 150 151 forceinline 152 ConflictGraph::~ConflictGraph(void) { 153 } 154 155 forceinline void 156 ConflictGraph::edge(int i, int j, bool add) { 157 if (add) { 158 assert(!node[i].n.in(j) && !node[j].n.in(i)); 159 node[i].n.incl(j); node[i].d++; node[i].w++; 160 node[j].n.incl(i); node[j].d++; node[j].w++; 161 } else { 162 assert(node[i].n.in(j) && node[j].n.in(i)); 163 node[i].n.excl(j); node[i].d--; 164 node[j].n.excl(i); node[j].d--; 165 } 166 } 167 168 forceinline bool 169 ConflictGraph::adjacent(int i, int j) const { 170 assert(node[i].n.in(j) == node[j].n.in(i)); 171 return node[i].n.in(j); 172 } 173 174 forceinline int 175 ConflictGraph::pivot(const NodeSet& a, const NodeSet& b) const { 176 Nodes i(a), j(b); 177 assert((i() < nodes()) || (j() < nodes())); 178 int p; 179 if (i() < nodes()) { 180 p = i(); ++i; 181 } else { 182 p = j(); ++j; 183 } 184 unsigned int m = node[p].d; 185 while (i() < nodes()) { 186 if (node[i()].d > m) { 187 p=i(); m=node[p].d; 188 } 189 ++i; 190 } 191 while (j() < nodes()) { 192 if (node[j()].d > m) { 193 p=j(); m=node[p].d; 194 } 195 ++j; 196 } 197 return p; 198 } 199 200 forceinline ExecStatus 201 ConflictGraph::clique(void) { 202 // Remember clique 203 if ((cur.c > max.c) || ((cur.c == max.c) && (cur.w > max.w))) { 204 max.n.copy(nodes(),cur.n); max.c=cur.c; max.w=cur.w; 205 if (max.c > bins) 206 return ES_FAILED; 207 } 208 // Compute corresponding variables 209 ViewArray<IntView> bv(home,static_cast<int>(cur.c)); 210 int i=0; 211 for (Nodes c(cur.n); c() < nodes(); ++c) 212 bv[i++] = b[c()]; 213 assert(i == static_cast<int>(cur.c)); 214 return Distinct::Dom<IntView>::post(home,bv); 215 } 216 217 forceinline ExecStatus 218 ConflictGraph::clique(int i) { 219 if (1 > max.c) { 220 assert(max.n.none(nodes())); 221 max.n.incl(i); max.c=1; max.w=0; 222 } 223 return ES_OK; 224 } 225 226 forceinline ExecStatus 227 ConflictGraph::clique(int i, int j) { 228 unsigned int w = node[i].w + node[j].w; 229 if ((2 > max.c) || ((2 == max.c) && (cur.w > max.w))) { 230 max.n.empty(nodes()); 231 max.n.incl(i); max.n.incl(j); 232 max.c=2; max.w=w; 233 if (max.c > bins) 234 return ES_FAILED; 235 } 236 return Rel::Nq<IntView,IntView>::post(home,b[i],b[j]); 237 } 238 239 forceinline ExecStatus 240 ConflictGraph::clique(int i, int j, int k) { 241 unsigned int w = node[i].w + node[j].w + node[k].w; 242 if ((3 > max.c) || ((3 == max.c) && (cur.w > max.w))) { 243 max.n.empty(nodes()); 244 max.n.incl(i); max.n.incl(j); max.n.incl(k); 245 max.c=3; max.w=w; 246 if (max.c > bins) 247 return ES_FAILED; 248 } 249 // Compute corresponding variables 250 ViewArray<IntView> bv(home,3); 251 bv[0]=b[i]; bv[1]=b[j]; bv[2]=b[k]; 252 return Distinct::Dom<IntView>::post(home,bv); 253 } 254 255 forceinline ExecStatus 256 ConflictGraph::post(void) { 257 // Find some simple cliques of sizes 2 and 3. 258 Region reg; 259 { 260 // Nodes can be entered twice (for degree 2 and later for degree 1) 261 Support::StaticStack<int,Region> n(reg,2*nodes()); 262 // Make a copy of the degree information to be used as weights 263 // and record all nodes of degree 1 and 2. 264 for (int i=0; i<nodes(); i++) { 265 if ((node[i].d == 1) || (node[i].d == 2)) 266 n.push(i); 267 } 268 while (!n.empty()) { 269 int i = n.pop(); 270 switch (node[i].d) { 271 case 0: 272 // Might happen as the edges have already been removed 273 break; 274 case 1: { 275 Nodes ii(node[i].n); 276 int j=ii(); 277 GECODE_ES_CHECK(clique(i,j)); 278 // Remove edge 279 edge(i,j,false); 280 if ((node[j].d == 1) || (node[j].d == 2)) 281 n.push(j); 282 break; 283 } 284 case 2: { 285 Nodes ii(node[i].n); 286 int j=ii(); ++ii; 287 int k=ii(); 288 if (adjacent(j,k)) { 289 GECODE_ES_CHECK(clique(i,j,k)); 290 // Can the edge j-k still be member of another clique? 291 if ((node[j].d == 2) || (node[k].d == 2)) 292 edge(j,k,false); 293 } else { 294 GECODE_ES_CHECK(clique(i,j)); 295 GECODE_ES_CHECK(clique(i,k)); 296 } 297 edge(i,j,false); 298 edge(i,k,false); 299 if ((node[j].d == 1) || (node[j].d == 2)) 300 n.push(j); 301 if ((node[k].d == 1) || (node[k].d == 2)) 302 n.push(k); 303 break; 304 } 305 default: GECODE_NEVER; 306 } 307 } 308 reg.free(); 309 } 310 // Initialize for Bron-Kerbosch 311 { 312 NodeSet p(reg,nodes()), x(reg,nodes()); 313 bool empty = true; 314 for (int i=0; i<nodes(); i++) 315 if (node[i].d > 0) { 316 p.incl(i); empty = false; 317 } else { 318 // Report clique of size 1 319 GECODE_ES_CHECK(clique(i)); 320 } 321 if (empty) 322 return ES_OK; 323 GECODE_ES_CHECK(bk(p,x)); 324 reg.free(); 325 } 326 return ES_OK; 327 } 328 329 inline IntSet 330 ConflictGraph::maxclique(void) const { 331 Region reg; 332 int* n=reg.alloc<int>(max.c); 333 int j=0; 334 for (Nodes i(max.n); i() < nodes(); ++i) 335 n[j++]=i(); 336 assert(j == static_cast<int>(max.c)); 337 IntSet s(n,static_cast<int>(max.c)); 338 return s; 339 } 340 341}}} 342 343// STATISTICS: int-prop 344