|
MTCT
Design Automation and Optimization for ETCS Railway Networks
|
<picture> <source media="(prefers-color-scheme: dark)" srcset="_img/logo-train-control-toolkit-white-medium.png" width="60%">
</picture>
Developers: Stefan Engels, Tom Peham, and Robert Wille
The European Train Control System (ETCS) harmonizes many national train control systems. Additionally, new specifications strive to increase the capacity of existing railway infrastructure. This is mainly achieved by separating the trains more accurately than the trackside train detection (TTD) hardware allows. If the existing TTD sections are subdivided into virtual subsections (VSS), which do not require additional hardware, one speaks of hybrid train detection (HTD, formerly known as ETCS Hybrid Level 3). If no trackside train detection is used at all, the trains are separated by their reported positions only, which is known as moving block.
Both settings pose planning tasks that are non-trivial and are currently done mainly manually. In our research at the Chair for Design Automation of the Technical University of Munich, we develop methods that solve them automatically and optimally concerning various optimality criteria. A journal article describing the arising design tasks in more detail is available [7].
For hybrid train detection, one has to decide where to place the VSS borders. First attempts using satisfiability solvers [1] and heuristics [2] have been implemented at https://github.com/cda-tum/da_etcs. Since the methods used there cannot model continuous properties directly, simplifying assumptions were made. This tool provides a flexible approach in which designers can individually trade off the efficiency of the solving process and the model's accuracy. Using an exact Mixed Integer Linear Programming (MILP) approach, it adds as few VSS as possible such that the timetable given in the instance can be operated exactly as specified [3]. Its runtime has been improved by an iterative approach [4] as well as by taking a precomputed moving block routing into account [6].
For moving block, no layout has to be designed, and the question becomes how to route and schedule the trains themselves. In this case, the times given in the instance are lower bounds only. The tool finds routings that minimize a weighted combination of the delays at the stations and when leaving the network. They can be obtained by a MILP [5] as well as by an A* search [8] on simulated train movements, whose runtime and scalability are improved considerably by time-aware state transitions [9].
All of these methods are built on a common problem description and are accessible through a command line app, which also builds and edits the instances they work on. The tool is under active development, and more features will follow.
The tool has been tested under Windows 11 (64-bit) using the MSVC compiler. It should also be compatible with any other compiler supporting C++23, where a minimum CMake version of 3.20 is required. More precisely, at least GCC 13.0, Clang 17.0, Apple Clang 16.0 (i.e., Xcode 16.0), or MSVC 19.34 (i.e., Visual Studio 2022 17.4) is needed.
Moreover, the tool requires a local installation of a recent Gurobi [10] version available at https://www.gurobi.com/downloads/gurobi-software/ as well as a valid license. For academic purposes, Gurobi offers free academic licenses. The project currently tests with Gurobi v13.0.3.
To build the tool, go to the project folder and execute the following:
Clone the submodules, if this has not already been done while cloning the repository.
Configure CMake
If the default compiler is too old, a suitable one has to be specified explicitly, e.g., using the following command on Linux and MacOS
When compiling, CMake automatically searches for Gurobi at the default locations, i.e.,
C:/gurobi<VERSION>/win64 for Windows systems/home/opt/gurobi<VERSION>/linux64 for Linux systems/Library/gurobi<VERSION>/macos_universal2 for MacOS systems where <VERSION> denotes the installed Gurobi version.If this does not work, please set the OS environment variable GUROBI_HOME to the respective install directory. This way, CMake can find Gurobi even in non-standard directories.
If you are using Windows, make sure that Gurobi's bin folder, i.e., <installdir>\bin, is appended to the Path environmental variable. The above variables are usually automatically set, if Gurobi is installed using the installer with administrator privileges. Otherwise, they have to be set manually, see also https://support.gurobi.com/hc/en-us/articles/360060996432-How-do-I-install-Gurobi-on-Windows-without-administrator-credentials-
The tool is used through rail_cli, built into build/apps/cli. It creates and edits problem instances and runs every solver on them, see Interactive Sessions.
In addition, each solver is available as a standalone app in build/apps, which solves one instance with one set of settings and terminates:
rail_vss_generation_timetable_mip_testing generates minimal VSS layouts for a given timetable using a MILP.rail_gen_po_moving_block_mip_testing routes trains optimally under moving block control using a MILP.rail_gen_po_moving_block_astar_testing routes trains optimally under moving block control using an A* search.A solver has the same settings whether it is called through rail_cli or through its standalone app. Called with --help (or -h), every app prints the full documentation of all of them, including their default values and their dependencies on each other. The following only summarizes the general ideas; for the exact meaning of a setting, please refer to that output, which is included below for the three standalone apps. Settings that exist in more than one solver use the same names everywhere. Every setting has a long name, which is used below, and most of them additionally have a short one.
All apps work on the same kind of problem instance, which consists of a railway network, a timetable, and routes. Whether these routes are used or optimized again is up to the respective solver and its settings. The timings of the timetable, however, are interpreted differently by the two problems. For VSS generation they are fixed, whereas for moving block routing they are lower bounds whose violation is minimized. An instance is identified by a working directory (--working-directory), a subdirectory (--instance-subdirectory), and its name (--instance-name), and is read from working_directory/instances/instance_subdirectory/instance_name. In rail_cli, the same three are the working directory of the session and the two arguments of instance load. Example instances can be found in test/data/instances.
By default, the solution is only printed and not saved. Using --export-solution (or --export-solution-and-instance, if the instance is to be exported alongside it) together with a subdirectory given by --solution-export-subdirectory, it is written to working_directory/solutions/solution_subdirectory/instance_subdirectory/instance_name. If the solutions belong somewhere else than the instances, a separate working directory can be given by --export-working-directory. Since the same instance is often solved with different settings, an identifier can be appended to the instance name in the export path. It is either specified explicitly by --parameter-identifier or generated from the used settings by --generate-parameter-identifier.
Hence, the instance SimpleStation can be solved and exported by the following command:
rail_cli keeps one instance in memory for a whole session, so that it can be built or changed command by command and solved once it is in shape.
A session looks as follows.
status says where the session is, instance info and network info what the two objects contain, and instance list and network list what else the working directory has to offer. help lists all commands, and every command explains its own settings with --help, for example train add --help.
Nothing is written before you ask for it. instance save writes the loaded instance, network save the network it uses, and instance save --with-network both at once. Keeping the two apart matters because several instances can share one network, so a network is never overwritten as a side effect of saving an instance. status marks what has been changed but not saved yet, and instance reload and network reload read the object back from disk, which is the quickest way out of a mistake. exit refuses to end a session with unsaved changes and says so; exit --force ends it anyway and discards them.
solve mb-mip, solve mb-astar, and solve vss-mip run the solvers described in the following sections, with the settings documented there. They work on the instance the session holds, including edits that have not been saved, so no --instance-name is needed:
Finally, the very same commands can be put in a file, one per line, and run with --script:
Such a file builds an instance reproducibly and keeps a record of how it was built next to it. The session then continues at the prompt with everything the script has done, so a script can also be used to set up an instance that is afterwards worked on by hand. Empty lines and lines starting with # are ignored, and rail_cli < build_stammstrecke.rail runs a file as well, but ends when it is through.
rail_vss_generation_timetable_mip_testing adds as few VSS as possible such that the timetable of the instance can be operated exactly as specified. The model can be built at different degrees of accuracy [3]. Among others, the length of the discretized time intervals (--delta-t), whether the routes are fixed (--fix-routes), and whether train dynamics (--train-dynamics) and braking curves (--braking-curves) are respected can be chosen. How the VSS borders themselves are modelled is controlled by --vss-model-type, where all but the continuous model additionally expect separation functions given by --separation-functions.
Instead of solving the full model at once, the number of VSS per edge can be increased iteratively by --iterative-approach, which often improves the runtime significantly [4]. Independent of that, --optimality-strategy decides whether a proven optimal solution is required or whether a likely optimal one suffices, which is particularly relevant for the iterative approach.
Finally, a previously computed moving block routing of the very same instance can be used to guide the search [6]. It is loaded by passing its solution subdirectory to --moving-block-solution-subdirectory, in which case additional settings control how much of that solution is fixed and how much is only hinted to the solver.
rail_vss_generation_timetable_mip_testingBoth moving block apps solve the same problem, namely routing and scheduling the trains such that they are separated by moving block. The times given in the instance are lower bounds only, and the objective is to minimize the weighted delays at the stations and when leaving the network. Unless --allow-late-entry is used, the trains enter the network exactly at their scheduled time. The two apps only differ in the method used to solve this problem.
rail_gen_po_moving_block_mip_testing uses a MILP in which the headway constraints are separated lazily [5]. Which violated constraints are added is controlled by --lazy-constraint-selection-strategy, and which train pairs are checked at all by --lazy-train-selection-strategy. Lazy separation can also be switched off by --no-lazy-constraints, in which case the full model is passed to Gurobi upfront. Alternatively, --simplify-headway-constraints uses simplified headway constraints, which are faster to solve but might not separate the trains accurately. This is worth considering if the results are only used to make preliminary decisions.
Moreover, the delays can be bounded, either separately by --max-exit-delay and --max-station-delay or jointly by --max-delay. Finally, the granularity of the velocity extensions can be adapted by --max-velocity-delta and --velocity-refinement-strategy.
rail_gen_po_moving_block_mip_testingrail_gen_po_moving_block_astar_testing searches for such a routing using an A* search on simulated train movements [8,9]. The time step of that simulation is given by --dt. How far the trains are moved in every step is controlled by --next-state-strategy, and which heuristic estimates the remaining time by --remaining-time-heuristic-strategy. Using --time-aware-state-transitions, states that cannot lead to a better solution are not explored, which reduces the runtime drastically. If a proven optimal solution is not needed, --heuristic-weight allows to weight the heuristic, which speeds up the search while still guaranteeing an approximation factor. In contrast to the MILP, the A* search does not support bounding the delays.
rail_gen_po_moving_block_astar_testingAdditionally, one can call the public methods to create, save, load, and solve respective instances in C++ directly. For this, we refer to the source code's docstrings and example usages in the Google Tests found in the test folder.
If you have any questions, feel free to contact us via etcs..nosp@m.cda@.nosp@m.xcit..nosp@m.tum..nosp@m.de or by creating an issue on GitHub.
[1] Robert Wille and Tom Peham and Judith Przigoda and Nils Przigoda. **"Towards Automatic Design and Verification for Level 3 of the European Train Control System"**. Design, Automation and Test in Europe (DATE), 2021 (doi, pdf)
[2] Tom Peham and Judith Przigoda and Nils Przigoda and Robert Wille. **"Optimal Railway Routing Using Virtual Subsections"**. Reliability, Safety and Security of Railway Systems (RSSRail), 2022 (doi, pdf)
[3] Stefan Engels and Tom Peham and Robert Wille. **"A Symbolic Design Method for ETCS Hybrid Level 3 at Different Degrees of Accuracy"**. Symposium on Algorithmic Approaches for Transportation Modelling, Optimization, and Systems (ATMOS), 2023 (doi, pdf)
[4] Stefan Engels and Robert Wille. **"Late Breaking Results: Iterative Design Automation for Train Control with Hybrid Train Detection"**. Design, Automation and Test in Europe (DATE), 2024 (doi, pdf)
[5] Stefan Engels and Robert Wille. **"Comparing Lazy Constraint Selection Strategies in Train Routing with Moving Block Control"**. Conference on Computer Science and Intelligence Systems (FedCSIS), 2024 (doi, arXiv, pdf)
[6] Stefan Engels and Robert Wille. **"Towards an Optimization Pipeline for the Design of Train Control Systems with Hybrid Train Detection"**. Symposium on Algorithmic Approaches for Transportation Modelling, Optimization, and Systems (ATMOS), 2024 (doi, pdf)
[7] Stefan Engels and Tom Peham and Judith Przigoda and Nils Przigoda and Robert Wille. **"Design tasks and their complexity for the European Train Control System with Hybrid Train Detection"**. EURO Journal on Transportation and Logistics, 2025 (doi, arXiv, pdf)
[8] Stefan Engels and Robert Wille. **"Using A\* for Optimal Train Routing on Moving Block Systems"**. Symposium on Algorithmic Approaches for Transportation Modelling, Optimization, and Systems (ATMOS), 2025 (doi, pdf)
[9] Stefan Engels and Robert Wille. **"Time-Aware A\* for Optimal Train Routing on Moving Block Systems"**. Symposium on Algorithmic Approaches for Transportation Modelling, Optimization, and Systems (ATMOS), 2026 (doi, pdf)
[10] Gurobi Optimization, LLC. **"Gurobi Optimizer Reference Manual"**. 2026