@@ -825,7 +825,7 @@ struct IndexedRectangle {
825825};
826826
827827void InsertRectanglePredecences (
828- const std::vector< IndexedRectangle>& rectangles,
828+ absl::Span< const IndexedRectangle> rectangles,
829829 absl::flat_hash_set<std::pair<int , int >>* precedences) {
830830 // TODO(user): Refine set of interesting points.
831831 std::vector<IntegerValue> interesting_points;
@@ -1148,7 +1148,7 @@ void NeighborhoodGeneratorHelper::AddSolutionHinting(
11481148
11491149Neighborhood NeighborhoodGeneratorHelper::RelaxGivenVariables (
11501150 const CpSolverResponse& initial_solution,
1151- const std::vector< int >& relaxed_variables) const {
1151+ absl::Span< const int > relaxed_variables) const {
11521152 std::vector<bool > relaxed_variables_set (model_proto_.variables_size (), false );
11531153 for (const int var : relaxed_variables) relaxed_variables_set[var] = true ;
11541154 absl::flat_hash_set<int > fixed_variables;
@@ -1737,8 +1737,8 @@ namespace {
17371737
17381738// Create a constraint sum (X - LB) + sum (UB - X) <= rhs.
17391739ConstraintProto DistanceToBoundsSmallerThanConstraint (
1740- const std::vector< std::pair<int , int64_t >>& dist_to_lower_bound,
1741- const std::vector< std::pair<int , int64_t >>& dist_to_upper_bound,
1740+ absl::Span< const std::pair<int , int64_t >> dist_to_lower_bound,
1741+ absl::Span< const std::pair<int , int64_t >> dist_to_upper_bound,
17421742 const int64_t rhs) {
17431743 DCHECK_GE (rhs, 0 );
17441744 ConstraintProto new_constraint;
@@ -2290,6 +2290,84 @@ Neighborhood RandomRectanglesPackingNeighborhoodGenerator::Generate(
22902290 return helper_.FixGivenVariables (initial_solution, variables_to_freeze);
22912291}
22922292
2293+ Neighborhood RectanglesPackingRelaxOneNeighborhoodGenerator::Generate (
2294+ const CpSolverResponse& initial_solution, SolveData& data,
2295+ absl::BitGenRef random) {
2296+ // First pick one rectangle.
2297+ const std::vector<ActiveRectangle> all_active_rectangles =
2298+ helper_.GetActiveRectangles (initial_solution);
2299+ if (all_active_rectangles.size () <= 1 ) return helper_.FullNeighborhood ();
2300+
2301+ const ActiveRectangle& base_rectangle =
2302+ all_active_rectangles[absl::Uniform<int >(random, 0 ,
2303+ all_active_rectangles.size ())];
2304+
2305+ const auto get_rectangle = [&initial_solution, helper = &helper_](
2306+ const ActiveRectangle& rectangle) {
2307+ const int x_interval_idx = rectangle.x_interval ;
2308+ const int y_interval_idx = rectangle.y_interval ;
2309+ const ConstraintProto& x_interval_ct =
2310+ helper->ModelProto ().constraints (x_interval_idx);
2311+ const ConstraintProto& y_interval_ct =
2312+ helper->ModelProto ().constraints (y_interval_idx);
2313+ return Rectangle{.x_min = GetLinearExpressionValue (
2314+ x_interval_ct.interval ().start (), initial_solution),
2315+ .x_max = GetLinearExpressionValue (
2316+ x_interval_ct.interval ().end (), initial_solution),
2317+ .y_min = GetLinearExpressionValue (
2318+ y_interval_ct.interval ().start (), initial_solution),
2319+ .y_max = GetLinearExpressionValue (
2320+ y_interval_ct.interval ().end (), initial_solution)};
2321+ };
2322+
2323+ const Rectangle center_rect = get_rectangle (base_rectangle);
2324+
2325+ // Now compute a neighborhood around that rectangle. In this neighborhood
2326+ // we prefer a "Square" region around the initial rectangle center rather than
2327+ // a circle.
2328+ //
2329+ // Note that we only consider two rectangles as potential neighbors if they
2330+ // are part of the same no_overlap_2d constraint.
2331+ absl::flat_hash_set<int > variables_to_freeze;
2332+ std::vector<std::pair<int , double >> distances;
2333+ distances.reserve (all_active_rectangles.size ());
2334+ for (int i = 0 ; i < all_active_rectangles.size (); ++i) {
2335+ const ActiveRectangle& rectangle = all_active_rectangles[i];
2336+ InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2337+ variables_to_freeze);
2338+ InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2339+ variables_to_freeze);
2340+
2341+ const Rectangle rect = get_rectangle (rectangle);
2342+ const bool same_no_overlap_as_center_rect = absl::c_any_of (
2343+ base_rectangle.no_overlap_2d_constraints , [&rectangle](const int c) {
2344+ return rectangle.no_overlap_2d_constraints .contains (c);
2345+ });
2346+ if (same_no_overlap_as_center_rect) {
2347+ distances.push_back (
2348+ {i, CenterToCenterLInfinityDistance (center_rect, rect)});
2349+ }
2350+ }
2351+ std::sort (distances.begin (), distances.end (),
2352+ [](const auto & a, const auto & b) { return a.second < b.second ; });
2353+
2354+ const int num_to_sample = data.difficulty * all_active_rectangles.size ();
2355+ absl::flat_hash_set<int > variables_to_relax;
2356+ const int num_to_relax = std::min<int >(distances.size (), num_to_sample);
2357+ for (int i = 0 ; i < num_to_relax; ++i) {
2358+ const int rectangle_idx = distances[i].first ;
2359+ const ActiveRectangle& rectangle = all_active_rectangles[rectangle_idx];
2360+ InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2361+ variables_to_relax);
2362+ InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2363+ variables_to_relax);
2364+ }
2365+ for (const int v : variables_to_relax) {
2366+ variables_to_freeze.erase (v);
2367+ }
2368+ return helper_.FixGivenVariables (initial_solution, variables_to_freeze);
2369+ }
2370+
22932371Neighborhood RectanglesPackingRelaxTwoNeighborhoodsGenerator::Generate (
22942372 const CpSolverResponse& initial_solution, SolveData& data,
22952373 absl::BitGenRef random) {
@@ -2327,22 +2405,16 @@ Neighborhood RectanglesPackingRelaxTwoNeighborhoodsGenerator::Generate(
23272405 y_interval_ct.interval ().end (), initial_solution)};
23282406 };
23292407
2330- // TODO(user): This computes the distance between the center of the
2331- // rectangles. We could use the real distance between the closest points, but
2332- // not sure it is worth the extra complexity.
2333- const auto compute_rectangle_distance = [](const Rectangle& rect1,
2334- const Rectangle& rect2) {
2335- return (static_cast <double >(rect1.x_min .value ()) + rect1.x_max .value () -
2336- rect2.x_min .value () - rect2.x_max .value ()) *
2337- (static_cast <double >(rect1.y_min .value ()) + rect1.y_max .value () -
2338- rect2.y_min .value () - rect2.y_max .value ());
2339- };
23402408 const Rectangle rect1 = get_rectangle (chosen_rectangle_1);
23412409 const Rectangle rect2 = get_rectangle (chosen_rectangle_2);
23422410
23432411 // Now compute a neighborhood around each rectangle. Note that we only
23442412 // consider two rectangles as potential neighbors if they are part of the same
23452413 // no_overlap_2d constraint.
2414+ //
2415+ // TODO(user): This computes the distance between the center of the
2416+ // rectangles. We could use the real distance between the closest points, but
2417+ // not sure it is worth the extra complexity.
23462418 absl::flat_hash_set<int > variables_to_freeze;
23472419 std::vector<std::pair<int , double >> distances1;
23482420 std::vector<std::pair<int , double >> distances2;
@@ -2367,10 +2439,10 @@ Neighborhood RectanglesPackingRelaxTwoNeighborhoodsGenerator::Generate(
23672439 return rectangle.no_overlap_2d_constraints .contains (c);
23682440 });
23692441 if (same_no_overlap_as_rect1) {
2370- distances1.push_back ({i, compute_rectangle_distance (rect1, rect)});
2442+ distances1.push_back ({i, CenterToCenterL2Distance (rect1, rect)});
23712443 }
23722444 if (same_no_overlap_as_rect2) {
2373- distances2.push_back ({i, compute_rectangle_distance (rect2, rect)});
2445+ distances2.push_back ({i, CenterToCenterL2Distance (rect2, rect)});
23742446 }
23752447 }
23762448 const int num_to_sample_each =
0 commit comments