taplite4mpo 0.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- taplite4mpo-0.2.0/LICENSE +21 -0
- taplite4mpo-0.2.0/MANIFEST.in +19 -0
- taplite4mpo-0.2.0/PKG-INFO +233 -0
- taplite4mpo-0.2.0/README.md +197 -0
- taplite4mpo-0.2.0/build.sh +23 -0
- taplite4mpo-0.2.0/docs/ARCHITECTURE.md +116 -0
- taplite4mpo-0.2.0/docs/GOLDEN_PATH_CHECKLIST.md +159 -0
- taplite4mpo-0.2.0/dtalite_qa/__init__.py +18 -0
- taplite4mpo-0.2.0/dtalite_qa/__main__.py +302 -0
- taplite4mpo-0.2.0/dtalite_qa/accessibility.py +187 -0
- taplite4mpo-0.2.0/dtalite_qa/adapt.py +173 -0
- taplite4mpo-0.2.0/dtalite_qa/agent_tools.py +132 -0
- taplite4mpo-0.2.0/dtalite_qa/calibrate.py +188 -0
- taplite4mpo-0.2.0/dtalite_qa/columns.py +303 -0
- taplite4mpo-0.2.0/dtalite_qa/control.py +115 -0
- taplite4mpo-0.2.0/dtalite_qa/convlog.py +91 -0
- taplite4mpo-0.2.0/dtalite_qa/csvio.py +44 -0
- taplite4mpo-0.2.0/dtalite_qa/demandbin.py +95 -0
- taplite4mpo-0.2.0/dtalite_qa/fill.py +113 -0
- taplite4mpo-0.2.0/dtalite_qa/forensics.py +310 -0
- taplite4mpo-0.2.0/dtalite_qa/guide.py +282 -0
- taplite4mpo-0.2.0/dtalite_qa/intake.py +376 -0
- taplite4mpo-0.2.0/dtalite_qa/inventory.py +79 -0
- taplite4mpo-0.2.0/dtalite_qa/lrs2gmns.py +157 -0
- taplite4mpo-0.2.0/dtalite_qa/mag_vdf.py +49 -0
- taplite4mpo-0.2.0/dtalite_qa/manifest.py +230 -0
- taplite4mpo-0.2.0/dtalite_qa/matrixio.py +190 -0
- taplite4mpo-0.2.0/dtalite_qa/multiperiod.py +116 -0
- taplite4mpo-0.2.0/dtalite_qa/net2gmns.py +298 -0
- taplite4mpo-0.2.0/dtalite_qa/nexta.py +243 -0
- taplite4mpo-0.2.0/dtalite_qa/plf.py +209 -0
- taplite4mpo-0.2.0/dtalite_qa/report.py +197 -0
- taplite4mpo-0.2.0/dtalite_qa/scenario.py +398 -0
- taplite4mpo-0.2.0/dtalite_qa/schema.py +106 -0
- taplite4mpo-0.2.0/dtalite_qa/skim.py +83 -0
- taplite4mpo-0.2.0/dtalite_qa/superzone.py +94 -0
- taplite4mpo-0.2.0/dtalite_qa/superzone_encoders.py +88 -0
- taplite4mpo-0.2.0/dtalite_qa/superzone_hier.py +185 -0
- taplite4mpo-0.2.0/dtalite_qa/templates/mpo_submission_template.yml +58 -0
- taplite4mpo-0.2.0/dtalite_qa/transcad_bin.py +128 -0
- taplite4mpo-0.2.0/dtalite_qa/validate.py +183 -0
- taplite4mpo-0.2.0/dtalite_qa/vizmap.py +119 -0
- taplite4mpo-0.2.0/dtalite_qa/workflow.py +511 -0
- taplite4mpo-0.2.0/kernel/CMakeLists.txt +44 -0
- taplite4mpo-0.2.0/kernel/python/CMakeLists.txt +32 -0
- taplite4mpo-0.2.0/kernel/python/binding.cpp +42 -0
- taplite4mpo-0.2.0/kernel/python/build_native.sh +29 -0
- taplite4mpo-0.2.0/kernel/python/build_shared.sh +28 -0
- taplite4mpo-0.2.0/kernel/src/TAPLite.cpp +8744 -0
- taplite4mpo-0.2.0/kernel/src/TAPLite.h +460 -0
- taplite4mpo-0.2.0/pyproject.toml +64 -0
- taplite4mpo-0.2.0/pytaplite/README.md +48 -0
- taplite4mpo-0.2.0/pytaplite/__init__.py +15 -0
- taplite4mpo-0.2.0/pytaplite/kernel.py +183 -0
- taplite4mpo-0.2.0/setup.cfg +4 -0
- taplite4mpo-0.2.0/setup.py +84 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/PKG-INFO +233 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/SOURCES.txt +60 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/dependency_links.txt +1 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/entry_points.txt +2 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/requires.txt +17 -0
- taplite4mpo-0.2.0/taplite4mpo.egg-info/top_level.txt +2 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Xuesong (Simon) Zhou and the DTALite/TAPLite contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Files needed to BUILD the package from an sdist (the C++ kernel source + binding).
|
|
2
|
+
include README.md LICENSE pyproject.toml setup.py
|
|
3
|
+
include kernel/src/TAPLite.cpp kernel/src/TAPLite.h
|
|
4
|
+
include kernel/python/binding.cpp kernel/python/CMakeLists.txt
|
|
5
|
+
include kernel/python/build_native.sh kernel/python/build_shared.sh
|
|
6
|
+
include kernel/CMakeLists.txt build.sh
|
|
7
|
+
recursive-include dtalite_qa *.yml
|
|
8
|
+
include docs/ARCHITECTURE.md docs/GOLDEN_PATH_CHECKLIST.md pytaplite/README.md
|
|
9
|
+
|
|
10
|
+
# Keep the sdist small — exclude the large example / benchmark / agency data.
|
|
11
|
+
prune examples
|
|
12
|
+
prune test_networks
|
|
13
|
+
prune kernel/data_sets
|
|
14
|
+
prune nvta_run
|
|
15
|
+
prune private
|
|
16
|
+
prune .github
|
|
17
|
+
global-exclude *.pyc
|
|
18
|
+
global-exclude __pycache__/*
|
|
19
|
+
global-exclude *.pyd *.so *.dll *.dylib *.egg-info
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: taplite4mpo
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Open C++ static traffic-assignment kernel (GMNS) for MPO/DOT models, with a Python QA/orchestration layer (dtalite_qa) and a kernel driver (pytaplite).
|
|
5
|
+
Author: ASU Trans-AI Lab
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/asu-trans-ai-lab/TAPLite4MPO
|
|
8
|
+
Project-URL: Repository, https://github.com/asu-trans-ai-lab/TAPLite4MPO
|
|
9
|
+
Project-URL: Documentation, https://github.com/asu-trans-ai-lab/TAPLite4MPO/blob/main/docs/ARCHITECTURE.md
|
|
10
|
+
Project-URL: Issues, https://github.com/asu-trans-ai-lab/TAPLite4MPO/issues
|
|
11
|
+
Keywords: traffic-assignment,transportation,user-equilibrium,frank-wolfe,gmns,dtalite,taplite,mpo,travel-demand-model,vdf,qvdf
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: C++
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Topic :: Scientific/Engineering
|
|
19
|
+
Requires-Python: >=3.8
|
|
20
|
+
Description-Content-Type: text/markdown
|
|
21
|
+
License-File: LICENSE
|
|
22
|
+
Provides-Extra: data
|
|
23
|
+
Requires-Dist: pandas; extra == "data"
|
|
24
|
+
Provides-Extra: science
|
|
25
|
+
Requires-Dist: numpy; extra == "science"
|
|
26
|
+
Requires-Dist: scipy; extra == "science"
|
|
27
|
+
Provides-Extra: gis
|
|
28
|
+
Requires-Dist: pyshp; extra == "gis"
|
|
29
|
+
Requires-Dist: pandas; extra == "gis"
|
|
30
|
+
Provides-Extra: all
|
|
31
|
+
Requires-Dist: pandas; extra == "all"
|
|
32
|
+
Requires-Dist: numpy; extra == "all"
|
|
33
|
+
Requires-Dist: scipy; extra == "all"
|
|
34
|
+
Requires-Dist: pyshp; extra == "all"
|
|
35
|
+
Dynamic: license-file
|
|
36
|
+
|
|
37
|
+
# TAPLite4MPO — open C++ static traffic assignment for MPOs
|
|
38
|
+
|
|
39
|
+
[](../../actions/workflows/ci.yml)
|
|
40
|
+
[](LICENSE)
|
|
41
|
+
|
|
42
|
+
A single-file, reproducible **C++ (CMake) static user-equilibrium traffic-assignment
|
|
43
|
+
kernel** (Frank–Wolfe) for GMNS networks — with the VDF library, generalized cost,
|
|
44
|
+
peak-load-factor, and solver options that **MPO/DOT static highway assignments** need —
|
|
45
|
+
plus a Python QA/automation package, open benchmark networks, and a two-volume user
|
|
46
|
+
guide. Built for teaching and for reproducing agency assignments (ARC, SERPM, TRPA,
|
|
47
|
+
MTC, SANDAG, MWCOG, VDOT, ODOT).
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
> The whole pipeline at a glance. Start with **[docs/GOLDEN_PATH_CHECKLIST.md](docs/GOLDEN_PATH_CHECKLIST.md)**.
|
|
52
|
+
> (Figure generated from `docs/IMAGE_PROMPTS.md`.)
|
|
53
|
+
|
|
54
|
+
> ### ⚙️ Which part solves the assignment?
|
|
55
|
+
> The **C++ kernel** (`bin/DTALite.exe`, `kernel/src/TAPLite.cpp`) is the **solver** —
|
|
56
|
+
> Frank–Wolfe equilibrium, the VDF library, OpenMP, the scale. The **`dtalite_qa` Python
|
|
57
|
+
> package is QA/orchestration only**: it validates inputs, builds scenarios, and *invokes* the
|
|
58
|
+
> kernel — **it does not compute the assignment.** So you **must build the kernel**
|
|
59
|
+
> (`bash build.sh`); running only Python assigns nothing. This is not a pure-Python solver.
|
|
60
|
+
> Full explanation, environment matrix, and how to call the kernel from Python:
|
|
61
|
+
> **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**.
|
|
62
|
+
|
|
63
|
+
**Features**
|
|
64
|
+
- Frank–Wolfe with an exact cost-based line search; **conjugate / bi-conjugate FW**
|
|
65
|
+
(`assignment_method`) for faster convergence on congested networks.
|
|
66
|
+
- **VDF library:** BPR, modified-BPR (linear term), conical (Spiess), QVDF (queue),
|
|
67
|
+
BPR2, INRETS, Akcelik, SANDAG signal-delay, SCAG piecewise-BPR, SCAG ramp-meter
|
|
68
|
+
(`vdf_type` 0–8).
|
|
69
|
+
- **QVDF congestion duration** — a D/C-consistent queue output (`P`, severe-congestion
|
|
70
|
+
duration, queue speeds), calibrated from corridor speeds by the **CBI sister project**.
|
|
71
|
+
- Multiclass: per-mode demand, **VOT**, **PCE**, occupancy, per-mode toll + distance
|
|
72
|
+
operating cost (generalized cost), `allowed_use` (HOV/truck/managed lanes).
|
|
73
|
+
- **Peak-Load-Factor / period-capacity** convention (`vdf_plf = φ/L`).
|
|
74
|
+
- Relative-gap stop (N consecutive iters), binary demand fast-load, OpenMP parallel.
|
|
75
|
+
|
|
76
|
+
> **Start with the flagship example → [`examples/arc_atlanta/`](examples/arc_atlanta/):**
|
|
77
|
+
> a complete end-to-end MPO run — reproduce the Atlanta Regional Commission's AM highway
|
|
78
|
+
> assignment and **validate it against ARC's own count benchmark** (region %RMSE 22 %,
|
|
79
|
+
> target ~38 %; re-baselined 2026-07 from 23 % after the Dijkstra-default and gap-metric
|
|
80
|
+
> kernel updates). It shows every MPO feature wired up, with a clean ARC-requirement →
|
|
81
|
+
> kernel-setting mapping. Background: [`docs/mpo_spec/`](docs/mpo_spec/) (the design spec
|
|
82
|
+
> + multi-agency survey).
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## 1. Build the kernel (the solver — required)
|
|
87
|
+
|
|
88
|
+
`bin/DTALite.exe` is the C++ engine that actually runs the assignment; the Python tools just
|
|
89
|
+
drive it. Build it first:
|
|
90
|
+
```bash
|
|
91
|
+
bash build.sh # -> bin/DTALite.exe (CMake + g++/MinGW, OpenMP, Release)
|
|
92
|
+
```
|
|
93
|
+
Requires CMake, a C++17 compiler (g++/clang/MSVC), and OpenMP. Output: `bin/DTALite.exe`.
|
|
94
|
+
(See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for why this is mandatory.)
|
|
95
|
+
|
|
96
|
+
### Install the Python packages
|
|
97
|
+
```bash
|
|
98
|
+
pip install . # installs dtalite_qa + pytaplite; compiles the in-process kernel binding
|
|
99
|
+
```
|
|
100
|
+
This builds `pytaplite._native` from the bundled kernel source (falls back to subprocess if no
|
|
101
|
+
compiler). Multi-platform PyPI wheels (`pip install taplite4mpo`) are produced by cibuildwheel
|
|
102
|
+
on a version tag — see **[RELEASE.md](RELEASE.md)**.
|
|
103
|
+
|
|
104
|
+
Then call the kernel from Python:
|
|
105
|
+
```python
|
|
106
|
+
import pytaplite
|
|
107
|
+
r = pytaplite.assign("kernel/data_sets/02_Sioux_Falls") # runs the C++ kernel
|
|
108
|
+
print(r.summary()) # links, VMT, VHT, returncode
|
|
109
|
+
```
|
|
110
|
+
Runnable demo: **[`examples/pytaplite_quickstart.py`](examples/pytaplite_quickstart.py)**
|
|
111
|
+
(`python examples/pytaplite_quickstart.py`).
|
|
112
|
+
|
|
113
|
+
## 2. Reproduce a run (open benchmark networks — no extra data needed)
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
cd kernel/data_sets/02_Sioux_Falls # or 03_chicago_sketch, 04_chicago_regional
|
|
117
|
+
cp ../../../bin/DTALite.exe .
|
|
118
|
+
./DTALite.exe # reads node/link/demand/settings, writes link_performance.csv
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Or via the Python QA wrapper (validates inputs first, then runs):
|
|
122
|
+
```bash
|
|
123
|
+
pip install -e .
|
|
124
|
+
python -m dtalite_qa run kernel/data_sets/02_Sioux_Falls --exe bin/DTALite.exe
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## 3. Regression / self-test
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
python test_networks/run_regression.py # builds & checks BPR/conic/QVDF, multimodal, turn restrictions
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 4. Documentation
|
|
136
|
+
- **[HANDOFF/](HANDOFF/)** — ⭐ **new engineer? start here.** The onboarding & handoff folder:
|
|
137
|
+
the ordered reading path, the runs to reproduce, the "which agency taught us this" issue
|
|
138
|
+
index, a **[BPR/VDF/PLF config-rules card](HANDOFF/BPR_AND_VDF_CONFIG_RULES.md)**, and a
|
|
139
|
+
**[hands-on lab](HANDOFF/REPRODUCE_THE_ISSUES.md)** that trips each classic conversion error
|
|
140
|
+
on the open networks so you learn to recognize it.
|
|
141
|
+
- **[docs/CONVERSION_ERRORS_CATALOG.md](docs/CONVERSION_ERRORS_CATALOG.md)** — the
|
|
142
|
+
**lessons-learned / error-source** reference: every way an MPO hand-off goes wrong
|
|
143
|
+
(capacity, PLF, units, demand, zones, VDF, truncation, allowed-use, count basis, build),
|
|
144
|
+
symptom → cause → fix → *which agency*.
|
|
145
|
+
- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — **the C++ kernel solves; the Python
|
|
146
|
+
package orchestrates.** Which part runs what, the environment matrix, and how to call the
|
|
147
|
+
kernel from Python. Read it if you're unsure what's doing the assignment.
|
|
148
|
+
- **[docs/GOLDEN_PATH_CHECKLIST.md](docs/GOLDEN_PATH_CHECKLIST.md)** — ⭐ **READ THIS FIRST.**
|
|
149
|
+
The Golden Path: from agency files to a trusted assignment, in 6 stages, framed by three
|
|
150
|
+
questions — *can I run? can I trust it? can I improve it?* Simple first, advanced later.
|
|
151
|
+
- **[docs/DATASET_LADDER.md](docs/DATASET_LADDER.md)** — which example to start with
|
|
152
|
+
(Chicago Sketch → Chicago Regional → ARC Atlanta → OSM quick start).
|
|
153
|
+
- **[docs/onboarding_guide.html](docs/onboarding_guide.html)** — **the visual onboarding guide**:
|
|
154
|
+
open in a browser for the staged journey (GIS field-map → declare → convert → intake →
|
|
155
|
+
quality → run → traceable workflow), each with its gate and a progress tracker. Generate
|
|
156
|
+
it anytime with `python -m dtalite_qa guide`.
|
|
157
|
+
- **[docs/MPO_ONBOARDING_GUIDE.md](docs/MPO_ONBOARDING_GUIDE.md)** — **start here for a new
|
|
158
|
+
agency model.** The process to turn a raw hand-off (shapefile + matrix + "alpha/beta")
|
|
159
|
+
into a trustworthy run: declare → convert → **intake audit** → resolve → validate. The
|
|
160
|
+
intake (`dtalite_qa intake`) never guesses a convention — it blocks on anything the MPO
|
|
161
|
+
didn't declare (capacity basis/period, PLF, units, trip kind) and produces an issue
|
|
162
|
+
report + conversion log + a guided HTML dashboard. The MPO fills
|
|
163
|
+
[`submission.yml`](dtalite_qa/templates/mpo_submission_template.yml) (the README for the
|
|
164
|
+
data; ARC's is in `examples/arc_atlanta/gmns/`).
|
|
165
|
+
- **[USER_GUIDE.md](USER_GUIDE.md)** — Volume 1: kernel reference (input schema, settings,
|
|
166
|
+
VDFs, outputs).
|
|
167
|
+
- **[USER_GUIDE_VOL2_MPO.md](USER_GUIDE_VOL2_MPO.md)** — Volume 2: static highway assignment
|
|
168
|
+
for MPOs (period capacity / PLF, generalized cost, convergence/solver, validation,
|
|
169
|
+
per-agency recipes).
|
|
170
|
+
- `examples/arc_atlanta/` — **complete worked MPO example** (ARC AM assignment, calibrate
|
|
171
|
+
→ run → validate vs the agency benchmark) with the ARC→kernel mapping.
|
|
172
|
+
- `docs/mpo_spec/` — design spec + **multi-agency survey/conformance** (ARC, SERPM, TRPA,
|
|
173
|
+
MTC, SANDAG, MWCOG, VDOT, ODOT): requirement → kernel feature → how to verify.
|
|
174
|
+
- `docs/qvdf_congestion_duration.md` — QVDF as the D/C-consistent congestion-**duration**
|
|
175
|
+
output, and the **CBI sister-project pipeline** (corridor speeds → QVDF params → kernel).
|
|
176
|
+
- `docs/` — methodology notes (peak load factor, super-zone aggregation, 4-step
|
|
177
|
+
integration, OD-compression operators).
|
|
178
|
+
- `docs/IMAGE_PROMPTS.md` — copy-paste prompts for GPT image tools to generate the
|
|
179
|
+
easy-to-follow figures (Golden Path, the 3 gates, super-zones, the skim advantage).
|
|
180
|
+
- `.claude/skills/taplite4mpo-pipeline/` — a Claude Code **skill** encoding the whole
|
|
181
|
+
pipeline (gates, stages, conventions, the ARC loop) for agent-assisted work in this repo.
|
|
182
|
+
- `dtalite_qa/` — Python package: `guide`, `intake`, `workflow`, `validate`, `fill`, `inventory`,
|
|
183
|
+
`accessibility`, `report`, `demand-bin`, `plf`, `adapt`, `run` (see `python -m dtalite_qa -h`).
|
|
184
|
+
- **[`pytaplite/`](pytaplite/)** — Python interface that **drives the C++ kernel**:
|
|
185
|
+
`pytaplite.assign(scenario)` → runs `DTALite.exe`, returns `link_performance` (subprocess, or
|
|
186
|
+
the in-process `_native` binding from [`kernel/python/`](kernel/python/) if built).
|
|
187
|
+
|
|
188
|
+
## 5. Folder map
|
|
189
|
+
```
|
|
190
|
+
TAPLite4MPO/
|
|
191
|
+
├── kernel/ C++ kernel (src/TAPLite.cpp, CMakeLists.txt) + open data_sets/
|
|
192
|
+
├── examples/
|
|
193
|
+
│ └── arc_atlanta/ complete end-to-end MPO example (ARC AM, validated)
|
|
194
|
+
├── dtalite_qa/ Python QA / control package
|
|
195
|
+
├── test_networks/ open test/benchmark networks + regression harness
|
|
196
|
+
├── schemas/ GMNS field schema (JSON)
|
|
197
|
+
├── docs/ methodology docs
|
|
198
|
+
│ └── mpo_spec/ design spec + multi-agency survey & conformance mapping
|
|
199
|
+
├── nvta_run/ NVTA run-configs + helper scripts (bring-your-own-data, §6)
|
|
200
|
+
├── USER_GUIDE.md Volume 1 (kernel)
|
|
201
|
+
├── USER_GUIDE_VOL2_MPO.md Volume 2 (MPOs)
|
|
202
|
+
└── build.sh
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
## 6. NVTA reproduction (bring-your-own-data)
|
|
206
|
+
|
|
207
|
+
The **NVTA dataset is agency-restricted and is NOT included** in this repository.
|
|
208
|
+
`nvta_run/` ships the run-configs and helper scripts (network prep, settings, conic/QVDF
|
|
209
|
+
staging). To run it, point the scripts at your own copy of the data:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
# option A: environment variable
|
|
213
|
+
export DTALITE_NVTA_INTERNAL=/path/to/nvta/_internal
|
|
214
|
+
# option B: nvta_run/local_config.json -> {"internal": "...", "subarea": "..."}
|
|
215
|
+
# option C: place the data in data/nvta_internal/
|
|
216
|
+
python nvta_run/run_nvta.py
|
|
217
|
+
```
|
|
218
|
+
If unconfigured, the runner prints a clear message. **All of §2–§3 reproduces fully
|
|
219
|
+
without it** using the open benchmark networks.
|
|
220
|
+
|
|
221
|
+
> Course note: instructors distribute the NVTA data to students through a separate
|
|
222
|
+
> channel (not this public repo); students set one of the options above.
|
|
223
|
+
|
|
224
|
+
---
|
|
225
|
+
|
|
226
|
+
## Continuous integration
|
|
227
|
+
`.github/workflows/ci.yml` builds the kernel (CMake + MSVC on `windows-latest`) and runs
|
|
228
|
+
the full regression suite on every push / pull request.
|
|
229
|
+
|
|
230
|
+
## License & citation
|
|
231
|
+
**MIT** — see `LICENSE`. If you use this kernel in research or coursework, please cite the
|
|
232
|
+
DTALite / TAPLite project. (Some `docs/` notes reference internal companion files that are
|
|
233
|
+
not part of this public release.)
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
# TAPLite4MPO — open C++ static traffic assignment for MPOs
|
|
2
|
+
|
|
3
|
+
[](../../actions/workflows/ci.yml)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
|
|
6
|
+
A single-file, reproducible **C++ (CMake) static user-equilibrium traffic-assignment
|
|
7
|
+
kernel** (Frank–Wolfe) for GMNS networks — with the VDF library, generalized cost,
|
|
8
|
+
peak-load-factor, and solver options that **MPO/DOT static highway assignments** need —
|
|
9
|
+
plus a Python QA/automation package, open benchmark networks, and a two-volume user
|
|
10
|
+
guide. Built for teaching and for reproducing agency assignments (ARC, SERPM, TRPA,
|
|
11
|
+
MTC, SANDAG, MWCOG, VDOT, ODOT).
|
|
12
|
+
|
|
13
|
+

|
|
14
|
+
|
|
15
|
+
> The whole pipeline at a glance. Start with **[docs/GOLDEN_PATH_CHECKLIST.md](docs/GOLDEN_PATH_CHECKLIST.md)**.
|
|
16
|
+
> (Figure generated from `docs/IMAGE_PROMPTS.md`.)
|
|
17
|
+
|
|
18
|
+
> ### ⚙️ Which part solves the assignment?
|
|
19
|
+
> The **C++ kernel** (`bin/DTALite.exe`, `kernel/src/TAPLite.cpp`) is the **solver** —
|
|
20
|
+
> Frank–Wolfe equilibrium, the VDF library, OpenMP, the scale. The **`dtalite_qa` Python
|
|
21
|
+
> package is QA/orchestration only**: it validates inputs, builds scenarios, and *invokes* the
|
|
22
|
+
> kernel — **it does not compute the assignment.** So you **must build the kernel**
|
|
23
|
+
> (`bash build.sh`); running only Python assigns nothing. This is not a pure-Python solver.
|
|
24
|
+
> Full explanation, environment matrix, and how to call the kernel from Python:
|
|
25
|
+
> **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)**.
|
|
26
|
+
|
|
27
|
+
**Features**
|
|
28
|
+
- Frank–Wolfe with an exact cost-based line search; **conjugate / bi-conjugate FW**
|
|
29
|
+
(`assignment_method`) for faster convergence on congested networks.
|
|
30
|
+
- **VDF library:** BPR, modified-BPR (linear term), conical (Spiess), QVDF (queue),
|
|
31
|
+
BPR2, INRETS, Akcelik, SANDAG signal-delay, SCAG piecewise-BPR, SCAG ramp-meter
|
|
32
|
+
(`vdf_type` 0–8).
|
|
33
|
+
- **QVDF congestion duration** — a D/C-consistent queue output (`P`, severe-congestion
|
|
34
|
+
duration, queue speeds), calibrated from corridor speeds by the **CBI sister project**.
|
|
35
|
+
- Multiclass: per-mode demand, **VOT**, **PCE**, occupancy, per-mode toll + distance
|
|
36
|
+
operating cost (generalized cost), `allowed_use` (HOV/truck/managed lanes).
|
|
37
|
+
- **Peak-Load-Factor / period-capacity** convention (`vdf_plf = φ/L`).
|
|
38
|
+
- Relative-gap stop (N consecutive iters), binary demand fast-load, OpenMP parallel.
|
|
39
|
+
|
|
40
|
+
> **Start with the flagship example → [`examples/arc_atlanta/`](examples/arc_atlanta/):**
|
|
41
|
+
> a complete end-to-end MPO run — reproduce the Atlanta Regional Commission's AM highway
|
|
42
|
+
> assignment and **validate it against ARC's own count benchmark** (region %RMSE 22 %,
|
|
43
|
+
> target ~38 %; re-baselined 2026-07 from 23 % after the Dijkstra-default and gap-metric
|
|
44
|
+
> kernel updates). It shows every MPO feature wired up, with a clean ARC-requirement →
|
|
45
|
+
> kernel-setting mapping. Background: [`docs/mpo_spec/`](docs/mpo_spec/) (the design spec
|
|
46
|
+
> + multi-agency survey).
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 1. Build the kernel (the solver — required)
|
|
51
|
+
|
|
52
|
+
`bin/DTALite.exe` is the C++ engine that actually runs the assignment; the Python tools just
|
|
53
|
+
drive it. Build it first:
|
|
54
|
+
```bash
|
|
55
|
+
bash build.sh # -> bin/DTALite.exe (CMake + g++/MinGW, OpenMP, Release)
|
|
56
|
+
```
|
|
57
|
+
Requires CMake, a C++17 compiler (g++/clang/MSVC), and OpenMP. Output: `bin/DTALite.exe`.
|
|
58
|
+
(See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for why this is mandatory.)
|
|
59
|
+
|
|
60
|
+
### Install the Python packages
|
|
61
|
+
```bash
|
|
62
|
+
pip install . # installs dtalite_qa + pytaplite; compiles the in-process kernel binding
|
|
63
|
+
```
|
|
64
|
+
This builds `pytaplite._native` from the bundled kernel source (falls back to subprocess if no
|
|
65
|
+
compiler). Multi-platform PyPI wheels (`pip install taplite4mpo`) are produced by cibuildwheel
|
|
66
|
+
on a version tag — see **[RELEASE.md](RELEASE.md)**.
|
|
67
|
+
|
|
68
|
+
Then call the kernel from Python:
|
|
69
|
+
```python
|
|
70
|
+
import pytaplite
|
|
71
|
+
r = pytaplite.assign("kernel/data_sets/02_Sioux_Falls") # runs the C++ kernel
|
|
72
|
+
print(r.summary()) # links, VMT, VHT, returncode
|
|
73
|
+
```
|
|
74
|
+
Runnable demo: **[`examples/pytaplite_quickstart.py`](examples/pytaplite_quickstart.py)**
|
|
75
|
+
(`python examples/pytaplite_quickstart.py`).
|
|
76
|
+
|
|
77
|
+
## 2. Reproduce a run (open benchmark networks — no extra data needed)
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
cd kernel/data_sets/02_Sioux_Falls # or 03_chicago_sketch, 04_chicago_regional
|
|
81
|
+
cp ../../../bin/DTALite.exe .
|
|
82
|
+
./DTALite.exe # reads node/link/demand/settings, writes link_performance.csv
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Or via the Python QA wrapper (validates inputs first, then runs):
|
|
86
|
+
```bash
|
|
87
|
+
pip install -e .
|
|
88
|
+
python -m dtalite_qa run kernel/data_sets/02_Sioux_Falls --exe bin/DTALite.exe
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## 3. Regression / self-test
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
python test_networks/run_regression.py # builds & checks BPR/conic/QVDF, multimodal, turn restrictions
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 4. Documentation
|
|
100
|
+
- **[HANDOFF/](HANDOFF/)** — ⭐ **new engineer? start here.** The onboarding & handoff folder:
|
|
101
|
+
the ordered reading path, the runs to reproduce, the "which agency taught us this" issue
|
|
102
|
+
index, a **[BPR/VDF/PLF config-rules card](HANDOFF/BPR_AND_VDF_CONFIG_RULES.md)**, and a
|
|
103
|
+
**[hands-on lab](HANDOFF/REPRODUCE_THE_ISSUES.md)** that trips each classic conversion error
|
|
104
|
+
on the open networks so you learn to recognize it.
|
|
105
|
+
- **[docs/CONVERSION_ERRORS_CATALOG.md](docs/CONVERSION_ERRORS_CATALOG.md)** — the
|
|
106
|
+
**lessons-learned / error-source** reference: every way an MPO hand-off goes wrong
|
|
107
|
+
(capacity, PLF, units, demand, zones, VDF, truncation, allowed-use, count basis, build),
|
|
108
|
+
symptom → cause → fix → *which agency*.
|
|
109
|
+
- **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** — **the C++ kernel solves; the Python
|
|
110
|
+
package orchestrates.** Which part runs what, the environment matrix, and how to call the
|
|
111
|
+
kernel from Python. Read it if you're unsure what's doing the assignment.
|
|
112
|
+
- **[docs/GOLDEN_PATH_CHECKLIST.md](docs/GOLDEN_PATH_CHECKLIST.md)** — ⭐ **READ THIS FIRST.**
|
|
113
|
+
The Golden Path: from agency files to a trusted assignment, in 6 stages, framed by three
|
|
114
|
+
questions — *can I run? can I trust it? can I improve it?* Simple first, advanced later.
|
|
115
|
+
- **[docs/DATASET_LADDER.md](docs/DATASET_LADDER.md)** — which example to start with
|
|
116
|
+
(Chicago Sketch → Chicago Regional → ARC Atlanta → OSM quick start).
|
|
117
|
+
- **[docs/onboarding_guide.html](docs/onboarding_guide.html)** — **the visual onboarding guide**:
|
|
118
|
+
open in a browser for the staged journey (GIS field-map → declare → convert → intake →
|
|
119
|
+
quality → run → traceable workflow), each with its gate and a progress tracker. Generate
|
|
120
|
+
it anytime with `python -m dtalite_qa guide`.
|
|
121
|
+
- **[docs/MPO_ONBOARDING_GUIDE.md](docs/MPO_ONBOARDING_GUIDE.md)** — **start here for a new
|
|
122
|
+
agency model.** The process to turn a raw hand-off (shapefile + matrix + "alpha/beta")
|
|
123
|
+
into a trustworthy run: declare → convert → **intake audit** → resolve → validate. The
|
|
124
|
+
intake (`dtalite_qa intake`) never guesses a convention — it blocks on anything the MPO
|
|
125
|
+
didn't declare (capacity basis/period, PLF, units, trip kind) and produces an issue
|
|
126
|
+
report + conversion log + a guided HTML dashboard. The MPO fills
|
|
127
|
+
[`submission.yml`](dtalite_qa/templates/mpo_submission_template.yml) (the README for the
|
|
128
|
+
data; ARC's is in `examples/arc_atlanta/gmns/`).
|
|
129
|
+
- **[USER_GUIDE.md](USER_GUIDE.md)** — Volume 1: kernel reference (input schema, settings,
|
|
130
|
+
VDFs, outputs).
|
|
131
|
+
- **[USER_GUIDE_VOL2_MPO.md](USER_GUIDE_VOL2_MPO.md)** — Volume 2: static highway assignment
|
|
132
|
+
for MPOs (period capacity / PLF, generalized cost, convergence/solver, validation,
|
|
133
|
+
per-agency recipes).
|
|
134
|
+
- `examples/arc_atlanta/` — **complete worked MPO example** (ARC AM assignment, calibrate
|
|
135
|
+
→ run → validate vs the agency benchmark) with the ARC→kernel mapping.
|
|
136
|
+
- `docs/mpo_spec/` — design spec + **multi-agency survey/conformance** (ARC, SERPM, TRPA,
|
|
137
|
+
MTC, SANDAG, MWCOG, VDOT, ODOT): requirement → kernel feature → how to verify.
|
|
138
|
+
- `docs/qvdf_congestion_duration.md` — QVDF as the D/C-consistent congestion-**duration**
|
|
139
|
+
output, and the **CBI sister-project pipeline** (corridor speeds → QVDF params → kernel).
|
|
140
|
+
- `docs/` — methodology notes (peak load factor, super-zone aggregation, 4-step
|
|
141
|
+
integration, OD-compression operators).
|
|
142
|
+
- `docs/IMAGE_PROMPTS.md` — copy-paste prompts for GPT image tools to generate the
|
|
143
|
+
easy-to-follow figures (Golden Path, the 3 gates, super-zones, the skim advantage).
|
|
144
|
+
- `.claude/skills/taplite4mpo-pipeline/` — a Claude Code **skill** encoding the whole
|
|
145
|
+
pipeline (gates, stages, conventions, the ARC loop) for agent-assisted work in this repo.
|
|
146
|
+
- `dtalite_qa/` — Python package: `guide`, `intake`, `workflow`, `validate`, `fill`, `inventory`,
|
|
147
|
+
`accessibility`, `report`, `demand-bin`, `plf`, `adapt`, `run` (see `python -m dtalite_qa -h`).
|
|
148
|
+
- **[`pytaplite/`](pytaplite/)** — Python interface that **drives the C++ kernel**:
|
|
149
|
+
`pytaplite.assign(scenario)` → runs `DTALite.exe`, returns `link_performance` (subprocess, or
|
|
150
|
+
the in-process `_native` binding from [`kernel/python/`](kernel/python/) if built).
|
|
151
|
+
|
|
152
|
+
## 5. Folder map
|
|
153
|
+
```
|
|
154
|
+
TAPLite4MPO/
|
|
155
|
+
├── kernel/ C++ kernel (src/TAPLite.cpp, CMakeLists.txt) + open data_sets/
|
|
156
|
+
├── examples/
|
|
157
|
+
│ └── arc_atlanta/ complete end-to-end MPO example (ARC AM, validated)
|
|
158
|
+
├── dtalite_qa/ Python QA / control package
|
|
159
|
+
├── test_networks/ open test/benchmark networks + regression harness
|
|
160
|
+
├── schemas/ GMNS field schema (JSON)
|
|
161
|
+
├── docs/ methodology docs
|
|
162
|
+
│ └── mpo_spec/ design spec + multi-agency survey & conformance mapping
|
|
163
|
+
├── nvta_run/ NVTA run-configs + helper scripts (bring-your-own-data, §6)
|
|
164
|
+
├── USER_GUIDE.md Volume 1 (kernel)
|
|
165
|
+
├── USER_GUIDE_VOL2_MPO.md Volume 2 (MPOs)
|
|
166
|
+
└── build.sh
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 6. NVTA reproduction (bring-your-own-data)
|
|
170
|
+
|
|
171
|
+
The **NVTA dataset is agency-restricted and is NOT included** in this repository.
|
|
172
|
+
`nvta_run/` ships the run-configs and helper scripts (network prep, settings, conic/QVDF
|
|
173
|
+
staging). To run it, point the scripts at your own copy of the data:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# option A: environment variable
|
|
177
|
+
export DTALITE_NVTA_INTERNAL=/path/to/nvta/_internal
|
|
178
|
+
# option B: nvta_run/local_config.json -> {"internal": "...", "subarea": "..."}
|
|
179
|
+
# option C: place the data in data/nvta_internal/
|
|
180
|
+
python nvta_run/run_nvta.py
|
|
181
|
+
```
|
|
182
|
+
If unconfigured, the runner prints a clear message. **All of §2–§3 reproduces fully
|
|
183
|
+
without it** using the open benchmark networks.
|
|
184
|
+
|
|
185
|
+
> Course note: instructors distribute the NVTA data to students through a separate
|
|
186
|
+
> channel (not this public repo); students set one of the options above.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
## Continuous integration
|
|
191
|
+
`.github/workflows/ci.yml` builds the kernel (CMake + MSVC on `windows-latest`) and runs
|
|
192
|
+
the full regression suite on every push / pull request.
|
|
193
|
+
|
|
194
|
+
## License & citation
|
|
195
|
+
**MIT** — see `LICENSE`. If you use this kernel in research or coursework, please cite the
|
|
196
|
+
DTALite / TAPLite project. (Some `docs/` notes reference internal companion files that are
|
|
197
|
+
not part of this public release.)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Canonical build for the consolidated DTALite/TAPLite C++ kernel.
|
|
3
|
+
# Self-contained: builds kernel/src/TAPLite.cpp -> bin/DTALite.exe via CMake.
|
|
4
|
+
#
|
|
5
|
+
# Output: a stripped Release standalone executable (App-Control-clean, ~1.5 MB).
|
|
6
|
+
# For gdb source debugging, turn OFF Windows Smart App Control, then build with
|
|
7
|
+
# -DCMAKE_BUILD_TYPE=RelWithDebInfo (larger binary, App Control may block it).
|
|
8
|
+
set -e
|
|
9
|
+
export PATH="/c/Users/xzhou/AppData/Local/Microsoft/WinGet/Packages/BrechtSanders.WinLibs.POSIX.UCRT_Microsoft.Winget.Source_8wekyb3d8bbwe/mingw64/bin:$PATH"
|
|
10
|
+
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
11
|
+
SRC="$HERE/kernel"
|
|
12
|
+
BUILD="$HERE/cmake_build_rel"
|
|
13
|
+
mkdir -p "$HERE/bin"
|
|
14
|
+
echo "[build] configure (Release, stripped, exe target)"
|
|
15
|
+
cmake -S "$SRC" -B "$BUILD" -G Ninja \
|
|
16
|
+
-DCMAKE_CXX_COMPILER=x86_64-w64-mingw32-g++.exe \
|
|
17
|
+
-DCMAKE_BUILD_TYPE=Release \
|
|
18
|
+
-DCMAKE_CXX_FLAGS="-fopenmp -O2 -DNDEBUG" \
|
|
19
|
+
-DCMAKE_EXE_LINKER_FLAGS="-s" >/dev/null
|
|
20
|
+
echo "[build] build DTALite_exe"
|
|
21
|
+
cmake --build "$BUILD" --target DTALite_exe
|
|
22
|
+
cp "$BUILD/DTALite_exe.exe" "$HERE/bin/DTALite.exe"
|
|
23
|
+
echo "[build] kernel -> $HERE/bin/DTALite.exe ($(stat -c%s "$HERE/bin/DTALite.exe") bytes)"
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# Architecture — what actually solves the assignment
|
|
2
|
+
|
|
3
|
+
**Read this if you're unsure which part does the work.** TAPLite4MPO is **two layers**, and it
|
|
4
|
+
matters which one you're using:
|
|
5
|
+
|
|
6
|
+
```
|
|
7
|
+
┌──────────────────────────────────────────────────────────────────┐
|
|
8
|
+
│ dtalite_qa (Python package) — QA / orchestration ONLY │
|
|
9
|
+
│ validates inputs · fills defaults · intake audit · builds │
|
|
10
|
+
│ scenarios · runs the R1-R6 workflow · super-zones · skims │
|
|
11
|
+
│ >>> it does NOT solve the assignment <<< │
|
|
12
|
+
└───────────────────────────────┬──────────────────────────────────┘
|
|
13
|
+
│ prepares CSVs, then invokes ↓ (subprocess)
|
|
14
|
+
┌───────────────────────────────▼──────────────────────────────────┐
|
|
15
|
+
│ THE KERNEL (C++17, bin/DTALite.exe) — the SOLVER / engine │
|
|
16
|
+
│ reads node/link/demand/settings CSV → Frank-Wolfe / conjugate / │
|
|
17
|
+
│ bi-conjugate user equilibrium (OpenMP, scalable) → writes │
|
|
18
|
+
│ link_performance.csv (volumes, V/C, speed, VMT/VHT, QVDF) │
|
|
19
|
+
└──────────────────────────────────────────────────────────────────┘
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**The C++ kernel is the engine.** All assignment math, the VDF library, the line search, the
|
|
23
|
+
parallelism, and the scale live in `kernel/src/TAPLite.cpp`. The Python package is a
|
|
24
|
+
*controller*: it never computes an equilibrium — it prepares the inputs the kernel reads and
|
|
25
|
+
then **shells out to `DTALite.exe`** (`dtalite_qa/control.py` → `subprocess.run`). If you run
|
|
26
|
+
only Python and never build the kernel, **nothing is assigned.** This is also why
|
|
27
|
+
`python -m dtalite_qa run` **requires `--exe`**, and why it now fails loudly with a pointer
|
|
28
|
+
here if the kernel binary is missing.
|
|
29
|
+
|
|
30
|
+
> Not the same as a pure-Python solver. Some traffic-assignment tools are entirely Python; this
|
|
31
|
+
> one is not. Python is the convenience/QA layer; the **C++ kernel does the assignment** and is
|
|
32
|
+
> what makes it scalable to a 145k-link / 6k-zone network in minutes.
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Two ways to run — and which environment each needs
|
|
37
|
+
|
|
38
|
+
| Path | What runs | You need |
|
|
39
|
+
|---|---|---|
|
|
40
|
+
| **A. Kernel directly** | the C++ solver only | a built `DTALite.exe`; nothing else |
|
|
41
|
+
| **B. Python-orchestrated** (recommended) | Python validates/builds, then calls the kernel | Python 3.8+ **and** a built `DTALite.exe` |
|
|
42
|
+
|
|
43
|
+
**A — run the kernel directly** (no Python at all):
|
|
44
|
+
```bash
|
|
45
|
+
cd kernel/data_sets/03_chicago_sketch
|
|
46
|
+
cp ../../../bin/DTALite.exe .
|
|
47
|
+
./DTALite.exe # reads the CSVs here, writes link_performance.csv
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**B — Python orchestrates the kernel** (QA gate first, then the same kernel):
|
|
51
|
+
```bash
|
|
52
|
+
pip install -e .
|
|
53
|
+
python -m dtalite_qa run <scenario> --exe bin/DTALite.exe
|
|
54
|
+
# = validate inputs → fill defaults → invoke DTALite.exe → check outputs
|
|
55
|
+
```
|
|
56
|
+
Either way **the C++ kernel does the assignment.** Path B just wraps it with validation and
|
|
57
|
+
reporting.
|
|
58
|
+
|
|
59
|
+
## Environment requirements
|
|
60
|
+
|
|
61
|
+
| To do this | You need |
|
|
62
|
+
|---|---|
|
|
63
|
+
| **Build the kernel** (once) | a C++17 compiler (g++/clang/MSVC) + CMake + OpenMP — `bash build.sh` → `bin/DTALite.exe` |
|
|
64
|
+
| Run the kernel | the built `DTALite.exe` (Windows/Linux/macOS); no runtime deps |
|
|
65
|
+
| Use `dtalite_qa` (intake/check/run/workflow/guide) | Python 3.8+ (standard library only) |
|
|
66
|
+
| Drive the kernel from Python (`pytaplite`) | Python 3.8+ (+ `pandas` for `to_pandas`) + a built `DTALite.exe` |
|
|
67
|
+
| Build the **native in-process binding** (optional) | `pybind11` + the C++ toolchain — `bash kernel/python/build_native.sh` |
|
|
68
|
+
| Super-zone encoders / skim recovery | Python + `numpy`, `scipy` (and `scikit-learn` for `demand_kmeans`) |
|
|
69
|
+
| Read agency shapefiles in the example converters | `pyshp` / `pyogrio` / `pandas` (provenance scripts only) |
|
|
70
|
+
|
|
71
|
+
CI (`.github/workflows/ci.yml`) builds the kernel with MSVC on `windows-latest` and runs the
|
|
72
|
+
regression — proof the C++ layer is the thing under test.
|
|
73
|
+
|
|
74
|
+
## Calling the C++ kernel from Python — two ways, both shipped
|
|
75
|
+
|
|
76
|
+
**1. `pytaplite` — the clean Python interface (recommended).**
|
|
77
|
+
```python
|
|
78
|
+
import pytaplite
|
|
79
|
+
r = pytaplite.assign("examples/arc_atlanta/gmns_calibrated") # runs the C++ kernel
|
|
80
|
+
print(r.summary()) # {'links': ..., 'total_VMT': ..., 'returncode': 0}
|
|
81
|
+
df = r.to_pandas() # link_performance as a DataFrame
|
|
82
|
+
```
|
|
83
|
+
It locates the binary, runs the assignment, and loads `link_performance.csv` back. It picks
|
|
84
|
+
the fastest of three execution paths automatically (all call the same C++ kernel):
|
|
85
|
+
|
|
86
|
+
**2. ctypes shared library — the Path4GMNS / DTALite pattern (in-process, no pybind11).**
|
|
87
|
+
The kernel exports the C-ABI symbols `DTA_AssignmentAPI()` / `DTA_SimulationAPI()`
|
|
88
|
+
(`extern "C"` in `kernel/src/TAPLite.h`), so it builds as a shared library that Python loads
|
|
89
|
+
with stdlib **`ctypes`** — exactly how [Path4GMNS](https://github.com/jdlph/Path4GMNS) ships
|
|
90
|
+
the `DTALite` engine:
|
|
91
|
+
```bash
|
|
92
|
+
bash kernel/python/build_shared.sh # -> pytaplite/DTALite.dll | libDTALite.so | libDTALite.dylib
|
|
93
|
+
```
|
|
94
|
+
`pytaplite.assign(...)` then loads it and calls `DTA_AssignmentAPI()` **in-process**. (CMake's
|
|
95
|
+
`add_library(DTALite SHARED ...)` target builds the same library.)
|
|
96
|
+
|
|
97
|
+
**3. pybind11 binding — `pytaplite._native` (alternative in-process; releases the GIL).**
|
|
98
|
+
`pip install pybind11 && bash kernel/python/build_native.sh`.
|
|
99
|
+
|
|
100
|
+
**Caveat (both in-process paths):** the kernel keeps global state, so run **one assignment
|
|
101
|
+
per process**; for many runs use a fresh `work_dir` per call, `multiprocessing`, or
|
|
102
|
+
`prefer_inproc=False` to use the subprocess path. The shared lib / native module are optional
|
|
103
|
+
and git-ignored; **subprocess works with no library build.**
|
|
104
|
+
|
|
105
|
+
Lowest level — just launch the binary yourself (any language can):
|
|
106
|
+
```python
|
|
107
|
+
import subprocess
|
|
108
|
+
subprocess.run(["bin/DTALite.exe"], cwd="my_scenario") # the solver, in that folder
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
The kernel is a **self-contained binary**, deliberately: it stays fast and dependency-free,
|
|
112
|
+
|
|
113
|
+
## Where each part lives
|
|
114
|
+
- `kernel/src/TAPLite.cpp`, `kernel/CMakeLists.txt`, `build.sh` — **the solver**.
|
|
115
|
+
- `dtalite_qa/` — the Python controller (`control.py` is where it invokes the kernel).
|
|
116
|
+
- `examples/`, `test_networks/`, `kernel/data_sets/` — inputs the kernel reads.
|