提交 fa1a0e70 编写于 作者: Z zhangchaolong

添加遗传算法求解TSP问题代码

上级 60cb5bcf
# tsp # TSP问题的求解方法
* **data**.C-TSP问题中国34个城市的经纬度。
* **ga**.遗传算法求解TSP问题代码。
[Blog:http://zh.5long.me](http://zh.5long.me)
TSP问题博文链接:<http://zh.5long.me/2015/genetic-algorithm-on-tsp/>
北京 ;116.46;39.92 天津 ;117.2;39.13 上海 ;121.48;31.22 重庆 ;106.54;29.59 拉萨 ;91.11;29.97 乌鲁木齐 ;87.68;43.77 银川 ;106.27;38.47 呼和浩特 ;111.65;40.82 南宁 ;108.33;22.84 哈尔滨 ;126.63;45.75 长春 ;125.35;43.88 沈阳 ;123.38;41.8 石家庄 ;114.48;38.03 太原 ;112.53;37.87 西宁 ;101.74;36.56 济南 ;117;36.65 郑州 ;113.6;34.76 南京;118.78;32.04 合肥;117.27;31.86 杭州;120.19;30.26 福州;119.3;26.08 南昌;115.89;28.68 长沙;113;28.21 武汉;114.31;30.52 广州;113.23;23.16 台北;121.5;25.05 海口;110.35;20.02 兰州;103.73;36.03 西安;108.95;34.27 成都;104.06;30.67 贵阳;106.71;26.57 昆明;102.73;25.04 香港;114.1;22.2 澳门;113.33;22.13
\ No newline at end of file
# -*- coding: utf-8 -*-
import random
from Life import Life
class GA(object):
"""遗传算法类"""
def __init__(self, aCrossRate, aMutationRage, aLifeCount, aGeneLenght, aMatchFun = lambda life : 1):
self.croessRate = aCrossRate
self.mutationRate = aMutationRage
self.lifeCount = aLifeCount
self.geneLenght = aGeneLenght
self.matchFun = aMatchFun #适配函数
self.lives = [] #种群
self.best = None #保存这一代中最好的个体
self.generation = 1
self.crossCount = 0
self.mutationCount = 0
self.bounds = 0.0 #适配值之和,用于选择是计算概率
self.initPopulation()
def initPopulation(self):
"""初始化种群"""
self.lives = []
for i in range(self.lifeCount):
gene = range(self.geneLenght)
random.shuffle(gene)
life = Life(gene)
self.lives.append(life)
def judge(self):
"""评估,计算每一个个体的适配值"""
self.bounds = 0.0
self.best = self.lives[0]
for life in self.lives:
life.score = self.matchFun(life)
self.bounds += life.score
if self.best.score < life.score:
self.best = life
def cross(self, parent1, parent2):
"""交叉"""
index1 = random.randint(0, self.geneLenght - 1)
index2 = random.randint(index1, self.geneLenght - 1)
tempGene = parent2.gene[index1:index2] #交叉的基因片段
newGene = []
p1len = 0
for g in parent1.gene:
if p1len == index1:
newGene.extend(tempGene) #插入基因片段
p1len += 1
if g not in tempGene:
newGene.append(g)
p1len += 1
self.crossCount += 1
return newGene
def mutation(self, gene):
"""突变"""
index1 = random.randint(0, self.geneLenght - 1)
index2 = random.randint(0, self.geneLenght - 1)
gene[index1], gene[index2] = gene[index2], gene[index1]
self.mutationCount += 1
return gene
def getOne(self):
"""选择一个个体"""
r = random.uniform(0, self.bounds)
for life in self.lives:
r -= life.score
if r <= 0:
return life
raise Exception("选择错误", self.bounds)
def newChild(self):
"""产生新后的"""
parent1 = self.getOne()
rate = random.random()
#按概率交叉
if rate < self.croessRate:
#交叉
parent2 = self.getOne()
gene = self.cross(parent1, parent2)
else:
gene = parent1.gene
#按概率突变
rate = random.random()
if rate < self.mutationRate:
gene = self.mutation(gene)
return Life(gene)
def next(self):
"""产生下一代"""
self.judge()
newLives = []
newLives.append(self.best) #把最好的个体加入下一代
while len(newLives) < self.lifeCount:
newLives.append(self.newChild())
self.lives = newLives
self.generation += 1
\ No newline at end of file
# -*- encoding: utf-8 -*-
SCORE_NONE = -1
class Life(object):
"""个体类"""
def __init__(self, aGene = None):
self.gene = aGene
self.score = SCORE_NONE
# -*- encoding: utf-8 -*-
import random
import math
import Tkinter
from GA import GA
class TSP(object):
def __init__(self, aLifeCount = 100,):
self.initCitys()
self.lifeCount = aLifeCount
self.ga = GA(aCrossRate = 0.7,
aMutationRage = 0.02,
aLifeCount = self.lifeCount,
aGeneLenght = len(self.citys),
aMatchFun = self.matchFun())
def initCitys(self):
self.citys = []
"""
for i in range(34):
x = random.randint(0, 1000)
y = random.randint(0, 1000)
self.citys.append((x, y))
"""
#中国34城市经纬度
self.citys.append((116.46, 39.92))
self.citys.append((117.2,39.13))
self.citys.append((121.48, 31.22))
self.citys.append((106.54, 29.59))
self.citys.append((91.11, 29.97))
self.citys.append((87.68, 43.77))
self.citys.append((106.27, 38.47))
self.citys.append((111.65, 40.82))
self.citys.append((108.33, 22.84))
self.citys.append((126.63, 45.75))
self.citys.append((125.35, 43.88))
self.citys.append((123.38, 41.8))
self.citys.append((114.48, 38.03))
self.citys.append((112.53, 37.87))
self.citys.append((101.74, 36.56))
self.citys.append((117,36.65))
self.citys.append((113.6,34.76))
self.citys.append((118.78, 32.04))
self.citys.append((117.27, 31.86))
self.citys.append((120.19, 30.26))
self.citys.append((119.3, 26.08))
self.citys.append((115.89, 28.68))
self.citys.append((113, 28.21))
self.citys.append((114.31, 30.52))
self.citys.append((113.23, 23.16))
self.citys.append((121.5, 25.05))
self.citys.append((110.35, 20.02))
self.citys.append((103.73, 36.03))
self.citys.append((108.95, 34.27))
self.citys.append((104.06, 30.67))
self.citys.append((106.71, 26.57))
self.citys.append((102.73, 25.04))
self.citys.append((114.1, 22.2))
self.citys.append((113.33, 22.13))
def distance(self, order):
distance = 0.0
for i in range(-1, len(self.citys) - 1):
index1, index2 = order[i], order[i + 1]
city1, city2 = self.citys[index1], self.citys[index2]
distance += math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2)
"""
R = 6371.004
Pi = math.pi
LatA = city1[1]
LatB = city2[1]
MLonA = city1[0]
MLonB = city2[0]
C = math.sin(LatA*Pi / 180) * math.sin(LatB * Pi / 180) + math.cos(LatA * Pi / 180) * math.cos(LatB * Pi / 180) * math.cos((MLonA - MLonB) * Pi / 180)
D = R * math.acos(C) * Pi / 100
distance += D
"""
return distance
def matchFun(self):
return lambda life: 1.0 / self.distance(life.gene)
def run(self, n = 0):
while n > 0:
self.ga.next()
distance = self.distance(self.ga.best.gene)
print (("%d : %f") % (self.ga.generation, distance))
n -= 1
def main():
tsp = TSP()
tsp.run(10000)
if __name__ == '__main__':
main()
# -*- encoding: utf-8 -*-
import random
import math
import Tkinter
from GA import GA
class TSP_WIN(object):
def __init__(self, aRoot, aLifeCount = 100, aWidth = 560, aHeight = 330):
self.root = aRoot
self.lifeCount = aLifeCount
self.width = aWidth
self.height = aHeight
self.canvas = Tkinter.Canvas(
self.root,
width = self.width,
height = self.height,
)
self.canvas.pack(expand = Tkinter.YES, fill = Tkinter.BOTH)
self.bindEvents()
self.initCitys()
self.new()
self.title("TSP")
def initCitys(self):
self.citys = []
#中国34城市经纬度
self.citys.append((116.46, 39.92))
self.citys.append((117.2,39.13))
self.citys.append((121.48, 31.22))
self.citys.append((106.54, 29.59))
self.citys.append((91.11, 29.97))
self.citys.append((87.68, 43.77))
self.citys.append((106.27, 38.47))
self.citys.append((111.65, 40.82))
self.citys.append((108.33, 22.84))
self.citys.append((126.63, 45.75))
self.citys.append((125.35, 43.88))
self.citys.append((123.38, 41.8))
self.citys.append((114.48, 38.03))
self.citys.append((112.53, 37.87))
self.citys.append((101.74, 36.56))
self.citys.append((117,36.65))
self.citys.append((113.6,34.76))
self.citys.append((118.78, 32.04))
self.citys.append((117.27, 31.86))
self.citys.append((120.19, 30.26))
self.citys.append((119.3, 26.08))
self.citys.append((115.89, 28.68))
self.citys.append((113, 28.21))
self.citys.append((114.31, 30.52))
self.citys.append((113.23, 23.16))
self.citys.append((121.5, 25.05))
self.citys.append((110.35, 20.02))
self.citys.append((103.73, 36.03))
self.citys.append((108.95, 34.27))
self.citys.append((104.06, 30.67))
self.citys.append((106.71, 26.57))
self.citys.append((102.73, 25.04))
self.citys.append((114.1, 22.2))
self.citys.append((113.33, 22.13))
#坐标变换
minX, minY = self.citys[0][0], self.citys[0][1]
maxX, maxY = minX, minY
for city in self.citys[1:]:
if minX > city[0]:
minX = city[0]
if minY > city[1]:
minY = city[1]
if maxX < city[0]:
maxX = city[0]
if maxY < city[1]:
maxY = city[1]
w = maxX - minX
h = maxY - minY
xoffset = 30
yoffset = 30
ww = self.width - 2 * xoffset
hh = self.height - 2 * yoffset
xx = ww / float(w)
yy = hh / float(h)
r = 5
self.nodes = []
self.nodes2 = []
for city in self.citys:
x = (city[0] - minX ) * xx + xoffset
y = hh - (city[1] - minY) * yy + yoffset
self.nodes.append((x, y))
node = self.canvas.create_oval(x - r, y -r, x + r, y + r,
fill = "#ff0000",
outline = "#000000",
tags = "node",)
self.nodes2.append(node)
def distance(self, order):
distance = 0.0
for i in range(-1, len(self.citys) - 1):
index1, index2 = order[i], order[i + 1]
city1, city2 = self.citys[index1], self.citys[index2]
distance += math.sqrt((city1[0] - city2[0]) ** 2 + (city1[1] - city2[1]) ** 2)
return distance
def matchFun(self):
return lambda life: 1.0 / self.distance(life.gene)
def title(self, text):
self.root.title(text)
def line(self, order):
self.canvas.delete("line")
for i in range(-1, len(order) -1):
p1 = self.nodes[order[i]]
p2 = self.nodes[order[i + 1]]
self.canvas.create_line(p1, p2, fill = "#000000", tags = "line")
def bindEvents(self):
self.root.bind("n", self.new)
self.root.bind("g", self.start)
self.root.bind("s", self.stop)
def new(self, evt = None):
self.isRunning = False
order = range(len(self.citys))
self.line(order)
self.ga = GA(aCrossRate = 0.7,
aMutationRage = 0.02,
aLifeCount = self.lifeCount,
aGeneLenght = len(self.citys),
aMatchFun = self.matchFun())
def start(self, evt = None):
self.isRunning = True
while self.isRunning:
self.ga.next()
distance = self.distance(self.ga.best.gene)
self.line(self.ga.best.gene)
self.title("TSP-gen: %d" % self.ga.generation)
self.canvas.update()
def stop(self, evt = None):
self.isRunning = False
def mainloop(self):
self.root.mainloop()
def main():
#tsp = TSP()
#tsp.run(10000)
tsp = TSP_WIN(Tkinter.Tk())
tsp.mainloop()
if __name__ == '__main__':
main()
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册