【问题标题】:Build a matrix depending on two random walks in a graph根据图中的两个随机游走构建矩阵
【发布时间】:2018-07-24 02:58:03
【问题描述】:

我正在做一个项目,我达到了这一点,但实际上我从一周前开始就一直坚持下去,我尝试了很多想法,但所有为我的算法编写代码的尝试都失败了。

假设我们有以下简单的图表:

边的顺序是:1--31--43--2

对于每条边,在每个顶点上定义一个随机游走以移动到它的一个邻居,例如:

对于第一条边,v1=1 ,v2=3, n1=3,4n2=1,2 按顺序排列,因此从 v1 和 v2 开始的可能移动是:

1 to 3,3 to 1
1 to 4,3 to 1
1 to 3,3 to 2
1 to 4,3 to 2

对于第二条边,依次为v1=1 ,v2=4, n1=3,4n2=1,因此从v1 和v2 可能的移动是:

1 to 3,4 to 1
1 to 4,3 to 1

对于第三条边,依次为v1=3 ,v2=2, n1=1,2n2=3,所以从v1和v2可能的移动是:

3 to 1,2 to 3
3 to 2,2 to 3

对于整个图表,只有 8 个可能的移动,所以我有 8 个变量来构造约束矩阵

让我们用 x 来表示移动(根据它们出现的顺序);即

(1 to 3,3 to 1) to be represented by x_1
(1 to 4,3 to 1) to be represented by x_2
                 :
(3 to 1,2 to 3) to be represented by x_7
(3 to 2,2 to 3) to be represented by x_8

我想根据这些移动构建所需的约束矩阵,约束的数量将等于\sum{i} ( number of neighbors for v1(i) * number of neighbors for v2(i) ),在我们的图中为 10。

我构建这个矩阵的算法是:

Step1: 1) select 1st edge, fix v1, v2, n2
       2) change n1 and fill the 1st row of the matrix by 1's in the place of the resulted moves and 0 if there is no similar move on the graph until you finish all elements in n1. 
Step2: move to the 2nd row of the matrix and select the 2nd element of n2 and
       1) loop over n1 
       2) fill the 2nd row by 1's in the place of the resulted moves until you finish all elements in n1. 
Step3: since you selected all elements in n1 and n2 for the vertices in the first edge move to a new row in the matrix 
Step4: Select next edges and do the same work done before until you finish all edges. 
Step5: select the 1st edge again and do the same work but while fixing v1,v2 &n1, loop over n2

根据该算法得到的矩阵将是:

1 1 0 0 0 0 0 0
0 0 1 1 0 0 0 0
0 0 0 0 1 1 0 0
0 0 0 0 0 0 1 1
1 0 1 0 0 0 0 0
0 1 0 1 0 0 0 0
0 0 0 0 1 0 0 0
0 0 0 0 0 1 0 0
0 0 0 0 0 0 1 0
0 0 0 0 0 0 0 1

我没有做的是:如何让矩阵知道有移动并在它的位置用1替换它,如果没有移动它用0替换它位置

我的代码是:

library(igraph)
graph<-matrix(c(1,3,1,4,3,2),ncol=2,byrow=TRUE)
g<-graph.data.frame(d = graph, directed = FALSE)

countercol<-0
for (edge in 1:length(E(g))){
v1<-ends(graph = g, es = edge)[1]
v2<-ends(graph = g, es = edge)[2]

n1<-neighbors(g,v1,mode=c("all"))
n2<-neighbors(g,v2,mode=c("all"))

countercol=countercol+(length(n1)*length(n2))
}

counterrow<-0
for (edge in 1:length(E(g))){
v1<-ends(graph = g, es = edge)[1]
v2<-ends(graph = g, es = edge)[2]

n1<-neighbors(g,v1,mode=c("all"))
n2<-neighbors(g,v2,mode=c("all"))

counterrow=counterrow+(length(n1)+length(n2))
}    

for (edge in 1:length(E(df))){
v1<-ends(graph = df, es = edge)[1]
v2<-ends(graph = df, es = edge)[2]
n1<-neighbors(df,v1,mode=c("all"))
n2<-neighbors(df,v2,mode=c("all"))
  ...
  ...
  ...
  }

我不是在找人来编写代码,我想要的是让程序区分可能的移动并将 1 和 0 存储在结果移动的合适位置。

非常感谢您的任何帮助

【问题讨论】:

  • 我很困惑你所说的 v1=1 ,v2=3, n1=3,4n2=1,2 是什么意思。 v 表示顶点,是吗? n 代表什么?
  • 您如何在这些示例中定义n2?我不明白你对问题的描述。
  • @InfiniteFlashChess 邻居
  • @InfiniteFlashChess v1, v2 是第一个和第二个顶点,因此 n1, n2 是 v1 和 v2 的邻居(相邻和连接的顶点)
  • @MrFlick n2 是 v2 的邻居(连接和相邻的顶点),v2 是任何边中的第二个顶点。函数neighbors(g,edge)在指定顶点时确定这些邻居

标签: r algorithm matrix optimization igraph


【解决方案1】:

这是一个由两部分组成的解决方案

edgeMoves <- function(e) {
  umoves <- sapply(ends(graph = g, es = e), neighbors, graph = g, mode = "all", simplify = FALSE)
  do.call(paste, c(expand.grid(mapply(function(x, y) 
    paste(x, names(y), sep =" to "), ends(graph = g, es = e), umoves, SIMPLIFY = FALSE)), sep = ", "))
}
edgeConstraints <- function(e) {
  v <- ends(graph = g, es = e)
  n1 <- names(neighbors(g, v[1], mode = "all"))
  n2 <- names(neighbors(g, v[2], mode = "all"))
  t(cbind(sapply(n2, function(nn2) moves %in% paste0(v[1], " to ", n1, ", ", v[2], " to ", nn2)),
          sapply(n1, function(nn1) moves %in% paste0(v[1], " to ", nn1, ", ", v[2], " to ", n2))))
}
moves <- do.call(c, sapply(E(g), edgeMoves))
moves
# [1] "1 to 3, 3 to 1" "1 to 4, 3 to 1" "1 to 3, 3 to 2"
# [4] "1 to 4, 3 to 2" "1 to 3, 4 to 1" "1 to 4, 4 to 1"
# [7] "3 to 1, 2 to 3" "3 to 2, 2 to 3"

do.call(rbind, sapply(E(g), edgeConstraints)) * 1
#   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
# 1    1    1    0    0    0    0    0    0
# 2    0    0    1    1    0    0    0    0
# 3    1    0    1    0    0    0    0    0
# 4    0    1    0    1    0    0    0    0
# 1    0    0    0    0    1    1    0    0
# 3    0    0    0    0    1    0    0    0
# 4    0    0    0    0    0    1    0    0
# 3    0    0    0    0    0    0    1    1
# 1    0    0    0    0    0    0    1    0
# 2    0    0    0    0    0    0    0    1

行顺序不同,但我怀疑这不是问题。此外,对于单个边缘,您可以使用 edgeMoves(e)edgeConstraints(e) * 1

【讨论】:

  • @user8003788,如果我应该添加任何解释,请告诉我
  • 感谢这个好代码,事实上我写了一些东西,但它更复杂!我会理解你的代码,如果有什么奇怪的地方我会问..再次感谢
  • 再次感谢您的大力帮助,它运行良好,但我正在关注它并试图了解如何让它单独在每个边缘上工作(即从只有一条边不是所有边都在一起)?
  • 第二个问题是我怎么知道结果矩阵中的第一个 1 与第一步有关(1 到 3,3 到 1)?即我不明白你是如何索引这些动作的?例如,如果我想知道第一行和第一列中的一个代表的移动是什么,我叫什么?并提前感谢
  • @user8003788,请参阅有关第一个请求的更新。我没有创建任何索引。它们由向量moves 中的移动顺序隐式给出(参见moves %in% 部分)。例如,如果您在第 2 列和第 4 列中看到一个,您可能会通过moves[c(2, 4)] 获得相应的移动。
猜你喜欢
  • 2021-02-09
  • 2011-07-29
  • 2021-06-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-03
  • 1970-01-01
相关资源
最近更新 更多