移動時間と配送計画

サプライ・チェインの諸問題に対しては、地点間の移動時間・距離・費用を算出する必要があることがままある。

Google Mapは高い。無料だとOpenStreetMapのOSRMが定番だが、使いにくい。

調べてみたらopentouteserviceなるものを見つけた。大学発らしい。

軽く使ってみた。地図描画はfoliumを使う。両方ともpipで入る。

import openrouteservice as ors
import folium
client = ors.Client(key="上のサイトで得たAPIキーを入れる")

緯度・経度のリストを与えると、距離行列が計算できる。

coordinates = [[13.384116, 52.533558], [13.428726, 52.519355], [13.41774, 52.498929], [13.374825, 52.496369]]
matrix = client.distance_matrix(
   locations=coordinates,
   profile='foot-walking',
   metrics=['distance', 'duration'],
   validate=False,
)
for marker in coordinates:
   folium.Marker(location=list(reversed(marker))).add_to(m)
print("Durations in secs: {}\n".format(matrix['durations']))
print("Distances in m: {}".format(matrix['distances']))

結果はこうなる。

Durations in secs: [[0.0, 2788.6, 3757.12, 3706.33], [2788.6, 0.0, 1996.2, 3974.9], [3757.12, 1996.2, 0.0, 2644.32], [3706.33, 3974.9, 2644.32, 0.0]]
Distances in m: [[0.0, 3873.13, 5218.31, 5147.78], [3873.13, 0.0, 2772.56, 5520.79], [5218.31, 2772.56, 0.0, 3672.74], [5147.78, 5520.79, 3672.74, 0.0]]

問題は速度だ。OSRMは高速な実装をしているはずだが、それを利用していれば速いはずだ。

Docker Imageも準備されている。配送計画やネットワーク設計に使えそうだ。

とおもったら,配送計画ソルバーもついているようだ.単純な時間枠と積込み・積み降ろしも入っているようだ.マニュアルが不備でよくわからないが,試してみてらわかるだろう.

m = folium.Map(location=[52.521861, 13.40744], tiles='cartodbpositron', zoom_start=13)
vehicle_locations = [[13.390446, 52.506087], [13.384116, 52.533558]]
job_locations = [[13.428726, 52.519355],
                [13.41774, 52.498929],
                [13.374825, 52.496369],
                [13.378859, 52.509796],
                [13.400488, 52.509691],
                [13.358517, 52.524264]]
# Assign vehicles to do the jobs
vehicles = []
for idx, coords in enumerate(vehicle_locations):
   vehicles.append(ors.optimization.Vehicle(
       id=idx,
       profile='driving-car',
       start=coords,
       end=coords,
       capacity=[3]  # Limit capacity so only 3 jobs can be taken by each vehicle
   ))
   folium.Marker(location=list(reversed(coords)), icon=folium.Icon(icon='truck', prefix='fa')).add_to(m)
# Define jobs to be carried out
jobs=[]
for idx, coords in enumerate(job_locations):
   jobs.append(ors.optimization.Job(
       id=idx,
       location=coords,
       amount=[1]  # Occupies capacity in vehicle
   ))
   folium.Marker(location=list(reversed(coords)), icon=folium.Icon(icon='archive', prefix='fa', color='green')).add_to(m)
optimized = client.optimization(
   jobs=jobs,
   vehicles=vehicles,
   geometry=True,  ## will output the geometry,
)
folium.PolyLine(
   locations=[list(reversed(coords)) for coords in ors.convert.decode_polyline(optimized['routes'][0]['geometry'])['coordinates']],
   color='red'
).add_to(m)
folium.PolyLine(
   locations=[list(reversed(coords)) for coords in ors.convert.decode_polyline(optimized['routes'][1]['geometry'])['coordinates']],
   color='orange'
).add_to(m)
m

いいなと思ったら応援しよう!