Architecture
Fait par Gillesto
Vue d'ensemble
SafeRoute/
├── src/
│ ├── saferoute/ ← Package Python (src-layout PyPA)
│ │ ├── engine.py ← Orchestrateur principal
│ │ ├── graph_cache.py ← Cache .graphml + .csv.gz
│ │ ├── kde_scorer.py ← Scoring KDE vectorisé
│ │ ├── familiarity.py ← Familiarité utilisateur
│ │ ├── data_loader.py ← Ingestion Police UK + SAPS
│ │ ├── exceptions.py ← Hiérarchie SafeRouteError
│ │ └── api/ ← FastAPI REST
│ └── rust/ ← Core Rust (PyO3/maturin)
│ └── src/
│ ├── algorithms/ ← recherche biobjectif ε (NAMOA*) + Pareto
│ ├── graph/ ← Graph, Node, Edge
│ └── scoring/ ← KDE gaussien (référence Rust ; le scoring de production est dans kde_scorer.py)
└── tests/ ← tests Python (+ tests Rust dans src/rust)
Protocole Python ↔ Rust (0.1.2)
Python Rust
│ colonnes numpy (octets <u8 / <f8) │
│ ────────────────────────────────────► │ PyGraph.from_arrays() (valide : nœuds uniques,
│ │ arcs sans extrémité inconnue,
│ │ poids finis >= 0)
│ update_familiarity(indices, valeurs) │
│ ────────────────────────────────────► │ seuls les arcs modifiés (record_trip)
│ │
│ compute_safe_routes(g, s, t, eps) │
│ ────────────────────────────────────► │ GIL relâché
│ │ 1. Dijkstra inverses : bornes exactes h_dist, h_risque
│ │ 2. étiquettes (arène, pointeurs parents)
│ │ 3. élagage ε sur g + h, dominance exacte par nœud
│ │ 4. budget de labels (BudgetExceededError)
│ list[PyRouteResult] │
│ ◄──────────────────────────────────── │
▼
ParetoSet.from_results()
Le cœur Rust (graph, algorithms, scoring) ne dépend pas de PyO3 : la couche Python vit dans
python.rs, derrière la feature python. cargo test s'exécute donc sans interpréteur Python.