title: how to find the shortest path to pick several objects?
body: <p>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</p>
  
  <pre><code>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 &lt; 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)
  </code></pre>