gmnsopt 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.
- gmnsopt-0.2.0/LICENSE +21 -0
- gmnsopt-0.2.0/PKG-INFO +149 -0
- gmnsopt-0.2.0/README.md +119 -0
- gmnsopt-0.2.0/pyproject.toml +36 -0
- gmnsopt-0.2.0/setup.cfg +4 -0
- gmnsopt-0.2.0/src/gmns_opt/__init__.py +17 -0
- gmnsopt-0.2.0/src/gmns_opt/applications/__init__.py +27 -0
- gmnsopt-0.2.0/src/gmns_opt/benchmark/__init__.py +4 -0
- gmnsopt-0.2.0/src/gmns_opt/benchmark/case.py +84 -0
- gmnsopt-0.2.0/src/gmns_opt/benchmark/registry.py +129 -0
- gmnsopt-0.2.0/src/gmns_opt/benchmark/report.py +44 -0
- gmnsopt-0.2.0/src/gmns_opt/cli.py +86 -0
- gmnsopt-0.2.0/src/gmns_opt/io/__init__.py +6 -0
- gmnsopt-0.2.0/src/gmns_opt/io/build_graph.py +36 -0
- gmnsopt-0.2.0/src/gmns_opt/io/read_gmns.py +88 -0
- gmnsopt-0.2.0/src/gmns_opt/io/validate_gmns.py +33 -0
- gmnsopt-0.2.0/src/gmns_opt/ml/__init__.py +8 -0
- gmnsopt-0.2.0/src/gmns_opt/ml/branching_dataset.py +29 -0
- gmnsopt-0.2.0/src/gmns_opt/ml/features.py +39 -0
- gmnsopt-0.2.0/src/gmns_opt/ml/warm_start.py +30 -0
- gmnsopt-0.2.0/src/gmns_opt/models/__init__.py +31 -0
- gmnsopt-0.2.0/src/gmns_opt/models/accessibility.py +43 -0
- gmnsopt-0.2.0/src/gmns_opt/models/facility_location.py +73 -0
- gmnsopt-0.2.0/src/gmns_opt/models/max_flow.py +36 -0
- gmnsopt-0.2.0/src/gmns_opt/models/min_cost_flow.py +46 -0
- gmnsopt-0.2.0/src/gmns_opt/models/multimodal_skeleton.py +40 -0
- gmnsopt-0.2.0/src/gmns_opt/models/network_design.py +66 -0
- gmnsopt-0.2.0/src/gmns_opt/models/odme.py +86 -0
- gmnsopt-0.2.0/src/gmns_opt/models/resilience.py +61 -0
- gmnsopt-0.2.0/src/gmns_opt/models/shortest_path.py +32 -0
- gmnsopt-0.2.0/src/gmns_opt/models/signal_timing.py +45 -0
- gmnsopt-0.2.0/src/gmns_opt/models/system_optimal.py +79 -0
- gmnsopt-0.2.0/src/gmns_opt/models/traffic_assignment.py +95 -0
- gmnsopt-0.2.0/src/gmns_opt/scenarios/__init__.py +3 -0
- gmnsopt-0.2.0/src/gmns_opt/scenarios/generator.py +50 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/__init__.py +19 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/base.py +20 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/commercial_placeholder.py +15 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/networkx_solver.py +13 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/neural_placeholder.py +15 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/ortools_adapter.py +13 -0
- gmnsopt-0.2.0/src/gmns_opt/solvers/scipy_highs.py +14 -0
- gmnsopt-0.2.0/src/gmns_opt/tensor/__init__.py +12 -0
- gmnsopt-0.2.0/src/gmns_opt/tensor/control_tensor.py +12 -0
- gmnsopt-0.2.0/src/gmns_opt/tensor/demand_tensor.py +44 -0
- gmnsopt-0.2.0/src/gmns_opt/tensor/scenario_tensor.py +37 -0
- gmnsopt-0.2.0/src/gmns_opt/tensor/schema.py +71 -0
- gmnsopt-0.2.0/src/gmns_opt/visualization/__init__.py +3 -0
- gmnsopt-0.2.0/src/gmns_opt/visualization/export_optimization_layers.py +54 -0
- gmnsopt-0.2.0/src/gmns_opt/viz/__init__.py +5 -0
- gmnsopt-0.2.0/src/gmns_opt/viz/export.py +27 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/PKG-INFO +149 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/SOURCES.txt +57 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/dependency_links.txt +1 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/entry_points.txt +2 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/requires.txt +16 -0
- gmnsopt-0.2.0/src/gmnsopt.egg-info/top_level.txt +1 -0
- gmnsopt-0.2.0/tests/test_gmns_opt.py +86 -0
- gmnsopt-0.2.0/tests/test_scaffold.py +85 -0
gmnsopt-0.2.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 gmnsopt 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.
|
gmnsopt-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: gmnsopt
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: GMNS-native transportation optimization testbed: reproducible, visual, data-grounded, progressively harder benchmark cases (shortest path -> assignment -> ODME -> signal -> resilience) for open-source & commercial solvers, ML-for-optimization, and RL/control.
|
|
5
|
+
Author: gmnsopt contributors
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Source, https://github.com/asu-trans-ai-lab/gmnsopt
|
|
8
|
+
Keywords: GMNS,transportation,optimization,traffic-assignment,ODME,benchmark,operations-research,networkx,HiGHS
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Requires-Python: >=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: numpy>=1.21
|
|
17
|
+
Requires-Dist: scipy>=1.7
|
|
18
|
+
Requires-Dist: networkx>=2.6
|
|
19
|
+
Requires-Dist: PyYAML>=5.4
|
|
20
|
+
Provides-Extra: viz
|
|
21
|
+
Requires-Dist: pandas>=1.3; extra == "viz"
|
|
22
|
+
Requires-Dist: matplotlib>=3.4; extra == "viz"
|
|
23
|
+
Provides-Extra: solvers
|
|
24
|
+
Requires-Dist: pyomo>=6.0; extra == "solvers"
|
|
25
|
+
Requires-Dist: highspy>=1.5; extra == "solvers"
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.1; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# gmnsopt
|
|
32
|
+
|
|
33
|
+
[](https://github.com/asu-trans-ai-lab/gmnsopt/actions/workflows/ci.yml)
|
|
34
|
+
[](https://pypi.org/project/gmnsopt/)
|
|
35
|
+
[](https://pypi.org/project/gmnsopt/)
|
|
36
|
+
[](LICENSE)
|
|
37
|
+
|
|
38
|
+
**A GMNS-native transportation optimization testbed** — reproducible, visual, data-grounded, and
|
|
39
|
+
progressively harder. It turns standardized [GMNS](https://github.com/zephyr-data-specs/GMNS) networks +
|
|
40
|
+
demand + operations data into mathematical-programming and network-optimization cases:
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
GMNS network + demand + operations data
|
|
44
|
+
→ optimization model template
|
|
45
|
+
→ solver / algorithm
|
|
46
|
+
→ (dynamic simulation check)
|
|
47
|
+
→ GUI4GMNS visualization
|
|
48
|
+
→ reproducible benchmark report
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
> **gmnsopt turns GMNS from a network data standard into a transportation optimization testbed
|
|
52
|
+
> for planning, operations, control, pricing, resilience, and multimodal decision-making** — where
|
|
53
|
+
> open-source solvers, commercial solvers, ML-for-optimization, and RL/control methods can all be tested on
|
|
54
|
+
> realistic, dynamic, stochastic, visually explainable mobility problems.
|
|
55
|
+
|
|
56
|
+
## What ships in v0.1 (working, dependency-light)
|
|
57
|
+
Core kernel + **ten runnable cases** across the model families and formulation classes (LP / MILP / convex-NLP
|
|
58
|
+
/ inverse), on the common **case contract** (`problem.yml` + GMNS `input/` → `output/solution.csv`,
|
|
59
|
+
`objective_trace.csv`, `constraint_status.csv`, `summary.md`):
|
|
60
|
+
|
|
61
|
+
| model | family | class | case | solver |
|
|
62
|
+
|---|---|---|---|---|
|
|
63
|
+
| `shortest_path` | A routing | LP | `cases/00_shortest_path_toy` | networkx Dijkstra |
|
|
64
|
+
| `min_cost_flow` | flow | LP | `cases/01_min_cost_flow_toy` | networkx |
|
|
65
|
+
| `traffic_assignment` (UE) | B assignment | convex-NLP | `cases/02_sioux_falls_assignment` | Frank-Wolfe + BPR |
|
|
66
|
+
| `system_optimal` (+ pricing) | B assignment | convex-NLP | `cases/03_system_optimal_pricing` | Frank-Wolfe (marginal cost) |
|
|
67
|
+
| `accessibility` | A routing | LP | `cases/04_accessibility` | networkx skims |
|
|
68
|
+
| `max_flow` (min-cut) | F resilience | LP | `cases/05_max_flow_evacuation` | networkx max-flow |
|
|
69
|
+
| `odme` (inverse) | C ODME | QP/NNLS | `cases/06_odme_sioux_falls` | scipy NNLS |
|
|
70
|
+
| `signal_timing` | D operations | LP | `cases/07_signal_timing_intersection` | scipy linprog (HiGHS) |
|
|
71
|
+
| `network_design` | E design | **MILP** | `cases/08_network_design_toy` | **scipy milp (HiGHS)** |
|
|
72
|
+
| `facility_location` (EV charging) | G siting | **MILP** | `cases/09_facility_location_charging` | **scipy milp (HiGHS)** |
|
|
73
|
+
|
|
74
|
+
Verified invariants: system-optimal total travel time **<** user-equilibrium; ODME count-RMSE 2720 → 185;
|
|
75
|
+
MILP network design respects the budget; p-median opens exactly K hubs. Only `numpy`, `scipy`, `networkx`,
|
|
76
|
+
`PyYAML` are required (MILP/LP use scipy's HiGHS backend — **no commercial solver needed**). Optional extras
|
|
77
|
+
add Pyomo/HiGHS bindings, pandas/matplotlib.
|
|
78
|
+
|
|
79
|
+
## Install
|
|
80
|
+
```bash
|
|
81
|
+
pip install -e . # core
|
|
82
|
+
pip install -e ".[viz,solvers,dev]" # + pandas/matplotlib, Pyomo/HiGHS, pytest/ruff
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Quick start
|
|
86
|
+
```bash
|
|
87
|
+
gmns-opt run cases/02_sioux_falls_assignment # -> output/ (solution, trace, summary)
|
|
88
|
+
gmns-opt validate cases/02_sioux_falls_assignment
|
|
89
|
+
gmns-opt list-families # the 10-family taxonomy (maturity + classes)
|
|
90
|
+
gmns-opt describe-family signal_queue_control
|
|
91
|
+
gmns-opt solver-status # available solver tiers
|
|
92
|
+
gmns-opt generate-scenarios --case cases/11_resilience_capacity_drop_toy --type capacity_drop --links 1,2,3 --drop 0.5
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Broader benchmark scaffold
|
|
96
|
+
Beyond the runnable models, the package is an open-science **ecosystem scaffold**:
|
|
97
|
+
- **Application taxonomy** — 10 families (`gmns_opt.applications` / `benchmark.registry`), each with formulation
|
|
98
|
+
classes, required/optional GMNS files, outputs, solver tier, visualization, and **maturity**
|
|
99
|
+
(runnable / scaffold / planned). See [docs/application_taxonomy.md](docs/application_taxonomy.md).
|
|
100
|
+
- **Tensor framework** — `gmns_opt.tensor`: sparse `x[o,d,m,p,τ,s,a]` + companion tensors (D/F/Q/U/C/R/V),
|
|
101
|
+
GMNS→demand-tensor conversion, scenario expansion, CSV/JSON export. See [docs/tensor_framework.md](docs/tensor_framework.md).
|
|
102
|
+
- **Scenario generator** — `gmns_opt.scenarios`: deterministic normal / capacity_drop / demand_surge / work_zone
|
|
103
|
+
/ weather / cav_penetration / uam_weather_restriction (fixed seeds).
|
|
104
|
+
- **Solver tiers** — `gmns_opt.solvers`: Tier 0 (networkx/scipy-HiGHS) → 1 (Pyomo) → 2 (commercial, optional) →
|
|
105
|
+
3 (GPU/neural/RL). No commercial dependency. See [docs/solver_tiers.md](docs/solver_tiers.md).
|
|
106
|
+
- **ML-for-optimization readiness** — `gmns_opt.ml`: GMNS feature extraction (GNN-ready), learning-to-warm-start
|
|
107
|
+
interface, learning-to-branch dataset schema. See [docs/ml_for_optimization.md](docs/ml_for_optimization.md).
|
|
108
|
+
- **GUI4GMNS visualization** — `gmns_opt.visualization.export_optimization_layers` → GeoJSON + decision/constraint/
|
|
109
|
+
trace/scenario CSVs. See [docs/gui4gmns_integration.md](docs/gui4gmns_integration.md).
|
|
110
|
+
- **Case templates** — `case_templates/` (one per family) and 13 runnable/scaffold seed cases (`cases/00..12`).
|
|
111
|
+
```python
|
|
112
|
+
from gmns_opt import run_case
|
|
113
|
+
res = run_case("cases/02_sioux_falls_assignment")
|
|
114
|
+
print(res["objective"], res["meta"]["final_relative_gap"]) # UE Beckmann + FW gap
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
## The benchmark ladder (design)
|
|
118
|
+
Not one benchmark — a **ladder** from transparent teaching cases to industrial-scale city cases:
|
|
119
|
+
|
|
120
|
+
| level | what | purpose |
|
|
121
|
+
|---|---|---|
|
|
122
|
+
| 0 | formulation micro-cases (5–20 nodes, 1 signal) | teach variables/constraints; debug solvers; validate LLM-generated models |
|
|
123
|
+
| 1 | classic research nets **as GMNS** (Sioux Falls, Anaheim, Chicago) | connect to the literature; algorithm comparison |
|
|
124
|
+
| 2 | open-city OSM2GMNS (Tempe, Phoenix, Atlanta, LA, Bay Area) | geographically meaningful; GIS/planning + GUI4GMNS outreach |
|
|
125
|
+
| 3 | dynamic corridor operations (signals, queues, work zones, incidents) | planning → operations (DTA/CBI/ODME) |
|
|
126
|
+
| 4 | stochastic / robust (demand, capacity, incident, weather, CAV/UAM uncertainty) | research-grade OR/AI |
|
|
127
|
+
| 5 | industrial-scale city (10⁴–10⁶ vars, multi-mode/period/scenario) | stress solvers + neural acceleration |
|
|
128
|
+
|
|
129
|
+
## Model families (implemented → planned)
|
|
130
|
+
A. shortest path / accessibility ✅ · B. traffic assignment & system-optimal ✅ (UE) · C. **ODME / inverse
|
|
131
|
+
optimization** · D. signal timing & arterial control (MILP/MPC) · E. network design & capacity planning ·
|
|
132
|
+
F. resilience / work-zone / incident / extreme-heat · G. freight / EV charging / UAM / multimodal logistics ·
|
|
133
|
+
H. transit frequency & accessibility. See [docs/BENCHMARK_SPEC.md](docs/BENCHMARK_SPEC.md).
|
|
134
|
+
|
|
135
|
+
## Solver tiers
|
|
136
|
+
`Tier 0` NetworkX / scipy / HiGHS / OR-Tools · `Tier 1` Pyomo + HiGHS/CBC/Ipopt · `Tier 2` Gurobi / CPLEX /
|
|
137
|
+
COPT / Mosek · `Tier 3` GPU / cuOpt / ADMM / RL / neural heuristics. Start license-free; scale up when needed.
|
|
138
|
+
|
|
139
|
+
## Docs
|
|
140
|
+
[vision](docs/vision.md) · [application taxonomy](docs/application_taxonomy.md) ·
|
|
141
|
+
[tensor framework](docs/tensor_framework.md) · [benchmark ladder](docs/benchmark_ladder.md) ·
|
|
142
|
+
[solver tiers](docs/solver_tiers.md) · [ML for optimization](docs/ml_for_optimization.md) ·
|
|
143
|
+
[GUI4GMNS integration](docs/gui4gmns_integration.md) · [open-science test cases](docs/open_science_test_cases.md) ·
|
|
144
|
+
[benchmark spec](docs/BENCHMARK_SPEC.md) · [data contract](docs/data_contract.md) ·
|
|
145
|
+
[roadmap](../dev/ROADMAP.md) · [references](../references/README.md)
|
|
146
|
+
|
|
147
|
+
## License
|
|
148
|
+
MIT — see [LICENSE](LICENSE). Bundled benchmark networks keep their own upstream licenses
|
|
149
|
+
(see [references](../references/README.md)); Sioux Falls is from the public Transportation Networks repo.
|
gmnsopt-0.2.0/README.md
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# gmnsopt
|
|
2
|
+
|
|
3
|
+
[](https://github.com/asu-trans-ai-lab/gmnsopt/actions/workflows/ci.yml)
|
|
4
|
+
[](https://pypi.org/project/gmnsopt/)
|
|
5
|
+
[](https://pypi.org/project/gmnsopt/)
|
|
6
|
+
[](LICENSE)
|
|
7
|
+
|
|
8
|
+
**A GMNS-native transportation optimization testbed** — reproducible, visual, data-grounded, and
|
|
9
|
+
progressively harder. It turns standardized [GMNS](https://github.com/zephyr-data-specs/GMNS) networks +
|
|
10
|
+
demand + operations data into mathematical-programming and network-optimization cases:
|
|
11
|
+
|
|
12
|
+
```
|
|
13
|
+
GMNS network + demand + operations data
|
|
14
|
+
→ optimization model template
|
|
15
|
+
→ solver / algorithm
|
|
16
|
+
→ (dynamic simulation check)
|
|
17
|
+
→ GUI4GMNS visualization
|
|
18
|
+
→ reproducible benchmark report
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
> **gmnsopt turns GMNS from a network data standard into a transportation optimization testbed
|
|
22
|
+
> for planning, operations, control, pricing, resilience, and multimodal decision-making** — where
|
|
23
|
+
> open-source solvers, commercial solvers, ML-for-optimization, and RL/control methods can all be tested on
|
|
24
|
+
> realistic, dynamic, stochastic, visually explainable mobility problems.
|
|
25
|
+
|
|
26
|
+
## What ships in v0.1 (working, dependency-light)
|
|
27
|
+
Core kernel + **ten runnable cases** across the model families and formulation classes (LP / MILP / convex-NLP
|
|
28
|
+
/ inverse), on the common **case contract** (`problem.yml` + GMNS `input/` → `output/solution.csv`,
|
|
29
|
+
`objective_trace.csv`, `constraint_status.csv`, `summary.md`):
|
|
30
|
+
|
|
31
|
+
| model | family | class | case | solver |
|
|
32
|
+
|---|---|---|---|---|
|
|
33
|
+
| `shortest_path` | A routing | LP | `cases/00_shortest_path_toy` | networkx Dijkstra |
|
|
34
|
+
| `min_cost_flow` | flow | LP | `cases/01_min_cost_flow_toy` | networkx |
|
|
35
|
+
| `traffic_assignment` (UE) | B assignment | convex-NLP | `cases/02_sioux_falls_assignment` | Frank-Wolfe + BPR |
|
|
36
|
+
| `system_optimal` (+ pricing) | B assignment | convex-NLP | `cases/03_system_optimal_pricing` | Frank-Wolfe (marginal cost) |
|
|
37
|
+
| `accessibility` | A routing | LP | `cases/04_accessibility` | networkx skims |
|
|
38
|
+
| `max_flow` (min-cut) | F resilience | LP | `cases/05_max_flow_evacuation` | networkx max-flow |
|
|
39
|
+
| `odme` (inverse) | C ODME | QP/NNLS | `cases/06_odme_sioux_falls` | scipy NNLS |
|
|
40
|
+
| `signal_timing` | D operations | LP | `cases/07_signal_timing_intersection` | scipy linprog (HiGHS) |
|
|
41
|
+
| `network_design` | E design | **MILP** | `cases/08_network_design_toy` | **scipy milp (HiGHS)** |
|
|
42
|
+
| `facility_location` (EV charging) | G siting | **MILP** | `cases/09_facility_location_charging` | **scipy milp (HiGHS)** |
|
|
43
|
+
|
|
44
|
+
Verified invariants: system-optimal total travel time **<** user-equilibrium; ODME count-RMSE 2720 → 185;
|
|
45
|
+
MILP network design respects the budget; p-median opens exactly K hubs. Only `numpy`, `scipy`, `networkx`,
|
|
46
|
+
`PyYAML` are required (MILP/LP use scipy's HiGHS backend — **no commercial solver needed**). Optional extras
|
|
47
|
+
add Pyomo/HiGHS bindings, pandas/matplotlib.
|
|
48
|
+
|
|
49
|
+
## Install
|
|
50
|
+
```bash
|
|
51
|
+
pip install -e . # core
|
|
52
|
+
pip install -e ".[viz,solvers,dev]" # + pandas/matplotlib, Pyomo/HiGHS, pytest/ruff
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Quick start
|
|
56
|
+
```bash
|
|
57
|
+
gmns-opt run cases/02_sioux_falls_assignment # -> output/ (solution, trace, summary)
|
|
58
|
+
gmns-opt validate cases/02_sioux_falls_assignment
|
|
59
|
+
gmns-opt list-families # the 10-family taxonomy (maturity + classes)
|
|
60
|
+
gmns-opt describe-family signal_queue_control
|
|
61
|
+
gmns-opt solver-status # available solver tiers
|
|
62
|
+
gmns-opt generate-scenarios --case cases/11_resilience_capacity_drop_toy --type capacity_drop --links 1,2,3 --drop 0.5
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Broader benchmark scaffold
|
|
66
|
+
Beyond the runnable models, the package is an open-science **ecosystem scaffold**:
|
|
67
|
+
- **Application taxonomy** — 10 families (`gmns_opt.applications` / `benchmark.registry`), each with formulation
|
|
68
|
+
classes, required/optional GMNS files, outputs, solver tier, visualization, and **maturity**
|
|
69
|
+
(runnable / scaffold / planned). See [docs/application_taxonomy.md](docs/application_taxonomy.md).
|
|
70
|
+
- **Tensor framework** — `gmns_opt.tensor`: sparse `x[o,d,m,p,τ,s,a]` + companion tensors (D/F/Q/U/C/R/V),
|
|
71
|
+
GMNS→demand-tensor conversion, scenario expansion, CSV/JSON export. See [docs/tensor_framework.md](docs/tensor_framework.md).
|
|
72
|
+
- **Scenario generator** — `gmns_opt.scenarios`: deterministic normal / capacity_drop / demand_surge / work_zone
|
|
73
|
+
/ weather / cav_penetration / uam_weather_restriction (fixed seeds).
|
|
74
|
+
- **Solver tiers** — `gmns_opt.solvers`: Tier 0 (networkx/scipy-HiGHS) → 1 (Pyomo) → 2 (commercial, optional) →
|
|
75
|
+
3 (GPU/neural/RL). No commercial dependency. See [docs/solver_tiers.md](docs/solver_tiers.md).
|
|
76
|
+
- **ML-for-optimization readiness** — `gmns_opt.ml`: GMNS feature extraction (GNN-ready), learning-to-warm-start
|
|
77
|
+
interface, learning-to-branch dataset schema. See [docs/ml_for_optimization.md](docs/ml_for_optimization.md).
|
|
78
|
+
- **GUI4GMNS visualization** — `gmns_opt.visualization.export_optimization_layers` → GeoJSON + decision/constraint/
|
|
79
|
+
trace/scenario CSVs. See [docs/gui4gmns_integration.md](docs/gui4gmns_integration.md).
|
|
80
|
+
- **Case templates** — `case_templates/` (one per family) and 13 runnable/scaffold seed cases (`cases/00..12`).
|
|
81
|
+
```python
|
|
82
|
+
from gmns_opt import run_case
|
|
83
|
+
res = run_case("cases/02_sioux_falls_assignment")
|
|
84
|
+
print(res["objective"], res["meta"]["final_relative_gap"]) # UE Beckmann + FW gap
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## The benchmark ladder (design)
|
|
88
|
+
Not one benchmark — a **ladder** from transparent teaching cases to industrial-scale city cases:
|
|
89
|
+
|
|
90
|
+
| level | what | purpose |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| 0 | formulation micro-cases (5–20 nodes, 1 signal) | teach variables/constraints; debug solvers; validate LLM-generated models |
|
|
93
|
+
| 1 | classic research nets **as GMNS** (Sioux Falls, Anaheim, Chicago) | connect to the literature; algorithm comparison |
|
|
94
|
+
| 2 | open-city OSM2GMNS (Tempe, Phoenix, Atlanta, LA, Bay Area) | geographically meaningful; GIS/planning + GUI4GMNS outreach |
|
|
95
|
+
| 3 | dynamic corridor operations (signals, queues, work zones, incidents) | planning → operations (DTA/CBI/ODME) |
|
|
96
|
+
| 4 | stochastic / robust (demand, capacity, incident, weather, CAV/UAM uncertainty) | research-grade OR/AI |
|
|
97
|
+
| 5 | industrial-scale city (10⁴–10⁶ vars, multi-mode/period/scenario) | stress solvers + neural acceleration |
|
|
98
|
+
|
|
99
|
+
## Model families (implemented → planned)
|
|
100
|
+
A. shortest path / accessibility ✅ · B. traffic assignment & system-optimal ✅ (UE) · C. **ODME / inverse
|
|
101
|
+
optimization** · D. signal timing & arterial control (MILP/MPC) · E. network design & capacity planning ·
|
|
102
|
+
F. resilience / work-zone / incident / extreme-heat · G. freight / EV charging / UAM / multimodal logistics ·
|
|
103
|
+
H. transit frequency & accessibility. See [docs/BENCHMARK_SPEC.md](docs/BENCHMARK_SPEC.md).
|
|
104
|
+
|
|
105
|
+
## Solver tiers
|
|
106
|
+
`Tier 0` NetworkX / scipy / HiGHS / OR-Tools · `Tier 1` Pyomo + HiGHS/CBC/Ipopt · `Tier 2` Gurobi / CPLEX /
|
|
107
|
+
COPT / Mosek · `Tier 3` GPU / cuOpt / ADMM / RL / neural heuristics. Start license-free; scale up when needed.
|
|
108
|
+
|
|
109
|
+
## Docs
|
|
110
|
+
[vision](docs/vision.md) · [application taxonomy](docs/application_taxonomy.md) ·
|
|
111
|
+
[tensor framework](docs/tensor_framework.md) · [benchmark ladder](docs/benchmark_ladder.md) ·
|
|
112
|
+
[solver tiers](docs/solver_tiers.md) · [ML for optimization](docs/ml_for_optimization.md) ·
|
|
113
|
+
[GUI4GMNS integration](docs/gui4gmns_integration.md) · [open-science test cases](docs/open_science_test_cases.md) ·
|
|
114
|
+
[benchmark spec](docs/BENCHMARK_SPEC.md) · [data contract](docs/data_contract.md) ·
|
|
115
|
+
[roadmap](../dev/ROADMAP.md) · [references](../references/README.md)
|
|
116
|
+
|
|
117
|
+
## License
|
|
118
|
+
MIT — see [LICENSE](LICENSE). Bundled benchmark networks keep their own upstream licenses
|
|
119
|
+
(see [references](../references/README.md)); Sioux Falls is from the public Transportation Networks repo.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "gmnsopt"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "GMNS-native transportation optimization testbed: reproducible, visual, data-grounded, progressively harder benchmark cases (shortest path -> assignment -> ODME -> signal -> resilience) for open-source & commercial solvers, ML-for-optimization, and RL/control."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.9"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [{ name = "gmnsopt contributors" }]
|
|
13
|
+
keywords = ["GMNS", "transportation", "optimization", "traffic-assignment", "ODME",
|
|
14
|
+
"benchmark", "operations-research", "networkx", "HiGHS"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Topic :: Scientific/Engineering",
|
|
19
|
+
"Intended Audience :: Science/Research",
|
|
20
|
+
]
|
|
21
|
+
dependencies = ["numpy>=1.21", "scipy>=1.7", "networkx>=2.6", "PyYAML>=5.4"]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
viz = ["pandas>=1.3", "matplotlib>=3.4"]
|
|
25
|
+
solvers = ["pyomo>=6.0", "highspy>=1.5"] # optional Tier-1 modeling + HiGHS bindings
|
|
26
|
+
dev = ["pytest>=7.0", "ruff>=0.1"]
|
|
27
|
+
|
|
28
|
+
[project.scripts]
|
|
29
|
+
gmns-opt = "gmns_opt.cli:main"
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Source = "https://github.com/asu-trans-ai-lab/gmnsopt"
|
|
33
|
+
|
|
34
|
+
[tool.setuptools.packages.find]
|
|
35
|
+
where = ["src"]
|
|
36
|
+
include = ["gmns_opt*"]
|
gmnsopt-0.2.0/setup.cfg
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""gmnsopt — a GMNS-native transportation optimization testbed.
|
|
2
|
+
|
|
3
|
+
Turns standardized GMNS networks + demand + operations data into reproducible optimization cases:
|
|
4
|
+
GMNS network + demand -> optimization model -> solver -> (simulation check) -> report.
|
|
5
|
+
|
|
6
|
+
Public API:
|
|
7
|
+
read_gmns, build_graph, validate_gmns (io)
|
|
8
|
+
shortest_path, min_cost_flow, traffic_assignment (models)
|
|
9
|
+
run_case (benchmark case runner)
|
|
10
|
+
"""
|
|
11
|
+
from .io import read_gmns, build_graph, validate_gmns
|
|
12
|
+
from .models import shortest_path, min_cost_flow, traffic_assignment
|
|
13
|
+
from .benchmark import run_case
|
|
14
|
+
|
|
15
|
+
__version__ = "0.2.0"
|
|
16
|
+
__all__ = ["read_gmns", "build_graph", "validate_gmns",
|
|
17
|
+
"shortest_path", "min_cost_flow", "traffic_assignment", "run_case"]
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Application taxonomy — the ten transportation optimization families.
|
|
2
|
+
|
|
3
|
+
Thin, registry-backed surface: the authoritative metadata lives in `gmns_opt.benchmark.registry`; this package
|
|
4
|
+
exposes it for discovery and groups families by maturity. See docs/application_taxonomy.md.
|
|
5
|
+
"""
|
|
6
|
+
from __future__ import annotations
|
|
7
|
+
from ..benchmark.registry import FAMILIES, list_families, get_family, ProblemFamily
|
|
8
|
+
|
|
9
|
+
BY_ID = {f.id: f for f in FAMILIES}
|
|
10
|
+
FAMILY_IDS = [f.id for f in FAMILIES]
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def by_maturity(maturity: str):
|
|
14
|
+
"""Families at a given maturity: 'runnable' | 'scaffold' | 'planned'."""
|
|
15
|
+
return [f for f in FAMILIES if f.maturity == maturity]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def runnable_models():
|
|
19
|
+
"""All registered runnable problem_type ids across families."""
|
|
20
|
+
out = []
|
|
21
|
+
for f in FAMILIES:
|
|
22
|
+
out.extend(f.runnable_models)
|
|
23
|
+
return sorted(set(out))
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
__all__ = ["FAMILIES", "FAMILY_IDS", "BY_ID", "list_families", "get_family", "ProblemFamily",
|
|
27
|
+
"by_maturity", "runnable_models"]
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Run a benchmark case: read `problem.yml` + GMNS `input/`, dispatch to a model, write `output/`.
|
|
2
|
+
|
|
3
|
+
Output set (the open-science case contract):
|
|
4
|
+
output/solution.csv per-link (or per-path) solution
|
|
5
|
+
output/objective_trace.csv iteration, objective, gap, ... (convergence)
|
|
6
|
+
output/constraint_status.csv constraint, status (feasibility)
|
|
7
|
+
output/summary.md human-readable headline + KPIs
|
|
8
|
+
"""
|
|
9
|
+
from __future__ import annotations
|
|
10
|
+
import os
|
|
11
|
+
import yaml
|
|
12
|
+
from ..io import read_gmns, validate_gmns
|
|
13
|
+
from ..models import (shortest_path, accessibility, min_cost_flow, max_flow, traffic_assignment,
|
|
14
|
+
system_optimal, odme, signal_timing, network_design, facility_location,
|
|
15
|
+
resilience_scenario, multimodal_skeleton)
|
|
16
|
+
from .report import write_outputs
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def _ml_features(net, p, cd):
|
|
20
|
+
from ..ml import extract_features
|
|
21
|
+
feat = extract_features(net, scenario=p.get("scenario", "normal"))
|
|
22
|
+
return {"objective": feat["stats"]["n_links"], "solution": [], "objective_trace": [],
|
|
23
|
+
"constraint_status": [{"constraint": "feature_extraction", "status": "ok"}],
|
|
24
|
+
"meta": {"feasible": True, "maturity": "scaffold", **feat["stats"],
|
|
25
|
+
"note": "GMNS feature blocks for ML-for-optimization (see docs/ml_for_optimization.md)"},
|
|
26
|
+
"features": feat}
|
|
27
|
+
|
|
28
|
+
# each entry: (net, params, case_dir) -> result dict
|
|
29
|
+
DISPATCH = {
|
|
30
|
+
"shortest_path": lambda net, p, cd: shortest_path(net, p["origin"], p["destination"],
|
|
31
|
+
weight=p.get("weight", "fftt_min"),
|
|
32
|
+
by_zone=p.get("by_zone", True)),
|
|
33
|
+
"accessibility": lambda net, p, cd: accessibility(net, threshold_min=p.get("threshold_min", 30.0),
|
|
34
|
+
weight=p.get("weight", "fftt_min"),
|
|
35
|
+
decay=p.get("decay", 0.0)),
|
|
36
|
+
"min_cost_flow": lambda net, p, cd: min_cost_flow(net, p["supplies"], weight=p.get("weight", "fftt_min"),
|
|
37
|
+
by_zone=p.get("by_zone", True), scale=p.get("scale", 1)),
|
|
38
|
+
"max_flow": lambda net, p, cd: max_flow(net, p["source"], p["sink"], by_zone=p.get("by_zone", True)),
|
|
39
|
+
"traffic_assignment": lambda net, p, cd: traffic_assignment(net, max_iter=p.get("max_iter", 60),
|
|
40
|
+
gap_tol=p.get("gap_tol", 1e-4),
|
|
41
|
+
by_zone=p.get("by_zone", True)),
|
|
42
|
+
"system_optimal": lambda net, p, cd: system_optimal(net, max_iter=p.get("max_iter", 80),
|
|
43
|
+
gap_tol=p.get("gap_tol", 1e-4),
|
|
44
|
+
by_zone=p.get("by_zone", True)),
|
|
45
|
+
"odme": lambda net, p, cd: odme(net, case_dir=cd, reg=p.get("reg", 0.1), by_zone=p.get("by_zone", True)),
|
|
46
|
+
"signal_timing": lambda net, p, cd: signal_timing(net, p["phases"], cycle=p.get("cycle", 90.0),
|
|
47
|
+
lost_time_per_phase=p.get("lost_time_per_phase", 4.0),
|
|
48
|
+
min_green=p.get("min_green", 7.0)),
|
|
49
|
+
"network_design": lambda net, p, cd: network_design(net, p["source"], p["sink"], p["flow"], p["budget"],
|
|
50
|
+
by_zone=p.get("by_zone", True),
|
|
51
|
+
candidate_link_ids=p.get("candidate_link_ids")),
|
|
52
|
+
"facility_location": lambda net, p, cd: facility_location(net, p["k"], candidates=p.get("candidates"),
|
|
53
|
+
weight=p.get("weight", "fftt_min")),
|
|
54
|
+
"resilience_scenario": lambda net, p, cd: resilience_scenario(net, drop_link_ids=p.get("drop_link_ids"),
|
|
55
|
+
drop=p.get("drop", 0.5), case_dir=cd,
|
|
56
|
+
by_zone=p.get("by_zone", True)),
|
|
57
|
+
"multimodal_skeleton": lambda net, p, cd: multimodal_skeleton(net, modes=p.get("modes"),
|
|
58
|
+
time_stages=p.get("time_stages", 4),
|
|
59
|
+
scenarios=p.get("scenarios")),
|
|
60
|
+
"ml_features": _ml_features,
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def run_case(case_dir: str, write: bool = True) -> dict:
|
|
65
|
+
"""Run the case in `case_dir`. Returns the result dict; writes output/ when `write` is True."""
|
|
66
|
+
with open(os.path.join(case_dir, "problem.yml"), encoding="utf-8") as f:
|
|
67
|
+
problem = yaml.safe_load(f)
|
|
68
|
+
ptype = problem["problem_type"]
|
|
69
|
+
if ptype not in DISPATCH:
|
|
70
|
+
raise ValueError(f"unknown problem_type '{ptype}'. Available: {sorted(DISPATCH)}")
|
|
71
|
+
|
|
72
|
+
net = read_gmns(case_dir)
|
|
73
|
+
report = validate_gmns(net)
|
|
74
|
+
if not report["ok"]:
|
|
75
|
+
raise ValueError(f"GMNS validation failed for {case_dir}: {report['errors'][:5]}")
|
|
76
|
+
|
|
77
|
+
result = DISPATCH[ptype](net, problem.get("params", {}) or {}, case_dir)
|
|
78
|
+
result["problem"] = problem
|
|
79
|
+
result["network_stats"] = report["stats"]
|
|
80
|
+
if write:
|
|
81
|
+
out = os.path.join(case_dir, "output")
|
|
82
|
+
write_outputs(out, problem, result, report)
|
|
83
|
+
result["output_dir"] = out
|
|
84
|
+
return result
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"""Benchmark category registry — the machine-readable taxonomy of transportation optimization families.
|
|
2
|
+
|
|
3
|
+
Each `ProblemFamily` records its formulation classes, required/optional GMNS files, required outputs, default
|
|
4
|
+
solver tier, visualization type, and maturity (runnable | scaffold | planned) plus the implemented model
|
|
5
|
+
templates (`problem_type` ids usable in a case `problem.yml`). This is the single source of truth surfaced by
|
|
6
|
+
`gmns-opt list-families` / `describe-family` and by `gmns_opt.applications`.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
from dataclasses import dataclass, field
|
|
10
|
+
from typing import List
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@dataclass(frozen=True)
|
|
14
|
+
class ProblemFamily:
|
|
15
|
+
id: str
|
|
16
|
+
name: str
|
|
17
|
+
formulation_classes: List[str]
|
|
18
|
+
required_files: List[str]
|
|
19
|
+
optional_files: List[str] = field(default_factory=list)
|
|
20
|
+
outputs: List[str] = field(default_factory=lambda: ["solution.csv", "objective_trace.csv",
|
|
21
|
+
"constraint_status.csv", "summary.md"])
|
|
22
|
+
default_solver_tier: int = 0
|
|
23
|
+
visualization: str = "link_flow"
|
|
24
|
+
maturity: str = "planned" # runnable | scaffold | planned
|
|
25
|
+
runnable_models: List[str] = field(default_factory=list) # registered problem_type ids
|
|
26
|
+
subtypes: List[str] = field(default_factory=list)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
FAMILIES: List[ProblemFamily] = [
|
|
30
|
+
ProblemFamily(
|
|
31
|
+
id="routing_accessibility", name="Routing & Accessibility",
|
|
32
|
+
formulation_classes=["LP", "network_flow"],
|
|
33
|
+
required_files=["node.csv", "link.csv"], optional_files=["zone.csv", "demand.csv", "transit_route.csv"],
|
|
34
|
+
default_solver_tier=0, visualization="path_highlight", maturity="runnable",
|
|
35
|
+
runnable_models=["shortest_path", "accessibility", "min_cost_flow"],
|
|
36
|
+
subtypes=["shortest_path", "multimodal_path", "accessibility", "equity_aware_access"]),
|
|
37
|
+
ProblemFamily(
|
|
38
|
+
id="traffic_assignment_pricing", name="Traffic Assignment & Pricing",
|
|
39
|
+
formulation_classes=["convex_NLP", "MIP", "dynamic", "stochastic"],
|
|
40
|
+
required_files=["node.csv", "link.csv", "demand.csv"], optional_files=["toll.csv", "scenario.csv"],
|
|
41
|
+
default_solver_tier=0, visualization="flow_height_speed_color", maturity="runnable",
|
|
42
|
+
runnable_models=["traffic_assignment", "system_optimal"],
|
|
43
|
+
subtypes=["user_equilibrium", "system_optimal", "dynamic_assignment", "congestion_pricing",
|
|
44
|
+
"managed_lane_control"]),
|
|
45
|
+
ProblemFamily(
|
|
46
|
+
id="odme_inverse_optimization", name="ODME & Inverse Optimization",
|
|
47
|
+
formulation_classes=["LP", "QP", "NLP", "stochastic", "inverse"],
|
|
48
|
+
required_files=["node.csv", "link.csv", "demand.csv"],
|
|
49
|
+
optional_files=["counts.csv", "detector.csv", "trajectory.csv", "scenario.csv"],
|
|
50
|
+
default_solver_tier=0, visualization="desire_line_delta", maturity="runnable",
|
|
51
|
+
runnable_models=["odme"],
|
|
52
|
+
subtypes=["od_matrix_estimation", "path_flow_correction", "sensor_residual_min", "demand_tensor_calibration"]),
|
|
53
|
+
ProblemFamily(
|
|
54
|
+
id="signal_queue_control", name="Signal & Queue Spillback Control",
|
|
55
|
+
formulation_classes=["MIP", "dynamic", "stochastic", "RL_ready"],
|
|
56
|
+
required_files=["node.csv", "link.csv", "demand.csv"],
|
|
57
|
+
optional_files=["movement.csv", "signal_timing.csv", "detector.csv", "scenario.csv"],
|
|
58
|
+
outputs=["solution_signal.csv", "queue_profile.csv", "constraint_status.csv", "objective_trace.csv"],
|
|
59
|
+
default_solver_tier=0, visualization="phase_clock_queue_ribbon", maturity="runnable",
|
|
60
|
+
runnable_models=["signal_timing"],
|
|
61
|
+
subtypes=["signal_timing", "green_split_offset_phase", "queue_spillback", "corridor_mpc_milp_rl"]),
|
|
62
|
+
ProblemFamily(
|
|
63
|
+
id="resilience_workzone_incident", name="Resilience, Work-Zone & Incident",
|
|
64
|
+
formulation_classes=["MIP", "stochastic", "dynamic", "robust"],
|
|
65
|
+
required_files=["node.csv", "link.csv", "demand.csv"], optional_files=["scenario.csv", "resource.csv"],
|
|
66
|
+
outputs=["scenario_summary.csv", "solution.csv", "constraint_status.csv", "objective_trace.csv"],
|
|
67
|
+
default_solver_tier=0, visualization="warning_layer_before_after", maturity="runnable",
|
|
68
|
+
runnable_models=["resilience_scenario", "max_flow"],
|
|
69
|
+
subtypes=["incident_response", "work_zone_scheduling", "extreme_heat_weather_flood",
|
|
70
|
+
"evacuation_recovery"]),
|
|
71
|
+
ProblemFamily(
|
|
72
|
+
id="cav_control", name="CAV Mixed-Traffic Control",
|
|
73
|
+
formulation_classes=["MIP", "QP", "NLP", "stochastic", "dynamic", "RL"],
|
|
74
|
+
required_files=["node.csv", "link.csv", "demand.csv"],
|
|
75
|
+
optional_files=["scenario.csv", "penetration.csv", "control_zone.csv"],
|
|
76
|
+
outputs=["decision_variable.csv", "constraint_status.csv", "objective_trace.csv", "summary.md"],
|
|
77
|
+
default_solver_tier=2, visualization="control_zone_speed", maturity="scaffold",
|
|
78
|
+
runnable_models=["multimodal_skeleton"],
|
|
79
|
+
subtypes=["mixed_traffic", "speed_advisory", "platooning", "lane_use_control", "ramp_metering",
|
|
80
|
+
"communication_failure"]),
|
|
81
|
+
ProblemFamily(
|
|
82
|
+
id="uam_air_ground_coordination", name="UAM Air–Ground Coordination",
|
|
83
|
+
formulation_classes=["MIP", "stochastic", "dynamic", "RL"],
|
|
84
|
+
required_files=["node.csv", "link.csv", "demand.csv"],
|
|
85
|
+
optional_files=["vertiport.csv", "air_link.csv", "weather_scenario.csv", "charging_station.csv"],
|
|
86
|
+
outputs=["decision_variable.csv", "constraint_status.csv", "objective_trace.csv", "summary.md"],
|
|
87
|
+
default_solver_tier=2, visualization="vertiport_queue_3d", maturity="scaffold",
|
|
88
|
+
runnable_models=["multimodal_skeleton"],
|
|
89
|
+
subtypes=["vertiport_capacity", "dispatch_repositioning", "weather_uncertainty", "battery_charging",
|
|
90
|
+
"ground_access_integration"]),
|
|
91
|
+
ProblemFamily(
|
|
92
|
+
id="freight_ev_logistics", name="Freight, EV & Logistics Routing",
|
|
93
|
+
formulation_classes=["MIP", "stochastic", "dynamic"],
|
|
94
|
+
required_files=["node.csv", "link.csv"],
|
|
95
|
+
optional_files=["vehicle.csv", "charging_station.csv", "delivery_demand.csv", "scenario.csv"],
|
|
96
|
+
default_solver_tier=1, visualization="route_energy", maturity="scaffold",
|
|
97
|
+
runnable_models=["facility_location"],
|
|
98
|
+
subtypes=["vrp", "ev_routing_charging", "time_windows", "curb_depot_fleet", "truck_drone_uam"]),
|
|
99
|
+
ProblemFamily(
|
|
100
|
+
id="transit_frequency_accessibility", name="Transit Frequency & Accessibility",
|
|
101
|
+
formulation_classes=["MIP", "LP", "stochastic"],
|
|
102
|
+
required_files=["node.csv", "link.csv", "demand.csv"],
|
|
103
|
+
optional_files=["transit_route.csv", "fleet.csv", "scenario.csv"],
|
|
104
|
+
default_solver_tier=1, visualization="frequency_accessibility", maturity="planned",
|
|
105
|
+
runnable_models=[],
|
|
106
|
+
subtypes=["bus_frequency", "fleet_allocation", "first_last_mile", "transfer_coordination",
|
|
107
|
+
"equity_service"]),
|
|
108
|
+
ProblemFamily(
|
|
109
|
+
id="solver_learning_and_neural_optimization", name="Solver Learning & Neural Optimization",
|
|
110
|
+
formulation_classes=["ML", "RL", "surrogate"],
|
|
111
|
+
required_files=["node.csv", "link.csv", "demand.csv"], optional_files=["scenario.csv"],
|
|
112
|
+
outputs=["features.json", "warm_start.csv", "objective_trace.csv", "summary.md"],
|
|
113
|
+
default_solver_tier=3, visualization="convergence_panel", maturity="scaffold",
|
|
114
|
+
runnable_models=["ml_features"],
|
|
115
|
+
subtypes=["learning_to_warm_start", "learning_to_branch", "graph_neural_features", "neural_surrogate",
|
|
116
|
+
"rl_policy_interface", "train_val_test_city_split"]),
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
_BY_ID = {f.id: f for f in FAMILIES}
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
def list_families() -> List[ProblemFamily]:
|
|
123
|
+
return list(FAMILIES)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def get_family(family_id: str) -> ProblemFamily:
|
|
127
|
+
if family_id not in _BY_ID:
|
|
128
|
+
raise KeyError(f"unknown family '{family_id}'. Known: {sorted(_BY_ID)}")
|
|
129
|
+
return _BY_ID[family_id]
|