Multi type of capacitated vehicle routing problem with a Genetic Algorithm (GA) and Deap library in python.
By: Marouane Najid
Tags: Shipping, Optimization, Genetic Algorithm, Metaheuristics, Python

Multi type of capacitated vehicle routing problem

In this application, I’ll try to solve a multi type of capacitated vehicle open routing problem (MCORT) using a genetic algorithm and Deap library in python.

The vehicle routing problem (VRP) is an optimization problem that asks, What is the optimal set of routes for a fleet of vehicles to traverse in order to deliver to a given set of customers?.. The objective of the VRP is to minimize the total route cost and the number of vehicles.

Also in this case we are dealing with ships not vehicles (just for the fun)

Hypothesis:

We are dealing with only one order

No time windows within which the deliveries (or visits) must be made.

Ships are not required to return to the depot (open routing problem).

Objective:

finding the shortest path that Minimizes the global transportation cost based on the global distance

Minimize and optimize the number of ships needed to serve the customer

While the most important parts of our GA is built from scratch, we’ll use a few standard packages to make things easier:

Create the initial map

We first create a map that gives the distance between every two points (for an impossible road we give it a very large number). the p_inf controls the percentage of impossible roads. This function returns an N by N matrix.

We create now a Navire class that will allow us to create and handle our navies.

To evaluate our solution we need to create a fitness function. To do so, because this is a minimizing multi objective problem, we associate each impossible solution with a very large number. This function returns a tuple that contains the route distance and the number of ships.

Create population

Our genotype (how the solution will be coded) will contain three parts, the first one is the road that all the navies will follow, the second one will be a list of four elements each one represent the chosen number of each type of navies for the trip, and the third part represents how the order will be distributed on the different types of ships.

ADD A PICTURE

We now create a function that distributes the order on the different types of ships. First of all, we select a random type of navie and we try to fill it up with the order, if it’s not sufficient we fill the available capacity and we complete with another type who is also chosen randomly.

We now can make our initial population (aka first generation). To do so, we need a way to create a function that produces a chromosome that follows our genotype.

the first part is the road that will follow all the ships starting from depart to arrivee (this means all the roads start by departure and end by arrival), the second part of our chromosome is created by choosing for each type of ship a random number between zero and the max number of ships that satisfy the order, and the last part is the distribution of the order on the ships.

Note: We only have to use these functions to create the initial population. Subsequent generations will be produced through crossover and mutation.

Genetic operators

Selection

We are going to proceed with the NSGA (nondominated sorting genetic algorithm) which is already implemented in the Deap library.

crossover

With the population created, we can create the next generation by breeding our solutions. We simply pick two crossover points and splice the two lists together to produce an offspring.

Mutation

Mutation helps to avoid local convergence by introducing some randomness to our chromosomes that will allow us to explore other parts of the solution space.

Note: we specify a probability of having a crossover and mutation.

Another design feature to consider is the use of elitism. With elitism, the best performing individuals from the population will automatically carry over to the next generation, ensuring that the most successful individuals persist.

Statistics

To keep an eye on the evolution of the generations, we are going to use the statistical tools implemented in the Deap library

Setting parameters

we set tuning parameters for our genetic algorithms, and we are also going to fix our initial map (for this example, departure is the node number 0 and the arrival is the node 5).

Run the evolution

let's put all the parts together and run the evolution

Results

we plot the results of each generation

Conclusion

I hope this was a fun, hands-on way to learn how to build your own GA. Try it for yourself and see how fast it goes. Or go further and try to implement a GA on another problem set (More complicated one to see the limits); see how you would change the genetic operators (crossovers, mutation, selection, …) to handle other types of chromosomes. We’re just scratching the surface here!