Skip to content

Commit

Permalink
Split duration among partitions correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
senhalil committed Feb 2, 2022
1 parent f834126 commit 073f17b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 1 deletion.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

### Fixed

- Split duration among partitions correctly [#336](https://github.com/Mapotempo/optimizer-api/pull/336)
- Fix find_best_heuristic selection logic [#337](https://github.com/Mapotempo/optimizer-api/pull/337)

## [v1.8.2] - 2022-01-19
Expand Down
11 changes: 10 additions & 1 deletion lib/interpreters/split_clustering.rb
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,18 @@ def self.generate_split_vrps(service_vrp, _job = nil, block = nil)
}
current_service_vrps = generated_service_vrps.flatten
else
raise OptimizerWrapper::UnsupportedProblemError, "Unknown partition method #{partition[:technique]}"
raise OptimizerWrapper::UnsupportedProblemError.new("Unknown partition technique #{partition[:technique]}")
end
}

total_size = current_service_vrps.sum{ |s_vrp| s_vrp[:vrp].services.size * [1, s_vrp[:vrp].vehicles.size].min }
current_service_vrps.each{ |s_vrp|
# If one sub vrp has no vehicle or no service, duration can be zero.
# We only split duration among sub_service_vrps that have at least one vehicle and one service.
this_sub_size = s_vrp[:vrp].services.size * [1, s_vrp[:vrp].vehicles.size].min
adjust_independent_duration(s_vrp[:vrp], this_sub_size, total_size)
}

current_service_vrps
end

Expand Down
25 changes: 25 additions & 0 deletions test/lib/interpreters/split_clustering_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -269,6 +269,31 @@ def test_work_day_without_vehicle_entity_small
assert_equal 2, generated_services_vrps.size
end

def test_partitioning_splits_resolution_duration
vrp = VRP.lat_lon_periodic_two_vehicles
vrp[:configuration][:preprocessing][:partitions] = [TestHelper.vehicle_and_days_partitions.first]
vrp[:configuration][:preprocessing][:partitions][0][:restarts] = 1

service_vrp = { vrp: TestHelper.create(vrp), service: :demo }
generated_services_vrps = Interpreters::SplitClustering.generate_split_vrps(service_vrp)
generated_services_vrps.flatten!
generated_services_vrps.compact!

assert_equal vrp[:vehicles].size, generated_services_vrps.size

assert_in_epsilon vrp[:configuration][:resolution][:duration],
generated_services_vrps.sum{ |sv| sv[:vrp].configuration.resolution.duration },
vrp[:vehicles].size # due to rounding we might have overshoot the duration

s_ratio = generated_services_vrps.map{ |sv| sv[:vrp].services.size }.inject{ |ratio, service_count|
ratio / service_count.to_f
}
d_ratio = generated_services_vrps.map{ |sv| sv[:vrp].configuration.resolution.duration }.inject{ |ratio, duration|
ratio / duration.to_f
}
assert_in_epsilon s_ratio, d_ratio, 0.05 # 5% diff can be expected due to rounding in extreme cases
end

def test_work_day_without_vehicle_entity
vrp = VRP.lat_lon_periodic_two_vehicles
vrp[:configuration][:preprocessing][:partitions] = TestHelper.vehicle_and_days_partitions
Expand Down

0 comments on commit 073f17b

Please sign in to comment.