Skip to main content

SafeRoute

Fait par Gillesto

CI PyPI Python License: MIT Documentation

⚠️ Avertissement d'usage. Le score de risque est une densité statistique de crimes passés (Police UK, SAPS). Il ne prédit pas un crime et ne garantit pas la sécurité d'un trajet : il aide à comparer des itinéraires, il ne remplace pas le jugement de la personne qui se déplace. Les sources sont anonymisées et biaisées par le signalement (voir docs/donnees.md).


Qu'est-ce que SafeRoute ?

SafeRoute est une bibliothèque Python de routage piéton sûr qui calcule simultanément trois itinéraires entre deux points d'une ville, en optimisant des objectifs contradictoires :

Itinéraire Optimise Compromis
shortest Distance minimale Peut traverser des zones à risque
safest Risque criminel minimal Peut allonger le trajet de 20–40%
balanced Équilibre distance + sécurité + familiarité Recommandé pour un usage quotidien

Le moteur de calcul est écrit en Rust (recherche multi-objectif ε-approximée) et exposé à Python via PyO3/maturin ; le scoring KDE est en Python (numpy/scipy). Les données de criminalité proviennent de sources officielles : Police UK API pour Londres et SAPS pour Le Cap — ou les vôtres, pour n'importe quelle ville (engine.load_graph(graphe_osmnx, crimes)).


Pourquoi SafeRoute ?

Les applications de navigation classiques (Google Maps, Waze) optimisent uniquement la distance ou le temps. SafeRoute résout un problème différent : comment rentrer chez soi en sécurité ?

La formule de coût intègre trois dimensions :

C = w₁ · Distance + w₂ · Risque − w₃ · Familiarité
  • Risque : densité criminelle sur chaque segment de rue, calculée par KDE gaussien à partir des données historiques de criminalité géolocalisées (bande passante réelle en mètres)
  • Familiarité : les rues que vous empruntez régulièrement sont mémorisées et cumulées (total_familiarity). Elle n'influence pas le choix des trois itinéraires (voir limites connues).
  • Algorithme : recherche à étiquettes biobjectif de type NAMOA*, inspirée de A*pex (Zhang et al., ICAPS 2022), avec bornes inférieures exactes et élagage ε. Garantie vérifiée par les tests contre un calcul exhaustif : chaque solution Pareto-optimale exacte est couverte à (1+ε) près (eps=0.1 → 10 %). Elle ne reprend pas le regroupement en « paires apex » de l'article.

Installation

# Bibliothèque seule (calcul d'itinéraires)
pip install saferoute

# Avec le serveur REST FastAPI
pip install "saferoute[api]"

Rust n'est pas requis : le wheel PyPI contient le binaire Rust précompilé (wheel abi3 : Windows, Linux et macOS, Python ≥ 3.10). Sans wheel pour votre plateforme, pip compile les sources et exige alors une chaîne Rust. Cartes et graphiques (notebook de démonstration) : pip install "saferoute[viz]".


Exemple concret : trouver le chemin le plus sûr à Londres

from saferoute import SafeRouteEngine
from saferoute.exceptions import SafeRouteError

# 1. Initialiser le moteur (eps=0.1 → approximation à 10% de l'optimal)
engine = SafeRouteEngine(eps=0.1)

# 2. Charger la ville — utilise le cache local si disponible,
#    télécharge OSMnx + données de criminalité sinon (~5 min la première fois)
engine.load_city("london")

# 3. Convertir des coordonnées GPS en identifiants de nœuds OSM
#    Départ : Gare de London Bridge
source = engine.nearest_node(lat=51.5055, lon=-0.0873)
#    Arrivée : Borough Market
target = engine.nearest_node(lat=51.5055, lon=-0.0910)

# 4. Calculer les 3 itinéraires Pareto-optimaux
try:
    pareto = engine.compute_routes(source, target)
except SafeRouteError as e:
    print(f"Erreur : {e}")
    raise

# 5. Comparer les résultats
print(f"Plus court  : {pareto.shortest.total_distance_m:.0f}m "
      f"en {pareto.shortest.estimated_time_min:.1f} min "
      f"(risque={pareto.shortest.total_risk:.3f})")

print(f"Plus sûr    : {pareto.safest.total_distance_m:.0f}m "
      f"en {pareto.safest.estimated_time_min:.1f} min "
      f"(risque={pareto.safest.total_risk:.3f})")

print(f"Équilibré   : {pareto.balanced.total_distance_m:.0f}m "
      f"en {pareto.balanced.estimated_time_min:.1f} min "
      f"(risque={pareto.balanced.total_risk:.3f})")

# Exemple de sortie typique :
# Plus court  : 380m en 5.7 min (risque=0.847)
# Plus sûr    : 510m en 7.7 min (risque=0.112)
# Équilibré   : 430m en 6.5 min (risque=0.341)

# 6. Enregistrer le trajet effectué pour améliorer les recommandations futures
#    (les rues empruntées régulièrement voient leur coût réduit)
engine.record_trip(pareto.balanced.path)

Utiliser l'API REST

# Démarrer le serveur
uvicorn saferoute.api.main:app --reload
# → Documentation interactive : http://localhost:8000/docs
# Charger une ville
curl -X POST http://localhost:8000/api/v1/load-city \
     -H "Content-Type: application/json" \
     -d '{"city": "london"}'

# Calculer les 3 itinéraires
curl -X POST http://localhost:8000/api/v1/route \
     -H "Content-Type: application/json" \
     -d '{
       "city": "london",
       "source_node": 123456789,
       "target_node": 987654321,
       "eps": 0.1
     }'

Réponse JSON consommable directement par React ou Flutter :

{
  "city": "london",
  "shortest": {
    "path": [123456789, 111, 222, 987654321],
    "total_distance_m": 380.0,
    "distance_km": 0.38,
    "total_risk": 0.847,
    "estimated_time_min": 5.7,
    "comfort_score": 0.17,
    "route_type": "shortest"
  },
  "safest": { "..." : "..." },
  "balanced": { "..." : "..." }
}

Performance mesurée

Mesures réelles et rejouables (python benchmarks/run.py --city london), portable 8 cœurs logiques / 15,8 Go, Windows 11, Python 3.13 (détail, méthode et limites : docs/benchmarks.md).

Londres (501 k nœuds, 1,29 M arcs, 100 917 crimes) Le Cap (127 k nœuds, 360 k arcs)
Lecture du graphe (cache graphml) 232 s 60 s
Conversion en colonnes numpy 8,5 s 2,1 s
KDE (100 917 crimes → 1,29 M arcs) 2,7 s 0,4 s
Construction du graphe Rust 1,2 s 0,3 s
Total au chargement 245 s (une fois par processus) 63 s
Mémoire du processus après chargement ≈ 5,5 Go ≈ 2,4 Go
Itinéraire 0,5–4 km (ε = 0,1), p50 / p95 0,5 s / 0,7 s 0,13 s / 0,18 s
Itinéraire 4–10 km (ε = 0,1), p50 1,8 s 0,8 s
Itinéraire 4–10 km, cas défavorables jusqu'à 31 s ou budget dépassé jusqu'à 40 s ou budget dépassé

La promesse « < 2 secondes sur Londres » des versions précédentes n'est vraie ni en général ni pour les trajets longs : elle l'est pour les trajets de moins de ~4 km et la médiane des 4–10 km. Une requête trop complexe s'arrête avec SearchBudgetExceededError (jamais un crash) ; augmenter eps (0,3) aide.

Villes supportées

Ville Données de criminalité Graphe routier
Londres data.police.uk — 100k crimes/trimestre 501k nœuds, 1.2M arcs
Le Cap SAPS — 30 stations de police 127k nœuds, 360k arcs

Architecture

SafeRoute/
├── src/
│   ├── saferoute/          ← Package Python
│   │   ├── engine.py       ← Orchestrateur principal
│   │   ├── exceptions.py   ← SafeRouteError, GraphNotLoadedError, ...
│   │   └── api/            ← Serveur FastAPI (optionnel)
│   └── rust/               ← Core de calcul Rust
│       └── src/
│           ├── algorithms/ ← A*pex + frontière de Pareto
│           ├── graph/      ← Structures Node, Edge, Graph
│           └── scoring/    ← KDE gaussien
└── tests/                  ← 170 tests Python + 64 tests Rust

Protocole Python ↔ Rust : Python convertit le graphe enrichi (OSMnx + scores KDE + familiarité) en colonnes numpy, une seule fois ; Rust reçoit les octets bruts (PyGraph.from_arrays, sans JSON) et valide le graphe. Quand la familiarité change, seuls les arcs modifiés sont renvoyés (update_familiarity). Rust exécute la recherche (GIL relâché) et retourne les routes → Python les convertit en dataclasses.

Limites connues

  • La familiarité ne modifie pas le choix des routes : elle est cumulée et rapportée, mais n'entre ni dans la dominance de Pareto ni dans la sélection de shortest / safest / balanced.
  • safest minimise le risque seul : sur un trajet de 7 km à Le Cap, il peut atteindre ~25 km.
  • Le défaut de bande passante (Silverman, 740–800 m) sur-lisse : en évaluation temporelle sur Londres (test sur 2 mois jamais vus), il n'atteint que AUC 0,536 (hasard = 0,5), contre 0,663 avec SafeRouteEngine(bandwidth_m="auto"). Utilisez "auto" ; voir docs/benchmarks.md.
  • Le cache d'origine de Londres n'avait pas de date et sous-échantillonnait les crimes (voir ci-dessous) ; benchmarks/download_dated_london.py télécharge des crimes datés (fetch_london_crimes conserve le mois).
  • Les crimes de Londres sont ancrés sur des points de rue : plusieurs crimes réels partagent les mêmes coordonnées (voir validate_crimes(..., deduplicate=False)).
  • Le graphe d'une grande ville occupe plusieurs Go de RAM ; le chargement du graphml est lent (4 min pour Londres) et est le goulot d'étranglement du démarrage.

Documentation complète

https://gillesto66.github.io/SafeRoute/


Développement

# Prérequis : Rust (https://rustup.rs)
git clone https://github.com/Gillesto66/SafeRoute.git
cd SafeRoute
pip install -e ".[dev,api]"           # compile aussi le core Rust (maturin)

# Tests (CI=true : l'absence du module natif devient un échec au lieu d'un test sauté)
CI=true python -m pytest tests/ -q    # tests Python
cargo test --workspace                # tests Rust : aucun Python requis

# Wheel construit, installé dans un environnement vierge
python -m maturin build --release --out dist && python scripts/smoke_wheel.py dist

Voir CONTRIBUTING.md pour le guide complet.


Licence

MIT — voir LICENSE

Metadata

Release files for saferoute 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for saferoute 0.1.2
File Size Uploaded Provenance
saferoute-0.1.2.tar.gz 75.6 kB With provenance Details

Built distributions (wheels)

Table of built distributions (wheels) for saferoute 0.1.2
File
saferoute-0.1.2-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details
saferoute-0.1.2-cp310-abi3-manylinux_2_28_aarch64.whl CPython 3.10 abi3 Linux glibc 2.28+ ARM64 Details
saferoute-0.1.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details
saferoute-0.1.2-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details
saferoute-0.1.2-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details

Total release size: 1.6 MB

Release files / saferoute-0.1.2.tar.gz

Download URL saferoute-0.1.2.tar.gz
Size 75.6 kB
Tags Source
SHA-256 checksum
How to use checksums
e67a9e2ec82265fc68a1c84fadb20ea5cc8d7ffb8b258fab9d556d035625572b
BLAKE2b-256 checksum
How to use checksums
304613fefc8177919ea9e8892feefb34845947db75cc6aa3cbe654db53e7d098
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / saferoute-0.1.2-cp310-abi3-win_amd64.whl

Download URL saferoute-0.1.2-cp310-abi3-win_amd64.whl
Size 230.4 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
36e48206e79877f411b88e770b50f2e0eddae1e014046d981168eec34a3b0120
BLAKE2b-256 checksum
How to use checksums
0bb7fc1f951976d8a159ae6de0954cc4a7f0b371e31b3fab5b24630ff7d49bd0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / saferoute-0.1.2-cp310-abi3-manylinux_2_28_aarch64.whl

Download URL saferoute-0.1.2-cp310-abi3-manylinux_2_28_aarch64.whl
Size 313.0 kB
Tags CPython 3.10 Linux glibc 2.28+ ARM64 abi3
SHA-256 checksum
How to use checksums
fd3462f5f0d2749f7355feb050dfb5279032bea88d4d42bc8fd08b504f633149
BLAKE2b-256 checksum
How to use checksums
e30bb7dc9bf39e5391725ef5074361edf5eef9384f15c5de60db2119b28b4671
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / saferoute-0.1.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL saferoute-0.1.2-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 324.6 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
471f6eb59864671254785c56b1f8b6e67c18fff0dda1f72770b91c73f49d1ae0
BLAKE2b-256 checksum
How to use checksums
39aa8fb80ee844f9245845617e95fe83b903d2978e37e0c609167dfefee9309b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / saferoute-0.1.2-cp310-abi3-macosx_11_0_arm64.whl

Download URL saferoute-0.1.2-cp310-abi3-macosx_11_0_arm64.whl
Size 298.2 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a48857ee5ad81a60635d9af4c6931b02e35cec3628eb9dd435742f297863462c
BLAKE2b-256 checksum
How to use checksums
f30aa4c19c4ed1a8af260faad3d26fcb7c70e7da5a5d5ad7e23b0385c3a63719
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Release files / saferoute-0.1.2-cp310-abi3-macosx_10_12_x86_64.whl

Download URL saferoute-0.1.2-cp310-abi3-macosx_10_12_x86_64.whl
Size 312.1 kB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
4f13792f739d18f79d5f91968062ee5b564dbafcca78885b70a3dff110aa2689
BLAKE2b-256 checksum
How to use checksums
14b2c14f2566ca2057d1a903a1c162ddce0fb8ce9ce730a646a369bba3795b9d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

Security for saferoute 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 6 files in this release have been uploaded with provenance metadata.

Select from 6 files

Attestation for saferoute-0.1.2.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.2 This release

6 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page