Spaces:
Running
Running
File size: 2,529 Bytes
a58f1b7 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 |
# modules/trip_generation.py
# TripAI – Trip Generation Model
from __future__ import annotations
import pandas as pd
import numpy as np
PURPOSES = ["HBW", "HBE", "HBS"]
def trip_generation(taz: pd.DataFrame) -> tuple[pd.DataFrame, pd.DataFrame]:
"""
Compute trip productions and attractions for each TAZ for three purposes:
- HBW: Home–Based Work
- HBE: Home–Based Education
- HBS: Home–Based Shopping/Other
The functional forms are deliberately simple but grounded in standard
trip-rate logic and can be modified for calibration.
Parameters
----------
taz : pd.DataFrame
TAZ-level attributes with at least the following columns:
['households', 'workers', 'students', 'cars',
'service_jobs', 'industrial_jobs', 'retail_jobs',
'school_capacity', 'retail_floor_area'].
Returns
-------
productions : pd.DataFrame
Index = TAZ, columns = ['HBW', 'HBE', 'HBS'].
attractions : pd.DataFrame
Index = TAZ, columns = ['HBW', 'HBE', 'HBS'], balanced so that
sum(P) = sum(A) for each purpose.
"""
df = taz.copy()
# ------------------------------------------------
# PRODUCTIONS (simple rate-based formulations)
# ------------------------------------------------
# HBW: mainly driven by workers and car availability
P_HBW = 0.8 * df["workers"] + 0.2 * df["cars"]
# HBE: driven by students
P_HBE = 1.2 * df["students"]
# HBS: driven by households (shopping, other)
P_HBS = 0.4 * df["households"]
productions = pd.DataFrame(
{"HBW": P_HBW, "HBE": P_HBE, "HBS": P_HBS},
index=df.index,
)
# ------------------------------------------------
# ATTRACTIONS (jobs, schools, retail)
# ------------------------------------------------
A_HBW = 0.7 * df["service_jobs"] + 0.3 * df["industrial_jobs"]
A_HBE = 1.5 * df["school_capacity"]
A_HBS = 1.3 * df["retail_floor_area"]
attractions = pd.DataFrame(
{"HBW": A_HBW, "HBE": A_HBE, "HBS": A_HBS},
index=df.index,
)
# ------------------------------------------------
# SIMPLE BALANCING (one-step scaling)
# ------------------------------------------------
for p in PURPOSES:
total_P = productions[p].sum()
total_A = attractions[p].sum()
if total_A > 0:
attractions[p] *= total_P / total_A
return productions, attractions
|