feat: support betweenness centrality algorithm (#801)#818
Conversation
97fc5fc to
aa9802a
Compare
| arr[SIGMA] = 1; | ||
| arr[FORWARDED] = 1; | ||
| Map<String, Object> state = newState(); | ||
| Map<Object, double[]> st = (Map<Object, double[]>) state.get("st"); |
There was a problem hiding this comment.
Thank you for your valuable contribution. I have some suggestions regarding this code and would like to discuss them with you.
Problem: The per-source states st (Map<Object, double[]>) and preds are kept in the vertex state. The current implementation does not release the corresponding entries after a source completes, causing them to accumulate and resulting in uncontrollable O(V^2) memory usage.
Suggestion: When a source's BACKWARD_DONE is set, immediately clear the entry for that source in st and preds (freeing up memory). It's possible to maintain a touched collection to only iterate over the sources actually involved (more efficient), but the minimum fix is to remove it after completion.
Here is a code example for reference; you might find it helpful.
// --- Insert/Replace Front: Safely Read or Initialize State ---
Map<String, Object> state;
if (updatedValues != null && updatedValues.isPresent()) {
state = (Map<String, Object>) updatedValues.get().getField(0, null);
if (state == null) {
state = newState();
}
} else {
/ // The vertex doesn't have a state yet, safely initialize it (so subsequent logic can rely on a non-null state)
state = newState();
}
double bc = 0.0;
if (state.get("bc") != null) {
bc = (Double) state.get("bc");
} final Map<Object, double[]> st = (Map<Object, double[]>) state.get("st");
| boolean childCountFinal = forwarded && arr[RESP_COUNT] >= outDegree; | ||
| if (childCountFinal && arr[RECV_CHILD] >= arr[CHILD_COUNT]) { | ||
| double sigma = arr[SIGMA]; | ||
| double delta = sigma * arr[PENDING_SUM]; |
There was a problem hiding this comment.
Problem: Calculating value = (1.0 + delta) / sigma and delta = sigma * pendingSum lacks protection against sigma == 0 (theoretically, sigma == 0 represents unaccessed data or an abnormal count), leading to division by zero or NaN.
Recommendation: Perform a sigma == 0 check (or sigma < eps) before using sigma for division; in this case, mark the source as complete and skip sending backwardMsg.
| } else if (tag == ACK) { | ||
| double[] arr = st.get(source); | ||
| if (arr != null) { | ||
| arr[CHILD_COUNT]++; |
There was a problem hiding this comment.
Robustness of ACK/NACK and Response Count
Issue: The logic for RESP_COUNT and CHILD_COUNT currently relies on outDegree(outEdges.size()) as the expected number of responses. However, in scenarios with directed graphs, parallel edges, or different edge loading methods, this may not be a strict match, leading to premature or delayed entry into the backward phase.
Recommendation: Record "how many forward messages have been sent to neighbors (actual childCandidates)" instead of directly using outDegree, or determine whether all responses have been received based on the touchedNeighbors set.
|
Hello @ArmxG, thank you for your valuable contribution! I've been a bit busy lately and just saw your code. I'm leaving some comments for you to review. Please feel free to point out any issues you find unreasonable. |
What this PR does
Adds a built-in Betweenness Centrality graph algorithm (UDGA), as requested in #801. The algorithm computes the betweenness centrality score for every vertex and outputs
(id, betweenness).Approach
This implementation uses a vertex-centric version of Brandes' algorithm with every vertex treated as a source.
sigma) and record predecessor information. ACK/NACK messages allow each vertex to determine when all child responses have been received.delta) from the leaves back to the source, accumulating each vertex's betweenness centrality score.Per-source state is stored in the vertex value, following the same design pattern as
AllSourceShortestPath. The algorithm has O(V·E) time complexity and O(V²) space complexity.Tests
gql_algorithm_betweenness.sqland its expected output, verified against the standard Brandes algorithm.testAlgorithmBetweennessCentralitytoGQLAlgorithmTest.