@@ -138,6 +138,46 @@ public async Task ExecuteAsync_IsolatedNodes_GetOwnCommunities()
138138 Assert . Equal ( 3 , communities . Count ) ;
139139 }
140140
141+ [ Fact ]
142+ public async Task ExecuteAsync_ParallelEdges_AggregatesWeightsWithoutBreakingCommunities ( )
143+ {
144+ // Arrange
145+ var options = new ClusterOptions { MaxIterations = 100 } ;
146+ var engine = new ClusterEngine ( options ) ;
147+
148+ var graph = new KnowledgeGraph ( ) ;
149+ var node1 = CreateNode ( "a" , "A" ) ;
150+ var node2 = CreateNode ( "b" , "B" ) ;
151+ var node3 = CreateNode ( "c" , "C" ) ;
152+
153+ graph . AddNode ( node1 ) ;
154+ graph . AddNode ( node2 ) ;
155+ graph . AddNode ( node3 ) ;
156+
157+ // Add repeated edges between the same nodes to exercise weighted-adjacency aggregation.
158+ graph . AddEdge ( CreateEdge ( node1 , node2 , 1.0 ) ) ;
159+ graph . AddEdge ( CreateEdge ( node1 , node2 , 2.0 ) ) ;
160+ graph . AddEdge ( CreateEdge ( node2 , node3 , 1.5 ) ) ;
161+ graph . AddEdge ( CreateEdge ( node2 , node3 , 2.5 ) ) ;
162+ graph . AddEdge ( CreateEdge ( node1 , node3 , 1.0 ) ) ;
163+ graph . AddEdge ( CreateEdge ( node1 , node3 , 1.0 ) ) ;
164+
165+ // Act
166+ var result = await engine . ExecuteAsync ( graph ) ;
167+
168+ // Assert
169+ var communities = result . GetNodes ( )
170+ . Where ( n => n . Community . HasValue )
171+ . Select ( n => n . Community ! . Value )
172+ . Distinct ( )
173+ . ToList ( ) ;
174+
175+ Assert . Equal ( 3 , result . NodeCount ) ;
176+ Assert . Equal ( 3 , result . GetNodes ( ) . Count ( n => n . Community . HasValue ) ) ;
177+ Assert . NotEmpty ( communities ) ;
178+ Assert . True ( communities . Count <= 2 , "Dense triangle with parallel edges should stay in one dense cluster." ) ;
179+ }
180+
141181 [ Fact ]
142182 public async Task ExecuteAsync_EmptyGraph_ReturnsUnchanged ( )
143183 {
0 commit comments