我想计算一个" distance_table = []"中的两个值之间的差异。通过排列,在这种情况下如何正确使用排列?

时间:2015-09-26 09:31:31

标签: python algorithm csv combinations permutation

我想计算一个距离表中两个值之间的差异,该距离表是从一个文件中读入的,一个csv文件与多个城市之间有距离。在.csv文件中,我有第一行有城市,     像这样:

  

巴塞罗那;贝尔格莱德;柏林

接下来的行是城市之间的距离,如下所示:

  

0; 1528.13; 1497.61

     

1528.13; 0; 999.25

     

1497.61; 999.25; 0

例如,从巴塞罗那到巴塞罗那的距离是0,(第一个数字),巴塞罗那和贝尔格莱德是1528.13,(第二个),贝尔格莱德和柏林999.25 ..等等

我正在尝试创建一个算法来搜索文件中所有城市中的最短路径。但我需要使用Python,也可能需要使用itertools的排列。

我不知道如何正确使用排列,所以我可以将不同可能性的距离加在一起。我怎么能这样做?

所以我要导入排列,csv,读取文件,然后从这里开始......

from itertools import permutations
import csv

# Read data file
distance_table = []
with open('european_cities.csv') as file:
  reader = csv.reader(file,delimiter=';')
  # First row is the city names
  city_names = reader.next()
  # The rest of the rows are the distance table
  for row in reader:
    distance_table.append([float(cell) for cell in row])

所以现在我可以从distance_table看到城市A和城市B之间的距离是这样的:

  

distance_table [city_A] [city_B]

当我只希望每个城市出现一次时,如何循环排列中的所有组合?

我想要例如:cityA-cityB + cityB-cityC + cityC-cityA 而不是:cityA-cityB + cityA-cityC + cityB-cityC + cityC-cityA etcetra。 。

我想在这里使用不同的算法,首先是一个愚蠢的算法蛮力,看看它和更智能的算法之间的时间差异,如最短路径算法。

但我不知道如何在城市中循环。怎么样?

4 个答案:

答案 0 :(得分:2)

你说你想要没有任何城市的所有排列出现两次,但你的例子最后再次列出了起始城市(cityA):

  

我想要例如:cityA-cityB + cityB-cityC + cityC-cityA

所以,假设第一个城市最后再次出现实际上是你的意思,我认为以下显示了如何生成你想要的城市的排列 - 如果这个假设是错误的,只需删除第一个城市的第一行城市是重复的。

为了获得不同的总距离(三个总是相同的),我添加了第四个城市并更改了输出格式,因此它更紧凑,更好地适应更多城市。

Barcelona;Belgrade;Berlin;Brussels
0;1528.13;1497.61;1346.0
1528.13;0;999.25;1723.0
1497.61;999.25;0;764.0
1346.0;1723.0;764.0;0

以下是代码:

from __future__ import print_function
import csv
import functools
try:
    from itertools import izip, imap
except ImportError:  # Python 3
    izip = zip
    imap = map
from itertools import permutations, repeat

# Create a dictance dictionary from csv data file with entries like this:
#     (city_a, city_b): float(distance-between-city_a-and-city_b)
# for all pairs of city names in the file.
data_filename = 'european_cities.csv'
dist_dict = {}
with open(data_filename, 'r') as file:
    reader = csv.reader(file, delimiter=';')
    cities = next(reader)  # header row
    num_cities = len(cities)
    for city in cities:  # should be a row of distances for each city
        from_city_iter = repeat(city, num_cities)
        dist_dict.update((pair for pair in izip(izip(from_city_iter, cities),
                                                imap(float, next(reader)))
                            if pair[1])) # skip 0 distances (city_a == city_b)

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2,s3), ..."
    a, b = iter(iterable), iter(iterable)
    next(b)  # advance second iterator one iteration
    return izip(a, b)

for tour in permutations(cities, len(cities)):
    tour += (tour[0],)  # make round trip by appending starting city
    route = '->'.join(tour)
    dist = sum(dist_dict[city_a, city_b] for city_a, city_b in pairwise(tour))
    print('{:^49}: {:,}'.format(route, dist))

输出:

Barcelona->Belgrade->Berlin->Brussels->Barcelona : 4,637.38
Barcelona->Belgrade->Brussels->Berlin->Barcelona : 5,512.74
Barcelona->Berlin->Belgrade->Brussels->Barcelona : 5,565.86
Barcelona->Berlin->Brussels->Belgrade->Barcelona : 5,512.74
Barcelona->Brussels->Belgrade->Berlin->Barcelona : 5,565.86
Barcelona->Brussels->Berlin->Belgrade->Barcelona : 4,637.38
 Belgrade->Barcelona->Berlin->Brussels->Belgrade : 5,512.74
 Belgrade->Barcelona->Brussels->Berlin->Belgrade : 4,637.38
 Belgrade->Berlin->Barcelona->Brussels->Belgrade : 5,565.86
 Belgrade->Berlin->Brussels->Barcelona->Belgrade : 4,637.38
 Belgrade->Brussels->Barcelona->Berlin->Belgrade : 5,565.86
 Belgrade->Brussels->Berlin->Barcelona->Belgrade : 5,512.74
  Berlin->Barcelona->Belgrade->Brussels->Berlin  : 5,512.74
  Berlin->Barcelona->Brussels->Belgrade->Berlin  : 5,565.86
  Berlin->Belgrade->Barcelona->Brussels->Berlin  : 4,637.38
  Berlin->Belgrade->Brussels->Barcelona->Berlin  : 5,565.86
  Berlin->Brussels->Barcelona->Belgrade->Berlin  : 4,637.38
  Berlin->Brussels->Belgrade->Barcelona->Berlin  : 5,512.74
 Brussels->Barcelona->Belgrade->Berlin->Brussels : 4,637.38
 Brussels->Barcelona->Berlin->Belgrade->Brussels : 5,565.86
 Brussels->Belgrade->Barcelona->Berlin->Brussels : 5,512.74
 Brussels->Belgrade->Berlin->Barcelona->Brussels : 5,565.86
 Brussels->Berlin->Barcelona->Belgrade->Brussels : 5,512.74
 Brussels->Berlin->Belgrade->Barcelona->Brussels : 4,637.38

答案 1 :(得分:1)

如果您仔细考虑一下,您会发现表单cityA-cityB + cityB-cityC + cityC-cityA的组合实际上只是A,B,C略有修改。您能想到将A,B,C转换为cityA-cityB + cityB-cityC + cityC-cityA的算法吗?也许您可以将这种修改功能与python工具结合使用,该工具可以从列表中生成唯一的组合。

答案 2 :(得分:1)

这个解决方案怎么样:

from itertools import permutations
import csv

    sums = []

    for p in permutations(distance_table[0], 2):
      sums.append(sum(p))

    for s in sums:
        print(s)

答案 3 :(得分:0)

使用排列函数的一种简单方法是:

N = len(city_names)
for perm in permutations(range(N)):
  dist = sum(distance_table[perm[i]][perm[(i+1)%N]] for i in range(N))
  print perm,dist