From 12230f831e3f403788c13634b81598ce7d402a48 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 17 Aug 2026 17:49:27 +0000 Subject: [PATCH] refactor: Rename `algo` to `algorithm` in `page_rank()`, `feedback_arc_set()` and `feedback_vertex_set()` (#2788, #526) The legacy `algo` spelling is recovered by the generated ARG_HANDLE blocks and soft-deprecated; abbreviations of both spellings are guarded as ambiguous. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01RTPj4qNv2FWui6etixZeuR --- R/centrality.R | 18 +++++++------ R/structural-properties.R | 30 ++++++++++++--------- man/feedback_arc_set.Rd | 6 ++--- man/feedback_vertex_set.Rd | 4 +-- man/page.rank.Rd | 10 ++----- man/page_rank.Rd | 4 +-- tests/testthat/_snaps/centrality.md | 10 +++++++ tests/testthat/test-centrality.R | 15 ++++++++--- tests/testthat/test-structural-properties.R | 24 +++++++++++++++-- tools/migrations/centrality.R | 4 +-- tools/migrations/structural-properties.R | 8 +++--- 11 files changed, 86 insertions(+), 47 deletions(-) diff --git a/R/centrality.R b/R/centrality.R index 39ee45778a7..b95ea2ea3fd 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -26,6 +26,8 @@ subgraph.centrality <- function(graph, diag = FALSE) { #' `page.rank()` was renamed to [page_rank()] to create a more #' consistent API. #' @inheritParams page_rank +#' @param algo `r lifecycle::badge("deprecated")` Use `algorithm` in +#' [page_rank()] instead. #' @keywords internal #' @export page.rank <- function( @@ -42,7 +44,7 @@ page.rank <- function( lifecycle::deprecate_warn("2.0.0", "page.rank()", "page_rank()") page_rank( graph = graph, - algo = algo, + algorithm = algo, vids = vids, directed = directed, damping = damping, @@ -1884,7 +1886,7 @@ hub_score <- function( #' #' @param graph The graph object. #' @inheritParams rlang::args_dots_empty -#' @param algo Character scalar, which implementation to use to carry out the +#' @param algorithm Character scalar, which implementation to use to carry out the #' calculation. The default is `"prpack"`, which uses the PRPACK library #' () to calculate PageRank scores #' by solving a set of linear equations. This is a new implementation in igraph @@ -1953,7 +1955,7 @@ hub_score <- function( page_rank <- function( graph, ..., - algo = c("prpack", "arpack"), + algorithm = c("prpack", "arpack"), vids = NULL, directed = TRUE, damping = 0.85, @@ -1964,7 +1966,7 @@ page_rank <- function( # BEGIN GENERATED ARG_HANDLE: page_rank, do not edit, see tools/generate-migrations.R # fmt: skip if (...length() > 0L) { - .arg_ambiguous <- base::intersect(base::names(base::substitute(...())), base::c("d")) + .arg_ambiguous <- base::intersect(base::names(base::substitute(...())), base::c("a", "al", "alg", "d")) if (base::length(.arg_ambiguous) > 0L) cli::cli_abort("Argument {.arg {(.arg_ambiguous[[1L]])}} matches multiple arguments of {.fn page_rank}.") # Pre-3.0.0 signature: page_rank(graph, algo, vids, directed, damping, personalized, weights, options) .old_signature <- function(algo, vids, directed, damping, personalized, weights, options, ...) { @@ -1975,7 +1977,7 @@ page_rank <- function( cli::cli_abort(base::c("Unexpected argument passed to {.fn page_rank}: {.arg {(.arg_extra)}}.", i = "Arguments after {.arg ...} must be spelled out in full."), call = base::parent.frame()) } base::c( - if (!base::missing(algo)) base::list(algo = algo), + if (!base::missing(algo)) base::list(algorithm = algo), if (!base::missing(vids)) base::list(vids = vids), if (!base::missing(directed)) base::list(directed = directed), if (!base::missing(damping)) base::list(damping = damping), @@ -1988,7 +1990,7 @@ page_rank <- function( if (base::length(.arg_handle) > 0L) { .arg_names <- base::names(.arg_handle) .arg_conflict <- base::intersect(.arg_names, base::c( - if (!base::missing(algo)) "algo", + if (!base::missing(algorithm)) "algorithm", if (!base::missing(vids)) "vids", if (!base::missing(directed)) "directed", if (!base::missing(damping)) "damping", @@ -2002,7 +2004,7 @@ page_rank <- function( "3.0.0", what = base::I("Calling `page_rank()` with positional or abbreviated arguments"), details = base::c( - i = base::paste0("Detected call: page_rank(", base::paste(base::c("graph", .arg_names), collapse = ", "), ")"), + i = base::paste0("Detected call: page_rank(", base::paste(base::c("graph", base::c(algorithm = "algo", vids = "vids", directed = "directed", damping = "damping", personalized = "personalized", weights = "weights", options = "options")[.arg_names]), collapse = ", "), ")"), i = base::paste0("Use instead: page_rank(", base::paste(base::c("graph", base::paste0(.arg_names, " = ")), collapse = ", "), ")") ) ) @@ -2016,7 +2018,7 @@ page_rank <- function( personalized_pagerank_impl( graph = graph, - algo = algo, + algo = algorithm, vids = vids, directed = directed, damping = damping, diff --git a/R/structural-properties.R b/R/structural-properties.R index c2970ebc5a9..36b37f0e397 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -3216,7 +3216,7 @@ topo_sort <- function( #' `NULL`, then the edge attribute is used automatically. The goal of #' the feedback arc set problem is to find a feedback arc set with the smallest #' total weight. -#' @param algo Specifies the algorithm to use. \dQuote{`exact_ip`} solves +#' @param algorithm Specifies the algorithm to use. \dQuote{`exact_ip`} solves #' the feedback arc set problem with an exact integer programming algorithm that #' guarantees that the total weight of the removed edges is as small as possible. #' \dQuote{`approx_eades`} uses a fast (linear-time) approximation @@ -3236,16 +3236,18 @@ topo_sort <- function( #' #' g <- sample_gnm(20, 40, directed = TRUE) #' feedback_arc_set(g) -#' feedback_arc_set(g, algo = "approx_eades") +#' feedback_arc_set(g, algorithm = "approx_eades") feedback_arc_set <- function( graph, ..., weights = NULL, - algo = c("approx_eades", "exact_ip") + algorithm = c("approx_eades", "exact_ip") ) { # BEGIN GENERATED ARG_HANDLE: feedback_arc_set, do not edit, see tools/generate-migrations.R # fmt: skip if (...length() > 0L) { + .arg_ambiguous <- base::intersect(base::names(base::substitute(...())), base::c("a", "al", "alg")) + if (base::length(.arg_ambiguous) > 0L) cli::cli_abort("Argument {.arg {(.arg_ambiguous[[1L]])}} matches multiple arguments of {.fn feedback_arc_set}.") # Pre-3.0.0 signature: feedback_arc_set(graph, weights, algo) .old_signature <- function(weights, algo, ...) { if (...length() > 0L) { @@ -3256,7 +3258,7 @@ feedback_arc_set <- function( } base::c( if (!base::missing(weights)) base::list(weights = weights), - if (!base::missing(algo)) base::list(algo = algo) + if (!base::missing(algo)) base::list(algorithm = algo) ) } .arg_handle <- .old_signature(...) @@ -3264,7 +3266,7 @@ feedback_arc_set <- function( .arg_names <- base::names(.arg_handle) .arg_conflict <- base::intersect(.arg_names, base::c( if (!base::missing(weights)) "weights", - if (!base::missing(algo)) "algo" + if (!base::missing(algorithm)) "algorithm" )) if (base::length(.arg_conflict) > 0L) cli::cli_abort(base::c("Argument {.arg {(.arg_conflict)}} of {.fn feedback_arc_set} was supplied more than once.", i = "Pass it exactly once, by its new name {.arg {(.arg_conflict)}}.")) base::list2env(.arg_handle, base::environment()) @@ -3272,7 +3274,7 @@ feedback_arc_set <- function( "3.0.0", what = base::I("Calling `feedback_arc_set()` with positional or abbreviated arguments"), details = base::c( - i = base::paste0("Detected call: feedback_arc_set(", base::paste(base::c("graph", .arg_names), collapse = ", "), ")"), + i = base::paste0("Detected call: feedback_arc_set(", base::paste(base::c("graph", base::c(weights = "weights", algorithm = "algo")[.arg_names]), collapse = ", "), ")"), i = base::paste0("Use instead: feedback_arc_set(", base::paste(base::c("graph", base::paste0(.arg_names, " = ")), collapse = ", "), ")") ) ) @@ -3283,7 +3285,7 @@ feedback_arc_set <- function( feedback_arc_set_impl( graph = graph, weights = weights, - algo = algo + algo = algorithm ) } @@ -3303,7 +3305,7 @@ feedback_arc_set <- function( #' `NULL`, then the vertex attribute is used automatically. The goal of #' the feedback vertex set problem is to find a feedback vertex set with #' the smallest total weight. -#' @param algo Specifies the algorithm to use. Currently, \dQuote{`exact_ip`}, +#' @param algorithm Specifies the algorithm to use. Currently, \dQuote{`exact_ip`}, #' which solves the feedback vertex set problem with an exact integer #' programming approach, is the only option. #' @return A vertex sequence (by default, but see the `return.vs.es` option @@ -3320,11 +3322,13 @@ feedback_vertex_set <- function( graph, ..., weights = NULL, - algo = c("exact_ip") + algorithm = c("exact_ip") ) { # BEGIN GENERATED ARG_HANDLE: feedback_vertex_set, do not edit, see tools/generate-migrations.R # fmt: skip if (...length() > 0L) { + .arg_ambiguous <- base::intersect(base::names(base::substitute(...())), base::c("a", "al", "alg")) + if (base::length(.arg_ambiguous) > 0L) cli::cli_abort("Argument {.arg {(.arg_ambiguous[[1L]])}} matches multiple arguments of {.fn feedback_vertex_set}.") # Pre-3.0.0 signature: feedback_vertex_set(graph, weights, algo) .old_signature <- function(weights, algo, ...) { if (...length() > 0L) { @@ -3335,7 +3339,7 @@ feedback_vertex_set <- function( } base::c( if (!base::missing(weights)) base::list(weights = weights), - if (!base::missing(algo)) base::list(algo = algo) + if (!base::missing(algo)) base::list(algorithm = algo) ) } .arg_handle <- .old_signature(...) @@ -3343,7 +3347,7 @@ feedback_vertex_set <- function( .arg_names <- base::names(.arg_handle) .arg_conflict <- base::intersect(.arg_names, base::c( if (!base::missing(weights)) "weights", - if (!base::missing(algo)) "algo" + if (!base::missing(algorithm)) "algorithm" )) if (base::length(.arg_conflict) > 0L) cli::cli_abort(base::c("Argument {.arg {(.arg_conflict)}} of {.fn feedback_vertex_set} was supplied more than once.", i = "Pass it exactly once, by its new name {.arg {(.arg_conflict)}}.")) base::list2env(.arg_handle, base::environment()) @@ -3351,7 +3355,7 @@ feedback_vertex_set <- function( "3.0.0", what = base::I("Calling `feedback_vertex_set()` with positional or abbreviated arguments"), details = base::c( - i = base::paste0("Detected call: feedback_vertex_set(", base::paste(base::c("graph", .arg_names), collapse = ", "), ")"), + i = base::paste0("Detected call: feedback_vertex_set(", base::paste(base::c("graph", base::c(weights = "weights", algorithm = "algo")[.arg_names]), collapse = ", "), ")"), i = base::paste0("Use instead: feedback_vertex_set(", base::paste(base::c("graph", base::paste0(.arg_names, " = ")), collapse = ", "), ")") ) ) @@ -3362,7 +3366,7 @@ feedback_vertex_set <- function( feedback_vertex_set_impl( graph = graph, weights = weights, - algo = algo + algo = algorithm ) } diff --git a/man/feedback_arc_set.Rd b/man/feedback_arc_set.Rd index 4e243de7630..b356af260c0 100644 --- a/man/feedback_arc_set.Rd +++ b/man/feedback_arc_set.Rd @@ -8,7 +8,7 @@ feedback_arc_set( graph, ..., weights = NULL, - algo = c("approx_eades", "exact_ip") + algorithm = c("approx_eades", "exact_ip") ) } \arguments{ @@ -22,7 +22,7 @@ attribute called \sQuote{\code{weight}}, and this argument is the feedback arc set problem is to find a feedback arc set with the smallest total weight.} -\item{algo}{Specifies the algorithm to use. \dQuote{\code{exact_ip}} solves +\item{algorithm}{Specifies the algorithm to use. \dQuote{\code{exact_ip}} solves the feedback arc set problem with an exact integer programming algorithm that guarantees that the total weight of the removed edges is as small as possible. \dQuote{\code{approx_eades}} uses a fast (linear-time) approximation @@ -53,7 +53,7 @@ component is a tree). g <- sample_gnm(20, 40, directed = TRUE) feedback_arc_set(g) -feedback_arc_set(g, algo = "approx_eades") +feedback_arc_set(g, algorithm = "approx_eades") } \references{ Peter Eades, Xuemin Lin and W.F.Smyth: A fast and effective diff --git a/man/feedback_vertex_set.Rd b/man/feedback_vertex_set.Rd index 89dd657e20d..660dd399f66 100644 --- a/man/feedback_vertex_set.Rd +++ b/man/feedback_vertex_set.Rd @@ -4,7 +4,7 @@ \alias{feedback_vertex_set} \title{Finding a feedback vertex set in a graph} \usage{ -feedback_vertex_set(graph, ..., weights = NULL, algo = c("exact_ip")) +feedback_vertex_set(graph, ..., weights = NULL, algorithm = c("exact_ip")) } \arguments{ \item{graph}{The input graph} @@ -17,7 +17,7 @@ attribute called \sQuote{\code{weight}}, and this argument is the feedback vertex set problem is to find a feedback vertex set with the smallest total weight.} -\item{algo}{Specifies the algorithm to use. Currently, \dQuote{\code{exact_ip}}, +\item{algorithm}{Specifies the algorithm to use. Currently, \dQuote{\code{exact_ip}}, which solves the feedback vertex set problem with an exact integer programming approach, is the only option.} } diff --git a/man/page.rank.Rd b/man/page.rank.Rd index 0c81f6fdfc3..41839e26df2 100644 --- a/man/page.rank.Rd +++ b/man/page.rank.Rd @@ -18,14 +18,8 @@ page.rank( \arguments{ \item{graph}{The graph object.} -\item{algo}{Character scalar, which implementation to use to carry out the -calculation. The default is \code{"prpack"}, which uses the PRPACK library -(\url{https://github.com/dgleich/prpack}) to calculate PageRank scores -by solving a set of linear equations. This is a new implementation in igraph -version 0.7, and the suggested one, as it is the most stable and the fastest -for all but small graphs. \code{"arpack"} uses the ARPACK library, the -default implementation from igraph version 0.5 until version 0.7. It computes -PageRank scores by solving an eingevalue problem.} +\item{algo}{\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} Use \code{algorithm} in +\code{\link[=page_rank]{page_rank()}} instead.} \item{vids}{The vertices of interest. The default \code{NULL} selects all vertices.} diff --git a/man/page_rank.Rd b/man/page_rank.Rd index 58937b15dfc..c205f129a6b 100644 --- a/man/page_rank.Rd +++ b/man/page_rank.Rd @@ -7,7 +7,7 @@ page_rank( graph, ..., - algo = c("prpack", "arpack"), + algorithm = c("prpack", "arpack"), vids = NULL, directed = TRUE, damping = 0.85, @@ -21,7 +21,7 @@ page_rank( \item{...}{These dots are for future extensions and must be empty.} -\item{algo}{Character scalar, which implementation to use to carry out the +\item{algorithm}{Character scalar, which implementation to use to carry out the calculation. The default is \code{"prpack"}, which uses the PRPACK library (\url{https://github.com/dgleich/prpack}) to calculate PageRank scores by solving a set of linear equations. This is a new implementation in igraph diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index bcb12bae957..fd6a1913e6f 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -59,3 +59,13 @@ Error in `arpack()`: ! Can't use unkown ARPACK options: unknown_thing1, unknown_thing2 +# page_rank(algo = ) is deprecated but still works + + Code + res_legacy <- page_rank(star, algo = "prpack") + Condition + Warning: + Calling `page_rank()` with positional or abbreviated arguments was deprecated in igraph 3.0.0. + i Detected call: page_rank(graph, algo) + i Use instead: page_rank(graph, algorithm = ) + diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index b7abe50bec2..240ac2ab849 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -1074,12 +1074,12 @@ test_that("page_rank() covers migrated tail args and positional recovery", { # The weight attribute is a decoy that the explicit `weights` must override. E(star)$weight <- c(10, rep(1, 8)) - # `algo` keeps its default value: + # `algorithm` keeps its default value: # non-default values select the legacy ARPACK implementation, # and `options` is only consumed by that implementation. res <- page_rank( star, - algo = "prpack", + algorithm = "prpack", vids = V(star)[1:5], directed = FALSE, damping = 0.9, @@ -1106,7 +1106,16 @@ test_that("page_rank() covers migrated tail args and positional recovery", { lifecycle::expect_deprecated( res_legacy <- page_rank(star, "prpack") ) - expect_identical(res_legacy, page_rank(star, algo = "prpack")) + expect_identical(res_legacy, page_rank(star, algorithm = "prpack")) +}) + +test_that("page_rank(algo = ) is deprecated but still works", { + rlang::local_options(lifecycle_verbosity = "warning") + star <- make_star(10, mode = "undirected") + expect_snapshot( + res_legacy <- page_rank(star, algo = "prpack") + ) + expect_identical(res_legacy, page_rank(star, algorithm = "prpack")) }) test_that("strength() covers migrated tail args and positional recovery", { diff --git a/tests/testthat/test-structural-properties.R b/tests/testthat/test-structural-properties.R index 6c4e5752024..d1a5424489e 100644 --- a/tests/testthat/test-structural-properties.R +++ b/tests/testthat/test-structural-properties.R @@ -1398,11 +1398,21 @@ test_that("feedback_arc_set() tail arguments and legacy positional recovery", { g <- make_ring(4, directed = TRUE) # The exact algorithm removes the cheapest edge of the single cycle. - fas <- feedback_arc_set(g, weights = c(4, 3, 2, 1), algo = "exact_ip") + fas <- feedback_arc_set(g, weights = c(4, 3, 2, 1), algorithm = "exact_ip") expect_equal(as.numeric(fas), 4) lifecycle::expect_deprecated(res <- feedback_arc_set(g, c(4, 3, 2, 1))) expect_equal(res, feedback_arc_set(g, weights = c(4, 3, 2, 1))) + + # The legacy `algo` name is recovered as `algorithm`. + lifecycle::expect_deprecated( + res_legacy <- feedback_arc_set( + g, + weights = c(4, 3, 2, 1), + algo = "exact_ip" + ) + ) + expect_equal(res_legacy, fas) }) test_that("feedback_vertex_set() tail arguments and legacy positional recovery", { @@ -1411,11 +1421,21 @@ test_that("feedback_vertex_set() tail arguments and legacy positional recovery", g <- make_ring(4, directed = TRUE) # The cheapest vertex of the single cycle is removed. - fvs <- feedback_vertex_set(g, weights = c(4, 3, 2, 1), algo = "exact_ip") + fvs <- feedback_vertex_set(g, weights = c(4, 3, 2, 1), algorithm = "exact_ip") expect_equal(as.numeric(fvs), 4) lifecycle::expect_deprecated(res <- feedback_vertex_set(g, c(4, 3, 2, 1))) expect_equal(res, feedback_vertex_set(g, weights = c(4, 3, 2, 1))) + + # The legacy `algo` name is recovered as `algorithm`. + lifecycle::expect_deprecated( + res_legacy <- feedback_vertex_set( + g, + weights = c(4, 3, 2, 1), + algo = "exact_ip" + ) + ) + expect_equal(res_legacy, fvs) }) test_that("girth() tail arguments and legacy positional recovery", { diff --git a/tools/migrations/centrality.R b/tools/migrations/centrality.R index 4e6c02ac37f..09b62a0fcb4 100644 --- a/tools/migrations/centrality.R +++ b/tools/migrations/centrality.R @@ -88,7 +88,7 @@ migrations <- list( page_rank = list( old = function( graph, - algo, + algo = algorithm, vids, directed, damping, @@ -99,7 +99,7 @@ migrations <- list( new = function( graph, ..., - algo = c("prpack", "arpack"), + algorithm = c("prpack", "arpack"), vids = NULL, directed = TRUE, damping = 0.85, diff --git a/tools/migrations/structural-properties.R b/tools/migrations/structural-properties.R index b7b781964f5..b0581d12904 100644 --- a/tools/migrations/structural-properties.R +++ b/tools/migrations/structural-properties.R @@ -218,23 +218,23 @@ migrations <- list( ), feedback_arc_set = list( - old = function(graph, weights, algo) {}, + old = function(graph, weights, algo = algorithm) {}, new = function( graph, ..., weights = NULL, - algo = c("approx_eades", "exact_ip") + algorithm = c("approx_eades", "exact_ip") ) {}, when = "3.0.0" ), feedback_vertex_set = list( - old = function(graph, weights, algo) {}, + old = function(graph, weights, algo = algorithm) {}, new = function( graph, ..., weights = NULL, - algo = c("exact_ip") + algorithm = c("exact_ip") ) {}, when = "3.0.0" ),