# File tests/testthat/test-extract-formulae.R in package tergm, part of the # Statnet suite of packages for network analysis, https://statnet.org . # # This software is distributed under the GPL-3 license. It is free, open # source, and has the attribution requirements (GPL Section 7) at # https://statnet.org/attribution . # # Copyright 2008-2025 Statnet Commons ################################################################################ test_that(".extract.fd.formulae behaves reasonably", { F1 <- ~Form(~edges) + Persist(~edges) F2 <- ~Form(~edges + gwesp(0,fixed=TRUE)) + Persist(~edges) F3 <- ~Form(~edges + gwesp(0,fixed=TRUE)) + Persist(~edges) + edges - triangle X <- ~edges F4 <- ~Form(X) + Persist(X) F5 <- ~Form(~offset(edges) + gwesp(0,fixed=TRUE)) + Persist(~offset(edges)) Y <- ~offset(edges) F6 <- ~Form(Y) - Persist(~edges) F7 <- ~Form(Y) - Persist(Y) F8 <- ~-Form(~edges - triangle) + Persist(~edges) + Persist(~triangle) + Persist(~-offset(triangle)) F9 <- ~-Form(~offset(edges) - offset(triangle) + offset(gwesp(0,fixed=TRUE))) + Persist(~edges) F10 <- ~-Form(~-edges + triangle) + Form(~-gwesp(0,fixed=TRUE)) - Persist(~-edges) + Persist(~triangle) + Persist(~-gwesp(0,fixed=TRUE)) R1 <- .extract.fd.formulae(F1) expect_equal(~.P(~edges), R1$form) expect_equal(~.P(~edges), R1$pers) expect_equal(~., R1$nonsep) expect_equal(~.P(~edges)+.P(~edges), R1$all) R2 <- .extract.fd.formulae(F2) expect_equal(~.P(~edges + gwesp(0,fixed=TRUE)), R2$form) expect_equal(~.P(~edges), R2$pers) expect_equal(~., R2$nonsep) expect_equal(~.P(~edges+gwesp(0,fixed=TRUE))+.P(~edges), R2$all) R3 <- .extract.fd.formulae(F3) expect_equal(~.P(~edges + gwesp(0,fixed=TRUE)), R3$form) expect_equal(~.P(~edges), R3$pers) expect_equal(~edges - triangle, R3$nonsep) expect_equal(~.P(~edges+gwesp(0,fixed=TRUE))+.P(~edges)+edges-triangle, R3$all) R4 <- .extract.fd.formulae(F4) expect_equal(~.P(X), R4$form) expect_equal(~.P(X), R4$pers) expect_equal(~., R4$nonsep) expect_equal(~.P(X)+.P(X), R4$all) R5 <- .extract.fd.formulae(F5) expect_equal(~.P(~offset(edges) + gwesp(0,fixed=TRUE)), R5$form) expect_equal(~.P(~offset(edges)), R5$pers) expect_equal(~., R5$nonsep) expect_equal(~.P(~offset(edges) + gwesp(0,fixed=TRUE)) + .P(~offset(edges)), R5$all) R6 <- .extract.fd.formulae(F6) expect_equal(~.P(Y), R6$form) expect_equal(~-.P(~edges), R6$pers) expect_equal(~., R6$nonsep) expect_equal(~.P(Y) - .P(~edges), R6$all) R7 <- .extract.fd.formulae(F7) expect_equal(~.P(Y), R7$form) expect_equal(~-.P(Y), R7$pers) expect_equal(~., R7$nonsep) expect_equal(~.P(Y) - .P(Y), R7$all) R8 <- .extract.fd.formulae(F8) expect_equal(~-.P(~edges-triangle), R8$form) expect_equal(~.P(~edges)+.P(~triangle)+.P(~-offset(triangle)), R8$pers) expect_equal(~., R8$nonsep) expect_equal(~-.P(~edges-triangle)+.P(~edges)+.P(~triangle)+.P(~-offset(triangle)), R8$all) R9 <- .extract.fd.formulae(F9) expect_equal(~-.P(~offset(edges)-offset(triangle)+offset(gwesp(0,fixed=TRUE))), R9$form) expect_equal(~.P(~edges), R9$pers) expect_equal(~., R9$nonsep) expect_equal(~-.P(~offset(edges)-offset(triangle)+offset(gwesp(0,fixed=TRUE)))+.P(~edges), R9$all) R10 <- .extract.fd.formulae(F10) expect_equal(~-.P(~-edges+triangle)+.P(~-gwesp(0,fixed=TRUE)), R10$form) expect_equal(~-.P(~-edges)+.P(~triangle)+.P(~-gwesp(0,fixed=TRUE)), R10$pers) expect_equal(~., R10$nonsep) expect_equal(~-.P(~-edges+triangle)+.P(~-gwesp(0,fixed=TRUE))-.P(~-edges)+.P(~triangle)+.P(~-gwesp(0,fixed=TRUE)), R10$all) F11 <- ~Form(~edges) + Persist(~edges) + edges environment(F11) <- new.env() R11 <- .extract.fd.formulae(F11) expect_identical(environment(F11), environment(R11$form)) expect_identical(environment(F11), environment(R11$pers)) expect_identical(environment(F11), environment(R11$nonsep)) expect_identical(environment(F11), environment(R11$all)) a <- ~edges b <- ~triangle environment(a) <- new.env() environment(b) <- new.env() F12 <- ~Form(a) + Persist(b) + edges environment(F12) <- new.env() environment(F12)$a <- a environment(F12)$b <- b R12 <- .extract.fd.formulae(F12) expect_identical(environment(F12), environment(R12$form)) expect_identical(environment(F12), environment(R12$pers)) expect_identical(environment(F12), environment(R12$nonsep)) expect_identical(environment(F12), environment(R12$all)) expect_identical(environment(a), environment(eval(R12$form[[2]][[2]], env = environment(R12$form)))) expect_identical(environment(b), environment(eval(R12$pers[[2]][[2]], env = environment(R12$form)))) F13 <- ~Form(~edges) + Persist(~edges) R13 <- .extract.fd.formulae(F13) expect_equal(~.P(~edges), R13$form) expect_equal(~.P(~edges), R13$pers) expect_equal(~., R13$nonsep) expect_equal(~.P(~edges)+.P(~edges), R13$all) x <- ~edges environment(x) <- new.env() F14 <- ~Form(~edges) + Persist(x) R14 <- .extract.fd.formulae(F14) expect_equal(~.P(~edges), R14$form) expect_equal(~.P(x), R14$pers) expect_equal(~., R14$nonsep) expect_equal(~.P(~edges)+.P(x), R14$all) expect_identical(environment(x), environment(eval(R14$pers[[2]][[2]], env = environment(R14$pers)))) F15 <- ~Form(~edges) + Persist(~edges) + Persist(~triangle) R15 <- .extract.fd.formulae(F15) expect_equal(~.P(~edges), R15$form) expect_equal(~.P(~edges)+.P(~triangle), R15$pers) expect_equal(~., R15$nonsep) expect_equal(~.P(~edges)+.P(~edges)+.P(~triangle), R15$all) make_formula <- function() { aaaaa <- 52 ~nodefactor(~0, levels = I(aaaaa)) } make_formula_2 <- function() { bbbbb <- 2 ~nodematch(~3:6, levels = bbbbb, diff = TRUE) } ff <- make_formula() ff2 <- make_formula_2() F16 <- ~Form(~edges) + Persist(ff2) + Persist(ff) R16 <- .extract.fd.formulae(F16) expect_equal(~.P(~edges), R16$form) expect_equal(~.P(ff2)+.P(ff), R16$pers) expect_equal(~., R16$nonsep) expect_equal(~.P(~edges)+.P(ff2)+.P(ff), R16$all) nw <- network.initialize(8, dir = FALSE) m <- ergm_model(R16$pers, nw = nw) expect_identical(param_names(m), c("nodematch.3:6.4", "nodefactor.0.52")) m2 <- ergm_model(R16$all, nw = nw) expect_identical(param_names(m2), c("edges", "nodematch.3:6.4", "nodefactor.0.52")) ## diss tests F17 <- ~Form(~edges) + Persist(~edges) + Diss(~triangle) R17 <- .extract.fd.formulae(F17) expect_equal(~.P(~edges), R17$form) expect_equal(~.P(~edges)+.M(~triangle), R17$pers) expect_equal(~., R17$nonsep) expect_equal(~.P(~edges)+.P(~edges)+.M(~triangle), R17$all) ## test diss environment x <- ~edges environment(x) <- new.env() y <- ~offset(triangle) environment(y) <- new.env() F18 <- ~Form(~edges) + Diss(y) + Persist(x) R18 <- .extract.fd.formulae(F18) expect_equal(~.P(~edges), R18$form) expect_equal(~.M(y)+.P(x), R18$pers) expect_equal(~., R18$nonsep) expect_equal(~.P(~edges)+.M(y)+.P(x), R18$all) expect_identical(environment(x), environment(eval(R18$pers[[2]][[3]][[2]], env = environment(R18$pers)))) expect_identical(environment(y), environment(eval(R18$pers[[2]][[2]][[2]], env = environment(R18$pers)))) ## combine diss F19 <- ~Diss(~triangle) + Form(~edges) + gwesp(0, fixed = TRUE) + Persist(~edges) + Diss(~concurrent) R19 <- .extract.fd.formulae(F19) expect_equal(~.P(~edges), R19$form) expect_equal(~.M(~triangle)+.P(~edges)+.M(~concurrent), R19$pers) expect_equal(~gwesp(0,fixed=TRUE), R19$nonsep) expect_equal(~.M(~triangle) + .P(~edges) + gwesp(0, fixed = TRUE) + .P(~edges) + .M(~concurrent), R19$all) ## make some ergm_model calls that would fail if environments were not handled correctly (in particular for diss) n43 <- "abs" make_formula_3 <- function() { a1 <- 87 ~nodefactor(~0:7, levels = I(a1)) } make_formula_4 <- function() { b6 <- 4 ~nodematch(~11:18, levels = b6, diff = TRUE) } make_formula_5 <- function() { n43 <- "wealth" ~nodecov(n43) } make_formula_6 <- function() { n43 <- "priorates" ~nodecov(n43) } ff3 <- make_formula_3() ff4 <- make_formula_4() ff5 <- make_formula_5() ff6 <- make_formula_6() n43 <- "diff" F20 <- ~Persist(ff4) + Diss(ff5) + nodecov(n43) + Form(ff3) + Persist(ff6) R20 <- .extract.fd.formulae(F20) expect_equal(~.P(ff3), R20$form) expect_equal(~.P(ff4)+.M(ff5)+.P(ff6), R20$pers) expect_equal(~nodecov(n43), R20$nonsep) expect_equal(~.P(ff4)+.M(ff5)+nodecov(n43)+.P(ff3)+.P(ff6), R20$all) nw <- network.initialize(8, dir = FALSE) nw %v% "abs" <- letters[1:8] nw %v% "diff" <- runif(8) nw %v% "wealth" <- runif(8) nw %v% "priorates" <- sample(1:10, 8, TRUE) m <- ergm_model(R20$form, nw = nw) expect_identical(param_names(m), c("nodefactor.0:7.87")) m <- ergm_model(R20$pers, nw = nw) expect_identical(param_names(m), c("nodematch.11:18.14", "nodecov.wealth", "nodecov.priorates")) m <- ergm_model(R20$nonsep, nw = nw) expect_identical(param_names(m), c("nodecov.diff")) m <- ergm_model(R20$all, nw = nw) expect_identical(param_names(m), c("nodematch.11:18.14", "nodecov.wealth", "nodecov.diff", "nodefactor.0:7.87", "nodecov.priorates")) ## test offsets F <- ~Form(~edges) + Form(~offset(triangle)) + offset(Form(~gwesp)) + offset(Diss(~cycle(4))) + edges + offset(concurrent) + Persist(~isolates) R <- .extract.fd.formulae(F) expect_equal(~.P(~edges)+.P(~offset(triangle))+offset(.P(~gwesp)),R$form) expect_equal(~offset(.M(~cycle(4)))+.P(~isolates),R$pers) expect_equal(~edges+offset(concurrent),R$nonsep) expect_equal(~.P(~edges)+.P(~offset(triangle))+offset(.P(~gwesp))+offset(.M(~cycle(4)))+edges+offset(concurrent)+.P(~isolates),R$all) ## test partial offsets F <- ~Form(~edges) + Form(~offset(triangle,3:4)) + offset(Form(~gwesp),c(TRUE,FALSE)) + offset(Diss(~cycle(4)),6) + edges + offset(concurrent) + Persist(~isolates) R <- .extract.fd.formulae(F) expect_equal(~.P(~edges)+.P(~offset(triangle,3:4))+offset(.P(~gwesp),c(TRUE,FALSE)),R$form) expect_equal(~offset(.M(~cycle(4)),6)+.P(~isolates),R$pers) expect_equal(~edges+offset(concurrent),R$nonsep) expect_equal(~.P(~edges)+.P(~offset(triangle,3:4))+offset(.P(~gwesp),c(TRUE,FALSE))+offset(.M(~cycle(4)),6)+edges+offset(concurrent)+.P(~isolates),R$all) ## test sticking in a formula-class formula with a non-default environment F <- ~Form(.) + edges + offset(Diss(.)) + Persist(~concurrent) u <- ~nodecov(uniquename) environment(u) <- new.env() environment(u)$uniquename <- "particularattrname" v <- ~isolates environment(v) <- new.env() F[[2]][[2]][[3]][[2]][[2]] <- v F[[2]][[2]][[2]][[2]][[2]] <- u R <- .extract.fd.formulae(F) expect_identical(environment(u), environment(R$form[[2]][[2]])) expect_identical(environment(v), environment(R$pers[[2]][[2]][[2]][[2]])) expect_equal(~.P(~nodecov(uniquename)), R$form, ignore_attr=TRUE) expect_equal(~offset(.M(~isolates))+.P(~concurrent), R$pers, ignore_attr=TRUE) expect_equal(~edges, R$nonsep) expect_equal(~.P(~nodecov(uniquename)) + edges + offset(.M(~isolates))+.P(~concurrent), R$all, ignore_attr=TRUE) nw <- network.initialize(10, dir = FALSE) expect_error(m <- ergm_model(R$form, nw = nw), "is/are not valid nodal attribute\\(s\\)") nw %v% "particularattrname" <- sample(1:5, 10, TRUE) expect_error(m <- ergm_model(R$form, nw = nw), NA) expect_identical(param_names(m, canonical = FALSE), "nodecov.particularattrname") ## test leading signs F <- ~edges - Form(~edges) R <- .extract.fd.formulae(F) expect_equal(~-.P(~edges), R$form) expect_equal(~., R$pers) expect_equal(~edges, R$nonsep) expect_equal(~edges-.P(~edges), R$all) F <- ~-edges + Form(~triangle) - Form(~edges) - Diss(~concurrent) R <- .extract.fd.formulae(F) expect_equal(~.P(~triangle)-.P(~edges), R$form) expect_equal(~-.M(~concurrent), R$pers) expect_equal(~-edges, R$nonsep) expect_equal(~-edges+.P(~triangle)-.P(~edges)-.M(~concurrent), R$all) F <- ~-offset(Form(~edges)) - Persist(~offset(concurrent)) + offset(Diss(~-isolates)) - offset(triangle) + edges R <- .extract.fd.formulae(F) expect_equal(~-offset(.P(~edges)), R$form) expect_equal(~-.P(~offset(concurrent))+offset(.M(~-isolates)), R$pers) expect_equal(~-offset(triangle)+edges, R$nonsep) expect_equal(~-offset(.P(~edges))-.P(~offset(concurrent))+offset(.M(~-isolates))-offset(triangle)+edges, R$all) ## test interactions F <- ~Form(~edges + triangle:gwesp(0,fixed=TRUE)) + edges*concurrent + Diss(~mean.age) + triangle + isolates:degree(1) R <- .extract.fd.formulae(F) expect_equal(~.P(~edges + triangle:gwesp(0,fixed=TRUE)), R$form) expect_equal(~.M(~mean.age), R$pers) expect_equal(~edges*concurrent + triangle + isolates:degree(1), R$nonsep) expect_equal(~.P(~edges + triangle:gwesp(0,fixed=TRUE)) + edges*concurrent + .M(~mean.age) + triangle + isolates:degree(1), R$all) ## test that interactions are always treated as non-separable (maybe not ideal, but at least documentable) F <- ~edges:Form(~edges) + Form(~edges)*edges + Diss(~edges)*Form(~edges) + Persist(~edges):Diss(~edges) + offset(edges):Form(~edges) + offset(edges:Form(~edges)) + edges:offset(Form(~edges)) + offset(edges)*Form(~edges) + offset(edges*Form(~edges)) + edges*offset(Form(~edges)) + Form(~edges):Form(~triangle) + Form(~edges)*Form(~triangle) R <- .extract.fd.formulae(F) expect_equal(~., R$form) expect_equal(~., R$pers) expect_equal(F, R$nonsep) expect_equal(F, R$all) }) test_that("terms .P/.M behave as plus/minus identity", { nw0 <- network.initialize(100, dir = FALSE) nw <- simulate(nw0 ~ edges, coef = c(-4), dynamic = TRUE, output = "final") ## non-durational, non-curved ff0 <- ~edges + triangle + gwesp(0, fixed = TRUE) + isolates + concurrent s1 <- summary(ff0, basis = nw) s2 <- summary(~.P(ff0), basis = nw) s3 <- summary(~.M(ff0), basis = nw) expect_equal(s1, s2) expect_equal(s1, -s3) ## non-durational, curved ff1 <- ~edges + triangle + gwesp(0, fixed = TRUE) + gwesp(fixed = FALSE, cutoff = 100) s1 <- summary(ff1, basis = nw) s2 <- summary(~.P(ff1), basis = nw) s3 <- summary(~.M(ff1), basis = nw) expect_equal(s1, s2) expect_equal(s1, -s3) set.seed(0) nw1 <- simulate(nw ~ Form(~edges + triangle) + Diss(~edges + gwesp(0, fixed = TRUE)), coef = c(-5, 0.01, -4, 0.01), time.slices = 10, dynamic = TRUE, output = "final") set.seed(0) nw2 <- simulate(nw ~ .P(~Form(~edges + triangle) + Diss(~edges + gwesp(0, fixed = TRUE))), coef = c(-5, 0.01, -4, 0.01), time.slices = 10, dynamic = TRUE, output = "final") set.seed(0) nw3 <- simulate(nw ~ .M(~Form(~edges + triangle) + Diss(~edges + gwesp(0, fixed = TRUE))), coef = c(5, -0.01, 4, -0.01), time.slices = 10, dynamic = TRUE, output = "final") attr(nw1, "coef") <- NULL attr(nw2, "coef") <- NULL attr(nw3, "coef") <- NULL expect_equal(nw1, nw2) expect_equal(nw1, nw3) nw <- nw1 ## durational, non-curved ff2 <- ~edges + triangle + gwesp(0, fixed = TRUE) + isolates + concurrent + edges.ageinterval(1) + edges.ageinterval(4) + edges.ageinterval(15) + mean.age + Form(~edges + triangle + mean.age) + Persist(~edges + concurrent + isolates + edges.ageinterval(2) + edges.ageinterval(6)) s1 <- summary(ff2, basis = nw) s2 <- summary(~.P(ff2), basis = nw) s3 <- summary(~.M(ff2), basis = nw) expect_equal(s1, s2) expect_equal(s1, -s3) ## durational, curved ff3 <- ~edges + triangle + gwesp(0, fixed = TRUE) + gwesp(fixed = FALSE, cutoff = 100) + mean.age + Form(~edges + triangle + mean.age) + Diss(~gwesp(fixed = FALSE, cutoff = 100)) s1 <- summary(ff3, basis = nw) s2 <- summary(~.P(ff3), basis = nw) s3 <- summary(~.M(ff3), basis = nw) expect_equal(s1, s2) expect_equal(s1, -s3) set.seed(0) sim01 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ff0, output = "stats") set.seed(0) sim02 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.P(ff0), output = "stats") set.seed(0) sim03 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.M(ff0), output = "stats") expect_equal(sim01, sim02) expect_equal(sim01, -sim03) set.seed(1) sim11 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ff1, output = "stats") set.seed(1) sim12 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.P(ff1), output = "stats") set.seed(1) sim13 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.M(ff1), output = "stats") expect_equal(sim11, sim12) expect_equal(sim11, -sim13) set.seed(2) sim21 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ff2, output = "stats") set.seed(2) sim22 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.P(ff2), output = "stats") set.seed(2) sim23 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.M(ff2), output = "stats") expect_equal(sim21, sim22) expect_equal(sim21, -sim23) set.seed(3) sim31 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ff3, output = "stats") set.seed(3) sim32 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.P(ff3), output = "stats") set.seed(3) sim33 <- simulate(nw ~ Form(~edges) + Persist(~edges), coef = c(-6, 2), time.slices = 10, dynamic = TRUE, monitor = ~.M(ff3), output = "stats") expect_equal(sim31, sim32) expect_equal(sim31, -sim33) m01 <- ergm_model(ff0, nw = nw) m02 <- ergm_model(~.P(ff0), nw = nw) m03 <- ergm_model(~.M(ff0), nw = nw) expect_true(!is.curved(m01)) expect_true(!is.curved(m02)) expect_true(!is.curved(m03)) expect_true(!is.durational(m01)) expect_true(!is.durational(m02)) expect_true(!is.durational(m03)) expect_identical(param_names(m01, canonical = FALSE), param_names(m02, canonical = FALSE)) expect_identical(param_names(m01, canonical = TRUE), param_names(m02, canonical = TRUE)) expect_identical(param_names(m01, canonical = FALSE), param_names(m03, canonical = FALSE)) expect_identical(param_names(m01, canonical = TRUE), param_names(m03, canonical = TRUE)) m11 <- ergm_model(ff1, nw = nw) m12 <- ergm_model(~.P(ff1), nw = nw) m13 <- ergm_model(~.M(ff1), nw = nw) expect_true(is.curved(m11)) expect_true(is.curved(m12)) expect_true(is.curved(m13)) expect_true(!is.durational(m11)) expect_true(!is.durational(m12)) expect_true(!is.durational(m13)) expect_identical(param_names(m11, canonical = FALSE), param_names(m12, canonical = FALSE)) expect_identical(param_names(m11, canonical = TRUE), param_names(m12, canonical = TRUE)) expect_identical(param_names(m11, canonical = FALSE), param_names(m13, canonical = FALSE)) expect_identical(param_names(m11, canonical = TRUE), param_names(m13, canonical = TRUE)) m21 <- ergm_model(ff2, nw = nw) m22 <- ergm_model(~.P(ff2), nw = nw) m23 <- ergm_model(~.M(ff2), nw = nw) expect_true(!is.curved(m21)) expect_true(!is.curved(m22)) expect_true(!is.curved(m23)) expect_true(is.durational(m21)) expect_true(is.durational(m22)) expect_true(is.durational(m23)) expect_identical(param_names(m21, canonical = FALSE), param_names(m22, canonical = FALSE)) expect_identical(param_names(m21, canonical = TRUE), param_names(m22, canonical = TRUE)) expect_identical(param_names(m21, canonical = FALSE), param_names(m23, canonical = FALSE)) expect_identical(param_names(m21, canonical = TRUE), param_names(m23, canonical = TRUE)) m31 <- ergm_model(ff3, nw = nw) m32 <- ergm_model(~.P(ff3), nw = nw) m33 <- ergm_model(~.M(ff3), nw = nw) expect_true(is.curved(m31)) expect_true(is.curved(m32)) expect_true(is.curved(m33)) expect_true(is.durational(m31)) expect_true(is.durational(m32)) expect_true(is.durational(m33)) expect_identical(param_names(m31, canonical = FALSE), param_names(m32, canonical = FALSE)) expect_identical(param_names(m31, canonical = TRUE), param_names(m32, canonical = TRUE)) expect_identical(param_names(m31, canonical = FALSE), param_names(m33, canonical = FALSE)) expect_identical(param_names(m31, canonical = TRUE), param_names(m33, canonical = TRUE)) })