scikit-network 0.33.4__cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.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.
Files changed (229) hide show
  1. scikit_network-0.33.4.dist-info/METADATA +122 -0
  2. scikit_network-0.33.4.dist-info/RECORD +229 -0
  3. scikit_network-0.33.4.dist-info/WHEEL +6 -0
  4. scikit_network-0.33.4.dist-info/licenses/AUTHORS.rst +43 -0
  5. scikit_network-0.33.4.dist-info/licenses/LICENSE +34 -0
  6. scikit_network-0.33.4.dist-info/top_level.txt +1 -0
  7. scikit_network.libs/libgomp-a34b3233.so.1.0.0 +0 -0
  8. sknetwork/__init__.py +21 -0
  9. sknetwork/base.py +67 -0
  10. sknetwork/classification/__init__.py +8 -0
  11. sknetwork/classification/base.py +138 -0
  12. sknetwork/classification/base_rank.py +129 -0
  13. sknetwork/classification/diffusion.py +127 -0
  14. sknetwork/classification/knn.py +131 -0
  15. sknetwork/classification/metrics.py +205 -0
  16. sknetwork/classification/pagerank.py +58 -0
  17. sknetwork/classification/propagation.py +144 -0
  18. sknetwork/classification/tests/__init__.py +1 -0
  19. sknetwork/classification/tests/test_API.py +30 -0
  20. sknetwork/classification/tests/test_diffusion.py +77 -0
  21. sknetwork/classification/tests/test_knn.py +23 -0
  22. sknetwork/classification/tests/test_metrics.py +53 -0
  23. sknetwork/classification/tests/test_pagerank.py +20 -0
  24. sknetwork/classification/tests/test_propagation.py +24 -0
  25. sknetwork/classification/vote.cpp +27593 -0
  26. sknetwork/classification/vote.cpython-312-x86_64-linux-gnu.so +0 -0
  27. sknetwork/classification/vote.pyx +56 -0
  28. sknetwork/clustering/__init__.py +8 -0
  29. sknetwork/clustering/base.py +168 -0
  30. sknetwork/clustering/kcenters.py +251 -0
  31. sknetwork/clustering/leiden.py +238 -0
  32. sknetwork/clustering/leiden_core.cpp +31928 -0
  33. sknetwork/clustering/leiden_core.cpython-312-x86_64-linux-gnu.so +0 -0
  34. sknetwork/clustering/leiden_core.pyx +124 -0
  35. sknetwork/clustering/louvain.py +282 -0
  36. sknetwork/clustering/louvain_core.cpp +31573 -0
  37. sknetwork/clustering/louvain_core.cpython-312-x86_64-linux-gnu.so +0 -0
  38. sknetwork/clustering/louvain_core.pyx +124 -0
  39. sknetwork/clustering/metrics.py +91 -0
  40. sknetwork/clustering/postprocess.py +66 -0
  41. sknetwork/clustering/propagation_clustering.py +100 -0
  42. sknetwork/clustering/tests/__init__.py +1 -0
  43. sknetwork/clustering/tests/test_API.py +38 -0
  44. sknetwork/clustering/tests/test_kcenters.py +60 -0
  45. sknetwork/clustering/tests/test_leiden.py +34 -0
  46. sknetwork/clustering/tests/test_louvain.py +135 -0
  47. sknetwork/clustering/tests/test_metrics.py +50 -0
  48. sknetwork/clustering/tests/test_postprocess.py +39 -0
  49. sknetwork/data/__init__.py +6 -0
  50. sknetwork/data/base.py +33 -0
  51. sknetwork/data/load.py +292 -0
  52. sknetwork/data/models.py +459 -0
  53. sknetwork/data/parse.py +644 -0
  54. sknetwork/data/test_graphs.py +93 -0
  55. sknetwork/data/tests/__init__.py +1 -0
  56. sknetwork/data/tests/test_API.py +30 -0
  57. sknetwork/data/tests/test_base.py +14 -0
  58. sknetwork/data/tests/test_load.py +61 -0
  59. sknetwork/data/tests/test_models.py +52 -0
  60. sknetwork/data/tests/test_parse.py +250 -0
  61. sknetwork/data/tests/test_test_graphs.py +29 -0
  62. sknetwork/data/tests/test_toy_graphs.py +68 -0
  63. sknetwork/data/timeout.py +38 -0
  64. sknetwork/data/toy_graphs.py +611 -0
  65. sknetwork/embedding/__init__.py +8 -0
  66. sknetwork/embedding/base.py +90 -0
  67. sknetwork/embedding/force_atlas.py +198 -0
  68. sknetwork/embedding/louvain_embedding.py +142 -0
  69. sknetwork/embedding/random_projection.py +131 -0
  70. sknetwork/embedding/spectral.py +137 -0
  71. sknetwork/embedding/spring.py +198 -0
  72. sknetwork/embedding/svd.py +351 -0
  73. sknetwork/embedding/tests/__init__.py +1 -0
  74. sknetwork/embedding/tests/test_API.py +49 -0
  75. sknetwork/embedding/tests/test_force_atlas.py +35 -0
  76. sknetwork/embedding/tests/test_louvain_embedding.py +33 -0
  77. sknetwork/embedding/tests/test_random_projection.py +28 -0
  78. sknetwork/embedding/tests/test_spectral.py +81 -0
  79. sknetwork/embedding/tests/test_spring.py +50 -0
  80. sknetwork/embedding/tests/test_svd.py +43 -0
  81. sknetwork/gnn/__init__.py +10 -0
  82. sknetwork/gnn/activation.py +117 -0
  83. sknetwork/gnn/base.py +181 -0
  84. sknetwork/gnn/base_activation.py +90 -0
  85. sknetwork/gnn/base_layer.py +109 -0
  86. sknetwork/gnn/gnn_classifier.py +305 -0
  87. sknetwork/gnn/layer.py +153 -0
  88. sknetwork/gnn/loss.py +180 -0
  89. sknetwork/gnn/neighbor_sampler.py +65 -0
  90. sknetwork/gnn/optimizer.py +164 -0
  91. sknetwork/gnn/tests/__init__.py +1 -0
  92. sknetwork/gnn/tests/test_activation.py +56 -0
  93. sknetwork/gnn/tests/test_base.py +75 -0
  94. sknetwork/gnn/tests/test_base_layer.py +37 -0
  95. sknetwork/gnn/tests/test_gnn_classifier.py +130 -0
  96. sknetwork/gnn/tests/test_layers.py +80 -0
  97. sknetwork/gnn/tests/test_loss.py +33 -0
  98. sknetwork/gnn/tests/test_neigh_sampler.py +23 -0
  99. sknetwork/gnn/tests/test_optimizer.py +43 -0
  100. sknetwork/gnn/tests/test_utils.py +41 -0
  101. sknetwork/gnn/utils.py +127 -0
  102. sknetwork/hierarchy/__init__.py +6 -0
  103. sknetwork/hierarchy/base.py +90 -0
  104. sknetwork/hierarchy/louvain_hierarchy.py +260 -0
  105. sknetwork/hierarchy/metrics.py +234 -0
  106. sknetwork/hierarchy/paris.cpp +37877 -0
  107. sknetwork/hierarchy/paris.cpython-312-x86_64-linux-gnu.so +0 -0
  108. sknetwork/hierarchy/paris.pyx +310 -0
  109. sknetwork/hierarchy/postprocess.py +350 -0
  110. sknetwork/hierarchy/tests/__init__.py +1 -0
  111. sknetwork/hierarchy/tests/test_API.py +24 -0
  112. sknetwork/hierarchy/tests/test_algos.py +34 -0
  113. sknetwork/hierarchy/tests/test_metrics.py +62 -0
  114. sknetwork/hierarchy/tests/test_postprocess.py +57 -0
  115. sknetwork/linalg/__init__.py +9 -0
  116. sknetwork/linalg/basics.py +37 -0
  117. sknetwork/linalg/diteration.cpp +27409 -0
  118. sknetwork/linalg/diteration.cpython-312-x86_64-linux-gnu.so +0 -0
  119. sknetwork/linalg/diteration.pyx +47 -0
  120. sknetwork/linalg/eig_solver.py +93 -0
  121. sknetwork/linalg/laplacian.py +15 -0
  122. sknetwork/linalg/normalizer.py +86 -0
  123. sknetwork/linalg/operators.py +225 -0
  124. sknetwork/linalg/polynome.py +76 -0
  125. sknetwork/linalg/ppr_solver.py +170 -0
  126. sknetwork/linalg/push.cpp +31081 -0
  127. sknetwork/linalg/push.cpython-312-x86_64-linux-gnu.so +0 -0
  128. sknetwork/linalg/push.pyx +71 -0
  129. sknetwork/linalg/sparse_lowrank.py +142 -0
  130. sknetwork/linalg/svd_solver.py +91 -0
  131. sknetwork/linalg/tests/__init__.py +1 -0
  132. sknetwork/linalg/tests/test_eig.py +44 -0
  133. sknetwork/linalg/tests/test_laplacian.py +18 -0
  134. sknetwork/linalg/tests/test_normalization.py +34 -0
  135. sknetwork/linalg/tests/test_operators.py +66 -0
  136. sknetwork/linalg/tests/test_polynome.py +38 -0
  137. sknetwork/linalg/tests/test_ppr.py +50 -0
  138. sknetwork/linalg/tests/test_sparse_lowrank.py +61 -0
  139. sknetwork/linalg/tests/test_svd.py +38 -0
  140. sknetwork/linkpred/__init__.py +2 -0
  141. sknetwork/linkpred/base.py +46 -0
  142. sknetwork/linkpred/nn.py +126 -0
  143. sknetwork/linkpred/tests/__init__.py +1 -0
  144. sknetwork/linkpred/tests/test_nn.py +26 -0
  145. sknetwork/log.py +19 -0
  146. sknetwork/path/__init__.py +5 -0
  147. sknetwork/path/dag.py +54 -0
  148. sknetwork/path/distances.py +98 -0
  149. sknetwork/path/search.py +31 -0
  150. sknetwork/path/shortest_path.py +61 -0
  151. sknetwork/path/tests/__init__.py +1 -0
  152. sknetwork/path/tests/test_dag.py +37 -0
  153. sknetwork/path/tests/test_distances.py +62 -0
  154. sknetwork/path/tests/test_search.py +40 -0
  155. sknetwork/path/tests/test_shortest_path.py +40 -0
  156. sknetwork/ranking/__init__.py +8 -0
  157. sknetwork/ranking/base.py +57 -0
  158. sknetwork/ranking/betweenness.cpp +9716 -0
  159. sknetwork/ranking/betweenness.cpython-312-x86_64-linux-gnu.so +0 -0
  160. sknetwork/ranking/betweenness.pyx +97 -0
  161. sknetwork/ranking/closeness.py +92 -0
  162. sknetwork/ranking/hits.py +90 -0
  163. sknetwork/ranking/katz.py +79 -0
  164. sknetwork/ranking/pagerank.py +106 -0
  165. sknetwork/ranking/postprocess.py +37 -0
  166. sknetwork/ranking/tests/__init__.py +1 -0
  167. sknetwork/ranking/tests/test_API.py +32 -0
  168. sknetwork/ranking/tests/test_betweenness.py +38 -0
  169. sknetwork/ranking/tests/test_closeness.py +30 -0
  170. sknetwork/ranking/tests/test_hits.py +20 -0
  171. sknetwork/ranking/tests/test_pagerank.py +62 -0
  172. sknetwork/ranking/tests/test_postprocess.py +26 -0
  173. sknetwork/regression/__init__.py +4 -0
  174. sknetwork/regression/base.py +57 -0
  175. sknetwork/regression/diffusion.py +204 -0
  176. sknetwork/regression/tests/__init__.py +1 -0
  177. sknetwork/regression/tests/test_API.py +32 -0
  178. sknetwork/regression/tests/test_diffusion.py +56 -0
  179. sknetwork/sknetwork.py +3 -0
  180. sknetwork/test_base.py +35 -0
  181. sknetwork/test_log.py +15 -0
  182. sknetwork/topology/__init__.py +8 -0
  183. sknetwork/topology/cliques.cpp +32574 -0
  184. sknetwork/topology/cliques.cpython-312-x86_64-linux-gnu.so +0 -0
  185. sknetwork/topology/cliques.pyx +149 -0
  186. sknetwork/topology/core.cpp +30660 -0
  187. sknetwork/topology/core.cpython-312-x86_64-linux-gnu.so +0 -0
  188. sknetwork/topology/core.pyx +90 -0
  189. sknetwork/topology/cycles.py +243 -0
  190. sknetwork/topology/minheap.cpp +27341 -0
  191. sknetwork/topology/minheap.cpython-312-x86_64-linux-gnu.so +0 -0
  192. sknetwork/topology/minheap.pxd +20 -0
  193. sknetwork/topology/minheap.pyx +109 -0
  194. sknetwork/topology/structure.py +194 -0
  195. sknetwork/topology/tests/__init__.py +1 -0
  196. sknetwork/topology/tests/test_cliques.py +28 -0
  197. sknetwork/topology/tests/test_core.py +19 -0
  198. sknetwork/topology/tests/test_cycles.py +65 -0
  199. sknetwork/topology/tests/test_structure.py +85 -0
  200. sknetwork/topology/tests/test_triangles.py +38 -0
  201. sknetwork/topology/tests/test_wl.py +72 -0
  202. sknetwork/topology/triangles.cpp +8903 -0
  203. sknetwork/topology/triangles.cpython-312-x86_64-linux-gnu.so +0 -0
  204. sknetwork/topology/triangles.pyx +151 -0
  205. sknetwork/topology/weisfeiler_lehman.py +133 -0
  206. sknetwork/topology/weisfeiler_lehman_core.cpp +27644 -0
  207. sknetwork/topology/weisfeiler_lehman_core.cpython-312-x86_64-linux-gnu.so +0 -0
  208. sknetwork/topology/weisfeiler_lehman_core.pyx +114 -0
  209. sknetwork/utils/__init__.py +7 -0
  210. sknetwork/utils/check.py +355 -0
  211. sknetwork/utils/format.py +221 -0
  212. sknetwork/utils/membership.py +82 -0
  213. sknetwork/utils/neighbors.py +115 -0
  214. sknetwork/utils/tests/__init__.py +1 -0
  215. sknetwork/utils/tests/test_check.py +190 -0
  216. sknetwork/utils/tests/test_format.py +63 -0
  217. sknetwork/utils/tests/test_membership.py +24 -0
  218. sknetwork/utils/tests/test_neighbors.py +41 -0
  219. sknetwork/utils/tests/test_tfidf.py +18 -0
  220. sknetwork/utils/tests/test_values.py +66 -0
  221. sknetwork/utils/tfidf.py +37 -0
  222. sknetwork/utils/values.py +76 -0
  223. sknetwork/visualization/__init__.py +4 -0
  224. sknetwork/visualization/colors.py +34 -0
  225. sknetwork/visualization/dendrograms.py +277 -0
  226. sknetwork/visualization/graphs.py +1039 -0
  227. sknetwork/visualization/tests/__init__.py +1 -0
  228. sknetwork/visualization/tests/test_dendrograms.py +53 -0
  229. sknetwork/visualization/tests/test_graphs.py +176 -0
@@ -0,0 +1,26 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for postprocessing"""
4
+
5
+ import unittest
6
+
7
+ import numpy as np
8
+
9
+ from sknetwork.ranking.postprocess import top_k
10
+
11
+
12
+ class TestPostprocessing(unittest.TestCase):
13
+
14
+ def test_top_k(self):
15
+ scores = np.arange(10)
16
+ index = top_k(scores, 3)
17
+ self.assertTrue(set(index) == {7, 8, 9})
18
+ index = top_k(scores, 10)
19
+ self.assertTrue(len(index) == 10)
20
+ index = top_k(scores, 20)
21
+ self.assertTrue(len(index) == 10)
22
+ scores = [3, 1, 6, 2]
23
+ index = top_k(scores, 2)
24
+ self.assertTrue(set(index) == {0, 2})
25
+ index = top_k(scores, 2, sort=True)
26
+ self.assertTrue(list(index) == [2, 0])
@@ -0,0 +1,4 @@
1
+ """regression module"""
2
+ from sknetwork.regression.base import BaseRegressor
3
+ from sknetwork.regression.diffusion import Diffusion, Dirichlet
4
+
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on April 2022
5
+ @author: Thomas Bonald <bonald@enst.fr>
6
+ """
7
+ from abc import ABC
8
+
9
+ import numpy as np
10
+
11
+ from sknetwork.base import Algorithm
12
+
13
+
14
+ class BaseRegressor(Algorithm, ABC):
15
+ """Base class for regression algorithms.
16
+
17
+ Attributes
18
+ ----------
19
+ values\_ : np.ndarray
20
+ Value of each node.
21
+ """
22
+ def __init__(self):
23
+ self.values_ = None
24
+
25
+ def predict(self, columns: bool = False) -> np.ndarray:
26
+ """Return the values predicted by the algorithm.
27
+
28
+ Parameters
29
+ ----------
30
+ columns : bool
31
+ If ``True``, return the prediction for columns.
32
+
33
+ Returns
34
+ -------
35
+ values : np.ndarray
36
+ Values.
37
+ """
38
+ if columns:
39
+ return self.values_col_
40
+ return self.values_
41
+
42
+ def fit_predict(self, *args, **kwargs) -> np.ndarray:
43
+ """Fit algorithm to data and return the values. Same parameters as the ``fit`` method.
44
+
45
+ Returns
46
+ -------
47
+ values : np.ndarray
48
+ Values.
49
+ """
50
+ self.fit(*args, **kwargs)
51
+ return self.values_
52
+
53
+ def _split_vars(self, shape):
54
+ n_row = shape[0]
55
+ self.values_row_ = self.values_[:n_row]
56
+ self.values_col_ = self.values_[n_row:]
57
+ self.values_ = self.values_row_
@@ -0,0 +1,204 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created in July 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ @author: Thomas Bonald <thomas.bonald@telecom-paris.fr>
7
+ """
8
+ from typing import Union, Optional, Tuple
9
+
10
+ import numpy as np
11
+ from scipy import sparse
12
+
13
+ from sknetwork.linalg.normalizer import normalize
14
+ from sknetwork.regression.base import BaseRegressor
15
+ from sknetwork.utils import get_adjacency_values, get_degrees
16
+
17
+
18
+ def init_temperatures(seeds: np.ndarray, init: Optional[float]) -> Tuple[np.ndarray, np.ndarray]:
19
+ """Init temperatures."""
20
+ n = len(seeds)
21
+ border = (seeds >= 0)
22
+ if init is None:
23
+ temperatures = seeds[border].mean() * np.ones(n)
24
+ else:
25
+ temperatures = init * np.ones(n)
26
+ temperatures[border] = seeds[border]
27
+ return temperatures, border
28
+
29
+
30
+ class Diffusion(BaseRegressor):
31
+ """Regression by diffusion along the edges, given the temperatures of some seed nodes (heat equation).
32
+
33
+ The row vector of tempreatures :math:`T` evolves like:
34
+
35
+ :math:`T \\gets (1-\\alpha) T + \\alpha PT`
36
+
37
+ where :math:`\\alpha` is the damping factor and :math:`P` is the transition matrix of the random walk in the graph.
38
+
39
+ All values are updated, including those of seed nodes (free diffusion).
40
+ See ``Dirichlet`` for diffusion with boundary constraints.
41
+
42
+ Parameters
43
+ ----------
44
+ n_iter : int
45
+ Number of iterations of the diffusion (must be positive).
46
+ damping_factor : float
47
+ Damping factor.
48
+
49
+ Attributes
50
+ ----------
51
+ values\_ : np.ndarray
52
+ Value of each node (= temperature).
53
+
54
+ Example
55
+ -------
56
+ >>> from sknetwork.data import house
57
+ >>> diffusion = Diffusion(n_iter=1)
58
+ >>> adjacency = house()
59
+ >>> values = {0: 1, 2: 0}
60
+ >>> values_pred = diffusion.fit_predict(adjacency, values)
61
+ >>> np.round(values_pred, 1)
62
+ array([0.8, 0.5, 0.2, 0.4, 0.6])
63
+
64
+ References
65
+ ----------
66
+ Chung, F. (2007). The heat kernel as the pagerank of a graph. Proceedings of the National Academy of Sciences.
67
+ """
68
+ def __init__(self, n_iter: int = 3, damping_factor: float = 0.5):
69
+ super(Diffusion, self).__init__()
70
+
71
+ if n_iter <= 0:
72
+ raise ValueError('The number of iterations must be positive.')
73
+ else:
74
+ self.n_iter = n_iter
75
+ self.damping_factor = damping_factor
76
+ self.bipartite = None
77
+
78
+ def fit(self, input_matrix: Union[sparse.csr_matrix, np.ndarray],
79
+ values: Optional[Union[dict, list, np.ndarray]] = None,
80
+ values_row: Optional[Union[dict, list, np.ndarray]] = None,
81
+ values_col: Optional[Union[dict, list, np.ndarray]] = None, init: Optional[float] = None,
82
+ force_bipartite: bool = False) -> 'Diffusion':
83
+ """Compute the diffusion (temperatures at equilibrium).
84
+
85
+ Parameters
86
+ ----------
87
+ input_matrix :
88
+ Adjacency matrix or biadjacency matrix of the graph.
89
+ values :
90
+ Temperatures of nodes in initial state (dictionary or vector). Negative temperatures ignored.
91
+ values_row, values_col :
92
+ Temperatures of rows and columns for bipartite graphs. Negative temperatures ignored.
93
+ init :
94
+ Temperature of nodes in initial state.
95
+ If ``None``, use the average temperature of seed nodes (default).
96
+ force_bipartite :
97
+ If ``True``, consider the input matrix as a biadjacency matrix (default = ``False``).
98
+
99
+ Returns
100
+ -------
101
+ self: :class:`Diffusion`
102
+ """
103
+ adjacency, values, self.bipartite = get_adjacency_values(input_matrix, force_bipartite=force_bipartite,
104
+ values=values,
105
+ values_row=values_row,
106
+ values_col=values_col)
107
+ values, _ = init_temperatures(values, init)
108
+ diffusion = normalize(adjacency.T.tocsr())
109
+ degrees = get_degrees(diffusion)
110
+ diag = sparse.diags((degrees == 0).astype(int)).tocsr()
111
+ diffusion += diag
112
+
113
+ diffusion = (1 - self.damping_factor) * sparse.identity(len(degrees)).tocsr() + self.damping_factor * diffusion
114
+
115
+ for i in range(self.n_iter):
116
+ values = diffusion.dot(values)
117
+
118
+ self.values_ = values
119
+ if self.bipartite:
120
+ self._split_vars(input_matrix.shape)
121
+
122
+ return self
123
+
124
+
125
+ class Dirichlet(BaseRegressor):
126
+ """Regression by the Dirichlet problem (heat diffusion with boundary constraints).
127
+
128
+ The temperatures of some seed nodes are fixed. The temperatures of other nodes are computed.
129
+
130
+ Parameters
131
+ ----------
132
+ n_iter : int
133
+ Number of iterations of the diffusion (must be positive).
134
+
135
+ Attributes
136
+ ----------
137
+ values\_ : np.ndarray
138
+ Value of each node (= temperature).
139
+
140
+ Example
141
+ -------
142
+ >>> from sknetwork.regression import Dirichlet
143
+ >>> from sknetwork.data import house
144
+ >>> dirichlet = Dirichlet()
145
+ >>> adjacency = house()
146
+ >>> values = {0: 1, 2: 0}
147
+ >>> values_pred = dirichlet.fit_predict(adjacency, values)
148
+ >>> np.round(values_pred, 2)
149
+ array([1. , 0.54, 0. , 0.31, 0.62])
150
+
151
+ References
152
+ ----------
153
+ Chung, F. (2007). The heat kernel as the pagerank of a graph. Proceedings of the National Academy of Sciences.
154
+ """
155
+ def __init__(self, n_iter: int = 10):
156
+ super(Dirichlet, self).__init__()
157
+
158
+ if n_iter <= 0:
159
+ raise ValueError('The number of iterations must be positive.')
160
+ else:
161
+ self.n_iter = n_iter
162
+ self.bipartite = None
163
+
164
+ def fit(self, input_matrix: Union[sparse.csr_matrix, np.ndarray],
165
+ values: Optional[Union[dict, list, np.ndarray]] = None,
166
+ values_row: Optional[Union[dict, list, np.ndarray]] = None,
167
+ values_col: Optional[Union[dict, list, np.ndarray]] = None, init: Optional[float] = None,
168
+ force_bipartite: bool = False) -> 'Dirichlet':
169
+ """Compute the solution to the Dirichlet problem (temperatures at equilibrium).
170
+
171
+ Parameters
172
+ ----------
173
+ input_matrix :
174
+ Adjacency matrix or biadjacency matrix of the graph.
175
+ values :
176
+ Temperatures of nodes (dictionary or vector). Negative temperatures ignored.
177
+ values_row, values_col :
178
+ Temperatures of rows and columns for bipartite graphs. Negative temperatures ignored.
179
+ init :
180
+ Temperature of nodes in initial state.
181
+ If ``None``, use the average temperature of seed nodes (default).
182
+ force_bipartite :
183
+ If ``True``, consider the input matrix as a biadjacency matrix (default = ``False``).
184
+
185
+ Returns
186
+ -------
187
+ self: :class:`Dirichlet`
188
+ """
189
+ adjacency, values, self.bipartite = get_adjacency_values(input_matrix, force_bipartite=force_bipartite,
190
+ values=values,
191
+ values_row=values_row,
192
+ values_col=values_col)
193
+ temperatures, border = init_temperatures(values, init)
194
+ values = temperatures.copy()
195
+ diffusion = normalize(adjacency)
196
+ for i in range(self.n_iter):
197
+ values = diffusion.dot(values)
198
+ values[border] = temperatures[border]
199
+
200
+ self.values_ = values
201
+ if self.bipartite:
202
+ self._split_vars(input_matrix.shape)
203
+
204
+ return self
@@ -0,0 +1 @@
1
+ """tests for regression"""
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for regression API"""
4
+ import unittest
5
+
6
+ from sknetwork.data.test_graphs import test_bigraph, test_graph, test_digraph
7
+ from sknetwork.regression import *
8
+
9
+
10
+ class TestAPI(unittest.TestCase):
11
+
12
+ def test_basic(self):
13
+ methods = [Diffusion(), Dirichlet()]
14
+ for adjacency in [test_graph(), test_digraph()]:
15
+ n = adjacency.shape[0]
16
+ for method in methods:
17
+ score = method.fit_predict(adjacency)
18
+ self.assertEqual(score.shape, (n, ))
19
+ self.assertTrue(min(score) >= 0)
20
+
21
+ def test_bipartite(self):
22
+ biadjacency = test_bigraph()
23
+ n_row, n_col = biadjacency.shape
24
+
25
+ methods = [Diffusion(), Dirichlet()]
26
+ for method in methods:
27
+ method.fit(biadjacency)
28
+ values_row = method.values_row_
29
+ values_col = method.values_col_
30
+
31
+ self.assertEqual(values_row.shape, (n_row,))
32
+ self.assertEqual(values_col.shape, (n_col,))
@@ -0,0 +1,56 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for diffusion.py"""
4
+
5
+ import unittest
6
+
7
+ from sknetwork.data.test_graphs import *
8
+ from sknetwork.regression import Diffusion, Dirichlet
9
+
10
+
11
+ # noinspection DuplicatedCode
12
+ class TestDiffusion(unittest.TestCase):
13
+
14
+ def setUp(self):
15
+ self.algos = [Diffusion(), Dirichlet()]
16
+
17
+ def test_predict(self):
18
+ adjacency = test_graph()
19
+ for algo in self.algos:
20
+ values = algo.fit_predict(adjacency, {0: 0, 1: 1, 2: 0.5})
21
+ values_ = algo.predict()
22
+ self.assertAlmostEqual(np.linalg.norm(values - values_), 0)
23
+
24
+ def test_no_iter(self):
25
+ with self.assertRaises(ValueError):
26
+ Diffusion(n_iter=-1)
27
+
28
+ def test_single_node_graph(self):
29
+ for algo in self.algos:
30
+ algo.fit(sparse.identity(1, format='csr'), {0: 1})
31
+ self.assertEqual(algo.values_, [1])
32
+
33
+ def test_range(self):
34
+ for adjacency in [test_graph(), test_digraph()]:
35
+ for algo in self.algos:
36
+ values = algo.fit_predict(adjacency, {0: 0, 1: 1, 2: 0.5})
37
+ self.assertTrue(np.all(values <= 1) and np.all(values >= 0))
38
+
39
+ biadjacency = test_bigraph()
40
+ for algo in [Diffusion(), Dirichlet()]:
41
+ values = algo.fit_predict(biadjacency, values_row={0: 1})
42
+ self.assertTrue(np.all(values <= 1) and np.all(values >= 0))
43
+ values = algo.fit_predict(biadjacency, values_row={0: 0.1}, values_col={1: 2}, init=0.3)
44
+ self.assertTrue(np.all(values <= 2) and np.all(values >= 0.1))
45
+ self.assertAlmostEqual(np.linalg.norm(algo.values_col_ - algo.predict(columns=True)), 0)
46
+
47
+ def test_initial_state(self):
48
+ for adjacency in [test_graph(), test_digraph()]:
49
+ for algo in self.algos:
50
+ values = algo.fit_predict(adjacency, {0: 0, 1: 1, 2: 0.5}, 0.3)
51
+ self.assertTrue(np.all(values <= 1) and np.all(values >= 0))
52
+
53
+ def test_n_iter(self):
54
+ with self.assertRaises(ValueError):
55
+ Dirichlet(n_iter=0)
56
+
sknetwork/sknetwork.py ADDED
@@ -0,0 +1,3 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """Main module."""
sknetwork/test_base.py ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for base.py"""
4
+ import unittest
5
+
6
+ from sknetwork.base import Algorithm
7
+
8
+
9
+ class TestBase(unittest.TestCase):
10
+
11
+ def setUp(self):
12
+ class NewAlgo(Algorithm):
13
+ """Docstring"""
14
+ def __init__(self, param: int, name: str):
15
+ self.param = param
16
+ self.name = name
17
+
18
+ def fit(self):
19
+ """Docstring"""
20
+ pass
21
+ self.algo = NewAlgo(1, 'abc')
22
+
23
+ def test_repr(self):
24
+ self.assertEqual(repr(self.algo), "NewAlgo(param=1, name='abc')")
25
+
26
+ def test_get_params(self):
27
+ self.assertEqual(len(self.algo.get_params()), 2)
28
+
29
+ def test_set_params(self):
30
+ self.algo.set_params({'param': 3})
31
+ self.assertEqual(self.algo.param, 3)
32
+
33
+ def test_fit(self):
34
+ stub = Algorithm()
35
+ self.assertRaises(NotImplementedError, stub.fit, None)
sknetwork/test_log.py ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for verbose.py"""
4
+
5
+ import unittest
6
+
7
+ from sknetwork.log import Log
8
+
9
+
10
+ class TestVerbose(unittest.TestCase):
11
+
12
+ def test_prints(self):
13
+ logger = Log(verbose=True)
14
+ logger.print_log('Hello', 42)
15
+ self.assertEqual(str(logger.log), 'Hello 42\n')
@@ -0,0 +1,8 @@
1
+ """Module on topology."""
2
+ from sknetwork.topology.cliques import count_cliques
3
+ from sknetwork.topology.core import get_core_decomposition
4
+ from sknetwork.topology.triangles import count_triangles, get_clustering_coefficient
5
+ from sknetwork.topology.structure import is_connected, is_bipartite, is_symmetric, get_connected_components, \
6
+ get_largest_connected_component
7
+ from sknetwork.topology.cycles import is_acyclic, get_cycles, break_cycles
8
+ from sknetwork.topology.weisfeiler_lehman import color_weisfeiler_lehman, are_isomorphic