For an exercise I have to find the optimal solution to this Travelling Salesman Problem, only difference is that the salesman may not visit the first coordinate twice. The optimum should lie around 1200 which is given. I don't see why this wouldn't converge. Also an important note is that the manhattan distance metric is used instead of the euclidian distance.
def shuffle_coords(coords):
x0 = coords[0]
coords = shuffle(coords[1:])
return np.insert(coords,0,x0,axis = 0)
def distance(x,y):
return abs(x[1] - y[1]) + abs(x[0] - y[0])
Here the coordinates are shuffled randomly.
def shuffle(array):
df = pd.DataFrame(array)
return df.sample(len(array)).to_numpy()
def path_distance(path):
dist = []
for i in range(1,len(path)):
dist.append(distance(path[i],path[i-1]))
return np.sum(dist)
Here the Simulated Annealing algorithm is initialised.
def SA_distance(path, T_0,T_min, alpha):
T = T_0
dist = path_distance(path)
while T > T_min:
new_path = gen_subtour(path)
diffF = path_distance(new_path) - dist
if diffF < 0:
path = new_path
dist = path_distance(path)
elif np.exp(-(diffF/T)) > random.uniform(0,1):
path = new_path
dist = path_distance(path)
T = T * alpha
print(dist,T)
return dist,path
Here the random subtour is generated while keeping x0 in place.
def gen_subtour(path):
subset = shuffle(np.delete(path,0,axis =0))
subset = shuffle(path)
if random.uniform(0,1) < 0.5:
subset = np.flipud(subset)
else:
j = random.randint(1,(len(subset)-1))
p = subset[j-1]
q = subset[j]
subset = np.delete(subset,[j-1,j],axis = 0)
subset = np.insert(subset,0,p,axis = 0)
subset = np.insert(subset,len(subset),q,axis = 0)
return np.insert(subset,0,path[0],axis = 0)
def main():
T_0 = 12
T_min = 10**-9
alpha = 0.999
coords = np.array([[375, 375],[161, 190], [186, 169],[185, 124],
[122, 104],[109, 258], [55, 153] ,[120, 49],
[39, 85] ,[59, 250] , [17, 310] ,[179, 265],
[184, 198]])
path , distance = SA_distance(coords,T_0,T_min,alpha)