Genetic algorithm in python

I made a genetic algorithm with python when I needed it. Actually, this is changed for special use in supercomputers, so it is not versatile. .. ..

The algorithm is as follows:

GA.002.png

as a feature:

I'm wondering if the source code is here. .. .. I will not post it because it is troublesome to use. You can see it by looking at the main routine.

In the previous source code, parallel processing using multiprocessing was wrong, and it was not parallel processing. In this version, parallel processing should be possible. .. ..

ga.py


u""" Genetic Algrithm.
"""

import numpy as np
from random import random
import copy
from multiprocessing import Process, Queue
from math import exp,cos,sin,log

large= 1e+10
tiny = 1e-10
init_murate= 0.06
maxid= 0

def test_rosen(var,*args):
    import scipy.optimize as opt
    return opt.rosen(var)

def test_func(var,*args):
    x,y= var
    res= x**2 +y**2 +100*exp(-x**2 -y**2)*sin(2.0*(x+y))*cos(2*(x-y)) \
        +80*exp(-(x-1)**2 -(y-1)**2)*cos(x+4*y)*sin(2*x-y) \
        +200*sin(x+y)*exp(-(x-3)**2-(y-1)**2)
    return res

def fitfunc1(val):
    return exp(-val)

def fitfunc2(val):
    return log(1.0/val +1.0)

def dec_to_bin(dec,nbitlen):
    bin= np.zeros(nbitlen,dtype=int)
    for i in range(nbitlen):
        bin[i]= dec % 2
        dec /= 2
    return bin

def bin_to_dec(bin,nbitlen):
    dec= 0
    for i in range(nbitlen):
        dec += bin[i]*2**(i)
    return dec

def crossover(ind1,ind2):
    u"""
    Homogeneous crossover of two individuals to create a offspring
    which has some similarities to the parents.
    """
    ind= copy.deepcopy(ind1)
    nbitlen= ind.genes[0].nbitlen
    for i in range(len(ind.genes)):
        g1= ind1.genes[i]
        g2= ind1.genes[i]
        for ib in range(nbitlen):
            if g1.brep[ib] != g2.brep[ib] and random() < 0.5:
                ind.genes[i].brep[ib]= g2.brep[ib]
    return ind

def make_pairs(num):
    u"""makes random pairs from num elements.
    """
    arr= range(num)
    pairs=[]
    while len(arr) >= 2:
        i= int(random()*len(arr))
        ival= arr.pop(i)
        j= int(random()*len(arr))
        jval= arr.pop(j)
        pairs.append((ival,jval))
    return pairs

class Gene:
    u"""Gene made of *nbitlen* bits.
    """

    def __init__(self,nbitlen,var,min=-large,max=large):
        self.nbitlen= nbitlen
        self.brep = np.zeros(nbitlen,dtype=int)
        self.set_range(min,max)
        self.set_var(var)

    def set_range(self,min,max):
        self.min= float(min)
        self.max= float(max)

    def set_var(self,var):
        dec= int((var-self.min)/(self.max-self.min) *(2**self.nbitlen-1))
        self.brep= dec_to_bin(dec,self.nbitlen)

    def get_var(self):
        dec= bin_to_dec(self.brep,self.nbitlen)
        return self.min +dec*(self.max-self.min)/(2**self.nbitlen-1)

    def mutate(self,rate):
        for i in range(self.nbitlen):
            if random() < rate:
                self.brep[i] = (self.brep[i]+1) % 2



class Individual:
    u"""Individual made of some genes which should return evaluation value..
    """

    def __init__(self,id,ngene,murate,func,*args):
        self.id= id
        self.ngene= ngene
        self.murate= murate
        self.func= func
        self.args= args
        self.value= 0.0

    def set_genes(self,genes):
        if len(genes) != self.ngene:
            print "{:*>20}: len(genes) != ngene !!!".format(' Error')
            exit()
        self.genes= genes

    def calc_func_value(self,q):
        u"""
        calculates the value of given function.
        """
        vars= np.zeros(len(self.genes))
        for i in range(len(self.genes)):
            vars[i]= self.genes[i].get_var()
        val= self.func(vars,self.args)
        q.put(val)
        #self.value= self.func(vars,self.args)
        print ' ID{:05d}: value= {:15.7f}'.format(self.id,val)

    def mutate(self):
        for gene in self.genes:
            gene.mutate(self.murate)

    def set_mutation_rate(self,rate):
        self.murate= rate

    def get_variables(self):
        vars= []
        for gene in self.genes:
            vars.append(gene.get_var())
        return vars


class GA:
    u""" Genetic Algorithm class.
    """

    def __init__(self,nindv,ngene,nbitlen,func,vars,vranges,fitfunc,*args):
        u"""Constructor of GA class.

        func
          function to be evaluated with arguments vars and *args.

        fitfunc
          function for fitness evaluation with using function value obtained above.
        """
        self.nindv= nindv
        self.ngene= ngene
        self.nbitlen= nbitlen
        self.func= func
        self.vars= vars
        self.vranges= vranges
        self.fitfunc= fitfunc
        self.args= args
        self.create_population()

    def keep_best_individual(self):
        vals= []
        for i in range(len(self.population)):
            vals.append(self.population[i].value)
        idx= vals.index(min(vals))
        self.best_individual= copy.deepcopy(self.population[idx])

    def create_population(self):
        u"""creates *nindv* individuals around the initial guess."""
        global maxid
        self.population= []
        #.....0th individual is the initial guess if there is
        ind= Individual(0,self.ngene,init_murate,self.func,self.args)
        genes=[]
        for ig in range(self.ngene):
            g= Gene(self.nbitlen,self.vars[ig]
                    ,min=self.vranges[ig,0],max=self.vranges[ig,1])
            genes.append(g)
        ind.set_genes(genes)
        self.population.append(ind)
        #.....other individuals whose genes are randomly distributed
        for i in range(self.nindv-1):
            ind= Individual(i+1,self.ngene,init_murate,self.func,self.args)
            maxid= i+1
            genes= []
            for ig in range(self.ngene):
                g= Gene(self.nbitlen,self.vars[ig]
                        ,min=self.vranges[ig,0],max=self.vranges[ig,1])
                #.....randomize by mutating with high rate
                g.mutate(0.25)
                genes.append(g)
            ind.set_genes(genes)
            self.population.append(ind)
        
    def roulette_selection(self):
        u"""selects *nindv* individuals according to their fitnesses
        by means of roulette.
        """
        #.....calc all the probabilities
        prob= []
        for ind in self.population:
            prob.append(self.fitfunc(ind.value))
        print prob

        self.keep_best_individual()

        istore=[]
        for i in range(len(self.population)):
            istore.append(0)
        print istore

        for i in range(self.nindv):
            ptot= 0.0
            for ii in range(len(self.population)):
                if istore[ii] == 1: continue
                ptot += prob[ii]
            prnd= random()*ptot
            ptot= 0.0
            for ii in range(len(self.population)):
                if istore[ii] == 1: continue
                ptot= ptot +prob[ii]
                #print ii,prnd,ptot
                if prnd < ptot:
                    istore[ii]= 1
                    break
        print istore

        while istore.count(0) > 0:
            idx= istore.index(0)
            del self.population[idx]
            del istore[idx]

        if len(self.population) != self.nindv:
            print "{:*>20}: len(self.population != self.nindv) !!!".format(' Error')
            print len(self.population), self.nindv
            exit()

    def run(self,maxiter=100):
        u"""main loop of GA.
        """
        global maxid
        #.....parallel processes of function evaluations
        prcs= []
        qs= []
        for i in range(self.nindv):
            qs.append(Queue())
            prcs.append(Process(target=self.population[i].calc_func_value
                                ,args=(qs[i],)))
        for p in prcs:
            p.start()
        for p in prcs:
            p.join()
        for i in range(self.nindv):
            self.population[i].value= qs[i].get()

        for it in range(maxiter):
            print ' step= {:8d}'.format(it+1)
            #.....give birth to some offsprings by crossover
            pairs= make_pairs(self.nindv)
            for pair in pairs:
                new_ind= crossover(self.population[pair[0]],
                                   self.population[pair[1]])
                maxid += 1
                new_ind.id= maxid
                self.population.append(new_ind)
            #.....mutation of new born offsprings
            for i in range(self.nindv,len(self.population)):
                self.population[i].mutate()
            #.....evaluate function values of new born offsprings
            prcs= []
            qs= []
            j=0
            for i in range(self.nindv,len(self.population)):
                qs.append(Queue())
                prcs.append(Process(target=self.population[i].calc_func_value,
                                    args=(qs[j],)))
                j += 1
            for p in prcs:
                p.start()
            for p in prcs:
                p.join()
            j=0
            for i in range(self.nindv,len(self.population)):
                self.population[i].value= qs[j].get()
                j += 1
            #.....selection
            self.roulette_selection()
            #.....output the current best if needed
            self.out_current_best()
        print ' Best record:'
        best= self.best_individual
        print '  ID= {:05d}'.format(best.id)
        print '  value= {:15.7f}'.format(best.value)
        print '  variables= ',best.get_variables()

    def out_current_best(self):
        best= self.best_individual
        print ' current best ID{:05d}, '.format(best.id) \
            +'value= {:15.7f}'.format(best.value)
        f=open('out.current_best','w')
        f.write('ID= {:05d}\n'.format(best.id))
        f.write('value= {:15.7f}\n'.format(best.value))
        f.write('variables:\n')
        vars= best.get_variables()
        for var in vars:
            f.write('{:15.7e}\n'.format(var))
        f.close()

if __name__ == '__main__':
    vars= np.array([0.1,0.2])
    vranges= np.array([[-5.0,5.0],[-5.0,5.0]])
    ga= GA(10,2,16,test_func,vars,vranges,fitfunc1)
    ga.run(20)

Recommended Posts

Genetic algorithm in python
Algorithm in Python (Bellman-Ford)
Algorithm in Python (Dijkstra's algorithm)
Python algorithm
Reproduce Euclidean algorithm in Python
Algorithm in Python (binary search)
Implement Dijkstra's Algorithm in python
I tried to implement GA (genetic algorithm) in Python
Algorithm in Python (breadth-first search, bfs)
Sorting algorithm and implementation in Python
Write A * (A-star) algorithm in Python
Develop an investment algorithm in Python 2
Algorithm in Python (depth-first search, dfs)
Implementing a simple algorithm in Python 2
Algorithm (segment tree) in Python (practice)
Run a simple algorithm in Python
Quadtree in Python --2
Python in optimization
CURL in python
Metaprogramming in Python
Python 3.3 in Anaconda
Geocoding in python
SendKeys in Python
Meta-analysis in Python
Python memorandum (algorithm)
Unittest in python
Epoch in Python
Discord in Python
Sudoku in Python
DCI in Python
quicksort in python
nCr in python
N-Gram in Python
Programming in python
Plink in Python
Constant in python
Lifegame in Python.
FizzBuzz in Python
Sqlite in python
StepAIC in Python
N-gram in python
LINE-Bot [0] in Python
Csv in python
Disassemble in Python
Reflection in Python
Constant in python
nCr in Python.
format in python
Scons in Python3
Puyo Puyo in python
python in virtualenv
PPAP in Python
Quad-tree in Python
Reflection in Python
Chemistry in Python
Hashable in python
DirectLiNGAM in Python
LiNGAM in Python
Flatten in python
flatten in python
Ant book in python: Sec.2-5 Dijkstra's algorithm