Open-source project
iRB-Lab/py-ga-VRPTW avatar
iRB-Lab/py-ga-VRPTW

py-ga-VRPTW: a readable genetic algorithm for vehicle routing with time windows

A Python Implementation of a Genetic Algorithm-based Solution to Vehicle Routing Problem with Time Windows

665 stars173 forksPythonMIT

At a glance

What is it?
py-ga-VRPTW is a Python implementation of a genetic algorithm for the vehicle routing problem with time windows, built on deap and numpy, with Solomon's benchmark instances, text and JSON instance formats and a documented API. It suits a researcher or student who wants to read and modify the operators, and its own author says the shipped examples perform poorly without tuning.
Who is it for?
Adopt py-ga-VRPTW if you want a compact, readable genetic algorithm for the vehicle routing problem with time windows that you can inspect and modify, and you are prepared to tune the parameters yourself, because the author states plainly that the shipped example results are very poor.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 42 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A course project that became a published solver

py-ga-VRPTW is a Python implementation of a genetic algorithm based solution to the vehicle routing problem with time windows. The repository tells the story of how it started, and the story is in the README rather than in a commit log.

In 2016, the author was asked by a friend majoring in logistic engineering to discuss his course work. The friend wanted to solve VRPTW using a genetic algorithm, which the author already knew, and the discussion gave the friend what he needed for the assignment. The author then implemented the approach in Python, and the first version came out that night.

That origin explains the shape of the project. This is code written to be understood rather than to be the fastest possible solver. The README has a table of contents with nine top-level entries, and it goes deep on the parts a course project would need to explain: the chromosome encoding and decoding, the evaluation function, the selection operator, the crossover operator, the mutation operator, the main algorithm loop, sample codes for named instances, the API reference for each module, the file structure and the references.

The technical stack is minimal and pinned. The requirements are Python 3.13 and pip, and the two runtime dependencies are pinned to exact versions:

python
deap==1.4.4
numpy==2.5.3

deap is the distributed evolutionary algorithms library that supplies the genetic operators, and numpy does the numeric work. Pinning both to exact versions is the right call for a research codebase where reproducibility matters more than picking up upstream improvements.

The licence is MIT, the default branch is master, and the project sits under the iRB-Lab organisation. There are no GitHub releases, so the commit history is the version history, and the last push was on 2026-09-11.

The operators: roulette wheel, partial matching crossover, inverse mutation

The README documents the algorithm in the order you would need it to read the code, and the operator choices are conventional, which is a good sign for anyone comparing it to the literature.

Selection is roulette wheel selection, where fitness is turned into selection probability in proportion to share. The individuals are called chromosomes, and the README has a dedicated section for the Individual class covering the coding and the decoding, plus a separate method for printing a route.

The evaluation function is what turns a chromosome into a cost, and it is the piece that encodes the time window constraint. In a VRPTW, a route can be short in distance and still be infeasible if a customer is served outside its window, so the evaluation has to account for waiting time and the due date at each stop, not just the distance. The README's separate treatment of evaluation, as its own section between the individual handling and the operators, reflects that it is where the problem-specific logic lives.

Crossover is Partially Matched Crossover, which is the standard way to combine two permutations without producing duplicate customers. Mutation is an inverse operation, which for a routing chromosome means reversing the order of a segment of the route, and the README calls it Mutation: Inverse Operation.

The consequence of that design is that the algorithm is fully legible. Every stage is a named piece with a section in the documentation, and the API reference breaks the package into three modules, gavrptw, gavrptw.core and gavrptw.utils, so you can see which part is the domain logic and which part is plumbing.

What you will not find in the documentation is a tuning guide. The README explains the operators, the data formats and the API, and the author's own performance note says that tuning the algorithm to yield a converged result would definitely require much more effort. So the operators are a starting point for your own experiments, not a tuned configuration.

Solomon's benchmark instances and the two file formats

The problem sets shipped with the project are Solomon's VRPTW benchmark problems, and the README includes the full description of what they are designed to expose, which is useful reading in its own right.

Solomon generated six sets of problems whose design highlights several factors affecting the behaviour of routing and scheduling algorithms: geographical data, the number of customers serviced by a vehicle, the percentage of time-constrained customers, and the tightness and positioning of the time windows. The sets are tabulated by random, clustered and random and clustered customer layouts, crossed with a short and a long scheduling horizon.

The R1, C1 and RC1 sets have a short scheduling horizon and allow only a few customers per route, approximately 5 to 10, while R2, C2 and RC2 have a long horizon permitting more than 30 customers on the same vehicle. The customer coordinates are identical for all problems within one type, the problems differ in how wide the time windows are, and time window density, the percentage of customers with time windows, was created at 25, 50, 75 and 100 percent. The larger problems are 100 customer euclidean problems where travel times equal the corresponding distances, and smaller problems were made by taking only the first 25 or 50 customers.

The text format for an instance is a fixed layout, and the README reproduces it:

bash
<Instance name>
<empty line>
VEHICLE
NUMBER     CAPACITY
  K           Q
<empty line>
CUSTOMER

Each text file is named after its instance and lives under data/text/, so the file for instance C101 is data/text/C101.txt. The notes on the format are precise: all constants are integers, customer number 0 denotes the depot where all vehicles must start and finish, K is the maximum number of vehicles, Q is the capacity of each vehicle, ready time is the earliest time at which service may start at a customer or depot, due date is the latest time at which service may start, and the value of time equals the value of distance.

That last rule is the one that catches people. Distances and times are the same number, so an instance is a pure euclidean problem, and any result you compare against must use the same convention.

JSON instances and the two conversion scripts

The project also supports a JSON format, and there are two scripts in the repository root that produce it: text2json.py and text2json_customize.py.

The plain converter handles the standard Solomon text files, and the customize variant handles customized instance data. Both are useful for a different reason than the obvious one. The text format is the format the benchmark sets ship in, and the JSON format is what you want when you are running many parameter combinations, because you can generate instances programmatically, hold them in one place and feed them to the solver without re-parsing text on every run.

The README's contents list has a nested structure for this part of the documentation: instance definitions, then text file format, then JSON format, then use customized instance data, then supported file format, then directory set-up, then convert *.txt to *.json, and then GA set-up. That ordering tells you the intended workflow. You define an instance, you express it in one of the two formats, you place the files where the solver expects them, you convert if you need to, and you configure the genetic algorithm.

The repository layout supports the same picture. There is a data/ directory for the instances, a results/ directory for output, the gavrptw/ package for the implementation, the three sample scripts named sample_R101.py, sample_C204.py and sample_customized_data.py, and the two conversion scripts at the root. The instance names in the samples are R101, which is a random, short-horizon, 100-customer instance, and C204, which is clustered, long-horizon.

The three sample scripts are the fastest way to see the whole pipeline, because they show a named benchmark instance being solved, a customized dataset being solved, and the results being written. The README also has a view logs section, so you can inspect what the run produced rather than guessing from the results directory.

The practical note is that the JSON path is a convenience feature, not a different algorithm. The same evaluation, the same operators and the same configuration apply whichever format you feed in.

The author says the examples perform poorly, and that is the point

The most valuable paragraph in this README is the one titled Performance Issue, and it deserves to be quoted rather than paraphrased, because it tells you exactly what kind of project this is.

The author writes that he wrote the project on the spur of that moment, and that after running a few tests with several combinations of parameters and set-ups he realised that implementing the idea is one thing and tuning the algorithm to yield a converged result is another thing, and that the latter would definitely require much more effort. To be precise, he says, the performances of the given examples are very poor. Tuning improvements of this algorithm and forks are always welcome.

That is an unusually candid statement from a project author, and it changes how you should read the samples. The R101 and C204 scripts demonstrate the pipeline: build a population, evaluate, select, cross over, mutate, repeat, and write out the routes and logs. They are not presented as state of the art results, and the author says so before you discover it yourself.

For a reader, the honest framing is that this is a well-documented reference implementation of the method, with a working instance pipeline and a clear operator design, whose output quality depends on tuning that has not been done here. That is exactly what a course project becomes useful for: a starting point you can tune, extend, or use as a comparison baseline.

The README also points at a fork it calls outstanding, paulliwali's py-ga-VRPTW, which is a pointer worth taking seriously, since it is the same lineage with different tuning. The topics on the repository are genetic-algorithm, python, vehicle-routing-problem, vrp and vrptw, and there is a Travis build badge for continuous integration, plus a CONTRIBUTING.md.

So the decision to adopt this project is really a decision about what you need. If you need a solver that produces good routes out of the box, this is not it, and the author has said so. If you need to understand, modify or re-implement a genetic algorithm for VRPTW in a codebase small enough to read in an afternoon, it is a good starting point.

Licence, versions and where this fits next to a solver library

The licence is MIT, with the LICENSE file at the root of the repository, and this article does not interpret it. For an academic or teaching codebase that people are invited to fork and tune, as this one is, a permissive licence is what you would expect, and it means a tuned fork can be published without a negotiation.

The versioning picture is thin in the way research code usually is. There are no GitHub releases, the default branch is master, and the last push was on 2026-09-11, with a Travis badge still in the README for the build status. The Python version is pinned hard at 3.13, and both dependencies are pinned to exact versions, deap 1.4.4 and numpy 2.5.3. That means the code is pinned to a recent interpreter and a recent numpy, which is worth knowing before you try to run it on an older environment where the array API has not kept pace.

The alternative to adopting this code is to use an existing optimisation library for the same problem, and the difference in approach is where the value sits. A general purpose solver framework gives you a maintained implementation of routing algorithms, industrial data interfaces, and in most cases a commercial or institutional support arrangement, at the cost of a configuration surface you do not control and operators you cannot read. This repository gives you the opposite: a few hundred lines of visible Python, the four operators named and documented, and an instance format you can generate yourself. The trade is entirely about who does the tuning.

The file structure section and the API reference are what make that trade work for a reader. The three modules, gavrptw, gavrptw.core and gavrptw.utils, plus the sample scripts and the data and results directories, give you a complete picture of where to change things. If your plan is to write a dissertation section, a course exercise, or a prototype that will later be replaced by a maintained solver, that is a reasonable use of this repository. If your plan is to run a delivery operation next month, the tuning work described by the author is the whole project, and you should budget for it or choose something else.

Editorial conclusion

Adopt py-ga-VRPTW if you want a compact, readable genetic algorithm for the vehicle routing problem with time windows that you can inspect and modify, and you are prepared to tune the parameters yourself, because the author states plainly that the shipped example results are very poor. Do not adopt it as a production routing solver or as a benchmark reference without running your own tuning, and do not expect the numbers in the examples to represent what the method can achieve. Verify first that your instance format matches the documented text or JSON layout, that deap and numpy versions match the pinned requirements, and that the tuning effort is in your plan, since the licence is MIT, the project has no GitHub releases, and the last push was on 2026-09-11.

Frequently asked questions

What does py-ga-VRPTW implement and what does it need?

It implements a genetic algorithm for the vehicle routing problem with time windows in Python, requiring Python 3.13 and pip, with the runtime dependencies pinned to deap 1.4.4 and numpy 2.5.3. The operators are roulette wheel selection, partially matched crossover and an inverse operation mutation.

How do I install and run py-ga-VRPTW?

The README gives a venv based flow: git clone https://github.com/iRB-Lab/py-ga-VRPTW.git, cd into the directory, python3 -m venv venv, source venv/bin/activate and pip install -r requirements.txt. The sample scripts sample_R101.py, sample_C204.py and sample_customized_data.py show how to run instances, and results are written under results/.

Which benchmark instances does py-ga-VRPTW ship with?

It ships Solomon's VRPTW benchmark problems, whose text files live under data/text/ and are named after their instance, for example data/text/C101.txt. The README also documents the JSON format and the text2json.py and text2json_customize.py conversion scripts, and notes that the value of time equals the value of distance in these instances.

How good are the results from py-ga-VRPTW?

The author states plainly that implementing the idea is one thing and tuning the algorithm to yield a converged result is another, and that to be precise the performances of the given examples are very poor. He invites tuning improvements and forks, and the README links a fork described as outstanding, paulliwali's py-ga-VRPTW.

Official sources

  1. iRB-Lab/py-ga-VRPTW on GitHub
  2. Issues
  3. License: MIT
  4. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/irb-lab-py-ga-vrptw.svg)](https://hysenlabs.com/projects/irb-lab-py-ga-vrptw)

Was this useful?