Search code examples
rgraphigraphgreedyconnected-components

How to add a edges between component of a graph in igraph R


I have a graph containing 4 components. Now, I want to add an edge among all components based on the size of the membership.

For example, the following graph contains 4 components.

enter image description here

First, I will connect all components with only one edge and take the edge randomly. I can do it using this code

graph1 <- graph_from_data_frame(g, directed = FALSE)
E(graph1)$weight <- g$new_ssp
cl <- components(graph1)

graph2 <- with(
  stack(membership(cl)),
  add.edges(
    graph1,
    c(combn(sapply(split(ind, values), sample, size = 1), 2)),
    weight = runif(choose(cl$no, 2))
  )
)

Secondly, now, I want to add an edge between component-1 and component-2. I want to add an edge between 2 components but rest of the component will be present in the new graph from the previous graph.

Like, after adding an edge between component-1 and component-2, the new graph will contain 3 component 1st (component-1 and component-2 as a 1 component because we added 1 edge), 2nd (component-3 from the main graph), and 3rd (component-4 from the main graph). I can do it using this code

dg <- decompose.graph(graph1)
graph3 <- (dg[[1]] %u% dg[[2]])

component_subgraph_1 <- components(graph3)

graph2 <- with(
  stack(membership(component_subgraph_1)),
  add.edges(
    graph1,
    c(combn(sapply(split(ind, values), sample, size = 1), 2)),
    weight = 0.01))

Figure: enter image description here

Same for all combinations. Such as, component-1 and component-3, and component-1 and component-4, and component-2 and component-3, and component-2 and component-4, and component-3 and component-4.

But, this is not feasible to write the code and change manually dg[[1]], dg[[2]], and so on. Moreover, my actual dataset contains a lot of components. So, in reality, this is impossible. Any idea, how can I do this automatically?

Actually, I have a scoring function (like the shortest path). So, I want to check the score after adding all components, or after adding only 2 components, after adding only 3 components, and so on! Something like greedy algorithms.

Reproducible Data:

g <- structure(list(query = structure(c(1L, 1L, 1L, 2L, 2L, 3L, 4L, 
                                   5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), .Label = c("ID_00104", 
                                                                                                       "ID_00136", "ID_00169", "ID_00178", "ID_00180"), class = "factor"), 
               target = structure(c(16L, 19L, 20L, 1L, 9L, 9L, 6L, 11L, 
                                    13L, 15L, 4L, 8L, 10L, 14L, 2L, 3L, 5L, 7L, 12L, 17L, 18L
               ), .Label = c("ID_00169", "ID_00288", "ID_00324", "ID_00394", 
                             "ID_00663", "ID_00790", "ID_00846", "ID_00860", "ID_00910", "ID_00959", 
                             "ID_01013", "ID_01047", "ID_01130", "ID_01222", "ID_01260", "ID_06663", 
                             "ID_06781", "ID_06786", "ID_06791", "ID_09099"), class = "factor"), 
               new_ssp = c(0.654172560113154, 0.919096895578551, 0.925821596244131, 
                           0.860406091370558, 0.746376811594203, 0.767195767195767, 
                           0.830379746835443, 0.661577608142494, 0.707520891364902, 
                           0.908193484698914, 0.657118786857624, 0.687664041994751, 
                           0.68586387434555, 0.874513618677043, 0.836646499567848, 0.618361836183618, 
                           0.684163701067616, 0.914728682170543, 0.876297577854671, 
                           0.732707087959009, 0.773116438356164)), row.names = c(NA, 
                                                                                 -21L), class = "data.frame")

Thanks in advance.


Solution

  • You are actually close to what you want already. Perhaps the code below could help you

    out <- with(
      stack(membership(cl)),
      lapply(
        combn(split(ind, values), 2, simplify = FALSE),
        function(x) {
          add.edges(
            graph1,
            c(combn(sapply(x, sample, size = 1), 2)),
            weight = 0.01
          )
        }
      )
    )
    

    and then you can run

    sapply(out, plot)
    

    to visualize all the combinations.

    enter image description here enter image description here enter image description here enter image description here enter image description here enter image description here