[Study notes] GA solution of TSP

GA solution of TSP

Genetic Algorithms

Written before genetic algorithms for Maximizing blog, will not go into the record about solving the code for TSP.
Algorithm is very simple, only caveat is how to define the problem, said crossover operator, mutation operator and fitness function.
A water, school teacher too sleepy, listen and write -

Problem representation

Access sequence represented by a set of sequences, only three sample nodes may be represented by a set of sequences, such as [2,1,0] II represents the first access node and access node 1, node 0 was last accessed.
Therefore generate a sample directly np.random.shuffle (np.arange (n)) of the sample can be generated.

Crossover

This problem relates to the intersection between the two sequences, such as sequences [2,1,3,4,0] and the sequence [1,2,3,4,0] cross at a position between 0 to 3 but direct exchange can lead to sample the exchange of duplicate numbers, so when I designed directly shuffle these locations.
Essentially does not implement cross, but the significance of the cross is in fact the presence of both good genes retained, randomly selected location may be good genes, or may not, by cross-exchange of good genes, I actually this operation is equivalent to the local variation, but it is good for the local variation of the parent, while retaining the parent, if the mutation is not good, will be eliminated out. Although the design is not very good, but the result was the work.

Mutation operator

Mutation operator is better implemented, a randomly selected interval, can be disrupted in a random sequence interval.

Coding

import numpy as np

class GA(object):
    def __init__(self,cities,num_iters = 250):
        self.cities = cities
        self.num_iters = num_iters
        init_number = 500
        n = self.cities.shape[0]
        self.weight = np.tile(np.arange(n)[np.newaxis,:],[init_number,1]) # 种群初始化数量为100个个体
        for i in range(n):
            np.random.shuffle(self.weight[i])
        self.distance = np.zeros((n,n))
        for i in range(n):
            for j in range(n):
                self.distance[i,j] = np.linalg.norm(self.cities[i] - self.cities[j])
    def solve(self):
        for iter in range(self.num_iters):
            
            n = self.weight.shape[0]
            w = [self.fitness(self.weight[i]) for i in range(n)]
            print(sum(w) / len(w))
            w/= sum(w)
            probablity = [sum(w[:i+1]) for i in range(len(w))]
            new_x = []
            for _ in range(n):
                p = np.random.random()
                for j in range(n):
                    if j ==0:
                        if p >=0 and p <= probablity[j]:
                            temp = self.weight[j].copy()
                            q = np.random.random()
                            if q > 0.4:
                                self.variation(temp)
                            new_x.append(temp)
                            break
                    else:
                        if p >= probablity[j-1] and p <= probablity[j]:
                            temp = self.weight[j].copy()
                            q = np.random.random()
                            if q > 0.4:
                                self.variation(temp)
                            new_x.append(temp)
                            break
            fm = sorted(new_x,key = lambda x:self.fitness(x))[0:2]
            new_x.extend(self.cross(fm[0],fm[1]))
            
            self.weight = np.array(new_x)
        result = sorted(self.weight.tolist(),key = lambda x:self.fitness(x))[-1]
        print(result,1./self.fitness(result))
    @staticmethod
    def variation(x):
        n = x.shape[0]
        a = np.random.randint(0,n-1)
        b = np.random.randint(0,n-1)
        a,b = (b,a) if b<a else (a,b)
        np.random.shuffle(x[a:b])
    @staticmethod
    def cross(x,y):
        n = x.shape[0]
        a = np.random.randint(0,n-1)
        b = np.random.randint(0,n-1)
        a,b = (b,a) if b<a else (a,b)
        xx = x.copy()
        yy = y.copy()
        np.random.shuffle(xx[a:b])
        np.random.shuffle(yy[a:b])
        #xx[a:b],yy[a:b] = yy[a:b],xx[a:b]
        return [xx,yy]


    def fitness(self,x):
        n = self.cities.shape[0]
        fit = 0.
        for i in range(n):
            j = i+1 if i+1 <n else 0
            fit += self.distance[x[i],x[j]]
        return 1./fit

if __name__ == "__main__":
    #cities = np.array([[0,0],[0,1],[1,0],[1,1]])
    cities = np.array([[2,6],[2,4],[1,3],[4,6],[5,5],[4,4],[6,4],[3,2]])
    # [2, 1, 0, 3, 5, 4, 6, 7] 16.084259940083065

    solver = GA(cities)
    #print(1./solver.fitness(np.array([1,2,0,3,5,4,6,7]))) # 17.246537600251443
    #solver.solve()

result

[2, 1, 0, 3, 5, 4, 6, 7] 16.084259940083065

Hopfield feeling and networks, in fact, the results of each run are not the same, hopfield I ran a total distance is better 14.714776642118863, a little better than this, there are also run than in the case of the difference. Less run node such as four nodes, the result is absolutely correct, the node may be a bit more unstable. (Because I do not know how much more is the minimum distance /)

Guess you like

Origin www.cnblogs.com/aoru45/p/12553188.html