From 0bac719e44c18024080163f52fbce373ebd2c26b Mon Sep 17 00:00:00 2001 From: David Schoch Date: Fri, 28 Feb 2025 09:46:12 +0100 Subject: [PATCH] test: added tests for untested files (#1728) --- R/layout.R | 389 ++++++++++++++++-- R/layout_drl.R | 304 -------------- R/minimum.spanning.tree.R | 4 +- .../testthat/_snaps/minimum.spanning.tree.md | 8 + tests/testthat/test-centralization.R | 28 ++ tests/testthat/test-cocitation.R | 11 + tests/testthat/test-minimum.spanning.tree.R | 41 ++ tests/testthat/test-similarity.R | 30 ++ tests/testthat/test-stochastic_matrix.R | 16 + 9 files changed, 483 insertions(+), 348 deletions(-) delete mode 100644 R/layout_drl.R create mode 100644 tests/testthat/_snaps/minimum.spanning.tree.md create mode 100644 tests/testthat/test-centralization.R create mode 100644 tests/testthat/test-cocitation.R create mode 100644 tests/testthat/test-minimum.spanning.tree.R create mode 100644 tests/testthat/test-similarity.R create mode 100644 tests/testthat/test-stochastic_matrix.R diff --git a/R/layout.R b/R/layout.R index 7efeb57337..3101514495 100644 --- a/R/layout.R +++ b/R/layout.R @@ -1072,7 +1072,7 @@ layout.random <- function(..., params = list()) { #' g_6 <- make_lattice(c(2, 2, 2)) #' plot(g_6, layout = layout_with_dh) #' -#' g_7 <- graph_from_literal(1:3:5 -- 2:4:6) +#' g_7 <- graph_from_literal(1:3:5 - -2:4:6) #' plot(g_7, layout = layout_with_dh, vertex.label = V(g_7)$name) #' #' g_8 <- make_ring(5) + make_ring(10) + make_ring(5) + @@ -1835,19 +1835,19 @@ with_mds <- function(...) layout_spec(layout_with_mds, ...) #' #' ## Data taken from http://tehnick-8.narod.ru/dc_clients/ #' DC <- graph_from_literal( -#' "DC++" -+ "LinuxDC++":"BCDC++":"EiskaltDC++":"StrongDC++":"DiCe!++", -#' "LinuxDC++" -+ "FreeDC++", "BCDC++" -+ "StrongDC++", -#' "FreeDC++" -+ "BMDC++":"EiskaltDC++", -#' "StrongDC++" -+ "AirDC++":"zK++":"ApexDC++":"TkDC++", -#' "StrongDC++" -+ "StrongDC++ SQLite":"RSX++", -#' "ApexDC++" -+ "FlylinkDC++ ver <= 4xx", -#' "ApexDC++" -+ "ApexDC++ Speed-Mod":"DiCe!++", -#' "StrongDC++ SQLite" -+ "FlylinkDC++ ver >= 5xx", -#' "ApexDC++ Speed-Mod" -+ "FlylinkDC++ ver <= 4xx", -#' "ApexDC++ Speed-Mod" -+ "GreylinkDC++", -#' "FlylinkDC++ ver <= 4xx" -+ "FlylinkDC++ ver >= 5xx", -#' "FlylinkDC++ ver <= 4xx" -+ AvaLink, -#' "GreylinkDC++" -+ AvaLink:"RayLinkDC++":"SparkDC++":PeLink +#' "DC++" - +"LinuxDC++":"BCDC++":"EiskaltDC++":"StrongDC++":"DiCe!++", +#' "LinuxDC++" - +"FreeDC++", "BCDC++" - +"StrongDC++", +#' "FreeDC++" - +"BMDC++":"EiskaltDC++", +#' "StrongDC++" - +"AirDC++":"zK++":"ApexDC++":"TkDC++", +#' "StrongDC++" - +"StrongDC++ SQLite":"RSX++", +#' "ApexDC++" - +"FlylinkDC++ ver <= 4xx", +#' "ApexDC++" - +"ApexDC++ Speed-Mod":"DiCe!++", +#' "StrongDC++ SQLite" - +"FlylinkDC++ ver >= 5xx", +#' "ApexDC++ Speed-Mod" - +"FlylinkDC++ ver <= 4xx", +#' "ApexDC++ Speed-Mod" - +"GreylinkDC++", +#' "FlylinkDC++ ver <= 4xx" - +"FlylinkDC++ ver >= 5xx", +#' "FlylinkDC++ ver <= 4xx" - +AvaLink, +#' "GreylinkDC++" - +AvaLink:"RayLinkDC++":"SparkDC++":PeLink #' ) #' #' ## Use edge types @@ -1914,36 +1914,36 @@ with_mds <- function(...) layout_spec(layout_with_mds, ...) #' ## Applications 9, 305--325 (2005). #' #' ex <- graph_from_literal( -#' 0 -+ 29:6:5:20:4, -#' 1 -+ 12, -#' 2 -+ 23:8, -#' 3 -+ 4, +#' 0 - +29:6:5:20:4, +#' 1 - +12, +#' 2 - +23:8, +#' 3 - +4, #' 4, -#' 5 -+ 2:10:14:26:4:3, -#' 6 -+ 9:29:25:21:13, +#' 5 - +2:10:14:26:4:3, +#' 6 - +9:29:25:21:13, #' 7, -#' 8 -+ 20:16, -#' 9 -+ 28:4, -#' 10 -+ 27, -#' 11 -+ 9:16, -#' 12 -+ 9:19, -#' 13 -+ 20, -#' 14 -+ 10, -#' 15 -+ 16:27, -#' 16 -+ 27, -#' 17 -+ 3, -#' 18 -+ 13, -#' 19 -+ 9, -#' 20 -+ 4, -#' 21 -+ 22, -#' 22 -+ 8:9, -#' 23 -+ 9:24, -#' 24 -+ 12:15:28, -#' 25 -+ 11, -#' 26 -+ 18, -#' 27 -+ 13:19, -#' 28 -+ 7, -#' 29 -+ 25 +#' 8 - +20:16, +#' 9 - +28:4, +#' 10 - +27, +#' 11 - +9:16, +#' 12 - +9:19, +#' 13 - +20, +#' 14 - +10, +#' 15 - +16:27, +#' 16 - +27, +#' 17 - +3, +#' 18 - +13, +#' 19 - +9, +#' 20 - +4, +#' 21 - +22, +#' 22 - +8:9, +#' 23 - +9:24, +#' 24 - +12:15:28, +#' 25 - +11, +#' 26 - +18, +#' 27 - +13:19, +#' 28 - +7, +#' 29 - +25 #' ) #' #' layers <- list( @@ -2295,3 +2295,308 @@ layout.fruchterman.reingold.grid <- function(graph, ...) { ) layout_with_fr(graph) } + +#' The DrL graph layout generator +#' +#' @description +#' `r lifecycle::badge("deprecated")` +#' +#' `layout.drl()` was renamed to `layout_with_drl()` to create a more +#' consistent API. +#' @inheritParams layout_with_drl +#' @keywords internal +#' @export +layout.drl <- function(graph, use.seed = FALSE, seed = matrix(runif(vcount(graph) * 2), ncol = 2), options = drl_defaults$default, weights = NULL, dim = 2) { # nocov start + lifecycle::deprecate_soft("2.0.0", "layout.drl()", "layout_with_drl()") + layout_with_drl(graph = graph, use.seed = use.seed, seed = seed, options = options, weights = weights, dim = dim) +} # nocov end + +#' The DrL graph layout generator +#' +#' DrL is a force-directed graph layout toolbox focused on real-world +#' large-scale graphs, developed by Shawn Martin and colleagues at Sandia +#' National Laboratories. +#' +#' This function implements the force-directed DrL layout generator. +#' +#' The generator has the following parameters: \describe{ \item{edge.cut}{Edge +#' cutting is done in the late stages of the algorithm in order to achieve less +#' dense layouts. Edges are cut if there is a lot of stress on them (a large +#' value in the objective function sum). The edge cutting parameter is a value +#' between 0 and 1 with 0 representing no edge cutting and 1 representing +#' maximal edge cutting. } \item{init.iterations}{Number of iterations in the +#' first phase.} \item{init.temperature}{Start temperature, first phase.} +#' \item{init.attraction}{Attraction, first phase.} +#' \item{init.damping.mult}{Damping, first phase.} +#' \item{liquid.iterations}{Number of iterations, liquid phase.} +#' \item{liquid.temperature}{Start temperature, liquid phase.} +#' \item{liquid.attraction}{Attraction, liquid phase.} +#' \item{liquid.damping.mult}{Damping, liquid phase.} +#' \item{expansion.iterations}{Number of iterations, expansion phase.} +#' \item{expansion.temperature}{Start temperature, expansion phase.} +#' \item{expansion.attraction}{Attraction, expansion phase.} +#' \item{expansion.damping.mult}{Damping, expansion phase.} +#' \item{cooldown.iterations}{Number of iterations, cooldown phase.} +#' \item{cooldown.temperature}{Start temperature, cooldown phase.} +#' \item{cooldown.attraction}{Attraction, cooldown phase.} +#' \item{cooldown.damping.mult}{Damping, cooldown phase.} +#' \item{crunch.iterations}{Number of iterations, crunch phase.} +#' \item{crunch.temperature}{Start temperature, crunch phase.} +#' \item{crunch.attraction}{Attraction, crunch phase.} +#' \item{crunch.damping.mult}{Damping, crunch phase.} +#' \item{simmer.iterations}{Number of iterations, simmer phase.} +#' \item{simmer.temperature}{Start temperature, simmer phase.} +#' \item{simmer.attraction}{Attraction, simmer phase.} +#' \item{simmer.damping.mult}{Damping, simmer phase.} +#' +#' There are five pre-defined parameter settings as well, these are called +#' `drl_defaults$default`, `drl_defaults$coarsen`, +#' `drl_defaults$coarsest`, `drl_defaults$refine` and +#' `drl_defaults$final`. } +#' +#' @aliases drl_defaults igraph.drl.coarsen +#' @aliases igraph.drl.coarsest igraph.drl.default igraph.drl.final +#' igraph.drl.refine +#' @param graph The input graph, in can be directed or undirected. +#' @param use.seed Logical scalar, whether to use the coordinates given in the +#' `seed` argument as a starting point. +#' @param seed A matrix with two columns, the starting coordinates for the +#' vertices is `use.seed` is `TRUE`. It is ignored otherwise. +#' @param options Options for the layout generator, a named list. See details +#' below. +#' @param weights The weights of the edges. It must be a positive numeric vector, +#' `NULL` or `NA`. If it is `NULL` and the input graph has a +#' \sQuote{weight} edge attribute, then that attribute will be used. If +#' `NULL` and no such attribute is present, then the edges will have equal +#' weights. Set this to `NA` if the graph was a \sQuote{weight} edge +#' attribute, but you don't want to use it for the layout. Larger edge weights +#' correspond to stronger connections. +#' @param dim Either \sQuote{2} or \sQuote{3}, it specifies whether we want a +#' two dimensional or a three dimensional layout. Note that because of the +#' nature of the DrL algorithm, the three dimensional layout takes +#' significantly longer to compute. +#' @return A numeric matrix with two columns. +#' @author Shawn Martin () +#' and Gabor Csardi \email{csardi.gabor@@gmail.com} for the R/igraph interface +#' and the three dimensional version. +#' @seealso [layout()] for other layout generators. +#' @references See the following technical report: Martin, S., Brown, W.M., +#' Klavans, R., Boyack, K.W., DrL: Distributed Recursive (Graph) Layout. SAND +#' Reports, 2008. 2936: p. 1-10. +#' @family layout_drl +#' @export +#' @importFrom stats runif +#' @keywords graphs +#' @examples +#' +#' g <- as_undirected(sample_pa(100, m = 1)) +#' l <- layout_with_drl(g, options = list(simmer.attraction = 0)) +#' plot(g, layout = l, vertex.size = 3, vertex.label = NA) +#' +layout_with_drl <- function(graph, use.seed = FALSE, + seed = matrix(runif(vcount(graph) * 2), ncol = 2), + options = drl_defaults$default, + weights = NULL, + dim = 2) { + ensure_igraph(graph) + + if (dim != 2 && dim != 3) { + stop("`dim' must be 2 or 3") + } + + use.seed <- as.logical(use.seed) + seed <- as.matrix(seed) + + options <- modify_list(drl_defaults$default, options) + + 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)) + if (dim == 2) { + res <- .Call( + R_igraph_layout_drl, graph, seed, use.seed, options, + weights + ) + } else { + res <- .Call( + R_igraph_layout_drl_3d, graph, seed, use.seed, options, + weights + ) + } + res +} + + +#' @rdname layout_with_drl +#' @param ... Passed to `layout_with_drl()`. +#' @family layout_drl +#' @export +with_drl <- function(...) layout_spec(layout_with_drl, ...) + + +#' @family layout_drl +#' @export +igraph.drl.default <- list( + edge.cut = 32 / 40, + init.iterations = 0, + init.temperature = 2000, + init.attraction = 10, + init.damping.mult = 1.0, + liquid.iterations = 200, + liquid.temperature = 2000, + liquid.attraction = 10, + liquid.damping.mult = 1.0, + expansion.iterations = 200, + expansion.temperature = 2000, + expansion.attraction = 2, + expansion.damping.mult = 1.0, + cooldown.iterations = 200, + cooldown.temperature = 2000, + cooldown.attraction = 1, + cooldown.damping.mult = .1, + crunch.iterations = 50, + crunch.temperature = 250, + crunch.attraction = 1, + crunch.damping.mult = 0.25, + simmer.iterations = 100, + simmer.temperature = 250, + simmer.attraction = .5, + simmer.damping.mult = 0 +) + +#' @family layout_drl +#' @export +igraph.drl.coarsen <- list( + edge.cut = 32 / 40, + init.iterations = 0, + init.temperature = 2000, + init.attraction = 10, + init.damping.mult = 1.0, + liquid.iterations = 200, + liquid.temperature = 2000, + liquid.attraction = 2, + liquid.damping.mult = 1.0, + expansion.iterations = 200, + expansion.temperature = 2000, + expansion.attraction = 10, + expansion.damping.mult = 1.0, + cooldown.iterations = 200, + cooldown.temperature = 2000, + cooldown.attraction = 1, + cooldown.damping.mult = .1, + crunch.iterations = 50, + crunch.temperature = 250, + crunch.attraction = 1, + crunch.damping.mult = 0.25, + simmer.iterations = 100, + simmer.temperature = 250, + simmer.attraction = .5, + simmer.damping.mult = 0 +) + +#' @family layout_drl +#' @export +igraph.drl.coarsest <- list( + edge.cut = 32 / 40, + init.iterations = 0, + init.temperature = 2000, + init.attraction = 10, + init.damping.mult = 1.0, + liquid.iterations = 200, + liquid.temperature = 2000, + liquid.attraction = 2, + liquid.damping.mult = 1.0, + expansion.iterations = 200, + expansion.temperature = 2000, + expansion.attraction = 10, + expansion.damping.mult = 1.0, + cooldown.iterations = 200, + cooldown.temperature = 2000, + cooldown.attraction = 1, + cooldown.damping.mult = .1, + crunch.iterations = 200, + crunch.temperature = 250, + crunch.attraction = 1, + crunch.damping.mult = 0.25, + simmer.iterations = 100, + simmer.temperature = 250, + simmer.attraction = .5, + simmer.damping.mult = 0 +) + +#' @family layout_drl +#' @export +igraph.drl.refine <- list( + edge.cut = 32 / 40, + init.iterations = 0, + init.temperature = 50, + init.attraction = .5, + init.damping.mult = 1.0, + liquid.iterations = 0, + liquid.temperature = 2000, + liquid.attraction = 2, + liquid.damping.mult = 1.0, + expansion.iterations = 50, + expansion.temperature = 500, + expansion.attraction = .1, + expansion.damping.mult = .25, + cooldown.iterations = 50, + cooldown.temperature = 250, + cooldown.attraction = 1, + cooldown.damping.mult = .1, + crunch.iterations = 50, + crunch.temperature = 250, + crunch.attraction = 1, + crunch.damping.mult = 0.25, + simmer.iterations = 0, + simmer.temperature = 250, + simmer.attraction = .5, + simmer.damping.mult = 0 +) + +#' @family layout_drl +#' @export +igraph.drl.final <- list( + edge.cut = 32 / 40, + init.iterations = 0, + init.temperature = 50, + init.attraction = .5, + init.damping.mult = 0, + liquid.iterations = 0, + liquid.temperature = 2000, + liquid.attraction = 2, + liquid.damping.mult = 1.0, + expansion.iterations = 50, + expansion.temperature = 2000, + expansion.attraction = 2, + expansion.damping.mult = 1.0, + cooldown.iterations = 50, + cooldown.temperature = 200, + cooldown.attraction = 1, + cooldown.damping.mult = .1, + crunch.iterations = 50, + crunch.temperature = 250, + crunch.attraction = 1, + crunch.damping.mult = 0.25, + simmer.iterations = 25, + simmer.temperature = 250, + simmer.attraction = .5, + simmer.damping.mult = 0 +) + +#' @family layout_drl +#' @export +drl_defaults <- list( + coarsen = igraph.drl.coarsen, + coarsest = igraph.drl.coarsest, + default = igraph.drl.default, + final = igraph.drl.final, + refine = igraph.drl.refine +) diff --git a/R/layout_drl.R b/R/layout_drl.R deleted file mode 100644 index c614c3520f..0000000000 --- a/R/layout_drl.R +++ /dev/null @@ -1,304 +0,0 @@ -#' The DrL graph layout generator -#' -#' @description -#' `r lifecycle::badge("deprecated")` -#' -#' `layout.drl()` was renamed to `layout_with_drl()` to create a more -#' consistent API. -#' @inheritParams layout_with_drl -#' @keywords internal -#' @export -layout.drl <- function(graph, use.seed = FALSE, seed = matrix(runif(vcount(graph) * 2), ncol = 2), options = drl_defaults$default, weights = NULL, dim = 2) { # nocov start - lifecycle::deprecate_soft("2.0.0", "layout.drl()", "layout_with_drl()") - layout_with_drl(graph = graph, use.seed = use.seed, seed = seed, options = options, weights = weights, dim = dim) -} # nocov end - -#' The DrL graph layout generator -#' -#' DrL is a force-directed graph layout toolbox focused on real-world -#' large-scale graphs, developed by Shawn Martin and colleagues at Sandia -#' National Laboratories. -#' -#' This function implements the force-directed DrL layout generator. -#' -#' The generator has the following parameters: \describe{ \item{edge.cut}{Edge -#' cutting is done in the late stages of the algorithm in order to achieve less -#' dense layouts. Edges are cut if there is a lot of stress on them (a large -#' value in the objective function sum). The edge cutting parameter is a value -#' between 0 and 1 with 0 representing no edge cutting and 1 representing -#' maximal edge cutting. } \item{init.iterations}{Number of iterations in the -#' first phase.} \item{init.temperature}{Start temperature, first phase.} -#' \item{init.attraction}{Attraction, first phase.} -#' \item{init.damping.mult}{Damping, first phase.} -#' \item{liquid.iterations}{Number of iterations, liquid phase.} -#' \item{liquid.temperature}{Start temperature, liquid phase.} -#' \item{liquid.attraction}{Attraction, liquid phase.} -#' \item{liquid.damping.mult}{Damping, liquid phase.} -#' \item{expansion.iterations}{Number of iterations, expansion phase.} -#' \item{expansion.temperature}{Start temperature, expansion phase.} -#' \item{expansion.attraction}{Attraction, expansion phase.} -#' \item{expansion.damping.mult}{Damping, expansion phase.} -#' \item{cooldown.iterations}{Number of iterations, cooldown phase.} -#' \item{cooldown.temperature}{Start temperature, cooldown phase.} -#' \item{cooldown.attraction}{Attraction, cooldown phase.} -#' \item{cooldown.damping.mult}{Damping, cooldown phase.} -#' \item{crunch.iterations}{Number of iterations, crunch phase.} -#' \item{crunch.temperature}{Start temperature, crunch phase.} -#' \item{crunch.attraction}{Attraction, crunch phase.} -#' \item{crunch.damping.mult}{Damping, crunch phase.} -#' \item{simmer.iterations}{Number of iterations, simmer phase.} -#' \item{simmer.temperature}{Start temperature, simmer phase.} -#' \item{simmer.attraction}{Attraction, simmer phase.} -#' \item{simmer.damping.mult}{Damping, simmer phase.} -#' -#' There are five pre-defined parameter settings as well, these are called -#' `drl_defaults$default`, `drl_defaults$coarsen`, -#' `drl_defaults$coarsest`, `drl_defaults$refine` and -#' `drl_defaults$final`. } -#' -#' @aliases drl_defaults igraph.drl.coarsen -#' @aliases igraph.drl.coarsest igraph.drl.default igraph.drl.final -#' igraph.drl.refine -#' @param graph The input graph, in can be directed or undirected. -#' @param use.seed Logical scalar, whether to use the coordinates given in the -#' `seed` argument as a starting point. -#' @param seed A matrix with two columns, the starting coordinates for the -#' vertices is `use.seed` is `TRUE`. It is ignored otherwise. -#' @param options Options for the layout generator, a named list. See details -#' below. -#' @param weights The weights of the edges. It must be a positive numeric vector, -#' `NULL` or `NA`. If it is `NULL` and the input graph has a -#' \sQuote{weight} edge attribute, then that attribute will be used. If -#' `NULL` and no such attribute is present, then the edges will have equal -#' weights. Set this to `NA` if the graph was a \sQuote{weight} edge -#' attribute, but you don't want to use it for the layout. Larger edge weights -#' correspond to stronger connections. -#' @param dim Either \sQuote{2} or \sQuote{3}, it specifies whether we want a -#' two dimensional or a three dimensional layout. Note that because of the -#' nature of the DrL algorithm, the three dimensional layout takes -#' significantly longer to compute. -#' @return A numeric matrix with two columns. -#' @author Shawn Martin () -#' and Gabor Csardi \email{csardi.gabor@@gmail.com} for the R/igraph interface -#' and the three dimensional version. -#' @seealso [layout()] for other layout generators. -#' @references See the following technical report: Martin, S., Brown, W.M., -#' Klavans, R., Boyack, K.W., DrL: Distributed Recursive (Graph) Layout. SAND -#' Reports, 2008. 2936: p. 1-10. -#' @family layout_drl -#' @export -#' @importFrom stats runif -#' @keywords graphs -#' @examples -#' -#' g <- as_undirected(sample_pa(100, m = 1)) -#' l <- layout_with_drl(g, options = list(simmer.attraction = 0)) -#' plot(g, layout = l, vertex.size = 3, vertex.label = NA) -#' -layout_with_drl <- function(graph, use.seed = FALSE, - seed = matrix(runif(vcount(graph) * 2), ncol = 2), - options = drl_defaults$default, - weights = NULL, - dim = 2) { - ensure_igraph(graph) - - if (dim != 2 && dim != 3) { - stop("`dim' must be 2 or 3") - } - - use.seed <- as.logical(use.seed) - seed <- as.matrix(seed) - - options <- modify_list(drl_defaults$default, options) - - 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)) - if (dim == 2) { - res <- .Call( - R_igraph_layout_drl, graph, seed, use.seed, options, - weights - ) - } else { - res <- .Call( - R_igraph_layout_drl_3d, graph, seed, use.seed, options, - weights - ) - } - res -} - - -#' @rdname layout_with_drl -#' @param ... Passed to `layout_with_drl()`. -#' @family layout_drl -#' @export -with_drl <- function(...) layout_spec(layout_with_drl, ...) - - -#' @family layout_drl -#' @export -igraph.drl.default <- list( - edge.cut = 32 / 40, - init.iterations = 0, - init.temperature = 2000, - init.attraction = 10, - init.damping.mult = 1.0, - liquid.iterations = 200, - liquid.temperature = 2000, - liquid.attraction = 10, - liquid.damping.mult = 1.0, - expansion.iterations = 200, - expansion.temperature = 2000, - expansion.attraction = 2, - expansion.damping.mult = 1.0, - cooldown.iterations = 200, - cooldown.temperature = 2000, - cooldown.attraction = 1, - cooldown.damping.mult = .1, - crunch.iterations = 50, - crunch.temperature = 250, - crunch.attraction = 1, - crunch.damping.mult = 0.25, - simmer.iterations = 100, - simmer.temperature = 250, - simmer.attraction = .5, - simmer.damping.mult = 0 -) - -#' @family layout_drl -#' @export -igraph.drl.coarsen <- list( - edge.cut = 32 / 40, - init.iterations = 0, - init.temperature = 2000, - init.attraction = 10, - init.damping.mult = 1.0, - liquid.iterations = 200, - liquid.temperature = 2000, - liquid.attraction = 2, - liquid.damping.mult = 1.0, - expansion.iterations = 200, - expansion.temperature = 2000, - expansion.attraction = 10, - expansion.damping.mult = 1.0, - cooldown.iterations = 200, - cooldown.temperature = 2000, - cooldown.attraction = 1, - cooldown.damping.mult = .1, - crunch.iterations = 50, - crunch.temperature = 250, - crunch.attraction = 1, - crunch.damping.mult = 0.25, - simmer.iterations = 100, - simmer.temperature = 250, - simmer.attraction = .5, - simmer.damping.mult = 0 -) - -#' @family layout_drl -#' @export -igraph.drl.coarsest <- list( - edge.cut = 32 / 40, - init.iterations = 0, - init.temperature = 2000, - init.attraction = 10, - init.damping.mult = 1.0, - liquid.iterations = 200, - liquid.temperature = 2000, - liquid.attraction = 2, - liquid.damping.mult = 1.0, - expansion.iterations = 200, - expansion.temperature = 2000, - expansion.attraction = 10, - expansion.damping.mult = 1.0, - cooldown.iterations = 200, - cooldown.temperature = 2000, - cooldown.attraction = 1, - cooldown.damping.mult = .1, - crunch.iterations = 200, - crunch.temperature = 250, - crunch.attraction = 1, - crunch.damping.mult = 0.25, - simmer.iterations = 100, - simmer.temperature = 250, - simmer.attraction = .5, - simmer.damping.mult = 0 -) - -#' @family layout_drl -#' @export -igraph.drl.refine <- list( - edge.cut = 32 / 40, - init.iterations = 0, - init.temperature = 50, - init.attraction = .5, - init.damping.mult = 1.0, - liquid.iterations = 0, - liquid.temperature = 2000, - liquid.attraction = 2, - liquid.damping.mult = 1.0, - expansion.iterations = 50, - expansion.temperature = 500, - expansion.attraction = .1, - expansion.damping.mult = .25, - cooldown.iterations = 50, - cooldown.temperature = 250, - cooldown.attraction = 1, - cooldown.damping.mult = .1, - crunch.iterations = 50, - crunch.temperature = 250, - crunch.attraction = 1, - crunch.damping.mult = 0.25, - simmer.iterations = 0, - simmer.temperature = 250, - simmer.attraction = .5, - simmer.damping.mult = 0 -) - -#' @family layout_drl -#' @export -igraph.drl.final <- list( - edge.cut = 32 / 40, - init.iterations = 0, - init.temperature = 50, - init.attraction = .5, - init.damping.mult = 0, - liquid.iterations = 0, - liquid.temperature = 2000, - liquid.attraction = 2, - liquid.damping.mult = 1.0, - expansion.iterations = 50, - expansion.temperature = 2000, - expansion.attraction = 2, - expansion.damping.mult = 1.0, - cooldown.iterations = 50, - cooldown.temperature = 200, - cooldown.attraction = 1, - cooldown.damping.mult = .1, - crunch.iterations = 50, - crunch.temperature = 250, - crunch.attraction = 1, - crunch.damping.mult = 0.25, - simmer.iterations = 25, - simmer.temperature = 250, - simmer.attraction = .5, - simmer.damping.mult = 0 -) - -#' @family layout_drl -#' @export -drl_defaults <- list( - coarsen = igraph.drl.coarsen, - coarsest = igraph.drl.coarsest, - default = igraph.drl.default, - final = igraph.drl.final, - refine = igraph.drl.refine -) diff --git a/R/minimum.spanning.tree.R b/R/minimum.spanning.tree.R index b10c24859d..e5aa1ef5dc 100644 --- a/R/minimum.spanning.tree.R +++ b/R/minimum.spanning.tree.R @@ -92,13 +92,13 @@ mst <- function(graph, weights = NULL, .Call(R_igraph_minimum_spanning_tree_unweighted, graph) } else if (algorithm == "prim") { if (is.null(weights) && !"weight" %in% edge_attr_names(graph)) { - stop("edges weights must be supplied for Prim's algorithm") + 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 { - stop("Invalid algorithm") + cli::cli_abort("Invalid {.arg algorithm}.") } } diff --git a/tests/testthat/_snaps/minimum.spanning.tree.md b/tests/testthat/_snaps/minimum.spanning.tree.md new file mode 100644 index 0000000000..9cdfaeb90d --- /dev/null +++ b/tests/testthat/_snaps/minimum.spanning.tree.md @@ -0,0 +1,8 @@ +# mst error works + + Code + mst(g, algorithm = "undefined") + Condition + Error in `mst()`: + ! Invalid `algorithm`. + diff --git a/tests/testthat/test-centralization.R b/tests/testthat/test-centralization.R new file mode 100644 index 0000000000..c01f59a8bf --- /dev/null +++ b/tests/testthat/test-centralization.R @@ -0,0 +1,28 @@ +test_that("centr_degree works", { + g <- make_star(5, "undirected") + g_centr <- centr_degree(g, normalized = FALSE) + g_centr_tmax <- centr_degree_tmax(g, loops = FALSE) + expect_equal(g_centr$centralization, g_centr_tmax) +}) + +test_that("centr_betw works", { + g <- make_star(5, "undirected") + g_centr <- centr_betw(g, normalized = FALSE) + g_centr_tmax <- centr_betw_tmax(g) + expect_equal(g_centr$centralization, g_centr_tmax) +}) + +test_that("centr_clo works", { + g <- make_star(5, "undirected") + g_centr <- centr_clo(g, normalized = FALSE) + g_centr_tmax <- centr_clo_tmax(g) + expect_equal(g_centr$centralization, g_centr_tmax) +}) + + +test_that("centr_eigen works", { + g <- make_star(2, "undirected") + g_centr <- centr_eigen(g, normalized = FALSE) + g_centr_tmax <- centr_eigen_tmax(g) + expect_equal(g_centr$centralization, g_centr_tmax) +}) diff --git a/tests/testthat/test-cocitation.R b/tests/testthat/test-cocitation.R new file mode 100644 index 0000000000..ba02ae168b --- /dev/null +++ b/tests/testthat/test-cocitation.R @@ -0,0 +1,11 @@ +test_that("cocitation works", { + g <- make_full_graph(10, directed = TRUE) + cocite_mat <- matrix(8, 10, 10) - diag(8, 10) + expect_equal(cocitation(g), cocite_mat) +}) + +test_that("bibcoupling works", { + g <- make_full_graph(10, directed = TRUE) + bib_mat <- matrix(8, 10, 10) - diag(8, 10) + expect_equal(bibcoupling(g), bib_mat) +}) diff --git a/tests/testthat/test-minimum.spanning.tree.R b/tests/testthat/test-minimum.spanning.tree.R new file mode 100644 index 0000000000..c6422d7a38 --- /dev/null +++ b/tests/testthat/test-minimum.spanning.tree.R @@ -0,0 +1,41 @@ +test_that("mst works", { + g <- graph_from_data_frame( + data.frame( + from = c(1, 1, 2, 2, 2, 3, 4), + to = c(2, 3, 3, 4, 5, 5, 5), + weight = c(1, 7, 5, 4, 3, 6, 2) + ), + directed = FALSE + ) + mst_true <- graph_from_data_frame( + data.frame( + from = c(1, 2, 2, 4), + to = c(2, 3, 5, 5), + weight = c(1, 5, 3, 2) + ), + directed = FALSE + ) + mst_g <- mst(g) + expect_isomorphic(mst_g, mst_true) + + mst_g_prim <- mst(g, algorithm = "prim") + expect_isomorphic(mst_g_prim, mst_true) + + mst_g_unweighted <- mst(g, algorithm = "unweighted") + mst_true_unweighted <- graph_from_data_frame( + data.frame( + from = c(1, 1, 2, 2), + to = c(2, 3, 4, 5) + ), + directed = FALSE + ) + expect_isomorphic(mst_g_unweighted, mst_true_unweighted) +}) + +test_that("mst error works", { + g <- sample_gnp(10, 0.4) + expect_snapshot( + mst(g, algorithm = "undefined"), + error = TRUE + ) +}) diff --git a/tests/testthat/test-similarity.R b/tests/testthat/test-similarity.R new file mode 100644 index 0000000000..f75eaaae7c --- /dev/null +++ b/tests/testthat/test-similarity.R @@ -0,0 +1,30 @@ +test_that("similarity works", { + g <- make_ring(5) + sim_dice <- similarity(g, method = "dice") + + sim_dice_true <- matrix( + c( + 1, 0, 0.5, 0.5, 0, + 0, 1, 0, 0.5, 0.5, + 0.5, 0, 1, 0, 0.5, + 0.5, 0.5, 0, 1, 0, + 0, 0.5, 0.5, 0, 1 + ), + nrow = 5L, + ncol = 5L + ) + expect_equal(sim_dice, sim_dice_true) + + sim_jac <- similarity(g, method = "jaccard") + sim_jac_true <- matrix( + c( + 1, 0, 0.3333333333333333, 0.3333333333333333, 0, 0, 1, 0, 0.3333333333333333, + 0.3333333333333333, 0.3333333333333333, 0, 1, 0, 0.3333333333333333, + 0.3333333333333333, 0.3333333333333333, 0, 1, 0, 0, 0.3333333333333333, + 0.3333333333333333, 0, 1 + ), + nrow = 5L, + ncol = 5L + ) + expect_equal(sim_jac, sim_jac_true) +}) diff --git a/tests/testthat/test-stochastic_matrix.R b/tests/testthat/test-stochastic_matrix.R new file mode 100644 index 0000000000..036efb5f32 --- /dev/null +++ b/tests/testthat/test-stochastic_matrix.R @@ -0,0 +1,16 @@ +test_that("stochastic_matrix works", { + g <- make_star(5, "undirected") + adj_mat <- as_adjacency_matrix(g) + stoch_mat_manual <- adj_mat / degree(g) + stoch_mat_calc <- stochastic_matrix(g) + expect_equal( + as_unnamed_dense_matrix(stoch_mat_manual), + as_unnamed_dense_matrix(stoch_mat_calc) + ) + + stoch_mat_calc_col <- stochastic_matrix(g, column.wise = TRUE) + expect_equal( + t(as_unnamed_dense_matrix(stoch_mat_manual)), + as_unnamed_dense_matrix(stoch_mat_calc_col) + ) +})