Tsp issue
Traveling salesman issues, namely
TSP The Traveling Salesman Problem, also translated as the Traveling Salesman Problem or the Salesman Problem, is one of the famous problems in the field of mathematics. Assuming a traveling salesman wants to visit n cities, he must choose the path he wants to take. The limit of the path is that each city can only be visited once, and he must eventually return to the original city of departure. The goal of path selection is to require the path distance to be the minimum value among all paths I won't go into other detailed details, as genetic algorithms are generally relatively easy to implement. I directly pasted the Python code, and if there are any unfamiliar ones, after reading the code, I basically understand it. Firstly, we need to randomly generate some nodes to simulate the cities in the tsp problem: Then, we can write the genetic algorithm: I have selected 40 cities here and iterated 1000 times. Before training, the randomly generated path is as follows: Overall, the mutation part in the code is not written very well because for the Tsp problem, sometimes the difference between the suboptimal path and the optimal path is very large. If it is not possible to obtain a path that is easily confused between the suboptimal and optimal paths in the early stage of population iteration, it may only regretfully see the suboptimal path at the end and be helpless due to insufficient mutation ability. If the mutation ability is very sufficient, mutation is equivalent to randomly generating new species, and the optimization speed in multi node tsp is extremely slow. I haven't come up with any solution yet. If you are interested, you can discuss it together!Introduction to Genetic Algorithm
Application of Genetic Algorithm in TSP Problems
Code implementation
Node Generation
def tsp_port(port_num=50, x_range=2500, y_range=2500):
return np.random.randint(0, x_range, port_num), np.random.randint(0, y_range, port_num)
GA
class Gant:
def __init__(self, port_num=50, x_range=2500, y_range=2500, gants_num=1000):
print('init...')
self.x, self.y = tsp_port(port_num, x_range, y_range) #randomly generated city coordinates
self.port_num = port_num #number of nodes
self.x_range = x_range #map range
self.y_range = y_range
self.gants_num = gants_num #population size
self.gants = []
self.get_new_gants() #randomly initialize population genes
def get_new_gants(self):
for i in range(self.gants_num):
self.gants.append(np.random.permutation(self.port_num))
def get_distance(self, i):
distance = 0
gant = self.gants[i]
for j in range(1, self.port_num):
distance += pow(self.x[gant[j]]-self.x[gant[j-1]], 2) + pow(self.y[gant[j]]-self.y[gant[j-1]], 2)
return distance
def get_distances(self):
dists = []
for i in range(self.gants_num):
dists.append([self.get_distance(i), i])
return sorted(dists)
def select(self):
res = []
dists = self.get_distances()
strong = int(self.gants_num/5)
for i in range(strong): #take out the strong part, the strong can directly choose
res.append(dists[i])
sele = np.random.permutation(strong*4)
for i in range(strong): #extract the lucky group
res.append(dists[i+strong])
return res
def cover(self, population): #breed
new_population = []
rand = np.random.permutation(int(self.gants_num/5))
for i in range(int(self.gants_num/5)):
father1 = self.gants[population[rand[i] * 2][1]]
father2 = self.gants[population[rand[i] * 2 + 1][1]]
cut_point_low = np.random.randint(self.port_num-1)
cut_point_high = np.random.randint(cut_point_low, self.port_num)
cut_gant = father1[cut_point_low:cut_point_high]
son1 = cp.copy(father1)
son2 = cp.copy(father2)
father_to_son1 = []
k = 0
for j in range(self.port_num):
if father2[j] not in cut_gant:
father_to_son1.append(father2[j])
else:
son2[j] = cut_gant[k]
k += 1
# print(cut_point_low, cut_point_high, np.shape(father_to_son1))
# if self.port_num - cut_point_high + cut_point_low != np.shape(father_to_son1)[0]:
# print(father_to_son1, cut_gant, father1, father2, len(set(father1)))
if cut_point_low == 0 and cut_point_high == self.port_num:
son1 = father2
son2 = father1
elif cut_point_low == 0:
son1[cut_point_high:self.port_num] = np.array(father_to_son1)
elif cut_point_high == self.port_num:
son1[0:cut_point_low] = np.array(father_to_son1)
else:
son1[0:cut_point_low] = np.array(father_to_son1[0:cut_point_low])
son1[cut_point_high:self.port_num] = np.array(father_to_son1[cut_point_low:])
new_population.append(father1)
new_population.append(father2)
new_population.append(son1)
new_population.append(son2)
#variation
rand = np.random.choice(int(self.gants_num/5)*4, int(self.gants_num/5), replace=False)
for i in rand:
new_gant = cp.copy(new_population[i])
rand_mod = np.random.randint(int(self.gants_num/40))
# if rand_mod == 0:
for l in range(rand_mod):
exchange = np.random.choice(self.port_num, 2)
a = new_gant[exchange[0]]
new_gant[exchange[0]] = new_gant[exchange[1]]
new_gant[exchange[1]] = a
# elif rand_mod == 1:
# exchangelong = np.random.randint(1, int(self.port_num/10))
# exchangepoint = np.random.randint(exchangelong, self.port_num - exchangelong)
# a = new_gant[exchangepoint: exchangepoint + exchangelong]
# new_gant[exchangepoint: exchangepoint + exchangelong] =
# new_gant[exchangepoint - exchangelong: exchangepoint]
# new_gant[exchangepoint - exchangelong: exchangepoint] = a
# else:
# # randint the random range of is [x,y)
# exchangelong = np.random.randint(1, int(self.port_num / 10))
# exchangepoint1 = np.random.randint(0, self.port_num - exchangelong*2)
# exchangepoint2 = np.random.randint(exchangepoint1, self.port_num - exchangelong)
# a = new_gant[exchangepoint1: exchangepoint1 + exchangelong]
# new_gant[exchangepoint1: exchangepoint1 + exchangelong] =
# new_gant[exchangepoint2: exchangepoint2 + exchangelong]
# new_gant[exchangepoint2: exchangepoint2 + exchangelong] = a
if len(set(new_gant)) != self.port_num:
# print(exchangelong, new_gant, rand_mod, len(set(new_gant)))
exit()
new_population.append(new_gant)
# print(np.shape(new_gant), type(new_gant))
self.gants = new_population
# for i in range(int(self.gants_num/5)):
# print(np.shape(np.random.permutation(self.port_num)), type(np.random.permutation(self.port_num)))
# new_population.append(np.random.permutation(self.port_num))
# self.gants = new_population
def draw_roadline(self):
dists = self.get_distances()
shortest_line = dists[0][1]
plt.scatter(self.x, self.y)
plt.plot(self.x[self.gants[shortest_line]], self.y[self.gants[shortest_line]])
plt.show()
plt.ion()
def train(self, op=1000):
for i in range(op):
res = self.select()
self.cover(res)
dist = self.get_distances()
if i%500 == 0:
self.draw_roadline()
print("distance:", dist[0][0], "op:", i)
# print(self.gants, np.shape(self.gants[0]))
def train_op(self, i):
res = self.select()
self.cover(res)
dist = self.get_distances()
print("distance:", dist[0][0], "op:", i )
Training
gant = Gant(port_num=40)
gant.train(1000)
gant.draw_roadline()
Result
After 500 iterations:
After 1000 generations:
It can be seen that due to the gradual stabilization of the species' morphology, the approximate route is almost the same as that of 500 iterations, only some routes have been optimized... I have seen some GA algorithms in the intelligent algorithm library that can achieve very good results, perhaps because my breeding and mutation algorithms are not written well enough

Summary