Skip to content

Refactor graph traversal methods to use new computeTraversalPartitions API#3753

Open
clementleclercRTE wants to merge 28 commits intomainfrom
graph-connected-components
Open

Refactor graph traversal methods to use new computeTraversalPartitions API#3753
clementleclercRTE wants to merge 28 commits intomainfrom
graph-connected-components

Conversation

@clementleclercRTE
Copy link
Contributor

@clementleclercRTE clementleclercRTE commented Feb 3, 2026

Please check if the PR fulfills these requirements

  • The commit message follows our guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)
  • [ ] A PR or issue has been opened in all impacted repositories (if any)

Does this PR already have an issue describing the problem?

What kind of change does this PR introduce?

Refactoring / New API

What is the current behavior?

Currently, BusBreakerTopologyModel, NodeBreakerTopologyModel, and DcTopologyModel all contain duplicated logic to traverse the graph and identify connected components (bus construction).

What is the new behavior (if this is a feature change)?

A new method computeTraversalPartitions has been introduced in the UndirectedGraph interface. It centralizes the graph traversal and connected component building logic, using standard
functional interfaces (Supplier, ObjIntConsumer) for flexibility. The three topology models have been refactored to use this shared method.

The previously public method traverse(int, TraversalType, Traverser, boolean[]) is now deprecated in favor of traverse(int, TraversalType, Traverser) and
computeTraversalPartitions(...).

Does this PR introduce a breaking change or deprecate an API?

  • Yes
  • No

If yes, please check if the following requirements are fulfilled

  • The Breaking Change or Deprecated label has been added
  • The migration steps are described in the following section

What changes might users need to make in their application due to this PR? (migration steps)

1. Deprecated: traverse(int, TraversalType, Traverser, boolean[])

If you were using this overload to manually track visited vertices, switch to the standard traverse(int, TraversalType, Traverser) overload. Visited vertices can be captured directly inside your
Traverser lambda.

2. Manual connected component computation

If you were manually implementing the traversal-and-partition pattern (iterating over vertices, tracking visited state, grouping results), you can now replace this logic with a call to
computeTraversalPartitions(Traverser) or its generic overload computeTraversalPartitions(Traverser, Supplier<C>, ObjIntConsumer<C>).

Other information:

…API.

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
…API.

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
… graph-connected-components

# Conflicts:
#	iidm/iidm-impl/src/main/java/com/powsybl/iidm/network/impl/NodeBreakerTopologyModel.java
@rolnico rolnico changed the title Refactor graph traversal methods to use new getConnectedComponents Refactor graph traversal methods to use new getConnectedComponents API Feb 3, 2026
… traversal components.

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
…Predicate`

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
…` API, and enhance vertex object handling in graph traversal implementations.

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Feb 9, 2026

}
return TraverseResult.CONTINUE;
}).forEach(nodes -> {
CopyOnWriteArrayList<NodeTerminal> terminals = new CopyOnWriteArrayList<>();
Copy link
Collaborator

Choose a reason for hiding this comment

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

I'm wondering if we really need the CopyOnWriteArrayList for buses

…comments

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
…comments

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
Copy link
Collaborator

@flo-dup flo-dup left a comment

Choose a reason for hiding this comment

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

The naming is questionable, as we're not computing connected component if we rely on graph theory definition. We should rather call it something like computeTraversalPartitions, as we're partitioning the graph (all the vertices are traversed if there's no TERMINATE_TRAVERSER return) based on a given traversal.

C component = collector.createComponent();
collector.addVertex(component, v);

traverse(v, TraversalType.BREADTH_FIRST, (v1, e, v2) -> {
Copy link
Collaborator

Choose a reason for hiding this comment

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

If traverse returns false, shouldn't we break?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed. Note that TERMINATE_TRAVERSER should not normally be used here.
Using TERMINATE_TRAVERSER would result in an incomplete partition. The break is just a safety net.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Your note should be included in the javadoc of computeTraversalPartitions

… update related tests, topology models, and traversal logic.

Signed-off-by: Leclerc Clement <clement.leclerc@rte-france.com>
@flo-dup flo-dup changed the title Refactor graph traversal methods to use new getConnectedComponents API Refactor graph traversal methods to use new computeTraversalPartitions API Mar 3, 2026

private void traverseVertex(int vToTraverse, boolean[] vEncountered, Deque<DirectedEdge> edgesToTraverse,
TIntArrayList[] adjacencyList, TraversalType traversalType) {
TIntArrayList[] adjacencyList, TraversalType traversalType, @Nullable IntConsumer vertexVisitor) {
Copy link
Collaborator

@flo-dup flo-dup Mar 3, 2026

Choose a reason for hiding this comment

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

we usually don't need nullability annotations on private methods. Besides, a nullable functional interface is creating unnecessary complexity (my bad, I suggested you to do so in a previous comment!), you'd rather use a no-op IntConsumer instead of null

Copy link
Collaborator

Choose a reason for hiding this comment

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

Remove the use of the deprecated traverse in tests

Comment on lines +242 to +245
if (sw != null && sw.isOpen()) {
return TraverseResult.TERMINATE_PATH;
}
return TraverseResult.CONTINUE;
Copy link
Collaborator

Choose a reason for hiding this comment

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

An edge cannot be null in DcTopologyModel

Suggested change
if (sw != null && sw.isOpen()) {
return TraverseResult.TERMINATE_PATH;
}
return TraverseResult.CONTINUE;
return sw.isOpen() ? TraverseResult.TERMINATE_PATH : TraverseResult.CONTINUE;

}

private boolean traverse(int v, TraversalType traversalType, Traverser traverser, boolean[] encounteredVertices, boolean[] encounteredEdges) {
return traverse(v, traversalType, traverser, encounteredVertices, encounteredEdges, null);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
return traverse(v, traversalType, traverser, encounteredVertices, encounteredEdges, null);
return traverse(v, traversalType, traverser, encounteredVertices, encounteredEdges, vIndex -> {});


void addVertex(C component, int vertexIndex);
}
<C> List<C> computeTraversalPartitions(Traverser traverser, Supplier<C> partitionFactory, ObjIntConsumer<C> vertexConsumer);
Copy link
Collaborator

Choose a reason for hiding this comment

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

You need to add javadoc to explain clearly the method and the parameters.
Besides, rename vertexConsumer into something more explicit (vertexCollector?)

@flo-dup
Copy link
Collaborator

flo-dup commented Mar 3, 2026

Could you also complete the PR description, regarding the migration guide / breaking changes part?

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 9, 2026

@clementleclercRTE clementleclercRTE added the Deprecated Methods have been deprecated label Mar 9, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Deprecated Methods have been deprecated

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants