statnet / ergm

Fit, Simulate and Diagnose Exponential-Family Models for Networks
Other
94 stars 36 forks source link

is.valued() function fails to identify valued networks generated using network function #459

Closed phuang5 closed 2 years ago

phuang5 commented 2 years ago
#Showcase the bug of the is.valued() term

library(network)
library(ergm.count)

#1. valued networks generated using network function
mat <- matrix(nrow = 3, ncol = 3, 0)
mat[1,2] <- 2
mat[2,1] <- 3
mat
net <- network(mat, names.eval = "e", ignore.eval=F)
as.sociomatrix(net, attrname = "e")

#2. simulate networks using ergm function
net2 <- simulate(net~sum, response="e", reference=~Poisson, coef=1, nsim = 1)
as.sociomatrix(net2, attrname = "e")

#identify them using is.valued()
is.valued(net)
is.valued(net2)
krivit commented 2 years ago

Thanks for the report!

is.valued() was always a property of the model, not of the network. ergm's ergmlhs API allows the network to be "instrumented" to contain valued response information, which is done at various entry points (including ergm() and simulate()). See help for ergm_preprocess_response() for the API.

I'll update help to make this more explicit.

phuang5 commented 2 years ago

Thanks so much for the comment, Pavel!

The issue actually comes from a bug when using ergm_model function with a valued ergm formula. The bug comes from the fact that is.valued() function employed in call.ErgmTerm does not recognize the LHS of the formula is a valued network, and therefore decides to use "InitErgm" rather than "InitWtErgm" in search of the terms on the RHS of the formula. See below for a toy example of demonstration.

Using ergm_preprocess_response() before passing the network to ergm_model function temporarily resolves the issue. Nevertheless, maybe putting ergm_preprocess_response() within the is.valued function in call.ErgmTerm will help remove the bug without requiring users to preprocess the network before passing it to ergm_model.

library(network);library(ergm.count)
#configure graph from adjancency matrix
mat <- matrix(nrow = 3, ncol = 3, 0)
mat[1,2] <- 2
mat[2,1] <- 3
mat
net <- network(mat, names.eval = "e", ignore.eval=F)
as.sociomatrix(net, attrname = "e")

#run ergm_model
m1 <- ergm_model(net~sum) #Error occurs
m2 <- ergm_model(ergm_preprocess_response(net, response = "e")~sum+mutual("min")) #No error occurs

Suggested modification to call.ErgmTerm function on line 3-5

termroot <- if (!is.valued(ergm_preprocess_response(nw, response = response))) 
    "InitErgm"
  else "InitWtErgm"

Thank you for your consideration!

krivit commented 2 years ago

ergm_model() and call.ErgmTerm() no longer take response= as an argument, since the information is now embedded in the network object. Your m2 example is correct and working as intended.

I'll add documentation to ergm_model() about that.