Skip to content

Commit 62b4788

Browse files
committed
google support, local osrm, numba
1 parent 0458a87 commit 62b4788

16 files changed

Lines changed: 807 additions & 55 deletions

File tree

.github/workflows/python-publish.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,9 @@
22
name: Publish to PyPI
33

44
on:
5-
release:
6-
types: [published]
5+
push:
6+
tags:
7+
- 'v*'
78
workflow_dispatch:
89
inputs:
910
use_test_pypi:
@@ -47,6 +48,8 @@ jobs:
4748

4849
steps:
4950
- uses: actions/checkout@v4
51+
with:
52+
fetch-depth: 0
5053

5154
- name: Install uv
5255
uses: astral-sh/setup-uv@v7

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ Thumbs.db
148148

149149
# Project specific
150150
/allocator/kahip/
151+
allocator/_version.py
151152
*.csv
152153
*.png
153154
*.svg
@@ -159,4 +160,4 @@ Thumbs.db
159160
*-output.csv
160161
*-output.png
161162
*-output.html
162-
*-output.json
163+
*-output.jsonscripts/osrm/data/

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22

33
All notable changes to the allocator project are documented in this file.
44

5+
## [1.3.0] - 2025-04-22
6+
7+
### Added
8+
9+
**Google Routes API Support:**
10+
- New `google_routes_distance_matrix()` function using official `google-maps-routing` library
11+
- Service account authentication with proper rate limiting handled by Google's client
12+
- Support for multiple travel modes: DRIVE, BICYCLE, WALK, TWO_WHEELER, TRANSIT
13+
- Returns duration (seconds) or distance (meters)
14+
15+
**Progress Reporting:**
16+
- Added `on_progress` callback to all distance matrix functions
17+
- Callback signature: `(current: int, total: int, message: str | None) -> None`
18+
- Useful for progress bars in long-running API requests
19+
20+
**Local OSRM Server:**
21+
- Added `scripts/osrm/` with Docker setup for running local OSRM
22+
- `setup.sh` script to download and preprocess OSM data for any region
23+
- `docker-compose.yml` for easy server management
24+
25+
### Changed
26+
27+
- Legacy `method="google"` now emits `DeprecationWarning` recommending `google_routes`
28+
- Added `google-maps-routing>=0.6.0` to dependencies
29+
30+
### Dependencies
31+
32+
- Added: `google-maps-routing>=0.6.0` (official Google Routes API client)
33+
34+
---
35+
536
## [1.2.0] - 2025-04-12
637

738
### Changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ Field teams, delivery services, and survey organizations waste time and money on
1313
- **Route**: Find the shortest path through locations (TSP)
1414
- **Assign**: Match locations to nearest workers or depots
1515
- **Random Walk**: Generate survey itineraries on road networks
16+
- **Distance Matrix**: Calculate travel times/distances via OSRM or Google Routes API
1617

1718
## Install
1819

@@ -68,6 +69,31 @@ result = allocator.random_walk(G, n_walks=10, walk_length_m=5000)
6869
print(result.data) # DataFrame with waypoints
6970
```
7071

72+
### Calculate distance matrix
73+
74+
```python
75+
from allocator.distances import get_distance_matrix
76+
import numpy as np
77+
78+
points = np.array([
79+
[-122.4194, 37.7749], # SF downtown
80+
[-122.4089, 37.7855], # North Beach
81+
])
82+
83+
# Local calculation (fast, no API)
84+
dist = get_distance_matrix(points, method="haversine")
85+
86+
# OSRM (free, real driving times)
87+
dist = get_distance_matrix(points, method="osrm")
88+
89+
# Google Routes API (requires service account)
90+
dist = get_distance_matrix(
91+
points,
92+
method="google_routes",
93+
credentials_file="/path/to/service-account.json"
94+
)
95+
```
96+
7197
## CLI
7298

7399
```bash

allocator/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,10 @@
7171
)
7272
from .viz.plotting import plot_assignments, plot_clusters, plot_comparison, plot_route
7373

74-
__version__ = "1.2.0"
74+
try:
75+
from ._version import __version__
76+
except ImportError:
77+
__version__ = "dev"
7578

7679
__all__ = [
7780
# Result types

allocator/core/itinerary.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,22 @@
1111
"""
1212

1313
import numpy as np
14+
from numba import njit
1415
from ortools.constraint_solver import pywrapcp, routing_enums_pb2
1516

1617

18+
@njit(cache=True)
19+
def _compute_route_distance_jit(route: np.ndarray, distance_matrix: np.ndarray) -> float:
20+
"""JIT-compiled route distance computation."""
21+
n = len(route)
22+
if n <= 1:
23+
return 0.0
24+
total = 0.0
25+
for i in range(n - 1):
26+
total += distance_matrix[route[i], route[i + 1]]
27+
return total
28+
29+
1730
def _ensure_rng(rng: np.random.Generator | None) -> np.random.Generator:
1831
"""Return rng if provided, otherwise create a new default RNG."""
1932
return rng if rng is not None else np.random.default_rng()
@@ -145,10 +158,8 @@ def compute_route_distance(route: list[int], distance_matrix: np.ndarray) -> flo
145158
"""
146159
if len(route) <= 1:
147160
return 0.0
148-
total = 0.0
149-
for i in range(len(route) - 1):
150-
total += distance_matrix[route[i], route[i + 1]]
151-
return total
161+
route_arr = np.asarray(route, dtype=np.int64)
162+
return float(_compute_route_distance_jit(route_arr, distance_matrix))
152163

153164

154165
def tsp_optimize_route(

allocator/distances/__init__.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
"""Distance matrix calculations."""
22

33
from .euclidean import euclidean_distance_matrix, latlon2xy, pairwise_distances, xy2latlog
4-
from .external_apis import google_distance_matrix, osrm_distance_matrix
4+
from .external_apis import (
5+
google_distance_matrix,
6+
google_routes_distance_matrix,
7+
osrm_distance_matrix,
8+
)
59
from .factory import get_distance_matrix
610
from .haversine import haversine_distance_matrix
711

812
__all__ = [
913
"euclidean_distance_matrix",
1014
"get_distance_matrix",
1115
"google_distance_matrix",
16+
"google_routes_distance_matrix",
1217
"haversine_distance_matrix",
1318
"latlon2xy",
1419
"osrm_distance_matrix",

0 commit comments

Comments
 (0)