Adding a new algorithmΒΆ

In this tutorial we will learn how to code a simple optimization algorithm. We will write the algorithm so that it manage multi-objective, mixed_int, constrained optimization as this will allow us to explain all the basic PyGMO functioning. Clearly our algorithm will not be very good ... a random search always useful to benchmark against :)

In a nutshell ... we will write a class deriving from PyGMO.algorithm.base and reimplement some of its ‘virtual’ methods, the main one being evolve!!!

class my_algorithm(base):
     """
     Monte-Carlo (random sampling) algorithm implemented purely in Python.
     """

     def __init__(self,iter = 10):
             """
             Constructs a Monte-Carlo (random sampling) algorithm

             USAGE: algorithm.my_algorithm(iter = 10)

             NOTE: At the end of each iteration, the randomly generated
                     point substitutes the worst individual in the population if better

             * iter: number of random samples
             """
             #We start calling the base constructor
             super(my_algorithm,self).__init__()
             #We then define the algorithm 'private' data members
             self.__iter = iter

     #This is the 'juice' of the algorithm, the method where the actual optimzation is coded.
     def evolve(self,pop):
             #If the population is empty (i.e. no individuals) nothing happens
             if len(pop) == 0:
                     return pop

             #Here we rename some variables, in particular the problem
             prob = pop.problem
             #Its dimensions (total and continuous)
             dim, cont_dim = prob.dimension, prob.dimension - prob.i_dimension
             #And the lower/upper bounds for the chromosome
             lb, ub = prob.lb, prob.ub
             import random

             #The algorithm now starts manipulating the population
             for _ in range(self.__iter):
                     #We create a random vector within the bounds ... first the continuous part
                     tmp_cont = [random.uniform(lb[i],ub[i]) for i in range(cont_dim)]
                     #then the integer part
                     tmp_int = [float(random.randint(lb[i],ub[i])) for i in range(cont_dim,dim)]
                     #and we assemble them into one decision vector
                     tmp_x = tmp_cont + tmp_int
                     #which we push back in the population
                     pop.push_back(tmp_x)
                     #to then remove the worst individual
                     pop.erase(pop.get_worst_idx())
             #at the end of it all we return the 'evolved' population
             return pop

     def get_name(self):
             return "Monte Carlo (Python)"

     def human_readable_extra(self):
             return "n_iter=" + str(self.__n_iter)

The above code contains a lot of interesting points worth to be discussed. So, we start

  • In PyGMO the decision vector (chromosome) is represented as an n-tuple. Its dimension and structure depends on the problem. Its dimension will be problem.dimension, the first prob.dimension - prob.i_dimension components will be continuous, the remaining problem.i_dimension will instead be integers.
  • When a chromosome is pushed back in a population, the domination count and the domination list (data members) are automatically updated
  • The get_worst_idx method sort the population with respect to the domination count, then domination list size (in inverse order)