Skip to content

New algorithm all_simple_paths_from#650

Open
bluss wants to merge 5 commits intomasterfrom
all-non-repeating-paths
Open

New algorithm all_simple_paths_from#650
bluss wants to merge 5 commits intomasterfrom
all-non-repeating-paths

Conversation

@bluss
Copy link
Member

@bluss bluss commented Jun 30, 2024

Breadth first search for all paths from a given starting point to all reachable nodes.

Paths are sequences of edge ids for this implementation.
This implementation is intentionally written using the visit traits so that it is compatible with multiple graph implementations, including graphs wrapped in NodeFiltered which enables running the algorithm on an induced subgraph.

This comes from this discussion: astral-sh/uv#4645

The graph in the test looks like this.

@bluss
Copy link
Member Author

bluss commented Jun 30, 2024

This is a WIP - does it do the right thing, does the API have the right shape, and so on.

Breadth first search for all paths from a given starting point to all
reachable nodes.

Paths are sequences of edge ids for this implementation.
@bluss bluss force-pushed the all-non-repeating-paths branch from 6bfabd8 to 03082ed Compare June 30, 2024 16:40
@bluss
Copy link
Member Author

bluss commented Jun 30, 2024

@Peiffap
Copy link

Peiffap commented Jun 30, 2024

This is very neat! I'm definitely in favor of calling this all_trails_from; perhaps another function all_trails_from_to (I'm not familiar with petgraph naming conventions) makes sense too if we're limiting the trails in an SCC to those starting in a node with incident edges from outside the SCC and ending in a node with outgoing edges to outside the SCC? I believe it would be useful for uv, but perhaps it's too far out of scope for petgraph to host that.

Copy link

@Peiffap Peiffap left a comment

Choose a reason for hiding this comment

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

A minor comment/question; I'm not familiar enough with Rust to quickly see what this is doing and I'm definitely not familiar enough with petgraph to know whether this fits. Also adding here (for visibility) that I'm +1 on using trail nomenclature instead of non-repeating path.

@bluss
Copy link
Member Author

bluss commented Jul 1, 2024

One question I had about this algorithm - not related to uv - if we start at 0, aren't both A, D and A, D, E, F, G valid trails from 0 to 3? The current implementation only produces the first trail. The second is disallowed because it starts with the same sequence as the first.

(I think this implementation is useful, but not sure what's correct w.r.t finding all trails.)

@Peiffap
Copy link

Peiffap commented Jul 1, 2024

I would say not allowed: 3 is a duplicate node if you allow that trail.

I got confused about paths vs. trails. I think you should actually allow the second trail too, since it's purely about the edges being traversed.

@DeliciousHair
Copy link

@bluss I noticed this PR the other day and thought it might be worth mentioning that a very similar thing was done in a recent student project here.

Your approach is less rough to be sure, but I'm putting this out there on account of the fact that using:

pub fn all_non_repeating_paths_from<
    G: IntoEdges + GraphProp<EdgeType = Directed> + GraphProp<NodeId = N> + GraphProp<EdgeId = E>,
    N: Eq + Copy + Clone,
    E: Eq + Copy + Clone,
>(
    graph: G,
    starting_node: G::NodeId,
) -> Vec<(G::NodeId, Vec<Path<G::EdgeId>>)> { ... }

gets to avoid using HashMap, if you're into that sort of thing of course! I have no idea how much of a no-std mentality one may be going for, and in fact what got me thinking about this + noticing this PR at all is that I have been thinking how to do the same thing lazily. I'm nowhere with that thinking just yet though.

@bluss
Copy link
Member Author

bluss commented Jul 14, 2024

@DeliciousHair I think that suggestion changes the algorithmic complexity of the implementation (not that I've analyzed fully), there needs to be some replacement of the O(1) hashmap lookup (could use compact space of integer indexes, but that's another constraint on the graph interface required - doesn't work well with the induced subgraph usecase of NodeFiltered?)

Also a tip, you don't need to have type parameters for N and E, they are available as G::NodeId and G::EdgeId (as seen in the PR).

@bluss
Copy link
Member Author

bluss commented Jul 14, 2024

@Peiffap I saw your edit now. I think we say the same thing now, the current algorithm finds only one path from 0 to 1 in this graph:

simple

  • The algorithm finds only the path A
  • All trails would find both A and A, B as trails from 0 to 1?

I think the current algorithm because of this is an "all simple paths" algorithm, and that's fine for me. (Is there something we're missing?)

@bluss bluss force-pushed the all-non-repeating-paths branch from 3288632 to 267253b Compare July 14, 2024 21:59
@Peiffap
Copy link

Peiffap commented Jul 15, 2024

How does this differ from the existing all_simple_paths() function? Is it just about directed vs undirected graphs?

Note that for the uv use-case this originally spawned from, I don't think trails that aren't paths are particularly interesting - they just add additional markers, if I understand correctly.

@bluss bluss changed the title New algorithm all_non_repeating_paths_from New algorithm all_simple_paths_from Jul 16, 2024
@bluss bluss marked this pull request as ready for review July 16, 2024 11:02
@bluss bluss force-pushed the all-non-repeating-paths branch from e401df9 to 7e76d10 Compare July 16, 2024 11:03
@bluss bluss force-pushed the all-non-repeating-paths branch from 7e76d10 to 9b55d77 Compare July 16, 2024 11:58
@bluss
Copy link
Member Author

bluss commented Jul 16, 2024

The existing all_simple_paths should also use directed graphs I think, not very familiar with it. It produces all paths between two particular vertices and the new function, now named all_simple_paths_from produces all paths from one particular vertex to all reachable from there.

@bluss
Copy link
Member Author

bluss commented Aug 8, 2024

User ms on the ndarray zulip endorsed the function as "it's very useful and solid" 🙂, so it's gotten one review

@DeliciousHair
Copy link

May I suggest that the documentation contain a note/warning added about the size of the result being potentially quite large in the case where the graph contains parallel edges?

DeliciousHair added a commit to DeliciousHair/petgraph that referenced this pull request Aug 11, 2024
This commit ends up touching a fair chunk of code outside of the (proposed)
`all_simple_paths_from` function.
* rename `all_simple_paths` -> `all_simple_node_paths`
* rename `all_simple_paths_from` -> `all_simple_edge_paths_from`
* add analogous function `all_simple_edge_paths` that gives an iteralbe over paths, specified by edges
* function signature altered to clarify language + remove opaque counting feature
* checking added, both functions will panic instead of quitely fixing things for the user
* tests added, including negative tests
@starovoid
Copy link
Collaborator

Hi all! Is there anything else that separates the adoption of this new algorithm in the next release?

@starovoid starovoid added the S-rebase-needed Status: Rebase needed label Jun 22, 2025
@starovoid starovoid added this to the 0.8.4 milestone Jun 22, 2025
@DeliciousHair
Copy link

Happy to put my hand up to fix the conflicts if that will get this merged?

@bluss
Copy link
Member Author

bluss commented Oct 15, 2025

@DeliciousHair I think that would be helpful

@RaoulLuque
Copy link
Member

RaoulLuque commented Oct 16, 2025

Happy to put my hand up to fix the conflicts if that will get this merged?

Thanks for the offer, that'd be wonderful 🌞 Note however, that currently a new major release is in the making which will break a lot of the existing functionality, which is why this change might need some time to be adopted until the scaffolding for 0.9 is done. As the algorithm will probably mostly use the current graph traits however, it should not be affected by the first "wave" of changes, which will keep the existing graph traits intact :)

TLDR: It might take more time than usual until this PR is merged :) Please also note the algorithm doc template we are using 👍

EDIT: Forgot to link the issue laying out the changes ^^
#891

@DeliciousHair
Copy link

Thanks for the heads up! With that in mind, if there are no objections I'll simply make a new pr to account for these details rather than trying to massage this one into a passing state. Sound OK?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

C-new-algorithm Category: A feature request for a new graph algorithm S-rebase-needed Status: Rebase needed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants