Skip to content

Commit 4efb0a2

Browse files
author
dirmeier
committed
Adds hub correction
1 parent c50fa90 commit 4efb0a2

File tree

15 files changed

+445
-206
lines changed

15 files changed

+445
-206
lines changed

DESCRIPTION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Package: diffusr
22
Type: Package
33
Title: Network Diffusion Algorithms
4-
Version: 0.1.2
4+
Version: 0.1.3
55
Date: 2017-10-29
66
Authors@R: person("Simon", "Dirmeier",
77
email = "simon.dirmeier@gmx.de",

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Generated by roxygen2: do not edit by hand
22

3+
S3method(hub.correction,numeric)
34
S3method(normalize.laplacian,numeric)
45
S3method(normalize.stochastic,numeric)
56
export(heat.diffusion)
7+
export(hub.correction)
68
export(nearest.neighbors)
79
export(normalize.laplacian)
810
export(normalize.stochastic)

R/RcppExports.R

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,14 @@ laplacian_ <- function(W) {
1313
.Call('_diffusr_laplacian_', PACKAGE = 'diffusr', W)
1414
}
1515

16+
node_degrees_ <- function(W) {
17+
.Call('_diffusr_node_degrees_', PACKAGE = 'diffusr', W)
18+
}
19+
20+
hub_normalize_ <- function(W) {
21+
.Call('_diffusr_hub_normalize_', PACKAGE = 'diffusr', W)
22+
}
23+
1624
mrwr_ <- function(p0, W, r, thresh, niter, do_analytical) {
1725
.Call('_diffusr_mrwr_', PACKAGE = 'diffusr', p0, W, r, thresh, niter, do_analytical)
1826
}

R/mat_util.R

Lines changed: 43 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,14 @@
2626
#' @param ... additional params
2727
#' @return returns the normalized matrix/vector
2828
#' @examples
29-
#' W <- matrix(abs(rnorm(10000)), 100, 100)
30-
#' stoch.W <- normalize.stochastic(W)
29+
#' W <- matrix(abs(rnorm(10000)), 100, 100)
30+
#' stoch.W <- normalize.stochastic(W)
3131
normalize.stochastic <- function(obj, ...)
3232
{
3333
UseMethod("normalize.stochastic")
3434
}
3535

36+
3637
#' @export
3738
#' @method normalize.stochastic numeric
3839
normalize.stochastic.numeric <- function(obj, ...)
@@ -58,6 +59,7 @@ normalize.stochastic.numeric <- function(obj, ...)
5859
return(obj)
5960
}
6061

62+
6163
#' Calculate the Laplacian of a matrix
6264
#'
6365
#' @export
@@ -66,13 +68,14 @@ normalize.stochastic.numeric <- function(obj, ...)
6668
#' @param ... additional params
6769
#' @return returns the Laplacian
6870
#' @examples
69-
#' W <- matrix(abs(rnorm(10000)), 100, 100)
70-
#' lapl.W <- normalize.laplacian(W)
71+
#' W <- matrix(abs(rnorm(10000)), 100, 100)
72+
#' lapl.W <- normalize.laplacian(W)
7173
normalize.laplacian <- function(obj, ...)
7274
{
7375
UseMethod("normalize.laplacian")
7476
}
7577

78+
7679
#' @export
7780
#' @method normalize.laplacian numeric
7881
normalize.laplacian.numeric <- function(obj, ...)
@@ -82,16 +85,48 @@ normalize.laplacian.numeric <- function(obj, ...)
8285
if (any(obj < 0.0))
8386
stop('please provide a matrix with only non-negative alues!')
8487
lapl <- laplacian_(obj)
85-
return(lapl)
88+
89+
lapl
90+
}
91+
92+
93+
94+
#' Correct for hubs in an adjacency matrix
95+
#'
96+
#' @export
97+
#'
98+
#' @param obj matrix for which hubs are corrected
99+
#' @return returns the matrix with hub correction
100+
#' @examples
101+
#' W <- matrix(abs(rnorm(10000)), 100, 100)
102+
#' cor.hub <- hub.correction(W)
103+
hub.correction <- function(obj)
104+
{
105+
UseMethod("hub.correction")
106+
}
107+
108+
109+
#' @export
110+
#' @method hub.correction numeric
111+
hub.correction.numeric <- function(obj)
112+
{
113+
if (!is.matrix(obj)) stop('please provide a matrix object!')
114+
if (nrow(obj) != ncol(obj)) stop('please provide a square matrix!')
115+
if (any(obj < 0.0))
116+
stop('please provide a matrix with only non-negative alues!')
117+
message("Correcting for hub degrees.")
118+
hub.mat <- hub_normalize_(obj)
119+
120+
hub.mat
86121
}
87122

123+
88124
#' @noRd
89125
#' @importFrom igraph graph_from_adjacency_matrix components
90126
.is.ergodic <- function(obj)
91127
{
92-
adj <- igraph::graph_from_adjacency_matrix(obj,
93-
mode="directed",
94-
weighted=TRUE)
128+
adj <- igraph::graph_from_adjacency_matrix(
129+
obj, mode="directed", weighted=TRUE)
95130
comps <- igraph::components(adj)
96131
ifelse(length(comps$csize) == 1, TRUE, FALSE)
97132
}

R/mrw.R

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,14 @@
4646
#' stop criterion.
4747
#' @param do.analytical boolean if the stationary distribution shall be
4848
#' computed solving the analytical solution or rather iteratively
49-
#' @param ... additional parameters
50-
#' @return returns the stationary distribution as numeric vector
49+
#' @param correct.for.hubs if \code{TRUE} multiplies a correction factor to the
50+
#' nodes, such that the random walk gets not biased to nodes with high
51+
#' degree.
52+
#' @return returns a list with the following elements
53+
#' \itemize{
54+
#' \item p.inf the stationary distribution as numeric vector
55+
#' \item transition.matrix the column normalized transition matrix used for the random walk
56+
#' }
5157
#'
5258
#' @references
5359
#' Tong, H., Faloutsos, C., & Pan, J. Y. (2006),
@@ -57,32 +63,38 @@
5763
#' \emph{The American Journal of Human Genetics}\cr \cr
5864
#'
5965
#' @examples
60-
#' # count of nodes
61-
#' n <- 5
62-
#' # starting distribution (has to sum to one)
63-
#' p0 <- as.vector(rmultinom(1, 1, prob=rep(.2, n)))
64-
#' # adjacency matrix (either normalized or not)
65-
#' graph <- matrix(abs(rnorm(n*n)), n, n)
66-
#' # computation of stationary distribution
67-
#' pt <- random.walk(p0, graph)
66+
#' # count of nodes
67+
#' n <- 5
68+
#' # starting distribution (has to sum to one)
69+
#' p0 <- as.vector(rmultinom(1, 1, prob=rep(.2, n)))
70+
#' # adjacency matrix (either normalized or not)
71+
#' graph <- matrix(abs(rnorm(n*n)), n, n)
72+
#' # computation of stationary distribution
73+
#' pt <- random.walk(p0, graph)
74+
#'
6875
setGeneric(
6976
"random.walk",
70-
function(p0, graph, r=.5, niter=1e4, thresh=1e-4, do.analytical=FALSE, ...)
77+
function(p0, graph, r=.5,
78+
niter=1e4, thresh=1e-4, do.analytical=FALSE,
79+
correct.for.hubs=FALSE)
7180
{
7281
standardGeneric("random.walk")
7382
},
7483
package="diffusr"
7584
)
7685

86+
7787
#' @rdname random-walk-methods
7888
#' @aliases random.walk,numeric,matrix-method
7989
setMethod(
8090
"random.walk",
8191
signature = signature(p0="numeric", graph="matrix"),
82-
function(p0, graph, r=.5, niter=1e4, thresh=1e-4, do.analytical=FALSE, ...)
92+
function(p0, graph, r=.5,
93+
niter=1e4, thresh=1e-4, do.analytical=FALSE,
94+
correct.for.hubs=FALSE)
8395
{
8496
p0 <- as.matrix(p0, ncol=1)
85-
random.walk(p0, graph, r, niter, thresh, do.analytical, ...)
97+
random.walk(p0, graph, r, niter, thresh, do.analytical, correct.for.hubs)
8698
}
8799
)
88100

@@ -91,9 +103,12 @@ setMethod(
91103
setMethod(
92104
"random.walk",
93105
signature = signature(p0="matrix", graph="matrix"),
94-
function(p0, graph, r=.5, niter=1e4, thresh=1e-4, do.analytical=FALSE, ...)
106+
function(p0, graph, r=.5,
107+
niter=1e4, thresh=1e-4, do.analytical=FALSE,
108+
correct.for.hubs=FALSE)
95109
{
96110
stopifnot(length(r) == 1)
111+
stopifnot(is.logical(correct.for.hubs))
97112
.check.restart(r)
98113
.check.starting.matrix(p0)
99114
.check.graph(graph, p0)
@@ -103,14 +118,17 @@ setMethod(
103118
message("setting diag of graph to zero")
104119
diag(graph) <- 0
105120
}
106-
121+
if (correct.for.hubs) graph <- hub.correction(graph)
107122
stoch.graph <- normalize.stochastic(graph)
108123
if(!.is.ergodic(stoch.graph))
109124
stop(paste("the provided graph has more than one component.",
110125
"It is likely not ergodic."))
111126

112-
invisible(
113-
mrwr_(normalize.stochastic(p0),
114-
stoch.graph, r, thresh, niter, do.analytical))
127+
l <- list(
128+
p.inf=mrwr_(normalize.stochastic(p0),
129+
stoch.graph, r, thresh, niter, do.analytical),
130+
transition.matrix=stoch.graph)
131+
132+
l
115133
}
116134
)

diffusr.Rproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
Version: 1.0
2+
3+
RestoreWorkspace: Default
4+
SaveWorkspace: Default
5+
AlwaysSaveHistory: Default
6+
7+
EnableCodeIndexing: Yes
8+
UseSpacesForTab: Yes
9+
NumSpacesForTab: 2
10+
Encoding: UTF-8
11+
12+
RnwWeave: knitr
13+
LaTeX: pdfLaTeX
14+
15+
AutoAppendNewline: Yes
16+
StripTrailingWhitespace: Yes
17+
18+
BuildType: Package
19+
PackageUseDevtools: Yes
20+
PackageInstallArgs: --no-multiarch --with-keep.source

inst/include/diffusr_RcppExports.h

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ namespace diffusr {
4040
if (rcpp_result_gen.inherits("interrupted-error"))
4141
throw Rcpp::internal::InterruptedException();
4242
if (rcpp_result_gen.inherits("try-error"))
43-
throw Rcpp::exception(as<std::string>(rcpp_result_gen).c_str());
43+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
4444
return Rcpp::as<Eigen::MatrixXd >(rcpp_result_gen);
4545
}
4646

@@ -59,7 +59,7 @@ namespace diffusr {
5959
if (rcpp_result_gen.inherits("interrupted-error"))
6060
throw Rcpp::internal::InterruptedException();
6161
if (rcpp_result_gen.inherits("try-error"))
62-
throw Rcpp::exception(as<std::string>(rcpp_result_gen).c_str());
62+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
6363
return Rcpp::as<Eigen::MatrixXd >(rcpp_result_gen);
6464
}
6565

@@ -78,7 +78,45 @@ namespace diffusr {
7878
if (rcpp_result_gen.inherits("interrupted-error"))
7979
throw Rcpp::internal::InterruptedException();
8080
if (rcpp_result_gen.inherits("try-error"))
81-
throw Rcpp::exception(as<std::string>(rcpp_result_gen).c_str());
81+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
82+
return Rcpp::as<Eigen::MatrixXd >(rcpp_result_gen);
83+
}
84+
85+
inline std::vector<double> node_degrees_(const Eigen::MatrixXd& W) {
86+
typedef SEXP(*Ptr_node_degrees_)(SEXP);
87+
static Ptr_node_degrees_ p_node_degrees_ = NULL;
88+
if (p_node_degrees_ == NULL) {
89+
validateSignature("std::vector<double>(*node_degrees_)(const Eigen::MatrixXd&)");
90+
p_node_degrees_ = (Ptr_node_degrees_)R_GetCCallable("diffusr", "_diffusr_node_degrees_");
91+
}
92+
RObject rcpp_result_gen;
93+
{
94+
RNGScope RCPP_rngScope_gen;
95+
rcpp_result_gen = p_node_degrees_(Shield<SEXP>(Rcpp::wrap(W)));
96+
}
97+
if (rcpp_result_gen.inherits("interrupted-error"))
98+
throw Rcpp::internal::InterruptedException();
99+
if (rcpp_result_gen.inherits("try-error"))
100+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
101+
return Rcpp::as<std::vector<double> >(rcpp_result_gen);
102+
}
103+
104+
inline Eigen::MatrixXd hub_normalize_(const Eigen::MatrixXd& W) {
105+
typedef SEXP(*Ptr_hub_normalize_)(SEXP);
106+
static Ptr_hub_normalize_ p_hub_normalize_ = NULL;
107+
if (p_hub_normalize_ == NULL) {
108+
validateSignature("Eigen::MatrixXd(*hub_normalize_)(const Eigen::MatrixXd&)");
109+
p_hub_normalize_ = (Ptr_hub_normalize_)R_GetCCallable("diffusr", "_diffusr_hub_normalize_");
110+
}
111+
RObject rcpp_result_gen;
112+
{
113+
RNGScope RCPP_rngScope_gen;
114+
rcpp_result_gen = p_hub_normalize_(Shield<SEXP>(Rcpp::wrap(W)));
115+
}
116+
if (rcpp_result_gen.inherits("interrupted-error"))
117+
throw Rcpp::internal::InterruptedException();
118+
if (rcpp_result_gen.inherits("try-error"))
119+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
82120
return Rcpp::as<Eigen::MatrixXd >(rcpp_result_gen);
83121
}
84122

@@ -97,7 +135,7 @@ namespace diffusr {
97135
if (rcpp_result_gen.inherits("interrupted-error"))
98136
throw Rcpp::internal::InterruptedException();
99137
if (rcpp_result_gen.inherits("try-error"))
100-
throw Rcpp::exception(as<std::string>(rcpp_result_gen).c_str());
138+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
101139
return Rcpp::as<Eigen::MatrixXd >(rcpp_result_gen);
102140
}
103141

@@ -116,7 +154,7 @@ namespace diffusr {
116154
if (rcpp_result_gen.inherits("interrupted-error"))
117155
throw Rcpp::internal::InterruptedException();
118156
if (rcpp_result_gen.inherits("try-error"))
119-
throw Rcpp::exception(as<std::string>(rcpp_result_gen).c_str());
157+
throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());
120158
return Rcpp::as<Rcpp::List >(rcpp_result_gen);
121159
}
122160

man/hub.correction.Rd

Lines changed: 21 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/normalize.laplacian.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

man/normalize.stochastic.Rd

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)