I have a list of tuples of the form:
data = [(\'Abe\', \'Bob\', \'3\'),
(\'Abe\', \'Frank\', \'5\'),
(\'Abe\', \'George\', \'4\'),
(
def get_rpath_with_weight(data,start,end):
rpath = []
reachable=False
nxt_dst = start
weight_ = 0
rpath.append(nxt_dst)
for datum in data:
if nxt_dst in datum:
#print datum
fm_ = datum[0]
to_ = datum[1]
weight_ = weight_ + int(datum[2])
if fm_ == nxt_dst:
nxt_dst = to_
else:
nxt_dst = fm_
if nxt_dst == end:
reachable=True
rpath.append(nxt_dst)
print rpath,weight_,reachable
get_rpath_with_weight(data,'Abe','Dan')
get_rpath_with_weight(data,'Dan','Frank')
Sample Output
['Abe', 'Bob', 'Carl', 'Dan'] 6 True
['Dan', 'Carl'] 2 False
Above example can may get path and determine if reachable, but I think you need to further enhance it to handle multiple paths too.
You could generate all the possible paths, and sort them by weight. Note I've changed the weights in the data to be numbers, not strings:
data = [
('Abe', 'Bob', 3),
('Abe', 'Frank', 5),
('Abe', 'George', 4),
('Carl', 'Bob', 1),
('Dan', 'Carl', 2),
]
WEIGHT = 0
NODES = slice(1, None)
def get_path_and_weight(data, start, end):
paths = [[0, start]]
added = True
while added:
added = False
for first, second, weight in data:
for path in paths:
candidate = None
if (first in path[NODES]) and (second not in path[NODES]):
candidate = second
elif (first not in path[NODES]) and (second in path[NODES]):
candidate = first
if candidate:
new_path = list(path)
new_path.append(candidate)
new_path[WEIGHT] += weight
if new_path not in paths:
paths.append(new_path)
added = True
for path in sorted(paths):
if end in path[NODES]:
return path
return None
You can then call this something like:
weight, *path = get_path_and_weight(data, "Abe", "Dan")
print(path, "with weight", weight)
Gives the result:
['Abe', 'Bob', 'Carl', 'Dan'] with weight 6
And since it returns a path or None
, you can still use it as predicate function as well:
if get_path_and_weight(data, "Abe", "Dan"):
print("connected")
There are several packages that are already developed and debugged that do this, e.g., networkx
import networkx as nx
data = [('Abe', 'Bob', '3'),
('Abe', 'Frank', '5'),
('Abe', 'George', '4'),
('Carl', 'Bob', '1'),
('Dan', 'Carl', '2')]
g = nx.Graph()
for e in data:
g.add_edge(e[0], e[1], distance=int(e[2]))
>>> nx.shortest_path(g, 'Abe', 'Bob', 'distance'), nx.shortest_path_length(g, 'Abe', 'Bob', 'distance')
(['Abe', 'Bob'], 3)