Home | History | Annotate | Download | only in tests
      1 # -*- coding: utf-8 -*-
      2 """Max flow algorithm test suite.
      3 
      4 Run with nose: nosetests -v test_max_flow.py
      5 """
      6 
      7 __author__ = """Loc Sguin-C. <loicseguin (at] gmail.com>"""
      8 # Copyright (C) 2010 Loc Sguin-C. <loicseguin (at] gmail.com>
      9 # All rights reserved.
     10 # BSD license.
     11 
     12 
     13 import networkx as nx
     14 from nose.tools import *
     15 
     16 def compare_flows(G, s, t, solnFlows, solnValue):
     17     flowValue, flowDict = nx.ford_fulkerson(G, s, t)
     18     assert_equal(flowValue, solnValue)
     19     assert_equal(flowDict, solnFlows)
     20     assert_equal(nx.min_cut(G, s, t), solnValue)
     21     assert_equal(nx.max_flow(G, s, t), solnValue)
     22     assert_equal(nx.ford_fulkerson_flow(G, s, t), solnFlows)
     23 
     24 
     25 class TestMaxflow:
     26     def test_graph1(self):
     27         # Trivial undirected graph
     28         G = nx.Graph()
     29         G.add_edge(1,2, capacity = 1.0)
     30 
     31         solnFlows = {1: {2: 1.0},
     32                      2: {1: 1.0}}
     33 
     34         compare_flows(G, 1, 2, solnFlows, 1.0)
     35 
     36     def test_graph2(self):
     37         # A more complex undirected graph
     38         # adapted from www.topcoder.com/tc?module=Statc&d1=tutorials&d2=maxFlow
     39         G = nx.Graph()
     40         G.add_edge('x','a', capacity = 3.0)
     41         G.add_edge('x','b', capacity = 1.0)
     42         G.add_edge('a','c', capacity = 3.0)
     43         G.add_edge('b','c', capacity = 5.0)
     44         G.add_edge('b','d', capacity = 4.0)
     45         G.add_edge('d','e', capacity = 2.0)
     46         G.add_edge('c','y', capacity = 2.0)
     47         G.add_edge('e','y', capacity = 3.0)
     48 
     49         H = {'x': {'a': 3, 'b': 1},
     50              'a': {'c': 3, 'x': 3},
     51              'b': {'c': 1, 'd': 2, 'x': 1},
     52              'c': {'a': 3, 'b': 1, 'y': 2},
     53              'd': {'b': 2, 'e': 2},
     54              'e': {'d': 2, 'y': 2},
     55              'y': {'c': 2, 'e': 2}}
     56 
     57         compare_flows(G, 'x', 'y', H, 4.0)
     58 
     59     def test_digraph1(self):
     60         # The classic directed graph example
     61         G = nx.DiGraph()
     62         G.add_edge('a','b', capacity = 1000.0)
     63         G.add_edge('a','c', capacity = 1000.0)
     64         G.add_edge('b','c', capacity = 1.0)
     65         G.add_edge('b','d', capacity = 1000.0)
     66         G.add_edge('c','d', capacity = 1000.0)
     67 
     68         H = {'a': {'b': 1000.0, 'c': 1000.0},
     69              'b': {'c': 0, 'd': 1000.0},
     70              'c': {'d': 1000.0},
     71              'd': {}}
     72 
     73         compare_flows(G, 'a', 'd', H, 2000.0)
     74 
     75         # An example in which some edges end up with zero flow.
     76         G = nx.DiGraph()
     77         G.add_edge('s', 'b', capacity = 2)
     78         G.add_edge('s', 'c', capacity = 1)
     79         G.add_edge('c', 'd', capacity = 1)
     80         G.add_edge('d', 'a', capacity = 1)
     81         G.add_edge('b', 'a', capacity = 2)
     82         G.add_edge('a', 't', capacity = 2)
     83 
     84         H = {'s': {'b': 2, 'c': 0},
     85              'c': {'d': 0},
     86              'd': {'a': 0},
     87              'b': {'a': 2},
     88              'a': {'t': 2},
     89              't': {}}
     90 
     91         compare_flows(G, 's', 't', H, 2)
     92 
     93     def test_digraph2(self):
     94         # A directed graph example from Cormen et al.
     95         G = nx.DiGraph()
     96         G.add_edge('s','v1', capacity = 16.0)
     97         G.add_edge('s','v2', capacity = 13.0)
     98         G.add_edge('v1','v2', capacity = 10.0)
     99         G.add_edge('v2','v1', capacity = 4.0)
    100         G.add_edge('v1','v3', capacity = 12.0)
    101         G.add_edge('v3','v2', capacity = 9.0)
    102         G.add_edge('v2','v4', capacity = 14.0)
    103         G.add_edge('v4','v3', capacity = 7.0)
    104         G.add_edge('v3','t', capacity = 20.0)
    105         G.add_edge('v4','t', capacity = 4.0)
    106 
    107         H = {'s': {'v1': 12.0, 'v2': 11.0},
    108              'v2': {'v1': 0, 'v4': 11.0},
    109              'v1': {'v2': 0, 'v3': 12.0},
    110              'v3': {'v2': 0, 't': 19.0},
    111              'v4': {'v3': 7.0, 't': 4.0},
    112              't': {}}
    113 
    114         compare_flows(G, 's', 't', H, 23.0)
    115 
    116     def test_digraph3(self):
    117         # A more complex directed graph
    118         # from www.topcoder.com/tc?module=Statc&d1=tutorials&d2=maxFlow
    119         G = nx.DiGraph()
    120         G.add_edge('x','a', capacity = 3.0)
    121         G.add_edge('x','b', capacity = 1.0)
    122         G.add_edge('a','c', capacity = 3.0)
    123         G.add_edge('b','c', capacity = 5.0)
    124         G.add_edge('b','d', capacity = 4.0)
    125         G.add_edge('d','e', capacity = 2.0)
    126         G.add_edge('c','y', capacity = 2.0)
    127         G.add_edge('e','y', capacity = 3.0)
    128 
    129         H = {'x': {'a': 2.0, 'b': 1.0},
    130              'a': {'c': 2.0},
    131              'b': {'c': 0, 'd': 1.0},
    132              'c': {'y': 2.0},
    133              'd': {'e': 1.0},
    134              'e': {'y': 1.0},
    135              'y': {}}
    136 
    137         compare_flows(G, 'x', 'y', H, 3.0)
    138 
    139     def test_optional_capacity(self):
    140         # Test optional capacity parameter.
    141         G = nx.DiGraph()
    142         G.add_edge('x','a', spam = 3.0)
    143         G.add_edge('x','b', spam = 1.0)
    144         G.add_edge('a','c', spam = 3.0)
    145         G.add_edge('b','c', spam = 5.0)
    146         G.add_edge('b','d', spam = 4.0)
    147         G.add_edge('d','e', spam = 2.0)
    148         G.add_edge('c','y', spam = 2.0)
    149         G.add_edge('e','y', spam = 3.0)
    150 
    151         solnFlows = {'x': {'a': 2.0, 'b': 1.0},
    152                      'a': {'c': 2.0},
    153                      'b': {'c': 0, 'd': 1.0},
    154                      'c': {'y': 2.0},
    155                      'd': {'e': 1.0},
    156                      'e': {'y': 1.0},
    157                      'y': {}}
    158         solnValue = 3.0
    159         s = 'x'
    160         t = 'y'
    161         
    162         flowValue, flowDict = nx.ford_fulkerson(G, s, t, capacity = 'spam')
    163         assert_equal(flowValue, solnValue)
    164         assert_equal(flowDict, solnFlows)
    165         assert_equal(nx.min_cut(G, s, t, capacity = 'spam'), solnValue)
    166         assert_equal(nx.max_flow(G, s, t, capacity = 'spam'), solnValue)
    167         assert_equal(nx.ford_fulkerson_flow(G, s, t, capacity = 'spam'),
    168                      solnFlows)
    169 
    170     def test_digraph_infcap_edges(self):
    171         # DiGraph with infinite capacity edges
    172         G = nx.DiGraph()
    173         G.add_edge('s', 'a')
    174         G.add_edge('s', 'b', capacity = 30)
    175         G.add_edge('a', 'c', capacity = 25)
    176         G.add_edge('b', 'c', capacity = 12)
    177         G.add_edge('a', 't', capacity = 60)
    178         G.add_edge('c', 't')
    179 
    180         H = {'s': {'a': 85, 'b': 12},
    181              'a': {'c': 25, 't': 60},
    182              'b': {'c': 12},
    183              'c': {'t': 37},
    184              't': {}}
    185 
    186         compare_flows(G, 's', 't', H, 97)
    187 
    188         # DiGraph with infinite capacity digon
    189         G = nx.DiGraph()
    190         G.add_edge('s', 'a', capacity = 85)
    191         G.add_edge('s', 'b', capacity = 30)
    192         G.add_edge('a', 'c')
    193         G.add_edge('c', 'a')
    194         G.add_edge('b', 'c', capacity = 12)
    195         G.add_edge('a', 't', capacity = 60)
    196         G.add_edge('c', 't', capacity = 37)
    197 
    198         H = {'s': {'a': 85, 'b': 12},
    199              'a': {'c': 25, 't': 60},
    200              'c': {'a': 0, 't': 37},
    201              'b': {'c': 12},
    202              't': {}}
    203 
    204         compare_flows(G, 's', 't', H, 97)
    205         
    206 
    207     def test_digraph_infcap_path(self):
    208         # Graph with infinite capacity (s, t)-path
    209         G = nx.DiGraph()
    210         G.add_edge('s', 'a')
    211         G.add_edge('s', 'b', capacity = 30)
    212         G.add_edge('a', 'c')
    213         G.add_edge('b', 'c', capacity = 12)
    214         G.add_edge('a', 't', capacity = 60)
    215         G.add_edge('c', 't')
    216 
    217         assert_raises(nx.NetworkXUnbounded,
    218                       nx.ford_fulkerson, G, 's', 't')
    219         assert_raises(nx.NetworkXUnbounded,
    220                       nx.max_flow, G, 's', 't')
    221         assert_raises(nx.NetworkXUnbounded,
    222                       nx.ford_fulkerson_flow, G, 's', 't')
    223         assert_raises(nx.NetworkXUnbounded,
    224                       nx.min_cut, G, 's', 't')
    225 
    226     def test_graph_infcap_edges(self):
    227         # Undirected graph with infinite capacity edges
    228         G = nx.Graph()
    229         G.add_edge('s', 'a')
    230         G.add_edge('s', 'b', capacity = 30)
    231         G.add_edge('a', 'c', capacity = 25)
    232         G.add_edge('b', 'c', capacity = 12)
    233         G.add_edge('a', 't', capacity = 60)
    234         G.add_edge('c', 't')
    235 
    236         H = {'s': {'a': 85, 'b': 12},
    237              'a': {'c': 25, 's': 85, 't': 60},
    238              'b': {'c': 12, 's': 12},
    239              'c': {'a': 25, 'b': 12, 't': 37},
    240              't': {'a': 60, 'c': 37}}
    241 
    242         compare_flows(G, 's', 't', H, 97)
    243 
    244     def test_digraph4(self):
    245         # From ticket #429 by mfrasca.
    246         G = nx.DiGraph()
    247         G.add_edge('s', 'a', capacity = 2)
    248         G.add_edge('s', 'b', capacity = 2)
    249         G.add_edge('a', 'b', capacity = 5)
    250         G.add_edge('a', 't', capacity = 1)
    251         G.add_edge('b', 'a', capacity = 1)
    252         G.add_edge('b', 't', capacity = 3)
    253         flowSoln = {'a': {'b': 1, 't': 1},
    254                     'b': {'a': 0, 't': 3},
    255                     's': {'a': 2, 'b': 2},
    256                     't': {}}
    257         compare_flows(G, 's', 't', flowSoln, 4)
    258 
    259 
    260     def test_disconnected(self):
    261         G = nx.Graph()
    262         G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
    263         G.remove_node(1)
    264         assert_equal(nx.max_flow(G,0,3),0)
    265 
    266     def test_source_target_not_in_graph(self):
    267         G = nx.Graph()
    268         G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
    269         G.remove_node(0)
    270         assert_raises(nx.NetworkXError,nx.max_flow,G,0,3)
    271         G.add_weighted_edges_from([(0,1,1),(1,2,1),(2,3,1)],weight='capacity')
    272         G.remove_node(3)
    273         assert_raises(nx.NetworkXError,nx.max_flow,G,0,3)
    274