def EarthMoversDistance( lengraph, supplygraph, length='length', weight1='weight1', weight2='weight2' ) :
    # lengraph is a *non*-multi DiGraph
    digraph, s, t = FLOW.obtainCapacityNetwork( lengraph, supplygraph, length, weight1, weight2 )
    #
    flowgraph = FLOW.obtainFlowNetwork( digraph, s, t, capacity='capacity' )
    costgraph = FLOW.obtainWeightedCosts( flowgraph, lengraph, weight=length )
    
    # compute optimal flow
    FLOW.max_flow_min_cost( flowgraph, costgraph )
    
    return FLOW.totalcost( costgraph ).value
 def obtainWassersteinProblem( lengraph, rategraph, length='length', rate='rate' ) :
     digraph = nx.DiGraph()
     digraph.add_edges_from( lengraph.edges_iter() )
     
     for u in rategraph.nodes_iter() :
         u_supply = rategraph.in_degree( u, rate ) - rategraph.out_degree( u, rate )
         if u_supply > 0. :
             digraph.add_edge( s, u, capacity = u_supply )
         elif u_supply < 0. :
             digraph.add_edge( u, t, capacity = -u_supply )
             
     flowgraph = FLOW.obtainFlowNetwork( digraph, s, t )
     costgraph = FLOW.obtainWeightedCosts( flowgraph, lengraph, weight=length )
     
     return flowgraph, costgraph
Esempio n. 3
0
def obtainWassersteinProblem( roadnet, length='length', weight1='weight1', weight2='weight2' ) :
    """
    input: a road network, with weights on its elements
    output:
    returns a graph summarizing the network optimization problem instance;
    roadnets are multi-digraph, where edge 'keys' are assumed to be unique,
    i.e., road names; and should be different from node labels too;
    """
    
    # for convenience
    #ROADS = [ key for u,v,key in roadnet.edges_iter( keys=True ) ]
    class node : pass
    node_s = node() ; node_t = node()
    
    digraph = nx.DiGraph()
    digraph.add_node( node_s )
    digraph.add_node( node_t )
    
    """ insert supply and demand of roads """
    for u,v, road, data in roadnet.edges_iter( keys=True, data=True ) :
        roadlen = data.get( length, 1. )
        assert roadlen >= 0.
        
        oneway = data.get( 'oneway', False )
        
        surplus = data.get( weight1, 0. ) - data.get( weight2, 0. )
        deficit = -surplus
        
        # supply layer
        if surplus > 0. :
            digraph.add_edge( node_s, road, capacity=surplus )
            
            w = roadlen / surplus
            if oneway : ends = [ v ]
            else : ends = [ u, v ]
            for node in ends :
                digraph.add_edge( road, node, decision_weight=w )
                
        # demand layers
        if deficit > 0. :
            digraph.add_edge( road, node_t, capacity=deficit )
            
            w = roadlen / deficit
            if oneway : ends = [ u ]
            else : ends = [ u, v ]
            for node in ends :
                digraph.add_edge( node, road, decision_weight=w )
                
    """ insert supply and demand of nodes """
    for u, data in roadnet.nodes_iter( data=True ) :
        surplus = data.get( weight1, 0. ) - data.get( weight2, 0. )
        deficit = -surplus
        
        # supply layer
        if surplus > 0. :
            digraph.add_edge( node_s, u, capacity=surplus )
        if deficit > 0. :
            digraph.add_edge( u, node_t, capacity=deficit )
            
    """ setup the network flow structure """
    conns = roadmap_basic.connectivity_graph( roadnet, length_in=length )
    for u, v, data in conns.edges_iter( data=True ) :
        w = data.get( 'length', 1 )
        digraph.add_edge( u, v, weight=w )
    
    #return digraph, node_s, node_t        # this *just* produced a flowgraph; no problem
    flowgraph = flownets.obtainFlowNetwork( digraph, node_s, node_t )
    costgraph = flownets.obtainWeightedCosts( flowgraph, digraph )        # cute trick
    
    #return flowgraph, costgraph
    
    for u,v, data in digraph.edges_iter( data=True ) :
        dec_weight = data.get( 'decision_weight', None )
        if dec_weight is None : continue
        #
        fdata = flowgraph.get_edge_data( u, v, 0 )   # key=0, because we have tightly controlled this construction
        flow = fdata.get( 'flow' )
        
        cost = .5 * dec_weight * cvxpy.square( flow )
        #print dec_weight, flow, cost
        
        cdata = costgraph.get_edge_data( u, v, 0 )
        #print cdata
        cdata['cost'] = cost
    
    return flowgraph, costgraph