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
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