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

Questionable semantics of DiGraph().all_simple_paths #12385

Closed
kini opened this issue Jan 30, 2012 · 26 comments
Closed

Questionable semantics of DiGraph().all_simple_paths #12385

kini opened this issue Jan 30, 2012 · 26 comments

Comments

@kini
Copy link
Contributor

kini commented Jan 30, 2012

See this sage-support thread.

The docstring of DiGraph().all_simple_paths starts with this paragraph:

       Returns a list of all the simple paths of self starting with one of
       the given vertices. A path is simple if no vertex occurs twice in
       it except possibly the starting and ending one. The paths are
       enumerated in increasing length order.

In short, the DiGraph().all_simple_paths function deems paths of the form [a, b, c, b] to be simple. This is not true according to the generally accepted definition of a simple path. I suspect the intent of the author was to allow paths of the form [b, c, b] (i.e. paths which are actually cycles), which seems reasonable.

Another possibility would be to use the definition found on Wikipedia, namely that a simple path must not have any repeated vertices, and that a "simple cycle" is a path whose first vertex is its last vertex but has no other vertex repetitions. In this case the function should exclude both paths of the form [a, b, c, b] and paths of the form [b, c, b]. But I don't see that this is very useful. The function allows you to specify sets of starting and ending points for the paths you want returned, and if you specify non-disjoint sets, you are likely asking for cycles to be included.

Incidentally, a definition that matches what is given in the first paragraph above is this: a "simple path" in a directed graph is a sequence of arcs such that the head of each arc is the tail of the next arc in the sequence, and no two arcs share the same head or the same tail.


Apply to $SAGE_ROOT/devel/sage:

  1. attachment: trac_12385-all-simple-paths.patch
  2. attachment: trac_12385_review.2.patch
  3. attachment: trac_12385-all-simple-paths.2.patch
  4. attachment: trac_12385-all-simple-paths.3.patch

CC: @nathanncohen @sagetrac-abmasse

Component: graph theory

Keywords: digraphs graphs all_simple_paths

Author: Keshav Kini

Reviewer: Nathann Cohen

Merged: sage-5.0.beta4

Issue created by migration from https://trac.sagemath.org/ticket/12385

@kini kini added this to the sage-5.0 milestone Jan 30, 2012
@kini kini self-assigned this Jan 30, 2012
@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

Author: Keshav Kini

@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

comment:1

Here's a patch which implements the first suggestion in the ticket description. The original ticket seems to be #8273 so I'm CCing the author and reviewer of that ticket.

Doing a make ptestlong on this patch now, though the file in question passes and search_src() tells me this function is not used by any other code, so I don't expect any doctest problems.

@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

apply to $SAGE_ROOT/devel/sage

@kini

This comment has been minimized.

@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

Changed keywords from graphs all_simple_paths to digraphs graphs all_simple_paths

@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

comment:2

Attachment: trac_12385-all-simple-paths.patch.gz

Whoops, sorry, this is a digraph method, not a graph method. I mistitled the ticket.

@kini kini changed the title Questionable semantics of Graph().all_simple_paths Questionable semantics of DiGraph().all_simple_paths Jan 30, 2012
@kini
Copy link
Contributor Author

kini commented Jan 30, 2012

comment:3

make ptestlong passes. Comments?

@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Jan 30, 2012

comment:4

First that what you are doing is totally right, then that I will try to review the ticket today :-)

Nathann

@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Jan 30, 2012

comment:5

Hellooooo !!!

Hmmm... I was a bit worried at your path.count(path[-1]) ^^;

What do you think of the alternative version I attach ? In this one I check whether the path is a cycle before adding it to the queue. This way a "neighbor in path" is sufficient.

I also do not understand why you removed the "if trivial" from before the loop to put it inside. It would be a waste to "test" trivial at each loop, and also to test len(path) > 1 when we know it will always be true after some step, wouldn't it ?

Tell me what you think :-)

Nathann

@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Jan 30, 2012

Attachment: trac_12385_review.patch.gz

@sagetrac-abmasse
Copy link
Mannequin

sagetrac-abmasse mannequin commented Jan 30, 2012

comment:6

Hi, Keshav and Nathann,

Thank you, Keshav, for finding that bug, I'm sorry we missed it the first time.

Since Nathann has already started the review, I'll let him finish it (I don't even have the last Sage version installed on my computer).

By the way, the title "Questionable semantics of DiGraph().all_simple_paths" could be replaced by "Wrong semantics of DiGraph().all_simple_paths" :-)

Alexandre

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

comment:7

Replying to @nathanncohen:

Hmmm... I was a bit worried at your path.count(path[-1]) ^^;

Can you explain? I think the same expression was used in the old code.

What do you think of the alternative version I attach ? In this one I check whether the path is a cycle before adding it to the queue. This way a "neighbor in path" is sufficient.

Nice! It's definitely better. I don't know why I avoided touching that last loop. Of course that is the better place to do this logic.

I also do not understand why you removed the "if trivial" from before the loop to put it inside. It would be a waste to "test" trivial at each loop, and also to test len(path) > 1 when we know it will always be true after some step, wouldn't it ?

Well, part of it was a mistake - I meant to put the check for trivial after the check for len(path). Because of the lazy evaluation of boolean operators in Python (a and b skips checking b if a is false, etc.), this would still make trivial be evaluated only once, and would reduce the number of yield statements in the code, making it "easier to read", theoretically. Also I made it so that len(path) would only be checked for each path with a desired endpoint, not every single path.

But you're right, it's possible to make this better by moving the condition check in the while loop to somewhere in the middle of the body rather than at the top. Patch attached! (Or will be after I post this comment.) I made some other changes too, such as inverting the loop and if/else in your code to check simple on every good incomplete path rather than every candidate extension. It would be best if simple and trivial could be declared as constant so that Python could optimize away all these checks. Or maybe it already knows this, since we don't assign any values to those variables... how smart is Python, anyway? I think I am getting stuck in the premature optimization trap... :P

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

Attachment: trac_12385-all-simple-paths.2.patch.gz

apply to $SAGE_ROOT/devel/sage

@kini

This comment has been minimized.

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

Attachment: trac_12385_review.2.patch.gz

apply to $SAGE_ROOT/devel/sage

@kini

This comment has been minimized.

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

comment:9

Your commit message was weird so I fixed it :)

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

comment:10

BTW, thanks Alexandre for writing the code in the first place :)

@kini

This comment has been minimized.

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

comment:12

Here's a documentation patch which changes the stated definition of simple paths as well (to the one I added to the description). I also took the opportunity to enforce PEP 8 in the functions I touched, with the exception of doctest input lines (because of #10458 which I really need to get back to one of these days...). Patch below!

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

Attachment: trac_12385-all-simple-paths.3.patch.gz

apply to $SAGE_ROOT/devel/sage

@kini

This comment has been minimized.

@nathanncohen
Copy link
Mannequin

nathanncohen mannequin commented Jan 31, 2012

comment:14

Weird loop, but it works :-)

If you are are also ok with it, you can set the ticket to "positive_review" !

Nathann

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

Reviewer: Nathann Cohen

@kini
Copy link
Contributor Author

kini commented Jan 31, 2012

comment:15

I wrote it, so I guess I'm OK with it :) Thanks!

@jdemeyer
Copy link

Merged: sage-5.0.beta4

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

No branches or pull requests

2 participants