0

I’m a student who is (trying) to write a python implementation of Dykstra’s Algorithm. I know this question has been asked 100 times before, but there are some specifics of my situation I’m not fully understanding.

I have a weighted, non-directed graph with 10 nodes. My actual graph will have many more nodes. The graph is sorted as a 3 dimensional list. I’m pasting in some output of the program we wrote to generate the graph.

`Hello. I’m a student who is (trying) to write a python implementation of Dykstra’s Algorithm. I know this question has been asked 100 times before, but there are some specifics of my situation I’m not fully understanding.

I have a weighted, non-directed graph with 10 nodes. My actual graph will have many more nodes. The graph is sorted as a 3 dimensional list. I’m pasting in some output of the program we wrote to generate the graph.

Node 1 : [[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]]
Node 2 : [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]]
Node 3 : [[6, 2], [1, 12], [5, 7], [9, 1]]
Node 4 : [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]]
Node 5 : [[2, 6], [4, 10], [3, 7], [7, 8]]
Node 6 : [[3, 2], [9, 10]]
Node 7 : [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]]
Node 8 : [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]]
Node 9 : [[1, 11], [6, 10], [3, 1]]
Node 10 : [[4, 5], [8, 4]]

In less readable format, the graph is stored as a 3 dimensional list. So for example, at index 0, there are connections to node 8,9,2,3 and 7. And the weight between node 8 and 0 is 3. The weight between node 0 and 9 and 11. I think you get the idea.

myGraph = [[[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]], [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]], [[6, 2], [1, 12], [5, 7], [9, 1]], [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]], [[2, 6], [4, 10], [3, 7], [7, 8]], [[3, 2], [9, 10]], [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]], [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]], [[1, 11], [6, 10], [3, 1]], [[4, 5], [8, 4]]]

So the challenge is finding a python implementation of dykstra’s that will accept a list as input, and output the optimal route. It seems like most graphs are built around a dictionary data type, but that isn’t my situation.

I’ve started to try to write my own version of dijkstra’s, using the 3D list, but not had luck, as it’s a bit complex for me. I've also tried to use previously posted versions of dijkstra's algorithm in Python, however they are designed to run dictionaries not 3 dimensional lists. Here is my earlier attempt.

[[[4, 2], [2, 1], [3, 4]], [[1, 1], [4, 2], [3, 4]], [[1, 4], [2, 4], 
[4, 4]], [[1, 2], [2, 2], [3, 4]]]

class Graph:
  def __init__(self):
    self.nodes = set()
    self.edges = defaultdict(list)
    self.distances = {}

  def add_node(self, value):
    self.nodes.add(value)

  def add_edge(self, from_node, to_node, distance):
    self.edges[from_node].append(to_node)
    self.edges[to_node].append(from_node)
    self.distances[(from_node, to_node)] = distance


def dijsktra(graph, initial):
  visited = {initial: 0}
  path = {}

  nodes = set(graph.nodes)

  while nodes:
    min_node = None
    for node in nodes:
      if node in visited:
        if min_node is None:
          min_node = node
        elif visited[node] < visited[min_node]:
          min_node = node

    if min_node is None:
      break

    nodes.remove(min_node)
    current_weight = visited[min_node]

    for edge in graph.edges[min_node]:
      weight = current_weight + graph.distance[(min_node, edge)]
      if edge not in visited or weight < visited[edge]:
        visited[edge] = weight
        path[edge] = min_node

  return visited, path

I really would be greatly appreciative of any help anyone could give to me, as I’ve been struggling with this for a while. Thank you!

JoeDoe
  • 3
  • 2

2 Answers2

0

The recommendations on trying available implementations seem good, but as it is not a complex algorithm you can try your own code.

Simple case of Dijkstra:

simple case of dijkstra

As the picture shows, you'll be running the algorithm on all nodes separately. Let's just take node 0 into account, you should have three data structures for 'chosen route' and 'all unvisited ones' and 'unused in previous iteration'. You start by checking the neighbors which can be implemented by a simple list comparison or checking, choosing the least costing neighbor and adding it to chosen route, and add the unused neighbor as unused in previous iteration. Then you go to chosen route node, comparing its neighbors with the one in the previous iteration. You continue this until all nodes are available in your chosen route structure.

JonathanDavidArndt
  • 2,518
  • 13
  • 37
  • 49
Danii-Sh
  • 447
  • 1
  • 4
  • 18
0

The following seems to work with your data-structure:

initial=1       #This is the number-label (not the index) of your starting node
assigned={}  #When a node has been given a permenant min-weight
visited={initial:0}  #When a node has a temporary min-weight
path={initial:[initial]}  #stores the path after a permenant weight has been assigned

myGraph = [[[8, 3], [9, 11], [2, 12], [3, 12], [7, 6]], [[5, 6], [4, 3], [1, 12], [8, 11], [7, 1]], [[6, 2], [1, 12], [5, 7], [9, 1]], [[2, 3], [8, 2], [10, 5], [5, 10], [7, 4]], [[2, 6], [4, 10], [3, 7], [7, 8]], [[3, 2], [9, 10]], [[2, 1], [4, 4], [5, 8], [1, 6], [8, 3]], [[1, 3], [2, 11], [4, 2], [7, 3], [10, 4]], [[1, 11], [6, 10], [3, 1]], [[4, 5], [8, 4]]]

while len(assigned)<len(myGraph):
    next_node= min(visited,key=visited.get)
    assigned[next_node]=visited[next_node]
    del visited[next_node]
    for node in myGraph[next_node-1]:  # The minus one is because your nodes are numbered from 1 (as apposed to 0).
        if node[0] in visited:
            if visited[node[0]]>assigned[next_node]+node[1]:
                visited[node[0]]=assigned[next_node]+node[1]
        else:
            if node[0] in assigned:
                if assigned[node[0]]+node[1]==assigned[next_node]:
                    path[next_node]=path[node[0]]+[next_node]
            else:
                visited[node[0]]=assigned[next_node]+node[1]

path is a dict containing lists to show you the path starting at whatever your initial node is. I would explaine each step but I think I would just be explaing Dikstra's algorithm (which you seem to already know) - please ask for clarification in the comments if there if you have questions though. I hope this helps you.

tim-mccurrach
  • 6,395
  • 4
  • 23
  • 41