Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test against ignored TWs & bump optimizer-ortools #262

Merged
merged 5 commits into from
Aug 10, 2021
Merged
Show file tree
Hide file tree
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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

- VROOM was used incorrectly in various cases: negative quantities, vehicle duration, activity position [#223](https://github.com/Mapotempo/optimizer-api/pull/223) [#242](https://github.com/Mapotempo/optimizer-api/pull/242)
- Capacity violation in periodic heuristic algorithm (`first_solution_strategy='periodic'`) [#227](https://github.com/Mapotempo/optimizer-api/pull/227)
- Service timewindows without an `end` were not respected [#262](https://github.com/Mapotempo/optimizer-api/pull/262)

## [v1.7.1] - 2021-05-20

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ bundle install

This project requires some solver and interface projects in order to be fully functionnal!
* [Vroom v1.8.0](https://github.com/VROOM-Project/vroom/releases/tag/v1.8.0)
* [Optimizer-ortools v1.5.0](https://github.com/Mapotempo/optimizer-ortools) & [OR-Tools v7.8](https://github.com/google/or-tools/releases/tag/v7.8) (use the version corresponding to your system operator, not source code).
* [Optimizer-ortools v1.6.0](https://github.com/Mapotempo/optimizer-ortools) & [OR-Tools v7.8](https://github.com/google/or-tools/releases/tag/v7.8) (use the version corresponding to your system operator, not source code).

Note : when updating OR-Tools you should to recompile optimizer-ortools.

Expand Down
2 changes: 1 addition & 1 deletion docker/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ ARG BUNDLE_WITHOUT="development test"
FROM vroomvrp/vroom-docker:${VROOM_VERSION:-v1.8.0} as vroom

# Rake
FROM ${REGISTRY}mapotempo-${BRANCH}/optimizer-ortools:${OPTIMIZER_ORTOOLS_VERSION:-v1.5.0}
FROM ${REGISTRY}mapotempo-${BRANCH}/optimizer-ortools:${OPTIMIZER_ORTOOLS_VERSION:-v1.6.0}
ARG BUNDLE_WITHOUT

ENV LANG C.UTF-8
Expand Down
48 changes: 45 additions & 3 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,15 @@ def self.coerce(vrp)
v[:skills].each{ |set| set.map!(&:to_sym) }
}

# trips parameter does not exist anymore
vrp[:vehicles]&.each{ |v|
next unless v[:trips]

raise 'vehicle[:trips] parameter does not exist' if v[:trips] > 1

v.delete(:trips)
}

vrp
end

Expand Down Expand Up @@ -255,6 +264,9 @@ def self.toy
configuration: {
resolution: {
duration: 100
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -310,7 +322,10 @@ def self.basic
resolution: {
duration: 100
},
preprocessing: {}
preprocessing: {},
restitution: {
intermediate_solutions: false,
}
}
}
end
Expand Down Expand Up @@ -489,7 +504,10 @@ def self.lat_lon
resolution: {
duration: 2000
},
preprocessing: {}
preprocessing: {},
restitution: {
intermediate_solutions: false,
}
}
}
end
Expand Down Expand Up @@ -607,7 +625,10 @@ def self.lat_lon_pud
resolution: {
duration: 2000
},
preprocessing: {}
preprocessing: {},
restitution: {
intermediate_solutions: false,
}
}
}
end
Expand Down Expand Up @@ -674,6 +695,9 @@ def self.periodic
start: 0,
end: 3
}
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -809,6 +833,9 @@ def self.lat_lon_capacitated
configuration: {
resolution: {
duration: 100
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -844,6 +871,9 @@ def self.lat_lon_periodic
start: 0,
end: 3
}
},
restitution: {
intermediate_solutions: false,
}
}

Expand Down Expand Up @@ -1043,6 +1073,9 @@ def self.lat_lon_two_vehicles
configuration: {
resolution: {
duration: 100
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -1175,6 +1208,9 @@ def self.periodic_seq_timewindows
start: 0,
end: 10
}
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -1285,6 +1321,9 @@ def self.independent
configuration: {
resolution: {
duration: 100
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down Expand Up @@ -1382,6 +1421,9 @@ def self.independent_skills
configuration: {
resolution: {
duration: 100
},
restitution: {
intermediate_solutions: false,
}
}
}
Expand Down
32 changes: 32 additions & 0 deletions test/wrappers/ortools_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5272,4 +5272,36 @@ def test_simplify_vehicle_pause_without_timewindow_or_duration
assert(result[:routes].first[:activities].any?{ |stop| stop[:type] == 'rest' })
assert_empty result[:unassigned]
end

def test_respect_timewindows_without_end
# first two services are forced to be performed at 5 and 10 due to travel time and their TW
# this pushes the third service out of its first TW (i.e., {start:5, end:10}) and
# forces it to be processed after 20 because of its second TW (i.e., {start:20})
# even though the vehicle arrives there at 15.
problem = VRP.basic
problem[:matrices][0][:time] = [
[0, 5, 5, 5],
[5, 0, 5, 5],
[5, 5, 0, 5],
[5, 5, 5, 0]
]
problem[:services].each{ |s|
s[:activity][:timewindows] = [{ start: 5, end: 10 }]
}
problem[:services].last[:activity][:timewindows] << { start: 20 }

vrp = TestHelper.create(problem)
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, vrp, nil)

assert_empty result[:unassigned], 'All three services should be planned. There is an obvious feasible solution.'

vrp.services.each{ |service|
planned_begin_time = result[:routes][0][:activities].find{ |a| a[:service_id] == service.id }[:begin_time]
assert service.activity.timewindows.one?{ |tw|
planned_begin_time >= tw.start && (tw.end.nil? || planned_begin_time <= tw.end)
}, 'Services should respect the TW without end and fall within exactly one of its TW ranges'
}

assert_equal 20, result[:routes][0][:activities].last[:begin_time], 'Third service should be planned at 20'
end
end