Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added NetSwan functions #25

Merged
merged 2 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: netrankr
Type: Package
Title: Analyzing Partial Rankings in Networks
Version: 1.2.3.9000
Version: 1.2.4
Authors@R: c(
person("David", "Schoch", email = "david@schochastics.net", role = c("aut", "cre"),
comment = c(ORCID = "0000-0003-2952-4812")),
Expand All @@ -25,7 +25,7 @@ Imports: igraph (>= 1.0.1),
Rcpp (>= 0.12.8),
Matrix
LinkingTo: Rcpp,RcppArmadillo
RoxygenNote: 7.2.3
RoxygenNote: 7.3.2
Roxygen: list(markdown = TRUE)
Suggests:
knitr,
Expand Down
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export(neighborhood_inclusion)
export(positional_dominance)
export(rank_intervals)
export(spectral_gap)
export(swan_closeness)
export(swan_combinatory)
export(swan_connectivity)
export(swan_efficiency)
export(threshold_graph)
export(transitive_reduction)
export(walks_attenuated)
Expand Down
4 changes: 4 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# netrankr 1.2.4

* added functions from archived NetSwan package

# netrankr 1.2.3

* removed test causing issues on some platforms
Expand Down
293 changes: 293 additions & 0 deletions R/netswan.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,293 @@
#' @name swan_closeness
#' @title Impact on closeness when a node is removed
#'
#' @description
#' `swan_closeness` measures the change in the sum of the inverse of distances between all node pairs
#' when excluding that node.#'
#' @param g An `igraph` object representing the graph to analyze.
#'
#' @details
#' `swan_closeness` measures the impact of a node's removal by computing the change in
#' the sum of inverse distances between all node pairs.
#'
#' The code is an adaptation from the NetSwan package that was archived on CRAN.
#' @return
#' A numeric vector containing the `swan_closeness` values for all vertices.
#'
#' @references
#' Lhomme S. (2015). *Analyse spatiale de la structure des réseaux techniques dans un contexte de risques*.
#' Cybergeo: European Journal of Geography.
#' @examples
#' library(igraph)
#' # Example graph (electrical network structure)
#' elec <- matrix(ncol = 2, byrow = TRUE, c(
#' 11,1, 11,10, 1,2, 2,3, 2,9,
#' 3,4, 3,8, 4,5, 5,6, 5,7,
#' 6,7, 7,8, 8,9, 9,10
#' ))
#' gra <- graph_from_edgelist(elec, directed = FALSE)
#'
#' # Compute swan_closeness
#' f2 <- swan_closeness(gra)
#'
#' # Compare with betweenness centrality
#' bet <- betweenness(gra)
#' reg <- lm(bet ~ f2)
#' summary(reg)
#' @export
swan_closeness <- function(g) {
n <- igraph::vcount(g)
swancc <- rep(0, n)
cc <- igraph::distances(g)
ccb <- 1 / cc
ccb[is.infinite(ccb)] <- 0
tot <- sum(ccb)
for (i in seq_len(n)) {
g2 <- g
g2 <- igraph::delete_vertices(g2, i)
cc_no_i <- igraph::distances(g2)
cc_no_ib <- 1 / cc_no_i
cc_no_ib[is.infinite(cc_no_ib)] <- 0
tot2 <- sum(cc_no_ib)
swancc[i] <- tot2 - (tot - sum(ccb[i, ]) - sum(ccb[, i]))
}
return(swancc)
}

#' @name swan_combinatory
#' @title Error and attack tolerance of complex networks
#'
#' @description
#' `swan_combinatory` assesses network vulnerability and the resistance of networks
#' to node removals, whether due to random failures or intentional attacks.
#'
#' @param g An `igraph` object representing the graph to analyze.
#' @param k The number of iterations for assessing the impact of random failures.
#'
#' @details
#' Many complex systems display a surprising degree of tolerance against random failures.
#' However, this resilience often comes at the cost of extreme vulnerability to targeted attacks,
#' where removing key nodes (high-degree or high-betweenness nodes) can severely impact network connectivity.
#'
#' `swan_combinatory` simulates different attack strategies:
#' - **Random failure:** Nodes are removed randomly over multiple iterations.
#' - **Degree-based attack:** Nodes are removed in decreasing order of their degree.
#' - **Betweenness-based attack:** Nodes are removed in decreasing order of their betweenness centrality.
#' - **Cascading failure:** Nodes are removed based on recalculated betweenness after each removal.
#'
#' The function returns a matrix showing the connectivity loss for each attack scenario.
#'
#' The code is an adaptation from the NetSwan package that was archived on CRAN.
#' @return
#' A matrix with five columns:
#' \itemize{
#' \item Column 1: Fraction of nodes removed.
#' \item Column 2: Connectivity loss from betweenness-based attack.
#' \item Column 3: Connectivity loss from degree-based attack.
#' \item Column 4: Connectivity loss from cascading failure.
#' \item Column 5: Connectivity loss from random failures (averaged over `k` iterations).
#' }
#'
#' @references
#' Albert R., Jeong H., Barabási A. (2000). *Error and attack tolerance of complex networks*.
#' Nature, 406(6794), 378-382.
#'
#' @examples
#' library(igraph)
#' # Example electrical network graph
#' elec <- matrix(ncol = 2, byrow = TRUE, c(
#' 11,1, 11,10, 1,2, 2,3, 2,9,
#' 3,4, 3,8, 4,5, 5,6, 5,7,
#' 6,7, 7,8, 8,9, 9,10
#' ))
#' gra <- graph_from_edgelist(elec, directed = FALSE)
#'
#' # Compute vulnerability measures
#' f4 <- swan_combinatory(gra, 10)
#' @export
swan_combinatory <- function(g, k) {
n <- igraph::vcount(g)
dist <- igraph::distances(g)
dist[is.infinite(dist)] <- 0
dist[dist > 0] <- 1
tot <- sum(dist)
fin <- matrix(ncol = 5, nrow = n, 0)
mat <- matrix(ncol = 2, nrow = n, 0)
mat[, 1] <- 1:n
bet <- igraph::betweenness(g)
mat[, 2] <- bet
matri <- mat[order(mat[, 2]), ]
g2 <- g
for (i in seq_len(n)) {
v = n + 1 - i
g2 <- igraph::delete_vertices(g2, matri[v, 1])
dist2 <- igraph::distances(g2)
dist2[is.infinite(dist2)] <- 0
dist2[dist2 > 0] <- 1
tot2 <- sum(dist2)
fin[i, 1] <- i / n
fin[i, 2] <- tot - tot2
matri[matri[, 1] > matri[v, 1], 1] <- matri[matri[, 1] > matri[v, 1], 1] - 1
}
mat <- matrix(ncol = 2, nrow = n, 0) #degree attack
mat[, 1] <- 1:n
deg <- igraph::degree(g)
mat[, 2] <- deg
matri <- mat[order(mat[, 2]), ]
g2 <- g
for (i in seq_len(n)) {
v = n + 1 - i
g2 <- igraph::delete_vertices(g2, matri[v, 1])
dist2 <- igraph::distances(g2)
dist2[is.infinite(dist2)] <- 0
dist2[dist2 > 0] <- 1
tot2 <- sum(dist2)
fin[i, 3] <- tot - tot2
matri[matri[, 1] > matri[v, 1], 1] <- matri[matri[, 1] > matri[v, 1], 1] -
1 #bluff
}
g2 <- g #cascading
npro <- n
lim <- n - 1
for (i in 1:lim) {
mat <- matrix(ncol = 2, nrow = npro, 0)
mat[, 1] <- 1:npro
bet <- igraph::betweenness(g2)
mat[, 2] <- bet
matri <- mat[order(mat[, 2]), ]
g2 <- igraph::delete_vertices(g2, matri[npro, 1])
dist2 <- igraph::distances(g2)
dist2[is.infinite(dist2)] <- 0
dist2[dist2 > 0] <- 1
tot2 <- sum(dist2)
fin[i, 4] <- tot - tot2
npro <- npro - 1
}
fin[n, 4] <- tot
#random
for (l in seq_len(k)) {
al <- sample(1:n, n)
g2 <- g
for (i in seq_len(k)) {
g2 <- igraph::delete_vertices(g2, al[i])
dist2 <- igraph::distances(g2)
dist2[is.infinite(dist2)] <- 0
dist2[dist2 > 0] <- 1
tot2 <- sum(dist2)
fin[i, 5] <- fin[i, 5] + (tot - tot2)
al[al > al[i]] <- al[al > al[i]] - 1 #bluff
}
}
fin[, 2:4] <- fin[, 2:4] / tot
fin[, 5] <- fin[, 5] / tot / k
return(fin)
}

#' @name swan_connectivity
#' @title Impact on connectivity when a node is removed
#'
#' @description
#' `swan_connectivity` measures the loss of connectivity when a node is removed from the network.
#'
#' @usage
#' swan_connectivity(g)
#'
#' @param g An `igraph` object representing the graph to analyze.
#'
#' @details
#' Connectivity loss indices quantify the decrease in the number of relationships between nodes
#' when one or more components are removed. `swan_connectivity` computes the connectivity loss
#' by systematically excluding each node and evaluating the resulting changes in the network structure.
#'
#' The code is an adaptation from the NetSwan package that was archived on CRAN.
#' @return
#' A numeric vector where each entry represents the connectivity loss when the corresponding node is removed.
#'
#' @references
#' Lhomme S. (2015). *Analyse spatiale de la structure des réseaux techniques dans un contexte de risques*.
#' Cybergeo: European Journal of Geography.
#' @examples
#' library(igraph)
#' # Example graph (electrical network structure)
#' elec <- matrix(ncol = 2, byrow = TRUE, c(
#' 11,1, 11,10, 1,2, 2,3, 2,9,
#' 3,4, 3,8, 4,5, 5,6, 5,7,
#' 6,7, 7,8, 8,9, 9,10
#' ))
#' gra <- graph_from_edgelist(elec, directed = FALSE)
#'
#' # Compute connectivity loss
#' f3 <- swan_connectivity(gra)
#' @export
swan_connectivity <- function(g) {
n <- igraph::vcount(g)
fin <- rep(0, n)
dist <- igraph::distances(g)
dist[!is.infinite(dist)] <- 0
dist[is.infinite(dist)] <- 1
con <- sum(dist)
for (i in seq_len(n)) {
g2 <- g
g2 <- igraph::delete_vertices(g2, i)
dist2 <- igraph::distances(g2)
dist2[!is.infinite(dist2)] <- 0
dist2[is.infinite(dist2)] <- 1
con2 <- sum(dist2)
fin[i] <- con2 - con
}
return(fin)
}

#' @name swan_efficiency
#' @title Impact on farness when a node is removed
#'
#' @description
#' `swan_efficiency` measures the change in the sum of distances between all node pairs
#' when excluding a node from the network.
#'
#' @param g An `igraph` object representing the graph to analyze.
#' `swan_efficiency` is based on geographic accessibility, similar to indices used for
#' assessing transportation network performance, such as closeness accessibility.
#' It quantifies the impact of node removal by calculating the change in the sum of
#' distances between all node pairs.
#'
#' The code is an adaptation from the NetSwan package that was archived on CRAN.
#'
#' @return
#' A numeric vector where each entry represents the `swan_efficiency` value for the
#' corresponding node.
#'
#' @references
#' Lhomme S. (2015). *Analyse spatiale de la structure des réseaux techniques dans un
#' contexte de risques*. Cybergeo: European Journal of Geography.
#'
#' @examples
#' library(igraph)
#' # Example graph (electrical network structure)
#' elec <- matrix(ncol = 2, byrow = TRUE, c(
#' 11,1, 11,10, 1,2, 2,3, 2,9,
#' 3,4, 3,8, 4,5, 5,6, 5,7,
#' 6,7, 7,8, 8,9, 9,10
#' ))
#' gra <- graph_from_edgelist(elec, directed = FALSE)
#'
#' # Compute efficiency impact of node removal
#' f2 <- swan_efficiency(gra)
#' bet <- betweenness(gra)
#' reg <- lm(bet ~ f2)
#' summary(reg)
#' @export
swan_efficiency <- function(g) {
n <- igraph::vcount(g)
fin <- rep(0, n)
dt = igraph::distances(g)
tot = sum(dt)
for (i in 1:n) {
g2 <- g
g2 <- igraph::delete_vertices(g2, i)
dt2 <- igraph::distances(g2)
tot2 <- sum(dt2)
fin[i] <- tot2 - (tot - sum(dt[i, ]) - sum(dt[, i]))
}
return(fin)
}
5 changes: 2 additions & 3 deletions cran-comments.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Update from 1.2.2 to 1.2.3
# Update from 1.2.3 to 1.2.4

quick bugfix release to prevent package from being deleted from CRAN due to
failing test
added functions from an archived CRAN package

## Test environments
* ubuntu 22.04, R 4.3.2
Expand Down
2 changes: 1 addition & 1 deletion man/netrankr-package.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

46 changes: 46 additions & 0 deletions man/swan_closeness.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading