Skip to content

Commit e9c63b7

Browse files
author
nilsnolde
committed
add optimization endpoint
1 parent 7a9edb3 commit e9c63b7

File tree

11 files changed

+383
-10
lines changed

11 files changed

+383
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
*.geojson
12
*.pyc
23
*.in
34
*egg-info/

CHANGELOG

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
# Unreleased
2+
3+
## 2.1.0
4+
5+
- fix minor problems, apply PEP lint, add some tests
6+
- Add optimization endpoint
7+
18
# 2.0.0
29

310
- implement all backend changes from moving to openrouteservice v5

README.rst

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ It performs requests against our API's for
3434
- `Pelias reverse geocoding`_
3535
- `Pelias structured geocoding`_
3636
- `Pelias autocomplete`_
37+
- Optimization_
3738

3839
For further details, please visit:
3940

@@ -61,6 +62,7 @@ By using this library, you agree to the ORS `terms and conditions`_.
6162
.. _`reverse geocoding`: https://openrouteservice.org/documentation/#/reference/geocoding/geocoding/geocoding-service
6263
.. _`matrix routing calculations`: https://openrouteservice.org/documentation/#/reference/matrix/matrix/matrix-service-(post)
6364
.. _places: https://github.com/GIScience/openpoiservice
65+
.. _Optimization: https://github.com/VROOM-Project/vroom/blob/master/docs/API.md
6466
.. _here: https://github.com/GIScience/openrouteservice-examples/tree/master/python
6567
.. _`terms and conditions`: https://openrouteservice.org/terms-of-service/
6668
.. _forum: https://ask.openrouteservice.org/c/sdks
@@ -146,7 +148,7 @@ To decode to a ``dict``, which is a GeoJSON geometry object, simply do
146148

147149
.. code:: python
148150
149-
import openrouteservice
151+
import openrouteservice
150152
from openrouteservice import convert
151153
152154
coords = ((8.34234,48.23424),(8.34423,48.26424))
@@ -189,9 +191,9 @@ If you're hosting your own ORS instance, you can alter the ``base_url`` paramete
189191
# Only works if you didn't change the ORS endpoints manually
190192
routes = client.directions(coords)
191193
192-
# If you did change the ORS endpoints for some reason
193-
# you'll have to pass url and required parameters explicitly:
194-
routes = client.request(
194+
# If you did change the ORS endpoints for some reason
195+
# you'll have to pass url and required parameters explicitly:
196+
routes = client.request(
195197
url='/new_url',
196198
post_json={
197199
'coordinates': coords,

docs/source/openrouteservice.rst

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ openrouteservice\.client module
99

1010
.. automodule:: openrouteservice.client
1111
:members:
12-
:exclude-members: directions, isochrones, distance_matrix, places, pelias_reverse, pelias_search, pelias_structured, pelias_autocomplete, elevation_line, elevation_point
12+
:exclude-members: directions, isochrones, distance_matrix, places, pelias_reverse, pelias_search, pelias_structured, pelias_autocomplete, elevation_line, elevation_point, optimization
1313
:show-inheritance:
1414

1515
openrouteservice\.convert module
@@ -68,6 +68,14 @@ openrouteservice\.places module
6868
:undoc-members:
6969
:show-inheritance:
7070

71+
openrouteservice\.optimization module
72+
------------------------------------
73+
74+
.. automodule:: openrouteservice.optimization
75+
:members:
76+
:undoc-members:
77+
:show-inheritance:
78+
7179
openrouteservice\.validator module
7280
------------------------------------
7381

openrouteservice/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
# the License.
1818
#
1919

20-
__version__ = "2.0.0"
20+
__version__ = "2.1.0"
2121

2222

2323
# Make sure QGIS plugin can import openrouteservice-py

openrouteservice/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ def _generate_auth_url(path, params):
279279
from openrouteservice.geocode import pelias_structured
280280
from openrouteservice.geocode import pelias_reverse
281281
from openrouteservice.places import places
282+
from openrouteservice.optimization import optimization
282283

283284

284285
def _make_api_method(func):
@@ -315,6 +316,7 @@ def wrapper(*args, **kwargs):
315316
Client.pelias_structured = _make_api_method(pelias_structured)
316317
Client.pelias_reverse = _make_api_method(pelias_reverse)
317318
Client.places = _make_api_method(places)
319+
Client.optimization = _make_api_method(optimization)
318320

319321

320322
def _urlencode_params(params):

openrouteservice/directions.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def directions(client,
5959
directions. One of ["driving-car", "driving-hgv", "foot-walking",
6060
"foot-hiking", "cycling-regular", "cycling-road","cycling-mountain",
6161
"cycling-electric",]. Default "driving-car".
62-
:type mode: string
62+
:type profile: string
6363
6464
:param format: Specifies the response format. One of ['json', 'geojson', 'gpx']. Default "json".
6565
Geometry format for "json" is Google's encodedpolyline. The GPX schema the response is validated

openrouteservice/optimization.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
# -*- coding: utf-8 -*-
2+
# Copyright (C) 2018 HeiGIT, University of Heidelberg.
3+
#
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License"); you may not
6+
# use this file except in compliance with the License. You may obtain a copy of
7+
# the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13+
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14+
# License for the specific language governing permissions and limitations under
15+
# the License.
16+
#
17+
18+
"""Performs requests to the ORS optimization API."""
19+
20+
21+
def optimization(client,
22+
jobs,
23+
vehicles,
24+
matrix=None,
25+
geometry=None,
26+
dry_run=None):
27+
"""Optimize a fleet of vehicles on a number of jobs.
28+
29+
For more information, visit https://github.com/VROOM-Project/vroom/blob/master/docs/API.md.
30+
31+
Example:
32+
33+
>>> from openrouteservice import Client, optimization
34+
>>> coordinates = [[8.688641, 49.420577], [8.680916, 49.415776]]
35+
>>> jobs, vehicles = list(), list()
36+
>>> for idx, coord in enumerate(coordinates):
37+
jobs.append(optimization.Job(id=idx, location=coord))
38+
vehicles.append(optimization.Vehicle(id=idx, location=coord))
39+
>>> api = Client(key='somekey')
40+
>>> result = api.optimization(jobs=jobs, vehicles=vehicles)
41+
42+
:param jobs: The Job objects to fulfill.
43+
:type jobs: list of :class:`openrouteservice.optimization.Job`
44+
45+
:param vehicles: The vehicles to fulfill the :class:`openrouteservice.optimization.Job`'s.
46+
:type vehicles: list of :class:`openrouteservice.optimization.Vehicle`
47+
48+
:param matrix: Specify a custom cost matrix. If not specified, it will be calculated with
49+
the :meth:`openrouteservice.matrix.matrix` endpoint.
50+
:type matrix: list of lists of int
51+
52+
:param geometry: If the geometry of the resulting routes should be calculated. Default True.
53+
:type geometry: bool
54+
55+
:param dry_run: Print URL and parameters without sending the request.
56+
:param dry_run: boolean
57+
58+
:returns: Response of optimization endpoint.
59+
:rtype: dict
60+
"""
61+
62+
assert all([isinstance(x, Job) for x in jobs])
63+
assert all([isinstance(x, Vehicle) for x in vehicles])
64+
65+
params = {"jobs": [job.__dict__ for job in jobs],
66+
"vehicles": [vehicle.__dict__ for vehicle in vehicles]}
67+
68+
if geometry is not None:
69+
params.update({"options": {"g": geometry}})
70+
71+
if matrix:
72+
params['matrix'] = matrix
73+
74+
return client.request("/optimization", {}, post_json=params, dry_run=dry_run)
75+
76+
77+
class Job(object):
78+
"""
79+
Class to create a Job object for optimization endpoint.
80+
81+
Full documentation at https://github.com/VROOM-Project/vroom/blob/master/docs/API.md#jobs.
82+
"""
83+
def __init__(self,
84+
id,
85+
location=None,
86+
location_index=None,
87+
service=None,
88+
amount=None,
89+
skills=None,
90+
time_windows=None
91+
):
92+
"""
93+
Create a job object for the optimization endpoint.
94+
95+
:param id: Integer used as unique identifier.
96+
:type id: int
97+
98+
:param location: Location of the job, as [lon, lat]. Optional if custom matrix is provided.
99+
:type location: tuple of float or list of float
100+
101+
:param location_index: Index of relevant row and column in custom matrix. Mandatory if custom
102+
matrix is provided. Irrelevant when no custom matrix is provided.
103+
:type location_index: int
104+
105+
:param service: Optional job service duration in seconds
106+
:type service: int
107+
108+
:param amount: An array of integers describing multidimensional quantities.
109+
:type amount: list of int or tuple of int
110+
111+
:param skills: An array of integers defining mandatory skills for this job.
112+
:type skills: list of int or tuple of int
113+
114+
:param time_windows: An array of time_window objects describing valid slots for job service start.
115+
:type time_windows: list of lists of int
116+
"""
117+
118+
# if validate:
119+
# validator.validator(locals(), 'job')
120+
121+
self.id = id
122+
123+
if location is not None:
124+
self.location = location
125+
126+
if location_index is not None:
127+
self.location_index = location_index
128+
129+
if service is not None:
130+
self.service = service
131+
132+
if amount is not None:
133+
self.amount = amount
134+
135+
if skills is not None:
136+
self.skills = skills
137+
138+
if time_windows is not None:
139+
self.time_windows = time_windows
140+
141+
142+
class Vehicle(object):
143+
"""
144+
Class to create a Vehicle object for optimization endpoint.
145+
146+
Full documentation at https://github.com/VROOM-Project/vroom/blob/master/docs/API.md#vehicles.
147+
"""
148+
149+
def __init__(self,
150+
id,
151+
profile='driving-car',
152+
start=None,
153+
start_index=None,
154+
end=None,
155+
end_index=None,
156+
capacity=None,
157+
skills=None,
158+
time_window=None):
159+
"""
160+
Create a Vehicle object for the optimization endpoint.
161+
162+
:param id: Integer used as unique identifier.
163+
:param id: int
164+
165+
:param profile: Specifies the mode of transport to use when calculating
166+
directions. One of ["driving-car", "driving-hgv", "foot-walking",
167+
"foot-hiking", "cycling-regular", "cycling-road","cycling-mountain",
168+
"cycling-electric",]. Default "driving-car".
169+
:type profile: str
170+
171+
:param start: Coordinate for the vehicle to start from. If not specified, the start
172+
location will be the first visited job, determined by the optimization engine.
173+
:type start: list of float or tuple of float
174+
175+
:param start_index: Index of relevant row and column in custom matrix. Irrelevant
176+
if no custom matrix is provided.
177+
:type start_index: int
178+
179+
:param end: Coordinate for the vehicle to end at. If not specified, the end
180+
location will be the last visited job, determined by the optimization engine.
181+
:type end: list of float or tuple of float
182+
183+
:param end_index: Index of relevant row and column in custom matrix. Irrelevant
184+
if no custom matrix is provided.
185+
:type end_index: int
186+
187+
:param capacity: An array of integers describing multidimensional quantities.
188+
:type capacity: list of int or tuple of int
189+
190+
:param skills: An array of integers defining skills for this vehicle.
191+
:param skills: list of int or tuple of int
192+
193+
:param time_window: A time_window object describing working hours for this vehicle.
194+
:param time_window: list of int or tuple of int
195+
"""
196+
197+
# if validate:
198+
# validator.validator(locals(), 'vehicle')
199+
200+
self.id = id
201+
self.profile = profile
202+
203+
if start is not None:
204+
self.start = start
205+
206+
if start_index is not None:
207+
self.start_index = start_index
208+
209+
if end is not None:
210+
self.end = end
211+
212+
if end_index is not None:
213+
self.end_index = end_index
214+
215+
if capacity is not None:
216+
self.capacity = capacity
217+
218+
if skills is not None:
219+
self.skills = skills
220+
221+
if time_window is not None:
222+
self.time_window = time_window

setup.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def readme():
2222

2323
setup(
2424
name='openrouteservice',
25-
version='2.0.0',
25+
version='2.1.0',
2626
description='Python client for requests to openrouteservice API services',
2727
long_description=readme(),
2828
classifiers=[
@@ -47,6 +47,8 @@ def readme():
4747
include_package_data=True,
4848
test_suite='nose.collector',
4949
tests_require=['nose>1.0',
50-
'responses>=0.10'],
50+
'requests>=2.0',
51+
'responses>=0.10',
52+
'coveralls>=1.7.0'],
5153
zip_safe=False
5254
)

0 commit comments

Comments
 (0)