Catalog PyPI
PACKAGE EXPLORERView in registry

agent-urban-planning

PyPI

Agent-based urban planning simulator with closed-form, hybrid, and full-LLM decision engines

agent-based-modelingahlfeldt-2015berlinlarge-language-modelsspatial-equilibriumurban-planning
Versions collected1
Direct dependencies28From release 0.1.0
Last observed20 Oct, 23:36 UTC

README

Version 0.1.0 documentation

agent-urban-planning

PyPI Documentation Status License: MIT Python 3.9+

Open-source Python library for agent-based urban planning simulation with closed-form, hybrid, and full-LLM decision engines. Companion to the NeurIPS Datasets & Benchmarks 2026 paper:

TBD — paper title

Workflow

workflow

The simulator is organized as a five-stage pipeline. (1) Environment — a city is described by zones, transportation graphs, land-use parameters, housing, amenities, and wages; an optional policy shock perturbs this state (e.g., a new rapid-transit line). (2) Agents — a population of heterogeneous household types (young professionals, families with kids, retirees, …) with demographic and preference attributes. (3) Decision — each agent picks a (residence, workplace) pair via one of three swappable engines: a closed-form UtilityEngine (V1–V3), a HybridDecisionEngine that elicits LLM-side preferences and resolves choice in closed form (V4), or a full LLMDecisionEngine that consults a language model end-to-end (V5 — the paper headline). (4) Market & Allocation — the macro layer aggregates choices, clears the housing/labor markets via tâtonnement (rents, wages, congestion), and allocates agents to zones. (5) Equilibrium — a fixed-point solver iterates 1→4 until prices and choices stop moving. Output is a bundle of welfare metrics, choropleth maps, and per-agent traces with a recorded seed for replay.

What it is

A modular ABM framework for simulating spatial-equilibrium urban policies. Five reference decision-engine variants ship as first-class API classes, configurable via kwargs:

Paper variantOne-line descriptionAPI call
V1 Baseline-softmaxClosed-form Cobb-Douglas + Fréchet softmaxaup.UtilityEngine(mode="softmax")
V2 Baseline-ABM argmaxABM with Fréchet idiosyncratic shocksaup.UtilityEngine(mode="argmax", noise="frechet")
V3 Normal-ABM argmaxABM with Gaussian shocksaup.UtilityEngine(mode="argmax", noise="normal")
V4 Hybrid-ABMLLM-elicited preferences + closed-form choiceaup.HybridDecisionEngine(elicitor=...)
V5 LLM-ABM (paper headline)Full LLM-as-decision-maker, score-all-96aup.LLMDecisionEngine(response_format="score_all", rebalance_instruction=True, stage2_top_k_residences=10)

Quickstart

git clone https://github.com/MASE-eLab/agent-urban-planning.git
cd agent-urban-planning
pip install -e ".[llm,plot,berlin]"
python examples/01_quickstart.py

The quickstart script walks through the five-stage pipeline (Environment → Agents → Decision → Market → Equilibrium) and runs a baseline simulation with V1 (closed-form softmax). Wall-clock <1 minute, no LLM credits required.

import agent_urban_planning as aup
from agent_urban_planning.data.loaders import load_scenario, load_agents

# Stage 1+2 — Environment + Agents
scenario = load_scenario("data/berlin/scenarios/berlin_2006_ortsteile.yaml")
agent_config = load_agents("data/berlin/agents/berlin_ortsteile_richer_10k.yaml")

# Stage 3 — Decision engine (V1; swap to V2/V3/V4/V5 with one constructor change)
engine = aup.UtilityEngine(scenario.ahlfeldt_params, mode="softmax")

# Stage 4 — SimulationEngine + market clearing (Stage 5 = result.metrics)
sim = aup.SimulationEngine(scenario=scenario, agent_config=agent_config,
                           engine=engine, seed=42)
result = sim.run(policy=None)

print(result.metrics.avg_utility, result.metrics.gini_coefficient)

The other 4 paper variants (V2, V3, V4, V5) swap only the decision engine — see the variant table below.

Berlin replication results

We benchmark all five variants on a 96-zone Berlin scenario (Ahlfeldt et al. 2015 calibration) under a hypothetical East–West Express rapid-transit shock (4 stations, 5-min between adjacent).

Choropleth: log-change in housing prices Δlog Q under the shock

Berlin Δlog Q

The structural family (V1, V2, V4) produces a visibly focal response — price effects concentrate at the four station catchments. LLM-ABM (V5) instead spreads the response broadly across the city, picking up the gradient-flattening + agglomeration effects that exogenous-productivity models forbid.

Choropleth: log-change in wages Δlog w under the shock

Berlin Δlog w

The wage maps tell the same story at the workplace side: structural variants forbid the agglomeration channel by construction (productivity A_i is exogenous), while LLM-ABM produces a coherent compensating-differential pattern via its training-data priors on urban economics.

Cross-variant moments

Distribution-shape moments across the 96 zones (baseline → shock):

Variantμ ΔlogQσ ΔlogQp95 |ΔlogQ|ΔY%Δ Q̄Δ⟨U⟩
V1 Baseline-softmax+0.00040.00700.0083+0.0007+0.0008−0.0032
V2 Baseline-ABM argmax+0.00040.00710.0080−0.0000+0.0007−0.0031
V3 Normal-ABM argmax+0.00040.00420.0048+0.0132+0.0001−0.0027
V4 Hybrid-ABM+0.00040.00680.0077+0.0002+0.0007−0.0031
V5 LLM-ABM+0.00160.00830.0172+0.0299+0.0111−0.0056

Full table + interpretation: figures/comparison_moments.csv.

Three takeaways.

  1. The structural family agrees. V1, V2, V4 (and V3 modulo Gaussian-vs-Fréchet tail differences) cluster tightly on μ ≈ +0.0004, σ ≈ 0.007, Δ⟨U⟩ ≈ −0.0031. They share the Cobb-Douglas + Fréchet architecture; the noise model and clustering wash out at zone-level moments. Architecturally distinct simulators give the same answer to a small policy shock — a useful sanity check for the structural family.
  2. LLM-ABM is qualitatively different. Its mean log-change in housing price is 4× the structural consensus; spread (σ, p95) is 1.2–2× larger; mean rent change is 14× larger; aggregate productivity gain (+3%) is the only sizable positive value. Welfare drop is ~2× the structural family's.
  3. All five agree on welfare direction. Δ⟨U⟩ < 0 across the board under the Baseline-softmax welfare ruler — the shock is a (small) net welfare loss. The mechanisms differ: structural variants attribute the drop to commute/wage compensation; LLM-ABM picks up the same direction at ~2× magnitude because its equilibrium reroutes more agents to lower-utility configurations under the structural ruler's lens.

The full paper §6 discusses why LLM-ABM diverges (gradient-flattening + agglomeration, both forbidden in exogenous-productivity structural models).

Reproduce the paper results

The paper's V1–V5 Berlin runs (baseline + East-West Express shock) reproduce end-to-end from a git clone. Pick a path:

git clone https://github.com/MASE-eLab/agent-urban-planning.git
cd agent-urban-planning
pip install -e ".[llm,plot,berlin]"

# Tier 1+2 — quickstart pipeline walkthrough (<1 min, V1 baseline only)
python examples/01_quickstart.py

# Tier 3 — V1/V2/V3 closed-form + ABM variants (~3 hr each, no LLM credits)
python examples/02_berlin_replication/run_v1_softmax.py
python examples/02_berlin_replication/run_v2_argmax_frechet.py
python examples/02_berlin_replication/run_v3_argmax_normal.py

# Tier 3d — V4 hybrid (~3 hr, ~$5 in LLM credits)
python examples/02_berlin_replication/run_v4_hybrid.py --llm-provider codex-cli

# Tier 4 — V5 LLM-ABM, paper headline. Two paths:
#   Path A: replay the bundled cache (~5–10 min, no credits, recommended for reviewers)
curl -L -o llm_cache_v5.tar.gz \
  https://github.com/MASE-eLab/agent-urban-planning/releases/download/v0.1.0-data/llm_cache_v5.tar.gz
tar -xzf llm_cache_v5.tar.gz -C data/berlin/
python examples/02_berlin_replication/run_v5_score_all.py --no-llm

#   Path B: rerun from scratch with live LLM (~10 hr, ~$30–50 credits)
python examples/02_berlin_replication/run_v5_score_all.py --llm-provider codex-cli
TierWhatWall-clockLLM credits
1pip install + import agent_urban_planning<30 sNo
2examples/01_quickstart.py<10 sNo
3a-cV1, V2, V3 Berlin baseline + shock~3 hr eachNo
3dV4 Berlin baseline + shock (hybrid)~3 hr~$5
4V5 Berlin baseline + shock (cache replay)~5–10 minNo
4V5 Berlin baseline + shock (live LLM)~10 hr~$30–50

Detailed instructions (real-run params, smoke testing, all 6 LLM provider options, cross-variant analysis snippets, numerical-reproducibility expectations) are in examples/02_berlin_replication/README.md. The full reproducibility tier ladder lives at docs/reproducibility/berlin_v1_v5.md (also rendered at https://agent-urban-planning.readthedocs.io/en/latest/reproducibility/berlin_v1_v5.html).

Documentation

Comprehensive API reference, tutorials, and concept guides:

→ https://agent-urban-planning.readthedocs.io

Repository layout

agent-urban-planning/
├── src/agent_urban_planning/      Library source
│   ├── core/                       Environment / Agents / Market / Engine / Metrics
│   ├── decisions/                  UtilityEngine / HybridDecisionEngine / LLMDecisionEngine
│   ├── data/                       Loaders + builtin scenarios
│   ├── analysis/                   Welfare + plotting
│   ├── llm/                        LLM client wrappers
│   └── research/                   Paper-specific helpers (Berlin)
├── examples/
│   ├── 01_quickstart.py   Full V1 pipeline walkthrough (<1 min)
│   └── 02_berlin_replication/      End-to-end V1–V5 Berlin runs
├── data/                           Bundled Berlin + Singapore data (git, not PyPI sdist)
├── docs/                           Sphinx documentation source
├── figures/                        README assets (workflow, choropleths, tables)
└── pyproject.toml

Citation

If you use this software in your research, please cite the accompanying paper (see CITATION.cff).

License

MIT License © 2026 The agent-urban-planning Authors

Acknowledgements

The Berlin replication is built on the Ahlfeldt, Redding, Sturm, Wolf (2015) "The Economics of Density: Evidence from the Berlin Wall" Econometrica 83(6) data and methodology. We are grateful for the authors' public release of the replication package; the data files in data/berlin/ and data/shapefiles/ derive from that release. See data/README.md for full attribution.

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.026 Apr 202628

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
mase-elab/agent-urban-planning

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 23:36 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:774741c71d7a77482fc469659dfa63fb67ad17290246941077d8f26dfffef676