improve 2d packing

This commit is contained in:
Laurent Perron
2025-07-16 17:41:33 +02:00
parent d14aa7a85a
commit a42647f9cf
3 changed files with 38 additions and 12 deletions

View File

@@ -20,10 +20,13 @@
#include <variant>
#include <vector>
#include "absl/algorithm/container.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/inlined_vector.h"
#include "absl/log/check.h"
#include "absl/log/log.h"
#include "absl/types/span.h"
#include "ortools/base/stl_util.h"
#include "ortools/sat/cp_model.pb.h"
#include "ortools/sat/integer.h"
#include "ortools/sat/integer_base.h"
@@ -31,6 +34,7 @@
#include "ortools/sat/model.h"
#include "ortools/sat/no_overlap_2d_helper.h"
#include "ortools/sat/precedences.h"
#include "ortools/sat/sat_base.h"
#include "ortools/sat/scheduling_helpers.h"
#include "ortools/sat/synchronization.h"
@@ -44,6 +48,7 @@ Precedences2DPropagator::Precedences2DPropagator(
linear2_watcher_(model->GetOrCreate<Linear2Watcher>()),
shared_stats_(model->GetOrCreate<SharedStatistics>()),
lin2_indices_(model->GetOrCreate<Linear2Indices>()),
trail_(model->GetOrCreate<Trail>()),
integer_trail_(model->GetOrCreate<IntegerTrail>()) {
model->GetOrCreate<LinearPropagator>()->SetPushAffineUbForBinaryRelation();
}
@@ -72,12 +77,25 @@ void Precedences2DPropagator::AddOrUpdateDataForPairOfBoxes(int box1,
if (box1 > box2) std::swap(box1, box2);
const auto [it, inserted] = non_trivial_pairs_index_.insert(
{std::make_pair(box1, box2), static_cast<int>(pair_data_.size())});
absl::InlinedVector<Literal, 4> presence_literals;
for (int dim = 0; dim < 2; ++dim) {
const SchedulingConstraintHelper& dim_helper =
dim == 0 ? helper_.x_helper() : helper_.y_helper();
for (const int box : {box1, box2}) {
if (dim_helper.IsOptional(box)) {
presence_literals.push_back(dim_helper.PresenceLiteral(box));
}
}
}
gtl::STLSortAndRemoveDuplicates(&presence_literals);
if (inserted) {
pair_data_.emplace_back();
pair_data_.emplace_back(
PairData{.pair_presence_literals = {presence_literals.begin(),
presence_literals.end()},
.box1 = box1,
.box2 = box2});
}
PairData& pair_data = pair_data_[it->second];
pair_data.box1 = box1;
pair_data.box2 = box2;
for (int dim = 0; dim < 2; ++dim) {
const SchedulingConstraintHelper& dim_helper =
dim == 0 ? helper_.x_helper() : helper_.y_helper();
@@ -146,8 +164,8 @@ IntegerValue Precedences2DPropagator::UpperBound(
}
bool Precedences2DPropagator::Propagate() {
if (!helper_.SynchronizeAndSetDirection()) return false;
if (last_helper_inprocessing_count_ != helper_.InProcessingCount()) {
if (!helper_.SynchronizeAndSetDirection()) return false;
last_helper_inprocessing_count_ = helper_.InProcessingCount();
UpdateVarLookups();
num_known_linear2_ = 0;
@@ -162,12 +180,10 @@ bool Precedences2DPropagator::Propagate() {
&helper_.y_helper()};
for (const PairData& pair_data : pair_data_) {
const int box1 = pair_data.box1;
const int box2 = pair_data.box2;
DCHECK(box1 < helper_.NumBoxes());
DCHECK(box2 < helper_.NumBoxes());
DCHECK_NE(box1, box2);
if (!helper_.IsPresent(box1) || !helper_.IsPresent(box2)) {
if (!absl::c_all_of(pair_data.pair_presence_literals,
[this](const Literal& literal) {
return trail_->Assignment().LiteralIsTrue(literal);
})) {
continue;
}
@@ -186,7 +202,10 @@ bool Precedences2DPropagator::Propagate() {
if (!is_unfeasible) continue;
// We have a mandatory overlap on both x and y! Explain and propagate.
if (!helper_.SynchronizeAndSetDirection()) return false;
const int box1 = pair_data.box1;
const int box2 = pair_data.box2;
helper_.ClearReason();
num_conflicts_++;

View File

@@ -19,12 +19,14 @@
#include <variant>
#include <vector>
#include "absl/container/fixed_array.h"
#include "absl/container/flat_hash_map.h"
#include "ortools/sat/integer.h"
#include "ortools/sat/integer_base.h"
#include "ortools/sat/model.h"
#include "ortools/sat/no_overlap_2d_helper.h"
#include "ortools/sat/precedences.h"
#include "ortools/sat/sat_base.h"
#include "ortools/sat/synchronization.h"
namespace operations_research {
@@ -61,6 +63,7 @@ class Precedences2DPropagator : public PropagatorInterface {
IntegerValue ub;
};
absl::FixedArray<Literal, 4> pair_presence_literals;
int box1;
int box2;
// start1_before_end2[0==x, 1==y][0=start_1_end_2, 1=start_2_end_1]
@@ -80,6 +83,7 @@ class Precedences2DPropagator : public PropagatorInterface {
Linear2Watcher* linear2_watcher_;
SharedStatistics* shared_stats_;
Linear2Indices* lin2_indices_;
Trail* trail_;
IntegerTrail* integer_trail_;
int last_helper_inprocessing_count_ = -1;

View File

@@ -17,7 +17,7 @@ load("@protobuf//bazel:cc_proto_library.bzl", "cc_proto_library")
load("@protobuf//bazel:java_proto_library.bzl", "java_proto_library")
load("@protobuf//bazel:proto_library.bzl", "proto_library")
load("@protobuf//bazel:py_proto_library.bzl", "py_proto_library")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test", "cc_shared_library")
load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
load("@rules_go//proto:def.bzl", "go_proto_library")
package(default_visibility = ["//visibility:public"])
@@ -126,10 +126,14 @@ cc_library(
":model",
":no_overlap_2d_helper",
":precedences",
":sat_base",
":scheduling_helpers",
":synchronization",
"//ortools/base:stl_util",
"@abseil-cpp//absl/algorithm:container",
"@abseil-cpp//absl/container:fixed_array",
"@abseil-cpp//absl/container:flat_hash_map",
"@abseil-cpp//absl/container:inlined_vector",
"@abseil-cpp//absl/log",
"@abseil-cpp//absl/log:check",
"@abseil-cpp//absl/types:span",
@@ -220,7 +224,6 @@ cc_test(
cc_proto_library(
name = "cp_model_cc_proto",
deps = [":cp_model_proto"],
linkshared = True,
)
py_proto_library(