Reputation: 13
I am trying to solve a problem similar to what I have described below. Could you please suggest a solution or recommend some algorithms to try in NetworkX. Many thanks.
Say there is a ball that has a starting momentum of 100. How far can the ball get down each of all the possible paths before it loses all momentum, and stops?
When the ball rolls uphill it loses momentum (i.e. the edge has a negative weight).
When the ball rolls downhill it gains momentum (i.e. the edge has a positive weight).
Examples:
1st path: (1)--[weight: -50]-->(2)--[weight: 40]-->(3)--[weight: -50]-->(4)--[weight: -90]-->(5)
2nd path: (1)--[weight: -105]-->(6)
Etc.
So, in the first path the ball gets only as far as node 4. In the second path the ball doesn’t get past node 1.
Upvotes: 0
Views: 396
Reputation: 13
The bellman_ford_predecessor_and_distance algorithm seems to work. If the distance <= -100 then the ball stopped at the predecessor node, so I copied the graph, removed the relevant edges, and ran the algorithm again to check.
import networkx as nx
G = nx.DiGraph()
G.add_edge(1, 2, weight= -50)
G.add_edge(2, 3, weight= 40)
G.add_edge(3, 4, weight= -50)
G.add_edge(4, 5, weight= -90)
G.add_edge(1, 6, weight= -105)
G.add_edge(6, 7, weight= 110)
pred, dist = nx.bellman_ford_predecessor_and_distance(G, 1)
print(pred, dist)
F = G
for x, y in dist.items():
if y <= -100:
z = pred.get(x)[0]
F.remove_edge(z,x)
pred, dist = nx.bellman_ford_predecessor_and_distance(G, 1)
print(pred, dist)
Upvotes: 1
Reputation: 17794
I haven‘t found any special algorithm in Networkx
for this purpose. You can use the following function, which uses Bellman-Ford Algorithm:
import networkx as nx
G = nx.DiGraph()
G.add_weighted_edges_from([(1, 2, -50), (2, 3, 40), (3, 4, -50),
(4, 5, -90), (1, 6, -105)])
def func(graph, source, target, start_weight):
total = start_weight
path = []
p = nx.bellman_ford_path(graph, source, target)
for u, v in zip(p, p[1:]):
total += G[u][v]['weight']
path.append(u)
if total < 0:
return path
else:
return path
print(func(G, 1, 5, 100))
# [1, 2, 3, 4]
print(func(G, 1, 6, 100))
# [1]
Upvotes: 1