Skip to content

Commit

Permalink
Remove trips field in vehicle model, add original info and transform …
Browse files Browse the repository at this point in the history
…relation types into symbols
  • Loading branch information
fonsecadeline committed Jun 2, 2021
1 parent cc9e534 commit b47c98c
Show file tree
Hide file tree
Showing 67 changed files with 53 additions and 105 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@

### Removed

- Field `trips` in vehicle model. Use `vehicle_trips` relation instead [#123](https://github.com/Mapotempo/optimizer-api/pull/123)

### Fixed

## [v1.7.1] - 2021-05-20
Expand Down
1 change: 0 additions & 1 deletion api/v01/entities/vrp_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,6 @@ module VrpVehicles
optional(:force_start, type: Boolean, documentation: { hidden: true }, desc: '[ DEPRECATED ]')
optional(:shift_preference, type: String, values: ['force_start', 'force_end', 'minimize_span'], desc: 'Force the vehicle to start as soon as the vehicle timewindow is open,
as late as possible or let vehicle start at any time. Not available with periodic heuristic, it will always leave as soon as possible.')
optional(:trips, type: Integer, default: 1, desc: 'The number of times a vehicle is allowed to return to the depot within its route. Not available with periodic heuristic.')

optional :matrix_id, type: String, desc: 'Related matrix, if already defined'
optional :value_matrix_id, type: String, desc: 'If any value matrix defined, related matrix index'
Expand Down
57 changes: 0 additions & 57 deletions lib/interpreters/multi_trips.rb

This file was deleted.

2 changes: 0 additions & 2 deletions models/vehicle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ class Vehicle < Base

field :force_start, default: false
field :shift_preference, default: :minimize_span
field :trips, default: 1
field :duration, default: nil
field :overall_duration, default: nil
field :distance, default: nil
Expand Down Expand Up @@ -92,7 +91,6 @@ class Vehicle < Base
# validates_numericality_of :global_day_index, allow_nil: true
# validates_inclusion_of :router_dimension, in: %w( time distance )
# validates_inclusion_of :shift_preference, in: %w( force_start force_end minimize_span )
# validates_numericality_of :trips, greater_than_or_equal_to: 0
# validates_numericality_of :speed_multiplier
# validates_numericality_of :duration, greater_than_or_equal_to: 0
# validates_numericality_of :overall_duration, greater_than_or_equal_to: 0
Expand Down
3 changes: 0 additions & 3 deletions optimizer_wrapper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@

require './lib/routers/router_wrapper.rb'
require './lib/interpreters/multi_modal.rb'
require './lib/interpreters/multi_trips.rb'
require './lib/interpreters/periodic_visits.rb'
require './lib/interpreters/split_clustering.rb'
require './lib/interpreters/compute_several_solutions.rb'
Expand Down Expand Up @@ -200,8 +199,6 @@ def self.solve(service_vrp, job = nil, block = nil)

tic = Time.now

Interpreters::MultiTrips.new.expand(vrp)

optim_result = nil

unfeasible_services = []
Expand Down
Binary file not shown.
Binary file modified test/fixtures/callage_freq.dump
Binary file not shown.
Binary file modified test/fixtures/cluster_dichotomious.dump
Binary file not shown.
Binary file modified test/fixtures/cluster_one_phase.dump
Binary file not shown.
Binary file modified test/fixtures/cluster_two_phases.dump
Binary file not shown.
Binary file modified test/fixtures/dichotomious_approach.dump
Binary file not shown.
Binary file modified test/fixtures/dichotomious_check_number_of_services.dump
Binary file not shown.
Binary file modified test/fixtures/geometry_polyline.dump
Binary file not shown.
Binary file modified test/fixtures/geometry_polyline_encoded.dump
Binary file not shown.
Binary file modified test/fixtures/geometry_route_single_activity.dump
Binary file not shown.
Binary file modified test/fixtures/geometry_with_rests.dump
Binary file not shown.
Binary file modified test/fixtures/instance_andalucia1_two_vehicles.dump
Binary file not shown.
Binary file modified test/fixtures/instance_andalucia2.dump
Binary file not shown.
Binary file modified test/fixtures/instance_baleares2.dump
Binary file not shown.
Binary file modified test/fixtures/instance_clustered.dump
Binary file not shown.
Binary file modified test/fixtures/instance_order.dump
Binary file not shown.
Binary file modified test/fixtures/instance_same_point_day.dump
Binary file not shown.
Binary file modified test/fixtures/length_centroid.dump
Binary file not shown.
Binary file modified test/fixtures/max_split_functionality.dump
Binary file not shown.
Binary file modified test/fixtures/minimum_duration_lapse_shipments.dump
Binary file not shown.
Binary file modified test/fixtures/no_doubles_3000.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_global_six_routes_without_rest.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_global_ten_routes_without_rest.dump
Binary file not shown.
Binary file not shown.

Large diffs are not rendered by default.

Binary file modified test/fixtures/ortools_multimodal_route.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_multimodal_route2.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_many_stops.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_with_rest.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_with_rest_and_waiting_time.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_with_single_mtws.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_without_rest.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_one_route_without_rest_2.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_open_timewindows.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_optimize_each.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_performance_when_duration_limit.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_single_route_with_route_order.dump
Binary file not shown.
Binary file modified test/fixtures/ortools_single_route_with_route_order_2.dump
Binary file not shown.
Binary file modified test/fixtures/performance_12vl.dump
Binary file not shown.
Binary file modified test/fixtures/performance_13vl.dump
Binary file not shown.
Binary file modified test/fixtures/performance_britanny.dump
Binary file not shown.
Binary file modified test/fixtures/problem_w_pause_that_can_be_simplified.dump
Binary file not shown.
2 changes: 1 addition & 1 deletion test/fixtures/problem_w_pause_that_can_be_simplified.json

Large diffs are not rendered by default.

Binary file modified test/fixtures/pud_initial_routes.dump
Binary file not shown.
Binary file modified test/fixtures/quality_with_minimum_stops_in_route.dump
Binary file not shown.
Binary file modified test/fixtures/results_regularity.dump
Binary file not shown.
Binary file modified test/fixtures/results_regularity_2.dump
Binary file not shown.
Binary file modified test/fixtures/route_initialisation.dump
Binary file not shown.
Binary file modified test/fixtures/same_point_day_relaxation.dump
Binary file not shown.
Binary file modified test/fixtures/scheduling_and_ortools.dump
Binary file not shown.
Binary file modified test/fixtures/scheduling_with_post_process.dump
Binary file not shown.
Binary file modified test/fixtures/treatment_site.dump
Binary file not shown.
Binary file not shown.
Binary file modified test/fixtures/vroom_optimize_each.dump
Binary file not shown.
Binary file modified test/fixtures/vrp_allow_partial_assigment_false.dump
Binary file not shown.
Binary file modified test/fixtures/vrp_ten_routes_with_rest.dump
Binary file not shown.
Binary file modified test/fixtures/without_same_point_day.dump
Binary file not shown.
8 changes: 4 additions & 4 deletions test/lib/interpreters/split_clustering_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -394,15 +394,15 @@ def test_good_vehicle_assignment_skills
metric: 'duration',
entity: :work_day
}]
vrp[:services].first[:skills] = ['skill']
vrp[:vehicles][0][:skills] = [['skill']]
vrp[:services].first[:skills] = [:skill]
vrp[:vehicles][0][:skills] = [[:skill]]
service_vrp = { vrp: TestHelper.create(vrp), service: :demo }
service_vrp[:vrp][:preprocessing_kmeans_centroids] = [1, 2]
generated_services_vrps = Interpreters::SplitClustering.generate_split_vrps(service_vrp)
generated_services_vrps.flatten!
generated_services_vrps.compact!
cluster_with_skill = generated_services_vrps.find{ |sub_vrp| sub_vrp[:vrp][:services].any?{ |s| s[:id] == vrp[:services][0][:id] } }
assert(cluster_with_skill[:vrp].vehicles.any?{ |v| v.skills.any?{ |skill_set| skill_set.include?('skill') } })
cluster_with_skill = generated_services_vrps.find{ |sub_vrp| sub_vrp[:vrp][:services].any?{ |s| s.id == vrp[:services][0][:id] } }
assert(cluster_with_skill[:vrp].vehicles.any?{ |v| v.skills.any?{ |skill_set| skill_set.include?(:skill) } })
end

def test_no_doubles_3000
Expand Down
8 changes: 4 additions & 4 deletions test/models/vrp_consistency_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -461,14 +461,14 @@ def test_compatible_days_availabilities_with_vehicle_trips

vrp[:vehicles][1][:timewindow] = { start: 0, end: 10, day_index: 1 }
# days are uncompatible
assert_raises OptimizerWrapper::DiscordantProblemError do
assert_raises OptimizerWrapper::UnsupportedProblemError do
check_consistency(vrp)
end

vrp[:vehicles][1][:timewindow] = nil
vrp[:vehicles][1][:sequence_timewindows] = [{ start: 0, end: 10, day_index: 0 }, { start: 0, end: 10, day_index: 1 }]
# vehicles have common day index 0 but they are still not available at exact same days
assert_raises OptimizerWrapper::DiscordantProblemError do
assert_raises OptimizerWrapper::UnsupportedProblemError do
check_consistency(vrp)
end
end
Expand All @@ -483,7 +483,7 @@ def test_unavailable_days_with_vehicle_trips
vrp[:vehicles][0][:unavailable_work_day_indices] = [0, 1]
vrp[:vehicles][1][:unavailable_work_day_indices] = [2, 3]
# no common day_index anymore
assert_raises OptimizerWrapper::DiscordantProblemError do
assert_raises OptimizerWrapper::UnsupportedProblemError do
check_consistency(vrp)
end
end
Expand All @@ -502,7 +502,7 @@ def test_vehicle_trips_uncompatible_with_clustering
vrp = VRP.lat_lon_two_vehicles
vrp[:relations] = [TestHelper.vehicle_trips_relation(vrp)]
vrp[:configuration][:preprocessing] = { partitions: TestHelper.vehicle_and_days_partitions }
assert_raises OptimizerWrapper::DiscordantProblemError do
assert_raises OptimizerWrapper::UnsupportedProblemError do
check_consistency(vrp)
end

Expand Down
4 changes: 2 additions & 2 deletions test/real_cases_scheduling_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def test_minimum_stop_in_route
assert result[:routes].all?{ |r| (r[:activities].size - 2).zero? || r[:activities].size - 2 >= 5 },
'Expecting no route with less than 5 stops unless it is an empty route'
assert_operator should_remain_assigned, :<=, (result[:routes].sum{ |r| r[:activities].size - 2 })
assert_equal 19, result[:unassigned].size
assert_equal 21, result[:unassigned].size

all_ids = (result[:routes].flat_map{ |route| route[:activities].collect{ |stop| stop[:service_id] } }.compact +
result[:unassigned].collect{ |un| un[:service_id] }).uniq
Expand All @@ -157,7 +157,7 @@ def test_performance_13vl

# voluntarily equal to watch evolution of scheduling algorithm performance
assert_equal expected, seen, 'Do not have the expected number of total visits'
assert_equal 294, unassigned_visits.sum, 'Do not have the expected number of unassigned visits'
assert_equal 291, unassigned_visits.sum, 'Do not have the expected number of unassigned visits'
end

def test_fill_days_and_post_processing
Expand Down
25 changes: 19 additions & 6 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,21 @@ def self.coerce(vrp)

[vrp[:services], vrp[:shipments]].each{ |group|
group&.each{ |s|
next if s.nil?
next if vrp.is_a?(Hash) && !s.key?(:visits_number)

raise StandardError, "Service/Shipment #{s[:id]} visits_number (#{s[:visits_number]}) is invalid." unless s[:visits_number].is_a?(Integer) && s[:visits_number].positive?
s[:skills]&.map!(&:to_sym)

[s[:activity] || s[:activities] || s[:pickup] || s[:delivery]].flatten.each{ |activity|
next unless activity[:position]

activity[:position] = activity[:position].to_sym
}

next if vrp.is_a?(Hash) && !s.key?(:visits_number)

unless s[:visits_number].is_a?(Integer) && s[:visits_number].positive?
raise StandardError.new(
"Service/Shipment #{s[:id]} visits_number (#{s[:visits_number]}) is invalid."
)
end
}
}

Expand Down Expand Up @@ -106,9 +111,17 @@ def self.coerce(vrp)
vrp[:configuration][:preprocessing][:partitions]&.each{ |partition| partition[:entity] = partition[:entity].to_sym } if vrp[:configuration] && vrp[:configuration][:preprocessing]
vrp.preprocessing_partitions&.each{ |partition| partition[:entity] = partition[:entity].to_sym } if vrp.is_a?(Models::Vrp)

vrp.provide_original_info unless vrp.is_a?(Hash) # TODO: re-dump with this modification
vrp[:relations]&.each{ |r| r[:type] = r[:type]&.to_sym }

vrp[:relations]&.each{ |r| r[:type] = r[:type]&.to_sym } # TODO: re-dump with this modification
vrp[:vehicles]&.each{ |v|
next if v[:skills].to_a.empty?

if v[:skills].first&.is_a?(Array)
v[:skills].each{ |set| set.map!(&:to_sym) }
else
v[:skills].map!(&:to_sym)
end
}

vrp
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,6 @@
require 'date'

class MultiTripsTest < Minitest::Test
def test_expand_vehicles_trips
vrp = VRP.lat_lon
vrp[:vehicles].first[:trips] = 2

vrp = Interpreters::MultiTrips.new.expand(TestHelper.create(vrp))

assert_equal 2, vrp.vehicles.size
assert_equal 1, vrp.relations.size
vrp.relations.each{ |relation|
assert_equal :vehicle_trips, relation.type
assert_includes relation.linked_vehicle_ids, 'vehicle_0_trip_0'
assert_includes relation.linked_vehicle_ids, 'vehicle_0_trip_1'
}

Interpreters::MultiTrips.new.expand(vrp) # consecutive MultiTrips.expand should not produce any error neither inconsistency
assert_equal 2, vrp.vehicles.size
assert_equal 1, vrp.relations.size
end

def test_solve_vehicles_trips_capacity
vrp = VRP.lat_lon_capacitated
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
Expand All @@ -46,15 +27,22 @@ def test_solve_vehicles_trips_capacity

# increasing number of trips increases overall available capacity and reduces unassigned :

vrp[:vehicles].first[:trips] = 2
vrp[:vehicles] << vrp[:vehicles].first.dup
vrp[:vehicles].last[:id] += '_second_trip'
vrp[:relations] = [{
type: 'vehicle_trips',
linked_vehicle_ids: [vrp[:vehicles].first[:id], vrp[:vehicles].last[:id]]
}]
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
assert_equal 2, result[:routes].size
assert_equal 2, result[:unassigned].size
routes_start = result[:routes].collect{ |route| route[:activities].first[:begin_time] }
routes_end = result[:routes].collect{ |route| route[:activities].last[:begin_time] }
assert_operator routes_end[0], :<=, routes_start[1]

vrp[:vehicles].first[:trips] = 3
vrp[:vehicles] << vrp[:vehicles].first.dup
vrp[:vehicles].last[:id] += '_third_trip'
vrp[:relations].first[:linked_vehicle_ids] << vrp[:vehicles].last[:id]
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
assert_equal 3, result[:routes].size
assert_empty result[:unassigned]
Expand All @@ -68,22 +56,30 @@ def test_solve_vehicles_trips_capacity
def test_solve_vehicles_trips_duration
vrp = VRP.basic
vrp[:matrices].first[:time] = vrp[:matrices].first[:time].collect{ |l| l.collect{ |v| v.positive? ? 4 : 0 } }
vrp[:vehicles].first[:duration] = 4
vrp[:vehicles].first[:end_point_id] = vrp[:vehicles].first[:start_point_id]
vrp[:vehicles].first[:duration] = 10
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
assert_equal 1, result[:routes].size
assert_equal 2, result[:unassigned].size

# increasing number of trips increases overall available duration and reduces unassigned :

vrp[:vehicles].first[:trips] = 2
vrp[:vehicles] << vrp[:vehicles].first.dup
vrp[:vehicles].last[:id] += '_second_trip'
vrp[:relations] = [{
type: 'vehicle_trips',
linked_vehicle_ids: [vrp[:vehicles].first[:id], vrp[:vehicles].last[:id]]
}]
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
assert_equal 2, result[:routes].size
assert_equal 1, result[:unassigned].size
routes_start = result[:routes].collect{ |route| route[:activities].first[:begin_time] }
routes_end = result[:routes].collect{ |route| route[:activities].last[:begin_time] }
assert_operator routes_end[0], :<=, routes_start[1]

vrp[:vehicles].first[:trips] = 3
vrp[:vehicles] << vrp[:vehicles].first.dup
vrp[:vehicles].last[:id] += '_third_trip'
vrp[:relations].first[:linked_vehicle_ids] << vrp[:vehicles].last[:id]
result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(vrp), nil)
assert_equal 3, result[:routes].size
assert_empty result[:unassigned]
Expand Down

0 comments on commit b47c98c

Please sign in to comment.