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

Implement isdigraphical and fix isgraphical #186

Merged
merged 8 commits into from
Jan 14, 2023

Conversation

InterdisciplinaryPhysicsTeam
Copy link
Member

Hello,

We're the developers of MultilayerGraphs.jl.

In this PR we implement the test for graphicality in the directed without loops case (see Fulkerson–Chen–Anstee theorem).

The new function is called isdigraphical, and we tried to implement it as similarly as we could to the already existing isgraphical. Implementation differences are highlighted using comments in the code.

We have already written the docstrings and added tests.

CC: @pitmonticone @ClaudMor

@codecov
Copy link

codecov bot commented Oct 30, 2022

Codecov Report

Merging #186 (f2694a6) into master (897e183) will increase coverage by 0.03%.
The diff coverage is 100.00%.

@@            Coverage Diff             @@
##           master     #186      +/-   ##
==========================================
+ Coverage   97.40%   97.43%   +0.03%     
==========================================
  Files         109      113       +4     
  Lines        6470     6554      +84     
==========================================
+ Hits         6302     6386      +84     
  Misses        168      168              

Copy link
Member

@aurorarossi aurorarossi left a comment

Choose a reason for hiding this comment

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

Thank you for the contribution!

src/connectivity.jl Outdated Show resolved Hide resolved
test/connectivity.jl Outdated Show resolved Hide resolved
test/connectivity.jl Outdated Show resolved Hide resolved
@InterdisciplinaryPhysicsTeam
Copy link
Member Author

Done @aurorarossi,

Thanks for your suggestions.

CC: @ClaudMor @pitmonticone

@aurorarossi
Copy link
Member

This branch has conflicts because we recently introduced a Julia Formatter. Can you do a merge with Graphs.jl/master? And format the files you changed? I tried to fix it but I don't have permissions to push to your branch. Thanks!


n = length(indegree_sequence)

n == length(outdegree_sequence) || return false
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be more appropriate to throw an exception in this case?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, done.

```
for each integer r <= n-1
"""
function isdigraphical(indegree_sequence::Vector{<:Integer}, outdegree_sequence::Vector{<:Integer} )
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
function isdigraphical(indegree_sequence::Vector{<:Integer}, outdegree_sequence::Vector{<:Integer} )
function isdigraphical(indegree_sequence::AbstractVector{<:Integer}, outdegree_sequence::AbstractVector{<:Integer} )

Copy link
Member Author

Choose a reason for hiding this comment

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

Done, but that is in contradiction with the @aurorarossi's request.

Copy link
Member

Choose a reason for hiding this comment

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

Which one?
I suggested changing the signature style of the function in the docstring, but not here

Copy link
Member Author

Choose a reason for hiding this comment

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

Ops sorry @aurorarossi, we've just noticed that Graphs.jl uses two different conventions for the code and its docstring.

We're going to keep the signature according to @simonschoelly's suggestion then.

@inbounds for r = 1:(n - 1)

indegree_sum += sorted_indegree_sequence[r]
outdegree_min_sum = sum([min(sorted_outdegree_sequence[i], r-1) for i in 1:r])
Copy link
Contributor

Choose a reason for hiding this comment

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

Here we allocate a new Vector in each iteration of the loop. Can we do this differently?

Copy link
Member Author

Choose a reason for hiding this comment

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

We were not able to use the same strategy adopted in isgraphical. For further details see in the comments.

sdg = SimpleDiGraph(10, 90)
@test @inferred(isdigraphical(indegree(sdg), outdegree(sdg)))
@test !@inferred(isdigraphical([1,1,1], [1,1,0]))

Copy link
Contributor

Choose a reason for hiding this comment

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

Can we also have a few edge cases here? Such as

  • Empty vectors
  • Graphs that only have a realization if there is a self-loop.
  • Graphs where the sum of the in and out degree sequences if the same, but there is still no valid realization.

Copy link
Member Author

Choose a reason for hiding this comment

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

We've just noticed that isgraphical and isdigraphical don't work properly in the edge cases you mentioned.

For example:

  • isgraphical([2]) returns true even if it's not possible to realise a simple undirected graph (no self-loops, no multi-edges) with just a vertex with $d(v)=2$.
  • isdigraphical([1],[1]) returns true even if it's not possible to realise a simple directed graph (no self-loops, no multi-edges) with just a vertex with $d_{in}(v)=d_{out}(v)=1$.

@InterdisciplinaryPhysicsTeam
Copy link
Member Author

This branch has conflicts because we recently introduced a Julia Formatter. Can you do a merge with Graphs.jl/master? And format the files you changed? I tried to fix it but I don't have permissions to push to your branch. Thanks!

@aurorarossi, we have just formatted the relevant files.

@InterdisciplinaryPhysicsTeam InterdisciplinaryPhysicsTeam changed the title Implement isdigraphical Implement isdigraphical and correct isgraphical Dec 11, 2022
@simonschoelly
Copy link
Contributor

@InterdisciplinaryPhysicsTeam Now there is a lot of noise in this PR because of the formatting changes. Perhaps if you rebase on the latest master branch, they will go away?

Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
@InterdisciplinaryPhysicsTeam
Copy link
Member Author

Hello @simonschoelly,

We rebased as you asked and updated the isgraphical and isdigraphical functions.

@pitmonticone @ClaudMor

Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
@InterdisciplinaryPhysicsTeam InterdisciplinaryPhysicsTeam changed the title Implement isdigraphical and correct isgraphical Implement isdigraphical and fix isgraphical Dec 16, 2022
@InterdisciplinaryPhysicsTeam
Copy link
Member Author

Hello @simonschoelly @aurorarossi @gdalle,

Since we are not maintainers, we need our fork to be on par with Graphs.jl's master branch in order to open new pull requests. Anyway, we cannot do it until this is merged.

May anyone with write permission review and merge this?

Comment on lines 770 to 774
According to Fulkerson-Chen-Anstee theorem, a sequence ``\\{(a_1, b_1), ...,(a_n, b_n)\\}`` (sorted in descending order of a) is graphic iff the sum of vertex degrees is even and ``\\sum_{i = 1}^{n} a_i = \\sum_{i = 1}^{n} b_i\\}`` and the sequence obeys the property -
```math
\\sum_{i=1}^{r} a_i \\leq \\sum_{i=r+1}^n min(r-1,b_i) + \\sum_{i=r+1}^n min(r,b_i)
```
for each integer r <= n-1.
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you have a source for these conditions? Because the ones on Wikipedia look differently.

I also notices that this algorithm does return incorrect results in some cases:

# would only work with a self-loop, but we don't allow these, right?
julia> isdigraphical([1],[1])
true

# would require multi-edges
julia> isdigraphical([5],[5])
true

# but this should also be true if we allow self-loops.
julia> isdigraphical([1,0],[1,0])
false

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, I was wondering if latex heavy docstrings are a good idea? We don't need to change it in this PR, as we always can do it latter, the issue is just that in the REPL it looks like this:

help?> isdigraphical
search: isdigraphical

  isdigraphical(indegree_sequence, outdegree_sequence)

  Check whether the given indegree sequence and outdegree sequence are digraphical, that is whether
  they can be the indegree and outdegree sequence of a digraph.

  Implementation Notes
  ––––––––––––––––––––––

  According to Fulkerson-Chen-Anstee theorem, a sequence \{(a_1, b_1), ...,(a_n, b_n)\} (sorted in
  descending order of a) is graphic iff the sum of vertex degrees is even and \sum_{i = 1}^{n} a_i =
  \sum_{i = 1}^{n} b_i\} and the sequence obeys the property -

  \sum_{i=1}^{r} a_i \leq \sum_{i=r+1}^n min(r-1,b_i) + \sum_{i=r+1}^n min(r,b_i)

  for each integer r <= n-1.

  See also: isgraphical

Copy link
Member Author

Choose a reason for hiding this comment

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

We removed the "the sum of vertex degrees is even" part from the docstring of isdigraphical which could be misleading.

The three cases you mentioned should now be fixed and added to tests. Thanks for pointing them out.

We will happily comply with whatever suggestion you give us for formatting docstrings.

Comment on lines 739 to 740
all(degs .>= 0) ||
throw(ArgumentError("The degree sequence must contain non-negative integers only."))
Copy link
Contributor

Choose a reason for hiding this comment

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

Wouldn't it be more reasonable to just return false here? Of course if that is so, we should probably do the same thing for isdigraphical.

Copy link
Member Author

Choose a reason for hiding this comment

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

We thought that false was reserved for when "the degree sequence is valid but not graphical", while errors should be thrown if the degree sequence is not even valid.

If it isn't appropriate we will change the behavior.

Copy link
Contributor

Choose a reason for hiding this comment

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

I leave the decision up too you. One thing that is nice about not throwing an error, that a user does not have to make an extra check for an error, if their input might contain a negative number.

But then we probably should also check, that all degrees are less or equal than n - 1?

Where is would still leave the throws check in, is in the isdigraphical method for inputs of different lengths.

Also note that by throwing an exception in isgraphical we kind of introduce a breaking change - but as this is a very rare edge case, I think that should be ok.

Let me know what you decide.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks for your argumentation.

We agree that returning false allows for simpler usage, and if the user wishes to get an error in specific circumstances, she/he may wrap the function. Thus we now return false when negative degrees are present, or when a degree exceeds n-1.

isdigraphical(indegree_sequence, outdegree_sequence)

Check whether the given indegree sequence and outdegree sequence are digraphical, that is whether they can be the indegree and outdegree sequence of a digraph.

Copy link
Contributor

Choose a reason for hiding this comment

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

We should probably mention here that

  • The digraph cannot have self-loops
  • indegree_sequence and outdegree_sequence are not independent, i.e. if entry i of indegree_sequence has value a_i and entry i of outdegree_sequence has value b_i then there will be a vertex with indegree a_i and outdegree b_i in the realization. (maybe there is an easier way to express this).

Copy link
Member Author

Choose a reason for hiding this comment

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

We modified the docstring trying to include your suggestions. Thanks.

)

n = length(indegree_sequence)
n == length(outdegree_sequence) || return false
Copy link
Contributor

Choose a reason for hiding this comment

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

We already check this on line 783.

Copy link
Member Author

Choose a reason for hiding this comment

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

We removed the redundant check and moved the definition of the variable n to the top of the function.

Copy link
Contributor

@simonschoelly simonschoelly left a comment

Choose a reason for hiding this comment

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

Hello @simonschoelly @aurorarossi @gdalle,

Since we are not maintainers, we need our fork to be on par with Graphs.jl's master branch in order to open new pull requests. Anyway, we cannot do it until this is merged.

May anyone with write permission review and merge this?

I am not sure, what you mean, by not being able to open new pull requests?

In any case, I think there are still some bugs here, that need to be fixed before we can merge.

Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
@InterdisciplinaryPhysicsTeam
Copy link
Member Author

Hi @simonschoelly ,

We realized that "not being able to open new pull requests" was due to a mistake of ours, we apologize for that.

We hope that the fixes above comply with your comments.

src/connectivity.jl Outdated Show resolved Hide resolved
src/connectivity.jl Outdated Show resolved Hide resolved
@simonschoelly
Copy link
Contributor

Some small fixes for the formula in the docstring and some decision to make, if we should throw errors - and then I think we can finally merge this.

Co-authored-by: Simon Schölly <sischoel@gmail.com>
Co-authored-by: Simon Schölly <sischoel@gmail.com>
Co-Authored-By: Pietro Monticone <38562595+pitmonticone@users.noreply.github.com>
Co-Authored-By: Claudio Moroni <43729990+ClaudMor@users.noreply.github.com>
@InterdisciplinaryPhysicsTeam
Copy link
Member Author

We committed your suggestions and accepted your proposal to return false above.

@simonschoelly simonschoelly merged commit c4360cf into JuliaGraphs:master Jan 14, 2023
@simonschoelly
Copy link
Contributor

Merged, thanks!

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

Successfully merging this pull request may close these issues.

None yet

3 participants