From 4b9596ddf890db7b37223029b71a8c426cd4a785 Mon Sep 17 00:00:00 2001 From: Laurent Perron Date: Mon, 15 Apr 2024 17:17:22 +0200 Subject: [PATCH] improve example --- examples/cpp/binpacking_2d_sat.cc | 37 +++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/examples/cpp/binpacking_2d_sat.cc b/examples/cpp/binpacking_2d_sat.cc index 4a0334bb20..7e96706e8d 100644 --- a/examples/cpp/binpacking_2d_sat.cc +++ b/examples/cpp/binpacking_2d_sat.cc @@ -18,10 +18,13 @@ #include #include +#include #include #include +#include #include +#include "absl/container/btree_map.h" #include "absl/container/btree_set.h" #include "absl/flags/flag.h" #include "absl/log/check.h" @@ -45,7 +48,7 @@ ABSL_FLAG(std::string, params, "", "Sat parameters in text proto format."); ABSL_FLAG(int, max_bins, 0, "Maximum number of bins. The 0 default value implies the code will " "use some heuristics to compute this number."); -ABSL_FLAG(bool, symmetry_breaking, true, "Use symmetry breaking constraints"); +ABSL_FLAG(int, symmetry_breaking_level, 2, "Use symmetry breaking constraints"); ABSL_FLAG(bool, use_global_cumulative, true, "Use a global cumulative relaxation"); @@ -393,6 +396,36 @@ void LoadAndSolve(const std::string& file_name, int instance) { LOG(INFO) << num_items_fixed_on_one_border << " items fixed on one border"; } + if (absl::GetFlag(FLAGS_symmetry_breaking_level) >= 2) { + // Break symmetry of a permutation of identical items + absl::btree_map, std::vector> + item_indexes_for_dimensions; + for (int item = 0; item < num_items; ++item) { + item_indexes_for_dimensions[{problem.items(item).shapes(0).dimensions(0), + problem.items(item).shapes(0).dimensions(1)}] + .push_back(item); + } + int num_identical_items = 0; + for (const auto& [dim, item_indexes] : item_indexes_for_dimensions) { + if (item_indexes.size() == 1) { + continue; + } + ++num_identical_items; + for (int i = 1; i < item_indexes.size(); ++i) { + const IntVar prev_start_x = starts_by_dimension[item_indexes[i - 1]][0]; + const IntVar curr_start_x = starts_by_dimension[item_indexes[i]][0]; + + const IntVar prev_start_y = starts_by_dimension[item_indexes[i - 1]][1]; + const IntVar curr_start_y = starts_by_dimension[item_indexes[i]][1]; + cp_model.AddLessOrEqual(prev_start_x * bin_sizes[1] + prev_start_y, + curr_start_x * bin_sizes[1] + curr_start_y); + } + } + if (num_identical_items > 0) { + LOG(INFO) << num_identical_items << " identical items"; + } + } + // Add non overlapping constraint. for (int b = 0; b < max_bins; ++b) { NoOverlap2DConstraint no_overlap_2d = cp_model.AddNoOverlap2D(); @@ -444,7 +477,7 @@ void LoadAndSolve(const std::string& file_name, int instance) { cp_model.AddImplication(bin_is_used[b], bin_is_used[b - 1]); } - if (absl::GetFlag(FLAGS_symmetry_breaking)) { + if (absl::GetFlag(FLAGS_symmetry_breaking_level) >= 1) { // First sort the items not yet fixed by area. std::vector not_placed_items; for (int item = 0; item < num_items; ++item) {