1

I'm using NetworkX to solve a maximum-flow problem with more than one source and sink. I found a function that works relatively well in NetworkX called max_cost_flow however the issue I'm having is that it requires that the net demand be zero, in other words no sink should get less than it needs, otherwise an error is raised.

What can I use (or how can I modify this algorithm) to allow it to calculate the best possible flow and not necessarily the one satisfies all conditions?

Per kraskevich's suggestion:

import networkx as nx

def convert(graph):

    allNodes = graph.nodes()

    newSource = len(allNodes) + 1
    newSink = len(allNodes) + 2

    graph.add_node(newSource)
    graph.add_node(newSink)


    for currentNode in allNodes:

        demand = graph.node[currentNode]['demand']

        if demand < 0 :
            graph.add_edge(newSource, currentNode, weight=0, capacity=demand)


        if demand > 0:
            graph.add_edge(newSink, currentNode, weight=0, capacity=demand)

    return graph



g = nx.DiGraph()

g.add_node(1, demand = 1)
g.add_node(2, demand = -2)
g.add_node(3, demand = 2)
g.add_node(4, demand = -4)

g.add_edge(1, 2, weight=4, capacity=100)
g.add_edge(1, 4, weight=3, capacity=100)
g.add_edge(3, 2, weight=5, capacity=100)
g.add_edge(3, 4, weight=2, capacity=100)
g.add_edge(3, 1, weight=1)
newGraph = convert(g)
print(nx.max_flow_min_cost(g, newGraph.nodes()[-2],newGraph.nodes()[-1]))
Lucas
  • 6,869
  • 5
  • 29
  • 44
ninesalt
  • 4,054
  • 5
  • 35
  • 75

1 Answers1

2
  1. You can convert a multi-source flow problem to a single-source problem by creating a new source vertex and adding edges with zero cost and the old value of demand from it to all old sources.

  2. You can do the same thing think with all sinks (but the edges should from the old sinks to a new one).

  3. After that, you can use the max_flow_min_cost function to find the maximum flow with the smallest cost (it doesn't require all demands to be satisfied).

Upd: there're a few bugs in your code. Here's a working example (I have slightly changed the graph so that the flow is non-zero):

import networkx as nx

def convert(graph):
    allNodes = graph.nodes()
    newSource = len(allNodes) + 1
    newSink = len(allNodes) + 2

    graph.add_node(newSource)
    graph.add_node(newSink)

    for currentNode in allNodes:
        demand = graph.node[currentNode]['demand']
        # Direction matters
        # It goes FROM the new source and TO the new sink
        if demand < 0:
            graph.add_edge(newSource, currentNode, weight=0, capacity=-demand)
        if demand > 0:
            graph.add_edge(currentNode, newSink, weight=0, capacity=demand)
        # We also need to zero out all demands
        graph.node[currentNode]['demand'] = 0
    return graph



g = nx.DiGraph()

g.add_node(1, demand = 1)
g.add_node(2, demand = -2)
g.add_node(3, demand = 2)
g.add_node(4, demand = -4)

g.add_edge(1, 2, weight=4, capacity=100)
g.add_edge(1, 4, weight=3, capacity=100)
g.add_edge(2, 3, weight=5, capacity=100)
g.add_edge(4, 3, weight=2, capacity=100)
g.add_edge(1, 3, weight=1)
newGraph = convert(g)
# The order of s and t matters here, too
print(nx.max_flow_min_cost(g, g.nodes()[-2], g.nodes()[-1]))
kraskevich
  • 18,368
  • 4
  • 33
  • 45
  • I dont understand what you mean by "and the old value of demand from it to all old sources." – ninesalt Mar 26 '17 at 17:07
  • Let's assume that you had a source `s_old` with a demand `d`. You need to an edge `new_source -> s_old` with `cost = 0` and `capacity = d`. – kraskevich Mar 26 '17 at 17:09
  • Oh so you just mean connect all the sources to a "main" source with demand equal to the total demand of the other sources and with a capacity = demand. Correct? – ninesalt Mar 26 '17 at 17:14
  • @Swailem95 Yes. You don't need the demand for the new "main" source though as the `max_flow_min_cost` function doesn't use the demand for the source and the sink (it just computes the maximum cheapest flow). – kraskevich Mar 26 '17 at 17:16
  • I just tried it but I got an error saying `total node demand is not zero`. I will post my code in the post now. – ninesalt Mar 26 '17 at 17:34
  • This is perfect. Thank you. – ninesalt Mar 26 '17 at 18:30