Skip to content

Commit

Permalink
Relations are symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
senhalil committed Mar 12, 2021
1 parent 8c6e262 commit a47a094
Show file tree
Hide file tree
Showing 15 changed files with 93 additions and 83 deletions.
2 changes: 1 addition & 1 deletion api/v01/entities/vrp_input.rb
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@ module VrpMisc
end

params :vrp_request_relation do
requires(:type, type: String, allow_blank: false, values: %w[same_route sequence order minimum_day_lapse maximum_day_lapse
requires(:type, type: Symbol, allow_blank: false, values: %i[same_route sequence order minimum_day_lapse maximum_day_lapse
shipment meetup
minimum_duration_lapse maximum_duration_lapse
force_first never_first force_end
Expand Down
6 changes: 3 additions & 3 deletions lib/interpreters/multi_trips.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ def expand(vrp)
relation.linked_vehicle_ids += new_ids
}

vrp.relations += [Models::Relation.new(type: 'vehicle_trips', linked_vehicle_ids: new_ids)]
# vrp.relations += [Models::Relation.new(type: 'vehicle_group_duration', linked_vehicle_ids: new_ids, lapse: vehicle.duration)] if vehicle.duration # TODO: Requires a complete rework of overall_duration
# vrp.relations += [Models::Relation.new(type: 'vehicle_group_duration', linked_vehicle_ids: new_ids, lapse: vehicle.overall_duration)] if vehicle.overall_duration # TODO: Requires a complete rework of overall_duration
vrp.relations += [Models::Relation.new(type: :vehicle_trips, linked_vehicle_ids: new_ids)]
# vrp.relations += [Models::Relation.new(type: :vehicle_group_duration, linked_vehicle_ids: new_ids, lapse: vehicle.duration)] if vehicle.duration # TODO: Requires a complete rework of overall_duration
# vrp.relations += [Models::Relation.new(type: :vehicle_group_duration, linked_vehicle_ids: new_ids, lapse: vehicle.overall_duration)] if vehicle.overall_duration # TODO: Requires a complete rework of overall_duration

vrp.services.select{ |service| service.sticky_vehicles.any?{ |sticky_vehicle| sticky_vehicle.id == vehicle.id } }.each{ |service|
service.sticky_vehicles -= [vehicle.id]
Expand Down
28 changes: 16 additions & 12 deletions lib/interpreters/periodic_visits.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,11 @@ def initialize(vrp)
def expand(vrp, job, &block)
return vrp unless vrp.scheduling?

vehicles_linked_by_duration = save_relations(vrp, 'vehicle_group_duration').concat(save_relations(vrp, 'vehicle_group_duration_on_weeks')).concat(save_relations(vrp, 'vehicle_group_duration_on_months'))
vehicles_linked_by_duration = save_relations(vrp, :vehicle_group_duration).concat(
save_relations(vrp, :vehicle_group_duration_on_weeks)
).concat(
save_relations(vrp, :vehicle_group_duration_on_months)
)
vrp.relations = generate_relations(vrp)
vrp.rests = []
vrp.vehicles = generate_vehicles(vrp).sort{ |a, b|
Expand Down Expand Up @@ -122,27 +126,27 @@ def generate_relations_between_visits(vrp, mission)
if mission.minimum_lapse && mission.maximum_lapse
(2..mission.visits_number).each{ |index|
current_lapse = (index - 1) * mission.minimum_lapse.to_i
vrp.relations << Models::Relation.new(type: 'minimum_day_lapse',
vrp.relations << Models::Relation.new(type: :minimum_day_lapse,
linked_ids: ["#{mission.id}_1_#{mission.visits_number}", "#{mission.id}_#{index}_#{mission.visits_number}"],
lapse: current_lapse)
}
(2..mission.visits_number).each{ |index|
current_lapse = (index - 1) * mission.maximum_lapse.to_i
vrp.relations << Models::Relation.new(type: 'maximum_day_lapse',
vrp.relations << Models::Relation.new(type: :maximum_day_lapse,
linked_ids: ["#{mission.id}_1_#{mission.visits_number}", "#{mission.id}_#{index}_#{mission.visits_number}"],
lapse: current_lapse)
}
elsif mission.minimum_lapse
(2..mission.visits_number).each{ |index|
current_lapse = mission.minimum_lapse.to_i
vrp.relations << Models::Relation.new(type: 'minimum_day_lapse',
vrp.relations << Models::Relation.new(type: :minimum_day_lapse,
linked_ids: ["#{mission.id}_#{index - 1}_#{mission.visits_number}", "#{mission.id}_#{index}_#{mission.visits_number}"],
lapse: current_lapse)
}
elsif mission.maximum_lapse
(2..mission.visits_number).each{ |index|
current_lapse = mission.maximum_lapse.to_i
vrp.relations << Models::Relation.new(type: 'maximum_day_lapse',
vrp.relations << Models::Relation.new(type: :maximum_day_lapse,
linked_ids: ["#{mission.id}_#{index - 1}_#{mission.visits_number}", "#{mission.id}_#{index}_#{mission.visits_number}"],
lapse: current_lapse)
}
Expand Down Expand Up @@ -252,7 +256,7 @@ def generate_vehicles(vrp)

if vehicle.overall_duration
new_relation = Models::Relation.new(
type: 'vehicle_group_duration',
type: :vehicle_group_duration,
linked_vehicle_ids: @equivalent_vehicles[vehicle.original_id],
lapse: vehicle.overall_duration + rests_durations[index]
)
Expand Down Expand Up @@ -333,7 +337,7 @@ def generate_routes(vrp)
residual_time = []
idx = 0
residual_time_for_vehicle = {}
vrp.relations.select{ |r| r.type == 'vehicle_group_duration' }.each{ |r|
vrp.relations.select{ |r| r.type == :vehicle_group_duration }.each{ |r|
r.linked_vehicle_ids.each{ |v|
residual_time_for_vehicle[v] = {
idx: idx,
Expand Down Expand Up @@ -457,7 +461,7 @@ def save_relations(vrp, relation_type)

def get_all_vehicles_in_relation(relations)
relations&.each{ |r|
next if r[:type] == 'vehicle_group_duration'
next if r[:type] == :vehicle_group_duration

new_list = []
r[:linked_vehicle_ids].each{ |v|
Expand All @@ -471,9 +475,9 @@ def generate_relations_on_periodic_vehicles(vrp, list)
new_relations = []
list.each{ |r|
case r[:type]
when 'vehicle_group_duration'
when :vehicle_group_duration
new_relations << [r[:linked_vehicle_ids], r[:lapse]]
when 'vehicle_group_duration_on_weeks'
when :vehicle_group_duration_on_weeks
current_sub_list = []
first_index = r[:linked_vehicle_ids].min.split('_').last.to_i
in_periodicity = first_index + 7 * (r[:periodicity] - 1)
Expand All @@ -491,7 +495,7 @@ def generate_relations_on_periodic_vehicles(vrp, list)
end
}
new_relations << [current_sub_list, r[:lapse]]
when 'vehicle_group_duration_on_months'
when :vehicle_group_duration_on_months
(0..vrp.schedule_months_indices.size - 1).step(r[:periodicity]).collect{ |v| p vrp.schedule_months_indices.slice(v, v + r[:periodicity]).flatten }.each{ |month_indices|
new_relations << [r[:linked_vehicle_ids].select{ |id| month_indices.include?(id.split('_').last.to_i) }, r[:lapse]]
}
Expand All @@ -500,7 +504,7 @@ def generate_relations_on_periodic_vehicles(vrp, list)

new_relations.each{ |linked_vehicle_ids, lapse|
vrp.relations << Models::Relation.new(
type: 'vehicle_group_duration',
type: :vehicle_group_duration,
linked_vehicle_ids: linked_vehicle_ids,
lapse: lapse
)
Expand Down
6 changes: 3 additions & 3 deletions models/concerns/expand_data.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,18 @@ def adapt_relations_between_shipments
services_ids << "#{shipment.id}delivery"
}
self.relations.each{ |relation|
if %w[minimum_duration_lapse maximum_duration_lapse].include?(relation.type)
if %i[minimum_duration_lapse maximum_duration_lapse].include?(relation.type)
relation.linked_ids[0] = "#{relation.linked_ids[0]}delivery" unless services_ids.include?(relation.linked_ids[0])
relation.linked_ids[1] = "#{relation.linked_ids[1]}pickup" unless services_ids.include?(relation.linked_ids[1])

relation.lapse ||= 0
elsif relation.type == 'same_route'
elsif relation.type == :same_route
relation.linked_ids.each_with_index{ |id, id_i|
next if services_ids.include?(id)

relation.linked_ids[id_i] = "#{id}pickup" # which will be in same_route as id_delivery
}
elsif %w[sequence order].include?(relation.type)
elsif %i[sequence order].include?(relation.type)
raise OptimizerWrapper::DiscordantProblemError, 'Relation between shipment pickup and delivery should be explicitly specified for relation.' unless (relation.linked_ids - services_ids).empty?
end
}
Expand Down
5 changes: 5 additions & 0 deletions models/relation.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,10 @@ class Relation < Base
# validates_numericality_of :lapse, allow_nil: true
# validates_numericality_of :periodicity, greater_than_or_equal_to: 1
# validates_inclusion_of :type, :in => %i(same_route sequence order minimum_day_lapse maximum_day_lapse shipment meetup maximum_duration_lapse vehicle_group_duration vehicle_group_duration_on_weeks vehicle_group_duration_on_months vehicle_trips)

def self.create(hash)
hash[:type] = hash[:type]&.to_sym if hash.key?(:type)
super(hash)
end
end
end
12 changes: 6 additions & 6 deletions models/vrp.rb
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,11 @@ def self.check_consistency(hash)
return unless periodic

if hash[:relations]
incompatible_relation_types = hash[:relations].collect{ |r| r[:type] }.uniq - ['force_first', 'never_first', 'force_end']
incompatible_relation_types = hash[:relations].collect{ |r| r[:type] }.uniq - %i[force_first never_first force_end]
raise OptimizerWrapper::DiscordantProblemError, "#{incompatible_relation_types} relations not available with specified first_solution_strategy" unless incompatible_relation_types.empty?
end

raise OptimizerWrapper::DiscordantProblemError, 'Vehicle group duration on weeks or months is not available with schedule_range_date.' if hash[:relations].to_a.any?{ |relation| relation[:type] == 'vehicle_group_duration_on_months' } &&
raise OptimizerWrapper::DiscordantProblemError, 'Vehicle group duration on weeks or months is not available with schedule_range_date.' if hash[:relations].to_a.any?{ |relation| relation[:type] == :vehicle_group_duration_on_months } &&
(!configuration[:schedule] || configuration[:schedule][:range_indice])

raise OptimizerWrapper::DiscordantProblemError, 'Shipments are not available with periodic heuristic.' unless hash[:shipments].to_a.empty?
Expand All @@ -250,23 +250,23 @@ def self.convert_position_relations(hash)
relations_to_remove = []
hash[:relations]&.each_with_index{ |r, r_i|
case r[:type]
when 'force_first'
when :force_first
r[:linked_ids].each{ |id|
to_modify = [hash[:services], hash[:shipments]].flatten.find{ |s| s[:id] == id }
raise OptimizerWrapper::DiscordantProblemError, 'Force first relation with service with activities. Use position field instead.' unless to_modify[:activity]

to_modify[:activity][:position] = :always_first
}
relations_to_remove << r_i
when 'never_first'
when :never_first
r[:linked_ids].each{ |id|
to_modify = [hash[:services], hash[:shipments]].flatten.find{ |s| s[:id] == id }
raise OptimizerWrapper::DiscordantProblemError, 'Never first relation with service with activities. Use position field instead.' unless to_modify[:activity]

to_modify[:activity][:position] = :never_first
}
relations_to_remove << r_i
when 'force_end'
when :force_end
r[:linked_ids].each{ |id|
to_modify = [hash[:services], hash[:shipments]].flatten.find{ |s| s[:id] == id }
raise OptimizerWrapper::DiscordantProblemError, 'Force end relation with service with activities. Use position field instead.' unless to_modify[:activity]
Expand Down Expand Up @@ -376,7 +376,7 @@ def self.remove_unnecessary_relations(hash)
return hash unless hash[:relations]&.any?

types_with_duration =
%w[minimum_day_lapse maximum_day_lapse
%i[minimum_day_lapse maximum_day_lapse
minimum_duration_lapse maximum_duration_lapse
vehicle_group_duration vehicle_group_duration_on_weeks
vehicle_group_duration_on_months vehicle_group_number]
Expand Down
16 changes: 8 additions & 8 deletions test/lib/interpreters/interpreter_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ def test_shipments_and_relation
}],
relations: [{
id: 'id_rel',
type: 'meetup',
type: :meetup,
linked_ids: ['shipment_0delivery', 'shipment_1delivery']
}],
configuration: {
Expand Down Expand Up @@ -1396,7 +1396,7 @@ def test_overall_duration_several_vehicles
problem = VRP.basic
problem[:vehicles] << { id: 'vehicle_1' }
problem[:relations] = [{
type: 'vehicle_group_duration_on_weeks',
type: :vehicle_group_duration_on_weeks,
linked_vehicle_ids: ['vehicle_0', 'vehicle_1'],
lapse: 10,
periodicity: 1
Expand All @@ -1407,12 +1407,12 @@ def test_overall_duration_several_vehicles
expanded_vrp = periodic_expand(problem)
assert_equal 2, expanded_vrp.relations.size

problem[:relations].first[:type] = 'vehicle_group_duration'
problem[:relations].first[:type] = :vehicle_group_duration
expanded_vrp = periodic_expand(vrp)
assert_equal 1, expanded_vrp.relations.size
assert_equal 4, expanded_vrp.relations.first[:linked_vehicle_ids].size

problem[:relations].first[:type] = 'vehicle_group_duration_on_months'
problem[:relations].first[:type] = :vehicle_group_duration_on_months
problem[:configuration][:schedule] = {
range_date: { start: Date.new(2020, 1, 31), end: Date.new(2020, 2, 1) }
}
Expand All @@ -1426,7 +1426,7 @@ def test_overall_duration_with_periodicity
problem = VRP.basic
problem[:vehicles] << { id: 'vehicle_1' }
problem[:relations] = [{
type: 'vehicle_group_duration_on_weeks',
type: :vehicle_group_duration_on_weeks,
linked_vehicle_ids: ['vehicle_0', 'vehicle_1'],
lapse: 10,
periodicity: 2
Expand All @@ -1437,7 +1437,7 @@ def test_overall_duration_with_periodicity
expanded_vrp = periodic_expand(problem)
assert_equal 1, expanded_vrp.relations.size

problem[:relations].first[:type] = 'vehicle_group_duration_on_months'
problem[:relations].first[:type] = :vehicle_group_duration_on_months
problem[:configuration][:schedule] = {
range_date: { start: Date.new(2020, 1, 31), end: Date.new(2020, 2, 1) }
}
Expand All @@ -1450,7 +1450,7 @@ def test_overall_duration_with_periodicity
def test_expand_relations_of_one_week_and_one_day
problem = VRP.basic
problem[:relations] = [{
type: 'vehicle_group_duration_on_weeks',
type: :vehicle_group_duration_on_weeks,
linked_vehicle_ids: ['vehicle_0'],
lapse: 10
}]
Expand All @@ -1474,7 +1474,7 @@ def test_expand_relations_of_one_week_and_one_day
def test_expand_relations_of_one_month_and_one_day
problem = VRP.basic
problem[:relations] = [{
type: 'vehicle_group_duration_on_months',
type: :vehicle_group_duration_on_months,
linked_vehicle_ids: ['vehicle_0'],
lapse: 10
}]
Expand Down
2 changes: 1 addition & 1 deletion test/lib/interpreters/multi_trips_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ def test_expand_vehicles_trips
assert_equal 2, vrp.vehicles.size
assert_equal 1, vrp.relations.size
vrp.relations.each{ |relation|
assert_equal 'vehicle_trips', relation.type
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'
}
Expand Down
11 changes: 5 additions & 6 deletions test/models/vrp_consistency_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def test_reject_if_service_with_activities_in_position_relation
vrp[:services].first.delete(:activity)
vrp[:relations] = [{
id: 'force_first',
type: 'force_first',
type: :force_first,
linked_ids: [vrp[:services].first[:id]]
}]

Expand All @@ -38,18 +38,17 @@ def test_reject_if_service_with_activities_in_position_relation

def test_reject_if_periodic_with_any_relation
vrp = VRP.scheduling
['shipment', 'meetup',
'same_route', 'sequence', 'order',
'minimum_day_lapse', 'maximum_day_lapse', 'minimum_duration_lapse', 'maximum_duration_lapse',
'vehicle_group_duration', 'vehicle_group_duration_on_weeks', 'vehicle_group_duration_on_months'].each{ |relation_type|
%i[shipment meetup same_route sequence order
minimum_day_lapse maximum_day_lapse minimum_duration_lapse maximum_duration_lapse
vehicle_group_duration vehicle_group_duration_on_weeks vehicle_group_duration_on_months].each{ |relation_type|
vrp[:relations] = [{
type: relation_type,
lapse: 1,
linked_ids: ['service_1', 'service_2']
}]

assert_raises OptimizerWrapper::DiscordantProblemError do
TestHelper.create(vrp)
TestHelper.create(vrp)
end
}
end
Expand Down
12 changes: 6 additions & 6 deletions test/models/vrp_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def test_vrp_scheduling
def test_month_indice_generation
problem = VRP.basic
problem[:relations] = [{
type: 'vehicle_group_duration_on_months',
type: :vehicle_group_duration_on_months,
linked_vehicle_ids: ['vehicle_0'],
lapse: 2,
periodicity: 1
Expand Down Expand Up @@ -129,7 +129,7 @@ def test_solver_parameter_retrocompatibility
def test_deduce_consistent_relations
vrp = VRP.pud

['minimum_duration_lapse', 'maximum_duration_lapse'].each{ |relation_type|
%i[minimum_duration_lapse maximum_duration_lapse].each{ |relation_type|
vrp[:relations] = [{
type: relation_type,
linked_ids: ['shipment_0', 'shipment_1'],
Expand All @@ -148,7 +148,7 @@ def test_deduce_consistent_relations
activity: { point_id: 'point_1' }
}]
vrp[:relations] = [{
type: 'minimum_duration_lapse',
type: :minimum_duration_lapse,
linked_ids: ['service', 'shipment_1'],
lapse: 3
}]
Expand All @@ -157,7 +157,7 @@ def test_deduce_consistent_relations
assert_includes generated_vrp.relations.first.linked_ids, 'shipment_1pickup'

vrp[:relations] = [{
type: 'same_route',
type: :same_route,
linked_ids: ['service', 'shipment_0', 'shipment_1'],
lapse: 3
}]
Expand All @@ -166,7 +166,7 @@ def test_deduce_consistent_relations
assert_includes generated_vrp.relations.first.linked_ids, 'shipment_0pickup'
assert_includes generated_vrp.relations.first.linked_ids, 'shipment_1pickup'

%w[sequence order].each{ |relation_type|
%i[sequence order].each{ |relation_type|
vrp[:relations].first[:type] = relation_type
vrp[:relations].first[:linked_ids] = ['service', 'shipment_1']
assert_raises OptimizerWrapper::DiscordantProblemError do
Expand All @@ -175,7 +175,7 @@ def test_deduce_consistent_relations
}

vrp[:relations].first[:linked_ids] = ['service']
%w[sequence order].each{ |relation_type|
%i[sequence order].each{ |relation_type|
vrp[:relations].first[:type] = relation_type
TestHelper.create(vrp) # check no error provided
}
Expand Down
2 changes: 2 additions & 0 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ def self.coerce(vrp)

vrp.provide_original_ids unless vrp.is_a?(Hash) # TODO: re-dump with this modification

vrp[:relations]&.each{ |r| r[:type] = r[:type]&.to_sym } # TODO: re-dump with this modification

vrp
end

Expand Down
4 changes: 2 additions & 2 deletions test/wrapper_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3010,7 +3010,7 @@ def test_assert_applicable_for_vroom_if_initial_routes
def test_assert_inapplicable_relations
problem = VRP.basic
problem[:relations] = [{
type: 'vehicle_group_duration',
type: :vehicle_group_duration,
linked_ids: [],
linked_vehicle_ids: [],
lapse: 1
Expand All @@ -3021,7 +3021,7 @@ def test_assert_inapplicable_relations
refute_includes OptimizerWrapper.config[:services][:ortools].inapplicable_solve?(vrp), :assert_no_relations

problem[:relations] = [{
type: 'vehicle_group_duration',
type: :vehicle_group_duration,
linked_ids: ['vehicle_0'],
linked_vehicle_ids: [],
lapse: 1
Expand Down
Loading

0 comments on commit a47a094

Please sign in to comment.