Skip to content

PNC k shortest simple path (for directed graphs) #40284

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

Open
wants to merge 17 commits into
base: develop
Choose a base branch
from

Conversation

kappybar
Copy link
Contributor

Implement PNC k shortest simple path for directed graphs.
I implemented for only directed graphs for simplicity first.

📝 Checklist

  • The title is concise and informative.
  • The description explains in detail what this PR is about.
  • I have linked a relevant issue or discussion.
  • I have created tests covering the changes.
  • I have updated the documentation and checked the documentation preview.

⌛ Dependencies

#40248
#40217

@dcoudert dcoudert added c: graph theory gsoc: 2025 Tag for GSoC2025 issues/PRs labels Jun 23, 2025
Copy link
Contributor

@dcoudert dcoudert left a comment

Choose a reason for hiding this comment

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

Why is it necessary to define PathCandidate in a .h file ? can't it be done in file path_enumeration.pxd ?

G.delete_edges(G.incoming_edges(source, labels=False))
G.delete_edges(G.outgoing_edges(target, labels=False))

if weight_function is not None:
Copy link
Contributor

Choose a reason for hiding this comment

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

this is done by the call to _get_weight_function. No need to duplicate.

if self.has_loops() or self.allows_multiple_edges():
G = self.to_simple(to_undirected=False, keep_label='min', immutable=False)
else:
G = self.copy()
Copy link
Contributor

Choose a reason for hiding this comment

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

to be on the safe side, use self.copy(immutable=False)

reverse_graph = G.reverse()
dist, successor = shortest_paths(reverse_graph, target, weight_function=reverse_weight_function,
algorithm='Dijkstra_Boost')
cdef set unnecessary_vertices = set(G) - set(dist) # no path to target
Copy link
Contributor

Choose a reason for hiding this comment

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

always add 2 spaces before a comment at the end of a line, so set(list) # vertices with no path to target


# ancestor_idx_dict[v] := the first vertex reachable by edges of
# first shortest path tree from v
ancestor_idx_dict = dict()
Copy link
Contributor

Choose a reason for hiding this comment

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

ancestor_idx_dict = {v: i for I, v in enumerate(path)}

@kappybar
Copy link
Contributor Author

Why is it necessary to define PathCandidate in a .h file ? can't it be done in file path_enumeration.pxd ?

Because I want to use priority_queue of C++ standard library, the type of PathCandidate must be struct of C++. Thus, I think I need definition of PathCandidate in .h file. However, There may be another way of doing so without .h file. I am looking for it.

@dcoudert
Copy link
Contributor

isn't it possible to use a tuple instead of PathCandidate ? or may be cdef priority_queue[pair[pair[double,bint], pair[int, int]]] heap_sorted_paths.
Priority should go to the path with smallest length and in case several paths have the same length, we want first the simple paths.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants