Changelog#

0.2.0 (2026-10-02)#

  • More of ergm’s vocabulary, checked against R: degrange, idegrange, odegrange, degree1.5 and its in- and out- versions, concurrentties, isolatededges, density, meandeg, dyadcov, hamming, attrcov, mm, diff, smalldiff, the covariate ranges (nodecovrange…) and distinct neighbour types (nodefactordistinct…), altkstar, the triad census and balance, intransitive, simmelian, nearsimmelian, simmelianties, transitiveties, cyclicalties, threetrail, opentriad, localtriangle, m2star, the directed d*sp aliases, and for bipartite networks b1degrange, b1mindegree, b1sociality, b1starmix, b1twostar, b1covrange, b1factordistinct and their b2 twins.

  • Term options: levels= (and the older keep=, base=) for nodematch, nodefactor and the bipartite factors; by= and homophily= for the degree terms and concurrent; attr= for the star and triangle terms, mutual(same=, by=), asymmetric, sociality and the geometrically weighted degrees; nodes= for sender, receiver and sociality; b1nodematch(diff=, alpha=, beta=, byb2attr=).

  • Interactions of dyad-independent terms, a:b and a*b.

  • Constraints: edges, b1degrees, b2degrees, Dyads(fix=, vary=), fixedas, fixallbut, observed, blockdiag and bd(attribs=).

  • Attributes with missing values are refused with a clear error, as in ergm.

  • ergm documents intransitive as intransitive triads and dyadcov’s utri as the upper triangle’s asymmetric dyads, but computes intransitive triples and swaps utri and ltri: ergmx follows the documentation and warns (ErgmDifferenceWarning).

  • Multilevel networks: MPNet’s configurations of directed two-level networks (in- and out-stars with affiliations, triangles, alternating triangles and three-paths of arcs and reciprocated pairs, cross-level three-paths, entrainment and exchange four-cycles, alternating stars at both ends), and the undirected EXTA, EXTB and ASAXASB; estimated decays (fixed=FALSE) for the configurations with one alternating part; goodness of fit by level, gof(by="level"); and S() between two sets of a directed network, the arcs from the first to the second, as in ergm.

  • Datasets: labs_sim, a multilevel network of 120 researchers and 30 laboratories simulated from a known model, with effects within each level and across levels.

  • tergm’s EGMME: tergm(network, ..., estimate="EGMME", targets=, target_stats=) fits a process to a single network and the ages of its ties, with tergm’s algorithm (EgmmeFit); tergm’s statistics of tie ages, edge.ages, mean.age, edges.ageinterval, edgecov.ages and nodefactor.mean.age, as targets and as monitors of dynamic simulations.

  • Series of networks: forward simulation of fits whose coefficients vary over time (lm=~.Time); missing dyads in the networks transitioned from, imputed as tergm’s NA.impute (na_impute= of NetSeries() and tergm()), and in the networks transitioned to, missing.

  • Samples of networks: gofN(), goodness of fit network by network as ergm.multi’s, with its summary and residual plots; N()’s subset, offset (and offset() in lm) and label, also for tergm’s operators.

  • ergm.multi’s gofN() reports degree0 and isolates minus the network size; ergmx reports them, and warns.

  • Scale: no array has a row or a cell per dyad any more. The MPLE builds the distinct rows of change statistics with their counts, in parallel (70 s and 6.8 GB on 10,000 vertices before, 0.5 s and 0.45 GB now); the sample spaces of combined and bipartite networks, missing dyads and the constraints fixedas, fixallbut, observed and blockdiag are described by groups of vertices and lists of dyads (500 classrooms of 20 in 0.27 GB rather than 0.75, and 1,500 in 0.57 GB rather than about 7); goodness of fit’s distances and shared partners come from the Rust core (0.1 s and 0.17 GB rather than 5.6 s and 2.3 GB on 10,000 vertices).

  • Speed: a shared partner cache, as ergm’s, for the shared partner terms on networks that aren’t sparse (10% faster on faux.mesa.high and faux.dixon.high), and tabulated geometric weights.

  • Saving fits: fit.save(path) and ergmx.load_fit(path); fits also pickle.

  • benchmarks/scale.R and scale.py time ergm and ergmx on networks of 1,461 to 10,000 vertices and on 500 classrooms.

  • Documentation: a Quick start, with two complete analyses: an ERGM and a multilevel ERGM.

  • Fixes: datasets.load() reads each bundled network once and returns copies (python-igraph leaves a C file stream open at each read, and Windows allows 512); the Monte Carlo MLE of curved models no longer fails in the linear algebra when the decay runs off along a flat direction of the approximation, and moves each decay by at most 1 per iteration.

0.1.0 (2026-10-01)#

The first version.

  • Terms: 58 of ergm’s terms for directed, undirected and bipartite networks, with ergm’s definitions and names, among them edges, mutual, edgecov, kstar, istar, ostar, degree, idegree, odegree, isolates, gwdegree, gwidegree, gwodegree, triangle, ttriple, ctriple, gwesp and gwdsp (OTP if directed), esp, dsp, nodematch (with diff=TRUE), nodemix, nodefactor, nodeifactor, nodeofactor, nodecov, nodeicov, nodeocov and absdiff.

  • More terms: asymmetric, sender, receiver, sociality, concurrent, twopath, transitive (transitive triads, as ergm documents it; ergm computes ttriple), cycle, gwnsp, nsp, absdiffcat, and the shared partner types of directed networks (OTP, ITP, RTP, OSP, ISP) for every shared partner term.

  • Bipartite networks, with 18 terms (b1star, b1degree, gwb1degree, b1concurrent, b1factor, b1cov, b1nodematch, b1dsp, gwb1dsp and their b2 twins) and ergm’s goodness of fit statistics.

  • Curved ERGMs: the decay of the geometrically weighted terms estimated (fixed=FALSE), in the MPLE, contrastive divergence, the Monte Carlo MLE and the log-likelihood.

  • Operators: offset() (with -inf to forbid ties) and F().

  • Samples of networks, as R’s ergm.multi: Networks() and the N() operator, with linear models of network-level attributes (lm=), curved terms, and pooled goodness of fit.

  • Temporal ERGMs, as R’s tergm: NetSeries(), the operators Form(), Persist(), Diss(), Cross() and Change(), tergm() for the conditional MLE (and MPLE), and dynamic simulation (simulate_dynamic(), fit.simulate(time_slices=)) with tergm’s per-step stopping rule and discordant-dyad proposals.

  • Constraints: bd, blocks, degrees, odegrees and idegrees, with degree-preserving MCMC moves.

  • Missing ties: likelihood inference conditional on the observed dyads (Handcock and Gile 2010), for estimates, standard errors, log-likelihoods and goodness of fit.

  • Estimation: the exact MLE of dyad-independent models; the Monte Carlo MLE of the others, with Hummel et al. (2012) step lengths, an adaptive MCMC interval and standard errors that include the MCMC error; MPLE and contrastive divergence estimates and starting values.

  • MCMC in Rust: tie/no-tie and triadic proposals, parallel chains, a density guard.

  • Checking models: MCMC diagnostics, goodness of fit, log-likelihoods by path sampling with an Euler–Maclaurin corrected rule, and model comparison.

  • Multilevel networks: ergm’s S() operator (terms on the network within a level, or on the bipartite network between two), and MPNet’s configurations of two-level networks (Wang et al. 2013): star2ax, axs1a, aas1x, aaaxs, txax, atxax, l3xax and their B twins, l3axb and c4axb.

  • Interpreting and reporting: tie probabilities (predict(), conditional and unconditional, as ergm’s), average marginal effects (as ergMargins, with full delta-method standard errors), odds ratios and confidence intervals, tables of models identical to texreg’s (table(): text, LaTeX, HTML and Markdown), and to_frame() for pandas.

  • Datasets: the networks of R’s ergm documentation, ergm.multi’s household networks Goeyvaerts, and multinets’ multilevel network linked_sim.

  • Packaging: Python 3.11 or newer; wheels with the compiled Rust core for Linux, macOS and Windows, one per platform for every Python version; development with uv, and the Rust version pinned in rust-toolchain.toml.