From 7285e5e5780cd0c915bfb029e8066431c43e4c53 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Wed, 9 Feb 2022 14:32:05 -0800 Subject: [PATCH 01/32] Hyppo 0.2.2 (and possibly earlier) use a private scipy function that has been moved in 1.8.0+. Until hyppo fixes this we need to restrict scipy to an earlier version. --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index 7dd8f75ec..be445964d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -39,7 +39,7 @@ install_requires = POT>=0.7.0 seaborn>= 0.11.0 scikit-learn>=0.22.0 - scipy>=1.4.0 + scipy>=1.4.0,<1.8.0 # restricted due to hyppo 0.2.2 bug umap-learn>=0.4.6 [options.packages.find] From 9e19f0f7612af2f4fc6c40212cae26924469f82e Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Wed, 9 Feb 2022 15:35:41 -0800 Subject: [PATCH 02/32] Someone, somewhere, thinks that dropping Python 3.6 support is only worth a patch increment in semver, and I just don't know where to start with that --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index be445964d..e01a359b0 100644 --- a/setup.cfg +++ b/setup.cfg @@ -36,7 +36,7 @@ install_requires = matplotlib>=3.0.0,!=3.3.* networkx>=2.1 numpy>=1.8.1 - POT>=0.7.0 + POT>=0.7.0,<0.8.1 # 0.8.1 drops python 3.6 support seaborn>= 0.11.0 scikit-learn>=0.22.0 scipy>=1.4.0,<1.8.0 # restricted due to hyppo 0.2.2 bug From dcff6b2dc2f3bdd4656fef38fa5031d6a3d532f0 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Thu, 10 Feb 2022 11:03:33 -0800 Subject: [PATCH 03/32] This hyppo fix is getting out of control. We have now officially deprecated Python 3.6, no longer need to limit POT, require the latest beartype in all the land just to avoid deprecation warnings if we use the old Exceptions instead of the Violations, and I did a lot of packaging junk to ensure it won't even try to install on Python 3.6 now --- .github/workflows/build.yml | 2 +- README.md | 11 +++---- docs/reference/release.rst | 2 ++ graspologic/partition/leiden.py | 4 +-- .../embed/adjacency_spectral_embedding.py | 2 +- graspologic/pipeline/embed/embeddings.py | 2 +- .../embed/laplacian_spectral_embedding.py | 2 +- .../pipeline/embed/omnibus_embedding.py | 2 +- pyproject.toml | 2 +- setup.cfg | 6 ++-- tests/partition/test_leiden.py | 30 +++++++++---------- .../test_adjacency_spectral_embedding.py | 16 +++++----- tests/pipeline/embed/test_embeddings.py | 8 ++--- .../test_laplacian_spectral_embedding.py | 22 +++++++------- .../pipeline/embed/test_omnibus_embedding.py | 16 +++++----- tests/test_plot.py | 10 +++---- 16 files changed, 70 insertions(+), 67 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 454c6f6b1..0ad74de13 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python_version: [3.6, 3.7, 3.8, 3.9] + python_version: [3.7, 3.8, 3.9, 3.10] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index d1ea38347..3284d1541 100644 --- a/README.md +++ b/README.md @@ -35,10 +35,11 @@ Please visit the [tutorial section](https://microsoft.github.io/graspologic/late - macOS x64 - Windows 10 x64 -And across the following versions of Python: -- 3.6 (x64) -- 3.7 (x64) -- 3.8 (x64) +And across the following **x86_64** versions of Python: +- 3.7 +- 3.8 +- 3.9 +- 3.10 If you try to use `graspologic` for a different platform than the ones listed and notice any unexpected behavior, please feel free to [raise an issue](https://github.com/microsoft/graspologic/issues/new). It's better for ourselves and our users @@ -74,4 +75,4 @@ We appreciate detailed bug reports and feature requests (though we appreciate pu # Citing `graspologic` If you find `graspologic` useful in your work, please cite the package via the [GraSPy paper](http://www.jmlr.org/papers/volume20/19-490/19-490.pdf) -> Chung, J., Pedigo, B. D., Bridgeford, E. W., Varjavand, B. K., Helm, H. S., & Vogelstein, J. T. (2019). GraSPy: Graph Statistics in Python. Journal of Machine Learning Research, 20(158), 1-7. +> Chung, J., Pedigo, B. D., Bridgeford, E. W., Varjavand, B. K., Helm, H. S., & Vogelstein, J. T. (2019). GraSPy: Graph Statistics in Python. Journal of Machine Learning Research, 20(158), 1-7. \ No newline at end of file diff --git a/docs/reference/release.rst b/docs/reference/release.rst index 275c78a8b..bd19f92db 100644 --- a/docs/reference/release.rst +++ b/docs/reference/release.rst @@ -5,6 +5,8 @@ Release Log graspologic 1.0.0 ----------------- +- Removed Python 3.6 support +- Officially added Python 3.9 and 3.10 support - Fixed a type in an error message `#904 ` - Added support for arbitrarily indexed node data for networkplot diff --git a/graspologic/partition/leiden.py b/graspologic/partition/leiden.py index 579dc3e98..7b2fac7e4 100644 --- a/graspologic/partition/leiden.py +++ b/graspologic/partition/leiden.py @@ -274,7 +274,7 @@ def leiden( ------ ValueError TypeError - BeartypeCallHintPepParamException + BeartypeCallHintParamViolation See Also -------- @@ -539,7 +539,7 @@ def hierarchical_leiden( ------ ValueError TypeError - BeartypeCallHintPepParamException + BeartypeCallHintParamViolation See Also -------- diff --git a/graspologic/pipeline/embed/adjacency_spectral_embedding.py b/graspologic/pipeline/embed/adjacency_spectral_embedding.py index 65de295dd..2422014f7 100644 --- a/graspologic/pipeline/embed/adjacency_spectral_embedding.py +++ b/graspologic/pipeline/embed/adjacency_spectral_embedding.py @@ -106,7 +106,7 @@ def adjacency_spectral_embedding( Raises ------ - beartype.roar.BeartypeCallHintPepParamException if parameters do not match type hints + beartype.roar.BeartypeCallHintParamViolation if parameters do not match type hints ValueError if values are not within appropriate ranges or allowed values See Also diff --git a/graspologic/pipeline/embed/embeddings.py b/graspologic/pipeline/embed/embeddings.py index df44592fa..43629e2c4 100644 --- a/graspologic/pipeline/embed/embeddings.py +++ b/graspologic/pipeline/embed/embeddings.py @@ -56,7 +56,7 @@ def __init__(self, labels: np.ndarray, embeddings: np.ndarray): Raises ------ - beartype.roar.BeartypeCallHintPepParamException if the types are invalid + beartype.roar.BeartypeCallHintParamViolation if the types are invalid ValueError if the row count of labels does not equal the row count of embeddings """ if labels.shape[0] != embeddings.shape[0]: diff --git a/graspologic/pipeline/embed/laplacian_spectral_embedding.py b/graspologic/pipeline/embed/laplacian_spectral_embedding.py index ca631fe4c..160c84d58 100644 --- a/graspologic/pipeline/embed/laplacian_spectral_embedding.py +++ b/graspologic/pipeline/embed/laplacian_spectral_embedding.py @@ -109,7 +109,7 @@ def laplacian_spectral_embedding( Raises ------ - beartype.roar.BeartypeCallHintPepParamException if parameters do not match type hints + beartype.roar.BeartypeCallHintParamViolation if parameters do not match type hints ValueError if values are not within appropriate ranges or allowed values See Also diff --git a/graspologic/pipeline/embed/omnibus_embedding.py b/graspologic/pipeline/embed/omnibus_embedding.py index 202bc55b5..c145ef8b8 100644 --- a/graspologic/pipeline/embed/omnibus_embedding.py +++ b/graspologic/pipeline/embed/omnibus_embedding.py @@ -107,7 +107,7 @@ def omnibus_embedding_pairwise( Raises ------ - beartype.roar.BeartypeCallHintPepParamException if parameters do not match type hints + beartype.roar.BeartypeCallHintParamViolation if parameters do not match type hints ValueError if values are not within appropriate ranges or allowed values See Also diff --git a/pyproject.toml b/pyproject.toml index 092a7288c..69b4656bb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools"] +requires = ["setuptools >= 24.2.0"] build-backend = "setuptools.build_meta" [tool.isort] diff --git a/setup.cfg b/setup.cfg index e01a359b0..3446b10c8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,7 +17,6 @@ classifiers = Topic :: Scientific/Engineering :: Mathematics License :: OSI Approved :: MIT License Programming Language :: Python :: 3 - Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 @@ -26,9 +25,10 @@ classifiers = [options] packages = find: include_package_data = True +python_requires = >=3.7, <3.11 install_requires = anytree>=2.8.0 - beartype>=0.9.0 + beartype>=0.10.0 gensim>=4.0.0 graspologic-native>=1.1.1 hyppo>=0.2.2 @@ -36,7 +36,7 @@ install_requires = matplotlib>=3.0.0,!=3.3.* networkx>=2.1 numpy>=1.8.1 - POT>=0.7.0,<0.8.1 # 0.8.1 drops python 3.6 support + POT>=0.7.0 seaborn>= 0.11.0 scikit-learn>=0.22.0 scipy>=1.4.0,<1.8.0 # restricted due to hyppo 0.2.2 bug diff --git a/tests/partition/test_leiden.py b/tests/partition/test_leiden.py index 23d3b3416..a9ab9c880 100644 --- a/tests/partition/test_leiden.py +++ b/tests/partition/test_leiden.py @@ -8,7 +8,7 @@ import numpy as np import pytest import scipy -from beartype.roar import BeartypeCallHintPepParamException +from beartype.roar import BeartypeCallHintParamViolation from graspologic.partition import ( HierarchicalCluster, @@ -91,7 +91,7 @@ def test_correct_types(self): graph.add_edge("2", "3", weight=4.0) leiden(graph=graph, **good_args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["starting_communities"] = 123 leiden(graph=graph, **args) @@ -100,7 +100,7 @@ def test_correct_types(self): args["starting_communities"] = None leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["extra_forced_iterations"] = 1234.003 leiden(graph=graph, **args) @@ -110,7 +110,7 @@ def test_correct_types(self): args["extra_forced_iterations"] = -4003 leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["resolution"] = "leiden" leiden(graph=graph, **args) @@ -120,7 +120,7 @@ def test_correct_types(self): args["resolution"] = 0 leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["randomness"] = "leiden" leiden(graph=graph, **args) @@ -130,12 +130,12 @@ def test_correct_types(self): args["randomness"] = 0 leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["use_modularity"] = 1234 leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["trials"] = "hotdog" leiden(graph=graph, **args) @@ -151,7 +151,7 @@ def test_correct_types(self): args["random_seed"] = None leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["random_seed"] = "leiden" leiden(graph=graph, **args) @@ -161,23 +161,23 @@ def test_correct_types(self): args["random_seed"] = -1 leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["is_weighted"] = "leiden" leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["weight_default"] = "leiden" leiden(graph=graph, **args) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["check_directed"] = "leiden" leiden(graph=graph, **args) # one extra parameter hierarchical needs - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): args = good_args.copy() args["max_cluster_size"] = "leiden" hierarchical_leiden(graph=graph, **args) @@ -349,7 +349,7 @@ def test_empty_edge_list(self): def test_assert_list_does_not_contain_tuples(self): edges = ["invalid"] - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): _edge_list_to_edge_list( edges=edges, identifier=_IdentityMapper(), @@ -357,7 +357,7 @@ def test_assert_list_does_not_contain_tuples(self): def test_assert_list_contains_misshapen_tuple(self): edges = [(1, 2, 1.0, 1.0)] - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): _edge_list_to_edge_list( edges=edges, identifier=_IdentityMapper(), @@ -365,7 +365,7 @@ def test_assert_list_contains_misshapen_tuple(self): def test_assert_wrong_types_in_tuples(self): edges = [(True, 4, "sandwich")] - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): _edge_list_to_edge_list( edges=edges, identifier=_IdentityMapper(), diff --git a/tests/pipeline/embed/test_adjacency_spectral_embedding.py b/tests/pipeline/embed/test_adjacency_spectral_embedding.py index 675cfc888..0c411df5d 100644 --- a/tests/pipeline/embed/test_adjacency_spectral_embedding.py +++ b/tests/pipeline/embed/test_adjacency_spectral_embedding.py @@ -6,7 +6,7 @@ import networkx as nx import numpy as np import pytest -from beartype.roar import BeartypeCallHintPepParamException +from beartype.roar import BeartypeCallHintParamViolation import graspologic.utils from graspologic.embed import AdjacencySpectralEmbed @@ -44,7 +44,7 @@ def parameters(): def test_argument_validation(self): # graph types - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): adjacency_spectral_embedding( graph=np.array([[1, 2], [2, 1]]), **self.default_parameters ) @@ -56,7 +56,7 @@ def test_argument_validation(self): # dimensions dimensions = [None, 1.3, "1"] for dimension in dimensions: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["dimensions"] = dimension params["graph"] = self.graph @@ -65,19 +65,19 @@ def test_argument_validation(self): # elbow_cuts elbow_cuts = ["3", 1.3] for elbow_cut in elbow_cuts: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["elbow_cut"] = elbow_cut params["graph"] = self.graph adjacency_spectral_embedding(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["svd_solver_algorithm"] = 1 params["graph"] = self.graph adjacency_spectral_embedding(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["svd_solver_algorithm"] = "sandwich" params["graph"] = self.graph @@ -86,7 +86,7 @@ def test_argument_validation(self): # svd_solver_iterations svd_solver_iterations = [None, "5", 5.1] for ssi in svd_solver_iterations: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["svd_solver_iterations"] = ssi params["graph"] = self.graph @@ -95,7 +95,7 @@ def test_argument_validation(self): # svd_seed svd_seeds = ["5", 5.1] for svd_seed in svd_seeds: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestAdjacencySpectralEmbedding.parameters() params["svd_seed"] = svd_seed params["graph"] = self.graph diff --git a/tests/pipeline/embed/test_embeddings.py b/tests/pipeline/embed/test_embeddings.py index 806d8053a..fc0dc793f 100644 --- a/tests/pipeline/embed/test_embeddings.py +++ b/tests/pipeline/embed/test_embeddings.py @@ -4,7 +4,7 @@ import unittest import numpy as np -from beartype.roar import BeartypeCallHintPepParamException +from beartype.roar import BeartypeCallHintParamViolation from graspologic.pipeline.embed import Embeddings @@ -46,11 +46,11 @@ def test_view(self): np.testing.assert_array_equal(expected[key], view[key]) def test_argument_types(self): - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): Embeddings(None, None) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): Embeddings(np.array(["hello"]), None) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): Embeddings(["hello"], [1.0]) with self.assertRaises(ValueError): Embeddings(np.array(["hello"]), np.array([[1.1, 1.2], [2.1, 2.2]])) diff --git a/tests/pipeline/embed/test_laplacian_spectral_embedding.py b/tests/pipeline/embed/test_laplacian_spectral_embedding.py index 6d2201313..4c6de0a78 100644 --- a/tests/pipeline/embed/test_laplacian_spectral_embedding.py +++ b/tests/pipeline/embed/test_laplacian_spectral_embedding.py @@ -7,7 +7,7 @@ import networkx as nx import numpy as np import pytest -from beartype.roar import BeartypeCallHintPepParamException +from beartype.roar import BeartypeCallHintParamViolation import graspologic.utils from graspologic.embed import LaplacianSpectralEmbed @@ -43,7 +43,7 @@ def parameters(graph: Optional[Union[nx.Graph, nx.DiGraph]] = None): def test_argument_validation(self): # graph types - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters() params["graph"] = np.array([[1, 2], [2, 1]]) laplacian_spectral_embedding(**params) @@ -55,7 +55,7 @@ def test_argument_validation(self): # dimensions dimensions = [None, 1.3, "1"] for dimension in dimensions: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["dimensions"] = dimension laplacian_spectral_embedding(**params) @@ -63,17 +63,17 @@ def test_argument_validation(self): # elbow_cuts elbow_cuts = ["3", 1.3] for elbow_cut in elbow_cuts: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["elbow_cut"] = elbow_cut laplacian_spectral_embedding(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["svd_solver_algorithm"] = 1 laplacian_spectral_embedding(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["svd_solver_algorithm"] = "sandwich" laplacian_spectral_embedding(**params) @@ -81,7 +81,7 @@ def test_argument_validation(self): # svd_solver_iterations svd_solver_iterations = [None, "5", 5.1] for ssi in svd_solver_iterations: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["svd_solver_iterations"] = ssi laplacian_spectral_embedding(**params) @@ -89,7 +89,7 @@ def test_argument_validation(self): # svd_seed svd_seeds = ["5", 5.1] for svd_seed in svd_seeds: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["svd_seed"] = svd_seed laplacian_spectral_embedding(**params) @@ -97,17 +97,17 @@ def test_argument_validation(self): # form forms = [0, None] for form in forms: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["form"] = form laplacian_spectral_embedding(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["form"] = "formless" laplacian_spectral_embedding(**params) # regularizer - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = TestLaplacianSpectralEmbedding.parameters(self.graph) params["regularizer"] = "1" laplacian_spectral_embedding(**params) diff --git a/tests/pipeline/embed/test_omnibus_embedding.py b/tests/pipeline/embed/test_omnibus_embedding.py index ed86632e7..06ee7bc95 100644 --- a/tests/pipeline/embed/test_omnibus_embedding.py +++ b/tests/pipeline/embed/test_omnibus_embedding.py @@ -5,7 +5,7 @@ import networkx as nx import numpy as np -from beartype.roar import BeartypeCallHintPepParamException +from beartype.roar import BeartypeCallHintParamViolation from graspologic.pipeline.embed import omnibus_embedding_pairwise @@ -24,7 +24,7 @@ def _default_parameters(self): } def test_argument_validation(self): - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): omnibus_embedding_pairwise(graphs=[1]) with self.assertRaises(ValueError): @@ -35,7 +35,7 @@ def test_argument_validation(self): # dimensions dimensions = [None, 1.3, "1"] for dimension in dimensions: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["dimensions"] = dimension params["graphs"] = self.graphs @@ -44,19 +44,19 @@ def test_argument_validation(self): # elbow_cuts elbow_cuts = ["3", 1.3] for elbow_cut in elbow_cuts: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["elbow_cut"] = elbow_cut params["graphs"] = self.graphs omnibus_embedding_pairwise(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["svd_solver_algorithm"] = 1 params["graphs"] = self.graphs omnibus_embedding_pairwise(**params) - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["svd_solver_algorithm"] = "sandwich" params["graphs"] = self.graphs @@ -65,7 +65,7 @@ def test_argument_validation(self): # svd_solver_iterations svd_solver_iterations = [None, "5", 5.1] for ssi in svd_solver_iterations: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["svd_solver_iterations"] = ssi params["graphs"] = self.graphs @@ -74,7 +74,7 @@ def test_argument_validation(self): # svd_seed svd_seeds = ["5", 5.1] for svd_seed in svd_seeds: - with self.assertRaises(BeartypeCallHintPepParamException): + with self.assertRaises(BeartypeCallHintParamViolation): params = self._default_parameters() params["svd_seed"] = svd_seed params["graphs"] = self.graphs diff --git a/tests/test_plot.py b/tests/test_plot.py index 3a1d8c522..b92defa16 100644 --- a/tests/test_plot.py +++ b/tests/test_plot.py @@ -63,7 +63,7 @@ def test_common_inputs(self): figsize = "bad figsize" with self.assertRaises(TypeError): heatmap(X, figsize=figsize) - with self.assertRaises(beartype.roar.BeartypeCallHintPepParamException): + with self.assertRaises(beartype.roar.BeartypeCallHintParamViolation): with self.assertRaises(TypeError): networkplot(adjacency=X, x=x, y=y, figsize=figsize) @@ -82,7 +82,7 @@ def test_common_inputs(self): gridplot([X], grid_labels, title=title) with self.assertRaises(TypeError): pairplot(X, title=title) - with self.assertRaises(beartype.roar.BeartypeCallHintPepParamException): + with self.assertRaises(beartype.roar.BeartypeCallHintParamViolation): with self.assertRaises(TypeError): networkplot(adjacency=X, x=x, y=y, title=title) @@ -94,7 +94,7 @@ def test_common_inputs(self): gridplot([X], grid_labels, context=context) with self.assertRaises(TypeError): pairplot(X, context=context) - with self.assertRaises(beartype.roar.BeartypeCallHintPepParamException): + with self.assertRaises(beartype.roar.BeartypeCallHintParamViolation): with self.assertRaises(TypeError): networkplot(adjacency=X, x=x, y=y, context=context) @@ -117,7 +117,7 @@ def test_common_inputs(self): gridplot([X], grid_labels, font_scale=font_scale) with self.assertRaises(TypeError): pairplot(X, font_scale=font_scale) - with self.assertRaises(beartype.roar.BeartypeCallHintPepParamException): + with self.assertRaises(beartype.roar.BeartypeCallHintParamViolation): with self.assertRaises(TypeError): networkplot(adjacency=X, x=x, y=y, font_scale=font_scale) @@ -283,7 +283,7 @@ def test_networkplot_inputs(self): X = er_np(15, 0.5) x = np.random.rand(15, 1) y = np.random.rand(15, 1) - with self.assertRaises(beartype.roar.BeartypeCallHintPepParamException): + with self.assertRaises(beartype.roar.BeartypeCallHintParamViolation): with self.assertRaises(TypeError): networkplot(adjacency="test", x=x, y=y) From d27cfb71f0b12e156c4775f97eb26f39aeb6c485 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Thu, 10 Feb 2022 12:18:51 -0800 Subject: [PATCH 04/32] Fixing documentation now that we enabled inherited members by default again (it worked when we used older sphinx, but new sphinx broke since we were using a deprecated manner to signal we wanted to document class membership and inheritence automatically) --- .github/workflows/build.yml | 2 +- docs/conf.py | 11 +++++++++-- docs/reference/reference/cluster.rst | 1 + graspologic/embed/ase.py | 1 - graspologic/embed/base.py | 10 ++++++---- graspologic/inference/latent_distribution_test.py | 2 +- graspologic/inference/latent_position_test.py | 2 +- 7 files changed, 19 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0ad74de13..d0610d7b9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python_version: [3.7, 3.8, 3.9, 3.10] + python_version: ["3.7", "3.8", "3.9", "3.10"] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/docs/conf.py b/docs/conf.py index f829586da..5620e0eb5 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -63,8 +63,15 @@ # -- sphinx.ext.autodoc autoclass_content = "both" -autodoc_default_flags = ["members", "inherited-members"] -autodoc_member_order = "bysource" # default is alphabetical +autodoc_default_options = { + 'members': True, + 'inherited-members': True, + 'member-order': 'bysource', + 'special-members': '__init__', + 'undoc-members': True, +} +autodoc_class_signature = "separated" +autodoc_typehints = "description" # -- sphinx.ext.intersphinx intersphinx_mapping = { diff --git a/docs/reference/reference/cluster.rst b/docs/reference/reference/cluster.rst index c166c3b8c..702237a03 100644 --- a/docs/reference/reference/cluster.rst +++ b/docs/reference/reference/cluster.rst @@ -17,3 +17,4 @@ Gaussian Mixture Models Clustering Hierarchical Clustering ---------------------------------- .. autoclass:: DivisiveCluster + :no-inherited-members: diff --git a/graspologic/embed/ase.py b/graspologic/embed/ase.py index 44867377f..3c0cdd7cd 100644 --- a/graspologic/embed/ase.py +++ b/graspologic/embed/ase.py @@ -70,7 +70,6 @@ class AdjacencySpectralEmbed(BaseSpectralEmbed): randomized svd solver for deterministic, albeit pseudo-randomized behavior. - Attributes ---------- n_features_in_: int diff --git a/graspologic/embed/base.py b/graspologic/embed/base.py index cdfd46b46..428a94573 100644 --- a/graspologic/embed/base.py +++ b/graspologic/embed/base.py @@ -247,8 +247,10 @@ def fit_transform( def transform(self, X): # type: ignore """ Obtain latent positions from an adjacency matrix or matrix of out-of-sample - vertices. For more details on transforming out-of-sample vertices, see the - :ref:`tutorials `. For mathematical background, see [2]. + vertices. For more details on transforming out-of-sample vertices, see `Out-of-Sample (OOS) Embedding + `_ + + For mathematical background, see [2]. Parameters ---------- @@ -293,8 +295,8 @@ def transform(self, X): # type: ignore References ---------- .. [1] Sussman, D.L., Tang, M., Fishkind, D.E., Priebe, C.E. "A - Consistent Adjacency Spectral Embedding for Stochastic Blockmodel Graphs," - Journal of the American Statistical Association, Vol. 107(499), 2012 + Consistent Adjacency Spectral Embedding for Stochastic Blockmodel Graphs," + Journal of the American Statistical Association, Vol. 107(499), 2012 .. [2] Levin, K., Roosta-Khorasani, F., Mahoney, M. W., & Priebe, C. E. (2018). Out-of-sample extension of graph adjacency spectral embedding. PMLR: Proceedings diff --git a/graspologic/inference/latent_distribution_test.py b/graspologic/inference/latent_distribution_test.py index 72aa6e0b4..fb1b34866 100644 --- a/graspologic/inference/latent_distribution_test.py +++ b/graspologic/inference/latent_distribution_test.py @@ -203,7 +203,7 @@ def latent_distribution_test( d must be same. n_components attribute is ignored in this case. Returns - ---------- + ------- stat : float The observed difference between the embedded latent positions of the two input graphs. diff --git a/graspologic/inference/latent_position_test.py b/graspologic/inference/latent_position_test.py index a57fb50b8..1ef67d8a1 100644 --- a/graspologic/inference/latent_position_test.py +++ b/graspologic/inference/latent_position_test.py @@ -88,7 +88,7 @@ def latent_position_test( Supply -1 to use all cores available. Returns - ---------- + ------- stat : float The observed difference between the embedded positions of the two input graphs after an alignment (the type of alignment depends on ``test_case``) From 0c4357840b3f6f49e335281c55a9aa6c18f744cc Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Thu, 10 Feb 2022 12:26:30 -0800 Subject: [PATCH 05/32] So much for adding 3.10 support - gensim is not working with 3.10, similar to our problems using gensim 3.8.3 on 3.6 last week --- .github/workflows/build.yml | 2 +- README.md | 3 +-- docs/reference/release.rst | 2 +- setup.cfg | 3 +-- 4 files changed, 4 insertions(+), 6 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d0610d7b9..68371060c 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -89,7 +89,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python_version: ["3.7", "3.8", "3.9", "3.10"] + python_version: ["3.7", "3.8", "3.9"] fail-fast: false steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 3284d1541..9ff814a10 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ And across the following **x86_64** versions of Python: - 3.7 - 3.8 - 3.9 -- 3.10 If you try to use `graspologic` for a different platform than the ones listed and notice any unexpected behavior, please feel free to [raise an issue](https://github.com/microsoft/graspologic/issues/new). It's better for ourselves and our users @@ -75,4 +74,4 @@ We appreciate detailed bug reports and feature requests (though we appreciate pu # Citing `graspologic` If you find `graspologic` useful in your work, please cite the package via the [GraSPy paper](http://www.jmlr.org/papers/volume20/19-490/19-490.pdf) -> Chung, J., Pedigo, B. D., Bridgeford, E. W., Varjavand, B. K., Helm, H. S., & Vogelstein, J. T. (2019). GraSPy: Graph Statistics in Python. Journal of Machine Learning Research, 20(158), 1-7. \ No newline at end of file +> Chung, J., Pedigo, B. D., Bridgeford, E. W., Varjavand, B. K., Helm, H. S., & Vogelstein, J. T. (2019). GraSPy: Graph Statistics in Python. Journal of Machine Learning Research, 20(158), 1-7. diff --git a/docs/reference/release.rst b/docs/reference/release.rst index bd19f92db..2a95947b1 100644 --- a/docs/reference/release.rst +++ b/docs/reference/release.rst @@ -6,7 +6,7 @@ Release Log graspologic 1.0.0 ----------------- - Removed Python 3.6 support -- Officially added Python 3.9 and 3.10 support +- Officially added Python 3.9 support - Fixed a type in an error message `#904 ` - Added support for arbitrarily indexed node data for networkplot diff --git a/setup.cfg b/setup.cfg index 3446b10c8..0752b2ff6 100644 --- a/setup.cfg +++ b/setup.cfg @@ -20,12 +20,11 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 [options] packages = find: include_package_data = True -python_requires = >=3.7, <3.11 +python_requires = >=3.7, <3.10 install_requires = anytree>=2.8.0 beartype>=0.10.0 From 024b86ae07d3d8772440658ecb35c084a074c5c0 Mon Sep 17 00:00:00 2001 From: bdpedigo Date: Thu, 10 Feb 2022 15:49:34 -0500 Subject: [PATCH 06/32] try removing scipy cap but bumping hyppo --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 0752b2ff6..a213a454d 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ install_requires = beartype>=0.10.0 gensim>=4.0.0 graspologic-native>=1.1.1 - hyppo>=0.2.2 + hyppo>=0.3.0 joblib>=0.17.0 # Older versions of joblib cause issue #806. Transitive dependency of hyppo. matplotlib>=3.0.0,!=3.3.* networkx>=2.1 @@ -38,7 +38,7 @@ install_requires = POT>=0.7.0 seaborn>= 0.11.0 scikit-learn>=0.22.0 - scipy>=1.4.0,<1.8.0 # restricted due to hyppo 0.2.2 bug + scipy>=1.4.0 umap-learn>=0.4.6 [options.packages.find] From 41bdf5e29c61d0ed4bcd6afe966e447fa5cb74bb Mon Sep 17 00:00:00 2001 From: bdpedigo Date: Thu, 10 Feb 2022 16:11:20 -0500 Subject: [PATCH 07/32] bump to 0.3.1 --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index a213a454d..aeb5ff201 100644 --- a/setup.cfg +++ b/setup.cfg @@ -30,7 +30,7 @@ install_requires = beartype>=0.10.0 gensim>=4.0.0 graspologic-native>=1.1.1 - hyppo>=0.3.0 + hyppo>=0.3.1 joblib>=0.17.0 # Older versions of joblib cause issue #806. Transitive dependency of hyppo. matplotlib>=3.0.0,!=3.3.* networkx>=2.1 From f51538c6c5371bbf59f9225f8797db73a1738f35 Mon Sep 17 00:00:00 2001 From: bdpedigo Date: Thu, 10 Feb 2022 16:51:45 -0500 Subject: [PATCH 08/32] bump hyppo again --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index aeb5ff201..c060b6922 100644 --- a/setup.cfg +++ b/setup.cfg @@ -27,10 +27,10 @@ include_package_data = True python_requires = >=3.7, <3.10 install_requires = anytree>=2.8.0 - beartype>=0.10.0 + beartype>=0.10.0 gensim>=4.0.0 graspologic-native>=1.1.1 - hyppo>=0.3.1 + hyppo>=0.3.2 # bug with lower versions and scipy>=1.8 joblib>=0.17.0 # Older versions of joblib cause issue #806. Transitive dependency of hyppo. matplotlib>=3.0.0,!=3.3.* networkx>=2.1 From 39170a163f7391f69079c090280c7820782abcf1 Mon Sep 17 00:00:00 2001 From: Julien Cortesi Date: Fri, 11 Feb 2022 14:28:45 +0000 Subject: [PATCH 09/32] Fixed typos in models/er.py & models/sbm_estimators.py (#920) Co-authored-by: Benjamin Pedigo --- graspologic/models/er.py | 4 ++-- graspologic/models/sbm_estimators.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/graspologic/models/er.py b/graspologic/models/er.py index 0203b0a3a..584159b40 100644 --- a/graspologic/models/er.py +++ b/graspologic/models/er.py @@ -26,7 +26,7 @@ class EREstimator(SBMEstimator): Parameters ---------- directed : boolean, optional (default=True) - Whether to treat the input graph as directed. Even if a directed graph is inupt, + Whether to treat the input graph as directed. Even if a directed graph is input, this determines whether to force symmetry upon the block probability matrix fit for the SBM. It will also determine whether graphs sampled from the model are directed. @@ -87,7 +87,7 @@ class DCEREstimator(DCSBMEstimator): Parameters ---------- directed : boolean, optional (default=True) - Whether to treat the input graph as directed. Even if a directed graph is inupt, + Whether to treat the input graph as directed. Even if a directed graph is input, this determines whether to force symmetry upon the block probability matrix fit for the SBM. It will also determine whether graphs sampled from the model are directed. diff --git a/graspologic/models/sbm_estimators.py b/graspologic/models/sbm_estimators.py index 2009cbcb8..515466a1d 100644 --- a/graspologic/models/sbm_estimators.py +++ b/graspologic/models/sbm_estimators.py @@ -73,7 +73,7 @@ class SBMEstimator(BaseGraphEstimator): Parameters ---------- directed : boolean, optional (default=True) - Whether to treat the input graph as directed. Even if a directed graph is inupt, + Whether to treat the input graph as directed. Even if a directed graph is input, this determines whether to force symmetry upon the block probability matrix fit for the SBM. It will also determine whether graphs sampled from the model are directed. @@ -266,7 +266,7 @@ class DCSBMEstimator(BaseGraphEstimator): Parameters ---------- directed : boolean, optional (default=True) - Whether to treat the input graph as directed. Even if a directed graph is inupt, + Whether to treat the input graph as directed. Even if a directed graph is input, this determines whether to force symmetry upon the block probability matrix fit for the SBM. It will also determine whether graphs sampled from the model are directed. From 7a2f22beefa4a5a70822a3a298961f1f7c17d096 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Fri, 11 Feb 2022 09:16:34 -0800 Subject: [PATCH 10/32] Preparing for 1.0.1 or other versions --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index c060b6922..ddbe41c40 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = graspologic -version = 1.0.0 +version = 1.0.1 description = A set of python modules for graph statistics long_description = file: README.md From ff34382d1ffa0b7ea5f0e005525b7364f977e86f Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Fri, 11 Feb 2022 09:43:20 -0800 Subject: [PATCH 11/32] Updating the development status --- setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.cfg b/setup.cfg index ddbe41c40..938645e0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -12,7 +12,7 @@ maintainer_email = daxpryce@microsoft.com url = https://github.com/microsoft/graspologic license = MIT classifiers = - Development Status :: 3 - Alpha + Development Status :: 5 - Production/Stable Intended Audience :: Science/Research Topic :: Scientific/Engineering :: Mathematics License :: OSI Approved :: MIT License From cb0f5a50dd98fdc1f9513c3a1ac635b497fdde9c Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Fri, 1 Apr 2022 07:12:10 -0700 Subject: [PATCH 12/32] Error message in Leiden when given a multigraph was incorrect (#926) The exception we raise when given a networkx graph if it's directed or a multigraph implies the only error condition is that it's a directed graph, when that isn't the case. --- graspologic/partition/leiden.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graspologic/partition/leiden.py b/graspologic/partition/leiden.py index 7b2fac7e4..43dff7f7e 100644 --- a/graspologic/partition/leiden.py +++ b/graspologic/partition/leiden.py @@ -50,7 +50,7 @@ def _nx_to_edge_list( check_argument( isinstance(graph, nx.Graph) and not (graph.is_directed() or graph.is_multigraph()), - "Only undirected networkx graphs are supported", + "Only undirected non-multi-graph networkx graphs are supported", ) native_safe: List[Tuple[str, str, float]] = [] edge_iter = ( From c85cb22471b36476251f3615c0dc07dadb4530d3 Mon Sep 17 00:00:00 2001 From: Eric Bridgeford Date: Wed, 13 Apr 2022 12:37:30 -0400 Subject: [PATCH 13/32] Fixed loops bug in SBM and DCSBM model fitting (#930) * hotfix for #928 * updated formatting * Update setup.cfg * Update setup.cfg Co-authored-by: Benjamin Pedigo --- graspologic/models/sbm_estimators.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/graspologic/models/sbm_estimators.py b/graspologic/models/sbm_estimators.py index 515466a1d..51ed86783 100644 --- a/graspologic/models/sbm_estimators.py +++ b/graspologic/models/sbm_estimators.py @@ -209,7 +209,9 @@ def fit( if not self.loops: graph = remove_loops(graph) - block_p = _calculate_block_p(graph, block_inds, block_vert_inds) + block_p = _calculate_block_p( + graph, block_inds, block_vert_inds, loops=self.loops + ) if not self.directed: block_p = symmetrize(block_p) @@ -409,7 +411,9 @@ def fit( if not self.loops: graph = graph - np.diag(np.diag(graph)) - block_p = _calculate_block_p(graph, block_inds, block_vert_inds) + block_p = _calculate_block_p( + graph, block_inds, block_vert_inds, loops=self.loops + ) out_degree = np.count_nonzero(graph, axis=1).astype(float) in_degree = np.count_nonzero(graph, axis=0).astype(float) @@ -484,12 +488,14 @@ def _calculate_block_p( block_inds: Collection[int], block_vert_inds: List[int], return_counts: bool = False, + loops: bool = False, ) -> np.ndarray: """ graph : input n x n graph block_inds : list of length n_communities block_vert_inds : list of list, for each block index, gives every node in that block return_counts : whether to calculate counts rather than proportions + loops : whether self loops are possible in the graph """ n_blocks = len(block_inds) @@ -502,6 +508,10 @@ def _calculate_block_p( from_inds = block_vert_inds[from_block] to_inds = block_vert_inds[to_block] block = graph[from_inds, :][:, to_inds] + # if a block is from a community to itself, self loops are possible, so remove + # them from the computation to avoid underbias + if from_block == to_block and not loops: + block = block[~np.eye(block.shape[0], dtype=bool)] if return_counts: p = np.count_nonzero(block) else: From e6c45cfc5578f96856c19cd01689f171e929a429 Mon Sep 17 00:00:00 2001 From: Benjamin Pedigo Date: Wed, 27 Apr 2022 17:48:04 -0400 Subject: [PATCH 14/32] fix mypy issue (#943) --- graspologic/simulations/simulations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/graspologic/simulations/simulations.py b/graspologic/simulations/simulations.py index 11eb1d58e..3f94f60ad 100644 --- a/graspologic/simulations/simulations.py +++ b/graspologic/simulations/simulations.py @@ -1000,7 +1000,7 @@ def mmsbm( # Naming convention follows paper listed in references. mm_vectors = rng.dirichlet(alpha_checked, n) - mm_vectors = np.array(sorted(mm_vectors, key=lambda x: np.argmax(x))) + mm_vectors = np.array(sorted(mm_vectors, key=np.argmax)) # labels:(n,n) matrix with all membership indicators for initiators and receivers # instead of storing the indicator vector, argmax is directly computed From 0f923d9055893076c099777799301af114162a97 Mon Sep 17 00:00:00 2001 From: kareef928 <51966539+kareef928@users.noreply.github.com> Date: Thu, 5 May 2022 15:16:28 -0400 Subject: [PATCH 15/32] Added Degree Preserving Edge Swaps (#935) * LPT tutorial render fix attempt * lpt tutorial changes * change order of inference functions return * fix add_variance * Revert "fix add_variance" This reverts commit 47b0c4d2eb76e4e0a03ed02916f1711722bf2b4f. * fix tutorials * create function * update edge swap * remove initial loops condition * less than two edges check * typo * add scipy function * finish scipy function * fix scipy function * add scipy function * remove print statements for sim * add edge swap tests * add scipy check_swaps method * add swap functions to init * fix functions * refactor numpy and scipy into one function * add functions to init * make numba workable * make edge swaps a class * remove no_jit function * fix tests * fix pr errors * add numba to mypy * sort imports * fix formatting * make edge_list an instance variable * sort imports * add docstrings * fix seed * fix seed * undirected implementation * fix type of edge list * format tests * remove extra line * add dpes tutorial * fix errors * fix numba import * add dpes to tutorials index * fix errors * remove print statements from test * Delete dpes.ipynb * formatting of tests * reformat tests * fix tutorials * fix seed type hinting * black * fix directed check * add scipy test * format * format * update language * Update index.rst * Update graspologic/models/edge_swaps.py * Update docs * update docs * fix bug * fix errors * format: * ensure build * change type hinting * remove some unused imports * remove unused parameter * simplify some input checking * simplify checking logic more * fix issue with not making a copy * update to use import_graph * manipulate LIL matrices * remove unused imports * simplify notebook and clear outputs * try reworking to use JIT optionally as a function * typo * fix seed * fix seed * format Co-authored-by: Benjamin Pedigo --- docs/tutorials/index.rst | 5 +- docs/tutorials/models/edge_swaps.ipynb | 172 ++++++++++++++++++++++ docs/tutorials/models/models.ipynb | 2 +- graspologic/models/__init__.py | 2 + graspologic/models/edge_swaps.py | 191 +++++++++++++++++++++++++ graspologic/utils/utils.py | 3 +- mypy.ini | 3 + tests/test_models.py | 39 +++++ 8 files changed, 414 insertions(+), 3 deletions(-) create mode 100644 docs/tutorials/models/edge_swaps.ipynb create mode 100644 graspologic/models/edge_swaps.py diff --git a/docs/tutorials/index.rst b/docs/tutorials/index.rst index 131f3a269..dc97436e8 100644 --- a/docs/tutorials/index.rst +++ b/docs/tutorials/index.rst @@ -8,14 +8,17 @@ Tutorials Models ====== -This tutorial presents several random graph models: the Erdos-Renyi (ER) model, degree-corrected ER model, +The first tutorial presents several random graph models: the Erdos-Renyi (ER) model, degree-corrected ER model, stochastic block model (SBM), degree-corrected SBM, and random dot product graph model. These models provide a basis for studying random graphs. All models are shown fit to the same dataset. +The next tutorial demonstrates how to sample graphs of the same degree sequence using degree preserving edge swaps. + .. toctree:: :maxdepth: 1 :titlesonly: models/models + models/edge_swaps .. _simulations_tutorials: diff --git a/docs/tutorials/models/edge_swaps.ipynb b/docs/tutorials/models/edge_swaps.ipynb new file mode 100644 index 000000000..ed2059c4d --- /dev/null +++ b/docs/tutorials/models/edge_swaps.ipynb @@ -0,0 +1,172 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Degree Preserving Edge Swaps" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "from graspologic.datasets import load_drosophila_right\n", + "from graspologic.models import EdgeSwapper\n", + "from graspologic.plot import heatmap\n", + "from graspologic.utils import binarize, symmetrize\n", + "import networkx as nx\n", + "from scipy.sparse import csr_matrix" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`EdgeSwapper` is a class that performs degree preserving edge swaps on networks. The distributions of graphs with a fixed degree sequence are known as configuration models, and these have extensive application for analyzing network datasets. The current implementation works on simple graphs (unewighted, no loops) that are of type `np.ndarray` or `csr_matrix`." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let us run dpes on these graphs and ensure that they have the same degree sequence" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To begin, we'll look at an example network, the _Drosophila melanogaster_ larva right mushroom body connectome from [Eichler et al. 2017](https://www.ncbi.nlm.nih.gov/pubmed/28796202). \n", + "\n", + "Note: here we make the network undirected and unweighted for compatibility with the current\n", + "implementation." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#load the data\n", + "adj, labels = load_drosophila_right(return_labels=True)\n", + "adj = symmetrize(adj)\n", + "adj = binarize(adj)\n", + "_ = heatmap(adj,\n", + " inner_hier_labels=labels,\n", + " title='Drosophila right MB',\n", + " font_scale=1.5,\n", + " sort_nodes=True, \n", + " cbar=False)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, we'll use `EdgeSwapper` to perform 10,000 random degree-preserving edge swaps - this\n", + "will dramatically change the structure of the network but keep the degree of each node\n", + "the same. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "swapper = EdgeSwapper(adj)\n", + "swapped_adj, _ = swapper.swap_edges(n_swaps=10000, seed=8888)\n", + "_ = heatmap(swapped_adj,\n", + " title='Drosophila right MB swapped',\n", + " font_scale=1.5,\n", + " sort_nodes=True, \n", + " inner_hier_labels=labels,\n", + " cbar=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can see how the structure of the network above has changed: for example, there are\n", + "now many edges among \"I\" (input) neurons when there were none before. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can verify that the degree of each node in the network has been preserved:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "g = nx.from_numpy_array(adj)\n", + "swapped_g = nx.from_numpy_array(swapped_adj)\n", + "print(list(g.degree()) == list(swapped_g.degree()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`EdgeSwapper` also works with `csr_matrix` adjacency representations. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "swapper = EdgeSwapper(csr_matrix(adj))\n", + "swapped_adj, _ = swapper.swap_edges(n_swaps=1000, seed=8888)\n", + "g = nx.from_numpy_array(adj)\n", + "swapped_g = nx.from_numpy_array(swapped_adj)\n", + "print(list(g.degree()) == list(swapped_g.degree()))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Often, degree-preserving edge swaps are used to sample a series of networks which resemble\n", + "the original network in degree, but are otherwise random. This distribution of networks\n", + "(sometimes called a configuration model) can be used to compare properties of the original\n", + "network to this null distribution in order to evaluate whether some property is more or\n", + "less prevalent in a given network than would be expected by chance. However, it is important\n", + "to know that in practice, it can be difficult to tell _how many_ edge swaps to perform\n", + "to find a new network which is independent from the one you started with. " + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.9.7" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/docs/tutorials/models/models.ipynb b/docs/tutorials/models/models.ipynb index 89d8064d1..bf5e0169c 100644 --- a/docs/tutorials/models/models.ipynb +++ b/docs/tutorials/models/models.ipynb @@ -362,7 +362,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.8.4" } }, "nbformat": 4, diff --git a/graspologic/models/__init__.py b/graspologic/models/__init__.py index 4dede1996..e6a94ba02 100644 --- a/graspologic/models/__init__.py +++ b/graspologic/models/__init__.py @@ -2,6 +2,7 @@ # Licensed under the MIT License. from .base import BaseGraphEstimator +from .edge_swaps import EdgeSwapper from .er import DCEREstimator, EREstimator from .rdpg import RDPGEstimator from .sbm_estimators import DCSBMEstimator, SBMEstimator @@ -13,4 +14,5 @@ "SBMEstimator", "DCSBMEstimator", "RDPGEstimator", + "EdgeSwapper", ] diff --git a/graspologic/models/edge_swaps.py b/graspologic/models/edge_swaps.py new file mode 100644 index 000000000..4b0334dbe --- /dev/null +++ b/graspologic/models/edge_swaps.py @@ -0,0 +1,191 @@ +from typing import Optional + +import numba as nb +import numpy as np +from beartype import beartype +from scipy.sparse import csr_matrix, lil_matrix + +from graspologic.preconditions import check_argument +from graspologic.types import AdjacencyMatrix, Tuple +from graspologic.utils import import_graph, is_loopless, is_symmetric, is_unweighted + + +# Code based on: https://github.com/joelnish/double-edge-swap-mcmc/blob/master/dbl_edge_mcmc.py +class EdgeSwapper: + """ + Degree Preserving Edge Swaps + + This class allows for performing degree preserving edge swaps to + generate new networks with the same degree sequence as the input network. + + Attributes + ---------- + adjacency : np.ndarray OR csr_matrix, shape (n_verts, n_verts) + The initial adjacency matrix to perform edge swaps on. Must be unweighted and undirected. + + edge_list : np.ndarray, shape (n_verts, 2) + The corresponding edgelist for the input network + + + References + ---------- + .. [1] Fosdick, B. K., Larremore, D. B., Nishimura, J., & Ugander, J. (2018). + Configuring random graph models with fixed degree sequences. + Siam Review, 60(2), 315-355. + + .. [2] Carstens, C. J., & Horadam, K. J. (2017). + Switching edges to randomize networks: what goes wrong and how to fix it. + Journal of Complex Networks, 5(3), 337-351. + + .. [3] https://github.com/joelnish/double-edge-swap-mcmc/blob/master/dbl_edge_mcmc.py + """ + + @beartype + def __init__(self, adjacency: AdjacencyMatrix): + + weight_check = is_unweighted(adjacency) + check_argument(weight_check, "adjacency must be unweighted") + + loop_check = is_loopless(adjacency) + check_argument(loop_check, "adjacency cannot have loops") + + direct_check = is_symmetric(adjacency) + check_argument(direct_check, "adjacency must be undirected") + + adjacency = import_graph(adjacency, copy=True) + + if isinstance(adjacency, csr_matrix): + # more efficient for manipulations which change sparsity structure + adjacency = lil_matrix(adjacency) + self._edge_swap_function = _edge_swap + else: + # for numpy input, use numba for JIT compilation + # NOTE: not convinced numba is helping much here, look into optimizing + self._edge_swap_function = nb.jit(_edge_swap) + + self.adjacency = adjacency + + edge_list = self._do_setup() + check_argument(len(edge_list) >= 2, "there must be at least 2 edges") + self.edge_list = edge_list + + def _do_setup(self) -> np.ndarray: + """ + Computes the edge_list from the adjancency matrix + + Returns + ------- + edge_list : np.ndarray, shape (n_verts, 2) + The corresponding edge_list of adjacency + """ + + # get edges for upper triangle of undirected graph + row_inds, col_inds = np.nonzero(self.adjacency) + upper = row_inds < col_inds + row_inds = row_inds[upper] + col_inds = col_inds[upper] + edge_list = np.stack((row_inds, col_inds)).T + return edge_list + + def swap_edges( + self, n_swaps: int = 1, seed: Optional[int] = None + ) -> Tuple[AdjacencyMatrix, np.ndarray]: + """ + Performs a number of edge swaps on the graph + + Parameters + ---------- + n_swaps : int (default 1), optional + The number of edge swaps to be performed + + Returns + ------- + self.adjacency : np.ndarray OR csr.matrix, shape (n_verts, n_verts) + The adjancency matrix after a number of edge swaps are performed on the graph + + self.edge_list : np.ndarray (n_verts, 2) + The edge_list after a number of edge swaps are perfomed on the graph + """ + + for _ in range(n_swaps): + self.adjacency, self.edge_list = self._edge_swap_function( + self.adjacency, self.edge_list, seed + ) + + adjacency = self.adjacency + if isinstance(adjacency, lil_matrix): + adjacency = csr_matrix(adjacency) + + return adjacency, self.edge_list + + +def _edge_swap( + adjacency: AdjacencyMatrix, edge_list: np.ndarray, seed: Optional[int] = None +) -> Tuple[AdjacencyMatrix, np.ndarray]: + """ + Performs the edge swap on the adjacency matrix. If adjacency is + np.ndarray, then nopython=True is used in numba, but if adjacency + is csr_matrix, then forceobj=True is used in numba + + Parameters + ---------- + adjacency : np.ndarray OR csr_matrix, shape (n_verts, n_verts) + The initial adjacency matrix in which edge swaps are performed on it + + edge_list : np.ndarray, shape (n_verts, 2) + The corresponding edge_list of adjacency + + Returns + ------- + adjacency : np.ndarray OR csr_matrix, shape (n_verts, n_verts) + The adjancency matrix after an edge swap is performed on the graph + + edge_list : np.ndarray (n_verts, 2) + The edge_list after an edge swap is perfomed on the graph + """ + if seed is not None: + np.random.seed(seed) + + # choose two indices at random + # NOTE: using np.random here for current numba compatibility + orig_inds = np.random.choice(len(edge_list), size=2, replace=False) + + u, v = edge_list[orig_inds[0]] + + # two types of swap orientations for undirected graph + if np.random.rand() < 0.5: + x, y = edge_list[orig_inds[1]] + else: + y, x = edge_list[orig_inds[1]] + + # ensures no initial loops + if u == v or x == y: + return adjacency, edge_list + + # ensures no loops after swap (must be swap on 4 distinct nodes) + if u == x or v == y: + return adjacency, edge_list + + # save edge values + w_ux = adjacency[u, x] + w_vy = adjacency[v, y] + + # ensures no multigraphs after swap + if w_ux >= 1 or w_vy >= 1: + return adjacency, edge_list + + # perform the swap + adjacency[u, v] = 0 + adjacency[v, u] = 0 + adjacency[x, y] = 0 + adjacency[y, x] = 0 + + adjacency[u, x] = 1 + adjacency[x, u] = 1 + adjacency[v, y] = 1 + adjacency[y, v] = 1 + + # update edge list + edge_list[orig_inds[0]] = [u, x] + edge_list[orig_inds[1]] = [v, y] + return adjacency, edge_list diff --git a/graspologic/utils/utils.py b/graspologic/utils/utils.py index 147be0a8e..ea67a74ec 100644 --- a/graspologic/utils/utils.py +++ b/graspologic/utils/utils.py @@ -208,7 +208,8 @@ def is_symmetric(X: np.ndarray) -> bool: def is_loopless(X: np.ndarray) -> bool: - return not np.any(np.diag(X) != 0) + diag_indices = np.diag_indices_from(X) + return not np.any(X[diag_indices] != 0) def is_unweighted( diff --git a/mypy.ini b/mypy.ini index b1e5ae02e..00412aa2a 100644 --- a/mypy.ini +++ b/mypy.ini @@ -26,6 +26,9 @@ ignore_missing_imports = True [mypy-mpl_toolkits.*] ignore_missing_imports = True +[mypy-numba.*] +ignore_missing_imports = True + [mypy-numpy] ignore_missing_imports = True diff --git a/tests/test_models.py b/tests/test_models.py index 70e4ee616..e03746eb4 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -3,14 +3,17 @@ import unittest +import networkx as nx import numpy as np from numpy.testing import assert_allclose +from scipy.sparse import csr_matrix from sklearn.exceptions import NotFittedError from sklearn.metrics import adjusted_rand_score from graspologic.models import ( DCEREstimator, DCSBMEstimator, + EdgeSwapper, EREstimator, RDPGEstimator, SBMEstimator, @@ -590,6 +593,42 @@ def _test_score(estimator, p_mat, graph): assert np.sum(lik) == estimator.score(graph) +class TestEdgeSwaps(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.A = er_np(100, 0.5) + cls.B = csr_matrix(cls.A) + cls.C = nx.from_numpy_array(cls.A) + cls.D = nx.from_scipy_sparse_matrix(cls.B) + + def test_numpy_edge_swap(self): + Swapper = EdgeSwapper(self.A) + swapped_er, _ = Swapper.swap_edges(n_swaps=100) + swapped_er_nx = nx.from_numpy_array(swapped_er) + assert list(self.C.degree()) == list(swapped_er_nx.degree()) + + def test_scipy_edge_swap(self): + Swapper = EdgeSwapper(self.B) + swapped_csr, _ = Swapper.swap_edges(n_swaps=100) + swapped_csr = swapped_csr.toarray() + swapped_csr_nx = nx.from_numpy_array(swapped_csr) + assert list(self.D.degree()) == list(swapped_csr_nx.degree()) + + def test_rep_numpy(self): + Swapper = EdgeSwapper(self.A) + swapped_er_1, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + swapped_er_2, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + assert (swapped_er_1 == swapped_er_2).all() + + def test_rep_scipy(self): + Swapper = EdgeSwapper(self.B) + swapped_csr_1, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + swapped_csr_2, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + swapped_csr_1 = swapped_csr_1.toarray() + swapped_csr_2 = swapped_csr_2.toarray() + assert (swapped_csr_1 == swapped_csr_2).all() + + def hardy_weinberg(theta): """ Maps a value from [0, 1] to the hardy weinberg curve. From 0d404caaa706f7bfbad694879c2e0d14bf3baaef Mon Sep 17 00:00:00 2001 From: Benjamin Pedigo Date: Tue, 10 May 2022 14:50:11 -0400 Subject: [PATCH 16/32] [BUG] Fixes reproducibility in EdgeSwapper and adds to docs (#945) * fix seeding and copying of outputs * fix reproducibility testing logic * add to documentation * fix notebook * windows can't handle the uint * try to fix windows bug * try to fix the fix * try uint32 again --- docs/reference/reference/models.rst | 5 ++++ docs/tutorials/models/edge_swaps.ipynb | 8 +++--- graspologic/models/edge_swaps.py | 38 ++++++++++++++++++++------ tests/test_models.py | 23 +++++++++++----- 4 files changed, 55 insertions(+), 19 deletions(-) diff --git a/docs/reference/reference/models.rst b/docs/reference/reference/models.rst index 18d90ab07..830d78a64 100644 --- a/docs/reference/reference/models.rst +++ b/docs/reference/reference/models.rst @@ -21,3 +21,8 @@ Latent position models ---------------------- .. autoclass:: RDPGEstimator + +Edge swapping (configuration models) +------------------------------------ + +.. autoclass:: EdgeSwapper \ No newline at end of file diff --git a/docs/tutorials/models/edge_swaps.ipynb b/docs/tutorials/models/edge_swaps.ipynb index ed2059c4d..dfce5c63d 100644 --- a/docs/tutorials/models/edge_swaps.ipynb +++ b/docs/tutorials/models/edge_swaps.ipynb @@ -78,8 +78,8 @@ "metadata": {}, "outputs": [], "source": [ - "swapper = EdgeSwapper(adj)\n", - "swapped_adj, _ = swapper.swap_edges(n_swaps=10000, seed=8888)\n", + "swapper = EdgeSwapper(adj, seed=8888)\n", + "swapped_adj, _ = swapper.swap_edges(n_swaps=10000)\n", "_ = heatmap(swapped_adj,\n", " title='Drosophila right MB swapped',\n", " font_scale=1.5,\n", @@ -127,8 +127,8 @@ "metadata": {}, "outputs": [], "source": [ - "swapper = EdgeSwapper(csr_matrix(adj))\n", - "swapped_adj, _ = swapper.swap_edges(n_swaps=1000, seed=8888)\n", + "swapper = EdgeSwapper(csr_matrix(adj), seed=8888)\n", + "swapped_adj, _ = swapper.swap_edges(n_swaps=1000)\n", "g = nx.from_numpy_array(adj)\n", "swapped_g = nx.from_numpy_array(swapped_adj)\n", "print(list(g.degree()) == list(swapped_g.degree()))" diff --git a/graspologic/models/edge_swaps.py b/graspologic/models/edge_swaps.py index 4b0334dbe..a147517f1 100644 --- a/graspologic/models/edge_swaps.py +++ b/graspologic/models/edge_swaps.py @@ -4,6 +4,7 @@ import numpy as np from beartype import beartype from scipy.sparse import csr_matrix, lil_matrix +from sklearn.utils import check_scalar from graspologic.preconditions import check_argument from graspologic.types import AdjacencyMatrix, Tuple @@ -26,6 +27,9 @@ class EdgeSwapper: edge_list : np.ndarray, shape (n_verts, 2) The corresponding edgelist for the input network + seed: int, optional + Random seed to make outputs reproducible, must be positive + References ---------- @@ -41,7 +45,7 @@ class EdgeSwapper: """ @beartype - def __init__(self, adjacency: AdjacencyMatrix): + def __init__(self, adjacency: AdjacencyMatrix, seed: Optional[int] = None): weight_check = is_unweighted(adjacency) check_argument(weight_check, "adjacency must be unweighted") @@ -52,6 +56,14 @@ def __init__(self, adjacency: AdjacencyMatrix): direct_check = is_symmetric(adjacency) check_argument(direct_check, "adjacency must be undirected") + max_seed = np.iinfo(np.uint32).max + if seed is None: + seed = np.random.randint(max_seed, dtype=np.int64) + seed = check_scalar( + seed, "seed", (int, np.integer), min_val=0, max_val=max_seed + ) + self._rng = np.random.default_rng(seed) + adjacency = import_graph(adjacency, copy=True) if isinstance(adjacency, csr_matrix): @@ -87,9 +99,7 @@ def _do_setup(self) -> np.ndarray: edge_list = np.stack((row_inds, col_inds)).T return edge_list - def swap_edges( - self, n_swaps: int = 1, seed: Optional[int] = None - ) -> Tuple[AdjacencyMatrix, np.ndarray]: + def swap_edges(self, n_swaps: int = 1) -> Tuple[AdjacencyMatrix, np.ndarray]: """ Performs a number of edge swaps on the graph @@ -100,23 +110,30 @@ def swap_edges( Returns ------- - self.adjacency : np.ndarray OR csr.matrix, shape (n_verts, n_verts) + adjacency : np.ndarray OR csr.matrix, shape (n_verts, n_verts) The adjancency matrix after a number of edge swaps are performed on the graph - self.edge_list : np.ndarray (n_verts, 2) + edge_list : np.ndarray (n_verts, 2) The edge_list after a number of edge swaps are perfomed on the graph """ + # Note: for some reason could not get reproducibility w/o setting seed + # inside of the _edge_swap_function itself + max_seed = np.iinfo(np.int32).max for _ in range(n_swaps): self.adjacency, self.edge_list = self._edge_swap_function( - self.adjacency, self.edge_list, seed + self.adjacency, + self.edge_list, + seed=self._rng.integers(max_seed), ) adjacency = self.adjacency if isinstance(adjacency, lil_matrix): adjacency = csr_matrix(adjacency) + else: + adjacency = adjacency.copy() - return adjacency, self.edge_list + return adjacency, self.edge_list.copy() def _edge_swap( @@ -135,6 +152,9 @@ def _edge_swap( edge_list : np.ndarray, shape (n_verts, 2) The corresponding edge_list of adjacency + seed: int, optional + Random seed to make outputs reproducible, must be positive + Returns ------- adjacency : np.ndarray OR csr_matrix, shape (n_verts, n_verts) @@ -143,6 +163,8 @@ def _edge_swap( edge_list : np.ndarray (n_verts, 2) The edge_list after an edge swap is perfomed on the graph """ + + # need to use np.random here instead of the generator for numba compatibility if seed is not None: np.random.seed(seed) diff --git a/tests/test_models.py b/tests/test_models.py index e03746eb4..2e16174e9 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -596,7 +596,7 @@ def _test_score(estimator, p_mat, graph): class TestEdgeSwaps(unittest.TestCase): @classmethod def setUpClass(cls): - cls.A = er_np(100, 0.5) + cls.A = er_np(20, 0.5) cls.B = csr_matrix(cls.A) cls.C = nx.from_numpy_array(cls.A) cls.D = nx.from_scipy_sparse_matrix(cls.B) @@ -615,19 +615,28 @@ def test_scipy_edge_swap(self): assert list(self.D.degree()) == list(swapped_csr_nx.degree()) def test_rep_numpy(self): - Swapper = EdgeSwapper(self.A) - swapped_er_1, _ = Swapper.swap_edges(n_swaps=100, seed=1234) - swapped_er_2, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + Swapper = EdgeSwapper(self.A, seed=1234) + swapped_er_1, _ = Swapper.swap_edges(n_swaps=100) + Swapper = EdgeSwapper(self.A, seed=1234) + swapped_er_2, _ = Swapper.swap_edges(n_swaps=100) assert (swapped_er_1 == swapped_er_2).all() def test_rep_scipy(self): - Swapper = EdgeSwapper(self.B) - swapped_csr_1, _ = Swapper.swap_edges(n_swaps=100, seed=1234) - swapped_csr_2, _ = Swapper.swap_edges(n_swaps=100, seed=1234) + Swapper = EdgeSwapper(self.B, seed=1234) + swapped_csr_1, _ = Swapper.swap_edges(n_swaps=100) + Swapper = EdgeSwapper(self.B, seed=1234) + swapped_csr_2, _ = Swapper.swap_edges(n_swaps=100) swapped_csr_1 = swapped_csr_1.toarray() swapped_csr_2 = swapped_csr_2.toarray() assert (swapped_csr_1 == swapped_csr_2).all() + def test_rep_agrees(self): + Swapper = EdgeSwapper(self.A, seed=1234) + swapped_numpy, _ = Swapper.swap_edges(n_swaps=100) + Swapper = EdgeSwapper(self.B, seed=1234) + swapped_scipy, _ = Swapper.swap_edges(n_swaps=100) + assert (swapped_numpy == swapped_scipy.toarray()).all() + def hardy_weinberg(theta): """ From c67f4ea653d8a05a7455d12c617f21e90f6122ff Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Mon, 13 Jun 2022 10:46:22 -0700 Subject: [PATCH 17/32] With changes in mypy and upstream typesheds, some of our downstream uses that were valid before became marked as invalid. Very few of them were actual bugs (though a few were), but regardless they were adjusted so that they did not, by and large, result in further mypy complaints. I will note that there are still known bugs in graspologic.models.sbm_estimators, and I don't know enough about the intent or the numpy wizardry to make any changes with confidence. Still this gets rid of the bulk of the issues and I'll rely on bdpedigo to shine a brilliant light on the rest. --- graspologic/align/seedless_procrustes.py | 11 +++---- graspologic/cluster/autogmm.py | 3 +- graspologic/inference/latent_position_test.py | 2 +- graspologic/match/gmp.py | 13 ++++---- graspologic/match/qap.py | 32 ++++++++++--------- graspologic/models/base.py | 4 ++- graspologic/nominate/VNviaSGM.py | 2 +- graspologic/plot/plot.py | 21 ++++++------ graspologic/simulations/simulations.py | 13 ++++---- graspologic/subgraph/sg.py | 12 +++---- 10 files changed, 58 insertions(+), 55 deletions(-) diff --git a/graspologic/align/seedless_procrustes.py b/graspologic/align/seedless_procrustes.py index 4e9d4aa14..f10e502ec 100644 --- a/graspologic/align/seedless_procrustes.py +++ b/graspologic/align/seedless_procrustes.py @@ -319,12 +319,11 @@ def _compute_objective( Y: np.ndarray, Q: Optional[np.ndarray] = None, P: Optional[np.ndarray] = None, - ) -> Union[float, np.ndarray]: - if Q is None: - Q = self.Q_ - if P is None: - P = self.P_ - return np.linalg.norm(X @ Q - P @ Y, ord="fro") + ) -> np.floating: + _Q = Q if Q is not None else self.Q_ + _P = P if P is not None else self.P_ + + return np.linalg.norm(X @ _Q - _P @ Y, ord="fro") def fit(self, X: np.ndarray, Y: np.ndarray) -> "SeedlessProcrustes": """ diff --git a/graspologic/cluster/autogmm.py b/graspologic/cluster/autogmm.py index 5ab71acec..65548e616 100644 --- a/graspologic/cluster/autogmm.py +++ b/graspologic/cluster/autogmm.py @@ -565,7 +565,7 @@ def fit(self, X: np.ndarray, y: Optional[np.ndarray] = None) -> "AutoGMMCluster" subset_idxs = np.random.choice(np.arange(0, n), self.max_agglom_size) X_subset = X[subset_idxs, :] - ag_labels = [] + ag_labels: List[np.ndarray] = [] if self.label_init is None: for p_ag in param_grid_ag: if p_ag["affinity"] != "none": @@ -580,6 +580,7 @@ def fit(self, X: np.ndarray, y: Optional[np.ndarray] = None) -> "AutoGMMCluster" def _fit_for_data(p: ParamGridType, seed: int) -> Dict[str, Any]: n_clusters = p[1]["n_components"] + agg_clustering: Union[List[int], np.ndarray] if (p[0]["affinity"] != "none") and (self.label_init is None): index = param_grid_ag.index(p[0]) agg_clustering = ag_labels[index][:, n_clusters - self.min_components] diff --git a/graspologic/inference/latent_position_test.py b/graspologic/inference/latent_position_test.py index 1ef67d8a1..d1b2c8a53 100644 --- a/graspologic/inference/latent_position_test.py +++ b/graspologic/inference/latent_position_test.py @@ -240,7 +240,7 @@ def _difference_norm( X2 = X2 / np.sqrt(normX2[:, None]) aligner = OrthogonalProcrustes() X1 = aligner.fit_transform(X1, X2) - return np.linalg.norm(X1 - X2) + return float(np.linalg.norm(X1 - X2)) def _embed( diff --git a/graspologic/match/gmp.py b/graspologic/match/gmp.py index 0fefbab1c..42f7dc3a4 100644 --- a/graspologic/match/gmp.py +++ b/graspologic/match/gmp.py @@ -237,26 +237,25 @@ def fit( seeds_B = column_or_1d(seeds_B) partial_match = np.column_stack((seeds_A, seeds_B)) - if S is None: - S = np.zeros((A.shape[0], B.shape[1])) - S = np.atleast_2d(S) + _S = S if S is not None else np.zeros((A.shape[0], B.shape[1])) + _S = np.atleast_2d(_S) msg = None - if S.ndim != 2: + if _S.ndim != 2: msg = "`S` must have exactly two dimensions" - elif A.shape[0] != S.shape[0] or B.shape[0] != S.shape[1]: + elif A.shape[0] != _S.shape[0] or B.shape[0] != _S.shape[1]: msg = "`S` must be of shape (n_A, n_B)" if msg is not None: raise ValueError(msg) # pads A and B according to section 2.5 of [2] if A.shape[0] != B.shape[0]: - A, B, S = _adj_pad(A, B, S, self.padding) + A, B, _S = _adj_pad(A, B, _S, self.padding) options = { "maximize": self.gmp, "partial_match": partial_match, - "S": S, + "S": _S, "P0": self.init, "shuffle_input": self.shuffle_input, "maxiter": self.max_iter, diff --git a/graspologic/match/qap.py b/graspologic/match/qap.py index 2767afb23..14bd94584 100644 --- a/graspologic/match/qap.py +++ b/graspologic/match/qap.py @@ -189,9 +189,11 @@ def _common_input_validation( A = np.atleast_2d(A) B = np.atleast_2d(B) - if partial_match is None: - partial_match = np.array([[], []]).T - partial_match = np.atleast_2d(partial_match).astype(int) + _partial_match = ( + partial_match if partial_match is not None else np.array([[], []]).T + ) + + _partial_match = np.atleast_2d(_partial_match).astype(int) msg = None if A.shape[0] != A.shape[1]: @@ -202,25 +204,25 @@ def _common_input_validation( msg = "`A` and `B` must have exactly two dimensions" elif A.shape != B.shape: msg = "`A` and `B` matrices must be of equal size" - elif partial_match.shape[0] > A.shape[0]: + elif _partial_match.shape[0] > A.shape[0]: msg = "`partial_match` can have only as many seeds as there are nodes" - elif partial_match.shape[1] != 2: + elif _partial_match.shape[1] != 2: msg = "`partial_match` must have two columns" - elif partial_match.ndim != 2: + elif _partial_match.ndim != 2: msg = "`partial_match` must have exactly two dimensions" - elif (partial_match < 0).any(): + elif (_partial_match < 0).any(): msg = "`partial_match` must contain only positive indices" - elif (partial_match >= len(A)).any(): + elif (_partial_match >= len(A)).any(): msg = "`partial_match` entries must be less than number of nodes" - elif not len(set(partial_match[:, 0])) == len(partial_match[:, 0]) or not len( - set(partial_match[:, 1]) - ) == len(partial_match[:, 1]): + elif not len(set(_partial_match[:, 0])) == len(_partial_match[:, 0]) or not len( + set(_partial_match[:, 1]) + ) == len(_partial_match[:, 1]): msg = "`partial_match` column entries must be unique" if msg is not None: raise ValueError(msg) - return A, B, partial_match + return A, B, _partial_match def _quadratic_assignment_faq( @@ -458,11 +460,11 @@ def _quadratic_assignment_faq( K = _doubly_stochastic(K) P = J * 0.5 + K * 0.5 elif isinstance(P0, np.ndarray): - P0 = np.atleast_2d(P0) - _check_init_input(P0, n_unseed) + _P0 = np.atleast_2d(P0) + _check_init_input(_P0, n_unseed) invert_inds = np.argsort(nonseed_B) perm_nonseed_B = np.argsort(invert_inds) - P = P0[:, perm_nonseed_B] + P = _P0[:, perm_nonseed_B] else: msg = "`init` must either be of type str or np.ndarray." raise TypeError(msg) diff --git a/graspologic/models/base.py b/graspologic/models/base.py index 74236f627..c91151a8b 100644 --- a/graspologic/models/base.py +++ b/graspologic/models/base.py @@ -83,7 +83,9 @@ def mse(self, graph: np.ndarray) -> float: Mean square error for the model's fit P matrix """ check_is_fitted(self, "p_mat_") - return np.linalg.norm(graph - self.p_mat_) ** 2 + return float( + np.linalg.norm(graph - self.p_mat_) ** 2 + ) # this should have been fine without the float def score_samples( self, graph: np.ndarray, clip: Optional[float] = None diff --git a/graspologic/nominate/VNviaSGM.py b/graspologic/nominate/VNviaSGM.py index 7e5599cf6..6c7ce3b12 100644 --- a/graspologic/nominate/VNviaSGM.py +++ b/graspologic/nominate/VNviaSGM.py @@ -382,7 +382,7 @@ def _get_induced_subgraph( The list containing all the vertices in the induced subgraph. """ # Note all nodes are zero based in this implementation, i.e the first node is 0 - dists = [[node]] + dists: List[Union[List[int], np.ndarray]] = [[node]] dists_conglom = [node] for ii in range(1, order + 1): clst = [] diff --git a/graspologic/plot/plot.py b/graspologic/plot/plot.py index d7f3d2279..657eb1df4 100644 --- a/graspologic/plot/plot.py +++ b/graspologic/plot/plot.py @@ -471,17 +471,16 @@ def gridplot( msg = "X must be a list, not {}.".format(type(X)) raise TypeError(msg) - if labels is None: - labels = np.arange(len(X)) + _labels = np.array(labels) if labels is not None else np.arange(len(X)) - check_consistent_length(X, labels) + check_consistent_length(X, _labels) graphs = _process_graphs( X, inner_hier_labels, outer_hier_labels, transform, sort_nodes ) if isinstance(palette, str): - palette = sns.color_palette(palette, desat=0.75, n_colors=len(labels)) + palette = sns.color_palette(palette, desat=0.75, n_colors=_labels.shape[0]) dfs = [] for idx, graph in enumerate(graphs): @@ -491,7 +490,7 @@ def gridplot( np.vstack([rdx + 0.5, cdx + 0.5, weights]).T, columns=["rdx", "cdx", "Weights"], ) - df[legend_name] = [labels[idx]] * len(cdx) + df[legend_name] = [_labels[idx]] * len(cdx) dfs.append(df) df = pd.concat(dfs, axis=0) @@ -1144,14 +1143,16 @@ def edgeplot( check_array(X) check_consistent_length((X, labels)) edges = X.ravel() - labels = np.tile(labels, (1, X.shape[1])) - labels = labels.ravel() # type: ignore + _labels: np.ndarray = ( + np.tile(labels, (1, X.shape[1])) if labels is not None else np.array([]) + ) + _labels = _labels.ravel() # type: ignore if nonzero: - labels = labels[edges != 0] + _labels = _labels[edges != 0] edges = edges[edges != 0] ax = _distplot( edges, - labels=labels, + labels=_labels, title=title, context=context, font_scale=font_scale, @@ -1525,7 +1526,7 @@ def _get_freqs( outer_freq_cumsum = np.hstack((0, outer_freq.cumsum())) # for each group of outer labels, calculate the boundaries of the inner labels - inner_freq = np.array([]) + inner_freq: np.ndarray = np.array([]) for i in range(outer_freq.size): start_ind = outer_freq_cumsum[i] stop_ind = outer_freq_cumsum[i + 1] diff --git a/graspologic/simulations/simulations.py b/graspologic/simulations/simulations.py index 3f94f60ad..eb53ca598 100644 --- a/graspologic/simulations/simulations.py +++ b/graspologic/simulations/simulations.py @@ -313,11 +313,11 @@ def er_nm( # choose M of them triu = np.random.choice(triu, size=m, replace=False) # unravel back - triu = np.unravel_index(triu, A.shape) + _triu = np.unravel_index(triu, A.shape) # check weight function if callable(wt): wt = wt(size=m, **wtargs) - A[triu] = wt + A[_triu] = wt if not directed: A = symmetrize(A, method="triu") @@ -630,8 +630,8 @@ def sbm( triu = triu[pchoice < block_p] if type(block_wt) is not int: block_wt = block_wt(size=len(triu), **block_wtargs) - triu = np.unravel_index(triu, A.shape) - A[triu] = block_wt + _triu = np.unravel_index(triu, A.shape) + A[_triu] = block_wt if not loops: A = A - np.diag(np.diag(A)) @@ -983,8 +983,7 @@ def mmsbm( if not isinstance(rng, np.random.Generator): msg = "rng must be not {}.".format(type(rng)) raise TypeError(msg) - elif rng == None: - rng = np.random.default_rng() + _rng = rng if rng is not None else np.random.default_rng() if type(loops) is not bool: raise TypeError("loops is not of type bool.") @@ -1007,7 +1006,7 @@ def mmsbm( # check docstrings for more info. labels = np.apply_along_axis( lambda p_vector: np.argmax( - rng.multinomial(n=1, pvals=p_vector, size=n), axis=1 + _rng.multinomial(n=1, pvals=p_vector, size=n), axis=1 ), axis=1, arr=mm_vectors, diff --git a/graspologic/subgraph/sg.py b/graspologic/subgraph/sg.py index c791d2801..13b1d14d0 100644 --- a/graspologic/subgraph/sg.py +++ b/graspologic/subgraph/sg.py @@ -122,11 +122,11 @@ def fit( if isinstance(constraints, (int)): # incoherent nedges = constraints - sigsub = np.dstack( + _sigsub_dstack = np.dstack( np.unravel_index(np.argsort(sigmat.ravel()), np.shape(sigmat)) ) - sigsub = sigsub[0, :nedges, :] - sigsub = tuple(np.transpose(sigsub)) + _sigsub = _sigsub_dstack[0, :nedges, :] + sigsub = tuple(np.transpose(_sigsub)) elif len(constraints) == 2: # coherent nedges = constraints[0] @@ -156,13 +156,13 @@ def fit( indsp = np.dstack( np.unravel_index(np.argsort(blank.ravel()), np.shape(blank)) ) - sigsub = indsp[0, :nedges, :] - sigsub = tuple(np.transpose(sigsub)) + _sigsub = indsp[0, :nedges, :] + sigsub = tuple(np.transpose(_sigsub)) wconv = 1 else: wcounter = wcounter + 1 if wcounter > len(wset): - sigsub = [] + sigsub = tuple() wconv = 1 else: msg = "Input constraints must be an int for the incoherent signal-subgraph estimator, or a vector of length 2 for the coherent subgraph estimator." From f3bbbb9c2f7018fb185b290d553bbf7ab1275eab Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Mon, 13 Jun 2022 13:16:25 -0700 Subject: [PATCH 18/32] The latest versions of sphinx were causing new problems in plot. I also updated the path too scipy's objects.inv because they've moved it (though we got a polite message it moved instead of just breaking entirely) --- docs/conf.py | 6 +++--- graspologic/plot/plot.py | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 5620e0eb5..99ac5b8ca 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -78,12 +78,12 @@ "anytree": ("https://anytree.readthedocs.io/en/latest/", None), "hyppo": ("https://hyppo.neurodata.io", None), "joblib": ("https://joblib.readthedocs.io/en/latest/", None), - "matplotlib": ("https://matplotlib.org", None), + "matplotlib": ("https://matplotlib.org/stable/", None), "networkx": ("https://networkx.org/documentation/stable", None), - "numpy": ("https://numpy.org/doc/stable", None), + "numpy": ("https://matplotlib.org/stable/", None), "pandas": ("https://pandas.pydata.org/pandas-docs/stable", None), "python": ("https://docs.python.org/3.9", None), - "scipy": ("https://docs.scipy.org/doc/scipy/reference", None), + "scipy": ("https://docs.scipy.org/doc/scipy", None), "seaborn": ("https://seaborn.pydata.org", None), "sklearn": ("https://scikit-learn.org/dev", None), } diff --git a/graspologic/plot/plot.py b/graspologic/plot/plot.py index 657eb1df4..a917ecd62 100644 --- a/graspologic/plot/plot.py +++ b/graspologic/plot/plot.py @@ -431,7 +431,7 @@ def gridplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib ` alpha : float [0, 1], default : 0.7 Alpha value of plotted gridplot points sizes : length 2 tuple, default: (10, 200) @@ -596,14 +596,14 @@ def pairplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. alpha : float, optional, default: 0.7 Opacity value of plotter markers between 0 and 1 size : float or int, optional, default: 50 Size of plotted markers. marker : string, optional, default: '.' Matplotlib marker specifier, see the marker options at - :doc:`Matplotlib style marker specification ` + :doc:`Matplotlib style marker specification ` """ _check_common_inputs( height=height, @@ -1059,7 +1059,7 @@ def degreeplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. figsize : tuple of length 2, default (10, 5) Size of the figure (width, height) @@ -1128,7 +1128,7 @@ def edgeplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. figsize : tuple of length 2, default (10, 5) Size of the figure (width, height) From eaca947d9369560bca1b10dd4f01638450532496 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Mon, 13 Jun 2022 13:40:18 -0700 Subject: [PATCH 19/32] Adding the security.md file that got into main but isn't in dev. This may bite me later but I want to get it in asap so we can close that bug it keeps opening. --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 000000000..869fdfe2b --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + + * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) + * Full paths of source file(s) related to the manifestation of the issue + * The location of the affected source code (tag/branch/commit or direct URL) + * Any special configuration required to reproduce the issue + * Step-by-step instructions to reproduce the issue + * Proof-of-concept or exploit code (if possible) + * Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). + + From 49d6929f14b57d74ba80f903a7aad19f5e4dafa2 Mon Sep 17 00:00:00 2001 From: Dax Pryce Date: Mon, 13 Jun 2022 14:27:18 -0700 Subject: [PATCH 20/32] NO MORE TYPE CHECK ERRORS however I'm not confident that this is the logic we want --- graspologic/models/sbm_estimators.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/graspologic/models/sbm_estimators.py b/graspologic/models/sbm_estimators.py index 51ed86783..1787662d5 100644 --- a/graspologic/models/sbm_estimators.py +++ b/graspologic/models/sbm_estimators.py @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation and contributors. # Licensed under the MIT License. -from typing import Any, Collection, Optional +from typing import Any, Optional import numpy as np from sklearn.utils import check_X_y @@ -440,7 +440,8 @@ def fit( p_mat = p_mat * np.outer(degree_corrections[:, 0], degree_corrections[:, -1]) if not self.loops: - p_mat -= np.diag(np.diag(p_mat)) + # there seems to be a bug in numpy around __isub__ here? + p_mat -= np.diag(np.diag(p_mat)) # type: ignore self.p_mat_ = p_mat self.block_p_ = block_p return self @@ -458,7 +459,7 @@ def _n_parameters(self) -> int: return n_parameters -def _get_block_indices(y: np.ndarray) -> Tuple[List[int], Collection[int], np.ndarray]: +def _get_block_indices(y: np.ndarray) -> Tuple[List[np.ndarray], range, np.ndarray]: """ y is a length n_verts vector of labels @@ -485,8 +486,8 @@ def _get_block_indices(y: np.ndarray) -> Tuple[List[int], Collection[int], np.nd def _calculate_block_p( graph: np.ndarray, - block_inds: Collection[int], - block_vert_inds: List[int], + block_inds: range, + block_vert_inds: List[np.ndarray], return_counts: bool = False, loops: bool = False, ) -> np.ndarray: From b6eeb576778aa4abc519ac91f067c3a0d6b0de85 Mon Sep 17 00:00:00 2001 From: Re Date: Tue, 28 Jun 2022 00:52:04 +0900 Subject: [PATCH 21/32] Removed default axis labels in networkplot. (#954) Co-authored-by: Benjamin Pedigo --- graspologic/plot/plot.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/graspologic/plot/plot.py b/graspologic/plot/plot.py index a917ecd62..3df626d2e 100644 --- a/graspologic/plot/plot.py +++ b/graspologic/plot/plot.py @@ -1399,6 +1399,8 @@ def networkplot( ) ax.add_collection(lc) ax.set(xticks=[], yticks=[]) + ax.set_xlabel("") + ax.set_ylabel("") return ax From d6392ac27a77065955ecb4f3215cda179a058083 Mon Sep 17 00:00:00 2001 From: Benjamin Pedigo Date: Thu, 30 Jun 2022 15:28:01 -0400 Subject: [PATCH 22/32] Fixed intersphinx bug and formatted docs/conf.py (#963) * fix intersphinx bug and black docs/conf.py * remove matplotlib: prefixes and pray --- docs/conf.py | 24 ++++++++++++++++-------- graspologic/plot/plot.py | 10 +++++----- 2 files changed, 21 insertions(+), 13 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 99ac5b8ca..e4499c01c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -15,7 +15,7 @@ import os import sys -sys.path.append(os.path.abspath('./sphinx-ext/')) +sys.path.append(os.path.abspath("./sphinx-ext/")) sys.path.insert(0, os.path.abspath("..")) # -- Project information ----------------------------------------------------- @@ -64,11 +64,11 @@ # -- sphinx.ext.autodoc autoclass_content = "both" autodoc_default_options = { - 'members': True, - 'inherited-members': True, - 'member-order': 'bysource', - 'special-members': '__init__', - 'undoc-members': True, + "members": True, + "inherited-members": True, + "member-order": "bysource", + "special-members": "__init__", + "undoc-members": True, } autodoc_class_signature = "separated" autodoc_typehints = "description" @@ -88,10 +88,18 @@ "sklearn": ("https://scikit-learn.org/dev", None), } +intersphinx_disabled_reftypes = [] + # -- sphinx options ---------------------------------------------------------- source_suffix = ".rst" -exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "**.ipynb_checkpoints", "tutorials"] -toc_filter_exclude = ['tutorials/index'] +exclude_patterns = [ + "_build", + "Thumbs.db", + ".DS_Store", + "**.ipynb_checkpoints", + "tutorials", +] +toc_filter_exclude = ["tutorials/index"] master_doc = "index" source_encoding = "utf-8" if tags.has("build_tutorials"): diff --git a/graspologic/plot/plot.py b/graspologic/plot/plot.py index 3df626d2e..d69e7a58c 100644 --- a/graspologic/plot/plot.py +++ b/graspologic/plot/plot.py @@ -431,7 +431,7 @@ def gridplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib ` + :doc:`Choosing Colormaps in Matplotlib ` alpha : float [0, 1], default : 0.7 Alpha value of plotted gridplot points sizes : length 2 tuple, default: (10, 200) @@ -596,14 +596,14 @@ def pairplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. alpha : float, optional, default: 0.7 Opacity value of plotter markers between 0 and 1 size : float or int, optional, default: 50 Size of plotted markers. marker : string, optional, default: '.' Matplotlib marker specifier, see the marker options at - :doc:`Matplotlib style marker specification ` + :doc:`Matplotlib style marker specification ` """ _check_common_inputs( height=height, @@ -1059,7 +1059,7 @@ def degreeplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. figsize : tuple of length 2, default (10, 5) Size of the figure (width, height) @@ -1128,7 +1128,7 @@ def edgeplot( Set of colors for mapping the ``hue`` variable. If a dict, keys should be values in the ``hue`` variable. For acceptable string arguments, see the palette options at - :doc:`Choosing Colormaps in Matplotlib `. + :doc:`Choosing Colormaps in Matplotlib `. figsize : tuple of length 2, default (10, 5) Size of the figure (width, height) From 9187abf9ddd40c0e7acb1e571a2109830cab490f Mon Sep 17 00:00:00 2001 From: Audrey Herskovits <102697879+aj-hersko@users.noreply.github.com> Date: Fri, 1 Jul 2022 05:55:34 -0700 Subject: [PATCH 23/32] Fixed repeated numba compilation in EdgeSwapper (#964) (#965) * Fix repeated compilation of numba and fixing incorrect PR location * final submittion with correct format --- graspologic/models/edge_swaps.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/graspologic/models/edge_swaps.py b/graspologic/models/edge_swaps.py index a147517f1..01e62ed19 100644 --- a/graspologic/models/edge_swaps.py +++ b/graspologic/models/edge_swaps.py @@ -73,7 +73,7 @@ def __init__(self, adjacency: AdjacencyMatrix, seed: Optional[int] = None): else: # for numpy input, use numba for JIT compilation # NOTE: not convinced numba is helping much here, look into optimizing - self._edge_swap_function = nb.jit(_edge_swap) + self._edge_swap_function = _edge_swap_numba self.adjacency = adjacency @@ -211,3 +211,6 @@ def _edge_swap( edge_list[orig_inds[0]] = [u, x] edge_list[orig_inds[1]] = [v, y] return adjacency, edge_list + + +_edge_swap_numba = nb.jit(_edge_swap) From 6ac2cdc08864915229b642f0f626e85db29d8e1c Mon Sep 17 00:00:00 2001 From: dokato Date: Wed, 6 Jul 2022 22:03:29 +0100 Subject: [PATCH 24/32] Fixed isolated nodes handling in node2vec (#953) * fixed isolated nodes handling in node2vec * n2v explicit booleanification Co-authored-by: Benjamin Pedigo --- graspologic/embed/n2v.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/graspologic/embed/n2v.py b/graspologic/embed/n2v.py index fb7c94de2..6d848b8a0 100644 --- a/graspologic/embed/n2v.py +++ b/graspologic/embed/n2v.py @@ -4,6 +4,7 @@ import logging import math import time +import warnings from typing import Any, Optional, Union import networkx as nx @@ -142,6 +143,10 @@ def node2vec_embed( labels = list(node2vec_graph.original_graph.nodes()) remapped_labels = node2vec_graph.label_map_to_string + isolated_nodes = [x for x in nx.isolates(node2vec_graph.original_graph)] + if len(isolated_nodes) > 0: + warnings.warn(f"Isolated nodes found: {isolated_nodes}") + labels = list(np.setdiff1d(labels, isolated_nodes)) return ( np.array([model.wv.get_vector(remapped_labels[node]) for node in labels]), From 03467c379c28ecec4d0ef7e78a6c6aa0abae322f Mon Sep 17 00:00:00 2001 From: Audrey Herskovits <102697879+aj-hersko@users.noreply.github.com> Date: Thu, 7 Jul 2022 09:42:35 -0700 Subject: [PATCH 25/32] Corrected notation in documentation of to_laplacians (#969) * fix in documentation of to_laplacian on right branch * new commit after formatting and making docs * fix D_i(r) defn Co-authored-by: Benjamin Pedigo --- graspologic/utils/utils.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/graspologic/utils/utils.py b/graspologic/utils/utils.py index ea67a74ec..4062ca26f 100644 --- a/graspologic/utils/utils.py +++ b/graspologic/utils/utils.py @@ -378,9 +378,8 @@ def to_laplacian( r""" A function to convert graph adjacency matrix to graph Laplacian. - Currently supports I-DAD, DAD, and R-DAD Laplacians, where D is the diagonal - matrix of degrees of each node raised to the -1/2 power, I is the - identity matrix, and A is the adjacency matrix. + Currently supports I-DAD, DAD, and R-DAD Laplacians, where D is the diagonal matrix + of degrees of each node, I is the identity matrix, and A is the adjacency matrix. R-DAD is regularized Laplacian: where :math:`D_t = D + regularizer \times I`. @@ -393,12 +392,12 @@ def to_laplacian( form: {'I-DAD', 'DAD' (default), 'R-DAD'}, string, optional - 'I-DAD' - Computes :math:`L = I - D_i A D_i` + Computes :math:`L = I - D_i^{-1/2} A D_i^{-1/2}` - 'DAD' - Computes :math:`L = D_o A D_i` + Computes :math:`L = D_o^{-1/2} A D_i^{-1/2}` - 'R-DAD' - Computes :math:`L = D_o^r A D_i^r` - where :math:`D_o^r = D_o + regularizer \times I` and likewise for :math:`D_i` + Computes :math:`L = D_o(r)^{-1/2} A D_i(r)^{-1/2}` + where :math:`D_o(r)^{-1/2} = D_o^{-1/2} + regularizer \times I` and likewise for :math:`D_i(r)^{-1/2}` regularizer: int, float or None, optional (default=None) Constant to add to the degree vector(s). If None, average node degree is added. From 7437d4ade1aefd147486cded0180183a206e3f27 Mon Sep 17 00:00:00 2001 From: Audrey Herskovits <102697879+aj-hersko@users.noreply.github.com> Date: Wed, 13 Jul 2022 07:26:27 -0700 Subject: [PATCH 26/32] Made improvements to contributing guidelines (#973) * improvements to contributing guidelines * additions from 1st set of comments * merge * changed subheading * reformat graspologic name * add a link to venv * add a bit under checking code * add something about tutorials * add a note about dev deps Co-authored-by: Benjamin Pedigo --- CONTRIBUTING.md | 210 +++++++++++++++++++++++++++--------------------- 1 file changed, 117 insertions(+), 93 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 081f7b246..8630ac6ee 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,8 +20,7 @@ to see a feature implemented. Please also feel free to tag one of the core contributors (see our [Roles page](https://github.com/microsoft/graspologic/blob/dev/ROLES.md)). In case you experience issues using this package, do not hesitate to submit a ticket to our -[Issue Tracker](https://github.com/microsoft/graspologic/issues). You are also welcome to post feature requests or pull -requests. +[Issue Tracker](https://github.com/microsoft/graspologic/issues). You are also welcome to post feature requests or pull requests. It is recommended to check that your issue complies with the following rules before submitting: @@ -61,18 +60,18 @@ follow these guidelines! This will make it a lot faster for us to respond to you [Creating and highlighting code blocks](https://help.github.com/articles/creating-and-highlighting-code-blocks) for more details. -# Contributing Code +# Contributing code -## Git workflow +## Setting up for development -The preferred workflow for contributing to Graspologic is to fork the main repository on GitHub, clone, and develop on a -branch. Steps: +The preferred workflow for contributing to `graspologic` is to fork the main repository on GitHub, clone, and develop on a +branch using a virtual environment. Steps: 1. Fork the [project repository](https://github.com/microsoft/graspologic) by clicking on the ‘Fork’ button near the top right of the page. This creates a copy of the code under your GitHub user account. For more details on how to fork a repository see [this guide](https://help.github.com/articles/fork-a-repo/). -2. Clone your fork of the Graspologic repo from your GitHub account to your local disk: +2. Clone your fork of the `graspologic` repo from your GitHub account to your local disk: ```bash git clone git@github.com:YourGithubAccount/graspologic.git @@ -88,43 +87,8 @@ branch. Steps: Always use a `feature` branch. Pull requests directly to either `dev` or `main` will be rejected until you create a feature branch based on `dev`. -4. Unit testing - - It's important to write unit tests for your bug fix and your features. When fixing a bug, first create a test that explicitly exercises the bug and results in a test case failure. Then create the fix and run the test again to verify your results. - - For new features, we advocate using [TDD](https://en.wikipedia.org/wiki/Test-driven_development) wherever possible. - - We also explicitly ask that you hew toward the `unittest` Python module for conformance. This will ensure it plays nicely with most common IDEs on the market. - -5. Code formatting: - It's important to us that you follow the standards of our project. Please use `black` and `isort` prior to - committing. - - ```bash - # Run "black" and "isort" using Make - make format - ``` - OR - ```bash - black graspologic/ tests/ - isort graspologic/ tests/ - ``` - -6. Develop the feature on your feature branch. Add changed files using `git add` and then `git commit` files: - - ```bash - git add modified_files - git commit - ``` - - After making all local changes, you will want to push your changes to your fork: - ```bash - git push -u origin my-feature - ``` - -## Local Developer Setup -1. Make sure you have a compatible version of Python 3 installed -2. From the project root, create a virtual environment and install all development dependencies. This example uses Python 3.8 but you may use any Python version supported by graspologic. +4. From the project root, create a [virtual environment](https://docs.python.org/3/library/venv.html) and install all development dependencies. Examples using various terminals are provided below. These examples use Python 3.8 but you may use any Python version supported by graspologic. These commands should install `graspologic` in editable mode, as well as +all of its dependencies and several tools you need for developing `graspologic`. **Bash** ```bash @@ -162,58 +126,118 @@ branch. Steps: pip install -U pip setuptools pip install -r requirements.txt ``` -3. Start playing with Graspologic code! -## Pull Request Checklist +## Code Changes + +### Writing Code +- Make sure to follow the coding guidelines outlined below: + - Uniformly formatted code makes it easier to share code ownership. Graspologic package closely follows the official Python guidelines detailed in [PEP8](https://www.python.org/dev/peps/pep-0008/) that detail how code should be formatted and indented. Please read it and follow it. + - In order to make sure all code is formatted seamlessly and uniformly, we use [black](https://github.com/psf/black) to automatically format our code. + - All new functions should have PEP-compliant type hints and [@beartype](https://github.com/beartype/beartype) decorator. This allows us a reasonable level of confidence that arguments passed into the API are what we expect them to be without sacrificing runtime speed. +- All public methods should have informative [`docstrings`](https://github.com/microsoft/graspologic/blob/dev/CONTRIBUTING.md#docstring-guidelines) with sample usage presented as doctests when appropriate. + - Properly formatted docstrings are required for documentation generation by [sphinx](https://www.sphinx-doc.org/en/master/usage/index.html). The graspologic package closely +follows the [numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html#overview) guidelines. Please read and follow the +numpydoc guidelines. Refer to the +[example.py](https://numpydoc.readthedocs.io/en/latest/example.html#example) provided by numpydoc. +- If proposing a new method, include at least one paragraph of narrative documentation with links to references in the literature (with PDF links when possible) and the example. +- If your feature is complex enough, consider creating a Jupyter notebook tutorial to illustrate its use instead. Tutorial Jupyter notebooks can be added to the docs [here](https://github.com/microsoft/graspologic/tree/dev/docs/tutorials). +- All functions and classes should be rigorously typed with Python 3.5+ [`typehinting`](https://docs.python.org/3/library/typing.html). +- All functions and classes must have unit tests. These should include, at the very least, type checking and ensuring correct computation/outputs. + + - It's important to write unit tests for your bug fix and your features. When fixing a bug, first create a test that explicitly exercises the bug and results in a test case failure. Then create the fix and run the test again to verify your results. + + - For new features, we advocate using [TDD](https://en.wikipedia.org/wiki/Test-driven_development) wherever possible. + +### Checking code + +After you have made changes to the `graspologic` code, you should use several +tools to help make sure your changes meet the standards for our repository. + +#### Code formatting +Please use `black` and `isort` so that the format of your code is compatible with our project. Format your code prior to committing using one of the following methods: +```bash +# Run "black" and "isort" using Make +make format +``` +OR +```bash +# Run "black" and "isort" +black graspologic/ tests/ +isort graspologic/ tests/ +``` + +#### Type checking +Validate your typehinting by running: +```bash +make type-check +``` +OR +```bash +mypy ./graspologic +``` + +#### Unit testing +To check if your code runs correctly, we recommend using unit testing that locally tests your code by implementing test cases. Execute these unit tests by running: +```bash +make test +``` +OR +```bash +pytest tests +``` + +#### Creating documentation +Build the documentation with the use of [sphinx](https://www.sphinx-doc.org/en/master/usage/index.html) by running: +```bash +make docs +``` +OR +```bash +sphinx-build -W -t build_tutorials -a docs/ docs/_build/html +``` +Please verify that the built documentation looks appropriate. You can view the `html` +from the `docs/_build/html` folder; click on `index.html` to see what the homepage would +look like and navigate from there. + +If you have made any changes that could affect the tutorials, please also build them. +This can take a bit longer because the code in each notebook actually needs to execute. +You can build the documentation and tutorials by running: +```bash +make docsWithTutorials +``` +OR +```bash +sphinx-build -W -t build_tutorials -a docs/ docs/_build/html +``` + +## Publishing Changes + +### Useful Git Commands +When working on a new feature, develop the feature on your feature branch. Add changed files using `git add` and then `git commit` files: + + ```bash + git add modified_files + git commit -m "your commit message" + ``` + + After making all local changes, you will want to push your changes to your fork: + ```bash + git push -u origin my-feature + ``` + +### Creating a pull request -We recommended that your contribution complies with the following rules before you submit a pull request: +We recommend that your pull request complies with the following rules before it is submitted: -- Follow the [coding-guidelines](#guidelines). -- Give your pull request (PR) a helpful title that summarizes what your contribution does. We are using PR titles to automatically generate release notes; examples of helpful PR title formats include: +- Make sure that the base repository and head repository, as well as the "base" file and "compare" file, are pointing to the correct locations +- Give your pull request (PR) a helpful title, set in the past tense, that summarizes what your contribution does. We are using PR titles to automatically generate release notes; examples of helpful PR title formats include: - `Added Feature[Set] {Title|Short Descriptor} in ModuleOrPackageName` - `Fixed bug in [ClassName.method_name|ModuleOrPackageName.function_name] where ShortDescription` - `Updated [ClassName[.method_name]|ModuleOrPackageName.function_name] to ShortDescription` -- Link your pull request to the issue (see: - [closing keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) - for an easy way of linking your issue) -- All public methods should have informative docstrings with sample usage presented as doctests when appropriate. -- At least one paragraph of narrative documentation with links to references in the literature (with PDF links when - possible) and the example. -- If your feature is complex enough that a doctest is insufficient to fully showcase the utility, consider creating a - Jupyter notebook to illustrate use instead -- All functions and classes must have unit tests. These should include, at the very least, type checking and ensuring - correct computation/outputs. -- All functions and classes should be rigorously typed with Python 3.5+ - [`typehinting`](https://docs.python.org/3/library/typing.html). Validate your typehinting by running `mypy ./graspologic` -- All code should be automatically formatted by `black`. You can run this formatter by calling: - ```bash - pip install black isort - black path/to/your_module.py - isort path/to/your_module.py - ``` -- Ensure all tests are passing locally using `pytest`. Install the necessary - packages by: - - ```bash - pip install pytest pytest-cov - pytest - ``` - -# Guidelines - -## Coding Guidelines - -Uniformly formatted code makes it easier to share code ownership. Graspologic package closely follows the official -Python guidelines detailed in [PEP8](https://www.python.org/dev/peps/pep-0008/) that detail how code should be -formatted and indented. Please read it and follow it. - -All new functions should have PEP-compliant type hints and "@beartype" annotations. This allows us a reasonable level -of confidence that arguments passed into the API are what we expect them to be without sacrificing runtime speed. See -https://github.com/beartype/beartype for more information. - -## Docstring Guidelines - -Properly formatted docstrings are required for documentation generation by Sphinx. The graspologic package closely -follows the numpydoc guidelines. Please read and follow the -[numpydoc](https://numpydoc.readthedocs.io/en/latest/format.html#overview) guidelines. Refer to the -[example.py](https://numpydoc.readthedocs.io/en/latest/example.html#example) provided by numpydoc. +- Link your pull request to the issue (see: [closing keywords](https://docs.github.com/en/github/managing-your-work-on-github/linking-a-pull-request-to-an-issue) for an easy way of linking your issue) +- Include a brief description of the changes you made in the code in the "write" box provided in the pull request page + +Once submitted, your PR will undergo automated tests that ensure its compilability and compatibility with our project. For debugging tests that raise errors online but passed locally, one can look at [this file](https://github.com/microsoft/graspologic/blob/dev/.github/workflows/build.yml) to see Github's exact execution. + + + From 74bf17b6b3bc4b2dc9128896810c3a61326831dd Mon Sep 17 00:00:00 2001 From: Vivek Gopalakrishnan Date: Wed, 20 Jul 2022 12:55:50 -0400 Subject: [PATCH 27/32] Added sex labels to (#967) Co-authored-by: Benjamin Pedigo --- graspologic/datasets/mice/participants.csv | 66 +++++++++++----------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/graspologic/datasets/mice/participants.csv b/graspologic/datasets/mice/participants.csv index 2b5c48dbd..a46fab505 100644 --- a/graspologic/datasets/mice/participants.csv +++ b/graspologic/datasets/mice/participants.csv @@ -1,33 +1,33 @@ -participant_id,genotype -sub-54776,DBA2 -sub-54777,DBA2 -sub-54779,DBA2 -sub-54781,DBA2 -sub-54790,B6 -sub-54793,B6 -sub-54794,B6 -sub-54797,B6 -sub-54811,BTBR -sub-54813,BTBR -sub-54815,BTBR -sub-54817,BTBR -sub-54821,CAST -sub-54823,CAST -sub-54829,DBA2 -sub-54831,DBA2 -sub-54833,DBA2 -sub-54835,DBA2 -sub-54842,CAST -sub-54847,CAST -sub-54849,BTBR -sub-54851,BTBR -sub-54853,BTBR -sub-54855,BTBR -sub-54864,B6 -sub-54866,B6 -sub-54868,B6 -sub-54870,B6 -sub-54883,CAST -sub-54885,CAST -sub-54887,CAST -sub-54890,CAST +participant_id,genotype,sex +sub-54776,DBA2,male +sub-54777,DBA2,male +sub-54779,DBA2,female +sub-54781,DBA2,female +sub-54790,B6,male +sub-54793,B6,male +sub-54794,B6,female +sub-54797,B6,female +sub-54811,BTBR,male +sub-54813,BTBR,male +sub-54815,BTBR,female +sub-54817,BTBR,female +sub-54821,CAST,male +sub-54823,CAST,male +sub-54829,DBA2,male +sub-54831,DBA2,male +sub-54833,DBA2,female +sub-54835,DBA2,female +sub-54842,CAST,female +sub-54847,CAST,female +sub-54849,BTBR,male +sub-54851,BTBR,male +sub-54853,BTBR,female +sub-54855,BTBR,female +sub-54864,B6,male +sub-54866,B6,male +sub-54868,B6,female +sub-54870,B6,female +sub-54883,CAST,male +sub-54885,CAST,male +sub-54887,CAST,female +sub-54890,CAST,female From 8516119d4092f3068ab9bc341e71dde0210745b9 Mon Sep 17 00:00:00 2001 From: Audrey Herskovits <102697879+aj-hersko@users.noreply.github.com> Date: Wed, 20 Jul 2022 10:44:50 -0700 Subject: [PATCH 28/32] fixing typo in aligning tutorial (#974) Co-authored-by: Benjamin Pedigo --- docs/tutorials/aligning/aligning.ipynb | 30 +++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/docs/tutorials/aligning/aligning.ipynb b/docs/tutorials/aligning/aligning.ipynb index b87c30563..dc0ae0162 100644 --- a/docs/tutorials/aligning/aligning.ipynb +++ b/docs/tutorials/aligning/aligning.ipynb @@ -5,7 +5,7 @@ "metadata": {}, "source": [ "# Aligning\n", - "`align` is a module that can be used to align two different datasets. In particular, all three currently existing classes, namely `SignFlips`, regular `OrthogonalProcrustes`, and `SeedlessProcrustes` are aimed at correcting an orthogonal transformation of the data, the exact form of which is unknwon. The motivation for this are orthogonal non-identifiabilities, which are common when dealing with various embedding methods, whether in statistical graphs or other domains. Noted that if two graphs are embedded using omnibus embedding - they don't need to be aligned." + "`align` is a module that can be used to align two different datasets. In particular, all three currently existing classes, namely `SignFlips`, regular `OrthogonalProcrustes`, and `SeedlessProcrustes` are aimed at correcting an orthogonal transformation of the data, the exact form of which is unknown. The motivation for this are orthogonal non-identifiabilities, which are common when dealing with various embedding methods, whether in statistical graphs or other domains. Noted that if two graphs are embedded using omnibus embedding - they don't need to be aligned." ] }, { @@ -70,7 +70,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -93,7 +93,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -161,7 +161,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -184,7 +184,7 @@ "outputs": [ { "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAWoAAAF1CAYAAADBWKCtAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAly0lEQVR4nO3df3Rc5X3n8fdXP2xJWDJYtomNbMsyYGxIF3YBg1TWIgQoCU6zp80SNgvYLG2JE0IpPZvyo07jlqbphrVZEqC0GwOnodS0J3GwYYNj1iTYQAJUZIOx+WVjKZDYlrFlox+WrGf/uHfkq2E0urLmxzMzn9c5OtKduXPvM+PxZ5557vc+15xziIiIv8ry3QAREUlPQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4jkFdQ6Y2RfM7OksbfshM/urbGw7G8zssJk15bsd+WBmm83shhzs5zUza832fpL2OfQ+NLOLzGxHLvdf7BTUGWJmv21mW83soJntN7MtZnYegHPue865y/LdxvEyM2dmp45h/Y8Ek3NuknPuncy3rnSY2QQzu9vMOsIPvp1mtipxv3PuTOfc5izsd6mZHQ33mfj5dvJ6zrmfOufmZ3r/pawi3w0oBmZWB6wHvgisBSYAFwF9+WzXWJhZhXNuIN/tkFhuA84FzgfeB+YA/zFH+37eOffbOdqXhNSjzozTAZxz/+ScO+qc63HOPe2c+wUM9USeS6wc9kyXm9mbZnbIzP7SzOaZ2fNm1mVma81sQrhua9hzut3M9pnZLjP7wkgNMbMrzazNzA6EPfzfSrOuM7MvmdmbwJvhbX9gZm+F3wp+aGYzw9t/Ej7s1bAndZWZnWRm681sr5l9EP7dEK5/F8GH1bejPa9or9zMJpvZI+Hj3zWzO82sLPqamdm3wm3vNLMr0jyXmWb2r+G2dprZV8Lbp4Sv35JweVL4/K4Nlz9tZv8Wvu7tZvYXkW02hu1dFt73gZndaGbnmdkvwtf425H1l4bfpO4Nv1ltN7NL0rT5ejN7Pdzuj8xszkjrJjkP+L5z7j0X2OWceySy3V1m9snw72ozezjcx+tm9t/NrCNp3T8Nn89BM/tnM6uK2Y6Rnldrin3cZmbbwnasSezDzKaG75sD4Xvup4n3gEQ45/Qzzh+gDugEHgauAE5Kun8p8Fxk2QE/DB93JkHPexPQBEwGtgHXheu2AgPA/wQmAouBD4H54f0PAX8V/v3vgT3AIqAcuA7YBUwcod0O2AhMAaqBTwD7wu1MBO4FfpK0/qmR5Xrg94AaoBZ4HPhB5P7NwA0p9nlq+PcjwLrwsY3AG8B/i7xm/cAfhM/li8B7gKV4HmXAy8AKgm8zTcA7wOXh/ZcBvwamA38P/Evksa3Ax8Nt/BbwG+Cz4X2NYXsfAKrC7fQCPwi3dUr4ei+OtHkAuAWoBK4CDgJTkl8P4LPAW8ACgm+2dwJbY77f7gR2A8vDtlvS/buAT4Z//w3wLHAS0AD8AuhIWvdnwMzwffA6cOMI+11K5H2cdN9DHHsftqbYxy+BWeE+tkTW/Ub4+laGPxel+jcu9Z+8N6BYfsL/cA8BHeF/1h8CJ4f3DXuDh//5WyLLLwNfjSzfDawO/24Nt3dC5P61wJ+Hf0f/g9wP/GVSu3YkgiRFmx3wicjy/wb+NrI8iSAsGyPrn5rmNTgb+CCyPBRMSfs8lSB8+4CFkfv+CNgcec3eitxXEz72Yyn2uwjYnXTbbcCayPK9wP8jCPv6NM9hNbAq/Lsx3Ocpkfs7gasiy/8K/HGkzcM+TAhC8Jrk1wN4ivBDKVwuA7qBOTHea+XAlwgCry/c53WR+3dxLKiHPrDC5Rv4aIj+18jy3wIPjLDfpeF78UDk54IU78PWFPu4MbL8KeDt8O+VBB/WI76v9OM09JEpzrnXnXNLnXMNwFkEPZTVaR7ym8jfPSmWJ0WWP3DOfRhZfjfcfrI5wK3h18gDZnaAoBeTat2E9sjfM8NtA+CcO0wQTKekeqCZ1ZjZ34XDFl3AT4ATzaw8zf4SphL0ft+N3PZu0r5+HWlLd/hn9HVJmAPMTHretwMnR9Z5kODfZY1zrjPyHBaZ2f8Nh0wOAjeGbYsay7/Vr1yYQJHnNNK/1T2R9u4HjBFe6ygXDK99xznXApwI3AV818wWpFh9JsP/jdtTrPPryN/dpH6NE15wzp0Y+XlhtPam2G/0NfkfBN8snjazd8zsz2Jur6QoqLPAObedoIdxVoY2eZKZnRBZnk3Qi0rWDtyV9B+pxjn3T+maG/n7PYIAASDcZz3wqxEeeyswH1jknKvj2AEtS7HtZPsIeuvRcdnZafaVTjuwM+l51zrnPhU+j3Lg7wiGWr5owytXHiX49jPLOTeZ4Gu4cfxOMbPo49P9W/1RUpurnXNbx7IzFxwP+Q7wAbAwxSrvEwx5JMway/YzKLrfodfEOXfIOXerc64JWAL8Sbpx/VKloM4AMzvDzG6NHEibBVwNxO1txPF1C8qyLgKuJBgPTvb3wI1hL9HM7ITwYFltzH08Ciwzs7PNbCLw18CLzrld4f2/IRj/Tagl6FEeMLMpwNeStpe8/hDn3FGCIZy7zKw2PJD2J8A/xmxr1M+ALjP7anjwrNzMzrKwPJKgdw1wPfAt4JFIr78W2O+c6zWz84H/chz7j5oOfMXMKs3scwRDYk+mWO8B4DYzOxOGDqx+LnGnBaWNf5FqB2b2x+EBu2ozqzCz68Ln8W8pVl8b7uckMzsF+PK4nt3x+5KZNYTvk9uBf4ahg9+nhh9uXcDR8EciFNSZcYhgnPRFM/uQIKB/SdDjzIRfE/SY3gO+RzDetz15JefcSwQH374drv8WwbhiLM65TcCfE4y7vg/MAz4fWeUvgIfDr+v/mWBop5qgd/wC8H+SNnkP8Pvhkf7/lWKXNxEcGH0HeI7gg+K7cdsbafdRgt7Y2cDOsD3/AEw2s/9A8AFwbbjeNwl6+omv2MuBlWZ2iOBg5Nqx7j/Ji8BpYRvuAn4/OtQSafP3w7Y8Fg4b/ZLgQHTCLIIx6FR6CI5j/Drcz5eA33Op69NXEhw32Qn8GPgX8lM2+ijwNMG/9TtA4iSt08J2HQaeB+5zWagBL3Q2fDhNfGPBGWb/GI59i8fMbCnBwcJx1RmH38wed85dmJGGDd/2F4HPO+cWZ3rbafa5i+B1+XGu9lls1KMW8YxzriNTIW1mM8ysxczKzGw+wbe872di25I7OjNRpLhNIDiQOpegnO4x4L58NkjGTkMfIiKe09CHiIjnFNQiIp7Lyhj11KlTXWNjYzY2LTIuH374ISeccMLoK4rk2Msvv7zPOTct1X1ZCerGxkZeeumlbGxaZFw2b95Ma2trvpsh8hFm9u5I92noQ0TEcwpqERHPKahFRDyXsxNe+vv76ejooLe3N1e7zKqqqioaGhqorKzMd1NEpMjlLKg7Ojqora2lsbGR4bNAFh7nHJ2dnXR0dDB37tx8N0dEilzOhj56e3upr68v+JAGMDPq6+uL5tuBiPgtp2PUxRDSCcX0XETEbzqYKCLiOQW1iIjnSi6o77//fpYvXz60fOedd3LNNdfksUUiIul5G9TJ069majrW6667jieeeIIDBw6wfv16NmzYwIMPPpiRbYuIZIOXFw5YtfENunr7WXHlQswM5xwr12+jrqqSWy49fVzbrqmp4eqrr+aOO+7gqaeeYuPGjVRXV2eo5SIimeddUDvn6OrtZ82WXQCsuHIhK9dvY82WXSxracQ5N+6Ki+uvv54FCxawbt065s2bl4FWi4hkj3dBbWasuHIhAGu27BoK7GUtjUM97PFauXIl06ZNY2BgYNzbEhHJNi/HqKNhnZCpkL777rvp7e1l7dq13HPPPePenohItnkZ1Ikx6aiV67eN+4DiM888w5o1a3j44YdpbW2lq6uLtra2cW1TRCTbvAvqREgnxqR3fuNTLGtpZM2WXeMK6927d3PDDTfw+OOPU1tbC8DNN9/M6tWrM9h6EZHM83KMuq6qctiYdGIYpK6q8riHP2bPns0777wz7LalS5eydOnS8TZZRCSrvAtqgFsuPX1YdUcirDW/hoiUIu+GPhKSQ1khLSKlytugFhGRgIJaRMRzCmoREc8pqEVEPKegFhHxnIJaRMRzfgZ1937Y/iQ89VX4wfLg9/Yng9vH4fXXX2fu3LkMDg4CMDg4yGWXXcYjjzySiVaLiGSFf0Hd+TZsWgnbN0D5RKhrCH5v3xDc3vn2cW96wYIFnHHGGaxfvx6A22+/nfnz53PttddmqvUiIhnn15mJ3fth671QUQ2TTj52e2U1TG6A3q7g/ktWQM2U49rFLbfcwqpVq+jv72fLli0888wzGWq8iEh2+NWj3v0CHO2HqrrU91fVwdEj0P7ice/isssuo6Ojg9tuu421a9dSWVl53NsSEckFv3rUO5+Fmvr069RMDdabf8Vx76a5uZlzzjmHGTNmHPc2RERyxa8edd8hqKhKv07FROg9NK7dbNu2jbPPPntc2xARyRW/gnpiLQz0pl9noA+qase1m9dee42zzjprXNsQEckVv4J67mLo7ky/Tve+YL3j1N7ezoknnsikSZOOexsiIrnkV1DPvgDKK4PqjlR6u6B8AsxadNy7mDVr1kcuICAi4jO/grpmCjTfBAM9cLAd+nvADQa/D7YHtzffdNyleSIihcivqg+A+nlBnXT7i0F1R1dnMCa9YEnQk1ZIi0iJ8S+oIQjj+VeMqwRPRKRY+DX0ISIiH6GgFhHxnIJaRMRzCmoREc8pqEVEPFdyQX3//fezfPnyoeU777yTa665Jo8tEpHxcs6lXS50JRfU1113HU888QQHDhxg/fr1bNiwgQcffDDfzRKR47Rq4xusXL9tKJydc6xcv41VG98YWqfQg9zPOmqgu7+bRY8OP1V8detqLplzybi2W1NTw9VXX80dd9zBU089xcaNG6murh7XNkUkP5xzdPX2s2bLLgBWXLmQleu3sWbLLpa1NOKcY/WP36Srt58VVy7EzIaCvK6qklsuPT2/TyAmb4N6xwc7AJheM53GukbKrZzTTjotI9u+/vrrWbBgAevWrWPevHkZ2aaI5J6ZseLKhQCs2bJrKLCXtTQO3T5akJtZPpo+Jt4G9bZ92wCYecJMmiY30Tyzmdl1szOy7ZUrVzJt2jQGBgaGbjty5Ai33nor5eXlHDhwgLvuuovPfOYznHfeeQCsXr2aqqpR5soWkZxLhHUijIGh3nPib0gd5IUQ0uDxGPUre14BoG1vG4/teIxNuzdlZLt33303vb29rF27lnvuuWfo9ueee45p06axevVqHnroIQYHBznvvPN44IEHeOCBBxTSIp5KDGVERceso73uhEIKafC4R922tw2AdZ9dR6VVMq1m2ri3+cwzz7BmzRqef/55amtr6erqoq2tjbPPPpsLL7yQTZs2cc0113D55ZczadIkXn/9dW688UauuuoqLr744nHvX0QyKxHSiaGM6NAGHOtNpwryQgprL4O672gfe7r3ML16Ok2TmzKyzd27d3PDDTewYcMGamuDK8TcfPPNQz3o6upq7rrrLgYHB2lpaeGTn/wkq1ev5pxzzsnI/kWSJY+PFsp4qU/MjLqqymFDGYlwrqsKLlw9WpAXwmvuZVDv79lPmZXRckpLxrY5e/bsj1wwYOnSpSxduhSA5cuXU1FRweHDh7n99tt56KGH+NrXvpax/YtErdr4RsFXIvjilktPH/YhlwjrxHK6IC+EkAZPg3rGpBm8eu2rOd3nfffdN2x5yZIlOd2/lI44JWWFEiC+SH69osujBXkh8DKoRYrZaCVlhRQghSJdkBcCb6s+RIpZMVQiSO4oqEXyYLSSMpGonAZ1Mb0Ji+m5SG4ll5Tt/ManWNbSyJotuxTWklLOxqirqqro7Oykvr6+4L/eOefo7OzUSTByXEYrKSv0/x+SeTkL6oaGBjo6Oti7d2+udplVVVVVNDQ05LsZUqCKoRJBcidnQV1ZWcncuXNztTsR7xV6JYLkjg4mioh4TkEtIuI5BbWIiOcU1CKSNYV+CSxfKKhFJCviXMtQ4lFQi0jGRSeeSoR14iSfrt5+9azHSJMyiUjGaeKpzFKPWkSyQhNPZY6CWkSyQhNPZY6CWkQyThNPZZbGqEUk4zTxVGYpqEUidMHZzNHEU5mjoQ+RkOp+M08TT2WGgloE1f2K3zT0IYLqfsVv6lGLhFT3K75SUIuEVPcrvlJQi6C632JX6LP4aYxaBNX9xlWI5YurNr5BV2//0L9r4kO5rqqSWy49Pd/Ni0VBLRJS3W96hRh40WoeCI45RL85FcIHDSioRYZR3W9qhRp4xVLNo6AWkVEVcuAl2p5oMxReNY8OJopILIVavlgM1TwKahGJpRADr1iqeTT0ISKjSg686Bg1+NuzLpZqHgW1iIyqkAOvGKp5FNQiEkshB16hV/NojFpEYiv0wCtUCmoREc8pqEVEPKegFhHxnIJaRMRzCmoRGVWhTxNa6BTUIpKWLvqbfwpqERmRLvrrB53wIiIjKuRZ84qJetQiklahzppXTBTUIpJWIc6aV2wU1CIyomKZJrTQaYxaREZUyLPmFRMFtYikVciz5hULDX2IyKg0a15+KahFRDynoBYR8ZyCWiQmzXch+aKgFolB811IPimoRUah+S4k31SeJzIKzXch+aYetUgMmu9C8klBLRKD5ruQfFJQi4xC811IvmmMWmQUmu9C8k1BLRKD5ruQfNLQh0hMhTbfhU7QKR4KapEipBN0iouCWqTI6ASd4qMxapEioxN0io961CJFSCfoFBcFtUgR0gk6xUVBLVJkSuUEnVKqatEYtUiRKYUTdFZtfIOu3v6h55f4cKqrquSWS0/Pd/MyTkEtUoQK5QSdaBsTy8BHbkteTlS1QDD2Hv0GkWr9dMuFQEEtUqR8P0EnVa/4P923BTC+v7x5xJ7yWKpaiqXnrTFqEcm5VLXeX3/iNdraD9LWfoCVT6Sv/45T1VJM9eTqUYtIzo3UK17aPAfDWLN1F2u2Brel6imPVNUSXa+Y6snVoxaRvEjVK/7akjNZsWT0nnLcqpZiqSdXUItIXqTqFX/9iddY+UT6+u+RqlqWtTR+pKqlWOrJNfQhIjmX3CteceVCvv7Eazy09V0AljU3smLJsWoOGN4TjlPVkmofI23PdwpqEcm5VL3iry05k7b2A4CxYsno9d9xloulntyy8RXg3HPPdS+99FLGtysyXps3b6a1tTXfzZDQ8dRRZ2IfPoa0mb3snDs31X3qUYtI3sSp9R5vqPpeTx6HDiaKiHhOQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4jkFtcgokq8rmo3rjIqko6AWSWPVxjdYuX7bUDg751i5fhurNr6R55ZJKVFQi4zAOUdXbz9rtuwaCuuV67exZssuunr71bOWnNFVyEVGYGasuHIhAGu27GLNll0ALGtpZMWVCwvyatZSmNSjFkkjGtYJCmnJNQW1SBqJ4Y6o6Ji1SC4oqEVGEB2TXtbSyM5vfIplLY3DxqxFckFj1CIjMDPqqiqHjUknhkHqqio1/CE5Eyuozex3gHuAcuAfnHN/k9VWiXjilktPxzk3FMqJsFZISy6NOvRhZuXAd4ArgIXA1Wa2MP2jRIpHcigrpCXX4oxRnw+85Zx7xzl3BHgM+N3sNktERBLiBPUpQHtkuSO8TUREciDOGHWq73kfOdxtZn8I/CHAySefzObNm8fXMpEsOHz4sN6bUnDiBHUHMCuy3AC8l7ySc+5B4EGAc88917W2tmaifSIZtXnzZvTelEITZ+jj58BpZjbXzCYAnwd+mN1miYhIwqg9aufcgJl9GfgRQXned51zr2W9ZSIiAsSso3bOPQk8meW2iIhICjozUQpGd383ix5dNOy21a2ruWTOJXlqkUhuKKilYOz4YAcA02um01jXSLmVc9pJp+W5VSLZp6CWgrFtXzCL3cwTZtJ0wkyay+qYveU70HcIJtbC3MUw+wKomZLnlopkloJaCsYre14BoG1vG2172+ipPJmLpzZD3WQY6IXtG+DNp6H5Jqifl+fWimSOgloKRtveNgDWTb6AyvJqptVMg7LwLVxZDZMboLcLtt4Ll6xQz1qKhuajloLQd7SPPd17mF5ZRxMTmDVpBlVlKfoZVXVw9Ai0v5j7RopkiYJaCsL+nv2UWRkt5XVQU59+5ZqpsPPZ3DRMJAcU1FIQZkyawavXvsrKiXOhoir9yhUTofdQbhomkgMKaiksE2uDA4fpDPRBVW1u2iOSAwpqKSxzF0N3Z/p1uvcF64kUCQW1FJbZF0B5ZVDdkUpvF5RPgFmLUt8vUoAU1FJYaqYEddIDPXCwHfp7wA0Gvw+2B7c336TSPCkqqqOWwlM/L6iTbn8xqO7o6gzGpBcsCXrSCmkpMgpqKUw1U2D+FcGPSJHT0IeIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOdKava87v5uFj06fEL51a2ruWTOJRnb3jcv+iZf/elXM7YPEZGSCuodH+wAYHrNdBrrGim3ck476bSMbq/MyjK6DxGRkgrqbfu2ATDzhJk0TW6ieWYzs+tmZ3R77x1+L6P7EBEpqaB+Zc8rALTtbaNtbxs9Az1cPPvij6wXd4gk1fZ6Bnpi7UNEJK6SCuq2vW0ArPvsOiqtkmk101KuF3eIJNX2Pv39T8fah4hIXCUT1H1H+9jTvYfp1dNpmtyUdt04QySptjeWfYiIxFUyQb2/Zz9lVkbLKS2jrhtniCTV9sayDxGRuEomqGdMmsGr174aa904QySptjeWfYiIxFUyQR1XKQxfZLqeXESyS0GdpBSGLzJdTy4i2aWgTlIKwxeZricXkexSUJeguPXkIuIHBXUJiltPLiJ+UFCXmFI4WCpSbDTNaYkphYOlIsVGPeoSUwoHS0WKjXrUIiKeU49avKcTdKTUKajFexk5Qad7P+x+Abo+gB8sh4m1MHcxzL4AaqZkodUimaOgFu+N+wSdzrdh671wtB/KWqCuAQZ6YfsGePNpaL4J6udlqfUi46cxavFe9ASdx3Y8xqbdm+I/uHt/ENIV1TC5AawMzKAyXK6oDu7v3p+l1ouMn3rU4r1xnaCz+4WgJz3p5NT3V9XBwYPQ/iLMv2L8jRXJAvWoxWvJJ+jMqptFVUVV/A3sfBZq6tOvUzM1WE/EU+pRy9glDsztfBb6DmX1wNy4T9DpOwR1k9OvUzERujqPb/siOaCglrGJHpirqQ9CMIsH5sZ9gs7E2qB9ldUjrzPQB1W1x78PkSzT0IfEl3xgrrLa/wNzcxdD9yi95e59wXoinlJQS3yJA3NVdanvr6qDo0eCA3O+mH0BlFdCb1fq+3u7oHwCzFqU+n4RD2jowzc5HP8ds7EcmPOlgqJmSjAcs/XeoLqjbA64wWC4o3tfENLNN+X/tRVJQ0HtkxyP/45ZoR6Yq58Hl6wIevo79kPXe8GY9IIlQU9aIS2eU1DnU7T3/OE+2PManNgIU08/dvArMf7b2xWE+CUr8hcshXxgrmZK0Mt/fzO0fiffrREZEwV1viT3ngcHwQEHO+DQ+9Bw/rBA7p5QzaI96+HxY2fl5XxiormLg9795IaR1+neF/RURSRjdDAxH1JVTxx8FybWBQfkyiqg42fQ3zP0kB39BwCYXlbF+R87nwtnXJj7K4frwJxIXiio8yFV9cTAkSCgIRjnHTwKXR1Dd2/rC0reZtoEmiY3cfUZV+f+yuGJA3MDPXCwPfggcYPB74Ptwe06MCeScRr6yIdU1RMVE2BwAMrDf5LKavjgXagPes2v9O0FoO1oF207HsvflcOjB+Z2PhscONSBOZGsUlDnQ6rqiRMbYd8bUB72sssqgvVCbUeCoF737/6UyqZP5PfK4YkDc76U4IkUOQX1WMWtc063XqrqickNsP/toGqiYmLQu66YCECfO8qeoz1Mtwk0nb5EvVaREqOgHou4dc6jrfexj8OvXhlePVFZDbPOh/afQW8fuAGYtgD6e9h/uIMyoKXhIoW0SAlSUMcVrdSIzm2cXOfc/JXR1+t4Kbitt2v4AcXqKUGve98bcOBdsHIYPMKMMz/Hq7O+pZAWKVEK6rjiTkDf9r3R1+s7CA3nwfuvBo+pmRoMcyROa679GFx+ly4PJSKAgjq+uPNcvPkjaPrE6Ovt26HqCRGJRUEdV9x5Lo58CKNdgSQxH4aqJ0QkBp3wEleiUiOdgT6YcEK89XycD0NEvKSgjivuBPSnXa6J6kUkoxTUccWd5+LsL2g+DBHJKAV1XHHnuahvyuh8GN393Xz84Y8P+9n07qbRHygiRaNkDiZ293ez6NHhvdgxTxMad56LDM6HseODHQBMr5lOY10j5Vae+1nzRCSvSiaoMxZ4cSs1MlTRsW3fNgBmnjCTpslNNM9szv2seSKSVyUT1IUaeK/seQWAtr1ttO1ty9+seeL39SylqJVMUBdq4LXtbQNg3WfXUWmV+Z01r5T5fj1LKWolE9SFGHh9R/vY072H6dXTaZrclN2dqbc4srjzvOTzepZS1Eqi6iM58GbVzaJqtLMHPbC/Zz9lVkbLKS3Z3VHn27BpZdA7LJ8IdQ3B7+0bgts7387u/n2X6oo8UVV1cPRIcPBYJAtKokeds8DLsBmTZvDqta9mdycF3lvMSDXPaOLO87LzWU0HIFlREkGdk8ArVHFnBWx/0csQykn5Ytx5XrpGOSNV5DiVxNCHpDGW3qKHkqt5snLR37jzvGj+FskSBXWp6zsUb7a/3kPp18mTaDXPYzseY9PuLJy1GXeeF83fIllSEkMfkkaq6zcm87i3mJNqntkXBCV4yVfkSdD8LZJl6lGXugLuLeasmifuPC8eHmyV4qCgLnVxZwX0sLeY02qexPwtC5bA4BHoei/4vWBJcLtOdpEs0tBHjuWknGwsEr3Frfemvn5j+QRve4s5r+bRFXkkTxTUOeblbHgZnO1PRDJPQZ1j3k4Opd6iiLcU1DlWqJNDiUj+KKhzrBAnhxKR/FJQ51BOZ8MbD82kJ+IVBXUOFcTkUJp3WcQ7Cuoc8n5yqAKfSU+kWOmEFzlG8y6LeElBLccU+Ex6IsVKQS3HFPhMeiLFSkEtx2jeZREvKajlmAKeSU+kmKnqQ47J0LzL3k08JVLgFNRyTIZm0vNy4imRAqagluEyMJOetxNPiRQoBbV81Dhn0tPEUyKZpaCWjPNq4qnkeUvKWmD7k5q3RAqKgloyyquJp1LNW3LYNG+JFJySCWpVIuSGNxNPjTRviZVp3hIpOCUT1KNVImQ1yEto2lBvJp5KzFsSDemoqrqgsqX9RV3VRrxXMkE9WiVC1krKNG1ofoxl3hIFtXiuZIJ6tEqErJSU+TptaCn08PsOBR+K6VRMDMoPRTxXMkE9WiVCVkrKfPz6XSo9/MS8JZXVI6+jeUukQJREUMepRMhKSZlvX7997eFnw9zFwYfP5IaR1+neF5zII+K5kpiUabRKhOQgn1U3i6rRpvuMw7dpQ0vpwgCzL4DyyuDDJ5WY85aI+KAketSjVSJkraTMt6/fvvXws2mkeUvcIBxsjz1viYgPSiKoR5O1kjLfvn6X2gG2VPOWlDWOad4SER8oqLMpQ9OGZoxvPfxcSJ63ZPNmmN+azxaJjFlJjFHnTeLr90BP8HW7vyf46t0fLg/05Pbrty4MIFKQFNTZlvj6vWAJDB6BrveC3wuWBLfnshROB9hECpKGPnJhnNOGZrQdGbgwgIjkloK61GTgwgAiklsK6lLkSw9fRGLRGLWIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOcU1CIinlNQi4h4TkEtIuI5BbWIiOcU1CIinlNQi4h4TvNRF5ru/bD7hWDS/75DwQVr5y4OLrOlSf9FipKCupB0vh1cRutoP9TUQ93k4Kri2zcEVztvvim312AUkZxQUPtmpB7ztDOCkK6ohkknH1u/shomNwQXpt16b3CZLfWsRYqKxqh90vk2bFoZ9JDLJ0JdQ/B7+wZ48lbo7oSqutSPraqDo0eCayGKSFFRUPuie/+xHvPkhqCnbHasx3x4H+x/B/p7Rt5GzdSgJy4iRUVB7YvdLwRjzyP1mHHggK6OkbdRMRF6D2WjdSKSRwpqX+x8NjhAOJKKicHPB++OvM5AH1TVZr5tIpJXCmpf9B2CiqqR7z9xDhztC8J4JN37ggOPIlJUFNS+mFgblNqNZHIDYOFPCr1dUD4BZi3KRutEJI8U1L6Yuzio6hhJZTVMaYTa6XCwPTio6AaD3wfbYaAnqKNWaZ5I0VEdtS9mXxCctNLblfqAYm9XUNXR/BXYtyMY0+7qDMakFywJetIKaZGipKD2Rc2UoEe89V44eDAI5YqJwZh0975gWKP5JqhvCn7mX5HvFotIjiiofVI/LzizsP1F9ZhFZIiC2jc1U4LesnrMIhLSwUQREc8pqEVEPKegFhHxnIJaRMRzCmoREc8pqEVEPKegFhHxnIJaRMRzCmoREc8pqEVEPGfOucxv1GwvkOZSJCJ5MxXYl+9GiKQwxzk3LdUdWQlqEV+Z2UvOuXPz3Q6RsdDQh4iI5xTUIiKeU1BLqXkw3w0QGSuNUYuIeE49ahERzymopSSY2e+Y2Q4ze8vM/izf7REZCw19SNEzs3LgDeBSoAP4OXC1c25bXhsmEpN61FIKzgfecs6945w7AjwG/G6e2yQSm4JaSsEpQHtkuSO8TaQgKKilFFiK2zTmJwVDQS2loAOYFVluAN7LU1tExkxBLaXg58BpZjbXzCYAnwd+mOc2icRWke8GiGSbc27AzL4M/AgoB77rnHstz80SiU3leSIintPQh4iI5xTUIiKeU1CLiHhOQS0i4jkFtYiI5xTUIiKeU1CLiHhOQS0i4rn/D2q12lYWst2fAAAAAElFTkSuQmCC\n", + "image/png": "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", "text/plain": [ "
" ] @@ -293,7 +293,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -318,7 +318,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -404,7 +404,7 @@ }, { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -427,7 +427,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -475,7 +475,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -515,7 +515,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -620,7 +620,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -659,7 +659,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -727,7 +727,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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", "text/plain": [ "
" ] @@ -765,7 +765,7 @@ "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAsoAAADRCAYAAADVGJQxAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjMuMCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy86wFpkAAAACXBIWXMAAAsTAAALEwEAmpwYAAAXNUlEQVR4nO3de4yld1nA8e8zs7t2azXtrhSDNV0pGlpaBYoaqtCNthjBUlqIAgoVvELBawNBjZEoRCOIlzSgiKHWRBDThaBVrm0pAnKxWreFCrRADZRettubbXd35vGPc2Z/0+WcM7NzzjvnPDPfT3Iy3XOb32z6bZ/3vJeJzESSJEnSI81NewGSJEnSLHJQliRJkgZwUJYkSZIGcFCWJEmSBnBQliRJkgZwUJYkSZIGcFCWJEmSBnBQliRJkgZwUJ6giNgeEb8SEddGxB0R8XBE3BIRfxkRu6a9PmmzsUmpDnvVLAp/M99kRMSTgXcBJwPvAT4GPAg8BXgxcB/wjMz81NQWKW0iNinVYa+aVQ7KExARTwSuohfy+Zl53RGP/xjwr8DngVMzc2HdFyltIjYp1WGvmmUOymOKiGOB/wROAn4gM/cOed4/Ac8Czs7Mj6zfCqXNxSalOuxVs85jlMf3i8B3A28aFnjf0hbyqd0vSdrUbFKqw1410xyUx/dLwALw5hWe93/9r1u6XY606dmkVIe9aqY5KI8hIh4DPB74VGb+7wpPf1z/663drkravGxSqsNeVYGD8nhO7n/94qgnRcQc8AzgEL0zeSV1Y6wmI+LHI+KaiLg9Iu6LiL0R8fz+Y/MR8X8R8UBE3L/s9oyufhhpg1vPXvdHxD9ExDd39cNoY3IXxmQcu8Ljz6N3osI/Zuad67AeabM76iYj4ifp7f79aeCD9P77eBa9S1RB79jI7cAJmbm/gzVLm1VXvR5Dr9d7IuJk4FPAy4E/nvhPoA3LQXk8NwGLwPdGROSAS4hExKOAP6UX72vWd3nSpjNOk78EvDMz/7X/50PAh5c9fibwVYdkaWK67vWmzLwHIDO/HBFfoTc8S6vmoRdjyMx9wD8Bp9DbSn2EiPhO4H3Ao4Gfy8wvrO8Kpc1lzCbvBM6PiF+MiO8a8PZnAjdMftXS5rQOvf57/32+KSJ+HjgNePdEfwhteF5HeUwR8R3AR4FdwBXAR+htIT8JeD7wEPDzmXnFtNYobSZrbTIiTgB+E7iA3v9Q9wK/kplX9R//KL3fEvbQspc9NTM/2+XPI21kHff6ZOBh4P7+46/LzI92/1NpI3FQnoCI2AFcAjwH+C7arp3LgFdl5u1TWpq0KY3bZP+TrLcCp2fmSf2Tie4FXuxGrzRZHfb6o5n5750tXJuCh15MQGbuy8zfyszTMnM78ATgAeCJ9GKVtI7GbTIzb6W3y3fpDPnH9//5k92sWNq8Our1WHqfIktjcVDuQGbeCLwM+D7g0ikvR9r0VmoyIl4TEbsj4tiI2BIRu+nt1l167pPpnci30rVeJY1pQr3enJkPrNOStYF56IWkTS8iXgdcSO8SVAeALwCXZubf9h9/E7ArMy+Y3iolwap7PTkzL5zeKrVROChLkiRJA3johSRJkjSAg7IkSZI0gIOyJEmSNICDsiRJkjSAg7IkSZI0gIOyJEmSNICDsiRJkjSAg7IkSZI0gIOyJEmSNICDsrRMRJwUEX8WER+NiPsjIiNi91G8/pSIeHdE3BMR90XElRFxWncrljY3m5XqqNirg7L0SI8DXgDcD3zoaF4YEScC1wK7gIv677MDuCYiTprsMiX12axUR7let3T1xlJRH8nMEwEi4jnAs4/itZcAJwBPycyv9t/j48AtwG8DL5vsUiVhs1Il5XodOSh/y9MvyS6+6Ub39kt/Y9pLKO25ZzwmpvW9M3NxjJdfAHxgKeD++90VEe8FLmQd/qe77Ukvtdk1uPdjl057CWUds3371HqF2s1+6+5X2+savOVNr5z2Esp64ZNOstej5KEX0gRExHbgFGDvgIevB07s7zaSNANsVqpjmr166IU2pIjYv9JzMvP4CX7LE4AA9g14bOm+ncDtE/ye0oZhs1Idm6lXB2WV9cuxa9Ruy3vWbSGPNGpN7mbVprVCr2Cz0syw18ZBWWVtmxt+qFUuTHRLdjXuphfpzgGP7eh/HbQlLG0Ko3oFm5Vmib02Dsoqa6WQ11NmPhgRNwOnD3j4DOCOzHQXrjatWeoVbFYaxV4bT+ZTWfMx/DYle4BzI+Lbl+6IiB3AecAVU1uVNANG9Wqz0myx18ZPlFVWV1u8EfG8/j9+f//r2RHxbcADmfkv/edcDZydmcsX8QbgRcCVEfFa4BDwO/2vr+9ksVIRXX5CZbPSZNlr46CssrZGZyG/64g//17/65fp/UaggTLz6xHxNHoxX05vj821wNMz8yuTX6ZUR4e9gs1KE2WvjYOyyprvKOQjtmCHPWf3kPs/D5w/6TVJ1XXVK9isNGn22jgoq6xZO9lA0nD2KtVhr42DssoyZKkOe5XqsNfGQVllTfHMW0lHyV6lOuy1cVBWWW7xSnXYq1SHvTYOyirLkKU67FWqw14bB2WV5a4hqQ57leqw18ZBWWW5xSvVYa9SHfbaOCirLEOW6rBXqQ57bRyUVVaXF0SXNFn2KtVhr42Dssqa3zI37SVIWiV7leqw18ZBWWXNb5uf9hIkrZK9SnXYa+OgrLLC03KlMuxVqsNeGwdllTW/1S1eqQp7leqw18ZBWWXNb/MYKqkKe5XqsNfGQVlleQyVVIe9SnXYa+OgrLLC6zxKZdirVIe9Ng7KKsstXqkOe5XqsNfGQVllGbJUh71Kddhr46Cssrx8jVSHvUp12GvjoKyyvHyNVIe9SnXYa+OgrLK8fI1Uh71Kddhr46CssmLekKUq7FWqw14bB2WVNb/VkKUq7FWqw14bB2WV5Vm5Uh32KtVhr42Dsspy15BUh71Kddhr49+EyprfumXobRwRcVxE/HlEfC0iHoyIT0fEs1fxut+LiBxwu22sBUkbwKhex2nWXqXJs9fGT5RV1ty2zv713QM8GXgVcAvws8CeiDgvM69cxevPBe5f9ucDE1+hVIy9SnXYa+OgrLJibvI7RCLimcA5wIWZuad/31XAY4E3AqsJ+dOZuX/ii5MKs1epDnttPPRCZc1t2zr0NoYLgHuA9yzdkZkJXAY8PiJOG2/V0uY0qtcxmrVXqQP22jgoq6yOjlE+HbgxMxePuP/6ZY+v5LMRsdA/BuutEXHiOAuSNoKOjnm0V6kD9tp46IXKGnVWbkTsX+n1mXn8gLt3Av8z4P59yx4f5ovAbwHX0Ttu6ofoHYf1oxFxZmbevdKapI1qpbPo19isvUodsNfGQVllzY15dYsRci2PZeblR9z14Yj4BPB+4GLgDyawNqkke5XqsNfGQVllzY84K3fIp8WrcReDt2p39L/uG/DYqHV8ICK+Bjx1jeuRNoRRvcKam7VXqQP22niMssqKubmhtzHcAJwaEUe+yRn9r3vX8J5zwJHHZEmbyqhex2jWXqUO2Osjv4FU0ty2LUNvY9gDHA+cd8T9LwZuyswbj+bNIuIZwKOBT4yzKKm6Ub2O0ay9Sh2w18ZDL1TW/NaxLgM3zJXAVcDbImInvQuiXwT8MHD+0pMi4mrg7MyMZfddB/wtcBNwEDgLuAT4AnBpF4uVqrBXqQ57bRyUVVYXvzkoMzMingO8vn87HriR3gXS37vCyz8HvBx4DLAVuBX4a+D3/YUG2uzsVarDXhsHZZXVxW8OAsjMe4FX9G/DnrN7wH0v6GRB0gZgr1Id9to4KKusDn8XvaQJs1epDntt/JtQWXNbOjmGSlIH7FWqw14bB2XVNTc/7RVIWi17leqw18MclFVWdHNWrqQO2KtUh702Dsqqa8u2aa9A0mrZq1SHvR7moKyyujorV9Lk2atUh702Dsqqyy1eqQ57leqw18MclFVWeFauVIa9SnXYa+OgrLo8K1eqw16lOuz1MAdlleVZuVId9irVYa+Ng7LKCo+hksqwV6kOe20clFWXZ+VKddirVIe9HuagrLLc4pXqsFepDnttHJRVlsdQSXXYq1SHvTYOyqrLs3KlOuxVqsNeD3NQVlle51Gqw16lOuy1cVBWXfOGLJVhr1Id9nqYg7LqCs/KlcqwV6kOez3MQVll5Zz/+kpV2KtUh702/k2ornlPNpDKsFepDns9zEFZZbnFK9Vhr1Id9tr4N6G6PIZKqsNepTrs9TAHZZXlFq9Uh71Kddhr49+E6vKC6FId9irVYa+HOSirLncNSXXYq1SHvR7m34TKyvktQ2/jiIjjIuLPI+JrEfFgRHw6Ip69yteeEhHvjoh7IuK+iLgyIk4ba0HSBjCq13GatVdp8uy1cVBWXXNbht/Gswf4aeB3gGcBNwJ7IuKZo14UEScC1wK7gIuAFwA7gGsi4qRxFyWVNqrX8Zq1V2nS7PUwD71QXR3sGurHeg5wYWbu6d93FfBY4I3AlSNefglwAvCUzPxq/7UfB24Bfht42cQXLFVhr1Id9nqYnyirrJzbMvQ2hguAe4D3HP4+mQlcBjx+hd08FwAfWIq4/9q7gPcCF46zKKm6Ub2O0ay9Sh2w18ZBWXXNzQ+/rd3pwI2ZuXjE/dcve/wbRMR24BRg74CHrwdO7O86kjanUb2uvVl7lbpgr4eN3Cy483ef0NX33dC+7eI/mfYSSnvuR96wqufliF1DEbF/xddnHj/g7p3A/wy4f9+yxwc5AYhlzxv22ttXWtc47v3YpV2+/Yb1rWddPO0llHXgur9Z1fNG9QprbrZ0r7e/aleXb79hnfjrfzHtJZT1wqv/aFXPs9fGY5RVVnZ3ncdc42PjvlbasOxVqsNeGwdllbWwOLyLIZ8Wr8ZdDN6q3dH/OmiLFuBueqGu5bXShjeqV1hzs/YqdcBeG49RVlk54jaGG4BTI75hv9MZ/a+DjpEiMx8EbmbwMVZnAHdkZqe7caVZNqrXMZq1V6kD9to4KKushcUcehvDHuB44Lwj7n8xcFNm3rjCa8+NiG9fuiMidvTf64pxFiVVN6rXMZq1V6kD9tp46IXKWujmiKQrgauAt0XETnrXaLwI+GHg/KUnRcTVwNmZGcte+wbgRcCVEfFa4BC9i6ofAl7fyWqlIuxVqsNeGz9RVlmLOfy2Vv1rOj4HeAe9+P4F+F56F0h/7wqv/TrwNOBW4HLgncB+4OmZ+ZW1r0qqb1Sva23WXqVu2GvjJ8oqayG72eTNzHuBV/Rvw56ze8j9n2fZlrGkHnuV6rDXxkFZZS0ceclySTPLXqU67LVxUFZZ2dEWr6TJs1epDnttHJRVVkcnG0jqgL1Kddhr46Cssro6hkrS5NmrVIe9Ng7KKstjqKQ67FWqw14bB2WVtdjdr3aXNGH2KtVhr42Dsspyi1eqw16lOuy1cVBWWR5DJdVhr1Id9to4KKssO5bqsFepDnttHJRV1kGvXyOVYa9SHfbaOCirrIOLHkQlVWGvUh322jgoq6xF9w1JZdirVIe9Ng7KKstdQ1Id9irVYa+Ng7LKOrhoyFIV9irVYa+Ng7LKWjBkqQx7leqw18ZBWWW5xSvVYa9SHfbaOCirrIP+6iCpDHuV6rDXxkFZZXlWrlSHvUp12GvjoKyy3DUk1WGvUh322jgoqywvXyPVYa9SHfbaOCirLHcNSXXYq1SHvTYOyirLkw2kOuxVqsNeGwdlleUxVFId9irVYa+Ng7LKWnDXkFSGvUp12GvjoKyyDhxy15BUhb1Kddhr46CssgxZqsNepTrstZmb9gKktTpwaHHobb1FxKMj4rKIuDMiHoiIayPirFW+9u0RkQNun+h63dJ6GdWrzUqzxV4bP1FWWQszcrJBRBwDfAg4DnglcBfwa8CHIuKszLxuFW9zP3DuEffdN8l1StM0K72CzUorsdfGQVllzdCuoZcCTwDOzMz/AIiIa4DPAq8HfnwV77GQmX4apQ1rhnoFm5VGstfGQVllPTw7IV8A/PdSwACZ+XBE/D3w6oj4lsz0kyZtajPUK9isNJK9Nh6jrLIWFnPoLSL2r3Sb4FJOB/YOuP96YB44dRXvcVxEfD0iFiLiyxHxxog4boJrlKZqVK82K80We238RFllHZid3xy0E9g34P59yx4f5b+A/6T3H4J5esdRvRJ4WkT8UGYenNA6pamZoV7BZqWR7LVxUFZZo46hyszj1/KeEbEbuGqVT39UZt659C1HPG/kWRGZ+aYj7npfRNwE/BXwU8DfrXI90sxa6ZhHm5Vmh702Dsoqq6Ozcj8HvGSVz106JuouBm/R7uh/HbQlvJK/A94CPBX/p6sNoMOz6G1WmjB7bRyUVdaBQwsTf8/MvA14+1G+7AZ6x1Ad6Qxggd5/GI5W9L/O1P4vaa266BVsVuqCvTaezKeyHj60OPS2zvYAZ0TEE5fuiIhtwAuAD2bmvWt4z5+h16eXn9KGMKpXm5Vmi702fqKssmboguhvAy4GroiI19DbDfSrwGOAn1z+xIj4EkBm7ur/+WTgcuDvgS/SO9HgHOAVwMeBd67HDyB1bYZ6BZuVRrLXxkFZZc3KBdEz86GI+BHgj4E3A8cA/wGcm5mfWeHl9wJ3Aq8GHk1vd9DNwB8Cf5iZhzpbuLSOZqVXsFlpJfbaOCirrBkL+TbgRat43q4j/nw3cGFHy5Jmxiz1CjYrjWKvjYOyysrZ2jUkaQR7leqw18ZBWWUtzNYF0SWNYK9SHfbaOCirrIUZ2zUkaTh7leqw18ZBWWWlHUtl2KtUh702Dsoqy11DUh32KtVhr42DsspadNeQVIa9SnXYa+OgrLIW07NypSrsVarDXhsHZZXlFq9Uh71Kddhr46CssjyGSqrDXqU67LVxUFZZC4fcNSRVYa9SHfbaOCirLH9zkFSHvUp12GvjoKyy3DUk1WGvUh322jgoqyxPNpDqsFepDnttHJRV1qK7hqQy7FWqw14bB2WVteiuIakMe5XqsNfGQVllLRw6NO0lSFole5XqsNfGQVll5eLCtJcgaZXsVarDXhsHZZW1ePDAtJcgaZXsVarDXhsHZZW1eMiQpSrsVarDXhsHZZXlriGpDnuV6rDXxkFZZbnFK9Vhr1Id9to4KKusBUOWyrBXqQ57bRyUVZa7hqQ67FWqw14bB2WV5Vm5Uh32KtVhr42DssryGCqpDnuV6rDXZm7aC5DWKhcXh97WU0Q8ISLeHBGfjIiHIiIjYtdRvseZEfGhiHggIu6OiHdExHd0tGRp3Y3q1Wal2WKvjYOyylo8dGDobZ09BTgPuA34t6N9cUScClwNBPA84BeAJwFXR8Rxk1umND2jerVZabbYa+OhFyprYXaOobo8My8DiIhfA37kKF//WuA+4LzMfKD/PnuBG4CLgT+a3FKl6ZihXsFmpZHstfETZZWViwtDb+u6jsw174eKiK3ATwD/uBRw/z0/B3wCeO74K5Smb1SvNivNFntt/ERZZY3a/RMR+1d6fWYeP8HlrNVjge3A3gGPXQ9ctL7Lkbqx0u5am5Vmh702Dsoq6+HPvDWGPRbx1/vXcSnj2Nn/um/AY/uA7RGxPTMfXMc1SRM3qlewWWmW2GvjoKwNaa1bshGxG7hqlU9/VGbeuZbvM0Cu8TFpQ7BZqY7N1OvIQfmbznnJyC0KDXbfOdNegcbwOeAlq3zufRP4fnf1v+4c8NgO4MHMfGi1b3bM9u02uwYHrvubaS9Ba1e22WOe+TJ7XYN7nzntFWgM5Xr1E2Vpmcy8DXj7On7Lm4EHgdMHPHYGg4+rktRns1IdFXv1qhfSFGXmQeCfgedGxLFL90fE9wBPBa6Y1tokfSObleqYRK+R6aFU0jj68S3tDHwW8LPAy4E7gDsy85plz/0SQGbuWnbfacAn6V2q5g3ANwOvA7YCT8zMSex+ktRns1Id0+7VQVkaU/9Xad4y5OFrMnP3sud+CR4Zcf/+76d30fMfBA4C7wd+MzNvnfiCpU3OZqU6pt2rg7IkSZI0gMcoS5IkSQM4KEuSJEkDOChLkiRJAzgoS5IkSQM4KEuSJEkDOChLkiRJAzgoS5IkSQM4KEuSJEkD/D9q0nzTN8+XuwAAAABJRU5ErkJggg==", "text/plain": [ "
" ] From 632c344f1677fc7815c3d9c1fae0ae8f62c1ebb3 Mon Sep 17 00:00:00 2001 From: Jacob Leksan <63938553+jmleksan@users.noreply.github.com> Date: Thu, 11 Aug 2022 16:11:42 -0400 Subject: [PATCH 29/32] Fixed mug2vec behavior for directed graphs Addresses bug #793 by making suggested changes by user bdpedigo. Co-authored-by: Benjamin Pedigo --- graspologic/embed/mug2vec.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/graspologic/embed/mug2vec.py b/graspologic/embed/mug2vec.py index 2257b2f38..2bb0542ea 100644 --- a/graspologic/embed/mug2vec.py +++ b/graspologic/embed/mug2vec.py @@ -153,10 +153,11 @@ def fit( n_components=self.omnibus_components, n_elbows=self.omnibus_n_elbows, svd_seed=self.svd_seed, + concat=True, ) omnibus_embedding = omni.fit_transform(graphs) - self.omnibus_n_components_ = omnibus_embedding.shape[-1] + self.omnibus_n_components_ = len(omni.singular_values_) cmds = ClassicalMDS( n_components=self.cmds_components, From f91f177a6d79f7b5f56768792bb4415da28f15b9 Mon Sep 17 00:00:00 2001 From: dokato Date: Mon, 29 Aug 2022 19:27:39 +0100 Subject: [PATCH 30/32] Added elbow marker to screeplot in plot module (#979) * elbow marker added to screeplot * elbow marker added to screeplot2 * isort applied to plotting * fixing docs in plotting Co-authored-by: Benjamin Pedigo --- graspologic/plot/plot.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/graspologic/plot/plot.py b/graspologic/plot/plot.py index d69e7a58c..e13dbd740 100644 --- a/graspologic/plot/plot.py +++ b/graspologic/plot/plot.py @@ -23,6 +23,7 @@ from graspologic.types import Dict, List, Tuple from ..embed import select_svd +from ..pipeline.embed._elbow import _index_of_elbow from ..preconditions import ( check_argument, check_argument_types, @@ -1413,6 +1414,7 @@ def screeplot( figsize: Tuple[int, int] = (10, 5), cumulative: bool = True, show_first: Optional[int] = None, + show_elbow: Optional[Union[bool, int]] = False, ) -> matplotlib.pyplot.Axes: r""" Plots the distribution of singular values for a matrix, either showing the @@ -1435,11 +1437,22 @@ def screeplot( Whether or not to plot a cumulative cdf of singular values show_first : int or None, default: None Whether to restrict the plot to the first ``show_first`` components + show_elbow : bool, or int, default: False + Whether to show an elbow (an optimal embedding dimension) estimated + via [1]. An integer is interpreted as a number of likelihood + elbows to return. Must be ``> 1``. Returns ------- ax : matplotlib axis object Output plot + + References + ---------- + .. [1] Zhu, M. and Ghodsi, A. (2006). + Automatic dimensionality selection from the scree plot via the use of + profile likelihood. Computational Statistics & Data Analysis, 51(2), + pp.918-930. """ _check_common_inputs( figsize=figsize, title=title, context=context, font_scale=font_scale @@ -1464,6 +1477,13 @@ def screeplot( ylabel = "Variance explained" with sns.plotting_context(context=context, font_scale=font_scale): plt.plot(y) + if show_elbow: + n_elbows = 2 + if isinstance(show_elbow, int): + n_elbows = show_elbow + elb_index = _index_of_elbow(D, n_elbows) + if elb_index < len(y): + plt.plot(elb_index, y[elb_index], "rx", markersize=20) plt.title(title) plt.xlabel(xlabel) plt.ylabel(ylabel) From facb6a86966066460776cca3e07bf729bb964d09 Mon Sep 17 00:00:00 2001 From: Benjamin Pedigo Date: Tue, 30 Aug 2022 10:59:22 -0700 Subject: [PATCH 31/32] Refactored graph matching code and added many new features (#960) * start on new gm code * add init * changes to solver * add a temporary warning about seeds * brief temporary description * draft wrapper * cleaning up setup * fix seeding permutation logic * add shell of a user-facing wrapper * add types to wrapper * add some type hints, remove _doubly_stochastic * take that, mypy * clean up constant terms handling * more cleanup * another type fix * try switching to typing_extensions for Literal * implement padding and optional shuffle * first draft of a wrapper function for the solver * fixes to wrapper * fix omitted param * try to add csr_array safely based on scipy ver * black * make mypy happy? * some comments * refactor module-specific typing * update param name to max_iter * beartype the wrapper * update max_iter in wrapper * input checks in progress * remove _qap tests * isort * change class name * fix issue w/ check_scalar * clarify naming in tests * tol for consistency * add checking for number of layers * fix some bugs * remove old method call * fix final permutation sign flip * add a type hint, bug in saved matrices for scoring * fix score computation * fixed edge case handling * test w/ random init * first take on docs * fix misc bug * ensure reproducibility * update custom init test * update custom init + seeds test * citation format * add headers * use typing.NamedTuple for output * axe all junk code * simplify init spec * axe now unused types * consolidate csr_array typing * fix parameterized type * typo in docstring * replace similarity test * fix imports * privatize _GraphMatchSolver * try sparsify some terms when 0 * bye bye numba * missed a use_numba ref * update and simplify FAQ notebook * deal with weirdness of adopted padding * remove numba reference in test * simplified, updated padding tutorial * simplified SGM notebook with new code * clear output for FAQ * adjust VNviaSGM * remove unused import * bye bye to the old code * add new func to docs * add a citation for multiplex * improve docs * bump major version for this breaking API change * run black * try to fix 3.7 error w/ trace * fix trace? * remove unneeded sparse spec * further simplify sparse logic * remove unnecessary comment * address confusion about `maximize` * allow `partial_match` to be a 2ple * rmv unnecessary comment * add custom input check and test * take that mypy * does that make you happy, mypy? --- docs/reference/reference/match.rst | 2 +- docs/tutorials/matching/faq.ipynb | 31 +- docs/tutorials/matching/padded_gm.ipynb | 126 ++-- docs/tutorials/matching/sgm.ipynb | 130 ++++- graspologic/match/__init__.py | 4 +- graspologic/match/gmp.py | 349 ----------- graspologic/match/qap.py | 608 ------------------- graspologic/match/solver.py | 747 ++++++++++++++++++++++++ graspologic/match/types.py | 31 + graspologic/match/wrappers.py | 322 ++++++++++ graspologic/nominate/VNviaSGM.py | 22 +- graspologic/types.py | 14 +- setup.cfg | 2 +- tests/test_match.py | 400 ++++++------- 14 files changed, 1515 insertions(+), 1273 deletions(-) delete mode 100644 graspologic/match/gmp.py delete mode 100644 graspologic/match/qap.py create mode 100644 graspologic/match/solver.py create mode 100644 graspologic/match/types.py create mode 100644 graspologic/match/wrappers.py diff --git a/docs/reference/reference/match.rst b/docs/reference/reference/match.rst index efe93021c..887a03343 100644 --- a/docs/reference/reference/match.rst +++ b/docs/reference/reference/match.rst @@ -5,4 +5,4 @@ Matching Graph Matching -------------------- -.. autoclass:: GraphMatch +.. autofunction:: graph_match diff --git a/docs/tutorials/matching/faq.ipynb b/docs/tutorials/matching/faq.ipynb index b7b44e408..6188383cd 100644 --- a/docs/tutorials/matching/faq.ipynb +++ b/docs/tutorials/matching/faq.ipynb @@ -63,7 +63,7 @@ "metadata": {}, "outputs": [], "source": [ - "from graspologic.match import GraphMatch as GMP\n", + "from graspologic.match import graph_match\n", "from graspologic.simulations import er_np" ] }, @@ -99,7 +99,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Visualize the graphs using heat mapping" + "## Visualize the adjacency matrices" ] }, { @@ -109,6 +109,7 @@ "outputs": [], "source": [ "from graspologic.plot import heatmap\n", + "\n", "heatmap(G1, cbar=False, title = 'G1 [ER-NP(50, 0.3) Simulation]')\n", "_ = heatmap(G2, cbar=False, title = 'G2 [G1 Randomly Shuffled]')" ] @@ -117,7 +118,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Below, we create a model to solve GMP. The model is then fitted for the two graphs $G_1$ and $G_2$. One of the option for the algorithm is the starting position of $P$. In this case, the class default of barycenter intialization is used, or the flat doubly stochastic matrix. The number of edge disagreements is printed below. With zero edge disagreements, we see that FAQ is successful in unshuffling the graph." + "Below, we solve the GMP using the `graph_match` function. The number of edge disagreements after optimization is printed below. With zero edge disagreements, we see that FAQ is successful in unshuffling the graph." ] }, { @@ -128,26 +129,15 @@ }, "outputs": [], "source": [ - "gmp = GMP()\n", - "gmp = gmp.fit(G1,G2)\n", - "G2 = G2[np.ix_(gmp.perm_inds_, gmp.perm_inds_)]\n", + "_, perm_inds, score, misc = graph_match(G1, G2)\n", + "G2 = G2[perm_inds][:, perm_inds] # permute both rows and columns to preserve adjacency\n", "print(\"Number of edge disagreements: \", np.sum(abs(G1-G2)))" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "heatmap(G1, cbar=False, title = 'G1[ER-NP(50, 0.3) Simulation]')\n", - "_ = heatmap(G2, cbar=False, title = 'G2[ER-NP(50, 0.3) Randomly Shuffled] unshuffled')" - ] } ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3.9.7 ('.venv': poetry)", "language": "python", "name": "python3" }, @@ -161,7 +151,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "bc13b1df6b0248aaf34f3e7f5790740f6f355623370613abc0a11b70d06c20f2" + } } }, "nbformat": 4, diff --git a/docs/tutorials/matching/padded_gm.ipynb b/docs/tutorials/matching/padded_gm.ipynb index ef7145864..432bad5bf 100644 --- a/docs/tutorials/matching/padded_gm.ipynb +++ b/docs/tutorials/matching/padded_gm.ipynb @@ -1,17 +1,5 @@ { "cells": [ - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import graspologic\n", - "\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt" - ] - }, { "cell_type": "markdown", "metadata": {}, @@ -29,7 +17,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "To demonstrate the difference between the two padding schemes, we sample two graph's $G_1'$ and $G_2$, each having 400 vertices, from a $0.5 \\sim SBM(4,b,\\Lambda)$, where b assigns 100 vertices to each of the k = 4 blocks, and\n", + "To demonstrate the difference between the two padding schemes, we sample two graph's $G_1$ and $G_2'$, each having 400 vertices, from a $0.5 \\sim SBM(4,b,\\Lambda)$, where b assigns 100 vertices to each of the k = 4 blocks, and\n", "\n", "\\begin{align*}\n", "\\Lambda &= \\begin{bmatrix} \n", @@ -40,9 +28,9 @@ "\\end{bmatrix}\\\\\n", "\\end{align*}\n", "\n", - "We realize $G_1$ from $G_1'$ by removing 25 nodes from each block of $G_1'$, yielding a 300 node graph (example adapted from section 2.5 of [1]).\n", + "We create $G_2$ from $G_2'$ by removing 25 nodes from each block of $G_2'$, yielding a 300 node graph (example adapted from section 2.5 of [1]).\n", "\n", - "The goal of the matching in this case is to recover $G_1$ by matching the right most figure below and $G_2$. That is, we seek to recover the shared community structure common between two graphs of differing shapes.\n", + "The goal of the matching in this case is to recover $G_2$ by matching the right most figure below and $G_1$. That is, we seek to recover the shared community structure common between two graphs of differing shapes.\n", "\n", "[1] \n", "D. Fishkind, S. Adali, H. Patsolic, L. Meng, D. Singh, V. Lyzinski, C. Priebe,\n", @@ -63,43 +51,46 @@ "outputs": [], "source": [ "# simulating G1', G2, deleting 25 vertices\n", - "from graspologic.match import GraphMatch as GMP\n", + "import numpy as np\n", + "import matplotlib.pyplot as plt\n", + "from graspologic.match import graph_match\n", "from graspologic.simulations import sbm_corr\n", "from graspologic.plot import heatmap\n", + "\n", "np.random.seed(1)\n", + "rng = np.random.default_rng(1)\n", "\n", "directed = False\n", "loops = False\n", - "block_probs = [[0.9,0.4,0.3,0.2],\n", - " [0.4,0.9,0.4,0.3],\n", - " [0.3,0.4,0.9,0.4],\n", - " [0.2,0.3,0.4,0.7]]\n", - "n =100\n", + "block_probs = [\n", + " [0.9, 0.4, 0.3, 0.2],\n", + " [0.4, 0.9, 0.4, 0.3],\n", + " [0.3, 0.4, 0.9, 0.4],\n", + " [0.2, 0.3, 0.4, 0.7],\n", + "]\n", + "n = 100\n", "n_blocks = 4\n", "rho = 0.5\n", "block_members = np.array(n_blocks * [n])\n", "n_verts = block_members.sum()\n", - "G1p, G2 = sbm_corr(block_members,block_probs, rho, directed, loops)\n", - "G1 = np.zeros((300,300))\n", - "c = np.copy(G1p)\n", - "\n", - "step1 = np.arange(4) * 100 + 75\n", - "step2 = np.arange(5) * 75\n", - "step3 = np.arange(4) * 100\n", - "for i in range(len(step1)):\n", - " block1 = np.arange(step1[i], step1[i]+25)\n", - " c[block1,:] = -1\n", - " c[:, block1] = -1\n", - " for j in range(len(step3)):\n", - " G1[step2[i]:step2[i+1], step2[j]:step2[j+1]] = G1p[step3[i]: step1[i], step3[j]:step1[j]]\n", - " \n", - "topleft_G1 = np.zeros((400,400))\n", - "topleft_G1[:300,:300] = G1\n", + "G1, G2_full = sbm_corr(block_members, block_probs, rho, directed, loops)\n", + "\n", + "keep_indices = np.concatenate(\n", + " (np.arange(75), np.arange(100, 175), np.arange(200, 275), np.arange(300, 375))\n", + ")\n", + "\n", + "G2 = G2_full[keep_indices][:, keep_indices]\n", + "\n", + "G2_deleted = np.full((G1.shape), -1)\n", + "G2_deleted[np.ix_(keep_indices, keep_indices)] = G2\n", + "\n", + "topleft_G2 = np.zeros((400, 400))\n", + "topleft_G2[:300, :300] = G2\n", "fig, axs = plt.subplots(1, 4, figsize=(20, 10))\n", - "heatmap(G1p, ax=axs[0], cbar=False, title=\"G1'\")\n", - "heatmap(G2, ax=axs[1], cbar=False, title=\"G2\")\n", - "heatmap(c, ax=axs[2], cbar=False, title=\"G1\")\n", - "_ = heatmap(topleft_G1, ax=axs[3], cbar=False, title=\"G1 (to top left corner)\")" + "heatmap(G1, ax=axs[0], cbar=False, title=\"G1'\")\n", + "heatmap(G2_full, ax=axs[1], cbar=False, title=\"G2 (before deletions)\")\n", + "heatmap(G2_deleted, ax=axs[2], cbar=False, title=\"G2 (after deletions)\")\n", + "_ = heatmap(topleft_G2, ax=axs[3], cbar=False, title=\"G2 (to top left corner)\")" ] }, { @@ -115,34 +106,46 @@ "metadata": {}, "outputs": [], "source": [ - "np.random.seed(1)\n", + "seed2 = rng.choice(np.arange(G2.shape[0]), 8)\n", + "seed1 = [int(x / 75) * 25 + x for x in seed2]\n", + "\n", + "partial_match = np.column_stack((seed1, seed2))\n", "\n", - "gmp_naive = GMP(padding='naive')\n", - "seed1 = np.random.choice(np.arange(300),8)\n", - "seed2 = [int(x/75)*25 + x for x in seed1]\n", - "gmp_naive = gmp_naive.fit(G2, G1, seed2, seed1)\n", - "G1_naive = topleft_G1[gmp_naive.perm_inds_][:, gmp_naive.perm_inds_]\n", + "naive_indices1, naive_indices2, _, _ = graph_match(\n", + " G1, G2, partial_match=partial_match, padding=\"naive\", rng=rng\n", + ")\n", + "G2_naive = G2[naive_indices2][:, naive_indices2]\n", + "G2_naive_full = np.zeros(G1.shape)\n", + "G2_naive_full[np.ix_(naive_indices1, naive_indices1)] = G2_naive\n", "\n", - "gmp_adopted = GMP(padding='adopted')\n", - "gmp_adopted = gmp_adopted.fit(G2, G1, seed2, seed1)\n", - "G1_adopted = topleft_G1[gmp_adopted.perm_inds_][:, gmp_adopted.perm_inds_]\n", + "adopted_indices1, adopted_indices2, _, _ = graph_match(\n", + " G1, G2, partial_match=partial_match, padding=\"adopted\", rng=rng\n", + ")\n", + "G2_adopted = G2[adopted_indices2][:, adopted_indices2]\n", + "G2_adopted_full = np.zeros(G1.shape)\n", + "G2_adopted_full[np.ix_(adopted_indices1, adopted_indices1)] = G2_adopted\n", "\n", "fig, axs = plt.subplots(1, 2, figsize=(14, 7))\n", - "heatmap(G1_naive, ax=axs[0], cbar=False, title=\"Naive Padding\")\n", - "heatmap(G1_adopted, ax=axs[1], cbar=False, title=\"Adopted Padding\")\n", + "heatmap(G2_naive_full, ax=axs[0], cbar=False, title=\"Naive Padding\")\n", + "heatmap(G2_adopted_full, ax=axs[1], cbar=False, title=\"Adopted Padding\")\n", "\n", - "naive_matching = np.concatenate([gmp_naive.perm_inds_[x * 100 : (x * 100) + 75] for x in range(n_blocks)])\n", - "adopted_matching = np.concatenate([gmp_adopted.perm_inds_[x * 100 : (x * 100) + 75] for x in range(n_blocks)])\n", "\n", - "print(f'Match ratio of nodes remaining in G1, with naive padding: {sum(naive_matching == np.arange(300))/300}')\n", - "print(f'Match ratio of nodes remaining in G1, with adopted padding: {sum(adopted_matching == np.arange(300))/300}')" + "def compute_match_ratio(indices1, indices2):\n", + " match_ratio = 0\n", + " for i in range(len(indices2)):\n", + " if (indices1[i] == keep_indices[i]) and (indices2[i] == i):\n", + " match_ratio += 1\n", + " return match_ratio / len(indices2)\n", + "\n", + "print(f\"Matching accuracy with naive padding: {compute_match_ratio(naive_indices1, naive_indices2):.2f}\")\n", + "print(f\"Matching accuracy with adopted padding: {compute_match_ratio(adopted_indices1, adopted_indices2):.2f}\")\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "We observe that the two padding schemes perform as expected. The naive scheme permutes $G_1$ such that it matches a subgraph of $G_2$, specifically the subgraph of the first three blocks. Additionally, (almost) all isolated vertices of $G_1$ are permuted to the fourth block of $G_2$.\n", + "We observe that the two padding schemes perform as expected. The naive scheme permutes $G_2$ such that it matches a subgraph of $G_1$, specifically the subgraph of the first three blocks. Additionally, (almost) all isolated vertices of $G_2$ are permuted to the fourth block of $G_1$.\n", "\n", "On the other hand, we see that adopted padding preserves the common block structure between $G_1$ and $G_2$." ] @@ -150,7 +153,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3.9.7 ('.venv': poetry)", "language": "python", "name": "python3" }, @@ -164,7 +167,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "bc13b1df6b0248aaf34f3e7f5790740f6f355623370613abc0a11b70d06c20f2" + } } }, "nbformat": 4, diff --git a/docs/tutorials/matching/sgm.ipynb b/docs/tutorials/matching/sgm.ipynb index f8c662228..fc64f9ec0 100644 --- a/docs/tutorials/matching/sgm.ipynb +++ b/docs/tutorials/matching/sgm.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -17,7 +17,8 @@ "import matplotlib.pyplot as plt\n", "import seaborn as sns\n", "import random\n", - "np.random.seed(8888)" + "np.random.seed(8888)\n", + "rng = np.random.default_rng(8888)" ] }, { @@ -29,11 +30,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ - "from graspologic.match import GraphMatch as GMP\n", + "from graspologic.match import graph_match\n", "from graspologic.plot import heatmap\n", "from graspologic.simulations import er_corr, sbm, sbm_corr" ] @@ -57,9 +58,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "directed = False\n", "loops = False\n", @@ -103,15 +127,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "\n", "node_shuffle_input = np.random.permutation(n_verts)\n", - "A2_shuffle = A2[np.ix_(node_shuffle_input, node_shuffle_input)]\n", - "node_unshuffle_input = np.array(range(n_verts))\n", - "node_unshuffle_input[node_shuffle_input] = np.array(range(n_verts))\n", + "A2_shuffle = A2[node_shuffle_input][:, node_shuffle_input]\n", + "node_unshuffle_input = np.argsort(node_shuffle_input)\n", "\n", "fig, axs = plt.subplots(1, 3, figsize=(10, 5))\n", "heatmap(A1, ax=axs[0], cbar=False, title=\"Graph 1\")\n", @@ -129,20 +163,37 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Match Ratio with no seeds: 0.0\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "sgm = GMP()\n", - "sgm = sgm.fit(A1,A2_shuffle)\n", - "A2_unshuffle = A2_shuffle[np.ix_(sgm.perm_inds_, sgm.perm_inds_)]\n", + "_, perm_inds, _, _ = graph_match(A1, A2_shuffle, rng=rng)\n", + "A2_unshuffle = A2_shuffle[perm_inds][:, perm_inds]\n", "\n", "fig, axs = plt.subplots(1, 3, figsize=(10, 5))\n", "heatmap(A1, ax=axs[0], cbar=False, title=\"Graph 1\")\n", "heatmap(A2_unshuffle, ax=axs[1], cbar=False, title=\"Graph 2 unshuffled\")\n", "heatmap(A1 - A2_unshuffle, ax=axs[2], cbar=False, title=\"Diff (G1 - G2 unshuffled)\")\n", "\n", - "match_ratio = 1-(np.count_nonzero(abs(sgm.perm_inds_-node_unshuffle_input))/n_verts)\n", + "match_ratio = (perm_inds == node_unshuffle_input).mean()\n", "print(\"Match Ratio with no seeds: \", match_ratio)" ] }, @@ -163,24 +214,42 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Match Ratio with 10 seeds: 1.0\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "W1 = np.sort(random.sample(list(range(n_verts)),10))\n", - "W1 = W1.astype(int)\n", - "W2 = np.array(node_unshuffle_input[W1])\n", + "seeds1 = np.sort(random.sample(list(range(n_verts)),10))\n", + "seeds1 = seeds1.astype(int)\n", + "seeds2 = np.array(node_unshuffle_input[seeds1])\n", + "partial_match = np.column_stack((seeds1, seeds2))\n", " \n", - "sgm = GMP()\n", - "sgm = sgm.fit(A1,A2_shuffle,W1,W2)\n", - "A2_unshuffle = A2_shuffle[np.ix_(sgm.perm_inds_, sgm.perm_inds_)]\n", + "_, perm_inds, _, _ = graph_match(A1, A2_shuffle, partial_match=partial_match, rng=rng)\n", + "A2_unshuffle = A2_shuffle[perm_inds][:, perm_inds]\n", "\n", "fig, axs = plt.subplots(1, 3, figsize=(10, 5))\n", "heatmap(A1, ax=axs[0], cbar=False, title=\"Graph 1\")\n", "heatmap(A2_unshuffle, ax=axs[1], cbar=False, title=\"Graph 2 unshuffled\")\n", "heatmap(A1 - A2_unshuffle, ax=axs[2], cbar=False, title=\"Diff (G1 - G2 unshuffled)\")\n", "\n", - "match_ratio = 1-(np.count_nonzero(abs(sgm.perm_inds_-node_unshuffle_input))/n_verts)\n", + "match_ratio = (perm_inds == node_unshuffle_input).mean()\n", "print(\"Match Ratio with 10 seeds: \", match_ratio)" ] }, @@ -194,7 +263,7 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3", + "display_name": "Python 3.9.7 ('.venv': poetry)", "language": "python", "name": "python3" }, @@ -208,7 +277,12 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.0" + "version": "3.9.7" + }, + "vscode": { + "interpreter": { + "hash": "bc13b1df6b0248aaf34f3e7f5790740f6f355623370613abc0a11b70d06c20f2" + } } }, "nbformat": 4, diff --git a/graspologic/match/__init__.py b/graspologic/match/__init__.py index 4ba1646aa..7575854b3 100644 --- a/graspologic/match/__init__.py +++ b/graspologic/match/__init__.py @@ -1,6 +1,6 @@ # Copyright (c) Microsoft Corporation and contributors. # Licensed under the MIT License. -from .gmp import GraphMatch +from .wrappers import graph_match -__all__ = ["GraphMatch"] +__all__ = ["graph_match"] diff --git a/graspologic/match/gmp.py b/graspologic/match/gmp.py deleted file mode 100644 index 42f7dc3a4..000000000 --- a/graspologic/match/gmp.py +++ /dev/null @@ -1,349 +0,0 @@ -# Copyright (c) Microsoft Corporation and contributors. -# Licensed under the MIT License. - -from typing import Optional, Union - -import numpy as np -from joblib import Parallel, delayed -from sklearn.base import BaseEstimator -from sklearn.utils import check_array, check_random_state, column_or_1d -from typing_extensions import Literal - -from graspologic.types import List, Tuple - -from .qap import quadratic_assignment - -# Type aliases -PaddingType = Literal["adopted", "naive"] -InitMethodType = Literal["barycenter", "rand", "randomized"] -RandomStateType = Optional[Union[int, np.random.RandomState, np.random.Generator]] -ArrayLikeOfIndexes = Union[List[int], np.ndarray] - - -class GraphMatch(BaseEstimator): - """ - This class solves the Graph Matching Problem and the Quadratic Assignment Problem - (QAP) through an implementation of the Fast Approximate QAP Algorithm (FAQ) (these - two problems are the same up to a sign change) [1]. - - This algorithm can be thought of as finding an alignment of the vertices of two - graphs which minimizes the number of induced edge disagreements, or, in the case - of weighted graphs, the sum of squared differences of edge weight disagreements. - The option to add seeds (known vertex correspondence between some nodes) is also - available [2]. - - - Parameters - ---------- - - n_init : int, positive (default = 1) - Number of random initializations of the starting permutation matrix that - the FAQ algorithm will undergo. - - init : string (default = 'barycenter') or 2d-array - The initial position chosen. - - "barycenter" : the non-informative “flat doubly stochastic matrix,” - :math:`J=1 \\times 1^T /n` , i.e the barycenter of the feasible region. This can - be thought of as the doubly stochastic matrix from which any permutation is - equally likely. - - "rand" : some random point near :math:`J, (J+K)/2`, where K is some random - doubly stochastic matrix. - - If 2d-array, ``init`` must be :math:`m' x m'`, where :math:`m'` is the number of - nonseeded vertices of ``B``. This initial position repesents a permutation or - assignment of the nonseeded vertices of ``B``, and thus must be doubly - stochastic (all of its rows and columns must sum to 1). Note that if using - seeds, this permutation/assignment is taken with respect to the nonseeded - vertices in the order in which they were input, even when - ``shuffle_input = True``. - - max_iter : int, positive (default = 30) - Integer specifying the max number of Franke-Wolfe iterations. - FAQ typically converges with modest number of iterations. - - shuffle_input : bool (default = True) - Gives users the option to shuffle the nodes of A matrix to avoid results - from inputs that were already matched. - - eps : float (default = 0.03) - A positive, threshold stopping criteria such that FW continues to iterate - while Frobenius norm of :math:`(P_{i}-P_{i+1}) > \\text{eps}` - - gmp : bool (default = True) - Gives users the option to solve QAP rather than the Graph Matching Problem - (GMP). This is accomplished through a negation of the objective function. - - padding : string (default = 'adopted') - Allows user to specify padding scheme if `A` and `B` are not of equal size. - Say that `A` and `B` have :math:`n_1` and :math:`n_2` nodes, respectively, and - :math:`n_1 < n_2`. - - "adopted" : matches `A` to the best fitting induced subgraph of `B`. Reduces the - affinity between isolated vertices added to `A` through padding and low-density - subgraphs of `B`. - - "naive" : matches `A` to the best fitting subgraph of `B`. - - random_state : {None, int, `~np.random.RandomState`, `~np.random.Generator`} - This parameter defines the object to use for drawing random - variates. - If `random_state` is ``None`` the `~np.random.RandomState` singleton is - used. - If `random_state` is an int, a new ``RandomState`` instance is used, - seeded with `random_state`. - If `random_state` is already a ``RandomState`` or ``Generator`` - instance, then that object is used. - Default is None. - - n_jobs : int or None, (default = None) - The number of jobs to run in parallel. Parallelization is over the - initializations, so only relevant when ``n_init > 1``. None means 1 unless in a - joblib.parallel_backend context. -1 means using all processors. See - :class:`joblib.Parallel` for more details. - - Attributes - ---------- - - perm_inds_ : array, size (n,) where n is the number of vertices in the fitted graphs. - The indices of the optimal permutation (with the fixed seeds given) on the nodes of B, - to best minimize the objective function :math:`f(P) = \\text{trace}(A^T PBP^T) - + \\text{trace}(S^T P)`. - - - score_ : float - The objective function value of for the optimal permutation found. - - n_iter_ : int - Number of Frank-Wolfe iterations run. If ``n_init > 1``, :attr:`n_iter_` reflects the number of - iterations performed at the initialization returned. - - - References - ---------- - .. [1] J.T. Vogelstein, J.M. Conroy, V. Lyzinski, L.J. Podrazik, S.G. Kratzer, - E.T. Harley, D.E. Fishkind, R.J. Vogelstein, and C.E. Priebe, “Fast - approximate quadratic programming for graph matching,” PLOS one, vol. 10, - no. 4, p. e0121002, 2015. - - .. [2] D. Fishkind, S. Adali, H. Patsolic, L. Meng, D. Singh, V. Lyzinski, C. Priebe, - Seeded graph matching, Pattern Recognit. 87 (2019) 203–215 - - - - """ - - init: Union[InitMethodType, np.ndarray] - - def __init__( - self, - n_init: int = 1, - init: Union[InitMethodType, np.ndarray] = "barycenter", - max_iter: int = 30, - shuffle_input: bool = True, - eps: float = 0.03, - gmp: bool = True, - padding: PaddingType = "adopted", - random_state: RandomStateType = None, - n_jobs: Optional[int] = None, - ): - if type(n_init) is int and n_init > 0: - self.n_init = n_init - else: - msg = '"n_init" must be a positive integer' - raise TypeError(msg) - if isinstance(init, np.ndarray): - self.init = init - elif init == "rand": - self.init = "randomized" - elif init == "barycenter": - self.init = "barycenter" - else: - msg = 'Invalid "init" parameter string' - raise ValueError(msg) - if max_iter > 0 and type(max_iter) is int: - self.max_iter = max_iter - else: - msg = '"max_iter" must be a positive integer' - raise TypeError(msg) - if type(shuffle_input) is bool: - self.shuffle_input = shuffle_input - else: - msg = '"shuffle_input" must be a boolean' - raise TypeError(msg) - if eps > 0 and type(eps) is float: - self.eps = eps - else: - msg = '"eps" must be a positive float' - raise TypeError(msg) - if type(gmp) is bool: - self.gmp = gmp - else: - msg = '"gmp" must be a boolean' - raise TypeError(msg) - if isinstance(padding, str) and padding in {"adopted", "naive"}: - self.padding = padding - elif isinstance(padding, str): - msg = 'Invalid "padding" parameter string' - raise ValueError(msg) - else: - msg = '"padding" parameter must be of type string' - raise TypeError(msg) - self.random_state = random_state - self.n_jobs = n_jobs - - def fit( - self, - A: np.ndarray, - B: np.ndarray, - seeds_A: ArrayLikeOfIndexes = [], - seeds_B: ArrayLikeOfIndexes = [], - S: Optional[np.ndarray] = None, - ) -> "GraphMatch": - """ - Fits the model with two assigned adjacency matrices - - Parameters - ---------- - A : 2d-array, square - A square adjacency matrix - - B : 2d-array, square - A square adjacency matrix - - seeds_A : 1d-array, shape (m , 1) where m <= number of nodes (default = []) - An array where each entry is an index of a node in ``A``. - - seeds_B : 1d-array, shape (m , 1) where m <= number of nodes (default = []) - An array where each entry is an index of a node in `B` The elements of - ``seeds_A`` and ``seeds_B`` are vertices which are known to be matched, that is, - ``seeds_A[i]`` is matched to vertex ``seeds_B[i]``. - S : 2d-array, square - A similarity matrix. Should be shape (n_A , n_B), the number of nodes in - ``A`` and ``B``, respectively. - - Note: the scale of ``S`` affects the weight placed on the term - :math:`\\text{trace}(S^T P)` relative to :math:`\\text{trace}(A^T PBP^T)` - during the optimization process. - - Returns - ------- - self : returns an instance of self - """ - A = check_array(A, copy=True, ensure_2d=True) - B = check_array(B, copy=True, ensure_2d=True) - seeds_A = column_or_1d(seeds_A) - seeds_B = column_or_1d(seeds_B) - partial_match = np.column_stack((seeds_A, seeds_B)) - - _S = S if S is not None else np.zeros((A.shape[0], B.shape[1])) - _S = np.atleast_2d(_S) - - msg = None - if _S.ndim != 2: - msg = "`S` must have exactly two dimensions" - elif A.shape[0] != _S.shape[0] or B.shape[0] != _S.shape[1]: - msg = "`S` must be of shape (n_A, n_B)" - if msg is not None: - raise ValueError(msg) - - # pads A and B according to section 2.5 of [2] - if A.shape[0] != B.shape[0]: - A, B, _S = _adj_pad(A, B, _S, self.padding) - - options = { - "maximize": self.gmp, - "partial_match": partial_match, - "S": _S, - "P0": self.init, - "shuffle_input": self.shuffle_input, - "maxiter": self.max_iter, - "tol": self.eps, - } - - rng = check_random_state(self.random_state) - results = Parallel(n_jobs=self.n_jobs)( - delayed(quadratic_assignment)(A, B, options={**options, **{"rng": r}}) - for r in rng.randint(np.iinfo(np.int32).max, size=self.n_init) - ) - func = max if self.gmp else min - res = func( - results, - key=lambda x: x.fun, - ) - - self.perm_inds_ = res.col_ind # permutation indices - self.score_ = res.fun # objective function value - self.n_iter_ = res.nit - return self - - def fit_predict( - self, - A: np.ndarray, - B: np.ndarray, - seeds_A: ArrayLikeOfIndexes = [], - seeds_B: ArrayLikeOfIndexes = [], - S: Optional[np.ndarray] = None, - ) -> np.ndarray: - """ - Fits the model with two assigned adjacency matrices, returning optimal - permutation indices - - Parameters - ---------- - A : 2d-array, square - A square adjacency matrix - - B : 2d-array, square - A square adjacency matrix - - seeds_A : 1d-array, shape (m , 1) where m <= number of nodes (default = []) - An array where each entry is an index of a node in ``A``. - - seeds_B : 1d-array, shape (m , 1) where m <= number of nodes (default = []) - An array where each entry is an index of a node in ``B`` The elements of - ``seeds_A`` and ``seeds_B`` are vertices which are known to be matched, that is, - ``seeds_A[i]`` is matched to vertex ``seeds_B[i]``. - - S : 2d-array, square - A similarity matrix. Should be shape (n_A , n_B), the number of nodes in - ``A`` and ``B``, respectively. - - Note: the scale of `S` affects the weight placed on the term - :math:`\\text{trace}(S^T P)` relative to :math:`\\text{trace}(A^T PBP^T)` - during the optimization process. - - Returns - ------- - perm_inds_ : 1-d array, some shuffling of [0, n_vert) - The optimal permutation indices to minimize the objective function - """ - self.fit(A, B, seeds_A, seeds_B, S) - return self.perm_inds_ - - -def _adj_pad( - A: np.ndarray, B: np.ndarray, S: np.ndarray, method: PaddingType -) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: - def pad(X: np.ndarray, n: np.ndarray) -> np.ndarray: - X_pad = np.zeros((n[1], n[1])) - X_pad[: n[0], : n[0]] = X - return X_pad - - A_n = A.shape[0] - B_n = B.shape[0] - n = np.sort([A_n, B_n]) - if method == "adopted": - A = 2 * A - np.ones((A_n, A_n)) - B = 2 * B - np.ones((B_n, B_n)) - - S_pad = np.zeros((n[1], n[1])) - S_pad[:A_n, :B_n] = S - - if A.shape[0] == n[0]: - A = pad(A, n) - else: - B = pad(B, n) - - return A, B, S_pad diff --git a/graspologic/match/qap.py b/graspologic/match/qap.py deleted file mode 100644 index 14bd94584..000000000 --- a/graspologic/match/qap.py +++ /dev/null @@ -1,608 +0,0 @@ -# adapted from scipy.optimze.quadratic_assignment() -# will live here temporalily until this function is officially released -# original code can be found here -# https://github.com/scipy/scipy/blob/master/scipy/optimize/_qap.py - -import numbers -import operator -from typing import Any, Optional, Union - -import numpy as np -from scipy.optimize import OptimizeResult, linear_sum_assignment -from typing_extensions import Literal - -from graspologic.types import Dict, Tuple - - -def quadratic_assignment( - A: np.ndarray, - B: np.ndarray, - method: Literal["faq"] = "faq", - options: Optional[Dict[str, Any]] = None, -) -> OptimizeResult: - r""" - Approximates solution to the quadratic assignment problem and - the graph matching problem. - Quadratic assignment solves problems of the following form: - .. math:: - \min_P & \ {\ \text{trace}(A^T P B P^T)}\\ - \mbox{s.t. } & {P \ \epsilon \ \mathcal{P}}\\ - where :math:`\mathcal{P}` is the set of all permutation matrices, - and :math:`A` and :math:`B` are square matrices. - Graph matching tries to *maximize* the same objective function. - This algorithm can be thought of as finding the alignment of the - nodes of two graphs that minimizes the number of induced edge - disagreements, or, in the case of weighted graphs, the sum of squared - edge weight differences. - Note that the quadratic assignment problem is NP-hard, is not - known to be solvable in polynomial time, and is computationally - intractable. Therefore, the results given are approximations, - not guaranteed to be exact solutions. - Parameters - ---------- - A : 2d-array, square - The square matrix :math:`A` in the objective function above. - B : 2d-array, square - The square matrix :math:`B` in the objective function above. - method : str in {'faq'} (default: 'faq') - The algorithm used to solve the problem. - :ref:`'faq' ` (default) and - options : dict, optional - A dictionary of solver options. All solvers support the following: - partial_match : 2d-array of integers, optional, (default = None) - Allows the user to fix part of the matching between the two - matrices. In the literature, a partial match is also - known as a "seed" [2]_. - Each row of `partial_match` specifies the indices of a pair of - corresponding nodes, that is, node ``partial_match[i, 0]`` of `A` - is matched to node ``partial_match[i, 1]`` of `B`. Accordingly, - ``partial_match`` is an array of size ``(m , 2)``, where ``m`` is - not greater than the number of nodes. - maximize : bool (default = False) - Setting `maximize` to ``True`` solves the Graph Matching Problem - (GMP) rather than the Quadratic Assingnment Problem (QAP). - rng : {None, int, `~np.random.RandomState`, `~np.random.Generator`} - This parameter defines the object to use for drawing random - variates. - If `rng` is ``None`` the `~np.random.RandomState` singleton is - used. - If `rng` is an int, a new ``RandomState`` instance is used, - seeded with `rng`. - If `rng` is already a ``RandomState`` or ``Generator`` - instance, then that object is used. - Default is None. - For method-specific options, see - :func:`show_options('quadratic_assignment') `. - Returns - ------- - res : OptimizeResult - A :class:`scipy.optimize.OptimizeResult` containing the following - fields. - col_ind : 1-D array - An array of column indices corresponding with the best - permutation of the nodes of `B` found. - fun : float - The corresponding value of the objective function. - nit : int - The number of iterations performed during optimization. - Notes - ----- - The default method :ref:`'faq' ` uses the Fast - Approximate QAP algorithm [1]_; it is typically offers the best - combination of speed and accuracy. - Method :ref:`'2opt' ` can be computationally expensive, - but may be a useful alternative, or it can be used to refine the solution - returned by another method. - References - ---------- - .. [1] J.T. Vogelstein, J.M. Conroy, V. Lyzinski, L.J. Podrazik, - S.G. Kratzer, E.T. Harley, D.E. Fishkind, R.J. Vogelstein, and - C.E. Priebe, "Fast approximate quadratic programming for graph - matching," PLOS one, vol. 10, no. 4, p. e0121002, 2015, - :doi:`10.1371/journal.pone.0121002` - .. [2] D. Fishkind, S. Adali, H. Patsolic, L. Meng, D. Singh, V. Lyzinski, - C. Priebe, "Seeded graph matching", Pattern Recognit. 87 (2019): - 203-215, :doi:`10.1016/j.patcog.2018.09.014` - .. [3] "2-opt," Wikipedia. - https://en.wikipedia.org/wiki/2-opt - Examples - -------- - >>> import numpy as np - >>> from scipy.optimize import quadratic_assignment - >>> A = np.array([[0, 80, 150, 170], [80, 0, 130, 100], - ... [150, 130, 0, 120], [170, 100, 120, 0]]) - >>> B = np.array([[0, 5, 2, 7], [0, 0, 3, 8], - ... [0, 0, 0, 3], [0, 0, 0, 0]]) - >>> res = quadratic_assignment(A, B) - >>> print(res) - col_ind: array([0, 3, 2, 1]) - fun: 3260 - nit: 9 - The see the relationship between the returned ``col_ind`` and ``fun``, - use ``col_ind`` to form the best permutation matrix found, then evaluate - the objective function :math:`f(P) = trace(A^T P B P^T )`. - >>> n = A.shape[0] - >>> perm = res['col_ind'] - >>> P = np.eye(n, dtype=int)[perm] - >>> fun = np.trace(A.T @ P @ B @ P.T) - >>> print(fun) - 3260 - Alternatively, to avoid constructing the permutation matrix explicitly, - directly permute the rows and columns of the distance matrix. - >>> fun = np.trace(A.T @ B[perm][:, perm]) - >>> print(fun) - 3260 - Although not guaranteed in general, ``quadratic_assignment`` happens to - have found the globally optimal solution. - >>> from itertools import permutations - >>> perm_opt, fun_opt = None, np.inf - >>> for perm in permutations([0, 1, 2, 3]): - ... perm = np.array(perm) - ... fun = np.trace(A.T @ B[perm][:, perm]) - ... if fun < fun_opt: - ... fun_opt, perm_opt = fun, perm - >>> print(np.array_equal(perm_opt, res['col_ind'])) - True - Here is an example for which the default method, - :ref:`'faq' `, does not find the global optimum. - >>> A = np.array([[0, 5, 8, 6], [5, 0, 5, 1], - ... [8, 5, 0, 2], [6, 1, 2, 0]]) - >>> B = np.array([[0, 1, 8, 4], [1, 0, 5, 2], - ... [8, 5, 0, 5], [4, 2, 5, 0]]) - >>> res = quadratic_assignment(A, B) - >>> print(res) - col_ind: array([1, 0, 3, 2]) - fun: 178 - nit: 13 - If accuracy is important, consider using :ref:`'2opt' ` - to refine the solution. - >>> guess = np.array([np.arange(A.shape[0]), res.col_ind]).T - >>> res = quadratic_assignment(A, B, method="2opt", - ... options = {'partial_guess': guess}) - >>> print(res) - col_ind: array([1, 2, 3, 0]) - fun: 176 - nit: 17 - """ - - if options is None: - options = {} - - method_key = method.lower() - methods = {"faq": _quadratic_assignment_faq} - if method_key not in methods: - raise ValueError(f"method {method_key} must be in {list(methods.keys())}.") - res = methods[method_key](A, B, **options) - return res - - -def _calc_score( - A: np.ndarray, B: np.ndarray, S: np.ndarray, perm: np.ndarray -) -> np.ndarray: - # equivalent to objective function but avoids matmul - return np.sum(A * B[perm][:, perm]) + np.sum(S[np.arange(len(S)), perm]) - - -def _common_input_validation( - A: np.ndarray, B: np.ndarray, partial_match: Optional[np.ndarray] -) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: - A = np.atleast_2d(A) - B = np.atleast_2d(B) - - _partial_match = ( - partial_match if partial_match is not None else np.array([[], []]).T - ) - - _partial_match = np.atleast_2d(_partial_match).astype(int) - - msg = None - if A.shape[0] != A.shape[1]: - msg = "`A` must be square" - elif B.shape[0] != B.shape[1]: - msg = "`B` must be square" - elif A.ndim != 2 or B.ndim != 2: - msg = "`A` and `B` must have exactly two dimensions" - elif A.shape != B.shape: - msg = "`A` and `B` matrices must be of equal size" - elif _partial_match.shape[0] > A.shape[0]: - msg = "`partial_match` can have only as many seeds as there are nodes" - elif _partial_match.shape[1] != 2: - msg = "`partial_match` must have two columns" - elif _partial_match.ndim != 2: - msg = "`partial_match` must have exactly two dimensions" - elif (_partial_match < 0).any(): - msg = "`partial_match` must contain only positive indices" - elif (_partial_match >= len(A)).any(): - msg = "`partial_match` entries must be less than number of nodes" - elif not len(set(_partial_match[:, 0])) == len(_partial_match[:, 0]) or not len( - set(_partial_match[:, 1]) - ) == len(_partial_match[:, 1]): - msg = "`partial_match` column entries must be unique" - - if msg is not None: - raise ValueError(msg) - - return A, B, _partial_match - - -def _quadratic_assignment_faq( - A: np.ndarray, - B: np.ndarray, - maximize: bool = False, - partial_match: Optional[np.ndarray] = None, - S: Optional[np.ndarray] = None, - rng: Optional[Union[int, np.random.RandomState, np.random.Generator]] = None, - P0: Union[Literal["barycenter", "randomized"], np.ndarray] = "barycenter", - shuffle_input: bool = False, - maxiter: int = 30, - tol: float = 0.03, -) -> OptimizeResult: - r""" - Solve the quadratic assignment problem (approximately). - This function solves the Quadratic Assignment Problem (QAP) and the - Graph Matching Problem (GMP) using the Fast Approximate QAP Algorithm - (FAQ) [1]_. - Quadratic assignment solves problems of the following form: - .. math:: - \min_P & \ {\ \text{trace}(A^T P B P^T)}\\ - \mbox{s.t. } & {P \ \epsilon \ \mathcal{P}}\\ - where :math:`\mathcal{P}` is the set of all permutation matrices, - and :math:`A` and :math:`B` are square matrices. - Graph matching tries to *maximize* the same objective function. - This algorithm can be thought of as finding the alignment of the - nodes of two graphs that minimizes the number of induced edge - disagreements, or, in the case of weighted graphs, the sum of squared - edge weight differences. - Note that the quadratic assignment problem is NP-hard, is not - known to be solvable in polynomial time, and is computationally - intractable. Therefore, the results given are approximations, - not guaranteed to be exact solutions. - Parameters - ---------- - A : 2d-array, square - The square matrix :math:`A` in the objective function above. - B : 2d-array, square - The square matrix :math:`B` in the objective function above. - method : str in {'faq', '2opt'} (default: 'faq') - The algorithm used to solve the problem. This is the method-specific - documentation for 'faq'. - :ref:`'2opt' ` is also available. - Options - ------- - maximize : bool (default = False) - Setting `maximize` to ``True`` solves the Graph Matching Problem (GMP) - rather than the Quadratic Assingnment Problem (QAP). This is - accomplished through trivial negation of the objective function. - rng : {None, int, `~np.random.RandomState`, `~np.random.Generator`} - This parameter defines the object to use for drawing random - variates. - If `rng` is ``None`` the `~np.random.RandomState` singleton is - used. - If `rng` is an int, a new ``RandomState`` instance is used, - seeded with `rng`. - If `rng` is already a ``RandomState`` or ``Generator`` - instance, then that object is used. - Default is None. - partial_match : 2d-array of integers, optional, (default = None) - Allows the user to fix part of the matching between the two - matrices. In the literature, a partial match is also known as a - "seed". - Each row of `partial_match` specifies the indices of a pair of - corresponding nodes, that is, node ``partial_match[i, 0]`` of `A` is - matched to node ``partial_match[i, 1]`` of `B`. Accordingly, - ``partial_match`` is an array of size ``(m , 2)``, where ``m`` is - not greater than the number of nodes, :math:`n`. - S : 2d-array, square - A similarity matrix. Should be same shape as ``A`` and ``B``. - Note: the scale of `S` may effect the weight placed on the term - :math:`\\text{trace}(S^T P)` relative to :math:`\\text{trace}(A^T PBP^T)` - during the optimization process. - P0 : 2d-array, "barycenter", or "randomized" (default = "barycenter") - The initial (guess) permutation matrix or search "position" - `P0`. - `P0` need not be a proper permutation matrix; - however, it must be :math:`m' x m'`, where :math:`m' = n - m`, - and it must be doubly stochastic: each of its rows and columns must - sum to 1. - If unspecified or ``"barycenter"``, the non-informative "flat - doubly stochastic matrix" :math:`J = 1*1^T/m'`, where :math:`1` is - a :math:`m' \times 1` array of ones, is used. This is the "barycenter" - of the search space of doubly-stochastic matrices. - If ``"randomized"``, the algorithm will start from the - randomized initial search position :math:`P_0 = (J + K)/2`, - where :math:`J` is the "barycenter" and :math:`K` is a random - doubly stochastic matrix. - shuffle_input : bool (default = False) - To avoid artificially high or low matching due to inherent - sorting of input matrices, gives users the option - to shuffle the nodes. Results are then unshuffled so that the - returned results correspond with the node order of inputs. - Shuffling may cause the algorithm to be non-deterministic, - unless a random seed is set or an `rng` option is provided. - maxiter : int, positive (default = 30) - Integer specifying the max number of Franke-Wolfe iterations performed. - tol : float (default = 0.03) - A threshold for the stopping criterion. Franke-Wolfe - iteration terminates when the change in search position between - iterations is sufficiently small, that is, when the relative Frobenius - norm, :math:`\frac{||P_{i}-P_{i+1}||_F}{\sqrt{len(P_{i})}} \leq tol`, - where :math:`i` is the iteration number. - Returns - ------- - res : OptimizeResult - A :class:`scipy.optimize.OptimizeResult` containing the following - fields. - col_ind : 1-D array - An array of column indices corresponding with the best - permutation of the nodes of `B` found. - fun : float - The corresponding value of the objective function. - nit : int - The number of Franke-Wolfe iterations performed. - Notes - ----- - The algorithm may be sensitive to the initial permutation matrix (or - search "position") due to the possibility of several local minima - within the feasible region. A barycenter initialization is more likely to - result in a better solution than a single random initialization. However, - ``quadratic_assignment`` calling several times with different random - initializations may result in a better optimum at the cost of longer - total execution time. - Examples - -------- - As mentioned above, a barycenter initialization often results in a better - solution than a single random initialization. - >>> np.random.seed(0) - >>> n = 15 - >>> A = np.random.rand(n, n) - >>> B = np.random.rand(n, n) - >>> res = quadratic_assignment(A, B) # FAQ is default method - >>> print(res.fun) - 46.871483385480545 # may vary - >>> options = {"P0": "randomized"} # use randomized initialization - >>> res = quadratic_assignment(A, B, options=options) - >>> print(res.fun) - 47.224831071310625 # may vary - However, consider running from several randomized initializations and - keeping the best result. - >>> res = min([quadratic_assignment(A, B, options=options) - ... for i in range(30)], key=lambda x: x.fun) - >>> print(res.fun) - 46.671852533681516 # may vary - The '2-opt' method can be used to further refine the results. - >>> options = {"partial_guess": np.array([np.arange(n), res.col_ind]).T} - >>> res = quadratic_assignment(A, B, method="2opt", options=options) - >>> print(res.fun) - 46.47160735721583 # may vary - References - ---------- - .. [1] J.T. Vogelstein, J.M. Conroy, V. Lyzinski, L.J. Podrazik, - S.G. Kratzer, E.T. Harley, D.E. Fishkind, R.J. Vogelstein, and - C.E. Priebe, "Fast approximate quadratic programming for graph - matching," PLOS one, vol. 10, no. 4, p. e0121002, 2015, - :doi:`10.1371/journal.pone.0121002` - .. [2] D. Fishkind, S. Adali, H. Patsolic, L. Meng, D. Singh, V. Lyzinski, - C. Priebe, "Seeded graph matching", Pattern Recognit. 87 (2019): - 203-215, :doi:`10.1016/j.patcog.2018.09.014` - """ - - maxiter = operator.index(maxiter) - - # ValueError check - A, B, partial_match_value = _common_input_validation(A, B, partial_match) - - msg = None - if isinstance(P0, str) and P0 not in {"barycenter", "randomized"}: - msg = "Invalid 'P0' parameter string" - elif maxiter <= 0: - msg = "'maxiter' must be a positive integer" - elif tol <= 0: - msg = "'tol' must be a positive float" - if msg is not None: - raise ValueError(msg) - - if not isinstance(S, np.ndarray): - raise ValueError("`S` must be an ndarray") - elif S.shape != (S.shape[0], S.shape[0]): - raise ValueError("`S` must be square") - elif S.shape != A.shape: - raise ValueError("`S`, `A`, and `B` matrices must be of equal size") - else: - s_value = S - - rng = check_random_state(rng) - n = A.shape[0] # number of vertices in graphs - n_seeds = partial_match_value.shape[0] # number of seeds - n_unseed = n - n_seeds - - # check outlier cases - if n == 0 or partial_match_value.shape[0] == n: - # Cannot assume partial_match is sorted. - sort_inds = np.argsort(partial_match_value[:, 0]) - partial_match_value = partial_match_value[sort_inds] - score = _calc_score(A, B, s_value, partial_match_value[:, 1]) - res = {"col_ind": partial_match_value[:, 1], "fun": score, "nit": 0} - return OptimizeResult(res) - - obj_func_scalar = 1 - if maximize: - obj_func_scalar = -1 - - nonseed_B = np.setdiff1d(range(n), partial_match_value[:, 1]) - perm_S = np.copy(nonseed_B) - if shuffle_input: - nonseed_B = rng.permutation(nonseed_B) - # shuffle_input to avoid results from inputs that were already matched - - nonseed_A = np.setdiff1d(range(n), partial_match_value[:, 0]) - perm_A = np.concatenate([partial_match_value[:, 0], nonseed_A]) - perm_B = np.concatenate([partial_match_value[:, 1], nonseed_B]) - - s_value = s_value[:, perm_B] - - # definitions according to Seeded Graph Matching [2]. - A11, A12, A21, A22 = _split_matrix(A[perm_A][:, perm_A], n_seeds) - B11, B12, B21, B22 = _split_matrix(B[perm_B][:, perm_B], n_seeds) - S22 = s_value[perm_S, n_seeds:] - - # [1] Algorithm 1 Line 1 - choose initialization - if isinstance(P0, str): - # initialize J, a doubly stochastic barycenter - J = np.ones((n_unseed, n_unseed)) / n_unseed - if P0 == "barycenter": - P = J - elif P0 == "randomized": - # generate a nxn matrix where each entry is a random number [0, 1] - # would use rand, but Generators don't have it - # would use random, but old mtrand.RandomStates don't have it - K = rng.uniform(size=(n_unseed, n_unseed)) - # Sinkhorn balancing - K = _doubly_stochastic(K) - P = J * 0.5 + K * 0.5 - elif isinstance(P0, np.ndarray): - _P0 = np.atleast_2d(P0) - _check_init_input(_P0, n_unseed) - invert_inds = np.argsort(nonseed_B) - perm_nonseed_B = np.argsort(invert_inds) - P = _P0[:, perm_nonseed_B] - else: - msg = "`init` must either be of type str or np.ndarray." - raise TypeError(msg) - - const_sum = A21 @ B21.T + A12.T @ B12 + S22 - - # [1] Algorithm 1 Line 2 - loop while stopping criteria not met - for n_iter in range(1, maxiter + 1): - # [1] Algorithm 1 Line 3 - compute the gradient of f(P) = -tr(APB^tP^t) - grad_fp = const_sum + A22 @ P @ B22.T + A22.T @ P @ B22 - # [1] Algorithm 1 Line 4 - get direction Q by solving Eq. 8 - _, cols = linear_sum_assignment(grad_fp, maximize=maximize) - Q = np.eye(n_unseed)[cols] - - # [1] Algorithm 1 Line 5 - compute the step size - # Noting that e.g. trace(Ax) = trace(A)*x, expand and re-collect - # terms as ax**2 + bx + c. c does not affect location of minimum - # and can be ignored. Also, note that trace(A@B) = (A.T*B).sum(); - # apply where possible for efficiency. - R = P - Q - b21 = ((R.T @ A21) * B21).sum() - b12 = ((R.T @ A12.T) * B12.T).sum() - AR22 = A22.T @ R - BR22 = B22 @ R.T - b22a = (AR22 * B22.T[cols]).sum() - b22b = (A22 * BR22[cols]).sum() - s = (S22 * R).sum() - a = (AR22.T * BR22).sum() - b = b21 + b12 + b22a + b22b + s - # critical point of ax^2 + bx + c is at x = -d/(2*e) - # if a * obj_func_scalar > 0, it is a minimum - # if minimum is not in [0, 1], only endpoints need to be considered - if a * obj_func_scalar > 0 and 0 <= -b / (2 * a) <= 1: - alpha = -b / (2 * a) - else: - alpha = np.argmin([0, (b + a) * obj_func_scalar]) - - # [1] Algorithm 1 Line 6 - Update P - P_i1 = alpha * P + (1 - alpha) * Q - if np.linalg.norm(P - P_i1) / np.sqrt(n_unseed) < tol: - P = P_i1 - break - P = P_i1 - # [1] Algorithm 1 Line 7 - end main loop - - # [1] Algorithm 1 Line 8 - project onto the set of permutation matrices - _, col = linear_sum_assignment(-P) - perm = np.concatenate((np.arange(n_seeds), col + n_seeds)) - - unshuffled_perm = np.zeros(n, dtype=int) - unshuffled_perm[perm_A] = perm_B[perm] - - score = _calc_score(A, B, s_value, unshuffled_perm) - - res = {"col_ind": unshuffled_perm, "fun": score, "nit": n_iter} - - return OptimizeResult(res) - - -def _check_init_input(P0: np.ndarray, n: int) -> None: - row_sum = np.sum(P0, axis=0) - col_sum = np.sum(P0, axis=1) - tol = 1e-3 - msg = None - if P0.shape != (n, n): - msg = "`P0` matrix must have shape m' x m', where m'=n-m" - elif ( - (~np.isclose(row_sum, 1, atol=tol)).any() - or (~np.isclose(col_sum, 1, atol=tol)).any() - or (P0 < 0).any() - ): - msg = "`P0` matrix must be doubly stochastic" - if msg is not None: - raise ValueError(msg) - - -def _split_matrix( - X: np.ndarray, n: int -) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]: - # definitions according to Seeded Graph Matching [2]. - upper, lower = X[:n], X[n:] - return upper[:, :n], upper[:, n:], lower[:, :n], lower[:, n:] - - -def _doubly_stochastic(P: np.ndarray, tol: float = 1e-3) -> np.ndarray: - # Adapted from @btaba implementation - # https://github.com/btaba/sinkhorn_knopp - # of Sinkhorn-Knopp algorithm - # https://projecteuclid.org/euclid.pjm/1102992505 - - max_iter = 1000 - c = 1 / P.sum(axis=0) - r = 1 / (P @ c) - P_eps = P - - for it in range(max_iter): - if (np.abs(P_eps.sum(axis=1) - 1) < tol).all() and ( - np.abs(P_eps.sum(axis=0) - 1) < tol - ).all(): - # All column/row sums ~= 1 within threshold - break - - c = 1 / (r @ P) - r = 1 / (P @ c) - P_eps = r[:, None] * P * c - - return P_eps - - -# copy-pasted from scipy scipy._lib._util -# which was copy-pasted from scikit-learn utils/validation.py -# this was just modified to add proper typing for returns -# also, shouldn't have been importing private function from scipy anyway -def check_random_state( - seed: Union[None, int, np.random.RandomState, np.random.Generator] -) -> Union[np.random.RandomState, np.random.Generator]: - """Turn seed into a np.random.RandomState instance - - If seed is None (or np.random), return the RandomState singleton used - by np.random. - If seed is an int, return a new RandomState instance seeded with seed. - If seed is already a RandomState instance, return it. - If seed is a new-style np.random.Generator, return it. - Otherwise raise ValueError. - """ - if seed is None or seed is np.random: - return np.random.mtrand._rand - if isinstance(seed, (numbers.Integral, np.integer)): - int_seed: int = int(seed) # necessary for typing/mypy - return np.random.RandomState(int_seed) - if isinstance(seed, np.random.RandomState): - return seed - try: - # Generator is only available in numpy >= 1.17 - if isinstance(seed, np.random.Generator): - return seed - except AttributeError: - pass - raise ValueError( - "%r cannot be used to seed a numpy.random.RandomState" " instance" % seed - ) diff --git a/graspologic/match/solver.py b/graspologic/match/solver.py new file mode 100644 index 000000000..a6ade40ff --- /dev/null +++ b/graspologic/match/solver.py @@ -0,0 +1,747 @@ +# Copyright (c) Microsoft Corporation and contributors. +# Licensed under the MIT License. + +import time +import warnings +from functools import wraps +from typing import Callable, Optional, Union + +import numpy as np +from beartype import beartype +from ot import sinkhorn +from scipy.optimize import linear_sum_assignment +from scipy.sparse import csr_matrix +from sklearn.utils import check_scalar + +from graspologic.types import List, RngType, Tuple + +from .types import ( + AdjacencyMatrix, + Int, + MultilayerAdjacency, + PaddingType, + PartialMatchType, + Scalar, + csr_array, +) + + +def parameterized(dec: Callable) -> Callable: + def layer(*args, **kwargs) -> Callable: # type: ignore + def repl(f: Callable) -> Callable: + return dec(f, *args, **kwargs) + + return repl + + return layer + + +@parameterized +def write_status(f: Callable, msg: str, level: int) -> Callable: + @wraps(f) + def wrap(*args, **kw): # type: ignore + obj = args[0] + verbose = obj.verbose + if level <= verbose: + total_msg = (level - 1) * " " + total_msg += obj.status() + " " + msg + print(total_msg) + if (verbose >= 4) and (level <= verbose): + ts = time.time() + result = f(*args, **kw) + te = time.time() + sec = te - ts + output = total_msg + f" took {sec:.3f} seconds." + print(output) + else: + result = f(*args, **kw) + return result + + return wrap + + +class _GraphMatchSolver: + @beartype + def __init__( + self, + A: MultilayerAdjacency, + B: MultilayerAdjacency, + AB: Optional[MultilayerAdjacency] = None, + BA: Optional[MultilayerAdjacency] = None, + S: Optional[AdjacencyMatrix] = None, + partial_match: Optional[PartialMatchType] = None, + init: Optional[np.ndarray] = None, + init_perturbation: Scalar = 0.0, + verbose: Int = False, + shuffle_input: bool = True, + padding: PaddingType = "naive", + maximize: bool = True, + max_iter: Int = 30, + tol: Scalar = 0.03, + transport: bool = False, + transport_regularizer: Scalar = 100, + transport_tol: Scalar = 5e-2, + transport_max_iter: Int = 1000, + ): + # TODO check if init is doubly stochastic + self.init = init + check_scalar( + init_perturbation, + name="init_perturbation", + target_type=(float, int), + min_val=0, + max_val=1, + ) + self.init_perturbation = init_perturbation + self.verbose = verbose + self.shuffle_input = shuffle_input + self.maximize = maximize + check_scalar(max_iter, name="max_iter", target_type=int, min_val=1) + self.max_iter = max_iter + check_scalar(tol, name="tol", target_type=(int, float), min_val=0) + self.tol = tol + self.padding = padding + + self.transport = transport + self.transport_regularizer = transport_regularizer + check_scalar( + transport_tol, name="transport_tol", target_type=(int, float), min_val=0 + ) + self.transport_tol = transport_tol + check_scalar( + transport_max_iter, name="transport_max_iter", target_type=int, min_val=1 + ) + self.transport_max_iter = transport_max_iter + + if maximize: + self.obj_func_scalar = -1 + else: + self.obj_func_scalar = 1 + + # convert everything to make sure they are 3D arrays (first dim is layer) + A = _check_input_matrix(A, n_layers=None) + self.n_layers = len(A) + B = _check_input_matrix(B, n_layers=self.n_layers) + if len(A) != len(B): + raise ValueError("`A` and `B` must have same number of layers.") + + # get some useful sizes + self.n_A = A[0].shape[0] + self.n_B = B[0].shape[0] + + if partial_match is None: + self._seeded = False + else: + self._seeded = True + + seeds = _check_partial_match(partial_match, self.n_A, self.n_B) + + n_seeds = len(seeds) + self.n_seeds = n_seeds + + if (self.n_A != self.n_B) and padding == "adopted": + contra_sparse = False + else: + contra_sparse = True + # check for between-graph terms + # default to sparse if possible since all 0s + if AB is None: + if contra_sparse: + AB = self.n_layers * [csr_array((self.n_A, self.n_B))] + else: + AB = self.n_layers * [np.zeros((self.n_A, self.n_B))] + else: + AB = _check_input_matrix(AB, n_layers=self.n_layers) + if BA is None: + if contra_sparse: + BA = self.n_layers * [csr_array((self.n_B, self.n_A))] + else: + BA = self.n_layers * [np.zeros((self.n_B, self.n_A))] + else: + BA = _check_input_matrix(BA, n_layers=self.n_layers) + + # check all input dims + # can safely assume that the first matrix in each is representative of dimension + # because of check done in _check_input_matrix + _compare_dimensions(A, A, "row", "column", "A", "A") + _compare_dimensions(B, B, "row", "column", "B", "B") + _compare_dimensions(A, AB, "row", "row", "A", "AB") + _compare_dimensions(B, AB, "row", "column", "B", "AB") + _compare_dimensions(A, BA, "row", "column", "A", "BA") + _compare_dimensions(B, BA, "row", "row", "B", "BA") + + # padding for unequally sized inputs + if self.n_A != self.n_B: + self.n = np.max((self.n_A, self.n_B)) + A = _multilayer_adj_pad(A, n_padded=self.n, method=self.padding) + B = _multilayer_adj_pad(B, n_padded=self.n, method=self.padding) + AB = _multilayer_adj_pad(AB, n_padded=self.n, method=self.padding) + BA = _multilayer_adj_pad(BA, n_padded=self.n, method=self.padding) + self.padded = True + if self.n_A > self.n_B: + self._padded_B = True + else: + self._padded_B = False + else: + self.padded = False + self.n = self.n_A + + # check for similarity term + if S is None: + S = csr_array((self.n, self.n)) + + _compare_dimensions(A, [S], "row", "row", "A", "S") + _compare_dimensions(B, [S], "row", "column", "B", "S") + + self.A = A + self.B = B + self.AB = AB + self.BA = BA + self.S = S + + # set up so that seeds are first and we can grab subgraphs easily + # TODO could also do this slightly more efficiently just w/ smart indexing? + sort_inds = np.argsort(seeds[:, 0]) + seeds = seeds[sort_inds] + self.seeds = seeds + nonseed_A = np.setdiff1d(np.arange(self.n), seeds[:, 0]) + nonseed_B = np.setdiff1d(np.arange(self.n), seeds[:, 1]) + perm_A = np.concatenate([seeds[:, 0], nonseed_A]) + perm_B = np.concatenate([seeds[:, 1], nonseed_B]) + self.perm_A = perm_A + self.perm_B = perm_B + self._undo_perm_A = np.argsort(perm_A) + self._undo_perm_B = np.argsort(perm_B) + + # permute each (sub)graph appropriately + A = _permute_multilayer(A, perm_A, rows=True, columns=True) + B = _permute_multilayer(B, perm_B, rows=True, columns=True) + AB = _permute_multilayer(AB, perm_A, rows=True, columns=False) + AB = _permute_multilayer(AB, perm_B, rows=False, columns=True) + BA = _permute_multilayer(BA, perm_A, rows=False, columns=True) + BA = _permute_multilayer(BA, perm_B, rows=True, columns=False) + S = S[perm_A][:, perm_B] + + # split into subgraphs of seed-to-seed (ss), seed-to-nonseed (sn), etc. + # main thing being permuted has no subscript + self.A_ss, self.A_sn, self.A_ns, self.A_nn = _split_multilayer_matrix( + A, n_seeds + ) + self.B_ss, self.B_sn, self.B_ns, self.B_nn = _split_multilayer_matrix( + B, n_seeds + ) + self.AB_ss, self.AB_sn, self.AB_ns, self.AB_nn = _split_multilayer_matrix( + AB, n_seeds + ) + self.BA_ss, self.BA_sn, self.BA_ns, self.BA_nn = _split_multilayer_matrix( + BA, n_seeds + ) + + self.n_unseed = self.B_nn[0].shape[0] + + self.S_ss, self.S_sn, self.S_ns, self.S_nn = _split_matrix(S, n_seeds) + + def solve(self, rng: RngType = None) -> None: + rng = np.random.default_rng(rng) + + self.n_iter_ = 0 + if self.n_seeds == self.n: # all seeded, break + P = np.empty((0, 0)) + self.converged_ = True + else: + P = self.initialize(rng) + self.compute_constant_terms() + for n_iter in range(self.max_iter): + self.n_iter_ = n_iter + 1 + + gradient = self.compute_gradient(P) + Q = self.compute_step_direction(gradient, rng) + alpha = self.compute_step_size(P, Q) + + # take a step in this direction + P_new = alpha * P + (1 - alpha) * Q + + if self.check_converged(P, P_new): + self.converged_ = True + P = P_new + break + P = P_new + + self.finalize(P, rng) + + @write_status("Initializing", 1) + def initialize(self, rng: np.random.Generator) -> np.ndarray: + # user custom initialization + if isinstance(self.init, np.ndarray): + _check_init_input(self.init, self.n_unseed) + J = self.init + # else, just a flat, uninformative initializaiton, also called the barycenter + # (of the set of doubly stochastic matrices) + else: + n_unseed = self.n_unseed + J = np.full((n_unseed, n_unseed), 1 / n_unseed) + + if self.init_perturbation > 0: + # create a random doubly stochastic matrix + # TODO unsure if this is actually uniform over the Birkoff polytope + # I suspect it is not. Not even sure if humankind knows how to generate such + # a matrix efficiently... + + # start with random (uniform 0-1 values) matrix + K = rng.uniform(size=(n_unseed, n_unseed)) + # use Sinkhorn algo. to project to closest doubly stochastic + K = _doubly_stochastic(K) + + # to a convex combination with either barycenter or input initialization + P = J * (1 - self.init_perturbation) + K * (self.init_perturbation) + else: + P = J + + self.converged_ = False + return P + + @write_status("Computing constant terms", 2) + def compute_constant_terms(self) -> None: + self.constant_sum = np.zeros((self.n_unseed, self.n_unseed)) + if self._seeded: + n_layers = len(self.A_nn) + for i in range(n_layers): + self.constant_sum += ( + self.A_ns[i] @ self.B_ns[i].T # ipsi + + self.A_sn[i].T @ self.B_sn[i] # ipsi + + self.AB_ns[i] @ self.BA_ns[i].T # contra + + self.BA_sn[i].T @ self.AB_sn[i] # contra + ) + self.constant_sum += self.S_nn + + @write_status("Computing gradient", 2) + def compute_gradient(self, P: np.ndarray) -> np.ndarray: + gradient = _compute_gradient( + P, self.A_nn, self.B_nn, self.AB_nn, self.BA_nn, self.constant_sum + ) + return gradient + + @write_status("Solving assignment problem", 2) + def compute_step_direction( + self, gradient: np.ndarray, rng: np.random.Generator + ) -> np.ndarray: + # [1] Algorithm 1 Line 4 - get direction Q by solving Eq. 8 + if self.transport: + Q = self.linear_sum_transport(gradient) + else: + permutation = self.linear_sum_assignment(gradient, rng) + Q = np.eye(self.n_unseed)[permutation] + return Q + + def linear_sum_assignment( + self, P: np.ndarray, rng: np.random.Generator, maximize: Optional[bool] = None + ) -> np.ndarray: + """This is a modified version of LAP which (in expectation) does not care + about the order of the inputs. This matters because scipy LAP settles ties + (which do come up) based on the ordering of the inputs. This can lead to + artificially high matching accuracy when the user inputs data which is in the + correct permutation, for example.""" + if self.shuffle_input: + row_perm = rng.permutation(P.shape[0]) + else: + row_perm = np.arange(P.shape[0]) + undo_row_perm = np.argsort(row_perm) + P_perm = P[row_perm] + if maximize is None: + maximize = self.maximize + _, permutation = linear_sum_assignment(P_perm, maximize=maximize) + return permutation[undo_row_perm] + + def linear_sum_transport( + self, + P: np.ndarray, + ) -> np.ndarray: + maximize = self.maximize + reg = self.transport_regularizer + + power = -1 if maximize else 1 + lamb = reg / np.max(np.abs(P)) + ones = np.ones(P.shape[0]) + P_eps, log = sinkhorn( + ones, + ones, + P, + power / lamb, + stopThr=self.transport_tol, + numItermax=self.transport_max_iter, + log=True, + warn=False, + ) + if log["niter"] == self.transport_max_iter - 1: + warnings.warn( + "Sinkhorn-Knopp algorithm for solving linear sum transport " + f"problem did not converge. The final error was {log['err'][-1]} " + f"and the `transport_tol` was {self.transport_tol}. " + "You may want to consider increasing " + "`transport_regularizer`, increasing `transport_max_iter`, or this " + "could be the result of `transport_tol` set too small." + ) + return P_eps + + @write_status("Computing step size", 2) + def compute_step_size(self, P: np.ndarray, Q: np.ndarray) -> float: + a, b = _compute_coefficients( + P, + Q, + self.A_nn, + self.B_nn, + self.AB_nn, + self.BA_nn, + self.A_ns, + self.A_sn, + self.B_ns, + self.B_sn, + self.AB_ns, + self.AB_sn, + self.BA_ns, + self.BA_sn, + self.S_nn, + ) + if a * self.obj_func_scalar > 0 and 0 <= -b / (2 * a) <= 1: + alpha = -b / (2 * a) + else: + alpha = float(np.argmin([0, (b + a) * self.obj_func_scalar])) + return alpha + + def check_converged(self, P: np.ndarray, P_new: np.ndarray) -> bool: + return np.linalg.norm(P - P_new) / np.sqrt(self.n_unseed) < self.tol + + @write_status("Finalizing assignment", 1) + def finalize(self, P: np.ndarray, rng: np.random.Generator) -> None: + self.convex_solution_ = P + + # project back onto the feasible region (permutations) + if P.shape != (0, 0): + permutation = self.linear_sum_assignment(P, rng, maximize=True) + else: # the case where input was all seeded + permutation = np.array([], dtype=int) + + # deal with seed-nonseed sorting from the initialization + permutation = np.concatenate( + (np.arange(self.n_seeds), permutation + self.n_seeds) + ) + final_permutation = np.empty(self.n, dtype=int) + final_permutation[self.perm_A] = self.perm_B[permutation] + + # deal with un-padding + matching = np.column_stack((np.arange(self.n), final_permutation)) + if self.padded: + if self._padded_B: + matching = matching[matching[:, 1] < self.n_B] + else: + matching = matching[: self.n_A] + + self.matching_ = matching + + # compute the objective function value for evaluation + score = self.compute_score(final_permutation) + self.score_ = score + + def compute_score(self, permutation: np.ndarray) -> float: + score = 0.0 + n_layers = self.n_layers + for layer in range(n_layers): + # casting explicitly to float here because mypy was yelling: + # 'Incompatible types in assignment (expression has type "floating[Any]", + # variable has type "float")' + score += np.sum(self.A[layer] * self.B[layer][permutation][:, permutation]) + score += np.sum( + self.AB[layer][:, permutation] * self.BA[layer][permutation] + ) + # for some reason, trace was not working on Py 3.7 + # this is equivalent to trace(SP^T) + score += float(np.sum(self.S[np.arange(self.S.shape[0]), permutation])) + return score + + def status(self) -> str: + if self.n_iter_ > 0: + return f"[Iteration: {self.n_iter_}]" + else: + return "[Pre-loop]" + + +def _permute_multilayer( + adjacency: MultilayerAdjacency, + permutation: np.ndarray, + rows: bool = True, + columns: bool = True, +) -> MultilayerAdjacency: + new_adjacency = [] + for layer_index in range(len(adjacency)): + layer = adjacency[layer_index] + if rows: + layer = layer[permutation] + if columns: + layer = layer[:, permutation] + new_adjacency.append(layer) + return new_adjacency + + +def _check_input_matrix( + A: MultilayerAdjacency, n_layers: Optional[int] +) -> MultilayerAdjacency: + if isinstance(A, np.ndarray) and (np.ndim(A) == 2): + A = [A] + elif isinstance(A, (csr_matrix, csr_array)): + A = [A] + elif isinstance(A, list): + # iterate over to make sure they're all same shape + first_layer = A[0] + for i in range(1, len(A)): + layer = A[i] + if (layer.shape[0] != first_layer.shape[0]) or ( + layer.shape[1] != first_layer.shape[1] + ): + raise ValueError( + "Layers in a multilayer network must all share the same shape." + ) + if isinstance(A[0], np.ndarray): + A = np.array(A, dtype=float) + elif isinstance(A[0], csr_matrix): + pass + if (n_layers is not None) and (len(A) != n_layers): + msg = ( + "Input multilayer matrices (A, B, AB, BA) must have the same " + "number of layers." + ) + raise ValueError(msg) + return A + + +def _compute_gradient( + P: np.ndarray, + A: MultilayerAdjacency, + B: MultilayerAdjacency, + AB: MultilayerAdjacency, + BA: MultilayerAdjacency, + const_sum: np.ndarray, +) -> np.ndarray: + n_layers = len(A) + grad = const_sum.copy() + for i in range(n_layers): + grad += ( + A[i] @ P @ B[i].T + + A[i].T @ P @ B[i] + + AB[i] @ P.T @ BA[i].T + + BA[i].T @ P.T @ AB[i] + ) + return grad + + +def _compute_coefficients( + P: np.ndarray, + Q: np.ndarray, + A: MultilayerAdjacency, + B: MultilayerAdjacency, + AB: MultilayerAdjacency, + BA: MultilayerAdjacency, + A_ns: MultilayerAdjacency, + A_sn: MultilayerAdjacency, + B_ns: MultilayerAdjacency, + B_sn: MultilayerAdjacency, + AB_ns: MultilayerAdjacency, + AB_sn: MultilayerAdjacency, + BA_ns: MultilayerAdjacency, + BA_sn: MultilayerAdjacency, + S: AdjacencyMatrix, +) -> Tuple[float, float]: + R = P - Q + # TODO make these "smart" traces like in the scipy code, couldn't hurt + # TODO can also refactor to not repeat multiplications like the old code but I was + # finding it harder to follow that way. + n_layers = len(A) + a_cross = 0 + b_cross = 0 + a_intra = 0 + b_intra = 0 + for i in range(n_layers): + a_cross += np.trace(AB[i].T @ R @ BA[i] @ R) + b_cross += np.trace(AB[i].T @ R @ BA[i] @ Q) + np.trace(AB[i].T @ Q @ BA[i] @ R) + b_cross += np.trace(AB_ns[i].T @ R @ BA_ns[i]) + np.trace( + AB_sn[i].T @ BA_sn[i] @ R + ) + a_intra += np.trace(A[i] @ R @ B[i].T @ R.T) + b_intra += np.trace(A[i] @ Q @ B[i].T @ R.T) + np.trace(A[i] @ R @ B[i].T @ Q.T) + b_intra += np.trace(A_ns[i].T @ R @ B_ns[i]) + np.trace(A_sn[i] @ R @ B_sn[i].T) + + a = a_cross + a_intra + b = b_cross + b_intra + b += np.sum(S * R) # equivalent to S.T @ R + + return a, b + + +def _split_matrix( + matrix: AdjacencyMatrix, n: int +) -> Tuple[AdjacencyMatrix, AdjacencyMatrix, AdjacencyMatrix, AdjacencyMatrix]: + upper, lower = matrix[:n], matrix[n:] + return upper[:, :n], upper[:, n:], lower[:, :n], lower[:, n:] + + +def _split_multilayer_matrix( + matrices: MultilayerAdjacency, n: int +) -> Tuple[ + MultilayerAdjacency, MultilayerAdjacency, MultilayerAdjacency, MultilayerAdjacency +]: + n_layers = len(matrices) + seed_to_seed = [] + seed_to_nonseed = [] + nonseed_to_seed = [] + nonseed_to_nonseed = [] + + for i in range(n_layers): + matrix = matrices[i] + ss, sn, ns, nn = _split_matrix(matrix, n) + seed_to_seed.append(ss) + seed_to_nonseed.append(sn) + nonseed_to_seed.append(ns) + nonseed_to_nonseed.append(nn) + return seed_to_seed, seed_to_nonseed, nonseed_to_seed, nonseed_to_nonseed + + +def _doubly_stochastic(P: np.ndarray, tol: float = 1e-3) -> np.ndarray: + # Adapted from @btaba implementation + # https://github.com/btaba/sinkhorn_knopp + # of Sinkhorn-Knopp algorithm + # https://projecteuclid.org/euclid.pjm/1102992505 + + max_iter = 1000 + c = 1 / P.sum(axis=0) + r = 1 / (P @ c) + P_eps = P + + for _ in range(max_iter): + if (np.abs(P_eps.sum(axis=1) - 1) < tol).all() and ( + np.abs(P_eps.sum(axis=0) - 1) < tol + ).all(): + # All column/row sums ~= 1 within threshold + break + + c = 1 / (r @ P) + r = 1 / (P @ c) + P_eps = r[:, None] * P * c + + return P_eps + + +def _multilayer_adj_pad( + matrices: MultilayerAdjacency, n_padded: int, method: PaddingType +) -> MultilayerAdjacency: + n1 = matrices[0].shape[0] + n2 = matrices[0].shape[1] + if (n1 == n_padded) and (n2 == n_padded): + return matrices + else: + new_matrices: List[AdjacencyMatrix] = [] + for matrix in matrices: + new_matrices.append(_adj_pad(matrix, n_padded, method)) + return new_matrices + + +def _adj_pad( + matrix: AdjacencyMatrix, n_padded: Int, method: PaddingType +) -> Tuple[np.ndarray, np.ndarray, np.ndarray]: + if isinstance(matrix, (csr_matrix, csr_array)) and (method == "adopted"): + msg = ( + "Using adopted padding method with a sparse adjacency representation; this " + "will convert the matrix to a dense representation and likely remove any " + "speedup from the sparse representation." + ) + warnings.warn(msg) + matrix = matrix.toarray() + + if method == "adopted": + matrix = 2 * matrix - np.ones(matrix.shape) + + if (method == "naive") and isinstance(matrix, (csr_matrix, csr_array)): + matrix_padded = csr_array((n_padded, n_padded)) + else: + matrix_padded = np.zeros((n_padded, n_padded)) + + matrix_padded[: matrix.shape[0], : matrix.shape[1]] = matrix + + return matrix_padded + + +def _compare_dimensions( + A: MultilayerAdjacency, + B: MultilayerAdjacency, + dimension_A: str, + dimension_B: str, + name1: str, + name2: str, +) -> None: + matrix_A = A[0] + matrix_B = B[0] + dim_index_A = 0 if dimension_A == "row" else 1 + dim_index_B = 0 if dimension_B == "row" else 1 + if not (matrix_A.shape[dim_index_A] == matrix_B.shape[dim_index_B]): + msg = ( + f"Input matrix/matrices `{name1}` number of {dimension_A}s must match " + f"`{name2}` number of {dimension_B}s." + ) + raise ValueError(msg) + + +def _check_partial_match( + partial_match: Optional[Union[np.ndarray, Tuple]], n1: int, n2: int +) -> np.ndarray: + + _partial_match: np.ndarray + if partial_match is None: + _partial_match = np.array([[], []]).T + elif isinstance(partial_match, tuple): + _partial_match = np.column_stack(partial_match) + else: + _partial_match = np.array(partial_match) + + _partial_match = np.atleast_2d(_partial_match).astype(int) + + _, seeds1_counts = np.unique(_partial_match[:, 0], return_counts=True) + _, seeds2_counts = np.unique(_partial_match[:, 1], return_counts=True) + + msg = None + if _partial_match.shape[0] > min(n1, n2): + msg = "`partial_match` can have only as many seeds as there are nodes" + elif _partial_match.shape[1] != 2: + msg = "`partial_match` must have two columns" + elif _partial_match.ndim != 2: + msg = "`partial_match` must have exactly two dimensions" + elif (_partial_match < 0).any(): + msg = "`partial_match` must contain only positive indices" + elif (_partial_match[:, 0] >= n1).any() or (_partial_match[:, 1] >= n2).any(): + msg = "`partial_match` entries must be less than number of nodes" + elif (len(_partial_match) > 0) and ( + (seeds1_counts.max() > 1) or (seeds2_counts.max() > 1) + ): + msg = "`partial_match` column entries must be unique" + + if msg is not None: + raise ValueError(msg) + + return _partial_match + + +def _check_init_input(init: np.ndarray, n: int) -> None: + if init.ndim != 2: + msg = "`init` matrix must be 2d" + raise ValueError(msg) + row_sum = np.sum(init, axis=0) + col_sum = np.sum(init, axis=1) + tol = 1e-3 + msg = "" + if init.shape != (n, n): + msg = "`init` matrix must be n x n, where n is the number of non-seeded nodes" + elif ( + (~np.isclose(row_sum, 1, atol=tol)).any() + or (~np.isclose(col_sum, 1, atol=tol)).any() + or (init < 0).any() + ): + msg = "`init` matrix must be doubly stochastic" + if msg != "": + raise ValueError(msg) diff --git a/graspologic/match/types.py b/graspologic/match/types.py new file mode 100644 index 000000000..0cec44fdc --- /dev/null +++ b/graspologic/match/types.py @@ -0,0 +1,31 @@ +# Copyright (c) Microsoft Corporation and contributors. +# Licensed under the MIT License. + +from typing import Union + +import numpy as np +from packaging import version +from scipy import __version__ as scipy_version +from scipy.sparse import csr_matrix + +if version.parse(scipy_version) >= version.parse("1.8.0"): + from scipy.sparse import csr_array +else: + csr_array = csr_matrix + +from typing_extensions import Literal + +from graspologic.types import List, Tuple + +# redefining since I don't want to add csr_array for ALL code in graspologic yet +AdjacencyMatrix = Union[np.ndarray, csr_matrix, csr_array] + +MultilayerAdjacency = Union[List[AdjacencyMatrix], AdjacencyMatrix, np.ndarray] + +PaddingType = Literal["adopted", "naive"] + +Scalar = Union[int, float, np.integer] + +Int = Union[int, np.integer] + +PartialMatchType = Union[np.ndarray, Tuple] diff --git a/graspologic/match/wrappers.py b/graspologic/match/wrappers.py new file mode 100644 index 000000000..50c031ad7 --- /dev/null +++ b/graspologic/match/wrappers.py @@ -0,0 +1,322 @@ +# Copyright (c) Microsoft Corporation and contributors. +# Licensed under the MIT License. + +from typing import Any, NamedTuple, Optional + +import numpy as np +from beartype import beartype +from joblib import Parallel, delayed +from sklearn.utils import check_scalar + +from graspologic.match.solver import _GraphMatchSolver +from graspologic.types import Dict, List, RngType + +from .types import ( + AdjacencyMatrix, + Int, + MultilayerAdjacency, + PaddingType, + PartialMatchType, + Scalar, +) + + +class MatchResult(NamedTuple): + indices_A: np.ndarray + """ + Sorted indices in ``A`` which were matched. + """ + + indices_B: np.ndarray + """ + Indices in ``B`` which were matched. Element ``indices_B[i]`` was matched + to element ``indices_A[i]``. ``indices_B`` can also be thought of as a + permutation of the nodes of ``B`` with respect to ``A``. + """ + + score: float + """ + Objective function value at the end of optimization. + """ + + misc: List[Dict[str, Any]] + """ + List of length ``n_init`` containing information about each run. Fields for + each run are ``score``, ``n_iter``, ``convex_solution``, and ``converged``. + """ + + +@beartype +def graph_match( + A: MultilayerAdjacency, + B: MultilayerAdjacency, + AB: Optional[MultilayerAdjacency] = None, + BA: Optional[MultilayerAdjacency] = None, + S: Optional[AdjacencyMatrix] = None, + partial_match: Optional[PartialMatchType] = None, + init: Optional[np.ndarray] = None, + init_perturbation: Scalar = 0.0, + n_init: Int = 1, + shuffle_input: bool = True, + maximize: bool = True, + padding: PaddingType = "naive", + n_jobs: Optional[Int] = None, + max_iter: Int = 30, + tol: Scalar = 0.01, + verbose: Int = 0, + rng: Optional[RngType] = None, + transport: bool = False, + transport_regularizer: Scalar = 100, + transport_tol: Scalar = 5e-2, + transport_max_iter: Int = 1000, +) -> MatchResult: + """ + Attempts to solve the Graph Matching Problem or the Quadratic Assignment Problem + (QAP) through an implementation of the Fast Approximate QAP (FAQ) Algorithm [1]. + + This algorithm can be thought of as finding an alignment of the vertices of two + graphs which minimizes the number of induced edge disagreements, or, in the case + of weighted graphs, the sum of squared differences of edge weight disagreements. + Various extensions to the original FAQ algorithm are also included in this function + ([2-5]). + + + Parameters + ---------- + A : {ndarray, csr_matrix, csr_array} of shape (n, n), or a list thereof + The first (potentially multilayer) adjacency matrix to be matched. Multiplex + networks (e.g. a network with multiple edge types) can be used by inputting a + list of the adjacency matrices for each edge type. + + B : {ndarray, csr_matrix, csr_array} of shape (m, m), or a list thereof + The second (potentially multilayer) adjacency matrix to be matched. Must have + the same number of layers as ``A``, but need not have the same size + (see ``padding``). + + AB : {ndarray, csr_matrix, csr_array} of shape (n, m), or a list thereof, default=None + A (potentially multilayer) matrix representing connections from the objects + indexed in ``A`` to those in ``B``, used for bisected graph matching (see [2]). + + BA : {ndarray, csr_matrix, csr_array} of shape (m, n), or a list thereof, default=None + A (potentially multilayer) matrix representing connections from the objects + indexed in ``B`` to those in ``A``, used for bisected graph matching (see [2]). + + S : {ndarray, csr_matrix, csr_array} of shape (n, m), default=None + A matrix representing the similarity of objects indexed in ``A`` to each object + indexed in ``B``. Note that the scale (i.e. the norm) of this matrix will affect + how strongly the similarity (linear) term is weighted relative to the adjacency + (quadratic) terms. + + partial_match : ndarray of shape (n_matches, 2), dtype=int, or tuple of two array-likes of shape (n_matches,), default=None + Indices specifying known matches to include in the optimization. The + first column represents indices of the objects in ``A``, and the second column + represents their corresponding matches in ``B``. + + init : ndarray of shape (n_unseed, n_unseed), default=None + Initialization for the algorithm. Setting to None specifies the "barycenter", + which is the most commonly used initialization and + represents an uninformative (flat) initialization. If a ndarray, then this + matrix must be square and have size equal to the number of unseeded (not + already matched in ``partial_match``) nodes. + + init_perturbation : float, default=0.0 + Weight of the random perturbation from ``init`` that the initialization will + undergo. Must be between 0 and 1. + + n_init : int, default=1 + Number of initializations/runs of the algorithm to repeat. The solution with + the best objective function value over all initializations is kept. Increasing + ``n_init`` can improve performance but will take longer. + + shuffle_input : bool, default=True + Whether to shuffle the order of the inputs internally during optimization. This + option is recommended to be kept to True besides for testing purposes; it + alleviates a dependence of the solution on the (arbitrary) ordering of the + input rows/columns. + + maximize : bool, default=True + Whether to maximize the objective function (graph matching problem) or minimize + it (quadratic assignment problem). ``maximize=True`` corresponds to trying to + find a permutation wherein the input matrices are as similar as possible - for + adjacency matrices, this corresponds to maximizing the overlap of the edges of + the two networks. Conversely, ``maximize=False`` would attempt to make this + overlap as small as possible. + + padding : {"naive", "adopted"}, default="naive" + Specification of a padding scheme if ``A`` and ``B`` are not of equal size. See + the `padded graph matching tutorial `_ + or [3] for more explanation. Adopted padding has not been tested for weighted + networks; use with caution. + + n_jobs : int, default=None + The number of jobs to run in parallel. Parallelization is over the + initializations, so only relevant when ``n_init > 1``. None means 1 unless in a + joblib.parallel_backend context. -1 means using all processors. See + :class:`joblib.Parallel` for more details. + + max_iter : int, default=30 + Must be 1 or greater, specifying the max number of iterations for the algorithm. + Setting this value higher may provide more precise solutions at the cost of + longer computation time. + + tol : float, default=0.01 + Stopping tolerance for the FAQ algorithm. Setting this value smaller may provide + more precise solutions at the cost of longer computation time. + + verbose : int, default=0 + A positive number specifying the level of verbosity for status updates in the + algorithm's progress. If ``n_jobs`` > 1, then this parameter behaves as the + ``verbose`` parameter for :class:`joblib.Parallel`. Otherwise, will print + increasing levels of information about the algorithm's progress for each + initialization. + + rng : int or np.random.Generator, default=None + Allows the specification of a random seed (positive integer) or a + :class:`np.random.Generator` object to ensure reproducibility. + + transport : bool, default=False + Whether to enable use of regularized optimal transport for determining the step + direction as described in [4]. May improve accuracy/speed, especially for large + inputs and data where the correlation between edges is not close to 1. + + transport_regularizer : int or float, default=100 + Strength of the entropic regularization in the optimal transport solver. + + transport_tol : int or float, default=0.05, + Must be positive. Stopping tolerance for the optimal transport solver. Setting + this value smaller may provide more precise solutions at the cost of longer + computation time. + + transport_max_iter : int, default=1000 + Must be positive. Maximum number of iterations for the optimal transport solver. + Setting this value higher may provide more precise solutions at the cost of + longer computation time. + + Returns + ------- + res: MatchResult + ``MatchResult`` containing the following fields. + + indices_A : ndarray + Sorted indices in ``A`` which were matched. + + indices_B : ndarray + Indices in ``B`` which were matched. Element ``indices_B[i]`` was matched + to element ``indices_A[i]``. ``indices_B`` can also be thought of as a + permutation of the nodes of ``B`` with respect to ``A``. + + score : float + Objective function value at the end of optimization. + + misc : list of dict + List of length ``n_init`` containing information about each run. Fields for + each run are ``score``, ``n_iter``, ``convex_solution``, and ``converged``. + + Notes + ----- + Many extensions [2-5] to the original FAQ algorithm are included in this function. + The full objective function which this function aims to solve can be written as + + .. math:: f(P) = - \sum_{k=1}^K \|A^{(k)} - PB^{(k)}P^T\|_F^2 - \sum_{k=1}^K \|(AB)^{(k)}P^T - P(BA)^{(k)}\|_F^2 + trace(SP^T) + + where :math:`P` is a permutation matrix we are trying to learn, :math:`A^{(k)}` is the adjacency + matrix in network :math:`A` for the :math:`k`-th edge type (and likewise for B), :math:`(AB)^{(k)}` + (with a slight abuse of notation, but for consistency with the code) is an adjacency + matrix representing a subgraph of any connections which go from objects in :math:`A` to + those in :math:`B` (and defined likewise for :math:`(BA)`), and :math:`S` is a + similarity matrix indexing the similarity of each object in :math:`A` to each object + in :math:`B`. + + If ``partial_match`` is used, then the above will be maximized/minimized over the + set of permutations which respect this partial matching of the two networks. + + If ``maximize``, this function will attempt to maximize :math:`f(P)` (solve the graph + matching problem); otherwise, it will be minimized. + + References + ---------- + .. [1] J.T. Vogelstein, J.M. Conroy, V. Lyzinski, L.J. Podrazik, S.G. Kratzer, + E.T. Harley, D.E. Fishkind, R.J. Vogelstein, and C.E. Priebe, “Fast + approximate quadratic programming for graph matching,” PLOS one, vol. 10, + no. 4, p. e0121002, 2015. + + .. [2] B.D. Pedigo, M. Winding, C.E. Priebe, J.T. Vogelstein, "Bisected graph + matching improves automated pairing of bilaterally homologous neurons from + connectomes," bioRxiv 2022.05.19.492713 (2022) + + .. [3] D. Fishkind, S. Adali, H. Patsolic, L. Meng, D. Singh, V. Lyzinski, C. Priebe, + "Seeded graph matching," Pattern Recognit. 87 (2019) 203–215 + + .. [4] A. Saad-Eldin, B.D. Pedigo, C.E. Priebe, J.T. Vogelstein "Graph Matching via + Optimal Transport," arXiv 2111.05366 (2021) + + .. [5] K. Pantazis, D.L. Sussman, Y. Park, Z. Li, C.E. Priebe, V. Lyzinski, + "Multiplex graph matching matched filters," Applied Network Science (2022) + """ + + max_seed = np.iinfo(np.uint32).max + + if (rng is not None) and (not isinstance(rng, np.random.Generator)): + check_scalar(rng, "rng", (int, np.integer), min_val=0, max_val=max_seed) + # otherwise the input is None or a random Generator - these can be passed in to + # default_rng safely + + rng = np.random.default_rng(rng) + + seeds = rng.integers(max_seed, size=n_init) + + if n_init > 1: + parallel_verbose = verbose + solver_verbose: Int = 0 + else: + parallel_verbose = 0 + solver_verbose = verbose + + solver = _GraphMatchSolver( + A=A, + B=B, + AB=AB, + BA=BA, + S=S, + partial_match=partial_match, + init=init, + init_perturbation=init_perturbation, + verbose=solver_verbose, + shuffle_input=shuffle_input, + padding=padding, + maximize=maximize, + max_iter=max_iter, + tol=tol, + transport=transport, + transport_regularizer=transport_regularizer, + transport_tol=transport_tol, + transport_max_iter=transport_max_iter, + ) + + def run_single_graph_matching(seed: RngType) -> MatchResult: + solver.solve(seed) + matching = solver.matching_ + indices_A = matching[:, 0] + indices_B = matching[:, 1] + score = solver.score_ + misc: Dict[str, Any] = {} + misc["score"] = score + misc["n_iter"] = solver.n_iter_ + misc["convex_solution"] = solver.convex_solution_ + misc["converged"] = solver.converged_ + return MatchResult(indices_A, indices_B, score, [misc]) + + seeds = rng.integers(max_seed, size=n_init) + parallel = Parallel(n_jobs=n_jobs, verbose=parallel_verbose) + results = parallel(delayed(run_single_graph_matching)(seed) for seed in seeds) + + # get the indices for the best run + best_func = max if maximize else min + best_result = best_func(results, key=lambda x: x.score) + + # also collate various extra info about all of the runs + miscs = [x.misc[0] for x in results] + + return MatchResult( + best_result.indices_A, best_result.indices_B, best_result.score, miscs + ) diff --git a/graspologic/nominate/VNviaSGM.py b/graspologic/nominate/VNviaSGM.py index 6c7ce3b12..99aedc90f 100644 --- a/graspologic/nominate/VNviaSGM.py +++ b/graspologic/nominate/VNviaSGM.py @@ -7,7 +7,7 @@ from graspologic.types import Dict, List -from ..match import GraphMatch as GMP +from ..match import graph_match # Type aliases SeedsType = Union[np.ndarray, List[List[int]]] @@ -164,6 +164,15 @@ def fit( elif A.shape[0] != A.shape[1] or B.shape[0] != B.shape[1]: msg = '"A" and "B" must be square' raise ValueError(msg) + elif A.shape[0] > B.shape[0]: + # NOTE: the new graph_match function can absolutely handle the reverse case. + # However, it would require me to appropriately deal with the nodes of A + # which are not matched, and I dont have time to figure out what this class + # is doing right now. Further, I think with the old code using GraphMatch + # this would have raised a silent bug in this case, so I think this is + # at least an improvement. + msg = '"A" is larger than "B"; please reverse the ordering of these inputs.' + raise ValueError(msg) if not isinstance(voi, int): msg = '"voi" must be an integer' @@ -288,18 +297,17 @@ def fit( # explanation self.n_seeds_ = len(close_seeds) seeds_fin = np.arange(self.n_seeds_) + partial_match = np.column_stack((seeds_fin, seeds_fin)) # Call the SGM algorithm using user set parameters and generate a prob # vector for the voi. - sgm = GMP( - **self.graph_match_kws, - ) - prob_vector = np.zeros((max(SG_1.shape[0], SG_2.shape[0]) - self.n_seeds_)) for ii in range(self.n_init): - sgm.fit(SG_1, SG_2, seeds_A=seeds_fin, seeds_B=seeds_fin) - prob_vector[sgm.perm_inds_[self.n_seeds_] - self.n_seeds_] += 1.0 + _, perm_inds, _, _ = graph_match( + SG_1, SG_2, partial_match=partial_match, **self.graph_match_kws + ) + prob_vector[perm_inds[self.n_seeds_] - self.n_seeds_] += 1.0 prob_vector /= self.n_init diff --git a/graspologic/types.py b/graspologic/types.py index 1b92ba135..02df60e70 100644 --- a/graspologic/types.py +++ b/graspologic/types.py @@ -6,7 +6,7 @@ """ import sys -from typing import Union +from typing import Optional, Union import networkx as nx import numpy as np @@ -38,4 +38,14 @@ GraphRepresentation = Union[np.ndarray, sp.csr_matrix, nx.Graph] -__all__ = ["AdjacencyMatrix", "Dict", "List", "GraphRepresentation", "Set", "Tuple"] +RngType = Optional[Union[int, np.integer, np.random.Generator]] + +__all__ = [ + "AdjacencyMatrix", + "Dict", + "List", + "GraphRepresentation", + "RngType", + "Set", + "Tuple", +] diff --git a/setup.cfg b/setup.cfg index 938645e0f..4eec80700 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,6 +1,6 @@ [metadata] name = graspologic -version = 1.0.1 +version = 2.0.0 description = A set of python modules for graph statistics long_description = file: README.md diff --git a/tests/test_match.py b/tests/test_match.py index d0208d087..9488b745b 100644 --- a/tests/test_match.py +++ b/tests/test_match.py @@ -5,202 +5,211 @@ import unittest import numpy as np +from beartype.roar import BeartypeCallHintParamViolation -from graspologic.align import SignFlips -from graspologic.embed import AdjacencySpectralEmbed -from graspologic.match import GraphMatch as GMP -from graspologic.match.qap import _quadratic_assignment_faq, quadratic_assignment -from graspologic.simulations import er_np, sbm_corr +from graspologic.match import graph_match +from graspologic.simulations import er_corr, er_np np.random.seed(1) - -class TestGMP(unittest.TestCase): - @classmethod - def setUpClass(cls) -> None: - cls.barycenter = GMP(gmp=False) - cls.rand = GMP(n_init=100, init="rand", gmp=False) - cls.barygm = GMP(gmp=True) - +# adjacency matrices from QAPLIB instance chr12c +# QAP problem is minimized with objective function value 11156 +A = [ + [0, 90, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0], + [90, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0], + [10, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0], + [0, 23, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0], + [0, 0, 43, 0, 0, 0, 26, 0, 0, 0, 0, 0], + [0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 0], + [0, 0, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0], + [0, 0, 0, 0, 0, 16, 0, 0, 0, 96, 0, 0], + [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 29, 0], + [0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 37], + [0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0], + [0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0], +] +B = [ + [0, 36, 54, 26, 59, 72, 9, 34, 79, 17, 46, 95], + [36, 0, 73, 35, 90, 58, 30, 78, 35, 44, 79, 36], + [54, 73, 0, 21, 10, 97, 58, 66, 69, 61, 54, 63], + [26, 35, 21, 0, 93, 12, 46, 40, 37, 48, 68, 85], + [59, 90, 10, 93, 0, 64, 5, 29, 76, 16, 5, 76], + [72, 58, 97, 12, 64, 0, 96, 55, 38, 54, 0, 34], + [9, 30, 58, 46, 5, 96, 0, 83, 35, 11, 56, 37], + [34, 78, 66, 40, 29, 55, 83, 0, 44, 12, 15, 80], + [79, 35, 69, 37, 76, 38, 35, 44, 0, 64, 39, 33], + [17, 44, 61, 48, 16, 54, 11, 12, 64, 0, 70, 86], + [46, 79, 54, 68, 5, 0, 56, 15, 39, 70, 0, 18], + [95, 36, 63, 85, 76, 34, 37, 80, 33, 86, 18, 0], +] +A, B = np.array(A), np.array(B) + + +class TestGraphMatch(unittest.TestCase): def test_SGM_inputs(self): - with self.assertRaises(TypeError): - GMP(n_init=-1.5) - with self.assertRaises(ValueError): - GMP(init="random") - with self.assertRaises(TypeError): - GMP(max_iter=-1.5) - with self.assertRaises(TypeError): - GMP(shuffle_input="hey") - with self.assertRaises(TypeError): - GMP(eps=-1) - with self.assertRaises(TypeError): - GMP(gmp="hey") - with self.assertRaises(TypeError): - GMP(padding=2) - with self.assertRaises(ValueError): - GMP(padding="hey") + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, n_init=-1.5) + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, init="not correct string") + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, max_iter=-1.5) + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, shuffle_input="hey") with self.assertRaises(ValueError): - GMP().fit( - np.random.random((3, 4)), - np.random.random((3, 4)), - np.arange(2), - np.arange(2), - ) + graph_match(A, B, tol=-1) + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, maximize="hey") + with self.assertRaises(BeartypeCallHintParamViolation): + graph_match(A, B, padding="hey") with self.assertRaises(ValueError): - GMP().fit( + # A, B need to be square + graph_match( np.random.random((3, 4)), np.random.random((3, 4)), - np.arange(2), - np.arange(2), ) with self.assertRaises(ValueError): - GMP().fit(np.identity(3), np.identity(3), np.identity(3), np.arange(2)) - with self.assertRaises(ValueError): - GMP().fit(np.identity(3), np.identity(3), np.arange(1), np.arange(2)) - with self.assertRaises(ValueError): - GMP().fit(np.identity(3), np.identity(3), np.arange(5), np.arange(5)) - with self.assertRaises(ValueError): - GMP().fit( - np.identity(3), np.identity(3), -1 * np.arange(2), -1 * np.arange(2) - ) - with self.assertRaises(ValueError): - GMP().fit( + # BA, AB need to match A, B on certain dims + graph_match( np.random.random((4, 4)), np.random.random((4, 4)), - np.arange(2), - np.arange(2), - np.random.random((3, 4)), + np.random.random((3, 3)), + np.random.random((3, 3)), ) with self.assertRaises(ValueError): - GMP().fit( - np.random.random((4, 4)), - np.random.random((4, 4)), - np.arange(2), - np.arange(2), - np.random.random((3, 3)), + # can't have more seeds than nodes + graph_match( + np.identity(3), np.identity(3), partial_match=np.full((5, 2), 1) ) with self.assertRaises(ValueError): - GMP().fit( - np.random.random((3, 3)), - np.random.random((4, 4)), - np.arange(2), - np.arange(2), - np.random.random((4, 4)), + # can't have seeds that are smaller than 0 + graph_match( + np.identity(3), np.identity(3), partial_match=np.full((2, 2), -1) ) - - def _get_AB(self): - # adjacency matrices from QAPLIB instance chr12c - # QAP problem is minimized with objective function value 11156 - - A = [ - [0, 90, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0], - [90, 0, 0, 23, 0, 0, 0, 0, 0, 0, 0, 0], - [10, 0, 0, 0, 43, 0, 0, 0, 0, 0, 0, 0], - [0, 23, 0, 0, 0, 88, 0, 0, 0, 0, 0, 0], - [0, 0, 43, 0, 0, 0, 26, 0, 0, 0, 0, 0], - [0, 0, 0, 88, 0, 0, 0, 16, 0, 0, 0, 0], - [0, 0, 0, 0, 26, 0, 0, 0, 1, 0, 0, 0], - [0, 0, 0, 0, 0, 16, 0, 0, 0, 96, 0, 0], - [0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 29, 0], - [0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 37], - [0, 0, 0, 0, 0, 0, 0, 0, 29, 0, 0, 0], - [0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 0], - ] - B = [ - [0, 36, 54, 26, 59, 72, 9, 34, 79, 17, 46, 95], - [36, 0, 73, 35, 90, 58, 30, 78, 35, 44, 79, 36], - [54, 73, 0, 21, 10, 97, 58, 66, 69, 61, 54, 63], - [26, 35, 21, 0, 93, 12, 46, 40, 37, 48, 68, 85], - [59, 90, 10, 93, 0, 64, 5, 29, 76, 16, 5, 76], - [72, 58, 97, 12, 64, 0, 96, 55, 38, 54, 0, 34], - [9, 30, 58, 46, 5, 96, 0, 83, 35, 11, 56, 37], - [34, 78, 66, 40, 29, 55, 83, 0, 44, 12, 15, 80], - [79, 35, 69, 37, 76, 38, 35, 44, 0, 64, 39, 33], - [17, 44, 61, 48, 16, 54, 11, 12, 64, 0, 70, 86], - [46, 79, 54, 68, 5, 0, 56, 15, 39, 70, 0, 18], - [95, 36, 63, 85, 76, 34, 37, 80, 33, 86, 18, 0], - ] - A, B = np.array(A), np.array(B) - return A, B + with self.assertRaises(ValueError): + # size of similarity must fit with A, B + graph_match(np.identity(3), np.identity(3), S=np.identity(4)) def test_barycenter_SGM(self): # minimize such that we achieve some number close to the optimum, # though strictly greater than or equal # results vary due to random shuffle within GraphMatch - A, B = self._get_AB() n = A.shape[0] pi = np.array([7, 5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - [1] * n - W1 = [4, 8, 10] - W2 = [pi[z] for z in W1] - chr12c = self.barycenter.fit(A, B, W1, W2) - score = chr12c.score_ + seeds1 = [4, 8, 10] + seeds2 = [pi[z] for z in seeds1] + partial_match = np.column_stack((seeds1, seeds2)) + _, _, score, _ = graph_match(A, B, partial_match=partial_match, maximize=False) self.assertTrue(11156 <= score < 21000) - W1 = np.sort(random.sample(list(range(n)), n - 1)) - W2 = [pi[z] for z in W1] - chr12c = self.barycenter.fit(A, B, W1, W2) - score = chr12c.score_ + seeds1 = np.sort(random.sample(list(range(n)), n - 1)) + seeds2 = [pi[z] for z in seeds1] + partial_match = np.column_stack((seeds1, seeds2)) + _, _, score, _ = graph_match(A, B, partial_match=partial_match, maximize=False) self.assertEqual(11156, score) - W1 = np.array(range(n)) - W2 = pi - chr12c = self.barycenter.fit(A, B, W1, W2) - score = chr12c.score_ - np.testing.assert_array_equal(chr12c.perm_inds_, pi) + seeds1 = np.array(range(n)) + seeds2 = pi + partial_match = np.column_stack((seeds1, seeds2)) + _, indices_B, score, _ = graph_match( + A, B, partial_match=partial_match, maximize=False + ) + np.testing.assert_array_equal(indices_B, pi) self.assertTrue(11156, score) - W1 = np.random.permutation(n) - W2 = [pi[z] for z in W1] - chr12c = self.barycenter.fit(A, B, W1, W2) - score = chr12c.score_ - np.testing.assert_array_equal(chr12c.perm_inds_, pi) + seeds1 = np.random.permutation(n) + seeds2 = [pi[z] for z in seeds1] + partial_match = np.column_stack((seeds1, seeds2)) + _, indices_B, score, _ = graph_match( + A, B, partial_match=partial_match, maximize=False + ) + np.testing.assert_array_equal(indices_B, pi) self.assertTrue(11156, score) + def test_barycenter_SGM_seed_lists(self): + # minimize such that we achieve some number close to the optimum, + # though strictly greater than or equal + # results vary due to random shuffle within GraphMatch + + n = A.shape[0] + pi = np.array([7, 5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - [1] * n + seeds1 = [4, 8, 10] + seeds2 = [pi[z] for z in seeds1] + _, _, score, _ = graph_match( + A, B, partial_match=(seeds1, seeds2), maximize=False + ) + self.assertTrue(11156 <= score < 21000) + def test_rand_SGM(self): - A, B = self._get_AB() - chr12c = self.rand.fit(A, B) - score = chr12c.score_ + _, _, score, _ = graph_match( + A, B, n_init=50, maximize=False, init_perturbation=0.5, rng=888 + ) self.assertTrue(11156 <= score < 13500) n = A.shape[0] pi = np.array([7, 5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - [1] * n - W1 = [4, 8, 10] - W2 = [pi[z] for z in W1] - chr12c = self.rand.fit(A, B, W1, W2) - score = chr12c.score_ + seeds1 = [4, 8, 10] + seeds2 = [pi[z] for z in seeds1] + partial_match = np.column_stack((seeds1, seeds2)) + _, _, score, _ = graph_match( + A, + B, + partial_match=partial_match, + maximize=False, + init_perturbation=0.5, + n_init=50, + rng=888, + ) self.assertTrue(11156 <= score < 12500) def test_parallel(self): - A, B = self._get_AB() - gmp = GMP(gmp=False, n_init=2, n_jobs=2) - gmp.fit(A, B) - score = gmp.score_ + _, _, score, _ = graph_match( + A, + B, + maximize=False, + n_init=2, + n_jobs=2, + rng=888, + ) self.assertTrue(11156 <= score < 13500) def test_padding(self): + np.random.seed(888) n = 50 p = 0.4 - G1 = er_np(n=n, p=p) - G2 = G1[:-2, :-2] # remove two nodes - gmp_adopted = GMP(padding="adopted") - res = gmp_adopted.fit(G1, G2) + A = er_np(n=n, p=p) + B = A[:-2, :-2] # remove two nodes + + indices_A, indices_B, _, _ = graph_match(A, B, rng=888, padding="adopted") - self.assertTrue(0.95 <= (sum(res.perm_inds_ == np.arange(n)) / n)) + self.assertTrue(np.array_equal(indices_A, np.arange(n - 2))) + self.assertTrue(np.array_equal(indices_B, np.arange(n - 2))) + + def test_reproducibility(self): + np.random.seed(888) + n = 10 + p = 0.2 + A = er_np(n=n, p=p) + B = A.copy() + permutation = np.random.permutation(n) + B = B[permutation][:, permutation] + _, indices_B, _, _ = graph_match(A, B, rng=999) + for i in range(10): + # this fails w/o rng set here; i.e. there is variance + _, indices_B_repeat, _, _ = graph_match(A, B, rng=999) + self.assertTrue(np.array_equal(indices_B, indices_B_repeat)) def test_custom_init(self): - A, B = self._get_AB() n = len(A) pi = np.array([7, 5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - [1] * n custom_init = np.eye(n) custom_init = custom_init[pi] - gm = GMP(n_init=1, init=custom_init, max_iter=30, shuffle_input=True, gmp=False) - gm.fit(A, B) + _, indices_B, score, _ = graph_match(A, B, init=custom_init, maximize=False) - self.assertTrue((gm.perm_inds_ == pi).all()) - self.assertEqual(gm.score_, 11156) + self.assertTrue((indices_B == pi).all()) + self.assertEqual(score, 11156) # we had thought about doing the test # `assert gm.n_iter_ == 1` # but note that GM doesn't necessarily converge in 1 iteration here @@ -209,8 +218,18 @@ def test_custom_init(self): # but we do indeed recover the correct permutation after a small number of # iterations + def test_wrong_custom_init(self): + n = len(A) + + custom_init = np.full(n, 1 / n) + with self.assertRaises(ValueError): + _, indices_B, score, _ = graph_match(A, B, init=custom_init, maximize=False) + + custom_init = np.full((n, n), 1) + with self.assertRaises(ValueError): + _, indices_B, score, _ = graph_match(A, B, init=custom_init, maximize=False) + def test_custom_init_seeds(self): - A, B = self._get_AB() n = len(A) pi_original = np.array([7, 5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - 1 pi = np.array([5, 1, 3, 10, 4, 8, 6, 9, 11, 2, 12]) - 1 @@ -220,66 +239,51 @@ def test_custom_init_seeds(self): # use seed 0 in A to 7 in B seeds_A = [0] seeds_B = [6] + seeds = np.column_stack((seeds_A, seeds_B)) custom_init = np.eye(n - 1) custom_init = custom_init[pi] - gm = GMP(n_init=1, init=custom_init, max_iter=30, shuffle_input=True, gmp=False) - gm.fit(A, B, seeds_A=seeds_A, seeds_B=seeds_B) - - self.assertTrue((gm.perm_inds_ == pi_original).all()) - self.assertEqual(gm.score_, 11156) - - def test_sim(self): - n = 150 - rho = 0.9 - n_per_block = int(n / 3) - n_blocks = 3 - block_members = np.array(n_blocks * [n_per_block]) - block_probs = np.array( - [[0.2, 0.01, 0.01], [0.01, 0.1, 0.01], [0.01, 0.01, 0.2]] + # gm = GMP(n_init=1, init=custom_init, max_iter=30, shuffle_input=True, gmp=False) + # gm.fit(A, B, seeds_A=seeds_A, seeds_B=seeds_B) + _, indices_B, score, _ = graph_match( + A, + B, + partial_match=seeds, + n_init=1, + init=custom_init, + max_iter=30, + maximize=False, ) - directed = False - loops = False - A1, A2 = sbm_corr( - block_members, block_probs, rho, directed=directed, loops=loops - ) - ase = AdjacencySpectralEmbed(n_components=3, algorithm="truncated") - x1 = ase.fit_transform(A1) - x2 = ase.fit_transform(A2) - xh1 = SignFlips().fit_transform(x1, x2) - S = xh1 @ x2.T - res = self.barygm.fit(A1, A2, S=S) - - self.assertTrue(0.7 <= (sum(res.perm_inds_ == np.arange(n)) / n)) - - A1 = A1[:-1, :-1] - xh1 = xh1[:-1, :] - S = xh1 @ x2.T - - res = self.barygm.fit(A1, A2, S=S) - - self.assertTrue(0.6 <= (sum(res.perm_inds_ == np.arange(n)) / n)) - -class TestQuadraticAssignment(unittest.TestCase): - def test_quadratic_assignment_does_not_accept_method_2opt(self): - arr = np.ones((2, 2)) - with self.assertRaises(ValueError): - quadratic_assignment(arr, arr, method="2opt") - - def test_quadratic_assignment_faq_requires_non_empty_S_argument(self): - arr = np.ones((2, 2)) - with self.assertRaises(ValueError): - _quadratic_assignment_faq(arr, arr) - - def test_quadratic_assignment_faq_requires_square_S_argument(self): - arr = np.ones((2, 2)) - with self.assertRaises(ValueError): - _quadratic_assignment_faq(arr, arr, S=np.ones((2, 2, 2))) - - def test_quadratic_assignment_faq_requires_S_argument_with_same_dimensions_as_A_and_B( - self, - ): - arr = np.ones((2, 2)) - with self.assertRaises(ValueError): - _quadratic_assignment_faq(arr, arr, S=np.ones((3, 3))) + self.assertTrue((indices_B == pi_original).all()) + self.assertEqual(score, 11156) + + def test_similarity_term(self): + rng = np.random.default_rng(888) + np.random.seed(888) + n = 10 + n_seeds = 1 + lamb = 0.8 # is diagnostic in the sense that w/ lamb=0, this test fails + n_sims = 10 + mean_match_ratio = 0.0 + for _ in range(n_sims): + A, B = er_corr(n, 0.3, 0.8, directed=True) + perm = rng.permutation(n) + undo_perm = np.argsort(perm) + B = B[perm][:, perm] + + seeds_A = np.random.choice(n, replace=False, size=n_seeds) + seeds_B = np.argsort(perm)[seeds_A] + partial_match = np.stack((seeds_A, seeds_B)).T + non_seeds_A = np.setdiff1d(np.arange(n), seeds_A) + + S = lamb * np.eye(B.shape[0]) + S = np.random.uniform(0, 1, (n, n)) + S + S = S[:, perm] + + _, indices_B, _, _ = graph_match(A, B, S=S, partial_match=partial_match) + mean_match_ratio += ( + indices_B[non_seeds_A] == undo_perm[non_seeds_A] + ).mean() / n_sims + + self.assertTrue(mean_match_ratio >= 0.999) From d5ef3b14a3c8f96bad42df792fab3f7c5a63d2f9 Mon Sep 17 00:00:00 2001 From: Benjamin Pedigo Date: Thu, 1 Sep 2022 15:17:46 -0700 Subject: [PATCH 32/32] Added release notes (#982) --- docs/reference/release.rst | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/docs/reference/release.rst b/docs/reference/release.rst index 2a95947b1..158c446e3 100644 --- a/docs/reference/release.rst +++ b/docs/reference/release.rst @@ -3,6 +3,43 @@ Release Log =========== +graspologic 2.0.0 +----------------- +- Refactored graph matching code and added many new features + `#960 ` +- Added elbow marker to screeplot in plot module + `#979 ` +- Fixed mug2vec behavior for directed graphs + `#968 ` +- Fixed typo in aligning tutorial + `#974 ` +- Added sex labels to mice dataset + `#967 ` +- Made improvements to contributing guidelines + `#973 ` +- Corrected notation in documentation of to_laplacians + `#969 ` +- Fixed isolated nodes handling in node2vec + `#953 ` +- Fixed repeated numba compilation in EdgeSwapper + `#965 ` +- Fixed intersphinx bug + `#963 ` +- Removed default axis labels in networkplot + `#954 ` +- Fixed reproducibility in EdgeSwapper and added to docs + `#945 ` +- Added Degree Preserving Edge Swaps + `#935 ` +- Fixed mypy issue + `#943 ` +- Fixed loops bug in SBM and DCSBM model fitting + `#930 ` +- Added error message in Leiden when given a multigraph was incorrect + `#926 ` +- Fixed typos in ER and SBM models + `#920 ` + graspologic 1.0.0 ----------------- - Removed Python 3.6 support