Skip to content

Commit

Permalink
feat: weight support for eccentricity() and radius() (#1211)
Browse files Browse the repository at this point in the history
Co-authored-by: Maëlle Salmon <[email protected]>
Co-authored-by: Kirill Müller <[email protected]>
  • Loading branch information
3 people authored Mar 25, 2024
1 parent 664215a commit aa0de48
Show file tree
Hide file tree
Showing 21 changed files with 767 additions and 647 deletions.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,7 @@ export(graph.union)
export(graph_)
export(graph_attr)
export(graph_attr_names)
export(graph_center)
export(graph_from_adj_list)
export(graph_from_adjacency_matrix)
export(graph_from_atlas)
Expand Down
50 changes: 6 additions & 44 deletions R/aaa-auto.R
Original file line number Diff line number Diff line change
Expand Up @@ -1777,23 +1777,9 @@ contract_vertices_impl <- function(graph, mapping, vertex.attr.comb=igraph_opt("
res
}

eccentricity_impl <- function(graph, vids=V(graph), mode=c("all", "out", "in", "total")) {
# Argument checks
ensure_igraph(graph)
vids <- as_igraph_vs(graph, vids)
mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L)

on.exit( .Call(R_igraph_finalizer) )
# Function call
res <- .Call(R_igraph_eccentricity, graph, vids-1, mode)
if (igraph_opt("add.vertex.names") && is_named(graph)) {
names(res) <- vertex_attr(graph, "name", vids)
}
res
}

eccentricity_dijkstra_impl <- function(graph, weights=NULL, vids=V(graph), mode=c("all", "out", "in", "total")) {
eccentricity_dijkstra_impl <- function(graph, vids=V(graph), ..., weights=NULL, mode=c("all", "out", "in", "total")) {
# Argument checks
check_dots_empty()
ensure_igraph(graph)
if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
weights <- E(graph)$weight
Expand All @@ -1815,22 +1801,9 @@ eccentricity_dijkstra_impl <- function(graph, weights=NULL, vids=V(graph), mode=
res
}

graph_center_impl <- function(graph, mode=c("all", "out", "in", "total")) {
# Argument checks
ensure_igraph(graph)
mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L)

on.exit( .Call(R_igraph_finalizer) )
# Function call
res <- .Call(R_igraph_graph_center, graph, mode)
if (igraph_opt("return.vs.es")) {
res <- create_vs(graph, res)
}
res
}

graph_center_dijkstra_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) {
graph_center_dijkstra_impl <- function(graph, ..., weights=NULL, mode=c("all", "out", "in", "total")) {
# Argument checks
check_dots_empty()
ensure_igraph(graph)
if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
weights <- E(graph)$weight
Expand All @@ -1851,20 +1824,9 @@ graph_center_dijkstra_impl <- function(graph, weights=NULL, mode=c("all", "out",
res
}

radius_impl <- function(graph, mode=c("all", "out", "in", "total")) {
# Argument checks
ensure_igraph(graph)
mode <- switch(igraph.match.arg(mode), "out"=1L, "in"=2L, "all"=3L, "total"=3L)

on.exit( .Call(R_igraph_finalizer) )
# Function call
res <- .Call(R_igraph_radius, graph, mode)

res
}

radius_dijkstra_impl <- function(graph, weights=NULL, mode=c("all", "out", "in", "total")) {
radius_dijkstra_impl <- function(graph, ..., weights=NULL, mode=c("all", "out", "in", "total")) {
# Argument checks
check_dots_empty()
ensure_igraph(graph)
if (is.null(weights) && "weight" %in% edge_attr_names(graph)) {
weights <- E(graph)$weight
Expand Down
101 changes: 83 additions & 18 deletions R/paths.R
Original file line number Diff line number Diff line change
Expand Up @@ -242,12 +242,8 @@ max_cardinality <- maximum_cardinality_search_impl
#'
#' @param graph The input graph, it can be directed or undirected.
#' @param vids The vertices for which the eccentricity is calculated.
#' @param mode Character constant, gives whether the shortest paths to or from
#' the given vertices should be calculated for directed graphs. If `out`
#' then the shortest paths *from* the vertex, if `in` then *to*
#' it will be considered. If `all`, the default, then the corresponding
#' undirected graph will be used, edge directions will be ignored. This
#' argument is ignored for undirected graphs.
#' @inheritParams distances
#' @inheritParams rlang::args_dots_empty
#' @return `eccentricity()` returns a numeric vector, containing the
#' eccentricity score of each given vertex.
#' @seealso [radius()] for a related concept,
Expand All @@ -259,29 +255,47 @@ max_cardinality <- maximum_cardinality_search_impl
#' eccentricity(g)
#' @family paths
#' @export
eccentricity <- eccentricity_impl
eccentricity <- function(graph, vids = V(graph), ..., weights = NULL, mode = c("all", "out", "in", "total")) {
if (...length() > 0) {
lifecycle::deprecate_soft(
"2.1.0",
"eccentricity(... =)",
details = "The arguments `weights` and `mode` must be named."
)

rlang::check_dots_unnamed()

dots <- list(...)

if (is.null(weights) && length(dots) > 0) {
weights <- dots[[1]]
dots <- dots[-1]
}

if (missing(mode) && length(dots) > 0) {
mode <- dots[[1]]
}
}

eccentricity_dijkstra_impl(graph, vids = vids, weights = weights, mode = mode)
}


#' Radius of a graph
#'
#' The eccentricity of a vertex is its shortest path distance from the
#' farthest other node in the graph. The smallest eccentricity in a graph
#' is called its radius
#' The eccentricity of a vertex is its distance from the farthest other node
#' in the graph. The smallest eccentricity in a graph is called its radius.
#'
#' The eccentricity of a vertex is calculated by measuring the shortest
#' distance from (or to) the vertex, to (or from) all vertices in the
#' graph, and taking the maximum.
#'
#' This implementation ignores vertex pairs that are in different
#' components. Isolate vertices have eccentricity zero.
#' components. Isolated vertices have eccentricity zero.
#'
#' @param graph The input graph, it can be directed or undirected.
#' @param mode Character constant, gives whether the shortest paths to or from
#' the given vertices should be calculated for directed graphs. If `out`
#' then the shortest paths *from* the vertex, if `in` then *to*
#' it will be considered. If `all`, the default, then the corresponding
#' undirected graph will be used, edge directions will be ignored. This
#' argument is ignored for undirected graphs.
#' @inheritParams eccentricity
#' @inheritParams rlang::args_dots_empty
#' @return A numeric scalar, the radius of the graph.
#' @seealso [eccentricity()] for the underlying
#' calculations, [distances] for general shortest path
Expand All @@ -294,7 +308,58 @@ eccentricity <- eccentricity_impl
#' radius(g)
#' @family paths
#' @export
radius <- radius_impl
radius <- function(graph, ..., weights = NULL, mode = c("all", "out", "in", "total")) {
if (...length() > 0) {
lifecycle::deprecate_soft(
"2.1.0",
"radius(... =)",
details = "The arguments `weights` and `mode` must be named."
)

rlang::check_dots_unnamed()

dots <- list(...)

if (is.null(weights) && length(dots) > 0) {
weights <- dots[[1]]
dots <- dots[-1]
}

if (missing(mode) && length(dots) > 0) {
mode <- dots[[1]]
}
}

radius_dijkstra_impl(graph, weights = weights, mode = mode)
}

#' Central vertices of a graph
#'
#' @description
#' `r lifecycle::badge("experimental")`
#'
#' The center of a graph is the set of its vertices with minimal eccentricity.
#'
#' @inheritParams eccentricity
#' @inheritParams rlang::args_dots_empty
#' @return The vertex IDs of the central vertices.
#' @seealso [eccentricity()], [radius()]
#' @family paths
#' @examples
#' tree <- make_tree(100, 7)
#' graph_center(tree)
#' graph_center(tree, mode = "in")
#' graph_center(tree, mode = "out")
#'
#' # Without and with weights
#' ring <- make_ring(10)
#' graph_center(ring)
#' # Add weights
#' E(ring)$weight <- seq_len(ecount(ring))
#' graph_center(ring)
#'
#' @export
graph_center <- graph_center_dijkstra_impl

#' @rdname distances
#' @param directed Whether to consider directed paths in directed graphs,
Expand Down
7 changes: 4 additions & 3 deletions R/structural.properties.R
Original file line number Diff line number Diff line change
Expand Up @@ -730,13 +730,14 @@ degree_distribution <- function(graph, cumulative = FALSE, ...) {
#' @param mode Character constant, gives whether the shortest paths to or from
#' the given vertices should be calculated for directed graphs. If `out`
#' then the shortest paths *from* the vertex, if `in` then *to*
#' it will be considered. If `all`, the default, then the corresponding
#' undirected graph will be used, i.e. not directed paths are searched. This
#' it will be considered. If `all`, the default, then the graph is treated
#' as undirected, i.e. edge directions are not taken into account. This
#' argument is ignored for undirected graphs.
#' @param weights Possibly a numeric vector giving edge weights. If this is
#' `NULL` and the graph has a `weight` edge attribute, then the
#' attribute is used. If this is `NA` then no weights are used (even if
#' the graph has a `weight` attribute).
#' the graph has a `weight` attribute). In a weighted graph, the length
#' of a path is the sum of the weights of its constituent edges.
#' @param algorithm Which algorithm to use for the calculation. By default
#' igraph tries to select the fastest suitable algorithm. If there are no
#' weights, then an unweighted breadth-first search is used, otherwise if all
Expand Down
1 change: 1 addition & 0 deletions man/all_simple_paths.Rd

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

3 changes: 2 additions & 1 deletion man/average.path.length.Rd

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

1 change: 1 addition & 0 deletions man/diameter.Rd

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

8 changes: 5 additions & 3 deletions man/distances.Rd

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

21 changes: 18 additions & 3 deletions man/eccentricity.Rd

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

7 changes: 4 additions & 3 deletions man/get.all.shortest.paths.Rd

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

7 changes: 4 additions & 3 deletions man/get.shortest.paths.Rd

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

Loading

0 comments on commit aa0de48

Please sign in to comment.