如何找到挑选几个物体的最短路径?

时间:2019-02-09 23:08:56

标签: python

我想找到机器人可以从特定空间中拾取某些物体的最佳路径,我要求用户输入他想拾取的物体的名称,当他键入2时,问题已经解决,但是当他输入更多,例如,当他输入3时,我的程序为他提供了两个之间的最短路径,然后将该路径添加到列表中,机器人选择了具有相同顺序的对象,这不是我想要的,我想要找到最短的方法来挑选所有的人

from collections import deque, namedtuple


# we'll use infinity as a default distance to nodes.
inf = float('inf')
Edge = namedtuple('Edge', 'start, end, cost')


def make_edge(start, end, cost=1):
  return Edge(start, end, cost)


class Graph:
    def __init__(self, edges):
        # let's check that the data is right
        wrong_edges = [i for i in edges if len(i) not in [2, 3]]
        if wrong_edges:
            raise ValueError('Wrong edges data: {}'.format(wrong_edges))

        self.edges = [make_edge(*edge) for edge in edges]

    @property
    def vertices(self):
        return set(
            sum(
                ([edge.start, edge.end] for edge in self.edges), []
            )
        )

    def get_node_pairs(self, n1, n2, both_ends=True):
        if both_ends:
            node_pairs = [[n1, n2], [n2, n1]]
        else:
            node_pairs = [[n1, n2]]
        return node_pairs

    def remove_edge(self, n1, n2, both_ends=True):
        node_pairs = self.get_node_pairs(n1, n2, both_ends)
        edges = self.edges[:]
        for edge in edges:
            if [edge.start, edge.end] in node_pairs:
                self.edges.remove(edge)

    def add_edge(self, n1, n2, cost=1, both_ends=True):
        node_pairs = self.get_node_pairs(n1, n2, both_ends)
        for edge in self.edges:
            if [edge.start, edge.end] in node_pairs:
                return ValueError('Edge {} {} already exists'.format(n1, n2))

        self.edges.append(Edge(start=n1, end=n2, cost=cost))
        if both_ends:
            self.edges.append(Edge(start=n2, end=n1, cost=cost))

    @property
    def neighbours(self):
        neighbours = {vertex: set() for vertex in self.vertices}
        for edge in self.edges:
            neighbours[edge.start].add((edge.end, edge.cost))

        return neighbours

    def dijkstra(self, source, dest):
        assert source in self.vertices, 'Such source node doesn\'t exist'
        distances = {vertex: inf for vertex in self.vertices}
        previous_vertices = {
            vertex: None for vertex in self.vertices
        }
        distances[source] = 0
        vertices = self.vertices.copy()

        while vertices:
            current_vertex = min(
                vertices, key=lambda vertex: distances[vertex])
            vertices.remove(current_vertex)
            if distances[current_vertex] == inf:
                break
            for neighbour, cost in self.neighbours[current_vertex]:
                alternative_route = distances[current_vertex] + cost
                if alternative_route < distances[neighbour]:
                    distances[neighbour] = alternative_route
                    previous_vertices[neighbour] = current_vertex

        path, current_vertex = deque(), dest
        while previous_vertices[current_vertex] is not None:
            path.appendleft(current_vertex)
            current_vertex = previous_vertices[current_vertex]
        if path:
            path.appendleft(current_vertex)
        return path

thing = [
    ["a0", "b0", 2], ["a0", "a1", 1],
    ["a1", "a2", 1], ["a2", "a3", 1],
    ["a3", "a4", 1], ["a4", "b4", 2],

    ["b0", "c0", 2], ["b0", "b1", 1],
    ["b1", "b2", 1], ["b2", "b3", 1],
    ["b3", "b4", 1], ["b4", "c4", 2],

    ["c0", "c1", 1], ["c1", "c2", 1],
    ["c2", "c3", 1], ["c3", "c4", 1],


    ["a4", "b4", 2], ["a4", "a5", 1],
    ["a5", "a6", 1], ["a6", "a7", 1],
    ["a7", "a8", 1], ["a8", "b8", 2],

    ["b4", "c4", 2], ["b4", "b5", 1],
    ["b5", "b6", 1], ["b6", "b7", 1],
    ["b7", "b8", 1], ["b8", "c8", 2],

    ["c4", "c5", 1], ["c5", "c6", 1],
    ["c6", "c7", 1], ["c7", "c8", 1]
]
other=[]

for i in thing:
    a=[]
    a.append(i[1])
    a.append(i[0])
    a.append(i[2])
    other.append(a)

result = thing + other


graph = Graph(result)

NumberOfThings = int(input('how many things would you like to pick ? '))

ThingsToPick=[]

for i in range(0, NumberOfThings):
    name=input(' - ')
    ThingsToPick.append(name)

len=len(ThingsToPick)

way=[]

for i in range(0,len-1):
    for j in list(graph.dijkstra(ThingsToPick[i], ThingsToPick[i+1])):
        way.append(j)

print(way)

1 个答案:

答案 0 :(得分:0)

我不熟悉python中的顶点和边缘。下面的代码在顶点之间具有一个函数distance [[a,b]),您需要将其替换为真实距离函数。

import itertools

def distance(alist)
   pairs=[[l[i],l[i+1]] for i in range(0,len(l)-2)]
   d=0
   for pair in pairs:
      d += distancebetweenvertices(pair)
   return d

l=['a','b','c','d']
ways=itertools.combinations(l)
bestdistance=distance(l)
bestway=l
for way in ways:
   if distance(way) < bestdistance:
      bestway=way

首先,我们为列表中顶点之间的总距离定义一个函数。距离函数将列表分成几对,使用顶点函数之间的(占位符)distance计算两个之间的距离并将其求和。

然后,它通过itertools创建所有可能方式的列表,将bestway和bestdistance的起始值设置为用户给出的输入顺序和相应的距离。现在,它会检查所有可能的方式,以检查总距离是否较小。如果是,则用这种方式和距离替换bestway和bestdistance。最后,您将在bestway和bestdistance变量中拥有最佳方式和距离。

希望有帮助。