Skip to content

feat(shifts): add shift time from first job param#12

Merged
hutchinsp01 merged 3 commits into
masterfrom
feat/add-shift-time-from-first-job-param
May 11, 2026
Merged

feat(shifts): add shift time from first job param#12
hutchinsp01 merged 3 commits into
masterfrom
feat/add-shift-time-from-first-job-param

Conversation

@hutchinsp01

@hutchinsp01 hutchinsp01 commented Mar 25, 2026

Copy link
Copy Markdown
Collaborator

Summary

Adds a shift_time_from_first_job: Option flag to VehicleLimits. When true, the shift's start window applies to the first job's arrival instead of
depot departure — so the vehicle can leave early and arrive on-site at shift start, rather than idling at the depot.

The shift end side is unchanged: shift.end.latest still bounds the depot return.

Implementation

  • New FirstJobArrivalFloor core dim; apply_first_job_arrival_floor in schedule update pre-shifts depot departure so the first job is reached at the floor.
  • create_travel_limit_feature takes a new shift_start_latest_fn arg to enforce shift.start.latest against the first-job arrival.
  • Pragmatic fleet reader blanks the depot-start window and sets the floor when the flag is on. Checker uses first-job arrival as effective shift start.
  • Pins toolchain to nightly-2026-02-10.

What this does not do

  • No change to max_duration accounting. Depot-to-first-job travel still counts toward the duration limit; users who want to exclude it can express that
    via shift.start.earliest instead.
  • No relaxation of the shift end. Last-job departure is still bounded by the depot-end window.

Test plan

  • cargo test passes for both vrp-core and vrp-pragmatic.
  • New test shift_time_from_first_job_moves_shift_bounds_onto_first_and_last_jobs.
  • Smoke-test against a real problem with the flag enabled.

@hutchinsp01 hutchinsp01 force-pushed the feat/add-shift-time-from-first-job-param branch from 1934418 to 6057f9e Compare April 29, 2026 05:48

@adamdickinson adamdickinson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's pair through this. And maybe get Evan onto it. You could say my rust is a little... rusty.

@hutchinsp01 hutchinsp01 force-pushed the feat/add-shift-time-from-first-job-param branch from 6057f9e to c71fca4 Compare May 4, 2026 01:50
Comment on lines +78 to +81
let target_departure = floor - travel;
if target_departure > start_departure {
route_ctx.route_mut().tour.get_mut(0).unwrap().schedule.departure = target_departure;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the scheduler change. Given a floor (shift start) and the depot > first-job travel time, set depot departure so arrival lands exactly on the floor.
Runs every time the route's schedule is recomputed.

Comment on lines +128 to 132
let start_time = if allow_out_of_hours_depot_travel {
TimeInterval { earliest: None, latest: None }
} else {
TimeInterval { earliest: Some(shift_start_earliest), latest: shift_start_latest }
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This removes the depots time window if we allow_out_of_hours_travel as the solver no longer enforces the shift window at the depo stop.

The insertions and departure calculation handle this instead now

Comment on lines +131 to +133
if arrival > start_latest {
return ConstraintViolation::skip(self.duration_code);
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This ensures we can't insert jobs that would cause us to start too late

Comment on lines +70 to +74
let effective_start = if allow_out_of_hours_depot_travel && tour.stops.len() > 2 {
parse_time(&tour.stops[1].schedule().arrival)
} else {
parse_time(&start.schedule().departure)
};

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validates the solution after we have solved. Check effective start on either the 1st or 2nd stop depending on if the flag is enabled

@kraklo kraklo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Logic looks sound to me. No heinous crimes or anything blocking. Only sketch thing is the toolchain pin (which is probably a good idea to do anyway) on nightly.

Other musing is do we want a test that still tests the start of shift time is still enforced. i.e. even moving the departure earlier, we still violate the arrival <= start_latest constraint

Comment thread vrp-core/src/construction/enablers/schedule_update.rs Outdated
Comment thread vrp-core/src/construction/enablers/schedule_update.rs Outdated
Comment thread vrp-core/src/construction/features/tour_limits.rs Outdated
Comment thread vrp-pragmatic/src/checker/limits.rs Outdated
Comment thread vrp-pragmatic/src/format/problem/fleet_reader.rs Outdated
Comment thread vrp-pragmatic/src/format/problem/fleet_reader.rs Outdated
Comment thread vrp-pragmatic/tests/features/limits/max_duration.rs Outdated
Comment thread vrp-pragmatic/tests/features/limits/max_duration.rs Outdated
Comment thread rust-toolchain.toml Outdated
hutchinsp01 and others added 2 commits May 7, 2026 14:47
Adds a boolean `allow_out_of_hours_depot_travel` flag on `VehicleLimits`. When
enabled, the shift's start window applies to the first job's arrival
rather than to depot departure, allowing the truck to leave the depot
before the shift starts so it arrives on-site at the shift start. The
end side is unchanged: `shift.end.latest` still bounds depot return.

Pins the rust toolchain to nightly-2026-02-10 for build stability.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hutchinsp01 hutchinsp01 force-pushed the feat/add-shift-time-from-first-job-param branch from c71fca4 to ae3137c Compare May 7, 2026 04:58
@hutchinsp01

hutchinsp01 commented May 7, 2026

Copy link
Copy Markdown
Collaborator Author

has_tour_travel_limits didn't include allow_out_of_hours_depot_travel, so when a vehicle used the flag without also setting max_duration or max_distance, the tour_limit feature wasn't added to the goal context. That meant the new shift.start.latest enforcement in tour_limits.rs:120-133 was silently dead code in that configuration. Now fixed.

New test: allow_out_of_hours_depot_travel_still_enforces_shift_start_latest covers the constraint direction: even with the flag on, a job whose travel time from the depot pushes first-job arrival past start.latest must remain unassigned.

@hutchinsp01 hutchinsp01 requested review from adamdickinson and removed request for adamdickinson May 7, 2026 05:03

@adamdickinson adamdickinson left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I vaguely get it, but I certainly am no rustacean.

As long as everyone is confident of operation, let's go!

@hutchinsp01 hutchinsp01 merged commit 9539e05 into master May 11, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants