scikit-network 0.33.3__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of scikit-network might be problematic. Click here for more details.
- scikit_network-0.33.3.dist-info/METADATA +122 -0
- scikit_network-0.33.3.dist-info/RECORD +228 -0
- scikit_network-0.33.3.dist-info/WHEEL +5 -0
- scikit_network-0.33.3.dist-info/licenses/AUTHORS.rst +43 -0
- scikit_network-0.33.3.dist-info/licenses/LICENSE +34 -0
- scikit_network-0.33.3.dist-info/top_level.txt +1 -0
- sknetwork/__init__.py +21 -0
- sknetwork/base.py +67 -0
- sknetwork/classification/__init__.py +8 -0
- sknetwork/classification/base.py +142 -0
- sknetwork/classification/base_rank.py +133 -0
- sknetwork/classification/diffusion.py +134 -0
- sknetwork/classification/knn.py +139 -0
- sknetwork/classification/metrics.py +205 -0
- sknetwork/classification/pagerank.py +66 -0
- sknetwork/classification/propagation.py +152 -0
- sknetwork/classification/tests/__init__.py +1 -0
- sknetwork/classification/tests/test_API.py +30 -0
- sknetwork/classification/tests/test_diffusion.py +77 -0
- sknetwork/classification/tests/test_knn.py +23 -0
- sknetwork/classification/tests/test_metrics.py +53 -0
- sknetwork/classification/tests/test_pagerank.py +20 -0
- sknetwork/classification/tests/test_propagation.py +24 -0
- sknetwork/classification/vote.cp313-win_amd64.pyd +0 -0
- sknetwork/classification/vote.cpp +27584 -0
- sknetwork/classification/vote.pyx +56 -0
- sknetwork/clustering/__init__.py +8 -0
- sknetwork/clustering/base.py +172 -0
- sknetwork/clustering/kcenters.py +253 -0
- sknetwork/clustering/leiden.py +242 -0
- sknetwork/clustering/leiden_core.cp313-win_amd64.pyd +0 -0
- sknetwork/clustering/leiden_core.cpp +31575 -0
- sknetwork/clustering/leiden_core.pyx +124 -0
- sknetwork/clustering/louvain.py +286 -0
- sknetwork/clustering/louvain_core.cp313-win_amd64.pyd +0 -0
- sknetwork/clustering/louvain_core.cpp +31220 -0
- sknetwork/clustering/louvain_core.pyx +124 -0
- sknetwork/clustering/metrics.py +91 -0
- sknetwork/clustering/postprocess.py +66 -0
- sknetwork/clustering/propagation_clustering.py +104 -0
- sknetwork/clustering/tests/__init__.py +1 -0
- sknetwork/clustering/tests/test_API.py +38 -0
- sknetwork/clustering/tests/test_kcenters.py +60 -0
- sknetwork/clustering/tests/test_leiden.py +34 -0
- sknetwork/clustering/tests/test_louvain.py +135 -0
- sknetwork/clustering/tests/test_metrics.py +50 -0
- sknetwork/clustering/tests/test_postprocess.py +39 -0
- sknetwork/data/__init__.py +6 -0
- sknetwork/data/base.py +33 -0
- sknetwork/data/load.py +406 -0
- sknetwork/data/models.py +459 -0
- sknetwork/data/parse.py +644 -0
- sknetwork/data/test_graphs.py +84 -0
- sknetwork/data/tests/__init__.py +1 -0
- sknetwork/data/tests/test_API.py +30 -0
- sknetwork/data/tests/test_base.py +14 -0
- sknetwork/data/tests/test_load.py +95 -0
- sknetwork/data/tests/test_models.py +52 -0
- sknetwork/data/tests/test_parse.py +250 -0
- sknetwork/data/tests/test_test_graphs.py +29 -0
- sknetwork/data/tests/test_toy_graphs.py +68 -0
- sknetwork/data/timeout.py +38 -0
- sknetwork/data/toy_graphs.py +611 -0
- sknetwork/embedding/__init__.py +8 -0
- sknetwork/embedding/base.py +94 -0
- sknetwork/embedding/force_atlas.py +198 -0
- sknetwork/embedding/louvain_embedding.py +148 -0
- sknetwork/embedding/random_projection.py +135 -0
- sknetwork/embedding/spectral.py +141 -0
- sknetwork/embedding/spring.py +198 -0
- sknetwork/embedding/svd.py +359 -0
- sknetwork/embedding/tests/__init__.py +1 -0
- sknetwork/embedding/tests/test_API.py +49 -0
- sknetwork/embedding/tests/test_force_atlas.py +35 -0
- sknetwork/embedding/tests/test_louvain_embedding.py +33 -0
- sknetwork/embedding/tests/test_random_projection.py +28 -0
- sknetwork/embedding/tests/test_spectral.py +81 -0
- sknetwork/embedding/tests/test_spring.py +50 -0
- sknetwork/embedding/tests/test_svd.py +43 -0
- sknetwork/gnn/__init__.py +10 -0
- sknetwork/gnn/activation.py +117 -0
- sknetwork/gnn/base.py +181 -0
- sknetwork/gnn/base_activation.py +90 -0
- sknetwork/gnn/base_layer.py +109 -0
- sknetwork/gnn/gnn_classifier.py +305 -0
- sknetwork/gnn/layer.py +153 -0
- sknetwork/gnn/loss.py +180 -0
- sknetwork/gnn/neighbor_sampler.py +65 -0
- sknetwork/gnn/optimizer.py +164 -0
- sknetwork/gnn/tests/__init__.py +1 -0
- sknetwork/gnn/tests/test_activation.py +56 -0
- sknetwork/gnn/tests/test_base.py +75 -0
- sknetwork/gnn/tests/test_base_layer.py +37 -0
- sknetwork/gnn/tests/test_gnn_classifier.py +130 -0
- sknetwork/gnn/tests/test_layers.py +80 -0
- sknetwork/gnn/tests/test_loss.py +33 -0
- sknetwork/gnn/tests/test_neigh_sampler.py +23 -0
- sknetwork/gnn/tests/test_optimizer.py +43 -0
- sknetwork/gnn/tests/test_utils.py +41 -0
- sknetwork/gnn/utils.py +127 -0
- sknetwork/hierarchy/__init__.py +6 -0
- sknetwork/hierarchy/base.py +96 -0
- sknetwork/hierarchy/louvain_hierarchy.py +272 -0
- sknetwork/hierarchy/metrics.py +234 -0
- sknetwork/hierarchy/paris.cp313-win_amd64.pyd +0 -0
- sknetwork/hierarchy/paris.cpp +37868 -0
- sknetwork/hierarchy/paris.pyx +316 -0
- sknetwork/hierarchy/postprocess.py +350 -0
- sknetwork/hierarchy/tests/__init__.py +1 -0
- sknetwork/hierarchy/tests/test_API.py +24 -0
- sknetwork/hierarchy/tests/test_algos.py +34 -0
- sknetwork/hierarchy/tests/test_metrics.py +62 -0
- sknetwork/hierarchy/tests/test_postprocess.py +57 -0
- sknetwork/linalg/__init__.py +9 -0
- sknetwork/linalg/basics.py +37 -0
- sknetwork/linalg/diteration.cp313-win_amd64.pyd +0 -0
- sknetwork/linalg/diteration.cpp +27400 -0
- sknetwork/linalg/diteration.pyx +47 -0
- sknetwork/linalg/eig_solver.py +93 -0
- sknetwork/linalg/laplacian.py +15 -0
- sknetwork/linalg/normalizer.py +86 -0
- sknetwork/linalg/operators.py +225 -0
- sknetwork/linalg/polynome.py +76 -0
- sknetwork/linalg/ppr_solver.py +170 -0
- sknetwork/linalg/push.cp313-win_amd64.pyd +0 -0
- sknetwork/linalg/push.cpp +31072 -0
- sknetwork/linalg/push.pyx +71 -0
- sknetwork/linalg/sparse_lowrank.py +142 -0
- sknetwork/linalg/svd_solver.py +91 -0
- sknetwork/linalg/tests/__init__.py +1 -0
- sknetwork/linalg/tests/test_eig.py +44 -0
- sknetwork/linalg/tests/test_laplacian.py +18 -0
- sknetwork/linalg/tests/test_normalization.py +34 -0
- sknetwork/linalg/tests/test_operators.py +66 -0
- sknetwork/linalg/tests/test_polynome.py +38 -0
- sknetwork/linalg/tests/test_ppr.py +50 -0
- sknetwork/linalg/tests/test_sparse_lowrank.py +61 -0
- sknetwork/linalg/tests/test_svd.py +38 -0
- sknetwork/linkpred/__init__.py +2 -0
- sknetwork/linkpred/base.py +46 -0
- sknetwork/linkpred/nn.py +126 -0
- sknetwork/linkpred/tests/__init__.py +1 -0
- sknetwork/linkpred/tests/test_nn.py +27 -0
- sknetwork/log.py +19 -0
- sknetwork/path/__init__.py +5 -0
- sknetwork/path/dag.py +54 -0
- sknetwork/path/distances.py +98 -0
- sknetwork/path/search.py +31 -0
- sknetwork/path/shortest_path.py +61 -0
- sknetwork/path/tests/__init__.py +1 -0
- sknetwork/path/tests/test_dag.py +37 -0
- sknetwork/path/tests/test_distances.py +62 -0
- sknetwork/path/tests/test_search.py +40 -0
- sknetwork/path/tests/test_shortest_path.py +40 -0
- sknetwork/ranking/__init__.py +8 -0
- sknetwork/ranking/base.py +61 -0
- sknetwork/ranking/betweenness.cp313-win_amd64.pyd +0 -0
- sknetwork/ranking/betweenness.cpp +9707 -0
- sknetwork/ranking/betweenness.pyx +97 -0
- sknetwork/ranking/closeness.py +92 -0
- sknetwork/ranking/hits.py +94 -0
- sknetwork/ranking/katz.py +83 -0
- sknetwork/ranking/pagerank.py +110 -0
- sknetwork/ranking/postprocess.py +37 -0
- sknetwork/ranking/tests/__init__.py +1 -0
- sknetwork/ranking/tests/test_API.py +32 -0
- sknetwork/ranking/tests/test_betweenness.py +38 -0
- sknetwork/ranking/tests/test_closeness.py +30 -0
- sknetwork/ranking/tests/test_hits.py +20 -0
- sknetwork/ranking/tests/test_pagerank.py +62 -0
- sknetwork/ranking/tests/test_postprocess.py +26 -0
- sknetwork/regression/__init__.py +4 -0
- sknetwork/regression/base.py +61 -0
- sknetwork/regression/diffusion.py +210 -0
- sknetwork/regression/tests/__init__.py +1 -0
- sknetwork/regression/tests/test_API.py +32 -0
- sknetwork/regression/tests/test_diffusion.py +56 -0
- sknetwork/sknetwork.py +3 -0
- sknetwork/test_base.py +35 -0
- sknetwork/test_log.py +15 -0
- sknetwork/topology/__init__.py +8 -0
- sknetwork/topology/cliques.cp313-win_amd64.pyd +0 -0
- sknetwork/topology/cliques.cpp +32565 -0
- sknetwork/topology/cliques.pyx +149 -0
- sknetwork/topology/core.cp313-win_amd64.pyd +0 -0
- sknetwork/topology/core.cpp +30651 -0
- sknetwork/topology/core.pyx +90 -0
- sknetwork/topology/cycles.py +243 -0
- sknetwork/topology/minheap.cp313-win_amd64.pyd +0 -0
- sknetwork/topology/minheap.cpp +27332 -0
- sknetwork/topology/minheap.pxd +20 -0
- sknetwork/topology/minheap.pyx +109 -0
- sknetwork/topology/structure.py +194 -0
- sknetwork/topology/tests/__init__.py +1 -0
- sknetwork/topology/tests/test_cliques.py +28 -0
- sknetwork/topology/tests/test_core.py +19 -0
- sknetwork/topology/tests/test_cycles.py +65 -0
- sknetwork/topology/tests/test_structure.py +85 -0
- sknetwork/topology/tests/test_triangles.py +38 -0
- sknetwork/topology/tests/test_wl.py +72 -0
- sknetwork/topology/triangles.cp313-win_amd64.pyd +0 -0
- sknetwork/topology/triangles.cpp +8894 -0
- sknetwork/topology/triangles.pyx +151 -0
- sknetwork/topology/weisfeiler_lehman.py +133 -0
- sknetwork/topology/weisfeiler_lehman_core.cp313-win_amd64.pyd +0 -0
- sknetwork/topology/weisfeiler_lehman_core.cpp +27635 -0
- sknetwork/topology/weisfeiler_lehman_core.pyx +114 -0
- sknetwork/utils/__init__.py +7 -0
- sknetwork/utils/check.py +355 -0
- sknetwork/utils/format.py +221 -0
- sknetwork/utils/membership.py +82 -0
- sknetwork/utils/neighbors.py +115 -0
- sknetwork/utils/tests/__init__.py +1 -0
- sknetwork/utils/tests/test_check.py +190 -0
- sknetwork/utils/tests/test_format.py +63 -0
- sknetwork/utils/tests/test_membership.py +24 -0
- sknetwork/utils/tests/test_neighbors.py +41 -0
- sknetwork/utils/tests/test_tfidf.py +18 -0
- sknetwork/utils/tests/test_values.py +66 -0
- sknetwork/utils/tfidf.py +37 -0
- sknetwork/utils/values.py +76 -0
- sknetwork/visualization/__init__.py +4 -0
- sknetwork/visualization/colors.py +34 -0
- sknetwork/visualization/dendrograms.py +277 -0
- sknetwork/visualization/graphs.py +1039 -0
- sknetwork/visualization/tests/__init__.py +1 -0
- sknetwork/visualization/tests/test_dendrograms.py +53 -0
- sknetwork/visualization/tests/test_graphs.py +176 -0
sknetwork/data/models.py
ADDED
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created in July 2019
|
|
5
|
+
@author: Thomas Bonald <bonald@enst.fr>
|
|
6
|
+
@author: Quentin Lutz <qlutz@enst.fr>
|
|
7
|
+
@author: Nathan de Lara <nathan.delara@polytechnique.org>
|
|
8
|
+
"""
|
|
9
|
+
from math import pi
|
|
10
|
+
from typing import Union, Optional, Iterable
|
|
11
|
+
|
|
12
|
+
import numpy as np
|
|
13
|
+
from scipy import sparse
|
|
14
|
+
|
|
15
|
+
from sknetwork.data.base import Dataset
|
|
16
|
+
from sknetwork.data.parse import from_edge_list
|
|
17
|
+
from sknetwork.utils.check import check_random_state
|
|
18
|
+
from sknetwork.utils.format import directed2undirected
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def block_model(sizes: Iterable, p_in: Union[float, list, np.ndarray] = .2, p_out: float = .05,
|
|
22
|
+
directed: bool = False, self_loops: bool = False, metadata: bool = False, seed: Optional[int] = None) \
|
|
23
|
+
-> Union[sparse.csr_matrix, Dataset]:
|
|
24
|
+
"""Stochastic block model.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
sizes :
|
|
29
|
+
Block sizes.
|
|
30
|
+
p_in :
|
|
31
|
+
Probability of connection within blocks.
|
|
32
|
+
p_out :
|
|
33
|
+
Probability of connection across blocks.
|
|
34
|
+
directed :
|
|
35
|
+
If ``True``, return a directed graph.
|
|
36
|
+
self_loops :
|
|
37
|
+
If ``True``, allow self-loops.
|
|
38
|
+
metadata :
|
|
39
|
+
If ``True``, return a `Dataset` object with labels.
|
|
40
|
+
seed :
|
|
41
|
+
Seed of the random generator (optional).
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
45
|
+
Adjacency matrix or graph with metadata (labels).
|
|
46
|
+
|
|
47
|
+
Example
|
|
48
|
+
-------
|
|
49
|
+
>>> from sknetwork.data import block_model
|
|
50
|
+
>>> sizes = np.array([4, 5])
|
|
51
|
+
>>> adjacency = block_model(sizes)
|
|
52
|
+
>>> adjacency.shape
|
|
53
|
+
(9, 9)
|
|
54
|
+
|
|
55
|
+
References
|
|
56
|
+
----------
|
|
57
|
+
Airoldi, E., Blei, D., Feinberg, S., Xing, E. (2007).
|
|
58
|
+
`Mixed membership stochastic blockmodels. <https://arxiv.org/pdf/0705.4485.pdf>`_
|
|
59
|
+
Journal of Machine Learning Research.
|
|
60
|
+
"""
|
|
61
|
+
random_state = check_random_state(seed)
|
|
62
|
+
|
|
63
|
+
if isinstance(p_in, (np.floating, float, int)):
|
|
64
|
+
p_in = p_in * np.ones_like(sizes)
|
|
65
|
+
else:
|
|
66
|
+
p_in = np.array(p_in)
|
|
67
|
+
|
|
68
|
+
blocks = []
|
|
69
|
+
for i, a in enumerate(sizes):
|
|
70
|
+
row = []
|
|
71
|
+
for j, b in enumerate(sizes):
|
|
72
|
+
if j == i:
|
|
73
|
+
row.append(sparse.random(a, a, p_in[i], dtype=bool, random_state=random_state))
|
|
74
|
+
else:
|
|
75
|
+
row.append(sparse.random(a, b, p_out, dtype=bool, random_state=random_state))
|
|
76
|
+
blocks.append(row)
|
|
77
|
+
adjacency = sparse.bmat(blocks)
|
|
78
|
+
if not self_loops:
|
|
79
|
+
adjacency = sparse.lil_matrix(adjacency)
|
|
80
|
+
adjacency.setdiag(0)
|
|
81
|
+
if directed:
|
|
82
|
+
adjacency = sparse.csr_matrix(adjacency)
|
|
83
|
+
else:
|
|
84
|
+
adjacency = directed2undirected(sparse.csr_matrix(sparse.triu(adjacency)), weighted=False)
|
|
85
|
+
if metadata:
|
|
86
|
+
graph = Dataset()
|
|
87
|
+
graph.adjacency = adjacency
|
|
88
|
+
labels = np.repeat(np.arange(len(sizes)), sizes)
|
|
89
|
+
graph.labels = labels
|
|
90
|
+
return graph
|
|
91
|
+
else:
|
|
92
|
+
return adjacency
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def erdos_renyi(n: int = 20, p: float = .3, directed: bool = False, self_loops: bool = False,
|
|
96
|
+
seed: Optional[int] = None) -> sparse.csr_matrix:
|
|
97
|
+
"""Erdos-Renyi graph.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
n :
|
|
102
|
+
Number of nodes.
|
|
103
|
+
p :
|
|
104
|
+
Probability of connection between nodes.
|
|
105
|
+
directed :
|
|
106
|
+
If ``True``, return a directed graph.
|
|
107
|
+
self_loops :
|
|
108
|
+
If ``True``, allow self-loops.
|
|
109
|
+
seed :
|
|
110
|
+
Seed of the random generator (optional).
|
|
111
|
+
|
|
112
|
+
Returns
|
|
113
|
+
-------
|
|
114
|
+
adjacency : sparse.csr_matrix
|
|
115
|
+
Adjacency matrix.
|
|
116
|
+
|
|
117
|
+
Example
|
|
118
|
+
-------
|
|
119
|
+
>>> from sknetwork.data import erdos_renyi
|
|
120
|
+
>>> adjacency = erdos_renyi(7)
|
|
121
|
+
>>> adjacency.shape
|
|
122
|
+
(7, 7)
|
|
123
|
+
|
|
124
|
+
References
|
|
125
|
+
----------
|
|
126
|
+
Erdős, P., Rényi, A. (1959). `On Random Graphs. <https://www.renyi.hu/~p_erdos/1959-11.pdf>`_
|
|
127
|
+
Publicationes Mathematicae.
|
|
128
|
+
"""
|
|
129
|
+
return block_model([n], p, 0., directed=directed, self_loops=self_loops, metadata=False, seed=seed)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def linear_digraph(n: int = 3, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
133
|
+
"""Linear graph (directed).
|
|
134
|
+
|
|
135
|
+
Parameters
|
|
136
|
+
----------
|
|
137
|
+
n : int
|
|
138
|
+
Number of nodes.
|
|
139
|
+
metadata : bool
|
|
140
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
145
|
+
Adjacency matrix or graph with metadata (positions).
|
|
146
|
+
|
|
147
|
+
Example
|
|
148
|
+
-------
|
|
149
|
+
>>> from sknetwork.data import linear_digraph
|
|
150
|
+
>>> adjacency = linear_digraph(5)
|
|
151
|
+
>>> adjacency.shape
|
|
152
|
+
(5, 5)
|
|
153
|
+
"""
|
|
154
|
+
row = np.arange(n - 1)
|
|
155
|
+
col = np.arange(1, n)
|
|
156
|
+
adjacency = sparse.csr_matrix((np.ones(len(row), dtype=int), (row, col)), shape=(n, n))
|
|
157
|
+
|
|
158
|
+
if metadata:
|
|
159
|
+
x = np.arange(n)
|
|
160
|
+
y = np.zeros(n)
|
|
161
|
+
graph = Dataset()
|
|
162
|
+
graph.adjacency = adjacency
|
|
163
|
+
graph.position = np.array((x, y)).T
|
|
164
|
+
return graph
|
|
165
|
+
else:
|
|
166
|
+
return adjacency
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
def linear_graph(n: int = 3, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
170
|
+
"""Linear graph (undirected).
|
|
171
|
+
|
|
172
|
+
Parameters
|
|
173
|
+
----------
|
|
174
|
+
n : int
|
|
175
|
+
Number of nodes.
|
|
176
|
+
metadata : bool
|
|
177
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
178
|
+
|
|
179
|
+
Returns
|
|
180
|
+
-------
|
|
181
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
182
|
+
Adjacency matrix or graph with metadata (positions).
|
|
183
|
+
|
|
184
|
+
Example
|
|
185
|
+
-------
|
|
186
|
+
>>> from sknetwork.data import linear_graph
|
|
187
|
+
>>> adjacency = linear_graph(5)
|
|
188
|
+
>>> adjacency.shape
|
|
189
|
+
(5, 5)
|
|
190
|
+
"""
|
|
191
|
+
graph = linear_digraph(n, True)
|
|
192
|
+
adjacency = graph.adjacency
|
|
193
|
+
adjacency = adjacency + adjacency.T
|
|
194
|
+
if metadata:
|
|
195
|
+
graph.adjacency = adjacency
|
|
196
|
+
return graph
|
|
197
|
+
else:
|
|
198
|
+
return adjacency
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def cyclic_position(n: int) -> np.ndarray:
|
|
202
|
+
"""Position nodes on a circle of unit radius.
|
|
203
|
+
|
|
204
|
+
Parameters
|
|
205
|
+
----------
|
|
206
|
+
n : int
|
|
207
|
+
Number of nodes.
|
|
208
|
+
|
|
209
|
+
Returns
|
|
210
|
+
-------
|
|
211
|
+
position : np.ndarray
|
|
212
|
+
Position of nodes.
|
|
213
|
+
"""
|
|
214
|
+
t = 2 * pi * np.arange(n).astype(float) / n
|
|
215
|
+
x = np.cos(t)
|
|
216
|
+
y = np.sin(t)
|
|
217
|
+
position = np.array((x, y)).T
|
|
218
|
+
return position
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def cyclic_digraph(n: int = 3, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
222
|
+
"""Cyclic graph (directed).
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
n : int
|
|
227
|
+
Number of nodes.
|
|
228
|
+
metadata : bool
|
|
229
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
230
|
+
|
|
231
|
+
Returns
|
|
232
|
+
-------
|
|
233
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
234
|
+
Adjacency matrix or graph with metadata (positions).
|
|
235
|
+
|
|
236
|
+
Example
|
|
237
|
+
-------
|
|
238
|
+
>>> from sknetwork.data import cyclic_digraph
|
|
239
|
+
>>> adjacency = cyclic_digraph(5)
|
|
240
|
+
>>> adjacency.shape
|
|
241
|
+
(5, 5)
|
|
242
|
+
"""
|
|
243
|
+
row = np.arange(n)
|
|
244
|
+
col = np.array(list(np.arange(1, n)) + [0])
|
|
245
|
+
adjacency = sparse.csr_matrix((np.ones(len(row), dtype=int), (row, col)), shape=(n, n))
|
|
246
|
+
|
|
247
|
+
if metadata:
|
|
248
|
+
graph = Dataset()
|
|
249
|
+
graph.adjacency = adjacency
|
|
250
|
+
graph.position = cyclic_position(n)
|
|
251
|
+
return graph
|
|
252
|
+
else:
|
|
253
|
+
return adjacency
|
|
254
|
+
|
|
255
|
+
|
|
256
|
+
def cyclic_graph(n: int = 3, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
257
|
+
"""Cyclic graph (undirected).
|
|
258
|
+
|
|
259
|
+
Parameters
|
|
260
|
+
----------
|
|
261
|
+
n : int
|
|
262
|
+
Number of nodes.
|
|
263
|
+
metadata : bool
|
|
264
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
265
|
+
|
|
266
|
+
Returns
|
|
267
|
+
-------
|
|
268
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
269
|
+
Adjacency matrix or graph with metadata (positions).
|
|
270
|
+
|
|
271
|
+
Example
|
|
272
|
+
-------
|
|
273
|
+
>>> from sknetwork.data import cyclic_graph
|
|
274
|
+
>>> adjacency = cyclic_graph(5)
|
|
275
|
+
>>> adjacency.shape
|
|
276
|
+
(5, 5)
|
|
277
|
+
"""
|
|
278
|
+
graph = cyclic_digraph(n, True)
|
|
279
|
+
graph.adjacency = directed2undirected(graph.adjacency)
|
|
280
|
+
if metadata:
|
|
281
|
+
return graph
|
|
282
|
+
else:
|
|
283
|
+
return graph.adjacency
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
def grid(n1: int = 10, n2: int = 10, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
287
|
+
"""Grid (undirected).
|
|
288
|
+
|
|
289
|
+
Parameters
|
|
290
|
+
----------
|
|
291
|
+
n1, n2 : int
|
|
292
|
+
Grid dimension.
|
|
293
|
+
metadata : bool
|
|
294
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
295
|
+
|
|
296
|
+
Returns
|
|
297
|
+
-------
|
|
298
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
299
|
+
Adjacency matrix or graph with metadata (positions).
|
|
300
|
+
|
|
301
|
+
Example
|
|
302
|
+
-------
|
|
303
|
+
>>> from sknetwork.data import grid
|
|
304
|
+
>>> adjacency = grid(10, 5)
|
|
305
|
+
>>> adjacency.shape
|
|
306
|
+
(50, 50)
|
|
307
|
+
"""
|
|
308
|
+
nodes = [(i1, i2) for i1 in range(n1) for i2 in range(n2)]
|
|
309
|
+
edges = [((i1, i2), (i1 + 1, i2)) for i1 in range(n1 - 1) for i2 in range(n2)]
|
|
310
|
+
edges += [((i1, i2), (i1, i2 + 1)) for i1 in range(n1) for i2 in range(n2 - 1)]
|
|
311
|
+
node_id = {u: i for i, u in enumerate(nodes)}
|
|
312
|
+
edges = list(map(lambda edge: (node_id[edge[0]], node_id[edge[1]]), edges))
|
|
313
|
+
adjacency = from_edge_list(edges, reindex=False, matrix_only=True)
|
|
314
|
+
if metadata:
|
|
315
|
+
graph = Dataset()
|
|
316
|
+
graph.adjacency = adjacency
|
|
317
|
+
graph.position = np.array(nodes)
|
|
318
|
+
return graph
|
|
319
|
+
else:
|
|
320
|
+
return adjacency
|
|
321
|
+
|
|
322
|
+
|
|
323
|
+
def star(n_branches: int = 3, metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
324
|
+
"""Star (undirected).
|
|
325
|
+
|
|
326
|
+
Parameters
|
|
327
|
+
----------
|
|
328
|
+
n_branches : int
|
|
329
|
+
Number of branches.
|
|
330
|
+
metadata : bool
|
|
331
|
+
If ``True``, return a `Dataset` object with metadata (positions).
|
|
332
|
+
|
|
333
|
+
Returns
|
|
334
|
+
-------
|
|
335
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
336
|
+
Adjacency matrix or graph with metadata (positions).
|
|
337
|
+
|
|
338
|
+
Example
|
|
339
|
+
-------
|
|
340
|
+
>>> from sknetwork.data import star
|
|
341
|
+
>>> adjacency = star()
|
|
342
|
+
>>> adjacency.shape
|
|
343
|
+
(4, 4)
|
|
344
|
+
"""
|
|
345
|
+
edges = [(0, i+1) for i in range(n_branches)]
|
|
346
|
+
adjacency = from_edge_list(edges, reindex=False, matrix_only=True)
|
|
347
|
+
if metadata:
|
|
348
|
+
graph = Dataset()
|
|
349
|
+
graph.adjacency = adjacency
|
|
350
|
+
angles = 2 * np.pi * np.arange(n_branches) / n_branches
|
|
351
|
+
x = [0] + list(np.cos(angles))
|
|
352
|
+
y = [0] + list(np.sin(angles))
|
|
353
|
+
graph.position = np.vstack([x, y]).T
|
|
354
|
+
return graph
|
|
355
|
+
else:
|
|
356
|
+
return adjacency
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
def albert_barabasi(n: int = 100, degree: int = 3, directed: bool = False, seed: Optional[int] = None) \
|
|
360
|
+
-> sparse.csr_matrix:
|
|
361
|
+
"""Albert-Barabasi model.
|
|
362
|
+
|
|
363
|
+
Parameters
|
|
364
|
+
----------
|
|
365
|
+
n : int
|
|
366
|
+
Number of nodes.
|
|
367
|
+
degree : int
|
|
368
|
+
Degree of incoming nodes (less than **n**).
|
|
369
|
+
directed : bool
|
|
370
|
+
If ``True``, return a directed graph.
|
|
371
|
+
seed :
|
|
372
|
+
Seed of the random generator (optional).
|
|
373
|
+
|
|
374
|
+
Returns
|
|
375
|
+
-------
|
|
376
|
+
adjacency : sparse.csr_matrix
|
|
377
|
+
Adjacency matrix.
|
|
378
|
+
|
|
379
|
+
Example
|
|
380
|
+
-------
|
|
381
|
+
>>> from sknetwork.data import albert_barabasi
|
|
382
|
+
>>> adjacency = albert_barabasi(30, 3)
|
|
383
|
+
>>> adjacency.shape
|
|
384
|
+
(30, 30)
|
|
385
|
+
|
|
386
|
+
References
|
|
387
|
+
----------
|
|
388
|
+
Albert, R., Barabási, L. (2002). `Statistical mechanics of complex networks
|
|
389
|
+
<https://journals.aps.org/rmp/abstract/10.1103/RevModPhys.74.47>`_
|
|
390
|
+
Reviews of Modern Physics.
|
|
391
|
+
"""
|
|
392
|
+
random_state = check_random_state(seed)
|
|
393
|
+
degrees = np.zeros(n, int)
|
|
394
|
+
degrees[:degree] = degree - 1
|
|
395
|
+
edges = [(i, j) for i in range(degree) for j in range(i)]
|
|
396
|
+
for i in range(degree, n):
|
|
397
|
+
neighbors = random_state.choice(a=i, p=degrees[:i]/degrees.sum(), size=degree, replace=False)
|
|
398
|
+
degrees[neighbors] += 1
|
|
399
|
+
degrees[i] = degree
|
|
400
|
+
edges += [(i, j) for j in neighbors]
|
|
401
|
+
return from_edge_list(edges, directed=directed, reindex=False, matrix_only=True)
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
def watts_strogatz(n: int = 100, degree: int = 6, prob: float = 0.05, seed: Optional[int] = None,
|
|
405
|
+
metadata: bool = False) -> Union[sparse.csr_matrix, Dataset]:
|
|
406
|
+
"""Watts-Strogatz model.
|
|
407
|
+
|
|
408
|
+
Parameters
|
|
409
|
+
----------
|
|
410
|
+
n :
|
|
411
|
+
Number of nodes.
|
|
412
|
+
degree :
|
|
413
|
+
Initial degree of nodes.
|
|
414
|
+
prob :
|
|
415
|
+
Probability of edge modification.
|
|
416
|
+
seed :
|
|
417
|
+
Seed of the random generator (optional).
|
|
418
|
+
metadata :
|
|
419
|
+
If ``True``, return a `Dataset` object with metadata.
|
|
420
|
+
Returns
|
|
421
|
+
-------
|
|
422
|
+
adjacency or graph : Union[sparse.csr_matrix, Dataset]
|
|
423
|
+
Adjacency matrix or graph with metadata (positions).
|
|
424
|
+
|
|
425
|
+
Example
|
|
426
|
+
-------
|
|
427
|
+
>>> from sknetwork.data import watts_strogatz
|
|
428
|
+
>>> adjacency = watts_strogatz(30, 4, 0.02)
|
|
429
|
+
>>> adjacency.shape
|
|
430
|
+
(30, 30)
|
|
431
|
+
|
|
432
|
+
References
|
|
433
|
+
----------
|
|
434
|
+
Watts, D., Strogatz, S. (1998). Collective dynamics of small-world networks, Nature.
|
|
435
|
+
"""
|
|
436
|
+
random_state = check_random_state(seed)
|
|
437
|
+
edges = np.array([(i, (i + j + 1) % n) for i in range(n) for j in range(degree // 2)])
|
|
438
|
+
row, col = edges[:, 0], edges[:, 1]
|
|
439
|
+
adjacency = sparse.coo_matrix((np.ones_like(row, int), (row, col)), shape=(n, n))
|
|
440
|
+
adjacency = sparse.lil_matrix(adjacency + adjacency.T)
|
|
441
|
+
nodes = np.arange(n)
|
|
442
|
+
for i in range(n):
|
|
443
|
+
neighbors = adjacency.rows[i]
|
|
444
|
+
candidates = list(set(nodes) - set(neighbors) - {i})
|
|
445
|
+
for j in neighbors:
|
|
446
|
+
if random_state.random() < prob:
|
|
447
|
+
node = random_state.choice(candidates)
|
|
448
|
+
adjacency[i, node] = 1
|
|
449
|
+
adjacency[node, i] = 1
|
|
450
|
+
adjacency[i, j] = 0
|
|
451
|
+
adjacency[j, i] = 0
|
|
452
|
+
adjacency = sparse.csr_matrix(adjacency, shape=adjacency.shape)
|
|
453
|
+
if metadata:
|
|
454
|
+
graph = Dataset()
|
|
455
|
+
graph.adjacency = adjacency
|
|
456
|
+
graph.position = cyclic_position(n)
|
|
457
|
+
return graph
|
|
458
|
+
else:
|
|
459
|
+
return adjacency
|