mixle.stats.graphs.temporal_graph_grammar module¶
Temporal (dynamic) graph grammar – a distribution over graph SEQUENCES you can score, fit, and sample.
A dynamic graph is observed as a sequence of adjacency snapshots [A_0, A_1, ..., A_T] (binary,
undirected; nodes may be appended and edges added over time – a growth process). The model is a Markov
chain over graphs whose transition kernel is a stochastic motif-edit grammar:
given G_{t-1}, draw a number of new edges, and produce each by firing a grammar rule – “add an edge that creates motif m” – where the rule is chosen from the motif distribution
wand an anchor is chosen uniformly among the non-edges of G_{t-1} that instantiate that motif.
So the grammar EDITS the graph over time, and its rule weights ARE the motif distribution it imposes. The default motif family bins a candidate edge by how many triangles it would close (its number of common neighbours: 0 = a bridge, 1, 2, 3+), i.e. a learnable triadic-closure profile; a custom mutually-exclusive motif partition can be supplied instead. Because the bins are mutually exclusive each added edge has a single motif, so scoring and fitting are exact (no per-edge latent – the VRG/HRG grammars marginalise over derivations; here the derivation is read off the snapshots).
Edges both FORM and DISSOLVE: an ADD grammar (motif_weights / edge_rate) draws new edges by the
motif each would create, and a separate REMOVE grammar (remove_weights / edge_remove_rate) deletes
existing edges by the motif each is part of (so e.g. growth can favour triadic closure while decay favours
bridges – ties in dense neighbourhoods persist). Removal defaults off, so the constructor is backward
compatible and a pure-growth grammar still scores a deletion as -inf.
Adjacencies may be dense ndarray or scipy.sparse – scoring and fitting never form the n*n bin
matrix (they touch only the changed edges and the wedge structure of A @ A), so a 200k-node graph
scores in a fraction of a second where a dense adjacency would need hundreds of GB. (Sampling stays
dense/moderate-scale.) LabeledTemporalGraphGrammarDistribution attaches node attributes (location,
name, age, …) and edge attributes (communication counts, channel, …) as ordinary mixle distributions
scored as emissions on top of the topology – the whole thing fits jointly with the full distribution
machinery (mixtures, every leaf family, the numba fusion).
Graphs may be directed (directed=True): the adjacency is asymmetric (i->j and j->i are distinct
edges), the candidate space is the full off-diagonal, and A @ A counts transitive i->k->j paths – a
directed triadic-closure profile. Weighted edges are just an edge attribute: put a weight distribution
(Poisson volume, Gaussian strength, …) in the labeled model’s edge_dist, so a directed + weighted +
attributed dynamic graph is a directed structure composed with node/edge emission models.
Nodes also LEAVE: ChurningTemporalGraphGrammarDistribution tracks stable node identities (each snapshot
is (adjacency, node_ids)) so a transition can remove nodes – those whose id disappears, their edges
vanishing with them – before running the edit grammar on the surviving subgraph. Node churn is a thin
wrapper: identity alignment + a node-removal Poisson term on top of all the motif/edge machinery.
The dynamics carry a HIDDEN REGIME: LatentTemporalGraphGrammarDistribution is an HMM whose emission
models ARE the edit grammars – a latent Markov state z_t selects which of K grammars governs transition t,
so the graph switches phases over time (bursty growth/densification, then fragmentation/decay – dynamics a
single grammar cannot produce). The sequence likelihood marginalises the regime path by the forward
algorithm; EM (Baum-Welch) runs forward-backward then a per-regime weighted M-step reusing each grammar’s
accumulator; decode (Viterbi) recovers the active regime at each step.
This is the temporal counterpart of the static vertex-/hyperedge-replacement grammars in this package. Scope: undirected or directed, binary topology (attribute models carry weights/labels); edges add+remove, nodes join+leave; dense or sparse scoring, dense or scalable (rejection) sampling; optional hidden regime. Sparse-path churn and directed scalable sampling are the remaining extensions.
- class CommonNeighbourMotif(bins=(0, 1, 2, 3), directed=False)[source]
Bases:
objectA motif rule keyed by how many common neighbours a candidate edge has (triangles it would close).
binsis an increasing list of thresholds; binbcovers common-neighbour counts in[bins[b], bins[b+1])with the last bin open-ended. The default[0, 1, 2, 3]gives the interpretable {bridge, closes-1, closes-2, closes-3+} partition. A non-edge falls in exactly one bin, so the motifs partition every candidate edge.- property num_motifs: int
Number of mutually exclusive motif bins.
- assign(adj, on_edges=False)[source]
Motif bin of every candidate pair (and -1 on non-candidates / diagonal).
The common-neighbour count of a pair (i, j) is
(A @ A)[i, j]– for a non-edge, how many triangles adding it would CLOSE; for an existing edge, how many triangles it is PART of. Binning byself.binsgives its motif. Withon_edges=Falsethe candidates are the non-edges (addition); withon_edges=Truethey are the existing edges (removal). Non-candidates and the diagonal -> -1.
- counts_and_binner(adj, on_edges)[source]
Return (candidate_counts[M], lookup(i, j) -> motif index) WITHOUT forming the n*n bin matrix.
Sparse-scalable: only the existing edges (O(m)) and the non-edges that close a triangle (O(wedges) =
A @ A’s nonzeros) are ever enumerated; the bridge count (cn=0 non-edges) is the analytic remainderpairs - edges - wedge_non_edges. The lookup reads(A @ A)[i, j]for the handful of observed edges. (For graphs with mega-hubs the wedge set itself is large – the documented limit.)
- class TemporalGraphGrammarDistribution(motif_weights, edge_rate=1.0, node_rate=0.0, remove_weights=None, edge_remove_rate=0.0, motif=None, directed=False, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionDistribution over dynamic graphs (sequences of adjacency snapshots) under a motif-edit grammar.
- Parameters:
- transition_components(prev, cur)[source]
The PARAMETER-INDEPENDENT decomposition of a transition:
(new_nodes, add_bins, add_cand, rem_bins, rem_cand, valid). Depends only on the graph pair and the motif, NOT on the grammar’s weights/rates – so K regimes sharing a motif can compute the (expensive A@A) decomposition ONCE and score it K times viascore_components().validis False for an impossible node removal.
- score_components(components)[source]
Score a precomputed
transition_components()decomposition under THIS grammar’s parameters.
- log_density(x)[source]
Log-density of one dynamic graph: the sum of transition log-densities over the snapshot chain.
xis a sequence of binary adjacency matrices – densendarrayorscipy.sparse(large graphs). The initial graph is taken as given (its marginal is not modelled, matching how the static grammars treat their start symbol).
- seq_encode(x)[source]
Return dynamic graph sequences unchanged for sequence scoring.
- seq_log_density(x)[source]
Score a batch of dynamic graph sequences.
- sampler(seed=None)[source]
Return a sampler for dynamic graph sequences.
- Parameters:
seed (int | None)
- Return type:
TemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the closed-form estimator for this motif grammar.
- Parameters:
pseudo_count (float | None)
- Return type:
TemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through data encoder for graph sequences.
- Return type:
TemporalGraphGrammarDataEncoder
- class TemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for dynamic graph sequences generated by a motif-edit grammar.
- Parameters:
dist (TemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=10, seed_graph=None, n_init=5)[source]
Run a derivation: from a seed graph, apply
num_stepsof grammar-sampled edits.
- sample_one_scalable(num_steps=10, seed_edges=None, n_init=5, max_reject=64)[source]
Sample a dynamic graph for a LARGE sparse graph – never materialises the n*n adjacency.
The dense
sample_one()is exact but O(n^2) in space (the full bin matrix). This path keeps the graph as an edge set and emitsscipy.sparsesnapshots, costing O(edges + wedges) per step:triangle-closing motifs (cn>=1) are exactly the wedge non-edges – the nonzeros of
A @ Athat aren’t edges – so they are enumerated directly from the wedge structure, never the full pair grid;bridges (cn=0) dominate a sparse graph and can’t be enumerated, so they are rejection-sampled: draw random pairs and accept those that are neither an edge nor a wedge (acceptance ~ 1 when the graph is sparse).
max_rejectattempts per bridge bound the loop; a shortfall is explicit capping (same realized-rate semantics as the dense sampler when a motif’s anchors run out).
Growth+removal; undirected or directed (directed: ordered i->j edges, full off-diagonal candidates,
A@A= transitive i->k->j wedges). Returns a list ofcsr_arraysnapshots. The realized motif distribution matches the weights, so a model fit on these snapshots recovers the grammar.
- class TemporalGraphGrammarEstimator(motif=None, pseudo_count=None, name=None)[source]
Bases:
ParameterEstimatorLearn the motif distribution (rule weights) + edge/node rates from observed dynamic graphs.
- accumulator_factory()[source]
Return the accumulator factory used by the estimator.
- Return type:
TemporalGraphGrammarAccumulatorFactory
- class TemporalGraphGrammarAccumulator(motif)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulate per-motif edge counts + step/edge/node totals – the exact sufficient statistics.
- Parameters:
motif (CommonNeighbourMotif)
- update(x, weight, estimate)[source]
Accumulate sufficient statistics from one dynamic graph sequence.
- seq_update(x, weights, estimate)[source]
Accumulate weighted sufficient statistics from a batch of sequences.
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
x (Any)
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- initialize(x, weight, rng)[source]
Initialize sufficient statistics from one weighted sequence.
- Parameters:
x (Any)
weight (float)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized sufficient statistics into this accumulator.
- Parameters:
suff_stat (tuple)
- Return type:
TemporalGraphGrammarAccumulator
- value()[source]
Return serialized sufficient statistics for estimation or merging.
- Return type:
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
TemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class TemporalGraphGrammarAccumulatorFactory(motif)[source]
Bases:
StatisticAccumulatorFactoryFactory for temporal graph grammar accumulators.
- Parameters:
motif (CommonNeighbourMotif)
- make()[source]
Create a fresh temporal graph grammar accumulator.
- Return type:
TemporalGraphGrammarAccumulator
- class TemporalGraphGrammarDataEncoder[source]
Bases:
DataSequenceEncoderPass-through encoder for dynamic graph sequence observations.
- class LabeledTemporalGraphGrammarDistribution(structure, node_dist=None, edge_dist=None, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA dynamic graph whose nodes and edges carry attributes.
Composes a structural
TemporalGraphGrammarDistribution(the topology over time) with two ordinary mixle distributions:node_distover per-node attribute records (location, name, age, … – typically aCompositeDistributionof leaves or a mixture) andedge_distover per-edge attribute records (communication counts, channel, weight, …). An observation is(snapshots, node_features, edge_features): the adjacency chain, one attribute record per node, and one per added edge. The likelihood factorises – structure x node attributes x edge attributes – so the attribute models are fit (and scored) with the full mixle distribution machinery (mixtures, fusion, all leaf families).- Parameters:
structure (TemporalGraphGrammarDistribution)
node_dist (SequenceEncodableProbabilityDistribution | None)
edge_dist (SequenceEncodableProbabilityDistribution | None)
name (str | None)
- log_density(x)[source]
Score one attributed dynamic graph observation.
- seq_encode(x)[source]
Return attributed dynamic graph observations unchanged.
- seq_log_density(x)[source]
Score a batch of attributed dynamic graph observations.
- sampler(seed=None)[source]
Return a sampler for attributed dynamic graph observations.
- Parameters:
seed (int | None)
- Return type:
LabeledTemporalGraphGrammarSampler
- estimator(**kw)[source]
Return the estimator for structure, node attributes, and edge attributes.
- Parameters:
kw (Any)
- Return type:
LabeledTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class LabeledTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for attributed dynamic graph observations.
- Parameters:
dist (LabeledTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(**kw)[source]
Draw one attributed dynamic graph observation.
- class LabeledTemporalGraphGrammarEstimator(structure_estimator, node_estimator=None, edge_estimator=None, name=None)[source]
Bases:
ParameterEstimatorEstimator for attributed temporal graph grammars.
- Parameters:
structure_estimator (Any)
node_estimator (Any)
edge_estimator (Any)
name (str | None)
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
LabeledTemporalGraphGrammarAccumulatorFactory
- class LabeledTemporalGraphGrammarAccumulator(structure_acc, node_acc, edge_acc)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for structure, node-attribute, and edge-attribute sufficient statistics.
- Parameters:
structure_acc (Any)
node_acc (Any)
edge_acc (Any)
- update(x, weight, estimate)[source]
Accumulate sufficient statistics from one attributed graph observation.
- seq_update(x, weights, estimate)[source]
Accumulate weighted sufficient statistics from a batch.
- initialize(x, weight, rng)[source]
Initialize sufficient statistics from one weighted observation.
- Parameters:
x (tuple)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
x (Any)
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized attributed-graph sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
LabeledTemporalGraphGrammarAccumulator
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
LabeledTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class LabeledTemporalGraphGrammarAccumulatorFactory(structure_factory, node_factory, edge_factory)[source]
Bases:
StatisticAccumulatorFactoryFactory for attributed temporal graph grammar accumulators.
- Parameters:
structure_factory (Any)
node_factory (Any)
edge_factory (Any)
- make()[source]
Create a fresh attributed temporal graph grammar accumulator.
- Return type:
LabeledTemporalGraphGrammarAccumulator
- class HomophilyTemporalGraphGrammarDistribution(rate, type_weights, node_rate=0.0, motif=None, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA growth grammar whose edge formation depends on node ATTRIBUTES, not just structure (homophily).
Each node carries a categorical
type(community / location-bucket / …). The per-step number of new edges of motifmbetween an (unordered) type pair (a, b) isPoisson(rate[m, a, b]), placed uniformly among the candidate non-edges of that motif and type pair. Makingrate[m, a, a]larger thanrate[m, a, b]is homophily (“similar nodes connect more”); the rate tensor is the learnable coupling between attributes and topology. New nodes draw their type fromtype_weights.Observation:
(snapshots, node_types)– the adjacency chain plus an int type per node. Exact and closed-form: the rate tensor is just edge counts per (motif, type-pair) over steps, and the type distribution is node-type counts. (Phase: growth-only, dense; add+remove and sparse compose with the machinery above and are the natural extensions.)- Parameters:
- log_density(x)[source]
Score one homophily dynamic graph observation.
- seq_encode(x)[source]
Return homophily observations unchanged for sequence scoring.
- seq_log_density(x)[source]
Score a batch of homophily dynamic graph observations.
- sampler(seed=None)[source]
Return a sampler for homophily dynamic graph observations.
- Parameters:
seed (int | None)
- Return type:
HomophilyTemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the estimator for homophily rates and node-type weights.
- Parameters:
pseudo_count (float | None)
- Return type:
HomophilyTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class HomophilyTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for homophily temporal graph observations.
- Parameters:
dist (HomophilyTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=8, seed_graph=None, n_init=8)[source]
Draw one homophily dynamic graph observation.
- class HomophilyTemporalGraphGrammarEstimator(M, K, motif=None, pseudo_count=None, name=None)[source]
Bases:
ParameterEstimatorEstimator for homophily temporal graph grammars.
- Parameters:
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
HomophilyTemporalGraphGrammarAccumulatorFactory
- class HomophilyTemporalGraphGrammarAccumulator(M, K, motif)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for homophily edge-rate and node-type sufficient statistics.
- update(x, weight, estimate)[source]
Accumulate sufficient statistics from one homophily observation.
- seq_update(x, weights, estimate)[source]
Accumulate weighted sufficient statistics from a batch.
- initialize(x, weight, rng)[source]
Initialize sufficient statistics from one weighted observation.
- Parameters:
x (tuple)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
x (Any)
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized homophily sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
HomophilyTemporalGraphGrammarAccumulator
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
HomophilyTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class HomophilyTemporalGraphGrammarAccumulatorFactory(M, K, motif)[source]
Bases:
StatisticAccumulatorFactoryFactory for homophily temporal graph grammar accumulators.
- make()[source]
Create a fresh homophily accumulator.
- Return type:
HomophilyTemporalGraphGrammarAccumulator
- class ChurningTemporalGraphGrammarDistribution(edit_grammar, node_remove_rate=0.0, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionDynamic graph where nodes both JOIN and LEAVE, tracked by stable identity.
Each snapshot is
(adjacency, node_ids)–node_ids[i]is the persistent identity of row i. A transition first removes nodes (those whose id disappears; count ~ Poisson(node_remove_rate), chosen uniformly, their edges vanishing with them), then runs the wrapped edit grammar on the surviving subgraph (which also appends new nodes + adds/removes edges). So churn is a thin wrapper: identity alignment + a node-removal Poisson term on top of all the existing motif/edge machinery. Scoring and fitting accept dense orscipy.sparseadjacencies (the id alignment slices either); the sampler is dense.- Parameters:
- log_density(x)[source]
Score one identity-tracked churning graph sequence.
- seq_encode(x)[source]
Return churning graph observations unchanged for scoring.
- seq_log_density(x)[source]
Score a batch of churning graph observations.
- sampler(seed=None)[source]
Return a sampler for churning graph observations.
- Parameters:
seed (int | None)
- Return type:
ChurningTemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the estimator for the wrapped edit grammar and node churn rate.
- Parameters:
pseudo_count (float | None)
- Return type:
ChurningTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class ChurningTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for identity-tracked churning temporal graph observations.
- Parameters:
dist (ChurningTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=10, seed_graph=None, n_init=8)[source]
Draw one churning graph sequence.
- class ChurningTemporalGraphGrammarEstimator(edit_estimator, name=None)[source]
Bases:
ParameterEstimatorEstimator for identity-tracked churning temporal graph grammars.
- Parameters:
edit_estimator (Any)
name (str | None)
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
ChurningTemporalGraphGrammarAccumulatorFactory
- class ChurningTemporalGraphGrammarAccumulator(edit_acc)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for churning graph grammar and node-removal sufficient statistics.
- Parameters:
edit_acc (Any)
- update(x, weight, estimate)[source]
Accumulate sufficient statistics from one churning graph sequence.
- seq_update(x, weights, estimate)[source]
Accumulate weighted sufficient statistics from a batch.
- initialize(x, weight, rng)[source]
Initialize sufficient statistics from one weighted sequence.
- Parameters:
x (Any)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
x (Any)
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized churning sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
ChurningTemporalGraphGrammarAccumulator
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
ChurningTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class ChurningTemporalGraphGrammarAccumulatorFactory(edit_factory)[source]
Bases:
StatisticAccumulatorFactoryFactory for churning temporal graph grammar accumulators.
- Parameters:
edit_factory (Any)
- make()[source]
Create a fresh churning accumulator.
- Return type:
ChurningTemporalGraphGrammarAccumulator
- class LatentTemporalGraphGrammarDistribution(states, initial_probs=None, transition_matrix=None, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA dynamic graph whose edit grammar is governed by a hidden, time-evolving REGIME.
A latent state z_t (a Markov chain:
initial_probspi,transition_matrixA) selects which of K edit grammars governs transition t. So the graph can switch regimes over time – e.g. a bursty growth / densification phase, then a fragmentation / decay phase – dynamics a single grammar cannot express. The sequence likelihood marginalises the regime path by the forward algorithm; emissions are the per- transition edit log-densities of each regime’s grammar, so this is an HMM whose emission models are the graph-edit grammars and EM reuses each grammar’s weighted accumulator for the M-step.Observation = a plain list of adjacency snapshots (same as the base grammar) – the regime is latent.
decodereturns the most likely regime active at each transition (Viterbi).- Parameters:
- log_density(x)[source]
Score one dynamic graph sequence with regimes marginalized out.
- decode(x)[source]
Viterbi: the most likely regime governing each transition.
- seq_encode(x)[source]
Return latent-regime graph observations unchanged for scoring.
- seq_log_density(x)[source]
Score a batch of latent-regime graph observations.
- sampler(seed=None)[source]
Return a sampler for latent-regime graph sequences.
- Parameters:
seed (int | None)
- Return type:
LatentTemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the Baum-Welch estimator for the latent-regime grammar.
- Parameters:
pseudo_count (float | None)
- Return type:
LatentTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for regime-switching temporal graph grammars.
- Parameters:
dist (LatentTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=10, seed_graph=None, n_init=5)[source]
Draw one latent-regime graph sequence.
- class LatentTemporalGraphGrammarEstimator(state_estimators, pseudo_count=None, name=None)[source]
Bases:
ParameterEstimatorEM (Baum-Welch) for the regime-switching grammar: forward-backward E-step, per-regime weighted M-step.
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
LatentTemporalGraphGrammarAccumulatorFactory
- class LatentTemporalGraphGrammarAccumulator(k, state_accs)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for latent-regime graph grammar EM sufficient statistics.
- Parameters:
k (int)
state_accs (Sequence[Any])
- update(x, weight, estimate)[source]
Accumulate posterior-weighted sufficient statistics for one sequence.
- initialize(x, weight, rng)[source]
Initialize latent-regime sufficient statistics with random soft assignments.
- Parameters:
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_update(x, weights, estimate)[source]
Accumulate posterior-weighted sufficient statistics from a batch.
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized latent-regime sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
LatentTemporalGraphGrammarAccumulator
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
LatentTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentTemporalGraphGrammarAccumulatorFactory(k, state_factories)[source]
Bases:
StatisticAccumulatorFactoryFactory for latent temporal graph grammar accumulators.
- Parameters:
k (int)
state_factories (Sequence[Any])
- make()[source]
Create a fresh latent-regime accumulator.
- Return type:
LatentTemporalGraphGrammarAccumulator
- class LatentAttributedTemporalGraphGrammarDistribution(structures, node_dists=None, edge_dists=None, initial_probs=None, transition_matrix=None, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA regime-switching dynamic graph where the hidden regime drives the STRUCTURE and the ATTRIBUTES.
Each of K regimes carries a full edit grammar plus (optionally) a node-attribute distribution and an edge-attribute distribution, all switched by one latent Markov state z_t. So a single regime change can densify the topology AND spike communication volume / shift node properties together – e.g. an “active” phase with bursty triadic closure and high message counts, vs a “quiet” phase. The per-transition emission under regime k is
structure_k(transition) + node_attrs_k(nodes added this step) + edge_attrs_k(edges added this step); the sequence likelihood marginalises the regime path by the forward algorithm and EM does forward-backward + a per-regime weighted M-step over each piece.Observation =
(snapshots, node_features, edge_features)wherenode_features[t]/edge_features[t]are the attribute records of the nodes / edges that appear at transition t (lists, length = #transitions).- Parameters:
- log_density(x)[source]
Score one attributed graph sequence with regimes marginalized out.
- decode(x)[source]
Viterbi: the most likely regime governing each transition (jointly explaining structure+attrs).
- seq_encode(x)[source]
Return attributed latent-regime observations unchanged for scoring.
- seq_log_density(x)[source]
Score a batch of attributed latent-regime observations.
- sampler(seed=None)[source]
Return a sampler for attributed latent-regime graph sequences.
- Parameters:
seed (int | None)
- Return type:
LatentAttributedTemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the EM estimator for structure and attribute regime models.
- Parameters:
pseudo_count (float | None)
- Return type:
LatentAttributedTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentAttributedTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for regime-switching attributed temporal graph grammars.
- Parameters:
dist (LatentAttributedTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=10, seed_graph=None, n_init=5)[source]
Draw one attributed latent-regime graph observation.
- class LatentAttributedTemporalGraphGrammarEstimator(structure_estimators, node_estimators=None, edge_estimators=None, pseudo_count=None, name=None)[source]
Bases:
ParameterEstimatorEM for the regime-switching attributed grammar: forward-backward E-step, per-regime weighted M-step over structure + node attrs + edge attrs together.
- Parameters:
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
LatentAttributedTemporalGraphGrammarAccumulatorFactory
- class LatentAttributedTemporalGraphGrammarAccumulator(k, struct_accs, node_accs, edge_accs)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for attributed latent-regime graph grammar EM statistics.
- Parameters:
k (int)
struct_accs (Sequence[Any])
node_accs (Any)
edge_accs (Any)
- update(x, weight, estimate)[source]
Accumulate posterior-weighted statistics for one attributed sequence.
- initialize(x, weight, rng)[source]
Initialize attributed latent-regime statistics with random soft assignments.
- Parameters:
x (tuple)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_update(x, weights, estimate)[source]
Accumulate posterior-weighted statistics from a batch.
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized attributed latent-regime sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
LatentAttributedTemporalGraphGrammarAccumulator
- value()[source]
Return serialized attributed latent-regime sufficient statistics.
- Return type:
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
LatentAttributedTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentAttributedTemporalGraphGrammarAccumulatorFactory(k, struct_factories, node_factories, edge_factories)[source]
Bases:
StatisticAccumulatorFactoryFactory for attributed latent-regime graph grammar accumulators.
- Parameters:
k (int)
struct_factories (Sequence[Any])
node_factories (Any)
edge_factories (Any)
- make()[source]
Create a fresh attributed latent-regime accumulator.
- Return type:
LatentAttributedTemporalGraphGrammarAccumulator
- class LatentChurningTemporalGraphGrammarDistribution(states, node_remove_rates=None, initial_probs=None, transition_matrix=None, name=None)[source]
Bases:
SequenceEncodableProbabilityDistributionA regime-switching dynamic graph where the hidden regime also governs NODE TURNOVER.
Combines the latent regime HMM with identity-tracked node churn: each of K regimes carries a full edit grammar AND its own node-removal rate, so the graph can switch between e.g. a stable phase (slow turnover, triadic growth) and a churn phase (fast member departure, fragmentation). Each snapshot is
(adjacency, node_ids); per transition the active regime first removes nodes (those whose id disappears) then edits the surviving subgraph, and the per-transition emission under regime k isnode_removal_k(#removed) + grammar_k(edit on the aligned surviving subgraph). The sequence likelihood marginalises the regime path by the forward algorithm; EM does forward-backward then a per-regime weighted M-step over both the grammar and the turnover rate.decoderecovers the active regime.Observation =
(snapshots, node_ids)wherenode_idsis a list of per-snapshot id arrays. Dense.- Parameters:
- log_density(x)[source]
Score one identity-tracked sequence with regimes marginalized out.
- decode(x)[source]
Return the most likely churn/edit regime for each transition.
- seq_encode(x)[source]
Return latent churning observations unchanged for scoring.
- seq_log_density(x)[source]
Score a batch of latent churning graph observations.
- sampler(seed=None)[source]
Return a sampler for latent churning graph sequences.
- Parameters:
seed (int | None)
- Return type:
LatentChurningTemporalGraphGrammarSampler
- estimator(pseudo_count=None)[source]
Return the EM estimator for regime-specific edit grammars and churn rates.
- Parameters:
pseudo_count (float | None)
- Return type:
LatentChurningTemporalGraphGrammarEstimator
- dist_to_encoder()[source]
Return the pass-through graph encoder.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentChurningTemporalGraphGrammarSampler(dist, seed=None)[source]
Bases:
DistributionSamplerSampler for regime-switching churning temporal graph grammars.
- Parameters:
dist (LatentChurningTemporalGraphGrammarDistribution)
seed (int | None)
- sample_one(num_steps=10, seed_graph=None, n_init=8)[source]
Draw one latent churning graph sequence.
- class LatentChurningTemporalGraphGrammarEstimator(state_estimators, pseudo_count=None, name=None)[source]
Bases:
ParameterEstimatorEstimator for regime-switching churning temporal graph grammars.
- accumulator_factory()[source]
Return the accumulator factory used by this estimator.
- Return type:
LatentChurningTemporalGraphGrammarAccumulatorFactory
- class LatentChurningTemporalGraphGrammarAccumulator(k, state_accs)[source]
Bases:
SequenceEncodableStatisticAccumulatorAccumulator for latent churning graph grammar EM sufficient statistics.
- Parameters:
k (int)
state_accs (Sequence[Any])
- update(x, weight, estimate)[source]
Accumulate posterior-weighted statistics for one churning sequence.
- initialize(x, weight, rng)[source]
Initialize latent churning statistics with random soft assignments.
- Parameters:
x (tuple)
weight (float)
rng (RandomState | None)
- Return type:
None
- seq_update(x, weights, estimate)[source]
Accumulate posterior-weighted statistics from a batch.
- seq_initialize(x, weights, rng)[source]
Initialize sufficient statistics from a weighted batch.
- Parameters:
weights (ndarray)
rng (RandomState | None)
- Return type:
None
- combine(suff_stat)[source]
Merge serialized latent churning sufficient statistics.
- Parameters:
suff_stat (tuple)
- Return type:
LatentChurningTemporalGraphGrammarAccumulator
- from_value(x)[source]
Restore accumulator state from serialized sufficient statistics.
- Parameters:
x (tuple)
- Return type:
LatentChurningTemporalGraphGrammarAccumulator
- key_merge(stats_dict)[source]
Merge keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- key_replace(stats_dict)[source]
Replace keyed sufficient statistics; unused for this accumulator.
- Parameters:
stats_dict (dict)
- Return type:
None
- acc_to_encoder()[source]
Return the encoder associated with this accumulator.
- Return type:
TemporalGraphGrammarDataEncoder
- class LatentChurningTemporalGraphGrammarAccumulatorFactory(k, state_factories)[source]
Bases:
StatisticAccumulatorFactoryFactory for latent churning temporal graph grammar accumulators.
- Parameters:
k (int)
state_factories (Sequence[Any])
- make()[source]
Create a fresh latent churning accumulator.
- Return type:
LatentChurningTemporalGraphGrammarAccumulator
- regime_moment_init(estimator, proto, data, k, seed=None)[source]
Seed a regime-switching grammar EM by clustering observed per-transition edit signatures.
Returns an initial distribution whose regimes are the k-means clusters of the (identifiable) transition signatures. Because the derivation is observed, these signatures are sufficient statistics that separate the regimes, so this avoids the local optima of random-restart EM.
protois any distribution of the target class (used only for its motif/attribute structure);estimatorproduces the fitted result.