aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py')
-rw-r--r--.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py b/.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py
new file mode 100644
index 00000000..39a87f74
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/networkx/generators/spectral_graph_forge.py
@@ -0,0 +1,120 @@
+"""Generates graphs with a given eigenvector structure"""
+
+import networkx as nx
+from networkx.utils import np_random_state
+
+__all__ = ["spectral_graph_forge"]
+
+
+@np_random_state(3)
+@nx._dispatchable(returns_graph=True)
+def spectral_graph_forge(G, alpha, transformation="identity", seed=None):
+ """Returns a random simple graph with spectrum resembling that of `G`
+
+ This algorithm, called Spectral Graph Forge (SGF), computes the
+ eigenvectors of a given graph adjacency matrix, filters them and
+ builds a random graph with a similar eigenstructure.
+ SGF has been proved to be particularly useful for synthesizing
+ realistic social networks and it can also be used to anonymize
+ graph sensitive data.
+
+ Parameters
+ ----------
+ G : Graph
+ alpha : float
+ Ratio representing the percentage of eigenvectors of G to consider,
+ values in [0,1].
+ transformation : string, optional
+ Represents the intended matrix linear transformation, possible values
+ are 'identity' and 'modularity'
+ seed : integer, random_state, or None (default)
+ Indicator of numpy random number generation state.
+ See :ref:`Randomness<randomness>`.
+
+ Returns
+ -------
+ H : Graph
+ A graph with a similar eigenvector structure of the input one.
+
+ Raises
+ ------
+ NetworkXError
+ If transformation has a value different from 'identity' or 'modularity'
+
+ Notes
+ -----
+ Spectral Graph Forge (SGF) generates a random simple graph resembling the
+ global properties of the given one.
+ It leverages the low-rank approximation of the associated adjacency matrix
+ driven by the *alpha* precision parameter.
+ SGF preserves the number of nodes of the input graph and their ordering.
+ This way, nodes of output graphs resemble the properties of the input one
+ and attributes can be directly mapped.
+
+ It considers the graph adjacency matrices which can optionally be
+ transformed to other symmetric real matrices (currently transformation
+ options include *identity* and *modularity*).
+ The *modularity* transformation, in the sense of Newman's modularity matrix
+ allows the focusing on community structure related properties of the graph.
+
+ SGF applies a low-rank approximation whose fixed rank is computed from the
+ ratio *alpha* of the input graph adjacency matrix dimension.
+ This step performs a filtering on the input eigenvectors similar to the low
+ pass filtering common in telecommunications.
+
+ The filtered values (after truncation) are used as input to a Bernoulli
+ sampling for constructing a random adjacency matrix.
+
+ References
+ ----------
+ .. [1] L. Baldesi, C. T. Butts, A. Markopoulou, "Spectral Graph Forge:
+ Graph Generation Targeting Modularity", IEEE Infocom, '18.
+ https://arxiv.org/abs/1801.01715
+ .. [2] M. Newman, "Networks: an introduction", Oxford university press,
+ 2010
+
+ Examples
+ --------
+ >>> G = nx.karate_club_graph()
+ >>> H = nx.spectral_graph_forge(G, 0.3)
+ >>>
+ """
+ import numpy as np
+ import scipy as sp
+
+ available_transformations = ["identity", "modularity"]
+ alpha = np.clip(alpha, 0, 1)
+ A = nx.to_numpy_array(G)
+ n = A.shape[1]
+ level = round(n * alpha)
+
+ if transformation not in available_transformations:
+ msg = f"{transformation!r} is not a valid transformation. "
+ msg += f"Transformations: {available_transformations}"
+ raise nx.NetworkXError(msg)
+
+ K = np.ones((1, n)) @ A
+
+ B = A
+ if transformation == "modularity":
+ B -= K.T @ K / K.sum()
+
+ # Compute low-rank approximation of B
+ evals, evecs = np.linalg.eigh(B)
+ k = np.argsort(np.abs(evals))[::-1] # indices of evals in descending order
+ evecs[:, k[np.arange(level, n)]] = 0 # set smallest eigenvectors to 0
+ B = evecs @ np.diag(evals) @ evecs.T
+
+ if transformation == "modularity":
+ B += K.T @ K / K.sum()
+
+ B = np.clip(B, 0, 1)
+ np.fill_diagonal(B, 0)
+
+ for i in range(n - 1):
+ B[i, i + 1 :] = sp.stats.bernoulli.rvs(B[i, i + 1 :], random_state=seed)
+ B[i + 1 :, i] = np.transpose(B[i, i + 1 :])
+
+ H = nx.from_numpy_array(B)
+
+ return H