blob: 41393c2d71db965fd79ab8b0bca8a3605b7d575d [file] [log] [blame]
# -*- coding: utf-8 -*-
"""Max flow algorithm test suite.
Run with nose: nosetests -v test_max_flow.py
"""
__author__ = """Loïc Séguin-C. <loicseguin@gmail.com>"""
# Copyright (C) 2010 Loïc Séguin-C. <loicseguin@gmail.com>
# All rights reserved.
# BSD license.
import networkx as nx
from nose.tools import *
def compare_flows(G, s, t, solnFlows, solnValue):
flowValue, flowDict = nx.ford_fulkerson(G, s, t)
assert_equal(flowValue, solnValue)
assert_equal(flowDict, solnFlows)
assert_equal(nx.min_cut(G, s, t), solnValue)
assert_equal(nx.max_flow(G, s, t), solnValue)
assert_equal(nx.ford_fulkerson_flow(G, s, t), solnFlows)
class TestMaxflow:
def test_graph1(self):
# Trivial undirected graph
G = nx.Graph()
G.add_edge(1,2, capacity = 1.0)
solnFlows = {1: {2: 1.0},
2: {1: 1.0}}
compare_flows(G, 1, 2, solnFlows, 1.0)
def test_graph2(self):
# A more complex undirected graph
# adapted from www.topcoder.com/tc?module=Statc&d1=tutorials&d2=maxFlow
G = nx.Graph()
G.add_edge('x','a', capacity = 3.0)
G.add_edge('x','b', capacity = 1.0)
G.add_edge('a','c', capacity = 3.0)
G.add_edge('b','c', capacity = 5.0)
G.add_edge('b','d', capacity = 4.0)
G.add_edge('d','e', capacity = 2.0)
G.add_edge('c','y', capacity = 2.0)
G.add_edge('e','y', capacity = 3.0)
H = {'x': {'a': 3, 'b': 1},
'a': {'c': 3, 'x': 3},
'b': {'c': 1, 'd': 2, 'x': 1},
'c': {'a': 3, 'b': 1, 'y': 2},
'd': {'b': 2, 'e': 2},
'e': {'d': 2, 'y': 2},
'y': {'c': 2, 'e': 2}}
compare_flows(G, 'x', 'y', H, 4.0)
def test_digraph1(self):
# The classic directed graph example
G = nx.DiGraph()
G.add_edge('a','b', capacity = 1000.0)
G.add_edge('a','c', capacity = 1000.0)
G.add_edge('b','c', capacity = 1.0)
G.add_edge('b','d', capacity = 1000.0)
G.add_edge('c','d', capacity = 1000.0)
H = {'a': {'b': 1000.0, 'c': 1000.0},
'b': {'c': 0, 'd': 1000.0},
'c': {'d': 1000.0},
'd': {}}
compare_flows(G, 'a', 'd', H, 2000.0)
# An example in which some edges end up with zero flow.
G = nx.DiGraph()
G.add_edge('s', 'b', capacity = 2)
G.add_edge('s', 'c', capacity = 1)
G.add_edge('c', 'd', capacity = 1)
G.add_edge('d', 'a', capacity = 1)
G.add_edge('b', 'a', capacity = 2)
G.add_edge('a', 't', capacity = 2)
H = {'s': {'b': 2, 'c': 0},
'c': {'d': 0},
'd': {'a': 0},
'b': {'a': 2},
'a': {'t': 2},
't': {}}
compare_flows(G, 's', 't', H, 2)
def test_digraph2(self):
# A directed graph example from Cormen et al.
G = nx.DiGraph()
G.add_edge('s','v1', capacity = 16.0)
G.add_edge('s','v2', capacity = 13.0)
G.add_edge('v1','v2', capacity = 10.0)
G.add_edge('v2','v1', capacity = 4.0)
G.add_edge('v1','v3', capacity = 12.0)
G.add_edge('v3','v2', capacity = 9.0)
G.add_edge('v2','v4', capacity = 14.0)
G.add_edge('v4','v3', capacity = 7.0)
G.add_edge('v3','t', capacity = 20.0)
G.add_edge('v4','t', capacity = 4.0)
H = {'s': {'v1': 12.0, 'v2': 11.0},
'v2': {'v1': 0, 'v4': 11.0},
'v1': {'v2': 0, 'v3': 12.0},
'v3': {'v2': 0, 't': 19.0},
'v4': {'v3': 7.0, 't': 4.0},
't': {}}
compare_flows(G, 's', 't', H, 23.0)
def test_digraph3(self):
# A more complex directed graph
# from www.topcoder.com/tc?module=Statc&d1=tutorials&d2=maxFlow
G = nx.DiGraph()
G.add_edge('x','a', capacity = 3.0)
G.add_edge('x','b', capacity = 1.0)
G.add_edge('a','c', capacity = 3.0)
G.add_edge('b','c', capacity = 5.0)
G.add_edge('b','d', capacity = 4.0)
G.add_edge('d','e', capacity = 2.0)
G.add_edge('c','y', capacity = 2.0)
G.add_edge('e','y', capacity = 3.0)
H = {'x': {'a': 2.0, 'b': 1.0},
'a': {'c': 2.0},
'b': {'c': 0, 'd': 1.0},
'c': {'y': 2.0},
'd': {'e': 1.0},
'e': {'y': 1.0},
'y': {}}
compare_flows(G, 'x', 'y', H, 3.0)
def test_optional_capacity(self):
# Test optional capacity parameter.
G = nx.DiGraph()
G.add_edge('x','a', spam = 3.0)
G.add_edge('x','b', spam = 1.0)
G.add_edge('a','c', spam = 3.0)
G.add_edge('b','c', spam = 5.0)
G.add_edge('b','d', spam = 4.0)
G.add_edge('d','e', spam = 2.0)
G.add_edge('c','y', spam = 2.0)
G.add_edge('e','y', spam = 3.0)
solnFlows = {'x': {'a': 2.0, 'b': 1.0},
'a': {'c': 2.0},
'b': {'c': 0, 'd': 1.0},
'c': {'y': 2.0},
'd': {'e': 1.0},
'e': {'y': 1.0},
'y': {}}
solnValue = 3.0
s = 'x'
t = 'y'
flowValue, flowDict = nx.ford_fulkerson(G, s, t, capacity = 'spam')
assert_equal(flowValue, solnValue)
assert_equal(flowDict, solnFlows)
assert_equal(nx.min_cut(G, s, t, capacity = 'spam'), solnValue)
assert_equal(nx.max_flow(G, s, t, capacity = 'spam'), solnValue)
assert_equal(nx.ford_fulkerson_flow(G, s, t, capacity = 'spam'),
solnFlows)
def test_digraph_infcap_edges(self):
# DiGraph with infinite capacity edges
G = nx.DiGraph()
G.add_edge('s', 'a')
G.add_edge('s', 'b', capacity = 30)
G.add_edge('a', 'c', capacity = 25)
G.add_edge('b', 'c', capacity = 12)
G.add_edge('a', 't', capacity = 60)
G.add_edge('c', 't')
H = {'s': {'a': 85, 'b': 12},
'a': {'c': 25, 't': 60},
'b': {'c': 12},
'c': {'t': 37},
't': {}}
compare_flows(G, 's', 't', H, 97)
# DiGraph with infinite capacity digon
G = nx.DiGraph()
G.add_edge('s', 'a', capacity = 85)
G.add_edge('s', 'b', capacity = 30)
G.add_edge('a', 'c')
G.add_edge('c', 'a')
G.add_edge('b', 'c', capacity = 12)
G.add_edge('a', 't', capacity = 60)
G.add_edge('c', 't', capacity = 37)
H = {'s': {'a': 85, 'b': 12},
'a': {'c': 25, 't': 60},
'c': {'a': 0, 't': 37},
'b': {'c': 12},
't': {}}
compare_flows(G, 's', 't', H, 97)
def test_digraph_infcap_path(self):
# Graph with infinite capacity (s, t)-path
G = nx.DiGraph()
G.add_edge('s', 'a')
G.add_edge('s', 'b', capacity = 30)
G.add_edge('a', 'c')
G.add_edge('b', 'c', capacity = 12)
G.add_edge('a', 't', capacity = 60)
G.add_edge('c', 't')
assert_raises(nx.NetworkXUnbounded,
nx.ford_fulkerson, G, 's', 't')
assert_raises(nx.NetworkXUnbounded,
nx.max_flow, G, 's', 't')
assert_raises(nx.NetworkXUnbounded,
nx.ford_fulkerson_flow, G, 's', 't')
assert_raises(nx.NetworkXUnbounded,
nx.min_cut, G, 's', 't')
def test_graph_infcap_edges(self):
# Undirected graph with infinite capacity edges
G = nx.Graph()
G.add_edge('s', 'a')
G.add_edge('s', 'b', capacity = 30)
G.add_edge('a', 'c', capacity = 25)
G.add_edge('b', 'c', capacity = 12)
G.add_edge('a', 't', capacity = 60)
G.add_edge('c', 't')
H = {'s': {'a': 85, 'b': 12},
'a': {'c': 25, 's': 85, 't': 60},
'b': {'c': 12, 's': 12},
'c': {'a': 25, 'b': 12, 't': 37},
't': {'a': 60, 'c': 37}}
compare_flows(G, 's', 't', H, 97)
def test_digraph4(self):
# From ticket #429 by mfrasca.
G = nx.DiGraph()
G.add_edge('s', 'a', capacity = 2)
G.add_edge('s', 'b', capacity = 2)
G.add_edge('a', 'b', capacity = 5)
G.add_edge('a', 't', capacity = 1)
G.add_edge('b', 'a', capacity = 1)
G.add_edge('b', 't', capacity = 3)
flowSoln = {'a': {'b': 1, 't': 1},
'b': {'a': 0, 't': 3},
's': {'a': 2, 'b': 2},
't': {}}
compare_flows(G, 's', 't', flowSoln, 4)
def test_disconnected(self):
G = nx.Graph()
G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
G.remove_node(1)
assert_equal(nx.max_flow(G,0,3),0)
def test_source_target_not_in_graph(self):
G = nx.Graph()
G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
G.remove_node(0)
assert_raises(nx.NetworkXError,nx.max_flow,G,0,3)
G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
G.remove_node(3)
assert_raises(nx.NetworkXError,nx.max_flow,G,0,3)