如何在不在 igraph 中创建重复边的情况下生成基于随机属性的边?

How to generate a random attribute based edge without creating a duplicate edge in igraph?

我目前有这样的代码:

g <- erdos.renyi.game(30, 151 , type = "gnm" , directed = F , loops = F)%>%
  set_vertex_attr("a", value = 0) 

V(g)$a <- sample(c(0, 1), vcount(g), replace = TRUE, prob = c(.25, .75))

g <- add_edges(g,c(sample(V(g)[V(g)$a==0],1), sample(V(g)[V(g)$a == 1], 1)))

我正在尝试根据属性值生成随机的新边。然而,目前由于图中边的密度很高,很多时候生成的边是重复的。如何修改最后一行代码,使其不生成重复边?

一种方法是找出哪些节点对之间没有边,然后从这些节点对中随机抽样。下面的代码可以打包成一个函数,这样你就可以连续地随机添加新的边。

library(purrr) # For map function

# Create graph reproducibly
set.seed(54)
g <- erdos.renyi.game(30, 151 , type = "gnm" , directed = F , loops = F) %>%
  set_vertex_attr("a", value = 0) 

V(g)$a <- sample(c(0, 1), vcount(g), replace = TRUE, prob = c(.25, .75))

# List all possible pairs of nodes
all_pairs = apply(combn(1:vcount(g), 2), 2, paste, collapse="-")

# List all pairs of nodes with edges between them
current_pairs = apply(get.edgelist(g), 1, paste, collapse="-")

# List all pairs of nodes with no edge between them
eligible_pairs = setdiff(all_pairs, current_pairs)

# Get indices of eligible pairs with desired attribute a criteria
attr_select = map_lgl(strsplit(eligible_pairs, "-"), function(p) {
  (p[1] %in% V(g)[V(g)$a==0] & p[2] %in% V(g)[V(g)$a==1]) |
    (p[1] %in% V(g)[V(g)$a==1] & p[2] %in% V(g)[V(g)$a==0])
})

# Keep only those pairs that meet the attribute a condition above
eligible_pairs = eligible_pairs[attr_select]

# Add an edge at random between two nodes that don't currently have an edge between them 
# and that meet the attribute a criteria
set.seed(10)  # This is just for reproducibility of this example. Remove this if you want a different pair selected each time in your actual use case.
new_edge = unlist(strsplit(sample(eligible_pairs, 1), "-"))

g <- add_edges(g, new_edge)