-
-
Notifications
You must be signed in to change notification settings - Fork 480
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add parameter sort_neighbors
to method init_short_digraph
#37662
Add parameter sort_neighbors
to method init_short_digraph
#37662
Conversation
sort_neighbors
to init_short_digraph
in src/sage/graphs/base/static_sparse_graph.pxd|pyx
sort_neighbors
to method init_short_digraph
Documentation preview for this PR (built with commit 052c58b; changes) is ready! 🎉 |
I will continue here the discussion started in issue #37642 I investigated more and I think I found two more problems.
cdef list vertices = vertex_list if vertex_list is not None else G.vertices(sort=True) It implies that if
So maybe, we could change
for u, v in G.edge_iterator(labels=False, sort_vertices=False):
... I claim that the complexity is O(n^2) when the backend is a dense data structure and O(m*log(m)) when the backend is a sparse data structure.
|
For the first point: parameter The second point is more tricky and you are right that the time complexity depends on the backend. |
For the dense backend, I see no way around it. For the sparse backend, I think it is possible to list the edges of a vertex in linear time with the current data structure (but not by using |
Indeed, we can certainly gain a lot this way.
It is better to make a dedicated PR.
You are right that for Consequently, priority should be given to improving the way the backends iterate over the neighbors / incident edges. We may also have a better method for listing all edges. In parallel, we can change the The changes proposed in this PR are interesting only for methods iterating multiple times on the neighbors of some vertices and exploiting the fact that vertices are relabeled in |
With the patch below to remove the sorting of vertices, I think this PR can be merged. diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx
index 35f3de67c9..aa05daa8bf 100644
--- a/src/sage/graphs/base/static_sparse_graph.pyx
+++ b/src/sage/graphs/base/static_sparse_graph.pyx
@@ -217,10 +217,7 @@ cdef int init_short_digraph(short_digraph g, G, edge_labelled=False, vertex_list
If ``vertex_list`` is given, it will be used to map vertices of
the graph to consecutive integers. Otherwise, the result of
- ``G.vertices(sort=True)`` will be used instead. Because this only
- works if the vertices can be sorted, using ``vertex_list`` is
- useful when working with possibly non-sortable objects in Python
- 3.
+ ``list(G)`` will be used instead.
"""
g.edge_labels = NULL
@@ -242,7 +239,7 @@ cdef int init_short_digraph(short_digraph g, G, edge_labelled=False, vertex_list
raise ValueError("The source graph must be either a DiGraph or a Graph object !")
cdef int i, j, v_id
- cdef list vertices = vertex_list if vertex_list is not None else G.vertices(sort=True)
+ cdef list vertices = vertex_list if vertex_list is not None else list(G)
cdef dict v_to_id = {v: i for i, v in enumerate(vertices)}
cdef list neighbor_label
cdef list edge_labels
|
I think I did all required changes. |
There is a failing doctest reported by the CI but I'm unable to reproduce it (with or without this PR) on my macOS laptop. Not sure of the origin of this failing doctest.
|
Update/rebase for a CI run? |
I have rebased the branch. I'm waiting for some feedback from @cyrilbouvier to know if this is ok or if he has better proposals. |
Except my review that has not been addressed (changing O(m + n\log{m}) by O(n + m\log{m}) in a comment, I have no more remarks. FYI, I am currently writing a PR to add a function that list the neighbors of a vertex in linear time for the sparse backend (one use case would be init_short_digraph). |
Should be ok now. |
LGTM |
Thank you for the review. I'm setting this PR to positive review. |
The CI reports some doctests errors that I cannot reproduce on my macOS laptop and that are not marked as |
…t_digraph` Fixes sagemath#37642. We add parameter `sort_edges` to method `init_short_digraph` of the `short_digraph` data structure defined in `src/sage/graphs/base/static_sparse_graph.pxd|pyx`. - When set to `True` (default), for each vertex, the list of neighbors is sorted by increasing vertex labels. This enables to search for a vertex in this list using binary search, and so in time `O(log(n))`, but the overall running time of method `init_short_digraph` is in `O(m + n*log(m))`. - When set to `False`, neighbors are not sorted. The running time of method `init_short_digraph` is reduced to `O(n + m)`, but the running time for searching in the list of neighbors increases to `O(m)`. So this new parameter is particularly useful for linear time algorithms such as `lex_BFS`. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [ ] I have created tests covering the changes. - [x] I have updated the documentation accordingly. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#37662 Reported by: David Coudert Reviewer(s):
…rs but without the extra log complexity <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> This PR improve the `init_short_digraph` function that is used to initialize `StaticSparseCGraph` (used for immutable `Graph` and `DiGraph`). Before, a boolean parameter `sort_neighbors` was used to specify if we wanted to sort the neighbors or not. It implied an extra `log` in the complexity (as `qsort` was called). With this PR, the neighbors are always sorted at no extra cost. It is done by appending to the neighbors list the vertices in the correct order so the call to `qsort` is not needed anymore. This PR partly reverts sagemath#38198 and mostly reverts sagemath#37662 ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#38427 Reported by: cyrilbouvier Reviewer(s): cyrilbouvier, David Coudert
…rs but without the extra log complexity (2nd try) <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> This PR is based on the closed PR sagemath#38427 (by myself) that was breaking too much doctests. This PR improve the `init_short_digraph` function that is used to initialize `StaticSparseCGraph` (used for immutable `Graph` and `DiGraph`). Before, a boolean parameter `sort_neighbors` was used to specify if we wanted to sort the neighbors or not. It implied an extra `log` in the complexity (as `qsort` was called). With this PR, the neighbors are always sorted at no extra cost. It is done by appending to the neighbors list the vertices in the correct order so the call to `qsort` is not needed anymore. This PR partly reverts sagemath#38198 and mostly reverts sagemath#37662 Contrary to PR sagemath#38427, I did not include the patch that remove the sorting of vertices when StaticSparseGraph are initialized because it was breaking too many doctests. Instead I added a option to disabled said sorting and use it in my doctests to check that the new code works. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#38664 Reported by: cyrilbouvier Reviewer(s): David Coudert
…rs but without the extra log complexity (2nd try) <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> This PR is based on the closed PR sagemath#38427 (by myself) that was breaking too much doctests. This PR improve the `init_short_digraph` function that is used to initialize `StaticSparseCGraph` (used for immutable `Graph` and `DiGraph`). Before, a boolean parameter `sort_neighbors` was used to specify if we wanted to sort the neighbors or not. It implied an extra `log` in the complexity (as `qsort` was called). With this PR, the neighbors are always sorted at no extra cost. It is done by appending to the neighbors list the vertices in the correct order so the call to `qsort` is not needed anymore. This PR partly reverts sagemath#38198 and mostly reverts sagemath#37662 Contrary to PR sagemath#38427, I did not include the patch that remove the sorting of vertices when StaticSparseGraph are initialized because it was breaking too many doctests. Instead I added a option to disabled said sorting and use it in my doctests to check that the new code works. ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [ ] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#38664 Reported by: cyrilbouvier Reviewer(s): David Coudert
Fixes #37642.
We add parameter
sort_edges
to methodinit_short_digraph
of theshort_digraph
data structure defined insrc/sage/graphs/base/static_sparse_graph.pxd|pyx
.True
(default), for each vertex, the list of neighbors is sorted by increasing vertex labels. This enables to search for a vertex in this list using binary search, and so in timeO(log(n))
, but the overall running time of methodinit_short_digraph
is inO(m + n*log(m))
.False
, neighbors are not sorted. The running time of methodinit_short_digraph
is reduced toO(n + m)
, but the running time for searching in the list of neighbors increases toO(m)
.So this new parameter is particularly useful for linear time algorithms such as
lex_BFS
.📝 Checklist
⌛ Dependencies