Skip to content

Commit 9462fac

Browse files
committed
Add community metrics Modularity and Conductance
1 parent 7527c74 commit 9462fac

7 files changed

+152
-32
lines changed

cypher/Community_Detection/Community_Detection_7d_Modularity_Members.cypher

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ CALL gds.modularity.stream(
2525
RETURN communityId
2626
,memberModularity
2727
,memberCount
28-
,shortMemberNames
29-
,memberNames
28+
,shortMemberNames[0..9] AS someMemberNamesShort
29+
,memberNames[0..9] AS someMemberNames
3030
ORDER BY communityId ASCENDING
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// Community Detection Conductance
2+
3+
CALL gds.conductance.stream(
4+
$dependencies_projection + '-cleaned', {
5+
relationshipWeightProperty: $dependencies_projection_weight_property
6+
,communityProperty: $dependencies_projection_write_property
7+
})
8+
YIELD community, conductance
9+
RETURN community, conductance
10+
ORDER BY community ASCENDING
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Community Detection Conductance Members
2+
3+
CALL gds.conductance.stream(
4+
$dependencies_projection + '-cleaned', {
5+
relationshipWeightProperty: $dependencies_projection_weight_property
6+
,communityProperty: $dependencies_projection_write_property
7+
})
8+
YIELD community AS communityId, conductance
9+
WITH collect({communityId: communityId, conductance: conductance}) AS communityMetrics
10+
MATCH (member)
11+
WHERE member[$dependencies_projection_write_property] IS NOT NULL
12+
AND $dependencies_projection_node IN LABELS(member)
13+
WITH communityMetrics
14+
,member[$dependencies_projection_write_property] AS communityId
15+
,coalesce(member.fqn, member.fileName, member.name) AS memberName
16+
,coalesce(member.name, replace(last(split(member.fileName, '/')), '.jar', '')) AS shortMemberName
17+
WITH communityMetrics
18+
,communityId
19+
,count(DISTINCT memberName) AS memberCount
20+
,collect(DISTINCT shortMemberName) AS shortMemberNames
21+
,collect(DISTINCT memberName) AS memberNames
22+
,reduce(memberConductance = 0, conductance IN communityMetrics |
23+
CASE conductance.communityId WHEN communityId THEN conductance.conductance
24+
ELSE memberConductance END) AS conductance
25+
RETURN communityId
26+
,conductance
27+
,memberCount
28+
,shortMemberNames[0..9] AS someMemberNamesShort
29+
,memberNames[0..9] AS someMemberNames
30+
ORDER BY communityId ASCENDING
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Community Metrics
2+
3+
CALL gds.conductance.stream(
4+
$dependencies_projection + '-cleaned', {
5+
relationshipWeightProperty: $dependencies_projection_weight_property
6+
,communityProperty: $dependencies_projection_write_property
7+
})
8+
YIELD community AS communityId, conductance
9+
WITH collect({communityId: communityId, conductance: conductance}) AS conductances
10+
CALL gds.modularity.stream(
11+
$dependencies_projection + '-cleaned', {
12+
relationshipWeightProperty: $dependencies_projection_weight_property
13+
,communityProperty: $dependencies_projection_write_property
14+
})
15+
YIELD communityId, modularity
16+
WITH conductances
17+
,collect({communityId: communityId, modularity: modularity}) AS modularities
18+
MATCH (member)
19+
WHERE member[$dependencies_projection_write_property] IS NOT NULL
20+
AND $dependencies_projection_node IN LABELS(member)
21+
WITH conductances
22+
,modularities
23+
,member[$dependencies_projection_write_property] AS communityId
24+
,coalesce(member.fqn, member.fileName, member.name) AS memberName
25+
,coalesce(member.name, replace(last(split(member.fileName, '/')), '.jar', '')) AS shortMemberName
26+
WITH conductances
27+
,modularities
28+
,communityId
29+
,count(DISTINCT memberName) AS memberCount
30+
,collect(DISTINCT shortMemberName) AS shortMemberNames
31+
,collect(DISTINCT memberName) AS memberNames
32+
,reduce(memberConductance = 0, conductance IN conductances |
33+
CASE conductance.communityId WHEN communityId THEN conductance.conductance
34+
ELSE memberConductance END) AS conductance
35+
,reduce(memberModularity = 0, modularity IN modularities |
36+
CASE modularity.communityId WHEN communityId THEN modularity.modularity
37+
ELSE memberModularity END) AS modularity
38+
RETURN communityId
39+
,conductance
40+
,modularity
41+
,memberCount
42+
,shortMemberNames[0..9] AS someMemberNamesShort
43+
,memberNames[0..9] AS someMemberNames
44+
ORDER BY communityId ASCENDING

cypher/Community_Detection_Label_Propagation.cypher

Lines changed: 0 additions & 9 deletions
This file was deleted.

cypher/Community_Detection_Weakly_Connected_Components.cypher

Lines changed: 0 additions & 9 deletions
This file was deleted.

scripts/reports/CommunityCsv.sh

Lines changed: 66 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ detectCommunitiesWithLouvain() {
113113
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyNameIntermediate}"
114114
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
115115
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
116+
117+
calculateCommunityMetrics "${@}" "${writePropertyName}"
116118
}
117119

118120
# Community Detection using the Leiden Algorithm
@@ -157,19 +159,8 @@ detectCommunitiesWithLeiden() {
157159
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyNameIntermediate}"
158160
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
159161
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
160-
}
161162

162-
# Write modularity for Leiden communities
163-
#
164-
# Required Parameters:
165-
# - dependencies_projection=...
166-
# Name prefix for the in-memory projection name for dependencies. Example: "package"
167-
# - dependencies_projection_weight_property=...
168-
# Name of the node property that contains the dependency weight. Example: "weight"
169-
writeLeidenModularity() {
170-
local COMMUNITY_DETECTION_CYPHER_DIR="${CYPHER_DIR}/Community_Detection"
171-
local writePropertyName="dependencies_projection_write_property=communityLeidenId"
172-
execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_7e_Write_Modularity.cypher" "${@}" "${writePropertyName}"
163+
calculateCommunityMetrics "${@}" "${writePropertyName}"
173164
}
174165

175166
# Community Detection using the Weakly Connected Components Algorithm
@@ -205,6 +196,8 @@ detectCommunitiesWithWeaklyConnectedComponents() {
205196
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyName}"
206197
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
207198
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
199+
200+
calculateCommunityMetrics "${@}" "${writePropertyName}"
208201
}
209202

210203
# Community Detection using the Label Propagation Algorithm
@@ -240,6 +233,8 @@ detectCommunitiesWithLabelPropagation() {
240233
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyName}"
241234
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
242235
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
236+
237+
calculateCommunityMetrics "${@}" "${writePropertyName}"
243238
}
244239

245240
# Community Detection using the K-Core Decomposition Algorithm
@@ -274,6 +269,8 @@ detectCommunitiesWithKCoreDecomposition() {
274269
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyName}"
275270
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
276271
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
272+
273+
calculateCommunityMetrics "${@}" "${writePropertyName}"
277274
}
278275

279276
# Community Detection using the Approximate Maximum k-cut Algorithm
@@ -310,6 +307,63 @@ detectCommunitiesWithApproximateMaximumKCut() {
310307
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_9_Write_Mutated.cypher" "${@}" "${writePropertyName}"
311308
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_10_Delete_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
312309
execute_cypher "${PROJECTION_CYPHER_DIR}/Dependencies_11_Add_Label.cypher" "${@}" "${writePropertyName}" "${writeLabelName}"
310+
311+
calculateCommunityMetrics "${@}" "${writePropertyName}"
312+
}
313+
314+
# Calculates community metrics including "Modularity" and "Conductance".
315+
#
316+
#
317+
# Required Parameters:
318+
# - dependencies_projection=...
319+
# Name prefix for the in-memory projection name for dependencies. Example: "package"
320+
# - writePropertyName=...
321+
# Name of the property that contains the communitiy id
322+
# - dependencies_projection_weight_property=...
323+
# Name of the node property that contains the dependency weight. Example: "weight"
324+
calculateCommunityMetrics() {
325+
local COMMUNITY_DETECTION_CYPHER_DIR="${CYPHER_DIR}/Community_Detection"
326+
327+
local nodeLabel
328+
nodeLabel=$( extractQueryParameter "dependencies_projection_node" "${@}")
329+
330+
local propertyName
331+
propertyName=$( extractQueryParameter "dependencies_projection_write_property" "${@}")
332+
333+
local fileNamePrefix
334+
fileNamePrefix="${FULL_REPORT_DIRECTORY}/${nodeLabel}_${propertyName}_Community_"
335+
336+
# Print results to CSV
337+
local combinedMetrics
338+
if combinedMetrics=$( execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_9_Community_Metrics.cypher" "${@}" ); then
339+
echo "${combinedMetrics}" > "${fileNamePrefix}_Metrics.csv"
340+
else
341+
# Combined metrics failed. Trying one by one at least get those that doesn't fail.
342+
local modularity
343+
if modularity=$( execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_7d_Modularity_Members.cypher" "${@}" ); then
344+
echo "${modularity}" > "${fileNamePrefix}_Modularity.csv"
345+
fi
346+
local conductance
347+
if conductance=$( execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_8d_Conductance_Members.cypher" "${@}" ); then
348+
echo "${conductance}" > "${fileNamePrefix}_Conductance.csv"
349+
fi
350+
fi
351+
# Continue even if there were metrics that failed since they aren't essential
352+
# and there seem to be open issues like:
353+
# gds.modularity.stream ArrayIndexOutOfBoundsException: Index -1 out of bounds for length 100
354+
}
355+
356+
# Write modularity for Leiden communities
357+
#
358+
# Required Parameters:
359+
# - dependencies_projection=...
360+
# Name prefix for the in-memory projection name for dependencies. Example: "package"
361+
# - dependencies_projection_weight_property=...
362+
# Name of the node property that contains the dependency weight. Example: "weight"
363+
writeLeidenModularity() {
364+
local COMMUNITY_DETECTION_CYPHER_DIR="${CYPHER_DIR}/Community_Detection"
365+
local writePropertyName="dependencies_projection_write_property=communityLeidenId"
366+
execute_cypher "${COMMUNITY_DETECTION_CYPHER_DIR}/Community_Detection_7e_Write_Modularity.cypher" "${@}" "${writePropertyName}"
313367
}
314368

315369
# Compare the results of different community detection algorighms

0 commit comments

Comments
 (0)