假设您有一个从A 到J 的点列表,那么将所有这些点配对的矩阵如下所示:
AA AB AC AD AE AF AG AH AI AJ
BA BB BC BD BE BF BG BH BI BJ
CA CB CC CD CE CF CG CH CI CJ
DA DB DC DD DE DF DG DH DI DJ
EA EB EC ED EE EF EG EH EI EJ
FA FB FC FD FE FF FG FH FI FJ
GA GB GC GD GE GF GG GH GI GJ
HA HB HC HD HE HF HG HH HI HJ
IA IB IC ID IE IF IG IH II IJ
JA JB JC JD JE JF JG JH JI JJ
这就是您的循环当前计算的结果。但是,AB 和 BA 的距离相等,并且中心线上的距离(AA、BB、...)始终为零。
我们可以通过仅计算矩阵中x < y 的点之间的距离,将工作量减少一半(甚至不到一半,从n^2 到n^2 / 2 - n)。
AB AC AD AE AF AG AH AI AJ
BC BD BE BF BG BH BI BJ
CD CE CF CG CH CI CJ
DE DF DG DH DI DJ
EF EG EH EI EJ
FG FH FI FJ
GH GI GJ
HI HJ
IJ
通过镜像上三角形可以轻松填充空白。留在示例中,这是:
addresses = ['A','B','C','D','E','F','G','H','I','J']
distances = []
for x, a in enumerate(addresses):
row = []
distances.append(row)
for y, b in enumerate(addresses):
if x < y:
row.append(a + b) # actually calculate something
elif x == y:
row.append('--') # that's always 0
else:
row.append(distances[y][x]) # we already calculated that
for row in distances:
print(' '.join(row))
给我们这个:
-- AB AC AD AE AF AG AH AI AJ
AB -- BC BD BE BF BG BH BI BJ
AC BC -- CD CE CF CG CH CI CJ
AD BD CD -- DE DF DG DH DI DJ
AE BE CE DE -- EF EG EH EI EJ
AF BF CF DF EF -- FG FH FI FJ
AG BG CG DG EG FG -- GH GI GJ
AH BH CH DH EH FH GH -- HI HJ
AI BI CI DI EI FI GI HI -- IJ
AJ BJ CJ DJ EJ FJ GJ HJ IJ --
速度的下一步可能是多线程,但也许这种优化已经足以满足您的用例。
上面的多线程实现可能看起来像这样(它可能不是 pythonic 不止一种,但它可以完成工作):
from multiprocessing import cpu_count
from multiprocessing.dummy import Pool as ThreadPool
# credit https://stackoverflow.com/a/54802737
def chunks(l, n):
"""Yield n number of striped chunks from l."""
for i in range(0, n):
yield l[i::n]
def calculate_travel_distance(a, b):
return a + b
def calculate_distance_matrix(addresses):
# prepare distance matrix, list of lists with n^2 slots
distance_matrix = [['--' for a in addresses] for b in addresses]
# the workload is the upper matrix triangle (where x < y)
# since we're multi-threading, also remember the x,y position
workload = [((a, b),(x, y)) for y, b in enumerate(addresses) for x, a in enumerate(addresses) if x < y]
# worker function
def worker(chunk):
return [(calculate_travel_distance(*points), matrix_pos) for points, matrix_pos in chunk]
# distribute workload over available CPU cores
pool = ThreadPool(cpu_count())
result_chunks = pool.map(worker, chunks(workload, cpu_count()))
# distribute result chunks into their slots
for result_chunk in result_chunks:
for result, matrix_pos in result_chunk:
x, y = matrix_pos
distance_matrix[x][y] = result
distance_matrix[y][x] = result
return distance_matrix
addresses = ['A','B','C','D','E','F','G','H','I','J']
distaince_matrix = calculate_distance_matrix(addresses)
for row in distaince_matrix:
print(' '.join(row))
它打印同样的东西:
-- AB AC AD AE AF AG AH AI AJ
AB -- BC BD BE BF BG BH BI BJ
AC BC -- CD CE CF CG CH CI CJ
AD BD CD -- DE DF DG DH DI DJ
AE BE CE DE -- EF EG EH EI EJ
AF BF CF DF EF -- FG FH FI FJ
AG BG CG DG EG FG -- GH GI GJ
AH BH CH DH EH FH GH -- HI HJ
AI BI CI DI EI FI GI HI -- IJ
AJ BJ CJ DJ EJ FJ GJ HJ IJ --