简体   繁体   English

如何找到选择多个对象的最短路径?

[英]how to find the shortest path to pick several objects?

I want to find the best path a robot can take to pick some objects from a specific space, I ask the user for the name of things he want to pick, when he types 2, the problem is already solved, but when he types more, for example, when he types 3, my program gives him the shortest path between each two, then adds the path to a list, the robot picks the objects with same order, and that's not what I want, I want it to find the shortest way to pick all of them 我想找到机器人可以从特定空间中拾取某些物体的最佳路径,我想问用户输入他想拾取的东西的名称,当他键入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)

I am not familiar with vertices amd edges in python. 我不熟悉python中的顶点amd边缘。 The below code has one function distancebetweenvertices([a,b]) you need to replace this with the real distance function. 下面的代码在顶点之间有一个函数distancebetween([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

At first, we define a function for the total distance between vertices in a list. 首先,我们为列表中顶点之间的总距离定义一个函数。 The distance function separates the list into pairs, calculates the distance between each two using the (placeholder) distancebetweenvertices function and sums it up. 距离函数将列表分成几对,使用(占位符)顶点之间的距离函数计算每两个列表之间的距离并将其求和。

Then it creates a list of all possible ways via itertools, sets the start values for bestway and bestdistance to the order the user gave the input and the according distance. 然后,它通过itertools创建所有可能方式的列表,将bestway和bestdistance的起始值设置为用户给出的输入顺序和相应的距离。 Now it checks for every possible way if the total distance is smaller. 现在,它会检查所有可能的方式,以检查总距离是否较小。 If yes, it replaces bestway and bestdistance with this way and this distance. 如果是,则用这种方式和距离替换bestway和bestdistance。 In the end, you will have best way and according distance in the bestway and bestdistance variables. 最后,您将在bestway和bestdistance变量中拥有最佳方式和相应距离。

Hope that helps. 希望能有所帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM