Skip to main content

KAYROS — exact & anytime solver for duration-minimization time-dependent vehicle routing (TDVRPTW / TDVRP)

Project description

KAYROS

PyPI SWH

KAYROS is an exact & anytime solver for duration-minimization time-dependent vehicle routing problems — TDVRPTW (with time windows) and TDVRP — benchmarked on the canonical MAMUT-routing TD instance families.

The name is a nod to Kairos, the ancient Greek notion of the right, opportune moment, fitting for a time-dependent solver where when each route departs is itself a decision. It is also a recursive acronym: Kayros Anytime-Yielding Routing Optimization Solver.

Status: alpha, under active development as part of a PhD. v0.4.0 ships two anytime heuristics — TD-ILS (single-trajectory iterated local search, the default) and TD-ACO, both over the same time-dependent granular local search; together they produced the large majority of the MAMUT store's best-known solutions. The exact branch-price-and-cut component (kayros.lera) certified 334 of them optimal.

Install

pip install kayros

This pulls everything, including the benchmark loaders and the reference checker (mamut-routing-lib). For development:

git clone https://github.com/0nyr/kayros && cd kayros
pip install -e . --group dev    # pip >= 25.1 (or: uv pip install -e . --group dev)

Requirements: Python ≥ 3.11. Building from source (sdist or checkout) additionally needs a C++23 compiler, CMake ≥ 3.26 (fetched automatically by the build backend when missing) and Boost.Graph headers+library; the HiGHS LP solver is fetched and built statically by CMake when no install is found.

Usage

Anytime heuristic solve — construction + ant colony + local search, streaming every new incumbent:

import kayros

# Any MAMUT-routing TD instance (.vrp.json with its .atf.json sidecar next to it)
instance_path = "benchmarks/TDVRPTW/Dabia2013/n=25/C101.vrp.json"
solution = kayros.solve(instance_path, time_limit=10.0, seed=42)
print(solution.duration, solution.num_routes, solution.status)

# Anytime: react to every new incumbent while the solve keeps running
def on_incumbent(incumbent, routes):
    print(f"[{incumbent.seconds:7.2f}s] {incumbent.value:.6f} ({incumbent.origin})")

solution = kayros.solve(instance_path, time_limit=60.0, on_incumbent=on_incumbent)

# Strategy (0.4.0): "ils" (single-trajectory iterated local search — the
# default), "aco" (the historical default through 0.3.x), or "aco+ils"
# (budget split, experimental).
solution = kayros.solve(instance_path, kayros.Params(strategy="aco"), time_limit=60.0)

Behavior changes in 0.4.0: (1) the default strategy is now "ils" — a 20,808-run head-to-head campaign (5 TD families, n=10..1000, equal time limits and seeds) had ILS beat ACO on 5714 of 6936 paired cells vs 305 losses, with the margin growing with instance size (−4.5% to −5.4% on n=200..1000); set Params(strategy="aco") to restore the 0.3.0 solver. Without a time limit the ILS run is bounded at five restart windows (5 * restart_no_improvement iterations). (2) The local search of every strategy now enumerates moves over granular candidate lists (num_neighbours=50, a time-dependent Vidal-style proximity) instead of exhaustive scans — up to ~13x faster descents at n=1000 for a sub-percent quality gap. Set Params(num_neighbours=0) to restore the 0.3.0 exhaustive enumeration.

Exact solve — branch-price-and-cut with checker-exact certificates, optionally warm-started from a known solution (the fast path when certifying near-optimal solutions, e.g. stored best-known ones):

from mamut_routing_lib.td import load_td_instance
from kayros.lera import solve_duration

loaded = load_td_instance(instance_path)
result = solve_duration(loaded, time_limit_s=600.0,
                        initial_routes=[list(r) for r in solution.routes])
print(result["exact_log"]["status"], result["value"])
# status == "Optimum" with routes == [] means: the warm-start solution itself
# is proven optimal. On a time limit, result["exact_log"]["best_bound"] is a
# valid global lower bound when the root relaxation finished (absent otherwise).

solution.duration and result["value"] are always values computed by the reference checker (mamut_routing_lib.td.check_td_solution) — never an internal approximation.

Design

KAYROS is two solving modes on one exact time-dependent engine:

  • The engine (cpp/pwlf, cpp/core) represents arrival times as non-decreasing continuous piecewise-linear functions (NDCPWLF) and evaluates routes by exact function composition — a bit-identical C++ port of the reference checker's arithmetic (gated by an equivalence suite over the full benchmark set).
  • The anytime stack (kayros.solve): greedy construction and two search strategies — a MAX-MIN TD ant colony and a single-trajectory TD iterated local search (granular ruin-and-recreate kicks, late-acceptance hill climbing, restart-to-best) — over one time-dependent local-search layer using LCA-BST move evaluation (Blauth et al. 2024) with granular candidate lists: tree-ranked relocate/swap/2-opt* where every accepted move is repriced by the checker-identical fold before it counts.
  • The exact component (kayros.lera): the branch-price-and-cut solver of Lera-Romero, Rönnqvist & Ljungqvist (2020), vendored under cpp/lera/ (see its NOTICE.md) on the open-source HiGHS LP backend, extended with deadline-compliant anytime behavior, warm starts through columns, TDVRP support, and honest time-limit gap reporting. Every column entering the master problem is repriced in the checker's arithmetic, so reported values — and optimality certificates — are checker-exact: optimal under checker-exact route costs and standard LP/pricing tolerances, completeness modulo the search engine's epsilon dominance.

Core principles

  • The checker is the referee. Every solution and every certificate is priced by the reference checker of mamut-routing-lib; the checker's value is the value.
  • Exact arithmetic. Plain IEEE-754 doubles, no epsilon comparisons in the engine, no FMA contraction (-ffp-contract=off); results are bit-reproducible across machines.
  • Anytime first. Time budgets are hard deadlines honored by every component (heuristics and exact search alike), and incumbents stream out as they are found — a solver that only answers at the end is not a solver you can interrupt.
  • One-command install, no proprietary dependency. The default build — including the exact component — is pure open source; HiGHS is built statically into the wheels. The faster CPLEX backend for the BPC remains strictly a source-build opt-in (-DLERA_LP_BACKEND=cplex) and never ships in wheels.
  • One run is one thread. No intra-run parallelism; parallelism belongs to the experiment layer above.
  • POD core. The fresh C++ is plain structs, flat arrays and free functions — optimization-kernel style, no framework (the vendored BPC keeps its upstream style, contained under cpp/lera/).

Archival and reproducibility

kayros is archived by Software Heritage; the badge above tracks the archive status of the GitHub origin (archived origin, archival visits). For academic referencing, prefer Software Heritage identifiers (SWHIDs) of the exact archived revision or release tag over the moving repository origin — when reporting computational results, cite both the kayros release used and the MAMUT-routing benchmark artifacts it was run on.

Provenance

KAYROS is developed by Florian Rascoussier (Onyr) as part of a PhD in operations research (IMT Atlantique / INSA Lyon), under the supervision of Romain Billot, Christine Solnon and Lina Fahed. The NDCPWLF composition engine follows Visser & Spliet (2020)'s move-evaluation theorems; the local-search move evaluation follows Blauth et al. (2024); the exact component vendors the branch-price-and-cut solver of Lera-Romero, Rönnqvist & Ljungqvist (2020, MIT-licensed — provenance and local modifications documented in cpp/lera/NOTICE.md); the TD-ACO is a rewrite of the author's heuristic layer originally built on that same solver. MIT license.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kayros-0.4.0.tar.gz (329.8 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

kayros-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

kayros-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

kayros-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (22.3 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file kayros-0.4.0.tar.gz.

File metadata

  • Download URL: kayros-0.4.0.tar.gz
  • Upload date:
  • Size: 329.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for kayros-0.4.0.tar.gz
Algorithm Hash digest
SHA256 24af44658187869ff972736887b43eb54ad01a2fac45f15f492af911e59eb21e
MD5 aabe50912970fdba896c28656c338643
BLAKE2b-256 c51606e32f9f114fb31a25a6269b31ebd597afaa5ac41165a8277d09e3ac1880

See more details on using hashes here.

Provenance

The following attestation bundles were made for kayros-0.4.0.tar.gz:

Publisher: publish.yml on 0nyr/kayros

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kayros-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kayros-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ba1361146db4760317e8d265122f9309302c8de13902c644e0ba039355579f49
MD5 98954c6b00395003cd40a82c8184b4f4
BLAKE2b-256 b6c5a65b5ef4e619714511f5eddd48bc0a907f643ab211ba0df307bcd1cc0d19

See more details on using hashes here.

Provenance

The following attestation bundles were made for kayros-0.4.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on 0nyr/kayros

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kayros-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kayros-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 546015bbff883264f59193ecdb166fc511c7a0f83d1f21a621b68e4a7491125f
MD5 373782317090c4b9a368f4b8526e4b59
BLAKE2b-256 5e6f87aec2381d94d08fe66b7e2f36dc14c8007694c669a26baccef3a32eaed3

See more details on using hashes here.

Provenance

The following attestation bundles were made for kayros-0.4.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on 0nyr/kayros

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kayros-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for kayros-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 383f879dd9a5753ebebe1db531d613e689d6e04c85da33ad79b0591207632139
MD5 7b0856fe493f761afcf5fa15d88874ed
BLAKE2b-256 8e86b76e5cc6b3bc1c1f6475ab4622c8637f32ee3d04a138ec20f84453d655f5

See more details on using hashes here.

Provenance

The following attestation bundles were made for kayros-0.4.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: publish.yml on 0nyr/kayros

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page