- TSP:Traveling Salesman Problem
- GA:Genetic Algorithm
- Python3.7
1. 第一问最小生成树问题
- 使用了Prim算法基于Python3.7实现
- 最小生成树(Prim算法)
2. 即TSP问题、这里用到GA解决
- 找了别人的GA板子,改动之后成型
- 清华大学【数据挖掘:进化计算】
- 进化算法 Evolutionary Algorithms (莫烦 Python 教程)
- 图转化为邻接矩阵 999表示不可达
- 最短路径即为 1、2、5、6、8、7、3、4、1
3.GA-TSP
import numpy as np
import random
def get_total_distance(x):
distance = 0
distance += Distance[origin][x[0]]
for i in range(len(x)):
if i == len(x) - 1:
distance += Distance[origin][x[i]]
else:
distance += Distance[x[i]][x[i + 1]]
return distance
def improve(x):
i = 0
distance = get_total_distance(x)
while i < improve_count:
u = random.randint(0, len(x) - 1)
v = random.randint(0, len(x) - 1)
if u != v:
new_x = x.copy()
t = new_x[u]
new_x[u] = new_x[v]
new_x[v] = t
new_distance = get_total_distance(new_x)
if new_distance < distance:
distance = new_distance
x = new_x.copy()
else:
continue
i += 1
def selection(population):
"""
选择
先对适应度从大到小排序,选出存活的染色体
再进行随机选择,选出适应度虽然小,但是幸存下来的个体
"""
graded = [[get_total_distance(x), x] for x in population]
graded = [x[1] for x in sorted(graded)]
retain_length = int(len(graded) * retain_rate)
parents = graded[:retain_length]
for chromosome in graded[retain_length:]:
if random.random() < random_select_rate:
parents.append(chromosome)
return parents
def read_array():
city_count = 8
Distance = np.zeros([city_count, city_count])
max_value = 999
row1 = [0, 2, 8, 1, max_value, max_value, max_value, max_value]
row2 = [2, 0, 6, max_value, 1, max_value, max_value, max_value]
row3 = [8, 6, 0, 7, 5, 1, 2, max_value]
row4 = [1, max_value, 7, 0, max_value, max_value, 9, max_value]
row5 = [max_value, 1, 5, max_value, 3, 0, max_value, 8]
row6 = [max_value, max_value, 1, max_value, 3, 0, 4, 6]
row7 = [max_value, max_value, 2, 9, max_value, 4, 0, 3]
row8 = [max_value, max_value, max_value, max_value, 8, 6, 3, 0]
graph = [row1, row2, row3, row4, row5, row6, row7, row8]
Distance = np.array(graph)
return Distance
def crossover(parents):
target_count = count - len(parents)
children = []
while len(children) < target_count:
male_index = random.randint(0, len(parents) - 1)
female_index = random.randint(0, len(parents) - 1)
if male_index != female_index:
male = parents[male_index]
female = parents[female_index]
left = random.randint(0, len(male) - 2)
right = random.randint(left + 1, len(male) - 1)
gene1 = male[left:right]
gene2 = female[left:right]
child1_c = male[right:] + male[:right]
child2_c = female[right:] + female[:right]
child1 = child1_c.copy()
child2 = child2_c.copy()
for o in gene2:
child1_c.remove(o)
for o in gene1:
child2_c.remove(o)
child1[left:right] = gene2
child2[left:right] = gene1
child1[right:] = child1_c[0:len(child1) - right]
child1[:left] = child1_c[len(child1) - right:]
child2[right:] = child2_c[0:len(child1) - right]
child2[:left] = child2_c[len(child1) - right:]
children.append(child1)
children.append(child2)
return children
def mutation(children):
for i in range(len(children)):
if random.random() < mutation_rate:
child = children[i]
u = random.randint(1, len(child) - 4)
v = random.randint(u + 1, len(child) - 3)
w = random.randint(v + 1, len(child) - 2)
child = children[i]
child = child[0:u] + child[v:w] + child[u:v] + child[w:]
def get_result(population):
graded = [[get_total_distance(x), x] for x in population]
graded = sorted(graded)
return graded[0][0], graded[0][1]
def begin():
population = []
for i in range(count):
x = index.copy()
random.shuffle(x)
improve(x)
population.append(x)
register = []
i = 0
distance, result_path = get_result(population)
while i < itter_time:
parents = selection(population)
children = crossover(parents)
mutation(children)
population = parents + children
distance, result_path = get_result(population)
register.append(distance)
i = i + 1
return distance, result_path
if __name__ == '__main__':
Distance = read_array()
count = 30
improve_count = 500
itter_time = 3000
retain_rate = 0.3
random_select_rate = 0.5
mutation_rate = 0.1
origin = 0
index = np.arange(8).tolist()
index.remove(origin)
distance, result_path = begin()
print(distance)
print(result_path)