scikit-network 0.33.0__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.
Potentially problematic release.
This version of scikit-network might be problematic. Click here for more details.
- scikit_network-0.33.0.dist-info/AUTHORS.rst +43 -0
- scikit_network-0.33.0.dist-info/LICENSE +34 -0
- scikit_network-0.33.0.dist-info/METADATA +517 -0
- scikit_network-0.33.0.dist-info/RECORD +217 -0
- scikit_network-0.33.0.dist-info/WHEEL +6 -0
- scikit_network-0.33.0.dist-info/top_level.txt +1 -0
- scikit_network.libs/libgomp-a34b3233.so.1.0.0 +0 -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.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -0
- sknetwork/clustering/leiden_core.pyx +124 -0
- sknetwork/clustering/louvain.py +286 -0
- sknetwork/clustering/louvain_core.cpython-312-x86_64-linux-gnu.so +0 -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 +129 -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 +89 -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.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -0
- sknetwork/topology/cliques.pyx +149 -0
- sknetwork/topology/core.cpython-312-x86_64-linux-gnu.so +0 -0
- sknetwork/topology/core.pyx +90 -0
- sknetwork/topology/cycles.py +243 -0
- sknetwork/topology/minheap.cpython-312-x86_64-linux-gnu.so +0 -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.cpython-312-x86_64-linux-gnu.so +0 -0
- sknetwork/topology/triangles.pyx +151 -0
- sknetwork/topology/weisfeiler_lehman.py +133 -0
- sknetwork/topology/weisfeiler_lehman_core.cpython-312-x86_64-linux-gnu.so +0 -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
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created in May 2023
|
|
5
|
+
@author: Thomas Bonald <bonald@enst.fr>
|
|
6
|
+
"""
|
|
7
|
+
from typing import Iterable, Optional, Union, Tuple
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
from scipy import sparse
|
|
11
|
+
|
|
12
|
+
from sknetwork.path.dag import get_dag
|
|
13
|
+
from sknetwork.utils.format import bipartite2undirected
|
|
14
|
+
from sknetwork.path.distances import get_distances
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def get_shortest_path(input_matrix: sparse.csr_matrix, source: Optional[Union[int, Iterable]] = None,
|
|
18
|
+
source_row: Optional[Union[int, Iterable]] = None,
|
|
19
|
+
source_col: Optional[Union[int, Iterable]] = None, force_bipartite: bool = False) \
|
|
20
|
+
-> Union[np.ndarray, Tuple[np.ndarray, np.ndarray], Tuple[np.ndarray, np.ndarray]]:
|
|
21
|
+
"""Get the shortest paths from a source (or a set of sources) in number of hops.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
input_matrix :
|
|
26
|
+
Adjacency matrix or biadjacency matrix of the graph.
|
|
27
|
+
source :
|
|
28
|
+
If an integer, index of the source node.
|
|
29
|
+
If a list, indices of source nodes (the shortest distances to one of these nodes in returned).
|
|
30
|
+
source_row, source_col :
|
|
31
|
+
For bipartite graphs, index of source nodes on rows and columns.
|
|
32
|
+
The parameter source_row is an alias for source (at least one of them must be ``None``).
|
|
33
|
+
force_bipartite :
|
|
34
|
+
If ``True``, consider the input matrix as the biadjacency matrix of a bipartite graph.
|
|
35
|
+
Set to ``True`` is the parameters source_row or source_col are specified.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
path : sparse.csr_matrix
|
|
40
|
+
Adjacency matrix of the graph of the shortest paths from the source node (or the set of source nodes).
|
|
41
|
+
If the input graph is a bipartite graph, the shape of the matrix is (n_row + n_col, n_row + n_col) with the new
|
|
42
|
+
index corresponding to the rows then the columns of the original graph.
|
|
43
|
+
|
|
44
|
+
Examples
|
|
45
|
+
--------
|
|
46
|
+
>>> from sknetwork.data import cyclic_digraph
|
|
47
|
+
>>> adjacency = cyclic_digraph(3)
|
|
48
|
+
>>> path = get_shortest_path(adjacency, source=0)
|
|
49
|
+
>>> path.toarray().astype(int)
|
|
50
|
+
array([[0, 1, 0],
|
|
51
|
+
[0, 0, 1],
|
|
52
|
+
[0, 0, 0]])
|
|
53
|
+
"""
|
|
54
|
+
distances = get_distances(input_matrix, source, source_row, source_col, force_bipartite)
|
|
55
|
+
if type(distances) == tuple:
|
|
56
|
+
adjacency = bipartite2undirected(input_matrix)
|
|
57
|
+
distances = np.hstack(distances)
|
|
58
|
+
else:
|
|
59
|
+
adjacency = input_matrix
|
|
60
|
+
return get_dag(adjacency, order=distances)
|
|
61
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""tests for path module"""
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
""""tests for search.py"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from sknetwork.data import cyclic_digraph
|
|
10
|
+
from sknetwork.data.test_graphs import *
|
|
11
|
+
from sknetwork.path import get_dag
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestSearch(unittest.TestCase):
|
|
15
|
+
|
|
16
|
+
def test(self):
|
|
17
|
+
adjacency = cyclic_digraph(3)
|
|
18
|
+
dag = get_dag(adjacency)
|
|
19
|
+
self.assertEqual(dag.nnz, 2)
|
|
20
|
+
|
|
21
|
+
adjacency = test_graph_empty()
|
|
22
|
+
dag = get_dag(adjacency)
|
|
23
|
+
self.assertEqual(dag.nnz, 0)
|
|
24
|
+
|
|
25
|
+
adjacency = test_graph()
|
|
26
|
+
dag = get_dag(adjacency)
|
|
27
|
+
self.assertEqual(dag.nnz, 12)
|
|
28
|
+
dag = get_dag(adjacency, order=np.arange(10) % 3)
|
|
29
|
+
self.assertEqual(dag.nnz, 10)
|
|
30
|
+
|
|
31
|
+
adjacency = test_disconnected_graph()
|
|
32
|
+
dag = get_dag(adjacency, 3)
|
|
33
|
+
self.assertEqual(dag.nnz, 1)
|
|
34
|
+
|
|
35
|
+
adjacency = test_digraph()
|
|
36
|
+
dag = get_dag(adjacency, 1)
|
|
37
|
+
self.assertEqual(dag.nnz, 4)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
""""tests for distances.py"""
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from sknetwork.data.test_graphs import *
|
|
7
|
+
from sknetwork.path.distances import get_distances
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestDistances(unittest.TestCase):
|
|
11
|
+
|
|
12
|
+
def test_input(self):
|
|
13
|
+
adjacency = test_graph()
|
|
14
|
+
with self.assertRaises(ValueError):
|
|
15
|
+
get_distances(adjacency)
|
|
16
|
+
with self.assertRaises(ValueError):
|
|
17
|
+
get_distances(adjacency, source=0, source_row=5)
|
|
18
|
+
|
|
19
|
+
def test_algo(self):
|
|
20
|
+
adjacency = test_graph()
|
|
21
|
+
distances = get_distances(adjacency, 0)
|
|
22
|
+
distances_ = np.array([0, 1, 3, 2, 2, 3, 2, 3, 4, 4])
|
|
23
|
+
self.assertTrue(all(distances == distances_))
|
|
24
|
+
distances = get_distances(adjacency, 0, transpose=True)
|
|
25
|
+
self.assertTrue(all(distances == distances_))
|
|
26
|
+
distances = get_distances(adjacency, [0, 5])
|
|
27
|
+
distances_ = np.array([0, 1, 3, 2, 1, 0, 1, 2, 4, 3])
|
|
28
|
+
self.assertTrue(all(distances == distances_))
|
|
29
|
+
|
|
30
|
+
adjacency = test_graph_empty()
|
|
31
|
+
source = [0, 3]
|
|
32
|
+
distances = get_distances(adjacency, source)
|
|
33
|
+
distances_ = -np.ones(len(distances), dtype=int)
|
|
34
|
+
distances_[source] = 0
|
|
35
|
+
self.assertTrue(all(distances == distances_))
|
|
36
|
+
|
|
37
|
+
adjacency = test_digraph()
|
|
38
|
+
distances = get_distances(adjacency, [0])
|
|
39
|
+
distances_ = np.array([0, 1, 3, 2, 2, 3, -1, -1, -1, -1])
|
|
40
|
+
self.assertTrue(all(distances == distances_))
|
|
41
|
+
distances = get_distances(adjacency, [0], transpose=True)
|
|
42
|
+
self.assertTrue(sum(distances < 0) == 9)
|
|
43
|
+
distances = get_distances(adjacency, [0, 5], transpose=True)
|
|
44
|
+
distances_ = np.array([0, 2, -1, -1, 1, 0, 1, -1, -1, -1])
|
|
45
|
+
self.assertTrue(all(distances == distances_))
|
|
46
|
+
|
|
47
|
+
biadjacency = test_bigraph()
|
|
48
|
+
distances_row, distances_col = get_distances(biadjacency, [0])
|
|
49
|
+
distances_row_, distances_col_ = np.array([0, -1, 2, -1, -1, -1]), np.array([3, 1, -1, -1, -1, -1, -1, -1])
|
|
50
|
+
self.assertTrue(all(distances_row == distances_row_))
|
|
51
|
+
self.assertTrue(all(distances_col == distances_col_))
|
|
52
|
+
|
|
53
|
+
adjacency = test_graph()
|
|
54
|
+
distances_row, distances_col = get_distances(adjacency, source_col=[0])
|
|
55
|
+
self.assertTrue(all(distances_row % 2))
|
|
56
|
+
self.assertTrue(all((distances_col + 1) % 2))
|
|
57
|
+
|
|
58
|
+
biadjacency = test_bigraph()
|
|
59
|
+
distances_row, distances_col = get_distances(biadjacency, source=0, source_col=[1, 2])
|
|
60
|
+
distances_row_, distances_col_ = np.array([0, 1, 1, -1, -1, -1]), np.array([2, 0, 0, 2, -1, -1, -1, -1])
|
|
61
|
+
self.assertTrue(all(distances_row == distances_row_))
|
|
62
|
+
self.assertTrue(all(distances_col == distances_col_))
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
""""tests for search.py"""
|
|
4
|
+
|
|
5
|
+
import unittest
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
|
|
9
|
+
from sknetwork.data import cyclic_digraph
|
|
10
|
+
from sknetwork.data.test_graphs import *
|
|
11
|
+
from sknetwork.path import breadth_first_search
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class TestSearch(unittest.TestCase):
|
|
15
|
+
|
|
16
|
+
def test_bfs(self):
|
|
17
|
+
adjacency = cyclic_digraph(3)
|
|
18
|
+
search = breadth_first_search(adjacency, 0)
|
|
19
|
+
search_ = np.arange(3)
|
|
20
|
+
self.assertTrue(all(search == search_))
|
|
21
|
+
|
|
22
|
+
adjacency = test_graph_empty()
|
|
23
|
+
search = breadth_first_search(adjacency, 0)
|
|
24
|
+
search_ = np.array([0])
|
|
25
|
+
self.assertTrue(all(search == search_))
|
|
26
|
+
|
|
27
|
+
adjacency = test_graph()
|
|
28
|
+
search = breadth_first_search(adjacency, 3)
|
|
29
|
+
search_ = np.array([3, 1, 2, 0, 4, 6, 8, 5, 7, 9])
|
|
30
|
+
self.assertTrue(all(search == search_))
|
|
31
|
+
|
|
32
|
+
adjacency = test_disconnected_graph()
|
|
33
|
+
search = breadth_first_search(adjacency, 2)
|
|
34
|
+
search_ = np.array([2, 3])
|
|
35
|
+
self.assertTrue(all(search == search_))
|
|
36
|
+
|
|
37
|
+
adjacency = test_digraph()
|
|
38
|
+
search = breadth_first_search(adjacency, 1)
|
|
39
|
+
search_ = {1, 3, 4, 2, 5}
|
|
40
|
+
self.assertTrue(set(list(search)) == search_)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
""""tests for shortest_path.py"""
|
|
4
|
+
import unittest
|
|
5
|
+
|
|
6
|
+
from sknetwork.data.test_graphs import *
|
|
7
|
+
from sknetwork.path.shortest_path import get_shortest_path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestShortestPath(unittest.TestCase):
|
|
11
|
+
|
|
12
|
+
def test_path(self):
|
|
13
|
+
adjacency = test_graph_empty()
|
|
14
|
+
path = get_shortest_path(adjacency, 0)
|
|
15
|
+
self.assertEqual(path.nnz, 0)
|
|
16
|
+
|
|
17
|
+
adjacency = test_graph()
|
|
18
|
+
path = get_shortest_path(adjacency, 0)
|
|
19
|
+
self.assertEqual(path.nnz, 10)
|
|
20
|
+
path = get_shortest_path(adjacency, [0, 4, 6])
|
|
21
|
+
self.assertEqual(path.nnz, 10)
|
|
22
|
+
path = get_shortest_path(adjacency, np.arange(10))
|
|
23
|
+
self.assertEqual(path.nnz, 0)
|
|
24
|
+
path = get_shortest_path(adjacency, [0, 5])
|
|
25
|
+
self.assertEqual(path.nnz, 9)
|
|
26
|
+
|
|
27
|
+
adjacency = test_disconnected_graph()
|
|
28
|
+
path = get_shortest_path(adjacency, 4)
|
|
29
|
+
self.assertEqual(path.nnz, 5)
|
|
30
|
+
|
|
31
|
+
adjacency = test_digraph()
|
|
32
|
+
path = get_shortest_path(adjacency, 0)
|
|
33
|
+
self.assertEqual(path.nnz, 5)
|
|
34
|
+
|
|
35
|
+
biadjacency = test_bigraph()
|
|
36
|
+
path = get_shortest_path(biadjacency, 0)
|
|
37
|
+
self.assertEqual(path.nnz, 3)
|
|
38
|
+
self.assertTrue(path.shape[0] == np.sum(biadjacency.shape))
|
|
39
|
+
path = get_shortest_path(biadjacency, source_col=np.arange(biadjacency.shape[1]))
|
|
40
|
+
self.assertEqual(path.nnz, biadjacency.nnz)
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"""ranking module"""
|
|
2
|
+
from sknetwork.ranking.base import BaseRanking
|
|
3
|
+
from sknetwork.ranking.betweenness import Betweenness
|
|
4
|
+
from sknetwork.ranking.closeness import Closeness
|
|
5
|
+
from sknetwork.ranking.hits import HITS
|
|
6
|
+
from sknetwork.ranking.katz import Katz
|
|
7
|
+
from sknetwork.ranking.pagerank import PageRank
|
|
8
|
+
from sknetwork.ranking.postprocess import top_k
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created in November 2019
|
|
5
|
+
@author: Nathan de Lara <nathan.delara@polytechnique.org>
|
|
6
|
+
"""
|
|
7
|
+
from abc import ABC
|
|
8
|
+
|
|
9
|
+
import numpy as np
|
|
10
|
+
|
|
11
|
+
from sknetwork.base import Algorithm
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class BaseRanking(Algorithm, ABC):
|
|
15
|
+
"""Base class for ranking algorithms.
|
|
16
|
+
|
|
17
|
+
Attributes
|
|
18
|
+
----------
|
|
19
|
+
scores_ : np.ndarray
|
|
20
|
+
Score of each node.
|
|
21
|
+
scores_row_: np.ndarray
|
|
22
|
+
Scores of rows, for bipartite graphs.
|
|
23
|
+
scores_col_: np.ndarray
|
|
24
|
+
Scores of columns, for bipartite graphs.
|
|
25
|
+
"""
|
|
26
|
+
def __init__(self):
|
|
27
|
+
self.scores_ = None
|
|
28
|
+
|
|
29
|
+
def predict(self, columns: bool = False) -> np.ndarray:
|
|
30
|
+
"""Return the scores predicted by the algorithm.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
columns : bool
|
|
35
|
+
If ``True``, return the prediction for columns.
|
|
36
|
+
|
|
37
|
+
Returns
|
|
38
|
+
-------
|
|
39
|
+
scores : np.ndarray
|
|
40
|
+
Scores.
|
|
41
|
+
"""
|
|
42
|
+
if columns:
|
|
43
|
+
return self.scores_col_
|
|
44
|
+
return self.scores_
|
|
45
|
+
|
|
46
|
+
def fit_predict(self, *args, **kwargs) -> np.ndarray:
|
|
47
|
+
"""Fit algorithm to data and return the scores. Same parameters as the ``fit`` method.
|
|
48
|
+
|
|
49
|
+
Returns
|
|
50
|
+
-------
|
|
51
|
+
scores : np.ndarray
|
|
52
|
+
Scores.
|
|
53
|
+
"""
|
|
54
|
+
self.fit(*args, **kwargs)
|
|
55
|
+
return self.scores_
|
|
56
|
+
|
|
57
|
+
def _split_vars(self, shape):
|
|
58
|
+
n_row = shape[0]
|
|
59
|
+
self.scores_row_ = self.scores_[:n_row]
|
|
60
|
+
self.scores_col_ = self.scores_[n_row:]
|
|
61
|
+
self.scores_ = self.scores_row_
|
|
Binary file
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# distutils: language = c++
|
|
2
|
+
# cython: language_level=3
|
|
3
|
+
"""
|
|
4
|
+
Created on September 17 2020
|
|
5
|
+
@author: Tiphaine Viard <tiphaine.viard@telecom-paris.fr>
|
|
6
|
+
"""
|
|
7
|
+
from typing import Union
|
|
8
|
+
import numpy as np
|
|
9
|
+
from scipy import sparse
|
|
10
|
+
|
|
11
|
+
from sknetwork.ranking.base import BaseRanking
|
|
12
|
+
from sknetwork.utils.check import check_format, check_square, check_connected
|
|
13
|
+
|
|
14
|
+
from libcpp.vector cimport vector
|
|
15
|
+
from libcpp.queue cimport queue
|
|
16
|
+
|
|
17
|
+
class Betweenness(BaseRanking):
|
|
18
|
+
""" Betweenness centrality, based on Brandes' algorithm.
|
|
19
|
+
|
|
20
|
+
Attributes
|
|
21
|
+
----------
|
|
22
|
+
scores_ : np.ndarray
|
|
23
|
+
Betweenness centrality value of each node
|
|
24
|
+
|
|
25
|
+
Example
|
|
26
|
+
-------
|
|
27
|
+
>>> from sknetwork.ranking import Betweenness
|
|
28
|
+
>>> from sknetwork.data.toy_graphs import bow_tie
|
|
29
|
+
>>> betweenness = Betweenness()
|
|
30
|
+
>>> adjacency = bow_tie()
|
|
31
|
+
>>> scores = betweenness.fit_transform(adjacency)
|
|
32
|
+
>>> scores
|
|
33
|
+
array([4., 0., 0., 0., 0.])
|
|
34
|
+
|
|
35
|
+
References
|
|
36
|
+
----------
|
|
37
|
+
Brandes, Ulrik (2001). A faster algorithm for betweenness centrality. Journal of Mathematical Sociology.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, normalized: bool = False):
|
|
41
|
+
super(Betweenness, self).__init__()
|
|
42
|
+
self.normalized_ = normalized
|
|
43
|
+
|
|
44
|
+
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'Betweenness':
|
|
45
|
+
adjacency = check_format(adjacency)
|
|
46
|
+
check_square(adjacency)
|
|
47
|
+
check_connected(adjacency)
|
|
48
|
+
|
|
49
|
+
cdef int source
|
|
50
|
+
cdef vector[ vector[int] ] preds
|
|
51
|
+
cdef vector[int] sigma
|
|
52
|
+
cdef vector[int] dists
|
|
53
|
+
cdef int i
|
|
54
|
+
cdef int j
|
|
55
|
+
cdef vector[float] delta
|
|
56
|
+
|
|
57
|
+
cdef int n = adjacency.shape[0]
|
|
58
|
+
self.scores_ = np.zeros(n)
|
|
59
|
+
cdef vector[int] seen # Using list as stack
|
|
60
|
+
cdef queue[int] bfs_queue
|
|
61
|
+
|
|
62
|
+
for source in range(n):
|
|
63
|
+
preds = [[] for _ in range(n)]
|
|
64
|
+
sigma = np.zeros(n)
|
|
65
|
+
sigma[source] = 1
|
|
66
|
+
dists = -np.ones(n, dtype=int)
|
|
67
|
+
dists[source] = 0
|
|
68
|
+
bfs_queue.push(source)
|
|
69
|
+
|
|
70
|
+
while bfs_queue.size() != 0:
|
|
71
|
+
i = bfs_queue.front()
|
|
72
|
+
bfs_queue.pop()
|
|
73
|
+
|
|
74
|
+
seen.push_back(i)
|
|
75
|
+
neighbors = adjacency.indices[adjacency.indptr[i]:adjacency.indptr[i + 1]]
|
|
76
|
+
for j in neighbors:
|
|
77
|
+
if dists[j] < 0: # j found for the first time?
|
|
78
|
+
dists[j] = dists[i] + 1
|
|
79
|
+
bfs_queue.push(j)
|
|
80
|
+
if dists[j] == dists[i] + 1: # shortest path to j via i?
|
|
81
|
+
sigma[j] += sigma[i]
|
|
82
|
+
preds[j].push_back(i)
|
|
83
|
+
|
|
84
|
+
# Now backtrack to compute betweenness scores
|
|
85
|
+
delta = np.zeros(n)
|
|
86
|
+
while len(seen) != 0:
|
|
87
|
+
j = seen.back()
|
|
88
|
+
seen.pop_back()
|
|
89
|
+
for i in preds[j]:
|
|
90
|
+
delta[i] += sigma[i] / sigma[j] * (1 + delta[j])
|
|
91
|
+
if j != source:
|
|
92
|
+
self.scores_[j] += delta[j]
|
|
93
|
+
|
|
94
|
+
# Undirected graph, divide all values by two
|
|
95
|
+
self.scores_ = 1 / 2 * self.scores_
|
|
96
|
+
|
|
97
|
+
return self
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created on November 12 2019
|
|
5
|
+
@author: Quentin Lutz <qlutz@enst.fr>
|
|
6
|
+
"""
|
|
7
|
+
from math import log
|
|
8
|
+
from typing import Union, Optional
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from scipy import sparse
|
|
12
|
+
|
|
13
|
+
from sknetwork.path.shortest_path import get_distances
|
|
14
|
+
from sknetwork.ranking.base import BaseRanking
|
|
15
|
+
from sknetwork.utils.check import check_format, check_square, check_connected
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class Closeness(BaseRanking):
|
|
19
|
+
"""Ranking by closeness centrality of each node in a connected graph, corresponding to the average length of the
|
|
20
|
+
shortest paths from that node to all the other ones.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
method :
|
|
25
|
+
Denotes if the results should be exact or approximate.
|
|
26
|
+
tol: float
|
|
27
|
+
If ``method=='approximate'``, the allowed tolerance on each score entry.
|
|
28
|
+
|
|
29
|
+
Attributes
|
|
30
|
+
----------
|
|
31
|
+
scores_ : np.ndarray
|
|
32
|
+
Closeness centrality of each node.
|
|
33
|
+
|
|
34
|
+
Example
|
|
35
|
+
-------
|
|
36
|
+
>>> from sknetwork.ranking import Closeness
|
|
37
|
+
>>> from sknetwork.data import cyclic_digraph
|
|
38
|
+
>>> closeness = Closeness()
|
|
39
|
+
>>> adjacency = cyclic_digraph(3)
|
|
40
|
+
>>> scores = closeness.fit_predict(adjacency)
|
|
41
|
+
>>> np.round(scores, 2)
|
|
42
|
+
array([0.67, 0.67, 0.67])
|
|
43
|
+
|
|
44
|
+
References
|
|
45
|
+
----------
|
|
46
|
+
Eppstein, D., & Wang, J. (2001, January).
|
|
47
|
+
`Fast approximation of centrality.
|
|
48
|
+
<http://jgaa.info/accepted/2004/EppsteinWang2004.8.1.pdf>`_
|
|
49
|
+
In Proceedings of the twelfth annual ACM-SIAM symposium on Discrete algorithms (pp. 228-229).
|
|
50
|
+
Society for Industrial and Applied Mathematics.
|
|
51
|
+
"""
|
|
52
|
+
|
|
53
|
+
def __init__(self, method: str = 'exact', tol: float = 1e-1):
|
|
54
|
+
super(Closeness, self).__init__()
|
|
55
|
+
|
|
56
|
+
self.method = method
|
|
57
|
+
self.tol = tol
|
|
58
|
+
|
|
59
|
+
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'Closeness':
|
|
60
|
+
"""Closeness centrality for connected graphs.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
adjacency :
|
|
65
|
+
Adjacency matrix of the graph.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
self: :class:`Closeness`
|
|
70
|
+
"""
|
|
71
|
+
adjacency = check_format(adjacency)
|
|
72
|
+
check_square(adjacency)
|
|
73
|
+
check_connected(adjacency)
|
|
74
|
+
n = adjacency.shape[0]
|
|
75
|
+
|
|
76
|
+
if self.method == 'exact':
|
|
77
|
+
n_sources = n
|
|
78
|
+
sources = np.arange(n)
|
|
79
|
+
elif self.method == 'approximate':
|
|
80
|
+
n_sources = min(int(log(n) / self.tol ** 2), n)
|
|
81
|
+
sources = np.random.choice(np.arange(n), n_sources, replace=False)
|
|
82
|
+
else:
|
|
83
|
+
raise ValueError("Method should be either 'exact' or 'approximate'.")
|
|
84
|
+
|
|
85
|
+
distances = np.array([get_distances(adjacency, source=source) for source in sources])
|
|
86
|
+
|
|
87
|
+
distances_min = np.min(distances, axis=1)
|
|
88
|
+
scores = (n - 1) / n / np.mean(distances, axis=1)
|
|
89
|
+
scores[distances_min < 0] = 0
|
|
90
|
+
self.scores_ = scores
|
|
91
|
+
|
|
92
|
+
return self
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created on Oct 07 2019
|
|
5
|
+
@author: Nathan de Lara <nathan.delara@polytechnique.org>
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import Union
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
from scipy import sparse
|
|
12
|
+
|
|
13
|
+
from sknetwork.linalg import SVDSolver, LanczosSVD
|
|
14
|
+
from sknetwork.ranking.base import BaseRanking
|
|
15
|
+
from sknetwork.utils.check import check_format
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class HITS(BaseRanking):
|
|
19
|
+
"""Hub and authority scores of each node.
|
|
20
|
+
For bipartite graphs, the hub score is computed on rows and the authority score on columns.
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
solver : ``'lanczos'`` (default, Lanczos algorithm) or :class:`SVDSolver` (custom solver)
|
|
25
|
+
Which solver to use.
|
|
26
|
+
|
|
27
|
+
Attributes
|
|
28
|
+
----------
|
|
29
|
+
scores_ : np.ndarray
|
|
30
|
+
Hub score of each node.
|
|
31
|
+
scores_row_ : np.ndarray
|
|
32
|
+
Hub score of each row, for bipartite graphs.
|
|
33
|
+
scores_col_ : np.ndarray
|
|
34
|
+
Authority score of each column, for bipartite graphs.
|
|
35
|
+
|
|
36
|
+
Example
|
|
37
|
+
-------
|
|
38
|
+
>>> from sknetwork.ranking import HITS
|
|
39
|
+
>>> from sknetwork.data import star_wars
|
|
40
|
+
>>> hits = HITS()
|
|
41
|
+
>>> biadjacency = star_wars()
|
|
42
|
+
>>> scores = hits.fit_predict(biadjacency)
|
|
43
|
+
>>> np.round(scores, 2)
|
|
44
|
+
array([0.5 , 0.23, 0.69, 0.46])
|
|
45
|
+
|
|
46
|
+
References
|
|
47
|
+
----------
|
|
48
|
+
Kleinberg, J. M. (1999). Authoritative sources in a hyperlinked environment.
|
|
49
|
+
Journal of the ACM, 46(5), 604-632.
|
|
50
|
+
"""
|
|
51
|
+
def __init__(self, solver: Union[str, SVDSolver] = 'lanczos'):
|
|
52
|
+
super(HITS, self).__init__()
|
|
53
|
+
|
|
54
|
+
if type(solver) == str:
|
|
55
|
+
self.solver: SVDSolver = LanczosSVD()
|
|
56
|
+
else:
|
|
57
|
+
self.solver = solver
|
|
58
|
+
|
|
59
|
+
def fit(self, adjacency: Union[sparse.csr_matrix, np.ndarray]) -> 'HITS':
|
|
60
|
+
"""Compute HITS algorithm with a spectral method.
|
|
61
|
+
|
|
62
|
+
Parameters
|
|
63
|
+
----------
|
|
64
|
+
adjacency :
|
|
65
|
+
Adjacency or biadjacency matrix of the graph.
|
|
66
|
+
|
|
67
|
+
Returns
|
|
68
|
+
-------
|
|
69
|
+
self: :class:`HITS`
|
|
70
|
+
"""
|
|
71
|
+
adjacency = check_format(adjacency)
|
|
72
|
+
|
|
73
|
+
self.solver.fit(adjacency, 1)
|
|
74
|
+
hubs: np.ndarray = self.solver.singular_vectors_left_.reshape(-1)
|
|
75
|
+
authorities: np.ndarray = self.solver.singular_vectors_right_.reshape(-1)
|
|
76
|
+
|
|
77
|
+
h_pos, h_neg = (hubs > 0).sum(), (hubs < 0).sum()
|
|
78
|
+
a_pos, a_neg = (authorities > 0).sum(), (authorities < 0).sum()
|
|
79
|
+
|
|
80
|
+
if h_pos > h_neg:
|
|
81
|
+
hubs = np.clip(hubs, a_min=0., a_max=None)
|
|
82
|
+
else:
|
|
83
|
+
hubs = np.clip(-hubs, a_min=0., a_max=None)
|
|
84
|
+
|
|
85
|
+
if a_pos > a_neg:
|
|
86
|
+
authorities = np.clip(authorities, a_min=0., a_max=None)
|
|
87
|
+
else:
|
|
88
|
+
authorities = np.clip(-authorities, a_min=0., a_max=None)
|
|
89
|
+
|
|
90
|
+
self.scores_row_ = hubs
|
|
91
|
+
self.scores_col_ = authorities
|
|
92
|
+
self.scores_ = hubs
|
|
93
|
+
|
|
94
|
+
return self
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
"""
|
|
4
|
+
Created on May 2020
|
|
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
|
+
from scipy.sparse.linalg import LinearOperator
|
|
12
|
+
|
|
13
|
+
from sknetwork.linalg.polynome import Polynome
|
|
14
|
+
from sknetwork.ranking.base import BaseRanking
|
|
15
|
+
from sknetwork.utils.check import check_format
|
|
16
|
+
from sknetwork.utils.format import get_adjacency
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class Katz(BaseRanking):
|
|
20
|
+
"""Katz centrality, defined by:
|
|
21
|
+
|
|
22
|
+
:math:`\\sum_{k=1}^K\\alpha^k(A^k)^T\\mathbf{1}`
|
|
23
|
+
|
|
24
|
+
where :math:`A` is the adjacency matrix, :math:`\\alpha` is the damping factor and :math:`K` is the path length.
|
|
25
|
+
|
|
26
|
+
Parameters
|
|
27
|
+
----------
|
|
28
|
+
damping_factor : float
|
|
29
|
+
Damping factor for path contributions.
|
|
30
|
+
path_length : int
|
|
31
|
+
Maximum length of the paths.
|
|
32
|
+
|
|
33
|
+
Attributes
|
|
34
|
+
----------
|
|
35
|
+
scores_ : np.ndarray
|
|
36
|
+
Score of each node.
|
|
37
|
+
scores_row_: np.ndarray
|
|
38
|
+
Scores of rows, for bipartite graphs.
|
|
39
|
+
scores_col_: np.ndarray
|
|
40
|
+
Scores of columns, for bipartite graphs.
|
|
41
|
+
|
|
42
|
+
Examples
|
|
43
|
+
--------
|
|
44
|
+
>>> from sknetwork.data.toy_graphs import house
|
|
45
|
+
>>> adjacency = house()
|
|
46
|
+
>>> katz = Katz()
|
|
47
|
+
>>> scores = katz.fit_predict(adjacency)
|
|
48
|
+
>>> np.round(scores, 2)
|
|
49
|
+
array([6.5 , 8.25, 5.62, 5.62, 8.25])
|
|
50
|
+
|
|
51
|
+
References
|
|
52
|
+
----------
|
|
53
|
+
Katz, L. (1953). `A new status index derived from sociometric analysis
|
|
54
|
+
<https://link.springer.com/content/pdf/10.1007/BF02289026.pdf>`_. Psychometrika, 18(1), 39-43.
|
|
55
|
+
"""
|
|
56
|
+
def __init__(self, damping_factor: float = 0.5, path_length: int = 4):
|
|
57
|
+
super(Katz, self).__init__()
|
|
58
|
+
self.damping_factor = damping_factor
|
|
59
|
+
self.path_length = path_length
|
|
60
|
+
self.bipartite = None
|
|
61
|
+
|
|
62
|
+
def fit(self, input_matrix: Union[sparse.csr_matrix, np.ndarray, LinearOperator]) -> 'Katz':
|
|
63
|
+
"""Katz centrality.
|
|
64
|
+
|
|
65
|
+
Parameters
|
|
66
|
+
----------
|
|
67
|
+
input_matrix :
|
|
68
|
+
Adjacency matrix or biadjacency matrix of the graph.
|
|
69
|
+
|
|
70
|
+
Returns
|
|
71
|
+
-------
|
|
72
|
+
self: :class:`Katz`
|
|
73
|
+
"""
|
|
74
|
+
input_matrix = check_format(input_matrix)
|
|
75
|
+
adjacency, self.bipartite = get_adjacency(input_matrix)
|
|
76
|
+
n = adjacency.shape[0]
|
|
77
|
+
coefs = self.damping_factor ** np.arange(self.path_length + 1)
|
|
78
|
+
coefs[0] = 0.
|
|
79
|
+
polynome = Polynome(adjacency.T.astype(bool).tocsr(), coefs)
|
|
80
|
+
self.scores_ = polynome.dot(np.ones(n))
|
|
81
|
+
if self.bipartite:
|
|
82
|
+
self._split_vars(input_matrix.shape)
|
|
83
|
+
return self
|