Stabiles Python-Environment zur Simulation und zum Vergleich von Engstellen-Dispatching-Strategien im Schienenverkehr.
Status: ✅ Thesis-ready | Python: ≥3.10 | Last Updated: Nov 15, 2025
Modelliert ein realistisches Engstellen-Szenario mit:
- Engstelle (Bottleneck) mit Kapazität 1 und konfigurierbarer Durchlaufzeit
- Mehreren Zügen mit Release-Zeit (Ankunft) und Sollzeit (Deadline)
- Diskreter Zeitsimulation (Zeitschritte = 1 Minute)
- Zentraler Leitstelle die in jedem Schritt entscheidet, welcher Zug die Engstelle passiert
Vergleich von 4 Dispatching-Strategien auf 4 Szenarien mit realistischen Variationen:
| Strategy | Type | Implementation |
|---|---|---|
| FCFS | Heuristic | First-Come-First-Served |
| EDD | Heuristic | Earliest Due Date |
| MIP | Optimization | OR-Tools CP-SAT Lookahead (k=10) |
| RL | Learning | PPO (Gymnasium wrapper, 100k steps) |
| Scenario | Arrivals | Deadlines | Trains |
|---|---|---|---|
| A | Uniform | Uniform | 15 |
| B | Uniform | Mixed (tight/loose) | 15 |
| C | Poisson | Uniform | 20 |
| D | Poisson | Mixed | 20 |
→ See docs/THESIS_READY/ for thesis-ready documentation and results
# Repository klonen
cd /path/to/dispatchEnv
# Virtual Environment (empfohlen)
python -m venv venv
source venv/bin/activate # Linux/macOS
# oder: venv\Scripts\activate # Windows
# Dependencies installieren
pip install -r requirements.txt# Alle 4 Strategien auf allen 4 Szenarien
python engstellensim/scripts/run_scenarios_abcd.py
# Oder einzeln mit Scenario-Parameter:
python engstellensim/scripts/run_greedy.py A # Szenario A (Baseline)
python engstellensim/scripts/run_greedy.py B # Szenario B (Mixed Deadlines)
python engstellensim/scripts/run_mip.py C # Szenario C (Poisson)
# Tests ausführen
pytest engstellensim/tests/ -vengstellensim/
├── env/
│ ├── core_env.py # BottleneckEnv (Kern-Simulator)
│ ├── scenario.py # Scenario + Train + Bottleneck Klassen
│ │ ├── create_realistic_scenario() # Scenario A (Baseline)
│ │ ├── create_scenario_b() # Scenario B (Mixed Deadlines)
│ │ ├── create_scenario_c() # Scenario C (Poisson)
│ │ └── create_scenario_d() # Scenario D (Complex)
│ ├── env_wrapper.py # BottleneckEnvGym (Gymnasium interface)
│ └── state_representation.py # Optional numerische Observationen
├── dispatchers/
│ ├── greedy.py # FCFS + EDD Heuristiken
│ ├── mip_dispatcher.py # OR-Tools CP-SAT Optimizer
│ └── rl_agent.py # PPO Training & Evaluation
├── evaluation/
│ ├── kpi.py # KPI-Berechnung
│ └── experiments.py # Experiment-Definitionen
├── scripts/
│ ├── scenario_utils.py # Central scenario factory (A-D)
│ ├── run_greedy.py # Greedy comparison
│ ├── run_mip.py # MIP comparison
│ ├── run_scenarios_abcd.py # Full comparison (RECOMMENDED)
│ ├── run_rl_train_extended.py # Multi-seed RL training
│ └── evaluate_holdout_simple.py # Robustness evaluation
├── models/
│ ├── ppo_agent_extended.zip # Single-seed trained model
│ └── ppo_agent_multiseed.zip # Multi-seed trained model
└── tests/
└── test_env_basic.py # 15 unit tests (all passing)
RESULTS.md # Complete experimental results
PHASES_5_3_TO_6.md # Phase documentation
PROJECT_MASTER_PLAN.md # Overall roadmap
pyproject.toml # Project configuration
from engstellensim.env.scenario import create_realistic_scenario
from engstellensim.env.core_env import BottleneckEnv
scenario = create_realistic_scenario(num_trains=15, seed=42)
env = BottleneckEnv(scenario)
# Episode
obs_dict = env.reset()
while not done:
train_id = choose_dispatch_decision(obs_dict, waiting_trains)
obs_dict, reward, done, info = env.step(train_id)
stats = env.compute_stats() # KPIs: avg_delay, p95, max, etc.State (obs_dict):
time: Current time stepbottleneck_free: Is bottleneck available?waiting_trains: List of waiting train IDstrain_info: Per-train status & metrics
Action:
int: Dispatch train with this IDNone: Wait (bottleneck busy)
Reward (for RL):
+10 - delay*0.5when train completes-0.01per step (efficiency penalty)
NOT_ARRIVED → WAITING → IN_BOTTLENECK → DONE
- NOT_ARRIVED: t < release_time
- WAITING: Ready at approach, waiting for dispatcher
- IN_BOTTLENECK: Traversing (duration = travel_time)
- DONE: Exited, delay = exit_time - scheduled_slot
Per episode:
- avg_delay: Mean delay (primary metric)
- p95_delay: 95th percentile
- max_delay: Maximum delay
- throughput: Trains/step
- completed_trains: Count of finished trains
from engstellensim.dispatchers.greedy import GreedyDispatcher
env = BottleneckEnv(scenario)
dispatcher = GreedyDispatcher(env, strategy="edd") # or "fcfs"
stats = dispatcher.run_episode()- FCFS: Dispatch oldest waiting train
- EDD: Dispatch train with earliest deadline
from engstellensim.dispatchers.mip_dispatcher import MIPDispatcher
env = BottleneckEnv(scenario)
dispatcher = MIPDispatcher(env, horizon_k=10)
stats = dispatcher.run_episode()- Lookahead optimization: Consider next k trains
- Cost model: delay + impact on others
- OR-Tools CP-SAT solver
- Robust fallback to EDD if solver fails
from engstellensim.env.env_wrapper import BottleneckEnvGym
from stable_baselines3 import PPO
env = BottleneckEnvGym(scenario)
model = PPO("MlpPolicy", env, ...)
model.learn(total_timesteps=100000)
model.save("my_agent.zip")
# Later:
model = PPO.load("my_agent.zip")
obs, _ = env.reset()
action, _ = model.predict(obs)Scenario A (Baseline - Uniform):
FCFS: 4.60 avg delay (baseline)
EDD: 3.87 (-15.9%) ✓
MIP: 3.87 (converges to EDD)
RL: 2.27 (-41.4% on training seed)
Scenario B (Mixed Deadlines):
FCFS: 3.93 avg delay
EDD: 2.53 (-35.6%) ✓✓
MIP: 2.53 (converges to EDD)
Key Finding: Deadline urgency (tight vs loose) drives strategy performance more than arrival patterns.
→ See RESULTS.md for complete results across all scenarios
- ✅ Schlank: Pure Python, keine SUMO/Flatland
- ✅ Fair: Alle Strategien auf identischem Environment
- ✅ Deterministisch: Reproducible with seed control
- ✅ Testbar: 15 unit tests, all passing
- ✅ Dokumentiert: Comprehensive docstrings
- ✅ Produktiv-reif: Error handling, fallbacks, logging
# All tests
pytest engstellensim/tests/ -v
# Specific test
pytest engstellensim/tests/test_env_basic.py::TestTrainStatusTransitions -v
# With coverage
pytest --cov=engstellensim engstellensim/tests/Status: ✅ All 15 tests passing
Alle Ergebnisse sind reproduzierbar mit:
# Genau die im Paper beschriebenen Ergebnisse
python engstellensim/scripts/run_scenarios_abcd.py
# Mit zufälligen Seeds für Robustheit
python engstellensim/scripts/evaluate_holdout_simple.pySeed-Werte dokumentiert, git history clean.
Minimal, production-ready:
numpy- numericsortools- MIP solver (optional für MIP strategy)gymnasium- RL environment interface (optional für RL)stable-baselines3- PPO algorithm (optional für RL)pytest- testing
For thesis-ready documentation, see docs/THESIS_READY/:
- METHODOLOGY.md - Complete methods chapter (architecture, algorithms, evaluation design)
- EVALUATION_OUTPUT_PLAN.md - Copy-paste ready results tables and charts
- RESULTS_FINAL.md - Phase 7 final results with analysis and interpretation
- ARCHITECTURE_VERIFICATION.md - Detailed architecture verification
Quick access:
- Methods chapter:
docs/THESIS_READY/METHODOLOGY.md - Results tables:
docs/THESIS_READY/EVALUATION_OUTPUT_PLAN.md - Code reference:
engstellensim/package structure documented inABOUT.mdfiles