@@ -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