Generative Rules
generative_rules
Generative rules for determining connection affinities in network models.
This subpackage provides various generative rules that determine how nodes in a network form connections based on different topological properties. These rules produce affinity matrices that represent the likelihood of connections forming between pairs of nodes.
The rules fall into several categories:
- Homophily-based rules (MatchingIndex, Neighbours): Nodes connect based on shared neighborhoods
- Clustering-based rules: Nodes connect based on clustering coefficient relationships
- Degree-based rules: Nodes connect based on node degree relationships
- Geometric rule: A baseline rule where all connections have equal affinity
Each rule produces an affinity matrix that can be used within a generative network model to determine connection probabilities along with other factors such as distance.
gnm.generative_rules.GenerativeRule
Bases: ABC
Abstract base class for generative rules.
Generative rules compute affinity factors between nodes in a network, which determine how likely nodes are to connect to each other. These affinity factors can be based on various network properties such as shared neighbors, clustering coefficients, or node degrees.
This base class provides common functionality for input validation and output processing, ensuring that all rule implementations follow consistent behavior.
Concrete classes inheriting from this abstract base must implement the `_rule' method.
See Also
model.GenerativeNetworkModel: Uses generative rules to build network models
__call__(adjacency_matrix)
Apply the generative rule to compute affinity matrices.
This method handles the complete process of validating inputs, applying the specific rule implementation, and processing outputs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adjacency_matrix
|
Float[Tensor, '... num_nodes num_nodes']
|
Batch of adjacency matrices with shape [..., num_nodes, num_nodes] |
required |
Returns:
| Type | Description |
|---|---|
Float[Tensor, '... num_nodes num_nodes']
|
Affinity matrices with the same shape |
Source code in src/gnm/generative_rules/generative_rules.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 | |
_rule(adjacency_matrix)
abstractmethod
Apply the specific generative rule.
This abstract method must be implemented by subclasses to define the specific rule for computing affinities between nodes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
adjacency_matrix
|
Float[Tensor, '... num_nodes num_nodes']
|
Batch of adjacency matrices with shape [..., num_nodes, num_nodes] |
required |
Returns:
| Type | Description |
|---|---|
Float[Tensor, '... num_nodes num_nodes']
|
Affinity matrices with the same shape |
Source code in src/gnm/generative_rules/generative_rules.py
114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 | |
Homophily-Based Rules
gnm.generative_rules.MatchingIndex(divisor='mean')
Bases: GenerativeRule
Compute affinity based on shared neighborhoods between nodes.
The matching index measures the similarity between the neighborhoods of two nodes, which is a form of homophily. Nodes with many common neighbors will have a high matching index, making them more likely to connect.
Two calculation methods are supported: 1. "mean" - Normalizes by the average size of the two neighborhoods 2. "union" - Normalizes by the size of the union of the two neighborhoods
Let \(N(u)\) be the neighborhood of node \(u\).
When the divisor is set to 'mean', the matching index is computed as: $$ K(u,v) = \frac{ | N(u) \cap N(v) | }{ ( |N(u) - {v}| + |N(v) - {u}| ) /2 }. $$
When the divisor is set to 'union', the matching index is computed as: $$ K(u,v) = \frac{ | N(u) \cap N(v) | }{ | N(u) \cup N(v) - {u,v}| }. $$
When \(N(u) - \{v\}\) and \(N(v) - \{u\}\) are both empty, the matching index is zero.
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import MatchingIndex
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply matching index with mean divisor
>>> rule = MatchingIndex(divisor="mean")
>>> affinity_matrix = rule(network)
>>> # Apply matching index with union divisor
>>> rule_union = MatchingIndex(divisor="union")
>>> affinity_matrix_union = rule_union(network)
See Also
generative_rules.GenerativeRule: The base class for generative rules, from which this class inherits.generative_rules.Neighbours: A simpler neighborhood-based rule
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
divisor
|
str
|
Which division mode to use: 'union' or 'mean'. The 'union' mode normalises by the size of the union of neighborhoods, while 'mean' normalises by the average size of the two neighborhoods. Defaults to "mean". |
'mean'
|
Raises:
| Type | Description |
|---|---|
AssertionError
|
If divisor is not one of "mean" or "union". |
Source code in src/gnm/generative_rules/generative_rules.py
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 | |
gnm.generative_rules.Neighbours
Bases: GenerativeRule
Compute affinity based on the number of shared neighbors.
This rule is a simpler version of the matching index rule. Instead of normalising by neighborhood sizes, it normalises by the total number of nodes in the network.
The affinity factor is computed as: $$ K(u,v) = | N(u) \cap N(v) | / |V|, $$ where \(|V|\) is the number of nodes in the graph.
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import Neighbours
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply neighbors rule
>>> rule = Neighbours()
>>> affinity_matrix = rule(network)
See Also
generative_rules.GenerativeRule: The base class for generative rules, from which this class inherits.generative_rules.MatchingIndex: A more complex homophily rule.
Geometric Rule
gnm.generative_rules.Geometric
Bases: GenerativeRule
A baseline generative rule that assigns equal affinity to all node pairs.
This rule creates a constant affinity matrix, meaning all potential connections have equal probability from the perspective of this rule. When used in a generative model, other factors like distance will determine connection formation.
The affinity factor is constant: $$ K(u,v) = 1. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import Geometric
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply geometric rule
>>> rule = Geometric()
>>> affinity_matrix = rule(network)
>>> # All non-diagonal elements should be 1
>>> torch.all(affinity_matrix[0][~torch.eye(network.shape[0], dtype=bool)] == 1)
tensor(True)
See Also
generative_rules.GenerativeRule: The base class for generative rules, from which this class inherits.
Clustering-Based Rules
gnm.generative_rules.ClusteringRule
Bases: GenerativeRule, ABC
Base class for clustering coefficient-based generative rules.
Clustering-based rules use the clustering coefficient of nodes to determine connection affinities. The clustering coefficient of each node measures how connected the neighbourhood of that node is.
The clustering coefficient is computed as: $$ c_u = \frac{t_u}{k_u(k_u - 1)}, $$ where \(k_u\) is the degree of node \(u\), and \(t_u\) is the number of (directed) triangles around node \(u\), computed as: $$ t_u = \sum_{v,w} A_{uv}A_{vw}A_{wu}. $$
Classes that inherit from this base class use the clustering coefficients to form various affinity factors based on different relationships between node pairs.
See Also
generative_rules.GenerativeRule: The base class for generative rules, from which this class inherits.utils.binary_clustering_coefficients: Function to compute clustering coefficients for binary networks.
gnm.generative_rules.ClusteringAverage
Bases: ClusteringRule
Compute affinity based on the average clustering coefficient of node pairs.
This rule creates affinities based on the average of the clustering coefficients of the two nodes being considered for connection. Higher average clustering tends to create more locally clustered networks.
The affinity factor is computed as the average of the clustering coefficients of the two nodes: $$ K(u,v) = (c_u + c_v) / 2. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import ClusteringAverage
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply clustering average rule
>>> rule = ClusteringAverage()
>>> affinity_matrix = rule(network)
See Also
generative_rules.ClusteringRule: The base class for clustering coefficient-based rules.generative_rules.DegreeAverage: Similar generative rule which uses degrees instead of clustering coefficients.
gnm.generative_rules.ClusteringMax
Bases: ClusteringRule
Compute affinity based on the maximum clustering coefficient between nodes.
This rule creates affinities based on the maximum of the clustering coefficients of the two nodes being considered for connection. It tends to favor connections where at least one node has high clustering.
The affinity factor is computed as the maximum of the clustering coefficients: $$ K(u,v) = \max(c_u, c_v). $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import ClusteringMax
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply clustering max rule
>>> rule = ClusteringMax()
>>> affinity_matrix = rule(network)
See Also
generative_rules.ClusteringRule: The base class for clustering coefficient-based rules.generative_rules.DegreeMax: Similar generative rule which uses degrees instead of clustering coefficients.
gnm.generative_rules.ClusteringMin
Bases: ClusteringRule
Compute affinity based on the minimum clustering coefficient between nodes.
This rule creates affinities based on the minimum of the clustering coefficients of the two nodes being considered for connection. It tends to favor connections where both nodes have reasonably high clustering.
The affinity factor is computed as the minimum of the clustering coefficients: $$ K(u,v) = \min(c_u, c_v). $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import ClusteringMin
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply clustering min rule
>>> rule = ClusteringMin()
>>> affinity_matrix = rule(network)
See Also
generative_rules.ClusteringRule: The base class for clustering coefficient-based rules.generative_rules.DegreeMin: Similar generative rule which uses degrees instead of clustering coefficients.
gnm.generative_rules.ClusteringDifference
Bases: ClusteringRule
Compute affinity based on the difference in clustering coefficients between nodes.
This rule creates affinities based on how different the clustering coefficients of two nodes are. It can be used to connect nodes with either similar (when using negative exponents in the generative model) or dissimilar (with positive exponents) clustering properties.
The affinity factor is computed as the absolute difference of the clustering coefficients: $$ K(u,v) = |c_u - c_v|. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import ClusteringDifference
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply clustering difference rule
>>> rule = ClusteringDifference()
>>> affinity_matrix = rule(network)
See Also
generative_rules.ClusteringRule: The base class for clustering coefficient-based rules.generative_rules.DegreeDifference: Similar generative rule which uses degrees instead of clustering coefficients.
gnm.generative_rules.ClusteringProduct
Bases: ClusteringRule
Compute affinity based on the product of clustering coefficients between nodes.
This rule creates affinities based on the product of the clustering coefficients of the two nodes being considered for connection. It strongly favors connections between nodes that both have high clustering.
The affinity factor is computed as the product of the clustering coefficients: $$ K(u,v) = c_u \times c_v. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import ClusteringProduct
>>> # Load a default binary network
>>> network = get_binary_network()[0] # Get first network from batch
>>> # Apply clustering product rule
>>> rule = ClusteringProduct()
>>> affinity_matrix = rule(network.unsqueeze(0))
See Also
generative_rules.ClusteringAverage: Uses average of clustering coefficientsgenerative_rules.DegreeProduct: Similar principle applied to degrees
Degree-Based Rules
gnm.generative_rules.DegreeRule
Bases: GenerativeRule, ABC
Base class for degree-based generative rules.
Degree-based rules use the degree (number of connections) of nodes to determine connection affinities. These rules can create various network structures by favoring connections between nodes with specific degree relationships.
The (normalised) degree of a node \(u\) is computed as: $$ k_u = \frac{1}{|V|} \sum_{v} A_{uv}. $$
The division by \(|V|\) (number of nodes) ensures that the degree is between 0 and 1.
Classes which inherit from this base class use the normalised degrees to form the affinity factor using different relationships between node pairs.
See Also
generative_rules.GenerativeRule: The base class for generative rules, from which this class inherits.
gnm.generative_rules.DegreeAverage
Bases: DegreeRule
Compute affinity based on the average degree of node pairs.
This rule creates affinities based on the average of the degrees of the two nodes being considered for connection. It tends to create networks with more uniform degree distributions.
The affinity factor is computed as the average of the normalised degrees: $$ K(u,v) = (k_u + k_v) / 2. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import DegreeAverage
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply degree average rule
>>> rule = DegreeAverage()
>>> affinity_matrix = rule(network)
See Also
generative_rules.DegreeRule: The base class for degree-based rules, from which this class inherits.generative_rules.ClusteringAverage: Similar generative rule which uses clustering coefficients instead of degrees.
gnm.generative_rules.DegreeMax
Bases: DegreeRule
Compute affinity based on the maximum degree between nodes.
This rule creates affinities based on the maximum of the degrees of the two nodes being considered for connection. It tends to favor connections where at least one node has high degree.
The affinity factor is computed as the maximum of the normalised degrees: $$ K(u,v) = \max(k_u,k_v). $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import DegreeMax
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply degree max rule
>>> rule = DegreeMax()
>>> affinity_matrix = rule(network)
See Also
generative_rules.DegreeRule: The base class for degree-based rules, from which this class inherits.generative_rules.ClusteringMax: Similar generative rule which uses clustering coefficients instead of degrees.
gnm.generative_rules.DegreeMin
Bases: DegreeRule
Compute affinity based on the minimum degree between nodes.
This rule creates affinities based on the minimum of the degrees of the two nodes being considered for connection. It tends to favor connections where both nodes have reasonably high degree.
The affinity factor is computed as the minimum of the normalised degrees: $$ K(u,v) = \min(k_u,k_v). $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import DegreeMin
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply degree min rule
>>> rule = DegreeMin()
>>> affinity_matrix = rule(network)
See Also
generative_rules.DegreeRule: The base class for degree-based rules, from which this class inherits.generative_rules.ClusteringMin: Similar generative rule which uses clustering coefficients instead of degrees.
gnm.generative_rules.DegreeDifference
Bases: DegreeRule
Compute affinity based on the difference in degrees between nodes.
This rule creates affinities based on how different the degrees of two nodes are. It can be used to connect nodes with either similar (when using negative exponents in the generative model) or dissimilar (with positive exponents) connectivity patterns.
The affinity factor is computed as the absolute difference of the normalised degrees: $$ K(u,v) = |k_u - k_v|. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import DegreeDifference
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply degree difference rule
>>> rule = DegreeDifference()
>>> affinity_matrix = rule(network)
See Also
generative_rules.DegreeRule: The base class for degree-based rules, from which this class inherits.generative_rules.ClusteringDifference: Similar generative rule which uses clustering coefficients instead of degrees.
gnm.generative_rules.DegreeProduct
Bases: DegreeRule
Compute affinity based on the product of degrees between nodes.
This rule creates affinities based on the product of the degrees of the two nodes being considered for connection. It strongly favors connections between nodes that both have high degree, potentially leading to rich-club structures.
The affinity factor is computed as the product of the normalised degrees: $$ K(u,v) = k_u \times k_v. $$
Examples:
>>> import torch
>>> from gnm.defaults import get_binary_network
>>> from gnm.generative_rules import DegreeProduct
>>> # Load a default binary network
>>> network = get_binary_network()
>>> # Apply degree product rule
>>> rule = DegreeProduct()
>>> affinity_matrix = rule(network)
See Also
generative_rules.DegreeRule: The base class for degree-based rules, from which this class inherits.generative_rules.ClusteringProduct: Similar principle applied to clustering coefficients