/* -*- mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*- */ /* * Main authors: * Christian Schulte * Stefano Gualandi * * Copyright: * Stefano Gualandi, 2013 * Christian Schulte, 2014 * * This file is part of Gecode, the generic constraint * development environment: * http://www.gecode.org * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * */ #include #include namespace Gecode { namespace Int { namespace BinPacking { forceinline int ConflictGraph::nodes(void) const { return b.size(); } forceinline ConflictGraph::NodeSet::NodeSet(void) {} forceinline ConflictGraph::NodeSet::NodeSet(Region& r, int n) : Support::RawBitSetBase(r,static_cast(n)) {} forceinline ConflictGraph::NodeSet::NodeSet(Region& r, int n, const NodeSet& ns) : Support::RawBitSetBase(r,static_cast(n),ns) {} forceinline void ConflictGraph::NodeSet::allocate(Region& r, int n) { Support::RawBitSetBase::allocate(r,static_cast(n)); } forceinline void ConflictGraph::NodeSet::init(Region& r, int n) { Support::RawBitSetBase::init(r,static_cast(n)); } forceinline bool ConflictGraph::NodeSet::in(int i) const { return RawBitSetBase::get(static_cast(i)); } forceinline void ConflictGraph::NodeSet::incl(int i) { RawBitSetBase::set(static_cast(i)); } forceinline void ConflictGraph::NodeSet::excl(int i) { RawBitSetBase::clear(static_cast(i)); } forceinline void ConflictGraph::NodeSet::copy(int n, const NodeSet& ns) { RawBitSetBase::copy(static_cast(n),ns); } forceinline void ConflictGraph::NodeSet::empty(int n) { RawBitSetBase::clearall(static_cast(n)); } forceinline bool ConflictGraph::NodeSet::iwn(NodeSet& cwa, const NodeSet& a, NodeSet& cwb, const NodeSet& b, const NodeSet& c, int _n) { unsigned int n = static_cast(_n); // This excludes the sentinel bit unsigned int pos = n / bpb; unsigned int bits = n % bpb; // Whether any bit is set Support::BitSetData abc; abc.init(); for (unsigned int i=0; i(c); } forceinline ConflictGraph::Clique::Clique(Region& r, int m) : n(r,m), c(0), w(0) {} forceinline void ConflictGraph::Clique::incl(int i, unsigned int wi) { n.incl(i); c++; w += wi; } forceinline void ConflictGraph::Clique::excl(int i, unsigned int wi) { n.excl(i); c--; w -= wi; } forceinline ConflictGraph::ConflictGraph(Home& h, Region& reg, const IntVarArgs& b0, int m) : home(h), b(b0), bins(static_cast(m)), node(reg.alloc(nodes())), cur(reg,nodes()), max(reg,nodes()) { for (int i=0; i m) { p=i(); m=node[p].d; } ++i; } while (j() < nodes()) { if (node[j()].d > m) { p=j(); m=node[p].d; } ++j; } return p; } forceinline ExecStatus ConflictGraph::clique(void) { // Remember clique if ((cur.c > max.c) || ((cur.c == max.c) && (cur.w > max.w))) { max.n.copy(nodes(),cur.n); max.c=cur.c; max.w=cur.w; if (max.c > bins) return ES_FAILED; } // Compute corresponding variables ViewArray bv(home,static_cast(cur.c)); int i=0; for (Nodes c(cur.n); c() < nodes(); ++c) bv[i++] = b[c()]; assert(i == static_cast(cur.c)); return Distinct::Dom::post(home,bv); } forceinline ExecStatus ConflictGraph::clique(int i) { if (1 > max.c) { assert(max.n.none(nodes())); max.n.incl(i); max.c=1; max.w=0; } return ES_OK; } forceinline ExecStatus ConflictGraph::clique(int i, int j) { unsigned int w = node[i].w + node[j].w; if ((2 > max.c) || ((2 == max.c) && (cur.w > max.w))) { max.n.empty(nodes()); max.n.incl(i); max.n.incl(j); max.c=2; max.w=w; if (max.c > bins) return ES_FAILED; } return Rel::Nq::post(home,b[i],b[j]); } forceinline ExecStatus ConflictGraph::clique(int i, int j, int k) { unsigned int w = node[i].w + node[j].w + node[k].w; if ((3 > max.c) || ((3 == max.c) && (cur.w > max.w))) { max.n.empty(nodes()); max.n.incl(i); max.n.incl(j); max.n.incl(k); max.c=3; max.w=w; if (max.c > bins) return ES_FAILED; } // Compute corresponding variables ViewArray bv(home,3); bv[0]=b[i]; bv[1]=b[j]; bv[2]=b[k]; return Distinct::Dom::post(home,bv); } forceinline ExecStatus ConflictGraph::post(void) { // Find some simple cliques of sizes 2 and 3. Region reg; { // Nodes can be entered twice (for degree 2 and later for degree 1) Support::StaticStack n(reg,2*nodes()); // Make a copy of the degree information to be used as weights // and record all nodes of degree 1 and 2. for (int i=0; i 0) { p.incl(i); empty = false; } else { // Report clique of size 1 GECODE_ES_CHECK(clique(i)); } if (empty) return ES_OK; GECODE_ES_CHECK(bk(p,x)); reg.free(); } return ES_OK; } inline IntSet ConflictGraph::maxclique(void) const { Region reg; int* n=reg.alloc(max.c); int j=0; for (Nodes i(max.n); i() < nodes(); ++i) n[j++]=i(); assert(j == static_cast(max.c)); IntSet s(n,static_cast(max.c)); return s; } }}} // STATISTICS: int-prop