@@ -23,53 +23,12 @@ public static IReadOnlyList<CommunityRecord> Build(
2323 return Array . Empty < CommunityRecord > ( ) ;
2424 }
2525
26- var adjacency = BuildAdjacency ( entities , relationships ) ;
2726 var titleLookup = entities . ToDictionary ( entity => entity . Title , StringComparer . OrdinalIgnoreCase ) ;
28- var random = new Random ( config . Seed ) ;
29-
30- var orderedTitles = titleLookup . Keys
31- . OrderBy ( _ => random . Next ( ) )
32- . ToList ( ) ;
33-
34- var visited = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
35- var components = new List < List < string > > ( ) ;
36-
37- foreach ( var title in orderedTitles )
27+ var components = config . Algorithm switch
3828 {
39- if ( ! visited . Add ( title ) )
40- {
41- continue ;
42- }
43-
44- var component = new List < string > ( ) ;
45- var queue = new Queue < string > ( ) ;
46- queue . Enqueue ( title ) ;
47-
48- while ( queue . Count > 0 )
49- {
50- var current = queue . Dequeue ( ) ;
51- component . Add ( current ) ;
52-
53- if ( ! adjacency . TryGetValue ( current , out var neighbors ) || neighbors . Count == 0 )
54- {
55- continue ;
56- }
57-
58- var orderedNeighbors = neighbors
59- . OrderBy ( _ => random . Next ( ) )
60- . ToList ( ) ;
61-
62- foreach ( var neighbor in orderedNeighbors )
63- {
64- if ( visited . Add ( neighbor ) )
65- {
66- queue . Enqueue ( neighbor ) ;
67- }
68- }
69- }
70-
71- components . Add ( component ) ;
72- }
29+ CommunityDetectionAlgorithm . FastLabelPropagation => BuildUsingLabelPropagation ( entities , relationships , config ) ,
30+ _ => BuildUsingConnectedComponents ( entities , relationships , config )
31+ } ;
7332
7433 if ( config . UseLargestConnectedComponent && components . Count > 0 )
7534 {
@@ -183,6 +142,90 @@ public static IReadOnlyList<CommunityRecord> Build(
183142 return communityRecords ;
184143 }
185144
145+ private static List < List < string > > BuildUsingConnectedComponents (
146+ IReadOnlyList < EntityRecord > entities ,
147+ IReadOnlyList < RelationshipRecord > relationships ,
148+ ClusterGraphConfig config )
149+ {
150+ var adjacency = BuildAdjacency ( entities , relationships ) ;
151+ var random = new Random ( config . Seed ) ;
152+ var orderedTitles = adjacency . Keys
153+ . OrderBy ( _ => random . Next ( ) )
154+ . ToList ( ) ;
155+
156+ var visited = new HashSet < string > ( StringComparer . OrdinalIgnoreCase ) ;
157+ var components = new List < List < string > > ( ) ;
158+
159+ foreach ( var title in orderedTitles )
160+ {
161+ if ( ! visited . Add ( title ) )
162+ {
163+ continue ;
164+ }
165+
166+ var component = new List < string > ( ) ;
167+ var queue = new Queue < string > ( ) ;
168+ queue . Enqueue ( title ) ;
169+
170+ while ( queue . Count > 0 )
171+ {
172+ var current = queue . Dequeue ( ) ;
173+ component . Add ( current ) ;
174+
175+ if ( ! adjacency . TryGetValue ( current , out var neighbors ) || neighbors . Count == 0 )
176+ {
177+ continue ;
178+ }
179+
180+ var orderedNeighbors = neighbors
181+ . OrderBy ( _ => random . Next ( ) )
182+ . ToList ( ) ;
183+
184+ foreach ( var neighbor in orderedNeighbors . Where ( visited . Add ) )
185+ {
186+ queue . Enqueue ( neighbor ) ;
187+ }
188+ }
189+
190+ components . Add ( component ) ;
191+ }
192+
193+ return components ;
194+ }
195+
196+ private static List < List < string > > BuildUsingLabelPropagation (
197+ IReadOnlyList < EntityRecord > entities ,
198+ IReadOnlyList < RelationshipRecord > relationships ,
199+ ClusterGraphConfig config )
200+ {
201+ var assignments = FastLabelPropagationCommunityDetector . AssignLabels ( entities , relationships , config ) ;
202+ if ( assignments . Count == 0 )
203+ {
204+ return new List < List < string > > ( ) ;
205+ }
206+
207+ var groups = new Dictionary < string , List < string > > ( StringComparer . OrdinalIgnoreCase ) ;
208+
209+ foreach ( var pair in assignments )
210+ {
211+ if ( ! groups . TryGetValue ( pair . Value , out var members ) )
212+ {
213+ members = new List < string > ( ) ;
214+ groups [ pair . Value ] = members ;
215+ }
216+
217+ members . Add ( pair . Key ) ;
218+ }
219+
220+ return groups . Values
221+ . Select ( list => list
222+ . Distinct ( StringComparer . OrdinalIgnoreCase )
223+ . OrderBy ( title => title , StringComparer . OrdinalIgnoreCase )
224+ . ToList ( ) )
225+ . Where ( list => list . Count > 0 )
226+ . ToList ( ) ;
227+ }
228+
186229 private static Dictionary < string , HashSet < string > > BuildAdjacency (
187230 IReadOnlyList < EntityRecord > entities ,
188231 IReadOnlyList < RelationshipRecord > relationships )
0 commit comments