-
-
Notifications
You must be signed in to change notification settings - Fork 427
Bound Diameter #2739
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
base: main
Are you sure you want to change the base?
Bound Diameter #2739
Conversation
af29a01
to
8482c56
Compare
@szhorvat This PR now also implements I was hoping everything I do would stay in one PR, let me know if you want the sets in a different one (or if you want a different solution entirely) |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## develop #2739 +/- ##
===========================================
+ Coverage 84.68% 84.72% +0.04%
===========================================
Files 380 380
Lines 62314 62577 +263
Branches 12192 12248 +56
===========================================
+ Hits 52770 53021 +251
- Misses 9544 9556 +12
... and 2 files with indirect coverage changes Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just a few small comments now, we can discuss more in person.
9fa9bf4
to
63f4199
Compare
@szhorvat Added more tests, including Barabasi; they pass. Added clean-up for containers as well, without it the address sanitiser kept complaining. Also, I found an OBOE in the Remaining big TODOs:
|
I wrote up some tips on efficient development: https://github.com/igraph/igraph/wiki/Tips-for-quicker-development |
@GrishaVar Do you need any input from me right now? I hope I did not miss any questions. |
@GrishaVar Can you please push what you have so far? This is the equivalent of the draft report submission for you. |
Please don't forget to push. |
@szhorvat update:
These are all pretty minor now, hopefully I can get this wrapped up soon 🙂 |
Let's put this to the bottom of the priority list, as it is very straightforward.
Optionally, you can use a debug macro that makes it possible to turn this on or off, on demand. You can grep the source tree for It is up to you whether you want to do this. I don't have a strong opinion. You can judge best if people might feel the need to turn on debug logging in the future for this function. Something that would be quite nice to have is a basic benchmark. You can see how these work in The purpose of this is to make future tuning of this function easier. I would put this second-to-last on the priority list, just above the weighted version. Actually, I would prioritize this over |
4a87cbe
to
24090e8
Compare
|
Could you please factor out the cleanup of |
80d39f5
to
9b7e6dd
Compare
Copilot reviews got support for C a few days ago. Let's see if produces anything useful. |
9b7e6dd
to
75f846e
Compare
Co-authored-by: Copilot <[email protected]>
Co-authored-by: Copilot <[email protected]>
@szhorvat Is this ready for merging, do you still want to have another review round, or shall I review it before merging? |
It'd be great if you could do a review, but I want to go through it again in detail before merging. It's best if I do that only after I'm back in Reykjavík. Note: I did not check the set removal function at all yet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR Summary
Implements a faster algorithm for computing graph diameters based on Borassi et al. (2015) paper, offering potential O(|E|) complexity for real-world networks versus the traditional O(|V||E|).
- Added
igraph_diameter_bound()
insrc/paths/distances.c
with optimized BFS-based diameter computation - Enhanced
src/core/set.c
with three new operations:push_back
,remove
, anddifference
for O(log n) set manipulations - Added specialized single-source variants
igraph_distances_1
andigraph_distances_dijkstra_1
in unweighted.c/dijkstra.c for improved performance - Included comprehensive test suite in
tests/unit/igraph_diameter_bound.c
covering various graph types and edge cases - Currently supports only undirected graphs, with thorough validation against original diameter calculation methods
14 files reviewed, 12 comments
Edit PR Review Bot Settings | Greptile
IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_add(igraph_set_t *set, igraph_integer_t e); | ||
IGRAPH_PRIVATE_EXPORT igraph_error_t igraph_set_push_back(igraph_set_t *set, igraph_integer_t e); | ||
IGRAPH_PRIVATE_EXPORT void igraph_set_remove(igraph_set_t *set, igraph_integer_t e); | ||
IGRAPH_PRIVATE_EXPORT void igraph_set_difference(igraph_set_t *set, igraph_set_t *to_remove); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: consider marking to_remove parameter as const since it's not modified
IGRAPH_PRIVATE_EXPORT void igraph_set_difference(igraph_set_t *set, igraph_set_t *to_remove); | |
IGRAPH_PRIVATE_EXPORT void igraph_set_difference(igraph_set_t *set, const igraph_set_t *to_remove); |
#define DENS 3.0/VCOUNT | ||
#define REP 1000 | ||
|
||
igraph_erdos_renyi_game_gnp(&g, VCOUNT, DENS, IGRAPH_DIRECTED, IGRAPH_NO_LOOPS); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Graph created with IGRAPH_DIRECTED but all diameter computations use IGRAPH_UNDIRECTED mode. Either the graph creation should be undirected or tests should cover directed case too.
IGRAPH_CHECK(igraph_2wheap_init(&Q, no_of_nodes)); | ||
IGRAPH_FINALLY(igraph_2wheap_destroy, &Q); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Missing FINALLY cleanup handler for Q heap if vector_resize fails on line 284
igraph_destroy(&g); | ||
|
||
#undef VCOUNT | ||
#undef DENS |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: DENS macro undefined but used in Barabási graph section - should be ECOUNT instead
#undef DENS | |
#undef ECOUNT |
* \ingroup set | ||
* \function igraph_set_remove | ||
* \brief Adds an element to the set. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Documentation header incorrectly says 'Adds an element to the set' but this is the remove function
* \ingroup set | |
* \function igraph_set_remove | |
* \brief Adds an element to the set. | |
/** | |
* \ingroup set | |
* \function igraph_set_remove | |
* \brief Removes an element from the set. | |
* |
igraph_diameter_bound(&g, NULL, &result, IGRAPH_UNDIRECTED, false); | ||
igraph_diameter(&g, NULL, &reference, NULL, NULL, NULL, NULL, IGRAPH_DIRECTED, 0); | ||
IGRAPH_ASSERT(result == reference); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: IGRAPH_UNDIRECTED used for bound but IGRAPH_DIRECTED used for reference - this inconsistency could mask errors
igraph_destroy(&g); | ||
|
||
// weighted ring graph | ||
igraph_vector_init_real(&weights, 9, 1.0, 2.675, 3.0, 4.0, 5.5, 1.0, 1.0, 1.0, 1.0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: weights vector initialized with 9 elements but ring graph has 10 nodes (10 edges) - potential buffer overflow
if (!weights && igraph_set_size(¤t_component) <= *diameter) { | ||
break; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Possible early termination bug - if !weights check should be comparing against current best bound not global diameter
update_to_max(&VECTOR(ecc_lower)[w], ecc_v-d); | ||
update_to_max(&VECTOR(ecc_lower)[w], d); | ||
update_to_min(&VECTOR(ecc_upper)[w], ecc_v+d); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
style: Update of ecc_lower twice using different formulas - these should be combined with a max() operation for clarity
const igraph_t *graph, // input graph | ||
const igraph_vector_t *weights, // optional weights | ||
igraph_real_t *diameter, // output diameter value | ||
igraph_bool_t directed, // treating this graph as undirected | ||
igraph_bool_t unconn // false: disconnected returns INF; true: returns largest diameter | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
logic: Parameter 'directed' description seems reversed - says 'treating this graph as undirected' but parameter indicates directedness
const igraph_t *graph, // input graph | |
const igraph_vector_t *weights, // optional weights | |
igraph_real_t *diameter, // output diameter value | |
igraph_bool_t directed, // treating this graph as undirected | |
igraph_bool_t unconn // false: disconnected returns INF; true: returns largest diameter | |
) { | |
const igraph_t *graph, // input graph | |
const igraph_vector_t *weights, // optional weights | |
igraph_real_t *diameter, // output diameter value | |
igraph_bool_t directed, // whether to consider directed paths | |
igraph_bool_t unconn // false: disconnected returns INF; true: returns largest diameter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
Implements the diameter‐bounding algorithm (#2684) and adds supporting set utilities, shortest‐path helpers, tests, benchmarks, example, and documentation updates.
- Added
igraph_diameter_bound
(and helper functions) to compute graph diameter with bounding/pruning. - Introduced
igraph_distances_1
andigraph_distances_dijkstra_1
for single‐source BFS/Dijkstra. - Expanded set interface with
igraph_set_push_back
/remove
/difference
and added unit tests and benchmarks.
Reviewed Changes
Copilot reviewed 14 out of 14 changed files in this pull request and generated 1 comment.
Show a summary per file
File | Description |
---|---|
src/paths/distances.c | Core implementation of igraph_diameter_bound . |
src/paths/unweighted.c | Added igraph_distances_1 single‐source BFS helper. |
src/paths/dijkstra.c | Added igraph_distances_dijkstra_1 single‐source Dijkstra helper. |
src/core/set.h / src/core/set.c | Extended set API: push_back, remove, difference. |
tests/unit/igraph_diameter_bound.c | Unit tests for igraph_diameter_bound . |
tests/unit/set.c / tests/unit/set.out | Unit tests and expected output for new set operations. |
tests/benchmarks/igraph_diameter_bound.c | Benchmarks for bound vs. original diameter routines. |
include/igraph_paths.h / interfaces/functions.yaml | API and header updates for new functions. |
examples/simple/igraph_diameter_bound.c | Example for new function. |
doc/structural.xxml | Documentation inclusion for igraph_diameter_bound . |
Comments suppressed due to low confidence (6)
src/core/set.c:355
- The doc comment for this block is labeled
\function igraph_set_remove
but the implementation below isigraph_set_difference
. Please update the\function
tag toigraph_set_difference
.
* \function igraph_set_remove
src/paths/dijkstra.c:252
- The doc comment for
igraph_distances_dijkstra_1
is justTODO
. Please provide a proper function description, parameters, and return value.
* TODO
examples/simple/igraph_diameter_bound.c:33
- The example calls
igraph_diameter_bound
but does not display or verifyresult
. Consider addingprintf
or assertion to show the computed diameter in this example.
igraph_diameter_bound(&g, NULL, &result, IGRAPH_UNDIRECTED, 0);
interfaces/functions.yaml:439
- The parameter in code is named
unconn
but here it’s labeledunconnected
. To avoid confusion for API consumers, align the YAML parameter name with the code (unconn
) or vice versa.
igraph_diameter_bound:
src/paths/unweighted.c:608
- No unit tests cover
igraph_distances_1
. Please add tests for this new helper to ensure correct behavior, including unreachable vertices and small graphs.
igraph_error_t igraph_distances_1(const igraph_adjlist_t *adjlist, igraph_vector_t *res, igraph_integer_t from) {
src/paths/dijkstra.c:254
igraph_distances_dijkstra_1
is introduced without any tests. Add unit tests that validate single‐source weighted distances, negative/NaN weight handling, and empty graphs.
igraph_error_t igraph_distances_dijkstra_1(const igraph_t *graph,
// component cannot increase the lower bound. So we can safely skip it | ||
// without exploring | ||
if (!weights && igraph_set_size(¤t_component) <= *diameter) { | ||
break; |
Copilot
AI
Jul 2, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using break
here exits the outer while (!igraph_set_empty(&to_inspect))
loop, so later components are never inspected. Replace break
with continue
to skip only this component.
break; | |
continue; |
Copilot uses AI. Check for mistakes.
Retargeting for 1.1 as it is not API-breaking and we need to clear the issue list for the 1.0 milestone now that we are getting closer to the release date. |
Implements #2684