Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions changelog.in
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,17 @@ The new fault-injection tests exercise clone, dispose-notice, IntSet,
MiniModel, and heap-allocation failure paths that are otherwise hard to
reproduce reliably.

[ENTRY]
Module: int
What: performance
Rank: minor
Issue: 202
Thanks: Fabio Tardivo
[DESCRIPTION]
Strengthen bin-packing propagation with lower bounds based on
dual-feasible functions, improving early detection of infeasible
packing states.

[ENTRY]
Module: other
What: change
Expand Down
11 changes: 8 additions & 3 deletions gecode/driver/options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,7 @@ namespace Gecode {
else if (!strncmp("dom",a,e)) { b = IPL_DOM; }
else if (!strncmp("basic",a,e)) { m |= IPL_BASIC; }
else if (!strncmp("advanced",a,e)) { m |= IPL_ADVANCED; }
else if (!strncmp("full",a,e)) { m |= IPL_FULL; }
else {
std::cerr << "Wrong argument \"" << a
<< "\" for option \"" << iopt << "\""
Expand All @@ -350,7 +351,7 @@ namespace Gecode {
IplOption::help(void) {
using namespace std;
cerr << '\t' << iopt
<< " (def,val,bnd,dom,basic,advanced)" << endl
<< " (def,val,bnd,dom,basic,advanced,full)" << endl
<< "\t\tdefault: ";
switch (vbd(cur)) {
case IPL_DEF: cerr << "def"; break;
Expand All @@ -359,8 +360,12 @@ namespace Gecode {
case IPL_DOM: cerr << "dom"; break;
default: GECODE_NEVER;
}
if (cur & IPL_BASIC) cerr << ",basic";
if (cur & IPL_ADVANCED) cerr << ",advanced";
if ((cur & IPL_FULL) == IPL_FULL)
cerr << ",full";
else {
if (cur & IPL_BASIC) cerr << ",basic";
if (cur & IPL_ADVANCED) cerr << ",advanced";
}
cerr << endl << "\t\t" << exp << endl;
}

Expand Down
20 changes: 19 additions & 1 deletion gecode/int.hh
Original file line number Diff line number Diff line change
Expand Up @@ -1015,6 +1015,7 @@ namespace Gecode {
IPL_BASIC = 4, ///< Use basic propagation algorithm
IPL_ADVANCED = 8, ///< Use advanced propagation algorithm
IPL_BASIC_ADVANCED = IPL_BASIC | IPL_ADVANCED, ///< Use both
IPL_FULL = IPL_BASIC_ADVANCED, ///< Use full propagation
IPL_BITS_ = 4 ///< Number of bits required (internal)
};

Expand Down Expand Up @@ -3147,7 +3148,16 @@ namespace Gecode {
* for each \f$i\f$ with \f$0\leq i<|b|\f$ the constraint
* \f$0\leq b_i<|l|\f$ holds.
*
* The propagation follows: Paul Shaw. A Constraint for Bin Packing. CP 2004.
* Basic and knapsack propagation are based on:
* Paul Shaw. A Constraint for Bin Packing. CP 2004.
* The lower-bound phase uses dual-feasible functions described in:
* Tardivo et al. CP for Bin Packing with Multi-Core and GPUs. CP 2024.
* The propagation level \a ipl controls the amount of filtering:
* - \a IPL_BASIC performs basic load and item filtering only.
* - \a IPL_ADVANCED performs basic filtering, knapsack filtering using
* NoSum, and a small DFF portfolio (CCM1 and MT). It is the default
* (\a IPL_DEF).
* - \a IPL_FULL performs all of the above and the complete DFF portfolio.
*
* Throws the following exceptions:
* - Of type Int::ArgumentSizeMismatch if \a b and \a s are not of
Expand Down Expand Up @@ -3191,6 +3201,14 @@ namespace Gecode {
* number of items due to the Bron-Kerbosch algorithm used for finding
* the maximal conflict item sets.
*
* The propagation level \a ipl controls the filtering performed by each
* per-dimension bin-packing propagator:
* - \a IPL_BASIC performs basic load and item filtering only.
* - \a IPL_ADVANCED performs basic filtering, knapsack filtering using
* NoSum, and a small DFF portfolio (CCM1 and MT). It is the default
* (\a IPL_DEF).
* - \a IPL_FULL performs all of the above and the complete DFF portfolio.
*
* Throws the following exceptions:
* - Of type Int::ArgumentSizeMismatch if any of the following properties
* is violated: \f$|b|=n\f$, \f$|l|=m\cdot d\f$, \f$|s|=n\cdot d\f$,
Expand Down
8 changes: 4 additions & 4 deletions gecode/int/bin-packing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ namespace Gecode {
binpacking(Home home,
const IntVarArgs& l,
const IntVarArgs& b, const IntArgs& s,
IntPropLevel) {
IntPropLevel ipl) {
using namespace Int;
if (same(l,b))
throw ArgumentSame("Int::binpacking");
Expand All @@ -59,14 +59,14 @@ namespace Gecode {
for (int i=0; i<bs.size(); i++)
bs[i] = BinPacking::Item(b[i],s[i]);

GECODE_ES_FAIL(Int::BinPacking::Pack::post(home,lv,bs));
GECODE_ES_FAIL(Int::BinPacking::Pack::post(home,lv,bs,ipl));
}

IntSet
binpacking(Home home, int d,
const IntVarArgs& l, const IntVarArgs& b,
const IntArgs& s, const IntArgs& c,
IntPropLevel) {
IntPropLevel ipl) {
using namespace Int;

if (same(l,b))
Expand Down Expand Up @@ -110,7 +110,7 @@ namespace Gecode {
for (int i=0; i<n; i++)
bv[i] = BinPacking::Item(b[i],s[i*d+k]);

if (Int::BinPacking::Pack::post(home,lv,bv) == ES_FAILED) {
if (Int::BinPacking::Pack::post(home,lv,bv,ipl) == ES_FAILED) {
home.fail();
return IntSet::empty;
}
Expand Down
54 changes: 51 additions & 3 deletions gecode/int/bin-packing.hh
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
* Christian Schulte <schulte@gecode.dev>
*
* Contributing authors:
* Fabio Tardivo <ftardivo@nmsu.edu>
* Stefano Gualandi <stefano.gualandi@gmail.com>
*
* Copyright:
* Fabio Tardivo, 2024
* Stefano Gualandi, 2013
* Christian Schulte, 2010
*
Expand Down Expand Up @@ -127,13 +129,21 @@ namespace Gecode { namespace Int { namespace BinPacking {
int operator [](int i) const;
};

/// Range of lambda values
struct LambdaRange {
int min;
int max;
};

/**
* \brief Bin-packing propagator
*
* The algorithm is taken from:
* Basic and knapsack propagation are based on:
* Paul Shaw. A Constraint for Bin Packing. CP 2004.
*
* The lower-bound phase uses dual-feasible functions described in:
* Tardivo et al. CP for Bin Packing with Multi-Core and GPUs. CP 2024.
*
* Requires \code #include <gecode/int/bin-packing.hh> \endcode
*
* \ingroup FuncIntProp
Expand All @@ -144,17 +154,21 @@ namespace Gecode { namespace Int { namespace BinPacking {
ViewArray<OffsetView> l;
/// Items with bin and size
ViewArray<Item> bs;
/// Propagation level
IntPropLevel ipl;
/// Total size of all items
int t;
/// Constructor for posting
Pack(Home home, ViewArray<OffsetView>& l, ViewArray<Item>& bs);
Pack(Home home, ViewArray<OffsetView>& l, ViewArray<Item>& bs,
IntPropLevel ipl);
/// Constructor for cloning \a p
Pack(Space& home, Pack& p);
public:
/// Post propagator for loads \a l and items \a bs
GECODE_INT_EXPORT
static ExecStatus post(Home home,
ViewArray<OffsetView>& l, ViewArray<Item>& bs);
ViewArray<OffsetView>& l, ViewArray<Item>& bs,
IntPropLevel ipl=IPL_DEF);
/// Detect non-existence of sums in \a a .. \a b
template<class SizeSet>
bool nosum(const SizeSet& s, int a, int b, int& ap, int& bp);
Expand All @@ -175,6 +189,40 @@ namespace Gecode { namespace Int { namespace BinPacking {
virtual Actor* copy(Space& home);
/// Destructor
virtual size_t dispose(Space& home);
/// Reductions
static int const n_reductions = 3;
static void calc_reductions(const ViewArray<Item>& bs,
const ViewArray<OffsetView>& l,
int* weights_base_reduction,
int& capacity_base_reduction,
int* delta_reductions);
/// Dual Feasible Functions
static int f_ccm1(int w, int l, int c);
static int f_mt(int w, int l, int c);
static int f_bj1(int w, int l, int c);
static int f_vb2_base(int w, int l, int c);
static int f_vb2(int w, int l, int c);
static int f_fs1(int w, int l, int c);
static int f_rad2_base(int w, int l, int c);
static int f_rad2(int w, int l, int c);
static int const n_lambda_samples = 256;
static LambdaRange l_ccm1(int c);
static LambdaRange l_mt(int c);
static LambdaRange l_bj1(int c);
static LambdaRange l_vb2(int c);
static LambdaRange l_fs1(int c);
static LambdaRange l_rad2(int c);
static LambdaRange sanitize_lambda_range(LambdaRange lambda,
int n_weights, int max_weight);
/// Lower bound
template<int f(int,int,int)>
static int calc_dff_lower_bound_single_lambda(const int* weights,
int n_weights,
int capacity, int lambda);
template<int f(int,int,int), LambdaRange l(int)>
static int calc_dff_lower_bound(const int* weights, int n_weights,
int capacity, int n_not_zero_weights,
int max_weight, bool sanitize = false);
};


Expand Down
Loading
Loading