1
\$\begingroup\$

I would like to create an igraph object. First, I set up the size of igraph object — n, m, then create a random matrix. As a result matrix B will be filled. Matrix B is the adjacency matrix for the igraph object. Inside for-loops I compute the distance d (scalar) and the weight matrix W. I would like to improve the perfomance of calculation. I think it is possible because I have used 4 for-loops in my code:

n <- 6 
m <- 7 

mat <- matrix(sample(0:255, n*m, replace=T), nrow = n, ncol = m)
R <- 2

a <- 1 
b <- 1 

d <- 0 
e <- 0 
g <- 0 

W <- matrix(0, n, m) 
B <- matrix(0, n*m, n*m)

for (i in 1:n){
for (j in 1:m){
  for (i0 in 1:n){
  for (j0 in 1:m){
            d <- ((i0 - i)^2+(j0 - j)^2)^(1/2) 
            e <- ifelse(d <= R, 1, 0)
            g <- abs(mat[i,j] - mat[i0,j0])
            W[i0,j0] <- e * ((a*g)^2 + (b*d)^2)^(1/2)
  } # for i0
  } # for j0
  B[m * (i-1)+j,] <- c(t(W)) 

} #for_j
} #for_i

Could anyone please give me an idea how to rewrite the above code with fewer or no for-loops?

\$\endgroup\$
3
\$\begingroup\$

Here is how you would do it with no for loops. The dist() function computes the distance between every pair of rows of a matrix. So you have to apply it to two matrices:

  1. the matrix C where each row contains the i and j coordinates of each vertex.
  2. the matrix matrix(M, ncol = 1) where each row contains the value at a vertex.

M <- t(mat)
C <- cbind(c(row(M)), c(col(M)))
D <- as.matrix(dist(C, method = "euclidean"))
E <- as.numeric(D <= R)
G <- as.matrix(dist(matrix(M, ncol = 1), method = "manhattan"))
B <- E * ((a * G) ^ 2 + (b * D) ^ 2) ^ (1 / 2)

Note that in R, matrices are stored using "Column Major", i.e. column by column. So it would be more natural to pick that the second row/col in B corresponds to the item at row 2 and col 1 in mat. You chose the opposite (row 1 col 2) which forced me to start my code with M <- t(mat). If you want to pick the more natural approach as I suggest, just replace that first line with M <- mat.

|improve this answer|||||
\$\endgroup\$
  • \$\begingroup\$ thanks you for review of code. I tried two option M<-mat and M<-t(mat), unfortunatly, I didn't see the difference. When I plot the igraph object I use: mylayout<-as.matrix(cbind(cx, -cy)), sing '-' before cy. \$\endgroup\$ – Nick Feb 6 '16 at 2:55
  • \$\begingroup\$ As the result I should obtain the symmetric matrix B. How can I do the calculation for upper right triangle (without the diagonal) only? \$\endgroup\$ – Nick Feb 7 '16 at 2:52
  • 1
    \$\begingroup\$ You can remove the two as.matrix() in my code, then the result will be of class dist. The code won't be noticeably faster. Maybe the only benefit is that B will occupy less memory space. \$\endgroup\$ – flodel Feb 8 '16 at 0:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.