Skip to content
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

Enhance traversal docs #1375

Merged
merged 15 commits into from
Feb 9, 2025
Merged

Conversation

barakatzir
Copy link
Contributor

This PR fixes #1361.
It add some elaboration to the traversal BFS and DFS functions, mainly with a more concrete pseudo-code.
I also fixed small doc errors in betweenness function's docstrings.
In the issue I also suggested doing a face-lift to the dijkstra_search. I can add this in to this PR in the style of the other docstrings changes I'm proposing If you'd like.

  • [v] I ran the nox -e docs and cargo doc to see that the result is good.
  • [v] I have read the CONTRIBUTING document.

@CLAassistant
Copy link

CLAassistant commented Jan 29, 2025

CLA assistant check
All committers have signed the CLA.

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

@IvanIsCoding
Copy link
Collaborator

Thanks for submitting this! I will try to review it when I can, but again this is a welcome contribution.

@coveralls
Copy link

coveralls commented Jan 30, 2025

Pull Request Test Coverage Report for Build 13229065253

Details

  • 0 of 0 changed or added relevant lines in 0 files are covered.
  • No unchanged relevant lines lost coverage.
  • Overall coverage remained the same at 95.819%

Totals Coverage Status
Change from base Build 13105099943: 0.0%
Covered Lines: 18381
Relevant Lines: 19183

💛 - Coveralls

Copy link
Collaborator

@IvanIsCoding IvanIsCoding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good to me with the caveat that I think for Python docstrings we should focus on the methods that highlight BFS/DFS only. I'd drop the iterator details

end while

If an exception is raised inside the callback function, the graph traversal
def BFSIterator(G, I, F):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For Python I think it makes more sense to talk about BFS than BFSIterator. I'd rewrite it to keep the old signature BFS(G, s)

@@ -1565,38 +1633,68 @@ def tree_edge(self, edge):

@_rustworkx_dispatch
def dfs_search(graph, source, visitor):
"""Depth-first traversal of a directed/undirected graph.
"""Iterative depth-first traversal of a directed/undirected graph.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could have a recursive DFS with something like https://crates.io/crates/recursive these days, so I am not opposed to saying this.

With that in mind, DFS order is implementation dependent and even the order we iterate edges is not promised to be stable so it is what it is.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I copied the Iterative prefix from the rustworkx-core since it made sense to me to differentiate this method from the DFS algorithm which has a single source vertex.
I didn't know about DFS (the CLRS ref you sent me was helpful!) but my friends who do know (both the algo and of CLRS) were confused a bit by how several source vertices are incorporated.
If the implementation detail of how several source vertices are incorporated into DFS is not guaranteed, the docs should probably mention that as well.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I will double check Georgios’ implementation in the source code and check.

I myself forgot the specifics, either the user passes it as an input or we pick an arbitrary node I think

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought that the source vertices are added to the stack in reverse order. I know that it is not implemented like that, but it is close to it.
That way when you pop from the stack you start with the first source node as the user specified, etc...
This behavior is similar in the BFS (just with a stack instead of a queue).
This is one the behaviors that I wanted to clarify in the docs.
How about I rewrite the pseudocode like that? That way its clear how the many source nodes relate to the single source node in the DFS algo.

PS if the user does not specify the source the docs already specify the behavior:

If this is not specified then a source will be chosen arbitrarily and repeated until all components of the graph are searched.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you rewrite the pseudo code to be similar to the implementation, users will like it. Go for it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll try to get to it tomorrow.

color[u] := BLACK finish vertex u

If an exception is raised inside the callback function, the graph traversal
def DFSIterator(G, I, F):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment from BFS

color[s] = GRAY
time += 1
F.Discover(s, time)
Q = [s] # LIFO vertex queue
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can call it a stack

@barakatzir
Copy link
Contributor Author

barakatzir commented Feb 9, 2025

I reverted to the pseudo-code styling of the algorithms. I couldn't simplify the algorithms while staying similar to the implementation, so I thought going with pseudo-code conveys better that this does not follow the implementation.

I also redid the Dijkstra search as it was similarly unclear (to me).
Also, added an example - a python version of the one in rustworkx-core.

I fixed a minor type annotation issue in the universal dijkstra_search.

I checked that that cargo doc and nox -edocs give good results.

Copy link
Collaborator

@IvanIsCoding IvanIsCoding left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the documentation improvements!

I will merge #1380 with this and then lets check the docs. I revised but there are multiple repetitions of the same docstring (unfortunately, that is how the docs work). So let's see the end result in the website and judge. I have a feeling it will be better

@IvanIsCoding IvanIsCoding added this pull request to the merge queue Feb 9, 2025
Merged via the queue into Qiskit:main with commit df38b0a Feb 9, 2025
31 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

python BFS and DFS search documentation improvements
4 participants