From 1b2ece3aa9daea4ad275706a352b6ef79e262513 Mon Sep 17 00:00:00 2001 From: Krause Date: Mon, 20 Apr 2026 20:09:38 -0400 Subject: [PATCH 01/20] fixing prcheck - i hope --- .github/workflows/prchecks.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/prchecks.yml b/.github/workflows/prchecks.yml index 9e541a0..b58bd2c 100644 --- a/.github/workflows/prchecks.yml +++ b/.github/workflows/prchecks.yml @@ -40,6 +40,7 @@ jobs: any::rcmdcheck - uses: r-lib/actions/check-r-package@v2 + env: _R_CHECK_FORCE_SUGGESTS_: false with: upload-snapshots: true From 59d4c10be8c0d3e6eed1af9b7a0ede0a68f54f93 Mon Sep 17 00:00:00 2001 From: Krause Date: Mon, 20 Apr 2026 20:16:44 -0400 Subject: [PATCH 02/20] .... --- tests/testthat.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/testthat.R b/tests/testthat.R index b1f9df7..369df81 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,6 +1,4 @@ library(testthat) library(infernet) -stocnet_theme("default") -test_check("infernet") devtools::test_coverage(pkg = "infernet", type = "tests") From a936060fa5a391ac782a2ae2326935beed1c910a Mon Sep 17 00:00:00 2001 From: James Hollway Date: Thu, 23 Apr 2026 11:28:08 +0200 Subject: [PATCH 03/20] Fixed testing issue --- tests/testthat.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat.R b/tests/testthat.R index 369df81..f5a8c68 100644 --- a/tests/testthat.R +++ b/tests/testthat.R @@ -1,4 +1,4 @@ library(testthat) library(infernet) -devtools::test_coverage(pkg = "infernet", type = "tests") +test_check("infernet") From 53ab5824ee8ad41b4a714ff5eda3aa14ac49c669 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Thu, 23 Apr 2026 11:32:02 +0200 Subject: [PATCH 04/20] Added logos --- inst/logo.png | Bin 0 -> 166102 bytes man/figures/logo.png | Bin 0 -> 166102 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 inst/logo.png create mode 100644 man/figures/logo.png diff --git a/inst/logo.png b/inst/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..7997505f1b05c5c8db0e13e142cde739b5e3c83c GIT binary patch literal 166102 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 hr~dnYKUBtWl$r&4T? Date: Thu, 23 Apr 2026 11:41:46 +0200 Subject: [PATCH 05/20] Fixed model_tests documentation --- DESCRIPTION | 10 ++++------ R/model_tests.R | 13 +++++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 5ecb80e..4993fac 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,7 +1,7 @@ Package: infernet Title: Basic inferential models for many different types of networks Version: 0.1.0 -Date: 2025-06-23 +Date: 2026-04-23 Description: TBD. URL: https://stocnet.github.io/infernet/ BugReports: https://github.com/stocnet/infernet/issues @@ -11,7 +11,8 @@ Encoding: UTF-8 LazyData: true RoxygenNote: 7.3.3 Depends: - R (>= 3.6.0) + R (>= 3.6.0), + manynet Authors@R: c(person(given = "James", family = "Hollway", @@ -29,11 +30,8 @@ Imports: furrr, future, future.apply, - manynet, purrr, - reformulas, - stats, - utils + reformulas Suggests: lme4, nnet, diff --git a/R/model_tests.R b/R/model_tests.R index 9139743..f7ebf75 100644 --- a/R/model_tests.R +++ b/R/model_tests.R @@ -23,10 +23,10 @@ NULL #' @rdname tests #' @importFrom manynet generate_random bind_node_attributes is_directed is_complex #' @examples -#' marvel_friends <- to_unsigned(ison_marvel_relationships) -#' marvel_friends <- to_giant(marvel_friends) %>% +#' marvel_friends <- fict_marvel %>% to_uniplex("relationship") %>% +#' to_unsigned() %>% to_giant() %>% #' to_subgraph(PowerOrigin == "Human") -#' (cugtest <- test_random(marvel_friends, manynet::net_heterophily, attribute = "Attractive", +#' (cugtest <- test_random(marvel_friends, net_by_heterophily, attribute = "Attractive", #' times = 200)) #' # plot(cugtest) #' @export @@ -86,7 +86,8 @@ test_configuration <- function(.data, FUN, ..., } oplan <- future::plan(strategy) on.exit(future::plan(oplan), add = TRUE) - rands <- furrr::future_map(1:times, manynet::generate_configuration, n = .data, + rands <- furrr::future_map(1:times, + ~ manynet::generate_configuration(.data), .progress = verbose, .options = furrr::furrr_options(seed = T)) if (length(args) > 0) { @@ -118,7 +119,7 @@ test_configuration <- function(.data, FUN, ..., #' @rdname tests #' @examples #' # (qaptest <- test_permutation(marvel_friends, -#' # manynet::net_heterophily, attribute = "Attractive", +#' # net_by_heterophily, attribute = "Attractive", #' # times = 200)) #' # plot(qaptest) #' @export @@ -133,7 +134,7 @@ test_permutation <- function(.data, FUN, ..., obsd <- FUN(.data) } n <- manynet::net_dims(.data) - d <- manynet::net_density(.data) + d <- netrics::net_by_density(.data) oplan <- future::plan(strategy) on.exit(future::plan(oplan), add = TRUE) rands <- furrr::future_map(1:times, From c4f6822f0ba486358961d7d8d420eb93031144c0 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Tue, 28 Apr 2026 10:18:05 +0200 Subject: [PATCH 06/20] Verbose now draws from global (snet) option, added parameter definition for strategy, and updated example --- R/model_tests.R | 14 ++++++++++---- man/tests.Rd | 25 +++++++++++++------------ 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/R/model_tests.R b/R/model_tests.R index f7ebf75..7a58b35 100644 --- a/R/model_tests.R +++ b/R/model_tests.R @@ -1,7 +1,7 @@ # Tests of network measures #### #' Tests of network measures -#' +#' @name tests #' @description #' These functions conduct tests of any network-level statistic: #' @@ -12,8 +12,14 @@ #' of a measure against a distribution of measures on permutations #' of the original network. #' -#' @name tests #' @inheritParams regression +#' @param strategy If `{furrr}` is installed, +#' then multiple cores can be used to accelerate the function. +#' By default `"sequential"`, +#' but if multiple cores available, +#' then `"multisession"` or `"multicore"` may be useful. +#' Generally this is useful only when `times` > 1000. +#' See [`{furrr}`](https://furrr.futureverse.org) for more. #' @family models #' @param FUN A graph-level statistic function to test. #' @param ... Additional arguments to be passed on to FUN, @@ -32,8 +38,8 @@ NULL #' @export test_random <- function(.data, FUN, ..., times = 1000, - strategy = "sequential", - verbose = FALSE){ + strategy = "sequential"){ + verbose <- ifelse(is.null(getOption("snet_verbosity")), FALSE, getOption("snet_verbosity") == "verbose") args <- unlist(list(...)) if (!is.null(args)) { obsd <- FUN(.data, args) diff --git a/man/tests.Rd b/man/tests.Rd index 938a09e..ef2815c 100644 --- a/man/tests.Rd +++ b/man/tests.Rd @@ -7,14 +7,7 @@ \alias{test_permutation} \title{Tests of network measures} \usage{ -test_random( - .data, - FUN, - ..., - times = 1000, - strategy = "sequential", - verbose = FALSE -) +test_random(.data, FUN, ..., times = 1000, strategy = "sequential") test_configuration( .data, @@ -47,6 +40,14 @@ e.g. the name of the attribute.} \item{times}{Integer. Number of permutations for the null distribution. 1000 is the default; publication-ready work usually needs 1000-10000.} + +\item{strategy}{If \code{{furrr}} is installed, +then multiple cores can be used to accelerate the function. +By default \code{"sequential"}, +but if multiple cores available, +then \code{"multisession"} or \code{"multicore"} may be useful. +Generally this is useful only when \code{times} > 1000. +See \href{https://furrr.futureverse.org}{\code{{furrr}}} for more.} } \description{ These functions conduct tests of any network-level statistic: @@ -60,14 +61,14 @@ of the original network. } } \examples{ -marvel_friends <- to_unsigned(ison_marvel_relationships) -marvel_friends <- to_giant(marvel_friends) \%>\% +marvel_friends <- fict_marvel \%>\% to_uniplex("relationship") \%>\% + to_unsigned() \%>\% to_giant() \%>\% to_subgraph(PowerOrigin == "Human") -(cugtest <- test_random(marvel_friends, manynet::net_heterophily, attribute = "Attractive", +(cugtest <- test_random(marvel_friends, net_by_heterophily, attribute = "Attractive", times = 200)) # plot(cugtest) # (qaptest <- test_permutation(marvel_friends, -# manynet::net_heterophily, attribute = "Attractive", +# net_by_heterophily, attribute = "Attractive", # times = 200)) # plot(qaptest) } From 96be71b552bc6f02f5a1be1558f81df00ba545f0 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Tue, 28 Apr 2026 10:18:19 +0200 Subject: [PATCH 07/20] Renamed logo --- inst/{logo.png => infernet.png} | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename inst/{logo.png => infernet.png} (100%) diff --git a/inst/logo.png b/inst/infernet.png similarity index 100% rename from inst/logo.png rename to inst/infernet.png From 643c99112576688bfc3f474714ac2911995d4ad4 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Tue, 28 Apr 2026 10:21:22 +0200 Subject: [PATCH 08/20] Added netrics as a dependency --- .Rbuildignore | 2 ++ .gitignore | 1 + DESCRIPTION | 3 ++- R/infernet-package.R | 20 ++++++++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 R/infernet-package.R diff --git a/.Rbuildignore b/.Rbuildignore index fb10167..03158ed 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -18,3 +18,5 @@ vignettes/precompile\.R ^CRAN-SUBMISSION$ ^README\.Rmd$ ^.mailmap$ +^\.positai$ +^\.claude$ diff --git a/.gitignore b/.gitignore index 02df9f1..580f8ab 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ CRAN-SUBMISSION toadd/* .data.csv cache/* +.positai diff --git a/DESCRIPTION b/DESCRIPTION index 4993fac..6fdd744 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -12,7 +12,8 @@ LazyData: true RoxygenNote: 7.3.3 Depends: R (>= 3.6.0), - manynet + manynet, + netrics Authors@R: c(person(given = "James", family = "Hollway", diff --git a/R/infernet-package.R b/R/infernet-package.R new file mode 100644 index 0000000..f2354ee --- /dev/null +++ b/R/infernet-package.R @@ -0,0 +1,20 @@ +# nocov start + +#' @keywords internal +"_PACKAGE" + +## usethis namespace: start +## usethis namespace: end +NULL + +# Suppress R CMD check note +# Namespace in Imports field not imported from: PKG +# All declared Imports should be used. +#' @importFrom netrics net_by_heterophily +ignore_unused_imports <- function() { + # This function exists only to reference functions and suppress R CMD check notes about unused imports. + netrics::net_by_heterophily + NULL +} + +# nocov end From 2039a0df253ac1dd6d159626dd5975241780af3a Mon Sep 17 00:00:00 2001 From: James Hollway Date: Tue, 28 Apr 2026 10:43:34 +0200 Subject: [PATCH 09/20] Fixed dependency issues --- DESCRIPTION | 9 +++++---- NAMESPACE | 1 + R/model_tests.R | 8 ++++---- R/zzz.R | 5 ++--- man/infernet-package.Rd | 30 ++++++++++++++++++++++++++++++ man/tests.Rd | 18 ++---------------- 6 files changed, 44 insertions(+), 27 deletions(-) create mode 100644 man/infernet-package.Rd diff --git a/DESCRIPTION b/DESCRIPTION index 6fdd744..13803ea 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,8 +1,11 @@ Package: infernet Title: Basic inferential models for many different types of networks Version: 0.1.0 -Date: 2026-04-23 -Description: TBD. +Date: 2026-04-28 +Description: A set of tools for testing networks. + It includes functions for univariate and multivariate + conditional uniform graph and quadratic assignment procedure testing, + and network regression. URL: https://stocnet.github.io/infernet/ BugReports: https://github.com/stocnet/infernet/issues License: MIT + file LICENSE @@ -26,8 +29,6 @@ Authors@R: comment = c(ORCID = "0000-0003-4288-4732")) ) Imports: - cli, - dplyr, furrr, future, future.apply, diff --git a/NAMESPACE b/NAMESPACE index 2711a77..7a081b9 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -14,3 +14,4 @@ importFrom(manynet,generate_configuration) importFrom(manynet,generate_random) importFrom(manynet,is_complex) importFrom(manynet,is_directed) +importFrom(netrics,net_by_heterophily) diff --git a/R/model_tests.R b/R/model_tests.R index 7a58b35..8e3d445 100644 --- a/R/model_tests.R +++ b/R/model_tests.R @@ -82,8 +82,8 @@ test_random <- function(.data, FUN, ..., #' @export test_configuration <- function(.data, FUN, ..., times = 1000, - strategy = "sequential", - verbose = FALSE){ + strategy = "sequential"){ + verbose <- ifelse(is.null(getOption("snet_verbosity")), FALSE, getOption("snet_verbosity") == "verbose") args <- unlist(list(...)) if (!is.null(args)) { obsd <- FUN(.data, args) @@ -131,8 +131,8 @@ test_configuration <- function(.data, FUN, ..., #' @export test_permutation <- function(.data, FUN, ..., times = 1000, - strategy = "sequential", - verbose = FALSE){ + strategy = "sequential"){ + verbose <- ifelse(is.null(getOption("snet_verbosity")), FALSE, getOption("snet_verbosity") == "verbose") args <- unlist(list(...)) if (!is.null(args)) { obsd <- FUN(.data, args) diff --git a/R/zzz.R b/R/zzz.R index d6b4dbb..8710cd0 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -14,8 +14,7 @@ # cran_version <- pkgs[pkgs$Package == "manynet","Version"] local_version <- utils::packageVersion("infernet") - cli::cli_inform("You are using {.pkg infernet} version {.version {local_version}}.", - class = "packageStartupMessage") + manynet::snet_info("You are using {.pkg infernet} version {.version {local_version}}.") old.list <- as.data.frame(utils::old.packages()) behind_cran <- "infernet" %in% old.list$Package @@ -32,7 +31,7 @@ # "i" = "You can list all the tutorials available in {.pkg manynet} using {.fn run_tute}, and run them too!", "i" = "Discover all the {.emph stocnet} R packages at {.url https://github.com/stocnet/}." ) - cli::cli_inform(sample(tips, 1), class = "packageStartupMessage") + manynet::snet_info(sample(tips, 1)) } if (interactive()) { diff --git a/man/infernet-package.Rd b/man/infernet-package.Rd new file mode 100644 index 0000000..5859ad3 --- /dev/null +++ b/man/infernet-package.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/infernet-package.R +\docType{package} +\name{infernet-package} +\alias{infernet} +\alias{infernet-package} +\title{infernet: Basic inferential models for many different types of networks} +\description{ +\if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} + +A set of tools for testing networks. It includes functions for univariate and multivariate conditional uniform graph and quadratic assignment procedure testing, and network regression. +} +\seealso{ +Useful links: +\itemize{ + \item \url{https://stocnet.github.io/infernet/} + \item Report bugs at \url{https://github.com/stocnet/infernet/issues} +} + +} +\author{ +\strong{Maintainer}: James Hollway \email{james.hollway@graduateinstitute.ch} (\href{https://orcid.org/0000-0002-8361-9647}{ORCID}) (IHEID) [contributor] + +Other contributors: +\itemize{ + \item Robert Krause (\href{https://orcid.org/0000-0003-4288-4732}{ORCID}) [contributor] +} + +} +\keyword{internal} diff --git a/man/tests.Rd b/man/tests.Rd index ef2815c..c2469f6 100644 --- a/man/tests.Rd +++ b/man/tests.Rd @@ -9,23 +9,9 @@ \usage{ test_random(.data, FUN, ..., times = 1000, strategy = "sequential") -test_configuration( - .data, - FUN, - ..., - times = 1000, - strategy = "sequential", - verbose = FALSE -) +test_configuration(.data, FUN, ..., times = 1000, strategy = "sequential") -test_permutation( - .data, - FUN, - ..., - times = 1000, - strategy = "sequential", - verbose = FALSE -) +test_permutation(.data, FUN, ..., times = 1000, strategy = "sequential") } \arguments{ \item{.data}{A manynet-consistent network (see From 9a7bf47d77ef62ddea32c27aeb670e99e71f0dcd Mon Sep 17 00:00:00 2001 From: James Hollway Date: Tue, 28 Apr 2026 12:36:13 +0200 Subject: [PATCH 10/20] Dropped cli importFrom --- NAMESPACE | 4 +--- R/zzz.R | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/NAMESPACE b/NAMESPACE index 7a081b9..4f4e187 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,12 +6,10 @@ export(net_regression) export(test_configuration) export(test_permutation) export(test_random) -importFrom(cli,cli_div) -importFrom(cli,cli_end) -importFrom(cli,cli_inform) importFrom(manynet,bind_node_attributes) importFrom(manynet,generate_configuration) importFrom(manynet,generate_random) importFrom(manynet,is_complex) importFrom(manynet,is_directed) +importFrom(manynet,snet_info) importFrom(netrics,net_by_heterophily) diff --git a/R/zzz.R b/R/zzz.R index 8710cd0..081bc53 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,4 +1,4 @@ -#' @importFrom cli cli_div cli_inform cli_end +#' @importFrom manynet snet_info .onAttach <- function(...) { # suppressMessages(suppressPackageStartupMessages(library("manynet", warn.conflicts = FALSE))) From 56306e0110f8f5fdf209436d362951c5a8f6f4f7 Mon Sep 17 00:00:00 2001 From: Robert Krause <43546240+RWKrause@users.noreply.github.com> Date: Tue, 18 Aug 2026 09:49:41 +0200 Subject: [PATCH 11/20] fix x --- R/model_regression.R | 171 +++++++++++++++++++++++++------------------ 1 file changed, 100 insertions(+), 71 deletions(-) diff --git a/R/model_regression.R b/R/model_regression.R index d025ece..cedfd24 100644 --- a/R/model_regression.R +++ b/R/model_regression.R @@ -72,7 +72,8 @@ #' @importFrom purrr flatten #' @importFrom future plan #' @importFrom furrr future_map_dfr furrr_options -#' @importFrom stats glm.fit as.formula df.residual pchisq +#' @importFrom stats as.formula lm glm fitted.values residuals coefficients +#' @importFrom lme4 lmer glmer deviance.merMod #' @references #' Krackhardt, David. 1988. #' “Predicting with Networks: Nonparametric Multiple Regression Analysis of Dyadic Data.” @@ -98,7 +99,7 @@ net_regression <- function(formula, times = 1000, control = list(method = c("qap","qapy"), strategy = "sequential", - family = "gaussian", + family = "auto", estimator = "auto", seed = NULL, groups = NULL, @@ -122,65 +123,76 @@ net_regression <- function(formula, n <- dim(g[[1]]) directed <- ifelse(manynet::is_directed(g[[1]]), "digraph", "graph") - valued <- manynet::is_weighted(g[[1]]) diag <- manynet::is_complex(g[[1]]) + valued <- manynet::is_weighted(g[[1]]) && family == "auto" base_data <- vectorise_list(g, simplex = !diag, directed = (directed == "digraph")) # Base #### + fit <- list() + if (valued) { - fit.base <- lm(convForm,base_data) - - - fit.base <- nlmfit(g, - directed = directed, - diag = diag, - rety = TRUE) - fit <- list() - fit$coefficients <- coefficients(fit.base) - fit$fitted.values <- fitted.values(fit.base) - fit$residuals <- residuals(fit.base) - fit$qr <- fit.base$qr - fit$rank <- fit.base$rank + if (!rand) { + fit$base <- stats::lm(formula, data = base_data) + fit$coefficients <- stats::coefficients(fit$base) + } else { + fit$base <- lme4::lmer(formula, data = base_data) + fit$coefficients <- fit.base@beta + } + + fit$fitted.values <- stats::fitted.values(fit$base) + fit$residuals <- stats::residuals(fit$base) + fit$rank <- length(fit$coefficients) fit$n <- length(fit$fitted.values) fit$df.residual <- fit$n - fit$rank - fit$tstat <- fit$coefficients / sqrt(diag(vcov(fit.base))) + fit$tstat <- fit$coefficients / sqrt(diag(vcov(fit$base))) } else { - fit.base <- nlgfit(g, - directed = directed, - diag = diag) - fit <- list() - fit$coefficients <- fit.base$coefficients - fit$fitted.values <- fit.base$fitted.values - fit$residuals <- fit.base$residuals - fit$se <- sqrt(diag(chol2inv(fit.base$qr$qr))) - fit$tstat <- fit$coefficients/fit$se - fit$linear.predictors <- fit.base$linear.predictors - fit$n <- length(fit.base$y) - fit$df.model <- fit.base$rank - fit$df.residual <- fit.base$df.residual - fit$deviance <- fit.base$deviance - fit$null.deviance <- fit.base$null.deviance - fit$df.null <- fit.base$df.null - fit$rank <- fit.base$rank - fit$aic <- fit.base$aic - fit$bic <- fit$deviance + fit$df.model * log(fit$n) - fit$qr <- fit.base$qr + if (family == "auto") { + family <- "binomial" + } + if (!rand) { + fit$base <- stats::glm(formula, data = base_data, family = family) + fit$coefficients <- stats::coefficients(fit$base) + fit$deviance <- fit.base$deviance + fit$null.deviance <- fit.base$null.deviance + fit$df.null <- fit.base$df.null + fit$aic <- fit.base$aic + fit$bic <- fit$deviance + fit$rank * log(fit$n) + } else { + fit$base <- lme4::glmer(formula, data = base_data, family = family) + fit$coefficients <- fit.base@beta + fit.base.sum <- summary(fit$base) + fit$deviance <- lme4:::deviance.merMod(fit$base) + fit$aic <- fit.base.sum$AICtab["AIC"] + fit$bic <- fit.base.sum$AICtab["BIC"] + # null model stuff not directly defined for mixed models... + } + fit$fitted.values <- fitted.values(fit$base) + fit$residuals <- residuals(fit$base) + fit$tstat <- fit$coefficients / sqrt(diag(vcov(fit$base))) + fit$fitted.values <- stats::fitted.values(fit$base) + fit$n <- length(fit$fitted.values) + fit$rank <- length(fit$coefficients) + fit$df.residual <- fit$n - fit$rank + fit$ctable <- table(as.numeric(fit$fitted.values >= 0.5), - fit.base$y, dnn = c("Predicted", "Actual")) + base_data[[getDependentName(formula)]], + dnn = c("Predicted", "Actual")) if (NROW(fit$ctable) == 1) { - if (rownames(fit$ctable) == "0") + if (rownames(fit$ctable) == "0") { fit$ctable <- rbind(fit$ctable, c(0, 0)) - else fit$ctable <- rbind(c(0, 0), fit$ctable) + } else { + fit$ctable <- rbind(c(0, 0), fit$ctable) + } rownames(fit$ctable) <- c("0", "1") } } # Null #### # qapy for univariate #### - if (method == "qapy" | nx == 2) { + if (method == "qapy" || nx == 1) { # why was nx == 2? oplan <- future::plan(strategy) on.exit(future::plan(oplan), add = TRUE) if (valued) { @@ -244,19 +256,20 @@ net_regression <- function(formula, 2, mean) fit$pgreq <- apply(sweep(fit$dist, 2, fit$tstat, ">="), 2, mean) - fit$pgreqabs <- apply(sweep(abs(fit$dist), 2, abs(fit$tstat), - ">="), 2, mean) - if (method == "qapy" | nx == 2) + fit$pgreqabs <- apply(sweep(abs(fit$dist), 2, abs(fit$tstat), ">="), 2, mean) + if (method == "qapy" | nx == 2) { fit$nullhyp <- "QAPy" - else fit$nullhyp <- "QAP-DSP" + } else { + fit$nullhyp <- "QAP-DSP" + } fit$names <- names(matrixList)[-1] fit$intercept <- TRUE - if (valued) + if (valued) { class(fit) <- "netlm" - else + } else { class(fit) <- "netlogit" - fit - + } + return(fit) } ################### auxilliary ---- @@ -274,27 +287,26 @@ gettval <- function(x, y, tol) { coef/se } -nlmfit <- function(glist, directed, diag, rety) { - z <- as.matrix(vectorise_list(glist, simplex = !diag, - directed = (directed == "digraph"))) - if (!rety) { - gettval(z[,2:ncol(z)], z[,1], tol = 1e-07) - } - else { - list(qr(z[,2:ncol(z)], tol = 1e-07), z[,1]) - } -} +#nlmfit <- function(glist, directed, diag, rety) { +# z <- as.matrix(vectorise_list(glist, simplex = !diag, +# directed = (directed == "digraph"))) +# if (!rety) { +# gettval(z[,2:ncol(z)], z[,1], tol = 1e-07) +# } +# else { +# list(qr(z[,2:ncol(z)], tol = 1e-07), z[,1]) +# } +#} +# +##' @importFrom stats binomial +#nlgfit <- function(glist, directed, diag) { +# z <- as.matrix(vectorise_list(glist, simplex = !diag, +# directed = (directed == "digraph"))) +# stats::glm.fit(z[,2:ncol(z)], z[,1], +# family = stats::binomial(), intercept = FALSE) +#} -#' @importFrom stats binomial -nlgfit <- function(glist, directed, diag) { - z <- as.matrix(vectorise_list(glist, simplex = !diag, - directed = (directed == "digraph"))) - stats::glm.fit(z[,2:ncol(z)], z[,1], - family = stats::binomial(), intercept = FALSE) -} - -vecto -rise_list <- function(glist, simplex, directed){ +vectorise_list <- function(glist, simplex, directed){ if (missing(simplex)) { simplex <- !manynet::is_complex(glist[[1]]) } @@ -308,8 +320,8 @@ rise_list <- function(glist, simplex, directed){ glist[[1]][upper.tri(glist[[1]])] <- NA } - furrr::future_map( - glist,function(x) c(x)) %>% + furrr::future_map(glist,function(x) { + c(x)}) %>% dplyr::bind_cols() %>% stats::na.omit() %>% suppressMessages() @@ -625,3 +637,20 @@ specificationAdvice <- function(formula, data) { } } } + +logit_moments <- function(theta, data) { + Y <- data$y + X <- data$x + prob <- 1 / (1 + exp(-1 * (X %*% theta))) + residuals <- as.vector(Y - prob) + g <- residuals * X + return(g) +} + +logit_resid <- function(gmmo) { + Y <- gmmo$dat$y + X <- gmmo$dat$x + prob <- 1 / (1 + exp(-1 * (X %*% gmmo$coefficients))) + residuals <- as.vector(Y - prob) + return(residuals) +} From 46f399dc21e232b574e639eb81e6f78261ddb7f9 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:12:31 +0200 Subject: [PATCH 12/20] Added clearer direction for contributors --- .Rbuildignore | 3 + .github/CONTRIBUTING.md | 521 ++++++++++++++++++++++++++++++++++++---- CLAUDE.md | 29 +++ 3 files changed, 507 insertions(+), 46 deletions(-) create mode 100644 CLAUDE.md diff --git a/.Rbuildignore b/.Rbuildignore index 03158ed..c8bddc1 100644 --- a/.Rbuildignore +++ b/.Rbuildignore @@ -20,3 +20,6 @@ vignettes/precompile\.R ^.mailmap$ ^\.positai$ ^\.claude$ +^CLAUDE\.md$ +^\.Rhistory$ +^\.RData$ diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 5e6cf14..d4e458b 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -4,7 +4,11 @@ Contributions to `infernet`, whether in the form of issue identification, bug fixes, new code or documentation are encouraged and welcome. -## Git and Bitbucket +Please note that the `infernet` project is released with a +[Contributor Code of Conduct](CODE_OF_CONDUCT.md). +By contributing to this project, you agree to abide by its terms. + +## Git `stocnet` projects are maintained using the git version control system. A plain-English introduction to git can be found [here](https://blog.red-badger.com/2016/11/29/gitgithub-in-plain-english). @@ -18,32 +22,38 @@ but I recommend [Fork](https://git-fork.com) software for Mac and Windows. This allows mostly visual management of commits, diffs, branches, etc. There are various other git software packages available, but this one is fairly fully featured. -The Github page allows to access the issues assigned to you and check the commits. +The GitHub page allows to access the issues assigned to you and check the commits. You can also access the documents in the repository, although this won't be necessary after you have cloned it on your computer via Fork. -## Style +### Identifying issues -In terms of style, we are aiming for pleasant predictability in terms of user experience. -To that end, we have a regular syntax that users can rely on producing expected effects. +Please use the issues tracker on GitHub to identify any function-related issues. +You can use these issues to track progress on the issue and +to comment or continue a conversation on that issue. +The most useful issues are ones that precisely identify an error, +or propose a test that should pass but instead fails. +Examples for documentation are also most welcome. -## Fork +Issues that belong to another package in the family should be transferred there +rather than fixed here: `gh issue transfer stocnet/`. +See the division of labour below. ### Cloning + Once you have downloaded Fork, the first thing you have to do is to clone the remote repository on your computer. Before cloning, you will be able to choose on which `branch` you want to work: develop or main. -### Pull -This command allows you to `pull` changes from the remote repository to your local repository on Sourcetree. +### Pull + +This command allows you to `pull` changes from the remote repository to your local repository. Make sure you do that before starting working on your files so you have the newest versions. -When pulling, make sure you choose master or develop, +When pulling, make sure you choose main or develop, depending on the branch you decided to work with. Once you pulled, you have now all the new commits and files and you can start working on your assigned tasks. -Note that you can access and open the files either from the Finder or from Fork. -Some documents might be stored using Large File Storage (LFS) to save space on the repository. ### Commit and Push @@ -51,55 +61,474 @@ Once you have made modifications on a file and saved them, it will appear in you Here you can control one last time your file, write the commit message with the issue reference (see below) and commit. Once your commit is ready, you can `push` them to the origin/main repository. -Note that you can click the "push immediately" box in the commit window -if you don't want to do it in two steps. If you are working on a separate branch, it is important to select this branch when pushing to origin/main. -## Issues and tests +Commits may reference an existing GitHub issue number. +Where the issue number is preceded by `resolve`/`resolves`/`resolved`, +`close`/`closes`/`closed`, or `fix`/`fixes`/`fixed` (capitalised or not), +GitHub updates the status of the issue automatically. -Please use the issues tracker on Github to identify any function-related issues. -You can use these issues to track progress on the issue and -to comment or continue a conversation on that issue. -Currently issue tracking is only open to those involved in the project. +### Branching and CI + +- `main` is the release branch; `develop` is the working branch (clone/work on `develop`). +- PRs into `main` trigger [prchecks.yml](workflows/prchecks.yml): R CMD check + (macOS/Windows/Linux), binary build, codecov, lintr, spell check, + and PR metadata checks (DESCRIPTION version bump, PR title/description conventions). +- Merges/pushes to `main` trigger [pushrelease.yml](workflows/pushrelease.yml): + check, auto-bump version tag, GitHub release with binaries and release notes + taken from `NEWS.md`, then pkgdown site deploy. +- The PR metadata job requires that each PR into `main` bumps the `Version:` field in + `DESCRIPTION` by the appropriate increment, names that new version in the PR title, + and itemizes its changes in the PR description under `##` subsection titles matching + the `NEWS.md` conventions below. +- Development dependencies are declared in `DESCRIPTION` under `Config/Needs/build`, + `Config/Needs/check`, and `Config/Needs/website` rather than `Suggests` — + the workflows install them via `needs:` in `setup-r-dependencies`. +- A merge that touches [R/model_regression.R](../R/model_regression.R) or the + `R/qap_*.R` engine files deserves a parse check before it is pushed + (`Rscript -e 'devtools::load_all()'`). + The merge that created the current engine silently dropped three function + headers and left an orphan function body, so the package did not parse at all. + +## Style + +In terms of style, we are aiming for "pleasant predictability" in terms of user experience. +To that end, we have a regular syntax that users can rely on producing expected effects. +Functions in the same family (`test_*()`, etc.) should share +argument order and naming, so that behaviour is guessable across the family. + +We are also aiming for "declarative simplicity", +where functions carry as few arguments as possible to reduce the documentation burden, +as well as the burden on users to understand all of the options. +Use sensible defaults instead. +Function and argument names should also follow the house rules (see below). + +When writing documentation or NEWS items, prefer breaking lines at punctuation. + +Make it clear when you are referring to functions by adding backticks and parentheses, +e.g. `a_function()`, and arguments by adding an equals sign, e.g. `argument=`. +Argument values or variables can be in double quotation marks, e.g. "value". + +## Package architecture + +### Project overview + +`infernet` is an R package (part of the [stocnet](https://github.com/stocnet) ecosystem) +providing the *inferential layer* for network analysis: +conditional uniform graph (CUG) and quadratic assignment procedure (QAP) tests of network +statistics, and multiple regression QAP (MRQAP) for network data. +Because it builds on `{manynet}`, every function accepts matrices, edgelists, +`{igraph}`, `{network}`, `{tidygraph}` or `stocnet` objects, +and one-mode or two-mode networks alike. + +`infernet` combines two lines of work: + +- the formula front end, multimodal treatment, + and ease of use of `{migraph}`'s `net_regression()`, and +- the estimator range, missing-data handling, and cognitive social structure (CSS) + treatment of Robert Krause's `MrQAP`, which is where the `R/qap_*.R` engine + files were ported from. + +Division of labour to keep in mind when adding functions: + +- `{manynet}`: network classes/coercion (`as_*()`), making and manipulating networks, + and network-level logical tests (e.g. `is_directed()`, `is_twomode()`). +- `{netrics}`: everything analytic — marks, measures, memberships, motifs — + at the node, tie, and network level. +- `{autograph}`: drawing graphs and plotting analytic, modelling, or diagnostic results, + along with deep (often institutional) theming. *All* plot methods should live there. +- `{infernet}` (this package): testing and modelling, e.g. CUG/QAP/MRQAP. +- `{migraph}`: the software companion to *Multimodal Political Networks*, holding the + `mpn_*` datasets and the diffusion models. + `{migraph}` still carries older copies of `net_regression()` and the `test_*()` family; + those are what `{infernet}` supersedes, so a fix made there needs porting here, + and a fix made here does not need porting back. +- `{goldfish}`: another stocnet package for estimating network event models + such as relational event models and dynamic network actor models. + Note that these two packages, `{infernet}` and `{goldfish}`, + should reuse similar vocabulary and syntax where possible + to improve the "pleasant predictability" of each package. + +### Common commands + +This is a standard R package developed with `devtools`/`roxygen2`. +Run these from an R console with the working directory set to the package root +(or via `Rscript -e`). + +- Load package for interactive development: `devtools::load_all()` +- Regenerate docs & NAMESPACE after editing roxygen comments: `devtools::document()` +- Run full test suite: `devtools::test()` +- Run a single test file: `devtools::test(filter = "net_regression")` + (matches `test-net_regression.R`), or `testthat::test_file("tests/testthat/test-net_regression.R")` +- Full package check (mirrors CI): `devtools::check()` or `rcmdcheck::rcmdcheck()` +- Lint: `lintr::lint_package()` +- Spell check: `spelling::spell_check_package()` +- Code coverage: `covr::package_coverage()` +- Rebuild `README.md` from `README.Rmd`: `devtools::build_readme()` +- Check every topic is in the pkgdown index: `pkgdown::check_pkgdown()` +- Build pkgdown site locally: `pkgdown::build_site()` + +There is no non-R build system — no package.json/Makefile. +Roxygen is configured with `markdown = TRUE`; +`NAMESPACE` and all `man/*.Rd` files are generated — never hand-edit them. +Likewise `README.md` is generated from `README.Rmd` — edit the `.Rmd` and re-knit. + +### File organization + +`R/` files are grouped by theme rather than one file per function. +The user-facing files are named `model_*.R`; +the internal engine ported from `MrQAP` is named `qap_*.R`. + +| File | Contains | +|---|---| +| `model_tests.R` | the test family: `test_random()` (CUG), `test_configuration()`, `test_permutation()` (QAP), and `print.network_test()` | +| `model_regression.R` | `net_regression()`, the formula front end (`convertToMatrixList()`, `getRHSNames()`, `specificationAdvice()`), and the `print.*` methods for its results | +| `qap_engine.R` | `QAPglm()` and `QAPglmPermEst()` — the matrix-level engine that performs the baseline fit and the permutation inference | +| `qap_utils.R` | formula parsing, input validation, `future` plumbing, matrix permutation (`RMPerm()`), the model-fitting dispatcher `fit_qap_model()`, and the permutation aggregators | +| `qap_css.R` | `QAPcss()` and `QAPcssPermEst()` — the parallel engine for cognitive social structures | +| `qap_gmm.R` | GMM moment conditions and residual functions for the `estimator = "gmm"` path | +| `qap_gpu.R` | the optional `{torch}` batch OLS path, `gpu_batch_ols()` | +| `qap_confusion.R` | probabilistic confusion matrices for binary outcomes | +| `qap_misc.R` | small combining and reshaping helpers | +| `infernet-package.R` | package-level doc, global variables, and the shim silencing R CMD check's unused-import note | +| `zzz.R` | the attach-time greeting and the cached stocnet version check | + +Only `model_*.R` holds exported functions. +Everything in `qap_*.R` is internal, and carries `@keywords internal` and `@noRd`. +Keep it that way: the engine's argument names are the `MrQAP` ones, and +exporting them would freeze an interface we still intend to tidy. + +### The `net_regression()` pipeline + +`net_regression()` ([R/model_regression.R](../R/model_regression.R)) is the single +regression entry point. Its control flow is: + +1. Merge the user's `control` list over `.default_control()`, + so an unnamed entry falls back to the default rather than to `NULL`. +2. Dispatch on the input shape. + A single network goes to `convertToMatrixList()`; + a list of networks goes to `.prepare_list_of_graphs()`, which converts each + network, drops the ones that are missing a predictor with a warning, + and pools the rest. +3. Resolve `family = "auto"` against the dependent variable + (binomial for a 0/1 outcome, gaussian otherwise), and resolve `mode` and + `diag` from the network with `manynet::is_directed()` and `manynet::is_complex()`. +4. Call `QAPglm()`, which parses the formula, fits the baseline model once + via `fit_qap_model()`, then runs `reps` permutations and aggregates them. +5. Attach a probabilistic confusion matrix where the outcome is binary, + and class the result `net_regression`. + +Inside `QAPglm()` the null hypothesis decides the permutation scheme: +`"qapy"` permutes the dependent matrix only, while `"qapspp"` implements Dekker +et al.'s double semi-partialling, running one permutation set per main predictor +after residualising it against the others. +Permuted coefficients and test statistics are then compared against the baseline +by `compare_perm_to_baseline()` and reduced to `lower`/`larger`/`abs` +p-value matrices by `aggregate_perm_results()`. +`QAPcss()` mirrors this same permute-refit-aggregate architecture for CSS data. + +The formula front end accepts these terms, and a new one should be added +to `getRHSNames()` and `convertToMatrixList()` together: + +- `ego(attr)` — the sender's value of a nodal attribute, +- `alter(attr)` — the receiver's value, +- `same(attr)` — 1 where sender and receiver share an attribute value, +- `dist(attr)` — the absolute difference in a numeric attribute, +- `sim(attr)` — the proportional similarity in a numeric attribute, +- `tertius(attr, fn)` — an aggregate of an attribute over a node's other ties, +- a plain name — another network, used as a dyadic covariate. + +A formula is meant to be reusable across models, +so a term must mean the same thing whichever family or engine consumes it. +Where a term cannot apply, say so through `snet_abort()` rather than +silently dropping it. + +### Function body conventions + +Test functions consistently: + +1. Compute the observed statistic by applying the user-supplied `FUN` to `.data`. +2. Generate `times` random, configuration-preserving, or permuted networks + via the corresponding `{manynet}` generator (`generate_random()`, + `generate_configuration()`, `to_permuted()`), rebinding node attributes with + `manynet::bind_node_attributes()` where the statistic needs them. +3. Recompute `FUN` over each simulated network. +4. Return a `network_test` object recording the test type, observed value, + simulated distribution, one- and two-tailed p-values, + and the network's properties (`is_directed()`, `is_complex()`). + +Properties of the dependent network — modes, directedness, loops — must always be +respected in permutations and analysis; +one-mode and two-mode cases are branched on explicitly rather than projected away. +All `manynet`, `netrics`, `furrr`, and `future` calls use explicit `::` namespacing +(with per-file `@importFrom` roxygen tags for NAMESPACE generation). +Plot methods belong in `{autograph}`, not here. + +Every `print.*` method returns `invisible(x)`. +A print method that returns the result of its last `cat()` prints `NULL` when its +value is used, which is what `print.network_test()` did before this was fixed. + +### Parallelism + +Every simulation-heavy function takes: + +- `times` — the number of simulations (default `1000`; 1,000–10,000 for publication). +- `strategy` — a `{future}` plan name (default `"sequential"`; + `"multisession"`/`"multicore"` for multiple cores), + set with `future::plan(strategy)` and restored via `on.exit()`. + In `net_regression()` this is passed through the `control` list. + +The `test_*()` family maps simulations with `furrr::future_map*()` using +`furrr::furrr_options(seed = TRUE)` for reproducible parallel RNG. +The regression engine wraps the same machinery in `setup_future_plan()` and +`run_permutations()` ([R/qap_utils.R](../R/qap_utils.R)); use those rather than +calling `future::plan()` from a new engine function. + +Progress reporting is not a separate argument. +It is read from `options(snet_verbosity)`, so that one option governs how +talkative every stocnet package is. + +### Input shapes + +Most defects reported against this package are not wrong arithmetic. +They are a network shape the function did not expect. +Before finishing a function, run it on a signed, a weighted, a directed, a two-mode, +a multiplex, a multilevel and a longitudinal network, and decide each case deliberately. +Document each decision in the roxygen block with an `@section` named for the shape, +e.g. `@section Two-mode networks:`. + +Missing data deserves particular care here, since handling it well is a reason +this package exists. +An unobserved dyad is `NA`, never a zero tie and never a source's numeric code. +`make_qap_data()` drops NA and diagonal cells before fitting, so a predictor +that introduces `NA` silently shrinks the sample: +report what was dropped rather than letting the count change without comment. + +### Console messaging + +All user-facing messages go through the `snet_*()` wrappers exported by `{manynet}`, +rather than base `message()`/`stop()`/`warning()` or `{cli}` calls directly: + +| Wrapper | Use for | +|---|---| +| `snet_abort()` | errors: the function cannot proceed | +| `snet_warn()` | the function proceeds, but the user should know something | +| `snet_info()` | notable information about what was done, e.g. a defaulted argument or the method dispatched to | +| `snet_minor_info()` | incidental detail | +| `snet_success()` | confirmation that a requested operation completed | +| `snet_unavailable()` | not-yet-implemented features | + +Every wrapper except `snet_abort()` is silenced by +`options(snet_verbosity = "quiet")`, which is the *default* — +so informational output must never be load-bearing, +and errors must carry everything the user needs to act. +Users opt in with e.g. `options(snet_verbosity = "verbose")`. + +These wrappers pass their input to `{cli}`, so: + +- Braces interpolate, replacing `paste()`: `snet_abort("{.val {dep}} is not in the data.")`. +- Use `{cli}` inline classes to mark up what you refer to — `{.fn}` for functions, + `{.arg}`/`{.var}` for arguments and variables, `{.val}` for values, + `{.pkg}` for packages, `{.url}` for links. +- Use `{cli}`'s pluralisation rather than hand-written branches: + `snet_warn("Dropped {length(dropped)} network{?s}.")`. + +Prefer "`{.arg times}` must be a positive whole number" over "invalid input". +Where a function needs a package from `Suggests`, name it and say how to get it: +`snet_abort(c("The {.pkg lme4} package is required for random effects.", i = "Install it with {.run install.packages(\"lme4\")}."))`. + +The model specification advice printed by `specificationAdvice()` is +informational, not load-bearing, so it belongs at `snet_info()`. + +### Dependencies + +`infernet` `Depends` on `{manynet}` (network classes, coercion and logical tests) +and `{netrics}` (measures), and `Imports` the `{future}`/`{furrr}`/`{purrr}` +stack plus `{reformulas}` for formula surgery. + +Everything that only one estimator needs is in `Suggests`: +`lme4` and `glmmTMB` (random effects), `fixest` (fixed effects), +`gmm` (GMM estimation), `MASS` (negative binomial), `pscl` (zero-inflated Poisson), +`nnet` (multinomial), and `torch` (the GPU path). +A code path that depends on a suggested package must guard with +`requireNamespace()` and abort with an actionable message, +and its tests must `skip_if_not_installed()`. +Keeping these optional is deliberate: the common case — a gaussian or binomial +MRQAP — must install and run with no compiler and no heavy dependency tree. + +The declared minimum of each `stocnet` dependency is the version on CRAN, +so that CI can install it. +Where `infernet` needs something that only a newer, unreleased `{manynet}` has, +reach it through a shim rather than by raising the minimum, +and resolve the name at call time from the namespace. +Test for the function rather than for the version string, +because a pre-release development build can carry the version +without yet exporting the function. + +### Tests -The most useful issues are ones that precisely identify an error, -or propose a test that should pass but instead fails. This package uses the `testthat` package for testing functions. Please see the [testthat website](https://testthat.r-lib.org) for more details. +`testthat` edition 3 with parallel execution is configured in `DESCRIPTION` +(`Config/testthat/parallel: true`). +`Config/testthat/start-first` should prioritise the test files that take longest to run. -## Bug fixing or adding new code +Tests in `tests/testthat/` mirror the `R/` files +(e.g. `test-net_regression.R`, `test-zzz.R`). +Fixtures live in `tests/testthat/testdata/`. -Independent or assigned code contributions are most welcome. -When writing new code, please follow -[standard R guidelines](https://www.r-bloggers.com/🖊-r-coding-style-guide/). -It can help to use packages such as `lintr`, `goodpractice` and `formatR` -to ensure these are followed. +Three things are worth asserting for every estimator that is added: -Currently, commits can only be pushed to Bitbucket where they reference an existing issue. -If no issue exists for the code you have developed, please add an issue first before pushing. -Once the issue exists, you will need to mention the issue number (preceded by a hash symbol: #) -in the commit description: +1. That the baseline coefficients match those of the equivalent + `lm()`/`glm()` fit on the same vectorised data. + The permutation inference is what is novel; the point estimates are not, + and they should agree. +2. That a given `seed` reproduces the same p-values. + Permutation results are only comparable across runs if the RNG is, + and `furrr_options(seed = TRUE)` is what makes that true in parallel. +3. That the estimator is reached at all. + Several paths in `fit_qap_model()` are selected by a combination of `family`, + `estimator` and the random/fixed effects flags, + so a test that does not name that combination does not cover it. -``` Resolved #31 by adding a new function that does things, also updated documentation ``` +The aim is to work towards comprehensive coverage, +so each change should be fully covered by tests. +However, we also need to keep an eye on the clock: +CRAN complains if tests take too long, +so use small fixtures, low `times`, and `skip_on_cran()` for taxing tests. +`# nocov start` and `# nocov end` can be used to exclude lines or functions +that are too difficult to cover. -Where the issue hash (i.e. #31) is preceded by -`resolve`, `resolves`, `resolved`, `close`, `closes`, `closed`, `fix`, `fixes`, or `fixed` -(capitalised or not), -Github will automatically updated the status of the issue(s) mentioned. +### Documentation -Our current syntactical standard is to mention the issue first and then -provide a short description of what the committed changes do -in relation to that issue. -Any ancillary changes can be mentioned after a comma. +Roxygen is configured with `markdown = TRUE`; +`NAMESPACE` and all `man/*.Rd` files are generated — never hand-edit them. +Run `devtools::document()` after changing any roxygen comment. -## Documentation +- Related functions share one roxygen block via `@name`/`@rdname`, + matching the file organisation above. +- Document each argument once. + `net_regression()` takes its options through a `control` list, so document + each entry of that list as a bullet under `@param control` rather than as its + own `@param`. A stray `@param` for something that is no longer a formal + argument is an R CMD check warning, and the duplicated blocks that the + engine merge introduced were exactly that. +- Every exported function needs a runnable `@examples` block: + examples are run by R CMD check, and they are also the fastest documentation for users. + Prefer the bundled `ison_*`/`fict_*` networks from `{manynet}` over ad hoc + constructions, and keep `times` small so the example is fast. +- Use the native pipe `|>` in examples, never `%>%`. + `{migraph}` shipped examples that called `%>%` after the re-export was + removed, and every one of them failed R CMD check. +- Cite the source of a method with `@references` in the ecosystem's format + (authors, year, title, journal, and `\doi{}` where available), + so that users can trace an implementation back to its definition. +- Documented behaviour and implemented behaviour must agree. + When you change a default, search the roxygen for it too. -A final way of contributing to the package is in developing the -vignettes/articles that illustrate the value added in the package. -Please contact me with any proposals here. +### README and website -Please note that the `infernet` project is released with a -[Contributor Code of Conduct](CODE_OF_CONDUCT.md). -By contributing to this project, you agree to abide by its terms. +The README offers a landing page for new users, both on the GitHub repository +as well as on the website. +As such, it should make a compelling case for the value added of the package, +and not drift out of date. +Note that `README.md` is generated from `README.Rmd` — edit `README.Rmd` and re-knit +(`devtools::build_readme()`), never edit `README.md` directly. + +The website is created by pkgdown from [pkgdown/_pkgdown.yml](../pkgdown/_pkgdown.yml), +and is deployed automatically when changes reach `main`. +Please make sure that the pkgdown website will build correctly before opening a PR: + +```r +pkgdown::check_pkgdown() # every topic is in the index +pkgdown::build_site(preview = FALSE) # everything else +``` + +The most common failure is a new exported function that is not picked up under the +function overview (the `reference:` section of `_pkgdown.yml`) — +pkgdown requires *every* exported topic to appear there exactly once, or it will not build. +A helper that users are not meant to call takes `@keywords internal` instead. +These `reference:` titles are also the headings used in `NEWS.md` (see below), +so keep the two in step. + +### `NEWS.md` conventions + +`NEWS.md` groups each version's changes under `##` headings that mirror the website +function overview (`pkgdown/_pkgdown.yml` `reference:` titles). +Lead with `## Package` (package-wide/website/infrastructure changes), +then `## Tests` (the `test_*()` family) and `## Regression` (`net_regression()` +and the engine behind it). +Each heading appears at most once per version. + +Start each bullet with a verb matching the change type: + +- `Added ...` — new functionality +- `Fixed ...` — bug fixes; if it relates to a GitHub issue, suffix with `(closing #123)` +- `Renamed ... to ...` — function or data name migrations +- `Improved ...` — functional updates to existing behaviour +- `Updated ...` — documentation changes + +If a cited GitHub issue was **not** authored by @jhollway, thank the author with an +`@`-tag in the bullet. + +#### Grouping + +Group first, and only then write the bullets. +The more entries a version holds, the more this matters. + +- Cluster related changes as indented sub-bullets under a lead bullet. +- Where several changes concern one function, lead with an `Improved ...` bullet naming + the function, and put the individual `Fixed ...`/`Added ...` points beneath it, + so the cluster groups by function rather than by change type. +- Under such a lead bullet, do not name the function again in the sub-bullets, + since the lead bullet already carries it. +- Where one decision runs across many functions, lead with the decision rather than + with each function. +- Sub-bullets indent by two spaces, and nest at most one level further (four spaces). + +#### Writing the bullets + +`NEWS.md` is read by users scanning for what changed, not by reviewers reading prose, +so each bullet is a headline rather than a sentence, +so avoid over-punctuation or over-explanation. +Details can be added to the function documentation, if necessary. + +- No full stop at the end of a bullet +- Keep every bullet to one line of fewer than 81 characters ideally + (a few more or less is fine) + - If a bullet wraps, it holds too much: shorten it, + or split it into a lead bullet and sub-bullets +- One clause where possible, and at most one comma + - Use a semicolon for a short second clause, e.g. "old spelling still works but warns" + - Use a sub-bullet where the second clause needs more room than that +- Name the function or object in backticks and say what changed to it, + dropping scaffolding like "This change ...", "In order to ...", or "as part of an effort to" +- Keep the *what*, and add the *why* only where the behaviour would otherwise look arbitrary +- No trailing rationale, no restating the same change twice in different words, + and no marketing adjectives such as "comprehensive" or "robust" +- A sub-bullet does not need a verb: it can state the consequence, + the previous behaviour, or an example call +- Cut a sub-bullet that only restates what the lead bullet already implies +- Where several bullets describe parallel changes, reuse the sentence structure, + so that a reader sees the parallelism at a glance +- Use one word for one thing throughout a version's entries, + rather than varying the wording for effect + +For example, instead of: + +> Fixed a bug where, in some cases, `print.network_test()` was not returning its +> input invisibly, which meant that `x <- print(test)` assigned NULL. + +write: + +> Fixed `print.network_test()` to return its input invisibly + +and instead of: + +> Added a new control option, `use_gpu`, which is a useful option that allows the +> permutations to be run in batch on the GPU using torch. + +write: +> Added `use_gpu` control for batch OLS permutations on the GPU diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..d4bde28 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,29 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project overview + +`infernet` is an R package (part of the [stocnet](https://github.com/stocnet) ecosystem) providing the *inferential layer* for network analysis: +conditional uniform graph (CUG) and quadratic assignment procedure (QAP) tests of network statistics, and multiple regression QAP (MRQAP). +It combines a formula front end with a range of estimator range, missing-data handling, and treatments for multimodal, multilevel, and cognitive social structure networks. +It builds on `{manynet}` (network classes and coercion) and `{netrics}` (measures), +so its functions accept matrices, edgelists, `{igraph}`, `{network}`, `{tidygraph}`, or `stocnet` objects, +and one-mode or two-mode networks alike. +Plotting results belongs in `{autograph}`. + +Full package documentation — common dev commands, file organization, the `net_regression()` pipeline, +function body and parallelism conventions, console messaging, dependency practice, test conventions, `NEWS.md` conventions, and branching/CI — lives in [.github/CONTRIBUTING.md](.github/CONTRIBUTING.md). +Read it before adding or restructuring functions, +or when you need the exact `devtools`/testing commands for this repo. + +Note that `{migraph}` still carries older copies of `net_regression()` and the `test_*()` family, +which `{infernet}` supersedes. +A fix made in `{migraph}` needs porting here; a fix made here does not need porting back. + +## Where to make changes + +- Make all changes on the `develop` branch. `develop` is the working branch; `main` is the release branch. +- Do not commit to `main` directly. Do not open a new feature branch for a fix unless the user asks. +- Keep changes reviewable. Leave them as an uncommitted working-tree diff on `develop`, or as local commits on `develop`. Commit only when the user asks. +- Do not push to `origin/develop` without explicit approval. `develop` is shared. From 17e49c249e99c94228cf6724a7f151e925e42162 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:13:59 +0200 Subject: [PATCH 13/20] Updated the Github Actions workflows --- .github/pull_request_template.md | 15 ++------ .github/workflows/prchecks.yml | 57 +++++++++++++++++++++++++++++-- .github/workflows/pushrelease.yml | 40 +++++++++++++++------- NEWS.md | 11 +++++- 4 files changed, 94 insertions(+), 29 deletions(-) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index b3a6137..6cf530b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -2,18 +2,7 @@ # Checklist: -- PR form - - [ ] Description above itemizes changes under subtitles, e.g. "## Data"" - - [ ] Any closed, fixed, or related issues are referenced and explained in the description above, e.g. "Fixed #0 by adding A" - - [ ] Package builds on my OS without issues -- PR checks all pass for latest commit - - [ ] CodeFactor check: Package improves or maintains good style - - [ ] Package builds on Mac - - [ ] Package builds on Windows - - [ ] Package builds on Linux - - [ ] CodeCov check: Package improves or maintains good test coverage - Documentation - - [ ] Any new or modified functions or data have roxygen style documentation in their .R scripts - - [ ] Longer functions are commented inline or broken down into helper functions so that it is easier to debug in the future + - [ ] Longer functions are commented inline or broken down into helper functions to help debugging +- PR form - [ ] PR description above and the NEWS.md file are aligned - - [ ] DESCRIPTION file version is bumped by the appropriate increment (major, minor, patch) diff --git a/.github/workflows/prchecks.yml b/.github/workflows/prchecks.yml index b58bd2c..05e3120 100644 --- a/.github/workflows/prchecks.yml +++ b/.github/workflows/prchecks.yml @@ -24,11 +24,13 @@ jobs: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - uses: r-lib/actions/setup-r@v2 with: r-version: ${{ matrix.config.r }} + http-user-agent: ${{ matrix.config.http-user-agent }} + use-public-rspm: true - uses: r-lib/actions/setup-pandoc@v2 @@ -54,13 +56,16 @@ jobs: shell: Rscript {0} - name: Save binary artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.config.asset_name }} path: build/ - name: Calculate code coverage - run: Rscript -e "covr::codecov()" + if: runner.os == 'macOS' + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + run: Rscript -e 'covr::codecov(token = Sys.getenv("CODECOV_TOKEN"))' - name: Lint run: lintr::lint_package() @@ -69,3 +74,49 @@ jobs: - name: Spell check run: spelling::spell_check_package() shell: Rscript {0} + + pr-metadata: + name: PR metadata checks + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v7 + with: + fetch-depth: 0 + + - name: Check DESCRIPTION version is bumped + env: + BASE_SHA: ${{ github.event.pull_request.base.sha }} + run: | + BASE_VERSION=$(git show "$BASE_SHA:DESCRIPTION" | grep -m1 '^Version:' | sed 's/Version: *//') + HEAD_VERSION=$(grep -m1 '^Version:' DESCRIPTION | sed 's/Version: *//') + echo "Base version: $BASE_VERSION" + echo "Head version: $HEAD_VERSION" + if [ "$BASE_VERSION" = "$HEAD_VERSION" ]; then + echo "::error::DESCRIPTION Version has not been bumped from $BASE_VERSION" + exit 1 + fi + HIGHEST=$(printf '%s\n%s\n' "$BASE_VERSION" "$HEAD_VERSION" | sort -V | tail -n1) + if [ "$HIGHEST" != "$HEAD_VERSION" ]; then + echo "::error::DESCRIPTION Version $HEAD_VERSION is not greater than base version $BASE_VERSION" + exit 1 + fi + + - name: Check PR title mentions the new version number + env: + PR_TITLE: ${{ github.event.pull_request.title }} + run: | + HEAD_VERSION=$(grep -m1 '^Version:' DESCRIPTION | sed 's/Version: *//') + if [[ "$PR_TITLE" != *"$HEAD_VERSION"* ]]; then + echo "::error::PR title does not mention the new version number ($HEAD_VERSION): \"$PR_TITLE\"" + exit 1 + fi + + - name: Check PR description itemizes changes under subsection titles + env: + PR_BODY: ${{ github.event.pull_request.body }} + run: | + if ! grep -qE '^##[[:space:]]' <<< "$PR_BODY"; then + echo "::error::PR description does not itemize changes under subsection titles (e.g. \"## Data\")" + exit 1 + fi diff --git a/.github/workflows/pushrelease.yml b/.github/workflows/pushrelease.yml index 9961552..da6afa5 100644 --- a/.github/workflows/pushrelease.yml +++ b/.github/workflows/pushrelease.yml @@ -24,7 +24,7 @@ jobs: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - uses: r-lib/actions/setup-r@v2 with: @@ -55,14 +55,16 @@ jobs: shell: Rscript {0} - name: Save binary artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v7 with: name: ${{ matrix.config.asset_name }} path: build/ - name: Calculate code coverage - if: runner.os == 'macOS-latest' - run: Rscript -e "covr::codecov()" + if: runner.os == 'macOS' + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + run: Rscript -e 'covr::codecov(token = Sys.getenv("CODECOV_TOKEN"))' release: name: Bump version and release @@ -73,7 +75,7 @@ jobs: contents: write steps: - name: Checkout one - uses: actions/checkout@v4 + uses: actions/checkout@v7 with: fetch-depth: '0' - name: Bump version and push tag @@ -85,7 +87,7 @@ jobs: DEFAULT_BUMP: patch RELEASE_BRANCHES: main - name: Checkout two - uses: actions/checkout@v4 + uses: actions/checkout@v7 - name: Extract version run: | @@ -93,7 +95,7 @@ jobs: echo "PACKAGE_NAME=$(grep '^Package' DESCRIPTION | sed 's/.*: *//')" >> $GITHUB_ENV - name: Download binaries - uses: actions/download-artifact@v4 + uses: actions/download-artifact@v8 - name: Rename binaries release shell: bash @@ -104,13 +106,27 @@ jobs: cp ./winOS/${{ env.PACKAGE_NAME }}_${{ env.PACKAGE_VERSION }}*.zip . echo "Renamed files" ls infernet_* - + + - name: Extract release notes from NEWS.md + shell: bash + run: | + # Take the NEWS.md section for this version, else the topmost section. + awk -v ver="${{ env.PACKAGE_NAME }} ${{ env.PACKAGE_VERSION }}" ' + /^# / { if (found) exit; if (substr($0, 3) == ver) { found = 1; next } } + found { print } + ' NEWS.md > RELEASE_NOTES.md + if [ ! -s RELEASE_NOTES.md ]; then + awk 'NR > 1 && /^# / { exit } NR > 1 { print }' NEWS.md > RELEASE_NOTES.md + fi + cat RELEASE_NOTES.md + - name: Create Release and Upload Assets id: create_release uses: softprops/action-gh-release@v2 with: tag_name: ${{ steps.newtag.outputs.tag }} name: Release ${{ steps.newtag.outputs.tag }} + body_path: RELEASE_NOTES.md draft: false prerelease: false fail_on_unmatched_files: true @@ -120,7 +136,7 @@ jobs: infernet_*.tar.gz infernet_*.zip env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} pkgdown: name: Build and deploy website @@ -130,11 +146,11 @@ jobs: env: GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v7 - uses: r-lib/actions/setup-r@v2 - - uses: r-lib/actions/setup-pandoc@v1 + - uses: r-lib/actions/setup-pandoc@v2 - uses: r-lib/actions/setup-r-dependencies@v2 with: @@ -143,7 +159,7 @@ jobs: any::rcmdcheck any::pkgdown any::rsconnect - needs: check + needs: website - name: Install package run: R CMD INSTALL . diff --git a/NEWS.md b/NEWS.md index 6d45571..2a021c0 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,15 @@ +# infernet 0.1.1 + +## Package + +- Updated the Github Actions workflows + - Added the PR metadata checks for the version bump and the PR title and body + - Release notes are now taken from the matching `NEWS.md` section + - Updated the action versions in `prchecks` and `pushrelease` +- Updated CONTRIBUTING to document the architecture and the house conventions + # infernet 0.1.0 ## Package - Initialised package - From 89d30c7a4a764ec85efc8221cdf09624a6c20df6 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:18:29 +0200 Subject: [PATCH 14/20] Updated `DESCRIPTION` --- DESCRIPTION | 21 +++++++++++++-------- NAMESPACE | 14 ++++++++------ NEWS.md | 3 +++ 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 13803ea..92c83f6 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,22 +1,25 @@ Package: infernet -Title: Basic inferential models for many different types of networks -Version: 0.1.0 -Date: 2026-04-28 +Title: Inferential Models for Many Different Types of Networks +Version: 0.1.1 Description: A set of tools for testing networks. It includes functions for univariate and multivariate conditional uniform graph and quadratic assignment procedure testing, - and network regression. + and multiple regression quadratic assignment procedure (MRQAP) models + for a range of families, with random and fixed effects, + missing data, and cognitive social structures. + Built on the 'manynet' package, all functions operate with matrices, + edge lists, and 'igraph', 'network', and 'tidygraph' objects, + and on one-mode and two-mode (bipartite) networks. URL: https://stocnet.github.io/infernet/ BugReports: https://github.com/stocnet/infernet/issues License: MIT + file LICENSE Language: en-GB Encoding: UTF-8 LazyData: true -RoxygenNote: 7.3.3 Depends: - R (>= 3.6.0), - manynet, - netrics + R (>= 4.1.0), + manynet (>= 2.3.1), + netrics (>= 1.0.1) Authors@R: c(person(given = "James", family = "Hollway", @@ -56,3 +59,5 @@ Config/Needs/website: pkgdown Config/testthat/parallel: true Config/testthat/edition: 3 +Config/testthat/start-first: net_regression +Config/roxygen2/version: 8.1.0 diff --git a/NAMESPACE b/NAMESPACE index 4f4e187..b0cf7af 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -6,10 +6,12 @@ export(net_regression) export(test_configuration) export(test_permutation) export(test_random) -importFrom(manynet,bind_node_attributes) -importFrom(manynet,generate_configuration) -importFrom(manynet,generate_random) -importFrom(manynet,is_complex) -importFrom(manynet,is_directed) -importFrom(manynet,snet_info) +importFrom(manynet, + bind_node_attributes, + generate_configuration, + generate_random, + is_complex, + is_directed, + snet_info +) importFrom(netrics,net_by_heterophily) diff --git a/NEWS.md b/NEWS.md index 2a021c0..e134dfb 100644 --- a/NEWS.md +++ b/NEWS.md @@ -2,6 +2,9 @@ ## Package +- Updated `DESCRIPTION` + - Raised the R minimum to 4.1.0, since the examples use the native pipe + - Pinned the minimum versions of `{manynet}` and `{netrics}` - Updated the Github Actions workflows - Added the PR metadata checks for the version bump and the PR title and body - Release notes are now taken from the matching `NEWS.md` section From 077b031ab0ad2ad326f0cdba703b6191c516e4aa Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:21:47 +0200 Subject: [PATCH 15/20] Added `README.Rmd` and `pkgdown/_pkgdown.yml` for this package --- NEWS.md | 2 + README.Rmd | 103 ++++++++++++++++++++++++++++++++++++++++++ README.md | 105 +++++++++++++++++++++++++++++++++++++++++++ cran-comments.md | 22 +++++++++ pkgdown/_pkgdown.yml | 48 ++++++++++++++++++++ 5 files changed, 280 insertions(+) create mode 100644 README.Rmd create mode 100644 README.md create mode 100644 cran-comments.md create mode 100644 pkgdown/_pkgdown.yml diff --git a/NEWS.md b/NEWS.md index e134dfb..669fc43 100644 --- a/NEWS.md +++ b/NEWS.md @@ -10,6 +10,8 @@ - Release notes are now taken from the matching `NEWS.md` section - Updated the action versions in `prchecks` and `pushrelease` - Updated CONTRIBUTING to document the architecture and the house conventions +- Added `README.Rmd` and `pkgdown/_pkgdown.yml` for this package + # infernet 0.1.0 diff --git a/README.Rmd b/README.Rmd new file mode 100644 index 0000000..83fb201 --- /dev/null +++ b/README.Rmd @@ -0,0 +1,103 @@ +--- +output: github_document +--- + + + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "100%" +) +``` + +# infernet +infernet logo + + +[![Lifecycle: experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +![CRAN/METACRAN](https://img.shields.io/cran/v/infernet) +![GitHub release (latest by date)](https://img.shields.io/github/v/release/stocnet/infernet) +![GitHub Release Date](https://img.shields.io/github/release-date/stocnet/infernet) +[![Codecov test coverage](https://codecov.io/gh/stocnet/infernet/branch/main/graph/badge.svg)](https://app.codecov.io/gh/stocnet/infernet?branch=main) + + +## About the package + +`{infernet}` is the inferential layer of the [stocnet](https://github.com/stocnet) +ecosystem. It offers two things: + +- **Tests of network statistics.** `test_random()` runs a conditional uniform +graph (CUG) test, `test_configuration()` conditions on the degree sequence, +and `test_permutation()` runs a quadratic assignment procedure (QAP) test. +Each takes any graph-level statistic and compares it against a simulated +null distribution. +- **Network regression.** `net_regression()` fits a multiple regression +quadratic assignment procedure (MRQAP) model, using either Dekker et al's +double semi-partialling or a permutation of the dependent network alone. + +The package combines the formula interface of `{migraph}` with the estimators, +missing-data handling, and cognitive social structure treatment of +Robert Krause's `MrQAP`. + +## A formula you can reuse + +Models are specified with a formula, so the same specification can be moved +between networks and between model types: + +```{r example, eval = FALSE} +library(infernet) + +networkers <- manynet::ison_networkers |> + manynet::to_subgraph(Discipline == "Sociology") + +net_regression(weight ~ ego(Citations) + alter(Citations) + sim(Citations), + networkers, times = 200) +``` + +Alongside plain references to other networks, which enter as dyadic +covariates, the right-hand side accepts: + +| Term | Constructs a matrix of | +|---|---| +| `ego(attr)` | the sender's value of a nodal attribute | +| `alter(attr)` | the receiver's value | +| `same(attr)` | 1 where sender and receiver share an attribute value | +| `dist(attr)` | the absolute difference in a numeric attribute | +| `sim(attr)` | the proportional similarity in a numeric attribute | +| `tertius(attr, fn)` | an aggregate of an attribute over a node's other ties | + +Further options are passed through a `control` list: the model family, +the null hypothesis, random or fixed effects, robust standard errors, +the parallel strategy, and an optional `{torch}` path for running +permutations on a GPU. + +## Installation + +### Development + +`{infernet}` is not yet on CRAN. +The latest binary releases for all major OSes -- Windows, Mac, and Linux -- +can be found [here](https://github.com/stocnet/infernet/releases/latest). +Download the appropriate binary for your operating system, +and install using an adapted version of the following commands: + +- For Windows: `install.packages("~/Downloads/infernet_winOS.zip", repos = NULL)` +- For Mac: `install.packages("~/Downloads/infernet_macOS.tgz", repos = NULL)` +- For Unix: `install.packages("~/Downloads/infernet_linuxOS.tar.gz", repos = NULL)` + +To install from source, +please install the `{remotes}` package from CRAN and then: + +- For latest stable version: +`remotes::install_github("stocnet/infernet")` +- For latest development version: +`remotes::install_github("stocnet/infernet@develop")` + +## Funding details + +Development on this package has been funded by the Swiss National Science Foundation (SNSF) +[Grant Number 188976](https://data.snf.ch/grants/grant/188976): +"Power and Networks and the Rate of Change in Institutional Complexes" (PANARCHIC). diff --git a/README.md b/README.md new file mode 100644 index 0000000..d002ab1 --- /dev/null +++ b/README.md @@ -0,0 +1,105 @@ + + + +# infernet + +infernet logo + + + +[![Lifecycle: +experimental](https://img.shields.io/badge/lifecycle-experimental-orange.svg)](https://lifecycle.r-lib.org/articles/stages.html#experimental) +![CRAN/METACRAN](https://img.shields.io/cran/v/infernet) ![GitHub +release (latest by +date)](https://img.shields.io/github/v/release/stocnet/infernet) +![GitHub Release +Date](https://img.shields.io/github/release-date/stocnet/infernet) +[![Codecov test +coverage](https://codecov.io/gh/stocnet/infernet/branch/main/graph/badge.svg)](https://app.codecov.io/gh/stocnet/infernet?branch=main) + + +## About the package + +`{infernet}` is the inferential layer of the +[stocnet](https://github.com/stocnet) ecosystem. It offers two things: + +- **Tests of network statistics.** `test_random()` runs a conditional + uniform graph (CUG) test, `test_configuration()` conditions on the + degree sequence, and `test_permutation()` runs a quadratic assignment + procedure (QAP) test. Each takes any graph-level statistic and + compares it against a simulated null distribution. +- **Network regression.** `net_regression()` fits a multiple regression + quadratic assignment procedure (MRQAP) model, using either Dekker et + al’s double semi-partialling or a permutation of the dependent network + alone. + +It offers these capabilities for one-mode and two-mode networks, and for unimodal, +directed, undirected, weighted, or cognitive social structure networks alike. +It accepts matrices, edgelists, +`{igraph}`, `{network}`, `{tidygraph}`, or `stocnet` objects, +and handles missing-data gracefully. +It can run permutations in parallel, and can optionally use a GPU via `{torch}`. + +## A formula you can reuse + +Models are specified with a formula, so the same specification can be +moved between networks and between model types: + +``` r +library(infernet) + +networkers <- manynet::ison_networkers |> + manynet::to_subgraph(Discipline == "Sociology") + +net_regression(weight ~ ego(Citations) + alter(Citations) + sim(Citations), + networkers, times = 200) +``` + +Alongside plain references to other networks, which enter as dyadic +covariates, the right-hand side accepts: + +| Term | Constructs a matrix of | +|---------------------|-------------------------------------------------------| +| `ego(attr)` | the sender’s value of a nodal attribute | +| `alter(attr)` | the receiver’s value | +| `same(attr)` | 1 where sender and receiver share an attribute value | +| `dist(attr)` | the absolute difference in a numeric attribute | +| `sim(attr)` | the proportional similarity in a numeric attribute | +| `tertius(attr, fn)` | an aggregate of an attribute over a node’s other ties | + +Further options are passed through a `control` list: the model family, +the null hypothesis, random or fixed effects, robust standard errors, +the parallel strategy, and an optional `{torch}` path for running +permutations on a GPU. + +## Installation + +### Development + +`{infernet}` is not yet on CRAN. The latest binary releases for all +major OSes – Windows, Mac, and Linux – can be found +[here](https://github.com/stocnet/infernet/releases/latest). Download +the appropriate binary for your operating system, and install using an +adapted version of the following commands: + +- For Windows: + `install.packages("~/Downloads/infernet_winOS.zip", repos = NULL)` +- For Mac: + `install.packages("~/Downloads/infernet_macOS.tgz", repos = NULL)` +- For Unix: + `install.packages("~/Downloads/infernet_linuxOS.tar.gz", repos = NULL)` + +To install from source, please install the `{remotes}` package from CRAN +and then: + +- For latest stable version: + `remotes::install_github("stocnet/infernet")` +- For latest development version: + `remotes::install_github("stocnet/infernet@develop")` + +## Funding details + +Development on this package has been funded by the Swiss National +Science Foundation (SNSF) [Grant Number +188976](https://data.snf.ch/grants/grant/188976): “Power and Networks +and the Rate of Change in Institutional Complexes” (PANARCHIC). diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..da2adfd --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,22 @@ +## Submission + +This is a first submission of `infernet` to CRAN. + +## Test environments + +* local R installation, aarch64-apple-darwin20, R 4.6.1 +* macOS (on Github Actions), R release +* Microsoft Windows Server 2022 (on Github Actions), R release +* Ubuntu 24.04 (on Github Actions), R release + +## R CMD check results + +0 errors | 0 warnings | 0 notes + +## Notes for reviewers + +* The package Depends on `manynet` and `netrics`, both on CRAN. +* All estimator-specific packages (`lme4`, `glmmTMB`, `fixest`, `gmm`, `MASS`, + `pscl`, `nnet`, `torch`) are in Suggests, and every code path that needs one + guards with `requireNamespace()`. +* Examples keep the number of permutations low so that they run quickly. diff --git a/pkgdown/_pkgdown.yml b/pkgdown/_pkgdown.yml new file mode 100644 index 0000000..152a50b --- /dev/null +++ b/pkgdown/_pkgdown.yml @@ -0,0 +1,48 @@ +url: https://stocnet.github.io/infernet/ +development: + mode: auto +template: + bootstrap: 5 + bootswatch: superhero +authors: + James Hollway: + href: https://jameshollway.com +navbar: + structure: + left: + - home + - intro + - reference + - news + right: + - search + - github + - cran + components: + home: + icon: fa-home fa-lg + href: index.html + aria-label: Go to home + reference: + text: Function Overview + href: reference/index.html + news: + text: News + href: news/index.html + github: + icon: "fab fa-github fa-lg" + href: https://github.com/stocnet/infernet + aria-label: View on Github + cran: + icon: "fab fa-r-project" + href: https://cloud.r-project.org/package=infernet + aria-label: View on CRAN +reference: + - title: "Tests" + desc: "Functions for testing network statistics against a null distribution:" + contents: + - starts_with("test") + - title: "Regression" + desc: "Functions for regressing networks on nodal and dyadic covariates:" + contents: + - regression From 9ec294668a317cb7a94c51155246823d7068f991 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:34:57 +0200 Subject: [PATCH 16/20] Improved the loading messages --- NEWS.md | 5 +++-- R/zzz.R | 61 +++++++++++++++++++++------------------------------------ 2 files changed, 25 insertions(+), 41 deletions(-) diff --git a/NEWS.md b/NEWS.md index 669fc43..a7e381f 100644 --- a/NEWS.md +++ b/NEWS.md @@ -5,12 +5,13 @@ - Updated `DESCRIPTION` - Raised the R minimum to 4.1.0, since the examples use the native pipe - Pinned the minimum versions of `{manynet}` and `{netrics}` +- Updated CONTRIBUTING to document the architecture and the house conventions +- Added `README.Rmd` and `pkgdown/_pkgdown.yml` for this package +- Improved the loading messages - Updated the Github Actions workflows - Added the PR metadata checks for the version bump and the PR title and body - Release notes are now taken from the matching `NEWS.md` section - Updated the action versions in `prchecks` and `pushrelease` -- Updated CONTRIBUTING to document the architecture and the house conventions -- Added `README.Rmd` and `pkgdown/_pkgdown.yml` for this package # infernet 0.1.0 diff --git a/R/zzz.R b/R/zzz.R index 081bc53..944a999 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,58 +1,41 @@ +# nocov start + +# The stocnet version check lives in {migraph}, which loads and checks the whole +# stack at once. This package is one of the packages it checks, so it does no +# version check of its own. #' @importFrom manynet snet_info .onAttach <- function(...) { - # suppressMessages(suppressPackageStartupMessages(library("manynet", warn.conflicts = FALSE))) if (!interactive()) return() - - # options(manynet_verbosity = getOption("manynet_verbosity", "verbose")) + options(stocnet_theme = getOption("stocnet_theme", "default")) - # options(cli.theme = manynet_console_theme()) - # options(cli.progress_clear = TRUE) - - # pkgs <- as.data.frame(utils::available.packages(utils::contrib.url(getOption("repos")))) - # - # cran_version <- pkgs[pkgs$Package == "manynet","Version"] local_version <- utils::packageVersion("infernet") - manynet::snet_info("You are using {.pkg infernet} version {.version {local_version}}.") - old.list <- as.data.frame(utils::old.packages()) - behind_cran <- "infernet" %in% old.list$Package - + manynet::snet_info("You are using {.infr infernet} version {.version {local_version}}.") + greet_startup_cli <- function() { tips <- c( - "i" = "There are lots of ways to contribute to {.pkg infernet} at {.url https://github.com/stocnet/infernet/}.", - "i" = "Please let us know any bugs, issues, or feature requests at {.url https://github.com/stocnet/infernet/issues}. It's really helpful!", - # "i" = "To eliminate package startup messages, use: `suppressPackageStartupMessages(library({.pkg autograph}))`.", - # "i" = "Changing the theme of all your graphs is straightforward with `set_manynet_theme()`", - # "i" = "If there are too many messages in the console, run `options(manynet_verbosity = 'quiet')`", - "i" = "Visit the website to learn more: {.url https://stocnet.github.io/infernet/}.", - "i" = "We recommend the 'Function Overview' page online to discover new analytic opportunities: {.url https://stocnet.github.io/infernet/reference/index.html}.", - # "i" = "Star me at {.url https://github.com/users/follow?target=jhollway}.", - # "i" = "You can list all the tutorials available in {.pkg manynet} using {.fn run_tute}, and run them too!", - "i" = "Discover all the {.emph stocnet} R packages at {.url https://github.com/stocnet/}." + "i" = "Share bugs, issues, or feature requests at {.url https://github.com/stocnet/infernet/issues}.", + "i" = "If too many messages appear in the console, run {.run base::options(snet_verbosity = 'quiet')}", + "i" = "Explore changes since the last version with {.run [news(package = 'infernet')](utils::news(package = 'infernet'))}.", + # "i" = "Test any network statistic against a null distribution with {.fn test_random}, {.fn test_configuration}, or {.fn test_permutation}.", + # "i" = "Regress a network on nodal and dyadic covariates with {.fn net_regression}.", + # "i" = "Write {.code ego()}, {.code alter()}, {.code same()}, {.code dist()}, {.code sim()}, or {.code tertius()} in a formula to build a predictor from a nodal attribute.", + "i" = "Speed up a long run with {.code control = list(strategy = 'multisession')}.", + # "i" = "Measures to test are in {.tric netrics}; plots of results are in {.auto autograph}.", + "i" = "Visit {.url https://stocnet.github.io/infernet/} to learn more.", + "i" = "Discover new functions at {.url https://stocnet.github.io/infernet/reference/index.html}.", + "i" = "Discover {.emph stocnet} R packages at {.url https://github.com/stocnet/}." ) manynet::snet_info(sample(tips, 1)) } - if (interactive()) { - if (behind_cran) { - msg <- "A new version of infernet is available with bug fixes and new features." - packageStartupMessage(msg, "\nWould you like to install it?") - if (utils::menu(c("Yes", "No")) == 1) { - utils::update.packages("infernet") - } - } else { - greet_startup_cli() - # packageStartupMessage(paste(strwrap(tip), collapse = "\n")) - } - } + greet_startup_cli() } +# nocov end + # Global variables #### # defining global variables more centrally utils::globalVariables(c(".data")) - - - - From 61525af52d821f9d4bb7c2b29d056946fdfe91d4 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:40:04 +0200 Subject: [PATCH 17/20] Improved console messaging to use the `snet_*()` wrappers from `{manynet}` and using native pipe everywhere --- NEWS.md | 8 +++++++ R/infernet-package.R | 14 ++++++++++++ R/model_tests.R | 21 +++++++++--------- R/qap_css.R | 45 ++++++++++++++++++++++++-------------- R/qap_engine.R | 5 +++-- R/qap_gpu.R | 4 ++-- R/qap_misc.R | 5 +++-- R/qap_utils.R | 48 +++++++++++++++++++---------------------- man/infernet-package.Rd | 9 ++++++-- man/regression.Rd | 6 +++--- man/tests.Rd | 8 +++---- 11 files changed, 105 insertions(+), 68 deletions(-) diff --git a/NEWS.md b/NEWS.md index a7e381f..aebf611 100644 --- a/NEWS.md +++ b/NEWS.md @@ -12,6 +12,14 @@ - Added the PR metadata checks for the version bump and the PR title and body - Release notes are now taken from the matching `NEWS.md` section - Updated the action versions in `prchecks` and `pushrelease` +- Improved console messaging to use the `snet_*()` wrappers from `{manynet}` + - Informational output is now silent by default, and follows `snet_verbosity` + - Errors name what is missing and what is available + - Added `thisRequires()`, which names the install command for a suggested package + +## Tests + +- Updated the examples to use the native pipe `|>` # infernet 0.1.0 diff --git a/R/infernet-package.R b/R/infernet-package.R index f2354ee..4376a4c 100644 --- a/R/infernet-package.R +++ b/R/infernet-package.R @@ -7,6 +7,20 @@ ## usethis namespace: end NULL +# Checks for a package in Suggests, and aborts with the install command where it +# is missing. Deliberately not a prompt: `utils::askYesNo()` reads from stdin, +# and a permutation run started from a script would stall on it. +#' @keywords internal +#' @noRd +thisRequires <- function(pkgname, why) { + if (!requireNamespace(pkgname, quietly = TRUE)) { + manynet::snet_abort( + c(paste0("The {.pkg ", pkgname, "} package is required ", why, "."), + i = paste0("Install it with {.run install.packages(\"", pkgname, "\")}."))) + } + invisible(TRUE) +} + # Suppress R CMD check note # Namespace in Imports field not imported from: PKG # All declared Imports should be used. diff --git a/R/model_tests.R b/R/model_tests.R index 8e3d445..d7e80b0 100644 --- a/R/model_tests.R +++ b/R/model_tests.R @@ -29,8 +29,8 @@ NULL #' @rdname tests #' @importFrom manynet generate_random bind_node_attributes is_directed is_complex #' @examples -#' marvel_friends <- fict_marvel %>% to_uniplex("relationship") %>% -#' to_unsigned() %>% to_giant() %>% +#' marvel_friends <- fict_marvel |> to_uniplex("relationship") |> +#' to_unsigned() |> to_giant() |> #' to_subgraph(PowerOrigin == "Human") #' (cugtest <- test_random(marvel_friends, net_by_heterophily, attribute = "Attractive", #' times = 200)) @@ -50,12 +50,12 @@ test_random <- function(.data, FUN, ..., on.exit(future::plan(oplan), add = TRUE) rands <- furrr::future_map(1:times, manynet::generate_random, n = .data, .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) if (length(args) > 0) { rands <- furrr::future_map(rands, manynet::bind_node_attributes, object2 = .data, .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) } if (!is.null(args)) { simd <- furrr::future_map_dbl(rands, @@ -95,12 +95,12 @@ test_configuration <- function(.data, FUN, ..., rands <- furrr::future_map(1:times, ~ manynet::generate_configuration(.data), .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) if (length(args) > 0) { rands <- furrr::future_map(rands, manynet::bind_node_attributes, object2 = .data, .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) } if (!is.null(args)) { simd <- furrr::future_map_dbl(rands, @@ -139,24 +139,22 @@ test_permutation <- function(.data, FUN, ..., } else { obsd <- FUN(.data) } - n <- manynet::net_dims(.data) - d <- netrics::net_by_density(.data) oplan <- future::plan(strategy) on.exit(future::plan(oplan), add = TRUE) rands <- furrr::future_map(1:times, function(x) manynet::to_permuted(.data), .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) if (!is.null(args)) { simd <- furrr::future_map_dbl(rands, FUN, args, .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) } else { simd <- furrr::future_map_dbl(rands, FUN, .progress = verbose, - .options = furrr::furrr_options(seed = T)) + .options = furrr::furrr_options(seed = TRUE)) } out <- list(test = "QAP", testval = obsd, @@ -178,5 +176,6 @@ print.network_test <- function(x, ..., cat("Observed Value:", x$testval, "\n") cat("Pr(X>=Obs):", x$pgteobs, "\n") cat("Pr(X<=Obs):", x$plteobs, "\n\n") + invisible(x) } diff --git a/R/qap_css.R b/R/qap_css.R index ef4e19c..a5c7b2d 100644 --- a/R/qap_css.R +++ b/R/qap_css.R @@ -192,7 +192,9 @@ QAPcssPermEst <- function(i, } if (trial >= max_trials) { - stop("Cannot find valid permutation after ", max_trials, " trials.") + manynet::snet_abort( + c("Cannot find a valid permutation after {max_trials} trials.", + i = "The network may be too sparse, or too many cells may be missing.")) } xi_arg <- if (!is.null(perm_var.)) perm_var. else NULL @@ -339,12 +341,13 @@ QAPcss <- function(formula, if (!large) { y <- data[[dep]] if (length(dim(y)) != 3) - stop("data[['", dep, "']] must be a 3-dimensional array ", - "[sender, receiver, perceiver].") + manynet::snet_abort( + "The dependent variable {.val {dep}} must be a 3-dimensional array of sender, receiver, and perceiver.") } else { for (i in seq_along(data[[dep]])) { if (length(dim(data[[dep]][[i]])) != 3) - stop("data[['", dep, "']][[", i, "]] must be a 3D array.") + manynet::snet_abort( + "Network {i} of the dependent variable {.val {dep}} must be a 3-dimensional array.") } } @@ -359,29 +362,36 @@ QAPcss <- function(formula, has_random <- grepl("\\(", mod_str) || parsed$has_random use_fixest <- parsed$use_fixest if (has_random && use_fixest) { - warning("Cannot combine fixest FE and lme4 random effects. ", - "Using lme4 only.") + manynet::snet_warn( + c("Cannot combine {.pkg fixest} fixed effects with {.pkg lme4} random effects.", + i = "Using the random effects only.")) use_fixest <- FALSE } mod <- stats::as.formula(mod_str) if (has_random && family == "multinom") { - warning("Random intercepts not implemented for multinomial. ", - "Using standard nnet::multinom().") + manynet::snet_warn( + c("Random intercepts are not implemented for the multinomial family.", + i = "Using {.fn nnet::multinom} instead.")) has_random <- FALSE } if (!is.null(reference) && !is.character(reference) && family == "multinom") reference <- as.character(reference) if (use_robust_errors && family == "multinom") { - warning("Robust SEs not implemented for multinomial.") + manynet::snet_warn( + "Robust standard errors are not implemented for the multinomial family.") use_robust_errors <- FALSE } if ((nullhyp == "qapspp") && (nx == 1)) nullhyp <- "qapy" if (mode == "undirected" && (ris || rir)) { - warning("Undirected mode: sender/receiver random intercepts set to FALSE.") + manynet::snet_warn( + c("An undirected network has no senders or receivers.", + i = "Setting the sender and receiver random intercepts to {.val FALSE}.")) ris <- rir <- FALSE } - if (diag) warning("Results may not be valid when diagonal is used.") + if (diag) + manynet::snet_warn( + "Results may not be valid where the diagonal is included.") rand_part <- "" if (rin) rand_part <- paste(rand_part, "+ (1|nv)") @@ -393,7 +403,8 @@ QAPcss <- function(formula, n <- dim(data[[dep]])[1] if (!is.null(groups)) { if (length(groups) != n) - stop("groups length (", length(groups), ") != N (", n, ").") + manynet::snet_abort( + "{.arg groups} is of length {length(groups)}, but the network has {n} nodes.") groups <- as.factor(groups) } else { groups <- as.factor(rep(1, n)) @@ -484,8 +495,9 @@ QAPcss <- function(formula, for (xi in main) { test_val <- data[[xi]] if (!is.numeric(test_val)) { - warning("Cannot residualise non-numeric predictor '", xi, - "'. Skipping qapspp for this variable.") + manynet::snet_warn( + c("Cannot residualise the non-numeric predictor {.val {xi}}.", + i = "Skipping double semi-partialling for this predictor.")) next } xR <- residualise_predictor(xi, pred, main, @@ -597,8 +609,9 @@ QAPcss <- function(formula, for (xi in main) { test_val <- if (!large) data[[xi]] else data[[xi]][[1]] if (!is.numeric(test_val)) { - warning("Cannot residualise non-numeric predictor '", xi, - "'. Skipping qapspp for this variable.") + manynet::snet_warn( + c("Cannot residualise the non-numeric predictor {.val {xi}}.", + i = "Skipping double semi-partialling for this predictor.")) next } diff --git a/R/qap_engine.R b/R/qap_engine.R index f582ed9..7d40c1c 100644 --- a/R/qap_engine.R +++ b/R/qap_engine.R @@ -50,8 +50,9 @@ QAPglm <- function(formula, has_random <- grepl("\\(", mod_str) || parsed$has_random use_fixest <- parsed$use_fixest if (has_random && use_fixest) { - warning("Cannot combine fixest FE and lme4 random effects. ", - "Using lme4 random effects only.") + manynet::snet_warn( + c("Cannot combine {.pkg fixest} fixed effects with {.pkg lme4} random effects.", + i = "Using the random effects only.")) use_fixest <- FALSE } diff --git a/R/qap_gpu.R b/R/qap_gpu.R index 8ad1ad5..61c39bf 100644 --- a/R/qap_gpu.R +++ b/R/qap_gpu.R @@ -15,7 +15,7 @@ gpu_batch_ols <- function(data, parsed, mode, diag, groups, reps, } if (device == "cuda" && !torch::cuda_is_available()) { - message("CUDA not available. Falling back to CPU torch.") + manynet::snet_info("CUDA is not available, so falling back to CPU {.pkg torch}.") device <- "cpu" } @@ -172,7 +172,7 @@ gpu_batch_ols_css <- function(data, parsed, mode, diag, groups, reps, } if (device == "cuda" && !torch::cuda_is_available()) { - message("CUDA not available. Falling back to CPU torch.") + manynet::snet_info("CUDA is not available, so falling back to CPU {.pkg torch}.") device <- "cpu" } diff --git a/R/qap_misc.R b/R/qap_misc.R index 9cb9823..d362a9b 100644 --- a/R/qap_misc.R +++ b/R/qap_misc.R @@ -103,8 +103,9 @@ df_to_mat <- function(df, if (loops) n_s * n_r else n_s * n_r - min(n_s, n_r) } if (anyNA(df[var_names]) || nrow(df) != expected) { - warning("Incomplete dyadic data: some cells will be NA.", - "\nCheck the data and consider coding matrices manually.") + manynet::snet_warn( + c("Incomplete dyadic data, so some cells will be {.val NA}.", + i = "Check the data, or code the matrices manually.")) } make_structure <- function(var) { diff --git a/R/qap_utils.R b/R/qap_utils.R index 7a02a39..7f58295 100644 --- a/R/qap_utils.R +++ b/R/qap_utils.R @@ -78,13 +78,13 @@ build_internal_formula <- function(formula, validate_qap_input <- function(data, parsed, css = FALSE) { dep <- parsed$dependent if (!(dep %in% names(data))) { - stop("Dependent variable '", dep, "' not found in data.") + manynet::snet_abort("Dependent variable {.val {dep}} not found in the data.") } structural_vars <- c("sv", "rv", "nv", "pv") for (v in parsed$all_data_vars) { if (v %in% structural_vars) next if (!(v %in% names(data))) { - stop("Predictor '", v, "' not found in data.") + manynet::snet_abort("Predictor {.val {v}} not found in the data.") } } @@ -93,21 +93,25 @@ validate_qap_input <- function(data, parsed, css = FALSE) { if (!css) { if (!large) { - if (!is.matrix(y)) stop("data[['", dep, "']] must be a matrix.") + if (!is.matrix(y)) + manynet::snet_abort("The dependent variable {.val {dep}} must be a matrix.") } else { for (i in seq_along(y)) { if (!is.matrix(y[[i]])) - stop("data[['", dep, "']][[", i, "]] must be a matrix.") + manynet::snet_abort( + "Network {i} of the dependent variable {.val {dep}} must be a matrix.") } } } else { if (!large) { if (length(dim(y)) != 3) - stop("data[['", dep, "']] must be a 3-dimensional array.") + manynet::snet_abort( + "The dependent variable {.val {dep}} must be a 3-dimensional array.") } else { for (i in seq_along(y)) { if (length(dim(y[[i]])) != 3) - stop("data[['", dep, "']][[", i, "]] must be a 3D array.") + manynet::snet_abort( + "Network {i} of the dependent variable {.val {dep}} must be a 3-dimensional array.") } } } @@ -279,8 +283,7 @@ fit_qap_model <- function(mod, pred, family, if (!is.null(reference)) { pred[[dep_var]] <- stats::relevel(pred[[dep_var]], ref = reference) } - if (!requireNamespace("nnet", quietly = TRUE)) - stop("Package 'nnet' is required for multinomial models.") + thisRequires("nnet", "for multinomial models") base_model <- nnet::multinom(mod, data = pred, trace = FALSE) fit$coefficients <- stats::coefficients(base_model) fit$t <- stats::coefficients(base_model) / @@ -290,8 +293,7 @@ fit_qap_model <- function(mod, pred, family, } if (estimator == "gmm") { - if (!requireNamespace("gmm", quietly = TRUE)) - stop("Package 'gmm' is required for GMM estimation.") + thisRequires("gmm", "for GMM estimation") y_vec <- pred[[dep_var]] x_mat <- cbind(1, as.matrix(pred[, main_vars, drop = FALSE])) @@ -326,8 +328,9 @@ fit_qap_model <- function(mod, pred, family, resid <- zip_resid(base_model) has_extra_param <- TRUE } else { - stop("GMM estimator is available for binomial, poisson, negbin, ", - "and zip families.") + manynet::snet_abort( + c("The GMM estimator is not available for the {.val {family}} family.", + i = "It is available for the binomial, poisson, negbin, and zip families.")) } all_coefs <- base_model$coefficients @@ -360,8 +363,7 @@ fit_qap_model <- function(mod, pred, family, if (family == "zip" && estimator == "standard") { if (has_random) { - if (!requireNamespace("glmmTMB", quietly = TRUE)) - stop("Package 'glmmTMB' is required for mixed ZIP models.") + thisRequires("glmmTMB", "for mixed zero-inflated Poisson models") base_model <- glmmTMB::glmmTMB(mod, data = pred, family = stats::poisson(), ziformula = ~1) @@ -376,8 +378,7 @@ fit_qap_model <- function(mod, pred, family, fit$random.intercepts[[rV]] <- re[[rV]][, 1] } } else { - if (!requireNamespace("pscl", quietly = TRUE)) - stop("Package 'pscl' is required for zero-inflated Poisson models.") + thisRequires("pscl", "for zero-inflated Poisson models") base_model <- pscl::zeroinfl(mod, data = pred, dist = "poisson") fit$coefficients <- base_model$coefficients$count resid <- stats::residuals(base_model, type = "response") @@ -395,8 +396,7 @@ fit_qap_model <- function(mod, pred, family, if (!has_random) { if (use_fixest) { - if (!requireNamespace("fixest", quietly = TRUE)) - stop("Package 'fixest' is required when fixest_se_cluster or fixed effects with | ") + thisRequires("fixest", "for fixed effects and clustered standard errors") fe_family <- if (family == "negbin") "negbin" else family base_model <- fixest::feglm(mod, data = pred, family = fe_family, @@ -428,8 +428,7 @@ fit_qap_model <- function(mod, pred, family, fit$r.squared <- summary(base_model)$r.squared fit$adj.r.squared <- summary(base_model)$adj.r.squared } else if (family == "negbin") { - if (!requireNamespace("MASS", quietly = TRUE)) - stop("Package 'MASS' is required for negative binomial models.") + thisRequires("MASS", "for negative binomial models") base_model <- MASS::glm.nb(mod, data = pred) fit$theta <- base_model$theta } else { @@ -447,12 +446,10 @@ fit_qap_model <- function(mod, pred, family, } } else { if (family == "gaussian") { - if (!requireNamespace("lme4", quietly = TRUE)) - stop("Package 'lme4' is required for random effects.") + thisRequires("lme4", "for random effects") base_model <- lme4::lmer(mod, data = pred) } else if (family == "negbin") { - if (!requireNamespace("glmmTMB", quietly = TRUE)) - stop("Package 'glmmTMB' is required for mixed negative binomial models.") + thisRequires("glmmTMB", "for mixed negative binomial models") base_model <- glmmTMB::glmmTMB(mod, data = pred, family = glmmTMB::nbinom2()) fit$coefficients <- glmmTMB::fixef(base_model)$cond @@ -473,8 +470,7 @@ fit_qap_model <- function(mod, pred, family, fit$base_model <- base_model return(fit) } else { - if (!requireNamespace("lme4", quietly = TRUE)) - stop("Package 'lme4' is required for random effects.") + thisRequires("lme4", "for random effects") base_model <- lme4::glmer(mod, data = pred, family = family, control = lme4::glmerControl( calc.derivs = FALSE, diff --git a/man/infernet-package.Rd b/man/infernet-package.Rd index 5859ad3..08ec645 100644 --- a/man/infernet-package.Rd +++ b/man/infernet-package.Rd @@ -4,11 +4,11 @@ \name{infernet-package} \alias{infernet} \alias{infernet-package} -\title{infernet: Basic inferential models for many different types of networks} +\title{infernet: Inferential Models for Many Different Types of Networks} \description{ \if{html}{\figure{logo.png}{options: style='float: right' alt='logo' width='120'}} -A set of tools for testing networks. It includes functions for univariate and multivariate conditional uniform graph and quadratic assignment procedure testing, and network regression. +A set of tools for testing networks. It includes functions for univariate and multivariate conditional uniform graph and quadratic assignment procedure testing, and multiple regression quadratic assignment procedure (MRQAP) models for a range of families, with random and fixed effects, missing data, and cognitive social structures. Built on the 'manynet' package, all functions operate with matrices, edge lists, and 'igraph', 'network', and 'tidygraph' objects, and on one-mode and two-mode (bipartite) networks. } \seealso{ Useful links: @@ -21,6 +21,11 @@ Useful links: \author{ \strong{Maintainer}: James Hollway \email{james.hollway@graduateinstitute.ch} (\href{https://orcid.org/0000-0002-8361-9647}{ORCID}) (IHEID) [contributor] +Authors: +\itemize{ + \item James Hollway \email{james.hollway@graduateinstitute.ch} (\href{https://orcid.org/0000-0002-8361-9647}{ORCID}) (IHEID) [contributor] +} + Other contributors: \itemize{ \item Robert Krause (\href{https://orcid.org/0000-0003-4288-4732}{ORCID}) [contributor] diff --git a/man/regression.Rd b/man/regression.Rd index 2fe38b2..0b5c0bd 100644 --- a/man/regression.Rd +++ b/man/regression.Rd @@ -27,7 +27,7 @@ dyadic covariate. }} \item{.data}{A manynet-consistent network (see -\code{\link[manynet:coerce_graph]{manynet::as_tidygraph()}}), or a list of such networks. When a list is +\code{\link[manynet:as_tidygraph]{manynet::as_tidygraph()}}), or a list of such networks. When a list is supplied the model is fit jointly; graphs missing any predictor are dropped with a warning.} @@ -96,7 +96,7 @@ dropped with a warning and the remaining networks are pooled. } \examples{ \dontrun{ -networkers <- manynet::ison_networkers \%>\% +networkers <- manynet::ison_networkers |> manynet::to_subgraph(Discipline == "Sociology") model1 <- net_regression( weight ~ ego(Citations) + alter(Citations) + sim(Citations), @@ -118,7 +118,7 @@ conditions." \doi{10.1007/s11336-007-9016-1}. } \seealso{ -Other models: +Other models: \code{\link{tests}} } \concept{models} diff --git a/man/tests.Rd b/man/tests.Rd index c2469f6..61718f8 100644 --- a/man/tests.Rd +++ b/man/tests.Rd @@ -15,7 +15,7 @@ test_permutation(.data, FUN, ..., times = 1000, strategy = "sequential") } \arguments{ \item{.data}{A manynet-consistent network (see -\code{\link[manynet:coerce_graph]{manynet::as_tidygraph()}}), or a list of such networks. When a list is +\code{\link[manynet:as_tidygraph]{manynet::as_tidygraph()}}), or a list of such networks. When a list is supplied the model is fit jointly; graphs missing any predictor are dropped with a warning.} @@ -47,8 +47,8 @@ of the original network. } } \examples{ -marvel_friends <- fict_marvel \%>\% to_uniplex("relationship") \%>\% - to_unsigned() \%>\% to_giant() \%>\% +marvel_friends <- fict_marvel |> to_uniplex("relationship") |> + to_unsigned() |> to_giant() |> to_subgraph(PowerOrigin == "Human") (cugtest <- test_random(marvel_friends, net_by_heterophily, attribute = "Attractive", times = 200)) @@ -59,7 +59,7 @@ marvel_friends <- fict_marvel \%>\% to_uniplex("relationship") \%>\% # plot(qaptest) } \seealso{ -Other models: +Other models: \code{\link{regression}} } \concept{models} From 4f1307be75a5b9d53fcc6c63f318fc4aa5bcd369 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 07:43:48 +0200 Subject: [PATCH 18/20] Updated the `tests` documentation to describe `test_configuration()` --- NEWS.md | 1 + R/model_tests.R | 3 +++ man/tests.Rd | 3 +++ 3 files changed, 7 insertions(+) diff --git a/NEWS.md b/NEWS.md index aebf611..6c0898b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,6 +19,7 @@ ## Tests +- Updated the `tests` documentation to describe `test_configuration()` - Updated the examples to use the native pipe `|>` diff --git a/R/model_tests.R b/R/model_tests.R index d7e80b0..908b110 100644 --- a/R/model_tests.R +++ b/R/model_tests.R @@ -8,6 +8,9 @@ #' - `test_random()` performs a conditional uniform graph (CUG) test #' of a measure against a distribution of measures on random networks #' of the same dimensions. +#' - `test_configuration()` performs a CUG test against a distribution of +#' measures on random networks that preserve the degree sequence +#' of the original network. #' - `test_permutation()` performs a quadratic assignment procedure (QAP) test #' of a measure against a distribution of measures on permutations #' of the original network. diff --git a/man/tests.Rd b/man/tests.Rd index 61718f8..57c3f7b 100644 --- a/man/tests.Rd +++ b/man/tests.Rd @@ -41,6 +41,9 @@ These functions conduct tests of any network-level statistic: \item \code{test_random()} performs a conditional uniform graph (CUG) test of a measure against a distribution of measures on random networks of the same dimensions. +\item \code{test_configuration()} performs a CUG test against a distribution of +measures on random networks that preserve the degree sequence +of the original network. \item \code{test_permutation()} performs a quadratic assignment procedure (QAP) test of a measure against a distribution of measures on permutations of the original network. From 01e32fac9937566bfe464d7a727c3bbe3aeb4d1b Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 08:06:12 +0200 Subject: [PATCH 19/20] Added more comprehensive test suite and fixed miscellaneous bugs --- .github/CONTRIBUTING.md | 62 ++++- DESCRIPTION | 2 +- NEWS.md | 44 ++++ R/model_regression.R | 282 ++++++++++++---------- R/qap_css.R | 16 +- R/qap_engine.R | 49 ++-- R/qap_gpu.R | 9 +- R/qap_utils.R | 146 ++++++++--- tests/testthat/helper-infernet.R | 106 ++++++++ tests/testthat/test-model_tests.R | 64 +++++ tests/testthat/test-net_regression.R | 30 +++ tests/testthat/test-qap_control.R | 77 ++++++ tests/testthat/test-qap_estimators.R | 239 ++++++++++++++++++ tests/testthat/test-qap_reproducibility.R | 64 +++++ tests/testthat/test-qap_shapes.R | 89 +++++++ 15 files changed, 1078 insertions(+), 201 deletions(-) create mode 100644 tests/testthat/helper-infernet.R create mode 100644 tests/testthat/test-model_tests.R create mode 100644 tests/testthat/test-qap_control.R create mode 100644 tests/testthat/test-qap_estimators.R create mode 100644 tests/testthat/test-qap_reproducibility.R create mode 100644 tests/testthat/test-qap_shapes.R diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index d4e458b..adbbcf2 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -374,24 +374,66 @@ Please see the [testthat website](https://testthat.r-lib.org) for more details. (`Config/testthat/parallel: true`). `Config/testthat/start-first` should prioritise the test files that take longest to run. -Tests in `tests/testthat/` mirror the `R/` files -(e.g. `test-net_regression.R`, `test-zzz.R`). -Fixtures live in `tests/testthat/testdata/`. +Tests in `tests/testthat/` mirror the `R/` files for the exported functions +(`test-net_regression.R`, `test-model_tests.R`), +and are grouped by contract for the engine: -Three things are worth asserting for every estimator that is added: - -1. That the baseline coefficients match those of the equivalent - `lm()`/`glm()` fit on the same vectorised data. +| File | Asserts | +|---|---| +| `test-qap_estimators.R` | each `family` and `estimator` combination, against the equivalent standard fit | +| `test-qap_shapes.R` | the dyads that reach the model, for each shape of network | +| `test-qap_reproducibility.R` | that a seed reproduces a run, sequentially and in parallel | +| `test-qap_control.R` | the `control` list and the choice of null hypothesis | + +[tests/testthat/helper-infernet.R](../tests/testthat/helper-infernet.R) +holds the shared fixtures and expectations: + +- `qap_net_gaussian()`, `qap_net_binary()`, `qap_net_count()`, `qap_net_zip()`, + `qap_net_undirected()`, `qap_net_twomode()` — each seeded, and each carrying + real signal, so that every family converges and the comparison is not testing + noise against noise. +- `qap_reference_data()` — rebuilds the dyad-level data frame the engine fits, + so a baseline coefficient can be compared against `lm()`, `glm()`, + `MASS::glm.nb()`, `pscl::zeroinfl()`, `lme4::lmer()` or `fixest::feglm()` + on identical data. +- `expect_qap_shape()` — the shape contract every estimator meets, whatever it + fits underneath: named coefficients, and `lower`/`larger`/`abs` as + two-row matrices of proportions with matching dimnames. + +Four things are worth asserting for every estimator that is added: + +1. That the baseline coefficients match those of the equivalent standard fit on + the same dyad-level data, using `qap_reference_data()`. The permutation inference is what is novel; the point estimates are not, and they should agree. -2. That a given `seed` reproduces the same p-values. +2. That the result meets `expect_qap_shape()`. + Most engine defects found so far surfaced as a name or a dimension, not as a + wrong number: a backticked coefficient name broke double semi-partialling, + and a stray placeholder intercept broke the `{fixest}` path. +3. That a given `seed` reproduces the same p-values. Permutation results are only comparable across runs if the RNG is, - and `furrr_options(seed = TRUE)` is what makes that true in parallel. -3. That the estimator is reached at all. + and `furrr_options(seed = TRUE)` and `future.seed = TRUE` are what make that + true in parallel. +4. That the estimator is reached at all. Several paths in `fit_qap_model()` are selected by a combination of `family`, `estimator` and the random/fixed effects flags, so a test that does not name that combination does not cover it. +An estimator that needs a package from `Suggests` takes +`skip_if_not_installed()`, so the suite still passes where that package is +absent. Do not let a path go untested because the package is missing locally: +install it, and check that the test runs before you rely on the skip. + +Count the dyads rather than checking that a call returns. +A directed network of *n* nodes contributes *n*(*n*-1) dyads, an undirected one +*n*(*n*-1)/2, and a two-mode one every cell of its incidence matrix. +Each of those was wrong at some point, and each looked like a working model. + +A fitter's warning raised inside the permutation loop is held back, since it +would print once per draw; `aggregate_perm_results()` reports the number of +draws that failed outright. A test therefore should not expect a convergence +warning from a permutation, only from the baseline. + The aim is to work towards comprehensive coverage, so each change should be fully covered by tests. However, we also need to keep an eye on the clock: diff --git a/DESCRIPTION b/DESCRIPTION index 92c83f6..d9a01f2 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -59,5 +59,5 @@ Config/Needs/website: pkgdown Config/testthat/parallel: true Config/testthat/edition: 3 -Config/testthat/start-first: net_regression +Config/testthat/start-first: qap_estimators, model_tests Config/roxygen2/version: 8.1.0 diff --git a/NEWS.md b/NEWS.md index 6c0898b..61cc9c9 100644 --- a/NEWS.md +++ b/NEWS.md @@ -19,9 +19,53 @@ ## Tests +- Improved `test_permutation()` by dropping two unused computations - Updated the `tests` documentation to describe `test_configuration()` - Updated the examples to use the native pipe `|>` +## Regression + +- Added a test suite for the regression engine, in four files + - `test-qap_estimators.R` compares each estimator's baseline against the + equivalent `lm()`, `glm()`, `MASS`, `pscl`, `lme4`, or `fixest` fit + - `test-qap_shapes.R` counts the dyads that reach the model for a directed, + an undirected, a two-mode, a pooled, and a partly missing network + - `test-qap_reproducibility.R` fixes the seed contract, sequential and parallel + - `test-qap_control.R` covers the control list and the null-hypothesis choice + - `helper-infernet.R` holds the seeded fixtures and `expect_qap_shape()` +- Fixed a two-mode network being read as a square one + - An 18x14 incidence matrix produced 306 dyads rather than 252 + - `RMPerm()` now permutes the rows and the columns of a rectangular matrix + independently, rather than erroring on the shorter side + - `dist()` and `sim()` now read each mode separately, as `ego()` and + `alter()` already did +- Fixed an undirected network contributing each dyad twice, shrinking the standard error +- Fixed `family = "zip"` failing during permutation + - Several estimators returned backticked coefficient names, which double + semi-partialling could not look up + - Coefficient names are now cleaned on the one path every estimator takes +- Fixed the `{fixest}` path reporting two intercepts where none was absorbed +- Fixed crossed sender and receiver intercepts aborting the run + - Residualising falls back to no random intercepts, with a warning, where the + mixed fit is singular +- Fixed `use_gpu = TRUE` aborting where `{torch}` or CUDA is unavailable +- Improved `control` to reject a name it does not take, and offer the nearest +- Improved the permutation loop to hold back a fitter's convergence warnings + - These printed once per draw; the count of failed draws is still reported +- Improved `lower`, `larger`, and `abs` to carry the same row names under both + null hypotheses +- Improved `HC3()` by dropping a `gc()` call that ran once per permutation +- Improved the missing-predictor error to name the sender, receiver, and + network indices that a formula can also use +- Fixed `tertius()` rejecting a quoted summary function + - `tertius(x, "mean")`, the documented spelling, now works alongside + `tertius(x, mean)` +- Added tests for the `tertius()` spellings and for the missing-attribute error +- Fixed `R/model_regression.R`, which a bad merge left unable to parse + - Restored `.default_control()`, `.is_list_of_graphs()`, and the head of + `.prepare_list_of_graphs()` + - Removed `vectorise_list()`, and the copies of `logit_moments()` and + `logit_resid()` that duplicate `R/qap_gmm.R` # infernet 0.1.0 diff --git a/R/model_regression.R b/R/model_regression.R index 689d638..5b639d9 100644 --- a/R/model_regression.R +++ b/R/model_regression.R @@ -66,56 +66,6 @@ #' probability fitted values are clamped to 0/1 before sampling. #' @name regression #' @family models -#' @param formula A formula describing the relationship being tested. -#' Several additional terms are available to assist users investigate -#' the effects they are interested in. These include: -#' - `ego()` constructs a matrix where the cells reflect the value of -#' a named nodal attribute for an edge's sending node -#' - `alter()` constructs a matrix where the cells reflect the value of -#' a named nodal attribute for an edge's receiving node -#' - `same()` constructs a matrix where a 1 reflects -#' if two nodes' attribute values are the same -#' - `dist()` constructs a matrix where the cells reflect the -#' absolute difference between the attribute's values -#' for the sending and receiving nodes -#' - `sim()` constructs a matrix where the cells reflect the -#' proportional similarity between the attribute's values -#' for the sending and receiving nodes -#' - `tertius()` constructs a matrix where the cells reflect some -#' aggregate of an attribute associated with a node's other ties. -#' Currently "mean" and "sum" are available aggregating functions. -#' 'ego' is excluded from these calculations. -#' See Haunss and Hollway (2023) for more on this effect. -#' - dyadic covariates (other networks) can just be named -#' @param .data A manynet-consistent network. -#' See e.g. `manynet::as_tidygraph()` for more details. -#' @param method A method for establishing the null hypothesis. -#' Note that "qap" uses Dekker et al's (2007) double semi-partialling technique, -#' whereas "qapy" permutes only the $y$ variable. -#' "qap" is the default. -#' @param times Integer indicating number of simulations used for quantile estimation. -#' (Relevant to the null hypothesis test only - -#' the analysis itself is unaffected by this parameter.) -#' Note that, as for all Monte Carlo procedures, convergence is slower for more -#' extreme quantiles. -#' By default, `times=1000`. -#' 1,000 - 10,000 repetitions recommended for publication-ready results. -#' @param strategy If `{furrr}` is installed, -#' then multiple cores can be used to accelerate the function. -#' By default `"sequential"`, -#' but if multiple cores available, -#' then `"multisession"` or `"multicore"` may be useful. -#' Generally this is useful only when `times` > 1000. -#' See [`{furrr}`](https://furrr.futureverse.org) for more. -#' @param verbose Whether the function should report on its progress. -#' By default FALSE. -#' See [`{progressr}`](https://progressr.futureverse.org) for more. -#' @importFrom dplyr bind_cols left_join -#' @importFrom purrr flatten -#' @importFrom future plan -#' @importFrom furrr future_map_dfr furrr_options -#' @importFrom stats as.formula lm glm fitted.values residuals coefficients -#' @importFrom lme4 lmer glmer deviance.merMod #' @references #' Krackhardt, David. 1988. #' "Predicting with Networks: Nonparametric Multiple Regression Analysis @@ -130,7 +80,7 @@ #' \doi{10.1007/s11336-007-9016-1}. #' @examples #' \dontrun{ -#' networkers <- manynet::ison_networkers %>% +#' networkers <- manynet::ison_networkers |> #' manynet::to_subgraph(Discipline == "Sociology") #' model1 <- net_regression( #' weight ~ ego(Citations) + alter(Citations) + sim(Citations), @@ -143,11 +93,7 @@ net_regression <- function(formula, times = 1000, control = list()) { - ctrl <- .default_control() - if (length(control) > 0) { - ctrl[names(control)] <- control - } - ctrl$method <- match.arg(ctrl$method, choices = c("qap", "qapy")) + ctrl <- .resolve_control(control) if (.is_list_of_graphs(.data)) { prepared <- .prepare_list_of_graphs(formula, .data) @@ -210,14 +156,101 @@ net_regression <- function(formula, fit } + +# ---- default control ------------------------------------------------------- + +# Merges the user's list over the defaults. A name that is not a control is +# rejected rather than added silently: a misspelt name would otherwise leave the +# option it was meant to set at its default, with nothing to say so. +#' @keywords internal +#' @noRd +.resolve_control <- function(control = list()) { + ctrl <- .default_control() + if (length(control) == 0) { + ctrl$method <- match.arg(ctrl$method, choices = c("qap", "qapy")) + return(ctrl) + } + if (is.null(names(control)) || any(!nzchar(names(control)))) { + manynet::snet_abort("Every entry of {.arg control} must be named.") + } + unknown <- setdiff(names(control), names(ctrl)) + if (length(unknown) > 0) { + near <- vapply(unknown, function(u) { + d <- utils::adist(u, names(ctrl), ignore.case = TRUE)[1, ] + if (min(d) <= max(2, nchar(u) %/% 3)) names(ctrl)[which.min(d)] else NA_character_ + }, character(1)) + msg <- c("{.arg control} does not take {.val {unknown}}.") + if (any(!is.na(near))) { + msg <- c(msg, i = "Did you mean {.val {unname(near[!is.na(near)])}}?") + } + msg <- c(msg, i = "Available controls: {.val {names(ctrl)}}.") + manynet::snet_abort(msg) + } + ctrl[names(control)] <- control + ctrl$method <- match.arg(ctrl$method, choices = c("qap", "qapy")) + ctrl +} + +.default_control <- function() { + list( + method = c("qap", "qapy"), + strategy = "sequential", + family = "auto", + estimator = "standard", + mode = NULL, + diag = NULL, + seed = NULL, + groups = NULL, + ncores = NULL, + use_robust_errors = FALSE, + fixest_se_cluster = NULL, + reference = NULL, + comparison = NULL, + random_intercept_nets = FALSE, + random_intercept_sender = FALSE, + random_intercept_receiver = FALSE, + less_mem = FALSE, + use_gpu = FALSE + ) +} + + +# ---- input dispatch -------------------------------------------------------- + +.is_list_of_graphs <- function(x) { + if (!is.list(x)) return(FALSE) + if (inherits(x, c("igraph", "tbl_graph", "network", "data.frame"))) + return(FALSE) + if (length(x) == 0) return(FALSE) + first <- x[[1]] + inherits(first, c("igraph", "tbl_graph", "network")) || is.matrix(first) +} + + +.prepare_list_of_graphs <- function(formula, glist) { + ml_list <- vector("list", length(glist)) + fail_idx <- integer(0) + fail_reason <- character(0) + + for (i in seq_along(glist)) { + res <- tryCatch( + convertToMatrixList(formula, glist[[i]], advise = FALSE), + error = function(e) list(error = conditionMessage(e)) + ) + if (!is.null(res$error)) { + fail_idx <- c(fail_idx, i) + fail_reason <- c(fail_reason, res$error) + ml_list[[i]] <- NULL } else { ml_list[[i]] <- res } } + keep <- setdiff(seq_along(glist), fail_idx) if (length(keep) == 0) { - stop("None of the supplied networks could be converted for the given ", - "formula. Reasons:\n ", paste(fail_reason, collapse = "\n ")) + manynet::snet_abort( + c("None of the supplied networks could be converted for this formula.", + stats::setNames(unique(fail_reason), rep("x", length(unique(fail_reason)))))) } ref_names <- names(ml_list[[keep[1]]]$mydata) @@ -237,13 +270,11 @@ net_regression <- function(formula, } else { paste0("[", dropped, "]") } - warning("Dropping ", length(dropped), - " network(s) missing one or more predictors: ", - paste(dropped_labels, collapse = ", "), - call. = FALSE) + manynet::snet_warn( + "Dropping {length(dropped)} network{?s} missing one or more predictors: {.val {dropped_labels}}.") } if (length(keep) == 0) { - stop("All supplied networks were dropped due to missing predictors.") + manynet::snet_abort("All the supplied networks were dropped for missing predictors.") } kept_mls <- ml_list[keep] @@ -274,30 +305,6 @@ net_regression <- function(formula, v[1] } -vectorise_list <- function(glist, simplex, directed){ - if (missing(simplex)) { - simplex <- !manynet::is_complex(glist[[1]]) - } - if (missing(directed)) { - directed <- manynet::is_directed(glist[[1]]) - } - if (simplex) { - diag(glist[[1]]) <- NA - } - if (!directed) { - glist[[1]][upper.tri(glist[[1]])] <- NA - } - - furrr::future_map(glist,function(x) { - c(x)}) %>% - dplyr::bind_cols() %>% - stats::na.omit() %>% - suppressMessages() - - #suppressMessages(stats::na.omit(dplyr::bind_cols(furrr::future_map( - # glist,function(x) c(x))))) -} - .is_binary_outcome <- function(y) { vals <- if (is.list(y)) unlist(y, use.names = FALSE) else as.vector(y) @@ -540,6 +547,22 @@ print.net_regression <- function(x, ..., convertToMatrixList <- function(formula, .data, advise = TRUE) { data <- manynet::as_tidygraph(.data) DV <- manynet::as_matrix(data) + # The sender and the receiver of a tie come from one nodeset in a one-mode + # network and from two in a two-mode one, so a dyadic term must read the + # attribute once per mode rather than once per network. + side_matrices <- function(attrib, DV, twomode, type) { + if (twomode) { + rows <- matrix(attrib[!type], nrow(DV), ncol(DV)) + cols <- matrix(attrib[type], nrow(DV), ncol(DV), byrow = TRUE) + } else { + rows <- matrix(attrib, nrow(DV), ncol(DV)) + cols <- matrix(attrib, nrow(DV), ncol(DV), byrow = TRUE) + } + list(rows = rows, cols = cols) + } + twomode <- manynet::is_twomode(data) + node_type <- if (twomode) manynet::node_attribute(data, "type") else NULL + names_form <- getRHSNames(formula) .check_formula_vars(names_form$IVnames, data) if (advise) specificationAdvice(names_form$IVnames, data) @@ -596,24 +619,28 @@ convertToMatrixList <- function(formula, .data, advise = TRUE) { out } else if (IV[[elem]][1] == "dist") { if (is.character(manynet::node_attribute(data, IV[[elem]][2]))) { - stop("Distance undefined for factors.") + manynet::snet_abort( + c("{.fn dist} is undefined for a categorical attribute.", + i = "Try {.fn same} instead.")) } - rows <- matrix(manynet::node_attribute(data, IV[[elem]][2]), - nrow(DV), ncol(DV)) - cols <- matrix(manynet::node_attribute(data, IV[[elem]][2]), - nrow(DV), ncol(DV), byrow = TRUE) + sides <- side_matrices(manynet::node_attribute(data, IV[[elem]][2]), + DV, twomode, node_type) + rows <- sides$rows + cols <- sides$cols out <- abs(rows - cols) out <- list(out) names(out) <- paste(IV[[elem]], collapse = " ") out } else if (IV[[elem]][1] == "sim") { if (is.character(manynet::node_attribute(data, IV[[elem]][2]))) { - stop("Similarity undefined for factors. Try `same()` instead.") + manynet::snet_abort( + c("{.fn sim} is undefined for a categorical attribute.", + i = "Try {.fn same} instead.")) } - rows <- matrix(manynet::node_attribute(data, IV[[elem]][2]), - nrow(DV), ncol(DV)) - cols <- matrix(manynet::node_attribute(data, IV[[elem]][2]), - nrow(DV), ncol(DV), byrow = TRUE) + sides <- side_matrices(manynet::node_attribute(data, IV[[elem]][2]), + DV, twomode, node_type) + rows <- sides$rows + cols <- sides$cols denom <- max(abs(rows - cols), na.rm = TRUE) if (!is.finite(denom) || denom == 0) denom <- 1 out <- abs(1 - abs(rows - cols) / denom) @@ -629,6 +656,9 @@ convertToMatrixList <- function(formula, .data, advise = TRUE) { if (is.na(IV[[elem]][3])) { IV[[elem]][3] <- "mean" } + # The deparsed term keeps the quotation marks of `tertius(x, "mean")`, + # so strip them; otherwise only the unquoted spelling is recognised. + IV[[elem]][3] <- gsub('^"|"$', "", IV[[elem]][3]) out <- t(vapply(seq_len(nrow(DV)), function(x) { if (IV[[elem]][3] == "mean") { @@ -636,7 +666,8 @@ convertToMatrixList <- function(formula, .data, advise = TRUE) { } else if (IV[[elem]][3] == "sum") { colSums(val[-x, ], na.rm = TRUE) } else { - stop("tertius summary function not recognised") + manynet::snet_abort( + "{.fn tertius} takes {.val mean} or {.val sum}, not {.val {IV[[elem]][3]}}.") } }, FUN.VALUE = numeric(ncol(DV)))) @@ -651,7 +682,7 @@ convertToMatrixList <- function(formula, .data, advise = TRUE) { names(out) <- IV[[elem]][1] out } else { - stop("Predictor '", IV[[elem]][1], "' not found in the network.") + manynet::snet_abort("Predictor {.val {IV[[elem]][1]}} not found in the network.") } } }) @@ -763,7 +794,11 @@ getRHSNames <- function(formula) { .check_formula_vars <- function(IVnames, data) { node_fns <- c("ego", "alter", "same", "dist", "sim", "tertius") node_attrs <- manynet::net_node_attributes(data) - tie_attrs <- manynet::net_tie_attributes(data) + # The engine builds these columns itself in `make_qap_data()`: the sender, the + # receiver, the network, and the perceiver index. They are what a user names + # after a `|` to absorb sender or receiver fixed effects, so they are not + # attributes of the network and must not be looked for among them. + tie_attrs <- c(manynet::net_tie_attributes(data), .structural_vars()) missing_node <- character(0) missing_tie <- character(0) @@ -783,22 +818,26 @@ getRHSNames <- function(formula) { } if (length(missing_node) > 0) { - stop("Node attribute(s) not found: ", - paste(shQuote(unique(missing_node)), collapse = ", "), - ".\n Available: ", - paste(shQuote(node_attrs), collapse = ", "), - call. = FALSE) + manynet::snet_abort( + c("Node attribute{?s} {.val {unique(missing_node)}} not found.", + i = "Available node attributes: {.val {node_attrs}}.")) } if (length(missing_tie) > 0) { - stop("Tie attribute / predictor(s) not found: ", - paste(shQuote(unique(missing_tie)), collapse = ", "), - ".\n Available tie attributes: ", - paste(shQuote(tie_attrs), collapse = ", "), - call. = FALSE) + available <- manynet::net_tie_attributes(data) + structurals <- .structural_vars() + manynet::snet_abort( + c("Tie attribute or predictor{?s} {.val {unique(missing_tie)}} not found.", + i = "Available tie attributes: {.val {available}}.", + i = "Sender, receiver, and network indices are also available as {.val {structurals}}.")) } invisible(TRUE) } +# Columns the engine builds for every dyad, rather than reads off the network. +#' @keywords internal +#' @noRd +.structural_vars <- function() c("sv", "rv", "nv", "pv") + #' @keywords internal #' @noRd @@ -833,26 +872,9 @@ specificationAdvice <- function(formula, data) { if (length(suggests) > 1) { suggests <- paste0(suggests, collapse = ", ") } - cat(paste("When testing for homophily,", - "it is recommended to include all more fundamental effects.\n", - "Try adding", suggests, "to the model specification.\n\n")) + manynet::snet_info( + "When testing for homophily, include all the more fundamental effects.", + "Try adding {suggests} to the model specification.") } } } - -logit_moments <- function(theta, data) { - Y <- data$y - X <- data$x - prob <- 1 / (1 + exp(-1 * (X %*% theta))) - residuals <- as.vector(Y - prob) - g <- residuals * X - return(g) -} - -logit_resid <- function(gmmo) { - Y <- gmmo$dat$y - X <- gmmo$dat$x - prob <- 1 / (1 + exp(-1 * (X %*% gmmo$coefficients))) - residuals <- as.vector(Y - prob) - return(residuals) -} diff --git a/R/qap_css.R b/R/qap_css.R index a5c7b2d..7b14fe4 100644 --- a/R/qap_css.R +++ b/R/qap_css.R @@ -200,8 +200,12 @@ QAPcssPermEst <- function(i, xi_arg <- if (!is.null(perm_var.)) perm_var. else NULL if (is.null(comp.)) { + # A fit inside the permutation loop runs `reps` times, so a fitter's + # convergence warning would print once per draw and drown the console. + # The count of draws that failed outright is reported by + # `aggregate_perm_results()`, which is the number the user needs. perm_fit <- tryCatch( - fit_qap_model(mod = mod., + suppressWarnings(fit_qap_model(mod = mod., pred = pred, family = family., estimator = estimator., @@ -210,7 +214,7 @@ QAPcssPermEst <- function(i, use_robust_errors = use_robust_errors., main_vars = main_vars., has_random = has_random., - reference = reference.), + reference = reference.)), error = function(e) NULL ) if (is.null(perm_fit)) return(NULL) @@ -226,8 +230,12 @@ QAPcssPermEst <- function(i, predK <- pred[pred[[dep]] %in% comp.[[k]], ] predK[[dep]] <- ifelse(predK[[dep]] == comp.[[k]][1], 0, 1) + # A fit inside the permutation loop runs `reps` times, so a fitter's + # convergence warning would print once per draw and drown the console. + # The count of draws that failed outright is reported by + # `aggregate_perm_results()`, which is the number the user needs. perm_fit <- tryCatch( - fit_qap_model(mod = mod., + suppressWarnings(fit_qap_model(mod = mod., pred = predK, family = family., estimator = estimator., @@ -236,7 +244,7 @@ QAPcssPermEst <- function(i, use_robust_errors = use_robust_errors., main_vars = main_vars., has_random = has_random., - reference = reference.), + reference = reference.)), error = function(e) NULL ) if (is.null(perm_fit)) return(NULL) diff --git a/R/qap_engine.R b/R/qap_engine.R index 7d40c1c..8290bf9 100644 --- a/R/qap_engine.R +++ b/R/qap_engine.R @@ -130,8 +130,19 @@ QAPglm <- function(formula, if ((nullhyp == "qapspp") && (length(main) == 1)) nullhyp <- "qapy" - if (use_gpu && family == "gaussian" && !has_random && !use_fixest && - is.null(comparison) && !large) { + # The GPU path is a shortcut, not a requirement, so an unmet condition falls + # back to the CPU permutation loop rather than aborting. `gpu_available()` + # covers the two conditions the user cannot see from the call: whether + # {torch} is installed, and whether CUDA is reachable. + use_gpu <- use_gpu && family == "gaussian" && !has_random && !use_fixest && + is.null(comparison) && !large + if (use_gpu && !gpu_available()) { + manynet::snet_info( + "No CUDA device is reachable, so using the CPU permutation path.") + use_gpu <- FALSE + } + + if (use_gpu) { if (nullhyp == "qapy") { gpu_res <- gpu_batch_ols(data = data, @@ -148,10 +159,10 @@ QAPglm <- function(formula, } else if (nullhyp == "qapspp") { n_coefs <- length(fit$base$coefficients) - fit$lower <- matrix(NA, nrow = 2, ncol = n_coefs) + fit$lower <- matrix(NA, nrow = 2, ncol = n_coefs, + dimnames = list(c("perm_coefs", "perm_t"), + names(fit$base$coefficients))) fit$larger <- fit$abs <- fit$lower - colnames(fit$lower) <- colnames(fit$larger) <- - colnames(fit$abs) <- names(fit$base$coefficients) for (xi in main) { xR <- residualise_predictor(xi, pred, main, @@ -229,10 +240,10 @@ QAPglm <- function(formula, } else if (nullhyp == "qapspp") { if (is.null(comparison)) { n_coefs <- length(fit$base$coefficients) - fit$lower <- matrix(NA, nrow = 2, ncol = n_coefs) + fit$lower <- matrix(NA, nrow = 2, ncol = n_coefs, + dimnames = list(c("perm_coefs", "perm_t"), + names(fit$base$coefficients))) fit$larger <- fit$abs <- fit$lower - colnames(fit$lower) <- colnames(fit$larger) <- - colnames(fit$abs) <- names(fit$base$coefficients) } else { fit$lower <- fit$larger <- fit$abs <- vector("list", length(comparison)) @@ -240,10 +251,10 @@ QAPglm <- function(formula, names(fit$abs) <- names(comparison) for (k in seq_along(comparison)) { n_coefs <- length(fit$base[[k]]$coefficients) - fit$lower[[k]] <- matrix(NA, nrow = 2, ncol = n_coefs) + fit$lower[[k]] <- matrix(NA, nrow = 2, ncol = n_coefs, + dimnames = list(c("perm_coefs", "perm_t"), + names(fit$base[[k]]$coefficients))) fit$larger[[k]] <- fit$abs[[k]] <- fit$lower[[k]] - colnames(fit$lower[[k]]) <- colnames(fit$larger[[k]]) <- - colnames(fit$abs[[k]]) <- names(fit$base[[k]]$coefficients) } } @@ -423,8 +434,12 @@ QAPglmPermEst <- function(i, xi_arg <- if (!is.null(perm_var.)) perm_var. else NULL if (is.null(comp.)) { + # A fit inside the permutation loop runs `reps` times, so a fitter's + # convergence warning would print once per draw and drown the console. + # The count of draws that failed outright is reported by + # `aggregate_perm_results()`, which is the number the user needs. perm_fit <- tryCatch( - fit_qap_model(mod = mod., + suppressWarnings(fit_qap_model(mod = mod., pred = pred, family = family., estimator = estimator., @@ -433,7 +448,7 @@ QAPglmPermEst <- function(i, use_robust_errors = use_robust_errors., main_vars = main_vars., has_random = has_random., - reference = reference.), + reference = reference.)), error = function(e) NULL ) if (is.null(perm_fit)) return(NULL) @@ -449,8 +464,12 @@ QAPglmPermEst <- function(i, predK <- pred[pred[[dep]] %in% comp.[[k]], ] predK[[dep]] <- ifelse(predK[[dep]] == comp.[[k]][1], 0, 1) + # A fit inside the permutation loop runs `reps` times, so a fitter's + # convergence warning would print once per draw and drown the console. + # The count of draws that failed outright is reported by + # `aggregate_perm_results()`, which is the number the user needs. perm_fit <- tryCatch( - fit_qap_model(mod = mod., + suppressWarnings(fit_qap_model(mod = mod., pred = predK, family = family., estimator = estimator., @@ -459,7 +478,7 @@ QAPglmPermEst <- function(i, use_robust_errors = use_robust_errors., main_vars = main_vars., has_random = has_random., - reference = reference.), + reference = reference.)), error = function(e) NULL ) if (is.null(perm_fit)) return(NULL) diff --git a/R/qap_gpu.R b/R/qap_gpu.R index 61c39bf..5367665 100644 --- a/R/qap_gpu.R +++ b/R/qap_gpu.R @@ -9,10 +9,7 @@ gpu_batch_ols <- function(data, parsed, mode, diag, groups, reps, baseline_fit, perm_var = NULL, batch_size = 500, device = "cuda") { - if (!requireNamespace("torch", quietly = TRUE)) { - stop("The 'torch' package is required for GPU acceleration. ", - "Install it with: install.packages('torch')") - } + thisRequires("torch", "for GPU acceleration") if (device == "cuda" && !torch::cuda_is_available()) { manynet::snet_info("CUDA is not available, so falling back to CPU {.pkg torch}.") @@ -167,9 +164,7 @@ gpu_batch_ols_css <- function(data, parsed, mode, diag, groups, reps, baseline_fit, perm_var = NULL, batch_size = 500, device = "cuda") { - if (!requireNamespace("torch", quietly = TRUE)) { - stop("The 'torch' package is required for GPU acceleration.") - } + thisRequires("torch", "for GPU acceleration") if (device == "cuda" && !torch::cuda_is_available()) { manynet::snet_info("CUDA is not available, so falling back to CPU {.pkg torch}.") diff --git a/R/qap_utils.R b/R/qap_utils.R index 7f58295..2afd0c5 100644 --- a/R/qap_utils.R +++ b/R/qap_utils.R @@ -151,6 +151,18 @@ run_permutations <- function(reps, FUN, ...) { # ---- matrix permutation ----------------------------------------------------- +# One permutation of the node order, respecting a blocking factor where its +# length matches the mode being permuted. A `groups` vector of the wrong length +# cannot describe this mode, so that mode permutes freely rather than silently +# recycling the factor, which is what `split()` did before. +#' @keywords internal +#' @noRd +.perm_order <- function(n, groups = NULL) { + if (is.null(groups) || length(groups) != n) return(sample(seq_len(n))) + groups <- as.character(groups) + unsplit(lapply(split(seq_len(n), groups), FUN = sample), groups) +} + #' @keywords internal #' @noRd RMPerm <- function(m, groups = NULL, CSS = FALSE) { @@ -166,8 +178,20 @@ RMPerm <- function(m, groups = NULL, CSS = FALSE) { } if (length(dim(m)) == 2) { - o <- unsplit(lapply(split(1:dim(m)[1], groups), FUN = sample), groups) - p <- matrix(data = m[o, o], nrow = dim(m)[1], ncol = dim(m)[2]) + nr <- dim(m)[1] + nc <- dim(m)[2] + if (nr == nc) { + o <- unsplit(lapply(split(1:nr, groups), FUN = sample), groups) + p <- matrix(data = m[o, o], nrow = nr, ncol = nc) + } else { + # A two-mode incidence matrix has two nodesets, so the rows and the + # columns permute independently. Permuting both by one order, as the + # square case does, indexes past the shorter side and errors. + or <- .perm_order(nr, groups) + oc <- .perm_order(nc, groups) + p <- matrix(data = m[or, oc], nrow = nr, ncol = nc) + } + dimnames(p) <- dimnames(m) } else if (CSS) { p <- array(dim = c(dim(m)[1], dim(m)[2], dim(m)[3])) o <- unsplit(lapply(split(1:dim(m)[2], groups), FUN = sample), groups) @@ -197,9 +221,21 @@ make_qap_data <- function(y, x, g = NULL, diag = FALSE, mode = "digraph", x[[xi]] <- RMPerm(x[[xi]], g) } - n <- dim(y)[1] - valid <- matrix(TRUE, n, n) - if (!diag) diag(valid) <- FALSE + # The dependent matrix is square for a one-mode network and rectangular for a + # two-mode one. Reading `nc` from the matrix rather than assuming `nr` is what + # keeps a two-mode network from being read as a square one, which used to + # wrap past the last column and invent dyads. + nr <- dim(y)[1] + nc <- dim(y)[2] + square <- identical(nr, nc) + + valid <- matrix(TRUE, nr, nc) + if (!diag && square) diag(valid) <- FALSE + # An undirected one-mode network holds each dyad twice, once on each side of + # the diagonal. Keeping both halves doubles the sample and shrinks every + # standard error, so take the lower triangle only. A two-mode incidence + # matrix has no such symmetry, and keeps every cell. + if (identical(mode, "graph") && square) valid[upper.tri(valid)] <- FALSE for (var in seq_len(nx)) { valid[is.na(x[[var]])] <- FALSE @@ -214,23 +250,22 @@ make_qap_data <- function(y, x, g = NULL, diag = FALSE, mode = "digraph", } if (sum(vv) == 0) { - stop("No valid dyads remain after removing NA and diagonal cells for ", - "network ", net, ". Check that your predictors and outcome have ", - "non-missing values for overlapping node pairs.", - call. = FALSE) + manynet::snet_abort( + c("No valid dyads remain in network {net} after dropping NA and diagonal cells.", + i = "Check that the predictors and the outcome are observed for the same node pairs.")) } pred <- data.frame( - location = as.vector(matrix(seq_len(n^2), n, n))[vv], + location = as.vector(matrix(seq_len(nr * nc), nr, nc))[vv], yv = as.vector(y)[vv] ) pred$nv <- as.factor(net) - sv <- matrix(seq_len(n), n, n) + sv <- matrix(seq_len(nr), nr, nc) sv[!valid] <- NA pred$sv <- as.vector(sv)[vv] - rv <- t(matrix(seq_len(n), n, n)) + rv <- matrix(seq_len(nc), nr, nc, byrow = TRUE) rv[!valid] <- NA pred$rv <- as.vector(rv)[vv] @@ -256,17 +291,34 @@ HC3 <- function(X, e) { } h <- apply(XO, 1, hf, XTXINV = XTXINV) om <- e^2 / (1 - h)^2 - x <- sqrt(diag(t(t(XTXINV %*% t(XO)) * om) %*% XO %*% XTXINV)) - gc() - return(x) + # No gc() here: this runs once per permutation, and forcing a collection + # thousands of times costs far more than the memory it returns. + sqrt(diag(t(t(XTXINV %*% t(XO)) * om) %*% XO %*% XTXINV)) } # ---- baseline + perm fitting ------------------------------------------------ +# The predictor names carry spaces ("ego Age"), so the model formula quotes them +# and several fitters hand the backticks back in the coefficient names. Double +# semi-partialling then looks a column up by the unquoted name and fails with a +# subscript error. The inner function has many early returns, one per estimator, +# so the names are cleaned here, where every path passes through exactly once. +#' @keywords internal +#' @noRd +fit_qap_model <- function(...) { + fit <- .fit_qap_model(...) + for (el in c("coefficients", "t", "zi_coefficients")) { + if (!is.null(fit[[el]]) && !is.null(names(fit[[el]]))) { + names(fit[[el]]) <- gsub("`", "", names(fit[[el]]), fixed = TRUE) + } + } + fit +} + #' @keywords internal #' @noRd -fit_qap_model <- function(mod, pred, family, +.fit_qap_model <- function(mod, pred, family, estimator = "standard", use_fixest = FALSE, fixest_se_cluster = NULL, @@ -401,17 +453,33 @@ fit_qap_model <- function(mod, pred, family, base_model <- fixest::feglm(mod, data = pred, family = fe_family, cluster = fixest_se_cluster) - fit$coefficients <- c("(Intercept)" = NA, base_model$coefficients) + # {fixest} reports an intercept where no fixed effect is absorbed, and + # none where one is. Add the placeholder only in the second case; + # otherwise the coefficient vector carries two intercepts. + fe_coefs <- base_model$coefficients + fit$coefficients <- if ("(Intercept)" %in% names(fe_coefs)) { + fe_coefs + } else { + c("(Intercept)" = NA, fe_coefs) + } resid <- stats::residuals(base_model) + # `HC3()` and `vcov()` both return one standard error per estimated + # coefficient, so the placeholder is needed only where the intercept was + # absorbed and `fit$coefficients` carries an NA for it. + absorbed <- !("(Intercept)" %in% names(fe_coefs)) if (use_robust_errors) { xv <- as.matrix(pred[, main_vars, drop = FALSE]) hc <- HC3(xv, resid) - fit$t <- fit$coefficients / c(NA, hc[-1]) + fit$t <- if (absorbed) { + fit$coefficients / c(NA, hc[-1]) + } else { + fit$coefficients / hc + } } else { fe_se <- sqrt(diag(stats::vcov(base_model))) - fit$t <- c("(Intercept)" = NA, - base_model$coefficients / fe_se) + fe_t <- fe_coefs / fe_se + fit$t <- if (absorbed) c("(Intercept)" = NA, fe_t) else fe_t } names(fit$t) <- names(fit$coefficients) @@ -496,14 +564,6 @@ fit_qap_model <- function(mod, pred, family, } fit$base_model <- base_model - - if (!is.null(fit$coefficients) && !is.null(names(fit$coefficients))) { - names(fit$coefficients) <- gsub("`", "", names(fit$coefficients), fixed = TRUE) - } - if (!is.null(fit$t) && !is.null(names(fit$t))) { - names(fit$t) <- gsub("`", "", names(fit$t), fixed = TRUE) - } - return(fit) } @@ -536,10 +596,13 @@ compare_perm_to_baseline <- function(perm_coefs, perm_t, base_fit, aggregate_perm_results <- function(results, reps) { results <- Filter(Negate(is.null), results) n_valid <- length(results) - if (n_valid == 0) stop("All permutations failed to converge.") + if (n_valid == 0) + manynet::snet_abort( + c("All {reps} permutations failed to converge.", + i = "Try a simpler model, another {.arg family}, or fewer predictors.")) if (n_valid < reps) { - warning(reps - n_valid, " of ", reps, - " permutations failed and were excluded.") + manynet::snet_warn( + "{reps - n_valid} of {reps} permutation{?s} failed and {?was/were} excluded.") } resL <- unlist(results, recursive = FALSE) list( @@ -574,9 +637,24 @@ residualise_predictor <- function(xi, pred, main_vars, if (!has_random) { xm <- stats::lm(modx, data = pred) } else { - if (!requireNamespace("lme4", quietly = TRUE)) - stop("Package 'lme4' is required for random effects.") - xm <- lme4::lmer(modx, data = pred) + thisRequires("lme4", "for random effects") + # Residualising is a step towards the null distribution, not a result the + # user reads, so a degenerate mixed fit here must not abort the whole run. + # Crossed sender and receiver intercepts on a predictor are often singular, + # and `lmer()` then stops with "Downdated VtV is not positive definite". + xm <- tryCatch(suppressWarnings(lme4::lmer(modx, data = pred)), + error = function(e) NULL) + if (is.null(xm)) { + manynet::snet_warn( + c("Could not residualise {.val {xi}} with random intercepts.", + i = "Residualising it without them instead.")) + xm <- stats::lm(stats::as.formula( + paste(bq(xi), "~ 1", + if (length(others) > 0) + paste("+", paste(vapply(others, bq, character(1)), + collapse = " + ")) else "")), + data = pred) + } } stats::residuals(xm) } diff --git a/tests/testthat/helper-infernet.R b/tests/testthat/helper-infernet.R new file mode 100644 index 0000000..6c1e688 --- /dev/null +++ b/tests/testthat/helper-infernet.R @@ -0,0 +1,106 @@ +# Shared fixtures and helpers. +# +# Every fixture is seeded and carries real signal, so that each family converges +# and the reference comparison is not testing noise against noise. +# `times` stays small everywhere: these tests check the estimator, not the +# precision of the null distribution. + +# ---- fixtures --------------------------------------------------------------- + +qap_net_gaussian <- function(n = 30, seed = 101) { + set.seed(seed) + age <- stats::runif(n, 20, 60) + m <- outer(age, age, function(a, b) 0.05 * a - 0.03 * b) + + matrix(stats::rnorm(n^2, sd = 0.5), n, n) + diag(m) <- 0 + manynet::mutate(manynet::as_tidygraph(m), + Age = age, + Cit = stats::rpois(n, 5), + Grp = rep(c("a", "b", "c"), length.out = n)) +} + +qap_net_binary <- function(n = 30, seed = 102) { + set.seed(seed) + age <- stats::runif(n, 20, 60) + p <- stats::plogis(outer(age, age, function(a, b) 0.06 * (a - 40) - 0.04 * (b - 40))) + m <- matrix(stats::rbinom(n^2, 1, p), n, n) + diag(m) <- 0 + manynet::mutate(manynet::as_tidygraph(m), + Age = age, + Grp = rep(c("a", "b", "c"), length.out = n)) +} + +qap_net_count <- function(n = 30, seed = 103) { + set.seed(seed) + age <- stats::runif(n, 20, 60) + lambda <- exp(outer(age, age, function(a, b) 0.02 * (a - 40) - 0.01 * (b - 40))) + m <- matrix(stats::rpois(n^2, lambda), n, n) + diag(m) <- 0 + manynet::mutate(manynet::as_tidygraph(m), Age = age) +} + +qap_net_zip <- function(n = 30, seed = 104) { + set.seed(seed) + age <- stats::runif(n, 20, 60) + lambda <- exp(outer(age, age, function(a, b) 0.02 * (a - 40) - 0.01 * (b - 40))) + m <- matrix(stats::rpois(n^2, lambda) * stats::rbinom(n^2, 1, 0.7), n, n) + diag(m) <- 0 + manynet::mutate(manynet::as_tidygraph(m), Age = age) +} + +qap_net_undirected <- function(n = 24, seed = 105) { + set.seed(seed) + age <- stats::runif(n, 20, 60) + m <- outer(age, age, function(a, b) 0.02 * (a + b)) + + matrix(stats::rnorm(n^2, sd = 0.5), n, n) + m <- (m + t(m)) / 2 + diag(m) <- 0 + manynet::mutate(manynet::as_tidygraph(m, twomode = FALSE), Age = age) +} + +qap_net_twomode <- function(seed = 106) { + set.seed(seed) + sw <- manynet::ison_southern_women + manynet::mutate(sw, Att = stats::runif(manynet::net_nodes(sw))) +} + +# ---- reference data --------------------------------------------------------- + +# Rebuilds the dyad-level data frame that the engine fits, so that a baseline +# coefficient can be compared against the equivalent standard fit on identical +# data. Anything this returns comes from the engine's own internals, so a +# comparison against it tests the estimator dispatch, not the vectorisation. +qap_reference_data <- function(formula, .data, mode = NULL, diag = FALSE) { + ml <- convertToMatrixList(formula, .data, advise = FALSE) + parsed <- parse_qap_formula(ml$formula) + g <- manynet::as_tidygraph(.data) + if (is.null(mode)) { + mode <- if (manynet::is_directed(g)) "digraph" else "graph" + } + pred <- make_qap_data(y = ml$mydata[[parsed$dependent]], + x = ml$mydata[parsed$main], + diag = diag, mode = mode) + names(pred)[names(pred) == "yv"] <- parsed$dependent + list(pred = pred, formula = ml$formula, parsed = parsed) +} + +# ---- expectations ----------------------------------------------------------- + +# The p-value matrices are the product of the permutation loop, so their shape +# is the contract every estimator has to meet, whatever it fits underneath. +expect_qap_shape <- function(fit, coefs) { + testthat::expect_s3_class(fit, "net_regression") + testthat::expect_named(fit$coefficients, coefs) + for (el in c("lower", "larger", "abs")) { + m <- fit[[el]] + testthat::expect_equal(dim(m), c(2L, length(coefs)), + info = paste("dim of", el)) + testthat::expect_equal(rownames(m), c("perm_coefs", "perm_t"), + info = paste("rownames of", el)) + testthat::expect_equal(colnames(m), coefs, info = paste("colnames of", el)) + finite <- m[!is.na(m)] + testthat::expect_true(all(finite >= 0 & finite <= 1), + info = paste(el, "outside [0, 1]")) + } + invisible(fit) +} diff --git a/tests/testthat/test-model_tests.R b/tests/testthat/test-model_tests.R new file mode 100644 index 0000000..360dc9f --- /dev/null +++ b/tests/testthat/test-model_tests.R @@ -0,0 +1,64 @@ +# Making sure the tests family of functions works as intended. +# Ported from {migraph}, which these functions supersede. + +marvel_friends <- manynet::to_uniplex(manynet::fict_marvel, "relationship") |> + manynet::to_giant() |> manynet::to_unsigned() |> + manynet::to_subgraph(PowerOrigin == "Human") + +cugtest <- test_random(marvel_friends, + netrics::net_by_heterophily, + attribute = "Attractive", + times = 200) +cugtest2 <- test_random(marvel_friends, + netrics::net_by_betweenness, + times = 200) + +test_that("test_random works", { + expect_equal(as.numeric(cugtest$testval), -0.85714, tolerance = 0.001) + expect_length(cugtest$testdist, 200) # NB: Stochastic + expect_false(cugtest$mode) + expect_false(cugtest$diag) + expect_equal(cugtest$cmode, "edges") + expect_type(cugtest$plteobs, "double") + expect_type(cugtest$pgteobs, "double") + expect_equal(cugtest$reps, 200) + expect_s3_class(cugtest, "network_test") + expect_equal(as.numeric(cugtest2$testval), 0.2375, tolerance = 0.001) + expect_length(cugtest2$testdist, 200) # NB: Stochastic + expect_equal(round(cugtest2$plteobs), 1) + expect_equal(round(cugtest2$pgteobs), 0) + expect_s3_class(cugtest2, "network_test") +}) + +qaptest <- test_permutation(marvel_friends, + netrics::net_by_heterophily, + attribute = "Attractive", + times = 200) + +test_that("test_permutation works", { + expect_equal(as.numeric(qaptest$testval), -0.85714, tolerance = 0.001) + expect_type(qaptest$plteobs, "double") # NB: Stochastic + expect_type(qaptest$pgteobs, "double") # NB: Stochastic + expect_length(qaptest$testdist, 200) # NB: Stochastic + expect_equal(qaptest$reps, 200) + expect_s3_class(qaptest, "network_test") +}) + +test_that("test_configuration works", { + testthat::skip_on_os("linux") + configtest <- test_configuration(marvel_friends, + netrics::net_by_heterophily, + attribute = "Attractive", + times = 200) + expect_s3_class(configtest, "network_test") + expect_equal(as.numeric(configtest$testval), -0.85714, tolerance = 0.001) + expect_type(configtest$plteobs, "double") # NB: Stochastic + expect_type(configtest$pgteobs, "double") # NB: Stochastic + expect_length(configtest$testdist, 200) # NB: Stochastic +}) + +test_that("print.network_test prints and returns its input invisibly", { + expect_output(print(cugtest), "CUG Test Results") + expect_invisible(print(cugtest)) + expect_identical(withVisible(print(cugtest))$value, cugtest) +}) diff --git a/tests/testthat/test-net_regression.R b/tests/testthat/test-net_regression.R index 8b1344e..8099553 100644 --- a/tests/testthat/test-net_regression.R +++ b/tests/testthat/test-net_regression.R @@ -140,3 +140,33 @@ test_that("method = 'qapy' runs and flags the nullhyp on the fit", { control = list(method = "qapy")) expect_equal(fit$nullhyp, "qapy") }) + + +# ---- tertius --------------------------------------------------------------- + +test_that("tertius() accepts a quoted and an unquoted summary function", { + g <- make_weighted_net() + quoted <- net_regression(weight ~ tertius(Age, "mean"), g, times = 10) + unquoted <- net_regression(weight ~ tertius(Age, mean), g, times = 10) + bare <- net_regression(weight ~ tertius(Age), g, times = 10) + expect_equal(quoted$coefficients, unquoted$coefficients) + expect_equal(quoted$coefficients, bare$coefficients) +}) + +test_that("tertius() sum differs from mean, and rejects anything else", { + g <- make_weighted_net() + mean_fit <- net_regression(weight ~ tertius(Age, "mean"), g, times = 10) + sum_fit <- net_regression(weight ~ tertius(Age, "sum"), g, times = 10) + expect_false(isTRUE(all.equal(mean_fit$coefficients, sum_fit$coefficients))) + expect_error(net_regression(weight ~ tertius(Age, "median"), g, times = 10), + "mean") +}) + + +# ---- messaging ------------------------------------------------------------- + +test_that("a missing attribute names what is available", { + g <- make_weighted_net() + expect_error(net_regression(weight ~ ego(Nope), g, times = 10), + "Age") +}) diff --git a/tests/testthat/test-qap_control.R b/tests/testthat/test-qap_control.R new file mode 100644 index 0000000..fcb98bd --- /dev/null +++ b/tests/testthat/test-qap_control.R @@ -0,0 +1,77 @@ +# `control` is merged over the defaults by name, so a name that is not a control +# would be added silently and the option it was meant to set would keep its +# default, with nothing to say so. + +FORM <- weight ~ ego(Age) + alter(Age) + +test_that("an unknown control name is rejected, with the nearest match", { + g <- qap_net_gaussian(n = 15) + expect_error( + net_regression(FORM, g, times = 5, control = list(strateggy = "sequential")), + "strategy") + expect_error( + net_regression(FORM, g, times = 5, control = list(nonsense = 1)), + "nonsense") +}) + +test_that("an unnamed control entry is rejected", { + g <- qap_net_gaussian(n = 15) + expect_error( + net_regression(FORM, g, times = 5, control = list("sequential")), + "named") +}) + +test_that("an empty control list gives the defaults", { + expect_equal(.resolve_control(list()), .resolve_control()) + expect_equal(.resolve_control()$method, "qap") + expect_equal(.resolve_control()$strategy, "sequential") + expect_equal(.resolve_control()$family, "auto") +}) + +test_that("a named control overrides only that default", { + ctrl <- .resolve_control(list(family = "poisson")) + expect_equal(ctrl$family, "poisson") + expect_equal(ctrl$strategy, "sequential") + expect_equal(ctrl$estimator, "standard") +}) + +test_that("method takes only the two spellings it documents", { + expect_equal(.resolve_control(list(method = "qapy"))$method, "qapy") + expect_error(.resolve_control(list(method = "spp"))) +}) + +test_that("method = 'qapy' is recorded on the fit and gives a full matrix", { + g <- qap_net_gaussian(n = 20) + fit <- net_regression(FORM, g, times = 10, + control = list(seed = 1, method = "qapy")) + expect_equal(fit$nullhyp, "qapy") + # Permuting y alone tests every coefficient, the intercept included, whereas + # double semi-partialling residualises one predictor at a time. + expect_false(anyNA(fit$lower)) + spp <- net_regression(FORM, g, times = 10, control = list(seed = 1)) + expect_equal(spp$nullhyp, "qapspp") + expect_true(all(is.na(spp$lower[, "(Intercept)"]))) +}) + +test_that("a single predictor falls back from qapspp to qapy", { + g <- qap_net_gaussian(n = 20) + fit <- net_regression(weight ~ ego(Age), g, times = 10, + control = list(seed = 1, method = "qap")) + # Double semi-partialling residualises a predictor against the others, and + # with one predictor there are none. + expect_equal(fit$nullhyp, "qapy") +}) + +test_that("mode and diag are read from the network unless set", { + g <- qap_net_gaussian(n = 15) + expect_equal(net_regression(FORM, g, times = 5, + control = list(seed = 1))$mode, "directed") + expect_equal(net_regression(FORM, g, times = 5, + control = list(seed = 1, + mode = "undirected"))$mode, + "undirected") + loops <- net_regression(FORM, g, times = 5, + control = list(seed = 1, diag = TRUE)) + expect_true(loops$diag) + expect_equal(nrow(loops$pred), 15 * 15) +}) diff --git a/tests/testthat/test-qap_estimators.R b/tests/testthat/test-qap_estimators.R new file mode 100644 index 0000000..2642e1b --- /dev/null +++ b/tests/testthat/test-qap_estimators.R @@ -0,0 +1,239 @@ +# Every estimator path in fit_qap_model() is selected by a combination of +# `family`, `estimator`, and the random and fixed effect flags. This file names +# each combination, so that a path with no test fails the build rather than +# going unnoticed. +# +# Two things are asserted for each. First, the baseline coefficients equal those +# of the equivalent standard fit on the same dyad-level data: the permutation +# inference is the novel part, the point estimates are not. Second, the result +# meets the shape contract in `expect_qap_shape()`. + +COEFS3 <- c("(Intercept)", "ego Age", "alter Age", "sim Age") +FORM <- weight ~ ego(Age) + alter(Age) + sim(Age) +FORM_B <- . ~ ego(Age) + alter(Age) + sim(Age) + + +# ---- gaussian -------------------------------------------------------------- + +test_that("gaussian baseline matches lm() on the same dyads", { + g <- qap_net_gaussian() + ref <- qap_reference_data(FORM, g) + lm_fit <- stats::lm(ref$formula, data = ref$pred) + + fit <- net_regression(FORM, g, times = 10, control = list(seed = 1)) + expect_qap_shape(fit, COEFS3) + expect_equal(unname(fit$coefficients), unname(stats::coef(lm_fit))) + expect_equal(unname(fit$t), unname(summary(lm_fit)$coefficients[, 3])) + expect_equal(fit$r.squared, summary(lm_fit)$r.squared) + expect_equal(fit$adj.r.squared, summary(lm_fit)$adj.r.squared) + expect_equal(fit$family, "gaussian") +}) + +test_that("gaussian with HC3 keeps the coefficients and changes the t values", { + g <- qap_net_gaussian() + plain <- net_regression(FORM, g, times = 10, control = list(seed = 1)) + robust <- net_regression(FORM, g, times = 10, + control = list(seed = 1, use_robust_errors = TRUE)) + expect_qap_shape(robust, COEFS3) + expect_equal(robust$coefficients, plain$coefficients) + expect_false(isTRUE(all.equal(robust$t, plain$t))) + expect_true(robust$robust_se) +}) + + +# ---- binomial and poisson -------------------------------------------------- + +test_that("binomial baseline matches glm() on the same dyads", { + g <- qap_net_binary() + ref <- qap_reference_data(FORM_B, g) + glm_fit <- stats::glm(ref$formula, data = ref$pred, + family = stats::binomial()) + + fit <- net_regression(FORM_B, g, times = 10, + control = list(seed = 1, family = "binomial")) + expect_qap_shape(fit, COEFS3) + expect_equal(unname(fit$coefficients), unname(stats::coef(glm_fit))) + expect_equal(unname(fit$t), unname(summary(glm_fit)$coefficients[, 3])) +}) + +test_that("family = 'auto' picks binomial for a binary outcome", { + auto <- net_regression(FORM_B, qap_net_binary(), times = 10, + control = list(seed = 1)) + named <- net_regression(FORM_B, qap_net_binary(), times = 10, + control = list(seed = 1, family = "binomial")) + expect_equal(auto$family, "binomial") + expect_equal(auto$coefficients, named$coefficients) +}) + +test_that("poisson baseline matches glm() on the same dyads", { + g <- qap_net_count() + ref <- qap_reference_data(FORM, g) + glm_fit <- stats::glm(ref$formula, data = ref$pred, family = stats::poisson()) + + fit <- net_regression(FORM, g, times = 10, + control = list(seed = 1, family = "poisson")) + expect_qap_shape(fit, COEFS3) + expect_equal(unname(fit$coefficients), unname(stats::coef(glm_fit))) +}) + + +# ---- negative binomial and zero-inflated Poisson --------------------------- + +test_that("negbin baseline matches MASS::glm.nb() on the same dyads", { + skip_if_not_installed("MASS") + g <- qap_net_count() + ref <- qap_reference_data(FORM, g) + nb <- suppressWarnings(MASS::glm.nb(ref$formula, data = ref$pred)) + + fit <- suppressWarnings( + net_regression(FORM, g, times = 10, + control = list(seed = 1, family = "negbin"))) + expect_qap_shape(fit, COEFS3) + expect_equal(unname(fit$coefficients), unname(stats::coef(nb))) + expect_equal(fit$theta, nb$theta) +}) + +test_that("zip baseline matches pscl::zeroinfl() and names its coefficients", { + skip_if_not_installed("pscl") + g <- qap_net_zip() + ref <- qap_reference_data(FORM, g) + zi <- pscl::zeroinfl(ref$formula, data = ref$pred, dist = "poisson") + + fit <- net_regression(FORM, g, times = 10, + control = list(seed = 1, family = "zip")) + # A backticked name here used to break double semi-partialling, which looks a + # column up by the unquoted predictor name. + expect_qap_shape(fit, COEFS3) + expect_false(any(grepl("`", names(fit$coefficients), fixed = TRUE))) + expect_equal(unname(fit$coefficients), unname(zi$coefficients$count)) + expect_equal(unname(fit$zi_coefficients), unname(zi$coefficients$zero)) +}) + + +# ---- GMM ------------------------------------------------------------------- + +test_that("the GMM estimator runs for each family it declares", { + skip_if_not_installed("gmm") + cases <- list( + list(form = FORM_B, net = qap_net_binary(), family = "binomial"), + list(form = FORM, net = qap_net_count(), family = "poisson"), + list(form = FORM, net = qap_net_count(), family = "negbin"), + list(form = FORM, net = qap_net_zip(), family = "zip") + ) + for (case in cases) { + fit <- suppressWarnings( + net_regression(case$form, case$net, times = 10, + control = list(seed = 1, family = case$family, + estimator = "gmm"))) + expect_qap_shape(fit, COEFS3) + expect_equal(fit$estimator, "gmm", info = case$family) + } +}) + +test_that("the GMM estimator rejects a family it cannot fit", { + skip_if_not_installed("gmm") + expect_error( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(family = "gaussian", estimator = "gmm")), + "binomial") +}) + + +# ---- random effects -------------------------------------------------------- + +test_that("gaussian random intercepts match lme4::lmer() on the same dyads", { + skip_if_not_installed("lme4") + g <- qap_net_gaussian() + ref <- qap_reference_data(FORM, g) + mixed <- suppressMessages(suppressWarnings( + lme4::lmer(build_internal_formula(ref$formula, ris = TRUE), + data = ref$pred))) + + fit <- suppressMessages(suppressWarnings( + net_regression(FORM, g, times = 10, + control = list(seed = 1, random_intercept_sender = TRUE)))) + expect_qap_shape(fit, COEFS3) + expect_equal(unname(fit$coefficients), + unname(summary(mixed)$coefficients[, 1])) + expect_named(fit$random.intercepts, "sv") +}) + +test_that("crossed sender and receiver intercepts do not abort the run", { + skip_if_not_installed("lme4") + # Residualising a predictor against both intercepts is often singular, and + # `lmer()` then stops with "Downdated VtV is not positive definite". That is + # a step towards the null distribution, so it falls back rather than aborting. + fit <- suppressMessages(suppressWarnings( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, + random_intercept_sender = TRUE, + random_intercept_receiver = TRUE)))) + expect_qap_shape(fit, COEFS3) +}) + +test_that("binomial and poisson random intercepts run", { + skip_if_not_installed("lme4") + bin <- suppressMessages(suppressWarnings( + net_regression(FORM_B, qap_net_binary(), times = 10, + control = list(seed = 1, family = "binomial", + random_intercept_sender = TRUE)))) + expect_qap_shape(bin, COEFS3) + pois <- suppressMessages(suppressWarnings( + net_regression(FORM, qap_net_count(), times = 10, + control = list(seed = 1, family = "poisson", + random_intercept_sender = TRUE)))) + expect_qap_shape(pois, COEFS3) +}) + + +# ---- fixed effects and clustered errors ------------------------------------ + +test_that("fixest reports one intercept, not two", { + skip_if_not_installed("fixest") + # `feglm()` reports an intercept where no fixed effect is absorbed. The engine + # used to prepend a placeholder regardless, giving two. + fit <- net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, fixest_se_cluster = "sv")) + expect_qap_shape(fit, COEFS3) + expect_equal(sum(names(fit$coefficients) == "(Intercept)"), 1L) + expect_false(anyNA(fit$coefficients)) + expect_equal(length(fit$t), length(fit$coefficients)) +}) + +test_that("fixest coefficients match a direct feglm() fit", { + skip_if_not_installed("fixest") + g <- qap_net_gaussian() + ref <- qap_reference_data(FORM, g) + fe <- fixest::feglm(ref$formula, data = ref$pred, + family = "gaussian", cluster = "sv") + + fit <- net_regression(FORM, g, times = 10, + control = list(seed = 1, fixest_se_cluster = "sv")) + expect_equal(unname(fit$coefficients), unname(fe$coefficients)) +}) + +test_that("fixed effects and random effects together fall back to random", { + skip_if_not_installed("fixest") + skip_if_not_installed("lme4") + expect_warning( + fit <- suppressMessages( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, fixest_se_cluster = "sv", + random_intercept_sender = TRUE))), + "random effects") + expect_qap_shape(fit, COEFS3) +}) + + +# ---- GPU ------------------------------------------------------------------- + +test_that("use_gpu falls back to the CPU rather than aborting", { + # The GPU path is a shortcut, so an unmet condition must not stop the run. + gpu <- suppressMessages( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, use_gpu = TRUE))) + cpu <- net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1)) + expect_qap_shape(gpu, COEFS3) + if (!gpu_available()) expect_equal(gpu$lower, cpu$lower) +}) diff --git a/tests/testthat/test-qap_reproducibility.R b/tests/testthat/test-qap_reproducibility.R new file mode 100644 index 0000000..afb1060 --- /dev/null +++ b/tests/testthat/test-qap_reproducibility.R @@ -0,0 +1,64 @@ +# A permutation result that cannot be reproduced cannot be published, so the +# seed is part of the interface rather than an implementation detail. + +FORM <- weight ~ ego(Age) + alter(Age) + sim(Age) + +test_that("the same seed gives the same p-values", { + g <- qap_net_gaussian() + a <- net_regression(FORM, g, times = 30, control = list(seed = 99)) + b <- net_regression(FORM, g, times = 30, control = list(seed = 99)) + expect_equal(a$lower, b$lower) + expect_equal(a$larger, b$larger) + expect_equal(a$abs, b$abs) + expect_equal(a$coefficients, b$coefficients) +}) + +test_that("a different seed gives a different null distribution", { + # Pure noise, so that the tallies land inside (0, 1) and can differ. A strong + # effect drives every p-value to 0 or 1 under any seed, which would make this + # assertion pass for the wrong reason. + set.seed(77) + n <- 25 + m <- matrix(stats::rnorm(n^2), n, n) + diag(m) <- 0 + g <- manynet::mutate(manynet::as_tidygraph(m), Age = stats::runif(n, 20, 60)) + a <- net_regression(FORM, g, times = 60, control = list(seed = 99)) + b <- net_regression(FORM, g, times = 60, control = list(seed = 7)) + # The observed model does not depend on the seed; only the null does. + expect_equal(a$coefficients, b$coefficients) + expect_false(isTRUE(all.equal(a$lower, b$lower))) +}) + +test_that("an outer set.seed() reproduces a run with no seed control", { + g <- qap_net_gaussian() + set.seed(5); a <- net_regression(FORM, g, times = 30) + set.seed(5); b <- net_regression(FORM, g, times = 30) + expect_equal(a$lower, b$lower) +}) + +test_that("a parallel plan gives the same answer as a sequential one", { + skip_on_cran() + g <- qap_net_gaussian() + seq <- net_regression(FORM, g, times = 30, control = list(seed = 99)) + par <- net_regression(FORM, g, times = 30, + control = list(seed = 99, strategy = "multisession")) + # `furrr_options(seed = TRUE)` and `future.seed = TRUE` are what make this + # true; without them the plan would change the result. + expect_equal(par$lower, seq$lower) + expect_equal(par$coefficients, seq$coefficients) +}) + +test_that("the future plan is restored after a run", { + before <- class(future::plan()) + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, strategy = "multisession")) + expect_equal(class(future::plan()), before) +}) + +test_that("the test family reproduces under an outer seed", { + g <- qap_net_gaussian(n = 18) + set.seed(3); a <- test_random(g, netrics::net_by_density, times = 30) + set.seed(3); b <- test_random(g, netrics::net_by_density, times = 30) + expect_equal(a$testdist, b$testdist) + expect_equal(a$pgteobs, b$pgteobs) +}) diff --git a/tests/testthat/test-qap_shapes.R b/tests/testthat/test-qap_shapes.R new file mode 100644 index 0000000..e5c81ac --- /dev/null +++ b/tests/testthat/test-qap_shapes.R @@ -0,0 +1,89 @@ +# Properties of the dependent network -- modes, directedness, loops -- must be +# respected in the data the engine fits and in the permutations it draws. +# Each shape below was wrong at some point, so each is asserted by counting the +# dyads that reach the model rather than by checking that the call returns. + +test_that("a directed network contributes every ordered dyad", { + g <- qap_net_gaussian(n = 20) + fit <- net_regression(weight ~ ego(Age), g, times = 10, control = list(seed = 1)) + expect_equal(fit$mode, "directed") + expect_equal(nrow(fit$pred), 20 * 19) +}) + +test_that("an undirected network contributes each dyad once", { + g <- qap_net_undirected(n = 24) + expect_false(manynet::is_directed(g)) + fit <- net_regression(weight ~ ego(Age), g, times = 10, control = list(seed = 1)) + # Both halves of a symmetric matrix hold the same dyad. Keeping both doubles + # the sample and shrinks every standard error by about a factor of root two. + expect_equal(fit$mode, "undirected") + expect_equal(nrow(fit$pred), 24 * 23 / 2) +}) + +test_that("a two-mode network contributes every cell of the incidence matrix", { + sw <- qap_net_twomode() + dims <- manynet::net_dims(sw) + fit <- net_regression(. ~ ego(Att) + alter(Att), sw, times = 10, + control = list(seed = 1)) + # An incidence matrix is rectangular, and has no diagonal to drop. Reading it + # as square wrapped past the last column and invented dyads. + expect_equal(nrow(fit$pred), dims[1] * dims[2]) + expect_named(fit$coefficients, c("(Intercept)", "ego Att", "alter Att")) +}) + +test_that("RMPerm() permutes a rectangular matrix without erroring", { + m <- matrix(seq_len(18 * 14), 18, 14) + p <- RMPerm(m) + expect_equal(dim(p), c(18L, 14L)) + # A permutation relabels the nodes, so it moves cells but keeps the multiset. + expect_setequal(as.vector(p), as.vector(m)) +}) + +test_that("RMPerm() keeps the row and column order aligned for a square matrix", { + set.seed(4) + m <- matrix(seq_len(36), 6, 6) + p <- RMPerm(m) + expect_equal(dim(p), c(6L, 6L)) + expect_setequal(as.vector(p), as.vector(m)) + # One order for both margins, so the diagonal stays the diagonal. + expect_setequal(diag(p), diag(m)) +}) + +test_that("dist() and sim() read each mode of a two-mode network separately", { + sw <- qap_net_twomode() + ml <- convertToMatrixList(. ~ ego(Att) + alter(Att) + dist(Att) + sim(Att), + sw, advise = FALSE) + ego <- ml$mydata[["ego Att"]] + alt <- ml$mydata[["alter Att"]] + expect_equal(ml$mydata[["dist Att"]], abs(ego - alt)) + denom <- max(abs(ego - alt)) + expect_equal(ml$mydata[["sim Att"]], abs(1 - abs(ego - alt) / denom)) +}) + +test_that("a list of networks is pooled, and one missing a predictor is dropped", { + good <- list(qap_net_gaussian(n = 18, seed = 1), + qap_net_gaussian(n = 18, seed = 2)) + fit <- net_regression(weight ~ ego(Age), good, times = 10, + control = list(seed = 1)) + expect_equal(nrow(fit$pred), 2 * 18 * 17) + expect_length(unique(fit$pred$nv), 2L) + + bare <- manynet::as_tidygraph(matrix(stats::rnorm(18^2), 18, 18)) + expect_warning( + dropped <- net_regression(weight ~ ego(Age), + list(good[[1]], bare, good[[2]]), + times = 10, control = list(seed = 1)), + "Dropping") + expect_equal(nrow(dropped$pred), 2 * 18 * 17) +}) + +test_that("a missing dyad is dropped from the model", { + g <- qap_net_gaussian(n = 20) + m <- manynet::as_matrix(g) + m[1, 2] <- NA + holed <- manynet::mutate(manynet::as_tidygraph(m), + Age = manynet::node_attribute(g, "Age")) + fit <- net_regression(weight ~ ego(Age), holed, times = 10, + control = list(seed = 1)) + expect_equal(nrow(fit$pred), 20 * 19 - 1) +}) From bb17b655e1d7439f7fa02aa4fef43406f56748a9 Mon Sep 17 00:00:00 2001 From: James Hollway Date: Sat, 5 Sep 2026 09:53:14 +0200 Subject: [PATCH 20/20] Fixed some small test issues --- .github/CONTRIBUTING.md | 13 +++++++++++++ R/qap_gpu.R | 7 ++++++- tests/testthat/helper-infernet.R | 27 +++++++++++++++++++++++++++ tests/testthat/test-net_regression.R | 16 +++++++++++----- tests/testthat/test-qap_estimators.R | 21 ++++++++++++++++++--- tests/testthat/test-qap_shapes.R | 17 ++++++++++++----- 6 files changed, 87 insertions(+), 14 deletions(-) diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index adbbcf2..859486f 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -424,6 +424,19 @@ An estimator that needs a package from `Suggests` takes absent. Do not let a path go untested because the package is missing locally: install it, and check that the test runs before you rely on the skip. +Note that `skip_if_not_installed()` is weaker than it looks. CI installs every +`Suggests`, so the skip does not fire there, and an installed package is not +always a working one: `{torch}` installs as an R package before its Lantern +backend is downloaded, and `torch::cuda_is_available()` then throws rather than +returning `FALSE`. Guard on the capability, not on the package. + +A test must not depend on a `{manynet}` feature newer than the CRAN version, or +it passes here and fails on CI. + +Note that `options(snet_verbosity)` is unset under `R CMD check`, +because manynet's `.onAttach` only sets it in an interactive session. +Never write a test that depends on `snet_info()` output. + Count the dyads rather than checking that a call returns. A directed network of *n* nodes contributes *n*(*n*-1) dyads, an undirected one *n*(*n*-1)/2, and a two-mode one every cell of its incidence matrix. diff --git a/R/qap_gpu.R b/R/qap_gpu.R index 5367665..92cdf97 100644 --- a/R/qap_gpu.R +++ b/R/qap_gpu.R @@ -309,5 +309,10 @@ gpu_batch_ols_css <- function(data, parsed, mode, diag, groups, reps, #' @noRd gpu_available <- function() { if (!requireNamespace("torch", quietly = TRUE)) return(FALSE) - torch::cuda_is_available() + # {torch} installs as an R package before its Lantern backend is downloaded, + # so `cuda_is_available()` throws rather than returning FALSE on a machine + # that has the package but not the runtime. That is the state of a CI runner + # that installed Suggests, and it must read as "no GPU", not as an error. + isTRUE(tryCatch(torch::cuda_is_available(), + error = function(e) FALSE, warning = function(w) FALSE)) } diff --git a/tests/testthat/helper-infernet.R b/tests/testthat/helper-infernet.R index 6c1e688..54f16f1 100644 --- a/tests/testthat/helper-infernet.R +++ b/tests/testthat/helper-infernet.R @@ -104,3 +104,30 @@ expect_qap_shape <- function(fit, coefs) { } invisible(fit) } + +# ---- version-tolerant warnings ---------------------------------------------- + +# `manynet::snet_warn()` only began raising a catchable warning condition in +# manynet 2.3.2. Before that it printed a cli alert that the default +# `snet_verbosity = "quiet"` suppressed, and signalled nothing. CI installs the +# CRAN version, so a test that expects a warning has to know which it has. +# Probe the behaviour rather than the version string: a development build can +# carry the version without the behaviour. +snet_warn_signals <- function() { + isTRUE(tryCatch({ + manynet::snet_warn("probe") + FALSE + }, warning = function(w) TRUE)) +} + +# Asserts the warning where manynet raises one, and otherwise just evaluates the +# expression, so that whatever the test asserts about the returned value still +# runs. The behaviour a warning accompanies is always asserted separately. +expect_snet_warning <- function(object, regexp) { + if (snet_warn_signals()) { + testthat::expect_warning(object, regexp) + } else { + testthat::skip(paste("manynet", utils::packageVersion("manynet"), + "does not signal snet_warn() conditions")) + } +} diff --git a/tests/testthat/test-net_regression.R b/tests/testthat/test-net_regression.R index 8099553..bf61f99 100644 --- a/tests/testthat/test-net_regression.R +++ b/tests/testthat/test-net_regression.R @@ -104,15 +104,21 @@ test_that("net_regression fits on a list of graphs", { # ---- list-of-graphs: drop graphs missing a predictor, with warning --------- -test_that("graphs missing a predictor are dropped with a warning", { +test_that("graphs missing a predictor are dropped", { g1 <- make_weighted_net(n = 8, seed = 1) g2 <- manynet::as_tidygraph(matrix(stats::rnorm(8^2), 8, 8)) gs <- list(A = g1, B = g2) - expect_warning( - fit <- net_regression(weight ~ sim(Age), gs, times = 10), - regexp = "Dropping" - ) + fit <- suppressWarnings(net_regression(weight ~ sim(Age), gs, times = 10)) expect_s3_class(fit, "net_regression") + expect_length(unique(fit$pred$nv), 1L) +}) + +test_that("dropping a graph warns", { + g1 <- make_weighted_net(n = 8, seed = 1) + g2 <- manynet::as_tidygraph(matrix(stats::rnorm(8^2), 8, 8)) + expect_snet_warning( + net_regression(weight ~ sim(Age), list(A = g1, B = g2), times = 10), + "Dropping") }) diff --git a/tests/testthat/test-qap_estimators.R b/tests/testthat/test-qap_estimators.R index 2642e1b..fe9d8c4 100644 --- a/tests/testthat/test-qap_estimators.R +++ b/tests/testthat/test-qap_estimators.R @@ -215,13 +215,28 @@ test_that("fixest coefficients match a direct feglm() fit", { test_that("fixed effects and random effects together fall back to random", { skip_if_not_installed("fixest") skip_if_not_installed("lme4") - expect_warning( - fit <- suppressMessages( + both <- suppressMessages(suppressWarnings( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, fixest_se_cluster = "sv", + random_intercept_sender = TRUE)))) + random_only <- suppressMessages(suppressWarnings( + net_regression(FORM, qap_net_gaussian(), times = 10, + control = list(seed = 1, random_intercept_sender = TRUE)))) + expect_qap_shape(both, COEFS3) + # The fixed effects are dropped, so the fit is the random-effects one. + expect_equal(both$coefficients, random_only$coefficients) + expect_named(both$random.intercepts, "sv") +}) + +test_that("combining fixed and random effects warns", { + skip_if_not_installed("fixest") + skip_if_not_installed("lme4") + expect_snet_warning( + suppressMessages( net_regression(FORM, qap_net_gaussian(), times = 10, control = list(seed = 1, fixest_se_cluster = "sv", random_intercept_sender = TRUE))), "random effects") - expect_qap_shape(fit, COEFS3) }) diff --git a/tests/testthat/test-qap_shapes.R b/tests/testthat/test-qap_shapes.R index e5c81ac..f821c93 100644 --- a/tests/testthat/test-qap_shapes.R +++ b/tests/testthat/test-qap_shapes.R @@ -69,14 +69,21 @@ test_that("a list of networks is pooled, and one missing a predictor is dropped" expect_length(unique(fit$pred$nv), 2L) bare <- manynet::as_tidygraph(matrix(stats::rnorm(18^2), 18, 18)) - expect_warning( - dropped <- net_regression(weight ~ ego(Age), - list(good[[1]], bare, good[[2]]), - times = 10, control = list(seed = 1)), - "Dropping") + dropped <- suppressWarnings( + net_regression(weight ~ ego(Age), list(good[[1]], bare, good[[2]]), + times = 10, control = list(seed = 1))) expect_equal(nrow(dropped$pred), 2 * 18 * 17) }) +test_that("dropping a network from a list warns", { + good <- qap_net_gaussian(n = 18, seed = 1) + bare <- manynet::as_tidygraph(matrix(stats::rnorm(18^2), 18, 18)) + expect_snet_warning( + net_regression(weight ~ ego(Age), list(good, bare), times = 10, + control = list(seed = 1)), + "Dropping") +}) + test_that("a missing dyad is dropped from the model", { g <- qap_net_gaussian(n = 20) m <- manynet::as_matrix(g)