Wang Haihua
🍈 🍉🍊 🍋 🍌
旅行商问题(TravelingSalesmanProblem,TSP)是一个经典的组合优化问题。经典的TSP可以描述为:一个商品推销员要去若干个城市推销商品,该推销员从一个城市出发,需要经过所有城市后,回到出发地。应如何选择行进路线,以使总的行程最短。从图论的角度来看,该问题实质是在一个带权完全无向图中,找一个权值最小的Hamilton回路。由于该问题的可行解是所有顶点的全排列,随着顶点数的增加,会产生组合爆炸,它是一个NP完全问题。由于其在交通运输、电路板线路设计以及物流配送等领域内有着广泛的应用,国内外学者对其进行了大量的研究。早期的研究者使用精确算法求解该问题,常用的方法包括:分枝定界法、线性规划法、动态规划法等。但是,随着问题规模的增大,精确算法将变得无能为力,因此,在后来的研究中,国内外学者重点使用近似算法或启发式算法,主要有遗传算法、模拟退火法、蚁群算法、禁忌搜索算法、贪婪算法和神经网络等。
给定52个城市坐标,要求寻找从第一个城市出发历经其他所有城市再回到第一个城市的路线。下表为前十个城市坐标
x | y | |
---|---|---|
0 | 565 | 575 |
1 | 25 | 185 |
2 | 345 | 750 |
3 | 945 | 685 |
4 | 845 | 655 |
5 | 880 | 660 |
6 | 25 | 230 |
7 | 525 | 1000 |
8 | 580 | 1175 |
9 | 650 | 1130 |
城市位置如下图所示
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 平面内不同城市坐标
coordinates = np.array([[565.0,575.0],[25.0,185.0],[345.0,750.0],[945.0,685.0],[845.0,655.0],
[880.0,660.0],[25.0,230.0],[525.0,1000.0],[580.0,1175.0],[650.0,1130.0],
[1605.0,620.0],[1220.0,580.0],[1465.0,200.0],[1530.0, 5.0],[845.0,680.0],
[725.0,370.0],[145.0,665.0],[415.0,635.0],[510.0,875.0],[560.0,365.0],
[300.0,465.0],[520.0,585.0],[480.0,415.0],[835.0,625.0],[975.0,580.0],
[1215.0,245.0],[1320.0,315.0],[1250.0,400.0],[660.0,180.0],[410.0,250.0],
[420.0,555.0],[575.0,665.0],[1150.0,1160.0],[700.0,580.0],[685.0,595.0],
[685.0,610.0],[770.0,610.0],[795.0,645.0],[720.0,635.0],[760.0,650.0],
[475.0,960.0],[95.0,260.0],[875.0,920.0],[700.0,500.0],[555.0,815.0],
[830.0,485.0],[1170.0, 65.0],[830.0,610.0],[605.0,625.0],[595.0,360.0],
[1340.0,725.0],[1740.0,245.0]])
#得到距离矩阵的函数
def getdistmat(coordinates):
num = coordinates.shape[0] #52个坐标点
distmat = np.zeros((52,52)) #52X52距离矩阵
for i in range(num):
for j in range(i,num):
distmat[i][j] = distmat[j][i]=np.linalg.norm(coordinates[i]-coordinates[j])
return distmat
def initpara():
alpha = 0.99
t = (1,100)
markovlen = 1000
return alpha,t,markovlen
num = coordinates.shape[0]
distmat = getdistmat(coordinates) #得到距离矩阵
solutionnew = np.arange(num)
solutioncurrent = solutionnew.copy()
valuecurrent =99000 #取一个较大值作为初始值
#print(valuecurrent)
solutionbest = solutionnew.copy()
valuebest = 99000
alpha,t2,markovlen = initpara()
t = t2[1]
result = [] #记录迭代过程中的最优解
while t > t2[0]:
for i in np.arange(markovlen):
#下面的两交换和三交换是两种扰动方式,用于产生新解
if np.random.rand() > 0.5:# 交换路径中的这2个节点的顺序
# np.random.rand()产生[0, 1)区间的均匀随机数
while True:#产生两个不同的随机数
loc1 = np.int(np.ceil(np.random.rand()*(num-1)))
loc2 = np.int(np.ceil(np.random.rand()*(num-1)))
## print(loc1,loc2)
if loc1 != loc2:
break
solutionnew[loc1],solutionnew[loc2] = solutionnew[loc2],solutionnew[loc1]
else: #三交换
while True:
loc1 = np.int(np.ceil(np.random.rand()*(num-1)))
loc2 = np.int(np.ceil(np.random.rand()*(num-1)))
loc3 = np.int(np.ceil(np.random.rand()*(num-1)))
if((loc1 != loc2)&(loc2 != loc3)&(loc1 != loc3)):
break
# 下面的三个判断语句使得loc1<loc2<loc3
if loc1 > loc2:
loc1,loc2 = loc2,loc1
if loc2 > loc3:
loc2,loc3 = loc3,loc2
if loc1 > loc2:
loc1,loc2 = loc2,loc1
#下面的三行代码将[loc1,loc2)区间的数据插入到loc3之后
tmplist = solutionnew[loc1:loc2].copy()
solutionnew[loc1:loc3-loc2+1+loc1] = solutionnew[loc2:loc3+1].copy()
solutionnew[loc3-loc2+1+loc1:loc3+1] = tmplist.copy()
valuenew = 0
for i in range(num-1):
valuenew += distmat[solutionnew[i]][solutionnew[i+1]]
valuenew += distmat[solutionnew[0]][solutionnew[51]]
# print (valuenew)
if valuenew<valuecurrent: #接受该解
#更新solutioncurrent 和solutionbest
valuecurrent = valuenew
solutioncurrent = solutionnew.copy()
if valuenew < valuebest:
valuebest = valuenew
solutionbest = solutionnew.copy()
else:#按一定的概率接受该解
if np.random.rand() < np.exp(-(valuenew-valuecurrent)/t):
valuecurrent = valuenew
solutioncurrent = solutionnew.copy()
else:
solutionnew = solutioncurrent.copy()
t = alpha*t
result.append(valuebest)
print (t) #程序运行时间较长,打印t来监视程序进展速度
#用来显示结果
plt.plot(np.array(result))
plt.ylabel("bestvalue")
plt.xlabel("t")
plt.show()
最优路线为[ 0, 35, 38, 39, 36, 37, 47, 23, 4, 14, 5, 3, 24, 11, 27, 26, 25,
46, 12, 13, 51, 10, 50, 32, 42, 9, 8, 7, 40, 18, 44, 31, 48, 34,
33, 43, 45, 15, 28, 49, 19, 22, 29, 1, 6, 41, 20, 16, 2, 17, 30,
21]
路线长度为:7675.77
参考资料
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# 平面内不同城市坐标
coordinates = np.array([[565.0,575.0],[25.0,185.0],[345.0,750.0],[945.0,685.0],[845.0,655.0],
[880.0,660.0],[25.0,230.0],[525.0,1000.0],[580.0,1175.0],[650.0,1130.0],
[1605.0,620.0],[1220.0,580.0],[1465.0,200.0],[1530.0, 5.0],[845.0,680.0],
[725.0,370.0],[145.0,665.0],[415.0,635.0],[510.0,875.0],[560.0,365.0],
[300.0,465.0],[520.0,585.0],[480.0,415.0],[835.0,625.0],[975.0,580.0],
[1215.0,245.0],[1320.0,315.0],[1250.0,400.0],[660.0,180.0],[410.0,250.0],
[420.0,555.0],[575.0,665.0],[1150.0,1160.0],[700.0,580.0],[685.0,595.0],
[685.0,610.0],[770.0,610.0],[795.0,645.0],[720.0,635.0],[760.0,650.0],
[475.0,960.0],[95.0,260.0],[875.0,920.0],[700.0,500.0],[555.0,815.0],
[830.0,485.0],[1170.0, 65.0],[830.0,610.0],[605.0,625.0],[595.0,360.0],
[1340.0,725.0],[1740.0,245.0]])
coordinates.shape
(52, 2)
plt.scatter(coordinates[:,0],coordinates[:,1],marker='*')
plt.savefig('images/opt1601.png')
num = 100
solutionnew = np.arange(num)
solutionnew
array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99])
#得到距离矩阵的函数
def getdistmat(coordinates):
num = coordinates.shape[0] #52个坐标点
distmat = np.zeros((52,52)) #52X52距离矩阵
for i in range(num):
for j in range(i,num):
distmat[i][j] = distmat[j][i]=np.linalg.norm(coordinates[i]-coordinates[j])
return distmat
def initpara():
alpha = 0.99
t = (1,100)
markovlen = 1000
return alpha,t,markovlen
num = coordinates.shape[0]
distmat = getdistmat(coordinates) #得到距离矩阵
solutionnew = np.arange(num)
solutioncurrent = solutionnew.copy()
valuecurrent =99000 #取一个较大值作为初始值
#print(valuecurrent)
solutionbest = solutionnew.copy()
valuebest = 99000
alpha,t2,markovlen = initpara()
t = t2[1]
result = [] #记录迭代过程中的最优解
while t > t2[0]:
for i in np.arange(markovlen):
#下面的两交换和三交换是两种扰动方式,用于产生新解
if np.random.rand() > 0.5:# 交换路径中的这2个节点的顺序
# np.random.rand()产生[0, 1)区间的均匀随机数
while True:#产生两个不同的随机数
loc1 = np.int(np.ceil(np.random.rand()*(num-1)))
loc2 = np.int(np.ceil(np.random.rand()*(num-1)))
## print(loc1,loc2)
if loc1 != loc2:
break
solutionnew[loc1],solutionnew[loc2] = solutionnew[loc2],solutionnew[loc1]
else: #三交换
while True:
loc1 = np.int(np.ceil(np.random.rand()*(num-1)))
loc2 = np.int(np.ceil(np.random.rand()*(num-1)))
loc3 = np.int(np.ceil(np.random.rand()*(num-1)))
if((loc1 != loc2)&(loc2 != loc3)&(loc1 != loc3)):
break
# 下面的三个判断语句使得loc1<loc2<loc3
if loc1 > loc2:
loc1,loc2 = loc2,loc1
if loc2 > loc3:
loc2,loc3 = loc3,loc2
if loc1 > loc2:
loc1,loc2 = loc2,loc1
#下面的三行代码将[loc1,loc2)区间的数据插入到loc3之后
tmplist = solutionnew[loc1:loc2].copy()
solutionnew[loc1:loc3-loc2+1+loc1] = solutionnew[loc2:loc3+1].copy()
solutionnew[loc3-loc2+1+loc1:loc3+1] = tmplist.copy()
valuenew = 0
for i in range(num-1):
valuenew += distmat[solutionnew[i]][solutionnew[i+1]]
valuenew += distmat[solutionnew[0]][solutionnew[51]]
# print (valuenew)
if valuenew<valuecurrent: #接受该解
#更新solutioncurrent 和solutionbest
valuecurrent = valuenew
solutioncurrent = solutionnew.copy()
if valuenew < valuebest:
valuebest = valuenew
solutionbest = solutionnew.copy()
else:#按一定的概率接受该解
if np.random.rand() < np.exp(-(valuenew-valuecurrent)/t):
valuecurrent = valuenew
solutioncurrent = solutionnew.copy()
else:
solutionnew = solutioncurrent.copy()
t = alpha*t
result.append(valuebest)
print (t) #程序运行时间较长,打印t来监视程序进展速度
#用来显示结果
plt.plot(np.array(result))
plt.ylabel("bestvalue")
plt.xlabel("t")
plt.show()
<ipython-input-8-4279cb99773f>:20: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations loc1 = np.int(np.ceil(np.random.rand()*(num-1))) <ipython-input-8-4279cb99773f>:21: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations loc2 = np.int(np.ceil(np.random.rand()*(num-1))) <ipython-input-8-4279cb99773f>:22: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations loc3 = np.int(np.ceil(np.random.rand()*(num-1))) <ipython-input-8-4279cb99773f>:12: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations loc1 = np.int(np.ceil(np.random.rand()*(num-1))) <ipython-input-8-4279cb99773f>:13: DeprecationWarning: `np.int` is a deprecated alias for the builtin `int`. To silence this warning, use `int` by itself. Doing this will not modify any behavior and is safe. When replacing `np.int`, you may wish to use e.g. `np.int64` or `np.int32` to specify the precision. If you wish to review your current use, check the release note link for additional information. Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations loc2 = np.int(np.ceil(np.random.rand()*(num-1)))
99.0 98.01 97.0299 96.059601 95.09900499 94.1480149401 93.206534790699 92.27446944279201 91.35172474836409 90.43820750088045 89.53382542587164 88.63848717161292 87.75210229989679 86.87458127689783 86.00583546412885 85.14577710948755 84.29431933839268 83.45137614500875 82.61686238355867 81.79069375972308 80.97278682212585 80.1630589539046 79.36142836436555 78.56781408072189 77.78213593991467 77.00431458051553 76.23427143471037 75.47192872036327 74.71720943315964 73.97003733882804 73.23033696543976 72.49803359578536 71.7730532598275 71.05532272722922 70.34476949995693 69.64132180495736 68.94490858690779 68.25545950103871 67.57290490602833 66.89717585696805 66.22820409839836 65.56592205741438 64.91026283684023 64.26116020847184 63.618548606387115 62.98236312032324 62.35253948912001 61.72901409422881 61.11172395328652 60.500606713753655 59.89560064661612 59.29664464014996 58.70367819374846 58.116641411810974 57.535474997692866 56.960120247715935 56.390519045238776 55.82661385478639 55.26834771623852 54.71566423907614 54.16850759668538 53.62682252071853 53.09055429551134 52.55964875255623 52.03405226503067 51.51371174238036 50.998574624956554 50.488588878706985 49.98370298991991 49.483865960020715 48.98902730042051 48.4991370274163 48.01414565714214 47.53400420057071 47.05866415856501 46.58807751697936 46.12219674180957 45.66097477439147 45.20436502664755 44.752321376381076 44.30479816261727 43.861750180991095 43.42313267918119 42.98890135238938 42.559012338865486 42.133422215476834 41.712087993322065 41.29496711338884 40.882017442254956 40.473197267832404 40.06846529515408 39.66778064220254 39.27110283578051 38.8783918074227 38.48960788934848 38.104711810454994 37.72366469235045 37.34642804542694 36.97296376497267 36.60323412732294 36.23720178604971 35.874829768189215 35.516081470507324 35.16092065580225 34.80931144924423 34.461218334751784 34.11660615140427 33.775440089890225 33.43768568899132 33.10330883210141 32.7722757437804 32.44455298634259 32.12010745647917 31.798906381914374 31.48091731809523 31.16610814491428 30.854447063465138 30.545902592830487 30.240443566902183 29.93803913123316 29.638658739920828 29.34227215252162 29.048849430996402 28.758360936686437 28.47077732731957 28.186069554046373 27.90420885850591 27.625166769920853 27.348915102221643 27.075425951199424 26.804671691687428 26.536624974770554 26.271258725022847 26.00854613777262 25.748460676394892 25.490976069630943 25.23606630893463 24.983705645845284 24.73386858938683 24.48652990349296 24.24166460445803 23.99924795841345 23.759255478829314 23.52166292404102 23.28644629480061 23.053581831852604 22.82304601353408 22.59481555339874 22.36886739786475 22.145178723886104 21.923726936647242 21.704489667280768 21.48744477060796 21.27257032290188 21.059844619672862 20.849246173476132 20.64075371174137 20.434346174623958 20.230002712877717 20.027702685748938 19.82742565889145 19.629151402302536 19.43285988827951 19.238531289396715 19.046145976502746 18.855684516737718 18.66712767157034 18.480456394854638 18.295651830906092 18.11269531259703 17.931568359471058 17.752252675876345 17.57473014911758 17.398982847626407 17.22499301915014 17.05274308895864 16.882215658069054 16.713393501488362 16.546259566473477 16.380796970808742 16.216989001100654 16.054819111089646 15.89427091997875 15.735328210778961 15.577974928671171 15.42219517938446 15.267973227590614 15.115293495314708 14.96414056036156 14.814499154757945 14.666354163210364 14.519690621578262 14.374493715362478 14.230748778208852 14.088441290426763 13.947556877522496 13.808081308747271 13.670000495659798 13.5333004907032 13.397967485796167 13.263987810938206 13.131347932828824 13.000034453500536 12.87003410896553 12.741333767875876 12.613920430197117 12.487781225895146 12.362903413636195 12.239274379499832 12.116881635704834 11.995712819347785 11.875755691154307 11.756998134242764 11.639428152900336 11.523033871371332 11.407803532657619 11.293725497331042 11.180788242357732 11.068980359934155 10.958290556334813 10.848707650771464 10.74022057426375 10.632818368521113 10.526490184835902 10.421225282987542 10.317013030157668 10.213842899856092 10.11170447085753 10.010587426148955 9.910481551887466 9.811376736368592 9.713262969004907 9.616130339314857 9.519969035921708 9.42476934556249 9.330521652106865 9.237216435585797 9.144844271229939 9.053395828517639 8.962861870232462 8.873233251530138 8.784500919014837 8.696655909824688 8.609689350726441 8.523592457219177 8.438356532646985 8.353972967320516 8.27043323764731 8.187728905270838 8.105851616218128 8.024793100055946 7.944545169055387 7.865099717364833 7.786448720191185 7.708584232989273 7.63149839065938 7.5551834067527865 7.479631572685259 7.404835256958406 7.330786904388821 7.257479035344933 7.1849042449914835 7.1130552025415685 7.041924650516153 6.971505404010991 6.901790349970882 6.832772446471173 6.764444722006462 6.696800274786397 6.6298322720385325 6.563533949318147 6.497898609824966 6.432919623726716 6.3685904274894485 6.304904523214554 6.2418554779824085 6.1794369232025845 6.117642553970558 6.056466128430853 5.9959014671465445 5.935942452475079 5.8765830279503275 5.817817197670824 5.759639025694116 5.7020426354371745 5.645022209082803 5.588571986991974 5.532686267122054 5.477359404450834 5.422585810406325 5.368359952302262 5.314676352779239 5.261529589251447 5.208914293358933 5.156825150425344 5.10525689892109 5.0542043299318795 5.003662286632561 4.953625663766235 4.9040894071285726 4.8550485130572865 4.806498027926714 4.758433047647447 4.710848717170973 4.663740229999263 4.61710282769927 4.570931799422278 4.525222481428055 4.4799702566137745 4.4351705540476365 4.39081884850716 4.346910660022088 4.303441553421867 4.260407137887648 4.217803066508771 4.175625035843683 4.133868785485246 4.0925300976303935 4.05160479665409 4.011088748687548 3.970977861200673 3.9312680825886663 3.8919554017627798 3.853035847745152 3.8145054892677006 3.7763604343750234 3.7385968300312733 3.7012108617309605 3.664198753113651 3.6275567655825145 3.591281197926689 3.555368385947422 3.519814702087948 3.4846165550670687 3.449770389516398 3.415272685621234 3.3811199587650216 3.347308759177371 3.3138356715855974 3.2806973148697414 3.247890341721044 3.2154114383038332 3.183257323920795 3.1514247506815867 3.1199105031747707 3.088711398143023 3.0578242841615926 3.0272460413199767 2.996973580906777 2.967003845097709 2.9373338066467323 2.907960468580265 2.8788808638944623 2.8500920552555176 2.8215911347029623 2.7933752233559326 2.765441471122373 2.7377870564111495 2.710409185847038 2.6833050939885674 2.656472043048682 2.629907322618195 2.603608249392013 2.577572166898093 2.551796445229112 2.526278480776821 2.501015695969053 2.4760055390093623 2.4512454836192688 2.426733028783076 2.402465698495245 2.3784410415102926 2.3546566310951897 2.3311100647842378 2.307798964136395 2.2847209744950314 2.261873764750081 2.23925502710258 2.2168624768315546 2.194693852063239 2.1727469135426065 2.1510194444071806 2.129509249963109 2.108214157463478 2.087132015888843 2.0662606957299547 2.045598088772655 2.0251421078849283 2.004890686806079 1.9848417799380185 1.9649933621386382 1.9453434285172517 1.9258899942320793 1.9066310942897584 1.8875647833468607 1.868689135513392 1.8500022441582582 1.8315022217166756 1.8131871994995088 1.7950553275045138 1.7771047742294686 1.7593337264871738 1.741740389222302 1.724322985330079 1.7070797554767783 1.6900089579220106 1.6731088683427904 1.6563777796593624 1.6398140018627687 1.623415861844141 1.6071817032256996 1.5911098861934427 1.5751987873315083 1.5594467994581933 1.5438523314636114 1.5284138081489753 1.5131296700674854 1.4979983733668105 1.4830183896331424 1.468188205736811 1.4535063236794428 1.4389712604426483 1.4245815478382218 1.4103357323598396 1.396232375036241 1.3822700512858788 1.36844735077302 1.3547628772652898 1.341215248492637 1.3278030960077105 1.3145250650476334 1.301379814397157 1.2883660162531856 1.2754823560906536 1.2627275325297471 1.2501002572044497 1.2375992546324053 1.2252232620860812 1.2129710294652205 1.2008413191705682 1.1888329059788625 1.1769445769190738 1.165175131149883 1.1535233798383842 1.1419881460400003 1.1305682645796002 1.1192625819338042 1.1080699561144662 1.0969892565533215 1.0860193639877882 1.0751591703479102 1.0644075786444311 1.0537635028579868 1.0432258678294068 1.0327936091511127 1.0224656730596016 1.0122410163290056 1.0021186061657157 0.9920974201040585
plt.plot(np.array(result))
plt.ylabel("bestvalue")
plt.xlabel("t")
plt.savefig('images/opt1602.png')
plt.show()
solutionbest
array([ 0, 35, 38, 39, 36, 37, 47, 23, 4, 14, 5, 3, 24, 11, 27, 26, 25, 46, 12, 13, 51, 10, 50, 32, 42, 9, 8, 7, 40, 18, 44, 31, 48, 34, 33, 43, 45, 15, 28, 49, 19, 22, 29, 1, 6, 41, 20, 16, 2, 17, 30, 21])
valuebest
7675.774696982935
plt.scatter(coordinates[:,0],coordinates[:,1],marker='*')
plt.plot(coordinates[:,0],coordinates[:,1])
[<matplotlib.lines.Line2D at 0x28ea1986340>]
solutionbest
array([ 0, 48, 35, 36, 47, 23, 4, 5, 3, 24, 11, 27, 26, 25, 46, 12, 13, 51, 10, 50, 32, 42, 14, 37, 39, 38, 34, 33, 43, 45, 15, 28, 49, 19, 22, 30, 17, 20, 29, 41, 1, 6, 16, 2, 40, 7, 8, 9, 18, 44, 31, 21])
plt.scatter(coordinates[solutionbest,0],coordinates[solutionbest,1],marker='*')
plt.plot(coordinates[solutionbest,0],coordinates[solutionbest,1])
[<matplotlib.lines.Line2D at 0x28ea18d4160>]