Commit | Line | Data |
---|---|---|
762721a5 BA |
1 | #' Compute the Euclidian Commute-Time Distances (ECTD) in an undirected graph. |
2 | #' | |
3 | #' Assuming similarity function doesn't depend on x, and undirected graph. | |
4 | #' | |
5 | #' @param o Output of \code{nng}. | |
6 | #' @param similarity function distance --> similarity. | |
7 | #' @param inf.replace Replace Inf values by large finite number ? | |
8 | #' | |
9 | #' @return A distances matrix (n x n) | |
10 | #' | |
11 | #' @export | |
12 | ectd <- function(o, similarity=function(x) 1, inf.replace=TRUE) | |
13 | { | |
0f87bb5b | 14 | if (igraph::is_directed(o$graph)) |
762721a5 BA |
15 | stop("Directed graph case unimplemented yet") |
16 | n <- igraph::vcount(o$graph) | |
17 | E <- igraph::as_edgelist(o$graph, names=FALSE) | |
18 | W <- matrix(0, nrow=n, ncol=n) | |
19 | for (i in seq_len(nrow(E))) { | |
20 | edge <- c(E[i,1], E[i,2]) | |
21 | W[edge[1], edge[2]] <- similarity(o$distances[i]) | |
22 | W[edge[2], edge[1]] <- W[edge[1], edge[2]] | |
23 | } | |
24 | L <- diag(rowSums(W)) - W | |
25 | cc <- igraph::components(o$graph) | |
26 | distances <- matrix(Inf, nrow=n, ncol=n) | |
27 | for (i in seq_len(cc$no)) { | |
28 | indices <- which(cc$membership == i) | |
29 | L_loc <- L[indices, indices] | |
30 | n_loc <- cc$csize[i] | |
31 | if (n_loc >= 2) L_inv = pracma::pinv(L_loc) | |
32 | else L_inv = matrix(ifelse(L_loc != 0, 1/L_loc[1], 0)) | |
33 | Lii = matrix(rep(diag(L_inv), each=n_loc), nrow=n_loc, byrow=TRUE) | |
34 | Ljj = matrix(rep(diag(L_inv), each=n_loc), nrow=n_loc) | |
35 | # https://math.stackexchange.com/questions/1321305/commute-time-distance-in-a-graph | |
36 | distances[indices, indices] <- Lii + Ljj - 2 * L_inv | |
37 | } | |
38 | if (inf.replace) { | |
39 | finiteMax <- max(distances[is.finite(distances)]) | |
40 | distances[is.infinite(distances)] <- finiteMax + 1 | |
41 | } | |
42 | distances | |
43 | } |