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

Make is_graphical functions linear time #2605

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

gendelpiekel
Copy link
Contributor

@gendelpiekel gendelpiekel commented May 4, 2024

Addresses #2546.

  • Changes igraph_i_is_bigraphical_simple to use counting sort to be linear time as discussed in the above issue.
  • Also changes igraph_i_is_graphical_undirected_loopy_simple which was using a comparison sort as well.

Now igraph_is_graphical() should be linear in all cases.

Benchmark results

To benchmark igraph_i_is_bigraphical_simple I used the benchmark for 'directed with single loops allowed' which is equivalent to it.

/* Directed graph with no multi-edges and at most one self-loop per vertex:
* - Degrees must be non-negative.
* - Equivalent to bipartite simple graph.
*/
static igraph_error_t igraph_i_is_graphical_directed_loopy_simple(const igraph_vector_int_t *out_degrees, const igraph_vector_int_t *in_degrees, igraph_bool_t *res) {
return igraph_i_is_bigraphical_simple(out_degrees, in_degrees, res);
}

bigraphical_simple before:

$ ./tests/benchmark_graphicality
| Directed loops,        PA,     n = 50, 2000000x                                   1.36s   1.36s      0s
| Directed loops,        G(n,p), n = 50, 2000000x                                   1.76s   1.76s      0s

| Directed loops,        PA,     n = 1000, 100000x                                  1.19s   1.19s      0s
| Directed loops,        G(n,p), n = 1000, 100000x                                  1.83s   1.83s      0s

| Directed loops,        PA,     n = 1000000, 100x                                  1.97s   1.97s      0s
| Directed loops,        G(n,p), n = 1000000, 100x                                  4.08s   4.07s      0s

bigraphical_simple after:

$ ./tests/benchmark_graphicality
| Directed loops,        PA,     n = 50, 2000000x                                  0.462s  0.462s      0s
| Directed loops,        G(n,p), n = 50, 2000000x                                  0.358s  0.358s      0s

| Directed loops,        PA,     n = 1000, 100000x                                 0.388s  0.388s      0s
| Directed loops,        G(n,p), n = 1000, 100000x                                 0.226s  0.226s      0s

| Directed loops,        PA,     n = 1000000, 100x                                 0.627s  0.627s      0s
| Directed loops,        G(n,p), n = 1000000, 100x                                  0.44s   0.44s      0s

graphical_undirected_loopy_simple before:

| Undirected loops,        PA,     n = 50, 2000000x                                0.881s  0.881s      0s
| Undirected loops,        G(n,p), n = 50, 2000000x                                 1.15s   1.15s      0s

| Undirected loops,        PA,     n = 1000, 100000x                               0.827s  0.827s      0s
| Undirected loops,        G(n,p), n = 1000, 100000x                               0.954s  0.954s      0s

| Undirected loops,        PA,     n = 1000000, 100x                                1.48s   1.48s      0s
| Undirected loops,        G(n,p), n = 1000000, 100x                                1.96s   1.94s      0s

graphical_undirected_loopy_simple after:

$ ./tests/benchmark_graphicality
| Undirected loops,        PA,     n = 50, 2000000x                                0.349s  0.349s      0s
| Undirected loops,        G(n,p), n = 50, 2000000x                                0.354s  0.354s      0s

| Undirected loops,        PA,     n = 1000, 100000x                               0.264s  0.264s      0s
| Undirected loops,        G(n,p), n = 1000, 100000x                               0.225s  0.225s      0s

| Undirected loops,        PA,     n = 1000000, 100x                               0.311s  0.311s      0s
| Undirected loops,        G(n,p), n = 1000000, 100x                               0.355s  0.355s      0s

Copy link

codecov bot commented May 4, 2024

Codecov Report

Attention: Patch coverage is 98.03922% with 1 lines in your changes are missing coverage. Please review.

Project coverage is 84.30%. Comparing base (223fd0e) to head (8a1afa9).
Report is 4 commits behind head on master.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff           @@
##           master    #2605   +/-   ##
=======================================
  Coverage   84.29%   84.30%           
=======================================
  Files         379      379           
  Lines       61949    61977   +28     
  Branches    12137    12147   +10     
=======================================
+ Hits        52221    52250   +29     
+ Misses       9728     9727    -1     
Files Coverage Δ
src/misc/graphicality.c 98.46% <98.03%> (+0.46%) ⬆️

... and 3 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 223fd0e...8a1afa9. Read the comment docs.

@szhorvat szhorvat added this to the 0.10.12 milestone May 4, 2024
@gendelpiekel gendelpiekel force-pushed the linear-is-bigraphical-simple branch from ffd1a10 to 36bd61c Compare May 4, 2024 14:13
@szhorvat szhorvat marked this pull request as draft May 4, 2024 14:21
@szhorvat szhorvat self-assigned this May 4, 2024
@szhorvat
Copy link
Member

szhorvat commented May 4, 2024

Thanks for taking on this issue! I marked this PR as draft for now. When it is ready to be merged, just click the "Ready for review" button. If you need help before then (for example to debug CI failures), let us know.

@szhorvat szhorvat linked an issue May 4, 2024 that may be closed by this pull request
@gendelpiekel gendelpiekel force-pushed the linear-is-bigraphical-simple branch from 36bd61c to d8bd722 Compare May 4, 2024 14:31
@szhorvat szhorvat marked this pull request as ready for review May 4, 2024 15:32
@szhorvat szhorvat marked this pull request as draft May 4, 2024 15:32
@gendelpiekel gendelpiekel marked this pull request as ready for review May 4, 2024 15:48
Copy link
Member

@ntamas ntamas left a comment

Choose a reason for hiding this comment

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

Thanks, this looks good to me!

Berger's relaxation is not mentioned any more in the documentation; I don't know the theorem well enough to judge whether this is correct or not so I leave it up to @szhorvat to decide.

@gendelpiekel
Copy link
Contributor Author

Berger's relaxation is not mentioned any more in the documentation; I don't know the theorem well enough to judge whether this is correct or not

I'm not familiar either but I assume it refers to this check:

/* Based on Theorem 3 in [Berger 2014], it is sufficient to do the check
* for k such that a_k > a_{k+1} and for k=(n_1-1).
*/
if (k < n1-1 && VECTOR(sorted_deg1)[k] == VECTOR(sorted_deg1)[k+1])
continue;

which I removed because in the original implementation it basically did an if check to see if it could skip another if check.

However, your comment made me realise that it basically allows you to combine all indices k with equal values of a_k which is very helpful if you're using counting sort... So I've added it back which makes the implementation simpler and also faster. Benchmark is also updated.

@szhorvat szhorvat self-requested a review May 5, 2024 11:59
@ntamas ntamas modified the milestones: 0.10.12, 0.10.x May 6, 2024
@szhorvat szhorvat modified the milestones: 0.10.x, 0.10.13 May 29, 2024
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.

Switch to bucket sort in igraph_i_is_bigraphical_simple
3 participants