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

Add lowest_common_ancestor algorithm #35

Open
wants to merge 6 commits into
base: branch-24.12
Choose a base branch
from

Conversation

eriknw
Copy link
Contributor

@eriknw eriknw commented Nov 20, 2024

This is a medium-priority algorithm that I considered pairing with @nv-rliu on instead of #32, so I thought I would knock it out while it was still fresh in mind. It was pretty quick.

To reviewers: this is low priority and may slip to the next release. Please do more important things first. It is reasonable to request benchmarking, which I hope to add when I get a chance.

I created more tests in networkx to help with this PR: networkx/networkx#7726

I think the implementation is pretty clean and straightforward, so hopefully others think so too (although it probably requires understanding what this algorithm does).

@eriknw eriknw requested a review from a team as a code owner November 20, 2024 04:13
@eriknw eriknw added improvement Improves an existing functionality non-breaking Introduces a non-breaking change labels Nov 20, 2024
__all__ = ["lowest_common_ancestor"]


@not_implemented_for("undirected")
Copy link
Contributor

Choose a reason for hiding this comment

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

Does adding this make the algorithm automatically raise errors on undirected graphs?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes. It's a decorator from networkx.

We place it before @networkx_algorithm, because NetworkX already checks and raises if the input graph is undirected before dispatching to backends:
https://github.com/networkx/networkx/blob/9beaf7a0b59fe21775cd93862d9c7b28152a2d8c/networkx/algorithms/lowest_common_ancestors.py#L115-L117

In other words, we use the same decorator so the algorithm behaves correctly when used directly such as nxcg.lowest_common_ancestor(G).

"""May not always raise NetworkXError for graphs that are not DAGs."""
G = _to_directed_graph(G)

# if not nxcg.is_directed_acyclic_graph(G): # TODO
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to wait on this before merging?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be nice to, but I don't think it's super important in practice so I would say no. We add a note to the docstring. If/when PLC can help answer whether a graph is a DAG, then we should add nxcg.is_directed_acyclic_graph ASAP.

The difference is that if the graph is not a DAG, then we may still give an answer or we may raise as networkx does. It's common to know whether your graph is a DAG or not (often by construction).

@eriknw
Copy link
Contributor Author

eriknw commented Nov 21, 2024

I added a basic benchmark where I force the input graph to be a DAG. The two initial nodes were chosen randomly; it would be nice to make benchmarks that take nodes a bit more robust. Here are some results:

lca_bench

Generally, I think relative performance should be comparable to ancestors.

@eriknw eriknw changed the title Add lowest_common_ancestors algorithm Add lowest_common_ancestor algorithm Nov 22, 2024
@eriknw
Copy link
Contributor Author

eriknw commented Nov 22, 2024

Companion PR that updates docs: rapidsai/cugraph#4779

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
benchmarks improvement Improves an existing functionality non-breaking Introduces a non-breaking change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants