scikit-network 0.28.3__cp39-cp39-macosx_12_0_arm64.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.

Files changed (240) hide show
  1. scikit_network-0.28.3.dist-info/AUTHORS.rst +41 -0
  2. scikit_network-0.28.3.dist-info/LICENSE +34 -0
  3. scikit_network-0.28.3.dist-info/METADATA +457 -0
  4. scikit_network-0.28.3.dist-info/RECORD +240 -0
  5. scikit_network-0.28.3.dist-info/WHEEL +5 -0
  6. scikit_network-0.28.3.dist-info/top_level.txt +1 -0
  7. sknetwork/__init__.py +21 -0
  8. sknetwork/classification/__init__.py +8 -0
  9. sknetwork/classification/base.py +84 -0
  10. sknetwork/classification/base_rank.py +143 -0
  11. sknetwork/classification/diffusion.py +134 -0
  12. sknetwork/classification/knn.py +162 -0
  13. sknetwork/classification/metrics.py +205 -0
  14. sknetwork/classification/pagerank.py +66 -0
  15. sknetwork/classification/propagation.py +152 -0
  16. sknetwork/classification/tests/__init__.py +1 -0
  17. sknetwork/classification/tests/test_API.py +35 -0
  18. sknetwork/classification/tests/test_diffusion.py +37 -0
  19. sknetwork/classification/tests/test_knn.py +24 -0
  20. sknetwork/classification/tests/test_metrics.py +53 -0
  21. sknetwork/classification/tests/test_pagerank.py +20 -0
  22. sknetwork/classification/tests/test_propagation.py +24 -0
  23. sknetwork/classification/vote.cpython-39-darwin.so +0 -0
  24. sknetwork/classification/vote.pyx +58 -0
  25. sknetwork/clustering/__init__.py +7 -0
  26. sknetwork/clustering/base.py +102 -0
  27. sknetwork/clustering/kmeans.py +142 -0
  28. sknetwork/clustering/louvain.py +255 -0
  29. sknetwork/clustering/louvain_core.cpython-39-darwin.so +0 -0
  30. sknetwork/clustering/louvain_core.pyx +134 -0
  31. sknetwork/clustering/metrics.py +91 -0
  32. sknetwork/clustering/postprocess.py +66 -0
  33. sknetwork/clustering/propagation_clustering.py +108 -0
  34. sknetwork/clustering/tests/__init__.py +1 -0
  35. sknetwork/clustering/tests/test_API.py +37 -0
  36. sknetwork/clustering/tests/test_kmeans.py +47 -0
  37. sknetwork/clustering/tests/test_louvain.py +104 -0
  38. sknetwork/clustering/tests/test_metrics.py +50 -0
  39. sknetwork/clustering/tests/test_post_processing.py +23 -0
  40. sknetwork/clustering/tests/test_postprocess.py +39 -0
  41. sknetwork/data/__init__.py +5 -0
  42. sknetwork/data/load.py +408 -0
  43. sknetwork/data/models.py +459 -0
  44. sknetwork/data/parse.py +621 -0
  45. sknetwork/data/test_graphs.py +84 -0
  46. sknetwork/data/tests/__init__.py +1 -0
  47. sknetwork/data/tests/test_API.py +30 -0
  48. sknetwork/data/tests/test_load.py +95 -0
  49. sknetwork/data/tests/test_models.py +52 -0
  50. sknetwork/data/tests/test_parse.py +253 -0
  51. sknetwork/data/tests/test_test_graphs.py +30 -0
  52. sknetwork/data/tests/test_toy_graphs.py +68 -0
  53. sknetwork/data/toy_graphs.py +619 -0
  54. sknetwork/embedding/__init__.py +10 -0
  55. sknetwork/embedding/base.py +90 -0
  56. sknetwork/embedding/force_atlas.py +197 -0
  57. sknetwork/embedding/louvain_embedding.py +174 -0
  58. sknetwork/embedding/louvain_hierarchy.py +142 -0
  59. sknetwork/embedding/metrics.py +66 -0
  60. sknetwork/embedding/random_projection.py +133 -0
  61. sknetwork/embedding/spectral.py +214 -0
  62. sknetwork/embedding/spring.py +198 -0
  63. sknetwork/embedding/svd.py +363 -0
  64. sknetwork/embedding/tests/__init__.py +1 -0
  65. sknetwork/embedding/tests/test_API.py +73 -0
  66. sknetwork/embedding/tests/test_force_atlas.py +35 -0
  67. sknetwork/embedding/tests/test_louvain_embedding.py +33 -0
  68. sknetwork/embedding/tests/test_louvain_hierarchy.py +19 -0
  69. sknetwork/embedding/tests/test_metrics.py +29 -0
  70. sknetwork/embedding/tests/test_random_projection.py +28 -0
  71. sknetwork/embedding/tests/test_spectral.py +84 -0
  72. sknetwork/embedding/tests/test_spring.py +50 -0
  73. sknetwork/embedding/tests/test_svd.py +37 -0
  74. sknetwork/flow/__init__.py +3 -0
  75. sknetwork/flow/flow.py +73 -0
  76. sknetwork/flow/tests/__init__.py +1 -0
  77. sknetwork/flow/tests/test_flow.py +17 -0
  78. sknetwork/flow/tests/test_utils.py +69 -0
  79. sknetwork/flow/utils.py +91 -0
  80. sknetwork/gnn/__init__.py +10 -0
  81. sknetwork/gnn/activation.py +117 -0
  82. sknetwork/gnn/base.py +155 -0
  83. sknetwork/gnn/base_activation.py +89 -0
  84. sknetwork/gnn/base_layer.py +109 -0
  85. sknetwork/gnn/gnn_classifier.py +381 -0
  86. sknetwork/gnn/layer.py +153 -0
  87. sknetwork/gnn/layers.py +127 -0
  88. sknetwork/gnn/loss.py +180 -0
  89. sknetwork/gnn/neighbor_sampler.py +65 -0
  90. sknetwork/gnn/optimizer.py +163 -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 +79 -0
  94. sknetwork/gnn/tests/test_base_layer.py +37 -0
  95. sknetwork/gnn/tests/test_gnn_classifier.py +192 -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 +93 -0
  101. sknetwork/gnn/utils.py +219 -0
  102. sknetwork/hierarchy/__init__.py +7 -0
  103. sknetwork/hierarchy/base.py +69 -0
  104. sknetwork/hierarchy/louvain_hierarchy.py +264 -0
  105. sknetwork/hierarchy/metrics.py +234 -0
  106. sknetwork/hierarchy/paris.cpython-39-darwin.so +0 -0
  107. sknetwork/hierarchy/paris.pyx +317 -0
  108. sknetwork/hierarchy/postprocess.py +350 -0
  109. sknetwork/hierarchy/tests/__init__.py +1 -0
  110. sknetwork/hierarchy/tests/test_API.py +25 -0
  111. sknetwork/hierarchy/tests/test_algos.py +29 -0
  112. sknetwork/hierarchy/tests/test_metrics.py +62 -0
  113. sknetwork/hierarchy/tests/test_postprocess.py +57 -0
  114. sknetwork/hierarchy/tests/test_ward.py +25 -0
  115. sknetwork/hierarchy/ward.py +94 -0
  116. sknetwork/linalg/__init__.py +9 -0
  117. sknetwork/linalg/basics.py +37 -0
  118. sknetwork/linalg/diteration.cpython-39-darwin.so +0 -0
  119. sknetwork/linalg/diteration.pyx +49 -0
  120. sknetwork/linalg/eig_solver.py +93 -0
  121. sknetwork/linalg/laplacian.py +15 -0
  122. sknetwork/linalg/normalization.py +66 -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.cpython-39-darwin.so +0 -0
  127. sknetwork/linalg/push.pyx +73 -0
  128. sknetwork/linalg/sparse_lowrank.py +142 -0
  129. sknetwork/linalg/svd_solver.py +91 -0
  130. sknetwork/linalg/tests/__init__.py +1 -0
  131. sknetwork/linalg/tests/test_eig.py +44 -0
  132. sknetwork/linalg/tests/test_laplacian.py +18 -0
  133. sknetwork/linalg/tests/test_normalization.py +38 -0
  134. sknetwork/linalg/tests/test_operators.py +70 -0
  135. sknetwork/linalg/tests/test_polynome.py +38 -0
  136. sknetwork/linalg/tests/test_ppr.py +50 -0
  137. sknetwork/linalg/tests/test_sparse_lowrank.py +61 -0
  138. sknetwork/linalg/tests/test_svd.py +38 -0
  139. sknetwork/linkpred/__init__.py +4 -0
  140. sknetwork/linkpred/base.py +80 -0
  141. sknetwork/linkpred/first_order.py +508 -0
  142. sknetwork/linkpred/first_order_core.cpython-39-darwin.so +0 -0
  143. sknetwork/linkpred/first_order_core.pyx +315 -0
  144. sknetwork/linkpred/postprocessing.py +98 -0
  145. sknetwork/linkpred/tests/__init__.py +1 -0
  146. sknetwork/linkpred/tests/test_API.py +49 -0
  147. sknetwork/linkpred/tests/test_postprocessing.py +21 -0
  148. sknetwork/path/__init__.py +4 -0
  149. sknetwork/path/metrics.py +148 -0
  150. sknetwork/path/search.py +65 -0
  151. sknetwork/path/shortest_path.py +186 -0
  152. sknetwork/path/tests/__init__.py +1 -0
  153. sknetwork/path/tests/test_metrics.py +29 -0
  154. sknetwork/path/tests/test_search.py +25 -0
  155. sknetwork/path/tests/test_shortest_path.py +45 -0
  156. sknetwork/ranking/__init__.py +9 -0
  157. sknetwork/ranking/base.py +56 -0
  158. sknetwork/ranking/betweenness.cpython-39-darwin.so +0 -0
  159. sknetwork/ranking/betweenness.pyx +99 -0
  160. sknetwork/ranking/closeness.py +95 -0
  161. sknetwork/ranking/harmonic.py +82 -0
  162. sknetwork/ranking/hits.py +94 -0
  163. sknetwork/ranking/katz.py +81 -0
  164. sknetwork/ranking/pagerank.py +107 -0
  165. sknetwork/ranking/postprocess.py +25 -0
  166. sknetwork/ranking/tests/__init__.py +1 -0
  167. sknetwork/ranking/tests/test_API.py +34 -0
  168. sknetwork/ranking/tests/test_betweenness.py +38 -0
  169. sknetwork/ranking/tests/test_closeness.py +34 -0
  170. sknetwork/ranking/tests/test_hits.py +20 -0
  171. sknetwork/ranking/tests/test_pagerank.py +69 -0
  172. sknetwork/regression/__init__.py +4 -0
  173. sknetwork/regression/base.py +56 -0
  174. sknetwork/regression/diffusion.py +190 -0
  175. sknetwork/regression/tests/__init__.py +1 -0
  176. sknetwork/regression/tests/test_API.py +34 -0
  177. sknetwork/regression/tests/test_diffusion.py +48 -0
  178. sknetwork/sknetwork.py +3 -0
  179. sknetwork/topology/__init__.py +9 -0
  180. sknetwork/topology/dag.py +74 -0
  181. sknetwork/topology/dag_core.cpython-39-darwin.so +0 -0
  182. sknetwork/topology/dag_core.pyx +38 -0
  183. sknetwork/topology/kcliques.cpython-39-darwin.so +0 -0
  184. sknetwork/topology/kcliques.pyx +193 -0
  185. sknetwork/topology/kcore.cpython-39-darwin.so +0 -0
  186. sknetwork/topology/kcore.pyx +120 -0
  187. sknetwork/topology/structure.py +234 -0
  188. sknetwork/topology/tests/__init__.py +1 -0
  189. sknetwork/topology/tests/test_cliques.py +28 -0
  190. sknetwork/topology/tests/test_cores.py +21 -0
  191. sknetwork/topology/tests/test_dag.py +26 -0
  192. sknetwork/topology/tests/test_structure.py +99 -0
  193. sknetwork/topology/tests/test_triangles.py +42 -0
  194. sknetwork/topology/tests/test_wl_coloring.py +49 -0
  195. sknetwork/topology/tests/test_wl_kernel.py +31 -0
  196. sknetwork/topology/triangles.cpython-39-darwin.so +0 -0
  197. sknetwork/topology/triangles.pyx +166 -0
  198. sknetwork/topology/weisfeiler_lehman.py +163 -0
  199. sknetwork/topology/weisfeiler_lehman_core.cpython-39-darwin.so +0 -0
  200. sknetwork/topology/weisfeiler_lehman_core.pyx +116 -0
  201. sknetwork/utils/__init__.py +40 -0
  202. sknetwork/utils/base.py +35 -0
  203. sknetwork/utils/check.py +354 -0
  204. sknetwork/utils/co_neighbor.py +71 -0
  205. sknetwork/utils/format.py +219 -0
  206. sknetwork/utils/kmeans.py +89 -0
  207. sknetwork/utils/knn.py +166 -0
  208. sknetwork/utils/knn1d.cpython-39-darwin.so +0 -0
  209. sknetwork/utils/knn1d.pyx +80 -0
  210. sknetwork/utils/membership.py +82 -0
  211. sknetwork/utils/minheap.cpython-39-darwin.so +0 -0
  212. sknetwork/utils/minheap.pxd +22 -0
  213. sknetwork/utils/minheap.pyx +111 -0
  214. sknetwork/utils/neighbors.py +115 -0
  215. sknetwork/utils/seeds.py +75 -0
  216. sknetwork/utils/simplex.py +140 -0
  217. sknetwork/utils/tests/__init__.py +1 -0
  218. sknetwork/utils/tests/test_base.py +28 -0
  219. sknetwork/utils/tests/test_bunch.py +16 -0
  220. sknetwork/utils/tests/test_check.py +190 -0
  221. sknetwork/utils/tests/test_co_neighbor.py +43 -0
  222. sknetwork/utils/tests/test_format.py +61 -0
  223. sknetwork/utils/tests/test_kmeans.py +21 -0
  224. sknetwork/utils/tests/test_knn.py +32 -0
  225. sknetwork/utils/tests/test_membership.py +24 -0
  226. sknetwork/utils/tests/test_neighbors.py +41 -0
  227. sknetwork/utils/tests/test_projection_simplex.py +33 -0
  228. sknetwork/utils/tests/test_seeds.py +67 -0
  229. sknetwork/utils/tests/test_verbose.py +15 -0
  230. sknetwork/utils/tests/test_ward.py +20 -0
  231. sknetwork/utils/timeout.py +38 -0
  232. sknetwork/utils/verbose.py +37 -0
  233. sknetwork/utils/ward.py +60 -0
  234. sknetwork/visualization/__init__.py +4 -0
  235. sknetwork/visualization/colors.py +34 -0
  236. sknetwork/visualization/dendrograms.py +229 -0
  237. sknetwork/visualization/graphs.py +819 -0
  238. sknetwork/visualization/tests/__init__.py +1 -0
  239. sknetwork/visualization/tests/test_dendrograms.py +53 -0
  240. sknetwork/visualization/tests/test_graphs.py +167 -0
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on Apr, 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ """
7
+ import warnings
8
+ from typing import Optional, Union
9
+
10
+ import numpy as np
11
+
12
+
13
+ def get_seeds(shape: tuple, seeds: Union[np.ndarray, dict], default_value: float = -1) -> np.ndarray:
14
+ """Get seeds as array."""
15
+ n = shape[0]
16
+ if isinstance(seeds, np.ndarray):
17
+ if len(seeds) != n:
18
+ raise ValueError('Dimensions mismatch between adjacency and seeds vector.')
19
+ else:
20
+ seeds = seeds.astype(float)
21
+ elif isinstance(seeds, dict):
22
+ keys, values = np.array(list(seeds.keys())), np.array(list(seeds.values()))
23
+ if np.min(values) < 0:
24
+ warnings.warn(Warning("Negative values will not be taken into account."))
25
+ seeds = default_value * np.ones(n)
26
+ seeds[keys] = values
27
+ else:
28
+ seeds = np.ones(n)
29
+ return seeds
30
+
31
+
32
+ def stack_seeds(shape: tuple, seeds_row: Optional[Union[np.ndarray, dict]],
33
+ seeds_col: Optional[Union[np.ndarray, dict]] = None, default_value: float = -1) -> np.ndarray:
34
+ """Process seeds for rows and columns and stack the results into a single vector."""
35
+ n_row, n_col = shape
36
+ if seeds_row is None and seeds_col is None:
37
+ seeds_row = np.ones(n_row)
38
+ seeds_col = default_value * np.ones(n_col)
39
+ elif seeds_row is None:
40
+ seeds_row = default_value * np.ones(n_row)
41
+ elif seeds_col is None:
42
+ seeds_col = default_value * np.ones(n_col)
43
+ seeds_row = get_seeds(shape, seeds_row, default_value)
44
+ seeds_col = get_seeds((n_col,), seeds_col, default_value)
45
+ return np.hstack((seeds_row, seeds_col))
46
+
47
+
48
+ def seeds2probs(n: int, seeds: np.ndarray = None) -> np.ndarray:
49
+ """Transform seed values into probability vector.
50
+
51
+ Parameters
52
+ ----------
53
+ n : int
54
+ Number of nodes.
55
+ seeds :
56
+ If ``None``, the uniform distribution is used.
57
+ Otherwise, a non-negative, non-zero vector or a dictionary must be provided.
58
+
59
+ Returns
60
+ -------
61
+ probs: np.ndarray
62
+ A probability vector.
63
+ """
64
+ if seeds is None:
65
+ return np.ones(n) / n
66
+ else:
67
+ seeds = get_seeds((n,), seeds)
68
+ probs = np.zeros_like(seeds, dtype=float)
69
+ ix = (seeds > 0)
70
+ probs[ix] = seeds[ix]
71
+ w: float = probs.sum()
72
+ if w > 0:
73
+ return probs / w
74
+ else:
75
+ raise ValueError('At least one seed must have a positive value.')
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on June 4 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ """
7
+ from typing import Union
8
+
9
+ import numpy as np
10
+ from scipy import sparse
11
+
12
+ from sknetwork.linalg.normalization import normalize
13
+
14
+
15
+ def projection_simplex_array(array: np.ndarray, scale: float = 1) -> np.ndarray:
16
+ """Project each line of the input onto the Euclidean simplex i.e. solve
17
+
18
+ :math:`\\underset{w}{min} ||w - x_i||_2^2` s.t. :math:`\\sum w_j = z, w_j \\ge 0`.
19
+
20
+ Parameters
21
+ ----------
22
+ array: np.ndarray
23
+ Data to project. Either one or two dimensional.
24
+ scale: float
25
+ Scale of the simplex i.e. sums of the projected coefficients.
26
+
27
+ Returns
28
+ -------
29
+ projection : np.ndarray
30
+ Array with the same shape as the input.
31
+
32
+ Example
33
+ -------
34
+ >>> X = np.array([[2, 2], [-0.75, 0.25]])
35
+ >>> projection_simplex_array(X)
36
+ array([[0.5, 0.5],
37
+ [0. , 1. ]])
38
+ """
39
+ if len(array.shape) == 1:
40
+ array = array.reshape(1, array.shape[0])
41
+ n_row, n_col = array.shape
42
+
43
+ sorted_array = -np.sort(-array)
44
+ cumsum_array = np.cumsum(sorted_array, axis=1) - scale
45
+ denom = 1 + np.arange(n_col)
46
+ condition = sorted_array - cumsum_array / denom > 0
47
+ max_index = np.argmax(condition / denom[::-1], axis=1)
48
+ threshold = (cumsum_array / denom)[np.arange(n_row), max_index]
49
+
50
+ return np.maximum(array - threshold[:, np.newaxis], 0)
51
+
52
+
53
+ def projection_simplex_csr(matrix: sparse.csr_matrix, scale: float = 1):
54
+ """Project each line of the input onto the Euclidean simplex i.e. solve
55
+
56
+ :math:`\\underset{w}{min} ||w - x_i||_2^2` s.t. :math:`\\sum w_j = z, w_j \\ge 0`.
57
+
58
+ Parameters
59
+ ----------
60
+ matrix : sparse.csr_matrix
61
+ Matrix whose rows must be projected.
62
+ scale: float
63
+ Scale of the simplex i.e. sums of the projected coefficients.
64
+
65
+ Returns
66
+ -------
67
+ projection : sparse.csr_matrix
68
+ Matrix with the same shape as the input.
69
+
70
+ Examples
71
+ --------
72
+ >>> X = sparse.csr_matrix(np.array([[2, 2], [-0.75, 0.25]]))
73
+ >>> X_proj = projection_simplex_csr(X)
74
+ >>> X_proj.nnz
75
+ 3
76
+ >>> X_proj.toarray()
77
+ array([[0.5, 0.5],
78
+ [0. , 1. ]])
79
+ """
80
+ data = matrix.data
81
+ if data.dtype == bool or (data.min() == data.max()):
82
+ return normalize(matrix, p=1)
83
+
84
+ indptr = matrix.indptr
85
+ new_data = np.zeros_like(data)
86
+
87
+ for i in range(indptr.size-1):
88
+ j1 = indptr[i]
89
+ j2 = indptr[i+1]
90
+ new_data[j1:j2] = projection_simplex_array(data[j1:j2], scale=scale)
91
+
92
+ new_matrix = sparse.csr_matrix((new_data, matrix.indices, indptr), shape=matrix.shape)
93
+ new_matrix.eliminate_zeros()
94
+ return new_matrix
95
+
96
+
97
+ def projection_simplex(x: Union[np.ndarray, sparse.csr_matrix], scale: float = 1.):
98
+ """Project each line of the input onto the Euclidean simplex i.e. solve
99
+
100
+ :math:`\\underset{w}{min} ||w - x_i||_2^2` s.t. :math:`\\sum w_j = z, w_j \\ge 0`.
101
+
102
+ Parameters
103
+ ----------
104
+ x :
105
+ Data to project. Either one or two dimensional. Can be sparse or dense.
106
+ scale : float
107
+ Scale of the simplex i.e. sums of the projected coefficients.
108
+
109
+ Returns
110
+ -------
111
+ projection : np.ndarray or sparse.csr_matrix
112
+ Array with the same type and shape as the input.
113
+
114
+ Example
115
+ -------
116
+ >>> X = np.array([[2, 2], [-0.75, 0.25]])
117
+ >>> projection_simplex(X)
118
+ array([[0.5, 0.5],
119
+ [0. , 1. ]])
120
+ >>> X_csr = sparse.csr_matrix(X)
121
+ >>> X_proj = projection_simplex(X_csr)
122
+ >>> X_proj.nnz
123
+ 3
124
+ >>> X_proj.toarray()
125
+ array([[0.5, 0.5],
126
+ [0. , 1. ]])
127
+
128
+ References
129
+ ----------
130
+ Duchi, J., Shalev-Shwartz, S., Singer, Y., & Chandra, T. (2008, July).
131
+ `Efficient projections onto the l 1-ball for learning in high dimensions.
132
+ <http://machinelearning.org/archive/icml2008/papers/361.pdf>`_
133
+ In Proceedings of the 25th international conference on Machine learning (pp. 272-279). ACM.
134
+ """
135
+ if isinstance(x, np.ndarray):
136
+ return projection_simplex_array(x, scale)
137
+ elif isinstance(x, sparse.csr_matrix):
138
+ return projection_simplex_csr(x, scale)
139
+ else:
140
+ raise TypeError('Input must be a numpy array or a CSR matrix.')
@@ -0,0 +1 @@
1
+ """tests for utils"""
@@ -0,0 +1,28 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for base.py"""
4
+ import unittest
5
+
6
+ from sknetwork.utils.base import Algorithm
7
+
8
+
9
+ class TestBase(unittest.TestCase):
10
+
11
+ def test_repr(self):
12
+ class Stub(Algorithm):
13
+ """Docstring"""
14
+ def __init__(self, some_param: int, another_param: str, random_state: int, some_unused_param: int):
15
+ self.some_param = some_param
16
+ self.another_param = another_param
17
+ self.random_state = random_state
18
+
19
+ def fit(self):
20
+ """Docstring"""
21
+ pass
22
+
23
+ stub = Stub(1, 'abc', 3, 4)
24
+ self.assertEqual(repr(stub), "Stub(some_param=1, another_param='abc')")
25
+
26
+ def test_fit(self):
27
+ stub = Algorithm()
28
+ self.assertRaises(NotImplementedError, stub.fit, None)
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for bunch"""
4
+
5
+ import unittest
6
+
7
+ from sknetwork.utils import Bunch
8
+
9
+
10
+ class TestBunch(unittest.TestCase):
11
+
12
+ def test_key_error(self):
13
+ bunch = Bunch(a=1, b=2)
14
+ with self.assertRaises(AttributeError):
15
+ # noinspection PyStatementEffect
16
+ bunch.c
@@ -0,0 +1,190 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """tests for check.py"""
4
+ import unittest
5
+
6
+ from sknetwork.data import cyclic_digraph
7
+ from sknetwork.data.test_graphs import test_graph_disconnect
8
+ from sknetwork.utils.check import *
9
+ from sknetwork.utils.format import check_csr_or_slr
10
+
11
+
12
+ class TestChecks(unittest.TestCase):
13
+
14
+ def setUp(self):
15
+ """Simple graphs for tests."""
16
+ self.adjacency = cyclic_digraph(3)
17
+ self.dense_mat = np.identity(3)
18
+
19
+ def test_check_csr_slr(self):
20
+ with self.assertRaises(TypeError):
21
+ check_csr_or_slr(np.ones(3))
22
+
23
+ def test_check_square(self):
24
+ with self.assertRaises(ValueError):
25
+ check_square(np.ones((3, 7)))
26
+
27
+ def test_check_connected(self):
28
+ with self.assertRaises(ValueError):
29
+ check_connected(test_graph_disconnect())
30
+
31
+ def test_check_symmetry(self):
32
+ with self.assertRaises(ValueError):
33
+ check_symmetry(self.adjacency)
34
+
35
+ def test_nonnegative_entries(self):
36
+ self.assertTrue(has_nonnegative_entries(self.adjacency))
37
+ self.assertTrue(has_nonnegative_entries(self.dense_mat))
38
+
39
+ def test_check_nonnegative(self):
40
+ with self.assertRaises(ValueError):
41
+ check_nonnegative(-self.dense_mat)
42
+
43
+ def test_positive_entries(self):
44
+ self.assertFalse(has_positive_entries(self.dense_mat))
45
+ with self.assertRaises(TypeError):
46
+ # noinspection PyTypeChecker
47
+ has_positive_entries(self.adjacency)
48
+
49
+ def test_check_positive(self):
50
+ check_positive(np.ones(3))
51
+ with self.assertRaises(ValueError):
52
+ check_positive(-self.dense_mat)
53
+
54
+ def test_probas(self):
55
+ self.assertTrue(is_proba_array(np.array([.5, .5])))
56
+ check_is_proba(0.5)
57
+ with self.assertRaises(TypeError):
58
+ is_proba_array(np.ones((2, 2, 2)))
59
+ self.assertRaises(TypeError, check_is_proba, 'toto')
60
+ with self.assertRaises(ValueError):
61
+ check_is_proba(2)
62
+
63
+ def test_damping(self):
64
+ with self.assertRaises(ValueError):
65
+ check_damping_factor(1)
66
+
67
+ def test_error_make_weights(self):
68
+ with self.assertRaises(ValueError):
69
+ make_weights(distribution='junk', adjacency=self.adjacency)
70
+
71
+ def test_error_check_is_proba(self):
72
+ with self.assertRaises(TypeError):
73
+ # noinspection PyTypeChecker
74
+ check_is_proba('junk')
75
+ with self.assertRaises(ValueError):
76
+ check_is_proba(2)
77
+
78
+ def test_error_check_weights(self):
79
+ with self.assertRaises(ValueError):
80
+ check_weights(np.zeros(4), self.adjacency)
81
+ with self.assertRaises(TypeError):
82
+ # noinspection PyTypeChecker
83
+ check_weights(2, self.adjacency)
84
+ with self.assertRaises(ValueError):
85
+ check_weights(np.zeros(3), self.adjacency, positive_entries=True)
86
+ with self.assertRaises(ValueError):
87
+ check_weights(-np.ones(3), self.adjacency)
88
+
89
+ def test_random_state(self):
90
+ random_state = np.random.RandomState(1)
91
+ self.assertEqual(type(check_random_state(random_state)), np.random.RandomState)
92
+
93
+ def test_error_random_state(self):
94
+ with self.assertRaises(TypeError):
95
+ # noinspection PyTypeChecker
96
+ check_random_state('junk')
97
+
98
+ def test_check_labels(self):
99
+ with self.assertRaises(ValueError):
100
+ check_labels(np.ones(3))
101
+ labels = np.ones(5)
102
+ labels[0] = 0
103
+ classes, n_classes = check_labels(labels)
104
+ self.assertTrue(np.equal(classes, np.arange(2)).all())
105
+ self.assertEqual(n_classes, 2)
106
+
107
+ def test_check_n_jobs(self):
108
+ self.assertEqual(check_n_jobs(None), 1)
109
+ self.assertEqual(check_n_jobs(-1), None)
110
+ self.assertEqual(check_n_jobs(8), 8)
111
+
112
+ def test_check_n_neighbors(self):
113
+ with self.assertWarns(Warning):
114
+ check_n_neighbors(10, 5)
115
+
116
+ def test_adj_vector(self):
117
+ n = 10
118
+ vector1 = np.random.rand(n)
119
+ vector2 = sparse.csr_matrix(vector1)
120
+ adj1 = check_adjacency_vector(vector1)
121
+ adj2 = check_adjacency_vector(vector2)
122
+
123
+ self.assertEqual((adj1 - adj2).nnz, 0)
124
+ self.assertEqual(adj1.shape, (1, n))
125
+
126
+ with self.assertRaises(ValueError):
127
+ check_adjacency_vector(vector1, 2 * n)
128
+
129
+ def test_check_n_clusters(self):
130
+ with self.assertRaises(ValueError):
131
+ check_n_clusters(3, 2)
132
+ with self.assertRaises(ValueError):
133
+ check_n_clusters(0, 2, 1)
134
+
135
+ def test_min_size(self):
136
+ with self.assertRaises(ValueError):
137
+ check_min_size(1, 3)
138
+
139
+ def test_min_nnz(self):
140
+ with self.assertRaises(ValueError):
141
+ check_min_nnz(1, 3)
142
+
143
+ def test_dendrogram(self):
144
+ with self.assertRaises(ValueError):
145
+ check_dendrogram(np.ones((3, 3)))
146
+
147
+ def test_n_components(self):
148
+ self.assertEqual(5, check_n_components(5, 10))
149
+ with self.assertWarns(Warning):
150
+ self.assertEqual(2, check_n_components(5, 2))
151
+
152
+ def test_scaling(self):
153
+ adjacency = cyclic_digraph(3)
154
+ with self.assertRaises(ValueError):
155
+ check_scaling(-1, adjacency, regularize=True)
156
+ adjacency = test_graph_disconnect()
157
+ with self.assertRaises(ValueError):
158
+ check_scaling(-1, adjacency, regularize=False)
159
+
160
+ def test_boolean_entries(self):
161
+ with self.assertRaises(TypeError):
162
+ has_boolean_entries([True, 0, 2])
163
+ self.assertFalse(has_boolean_entries(np.array([0, 1, True])))
164
+
165
+ def test_boolean(self):
166
+ check_boolean(np.array([True, False, True]))
167
+ with self.assertRaises(ValueError):
168
+ check_boolean(np.array([True, 0, 2]))
169
+
170
+ def test_check_vector_format(self):
171
+ check_vector_format(np.arange(4), np.ones(4))
172
+ with self.assertRaises(ValueError):
173
+ check_vector_format(np.arange(4), np.ones((4, 3)))
174
+ with self.assertRaises(ValueError):
175
+ check_vector_format(np.arange(4), np.ones(5))
176
+
177
+ def test_has_self_loops(self):
178
+ self.assertTrue(has_self_loops(sparse.csr_matrix(np.array([[1, 0], [1, 1]]))))
179
+ self.assertFalse(has_self_loops(sparse.csr_matrix(np.array([[0, 0], [1, 1]]))))
180
+
181
+ def test_add_self_loops(self):
182
+ # Square adjacency
183
+ adjacency = sparse.csr_matrix(np.array([[0, 0], [1, 1]]))
184
+ self.assertFalse(has_self_loops(adjacency))
185
+ adjacency = add_self_loops(adjacency)
186
+ self.assertTrue(has_self_loops(adjacency))
187
+ # Non square adjacency
188
+ adjacency = sparse.csr_matrix(np.array([[0, 0, 1], [1, 1, 1]]))
189
+ n_row, n_col = adjacency.shape
190
+ self.assertTrue(has_self_loops(add_self_loops(adjacency)[:, :n_row]))
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on October 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ """
7
+ import unittest
8
+
9
+ import numpy as np
10
+
11
+ from sknetwork.data import movie_actor
12
+ from sknetwork.linalg import CoNeighbor
13
+ from sknetwork.utils import co_neighbor_graph
14
+
15
+
16
+ class TestCoNeighbors(unittest.TestCase):
17
+
18
+ def setUp(self):
19
+ """Simple biadjacency for tests."""
20
+ self.biadjacency = movie_actor()
21
+
22
+ def test_exact(self):
23
+ n = self.biadjacency.shape[0]
24
+ adjacency = co_neighbor_graph(self.biadjacency, method='exact', normalized=False)
25
+ self.assertEqual(adjacency.shape, (n, n))
26
+ adjacency = co_neighbor_graph(self.biadjacency, method='exact')
27
+ self.assertEqual(adjacency.shape, (n, n))
28
+
29
+ operator = CoNeighbor(self.biadjacency)
30
+ x = np.random.randn(n)
31
+ y1 = adjacency.dot(x)
32
+ y2 = operator.dot(x)
33
+ self.assertAlmostEqual(np.linalg.norm(y1 - y2), 0)
34
+
35
+ def test_knn(self):
36
+ n = self.biadjacency.shape[0]
37
+ adjacency = co_neighbor_graph(self.biadjacency, method='knn')
38
+ self.assertEqual(adjacency.shape, (n, n))
39
+ adjacency = co_neighbor_graph(self.biadjacency, method='knn', normalized=False)
40
+ self.assertEqual(adjacency.shape, (n, n))
41
+
42
+ def test_invalid(self):
43
+ self.assertRaises(ValueError, co_neighbor_graph, self.biadjacency, method='toto')
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """Tests for format.py"""
4
+ import unittest
5
+
6
+ from sknetwork.data.test_graphs import *
7
+ from sknetwork.utils.format import *
8
+
9
+
10
+ class TestFormats(unittest.TestCase):
11
+
12
+ def setUp(self):
13
+ """Basic biadjacency for tests."""
14
+ self.biadjacency = test_bigraph()
15
+
16
+ def test_directed2undirected(self):
17
+ adjacency = test_digraph()
18
+ ref = directed2undirected(adjacency)
19
+ self.assertEqual(ref.shape, adjacency.shape)
20
+ self.assertTrue(is_symmetric(ref))
21
+
22
+ adjacency = test_graph().astype(bool)
23
+ n = adjacency.shape[0]
24
+ diff = directed2undirected(adjacency, weighted=False) - adjacency
25
+ self.assertEqual(diff.nnz, 0)
26
+
27
+ slr = SparseLR(adjacency, [(np.zeros(n), np.zeros(n))])
28
+ self.assertRaises(ValueError, directed2undirected, slr, weighted=False)
29
+ slr = 0.5 * directed2undirected(slr)
30
+ self.assertEqual(slr.shape, (n, n))
31
+
32
+ x = np.random.randn(n)
33
+ error = np.linalg.norm(slr.dot(x) - adjacency.dot(x))
34
+ self.assertAlmostEqual(error, 0)
35
+
36
+ def test_bipartite2directed(self):
37
+ n_row, n_col = self.biadjacency.shape
38
+ n = n_row + n_col
39
+
40
+ directed_graph = bipartite2directed(self.biadjacency)
41
+ self.assertEqual(directed_graph.shape, (n, n))
42
+
43
+ slr = SparseLR(self.biadjacency, [(np.ones(n_row), np.ones(n_col))])
44
+ directed_graph = bipartite2directed(slr)
45
+ self.assertTrue(type(directed_graph) == SparseLR)
46
+
47
+ def test_bipartite2undirected(self):
48
+ n_row, n_col = self.biadjacency.shape
49
+ n = n_row + n_col
50
+
51
+ undirected_graph = bipartite2undirected(self.biadjacency)
52
+ self.assertEqual(undirected_graph.shape, (n, n))
53
+ self.assertTrue(is_symmetric(undirected_graph))
54
+
55
+ slr = SparseLR(self.biadjacency, [(np.ones(n_row), np.ones(n_col))])
56
+ undirected_graph = bipartite2undirected(slr)
57
+ self.assertTrue(type(undirected_graph) == SparseLR)
58
+
59
+ def test_check(self):
60
+ with self.assertRaises(ValueError):
61
+ check_format(sparse.csr_matrix((3, 4)))
@@ -0,0 +1,21 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on October 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ """
7
+ import unittest
8
+
9
+ import numpy as np
10
+
11
+ from sknetwork.utils import KMeansDense
12
+
13
+
14
+ class TestKMeans(unittest.TestCase):
15
+
16
+ def test_kmeans(self):
17
+ x = np.random.randn(10, 3)
18
+ kmeans = KMeansDense(n_clusters=2)
19
+ labels = kmeans.fit_transform(x)
20
+ self.assertEqual(labels.shape, (x.shape[0],))
21
+ self.assertEqual(kmeans.cluster_centers_.shape, (kmeans.n_clusters, x.shape[1]))
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on October 2019
5
+ @author: Nathan de Lara <nathan.delara@polytechnique.org>
6
+ """
7
+ import unittest
8
+
9
+ import numpy as np
10
+ from scipy import sparse
11
+ from scipy.sparse.linalg import norm
12
+
13
+ from sknetwork.utils import KNNDense, CNNDense
14
+
15
+
16
+ class TestKNN(unittest.TestCase):
17
+
18
+ def test_basics(self):
19
+ x = np.array([[-2, -1], [-2, 1], [2, 1], [2, -1]])
20
+ knn = KNNDense(n_neighbors=1)
21
+ knn.fit(x)
22
+ truth = np.zeros(16).reshape((4, 4))
23
+ truth[0, 1] = 1
24
+ truth[2, 3] = 1
25
+ truth = sparse.csr_matrix(truth + truth.T)
26
+ self.assertAlmostEqual(norm(truth - knn.adjacency_), 0)
27
+
28
+ def test_pknn(self):
29
+ x = np.array([(0, 4), (1, 0), (2, 1), (3, 2), (4, 3)])
30
+ pknn = CNNDense(n_neighbors=1)
31
+ adj = pknn.fit_transform(x)
32
+ self.assertEqual(adj.shape, (5, 5))
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created in July 2022
5
+ @author: Thomas Bonald <thomas.bonald@telecom-paris.fr>
6
+ """
7
+ import unittest
8
+
9
+ import numpy as np
10
+
11
+ from sknetwork.utils.membership import get_membership, from_membership
12
+
13
+
14
+ class TestMembership(unittest.TestCase):
15
+
16
+ def test_membership(self):
17
+ labels = np.array([0, 0, 1, 2, 1, 1])
18
+ membership = get_membership(labels)
19
+ self.assertEqual(membership.nnz, 6)
20
+ self.assertEqual(np.linalg.norm(labels - from_membership(membership)), 0)
21
+ labels = np.array([0, 0, 1, 2, 1, -1])
22
+ membership = get_membership(labels)
23
+ self.assertEqual(membership.nnz, 5)
24
+ self.assertEqual(np.linalg.norm(labels - from_membership(membership)), 0)
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Created on December 2020
5
+ @author: Thomas Bonald <bonald@enst.fr>
6
+ """
7
+ import unittest
8
+
9
+ import numpy as np
10
+ from numpy.linalg import norm
11
+
12
+ from sknetwork.data import karate_club, painters
13
+ from sknetwork.utils import get_neighbors, get_degrees, get_weights
14
+
15
+
16
+ class TestNeighbors(unittest.TestCase):
17
+
18
+ def test_graph(self):
19
+ adjacency = karate_club()
20
+ neighbors = get_neighbors(adjacency, 5)
21
+ degrees = get_degrees(adjacency)
22
+ neighbors_true = np.array([0, 6, 10, 16])
23
+ self.assertEqual(norm(neighbors - neighbors_true), 0)
24
+ self.assertEqual(degrees[5], 4)
25
+
26
+ def test_digraph(self):
27
+ adjacency = painters()
28
+ neighbors = get_neighbors(adjacency, 0)
29
+ out_degrees = get_degrees(adjacency)
30
+ out_weights = get_weights(adjacency)
31
+ neighbors_true = np.array([3, 10])
32
+ self.assertEqual(norm(neighbors - neighbors_true), 0)
33
+ self.assertEqual(out_degrees[0], 2)
34
+ self.assertEqual(out_weights[0], 2)
35
+ neighbors = get_neighbors(adjacency, 0, transpose=True)
36
+ in_degrees = get_degrees(adjacency, transpose=True)
37
+ in_weights = get_weights(adjacency, transpose=True)
38
+ neighbors_true = np.array([3, 6, 8, 10, 11])
39
+ self.assertEqual(norm(neighbors - neighbors_true), 0)
40
+ self.assertEqual(in_degrees[0], 5)
41
+ self.assertEqual(in_weights[0], 5)