|
47 | 47 | namespace operations_research { |
48 | 48 | namespace sat { |
49 | 49 |
|
| 50 | +namespace { |
| 51 | + |
50 | 52 | // Helper to compute lower bounds based on binary relations enforced by arc |
51 | 53 | // literals in a RoutesConstraint. |
52 | 54 | class LowerBoundsHelper { |
@@ -171,6 +173,8 @@ class LowerBoundsHelper { |
171 | 173 | lower_bound_by_var_and_arc_index_; |
172 | 174 | }; |
173 | 175 |
|
| 176 | +} // namespace |
| 177 | + |
174 | 178 | MinOutgoingFlowHelper::MinOutgoingFlowHelper( |
175 | 179 | int num_nodes, const std::vector<int>& tails, const std::vector<int>& heads, |
176 | 180 | const std::vector<Literal>& literals, Model* model) |
@@ -310,6 +314,7 @@ class OutgoingCutHelper { |
310 | 314 | // Compute the total demands in order to know the minimum incoming/outgoing |
311 | 315 | // flow. |
312 | 316 | for (const int64_t demand : demands) total_demand_ += demand; |
| 317 | + complement_of_subset_.reserve(num_nodes_); |
313 | 318 | } |
314 | 319 |
|
315 | 320 | // Try to add an outgoing cut from the given subset. |
@@ -356,6 +361,7 @@ class OutgoingCutHelper { |
356 | 361 |
|
357 | 362 | int64_t total_demand_ = 0; |
358 | 363 | std::vector<bool> in_subset_; |
| 364 | + std::vector<int> complement_of_subset_; |
359 | 365 | MinOutgoingFlowHelper min_outgoing_flow_helper_; |
360 | 366 | }; |
361 | 367 |
|
@@ -469,15 +475,23 @@ bool OutgoingCutHelper::TrySubsetCut(std::string name, |
469 | 475 | // Bounds inferred automatically from the enforced binary relation of the |
470 | 476 | // model. |
471 | 477 | // |
472 | | - // TODO(user): use the complement of subset if contain_depot? |
473 | | - // |
474 | 478 | // TODO(user): This is still not as good as the "capacity" bounds below in |
475 | 479 | // some cases. Fix! we should be able to use the same relation to infer the |
476 | 480 | // capacity bounds somehow. |
477 | | - if (subset.size() <= routing_cut_subset_size_for_binary_relation_bound_ && |
478 | | - !contain_depot) { |
479 | | - const int64_t automatic_bound = |
480 | | - min_outgoing_flow_helper_.ComputeMinOutgoingFlow(subset); |
| 481 | + if ((contain_depot ? num_nodes_ - subset.size() : subset.size()) <= |
| 482 | + routing_cut_subset_size_for_binary_relation_bound_) { |
| 483 | + int automatic_bound; |
| 484 | + if (contain_depot) { |
| 485 | + complement_of_subset_.clear(); |
| 486 | + for (int i = 0; i < num_nodes_; ++i) { |
| 487 | + if (!in_subset_[i]) complement_of_subset_.push_back(i); |
| 488 | + } |
| 489 | + automatic_bound = min_outgoing_flow_helper_.ComputeMinOutgoingFlow( |
| 490 | + complement_of_subset_); |
| 491 | + } else { |
| 492 | + automatic_bound = |
| 493 | + min_outgoing_flow_helper_.ComputeMinOutgoingFlow(subset); |
| 494 | + } |
481 | 495 | if (automatic_bound > min_outgoing_flow) { |
482 | 496 | absl::StrAppend(&name, "Automatic"); |
483 | 497 | min_outgoing_flow = automatic_bound; |
|
0 commit comments