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()
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
run_array[min_b][min_a]=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
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
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()
for i in range(n):
obway[i] = bestway[i]
f1 = obscore
while t > tf :
for iter in range(10):
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()
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)):
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)]
score = [0]*10
dnat = [[0]*n for i in range(8)]
for i in range(10):
visit = [0]*n
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):
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)
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):
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):
dnat[0][i]= dna[n1][i]
dnat[1][i] = dna[n2][i]
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
if(c1==0 and c2==123):
continue
tag=1
'''将dnat[0]中c1到c2之外的基因,用dnat[1]的基因顺序填充(顺序交叉法),保证基因不
重复,交叉的结果存入dnat[2]
中'''
v = 0
for i in range(c1):
insert = 0
while insert == 0:
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][i]=dnat[0][i]
for i in range(c2+1,n):
insert = 0
while insert == 0:
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)]
obscore=10000
obway=[0]*n
for iter in range(100):
road=[[0]*n for i in range(m)]
vc=[[0]*n for i in range(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):
for j in range(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):
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("bestway",bestway)
print("score:",comp_bestway_score())
time_end=time.time()
print("totally time:",time_end-time_start)
draw_bestway()