Search code examples
rigraphsubgraph

How to define the mapping parameter iteratively to contract vertices chains?


I have a simple graph g. It is requared to smoth the graph by deleting the vertices whose degree is 2 with preserving the layout of the original graph. The same task was solved in the Mathematica.

library(igraph)
set.seed(1)
# preprocessing
g          <- sample_gnp(40, 1/20)
V(g)$name  <- seq(1:vcount(g))
components <- clusters(g, mode="weak")
biggest_cluster_id <- which.max(components$csize)
vert_ids           <- V(g)[components$membership == biggest_cluster_id]
vert_ids

# input random graph
g    <- induced_subgraph(g, vert_ids)
LO = layout.fruchterman.reingold(g)
plot(g, vertex.color = ifelse(degree(g)==2, "red", "green"), main ="g", layout = LO)

I have selected vertices chains with a degree of 2.

subg     <- induced_subgraph(g, degree(g)==2)
subg_ids <- V(subg); subg_ids

I have read the Q&A and I manually define the mapping parameter of the contract() function.

# join nodes 3 -> 14, 15 -> 40, 13 -> 31, 29 -> 6
mapping = c(2, 3, 4, 5, 6, 7, 8, 10, 13, 3, 15, 16, 17, 18, 19, 20, 21, 22, 23, 25, 26, 27, 6, 30, 13, 32, 33, 34, 35, 36, 38, 39, 15)

g2 <- simplify(contract(g, mapping=mapping, vertex.attr.comb=toString))
# L2 <- LO[-as.numeric(c(14, 40, 31, 6)),] # not working
plot(g2, vertex.color = ifelse(degree(g2)==2, "red", "green"), main ="g2")

Question. What is a possible way to define the mapping parameter iteratively?

enter image description here


Solution

  • Here is an option without mapping in contract (so you don't need to configure mapping manually)

    g2 <- graph_from_data_frame(
      rbind(
        get.data.frame(delete.vertices(g, names(subg_ids))),
        do.call(
          rbind,
          lapply(
            decompose(subg),
            function(x) {
              nbs <- names(unlist(neighborhood(g, nodes = names(V(x))[degree(x) < 2])))
              setNames(data.frame(t(subset(nbs, !nbs %in% names(subg_ids)))), c("from", "to"))
            }
          )
        )
      ),
      directed = FALSE
    )
    

    and you will see the graph below after running

    plot(g2, main = "g2", layout = LO[match(names(V(g2)), names(V(g))), ])
    

    enter image description here