polish examples
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user