From 33c2e7928066dbe1335bcbf982447cd80bc6be77 Mon Sep 17 00:00:00 2001 From: Braktar Date: Fri, 25 Jun 2021 15:58:33 +0200 Subject: [PATCH] [OO] Add maximum initial quantity to ortools --- CHANGELOG.md | 1 + test/wrappers/ortools_test.rb | 23 +++++++++++++++++++++++ wrappers/ortools.rb | 15 +++++++++++++-- wrappers/ortools_vrp_pb.rb | 1 + wrappers/vroom.rb | 1 + wrappers/wrapper.rb | 2 +- 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99800fdde..d8a346aeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - CSV headers adapts to the language provided through HTTP_ACCEPT_LANGUAGE header to facilitate import in Mapotempo-Web [#196](https://github.com/Mapotempo/optimizer-api/pull/196) - Return route day/date and visits' index in result [#196](https://github.com/Mapotempo/optimizer-api/pull/196) +- OR-Tools wrapper can use `initial` capacity value [#245](https://github.com/Mapotempo/optimizer-api/pull/245) ### Changed diff --git a/test/wrappers/ortools_test.rb b/test/wrappers/ortools_test.rb index 127251a38..0bb594e00 100644 --- a/test/wrappers/ortools_test.rb +++ b/test/wrappers/ortools_test.rb @@ -5641,6 +5641,29 @@ def test_quantity_precision } end + def test_initial_quantity + problem = VRP.basic + problem[:services].first[:quantities] = [{ unit_id: 'kg', value: -1 }] + problem[:services].last[:quantities] = [{ unit_id: 'kg', value: -1 }] + problem[:vehicles].each{ |vehicle| + vehicle[:capacities] = [{ unit_id: 'kg', limit: 3, initial: 0 }] + } + + result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(problem), nil) + assert_equal 2, result[:unassigned].size, 'The result is expected to contain 2 unassigned' + + problem = VRP.basic + problem[:services].first[:quantities] = [{ unit_id: 'kg', value: -1 }] + problem[:services].last[:quantities] = [{ unit_id: 'kg', value: 1 }] + problem[:vehicles].each{ |vehicle| + vehicle[:capacities] = [{ unit_id: 'kg', limit: 3, initial: 0 }] + } + + result = OptimizerWrapper.wrapper_vrp('demo', { services: { vrp: [:ortools] }}, TestHelper.create(problem), nil) + assert result[:routes].first[:activities].index{ |act| act[:service_id] == problem[:services].last[:id] } < + result[:routes].first[:activities].index{ |act| act[:service_id] == problem[:services].first[:id] } + end + def test_simplify_vehicle_pause_without_timewindow_or_duration complete_vrp = VRP.pud complete_vrp[:rests] = [{ diff --git a/wrappers/ortools.rb b/wrappers/ortools.rb index 40660a25a..8fc084025 100644 --- a/wrappers/ortools.rb +++ b/wrappers/ortools.rb @@ -36,7 +36,6 @@ def solver_constraints super + [ :assert_end_optimization, :assert_vehicles_objective, - :assert_vehicles_no_capacity_initial, :assert_vehicles_no_alternative_skills, :assert_zones_only_size_one_alternative, :assert_only_empty_or_fill_quantities, @@ -100,6 +99,17 @@ def solve(vrp, job, thread_proc = nil, &block) empty: false } } + sum_quantities = vrp.units.map{ |unit| [unit.id, 0] }.to_h + vrp.services.each{ |service| + service.quantities.each{ |q| + sum_quantities[q.unit.id] += (q.value || 0).abs + } + } + vrp.shipments.each{ |shipment| + shipment.quantities.each{ |q| + sum_quantities[q.unit.id] += (q.value || 0).abs + } + } vrp.services.each{ |service| service.quantities.each{ |quantity| @@ -366,7 +376,8 @@ def solve(vrp, job, thread_proc = nil, &block) OrtoolsVrp::Capacity.new( limit: (q&.limit && q.limit < 1e+22) ? q.limit : -1, overload_multiplier: q&.overload_multiplier || 0, - counting: unit&.counting || false + counting: unit&.counting || false, + initial: q.initial || [sum_quantities[unit.id], q.limit].compact.max ) }, time_window: OrtoolsVrp::TimeWindow.new( diff --git a/wrappers/ortools_vrp_pb.rb b/wrappers/ortools_vrp_pb.rb index 7328a2524..dda1b9387 100644 --- a/wrappers/ortools_vrp_pb.rb +++ b/wrappers/ortools_vrp_pb.rb @@ -40,6 +40,7 @@ optional :limit, :float, 1 optional :overload_multiplier, :float, 2 optional :counting, :bool, 3 + optional :initial, :float, 4 end add_message 'ortools_vrp.Vehicle' do optional :id, :string, 1 diff --git a/wrappers/vroom.rb b/wrappers/vroom.rb index 21833ef53..f439d7496 100644 --- a/wrappers/vroom.rb +++ b/wrappers/vroom.rb @@ -51,6 +51,7 @@ def solver_constraints :assert_matrices_only_one, :assert_no_distance_limitation, :assert_no_service_duration_modifiers, + :assert_vehicles_no_capacity_initial, :assert_vehicles_no_duration_limit, :assert_vehicles_no_force_start, :assert_vehicles_no_late_multiplier_or_single_vehicle, diff --git a/wrappers/wrapper.rb b/wrappers/wrapper.rb index ba1728404..fc39f8c7d 100644 --- a/wrappers/wrapper.rb +++ b/wrappers/wrapper.rb @@ -56,7 +56,7 @@ def assert_vehicles_start_or_end(vrp) def assert_vehicles_no_capacity_initial(vrp) vrp.vehicles.none?{ |vehicle| - vehicle.capacities.find{ |c| c.initial&.positive? } + vehicle.capacities.any?{ |c| c.initial && c.initial < c.limit } } end