Skip to content

Commit

Permalink
Merge pull request #289 from stocnet/develop
Browse files Browse the repository at this point in the history
v1.3.1
  • Loading branch information
jhollway committed Jan 25, 2024
2 parents ea4f16e + fd7ab47 commit 2146895
Show file tree
Hide file tree
Showing 22 changed files with 294 additions and 202 deletions.
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: migraph
Title: Many Network Measures, Motifs, Members, and Models
Version: 1.3.0
Date: 2024-01-24
Version: 1.3.1
Date: 2024-01-25
Description: A set of tools for analysing multimodal networks.
It includes functions for measuring
centrality, centralization, cohesion, closure, constraint and diversity,
Expand Down
22 changes: 22 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,25 @@
# migraph 1.3.1

2024-01-24

## Package

- Completed significant documentation updates

## Measures

- `over_*()` now reverts future plan on exit

## Motifs

- `node_brokerage_census()` and `network_brokerage_census()` now treat two-mode networks correctly (closed #35)

## Models

- `test_random()` now reverts future plan on exit
- `test_permutation()` now reverts future plan on exit
- `network_reg()` now reverts future plan on exit

# migraph 1.3.0

2024-01-24
Expand Down
6 changes: 4 additions & 2 deletions R/measure_diffusion.R
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# net_diffusion ####

#' Diffusion metrics for networks
#' Measures of network diffusion
#' @description
#' These functions allow measurement of various features of
#' a diffusion process:
Expand All @@ -17,6 +17,7 @@
#' to be protected through vaccination, isolation, or recovery for herd immunity to be reached.
#' - `network_hazard()` measures the hazard rate or instantaneous probability that
#' nodes will adopt/become infected at that time
#'
#' @param diff_model A valid network diffusion model,
#' as created by `as_diffusion()` or `play_diffusion()`.
#' @family measures
Expand Down Expand Up @@ -199,7 +200,7 @@ network_hazard <- function(diff_model){

# node_diffusion ####

#' Diffusion metrics for nodes
#' Measures of nodes in a diffusion
#' @description
#' These functions allow measurement of various features of
#' a diffusion process:
Expand All @@ -215,6 +216,7 @@ network_hazard <- function(diff_model){
#' a given mark
#' - `node_is_exposed()`: Marks the nodes that are susceptible,
#' i.e. are in the immediate neighbourhood of given mark vector
#'
#' @inheritParams cohesion
#' @inheritParams net_diffusion
#' @family measures
Expand Down
8 changes: 5 additions & 3 deletions R/measure_over.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@ NULL
over_waves <- function(.data, FUN, ..., attribute = "wave",
strategy = "sequential",
verbose = FALSE){
future::plan(strategy)
furrr::future_map_dbl(manynet::to_waves(.data, attribute), function(j) FUN(j, ...),
oplan <- future::plan(strategy)
on.exit(future::plan(oplan), add = TRUE)
furrr::future_map_dbl(manynet::to_waves(.data, attribute), function(j) FUN(j, ...),
.progress = verbose, .options = furrr::furrr_options(seed = T))
}

Expand All @@ -26,7 +27,8 @@ over_time <- function(.data, FUN, ..., attribute = "time",
slice = NULL,
strategy = "sequential",
verbose = FALSE){
future::plan(strategy)
oplan <- future::plan(strategy)
on.exit(future::plan(oplan), add = TRUE)
out <- furrr::future_map_dbl(manynet::to_slices(.data, attribute, slice),
function(j) FUN(j, ...),
.progress = verbose,
Expand Down
111 changes: 64 additions & 47 deletions R/member_community.R
Original file line number Diff line number Diff line change
@@ -1,17 +1,40 @@
#' Community partitioning algorithms
#'
#' @description
#' These functions offer different algorithms useful for partitioning
#' networks into sets of communities.
#' The different algorithms offer various advantages in terms of computation time,
#' availability on different types of networks, ability to maximise modularity,
#' and their logic or domain of inspiration.
#' These functions offer different algorithms useful for partitioning
#' networks into sets of communities:
#'
#' - `node_optimal()` is a problem-solving algorithm that seeks to maximise
#' modularity over all possible partitions.
#' - `node_kernaghinlin()` is a greedy, iterative, deterministic
#' partitioning algorithm that results in two equally-sized communities.
#' - `node_edge_betweenness()` is a hierarchical, decomposition algorithm
#' where edges are removed in decreasing order of the number of
#' shortest paths passing through the edge.
#' - `node_fast_greedy()` is a hierarchical, agglomerative algorithm,
#' that tries to optimize modularity in a greedy manner.
#' - `node_leading_eigen()` is a top-down, hierarchical algorithm.
#' - `node_walktrap()` is a hierarchical, agglomerative algorithm based on random walks.
#' - `node_infomap()` is a hierarchical algorithm based on the information in random walks.
#' - `node_spinglass()` is a greedy, iterative, probabilistic algorithm,
#' based on analogy to model from statistical physics.
#' - `node_fluid()` is a propogation-based partitioning algorithm,
#' based on analogy to model from fluid dynamics.
#' - `node_louvain()` is an agglomerative multilevel algorithm that seeks to maximise
#' modularity over all possible partitions.
#' - `node_leiden()` is an agglomerative multilevel algorithm that seeks to maximise
#' the Constant Potts Model over all possible partitions.
#'
#' The different algorithms offer various advantages in terms of computation time,
#' availability on different types of networks, ability to maximise modularity,
#' and their logic or domain of inspiration.
#'
#' @inheritParams cohesion
#' @name community
#' @family memberships
NULL

#' @describeIn community A problem-solving algorithm that seeks to maximise modularity over all possible partitions.
#' @rdname community
#' @section Optimal:
#' The general idea is to calculate the modularity of all possible partitions,
#' and choose the community structure that maximises this modularity measure.
Expand All @@ -30,8 +53,7 @@ node_optimal <- function(.data){
make_node_member(out, .data)
}

#' @describeIn community A greedy, iterative, deterministic
#' partitioning algorithm that results in two equally-sized communities.
#' @rdname community
#' @references
#' Kernighan, Brian W., and Shen Lin. 1970.
#' "An efficient heuristic procedure for partitioning graphs."
Expand Down Expand Up @@ -86,10 +108,7 @@ node_kernighanlin <- function(.data){
make_node_member(out, .data)
}

#' @describeIn community A hierarchical, decomposition algorithm
#' where edges are removed in decreasing order of the number of
#' shortest paths passing through the edge,
#' resulting in a hierarchical representation of group membership.
#' @rdname community
#' @section Edge-betweenness:
#' This is motivated by the idea that edges connecting different groups
#' are more likely to lie on multiple shortest paths when they are the
Expand All @@ -112,8 +131,7 @@ node_edge_betweenness <- function(.data){
make_node_member(out, .data)
}

#' @describeIn community A hierarchical, agglomerative algorithm,
#' that tries to optimize modularity in a greedy manner.
#' @rdname community
#' @section Fast-greedy:
#' Initially, each node is assigned a separate community.
#' Communities are then merged iteratively such that each merge
Expand All @@ -134,7 +152,7 @@ node_fast_greedy <- function(.data){
make_node_member(out, .data)
}

#' @describeIn community A top-down, hierarchical algorithm.
#' @rdname community
#' @section Leading eigenvector:
#' In each step, the network is bifurcated such that modularity increases most.
#' The splits are determined according to the leading eigenvector of the modularity matrix.
Expand All @@ -155,7 +173,7 @@ node_leading_eigen <- function(.data){
make_node_member(out, .data)
}

#' @describeIn community A hierarchical, agglomerative algorithm based on random walks.
#' @rdname community
#' @section Walktrap:
#' The general idea is that random walks on a network are more likely to stay
#' within the same community because few edges lead outside a community.
Expand All @@ -176,7 +194,7 @@ node_walktrap <- function(.data, times = 50){

}

#' @describeIn community A hierarchical algorithm based on the information in random walks.
#' @rdname community
#' @section Infomap:
#' Motivated by information theoretic principles, this algorithm tries to build
#' a grouping that provides the shortest description length for a random walk,
Expand All @@ -201,8 +219,7 @@ node_infomap <- function(.data, times = 50){
make_node_member(out, .data)
}

#' @describeIn community A greedy, iterative, probabilistic algorithm,
#' based on analogy to model from statistical physics.
#' @rdname community
#' @param max_k Integer constant, the number of spins to use as an upper limit
#' of communities to be found. Some sets can be empty at the end.
#' @param resolution The Reichardt-Bornholdt “gamma” resolution parameter for modularity.
Expand Down Expand Up @@ -237,7 +254,33 @@ node_spinglass <- function(.data, max_k = 200, resolution = 1){
make_node_member(out, .data)
}

#' @describeIn community An agglomerative multilevel algorithm that seeks to maximise modularity over all possible partitions.
#' @rdname community
#' @section Fluid:
#' The general idea is to observe how a discrete number of fluids interact, expand and contract,
#' in a non-homogenous environment, i.e. the network structure.
#' Unlike the `{igraph}` implementation that this function wraps,
#' this function iterates over all possible numbers of communities and returns the membership
#' associated with the highest modularity.
#' @references
#' Parés F, Gasulla DG, et. al. 2018.
#' "Fluid Communities: A Competitive, Scalable and Diverse Community Detection Algorithm".
#' In: _Complex Networks & Their Applications VI_
#' Springer, 689: 229.
#' \doi{10.1007/978-3-319-72150-7_19}
#' @examples
#' node_fluid(ison_adolescents)
#' @export
node_fluid <- function(.data){
.data <- as_igraph(.data)
mods <- vapply(seq.int(manynet::network_nodes(.data)),
function(x) igraph::cluster_fluid_communities(.data, no.of.communities = x)$modularity,
FUN.VALUE = numeric(1))
out <- igraph::cluster_fluid_communities(manynet::as_igraph(.data),
no.of.communities = which.max(mods))$membership
make_node_member(out, .data)
}

#' @rdname community
#' @section Louvain:
#' The general idea is to take a hierarchical approach to optimising the modularity criterion.
#' Nodes begin in their own communities and are re-assigned in a local, greedy way:
Expand All @@ -259,8 +302,7 @@ node_louvain <- function(.data, resolution = 1){
make_node_member(out, .data)
}

#' @describeIn community An agglomerative multilevel algorithm that seeks to maximise
#' the Constant Potts Model over all possible partitions.
#' @rdname community
#' @section Leiden:
#' The general idea is to optimise the Constant Potts Model,
#' which does not suffer from the resolution limit, instead of modularity.
Expand Down Expand Up @@ -294,28 +336,3 @@ node_leiden <- function(.data, resolution = 1){
make_node_member(out, .data)
}

#' @describeIn community A propogation-based partitioning algorithm
#' @section Fluid:
#' The general idea is to observe how a discrete number of fluids interact, expand and contract,
#' in a non-homogenous environment, i.e. the network structure.
#' Unlike the `{igraph}` implementation that this function wraps,
#' this function iterates over all possible numbers of communities and returns the membership
#' associated with the highest modularity.
#' @references
#' Parés F, Gasulla DG, et. al. 2018.
#' "Fluid Communities: A Competitive, Scalable and Diverse Community Detection Algorithm".
#' In: _Complex Networks & Their Applications VI_
#' Springer, 689: 229.
#' \doi{10.1007/978-3-319-72150-7_19}
#' @examples
#' node_fluid(ison_adolescents)
#' @export
node_fluid <- function(.data){
.data <- as_igraph(.data)
mods <- vapply(seq.int(manynet::network_nodes(.data)),
function(x) igraph::cluster_fluid_communities(.data, no.of.communities = x)$modularity,
FUN.VALUE = numeric(1))
out <- igraph::cluster_fluid_communities(manynet::as_igraph(.data),
no.of.communities = which.max(mods))$membership
make_node_member(out, .data)
}
19 changes: 12 additions & 7 deletions R/member_components.R
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@
#'
#' @description
#' These functions create a vector of nodes' memberships in
#' components or degrees of coreness.
#' components or degrees of coreness:
#'
#' - `node_components()` assigns nodes' component membership
#' using edge direction where available.
#' - `node_weak_components()` assigns nodes' component membership
#' ignoring edge direction.
#' - `node_strong_components()` assigns nodes' component membership
#' based on edge direction.
#' - `node_roulette()`
#'
#' In graph theory, components, sometimes called connected components,
#' are induced subgraphs from partitioning the nodes into disjoint sets.
Expand All @@ -25,8 +33,7 @@
#' @family memberships
NULL

#' @describeIn components Returns nodes' component membership
#' using edge direction where available.
#' @rdname components
#' @importFrom igraph components
#' @examples
#' node_components(mpn_bristol)
Expand All @@ -37,8 +44,7 @@ node_components <- function(.data){
.data)
}

#' @describeIn components Returns nodes' component membership
#' ignoring edge direction.
#' @rdname components
#' @importFrom igraph components
#' @export
node_weak_components <- function(.data){
Expand All @@ -47,8 +53,7 @@ node_weak_components <- function(.data){
.data)
}

#' @describeIn components Returns nodes' component membership
#' based on edge direction.
#' @rdname components
#' @importFrom igraph components
#' @export
node_strong_components <- function(.data){
Expand Down
31 changes: 20 additions & 11 deletions R/member_core.R
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
#' Core-periphery clustering algorithms
#' @description
#' @description
#' These functions identify nodes belonging to (some level of) the core of a network:
#'
#' - `node_core()` assigns nodes to either the core or periphery.
#' - `node_coreness()` assigns nodes to their level of k-coreness.
#'
#' @inheritParams cohesion
#' @param method Which method to use to identify cores and periphery.
#' By default this is "degree",
#' which relies on the heuristic that high degree nodes are more likely to be in the core.
#' An alternative is "eigenvector", which instead begins with high eigenvector nodes.
#' Other methods, such as a genetic algorithm, CONCOR, and Rombach-Porter,
#' can be added if there is interest.
#' @name core
#' @family memberships
NULL

#' @rdname core
#' @section Core-periphery:
#' This function is used to identify which nodes should belong to the core,
#' and which to the periphery.
#' It seeks to minimize the following quantity:
Expand All @@ -10,15 +28,6 @@
#' Note that minimising this quantity maximises density in the core block
#' and minimises density in the periphery block;
#' it ignores ties between these blocks.
#' @inheritParams cohesion
#' @param method Which method to use to identify cores and periphery.
#' By default this is "degree",
#' which relies on the heuristic that high degree nodes are more likely to be in the core.
#' An alternative is "eigenvector", which instead begins with high eigenvector nodes.
#' Other methods, such as a genetic algorithm, CONCOR, and Rombach-Porter,
#' can be added if there is interest.
#' @name core
#' @family memberships
#' @references
#' Borgatti, Stephen P., & Everett, Martin G. 1999.
#' Models of core /periphery structures.
Expand Down Expand Up @@ -59,7 +68,7 @@ node_core <- function(.data, method = c("degree", "eigenvector")){
make_node_member(out, .data)
}

#' @describeIn core Returns k-cores
#' @rdname core
#' @examples
#' node_coreness(ison_adolescents)
#' @export
Expand Down
Loading

0 comments on commit 2146895

Please sign in to comment.