Skip to content

Commit

Permalink
tweak c++ examples
Browse files Browse the repository at this point in the history
  • Loading branch information
lperron committed Oct 27, 2023
1 parent 67d4792 commit ba7735e
Showing 1 changed file with 40 additions and 34 deletions.
74 changes: 40 additions & 34 deletions examples/cpp/binpacking_2d_sat.cc
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,10 @@ class GreaterByArea {
: problem_(problem) {}

bool operator()(int a, int b) const {
const auto& a_dims = problem_.items(a).shapes(0).dimensions();
const auto& b_dims = problem_.items(b).shapes(0).dimensions();
const auto& a_sizes = problem_.items(a).shapes(0).dimensions();
const auto& b_sizes = problem_.items(b).shapes(0).dimensions();

return a_dims.Get(0) * a_dims.Get(1) > b_dims.Get(0) * b_dims.Get(1);
return a_sizes.Get(0) * a_sizes.Get(1) > b_sizes.Get(0) * b_sizes.Get(1);
}

private:
Expand All @@ -73,12 +73,12 @@ class GreaterByArea {
bool ItemsAreIncompatible(
const packing::MultipleDimensionsBinPackingProblem& problem, int i1,
int i2) {
const auto& box_dimensions = problem.box_shape().dimensions();
const auto& i1_dims = problem.items(i1).shapes(0).dimensions();
const auto& i2_dims = problem.items(i2).shapes(0).dimensions();
const auto& bin_sizes = problem.box_shape().dimensions();
const auto& i1_sizes = problem.items(i1).shapes(0).dimensions();
const auto& i2_sizes = problem.items(i2).shapes(0).dimensions();

return (i1_dims.Get(0) + i2_dims.Get(0) > box_dimensions[0]) &&
(i1_dims.Get(1) + i2_dims.Get(1) > box_dimensions[1]);
return (i1_sizes.Get(0) + i2_sizes.Get(0) > bin_sizes[0]) &&
(i1_sizes.Get(1) + i2_sizes.Get(1) > bin_sizes[1]);
}

absl::btree_set<int> FindFixedItems(
Expand All @@ -89,11 +89,11 @@ absl::btree_set<int> FindFixedItems(
// See Côté; Haouari; Iori. (2019). A Primal Decomposition Algorithm for the
// Two-dimensional Bin Packing Problem (https://arxiv.org/pdf/1909.06835.pdf).
const int num_items = problem.items_size();
const auto box_dimensions = problem.box_shape().dimensions();
const auto bin_sizes = problem.box_shape().dimensions();

for (int i = 0; i < num_items; ++i) {
if (2 * problem.items(i).shapes(0).dimensions(0) > box_dimensions[0] &&
2 * problem.items(i).shapes(0).dimensions(1) > box_dimensions[1]) {
if (2 * problem.items(i).shapes(0).dimensions(0) > bin_sizes[0] &&
2 * problem.items(i).shapes(0).dimensions(1) > bin_sizes[1]) {
// Big items are pairwise incompatible. Just fix them in different bins.
fixed_items.insert(i);
}
Expand Down Expand Up @@ -184,8 +184,8 @@ void LoadAndSolve(const std::string& file_name, int instance) {
<< file_name << "'";
LOG(INFO) << "Instance has " << problem.items_size() << " items";

const auto box_dimensions = problem.box_shape().dimensions();
const int num_dimensions = box_dimensions.size();
const auto bin_sizes = problem.box_shape().dimensions();
const int num_dimensions = bin_sizes.size();
const int num_items = problem.items_size();

// Non overlapping.
Expand All @@ -195,7 +195,7 @@ void LoadAndSolve(const std::string& file_name, int instance) {
LOG(FATAL) << num_dimensions << " dimensions not supported.";
}

const int64_t area_of_one_bin = box_dimensions[0] * box_dimensions[1];
const int64_t area_of_one_bin = bin_sizes[0] * bin_sizes[1];
int64_t sum_of_items_area = 0;
for (const auto& item : problem.items()) {
CHECK_EQ(1, item.shapes_size());
Expand Down Expand Up @@ -269,9 +269,9 @@ void LoadAndSolve(const std::string& file_name, int instance) {
LOG(INFO) << num_incompatible_pairs << " incompatible pairs of items";
}

// Compute the min size in each dimension.
std::vector<int64_t> min_sizes_per_dimension = {box_dimensions.begin(),
box_dimensions.end()};
// Compute the min size of all items in each dimension.
std::vector<int64_t> min_sizes_per_dimension = {bin_sizes.begin(),
bin_sizes.end()};
for (int item = 0; item < num_items; ++item) {
for (int dim = 0; dim < num_dimensions; ++dim) {
min_sizes_per_dimension[dim] =
Expand All @@ -291,19 +291,19 @@ void LoadAndSolve(const std::string& file_name, int instance) {
for (int b = 0; b < max_bins; ++b) {
interval_by_item_bin_dimension[item][b].resize(num_dimensions);
for (int dim = 0; dim < num_dimensions; ++dim) {
const int64_t dimension = box_dimensions[dim];
const int64_t bin_size = bin_sizes[dim];
const int64_t size = problem.items(item).shapes(0).dimensions(dim);
IntVar start;
if (b == 0) {
// For item fixed to a given bin, by symmetry of rotation we can also
// assume it is in the lower left corner.
const int64_t start_max = fixed_items.contains(item)
? (dimension - size + 1) / 2
: dimension - size;
? (bin_size - size + 1) / 2
: bin_size - size;
start = cp_model.NewIntVar({0, start_max});
starts_by_dimension[item][dim] = start;

if (size + min_sizes_per_dimension[dim] > dimension) {
if (size + min_sizes_per_dimension[dim] > bin_size) {
items_exclusive_in_at_least_one_dimension.insert(item);
}
} else {
Expand All @@ -317,29 +317,35 @@ void LoadAndSolve(const std::string& file_name, int instance) {
}

if (!items_exclusive_in_at_least_one_dimension.empty()) {
int num_boxes_fixed_in_corner = 0;
int num_boxes_fixed_on_one_border = 0;
int num_items_fixed_in_corner = 0;
int num_items_fixed_on_one_border = 0;
for (const int item : items_exclusive_in_at_least_one_dimension) {
for (int dim = 0; dim < num_dimensions; ++dim) {
if (fixed_items.contains(item)) { // Fix to down left corner (0, 0).
cp_model.AddEquality(starts_by_dimension[item][dim], 0);
if (dim == 0) ++num_boxes_fixed_in_corner;
if (fixed_items.contains(item)) {
// Since this item is alone on its bin and effectively divides
// the bin in two we can put it in one corner. For example,
// for a horizontal long item, solutions where the long item
// sits in the middle would mean that there is also a
// solution the long item is in the bottom and the items below
// it were moved above it.
cp_model.FixVariable(starts_by_dimension[item][dim], 0);
if (dim == 0) ++num_items_fixed_in_corner;
} else {
const int64_t dimension = box_dimensions[dim];
const int64_t bin_size = bin_sizes[dim];
const int64_t size = problem.items(item).shapes(0).dimensions(dim);
if (size + min_sizes_per_dimension[dim] > dimension) {
cp_model.AddEquality(starts_by_dimension[item][dim], 0);
++num_boxes_fixed_on_one_border;
if (size + min_sizes_per_dimension[dim] > bin_size) {
cp_model.FixVariable(starts_by_dimension[item][dim], 0);
++num_items_fixed_on_one_border;
}
}
}
}
LOG(INFO) << num_boxes_fixed_in_corner << " boxes fixed in one corner";
LOG(INFO) << num_boxes_fixed_on_one_border << " boxes fixed on one border";
LOG(INFO) << num_items_fixed_in_corner << " items fixed in one corner";
LOG(INFO) << num_items_fixed_on_one_border << " items fixed on one border";
}

// Non overlapping.
LOG(INFO) << "Box size: " << box_dimensions[0] << "*" << box_dimensions[1];
LOG(INFO) << "Box size: " << bin_sizes[0] << "*" << bin_sizes[1];
for (int b = 0; b < max_bins; ++b) {
NoOverlap2DConstraint no_overlap_2d = cp_model.AddNoOverlap2D();
for (int item = 0; item < num_items; ++item) {
Expand All @@ -355,7 +361,7 @@ void LoadAndSolve(const std::string& file_name, int instance) {
if (absl::GetFlag(FLAGS_use_global_cumulative)) {
DCHECK_EQ(num_dimensions, 2);
for (int dim = 0; dim < num_dimensions; ++dim) {
const int other_size = box_dimensions[1 - dim];
const int other_size = bin_sizes[1 - dim];
CumulativeConstraint cumul = cp_model.AddCumulative(obj * other_size);
for (int item = 0; item < num_items; ++item) {
const int size = problem.items(item).shapes(0).dimensions(dim);
Expand Down

0 comments on commit ba7735e

Please sign in to comment.