An agent-based route optimizer that maps Big-Five personality scores to Multinomial-Logit (MNL) discrete-choice weights, so different people get genuinely different "best" routes across the same campus graph. Discrete-choice econometrics + agent-based simulation, with a 407-test suite and property-based invariants.
Generated from the model: make hero. Optionally add a short GIF of the live Streamlit demo too.
Try it live in 10 seconds — no database, no keys:
ROTA_DEMO=1 uv run streamlit run src/api/pilot_app.pyOpen http://localhost:8501 → Demo: Persona Grubu vs Demo: Kontrol Grubu and watch the same origin→destination produce different routes per personality.
Standard pedestrian routers optimize one universal cost (usually distance or time), so everyone gets the same path. But an anxious first-year and a sensation-seeking senior don't want the same route — one avoids crowds, weather exposure, and badly-lit stretches; the other takes the scenic shortcut. Rota is a research engine (a B.Sc. thesis at Boğaziçi University) that treats route choice as a discrete-choice problem: it derives per-person edge-cost weights from a psychometric survey via a Multinomial-Logit model, runs them through Yen's k-shortest-paths for genuine A/B differentiation, and validates the whole thing in a Mesa agent-based simulation of 2,000 synthetic students before a real campus field pilot.
Simulation experiments (2,000 agents on the real Boğaziçi campus graph) and the Phase-1 human survey:
| Experiment | Metric | Result |
|---|---|---|
| Exp 1 — persona vs control routing | route–persona alignment | +15% (Cohen's d = 0.149) |
| Exp 2 — congestion-aware fleet | mean wait time | −21.4% |
| Exp 3 — crowd avoidance | peak crowding | −17% |
| Exp 4 — multimodal (walk + shuttle + scooter) | travel time | −43% |
| Phase-1 survey (n = 26) | MNL weight-sign agreement vs predicted | 70% confirmed, p = .047 |
| Test suite | unit + property-based + integration | 407 tests |
(Results are simulation/pilot outcomes from the thesis, not production traffic. Method and caveats below.)
The core is a persona-weighted edge cost, with weights derived from psychometrics rather than hand-tuned:
-
$f_k(r)$ — eight cost-transformed route attributes: travel time, scenic (inverted), elevation gain, reliability (inverted), carbon, crowding, weather exposure, safety-lighting (inverted); each in$[0,1]$ . -
$\Psi_j$ — six psychometric scores (Big-Five OCEAN + Sensation-Seeking) from a TIPI-TR / BFI-2-XS survey. -
$\gamma_{kj}$ — an 8×6 personality×attribute interaction matrix (the primary thesis output); weights are floored at1e-4and normalized so$\sum_k \beta_k = 1$ . - K-means groups people into six interpretable archetypes (Social Navigator, Pragmatist, Anxious Walker, Minimalist, Adventurer, Eco-Conscious).
- Yen's k-shortest-paths surfaces genuinely distinct candidate routes (fixing a bug where every persona collapsed to the same path), then an optional, bounded LLM re-ranker does contextual tie-breaking.
Grounded in discrete-choice theory (McFadden, 1974). Phase 1 sets γ from literature hypotheses; Phase 2 estimates it empirically with Biogeme from a discrete-choice-experiment survey. The ABM layer is Mesa 3.x; the campus graph is built with OSMnx from OpenStreetMap.
The suite's spine is a property-based check (Hypothesis) that the MNL cost function stays well-formed for any random persona — weights normalize to 1 and the cost responds monotonically to each attribute — rather than only checking hand-picked examples. Property-based testing caught roughly 90% of the late-stage P0 bugs in this project.
uv sync --extra dev
uv run pytest -m "not integration and not slow" -q # ~14s, unit + property-based
uv run pytest # full suite, 407 tests
uv run ruff check .| Path | What it is |
|---|---|
src/core/ |
Persona model, MNL weight derivation, 8-dim cost function, multimodal graph |
src/routing/ |
A* / Dijkstra + Yen's k-shortest, persona-weighted and multimodal |
src/agents/, src/llm/ |
Mesa agents (student/vehicle/shuttle) + bounded LLM re-ranker |
src/api/ |
FastAPI GPS-ingest endpoint + Streamlit pilot app + admin dashboard |
simulation/ |
Mesa agent-based campus model + the four experiments |
analysis/ |
Statistics + thesis figure/table generation |
data/campus/ |
Boğaziçi multi-campus graph (OSMnx from OpenStreetMap) |
tests/ |
407 tests — unit/, property_based/ (Hypothesis), integration/ |
Stack: Python 3.12 · Mesa 3.x · NetworkX · OSMnx 2.x · scikit-learn · FastAPI · Streamlit · Supabase (PostgreSQL + PostGIS). Field-study environment variables are documented in .env.example; GPS traces are H3-cloaked and KVKK-retention-bounded (raw points never stored).
The environment is fully pinned (.python-version + uv.lock) and RNG-seeded, so a clean checkout is deterministic. Common tasks run through a Makefile:
make setup # uv sync --extra dev → installs Python 3.12 + locked deps
make check # exactly what CI runs: ruff lint + format-check + fast tests
make demo # Streamlit pilot in demo mode (no DB, no keys)
make reproduce # re-run the multi-modal simulation experiment (tracked data)
make help # list all targetsFull setup, conventions, and result-reproduction steps are in CONTRIBUTING.md. CI (ruff lint + format + the fast suite on Python 3.12) runs on every push; src/ and simulation/ are held to the full ruleset, one-off scripts/+analysis/ utilities are scope-relaxed.
- Phase-1 survey is small (n = 26); the γ interaction matrix is a first literature-seeded calibration, not a population estimate — Phase 2 re-fits it with Biogeme on field data.
- Effect sizes come from synthetic-agent simulation and a small pilot, not large-scale real-world traffic.
- The LLM re-ranker is optional and bounded (<200 calls/run via archetype clustering); core routing is fully deterministic without it.
- Requires Python 3.12 exactly; geospatial deps (OSMnx/GeoPandas/rasterio) pull GDAL-backed wheels.
Machine-readable metadata lives in CITATION.cff (GitHub renders a Cite this repository button from it).
@thesis{kenter2026rota,
title = {Agent-Based Psychometric Route Optimization},
author = {Kenter, Çağatay},
school = {Boğaziçi University},
year = {2026}
}MIT — see LICENSE.
