Conversions for tergm version 4.0

# Conversions for `tergm` version 4.0

# Introduction

Version 4.0 of the `tergm` package introduces new user interfaces for specifying `tergm` models. While an effort has been made to maintain a high degree of backwards compatibility, there are some points of backwards incompatibility, and some users may wish to convert their code to use the new interfaces anyway, so this document describes how to go about doing that. The examples given here are somewhat artificial so as to better illustrate the range of possible changes needed; they may not be typical or even plausible in every detail, but are intended to exhibit the types of updates that users may need to make.

# Estimation

Estimation calls in `tergm` 3.x might look something like

    data(samplk)
    samp <- list(samplk1, samplk2, samplk3)
    samp.fit <- stergm(samp,
                       formation = ~edges+mutual+cyclicalties+transitiveties,
                       dissolution = ~edges+mutual+cyclicalties+transitiveties,
                       estimate = "CMLE",
                       times = 1:3,
                       control = control.stergm(CMLE.control.form = control.ergm(init = c(-3.5,2,0,NA)),
                                                CMLE.control.diss = control.ergm(init = c(0,1,0,1/2))))

for CMLE, and

    data(florentine)
    stergm.fit.1 <- stergm(flobusiness,
                           formation = ~edges+gwesp(0,fixed=T),
                           dissolution = ~offset(edges),
                           targets = "formation",
                           offset.coef.diss = log(9),
                           estimate = "EGMME",
                           control = control.stergm(SA.plot.progress=TRUE))

for EGMME.

To convert these to the new 4.0 user interface, we make the following changes.

- Replace the function name `stergm` with `tergm` (in 4.0, the tergms need not be separable, hence we drop the s).

- Combine the network (or network list), formation, and dissolution formulas into a single formula, schematically of the form

      network ~ Form(formation formula) +
                Persist(dissolution formula)

  where `Form` and `Persist` are operator terms defined in `tergm` 4.0.

  For the CMLE example, this results in the formula

      samp ~ Form(~edges+mutual+cyclicalties+transitiveties) +
             Persist(~edges+mutual+cyclicalties+transitiveties)

  and for the EGMME example, it results in the formula

      flobusiness ~ Form(~edges+gwesp(0,fixed=T)) +
                    Persist(~offset(edges))

  These formulas will be our first arguments to the `tergm` function.

- The control argument (if present), previously of class `control.stergm`, should be replaced by one of class `control.tergm`. This can be accomplished by replacing `control.stergm()` with `control.tergm()`, `snctrl()`, or `list()`, and updating arguments as follows. Arguments to `control.stergm()` occurring in pairs with `.form` and `.diss` in their names have been collapsed to single, correspondingly named arguments to `control.tergm()` without `.form` or `.diss`. Additionally, the arguments `CMLE.control.form` and `CMLE.control.diss` to `control.stergm()` correspond to the `CMLE.ergm` argument to `control.tergm()` (and have been renamed as the `CMLE.form.ergm` and `CMLE.diss.ergm` control arguments to `control.stergm()`). Furthermore, the arguments `MCMC.init.maxedges` and `MCMC.init.maxchanges` to `control.stergm()` have been replaced by the `MCMC.maxedges` and `MCMC.maxchanges` arguments to `control.tergm()`; these arguments have also been replaced in `control.stergm()`, so code continuing to use the old interface will still need to change from using `MCMC.init.maxedges` and `MCMC.init.maxchanges` to using `MCMC.maxedges` and `MCMC.maxchanges`.

  Our discussion of initial coefficient values below will also include the necessary control argument changes for our examples above.

- The initial coefficient specifications for the formation and dissolution models, if passed, should be combined into a specification of initial coefficients for the combined model. This can be done through the `tergm` function’s `offset.coef`, `control$init`, and/or `control$CMLE.ergm$init` arguments (the final one applying only to the CMLE case). If `offset.coef` is passed, it should have length equal to the number of offset thetas in the combined model, and if `control$init` or `control$CMLE.ergm$init` is passed, it should have length equal to the total number of thetas in the combined model. (`NA`s may be used in `control$init` or `control$CMLE.ergm$init` to indicate that initial values for those (non-offset) thetas are not being passed.) Here `control` refers to the `control.tergm` class control discussed in the previous bullet point.

  In our examples, the CMLE call specifies initial coefficient values through `control$CMLE.control.*$init`. We can combine these into `control$CMLE.ergm$init` as

      control = control.tergm(CMLE.ergm = control.ergm(init = c(-3.5,2,0,NA,0,1,0,1/2)))

  noting that we also replaced `control.stergm()` with `control.tergm()`. We can simplify this further by exploiting new control list flattening features, writing

      control = snctrl(init = c(-3.5,2,0,NA,0,1,0,1/2))

  instead.

  The EGMME call specifies only a single dissolution offset, which we can specify through `offset.coef` as

      offset.coef = log(9)

Overall, this produces the new-style calls

    data(samplk)
    samp <- list(samplk1, samplk2, samplk3)
    samp.fit <- tergm(samp ~ Form(~edges+mutual+cyclicalties+transitiveties) +
                             Persist(~edges+mutual+cyclicalties+transitiveties),
                      estimate = "CMLE",
                      times = 1:3,
                      control = snctrl(init = c(-3.5,2,0,NA,0,1,0,1/2)))

for CMLE, and

    data(florentine)
    tergm.fit.1 <- tergm(flobusiness ~ Form(~edges+gwesp(0,fixed=T)) +
                                       Persist(~offset(edges)),
                         targets = "formation",
                         offset.coef = log(9),
                         estimate = "EGMME",
                         control = control.tergm(SA.plot.progress=TRUE))

for EGMME.

# Simulation

## From a fitted `tergm` object

A call in `tergm` 3.x for simulating from a fitted `stergm` might look something like

    stergm.sim.1 <- simulate(stergm.fit.1,
                             stats.form = TRUE,
                             nsim = 1,
                             time.slices = 1000,
                             control = control.simulate.stergm(MCMC.init.maxchanges = 10000))

There is no `simulate.stergm` function in `tergm` 4.0, only a `simulate.tergm` function, so the changes described in this section are generally mandatory, with the exception of the control list class, which can be left as `control.simulate.stergm` if desired (although this is not recommended). Even if one calls the old `stergm()` function to estimate the model, calling `simulate` on the returned object will dispatch to the `simulate.tergm` function described here.

To convert from simulating a fitted `stergm` in `tergm` 3.x to simulating a fitted `tergm` in `tergm` 4.0, we make the following changes.

- Replace the `coef.form` and `coef.diss` arguments (which will default to the coefficients of the fitted `stergm`) with the `coef` argument (which will default to the coefficients of the fitted `tergm`), which is schematically of the form `coef = c(coef.form, coef.diss)`, assuming the combined formula used when estimating the `tergm` was of the form described in the Estimation section (with `Form(formation formula)` preceding `Persist(dissolution formula)`).

  These arguments are not passed in the example above, so no corresponding changes are needed in that example.

- Replace the `stats.form` and `stats.diss` arguments (if passed) with the `stats` argument, which will give all generative model statistics if set to `TRUE`.

  In the example above, we pass `stats.form = TRUE`, so in the 4.0 version of the call, we will set `stats = TRUE`.

- The control argument (if passed), previously of class `control.simulate.stergm`, should be replaced by one of class `control.simulate.tergm`. This can be accomplished by replacing `control.simulate.stergm()` with `control.simulate.tergm()`, `snctrl()`, or `list()`, and updating arguments as follows. Arguments to `control.simulate.stergm()` occurring in pairs with `.form` and `.diss` in their names have been collapsed to single, correspondingly named arguments to `control.simulate.tergm()` without `.form` or `.diss`. Additionally, the arguments `MCMC.init.maxedges` and `MCMC.init.maxchanges` to `control.simulate.stergm()` have been replaced by the `MCMC.maxedges` and `MCMC.maxchanges` arguments to `control.simulate.tergm()`; these arguments have also been replaced in `control.simulate.stergm()`, so code continuing to use `control.simulate.stergm()` will still need to change from using `MCMC.init.maxedges` and `MCMC.init.maxchanges` to using `MCMC.maxedges` and `MCMC.maxchanges`.

  In the example above, we passed `MCMC.init.maxchanges = 10000`; since this is enough to accomodate all expected changes throughout the entire simulation, we will pass

      control = snctrl(MCMC.maxchanges = 10000)

  in the 4.0 version of the call.

Thus, dropping the s from the object names for consistency, we obtain the 4.0 style call

    tergm.sim.1 <- simulate(tergm.fit.1,
                            stats = TRUE,
                            nsim = 1,
                            time.slices = 1000,
                            control = snctrl(MCMC.maxchanges = 10000))

## From a network (or networkDynamic)

A call in `tergm` 3.x for simulating based on a starting network (or networkDynamic), along with specified formation and dissolution formulas and coefficients, might look something like

    stergm.sim.2 <- simulate(flobusiness,
                             formation = ~edges+gwesp(0,fixed=T),
                             dissolution = ~edges,
                             monitor = "formation",
                             coef.form = c(-7.981749, 1.575780),
                             coef.diss = log(99),
                             time.slices = 50000)

To convert from simulating based on a starting network in `tergm` 3.x to simulating based on a starting network in `tergm` 4.0, we make the following changes.

- Combine the network, formation, and dissolution formulas into a single formula, schematically of the form

      network ~ Form(formation formula) +
                Persist(dissolution formula)

  as for estimation.

- Combine the `coef.form` and `coef.diss` arguments into a single `coef` argument, schematically of the form `coef = c(coef.form, coef.diss)`, assuming the combined formula is specified as in the previous bullet point (with `Form(formation formula)` preceding `Persist(dissolution formula)`).

- The control argument (if passed), previously of class `control.simulate.network`, should be replaced by one of class `control.simulate.formula.tergm`. This can be accomplished by replacing `control.simulate.network()` with `control.simulate.formula.tergm()`, `snctrl()`, or `list()`, and updating arguments as when simulating from a fitted `tergm`.

- Combine the `stats.form` and `stats.diss` arguments (if passed) into a single `stats` argument.

- Pass `dynamic = TRUE` to indicate that you want dynamic `tergm` simulation.

Thus, we obtain the 4.0 simulation call

    tergm.sim.2 <- simulate(flobusiness ~ Form(~edges+gwesp(0,fixed=T)) +
                                          Persist(~edges),
                            monitor = "formation",
                            coef = c(-7.981749, 1.575780, log(99)),
                            time.slices = 50000,
                            dynamic = TRUE)