polish examples

This commit is contained in:
Laurent Perron
2023-12-03 16:59:16 +01:00
parent 0d01301f26
commit afa29bc06a
3 changed files with 50 additions and 20 deletions

View File

@@ -170,6 +170,22 @@ absl::btree_set<int> FindFixedItems(
return fixed_items;
}
// Solves a subset sum problem to find the maximum reachable max size.
int64_t MaxSubsetSumSize(const std::vector<int64_t>& sizes, int64_t max_size) {
CpModelBuilder builder;
LinearExpr weighed_sum;
for (const int size : sizes) {
BoolVar var = builder.NewBoolVar();
weighed_sum += size * var;
}
builder.AddLessOrEqual(weighed_sum, max_size);
builder.Maximize(weighed_sum);
const CpSolverResponse response = Solve(builder.Build());
return static_cast<int64_t>(response.objective_value());
}
} // namespace
// Load a 2D bin packing problem and solve it.
@@ -184,8 +200,8 @@ void LoadAndSolve(const std::string& file_name, int instance) {
<< file_name << "'";
LOG(INFO) << "Instance has " << problem.items_size() << " items";
const auto bin_sizes = problem.box_shape().dimensions();
const int num_dimensions = bin_sizes.size();
const auto original_bin_sizes = problem.box_shape().dimensions();
const int num_dimensions = original_bin_sizes.size();
const int num_items = problem.items_size();
// Non overlapping.
@@ -195,14 +211,23 @@ void LoadAndSolve(const std::string& file_name, int instance) {
LOG(FATAL) << num_dimensions << " dimensions not supported.";
}
const int64_t area_of_one_bin = bin_sizes[0] * bin_sizes[1];
// Reduce the size of the box with subset-sum.
std::vector<int64_t> x_sizes;
std::vector<int64_t> y_sizes;
int64_t sum_of_items_area = 0;
for (const auto& item : problem.items()) {
CHECK_EQ(1, item.shapes_size());
const auto& shape = item.shapes(0);
CHECK_EQ(2, shape.dimensions_size());
sum_of_items_area += shape.dimensions(0) * shape.dimensions(1);
x_sizes.push_back(shape.dimensions(0));
y_sizes.push_back(shape.dimensions(1));
}
std::vector<int64_t> bin_sizes(2);
bin_sizes[0] = MaxSubsetSumSize(x_sizes, original_bin_sizes[0]);
bin_sizes[1] = MaxSubsetSumSize(y_sizes, original_bin_sizes[1]);
const int64_t area_of_one_bin = bin_sizes[0] * bin_sizes[1];
const int64_t trivial_lb = CeilOfRatio(sum_of_items_area, area_of_one_bin);
LOG(INFO) << "Trivial lower bound of the number of bins = " << trivial_lb;
@@ -270,8 +295,7 @@ void LoadAndSolve(const std::string& file_name, int instance) {
}
// Compute the min size of all items in each dimension.
std::vector<int64_t> min_sizes_per_dimension = {bin_sizes.begin(),
bin_sizes.end()};
std::vector<int64_t> min_sizes_per_dimension = bin_sizes;
for (int item = 0; item < num_items; ++item) {
for (int dim = 0; dim < num_dimensions; ++dim) {
min_sizes_per_dimension[dim] =
@@ -295,14 +319,12 @@ void LoadAndSolve(const std::string& file_name, int instance) {
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.
// Note that the data defines the global size, so the range of the
// interval is [0, bin_size - 1].
// For item fixed to a given bin, by symmetry, we can also assume it
// is in the lower left corner.
const int64_t start_max = fixed_items.contains(item)
? (bin_size - size) / 2
: bin_size - 1 - size;
start = cp_model.NewIntVar({0, start_max});
? (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] > bin_size) {
@@ -351,7 +373,14 @@ void LoadAndSolve(const std::string& file_name, int instance) {
}
// Non overlapping.
LOG(INFO) << "Box size: " << bin_sizes[0] << "*" << bin_sizes[1];
if (bin_sizes[0] == original_bin_sizes[0] &&
bin_sizes[1] == original_bin_sizes[1]) {
LOG(INFO) << "Box size: [" << bin_sizes[0] << " * " << bin_sizes[1] << "]";
} else {
LOG(INFO) << "Box size: [" << bin_sizes[0] << " * " << bin_sizes[1]
<< "] reduced from [" << original_bin_sizes[0] << " * "
<< original_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) {

View File

@@ -31,6 +31,7 @@
#include "absl/flags/flag.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/str_format.h"
#include "absl/types/span.h"
#include "ortools/base/init_google.h"
#include "ortools/base/logging.h"
#include "ortools/base/types.h"
@@ -48,7 +49,7 @@ namespace operations_research {
namespace sat {
// Checks that all pairwise distances are unique and returns all violators
void CheckConstraintViolators(const std::vector<int64_t>& vars,
void CheckConstraintViolators(absl::Span<const int64_t> vars,
std::vector<int>* const violators) {
int dim = vars.size();