Tubeulator Models
Graph neural network models of the London Underground trained on TfL timetable data.
Two models share a GATv2 encoder over the station topology graph and differ in their decoder head:
- nexthop policy — given a current station and destination, predicts the optimal next station to visit. Greedy rollout achieves 1.09× Dijkstra ratio with 100% success across all 239,610 origin–destination pairs.
- nexthop value — predicts shortest travel time in minutes between any pair of stations. MAE of ~0.5 min vs. Floyd–Warshall ground truth.
Installation
pip install tubeulator-models[inference]
For the CLI:
pip install tubeulator-models[cli]
Usage
Python API
from tubeulator_models import TubeRouter
router = TubeRouter.from_pretrained("permutans/tube-nexthop-policy")
route = router.route("West Ham", "Shoreditch")
print(route)
# West Ham
# → [district] Bromley-by-Bow (2.0m)
# ...
# ✓ 8 hops · 2 lines · 1 transfer · 16.0 min
Route through waypoints:
route = router.route("Camden Town", "Canary Wharf", via=["King's Cross"])
The Route object has .steps, .total_minutes, .lines_used, .n_transfers, .success, and a .to_dict() method.
CLI
tm-infer policy --model permutans/tube-nexthop-policy -o "West Ham" -d Shoreditch
tm-infer policy --model permutans/tube-nexthop-policy -o "Camden Town" -d "Canary Wharf" -v "King's Cross"
tm-infer value --model permutans/tube-nexthop-value -o "West Ham" -d Shoreditch
Training from source
Clone the repo and use the justfile recipes:
just all # fetch data + build graph + train
Or step by step:
just fetch # pull timetables from TfL API → GTFS zip
just graph # GTFS → GeoParquet → PyG graph objects
just train nexthop full
just train nexthop full --value-primary --batch-size 1024 --epochs 200
All hyperparameters live in defaults.toml. CLI flags override the TOML but never replace it:
tm-train --model nexthop --profile full --lr 5e-5
Profiles control the training regime:
| Profile | Epochs | Batch size | LR | Notes |
|---|---|---|---|---|
dev |
20 | 512 | 5e-4 | Fast iteration |
full |
200 | 256 | 1e-4 | Production, d_model=512, 16-layer encoder |
Data pipeline
| Step | CLI | Recipe | Output |
|---|---|---|---|
| Fetch timetables | tm-build-gtfs |
just fetch |
data/tfl_station_data_gtfs.zip |
| Build graph | tm-gtfs2pyg |
just graph |
data/graph/, data/pyg/ |
| Plot network | tm-plot |
just plot |
data/graph/network.png |
| Train | tm-train |
just train |
checkpoints/ |
| Export | tm-export |
just upload |
models/ → HuggingFace |
Staged graph conversion is also available:
uv run --group prep tm-gtfs2graph # GTFS → GeoParquet
uv run --group pyg tm-graph2pyg # GeoParquet → PyG .pt
Configuration
defaults.toml is the single source of truth for all tuneable values. The merge order is:
[base] → [model.<type>] → [profiles.<name>] → [profiles.<name>.model.<type>] → CLI overrides
Development
just lint # ruff check
just clean # remove data/ and checkpoints/
Links
Metadata
Release files for tubeulator-models 0.1.5
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| tubeulator_models-0.1.5.tar.gz | 60.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| tubeulator_models-0.1.5-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 134.0 kB
Release files / tubeulator_models-0.1.5.tar.gz
| Download URL | tubeulator_models-0.1.5.tar.gz |
|---|---|
| Size | 60.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
4ef62b35fbaa5d9fa2728261221ab6a3f0c14526eac9685b1aa80a749ae86492
|
|
BLAKE2b-256 checksum How to use checksums |
3c724f54044af51814382553d8871b1a478a97de66e944be4ba1ac53de1c25f4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22","id":"wilma","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / tubeulator_models-0.1.5-py3-none-any.whl
| Download URL | tubeulator_models-0.1.5-py3-none-any.whl |
|---|---|
| Size | 73.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ace246816098540a0761a8dda19e37b7f525c1fdadd5636295eb4a9cceef377a
|
|
BLAKE2b-256 checksum How to use checksums |
10baec713e796b297688fa0eae7ba632be77e8b390f46c0cca2dfea5c19b7e50
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.26 {"installer":{"name":"uv","version":"0.9.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Linux Mint","version":"22","id":"wilma","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|