Python 带遗传、变异、交叉的旅行商
上学期上学时,我写了一个python程序来解决旅行推销员问题。对于那些不熟悉它是什么的人来说,wolfram alpha解释很好地解释了它 这是我最早用Python编写的程序之一,到目前为止,我喜欢这种语言,它来自C++/Java背景。无论如何,我使用了很多低效的方法/编程实践来让它工作,所以我想回去改进。我使用了一种带有突变和有序交叉的遗传算法。首先,我创建一个具有给定长度和给定策略数的随机唯一节点列表。遗传算法通过给定数量的这些策略,通过使用有序交叉和两个随机指数之间的反向变异来改变策略的随机选择。每个策略都有一个给定的变异概率和另一个交叉概率。在此之后,算法随机选择两种策略,选择最佳策略,然后将其与迄今为止找到的最佳解决方案进行比较。该程序的最终目标是找到通过所有节点的最短距离 以下是我更新、高效、不起作用的代码:Python 带遗传、变异、交叉的旅行商,python,algorithm,Python,Algorithm,上学期上学时,我写了一个python程序来解决旅行推销员问题。对于那些不熟悉它是什么的人来说,wolfram alpha解释很好地解释了它 这是我最早用Python编写的程序之一,到目前为止,我喜欢这种语言,它来自C++/Java背景。无论如何,我使用了很多低效的方法/编程实践来让它工作,所以我想回去改进。我使用了一种带有突变和有序交叉的遗传算法。首先,我创建一个具有给定长度和给定策略数的随机唯一节点列表。遗传算法通过给定数量的这些策略,通过使用有序交叉和两个随机指数之间的反向变异来改变策略的随
import random
import math
import pprint
from matplotlib import pyplot as plt
def create_nodes(num_nodes, num_rows):
elements = range(1, num_nodes + 1)
return [random.sample(elements, num_nodes) for _ in range(num_rows)]
def mutate(table, node_table, mutate_probability, cross_probability):
for next_id, row in enumerate(table, 1):
nodes = len(row)
# print
# print "Original: ", row
#mutation
if random.random() > mutate_probability:
mini, maxi = sorted(random.sample(range(nodes),2))
row[mini:maxi+1] = row[mini:maxi+1][::-1]
# print "After mutation: ", row
# print "Between: ", mini, maxi
#crossover
if random.random() > cross_probability:
try:
next_row = table[next_id]
# print "Parent: ", next_row
except IndexError:
pass
else:
half_length = nodes//2
mini = random.randint(0, half_length)
maxi = mini + half_length - 1 + (nodes % 2)
crossed = [None] * nodes
# print "Before crossed: ", row
crossed[mini:maxi+1] = next_row[mini:maxi+1]
# print "Cross with: ", crossed
iterator = 0
for element in row:
if element in crossed:
continue
while mini <= iterator <= maxi:
iterator += 1
crossed[iterator] = element
iterator += 1
row[:] = crossed
# print "After crossed: ", row
# print "Between: ", mini, maxi
def sample_best(table, node_table):
t1, t2 = random.sample(table[1:], 2)
return distance(t1, t2, node_table)
def distance(s1, s2, node_table):
distance1 = sum_distances(s1, node_table)
distance2 = sum_distances(s2, node_table)
if distance1 < distance2:
return s1, distance1
else:
return s2, distance2
def sum_distances(strategy, node_table):
dist = 0
first_row, second_row = node_table
for idx_next_node, node1 in enumerate(strategy, 1):
try:
node2 = strategy[idx_next_node]
except IndexError:
node2 = strategy[0]
dist += math.hypot(
first_row[node2-1] - first_row[node1-1],
second_row[node2-1] - second_row[node1-1])
return dist
def draw_graph(node_table, strategy):
graphX = [node_table[0][index - 1] for index in strategy]
graphY = [node_table[1][index - 1] for index in strategy]
plt.scatter(graphX, graphY)
plt.plot(graphX, graphY)
plt.show()
def main(nodes=8, strategies=100, generations=10000, mutateP=.7, crossP=.7):
#create node locations
node_table = create_nodes(nodes, 2)
# for i in range(2):
# print node_table[i]
#create first generation
table = create_nodes(nodes, strategies)
# for i in range(strategies):
# print i
# print table[i]
print "TOP MEN are looking through:"
print strategies, "strategies in", generations, "generations with",
print nodes, "nodes in each strategy..."
best_score = None
for count in range(generations):
mutate(table, node_table, mutateP, crossP)
# crossover(table, node_table, crossP)
strategy, score = sample_best(table, node_table)
if best_score is None or score < best_score:
best_strategy = strategy
best_score = score
if count % 100 == 0:
print "Foraged", count, "berries"
print "Best we got so far:", best_score, "with: ", best_strategy
# if count % 2 == 0:
# print count
# for i in range(strategies):
# print table[i]
print "=========================================================================="
print "Best we could find: ", best_score, "for strategy", best_strategy
draw_graph(node_table, best_strategy)
main()
随机导入
输入数学
导入pprint
从matplotlib导入pyplot作为plt
def创建_节点(num_节点,num_行):
元素=范围(1,num_节点+1)
return[random.sample(elements,num_nodes)for u in range(num_rows)]
def mutate(表、节点表、变异概率、交叉概率):
对于下一个_id,枚举(表1)中的行:
节点=len(行)
#印刷品
#打印“原件:”,第行
#突变
如果random.random()>变异概率:
mini,maxi=sorted(random.sample(范围(节点),2))
行[mini:maxi+1]=行[mini:maxi+1][:-1]
#打印“变异后:”,第行
#打印“介于:”、mini、maxi之间
#交叉
如果random.random()>交叉概率:
尝试:
下一行=表[下一行id]
#打印“父项:”,下一行
除索引器外:
通过
其他:
半长=节点//2
mini=random.randint(0,半长)
最大=最小+半长-1+(节点%2)
交叉=[无]*节点
#打印“划线前:”,第行
交叉[mini:maxi+1]=下一行[mini:maxi+1]
#打印“带:”,划线
迭代器=0
对于行中的元素:
如果元素交叉:
持续
而mini的目标函数是什么?