我使用R(和igraph包)创建了一个随机(Erdos-Renyi)网络,该网络有10个节点。每个节点都被随机分配了0或1的属性。
我在这些节点上应用了简单多数规则,这样如果节点的大多数邻居具有0的属性,那么节点的属性也会变为0(如果大多数具有1,则为1)。它根据数字(1-10)迭代地遍历网络中的所有节点,并应用简单多数规则。
以下是我创建图表的代码:
# Creates an Erdos-Renyi graph with 10 nodes and edges with p=0.2
num_nodes <- 10
prob <- 0.2
graph <- erdos.renyi.game(num_nodes, prob, type=c("gnp", "gnm"), directed=FALSE,
loops=FALSE)
# Randomly sets the attributes of the nodes to either 0 or 1
graph <- set.vertex.attribute(graph, "value", value = sample(0:1, num_nodes,
replace=TRUE))
这是我的代码应用到目前为止的简单多数规则:
modified <- FALSE
iterations <- 0 #keeps track of how many iterations take place
for (i in 1:num_nodes*10) {
modified = FALSE
iterations <- iterations + 1
for (i in 1:num_nodes) {
adj_ones <- 0 #keeps track of how many neighbors of a node have 1s
adj_zeros <- 0 #keeps track of how many neighbors of a node have 0s
for (j in neighbors(graph, i)) { #looks at the neighbors of a node
if (get.vertex.attribute(graph, "value", index = j) == 1) {
adj_ones <- adj_ones + 1 #increments one count if neighbor is 1
} else {
adj_zeros <- adj_zeros + 1 # or increments zero count if
#neighbor is 0
}
}
modified = FALSE
#I need to modify this bit so that the 0 or 1 changes are only stored
#rather than actually changed
if (adj_ones > adj_zeros) { #updates 0 or 1 value of node
if (V(graph)$value[which(V(graph)==i)] == 0) {
modified = TRUE
V(graph)$value[which(V(graph)==i)] = 1
}
} else if (adj_ones < adj_zeros) {
if (V(graph)$value[which(V(graph)==i)] == 1) {
modified = TRUE
V(graph)$value[which(V(graph)==i)] = 0
}
}
if (!modified) {
break
}
}
一切正常,但我需要对其进行修改,以便在查看节点后,如果需要更改此节点的0或1值,而不是更改它,则会存储新值。因此,当检查此节点的邻居时,它们使用节点的原始值而不是其更改(存储)的值。在每次迭代所有节点之后,需要根据需要更新每个节点的存储值。 (即所有节点值的第二次迭代使用第一次迭代的节点值,第三次迭代使用第二次迭代的值)。
我不太确定如何做到这一点。我是否需要将更新的值存储在数据框中并使用此方法为每次迭代访问它们?我该怎么做呢?或者有不同的方法吗?
答案 0 :(得分:2)
您可以为每个节点创建第二个变量(让我们称之为“翻转”),如果节点因为大多数邻居不同而需要翻转,则设置该变量。在每次迭代的第一次传递中,标记需要翻转的所有节点。在第二遍中,您实际更新了所有值。
以下是我认为应该做的一些代码(主要基于您发布的代码):
library(igraph)
# Creates an Erdos-Renyi graph with 10 nodes and edges with p=0.2
num_nodes <- 10
prob <- 0.2
graph <- erdos.renyi.game(num_nodes, prob, type=c("gnp", "gnm"), directed=FALSE,
loops=FALSE)
# Randomly sets the attributes of the nodes to either 0 or 1
graph <- set.vertex.attribute(graph, "value", value = sample(0:1, num_nodes,
replace=TRUE))
modified <- FALSE
iterations <- 0 #keeps track of how many iterations take place
for (i in 1:num_nodes*10) {
# Initially set flip to all false
graph <- set.vertex.attribute(graph, "flip", value=rep(FALSE, num_nodes))
modified = FALSE
iterations <- iterations + 1
for (i in 1:num_nodes) {
adj_ones <- 0 #keeps track of how many neighbors of a node have 1s
adj_zeros <- 0 #keeps track of how many neighbors of a node have 0s
for (j in neighbors(graph, i)) { #looks at the neighbors of a node
if (get.vertex.attribute(graph, "value", index = j) == 1) {
adj_ones <- adj_ones + 1 #increments one count if neighbor is 1
} else {
adj_zeros <- adj_zeros + 1 # or increments zero count if
#neighbor is 0
}
}
modified = FALSE
#I need to modify this bit so that the 0 or 1 changes are only stored
#rather than actually changed
i.pos = which(V(graph) == i)
if (adj_ones > adj_zeros) { #updates 0 or 1 value of node
if (V(graph)$value[i.pos] == 0) {
modified = TRUE
V(graph)$flip[i.pos] = TRUE
}
} else if (adj_ones < adj_zeros) {
if (V(graph)$value[which(V(graph)==i)] == 1) {
modified = TRUE
V(graph)$flip[i.pos] = TRUE
}
}
}
if (!modified) {
break
}
# Actually flip the things we labeled as needing to flip
for (i in 1:num_nodes) {
if (V(graph)$flip[i]) {
V(graph)$value[i] = 1-V(graph)$value[i]
}
}
}