@@ -558,7 +558,7 @@ struct TimePartition {
558558// Selects all intervals in a random time window to meet the difficulty
559559// requirement.
560560TimePartition PartitionIndicesAroundRandomTimeWindow (
561- const std::vector< int >& intervals, const CpModelProto& model_proto,
561+ absl::Span< const int > intervals, const CpModelProto& model_proto,
562562 const CpSolverResponse& initial_solution, double difficulty,
563563 absl::BitGenRef random) {
564564 std::vector<StartEndIndex> start_end_indices;
@@ -1036,15 +1036,10 @@ std::vector<std::vector<int>> NeighborhoodGeneratorHelper::GetRoutingPaths(
10361036
10371037Neighborhood NeighborhoodGeneratorHelper::FixGivenVariables (
10381038 const CpSolverResponse& base_solution,
1039- const absl::flat_hash_set<int >& variables_to_fix) const {
1040- int initial_num_variables = 0 ;
1041- {
1042- absl::ReaderMutexLock domain_lock (&domain_mutex_);
1043-
1044- initial_num_variables =
1045- model_proto_with_only_variables_->variables ().size ();
1046- }
1047- Neighborhood neighborhood (initial_num_variables);
1039+ const Bitset64<int >& variables_to_fix) const {
1040+ const int num_variables = variables_to_fix.size ();
1041+ Neighborhood neighborhood (num_variables);
1042+ neighborhood.delta .mutable_variables ()->Reserve (num_variables);
10481043
10491044 // TODO(user): Maybe relax all variables in the objective when the number
10501045 // is small or negligible compared to the number of variables.
@@ -1054,12 +1049,9 @@ Neighborhood NeighborhoodGeneratorHelper::FixGivenVariables(
10541049 : -1 ;
10551050
10561051 // Fill in neighborhood.delta all variable domains.
1052+ int num_fixed = 0 ;
10571053 {
10581054 absl::ReaderMutexLock domain_lock (&domain_mutex_);
1059-
1060- const int num_variables =
1061- model_proto_with_only_variables_->variables ().size ();
1062- neighborhood.delta .mutable_variables ()->Reserve (num_variables);
10631055 for (int i = 0 ; i < num_variables; ++i) {
10641056 const IntegerVariableProto& current_var =
10651057 model_proto_with_only_variables_->variables (i);
@@ -1068,17 +1060,20 @@ Neighborhood NeighborhoodGeneratorHelper::FixGivenVariables(
10681060 // We only copy the name in debug mode.
10691061 if (DEBUG_MODE) new_var->set_name (current_var.name ());
10701062
1071- const Domain domain = ReadDomainFromProto (current_var);
1072- const int64_t base_value = base_solution. solution (i) ;
1063+ if (variables_to_fix[i] && i != unique_objective_variable) {
1064+ ++num_fixed ;
10731065
1074- if (variables_to_fix.contains (i) && i != unique_objective_variable) {
1075- if (domain.Contains (base_value)) {
1066+ // Note the use of DomainInProtoContains() instead of
1067+ // ReadDomainFromProto() as the later is slower and allocate memory.
1068+ const int64_t base_value = base_solution.solution (i);
1069+ if (DomainInProtoContains (current_var, base_value)) {
10761070 new_var->add_domain (base_value);
10771071 new_var->add_domain (base_value);
10781072 } else {
10791073 // If under the updated domain, the base solution is no longer valid,
10801074 // We should probably regenerate this neighborhood. But for now we
10811075 // just do a best effort and take the closest value.
1076+ const Domain domain = ReadDomainFromProto (current_var);
10821077 int64_t closest_value = domain.Min ();
10831078 int64_t closest_dist = std::abs (closest_value - base_value);
10841079 for (const ClosedInterval interval : domain) {
@@ -1093,7 +1088,7 @@ Neighborhood NeighborhoodGeneratorHelper::FixGivenVariables(
10931088 FillDomainInProto (Domain (closest_value, closest_value), new_var);
10941089 }
10951090 } else {
1096- FillDomainInProto (domain, new_var );
1091+ *new_var-> mutable_domain () = current_var. domain ( );
10971092 }
10981093 }
10991094 }
@@ -1138,10 +1133,15 @@ Neighborhood NeighborhoodGeneratorHelper::FixGivenVariables(
11381133 neighborhood.variables_that_can_be_fixed_to_local_optimum .clear ();
11391134 }
11401135
1136+ const int num_relaxed = num_variables - num_fixed;
1137+ neighborhood.delta .mutable_solution_hint ()->mutable_vars ()->Reserve (
1138+ num_relaxed);
1139+ neighborhood.delta .mutable_solution_hint ()->mutable_values ()->Reserve (
1140+ num_relaxed);
11411141 AddSolutionHinting (base_solution, &neighborhood.delta );
11421142
11431143 neighborhood.is_generated = true ;
1144- neighborhood.is_reduced = !variables_to_fix. empty () ;
1144+ neighborhood.is_reduced = num_fixed > 0 ;
11451145 neighborhood.is_simple = true ;
11461146
11471147 // TODO(user): force better objective? Note that this is already done when the
@@ -1172,25 +1172,26 @@ void NeighborhoodGeneratorHelper::AddSolutionHinting(
11721172Neighborhood NeighborhoodGeneratorHelper::RelaxGivenVariables (
11731173 const CpSolverResponse& initial_solution,
11741174 absl::Span<const int > relaxed_variables) const {
1175- std::vector<bool > relaxed_variables_set (model_proto_.variables_size (), false );
1176- for (const int var : relaxed_variables) relaxed_variables_set[var] = true ;
1177- absl::flat_hash_set<int > fixed_variables;
1175+ Bitset64<int > fixed_variables (NumVariables ());
11781176 {
11791177 absl::ReaderMutexLock graph_lock (&graph_mutex_);
11801178 for (const int i : active_variables_) {
1181- if (!relaxed_variables_set[i]) {
1182- fixed_variables.insert (i);
1183- }
1179+ fixed_variables.Set (i);
11841180 }
11851181 }
1182+ for (const int var : relaxed_variables) fixed_variables.Clear (var);
11861183 return FixGivenVariables (initial_solution, fixed_variables);
11871184}
11881185
11891186Neighborhood NeighborhoodGeneratorHelper::FixAllVariables (
11901187 const CpSolverResponse& initial_solution) const {
1191- const std::vector<int >& all_variables = ActiveVariables ();
1192- const absl::flat_hash_set<int > fixed_variables (all_variables.begin (),
1193- all_variables.end ());
1188+ Bitset64<int > fixed_variables (NumVariables ());
1189+ {
1190+ absl::ReaderMutexLock graph_lock (&graph_mutex_);
1191+ for (const int i : active_variables_) {
1192+ fixed_variables.Set (i);
1193+ }
1194+ }
11941195 return FixGivenVariables (initial_solution, fixed_variables);
11951196}
11961197
@@ -1319,8 +1320,10 @@ Neighborhood RelaxRandomVariablesGenerator::Generate(
13191320 absl::BitGenRef random) {
13201321 std::vector<int > fixed_variables = helper_.ActiveVariables ();
13211322 GetRandomSubset (1.0 - data.difficulty , &fixed_variables, random);
1322- return helper_.FixGivenVariables (
1323- initial_solution, {fixed_variables.begin (), fixed_variables.end ()});
1323+
1324+ Bitset64<int > to_fix (helper_.NumVariables ());
1325+ for (const int var : fixed_variables) to_fix.Set (var);
1326+ return helper_.FixGivenVariables (initial_solution, to_fix);
13241327}
13251328
13261329Neighborhood RelaxRandomConstraintsGenerator::Generate (
@@ -2302,14 +2305,13 @@ Neighborhood RandomRectanglesPackingNeighborhoodGenerator::Generate(
23022305 helper_.GetActiveRectangles (initial_solution);
23032306 GetRandomSubset (1.0 - data.difficulty , &rectangles_to_freeze, random);
23042307
2305- absl::flat_hash_set <int > variables_to_freeze;
2308+ Bitset64 <int > variables_to_freeze (helper_. NumVariables ()) ;
23062309 for (const ActiveRectangle& rectangle : rectangles_to_freeze) {
2307- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2308- variables_to_freeze);
2309- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2310- variables_to_freeze);
2310+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.x_interval ,
2311+ variables_to_freeze);
2312+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.y_interval ,
2313+ variables_to_freeze);
23112314 }
2312-
23132315 return helper_.FixGivenVariables (initial_solution, variables_to_freeze);
23142316}
23152317
@@ -2351,15 +2353,15 @@ Neighborhood RectanglesPackingRelaxOneNeighborhoodGenerator::Generate(
23512353 //
23522354 // Note that we only consider two rectangles as potential neighbors if they
23532355 // are part of the same no_overlap_2d constraint.
2354- absl::flat_hash_set <int > variables_to_freeze;
2356+ Bitset64 <int > variables_to_freeze (helper_. NumVariables ()) ;
23552357 std::vector<std::pair<int , double >> distances;
23562358 distances.reserve (all_active_rectangles.size ());
23572359 for (int i = 0 ; i < all_active_rectangles.size (); ++i) {
23582360 const ActiveRectangle& rectangle = all_active_rectangles[i];
2359- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2360- variables_to_freeze);
2361- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2362- variables_to_freeze);
2361+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.x_interval ,
2362+ variables_to_freeze);
2363+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.y_interval ,
2364+ variables_to_freeze);
23632365
23642366 const Rectangle rect = get_rectangle (rectangle);
23652367 const bool same_no_overlap_as_center_rect = absl::c_any_of (
@@ -2398,14 +2400,10 @@ Neighborhood RectanglesPackingRelaxOneNeighborhoodGenerator::Generate(
23982400
23992401 for (const int b : boxes_to_relax) {
24002402 const ActiveRectangle& rectangle = all_active_rectangles[b];
2401- absl::flat_hash_set<int > variables_to_relax;
2402- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2403- variables_to_relax);
2404- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2405- variables_to_relax);
2406- for (const int v : variables_to_relax) {
2407- variables_to_freeze.erase (v);
2408- }
2403+ RemoveVariablesFromInterval (helper_.ModelProto (), rectangle.x_interval ,
2404+ variables_to_freeze);
2405+ RemoveVariablesFromInterval (helper_.ModelProto (), rectangle.y_interval ,
2406+ variables_to_freeze);
24092407 }
24102408 Neighborhood neighborhood =
24112409 helper_.FixGivenVariables (initial_solution, variables_to_freeze);
@@ -2489,17 +2487,17 @@ Neighborhood RectanglesPackingRelaxTwoNeighborhoodsGenerator::Generate(
24892487 // TODO(user): This computes the distance between the center of the
24902488 // rectangles. We could use the real distance between the closest points, but
24912489 // not sure it is worth the extra complexity.
2492- absl::flat_hash_set <int > variables_to_freeze;
2490+ Bitset64 <int > variables_to_freeze (helper_. NumVariables ()) ;
24932491 std::vector<std::pair<int , double >> distances1;
24942492 std::vector<std::pair<int , double >> distances2;
24952493 distances1.reserve (all_active_rectangles.size ());
24962494 distances2.reserve (all_active_rectangles.size ());
24972495 for (int i = 0 ; i < all_active_rectangles.size (); ++i) {
24982496 const ActiveRectangle& rectangle = all_active_rectangles[i];
2499- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2500- variables_to_freeze);
2501- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2502- variables_to_freeze);
2497+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.x_interval ,
2498+ variables_to_freeze);
2499+ InsertVariablesFromInterval (helper_.ModelProto (), rectangle.y_interval ,
2500+ variables_to_freeze);
25032501
25042502 const Rectangle rect = get_rectangle (rectangle);
25052503 const bool same_no_overlap_as_rect1 =
@@ -2525,22 +2523,18 @@ Neighborhood RectanglesPackingRelaxTwoNeighborhoodsGenerator::Generate(
25252523 [](const auto & a, const auto & b) { return a.second < b.second ; });
25262524 std::sort (distances2.begin (), distances2.end (),
25272525 [](const auto & a, const auto & b) { return a.second < b.second ; });
2528- absl::flat_hash_set<int > variables_to_relax;
25292526 for (auto & samples : {distances1, distances2}) {
25302527 const int num_potential_samples = samples.size ();
25312528 for (int i = 0 ; i < std::min (num_potential_samples, num_to_sample_each);
25322529 ++i) {
25332530 const int rectangle_idx = samples[i].first ;
25342531 const ActiveRectangle& rectangle = all_active_rectangles[rectangle_idx];
2535- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.x_interval ,
2536- variables_to_relax );
2537- InsertVariablesFromConstraint (helper_.ModelProto (), rectangle.y_interval ,
2538- variables_to_relax );
2532+ RemoveVariablesFromInterval (helper_.ModelProto (), rectangle.x_interval ,
2533+ variables_to_freeze );
2534+ RemoveVariablesFromInterval (helper_.ModelProto (), rectangle.y_interval ,
2535+ variables_to_freeze );
25392536 }
25402537 }
2541- for (const int v : variables_to_relax) {
2542- variables_to_freeze.erase (v);
2543- }
25442538
25452539 return helper_.FixGivenVariables (initial_solution, variables_to_freeze);
25462540}
@@ -2583,15 +2577,15 @@ Neighborhood SlicePackingNeighborhoodGenerator::Generate(
25832577 indices_to_fix[index] = false ;
25842578 }
25852579
2586- absl::flat_hash_set <int > variables_to_freeze;
2580+ Bitset64 <int > variables_to_freeze (helper_. NumVariables ()) ;
25872581 for (int index = 0 ; index < active_rectangles.size (); ++index) {
25882582 if (indices_to_fix[index]) {
2589- InsertVariablesFromConstraint (helper_.ModelProto (),
2590- active_rectangles[index].x_interval ,
2591- variables_to_freeze);
2592- InsertVariablesFromConstraint (helper_.ModelProto (),
2593- active_rectangles[index].y_interval ,
2594- variables_to_freeze);
2583+ InsertVariablesFromInterval (helper_.ModelProto (),
2584+ active_rectangles[index].x_interval ,
2585+ variables_to_freeze);
2586+ InsertVariablesFromInterval (helper_.ModelProto (),
2587+ active_rectangles[index].y_interval ,
2588+ variables_to_freeze);
25952589 }
25962590 }
25972591
@@ -2613,8 +2607,10 @@ Neighborhood RoutingRandomNeighborhoodGenerator::Generate(
26132607 all_path_variables.end ());
26142608 std::sort (fixed_variables.begin (), fixed_variables.end ());
26152609 GetRandomSubset (1.0 - data.difficulty , &fixed_variables, random);
2616- return helper_.FixGivenVariables (
2617- initial_solution, {fixed_variables.begin (), fixed_variables.end ()});
2610+
2611+ Bitset64<int > to_fix (helper_.NumVariables ());
2612+ for (const int var : fixed_variables) to_fix.Set (var);
2613+ return helper_.FixGivenVariables (initial_solution, to_fix);
26182614}
26192615
26202616Neighborhood RoutingPathNeighborhoodGenerator::Generate (
@@ -2656,11 +2652,11 @@ Neighborhood RoutingPathNeighborhoodGenerator::Generate(
26562652 }
26572653
26582654 // Compute the set of variables to fix.
2659- absl::flat_hash_set <int > fixed_variables ;
2655+ Bitset64 <int > to_fix (helper_. NumVariables ()) ;
26602656 for (const int var : all_path_variables) {
2661- if (!relaxed_variables.contains (var)) fixed_variables. insert (var);
2657+ if (!relaxed_variables.contains (var)) to_fix. Set (var);
26622658 }
2663- return helper_.FixGivenVariables (initial_solution, fixed_variables );
2659+ return helper_.FixGivenVariables (initial_solution, to_fix );
26642660}
26652661
26662662Neighborhood RoutingFullPathNeighborhoodGenerator::Generate (
@@ -2722,11 +2718,11 @@ Neighborhood RoutingFullPathNeighborhoodGenerator::Generate(
27222718 }
27232719
27242720 // Compute the set of variables to fix.
2725- absl::flat_hash_set <int > fixed_variables ;
2721+ Bitset64 <int > to_fix (helper_. NumVariables ()) ;
27262722 for (const int var : all_path_variables) {
2727- if (!relaxed_variables.contains (var)) fixed_variables. insert (var);
2723+ if (!relaxed_variables.contains (var)) to_fix. Set (var);
27282724 }
2729- return helper_.FixGivenVariables (initial_solution, fixed_variables );
2725+ return helper_.FixGivenVariables (initial_solution, to_fix );
27302726}
27312727
27322728bool RelaxationInducedNeighborhoodGenerator::ReadyToGenerate () const {
0 commit comments