Skip to content

Commit

Permalink
Merge pull request #145 from senhalil/feat/support_pud_in_split
Browse files Browse the repository at this point in the history
Support relations in split & partitions
  • Loading branch information
fab-girard authored Apr 6, 2021
2 parents 75f96e8 + 0131ee1 commit c20b5c1
Show file tree
Hide file tree
Showing 23 changed files with 379 additions and 200 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- Corresponding vehicle_id is returned within each service's skills if problem is partitioned with vehicle entity [#110](https://github.com/Mapotempo/optimizer-api/pull/110)
- Support initial routes and skills in split_solve (`max_split_size`) algorithm [#140](https://github.com/Mapotempo/optimizer-api/pull/140)
- Support relations (`order`, `same_route`, `sequence`, `shipment`) in split_solve algorithm (`max_split_size`) and partitions (`[:configuration][:preprocessing][:partitions]`) [PR145](https://github.com/Mapotempo/optimizer-api/pull/145)
- split_solve algorithm (`max_split_size`) respects relations (`vehicle_trips`, `meetup`, `minimum_duration_lapse`, `maximum_duration_lapse`, `minimum_day_lapse`, `maximum_day_lapse`) [PR145](https://github.com/Mapotempo/optimizer-api/pull/145)

### Changed

Expand Down
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ gem 'resque-status', '>0.4'
gem 'rest-client'

gem 'ai4r'
gem 'balanced_vrp_clustering', github: 'Mapotempo/balanced_vrp_clustering', branch: 'dev'
gem 'balanced_vrp_clustering', github: 'senhalil/balanced_vrp_clustering', branch: 'dev' # Replace senhalil with Mapotempo when the following PR is merged https://github.com/Mapotempo/balanced_vrp_clustering/pull/16
gem 'sim_annealing'

gem 'polylines'
Expand Down
8 changes: 4 additions & 4 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ GIT
activesupport (>= 5.0.0)

GIT
remote: https://github.com/Mapotempo/balanced_vrp_clustering.git
revision: f05b84f49cfc8803ef0adc2bdc12627720d82796
remote: https://github.com/senhalil/balanced_vrp_clustering.git
revision: 657b71af8721cbbae44c5bba36790fb1c1d6842f
branch: dev
specs:
balanced_vrp_clustering (0.1.7)
balanced_vrp_clustering (0.2.0)
awesome_print
color-generator
geojson2image
Expand Down Expand Up @@ -52,7 +52,7 @@ GEM
anyway_config (2.0.6)
ruby-next-core (>= 0.8.0)
ast (2.4.1)
awesome_print (1.8.0)
awesome_print (1.9.2)
backport (1.1.2)
benchmark (0.1.0)
benchmark-ips (2.8.3)
Expand Down
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
2 changes: 1 addition & 1 deletion lib/heuristics/dichotomious_approach.rb
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,7 @@ def self.kmeans(vrp, cut_symbol)

options[:clusters_infos] = SplitClustering.collect_cluster_data(vrp, nb_clusters)

clusters = SplitClustering.kmeans_process(nb_clusters, data_items, unit_symbols, limits, options)
clusters = SplitClustering.kmeans_process(nb_clusters, data_items, {}, limits, options)

services_by_cluster = clusters.collect{ |cluster|
cluster.data_items.flat_map{ |data|
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 @@ -130,27 +134,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 @@ -260,7 +264,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 @@ -341,7 +345,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 @@ -465,7 +469,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 @@ -479,9 +483,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 @@ -499,7 +503,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 @@ -508,7 +512,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
Loading

0 comments on commit c20b5c1

Please sign in to comment.