diff --git a/R/structural.properties.R b/R/structural.properties.R index 0838746588..f86f93b529 100644 --- a/R/structural.properties.R +++ b/R/structural.properties.R @@ -677,8 +677,10 @@ degree_distribution <- function(graph, cumulative = FALSE, ...) { #' are breadth-first search (\sQuote{`unweighted`}), this only works for #' unweighted graphs; the Dijkstra algorithm (\sQuote{`dijkstra`}), this #' works for graphs with non-negative edge weights; the Bellman-Ford algorithm -#' (\sQuote{`bellman-ford`}), and Johnson's algorithm -#' (\sQuote{`johnson`}). The latter two algorithms work with arbitrary +#' (\sQuote{`bellman-ford`}); Johnson's algorithm +#' (\sQuote{`johnson`}); and a faster version of the Floyd-Warshall algorithm +#' with expected quadratic running time (\sQuote{`floyd-warshall`}). The latter +#' three algorithms work with arbitrary #' edge weights, but (naturally) only for graphs that don't have a negative #' cycle. Note that a negative-weight edge in an undirected graph implies #' such a cycle. Johnson's algorithm performs better than the Bellman-Ford @@ -833,7 +835,7 @@ distances <- function(graph, v = V(graph), to = V(graph), weights = NULL, algorithm = c( "automatic", "unweighted", "dijkstra", - "bellman-ford", "johnson" + "bellman-ford", "johnson", "floyd-warshall" )) { ensure_igraph(graph) @@ -858,7 +860,8 @@ distances <- function(graph, v = V(graph), to = V(graph), "unweighted" = 1, "dijkstra" = 2, "bellman-ford" = 3, - "johnson" = 4 + "johnson" = 4, + "floyd-warshall" = 5 ) if (is.null(weights)) { diff --git a/man/distances.Rd b/man/distances.Rd index 46c437c4d5..6e48a7114a 100644 --- a/man/distances.Rd +++ b/man/distances.Rd @@ -24,7 +24,8 @@ distances( to = V(graph), mode = c("all", "out", "in"), weights = NULL, - algorithm = c("automatic", "unweighted", "dijkstra", "bellman-ford", "johnson") + algorithm = c("automatic", "unweighted", "dijkstra", "bellman-ford", "johnson", + "floyd-warshall") ) shortest_paths( @@ -176,8 +177,10 @@ the \code{weight} edge attribute of the graph. The implemented algorithms are breadth-first search (\sQuote{\code{unweighted}}), this only works for unweighted graphs; the Dijkstra algorithm (\sQuote{\code{dijkstra}}), this works for graphs with non-negative edge weights; the Bellman-Ford algorithm -(\sQuote{\code{bellman-ford}}), and Johnson's algorithm -(\sQuote{\code{johnson}}). The latter two algorithms work with arbitrary +(\sQuote{\code{bellman-ford}}); Johnson's algorithm +(\sQuote{\code{johnson}}); and a faster version of the Floyd-Warshall algorithm +with expected quadratic running time (\sQuote{\code{floyd-warshall}}). The latter +three algorithms work with arbitrary edge weights, but (naturally) only for graphs that don't have a negative cycle. Note that a negative-weight edge in an undirected graph implies such a cycle. Johnson's algorithm performs better than the Bellman-Ford diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index b6a9b8fbb4..ea5036647e 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -4244,7 +4244,7 @@ SEXP R_igraph_shortest_paths(SEXP graph, SEXP pvids, SEXP pto, switch (algo) { case 0: /* automatic */ if (negw && mode != IGRAPH_ALL && Rf_xlength(pvids)>100) { - distances_johnson(&g, &res, vs, to, pw, mode, negw); + IGRAPH_R_CHECK(distances_johnson(&g, &res, vs, to, pw, mode, negw)); } else if (negw) { IGRAPH_R_CHECK(igraph_distances_bellman_ford(&g, &res, vs, to, pw, mode)); } else { @@ -4262,7 +4262,10 @@ SEXP R_igraph_shortest_paths(SEXP graph, SEXP pvids, SEXP pto, IGRAPH_R_CHECK(igraph_distances_bellman_ford(&g, &res, vs, to, pw, mode)); break; case 4: /* johnson */ - distances_johnson(&g, &res, vs, to, pw, mode, negw); + IGRAPH_R_CHECK(distances_johnson(&g, &res, vs, to, pw, mode, negw)); + break; + case 5: /* floyd-warshall */ + IGRAPH_R_CHECK(igraph_distances_floyd_warshall(&g, &res, vs, to, pw, mode, IGRAPH_FLOYD_WARSHALL_AUTOMATIC)); break; } PROTECT(result=R_igraph_matrix_to_SEXP(&res)); diff --git a/tests/testthat/test-distances.R b/tests/testthat/test-distances.R new file mode 100644 index 0000000000..c8a5b81d5c --- /dev/null +++ b/tests/testthat/test-distances.R @@ -0,0 +1,37 @@ +test_that("distances works", { + g <- make_graph(c(1, 5, 1, 7, 1, 8, 1, 10, 2, 6, + 2, 7, 2, 8, 2, 10, 3, 4, 3, 5, + 3, 9, 5, 6, 5, 7, 5, 10, 6, 8, + 7, 8, 7, 9, 8, 9, 8, 10, 9, 10), + directed = FALSE) + + mu <- distances(g, algorithm = "unweighted") + + # unit weights + E(g)$weight <- rep(1, ecount(g)) + + ma <- distances(g) # automatic + md <- distances(g, algorithm = "dijkstra") + mbf <- distances(g, algorithm = "bellman-ford") + mj <- distances(g, algorithm = "johnson") + mfw <- distances(g, algorithm = "floyd-warshall") + + expect_equal(mu, ma) + expect_equal(mu, md) + expect_equal(mu, mbf) + expect_equal(mu, mj) + expect_equal(mu, mfw) + + E(g)$weight <- 0.25 * (1:ecount(g)) + + ma <- distances(g) # automatic + md <- distances(g, algorithm = "dijkstra") + mbf <- distances(g, algorithm = "bellman-ford") + mj <- distances(g, algorithm = "johnson") + mfw <- distances(g, algorithm = "floyd-warshall") + + expect_equal(ma, md) + expect_equal(ma, mbf) + expect_equal(ma, mj) + expect_equal(ma, mfw) +})