Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 31 additions & 11 deletions ortools/routing/routing.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1401,18 +1401,28 @@ void RoutingModel::AddRouteConstraint(
void RoutingModel::FinalizeAllowedVehicles() {
const std::vector<RoutingDimension*> unary_dimensions = GetUnaryDimensions();

// Pre-process the node transit values to find the maximum transit for each
// unary dimension to avoid unnecessary computations below.
std::vector<int64_t> dimension_max_node_transit(unary_dimensions.size(), 0);
for (int i = 0; i < unary_dimensions.size(); ++i) {
int64_t& max_node_transit = dimension_max_node_transit[i];
const RoutingDimension* dimension = unary_dimensions[i];
// Pre-process the node transit values to find, for each unary dimension, the
// maximum positive transit and the most negative transit. These bounds let us
// skip per-node checks when a vehicle's capacity and slack dominate them.
const int num_dimensions = unary_dimensions.size();
std::vector<int64_t> dimension_max_positive_transit(num_dimensions, 0);
std::vector<int64_t> dimension_min_transit(num_dimensions, 0);
std::vector<int64_t> dimension_slack_max(num_dimensions, 0);
for (int i = 0; i < num_dimensions; ++i) {
int64_t& max_positive_transit = dimension_max_positive_transit[i];
int64_t& min_transit = dimension_min_transit[i];
const RoutingDimension* const dimension = unary_dimensions[i];
dimension_slack_max[i] = dimension->SlackVar(0)->Max();
for (int node = 0; node < Size(); ++node) {
if (IsStart(node)) continue;
for (int callback_index : dimension->class_evaluators_) {
max_node_transit = std::max(
max_node_transit,
std::abs(UnaryTransitCallbackOrNull(callback_index)(node)));
const int64_t transit = UnaryTransitCallbackOrNull(callback_index)(node);
if (transit > max_positive_transit) {
max_positive_transit = transit;
}
if (transit < min_transit) {
min_transit = transit;
}
}
}
}
Expand All @@ -1427,7 +1437,13 @@ void RoutingModel::FinalizeAllowedVehicles() {
dim->GetUnaryTransitEvaluator(vehicle);
DCHECK(transit_evaluator != nullptr);
const int64_t capacity = dim->vehicle_capacities()[vehicle];
if (capacity >= dimension_max_node_transit[i]) continue;
const int64_t slack_max = dimension_slack_max[i];
const int64_t min_allowed_transit =
CapSub(0, CapAdd(capacity, slack_max));
if (capacity >= dimension_max_positive_transit[i] &&
dimension_min_transit[i] >= min_allowed_transit) {
continue;
}

for (int node = 0; node < Size(); ++node) {
if (IsStart(node)) continue;
Expand All @@ -1436,7 +1452,11 @@ void RoutingModel::FinalizeAllowedVehicles() {
// The vehicle is already forbidden for this node.
continue;
}
if (std::abs(transit_evaluator(node)) <= capacity) continue;
// Positive transits must fit within the vehicle capacity. Negative
// transits can only decrease the cumul as far as the capacity supplemented
// by the dimension slack allows.
const int64_t transit = transit_evaluator(node);
if (transit <= capacity && transit >= min_allowed_transit) continue;

// 'node' can't be served by 'vehicle', so we remove the 'vehicle'
// from the node's set of allowed_vehicles_.
Expand Down
Loading