Skip to main content

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

  1. Clone the repository

    git clone git@github.com:mpm-tu-berlin/eflips-opt.git
    
  2. Install the packages listed in poetry.lock and pyproject.toml into your Python environment. Notes:

    • Python 3.11 to 3.15 is supported.
    • Using the poetry package manager is recommended. It can be installed according to the instructions listed here.
  3. 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)

Source distribution for eflips-opt 1.1.0
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)

Table of built distributions (wheels) for eflips-opt 1.1.0
File Interpreter ABI Platform Actions
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 log

Release 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 log

Security 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.

Select from 2 files

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 log

A 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.

Release history Release notifications | RSS feed

This release

1.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page