Skip to content

Commit 050ee1d

Browse files
committed
Merge branch 'enhancement/break-positioning-heuristic'
2 parents 7163563 + 0befc08 commit 050ee1d

2 files changed

Lines changed: 44 additions & 18 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
- Wrong evaluation in `ReverseTwoOpt` (#1271)
6969
- Misleading error with custom distance matrix (#1281)
7070
- Wrong distance-based optimization with only custom durations (#1298)
71+
- Break positioning heuristic shortcoming (#1251)
7172

7273
#### Internals
7374

src/structures/vroom/tw_route.cpp

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -553,9 +553,8 @@ OrderChoice TWRoute::order_choice(const Input& input,
553553
}
554554

555555
if (check_max_load && j.type == JOB_TYPE::SINGLE &&
556-
(!b.is_valid_for_load(current_load + j.pickup - j.delivery) ||
557-
!(j.pickup <= bwd_smallest_breaks_load_margin[v.break_rank(b.id)]))) {
558-
// Break won't fit right after job for load reason.
556+
!(j.pickup <= bwd_smallest_breaks_load_margin[v.break_rank(b.id)])) {
557+
// Break won't fit after job for load reason.
559558
oc.add_break_first = b.is_valid_for_load(current_load);
560559
return oc;
561560
}
@@ -853,14 +852,27 @@ bool TWRoute::is_valid_addition_for_tw(const Input& input,
853852
? j.services[v_type]
854853
: j.setups[v_type] + j.services[v_type];
855854

856-
auto oc = order_choice(input,
857-
*current_job,
858-
job_action_time,
859-
b,
860-
current,
861-
next,
862-
current_load,
863-
check_max_load);
855+
// Use next info after insertion range for ordering decision,
856+
// except if there are still jobs to insert after j, in which case
857+
// we might have tighter constraints.
858+
auto tighter_next = next;
859+
if (current_job + 1 < last_job) {
860+
const auto& next_j = input.jobs[*(current_job + 1)];
861+
862+
assert(next.travel <= next.latest);
863+
tighter_next.latest =
864+
std::min(next.latest - next.travel, next_j.tws.back().end);
865+
tighter_next.travel = v.duration(j.index(), next_j.index());
866+
}
867+
868+
const auto oc = order_choice(input,
869+
*current_job,
870+
job_action_time,
871+
b,
872+
current,
873+
tighter_next,
874+
current_load,
875+
check_max_load);
864876

865877
if (!oc.add_job_first && !oc.add_break_first) {
866878
// Infeasible insertion.
@@ -1227,13 +1239,26 @@ void TWRoute::replace(const Input& input,
12271239
? j.services[v_type]
12281240
: j.setups[v_type] + j.services[v_type];
12291241

1230-
auto oc = order_choice(input,
1231-
*current_job,
1232-
job_action_time,
1233-
b,
1234-
current,
1235-
next,
1236-
current_load);
1242+
// Use next info after insertion range for ordering decision,
1243+
// except if there are still jobs to insert after j, in which case
1244+
// we might have tighter constraints.
1245+
auto tighter_next = next;
1246+
if (current_job + 1 < last_job) {
1247+
const auto& next_j = input.jobs[*(current_job + 1)];
1248+
1249+
assert(next.travel <= next.latest);
1250+
tighter_next.latest =
1251+
std::min(next.latest - next.travel, next_j.tws.back().end);
1252+
tighter_next.travel = v.duration(j.index(), next_j.index());
1253+
}
1254+
1255+
const auto oc = order_choice(input,
1256+
*current_job,
1257+
job_action_time,
1258+
b,
1259+
current,
1260+
tighter_next,
1261+
current_load);
12371262

12381263
assert(oc.add_job_first xor oc.add_break_first);
12391264
if (oc.add_break_first) {

0 commit comments

Comments
 (0)