eflips-opt
Part of the eFLIPS/simBA list of projects.
This repository contains code for optimizing (electric) bus networks. The following optimization problems are considered:
- Depot-Rotation Matching: Given a set of depots and a set of rotations, find the optimal assignment of rotations to depots.
- Vehicle Scheduling: Given a set of trips, find the set of rotations (vehicle blocks) that serves all trips with the minimum number of vehicles, optionally respecting battery and duration limits.
- Smart Charging (
eflips.opt.smart_charging): After a simulation, smooth the depot charging events to reduce peak power.
Installation
-
Clone the repository
git clone git@github.com:mpm-tu-berlin/eflips-opt.git
-
Install the packages listed in
poetry.lockandpyproject.tomlinto your Python environment. Notes: -
In order to use the Depot-Rotation Matching, it is recommended to install the Gurobi solver. The solver can be installed by following the instructions listed here. The solver can be used with a license for academic purposes. If you do not have a license, you can request one here.
Usage
Depot-Rotation Matching
Example scripts for the Depot-Rotation Matching problem can be found in the examples/depot_rotation_matching directory.
The general usage is as follows:
from eflips.opt.depot_rotation_matching import DepotRotationOptimizer
# Initialize the optimizer
optimizer = DepotRotationOptimizer(session, SCENARIO_ID)
# Create a depot input. Both existing and new depots can be added.
user_input_depot = [
{
"depot_station": 103281393,
"capacity": 300,
"vehicle_type": [84, 86, 87, 90],
}, # Indira-Gandhi-Str
{
"name": "Suedost",
"depot_station": (13.497371828836501, 52.46541010322369),
"capacity": 260,
"vehicle_type": [82, 84, 85, 86, 87, 90],
}, # Südost
]
optimizer.get_depot_from_input(user_input_depot)
optimizer.data_preparation()
optimizer.optimize(time_report=True)
optimizer.write_optimization_results(delete_original_data=True)
Vehicle Scheduling
The scheduling problem is formulated as a directed acyclic graph: nodes are trips, edges are feasible connections between trips, weighted by the waiting time. The minimum number of rotations is a minimum path cover of this graph, which is computed by the Rust solver eflips-schedule-rust. Per-trip weights (e.g. the state-of-charge used by each trip) let the solver keep each rotation within the battery capacity and a maximum duration.
from datetime import timedelta
from eflips.opt.scheduling import (
passenger_trips_by_vehicle_type,
create_graph,
solve,
write_back_rotation_plan,
)
# Create one schedule per vehicle type, so trips of e.g. 12m and 18m buses are not mixed
trips_by_vt = passenger_trips_by_vehicle_type(scenario, session)
for vehicle_type, trips in trips_by_vt.items():
if not trips:
continue
# delta_socs: optional {trip_id: fraction of the battery used by the trip}
graph = create_graph(trips, maximum_schedule_duration=timedelta(hours=24))
rotation_graph = solve(graph, maximum_schedule_duration=timedelta(hours=24))
# Replace the scenario's original rotations with the new ones
write_back_rotation_plan(rotation_graph, session)
session.commit()
create_graph() has further parameters for break times and for preferring connections on the same line.
visualize_with_dash_cytoscape(graph) shows a graph in the browser.
Development
We utilize the GitHub Flow branching structure. This means
that the main branch is always deployable and that all development happens in feature branches. The feature branches
are merged into main via pull requests.
We use black for code formatting. You can use pre-commit to ensure the code is formatted correctly before committing. You are also free to use other methods to format the code, but please ensure that the code is formatted correctly before committing.
Please make sure that your poetry.lock and pyproject.toml files are consistent before committing. You can use poetry check to check this. This is also checked by pre-commit.
Each pull request must increase the version number in pyproject.toml (CI checks it against PyPI), following
Semantic Versioning: patch for changes without API changes, minor for backwards-compatible
API changes such as new features, major for breaking changes. Every merge to main is published to PyPI.
Tests need a PostgreSQL/PostGIS database, given in DATABASE_URL. All data in it is deleted.
DATABASE_URL=postgresql://user:password@localhost/database PYTHONPATH=tests:. poetry run pytest
License
This project is licensed under the AGPLv3 license - see the LICENSE file for details.
Funding Notice
This code was developed as part of the project eBus2030+ funded by the Federal German Ministry for Digital and Transport (BMDV) under grant number 03EMF0402.
Metadata
Release files for eflips-opt 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| eflips_opt-1.1.0.tar.gz | 43.8 kB | With provenance | Details for eflips_opt-1.1.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| eflips_opt-1.1.0-py3-none-any.whl | Python 3 | none | any | Details for eflips_opt-1.1.0-py3-none-any.whl |
Total release size: 88.6 kB
Release files / eflips_opt-1.1.0.tar.gz
| Download URL | eflips_opt-1.1.0.tar.gz |
|---|---|
| Size | 43.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9682ed74eb265aa602a9d47a8b8a8fd7968f74f0084a01f1e193b1a44ed92e1a
|
|
BLAKE2b-256 checksum How to use checksums |
5b6ac95624cadb4c5b8d3a6c977fa8ea711991ab38a1cf8878c16f9644bc6616
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logRelease files / eflips_opt-1.1.0-py3-none-any.whl
| Download URL | eflips_opt-1.1.0-py3-none-any.whl |
|---|---|
| Size | 44.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c27a230fe137d437300402f5b0f075a203a4c53f3771a475e29d136ddde9a5b5
|
|
BLAKE2b-256 checksum How to use checksums |
3076dd2f52a1bb9afb768c2935268320efb3b29874c85de9396a5fa63a11d2e2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logSecurity for eflips-opt 1.1.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for eflips_opt-1.1.0.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.