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

UnweightedBellmanFord #523

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

UnweightedBellmanFord #523

wants to merge 6 commits into from

Conversation

baydrea
Copy link
Contributor

@baydrea baydrea commented Dec 6, 2021

No description provided.

@james-d-mitchell
Copy link
Member

Thanks for the PR @baydrea ! Before I review this, can you please try to fix the CI? Everything has passed except linting, you can install gaplint by doing:

python3 -m pip install gaplint

then run it on the file gap/attr.gi by doing (from within the digraphs directory):

gaplint gap/attr.gi

and then fix the errors indicated.

doc/attr.xml Outdated

If there is a directed path from <A>source</A> to vertex <C>i</C>, then
the value of the entry i in the first sublist is the length of the shortest such directed
path and the entry i in the second sublist is the vertex preceding the vertex of that entry. If no such directed path exists, then the value of i is <C>fail</C>. We use the convention that the distance from every vertex to
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure what the vertex preceding the vertex of that entry means, can you please clarify? And also please wrap the line so that it is at most 80 chars long.

@james-d-mitchell james-d-mitchell added the new-feature A label for new features. label Jan 6, 2022
Copy link
Collaborator

@flsmith flsmith 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 pull request. I've left a few things that should be addressed before we merge this in.

<#GAPDoc Label="UnweightedBellmanFord">
<ManSection>
<Attr Name="UnweightedBellmanFord" Arg="digraph","source"/>
<Returns>A list of integers or <K>fail</K>.</Returns>
Copy link
Collaborator

Choose a reason for hiding this comment

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

This is not what the rest of the documentation claims as the return value

<Attr Name="UnweightedBellmanFord" Arg="digraph","source"/>
<Returns>A list of integers or <K>fail</K>.</Returns>
<Description>
If <A>digraph</A> is a digraph with <M>n</M> vertices, then this
Copy link
Collaborator

Choose a reason for hiding this comment

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

and <C>source</C> is?

<Returns>A list of integers or <K>fail</K>.</Returns>
<Description>
If <A>digraph</A> is a digraph with <M>n</M> vertices, then this
function returns a list with two sublists of <M>n</M> entries, where each entry is
Copy link
Collaborator

Choose a reason for hiding this comment

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

"...a list <C>L = [distances, predecessors]</C>..." so they can be referred to later

function returns a list with two sublists of <M>n</M> entries, where each entry is
either a non-negative integer, or <K>fail</K>. <P/>

If there is a directed path from <A>source</A> to vertex <C>i</C>, then for each i-th entry the first sublist contains
Copy link
Collaborator

Choose a reason for hiding this comment

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

<C>i</C>th

either a non-negative integer, or <K>fail</K>. <P/>

If there is a directed path from <A>source</A> to vertex <C>i</C>, then for each i-th entry the first sublist contains
the length of the shortest directed path to that i-th vertex and second sublist contains the vertex preceding that i-th
Copy link
Collaborator

Choose a reason for hiding this comment

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

This could be clearer - maybe something like "... vertex <C>i</C>, then <C>distances[i]</C> contains the length of the shortest path from <C>source</C> to vertex i, and <C>predecessors[i]</C> contains the vertex before <C>i</C> on such a shortest path."

for edge in DigraphEdges(digraph) do
u := edge[1];
v := edge[2];
# only works for unweighted graphs, w needs to be changed into a variable
Copy link
Collaborator

Choose a reason for hiding this comment

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

But for this function which is only supposed to do the unweighted version, is there any reason to have this comment or use the variable w? Particularly since w is not very descriptive.
There is some sort of argument for using a constant edge_weight := 1 defined near the start of the function, but most people would probably just replace w by 1 everywhere.

# only works for unweighted graphs, w needs to be changed into a variable
w := 1;
if distance[u] + w < distance[v] then
Print("Graph contains a negative-weight cycle");
Copy link
Collaborator

Choose a reason for hiding this comment

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

We almost never want our functions to Print things. In the unweighted case, there's no need for this check is there? It's impossible to have a negative-weight cycle when all edges have weight 1.

fi;
od;
for i in DigraphVertices(digraph) do
if distance[i] >= inf then
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can this value really ever be greater than inf?

if distance[i] >= inf then
distance[i] := fail;
fi;
if predecessor[i] = 0 then
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would be tempted to use inf to represent failure for both distance and predecessor, rather than inf and 0 - especially since they can only fail at the same time. Since they can only fail at the same time, you could also replace the two loops with one that looks like

for i in DigraphVertices(digraph) do
    if distance[i] = inf or predecessor[i] = inf then
        ...

for edge in DigraphEdges(digraph) do
u := edge[1];
v := edge[2];
# only works for unweighted graphs, w needs to be changed into a variable
Copy link
Collaborator

Choose a reason for hiding this comment

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

As above.

@github-actions
Copy link

Stale pull request message

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new-feature A label for new features.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants