def measurenx_to_approxnx( roadnet, epsilon, 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; """ digraph = nx.DiGraph() #digraph.add_node('s') #digraph.add_node('t') SUPPLY = [] DEMAND = [] """ insert supply and demand of roads """ for u,v, road, data in roadnet.edges_iter( keys=True, data=True ) : roadlen = float( data.get( length, 1 ) ) # float() just in case assert roadlen >= 0. """ split the road into equal-length segments; create a node for each segment; record boundary points, and mass contained """ N = int( np.ceil( roadlen / epsilon ) ) eps = roadlen / N surplus = float( data.get( weight1, 0. ) ) - data.get( weight2, 0. ) deficit = -surplus bd = np.linspace( 0, roadlen, N+1 ) bd = [ roadmaps.RoadAddress( road, x ) for x in bd ] for i, boundary in enumerate( zip( bd[:-1], bd[1:] ) ) : if surplus > 0. : node = (road,i,'supply') digraph.add_node( node, boundary=boundary ) digraph.add_edge( 's', node, flow=cvxpy.variable(), minflow=0., maxflow=surplus/N ) SUPPLY.append( node ) if deficit > 0. : node = (road,i,'demand') digraph.add_node( node, boundary=boundary ) digraph.add_edge( node, 't', flow=cvxpy.variable(), minflow=0., maxflow=deficit/N ) DEMAND.append( node ) """ ...and nodes """ for u, data in roadnet.nodes_iter( data=True ) : surplus = data.get( weight1, 0. ) - data.get( weight2, 0. ) deficit = -surplus if surplus > 0. : boundary = [ roadmaps.roadify( roadnet, u, weight=length ) ] node = (u,'supply') digraph.add_node( node, boundary=boundary ) digraph.add_edge( 's', node, flow=cvxpy.variable(), minflow=0., maxflow=surplus ) SUPPLY.append( node ) if deficit > 0. : boundary = [ roadmaps.roadify( roadnet, v, weight=length ) ] node = (u,'demand') digraph.add_node( node, boundary=boundary ) digraph.add_edge( node, 't', flow=cvxpy.variable(), minflow=0., maxflow=deficit ) DEMAND.append( node ) """ generate bipartite graph b/w SUPPLY and DEMAND """ for u, v in itertools.product( SUPPLY, DEMAND ) : bd_u = digraph.node[u]['boundary'] bd_v = digraph.node[v]['boundary'] options = [ pair for pair in itertools.product( bd_u, bd_v ) ] options = [ roadmaps.distance( roadnet, p, q, weight=length ) for p,q in options ] #options = [ np.inf ] w = min( options ) W = max( options ) flowvar = cvxpy.variable() digraph.add_edge( u, v, flow=flowvar, minflow=0., w=w, W=W, cost_lo = w * flowvar, cost_hi = W * flowvar ) nxopt.attach_flownx_constraints( digraph ) return digraph # a flow network
def measurenx_to_approxnx(roadnet, epsilon, 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; """ digraph = nx.DiGraph() digraph.add_node("s") digraph.add_node("t") """ insert supply and demand of roads """ for u, v, road, data in roadnet.edges_iter(keys=True, data=True): roadlen = float(data.get(length, 1)) # float() just in case assert roadlen >= 0.0 oneway = data.get("oneway", False) surplus = float(data.get(weight1, 0.0)) - data.get(weight2, 0.0) deficit = -surplus """ split the road into equal-length segments; create a node for each segment; """ N = int(np.ceil(roadlen / epsilon)) eps = roadlen / N if surplus > 0.0: NODES = [(road, k, "supply") for k in range(N)] for node in NODES: digraph.add_edge( "s", node, flow=cvxpy.variable(), minflow=0.0, maxflow=surplus / N, w_lo=-eps, w_hi=0.0 ) SEQ = [u] + NODES + [v] for lnode, rnode in zip(SEQ[:-1], SEQ[1:]): digraph.add_edge(lnode, rnode, flow=cvxpy.variable(), minflow=0.0, w_lo=eps, w_hi=eps) if not oneway: digraph.add_edge(rnode, lnode, flow=cvxpy.variable(), minflow=0.0, w_lo=eps, w_hi=eps) if deficit > 0.0: NODES = [(road, k, "demand") for k in range(N)] for node in NODES: digraph.add_edge( node, "t", flow=cvxpy.variable(), minflow=0.0, maxflow=deficit / N, w_lo=-eps, w_hi=0.0 ) SEQ = [u] + NODES + [v] for lnode, rnode in zip(SEQ[:-1], SEQ[1:]): digraph.add_edge(lnode, rnode, flow=cvxpy.variable(), minflow=0.0, w_lo=eps, w_hi=eps) if not oneway: digraph.add_edge(rnode, lnode, flow=cvxpy.variable(), minflow=0.0, w_lo=eps, w_hi=eps) """ insert supply and demand of nodes """ for u, data in roadnet.nodes_iter(data=True): surplus = data.get(weight1, 0.0) - data.get(weight2, 0.0) deficit = -surplus # supply layer if surplus > 0.0: digraph.add_edge("s", u, flow=cvxpy.variable(), minflow=0.0, maxflow=surplus) if deficit > 0.0: digraph.add_edge(u, "t", flow=cvxpy.variable(), minflow=0.0, maxflow=deficit) """ setup the network flow structure """ conns = roadmaps.connectivity_graph(roadnet) for u, v, data in conns.edges_iter(data=True): weight = data.get(length, 1) flowvar = cvxpy.variable() digraph.add_edge(u, v, flow=cvxpy.variable(), minflow=0.0, w_lo=weight, w_hi=weight) """ turn the weights into costs """ for _, __, data in digraph.edges_iter(data=True): flowvar = data["flow"] if "w_lo" in data: data["cost_lo"] = data["w_lo"] * flowvar if "w_hi" in data: data["cost_hi"] = data["w_hi"] * flowvar nxopt.attach_flownx_constraints(digraph) return digraph # a flownx