This is my implementation of the Floyd Warshall algorithm:
def algorithm(self, graph):
nodes = graph.keys()
shuffle(nodes, lambda : 0.5)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, 0)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, 0)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in range(1, len(nodes)):
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
If I change the seed of the shuffle, the results sometimes change.
Why does it happen?
edit.
Here a minimal working example:
from random import shuffle
def algorithm(graph, n):
nodes = graph.keys()
shuffle(nodes, lambda : n)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, 0)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, 0)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in range(1, len(nodes)):
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
if __name__ == "__main__":
graph = {'Z': ['B', 'H', 'G', 'O', 'I'], 'F': ['C', 'G', 'D', 'O'], 'L': ['M', 'C', 'D', 'E', 'H'], 'C': ['F', 'G', 'B', 'L', 'M', 'I'], 'B': ['C', 'Z', 'I', 'O', 'H', 'G'], 'D': ['F', 'L', 'G', 'M', 'E'], 'E': ['L', 'D', 'G', 'M'], 'H': ['B', 'L', 'Z', 'I', 'O'], 'G': ['C', 'F', 'D', 'E', 'Z', 'B'], 'O': ['B', 'H', 'F', 'I', 'Z'], 'M': ['L', 'D', 'E', 'C'], 'I': ['B', 'H', 'O', 'Z', 'C']}
for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]:
dis1 = algorithm(graph,i )
print sum(dis1.values())
And this is the output:
244
246
244
244
242
242
242
242
242
The total leght should be the same, but it changes as the seed changes.
Your final set of loops is not considering k=0, and it should, otherwise you omit paths of form a->0->b in your search. In general the idea of using k to index both nodes and iteration is a bit odd (and makes debugging harder).
You could easily fix it by
from random import shuffle
def algorithm(graph, n):
nodes = graph.keys()
shuffle(nodes, lambda : n)
int_nodes = range(len(nodes))
arcs = set((a,b) for a in nodes for b in graph[a])
distances = {}
for i in int_nodes:
distances[(i, i, -1)] = 0
for i in int_nodes:
for j in int_nodes:
distances[(i, j, -1)] = 1 if (nodes[i], nodes[j]) in arcs else float("inf")
for k in int_nodes:
for i in int_nodes:
for j in int_nodes:
distances[(i, j, k)] = min(distances[(i, j, k-1)], distances[(i, k, k-1)] + distances[(k, j, k-1)])
return {(nodes[i], nodes[j]): distances[(i, j, len(nodes)-1)] for i in int_nodes for j in int_nodes}
if __name__ == "__main__":
graph = {'Z': ['B', 'H', 'G', 'O', 'I'], 'F': ['C', 'G', 'D', 'O'], 'L': ['M', 'C', 'D', 'E', 'H'], 'C': ['F', 'G', 'B', 'L', 'M', 'I'], 'B': ['C', 'Z', 'I', 'O', 'H', 'G'], 'D': ['F', 'L', 'G', 'M', 'E'], 'E': ['L', 'D', 'G', 'M'], 'H': ['B', 'L', 'Z', 'I', 'O'], 'G': ['C', 'F', 'D', 'E', 'Z', 'B'], 'O': ['B', 'H', 'F', 'I', 'Z'], 'M': ['L', 'D', 'E', 'C'], 'I': ['B', 'H', 'O', 'Z', 'C']}
for i in [0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9]:
dis1 = algorithm(graph,i )
print sum(dis1.values())
which gives
238
238
238
238
238
238
238
238
238