Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kou's algorithm to find Steiner Tree using igraph

Tags:

r

igraph

I am trying to implement the Kou's algorithm to identify Steiner Tree(s) in R using igraph.

The Kou's algorithm can be described like this:

  1. Find the complete distance graph G' (G' has V' = S (steiner nodes) , and for each pair of nodes (u,v) in VxV there is an edge with weight equal to the weight of the min-cost path between these nodes p_(u,v) in G)
  2. Find a minimum spanning tree T' in G'
  3. Construct the subgraph Gs, of G by substituting every edge of T', which is an edge of G' with the corresponding shortest path of G (it there are several shortest paths, pick an arbitrary one).
  4. Find the minimal spanning tree, Ts, of Gs (If there are several minimal spanning trees, pick an arbitrary one)
  5. Construct a Steiner tree, Th, from Ts by deleting edges in Ts, if necessary, to that all the leaves in Th are Steiner nodes.

The first 2 steps are easy:

g <- erdos.renyi.game(100, 1/10) # graph
V(g)$name <- 1:100

# Some steiner nodes
steiner.points <- sample(1:100, 5)

# Complete distance graph G'
Gi <- graph.full(5)
V(Gi)$name <- steiner.points

# Find a minimum spanning tree T' in G'
mst <- minimum.spanning.tree(Gi)

However, I don't know how to replace the edges in T' for the shortest path in G. I know that with get.shortest.paths I can get the vpath from a pair of nodes, but how I replace and edge in T' with the shortest.path in G?

Many thanks in advance

like image 380
user2380782 Avatar asked May 06 '15 23:05

user2380782


1 Answers

If I'm understanding the algorithm as you've written it, I think this gets you through step 3, but please clarify if that's not the case:

library(igraph)

set.seed(2002)

g <- erdos.renyi.game(100, 1/10) # graph
V(g)$name <- as.character(1:100)

## Some steiner nodes:
steiner.points <- sample(1:100, 5)

## Complete distance graph G'
Gi <- graph.full(5)
V(Gi)$name <- steiner.points

## Find a minimum spanning tree T' in G'
mst <- minimum.spanning.tree(Gi)

##  For each edge in mst, replace with shortest path:
edge_list <- get.edgelist(mst)

Gs <- mst
for (n in 1:nrow(edge_list)) {
    i <- edge_list[n,2]
    j <- edge_list[n,1]
    ##  If the edge of T' mst is shared by Gi, then remove the edge from T'
    ##    and replace with the shortest path between the nodes of g: 
    if (length(E(Gi)[which(V(mst)$name==i) %--% which(V(mst)$name==j)]) == 1) {
        ##  If edge is present then remove existing edge from the 
        ##    minimum spanning tree:
        Gs <- Gs - E(Gs)[which(V(mst)$name==i) %--% which(V(mst)$name==j)]

        ##  Next extract the sub-graph from g corresponding to the 
        ##    shortest path and union it with the mst graph:
        g_sub <- induced.subgraph(g, (get.shortest.paths(g, from=V(g)[i], to=V(g)[j])$vpath[[1]]))
        Gs <- graph.union(Gs, g_sub, byname=T)
  }
}

par(mfrow=c(1,2))
plot(mst)
plot(Gs)

Plot of minimum spanning tree on the left, replaced with shortest paths on right:

network plots

like image 86
Forrest R. Stevens Avatar answered Sep 22 '22 20:09

Forrest R. Stevens