#coding=utf-8
import matplotlib.pyplot as plt
import math
import time
import random
x = [4475,4475,4475,4475,5450,5475,5475,4575,5425,5425,5425,5425,5425,6000,6375,6000,6375,6475,6475,6475,6475,6100,6350,6350,6100,6550,5775,6075,6375,6375,6075,5775,6975,6675,6675,6875,6850,6600,6600,6850,7100,7100,7100,7100,7100,6925,6925,6925,6925,6925,6925,7700,7850,7700,7750,8125,8500,8500,7600,8350,7975,8350,9375,9531,9475,9275,10375,9687,9843,9999,10155,10311,10467,10623,10779,10935,11091,11247,11403,11559,11175,11275,10650,11275,11125,11025,11000,11000,11650,11725,12500,11715,11871,12027,12183,12339,12495,12651,12807,12963,13325,13100,12825,12850,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585,13585]
y = [8657,8969,9407,9719,10475,9750,8650,8425,3300,3000,2400,2100,1800,2375,2375,3375,3375,4675,4875,5275,5475,6675,6675,7275,7275,7625,8650,8650,8650,9750,9750,9750,9750,9750,8650,8650,7275,7275,6675,6675,5425,5275,5075,4875,4675,3300,3000,2700,2400,2100,1800,3725,3700,4725,7475,7525,7475,8225,9025,9025,9075,9775,11225,11225,10275,10050,9525,11225,11225,11225,11225,11225,11225,11225,11225,11225,11225,11225,11225,11225,9800,9475,9400,9175,5350,4750,4600,3600,3350,4825,5950,11225,11225,11225,11225,11225,11225,11225,11225,11225,6100,4625,3800,2425,1975,2131,2287,2443,2599,2755,2911,3067,3223,3379,9615,9771,9927,10083,10239,10395,10551,10707,10863,11019]
n = len(x)
bestway = [i for i in range(n)]
dis_array = [[0]*n for i in range(n)]
#绘制最优路径
def draw_bestway():
best_x = []
best_y = []
for i in range(n):
p = bestway[i]
best_x.append(x[p])
best_y.append(y[p])
best_x.append(best_x[0])
best_y.append(best_y[0])
plt.rcParams['font.sans-serif'] = 'SimHei'
plt.title("TSP图解")
plt.plot(best_x,best_y,color="green",linestyle="-",marker="o",markerfacecolor="red")
plt.show()
##计算最优路径分值
def comp_bestway_score():
best_x = []
best_y = []
for i in range(n):
p = bestway[i]
best_x.append(x[p])
best_y.append(y[p])
value=0.0
for i in range(1,n):
x2 = (best_x[i - 1] - best_x[i]) * (best_x[i - 1]-best_x[i])
y2 = (best_y[i - 1] - best_y[i]) * (best_y[i - 1] - best_y[i])
value = value + math.sqrt(x2 + y2)
x2 = (best_x[0] - best_x[n - 1]) * (best_x[0] - best_x[n - 1])
y2 = (best_y[0] - best_y[n - 1]) * (best_y[0] - best_y[n - 1])
value = value + math.sqrt(x2 + y2)
return(value)
##建立距离矩阵
def build_dis_array():
for i in range(n):
for j in range(n):
dis_array[i][j]=math.sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]))
#打印距离矩阵
def print_dis_array():
for i in range(n):
for j in range(n):
print('%.2f' % dis_array[i][j], end=',')
print()
#贪心算法求解TSP
def greedy():
#选择相邻距离最近的两个结点作为最初的线段
min_dis = 10000
way = []
run_array = [[0]*n for i in range(n)]#复制距离矩阵,在该矩阵上寻找新的最短路径结点
for i in range(n):
for j in range(n):
run_array[i][j] = dis_array[i][j]
#在运行矩阵上寻找相邻距离最近的两个结点
for i in range(1,n):
for j in range(i):
if(run_array[i][j]>0 and run_array[i][j]<min_dis):
min_dis=run_array[i][j]
min_a=i
min_b=j
way.append(min_a)
way.append(min_b)
run_array[min_a][min_b]=0#访问过的路径在矩阵中置0,禁止再次访问
run_array[min_b][min_a]=0#访问过的路径在矩阵中置0,禁止再次访问
#从两端在未访问的结点中选择最近的结点扩展,直到所有结点均已访问
for i in range(n-2):
min_dis=10000
# 搜索与当前路径最左侧结点相邻的结点,寻找最近的结点
for j in range(n):
if(run_array[j][way[0]]>0 and run_array[j][way[0]]<min_dis):
min_dis = run_array[j][way[0]]
min_a = j
min_b = way[0]
# 搜索与当前路径最右侧结点相邻的结点,寻找最近的结点
for j in range(n):
if(run_array[way[len(way)-1]][j]>0 and run_array[way[len(way)-1]][j]<min_dis):
min_dis = run_array[way[len(way)-1]][j]
min_a = way[len(way)-1]
min_b = j
# 如果最近的结点是在右端,则插入右端,并将新变成中间结点的原尾结点与其他所有结点距离置0,表示不可访问
if(min_a==way[len(way)-1]):
way.append(min_b);run_array[way[0]][min_b]=0;run_array[min_b][way[0]]=0
for j in range(n):
run_array[min_a][j]=0;run_array[j][min_a]=0
# 如果最近的结点是在左端,则插入左端,并将新变成中间结点的原头结点与其他所有结点距离置0,表示不可访问
else:
way.insert(0,min_a);run_array[way[len(way)-1]][min_a]=0;run_array[min_a][way[len(way)-1]]=0
for j in range(n):
run_array[min_b][j]=0;run_array[j][min_b]=0
for i in range(n):
bestway[i]=way[i]
#模拟退火算法
#利用温度控制逐步减少接受差解的概率,最终达到局部最优
def sa():
obway = [0]*n#保存当前全局最优解
t = 20
tf = 0.001
obscore = comp_bestway_score() #obscore保存全局最优值
for i in range(n):
obway[i] = bestway[i]
f1 = obscore#f1保存当前解分值
while t > tf :
for iter in range(10):# iter为等温过程迭代次数
v1 = random.randint(0,n-1)
v2 = random.randint(0,n-1)
if(v1!=v2):#随机选择两个不同的结点
bestway[v1],bestway[v2]= bestway[v2],bestway[v1]#交换随机选择的两个节点
f2 = comp_bestway_score()#计算候选解的分值,f2保存候选解
if(f2 < obscore):#如果候选解分值优于全局最优解,则更新全局最优解
obscore = f2
for i in range(n):
obway[i]=bestway[i]
delta = f2 -f1#计算候选解与当前解之间的差值
alpha = random.random()
if(delta<0):#直接接受候选解
f1 = f2
elif(alpha < math.exp(-delta / t)):#根据Metropolis准则接受交换
f1 =f2
else:#不接受候选解,回退到当前解
bestway[v2], bestway[v1] = bestway[v1],bestway[v2]
t = t * 0.995#降温
#禁忌算法
def tabu():
tabu_long=5;
tabulist=[[0]*n for i in range(n)]
obway=[0]*n
way=[0]*n
better_way=[0]*n
for i in range(n):
obway[i]=bestway[i]
way[i]=bestway[i]
obscore=comp_bestway_score()
for iter in range(200):
bestscore=10000
for a in range(1,n):
for b in range(a):
for i in range(n):
bestway[i]=way[i]
bestway[a],bestway[b]=bestway[b],bestway[a]
score=comp_bestway_score()
if(score < obscore):
obscore=score
for i in range(n):
obway[i]=bestway[i]
bestscore=score;v1=a;v2=b
elif(score<bestscore and tabulist[a][b]==0):
bestscore = score;
v1=a;v2=b
way[v1],way[v2]=way[v2],way[v1]
for i in range(n):
for j in range(n):
if(tabulist[i][j]>0):
tabulist[i][j]=tabulist[i][j]-1
tabulist[v1][v2]=tabu_long
tabulist[v2][v1]=tabu_long
for i in range(n):
bestway[i]=obway[i]
#遗传算法
def genetic():
dna = [[0]*n for i in range(10)]#保存10条dna所代表的可行解
score = [0]*10 #保存10个可行解的对应分值
dnat = [[0]*n for i in range(8)]#临时存放交叉变异过程中的dna
# (0-1保存原始dna,2-3保存交叉后dna,4-7保存突变后dna)
for i in range(10):#随机生成10条dna初始解
visit = [0]*n # 保存访问记录,0代表未访问,1代表已访问
inway = 0 # 记录已访问的结点数
while inway < n :
v = random.randint(0,n-1)
if(visit[v]==0):
dna[i][inway] = v
visit[v] = 1
inway = inway + 1
for i in range(10): # 计算10条dna的个体分值
for j in range(n):
bestway[j] = dna[i][j]
score[i]=comp_bestway_score()
sortscore = []#保存排序后的可行解分值
sortsite = []#保存排序后分值对应的dna号
for i in range(10):#每次从后面取一个插入到前面排好的序列中
for j in range(i+1):#插入排序由小到大建立dna排序列表
if(j>=i or sortscore[j]>score[i]):
break
sortscore.insert(j,score[i])
sortsite.insert(j,i)
for iter in range(500):
'''按照概率选择两条dna,保证两条dna不同
对选取的两条dna进行交叉操作,生成两条新的dna
对四条dna进行变异操作
从原始和交叉、变异后的八条dna中选择两条最优dna更新原始dna
对新的种群重新排序'''
'''选择'''
r = random.randint(0,54)
if(r<10):
n1 = sortsite[0]
elif(r<19):
n1 = sortsite[1]
elif(r<27):
n1 = sortsite[2]
elif(r<34):
n1 = sortsite[3]
elif(r<40):
n1 = sortsite[4]
elif(r<45):
n1 = sortsite[5]
elif(r<49):
n1 = sortsite[6]
elif(r<52):
n1 = sortsite[7]
elif(r<54):
n1 = sortsite[8]
else:
n1 = sortsite[9]
n2 = n1
while(n1==n2): #反复选择,直到选择的第2条dna与第1条不同
r = random.randint(0, 54)
if (r < 10):
n2 = sortsite[0]
elif (r < 19):
n2 = sortsite[1]
elif (r < 27):
n2 = sortsite[2]
elif (r < 34):
n2 = sortsite[3]
elif (r < 40):
n2 = sortsite[4]
elif (r < 45):
n2 = sortsite[5]
elif (r < 49):
n2 = sortsite[6]
elif (r < 52):
n2 = sortsite[7]
elif (r < 54):
n2 = sortsite[8]
else:
n2 = sortsite[9]
'''交叉'''
for i in range(n):#将随机选择的两条dna保存在dnat[0]和dnat[1]中
dnat[0][i]= dna[n1][i]
dnat[1][i] = dna[n2][i]
# 随机选择交叉片段的两个端点,保证端点不相同且片段不为整个dna序列
tag = 0#标记端点选择未完成
while(tag == 0):
c1 = random.randint(0, n-1)
c2 = random.randint(0, n-1)
if(c1==c2):
continue
if(c1>c2):
c1,c2=c2,c1 #保证c1在前、c2在后
if(c1==0 and c2==123):
continue
tag=1
'''将dnat[0]中c1到c2之外的基因,用dnat[1]的基因顺序填充(顺序交叉法),保证基因不
重复,交叉的结果存入dnat[2]
中'''
v = 0 #记录dna1[1]当前插入基因的位置
for i in range(c1):#对dnat[2]中c1前的基因从dnat[1]中顺序插入
insert = 0#记录当前位置基因是否插入成功,insert=0代表未插入成功
while insert == 0:
find = 0 #标记当前基因v是否与c1-c2中的基因冲突,find=0代表未发现冲突
for j in range(c1,c2+1):
if(dnat[1][v]==dnat[0][j]):
find = 1
break
if(find==0):
dnat[2][i] = dnat[1][v]
insert = 1
v = v+1
for i in range(c1,c2+1):#对dnat[2]中c1-c2基因从dnat[0]中对应位置复制
dnat[2][i]=dnat[0][i]
for i in range(c2+1,n):#对dnat[2]中c2后的基因从dnat[1]中顺序插入
insert = 0 #记录当前位置基因是否插入成功,insert=0代表未插入成功
while insert == 0:
find = 0 #标记当前基因v是否与c1-c2中的基因冲突,find=0代表未发现冲突
for j in range(c1,c2+1):
if(dnat[1][v]==dnat[0][j]):
find = 1
break
if(find==0):
dnat[2][i] = dnat[1][v]
insert = 1
v = v+1
v = 0
for i in range(c1):
insert = 0
while insert == 0:
find = 0
for j in range(c1,c2+1):
if(dnat[0][v]==dnat[1][j]):
find = 1
break
if(find==0):
dnat[3][i] = dnat[0][v]
insert = 1
v = v+1
for i in range(c1,c2+1):
dnat[3][i]=dnat[1][i]
for i in range(c2+1,n):
insert = 0
while insert == 0:
find = 0
for j in range(c1,c2+1):
if(dnat[0][v]==dnat[1][j]):
find = 1
break
if(find==0):
dnat[3][i] = dnat[0][v]
insert = 1
v = v + 1
'''变异'''
for i in range(4):
for j in range(n):
dnat[i+4][j]=dnat[i][j]
for i in range(4,8):
tag = 0
while tag==0:
v1 = random.randint(0,n-1)
v2 = random.randint(0,n-1)
if(v1!=v2):
dnat[i][v1],dnat[i][v2]=dnat[i][v2],dnat[i][v1]
tag = 1
tscore = [0]*8
tsortscore = [0]*8
tsortsite = [0]*8
for i in range(8):
for j in range(n):
bestway[i]=dnat[i][j]
tscore[i]=comp_bestway_score()
for i in range(8):
tsortscore[i]=tscore[i]
tsortscore.sort()
for i in range(8):
tsortsite[i]= tscore.index(tsortscore[i])
for i in range(n):
dna[n1][i]=dnat[tsortsite[0]][i]
dna[n2][i]=dnat[tsortsite[1]][i]
for i in range(10):
for j in range(n):
bestway[j] = dna[i][j]
score[i]=comp_bestway_score()
sortscore = []
sortsite = []
for i in range(10):
for j in range(i+1):
if(j>=i or sortscore[j]>score[i]):
break
sortscore.insert(j,score[i])
sortsite.insert(j,i)
#蚁群算法
def antcolony():
m=100#蚂蚁数
q=100#一只蚂蚁巡回一次释放的信息素总量
t=0.4#挥发率
x=q/n #计算每个城市的平均信息素浓度
pheromone = [[x] * n for i in range(n)] # 信息素浓度矩阵
#print(pheromone)
obscore=10000#保存当前全局最优分值
obway=[0]*n# 保存当前全局最优解
for iter in range(100):
road=[[0]*n for i in range(m)]#保存m只蚂蚁的对n个城市巡回路线
vc=[[0]*n for i in range(m)]# 保存m只蚂蚁已经访问过的城市,0代表未访问
# 随机选择m只蚂蚁的出发城市
for i in range(m):
v=random.randint(0,n-1)
road[i][0]=v#记录起始城市
vc[i][v]=1#该城市已经访问
for i in range(n-1):#遍历剩下的n-1个城市
for j in range(m):#遍历m只蚂蚁
v=road[j][i]#取出当前城市
# 保存当前城市到其他城市的权重
weight=[0]*n
p=[0]*n#保存每个城市的选择概率
tolweight = 0 # 保存总权重
for k in range(n):#遍历未访问城市计算权重
if(vc[j][k]!=1):
weight[k]=pheromone[v][k]/dis_array[v][k]
else:
weight[k]=0
tolweight=tolweight+weight[k]
if(tolweight==0):#当总权重为0,代表所有城市均已访问过
break
else:
for k in range(n):#计算各城市的选择概率
p[k]=weight[k]/tolweight
r=random.random()
wheel=0
for k in range(n):
wheel=wheel+p[k]
if(wheel>=r):
break
road[j][i+1]=k
vc[j][k]=1
roadscore=[0]*m
for i in range(m):
for j in range(n):
bestway[j]=road[i][j]
roadscore[i]=comp_bestway_score()
if(roadscore[i]<obscore):
obscore=roadscore[i]
for k in range(n):
obway[k]=bestway[k]
for i in range(n):
for j in range(n):
pheromone[i][j]=t*pheromone[i][j]
for i in range(m):
for j in range(n-1):
v1=road[i][j]
v2=road[i][j+1]
pheromone[v1][v2]=pheromone[v1][v2]+q/roadscore[i]
pheromone[v2][v1]=pheromone[v2][v1]+q/roadscore[i]
v1=road[i][n-1]
v2=road[i][0]
pheromone[v1][v2]=pheromone[v1][v2]+q/roadscore[i]
pheromone[v2][v1]=pheromone[v2][v1]+q/roadscore[i]
print("number:",n)
print("init bestway:")
print("bestway",bestway)
print("score:",comp_bestway_score())
draw_bestway()
build_dis_array()
print_dis_array()
time_start=time.time()
print("\nGreedy:")
greedy()
#print("\nsa:")
#sa()
#print("\ntabu:")
#tabu()
#print("\ngenetic:")
#genetic()
#print("\nantcolony:")
#antcolony()
print("bestway",bestway)
print("score:",comp_bestway_score())
time_end=time.time()
print("totally time:",time_end-time_start)
draw_bestway()
标签:bestway,dna,dnat,Python,TSP,range,解法,11225,best
From: https://blog.51cto.com/u_16342340/8190612