diff --git a/R/centrality.R b/R/centrality.R index 54f9c4bbb00..58112f7bdcb 100644 --- a/R/centrality.R +++ b/R/centrality.R @@ -184,6 +184,8 @@ graph.diversity <- function(graph, weights = NULL, vids = V(graph)) { #' `evcent()` was renamed to [eigen_centrality()] to create a more #' consistent API. #' @inheritParams eigen_centrality +#' @param directed Logical scalar, whether to consider direction of the edges +#' in directed graphs. It is ignored for undirected graphs. #' @keywords internal #' @export evcent <- function( @@ -1312,7 +1314,7 @@ eigen_defaults <- function() { #' computation, see [arpack()] for more about ARPACK in igraph. #' #' @param graph Graph to be analyzed. -#' @param directed Logical scalar, whether to consider direction of the edges +#' @param directed `r lifecycle::badge("deprecated")` Logical scalar, whether to consider direction of the edges #' in directed graphs. It is ignored for undirected graphs. #' @param scale `r lifecycle::badge("deprecated")` Normalization will always take #' place. @@ -1329,6 +1331,17 @@ eigen_defaults <- function() { #' weights spread the centrality better. #' @param options A named list, to override some ARPACK options. See #' [arpack()] for details. +#' @param mode How to consider edge directions in directed graphs. +#' It is ignored for undirected graphs. +#' Possible values: +#' - `"out"` the left eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices pointing to it. This is the standard eigenvector centrality. +#' - `"in"` the right eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices it points to. +#' - `"all"` edge directions are ignored, +#' and the unweighted eigenvector centrality is calculated. #' @return A named list with components: #' \describe{ #' \item{vector}{ @@ -1358,10 +1371,11 @@ eigen_defaults <- function() { #' @cdocs igraph_eigenvector_centrality eigen_centrality <- function( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), weights = NULL, - options = arpack_defaults() + options = arpack_defaults(), + mode = c("out", "in", "all") ) { if (is.function(options)) { lifecycle::deprecate_soft( @@ -1390,10 +1404,33 @@ eigen_centrality <- function( } } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } + eigenvector_centrality_impl( graph = graph, - directed = directed, - scale = TRUE, + mode = mode, weights = weights, options = options ) @@ -1517,9 +1554,7 @@ diversity <- function(graph, weights = NULL, vids = V(graph)) { #' scores are the same as authority scores. #' #' @param graph The input graph. -#' @param scale Logical scalar, whether to scale the result to have a maximum -#' score of one. If no scaling is used then the result vector has unit length -#' in the Euclidean norm. +#' @param scale `r lifecycle::badge("deprecated")` Ignored, always scaled. #' @param weights Optional positive weight vector for calculating weighted #' scores. If the graph has a `weight` edge attribute, then this is used #' by default. Pass `NA` to ignore the weight attribute. This function @@ -1565,15 +1600,22 @@ diversity <- function(graph, weights = NULL, vids = V(graph)) { hits_scores <- function( graph, ..., - scale = TRUE, + scale = deprecated(), weights = NULL, options = arpack_defaults() ) { rlang::check_dots_empty() + if (lifecycle::is_present(scale)) { + lifecycle::deprecate_soft( + "2.1.5", + "hits_scores(scale = )", + details = "The function always behaves as if `scale = TRUE`. + The argument will be removed in the future." + ) + } hub_and_authority_scores_impl( graph = graph, - scale = scale, weights = weights, options = options ) @@ -1609,7 +1651,8 @@ authority_score <- function( weights = weights, options = options ) - scores$hub <- NULL + scores[["hub_vector"]] <- NULL + rlang::set_names(scores, c("vector", "value", "options")) } @@ -1654,7 +1697,7 @@ hub_score <- function( weights = weights, options = options ) - scores$authority <- NULL + scores[["authority_vector"]] <- NULL rlang::set_names(scores, c("vector", "value", "options")) } diff --git a/R/centralization.R b/R/centralization.R index 6fa6678fdc5..e5e9d44aff2 100644 --- a/R/centralization.R +++ b/R/centralization.R @@ -56,6 +56,8 @@ centralization.evcent.tmax <- function( #' `centralization.evcent()` was renamed to [centr_eigen()] to create a more #' consistent API. #' @inheritParams centr_eigen +#' @param directed logical scalar, whether to use directed shortest paths for +#' calculating eigenvector centrality. #' @keywords internal #' @export centralization.evcent <- function( @@ -306,7 +308,7 @@ NULL #' #' # Calculate centralization from pre-computed scores #' deg <- degree(g) -#' tmax <- centr_degree_tmax(g, loops = FALSE) +#' tmax <- centr_degree_tmax(g, loops = "none") #' centralize(deg, tmax) #' #' # The most centralized graph according to eigenvector centrality @@ -385,8 +387,11 @@ centr_degree <- function( #' @param nodes The number of vertices. This is ignored if the graph is given. #' @param mode This is the same as the `mode` argument of `degree()`. Ignored #' if `graph` is given and the graph is undirected. -#' @param loops Logical scalar, whether to consider loops edges when -#' calculating the degree. +#' @param loops Character string, +#' `"none"` (the default) ignores loop edges; +#' `"once"` counts each loop edge only once; +#' `"twice"` counts each loop edge twice in undirected graphs. +#' and once in directed graphs. #' @return Real scalar, the theoretical maximum (unnormalized) graph degree #' centrality score for graphs with given order and other parameters. #' @@ -397,8 +402,8 @@ centr_degree <- function( #' @examples #' # A BA graph is quite centralized #' g <- sample_pa(1000, m = 4) -#' centr_degree(g, normalized = FALSE)$centralization %>% -#' `/`(centr_degree_tmax(g, loops = FALSE)) +#' centr_degree(g, normalized = FALSE)$centralization / +#' centr_degree_tmax(g, loops = "twice") #' centr_degree(g, normalized = TRUE)$centralization centr_degree_tmax <- function( graph = NULL, @@ -412,7 +417,7 @@ centr_degree_tmax <- function( what = "centr_degree_tmax(loops = 'must be explicit')", details = "The default value (currently `FALSE`) will be dropped in the next release. Add an explicit value for the `loops` argument." ) - loops <- FALSE + loops <- "none" } # Argument checks @@ -420,8 +425,6 @@ centr_degree_tmax <- function( nodes <- as.numeric(nodes) - loops <- as.logical(loops) - # Function call res <- centralization_degree_tmax_impl( graph, @@ -611,12 +614,22 @@ centr_clo_tmax <- function( #' See [centralize()] for a summary of graph centralization. #' #' @param graph The input graph. -#' @param directed logical scalar, whether to use directed shortest paths for -#' calculating eigenvector centrality. +#' @param directed `r lifecycle::badge("deprecated")` Use `mode` instead. #' @param scale `r lifecycle::badge("deprecated")` Ignored. Computing #' eigenvector centralization requires normalized eigenvector centrality scores. #' @param options This is passed to [eigen_centrality()], the options #' for the ARPACK eigensolver. +#' @param mode How to consider edge directions in directed graphs. +#' It is ignored for undirected graphs. +#' Possible values: +#' - `"out"` the left eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices pointing to it. This is the standard eigenvector centrality. +#' - `"in"` the right eigenvector of the adjacency matrix is calculated, +#' i.e. the centrality of a vertex is proportional to the sum of centralities +#' of vertices it points to. +#' - `"all"` edge directions are ignored, +#' and the unweighted eigenvector centrality is calculated. #' @param normalized Logical scalar. Whether to normalize the graph level #' centrality score by dividing by the theoretical maximum. #' @return A named list with the following components: @@ -659,10 +672,11 @@ centr_clo_tmax <- function( #' @cdocs igraph_centralization_eigenvector_centrality centr_eigen <- function( graph, - directed = FALSE, + directed = deprecated(), scale = deprecated(), options = arpack_defaults(), - normalized = TRUE + normalized = TRUE, + mode = c("out", "in", "all") ) { if (lifecycle::is_present(scale)) { lifecycle::deprecate_soft( @@ -673,12 +687,35 @@ centr_eigen <- function( ) } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } + centralization_eigenvector_centrality_impl( graph = graph, - directed = directed, options = options, normalized = normalized, - scale = TRUE + mode = mode ) } @@ -693,7 +730,9 @@ centr_eigen <- function( #' @param directed logical scalar, whether to consider edge directions #' during the calculation. Ignored in undirected graphs. #' @param scale `r lifecycle::badge("deprecated")` Ignored. Computing -#' eigenvector centralization requires normalized eigenvector centrality scores. +#' eigenvector centralization requires normalized eigenvector centrality scores. +#' @param mode This is the same as the `mode` argument of +#' `degree()`. #' @return Real scalar, the theoretical maximum (unnormalized) graph #' eigenvector centrality score for graphs with given vertex count and #' other parameters. @@ -712,8 +751,9 @@ centr_eigen <- function( centr_eigen_tmax <- function( graph = NULL, nodes = 0, - directed = FALSE, - scale = deprecated() + directed = deprecated(), + scale = deprecated(), + mode = c("out", "in", "all") ) { if (lifecycle::is_present(scale)) { lifecycle::deprecate_soft( @@ -723,11 +763,33 @@ centr_eigen_tmax <- function( The argument will be removed in the future." ) } + mode <- igraph.match.arg(mode) + + if (lifecycle::is_present(directed)) { + if (directed) { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "out" + } + } else { + lifecycle::deprecate_soft( + "2.2.0", + "eigen_centrality(directed)", + details = "Use the mode argument." + ) + if (!lifecycle::is_present(mode)) { + mode <- "all" + } + } + } centralization_eigenvector_centrality_tmax_impl( graph = graph, nodes = nodes, - directed = directed, - scale = TRUE + mode = mode ) } diff --git a/R/community.R b/R/community.R index af6497a92c6..ba92e3afe7a 100644 --- a/R/community.R +++ b/R/community.R @@ -2345,6 +2345,10 @@ cluster_leading_eigen <- function( #' @param fixed Logical vector denoting which labels are fixed. Of course this #' makes sense only if you provided an initial state, otherwise this element #' will be ignored. Also note that vertices without labels cannot be fixed. +#' @param lpa_variant Which variant of the label propagation algorithm to run. +#' - `"dominance"` (default) check for dominance of all nodes after each iteration. +#' - `"retention"` keep current label if among dominant labels, only check if labels changed. +#' - `"fast"` sample from dominant labels, only check neighbors. #' @return `cluster_label_prop()` returns a #' [communities()] object, please see the [communities()] #' manual page for details. @@ -2373,7 +2377,8 @@ cluster_label_prop <- function( ..., mode = c("out", "in", "all"), initial = NULL, - fixed = NULL + fixed = NULL, + lpa_variant = c("dominance", "retention", "fast") ) { if (...length() > 0) { lifecycle::deprecate_soft( @@ -2395,7 +2400,7 @@ cluster_label_prop <- function( return(inject(cluster_label_prop0(!!!dots))) } - cluster_label_prop0(graph, weights, mode, initial, fixed) + cluster_label_prop0(graph, weights, mode, initial, fixed, lpa_variant) } cluster_label_prop0 <- function( @@ -2403,13 +2408,15 @@ cluster_label_prop0 <- function( weights = NULL, mode = c("out", "in", "all"), initial = NULL, - fixed = NULL + fixed = NULL, + lpa_variant = c("dominance", "retention", "fast") ) { # Argument checks ensure_igraph(graph) # Necessary because evaluated later mode <- igraph.match.arg(mode) + lpa_variant <- igraph.match.arg(lpa_variant) # Function call membership <- community_label_propagation_impl( @@ -2417,8 +2424,10 @@ cluster_label_prop0 <- function( mode = mode, weights = weights, initial = initial, - fixed = fixed + fixed = fixed, + lpa.variant = lpa_variant ) + res <- list() if (igraph_opt("add.vertex.names") && is_named(graph)) { res$names <- V(graph)$name diff --git a/R/console.R b/R/console.R index 882e7d3b6b1..47e748b3402 100644 --- a/R/console.R +++ b/R/console.R @@ -95,18 +95,26 @@ console <- function() { #' @inheritParams .igraph.progress #' @dev .igraph.status <- function(message) { - type <- igraph_opt("verbose") - if (is.logical(type) && type) { - message(message, appendLF = FALSE) - } else { - switch( - type, - "tk" = message(message, appendLF = FALSE), - "tkconsole" = .igraph.progress.tkconsole.message(message, start = TRUE), - stop("Cannot interpret 'verbose' option, this should not happen") - ) - } - 0L + # Catch all errors + tryCatch( + { + type <- igraph::igraph_opt("verbose") + if (is.logical(type) && type) { + message(message, appendLF = FALSE) + } else { + switch( + type, + "tk" = message(message, appendLF = FALSE), + "tkconsole" = .igraph.progress.tkconsole.message( + message, + start = TRUE + ), + stop("Cannot interpret 'verbose' option, this should not happen") + ) + } + }, + error = function(e) {} + ) } #' @importFrom utils txtProgressBar setTxtProgressBar diff --git a/R/games.R b/R/games.R index 0d848daabca..862d416bcbc 100644 --- a/R/games.R +++ b/R/games.R @@ -938,10 +938,6 @@ sample_pa <- function( )) } - if (is.null(out.seq)) { - out.seq <- numeric() - } - algorithm <- igraph.match.arg(algorithm) algorithm1 <- switch( algorithm, @@ -1081,7 +1077,8 @@ sample_gnm <- function(n, m, directed = FALSE, loops = FALSE) { as.numeric(n), as.numeric(m), as.logical(directed), - as.logical(loops) + as.logical(loops), + FALSE ) if (igraph_opt("add.params")) { @@ -3076,7 +3073,7 @@ sample_fitness_pl <- function( multiple = FALSE, finite.size.correction = TRUE ) { - static_power_law_game_impl( + res <- static_power_law_game_impl( no.of.nodes = no.of.nodes, no.of.edges = no.of.edges, exponent.out = exponent.out, @@ -3085,6 +3082,13 @@ sample_fitness_pl <- function( multiple = multiple, finite.size.correction = finite.size.correction ) + + if (igraph_opt("add.params")) { + res$loops <- loops + res$multiple <- multiple + } + + res } diff --git a/R/interface.R b/R/interface.R index 44e0efc67c0..5ae535c82c5 100644 --- a/R/interface.R +++ b/R/interface.R @@ -366,6 +366,13 @@ neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { #' @param mode Whether to query outgoing (\sQuote{out}), incoming #' (\sQuote{in}) edges, or both types (\sQuote{all}). This is #' ignored for undirected graphs. +#' @param loops Specifies how to treat loop edges. +#' `"none"` removes loop edges from the result. +#' `"once"` makes each loop edge appear only once in the result. +#' `"twice"` makes loop edges appear twice in the result +#' if the graph is undirected or `mode` is set to `"all"` +#' (and once otherwise as returning them twice +#' does not make sense for directed graphs). #' @return An edge sequence containing the incident edges of #' the input vertex. #' @@ -376,26 +383,30 @@ neighbors <- function(graph, v, mode = c("out", "in", "all", "total")) { #' g <- make_graph("Zachary") #' incident(g, 1) #' incident(g, 34) -incident <- function(graph, v, mode = c("all", "out", "in", "total")) { +incident <- function( + graph, + v, + mode = c("all", "out", "in", "total"), + loops = c("twice", "none", "once") +) { ensure_igraph(graph) if (is_directed(graph)) { mode <- igraph.match.arg(mode) - mode <- switch(mode, "out" = 1, "in" = 2, "all" = 3, "total" = 3) } else { - mode <- 1 + mode <- "out" } + loops <- igraph.match.arg(loops) v <- as_igraph_vs(graph, v) if (length(v) == 0) { stop("No vertex was specified") } - on.exit(.Call(R_igraph_finalizer)) - res <- .Call(R_igraph_incident, graph, v - 1, as.numeric(mode)) + 1L - if (igraph_opt("return.vs.es")) { - res <- create_es(graph, res) - } - - res + incident_impl( + graph, + vid = v, + mode = mode, + loops = loops + ) } #' Check whether a graph is directed diff --git a/R/make.R b/R/make.R index 7547b44e593..3d607cee373 100644 --- a/R/make.R +++ b/R/make.R @@ -384,7 +384,7 @@ graph.lcf <- function(n, shifts, repeats = 1) { # nocov start lifecycle::deprecate_soft("2.1.0", "graph.lcf()", "graph_from_lcf()") # Use the _impl function - lcf_vector_impl(n = n, shifts = shifts, repeats = repeats) + lcf_impl(n = n, shifts = shifts, repeats = repeats) } # nocov end #' Create a lattice graph @@ -2609,7 +2609,7 @@ full_citation_graph <- function(...) { #' g2 <- make_graph("Franklin") #' isomorphic(g1, g2) #' @export -#' @cdocs igraph_lcf_vector +#' @cdocs igraph_lcf graph_from_lcf <- function( shifts, ..., @@ -2637,7 +2637,7 @@ graph_from_lcf <- function( ) } - lcf_vector_impl(n = n, shifts = shifts, repeats = repeats) + lcf_impl(n = n, shifts = shifts, repeats = repeats) } ## ----------------------------------------------------------------- diff --git a/R/minimum.spanning.tree.R b/R/minimum.spanning.tree.R index 4a47836555d..e5edb8eaf63 100644 --- a/R/minimum.spanning.tree.R +++ b/R/minimum.spanning.tree.R @@ -58,7 +58,7 @@ minimum.spanning.tree <- function( #' distances. #' @param algorithm The algorithm to use for calculation. `unweighted` can #' be used for unweighted graphs, and `prim` runs Prim's algorithm for -#' weighted graphs. If this is `NULL` then igraph will select the +#' weighted graphs. By default igraph will select the #' algorithm automatically: if the graph has an edge attribute called #' `weight` or the `weights` argument is not `NULL` then Prim's #' algorithm is chosen, otherwise the unweighted algorithm is used. @@ -79,29 +79,17 @@ minimum.spanning.tree <- function( #' g <- sample_gnp(100, 3 / 100) #' g_mst <- mst(g) #' -mst <- function(graph, weights = NULL, algorithm = NULL, ...) { +mst <- function( + graph, + weights = NULL, + algorithm = c("automatic", "unweighted", "prim", "kruskal"), + ... +) { ensure_igraph(graph) - - if (is.null(algorithm)) { - if (!is.null(weights) || "weight" %in% edge_attr_names(graph)) { - algorithm <- "prim" - } else { - algorithm <- "unweighted" - } - } - - if (algorithm == "unweighted") { - on.exit(.Call(R_igraph_finalizer)) - .Call(R_igraph_minimum_spanning_tree_unweighted, graph) - } else if (algorithm == "prim") { - if (is.null(weights) && !"weight" %in% edge_attr_names(graph)) { - cli::cli_abort("edges weights must be supplied for Prim's algorithm.") - } else if (is.null(weights)) { - weights <- E(graph)$weight - } - on.exit(.Call(R_igraph_finalizer)) - .Call(R_igraph_minimum_spanning_tree_prim, graph, as.numeric(weights)) - } else { - cli::cli_abort("Invalid {.arg algorithm}.") - } + algorithm <- igraph.match.arg(algorithm) + minimum_spanning_tree_impl( + graph, + weights = weights, + method = algorithm + ) } diff --git a/R/other.R b/R/other.R index a28d2cf8c8c..921d11d57b8 100644 --- a/R/other.R +++ b/R/other.R @@ -224,5 +224,5 @@ igraph.i.spMatrix <- function(M) { #' @export #' @cdocs igraph_convex_hull convex_hull <- function(data) { - convex_hull_2d_impl(data = data) + convex_hull_impl(data = data) } diff --git a/R/paths.R b/R/paths.R index 857bbf8bf04..c7ccd32f42c 100644 --- a/R/paths.R +++ b/R/paths.R @@ -127,7 +127,6 @@ all_simple_paths <- function( mode = mode ) ) - res <- get.all.simple.paths.pp(res) if (igraph_opt("return.vs.es")) { res <- lapply(res, unsafe_create_vs, graph = graph, verts = V(graph)) @@ -276,7 +275,7 @@ max_cardinality <- function(graph) { #' eccentricity(g) #' @family paths #' @export -#' @cdocs igraph_eccentricity_dijkstra +#' @cdocs igraph_eccentricity eccentricity <- function( graph, vids = V(graph), @@ -300,7 +299,7 @@ eccentricity <- function( } } - eccentricity_dijkstra_impl(graph, vids = vids, weights = weights, mode = mode) + eccentricity_impl(graph, vids = vids, weights = weights, mode = mode) } @@ -331,7 +330,7 @@ eccentricity <- function( #' radius(g) #' @family paths #' @export -#' @cdocs igraph_radius_dijkstra +#' @cdocs igraph_radius radius <- function( graph, ..., @@ -354,7 +353,7 @@ radius <- function( } } - radius_dijkstra_impl(graph, weights = weights, mode = mode) + radius_impl(graph, weights = weights, mode = mode) } #' Central vertices of a graph @@ -383,14 +382,14 @@ radius <- function( #' graph_center(ring) #' #' @export -#' @cdocs igraph_graph_center_dijkstra +#' @cdocs igraph_graph_center graph_center <- function( graph, ..., weights = NULL, mode = c("all", "out", "in", "total") ) { - graph_center_dijkstra_impl( + graph_center_impl( graph = graph, ..., weights = weights, diff --git a/R/pp.R b/R/pp.R deleted file mode 100644 index d452b97fa12..00000000000 --- a/R/pp.R +++ /dev/null @@ -1,24 +0,0 @@ -# IGraph R package -# Copyright (C) 2014 Gabor Csardi -# 334 Harvard street, Cambridge, MA 02139 USA -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA -# -################################################################### - -get.all.simple.paths.pp <- function(vect) { - .Call(R_igraph_get_all_simple_paths_pp, vect) -} diff --git a/R/rewire.R b/R/rewire.R index 44354e904b2..86783aafe04 100644 --- a/R/rewire.R +++ b/R/rewire.R @@ -41,7 +41,7 @@ rewire <- function(graph, with) { if (!is(with, "igraph_rewiring_method")) { cli::cli_abort( - "{.arg with} must be an igraph rewiring method, + "{.arg with} must be an igraph rewiring method, not {.obj_type_friendly {with}}." ) } diff --git a/R/similarity.R b/R/similarity.R index b86fd2f9c3e..0feaa99ee46 100644 --- a/R/similarity.R +++ b/R/similarity.R @@ -26,7 +26,11 @@ #' 25(3):211-230, 2003. #' #' @param graph The input graph. -#' @param vids The vertex ids for which the similarity is calculated. +#' @param vids lifecycle::badge("deprecated") +#' @param vids_from The vertex IDs of the first set of vertices of the pairs +#' for which the calculation will be done. +#' @param vids_to The vertex IDs of the second set of vertices of the pairs +#' for which the calculation will be done. #' @param mode The type of neighboring vertices to use for the calculation, #' possible values: \sQuote{`out`}, \sQuote{`in`}, #' \sQuote{`all`}. @@ -52,7 +56,7 @@ #' similarity(g, method = "jaccard") similarity <- function( graph, - vids = V(graph), + vids = deprecated(), mode = c( "all", "out", @@ -64,16 +68,47 @@ similarity <- function( "jaccard", "dice", "invlogweighted" - ) + ), + vids_from = V(graph), + vids_to = vids_from ) { - method <- igraph.match.arg(method) - if (method == "jaccard") { - similarity_jaccard_impl(graph, vids, mode, loops) - } else if (method == "dice") { - similarity_dice_impl(graph, vids, mode, loops) - } else if (method == "invlogweighted") { - similarity_inverse_log_weighted_impl(graph, vids, mode) + if (lifecycle::is_present(vids)) { + lifecycle::deprecate_soft( + "similarity(vids =)", + I("similarity(vids_from =, vids_to =)"), + when = "3.0.0" + ) + if (!lifecycle::is_present(vids_from)) { + vids_from <- vids + vids_to <- vids_from + } } + + method <- igraph.match.arg(method) + + switch( + method, + jaccard = similarity_jaccard_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode, + loops = loops + ), + dice = similarity_dice_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode, + loops = loops + ), + invlogweighted = similarity_inverse_log_weighted_impl( + graph, + vit.from = vids_from, + vit.to = vids_to, + mode = mode + ) + ) } #' Similarity measures of two vertices (Jaccard) @@ -83,6 +118,7 @@ similarity <- function( #' #' Please use [similarity()] with `method = "jaccard"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.jaccard <- function( @@ -114,6 +150,7 @@ similarity.jaccard <- function( #' #' Please use [similarity()] with `method = "dice"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.dice <- function( @@ -145,6 +182,7 @@ similarity.dice <- function( #' #' Please use [similarity()] with `method = "invlogweighted"` instead. #' @inheritParams similarity +#' @param vids The vertex ids for which the similarity is calculated. #' @keywords internal #' @export similarity.invlogweighted <- function( diff --git a/R/simple.R b/R/simple.R index 78132bd4dc5..f05142ff5a5 100644 --- a/R/simple.R +++ b/R/simple.R @@ -71,6 +71,11 @@ is.simple <- function(graph) { #' `remove.multiple=TRUE`. In this case many edges might be mapped to a #' single one in the new graph, and their attributes are combined. Please see #' [attribute.combination()] for details on this. +#' @param directed Boolean.Whether to consider the directions of edges. +#' The default, `TRUE` means that edge directions will be considered. +#' `FALSE` means that edge directions will be ignored and a directed graph +#' with at least one mutual edge pair will be considered non-simple. +#' Ignored for undirected graphs. #' @return a new graph object with the edges deleted. #' @author Gabor Csardi \email{csardi.gabor@@gmail.com} #' @seealso [which_loop()], [which_multiple()] and @@ -84,6 +89,11 @@ is.simple <- function(graph) { #' is_simple(simplify(g, remove.loops = FALSE)) #' is_simple(simplify(g, remove.multiple = FALSE)) #' is_simple(simplify(g)) +#' +#' # directed argument +#' g <- graph_from_literal(1 +-+ 2 -+ 3) +#' is_simple(g) +#' is_simple(g, directed = FALSE) #' @family simple #' @family functions for manipulating graph structure #' @family isomorphism diff --git a/R/structural-properties.R b/R/structural-properties.R index b99ba9e37f5..21f26dd2e48 100644 --- a/R/structural-properties.R +++ b/R/structural-properties.R @@ -758,23 +758,13 @@ diameter <- function( ) { ensure_igraph(graph) - if (is.null(weights) && "weight" %in% edge_attr_names(graph)) { - weights <- E(graph)$weight - } - if (!is.null(weights) && any(!is.na(weights))) { - weights <- as.numeric(weights) - } else { - weights <- NULL - } - - on.exit(.Call(R_igraph_finalizer)) - .Call( - R_igraph_diameter, + res <- diameter_impl( graph, - as.logical(directed), - as.logical(unconnected), - weights + weights = weights, + directed = directed, + unconnected = unconnected ) + res$res } #' @rdname diameter @@ -851,9 +841,29 @@ farthest_vertices <- function( #' @export #' @rdname distances -#' @cdocs igraph_average_path_length_dijkstra -mean_distance <- average_path_length_dijkstra_impl +#' @cdocs igraph_average_path_length +mean_distance <- function( + graph, + weights = NULL, + directed = TRUE, + unconnected = TRUE, + details = FALSE +) { + res <- average_path_length_impl( + graph, + weights = weights, + directed = directed, + unconn = unconnected, + details = details + ) + if (details) { + res$unconnected <- res$unconn_pair + res$unconn_pair <- NULL + } + + res +} #' Degree and degree distribution of the vertices #' @@ -866,7 +876,11 @@ mean_distance <- average_path_length_dijkstra_impl #' @param mode Character string, \dQuote{out} for out-degree, \dQuote{in} for #' in-degree or \dQuote{total} for the sum of the two. For undirected graphs #' this argument is ignored. \dQuote{all} is a synonym of \dQuote{total}. -#' @param loops Logical; whether the loop edges are also counted. +#' @param loops Character string, +#' `"none"` ignores loop edges; +#' `"once"` counts each loop edge only once; +#' `"twice"` (the default) counts each loop edge twice in undirected graphs +#' and once in directed graphs. #' @param normalized Logical scalar, whether to normalize the degree. If #' `TRUE` then the result is divided by \eqn{n-1}, where \eqn{n} is the #' number of vertices in the graph. @@ -897,19 +911,33 @@ degree <- function( graph, v = V(graph), mode = c("all", "out", "in", "total"), - loops = TRUE, + loops = c("twice", "none", "once"), normalized = FALSE ) { ensure_igraph(graph) - v <- as_igraph_vs(graph, v) mode <- igraph.match.arg(mode) + if (is.logical(loops)) { + lifecycle::deprecate_soft( + "2.2.0", + "degree(loops = 'must be a character string')" + ) + if (loops) { + loops <- "twice" + } else { + loops <- "none" + } + } + + loops <- igraph.match.arg(loops) + res <- degree_impl( graph, vids = v, mode = mode, loops = loops ) + if (normalized) { res <- res / (vcount(graph) - 1) } @@ -922,8 +950,36 @@ degree <- function( #' @rdname degree #' @export #' @cdocs igraph_maxdegree -max_degree <- maxdegree_impl +max_degree <- function( + graph, + ..., + v = V(graph), + mode = c("all", "out", "in", "total"), + loops = c("twice", "none", "once") +) { + ensure_igraph(graph) + mode <- igraph.match.arg(mode) + + if (is.logical(loops)) { + lifecycle::deprecate_soft( + "2.2.0", + "max_degree(loops = 'must be a character string')" + ) + if (loops) { + loops <- "twice" + } else { + loops <- "none" + } + } + loops <- igraph.match.arg(loops) + maxdegree_impl( + graph, + v = v, + mode = mode, + loops = loops + ) +} #' @rdname degree #' @param cumulative Logical; whether the cumulative degree distribution is to #' be calculated. diff --git a/R/topology.R b/R/topology.R index 14bc4bd81f3..9012a65fa80 100644 --- a/R/topology.R +++ b/R/topology.R @@ -1122,7 +1122,7 @@ canonical_permutation <- function( colors = NULL, sh = c("fm", "f", "fs", "fl", "flm", "fsm") ) { - canonical_permutation_impl( + canonical_permutation_bliss_impl( graph = graph, colors = if (missing(colors)) missing_arg() else colors, sh = sh @@ -1274,7 +1274,7 @@ count_automorphisms <- function( colors = NULL, sh = c("fm", "f", "fs", "fl", "flm", "fsm") ) { - count_automorphisms_impl( + count_automorphisms_bliss_impl( graph = graph, colors = if (missing(colors)) missing_arg() else colors, sh = sh @@ -1305,24 +1305,6 @@ count_automorphisms <- function( #' vertices, or, if there is no such vertex attribute, it simply assumes that #' all vertices have the same color. Pass NULL explicitly if the graph has a #' `color` vertex attribute but you do not want to use it. -#' @param sh The splitting heuristics for the BLISS algorithm. Possible values -#' are: -#' \sQuote{`f`}: -#' first non-singleton cell, -#' \sQuote{`fl`}: -#' first largest non-singleton cell, -#' \sQuote{`fs`}: -#' first smallest non-singleton cell, -#' \sQuote{`fm`}: -#' first maximally non-trivially connected -#' non-singleton cell, -#' \sQuote{`flm`}: -#' first largest maximally -#' non-trivially connected non-singleton cell, -#' \sQuote{`fsm`}: -#' first smallest maximally non-trivially connected non-singleton cell. -#' @param details Specifies whether to provide additional details about the -#' BLISS internals in the result. #' @return When `details` is `FALSE`, a list of vertex permutations #' that form a generating set of the automorphism group of the input graph. #' When `details` is `TRUE`, a named list with two members: diff --git a/R/trees.R b/R/trees.R index 49e0e3d45f7..3852dac3e8c 100644 --- a/R/trees.R +++ b/R/trees.R @@ -145,7 +145,7 @@ to_prufer <- function(graph) { #' @param graph The input graph to sample from. Edge directions are ignored if #' the graph is directed. #' @param vid When the graph is disconnected, this argument specifies how to -#' handle the situation. When the argument is zero (the default), the sampling +#' handle the situation. When the argument is `NULL` (the default), the sampling #' will be performed component-wise, and the result will be a spanning forest. #' When the argument contains a vertex ID, only the component containing the #' given vertex will be processed, and the result will be a spanning tree of the @@ -164,4 +164,7 @@ to_prufer <- function(graph) { #' @family trees #' @export #' @cdocs igraph_random_spanning_tree -sample_spanning_tree <- random_spanning_tree_impl +sample_spanning_tree <- function(graph, vid = NULL) { + vid <- vid %||% 0 + random_spanning_tree_impl(graph, vid) +} diff --git a/R/triangles.R b/R/triangles.R index 8321e044795..1745ab62254 100644 --- a/R/triangles.R +++ b/R/triangles.R @@ -97,7 +97,7 @@ triangles <- function(graph) { #' @export #' @rdname count_triangles -#' @cdocs igraph_adjacent_triangles +#' @cdocs igraph_count_adjacent_triangles count_triangles <- function(graph, vids = V(graph)) { count_adjacent_triangles_impl( graph = graph, diff --git a/src/rinterface_extra.c b/src/rinterface_extra.c index 5e08a4021b1..1f6d7763ffb 100644 --- a/src/rinterface_extra.c +++ b/src/rinterface_extra.c @@ -21,6 +21,8 @@ */ +#include "igraph_random.h" +#include "igraph_sampling.h" #include "rinterface.h" #include "rrandom.h" @@ -43,6 +45,11 @@ #include #endif + +#define RNG_BEGIN() GetRNGstate() +#define RNG_END() PutRNGstate() + + enum igraph_t_idx { igraph_t_idx_n = 0, igraph_t_idx_directed = 1, @@ -132,6 +139,11 @@ void igraph_vector_int_list_destroy_pv(void *pv_ptr) igraph_vector_int_list_destroy((igraph_vector_int_list_t*) pv_ptr); } +void igraph_es_destroy_pv(void* pv_ptr) +{ + igraph_es_destroy((igraph_es_t*) pv_ptr); +} + igraph_error_t R_get_int_scalar(SEXP sexp, R_xlen_t index, igraph_integer_t *res) { if (Rf_xlength(sexp) <= index) @@ -377,7 +389,7 @@ void R_igraph_attribute_clean_preserve_list(void) { } } -igraph_error_t R_igraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *attr) { +igraph_error_t R_igraph_attribute_init(igraph_t *graph, const igraph_attribute_record_list_t *attr) { SEXP result, names, gal; int px = 0; @@ -404,12 +416,12 @@ igraph_error_t R_igraph_attribute_init(igraph_t *graph, igraph_vector_ptr_t *att graph->attr=result; /* Add graph attributes */ - igraph_integer_t attrno= attr==NULL ? 0 : igraph_vector_ptr_size(attr); + igraph_integer_t attrno= attr==NULL ? 0 : igraph_attribute_record_list_size(attr); SET_VECTOR_ELT(result, 1, NEW_LIST(attrno)); gal=VECTOR_ELT(result, 1); PROTECT(names=NEW_CHARACTER(attrno)); px++; for (igraph_integer_t i=0; itype) { case IGRAPH_ATTRIBUTE_NUMERIC: - vec=(igraph_vector_t*) rec->value; + vec = rec->value.as_vector; if (igraph_vector_size(vec) > 0) { SET_VECTOR_ELT(gal, i, NEW_NUMERIC(1)); REAL(VECTOR_ELT(gal, i))[0]=VECTOR(*vec)[0]; } break; case IGRAPH_ATTRIBUTE_BOOLEAN: - log=(igraph_vector_bool_t*) rec->value; + log = rec->value.as_vector_bool; if (igraph_vector_bool_size(log) > 0) { SET_VECTOR_ELT(gal, i, NEW_LOGICAL(1)); LOGICAL(VECTOR_ELT(gal, i))[0]=VECTOR(*log)[0]; } break; case IGRAPH_ATTRIBUTE_STRING: - strvec=(igraph_strvector_t*) rec->value; + strvec = rec->value.as_strvector; if (igraph_strvector_size(strvec) > 0) { SET_VECTOR_ELT(gal, i, NEW_CHARACTER(1)); SET_STRING_ELT(VECTOR_ELT(gal,i), 0, Rf_mkChar(igraph_strvector_get(strvec, 0))); @@ -487,22 +499,22 @@ igraph_error_t R_igraph_attribute_copy(igraph_t *to, const igraph_t *from, return 0; } -SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, +SEXP R_igraph_attribute_add_vertices_append1(const igraph_attribute_record_list_t *nattr, int j, int nv) { SEXP app = R_NilValue; - igraph_attribute_record_t *tmprec=VECTOR(*nattr)[j-1]; + igraph_attribute_record_t *tmprec=igraph_attribute_record_list_get_ptr(nattr, j-1); igraph_integer_t len = 0; switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - len = igraph_vector_size(tmprec->value); + len = igraph_vector_size(tmprec->value.as_vector); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - len = igraph_vector_bool_size(tmprec->value); + len = igraph_vector_bool_size(tmprec->value.as_vector_bool); break; case IGRAPH_ATTRIBUTE_STRING: - len = igraph_strvector_size(tmprec->value); + len = igraph_strvector_size(tmprec->value.as_strvector); break; case IGRAPH_ATTRIBUTE_OBJECT: igraph_error("R objects not implemented yet", __FILE__, __LINE__, @@ -525,13 +537,13 @@ SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: PROTECT(app=NEW_NUMERIC(nv)); - igraph_vector_copy_to(tmprec->value, REAL(app)); + igraph_vector_copy_to(tmprec->value.as_vector, REAL(app)); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value.as_vector_bool)); break; default: /* IGRAPH_ATTRIBUTE_STRING */ - PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value.as_strvector)); break; } @@ -540,7 +552,7 @@ SEXP R_igraph_attribute_add_vertices_append1(igraph_vector_ptr_t *nattr, } void R_igraph_attribute_add_vertices_append(SEXP val, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP names; igraph_integer_t valno, nattrno; SEXP rep = R_NilValue; @@ -551,7 +563,7 @@ void R_igraph_attribute_add_vertices_append(SEXP val, igraph_integer_t nv, if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } for (igraph_integer_t i=0; iname); } if (l) { @@ -596,7 +608,7 @@ SEXP R_igraph_attribute_add_vertices_dup(SEXP attr) { } igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t nv, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP attr=graph->attr; SEXP val, rep=0, names, newnames; igraph_vector_int_t news; @@ -612,7 +624,7 @@ igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } origlen=igraph_vcount(graph)-nv; @@ -621,7 +633,7 @@ igraph_error_t R_igraph_attribute_add_vertices(igraph_t *graph, igraph_integer_t if (igraph_vector_int_init(&news, 0)) Rf_error("Out of memory"); IGRAPH_FINALLY_PV(igraph_vector_int_destroy, &news); for (igraph_integer_t i=0; iname; igraph_bool_t l=0; for (igraph_integer_t j=0; !l && jname)); } @@ -827,22 +839,22 @@ SEXP R_igraph_attribute_add_edges_dup(SEXP attr) { return newattr; } -SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_integer_t j, +SEXP R_igraph_attribute_add_edges_append1(const igraph_attribute_record_list_t *nattr, igraph_integer_t j, igraph_integer_t ne) { SEXP app = R_NilValue; - igraph_attribute_record_t *tmprec=VECTOR(*nattr)[j-1]; + igraph_attribute_record_t *tmprec=igraph_attribute_record_list_get_ptr(nattr, j-1); igraph_integer_t len = 0; switch(tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: - len = igraph_vector_size(tmprec->value); + len = igraph_vector_size(tmprec->value.as_vector); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - len = igraph_vector_bool_size(tmprec->value); + len = igraph_vector_bool_size(tmprec->value.as_vector_bool); break; case IGRAPH_ATTRIBUTE_STRING: - len = igraph_strvector_size(tmprec->value); + len = igraph_strvector_size(tmprec->value.as_strvector); break; case IGRAPH_ATTRIBUTE_OBJECT: igraph_error("R objects not implemented yet", __FILE__, __LINE__, @@ -865,13 +877,15 @@ SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_int switch (tmprec->type) { case IGRAPH_ATTRIBUTE_NUMERIC: PROTECT(app=NEW_NUMERIC(ne)); - igraph_vector_copy_to(tmprec->value, REAL(app)); + igraph_vector_copy_to(tmprec->value.as_vector, REAL(app)); break; case IGRAPH_ATTRIBUTE_BOOLEAN: - PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value)); + PROTECT(app=R_igraph_vector_bool_to_SEXP(tmprec->value.as_vector_bool)); break; - default: /* IGRAPH_ATTRIBUTE_STRING */ - PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value)); + case IGRAPH_ATTRIBUTE_STRING: + PROTECT(app=R_igraph_strvector_to_SEXP(tmprec->value.as_strvector)); + break; + default: break; } @@ -881,7 +895,7 @@ SEXP R_igraph_attribute_add_edges_append1(igraph_vector_ptr_t *nattr, igraph_int void R_igraph_attribute_add_edges_append(SEXP eal, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP names; igraph_integer_t ealno; igraph_integer_t ne=igraph_vector_int_size(edges)/2, nattrno; @@ -893,7 +907,7 @@ void R_igraph_attribute_add_edges_append(SEXP eal, if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } for (igraph_integer_t i=0; iname); } if (l) { @@ -930,7 +944,7 @@ void R_igraph_attribute_add_edges_append(SEXP eal, } igraph_error_t R_igraph_attribute_add_edges(igraph_t *graph, const igraph_vector_int_t *edges, - igraph_vector_ptr_t *nattr) { + const igraph_attribute_record_list_t *nattr) { SEXP attr=graph->attr; SEXP eal, names, newnames; igraph_vector_int_t news; @@ -950,14 +964,14 @@ igraph_error_t R_igraph_attribute_add_edges(igraph_t *graph, const igraph_vector if (nattr==NULL) { nattrno=0; } else { - nattrno=igraph_vector_ptr_size(nattr); + nattrno=igraph_attribute_record_list_size(nattr); } origlen=igraph_ecount(graph)-ne; /* First add the new attributes, if any */ newattrs=0; for (igraph_integer_t i=0; iname; igraph_bool_t l=0; for (igraph_integer_t j=0; !l && jname)); } @@ -1905,7 +1919,7 @@ igraph_error_t R_igraph_attribute_combine_vertices(const igraph_t *graph, /* Create the TODO list first */ PROTECT(names=GET_NAMES(val)); px++; - TODO=igraph_Calloc(valno, igraph_integer_t); + TODO=IGRAPH_CALLOC(valno, igraph_integer_t); if (!TODO) { UNPROTECT(px); IGRAPH_ERROR("Cannot combine edge attributes", @@ -2079,7 +2093,7 @@ igraph_error_t R_igraph_attribute_combine_edges(const igraph_t *graph, IGRAPH_ENOMEM); } IGRAPH_FINALLY(igraph_free, TODO); - funcs=igraph_Calloc(ealno, igraph_function_pointer_t); + funcs=IGRAPH_CALLOC(ealno, igraph_function_pointer_t); if (!funcs) { UNPROTECT(px); IGRAPH_ERROR("Cannot combine edge attributes", @@ -2352,7 +2366,7 @@ void checkInterruptFn(void *dummy) { R_CheckUserInterrupt(); } -igraph_error_t R_igraph_interrupt_handler(void *data) { +igraph_bool_t R_igraph_interrupt_handler(void) { /* We need to call R_CheckUserInterrupt() regularly to enable interruptions. * However, if an interruption is pending, R_CheckUserInterrupt() will * longjmp back to the top level so we cannot clean up ourselves by calling @@ -2368,9 +2382,9 @@ igraph_error_t R_igraph_interrupt_handler(void *data) { */ if (R_ToplevelExec(checkInterruptFn, NULL) == FALSE) { IGRAPH_FINALLY_FREE(); - return IGRAPH_INTERRUPTED; + return true; } - return IGRAPH_SUCCESS; + return false; } igraph_error_t R_igraph_progress_handler(const char *message, double percent, @@ -2394,17 +2408,15 @@ igraph_error_t R_igraph_progress_handler(const char *message, double percent, } igraph_error_t R_igraph_status_handler(const char *message, void *data) { - SEXP l1 = PROTECT(Rf_install("getNamespace")); - SEXP l2 = PROTECT(Rf_ScalarString(PROTECT(Rf_mkChar("igraph")))); - SEXP l3 = PROTECT(Rf_lang2(l1, l2)); - SEXP rho = PROTECT(Rf_eval(l3, R_BaseEnv)); - - SEXP l4 = PROTECT(Rf_install(".igraph.status")); + SEXP l1 = PROTECT(Rf_install(":::")); + SEXP l2 = PROTECT(Rf_install("igraph")); + SEXP l3 = PROTECT(Rf_install(".igraph.status")); + SEXP l4 = PROTECT(Rf_lang3(l1, l2, l3)); SEXP l5 = PROTECT(Rf_ScalarString(PROTECT(Rf_mkChar(message)))); SEXP l6 = PROTECT(Rf_lang2(l4, l5)); - PROTECT(Rf_eval(l6, rho)); + PROTECT(Rf_eval(l6, R_BaseEnv)); - UNPROTECT(10); + UNPROTECT(8); return 0; } @@ -2660,7 +2672,7 @@ SEXP R_igraph_matrix_to_SEXP(const igraph_matrix_t *m) { } PROTECT(result=NEW_NUMERIC(igraph_matrix_size(m))); - igraph_matrix_copy_to(m, REAL(result)); + igraph_matrix_copy_to(m, REAL(result), IGRAPH_COLUMN_MAJOR); PROTECT(dim=NEW_INTEGER(2)); INTEGER(dim)[0] = (int) nrow; INTEGER(dim)[1] = (int) ncol; @@ -2727,7 +2739,7 @@ SEXP R_igraph_matrix_complex_to_SEXP(const igraph_matrix_complex_t *m) { } PROTECT(result=NEW_COMPLEX(igraph_matrix_complex_size(m))); - igraph_matrix_complex_copy_to(m, (igraph_complex_t*) COMPLEX(result)); + igraph_matrix_complex_copy_to(m, (igraph_complex_t*) COMPLEX(result), IGRAPH_COLUMN_MAJOR); PROTECT(dim=NEW_INTEGER(2)); INTEGER(dim)[0] = (int) nrow; INTEGER(dim)[1] = (int) ncol; @@ -3257,7 +3269,7 @@ SEXP R_igraph_sparsemat_to_SEXP_cc(const igraph_sparsemat_t *sp) { igraph_vector_t x; R_SEXP_to_vector_int_copy(VECTOR_ELT(res, 2), &p); R_SEXP_to_vector_int_copy(VECTOR_ELT(res, 3), &i); - igraph_vector_view(&x, REAL(VECTOR_ELT(res, 4)), nz); + x = igraph_vector_view(REAL(VECTOR_ELT(res, 4)), nz); igraph_sparsemat_getelements_sorted(sp, &i, &p, &x); } @@ -3323,7 +3335,7 @@ void R_igraph_SEXP_to_vector_list(SEXP vectorlist, igraph_vector_list_t *list) { for (igraph_integer_t i=0; istor_begin=(char**) R_alloc((size_t) length, sizeof(char*)); + sv->stor_begin=(const char**) R_alloc((size_t) length, sizeof(char*)); sv->stor_end=sv->stor_begin+length; sv->end=sv->stor_end; for (igraph_integer_t i=0; i3 1->2 2->3 - -# transitive_closure_dag_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # transitive_closure_impl basic Code @@ -4045,7 +3706,7 @@ x Condition Error in `bipartite_game_gnp_impl()`: - ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite G(n,p) model. Invalid value # bipartite_game_gnm_impl basic @@ -4081,7 +3742,7 @@ x Condition Error in `bipartite_game_gnm_impl()`: - ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite graph. Invalid value + ! At vendor/cigraph/src/misc/bipartite.c:xx : Invalid number of vertices for bipartite G(n,m) model. Invalid value # get_laplacian_impl basic @@ -5120,7 +4781,7 @@ --- Code - similarity_dice_impl(g, vids = 1:2, mode = "in", loops = TRUE) + similarity_dice_impl(g, vit.from = 1:2, mode = "in", loops = TRUE) Output [,1] [,2] [1,] 1.0 0.8 @@ -5219,7 +4880,7 @@ --- Code - similarity_jaccard_impl(g, vids = 1:2, mode = "in", loops = TRUE) + similarity_jaccard_impl(g, vit.from = 1:2, mode = "in", loops = TRUE) Output [,1] [,2] [1,] 1.0000000 0.6666667 @@ -5371,7 +5032,7 @@ # community_label_propagation_impl basic Code - community_label_propagation_impl(g) + community_label_propagation_impl(g, lpa.variant = "dominance") Output [1] 0 0 0 @@ -5379,7 +5040,7 @@ Code community_label_propagation_impl(g, mode = "in", weights = c(1, 2), initial = 1: - 3, fixed = c(TRUE, FALSE, TRUE)) + 3, fixed = c(TRUE, FALSE, TRUE), lpa.variant = "retention") Output [1] 0 1 1 @@ -5466,7 +5127,7 @@ # community_leiden_impl basic Code - community_leiden_impl(g, weights = c(1, 2), vertex.weights = c(1, 2, 3), + community_leiden_impl(g, weights = c(1, 2), vertex.out.weights = c(1, 2, 3), resolution = 0.5, beta = 0.1, start = TRUE, n.iterations = 1, membership = 1:3) Output $membership @@ -5524,7 +5185,7 @@ --- Code - community_infomap_impl(g, e.weights = c(1, 2), v.weights = c(1, 2, 3), + community_infomap_impl(g, edge.weights = c(1, 2), vertex.weights = c(1, 2, 3), nb.trials = 2) Output $membership @@ -6075,7 +5736,7 @@ triad_census_impl(g) Condition Warning in `triad_census_impl()`: - At vendor/cigraph/src/misc/motifs.c:1157 : Triad census called on an undirected graph. All connections will be treated as mutual. + At vendor/cigraph/src/misc/motifs.c:1170 : Triad census called on an undirected graph. All connections will be treated as mutual. Output [1] 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 @@ -7188,7 +6849,7 @@ --- Code - canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl") + canonical_permutation_impl(g, colors = c(1, 2, 3)) Output $labeling [1] 1 2 3 @@ -7384,7 +7045,7 @@ --- Code - count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl") + count_automorphisms_impl(g, colors = c(1, 2, 3)) Output $nof_nodes [1] 1 @@ -7426,7 +7087,7 @@ --- Code - automorphism_group_impl(g, colors = c(1, 2, 3), sh = "fl", details = TRUE) + automorphism_group_impl(g, colors = c(1, 2, 3)) Output $generators list() @@ -9452,30 +9113,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# convex_hull_2d_impl basic - - Code - convex_hull_2d_impl(matrix(1:6, ncol = 2)) - Output - $resverts - [1] 1 3 - - $rescoords - [,1] [,2] - [1,] 1 4 - [2,] 3 6 - - -# convex_hull_2d_impl errors - - Code - x - Condition - Warning in `convex_hull_2d_impl()`: - NAs introduced by coercion - Error in `convex_hull_2d_impl()`: - ! REAL() can only be applied to a 'numeric', not a 'character' - # dim_select_impl basic Code @@ -9941,99 +9578,6 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# deterministic_optimal_imitation_impl basic - - Code - deterministic_optimal_imitation_impl(g, 1, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 2 2 3 - ---- - - Code - deterministic_optimal_imitation_impl(g, 1, optimality = "minimum", quantities = c( - 1, 2, 3), strategies = c(1, 2, 3), mode = "in") - Output - [1] 1 2 3 - -# deterministic_optimal_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# moran_process_impl basic - - Code - moran_process_impl(g, weights = c(1, 1), quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - $quantities - [1] 1 3 3 - - $strategies - [1] 1 3 3 - - -# moran_process_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# roulette_wheel_imitation_impl basic - - Code - roulette_wheel_imitation_impl(g, 1, TRUE, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 1 2 3 - ---- - - Code - roulette_wheel_imitation_impl(g, 1, FALSE, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - [1] 3 2 3 - -# roulette_wheel_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - -# stochastic_imitation_impl basic - - Code - stochastic_imitation_impl(g, 1, algo = 1, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3)) - Output - [1] 1 2 3 - ---- - - Code - stochastic_imitation_impl(g, 1, algo = 2, quantities = c(1, 2, 3), strategies = c( - 1, 2, 3), mode = "in") - Output - [1] 1 2 3 - -# stochastic_imitation_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # invalidate_cache_impl basic Code @@ -10051,36 +9595,12 @@ Error in `ensure_igraph()`: ! Must provide a graph object (provided `NULL`). -# vertex_path_from_edge_path_impl basic - - Code - vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1, 2)) - Output - + 3/3 vertices: - [1] 1 2 3 - ---- - - Code - vertex_path_from_edge_path_impl(g, start = 1, edge.path = c(1), mode = "in") - Output - + 2/3 vertices: - [1] 1 2 - -# vertex_path_from_edge_path_impl errors - - Code - x - Condition - Error in `ensure_igraph()`: - ! Must provide a graph object (provided `NULL`). - # version_impl basic Code version_impl_clean() Output - [1] "0.10.17" + [1] "1.0.0" # version_impl errors diff --git a/tests/testthat/_snaps/centrality.md b/tests/testthat/_snaps/centrality.md index 62a6c46264f..febfd202987 100644 --- a/tests/testthat/_snaps/centrality.md +++ b/tests/testthat/_snaps/centrality.md @@ -10,6 +10,9 @@ arpack_defaults was deprecated in igraph 1.6.0. i Please use `arpack_defaults()` instead. i So the function arpack_defaults(), not an object called arpack_defaults. + Warning: + The `scale` argument of `hits_scores()` is deprecated as of igraph 2.1.5. + i The function always behaves as if `scale = TRUE`. The argument will be removed in the future. # `hub_score()` works @@ -23,6 +26,9 @@ arpack_defaults was deprecated in igraph 1.6.0. i Please use `arpack_defaults()` instead. i So the function arpack_defaults(), not an object called arpack_defaults. + Warning: + The `scale` argument of `hits_scores()` is deprecated as of igraph 2.1.5. + i The function always behaves as if `scale = TRUE`. The argument will be removed in the future. # eigen_centrality() deprecated scale argument @@ -48,7 +54,7 @@ arpack(f, options = list(nev = 2, ncv = 4), sym = TRUE) Condition Error in `arpack()`: - ! At vendor/cigraph/src/linalg/arpack.c:1102 : ARPACK error, N must be positive + ! At vendor/cigraph/src/linalg/arpack.c:1025 : N must be positive, ARPACK error --- diff --git a/tests/testthat/_snaps/incidence.md b/tests/testthat/_snaps/incidence.md index dbb1ba9a91e..541b8034a6d 100644 --- a/tests/testthat/_snaps/incidence.md +++ b/tests/testthat/_snaps/incidence.md @@ -6,7 +6,7 @@ IGRAPH UN-B 8 7 -- + attr: type (v/l), name (v/c) + edges (vertex names): - [1] A--c A--d B--b B--c B--e C--b C--d + [1] B--b C--b A--c B--c A--d C--d B--e --- @@ -26,7 +26,7 @@ IGRAPH UN-B 8 10 -- + attr: type (v/l), name (v/c) + edges (vertex names): - [1] A--c A--d A--d A--e B--b B--e C--b C--c C--c C--e + [1] B--b C--b A--c C--c C--c A--d A--d A--e B--e C--e # graph_from_biadjacency_matrix() works -- sparse diff --git a/tests/testthat/_snaps/interface.md b/tests/testthat/_snaps/interface.md index d394032f7a6..1c13eac2c5e 100644 --- a/tests/testthat/_snaps/interface.md +++ b/tests/testthat/_snaps/interface.md @@ -33,3 +33,21 @@ Error in `el_to_vec()`: ! The columns of the data.frame are of different type (character and double) +# incident() works + + Code + incident(g, 1) + Output + + 16/78 edges: + [1] 1-- 2 1-- 3 1-- 4 1-- 5 1-- 6 1-- 7 1-- 8 1-- 9 1--11 1--12 1--13 1--14 + [13] 1--18 1--20 1--22 1--32 + +--- + + Code + incident(g, 34) + Output + + 17/78 edges: + [1] 9--34 10--34 14--34 15--34 16--34 19--34 20--34 21--34 23--34 24--34 + [11] 27--34 28--34 29--34 30--34 31--34 32--34 33--34 + diff --git a/tests/testthat/_snaps/minimum.spanning.tree.md b/tests/testthat/_snaps/minimum.spanning.tree.md index 9cdfaeb90d6..d14e5554966 100644 --- a/tests/testthat/_snaps/minimum.spanning.tree.md +++ b/tests/testthat/_snaps/minimum.spanning.tree.md @@ -4,5 +4,6 @@ mst(g, algorithm = "undefined") Condition Error in `mst()`: - ! Invalid `algorithm`. + ! `algorithm` must be one of "automatic", "unweighted", "prim", or "kruskal", not "undefined". + i Did you mean "unweighted"? diff --git a/tests/testthat/test-aaa-auto.R b/tests/testthat/test-aaa-auto.R index b51a615c7b2..a6f6732b83a 100644 --- a/tests/testthat/test-aaa-auto.R +++ b/tests/testthat/test-aaa-auto.R @@ -43,21 +43,6 @@ test_that("copy_impl errors", { expect_snapshot_igraph_error(copy_impl(NULL)) }) -# 4. delete_vertices_idx_impl - -test_that("delete_vertices_idx_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- empty_impl(3) - expect_snapshot(delete_vertices_idx_impl(g, 1)) -}) - -test_that("delete_vertices_idx_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(delete_vertices_idx_impl(NULL, 1)) -}) - # 5. vcount_impl test_that("vcount_impl basic", { @@ -338,18 +323,6 @@ test_that("kautz_impl errors", { expect_snapshot_igraph_error(kautz_impl(-1, 3)) }) -# 23. lcf_vector_impl -test_that("lcf_vector_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(lcf_vector_impl(10, c(3, -3, 4), 2)) -}) -test_that("lcf_vector_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(lcf_vector_impl(-1, c(3, -3, 4), 2)) -}) - # 24. mycielski_graph_impl test_that("mycielski_graph_impl basic", { withr::local_seed(20250909) @@ -843,55 +816,6 @@ test_that("dot_product_game_impl errors", { expect_snapshot_igraph_error(dot_product_game_impl(NULL)) }) -# 52. sample_sphere_surface_impl - -test_that("sample_sphere_surface_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_sphere_surface_impl(3, 5)) - expect_snapshot(sample_sphere_surface_impl( - 3, - 5, - radius = 2, - positive = FALSE - )) -}) - -test_that("sample_sphere_surface_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_sphere_surface_impl(-1, 5)) -}) - -# 53. sample_sphere_volume_impl - -test_that("sample_sphere_volume_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_sphere_volume_impl(3, 5)) - expect_snapshot(sample_sphere_volume_impl(3, 5, radius = 2, positive = FALSE)) -}) - -test_that("sample_sphere_volume_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_sphere_volume_impl(-1, 5)) -}) - -# 54. sample_dirichlet_impl - -test_that("sample_dirichlet_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(sample_dirichlet_impl(5, c(1, 1, 1))) -}) - -test_that("sample_dirichlet_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(sample_dirichlet_impl(-1, c(1, 1, 1))) -}) - # 55. are_adjacent_impl test_that("are_adjacent_impl basic", { @@ -950,13 +874,13 @@ test_that("get_shortest_path_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(get_shortest_path_impl(g, 1, 3)) + expect_snapshot(get_shortest_path_impl(g, from = 1, to = 3)) }) test_that("get_shortest_path_impl errors", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(get_shortest_path_impl(NULL, 1, 3)) + expect_snapshot_igraph_error(get_shortest_path_impl(NULL, from = 1, to = 3)) }) # 59. get_shortest_path_bellman_ford_impl @@ -995,13 +919,17 @@ test_that("get_all_shortest_paths_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(get_all_shortest_paths_impl(g, 1, 3)) + expect_snapshot(get_all_shortest_paths_impl(g, from = 1, to = 3)) }) test_that("get_all_shortest_paths_impl errors", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(get_all_shortest_paths_impl(NULL, 1, 3)) + expect_snapshot_igraph_error(get_all_shortest_paths_impl( + NULL, + from = 1, + to = 3 + )) }) # 62. get_all_shortest_paths_dijkstra_impl @@ -1431,7 +1359,7 @@ test_that("maxdegree_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(maxdegree_impl(g)) - expect_snapshot(maxdegree_impl(g, mode = "in", loops = FALSE)) + expect_snapshot(maxdegree_impl(g, mode = "in", loops = "twice")) }) test_that("maxdegree_impl errors", { @@ -1660,11 +1588,7 @@ test_that("eigenvector_centrality_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(eigenvector_centrality_impl(g)) - expect_snapshot(eigenvector_centrality_impl( - g, - directed = TRUE, - scale = FALSE - )) + expect_snapshot(eigenvector_centrality_impl(g, mode = "out")) }) test_that("eigenvector_centrality_impl errors", { @@ -1679,8 +1603,7 @@ test_that("hub_and_authority_scores_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- make_full_graph(5) - expect_snapshot(hub_and_authority_scores_impl(g)) - expect_snapshot(hub_and_authority_scores_impl(g, scale = FALSE)) + expect_snapshot(suppressWarnings(hub_and_authority_scores_impl(g))) }) test_that("hub_and_authority_scores_impl errors", { @@ -1824,7 +1747,7 @@ test_that("strength_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(strength_impl(g)) - expect_snapshot(strength_impl(g, mode = "in", loops = FALSE)) + expect_snapshot(strength_impl(g, mode = "in", loops = "twice")) }) test_that("strength_impl errors", { @@ -1862,7 +1785,7 @@ test_that("centralization_degree_impl basic", { expect_snapshot(centralization_degree_impl( g, mode = "in", - loops = FALSE, + loops = "twice", normalized = FALSE )) }) @@ -1873,27 +1796,6 @@ test_that("centralization_degree_impl errors", { expect_snapshot_igraph_error(centralization_degree_impl(NULL)) }) -# 136. centralization_degree_tmax_impl - -test_that("centralization_degree_tmax_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(centralization_degree_tmax_impl(nodes = 3, loops = TRUE)) - expect_snapshot(centralization_degree_tmax_impl( - nodes = 3, - mode = "in", - loops = FALSE - )) -}) - -test_that("centralization_degree_tmax_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - centralization_degree_tmax_impl(nodes = -1, loops = TRUE) - ) -}) - # 137. centralization_betweenness_impl test_that("centralization_betweenness_impl basic", { @@ -1981,7 +1883,7 @@ test_that("centralization_eigenvector_centrality_impl basic", { expect_snapshot(centralization_eigenvector_centrality_impl(g)) expect_snapshot(centralization_eigenvector_centrality_impl( g, - directed = TRUE, + mode = "out", normalized = FALSE )) }) @@ -2002,7 +1904,7 @@ test_that("centralization_eigenvector_centrality_tmax_impl basic", { expect_snapshot(centralization_eigenvector_centrality_tmax_impl(nodes = 3)) expect_snapshot(centralization_eigenvector_centrality_tmax_impl( nodes = 3, - directed = TRUE + mode = "out" )) }) @@ -2155,64 +2057,16 @@ test_that("contract_vertices_impl errors", { expect_snapshot_igraph_error(contract_vertices_impl(NULL, c(1, 1, 2))) }) -# 150. eccentricity_dijkstra_impl - -test_that("eccentricity_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(eccentricity_dijkstra_impl(g)) - expect_snapshot(eccentricity_dijkstra_impl(g, mode = "in")) -}) - -test_that("eccentricity_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(eccentricity_dijkstra_impl(NULL)) -}) - -# 151. graph_center_dijkstra_impl - -test_that("graph_center_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(graph_center_dijkstra_impl(g)) - expect_snapshot(graph_center_dijkstra_impl(g, mode = "in")) -}) - -test_that("graph_center_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(graph_center_dijkstra_impl(NULL)) -}) - -# 152. radius_dijkstra_impl - -test_that("radius_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(radius_dijkstra_impl(g)) - expect_snapshot(radius_dijkstra_impl(g, mode = "in")) -}) - -test_that("radius_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(radius_dijkstra_impl(NULL)) -}) - # 153. pseudo_diameter_impl test_that("pseudo_diameter_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(pseudo_diameter_impl(g, 1)) + expect_snapshot(pseudo_diameter_impl(g, start.vid = 1)) expect_snapshot(pseudo_diameter_impl( g, - 1, + start.vid = 1, directed = FALSE, unconnected = FALSE )) @@ -2224,29 +2078,6 @@ test_that("pseudo_diameter_impl errors", { expect_snapshot_igraph_error(pseudo_diameter_impl(NULL, 1)) }) -# 154. pseudo_diameter_dijkstra_impl - -test_that("pseudo_diameter_dijkstra_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(pseudo_diameter_dijkstra_impl(g, start.vid = 1)) - expect_snapshot(pseudo_diameter_dijkstra_impl( - g, - start.vid = 1, - directed = FALSE, - unconnected = FALSE - )) -}) - -test_that("pseudo_diameter_dijkstra_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - pseudo_diameter_dijkstra_impl(NULL, start.vid = 1) - ) -}) - # 155. diversity_impl test_that("diversity_impl basic", { @@ -2331,21 +2162,6 @@ test_that("average_local_efficiency_impl errors", { expect_snapshot_igraph_error(average_local_efficiency_impl(NULL)) }) -# 160. transitive_closure_dag_impl - -test_that("transitive_closure_dag_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3, directed = TRUE) - expect_snapshot(transitive_closure_dag_impl(g)) -}) - -test_that("transitive_closure_dag_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(transitive_closure_dag_impl(NULL)) -}) - # 161. transitive_closure_impl test_that("transitive_closure_impl basic", { @@ -3234,7 +3050,7 @@ test_that("similarity_dice_impl basic", { expect_snapshot(similarity_dice_impl(g)) expect_snapshot(similarity_dice_impl( g, - vids = 1:2, + vit.from = 1:2, mode = "in", loops = TRUE )) @@ -3322,7 +3138,7 @@ test_that("similarity_jaccard_impl basic", { expect_snapshot(similarity_jaccard_impl(g)) expect_snapshot(similarity_jaccard_impl( g, - vids = 1:2, + vit.from = 1:2, mode = "in", loops = TRUE )) @@ -3466,13 +3282,17 @@ test_that("community_label_propagation_impl basic", { withr::local_seed(20250909) local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) - expect_snapshot(community_label_propagation_impl(g)) + expect_snapshot(community_label_propagation_impl( + g, + lpa.variant = "dominance" + )) expect_snapshot(community_label_propagation_impl( g, mode = "in", weights = c(1, 2), initial = 1:3, - fixed = c(TRUE, FALSE, TRUE) + fixed = c(TRUE, FALSE, TRUE), + lpa.variant = "retention" )) }) @@ -3527,7 +3347,7 @@ test_that("community_leiden_impl basic", { expect_snapshot(community_leiden_impl( g, weights = c(1, 2), - vertex.weights = c(1, 2, 3), + vertex.out.weights = c(1, 2, 3), resolution = 0.5, beta = 0.1, start = TRUE, @@ -3565,8 +3385,8 @@ test_that("community_infomap_impl basic", { expect_snapshot(community_infomap_impl(g)) expect_snapshot(community_infomap_impl( g, - e.weights = c(1, 2), - v.weights = c(1, 2, 3), + edge.weights = c(1, 2), + vertex.weights = c(1, 2, 3), nb.trials = 2 )) }) @@ -4116,12 +3936,12 @@ test_that("local_scan_neighborhood_ecount_impl basic", { g <- path_graph_impl(4) expect_snapshot(local_scan_neighborhood_ecount_impl( g, - neighborhoods = list(1:2, 2:3, 2:4, 2) + neighborhoods = list(1:2 - 1, 2:3 - 1, 2:4 - 1, 2 - 1) )) expect_snapshot(local_scan_neighborhood_ecount_impl( g, weights = c(1, 2, 3), - neighborhoods = list(1:2, 1:3, 2:4, 1) + neighborhoods = list(1:2 - 1, 1:3 - 1, 2:4 - 1, 1 - 1) )) }) @@ -4715,7 +4535,7 @@ test_that("canonical_permutation_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(canonical_permutation_impl(g)) - expect_snapshot(canonical_permutation_impl(g, colors = c(1, 2, 3), sh = "fl")) + expect_snapshot(canonical_permutation_impl(g, colors = c(1, 2, 3))) }) test_that("canonical_permutation_impl errors", { @@ -4769,7 +4589,7 @@ test_that("count_automorphisms_impl basic", { local_igraph_options(print.id = FALSE) g <- path_graph_impl(3) expect_snapshot(count_automorphisms_impl(g)) - expect_snapshot(count_automorphisms_impl(g, colors = c(1, 2, 3), sh = "fl")) + expect_snapshot(count_automorphisms_impl(g, colors = c(1, 2, 3))) }) test_that("count_automorphisms_impl errors", { @@ -4787,9 +4607,7 @@ test_that("automorphism_group_impl basic", { expect_snapshot(automorphism_group_impl(g)) expect_snapshot(automorphism_group_impl( g, - colors = c(1, 2, 3), - sh = "fl", - details = TRUE + colors = c(1, 2, 3) )) }) @@ -4992,20 +4810,6 @@ test_that("sir_impl errors", { expect_snapshot_igraph_error(sir_impl(NULL, beta = 0.1, gamma = 0.1)) }) -# 304. convex_hull_2d_impl - -test_that("convex_hull_2d_impl basic", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot(convex_hull_2d_impl(matrix(1:6, ncol = 2))) -}) - -test_that("convex_hull_2d_impl errors", { - withr::local_seed(20250909) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error(convex_hull_2d_impl("a")) -}) - # 305. dim_select_impl test_that("dim_select_impl basic", { @@ -5359,138 +5163,6 @@ test_that("is_edge_coloring_impl errors", { expect_snapshot_igraph_error(is_edge_coloring_impl(NULL, types = c(1, 2))) }) -# 327. deterministic_optimal_imitation_impl - -test_that("deterministic_optimal_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(deterministic_optimal_imitation_impl( - g, - 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(deterministic_optimal_imitation_impl( - g, - 1, - optimality = "minimum", - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("deterministic_optimal_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - deterministic_optimal_imitation_impl( - NULL, - 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - -# 328. moran_process_impl - -test_that("moran_process_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(moran_process_impl( - g, - weights = c(1, 1), - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("moran_process_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - moran_process_impl(NULL, quantities = c(1, 2, 3), strategies = c(1, 2, 3)) - ) -}) - -# 329. roulette_wheel_imitation_impl - -test_that("roulette_wheel_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(roulette_wheel_imitation_impl( - g, - 1, - TRUE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(roulette_wheel_imitation_impl( - g, - 1, - FALSE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("roulette_wheel_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - roulette_wheel_imitation_impl( - NULL, - 1, - TRUE, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - -# 330. stochastic_imitation_impl - -test_that("stochastic_imitation_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(stochastic_imitation_impl( - g, - 1, - algo = 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - )) - expect_snapshot(stochastic_imitation_impl( - g, - 1, - algo = 2, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3), - mode = "in" - )) -}) - -test_that("stochastic_imitation_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - stochastic_imitation_impl( - NULL, - 1, - algo = 1, - quantities = c(1, 2, 3), - strategies = c(1, 2, 3) - ) - ) -}) - # 331. invalidate_cache_impl test_that("invalidate_cache_impl basic", { @@ -5506,33 +5178,6 @@ test_that("invalidate_cache_impl errors", { expect_snapshot_igraph_error(invalidate_cache_impl(NULL)) }) -# 332. vertex_path_from_edge_path_impl - -test_that("vertex_path_from_edge_path_impl basic", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - g <- path_graph_impl(3) - expect_snapshot(vertex_path_from_edge_path_impl( - g, - start = 1, - edge.path = c(1, 2) - )) - expect_snapshot(vertex_path_from_edge_path_impl( - g, - start = 1, - edge.path = c(1), - mode = "in" - )) -}) - -test_that("vertex_path_from_edge_path_impl errors", { - withr::local_seed(12345) - local_igraph_options(print.id = FALSE) - expect_snapshot_igraph_error( - vertex_path_from_edge_path_impl(NULL, start = 1, edge.path = c(1, 2)) - ) -}) - # 333. version_impl test_that("version_impl basic", { diff --git a/tests/testthat/test-centrality.R b/tests/testthat/test-centrality.R index 367e88e0248..f78a23d8fd8 100644 --- a/tests/testthat/test-centrality.R +++ b/tests/testthat/test-centrality.R @@ -590,7 +590,8 @@ test_that("eigen_centrality() works", { for (i in 1:1000) { G <- sample_gnm(10, sample(1:20, 1)) - ev <- eigen_centrality(G) + # FIXME: Find a way to avoid warnings + suppressWarnings(ev <- eigen_centrality(G)) expect_good( as_adjacency_matrix(G, sparse = FALSE), ev$vector, diff --git a/tests/testthat/test-interface.R b/tests/testthat/test-interface.R index d1f5b10ecc1..a40b91f2ea4 100644 --- a/tests/testthat/test-interface.R +++ b/tests/testthat/test-interface.R @@ -222,3 +222,10 @@ test_that("get_edge_id() errors correctly for wrong matrices", { mat <- matrix(c(1, 2, 1, 3, 1, 4), nrow = 2, ncol = 3) lifecycle::expect_deprecated(get_edge_ids(g, mat)) }) + +test_that("incident() works", { + local_igraph_options(print.id = FALSE) + g <- make_graph("Zachary") + expect_snapshot(incident(g, 1)) + expect_snapshot(incident(g, 34)) +}) diff --git a/tests/testthat/test-simple.R b/tests/testthat/test-simple.R new file mode 100644 index 00000000000..aff0bea5c1e --- /dev/null +++ b/tests/testthat/test-simple.R @@ -0,0 +1,5 @@ +test_that("is_simple() works", { + g <- graph_from_literal(1 +-+ 2 -+ 3) + expect_true(is_simple(g)) + expect_false(is_simple(g, directed = FALSE)) +}) diff --git a/tests/testthat/test-structural-properties.R b/tests/testthat/test-structural-properties.R index f938d495dd0..0c92d2299b9 100644 --- a/tests/testthat/test-structural-properties.R +++ b/tests/testthat/test-structural-properties.R @@ -65,9 +65,9 @@ test_that("max_degree() works", { g <- make_graph(c(1, 2, 2, 2, 2, 3), directed = TRUE) expect_equal(max_degree(g), 4) expect_equal(max_degree(g, mode = "out"), 2) - expect_equal(max_degree(g, loops = FALSE), 2) - expect_equal(max_degree(g, mode = "out", loops = FALSE), 1) - expect_equal(max_degree(g, mode = "in", loops = FALSE), 1) + expect_equal(max_degree(g, loops = "none"), 2) + expect_equal(max_degree(g, mode = "out", loops = "none"), 1) + expect_equal(max_degree(g, mode = "in", loops = "none"), 1) expect_equal(max_degree(g, v = c()), 0) expect_equal(max_degree(make_empty_graph()), 0) }) @@ -905,7 +905,7 @@ test_that("edge_density works", { expect_equal(gd, gd2) }) -test_that("knn works", { +test_that("knn works -- trivial examples", { withr::local_seed(42) ## Some trivial ones @@ -917,23 +917,28 @@ test_that("knn works", { knn(g2), list(knn = c(1, rep(9, 9)), knnk = c(9, rep(NaN, 7), 1)) ) +}) - ## A scale-free one, try to plot 'knnk' +test_that("knn works -- scale-free one", { + withr::local_seed(42) g3 <- simplify(sample_pa(1000, m = 5)) r3 <- knn(g3) expect_equal(r3$knn[43], 46) expect_equal(r3$knn[1000], 192.4) expect_equal(r3$knnk[100], 18.78) expect_equal(length(r3$knnk), 359) +}) - ## A random graph +test_that("knn works -- random graph", { + withr::local_seed(42) g4 <- sample_gnp(1000, p = 5 / 1000) r4 <- knn(g4) - expect_equal(r4$knn[1000], 20 / 3) + expect_equal(r4$knn[1000], 5) expect_equal(length(r4$knnk), 15) - expect_equal(r4$knnk[12], 19 / 3) + expect_equal(r4$knnk[12], 5.6389, tolerance = 1e-5) +}) - ## A weighted graph +test_that("knn works -- weighted graph", { g5 <- make_star(10) E(g5)$weight <- seq(ecount(g5)) r5 <- knn(g5)