-
-
Notifications
You must be signed in to change notification settings - Fork 203
/
Copy pathscg.R
146 lines (137 loc) · 5.65 KB
/
scg.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#' Stochastic matrix of a graph
#'
#' @description
#' `r lifecycle::badge("deprecated")`
#'
#' `get.stochastic()` was renamed to `stochastic_matrix()` to create a more
#' consistent API.
#' @inheritParams stochastic_matrix
#' @keywords internal
#' @export
get.stochastic <- function(graph, column.wise = FALSE, sparse = igraph_opt("sparsematrices")) { # nocov start
lifecycle::deprecate_soft("2.0.0", "get.stochastic()", "stochastic_matrix()")
stochastic_matrix(graph = graph, column.wise = column.wise, sparse = sparse)
} # nocov end
# IGraph R package
# Copyright (C) 2010-2012 Gabor Csardi <[email protected]>
# 334 Harvard street, Cambridge, MA 02139 USA
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
# 02110-1301 USA
#
###################################################################
#' Spectral Coarse Graining
#'
#' Functions to perform the Spectral Coarse Graining (SCG) of matrices and
#' graphs.
#'
#' @name scg-method
#' @family scg
#' @section Introduction: The SCG functions provide a framework, called
#' Spectral Coarse Graining (SCG), for reducing large graphs while preserving
#' their *spectral-related features*, that is features closely related
#' with the eigenvalues and eigenvectors of a graph matrix (which for now can
#' be the adjacency, the stochastic, or the Laplacian matrix).
#'
#' Common examples of such features comprise the first-passage-time of random
#' walkers on Markovian graphs, thermodynamic properties of lattice models in
#' statistical physics (e.g. Ising model), and the epidemic threshold of
#' epidemic network models (SIR and SIS models).
#'
#' SCG differs from traditional clustering schemes by producing a
#' *coarse-grained graph* (not just a partition of the vertices),
#' representative of the original one. As shown in \[1\], Principal Component
#' Analysis can be viewed as a particular SCG, called *exact SCG*, where
#' the matrix to be coarse-grained is the covariance matrix of some data set.
#'
#' SCG should be of interest to practitioners of various fields dealing with
#' problems where matrix eigenpairs play an important role, as for instance is
#' the case of dynamical processes on networks.
#' @author David Morton de Lachapelle.
#' @references D. Morton de Lachapelle, D. Gfeller, and P. De Los Rios,
#' Shrinking Matrices while Preserving their Eigenpairs with Application to the
#' Spectral Coarse Graining of Graphs. Submitted to *SIAM Journal on
#' Matrix Analysis and Applications*, 2008.
#' <https://www.epfl.ch/labs/lbs/wp-content/uploads/2018/07/scg_math_paper_dml_dg_pdl.pdf>
#'
#' D. Gfeller, and P. De Los Rios, Spectral Coarse Graining and Synchronization
#' in Oscillator Networks. *Physical Review Letters*, **100**(17),
#' 2008. <https://arxiv.org/abs/0708.2055>
#'
#' D. Gfeller, and P. De Los Rios, Spectral Coarse Graining of Complex
#' Networks, *Physical Review Letters*, **99**(3), 2007.
#' <https://arxiv.org/abs/0706.0812>
#' @keywords graphs
NULL
#' Stochastic matrix of a graph
#'
#' Retrieves the stochastic matrix of a graph of class `igraph`.
#'
#' Let \eqn{M} be an \eqn{n \times n}{n x n} adjacency matrix with real
#' non-negative entries. Let us define \eqn{D = \textrm{diag}(\sum_{i}M_{1i},
#' \dots, \sum_{i}M_{ni})}{D=diag( sum(M[1,i], i), ..., sum(M[n,i], i) )}
#'
#' The (row) stochastic matrix is defined as \deqn{W = D^{-1}M,}{W = inv(D) M,}
#' where it is assumed that \eqn{D} is non-singular. Column stochastic
#' matrices are defined in a symmetric way.
#'
#' @param graph The input graph. Must be of class `igraph`.
#' @param column.wise If `FALSE`, then the rows of the stochastic matrix
#' sum up to one; otherwise it is the columns.
#' @param sparse Logical scalar, whether to return a sparse matrix. The
#' `Matrix` package is needed for sparse matrices.
#' @return A regular matrix or a matrix of class `Matrix` if a
#' `sparse` argument was `TRUE`.
#' @author Gabor Csardi \email{csardi.gabor@@gmail.com}
#' @seealso [as_adj()]
#' @family scg
#' @export
#' @keywords graphs
#' @examples
#'
#' library(Matrix)
#' ## g is a large sparse graph
#' g <- sample_pa(n = 10^5, power = 2, directed = FALSE)
#' W <- stochastic_matrix(g, sparse = TRUE)
#'
#' ## a dense matrix here would probably not fit in the memory
#' class(W)
#'
#' ## may not be exactly 1, due to numerical errors
#' max(abs(rowSums(W)) - 1)
#'
stochastic_matrix <- function(graph, column.wise = FALSE,
sparse = igraph_opt("sparsematrices")) {
ensure_igraph(graph)
column.wise <- as.logical(column.wise)
if (length(column.wise) != 1) {
stop("`column.wise' must be a logical scalar")
}
sparse <- as.logical(sparse)
if (length(sparse) != 1) {
stop("`sparse' must be a logical scalar")
}
on.exit(.Call(R_igraph_finalizer))
if (sparse) {
res <- .Call(R_igraph_get_stochastic_sparse, graph, column.wise, NULL)
res <- igraph.i.spMatrix(res)
} else {
res <- .Call(R_igraph_get_stochastic, graph, column.wise, NULL)
}
if (igraph_opt("add.vertex.names") && is_named(graph)) {
rownames(res) <- colnames(res) <- V(graph)$name
}
res
}