Example #1
0
def edge_disjoint_shortest_pair(g, src, dst):
    '''Return list of two edge-disjoint paths w/shortest total cost.

    @param g: NetworkX Graph object
    @param src: src node label
    @param dst: dst node label
    @param paths: two-element list of path lists, arbitrary ordering
    '''
    # 1. Use BFS to get shortest path.
    shortest_path = BFS(g, src, dst)

    # 2. Replace each edge of the shortest path (equivalent to two oppositely
    # directed arcs) by a single arc directed toward the source vertex.
    # 3. Make the length of each of the above arcs negative.
    g2 = flip_and_negate_path(g, shortest_path)

    # 4. Run the modified Dijkstra or the BFS algorithm again and from the
    # source vertex to the destination vertex in the above modified graph.
    shortest_path_2 = BFS(g2, src, dst)
    first_pathtotal = pathlen(g, shortest_path) + pathlen(g2, shortest_path_2)

    # 5. Transform to the original graph, and erase any interlacing edges of
    # the two paths found.  Group the remaining edges to obtain the shortest
    # pair of edge-disjoint paths.
    path1, path2 = grouped_shortest_pair(g, shortest_path, shortest_path_2)

    path1len = pathlen(g, path1)
    path2len = pathlen(g, path2)
    second_pathtotal = path1len + path2len
    assert (first_pathtotal == second_pathtotal)

    return [path1, path2]
Example #2
0
def edge_disjoint_shortest_pair(g, src, dst):
    '''Return list of two edge-disjoint paths w/shortest total cost.

    @param g: NetworkX Graph object
    @param src: src node label
    @param dst: dst node label
    @param paths: two-element list of path lists, arbitrary ordering
    '''
    # 1. Use BFS to get shortest path.
    shortest_path = BFS(g, src, dst)

    # 2. Replace each edge of the shortest path (equivalent to two oppositely
    # directed arcs) by a single arc directed toward the source vertex.
    # 3. Make the length of each of the above arcs negative.
    g2 = flip_and_negate_path(g, shortest_path)

    # 4. Run the modified Dijkstra or the BFS algorithm again and from the
    # source vertex to the destination vertex in the above modified graph.
    shortest_path_2 = BFS(g2, src, dst)
    first_pathtotal = pathlen(g, shortest_path) + pathlen(g2, shortest_path_2)

    # 5. Transform to the original graph, and erase any interlacing edges of
    # the two paths found.  Group the remaining edges to obtain the shortest
    # pair of edge-disjoint paths.
    path1, path2 = grouped_shortest_pair(g, shortest_path, shortest_path_2)
    path1len = pathlen(g, path1)
    path2len = pathlen(g, path2)
    second_pathtotal = path1len + path2len
    assert(first_pathtotal == second_pathtotal)
    return [path1, path2]
Example #3
0
def vertex_disjoint_shortest_pair(g, src, dst):
    '''Return list of two vertex-disjoint paths w/shortest total cost.

    @param g: NetworkX Graph object
    @param src: src node label
    @param dst: dst node label
    @param paths: two-element list of path lists, arbitrary ordering
    '''
    # 1. Use BFS to get shortest path.
    shortest_path = BFS(g, src, dst)

    # 2. Replace each edge of the shortest path (equivalent to two oppositely
    # directed arcs) by a single arc directed toward the source vertex.
    # Also make the arc lengths negative.
    g2 = flip_and_negate_path(g, shortest_path)

    # 3. Find the first intermediate vertex from the destination vertex whose
    # degree is greater than 3 (vertex F in Figure 3.16b).  Replace the
    # external edges by arcs incident on this vertex.

    # Use list comprehension to get an indexable reversed array.
    sp_rev = [n for n in reversed(shortest_path)]
    special_v_index = len(shortest_path) - 1  # Large to skip if not found.
    for i in range(1, len(shortest_path) - 1):
        v = sp_rev[i]
        if g.degree(v) > 3:
            next_v = sp_rev[i + 1]
            prev_v = sp_rev[i - 1]
            # We don't need to delete prev_v's edge because it was already
            # made uni-direction in flip_and_negate_path.
            ext_vs = [n for n in g.neighbors(v) if n != next_v and n != prev_v]
            for ext_v in ext_vs:
                # Since g2 is directed, remove outgoing edge only, leaving
                # the internally-directed edge.
                g2.remove_edge(v, ext_v)
            special_v_index = i
            break

    # 4. Split each intermediate vertex on the shortest path (except the vertex
    # found in Step 3) into as many subvertices as there are external edges
    # connected to it; connect the external edges to these subvertices, one
    # edge to one subvertex (see Figure 3.16c).  Note splitting is absent for
    # a vertex with degree 2 or 3.

    subvertices = {}  # subvertices[v] = list of created subvertices
    special_v = sp_rev[special_v_index]
    subvertices[special_v] = [special_v]
    for i in range(special_v_index + 1, len(shortest_path)):
        v = sp_rev[i]
        subvertices[v] = []
        if g.degree(v) > 3:
            prev_v = sp_rev[i - 1]
            next_v = sp_rev[i + 1]
            ext_vs = [n for n in g.neighbors(v) if n != next_v and n != prev_v]

            primes = ""
            for ext_v in ext_vs:
                # Create subvertex: vertex-prime
                primes += "'"
                subvertex = v + primes
                subvertices[v].append(subvertex)

                # Step 4: split and connect external edge
                add_edge_bidir(g2, subvertex, ext_v, g[v][ext_v]['weight'])

            # Remove original vertex v, which will delete all edges to v.
            # Edges connecting to v on the reversed shortest path will be
            # added in the next step.
            g2.remove_node(v)

        else:
            subvertices[v].append(v)

    # 5. Add arcs in parallel on the shortest path such that each subvertex
    # belonging to a vertex is connected to subvertices of a neighboring
    # vertex.   All the added arcs must be directed toward the source vertex.
    # If m and n denote the number of subvertices of a pair of neighboring
    # vertices, there will be a total of m x n arcs in parallel between them
    # (see Figure 3.16d), each with a length equal to the negative of the
    # length of the corresponding edge in the original graph.
    for i in range(special_v_index, len(shortest_path) - 1):
        v = sp_rev[i]
        next_v = sp_rev[i + 1]
        for v_src in subvertices[v]:
            for next_v_dst in subvertices[next_v]:
                g2.add_edge(v_src, next_v_dst)
                g2[v_src][next_v_dst]['weight'] = -g[v][next_v]['weight']

    # 6. Run the modified Dijkstra or the BFS algorithm again from the source
    # vertex to the destination vertex in the above modified graph.
    shortest_path_2 = BFS(g2, src, dst)

    # 7. (A) Coalesce the subvertices back into their parent vertices, and the
    # parallel arcs into single arcs.  (B) Replace single arcs on the shortest
    # path by edges of positive length.  (C) Remove interlacing edges of the
    # two paths found above to obtain the shortest pair of vertex-disjoint
    # paths.
    for i, v in enumerate(sp_rev):
        # Ignore destination
        if i == 0 or i == len(sp_rev) - 1:
            continue
        prev_v = sp_rev[i - 1]
        next_v = sp_rev[i + 1]
        # Is this a split vertex?
        if v in subvertices and len(subvertices[v]) > 1:
            g2.add_node(v)
            # (A) Coalesce subvertices back into parent vertices
            for subvertex in subvertices[v]:
                # Restore external edges of subvertics
                neighbors = g2.neighbors(subvertex)
                ext_vs = [n for n in neighbors if n != prev_v and n != next_v]
                for ext_v in ext_vs:
                    add_edge_bidir(g2, v, ext_v, g[v][ext_v]['weight'])
                # Clear subvertex and all its edges
                g2.remove_node(subvertex)
        # (B) Replace single arcs on the shortest path by edges of
        # positive length.
        add_edge_bidir(g2, prev_v, v, g[prev_v][v]['weight'])
        add_edge_bidir(g2, v, next_v, g[v][next_v]['weight'])

    # Second part of (A) - coalesce nodes names in the second path.
    # Strip away any "prime" characters.
    shortest_path_2 = [n.rstrip("'") for n in shortest_path_2]

    # (C) Remove interlacing edges and return shortest pair
    path1, path2 = grouped_shortest_pair(g, shortest_path, shortest_path_2)
    return [path1, path2]
Example #4
0
def vertex_disjoint_shortest_pair(g, src, dst):
    '''Return list of two vertex-disjoint paths w/shortest total cost.

    @param g: NetworkX Graph object
    @param src: src node label
    @param dst: dst node label
    @param paths: two-element list of path lists, arbitrary ordering
    '''
    mylist = []
    # 1. Use BFS to get shortest path.
    shortest_path = BFS(g, src, dst)
    if shortest_path == None:
	return [None,None]
	

    # 2. Replace each edge of the shortest path (equivalent to two oppositely
    # directed arcs) by a single arc directed toward the source vertex.
    # Also make the arc lengths negative.
    g2 = flip_and_negate_path(g, shortest_path)
    # 3. Find the first intermediate vertex from the destination vertex whose
    # degree is greater than 3 (vertex F in Figure 3.16b).  Replace the
    # external edges by arcs incident on this vertex.

    # Use list comprehension to get an indexable reversed array.
    sp_rev = [n for n in reversed(shortest_path)]
    special_v_index = len(shortest_path) - 1   # Large to skip if not found.
    for i in range(1, len(shortest_path) - 1):
        v = sp_rev[i]
        if g.degree(v) > 3:
            next_v = sp_rev[i + 1]
            prev_v = sp_rev[i - 1]
            # We don't need to delete prev_v's edge because it was already
            # made uni-direction in flip_and_negate_path.
            ext_vs = [n for n in g.neighbors(v) if n != next_v and n != prev_v]
            for ext_v in ext_vs:
                # Since g2 is directed, remove outgoing edge only, leaving
                # the internally-directed edge.
                g2.remove_edge(v, ext_v)
            special_v_index = i
            break

    # 4. Split each intermediate vertex on the shortest path (except the vertex
    # found in Step 3) into as many subvertices as there are external edges
    # connected to it; connect the external edges to these subvertices, one
    # edge to one subvertex (see Figure 3.16c).  Note splitting is absent for
    # a vertex with degree 2 or 3.

    subvertices = {}  # subvertices[v] = list of created subvertices
    special_v = sp_rev[special_v_index]
    subvertices[special_v] = [special_v]
    for i in range(special_v_index +1, len(shortest_path)):
        v = sp_rev[i]
        subvertices[v] = []
        if g.degree(v) > 3:
	    prev_v = sp_rev[i-1]
	    try:
            	next_v = sp_rev[i+1]
	    except IndexError:
		return [shortest_path,None]
		pass
            ext_vs = [n for n in g.neighbors(v) if n != next_v and n != prev_v]
            primes = ''
            for ext_v in ext_vs:
                # Create subvertex: vertex-prime
                primes += "'"
                subvertex = v + primes
                subvertices[v].append(subvertex)

                # Step 4: split and connect external edge
                add_edge_bidir(g2, subvertex, ext_v, g[v][ext_v]['weight'])

            # Remove original vertex v, which will delete all edges to v.
            # Edges connecting to v on the reversed shortest path will be
            # added in the next step.
            g2.remove_node(v)
	else:
	    subvertices[v].append(v)
	#subvertices[v].append() #test
    # 5. Add arcs in parallel on the shortest path such that each subvertex
    # belonging to a vertex is connected to subvertices of a neighboring
    # vertex.   All the added arcs must be directed toward the source vertex.
    # If m and n denote the number of subvertices of a pair of neighboring
    # vertices, there will be a total of m x n arcs in parallel between them
    # (see Figure 3.16d), each with a length equal to the negative of the
    # length of the corresponding edge in the original graph.
    for i in range(special_v_index, len(shortest_path) - 1):
        v = sp_rev[i]
        next_v = sp_rev[i + 1]
        for v_src in subvertices[v]:
            for next_v_dst in subvertices[next_v]:
                g2.add_edge(v_src, next_v_dst)
                g2[v_src][next_v_dst]['weight'] = -g[v][next_v]['weight']

    # 6. Run the modified Dijkstra or the BFS algorithm again from the source
    # vertex to the destination vertex in the above modified graph.
    shortest_path_2 = BFS(g2, src, dst)
    if shortest_path_2 == None:
    	return [shortest_path,None]

    # 7. (A) Coalesce the subvertices back into their parent vertices, and the
    # parallel arcs into single arcs.  (B) Replace single arcs on the shortest
    # path by edges of positive length.  (C) Remove interlacing edges of the
    # two paths found above to obtain the shortest pair of vertex-disjoint
    # paths.
    for i, v in enumerate(sp_rev):
        # Ignore destination
        if i == 0 or i == len(sp_rev) - 1:
            continue
        prev_v = sp_rev[i - 1]
        next_v = sp_rev[i + 1]
        # Is this a split vertex?
        if v in subvertices and len(subvertices[v]) > 1:
            g2.add_node(v)
            # (A) Coalesce subvertices back into parent vertices
            for subvertex in subvertices[v]:
                # Restore external edges of subvertics
                neighbors = g2.neighbors(subvertex)
                ext_vs = [n for n in neighbors if n != prev_v and n != next_v]
                for ext_v in ext_vs:
		    try:
                    	add_edge_bidir(g2, v, ext_v, g[v][ext_v]['weight'])
		    except KeyError:
			return shortest_path,shortest_path_2
		# Clear subvertex and all its edges
                g2.remove_node(subvertex)
        # (B) Replace single arcs on the shortest path by edges of
        # positive length.
        add_edge_bidir(g2, prev_v, v, g[prev_v][v]['weight'])
        add_edge_bidir(g2, v, next_v, g[v][next_v]['weight'])

    # Second part of (A) - coalesce nodes names in the second path.
    # Strip away any "prime" characters.
    shortest_path_2 = [n.rstrip("'") for n in shortest_path_2] 

    # (C) Remove interlacing edges and return shortest pair
    path1, path2 = grouped_shortest_pair(g, shortest_path, shortest_path_2)
    return [path1, path2]