import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import matplotlib as mt
R = 6371 # 地球距离
# 参数
citys = 34 # 染色体DNA长度
pc = 0.1
pc = 0.2 # 交叉概率
pc = 0.3 # 交叉概率
pm = 0.12 # 变异概率
popsize = 500 # 种群规模
iternum = 1000 # 迭代次数
Fitness_choice = [100**0,100**1,100**2,(100**3)/2,100**3,2*100**4]
def Setdistance(file = 'D:/python/pycharm/pythonProject1/file/x_y.txt'):
fi = open(file,'rt',encoding = 'UTF-8');txt = fi.readlines()
spots = [];X_Y = []
for i in range(len(txt)):
txt[i] = txt[i].rstrip('\n')
if i%2 == 0:
spots.append(txt[i])
else:
X_Y.append(txt[i])
for i in range(len(X_Y)):
x_y =[eval(i) for i in X_Y[i].split(',')]
X_Y[i] = x_y
global cities
cities = pd.DataFrame({'spot':spots,'x_y':X_Y})
Setdistance()
fi = open('distance.csv','rt');Distance = np.array([[eval(j) for j in i.strip('\n').split(',')] for i in fi.readlines()])
class GA(object):
def __init__(self, citys, pc, pm, popsize, ):
self.citys = citys
self.pc = pc
self.pm = pm
self.popsize = popsize
self.pop = np.vstack([np.random.permutation(citys) for _ in range(popsize)])
def translateDNA(self, DNA, city_position):
lineX = np.empty_like(DNA, dtype=np.float64)
lineY = np.empty_like(DNA, dtype=np.float64)
for i, d in enumerate(DNA):
city_coord = city_position[d]
lineX[i, :] = city_coord[:, 0]
lineY[i, :] = city_coord[:, 1]
return lineX, lineY
def getdist(self,x_y1,x_y2):
return R * np.arccos(np.cos(np.radians(x_y1[1])) * np.cos(np.radians(x_y2[1])) * np.cos(np.radians(x_y1[0]- x_y2[0])) + np.sin(np.radians(x_y1[1])) * np.sin(np.radians(x_y2[1])))
def getFitness(self, lineX, lineY):
totalDis = np.empty((lineX.shape[0],), dtype=np.float64)
for j, (xval, yval) in enumerate(zip(lineX, lineY)):
sum = 0
for i in range(len(xval)-1):
sum += self.getdist((xval[i],yval[i]),(xval[i+1],yval[i+1]))
sum += self.getdist((xval[len(xval)-1],yval[len(xval)-1]),(xval[0],yval[0]))
totalDis[j] = sum
TotalDis = totalDis.copy()
Dissort = sorted(TotalDis,reverse=True);m1 = Dissort[int(self.popsize/5)];m2 = Dissort[int(self.popsize/3)];m3 = Dissort[int(4*self.popsize/5)];m4 = Dissort[int(99*self.popsize/100)+1];m5 = Dissort[-3]
m = [m1,m2,m3,m4,m5]
Fitness = np.zeros_like(totalDis)
count = 4
for i in Fitness_choice[4::-1]:
Fitness[TotalDis>m[count]] = i
count -= 1
Fitness[TotalDis<=m[4]] = Fitness_choice[5]
return Fitness, totalDis
def selection(self, fitness):
idx = np.random.choice(np.arange(self.popsize), size=self.popsize, replace=True, p=fitness / fitness.sum())
return self.pop[idx]
def crossover(self, parent, pop):
if np.random.rand() < self.pc:
i = np.random.randint(0, self.popsize, size=1) # 随机选取一个个体进行交换
if np.random.rand() < 0.3:
cross_points = np.random.randint(0, 2, self.citys).astype(np.bool) # 随机