From 1f4401ed73356cbf89c2f35fd35d6a981f4caea0 Mon Sep 17 00:00:00 2001
From: "Pavel N. Krivitsky"
Date: Tue, 2 Jul 2024 16:46:12 +0100
Subject: [PATCH] In ergm_edgecov_args(), the helper for edgecov() and
dyadcov() terms, fixed handling of network input and implemented a dimension
check for the covariate matrix; documentation cleaned up as well.
fixes statnet/ergm#568
---
DESCRIPTION | 4 ++--
R/InitErgmTerm.R | 10 +++++++++-
man-roxygen/ergmTerm-x-attrname.R | 23 ++++++++++++++++-------
man/dyadcov-ergmTerm-5fba5404.Rd | 23 ++++++++++++++++-------
man/edgecov-ergmTerm-1fb5ef19.Rd | 23 ++++++++++++++++-------
tests/testthat/test-term-flexible.R | 10 ++++++++++
6 files changed, 69 insertions(+), 24 deletions(-)
diff --git a/DESCRIPTION b/DESCRIPTION
index f3716cf8b..787140e94 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
Package: ergm
-Version: 4.7-7368
-Date: 2024-06-11
+Version: 4.7-7374
+Date: 2024-07-02
Title: Fit, Simulate and Diagnose Exponential-Family Models for Networks
Authors@R: c(
person(c("Mark", "S."), "Handcock", role=c("aut"), email="handcock@stat.ucla.edu"),
diff --git a/R/InitErgmTerm.R b/R/InitErgmTerm.R
index c5f0ea62f..61668b0c3 100644
--- a/R/InitErgmTerm.R
+++ b/R/InitErgmTerm.R
@@ -202,7 +202,7 @@ ergm_edgecov_args <- function(name, nw, a){
xm <- as.matrix(a$x, matrix.type="adjacency", a$attrname)
}else if(is.character(a$x)){
xm <- get.network.attribute(nw, a$x)
- if(is.null(xm) || !is.matrix(xm)) ergm_Init_abort("There is no network attribute named ", sQuote(a$x), " or it is not a matrix.")
+ if(is.null(xm) || !(is.matrix(xm) || is.network(xm))) ergm_Init_abort("There is no network attribute named ", sQuote(a$x), " or it is not a matrix or a network.")
if(is.network(xm)){
if(!is.null(a$attrname) && !a$attrname %in% list.edge.attributes(xm)) ergm_Init_abort("Network at attribute named ", sQuote(a$x), " does not have an edge attribute ", sQuote(a$attrname), ".")
xm <- as.matrix(xm, matrix.type="adjacency", attrname=a$attrname)
@@ -210,6 +210,14 @@ ergm_edgecov_args <- function(name, nw, a){
}
}else xm <- as.matrix(a$x)
+ # Check dimension
+ actual <- dim(xm)
+ expected <-
+ if(is.bipartite(nw)) c(nw %n% "bipartite", network.size(nw) - nw %n% "bipartite")
+ else rep(network.size(nw), 2)
+
+ if(any(actual!=expected)) ergm_Init_stop("Dyadic covariate matrix has dimension ", actual[1], "x", actual[2], ", ", expected[1], "x", expected[2], " expected.")
+
cn <- if(!is.null(a$attrname)) paste(name, a$attrname, sep = ".")
else paste(name, if(is.character(a$x)) a$x else deparse1(attr(a,"exprs")$x), sep = ".")
diff --git a/man-roxygen/ergmTerm-x-attrname.R b/man-roxygen/ergmTerm-x-attrname.R
index c73cbe25e..c8f1dd3cf 100644
--- a/man-roxygen/ergmTerm-x-attrname.R
+++ b/man-roxygen/ergmTerm-x-attrname.R
@@ -7,10 +7,19 @@
#
# Copyright 2003-2023 Statnet Commons
################################################################################
-#' @param x,attrname either a square matrix of covariates, one for
-#' each possible edge in the network, the name of a network
-#' attribute of covariates, or a network; if the latter, or if the
-#' network attribute named by `x` is itself a network, optional
-#' argument `attrname` provides the name of the quantitative edge
-#' attribute to use for covariate values (in this case, missing
-#' edges in `x` are assigned a covariate value of zero).
+#' @param x,attrname a specification for the dyadic covariate: either
+#' one of the following, or the name of a network attribute
+#' containing one of the following: \describe{
+#'
+#' \item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n}
+#' for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for
+#' bipartite networks; `attrname`, if given, is used to construct
+#' the term name.}
+#'
+#' \item{a network object}{with the same size and bipartitedness as
+#' LHS; `attrname`, if given, provides the name of the
+#' quantitative edge attribute to use for covariate values (in
+#' this case, missing edges in `x` are assigned a covariate value
+#' of zero).}
+#'
+#' }
diff --git a/man/dyadcov-ergmTerm-5fba5404.Rd b/man/dyadcov-ergmTerm-5fba5404.Rd
index 3d1dd9138..ac98941a6 100644
--- a/man/dyadcov-ergmTerm-5fba5404.Rd
+++ b/man/dyadcov-ergmTerm-5fba5404.Rd
@@ -8,13 +8,22 @@
# binary: dyadcov(x, attrname=NULL)
}
\arguments{
-\item{x, attrname}{either a square matrix of covariates, one for
-each possible edge in the network, the name of a network
-attribute of covariates, or a network; if the latter, or if the
-network attribute named by \code{x} is itself a network, optional
-argument \code{attrname} provides the name of the quantitative edge
-attribute to use for covariate values (in this case, missing
-edges in \code{x} are assigned a covariate value of zero).}
+\item{x, attrname}{a specification for the dyadic covariate: either
+one of the following, or the name of a network attribute
+containing one of the following: \describe{
+
+\item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n}
+for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for
+bipartite networks; \code{attrname}, if given, is used to construct
+the term name.}
+
+\item{a network object}{with the same size and bipartitedness as
+LHS; \code{attrname}, if given, provides the name of the
+quantitative edge attribute to use for covariate values (in
+this case, missing edges in \code{x} are assigned a covariate value
+of zero).}
+
+}}
}
\description{
This term adds three statistics to the model, each equal to the sum of the
diff --git a/man/edgecov-ergmTerm-1fb5ef19.Rd b/man/edgecov-ergmTerm-1fb5ef19.Rd
index f0a6d67a6..c2c2935c1 100644
--- a/man/edgecov-ergmTerm-1fb5ef19.Rd
+++ b/man/edgecov-ergmTerm-1fb5ef19.Rd
@@ -11,13 +11,22 @@
# valued: edgecov(x, attrname=NULL, form="sum")
}
\arguments{
-\item{x, attrname}{either a square matrix of covariates, one for
-each possible edge in the network, the name of a network
-attribute of covariates, or a network; if the latter, or if the
-network attribute named by \code{x} is itself a network, optional
-argument \code{attrname} provides the name of the quantitative edge
-attribute to use for covariate values (in this case, missing
-edges in \code{x} are assigned a covariate value of zero).}
+\item{x, attrname}{a specification for the dyadic covariate: either
+one of the following, or the name of a network attribute
+containing one of the following: \describe{
+
+\item{a covariate matrix}{with dimensions \eqn{n \times n}{n*n}
+for unipartite networks and \eqn{b \times (n-b)}{b*(n-b)} for
+bipartite networks; \code{attrname}, if given, is used to construct
+the term name.}
+
+\item{a network object}{with the same size and bipartitedness as
+LHS; \code{attrname}, if given, provides the name of the
+quantitative edge attribute to use for covariate values (in
+this case, missing edges in \code{x} are assigned a covariate value
+of zero).}
+
+}}
\item{form}{character how to aggregate tie values in a valued ERGM}
}
diff --git a/tests/testthat/test-term-flexible.R b/tests/testthat/test-term-flexible.R
index 85801a3e3..51e52e650 100644
--- a/tests/testthat/test-term-flexible.R
+++ b/tests/testthat/test-term-flexible.R
@@ -159,6 +159,16 @@ test_that("edges, either", {
expect_summary(s.0, e.0, 203, -.9072)
})
+test_that("edgecov, dimension check, unipartite", {
+ cov <- matrix(0, 18, 19)
+ expect_error(summary(samplike~edgecov(cov)), '.*Dyadic covariate matrix has dimension 18x19, 18x18 expected.*')
+})
+
+test_that("edgecov, dimension check, bipartite", {
+ cov <- matrix(0, 129, 129)
+ expect_error(summary(bipnw~edgecov(cov)), '.*Dyadic covariate matrix has dimension 129x129, 100x29 expected.*')
+})
+
#test_that("hamming, any", {
# mat.d <- matrix(0,18,18)
# mat.u <- matrix(0, 205, 205)