@optave/codegraph 3.8.0 → 3.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -8
- package/dist/ast-analysis/engine.d.ts.map +1 -1
- package/dist/ast-analysis/engine.js +95 -87
- package/dist/ast-analysis/engine.js.map +1 -1
- package/dist/ast-analysis/metrics.d.ts +0 -3
- package/dist/ast-analysis/metrics.d.ts.map +1 -1
- package/dist/ast-analysis/metrics.js +30 -13
- package/dist/ast-analysis/metrics.js.map +1 -1
- package/dist/ast-analysis/shared.d.ts.map +1 -1
- package/dist/ast-analysis/shared.js +24 -19
- package/dist/ast-analysis/shared.js.map +1 -1
- package/dist/ast-analysis/visitor-utils.d.ts.map +1 -1
- package/dist/ast-analysis/visitor-utils.js +55 -39
- package/dist/ast-analysis/visitor-utils.js.map +1 -1
- package/dist/ast-analysis/visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitor.js +91 -70
- package/dist/ast-analysis/visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/ast-store-visitor.js +54 -58
- package/dist/ast-analysis/visitors/ast-store-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/complexity-visitor.js +32 -39
- package/dist/ast-analysis/visitors/complexity-visitor.js.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.d.ts.map +1 -1
- package/dist/ast-analysis/visitors/dataflow-visitor.js +57 -38
- package/dist/ast-analysis/visitors/dataflow-visitor.js.map +1 -1
- package/dist/cli/commands/watch.d.ts.map +1 -1
- package/dist/cli/commands/watch.js +16 -2
- package/dist/cli/commands/watch.js.map +1 -1
- package/dist/db/connection.d.ts.map +1 -1
- package/dist/db/connection.js +29 -26
- package/dist/db/connection.js.map +1 -1
- package/dist/db/query-builder.d.ts.map +1 -1
- package/dist/db/query-builder.js +16 -5
- package/dist/db/query-builder.js.map +1 -1
- package/dist/db/repository/base.d.ts +10 -0
- package/dist/db/repository/base.d.ts.map +1 -1
- package/dist/db/repository/base.js +17 -0
- package/dist/db/repository/base.js.map +1 -1
- package/dist/db/repository/native-repository.d.ts +6 -1
- package/dist/db/repository/native-repository.d.ts.map +1 -1
- package/dist/db/repository/native-repository.js +77 -1
- package/dist/db/repository/native-repository.js.map +1 -1
- package/dist/db/repository/nodes.d.ts.map +1 -1
- package/dist/db/repository/nodes.js +8 -4
- package/dist/db/repository/nodes.js.map +1 -1
- package/dist/db/repository/sqlite-repository.d.ts +3 -0
- package/dist/db/repository/sqlite-repository.d.ts.map +1 -1
- package/dist/db/repository/sqlite-repository.js +26 -0
- package/dist/db/repository/sqlite-repository.js.map +1 -1
- package/dist/domain/analysis/brief.d.ts.map +1 -1
- package/dist/domain/analysis/brief.js +13 -17
- package/dist/domain/analysis/brief.js.map +1 -1
- package/dist/domain/analysis/context.d.ts.map +1 -1
- package/dist/domain/analysis/context.js +14 -11
- package/dist/domain/analysis/context.js.map +1 -1
- package/dist/domain/analysis/dependencies.d.ts.map +1 -1
- package/dist/domain/analysis/dependencies.js +53 -52
- package/dist/domain/analysis/dependencies.js.map +1 -1
- package/dist/domain/analysis/fn-impact.d.ts +2 -7
- package/dist/domain/analysis/fn-impact.d.ts.map +1 -1
- package/dist/domain/analysis/fn-impact.js +33 -31
- package/dist/domain/analysis/fn-impact.js.map +1 -1
- package/dist/domain/analysis/implementations.d.ts.map +1 -1
- package/dist/domain/analysis/implementations.js +11 -19
- package/dist/domain/analysis/implementations.js.map +1 -1
- package/dist/domain/analysis/module-map.d.ts.map +1 -1
- package/dist/domain/analysis/module-map.js +55 -76
- package/dist/domain/analysis/module-map.js.map +1 -1
- package/dist/domain/analysis/query-helpers.d.ts +7 -0
- package/dist/domain/analysis/query-helpers.d.ts.map +1 -1
- package/dist/domain/analysis/query-helpers.js +15 -1
- package/dist/domain/analysis/query-helpers.js.map +1 -1
- package/dist/domain/graph/builder/pipeline.d.ts.map +1 -1
- package/dist/domain/graph/builder/pipeline.js +255 -105
- package/dist/domain/graph/builder/pipeline.js.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/build-edges.js +22 -17
- package/dist/domain/graph/builder/stages/build-edges.js.map +1 -1
- package/dist/domain/graph/builder/stages/detect-changes.js +2 -2
- package/dist/domain/graph/builder/stages/detect-changes.js.map +1 -1
- package/dist/domain/graph/builder/stages/finalize.js +2 -2
- package/dist/domain/graph/builder/stages/finalize.js.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/insert-nodes.js +32 -21
- package/dist/domain/graph/builder/stages/insert-nodes.js.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.d.ts.map +1 -1
- package/dist/domain/graph/builder/stages/resolve-imports.js +95 -84
- package/dist/domain/graph/builder/stages/resolve-imports.js.map +1 -1
- package/dist/domain/graph/cycles.d.ts +6 -0
- package/dist/domain/graph/cycles.d.ts.map +1 -1
- package/dist/domain/graph/cycles.js +114 -22
- package/dist/domain/graph/cycles.js.map +1 -1
- package/dist/domain/graph/resolve.js +1 -1
- package/dist/domain/graph/resolve.js.map +1 -1
- package/dist/domain/graph/watcher.d.ts +2 -0
- package/dist/domain/graph/watcher.d.ts.map +1 -1
- package/dist/domain/graph/watcher.js +170 -75
- package/dist/domain/graph/watcher.js.map +1 -1
- package/dist/domain/parser.d.ts +0 -5
- package/dist/domain/parser.d.ts.map +1 -1
- package/dist/domain/parser.js +13 -28
- package/dist/domain/parser.js.map +1 -1
- package/dist/domain/search/generator.js +1 -1
- package/dist/domain/search/generator.js.map +1 -1
- package/dist/domain/search/models.d.ts +4 -3
- package/dist/domain/search/models.d.ts.map +1 -1
- package/dist/domain/search/models.js +18 -5
- package/dist/domain/search/models.js.map +1 -1
- package/dist/domain/search/search/hybrid.d.ts.map +1 -1
- package/dist/domain/search/search/hybrid.js +29 -18
- package/dist/domain/search/search/hybrid.js.map +1 -1
- package/dist/extractors/go.js +36 -33
- package/dist/extractors/go.js.map +1 -1
- package/dist/extractors/helpers.d.ts.map +1 -1
- package/dist/extractors/helpers.js +40 -29
- package/dist/extractors/helpers.js.map +1 -1
- package/dist/extractors/java.js +58 -46
- package/dist/extractors/java.js.map +1 -1
- package/dist/extractors/javascript.js +46 -45
- package/dist/extractors/javascript.js.map +1 -1
- package/dist/extractors/kotlin.js +84 -78
- package/dist/extractors/kotlin.js.map +1 -1
- package/dist/extractors/python.js +29 -24
- package/dist/extractors/python.js.map +1 -1
- package/dist/extractors/rust.js +41 -32
- package/dist/extractors/rust.js.map +1 -1
- package/dist/extractors/solidity.js +58 -67
- package/dist/extractors/solidity.js.map +1 -1
- package/dist/extractors/swift.js +83 -81
- package/dist/extractors/swift.js.map +1 -1
- package/dist/extractors/zig.js +58 -60
- package/dist/extractors/zig.js.map +1 -1
- package/dist/features/ast.d.ts +16 -14
- package/dist/features/ast.d.ts.map +1 -1
- package/dist/features/ast.js +83 -81
- package/dist/features/ast.js.map +1 -1
- package/dist/features/audit.d.ts.map +1 -1
- package/dist/features/audit.js +8 -6
- package/dist/features/audit.js.map +1 -1
- package/dist/features/branch-compare.d.ts.map +1 -1
- package/dist/features/branch-compare.js +69 -72
- package/dist/features/branch-compare.js.map +1 -1
- package/dist/features/communities.d.ts.map +1 -1
- package/dist/features/communities.js +19 -7
- package/dist/features/communities.js.map +1 -1
- package/dist/features/complexity.d.ts.map +1 -1
- package/dist/features/complexity.js +120 -125
- package/dist/features/complexity.js.map +1 -1
- package/dist/features/dataflow.d.ts.map +1 -1
- package/dist/features/dataflow.js +136 -137
- package/dist/features/dataflow.js.map +1 -1
- package/dist/features/flow.d.ts.map +1 -1
- package/dist/features/flow.js +84 -79
- package/dist/features/flow.js.map +1 -1
- package/dist/features/structure-query.d.ts.map +1 -1
- package/dist/features/structure-query.js +69 -65
- package/dist/features/structure-query.js.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/optimiser.js +70 -55
- package/dist/graph/algorithms/leiden/optimiser.js.map +1 -1
- package/dist/graph/algorithms/leiden/partition.d.ts.map +1 -1
- package/dist/graph/algorithms/leiden/partition.js +288 -266
- package/dist/graph/algorithms/leiden/partition.js.map +1 -1
- package/dist/graph/model.d.ts.map +1 -1
- package/dist/graph/model.js +5 -1
- package/dist/graph/model.js.map +1 -1
- package/dist/infrastructure/config.d.ts.map +1 -1
- package/dist/infrastructure/config.js +6 -4
- package/dist/infrastructure/config.js.map +1 -1
- package/dist/infrastructure/suppress.d.ts +25 -0
- package/dist/infrastructure/suppress.d.ts.map +1 -0
- package/dist/infrastructure/suppress.js +43 -0
- package/dist/infrastructure/suppress.js.map +1 -0
- package/dist/mcp/server.d.ts.map +1 -1
- package/dist/mcp/server.js +29 -24
- package/dist/mcp/server.js.map +1 -1
- package/dist/presentation/dataflow.d.ts.map +1 -1
- package/dist/presentation/dataflow.js +47 -38
- package/dist/presentation/dataflow.js.map +1 -1
- package/dist/presentation/diff-impact-mermaid.d.ts.map +1 -1
- package/dist/presentation/diff-impact-mermaid.js +60 -51
- package/dist/presentation/diff-impact-mermaid.js.map +1 -1
- package/dist/presentation/queries-cli/exports.d.ts.map +1 -1
- package/dist/presentation/queries-cli/exports.js +20 -14
- package/dist/presentation/queries-cli/exports.js.map +1 -1
- package/dist/presentation/queries-cli/impact.d.ts.map +1 -1
- package/dist/presentation/queries-cli/impact.js +15 -13
- package/dist/presentation/queries-cli/impact.js.map +1 -1
- package/dist/presentation/queries-cli/inspect.d.ts.map +1 -1
- package/dist/presentation/queries-cli/inspect.js +101 -79
- package/dist/presentation/queries-cli/inspect.js.map +1 -1
- package/dist/presentation/queries-cli/overview.d.ts.map +1 -1
- package/dist/presentation/queries-cli/overview.js +25 -16
- package/dist/presentation/queries-cli/overview.js.map +1 -1
- package/dist/presentation/queries-cli/path.js +26 -20
- package/dist/presentation/queries-cli/path.js.map +1 -1
- package/dist/presentation/result-formatter.d.ts +10 -0
- package/dist/presentation/result-formatter.d.ts.map +1 -1
- package/dist/presentation/result-formatter.js +16 -1
- package/dist/presentation/result-formatter.js.map +1 -1
- package/dist/presentation/viewer.d.ts.map +1 -1
- package/dist/presentation/viewer.js +18 -12
- package/dist/presentation/viewer.js.map +1 -1
- package/dist/shared/errors.d.ts +5 -0
- package/dist/shared/errors.d.ts.map +1 -1
- package/dist/shared/errors.js +5 -0
- package/dist/shared/errors.js.map +1 -1
- package/dist/shared/hierarchy.d.ts +8 -2
- package/dist/shared/hierarchy.d.ts.map +1 -1
- package/dist/shared/hierarchy.js +42 -1
- package/dist/shared/hierarchy.js.map +1 -1
- package/dist/shared/normalize.d.ts +6 -1
- package/dist/shared/normalize.d.ts.map +1 -1
- package/dist/shared/normalize.js +20 -12
- package/dist/shared/normalize.js.map +1 -1
- package/dist/shared/paginate.d.ts +0 -9
- package/dist/shared/paginate.d.ts.map +1 -1
- package/dist/shared/paginate.js +0 -15
- package/dist/shared/paginate.js.map +1 -1
- package/dist/types.d.ts +10 -4
- package/dist/types.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/ast-analysis/engine.ts +126 -105
- package/src/ast-analysis/metrics.ts +33 -11
- package/src/ast-analysis/shared.ts +33 -24
- package/src/ast-analysis/visitor-utils.ts +52 -32
- package/src/ast-analysis/visitor.ts +132 -71
- package/src/ast-analysis/visitors/ast-store-visitor.ts +53 -50
- package/src/ast-analysis/visitors/complexity-visitor.ts +35 -40
- package/src/ast-analysis/visitors/dataflow-visitor.ts +87 -43
- package/src/cli/commands/watch.ts +16 -2
- package/src/db/connection.ts +29 -28
- package/src/db/query-builder.ts +15 -3
- package/src/db/repository/base.ts +20 -0
- package/src/db/repository/native-repository.ts +79 -1
- package/src/db/repository/nodes.ts +13 -8
- package/src/db/repository/sqlite-repository.ts +29 -0
- package/src/domain/analysis/brief.ts +15 -25
- package/src/domain/analysis/context.ts +17 -10
- package/src/domain/analysis/dependencies.ts +67 -76
- package/src/domain/analysis/fn-impact.ts +36 -43
- package/src/domain/analysis/implementations.ts +11 -17
- package/src/domain/analysis/module-map.ts +58 -92
- package/src/domain/analysis/query-helpers.ts +18 -1
- package/src/domain/graph/builder/pipeline.ts +286 -97
- package/src/domain/graph/builder/stages/build-edges.ts +22 -18
- package/src/domain/graph/builder/stages/detect-changes.ts +2 -2
- package/src/domain/graph/builder/stages/finalize.ts +2 -2
- package/src/domain/graph/builder/stages/insert-nodes.ts +59 -34
- package/src/domain/graph/builder/stages/resolve-imports.ts +122 -100
- package/src/domain/graph/cycles.ts +110 -23
- package/src/domain/graph/resolve.ts +1 -1
- package/src/domain/graph/watcher.ts +202 -96
- package/src/domain/parser.ts +14 -26
- package/src/domain/search/generator.ts +1 -1
- package/src/domain/search/models.ts +17 -4
- package/src/domain/search/search/hybrid.ts +69 -51
- package/src/extractors/go.ts +43 -33
- package/src/extractors/helpers.ts +37 -23
- package/src/extractors/java.ts +66 -47
- package/src/extractors/javascript.ts +45 -46
- package/src/extractors/kotlin.ts +84 -77
- package/src/extractors/python.ts +31 -25
- package/src/extractors/rust.ts +37 -29
- package/src/extractors/solidity.ts +57 -61
- package/src/extractors/swift.ts +81 -80
- package/src/extractors/zig.ts +58 -61
- package/src/features/ast.ts +130 -110
- package/src/features/audit.ts +8 -6
- package/src/features/branch-compare.ts +105 -79
- package/src/features/communities.ts +25 -10
- package/src/features/complexity.ts +171 -134
- package/src/features/dataflow.ts +165 -175
- package/src/features/flow.ts +129 -92
- package/src/features/structure-query.ts +79 -64
- package/src/graph/algorithms/leiden/optimiser.ts +99 -55
- package/src/graph/algorithms/leiden/partition.ts +359 -294
- package/src/graph/model.ts +6 -1
- package/src/infrastructure/config.ts +6 -4
- package/src/infrastructure/suppress.ts +47 -0
- package/src/mcp/server.ts +53 -37
- package/src/presentation/dataflow.ts +50 -44
- package/src/presentation/diff-impact-mermaid.ts +104 -62
- package/src/presentation/queries-cli/exports.ts +21 -13
- package/src/presentation/queries-cli/impact.ts +15 -13
- package/src/presentation/queries-cli/inspect.ts +100 -81
- package/src/presentation/queries-cli/overview.ts +26 -16
- package/src/presentation/queries-cli/path.ts +33 -25
- package/src/presentation/result-formatter.ts +19 -1
- package/src/presentation/viewer.ts +42 -14
- package/src/shared/errors.ts +6 -0
- package/src/shared/hierarchy.ts +50 -2
- package/src/shared/normalize.ts +31 -12
- package/src/shared/paginate.ts +0 -17
- package/src/types.ts +24 -4
|
@@ -56,6 +56,34 @@ function u8get(a: Uint8Array, i: number): number {
|
|
|
56
56
|
return a[i] as number;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/* ------------------------------------------------------------------ */
|
|
60
|
+
/* Internal mutable state bucket shared by all extracted functions */
|
|
61
|
+
/* ------------------------------------------------------------------ */
|
|
62
|
+
|
|
63
|
+
interface PartitionState {
|
|
64
|
+
graph: GraphAdapter;
|
|
65
|
+
n: number;
|
|
66
|
+
nodeCommunity: Int32Array;
|
|
67
|
+
communityCount: number;
|
|
68
|
+
communityTotalSize: Float64Array;
|
|
69
|
+
communityNodeCount: Int32Array;
|
|
70
|
+
communityInternalEdgeWeight: Float64Array;
|
|
71
|
+
communityTotalStrength: Float64Array;
|
|
72
|
+
communityTotalOutStrength: Float64Array;
|
|
73
|
+
communityTotalInStrength: Float64Array;
|
|
74
|
+
/* scratch arrays for neighbor accumulation */
|
|
75
|
+
candidateCommunities: Int32Array;
|
|
76
|
+
candidateCommunityCount: number;
|
|
77
|
+
neighborEdgeWeightToCommunity: Float64Array;
|
|
78
|
+
outEdgeWeightToCommunity: Float64Array;
|
|
79
|
+
inEdgeWeightFromCommunity: Float64Array;
|
|
80
|
+
isCandidateCommunity: Uint8Array;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* ------------------------------------------------------------------ */
|
|
84
|
+
/* Aggregate helpers (shared by initializeAggregates & compact) */
|
|
85
|
+
/* ------------------------------------------------------------------ */
|
|
86
|
+
|
|
59
87
|
/**
|
|
60
88
|
* Accumulate per-community node-level totals (size, count, strength) into the
|
|
61
89
|
* provided aggregate arrays. Both `initializeAggregates` and `compactCommunityIds`
|
|
@@ -159,343 +187,380 @@ function buildSortedCommunityIds(
|
|
|
159
187
|
}
|
|
160
188
|
}
|
|
161
189
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
for (let i = 0; i < n; i++) nodeCommunity[i] = i;
|
|
166
|
-
let communityCount: number = n;
|
|
167
|
-
|
|
168
|
-
let communityTotalSize = new Float64Array(communityCount);
|
|
169
|
-
let communityNodeCount = new Int32Array(communityCount);
|
|
170
|
-
let communityInternalEdgeWeight = new Float64Array(communityCount);
|
|
171
|
-
let communityTotalStrength = new Float64Array(communityCount);
|
|
172
|
-
let communityTotalOutStrength = new Float64Array(communityCount);
|
|
173
|
-
let communityTotalInStrength = new Float64Array(communityCount);
|
|
174
|
-
|
|
175
|
-
const candidateCommunities = new Int32Array(n);
|
|
176
|
-
let candidateCommunityCount: number = 0;
|
|
177
|
-
const neighborEdgeWeightToCommunity = new Float64Array(n);
|
|
178
|
-
const outEdgeWeightToCommunity = new Float64Array(n);
|
|
179
|
-
const inEdgeWeightFromCommunity = new Float64Array(n);
|
|
180
|
-
const isCandidateCommunity = new Uint8Array(n);
|
|
181
|
-
|
|
182
|
-
function ensureCommCapacity(newCount: number): void {
|
|
183
|
-
if (newCount <= communityTotalSize.length) return;
|
|
184
|
-
const growTo: number = Math.max(newCount, Math.ceil(communityTotalSize.length * 1.5));
|
|
185
|
-
communityTotalSize = growFloat(communityTotalSize, growTo);
|
|
186
|
-
communityNodeCount = growInt(communityNodeCount, growTo);
|
|
187
|
-
communityInternalEdgeWeight = growFloat(communityInternalEdgeWeight, growTo);
|
|
188
|
-
communityTotalStrength = growFloat(communityTotalStrength, growTo);
|
|
189
|
-
communityTotalOutStrength = growFloat(communityTotalOutStrength, growTo);
|
|
190
|
-
communityTotalInStrength = growFloat(communityTotalInStrength, growTo);
|
|
191
|
-
}
|
|
190
|
+
/* ------------------------------------------------------------------ */
|
|
191
|
+
/* Extracted: capacity management */
|
|
192
|
+
/* ------------------------------------------------------------------ */
|
|
192
193
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
194
|
+
function ensureCommCapacity(s: PartitionState, newCount: number): void {
|
|
195
|
+
if (newCount <= s.communityTotalSize.length) return;
|
|
196
|
+
const growTo: number = Math.max(newCount, Math.ceil(s.communityTotalSize.length * 1.5));
|
|
197
|
+
s.communityTotalSize = growFloat(s.communityTotalSize, growTo);
|
|
198
|
+
s.communityNodeCount = growInt(s.communityNodeCount, growTo);
|
|
199
|
+
s.communityInternalEdgeWeight = growFloat(s.communityInternalEdgeWeight, growTo);
|
|
200
|
+
s.communityTotalStrength = growFloat(s.communityTotalStrength, growTo);
|
|
201
|
+
s.communityTotalOutStrength = growFloat(s.communityTotalOutStrength, growTo);
|
|
202
|
+
s.communityTotalInStrength = growFloat(s.communityTotalInStrength, growTo);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* ------------------------------------------------------------------ */
|
|
206
|
+
/* Extracted: aggregate initialization */
|
|
207
|
+
/* ------------------------------------------------------------------ */
|
|
208
|
+
|
|
209
|
+
function initAggregates(s: PartitionState): void {
|
|
210
|
+
s.communityTotalSize.fill(0);
|
|
211
|
+
s.communityNodeCount.fill(0);
|
|
212
|
+
s.communityInternalEdgeWeight.fill(0);
|
|
213
|
+
s.communityTotalStrength.fill(0);
|
|
214
|
+
s.communityTotalOutStrength.fill(0);
|
|
215
|
+
s.communityTotalInStrength.fill(0);
|
|
216
|
+
accumulateNodeAggregates(
|
|
217
|
+
s.graph,
|
|
218
|
+
s.nodeCommunity,
|
|
219
|
+
s.n,
|
|
220
|
+
s.communityTotalSize,
|
|
221
|
+
s.communityNodeCount,
|
|
222
|
+
s.communityInternalEdgeWeight,
|
|
223
|
+
s.communityTotalStrength,
|
|
224
|
+
s.communityTotalOutStrength,
|
|
225
|
+
s.communityTotalInStrength,
|
|
226
|
+
);
|
|
227
|
+
accumulateInternalEdgeWeights(s.graph, s.nodeCommunity, s.n, s.communityInternalEdgeWeight);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* ------------------------------------------------------------------ */
|
|
231
|
+
/* Extracted: neighbor accumulation */
|
|
232
|
+
/* ------------------------------------------------------------------ */
|
|
233
|
+
|
|
234
|
+
function resetScratch(s: PartitionState): void {
|
|
235
|
+
for (let i = 0; i < s.candidateCommunityCount; i++) {
|
|
236
|
+
const c: number = iget(s.candidateCommunities, i);
|
|
237
|
+
s.isCandidateCommunity[c] = 0;
|
|
238
|
+
s.neighborEdgeWeightToCommunity[c] = 0;
|
|
239
|
+
s.outEdgeWeightToCommunity[c] = 0;
|
|
240
|
+
s.inEdgeWeightFromCommunity[c] = 0;
|
|
212
241
|
}
|
|
242
|
+
s.candidateCommunityCount = 0;
|
|
243
|
+
}
|
|
213
244
|
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
245
|
+
function touchCandidate(s: PartitionState, c: number): void {
|
|
246
|
+
if (u8get(s.isCandidateCommunity, c)) return;
|
|
247
|
+
s.isCandidateCommunity[c] = 1;
|
|
248
|
+
s.candidateCommunities[s.candidateCommunityCount++] = c;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function accumulateNeighborWeights(s: PartitionState, v: number): number {
|
|
252
|
+
resetScratch(s);
|
|
253
|
+
const ci: number = iget(s.nodeCommunity, v);
|
|
254
|
+
touchCandidate(s, ci);
|
|
255
|
+
if (s.graph.directed) {
|
|
256
|
+
const outL = s.graph.outEdges[v]!;
|
|
257
|
+
for (let k = 0; k < outL.length; k++) {
|
|
258
|
+
const j: number = outL[k]!.to;
|
|
259
|
+
const w: number = outL[k]!.w;
|
|
260
|
+
const cj: number = iget(s.nodeCommunity, j);
|
|
261
|
+
touchCandidate(s, cj);
|
|
262
|
+
s.outEdgeWeightToCommunity[cj] = fget(s.outEdgeWeightToCommunity, cj) + w;
|
|
263
|
+
}
|
|
264
|
+
const inL = s.graph.inEdges[v]!;
|
|
265
|
+
for (let k = 0; k < inL.length; k++) {
|
|
266
|
+
const i2: number = inL[k]!.from;
|
|
267
|
+
const w: number = inL[k]!.w;
|
|
268
|
+
const ci2: number = iget(s.nodeCommunity, i2);
|
|
269
|
+
touchCandidate(s, ci2);
|
|
270
|
+
s.inEdgeWeightFromCommunity[ci2] = fget(s.inEdgeWeightFromCommunity, ci2) + w;
|
|
271
|
+
}
|
|
272
|
+
} else {
|
|
273
|
+
const list = s.graph.outEdges[v]!;
|
|
274
|
+
for (let k = 0; k < list.length; k++) {
|
|
275
|
+
const j: number = list[k]!.to;
|
|
276
|
+
const w: number = list[k]!.w;
|
|
277
|
+
const cj: number = iget(s.nodeCommunity, j);
|
|
278
|
+
touchCandidate(s, cj);
|
|
279
|
+
s.neighborEdgeWeightToCommunity[cj] = fget(s.neighborEdgeWeightToCommunity, cj) + w;
|
|
221
280
|
}
|
|
222
|
-
candidateCommunityCount = 0;
|
|
223
281
|
}
|
|
282
|
+
return s.candidateCommunityCount;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
/* ------------------------------------------------------------------ */
|
|
286
|
+
/* Extracted: modularity delta computations */
|
|
287
|
+
/* ------------------------------------------------------------------ */
|
|
224
288
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
289
|
+
function computeDeltaModularityUndirected(
|
|
290
|
+
s: PartitionState,
|
|
291
|
+
v: number,
|
|
292
|
+
newC: number,
|
|
293
|
+
gamma: number = 1.0,
|
|
294
|
+
): number {
|
|
295
|
+
const oldC: number = iget(s.nodeCommunity, v);
|
|
296
|
+
if (newC === oldC) return 0;
|
|
297
|
+
const twoM: number = s.graph.totalWeight;
|
|
298
|
+
const strengthV: number = fget(s.graph.strengthOut, v);
|
|
299
|
+
const weightToNew: number =
|
|
300
|
+
newC < s.neighborEdgeWeightToCommunity.length
|
|
301
|
+
? fget(s.neighborEdgeWeightToCommunity, newC) || 0
|
|
302
|
+
: 0;
|
|
303
|
+
const weightToOld: number = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
|
|
304
|
+
const totalStrengthNew: number =
|
|
305
|
+
newC < s.communityTotalStrength.length ? fget(s.communityTotalStrength, newC) : 0;
|
|
306
|
+
const totalStrengthOld: number = fget(s.communityTotalStrength, oldC);
|
|
307
|
+
const gain_remove: number = -(
|
|
308
|
+
weightToOld / twoM -
|
|
309
|
+
(gamma * (strengthV * totalStrengthOld)) / (twoM * twoM)
|
|
310
|
+
);
|
|
311
|
+
const gain_add: number =
|
|
312
|
+
weightToNew / twoM - (gamma * (strengthV * totalStrengthNew)) / (twoM * twoM);
|
|
313
|
+
return gain_remove + gain_add;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
function computeDeltaModularityDirected(
|
|
317
|
+
s: PartitionState,
|
|
318
|
+
v: number,
|
|
319
|
+
newC: number,
|
|
320
|
+
gamma: number = 1.0,
|
|
321
|
+
): number {
|
|
322
|
+
const oldC: number = iget(s.nodeCommunity, v);
|
|
323
|
+
if (newC === oldC) return 0;
|
|
324
|
+
const totalEdgeWeight: number = s.graph.totalWeight;
|
|
325
|
+
const strengthOutV: number = fget(s.graph.strengthOut, v);
|
|
326
|
+
const strengthInV: number = fget(s.graph.strengthIn, v);
|
|
327
|
+
const inFromNew: number =
|
|
328
|
+
newC < s.inEdgeWeightFromCommunity.length ? fget(s.inEdgeWeightFromCommunity, newC) || 0 : 0;
|
|
329
|
+
const outToNew: number =
|
|
330
|
+
newC < s.outEdgeWeightToCommunity.length ? fget(s.outEdgeWeightToCommunity, newC) || 0 : 0;
|
|
331
|
+
const inFromOld: number = fget(s.inEdgeWeightFromCommunity, oldC) || 0;
|
|
332
|
+
const outToOld: number = fget(s.outEdgeWeightToCommunity, oldC) || 0;
|
|
333
|
+
const totalInStrengthNew: number =
|
|
334
|
+
newC < s.communityTotalInStrength.length ? fget(s.communityTotalInStrength, newC) : 0;
|
|
335
|
+
const totalOutStrengthNew: number =
|
|
336
|
+
newC < s.communityTotalOutStrength.length ? fget(s.communityTotalOutStrength, newC) : 0;
|
|
337
|
+
const totalInStrengthOld: number = fget(s.communityTotalInStrength, oldC);
|
|
338
|
+
const totalOutStrengthOld: number = fget(s.communityTotalOutStrength, oldC);
|
|
339
|
+
// Self-loop correction + constant term (see modularity.ts diffModularityDirected)
|
|
340
|
+
const selfW: number = fget(s.graph.selfLoop, v) || 0;
|
|
341
|
+
const deltaInternal: number =
|
|
342
|
+
(inFromNew + outToNew - inFromOld - outToOld + 2 * selfW) / totalEdgeWeight;
|
|
343
|
+
const deltaExpected: number =
|
|
344
|
+
(gamma *
|
|
345
|
+
(strengthOutV * (totalInStrengthNew - totalInStrengthOld) +
|
|
346
|
+
strengthInV * (totalOutStrengthNew - totalOutStrengthOld) +
|
|
347
|
+
2 * strengthOutV * strengthInV)) /
|
|
348
|
+
(totalEdgeWeight * totalEdgeWeight);
|
|
349
|
+
return deltaInternal - deltaExpected;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function computeDeltaCPM(s: PartitionState, v: number, newC: number, gamma: number = 1.0): number {
|
|
353
|
+
const oldC: number = iget(s.nodeCommunity, v);
|
|
354
|
+
if (newC === oldC) return 0;
|
|
355
|
+
let w_old: number;
|
|
356
|
+
let w_new: number;
|
|
357
|
+
let selfCorrection: number = 0;
|
|
358
|
+
if (s.graph.directed) {
|
|
359
|
+
w_old =
|
|
360
|
+
(fget(s.outEdgeWeightToCommunity, oldC) || 0) +
|
|
361
|
+
(fget(s.inEdgeWeightFromCommunity, oldC) || 0);
|
|
362
|
+
w_new =
|
|
363
|
+
newC < s.outEdgeWeightToCommunity.length
|
|
364
|
+
? (fget(s.outEdgeWeightToCommunity, newC) || 0) +
|
|
365
|
+
(fget(s.inEdgeWeightFromCommunity, newC) || 0)
|
|
366
|
+
: 0;
|
|
367
|
+
// Self-loop correction (see cpm.ts diffCPM)
|
|
368
|
+
selfCorrection = 2 * (fget(s.graph.selfLoop, v) || 0);
|
|
369
|
+
} else {
|
|
370
|
+
w_old = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
|
|
371
|
+
w_new =
|
|
372
|
+
newC < s.neighborEdgeWeightToCommunity.length
|
|
373
|
+
? fget(s.neighborEdgeWeightToCommunity, newC) || 0
|
|
374
|
+
: 0;
|
|
229
375
|
}
|
|
376
|
+
const nodeSz: number = fget(s.graph.size, v) || 1;
|
|
377
|
+
const sizeOld: number = fget(s.communityTotalSize, oldC) || 0;
|
|
378
|
+
const sizeNew: number = newC < s.communityTotalSize.length ? fget(s.communityTotalSize, newC) : 0;
|
|
379
|
+
return w_new - w_old + selfCorrection - gamma * nodeSz * (sizeNew - sizeOld + nodeSz);
|
|
380
|
+
}
|
|
230
381
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
touch(cj);
|
|
242
|
-
outEdgeWeightToCommunity[cj] = fget(outEdgeWeightToCommunity, cj) + w;
|
|
243
|
-
}
|
|
244
|
-
const inL = graph.inEdges[v]!;
|
|
245
|
-
for (let k = 0; k < inL.length; k++) {
|
|
246
|
-
const i2: number = inL[k]!.from;
|
|
247
|
-
const w: number = inL[k]!.w;
|
|
248
|
-
const ci2: number = iget(nodeCommunity, i2);
|
|
249
|
-
touch(ci2);
|
|
250
|
-
inEdgeWeightFromCommunity[ci2] = fget(inEdgeWeightFromCommunity, ci2) + w;
|
|
251
|
-
}
|
|
252
|
-
} else {
|
|
253
|
-
const list = graph.outEdges[v]!;
|
|
254
|
-
for (let k = 0; k < list.length; k++) {
|
|
255
|
-
const j: number = list[k]!.to;
|
|
256
|
-
const w: number = list[k]!.w;
|
|
257
|
-
const cj: number = iget(nodeCommunity, j);
|
|
258
|
-
touch(cj);
|
|
259
|
-
neighborEdgeWeightToCommunity[cj] = fget(neighborEdgeWeightToCommunity, cj) + w;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
return candidateCommunityCount;
|
|
382
|
+
/* ------------------------------------------------------------------ */
|
|
383
|
+
/* Extracted: node move */
|
|
384
|
+
/* ------------------------------------------------------------------ */
|
|
385
|
+
|
|
386
|
+
function moveNode(s: PartitionState, v: number, newC: number): boolean {
|
|
387
|
+
const oldC: number = iget(s.nodeCommunity, v);
|
|
388
|
+
if (oldC === newC) return false;
|
|
389
|
+
if (newC >= s.communityCount) {
|
|
390
|
+
ensureCommCapacity(s, newC + 1);
|
|
391
|
+
s.communityCount = newC + 1;
|
|
263
392
|
}
|
|
393
|
+
const strengthOutV: number = fget(s.graph.strengthOut, v);
|
|
394
|
+
const strengthInV: number = fget(s.graph.strengthIn, v);
|
|
395
|
+
const selfLoopWeight: number = fget(s.graph.selfLoop, v);
|
|
396
|
+
const nodeSz: number = fget(s.graph.size, v);
|
|
264
397
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const totalStrengthOld: number = fget(communityTotalStrength, oldC);
|
|
278
|
-
const gain_remove: number = -(
|
|
279
|
-
weightToOld / twoMUndirected -
|
|
280
|
-
(gamma * (strengthV * totalStrengthOld)) / (twoMUndirected * twoMUndirected)
|
|
281
|
-
);
|
|
282
|
-
const gain_add: number =
|
|
283
|
-
weightToNew / twoMUndirected -
|
|
284
|
-
(gamma * (strengthV * totalStrengthNew)) / (twoMUndirected * twoMUndirected);
|
|
285
|
-
return gain_remove + gain_add;
|
|
398
|
+
s.communityNodeCount[oldC] = iget(s.communityNodeCount, oldC) - 1;
|
|
399
|
+
s.communityNodeCount[newC] = iget(s.communityNodeCount, newC) + 1;
|
|
400
|
+
s.communityTotalSize[oldC] = fget(s.communityTotalSize, oldC) - nodeSz;
|
|
401
|
+
s.communityTotalSize[newC] = fget(s.communityTotalSize, newC) + nodeSz;
|
|
402
|
+
if (s.graph.directed) {
|
|
403
|
+
s.communityTotalOutStrength[oldC] = fget(s.communityTotalOutStrength, oldC) - strengthOutV;
|
|
404
|
+
s.communityTotalOutStrength[newC] = fget(s.communityTotalOutStrength, newC) + strengthOutV;
|
|
405
|
+
s.communityTotalInStrength[oldC] = fget(s.communityTotalInStrength, oldC) - strengthInV;
|
|
406
|
+
s.communityTotalInStrength[newC] = fget(s.communityTotalInStrength, newC) + strengthInV;
|
|
407
|
+
} else {
|
|
408
|
+
s.communityTotalStrength[oldC] = fget(s.communityTotalStrength, oldC) - strengthOutV;
|
|
409
|
+
s.communityTotalStrength[newC] = fget(s.communityTotalStrength, newC) + strengthOutV;
|
|
286
410
|
}
|
|
287
411
|
|
|
288
|
-
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
const totalEdgeWeight: number = graph.totalWeight;
|
|
292
|
-
const strengthOutV: number = fget(graph.strengthOut, v);
|
|
293
|
-
const strengthInV: number = fget(graph.strengthIn, v);
|
|
294
|
-
const inFromNew: number =
|
|
295
|
-
newC < inEdgeWeightFromCommunity.length ? fget(inEdgeWeightFromCommunity, newC) || 0 : 0;
|
|
412
|
+
if (s.graph.directed) {
|
|
413
|
+
const outToOld: number = fget(s.outEdgeWeightToCommunity, oldC) || 0;
|
|
414
|
+
const inFromOld: number = fget(s.inEdgeWeightFromCommunity, oldC) || 0;
|
|
296
415
|
const outToNew: number =
|
|
297
|
-
newC < outEdgeWeightToCommunity.length ? fget(outEdgeWeightToCommunity, newC) || 0 : 0;
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
const
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
strengthInV * (totalOutStrengthNew - totalOutStrengthOld) +
|
|
314
|
-
2 * strengthOutV * strengthInV)) /
|
|
315
|
-
(totalEdgeWeight * totalEdgeWeight);
|
|
316
|
-
return deltaInternal - deltaExpected;
|
|
416
|
+
newC < s.outEdgeWeightToCommunity.length ? fget(s.outEdgeWeightToCommunity, newC) || 0 : 0;
|
|
417
|
+
const inFromNew: number =
|
|
418
|
+
newC < s.inEdgeWeightFromCommunity.length ? fget(s.inEdgeWeightFromCommunity, newC) || 0 : 0;
|
|
419
|
+
// outToOld/inFromOld already include the self-loop weight (self-loops are
|
|
420
|
+
// in outEdges/inEdges), so subtract it once to avoid triple-counting.
|
|
421
|
+
s.communityInternalEdgeWeight[oldC] =
|
|
422
|
+
fget(s.communityInternalEdgeWeight, oldC) - (outToOld + inFromOld - selfLoopWeight);
|
|
423
|
+
s.communityInternalEdgeWeight[newC] =
|
|
424
|
+
fget(s.communityInternalEdgeWeight, newC) + (outToNew + inFromNew + selfLoopWeight);
|
|
425
|
+
} else {
|
|
426
|
+
const weightToOld: number = fget(s.neighborEdgeWeightToCommunity, oldC) || 0;
|
|
427
|
+
const weightToNew: number = fget(s.neighborEdgeWeightToCommunity, newC) || 0;
|
|
428
|
+
s.communityInternalEdgeWeight[oldC] =
|
|
429
|
+
fget(s.communityInternalEdgeWeight, oldC) - (2 * weightToOld + selfLoopWeight);
|
|
430
|
+
s.communityInternalEdgeWeight[newC] =
|
|
431
|
+
fget(s.communityInternalEdgeWeight, newC) + (2 * weightToNew + selfLoopWeight);
|
|
317
432
|
}
|
|
318
433
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
let w_old: number;
|
|
323
|
-
let w_new: number;
|
|
324
|
-
let selfCorrection: number = 0;
|
|
325
|
-
if (graph.directed) {
|
|
326
|
-
w_old =
|
|
327
|
-
(fget(outEdgeWeightToCommunity, oldC) || 0) + (fget(inEdgeWeightFromCommunity, oldC) || 0);
|
|
328
|
-
w_new =
|
|
329
|
-
newC < outEdgeWeightToCommunity.length
|
|
330
|
-
? (fget(outEdgeWeightToCommunity, newC) || 0) +
|
|
331
|
-
(fget(inEdgeWeightFromCommunity, newC) || 0)
|
|
332
|
-
: 0;
|
|
333
|
-
// Self-loop correction (see cpm.ts diffCPM)
|
|
334
|
-
selfCorrection = 2 * (fget(graph.selfLoop, v) || 0);
|
|
335
|
-
} else {
|
|
336
|
-
w_old = fget(neighborEdgeWeightToCommunity, oldC) || 0;
|
|
337
|
-
w_new =
|
|
338
|
-
newC < neighborEdgeWeightToCommunity.length
|
|
339
|
-
? fget(neighborEdgeWeightToCommunity, newC) || 0
|
|
340
|
-
: 0;
|
|
341
|
-
}
|
|
342
|
-
const nodeSz: number = fget(graph.size, v) || 1;
|
|
343
|
-
const sizeOld: number = fget(communityTotalSize, oldC) || 0;
|
|
344
|
-
const sizeNew: number = newC < communityTotalSize.length ? fget(communityTotalSize, newC) : 0;
|
|
345
|
-
return w_new - w_old + selfCorrection - gamma * nodeSz * (sizeNew - sizeOld + nodeSz);
|
|
346
|
-
}
|
|
434
|
+
s.nodeCommunity[v] = newC;
|
|
435
|
+
return true;
|
|
436
|
+
}
|
|
347
437
|
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
if (newC >= communityCount) {
|
|
352
|
-
ensureCommCapacity(newC + 1);
|
|
353
|
-
communityCount = newC + 1;
|
|
354
|
-
}
|
|
355
|
-
const strengthOutV: number = fget(graph.strengthOut, v);
|
|
356
|
-
const strengthInV: number = fget(graph.strengthIn, v);
|
|
357
|
-
const selfLoopWeight: number = fget(graph.selfLoop, v);
|
|
358
|
-
const nodeSz: number = fget(graph.size, v);
|
|
359
|
-
|
|
360
|
-
communityNodeCount[oldC] = iget(communityNodeCount, oldC) - 1;
|
|
361
|
-
communityNodeCount[newC] = iget(communityNodeCount, newC) + 1;
|
|
362
|
-
communityTotalSize[oldC] = fget(communityTotalSize, oldC) - nodeSz;
|
|
363
|
-
communityTotalSize[newC] = fget(communityTotalSize, newC) + nodeSz;
|
|
364
|
-
if (graph.directed) {
|
|
365
|
-
communityTotalOutStrength[oldC] = fget(communityTotalOutStrength, oldC) - strengthOutV;
|
|
366
|
-
communityTotalOutStrength[newC] = fget(communityTotalOutStrength, newC) + strengthOutV;
|
|
367
|
-
communityTotalInStrength[oldC] = fget(communityTotalInStrength, oldC) - strengthInV;
|
|
368
|
-
communityTotalInStrength[newC] = fget(communityTotalInStrength, newC) + strengthInV;
|
|
369
|
-
} else {
|
|
370
|
-
communityTotalStrength[oldC] = fget(communityTotalStrength, oldC) - strengthOutV;
|
|
371
|
-
communityTotalStrength[newC] = fget(communityTotalStrength, newC) + strengthOutV;
|
|
372
|
-
}
|
|
438
|
+
/* ------------------------------------------------------------------ */
|
|
439
|
+
/* Extracted: community compaction */
|
|
440
|
+
/* ------------------------------------------------------------------ */
|
|
373
441
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
newC < outEdgeWeightToCommunity.length ? fget(outEdgeWeightToCommunity, newC) || 0 : 0;
|
|
379
|
-
const inFromNew: number =
|
|
380
|
-
newC < inEdgeWeightFromCommunity.length ? fget(inEdgeWeightFromCommunity, newC) || 0 : 0;
|
|
381
|
-
// outToOld/inFromOld already include the self-loop weight (self-loops are
|
|
382
|
-
// in outEdges/inEdges), so subtract it once to avoid triple-counting.
|
|
383
|
-
communityInternalEdgeWeight[oldC] =
|
|
384
|
-
fget(communityInternalEdgeWeight, oldC) - (outToOld + inFromOld - selfLoopWeight);
|
|
385
|
-
communityInternalEdgeWeight[newC] =
|
|
386
|
-
fget(communityInternalEdgeWeight, newC) + (outToNew + inFromNew + selfLoopWeight);
|
|
387
|
-
} else {
|
|
388
|
-
const weightToOld: number = fget(neighborEdgeWeightToCommunity, oldC) || 0;
|
|
389
|
-
const weightToNew: number = fget(neighborEdgeWeightToCommunity, newC) || 0;
|
|
390
|
-
communityInternalEdgeWeight[oldC] =
|
|
391
|
-
fget(communityInternalEdgeWeight, oldC) - (2 * weightToOld + selfLoopWeight);
|
|
392
|
-
communityInternalEdgeWeight[newC] =
|
|
393
|
-
fget(communityInternalEdgeWeight, newC) + (2 * weightToNew + selfLoopWeight);
|
|
394
|
-
}
|
|
442
|
+
function compactIds(s: PartitionState, opts: CompactOptions = {}): void {
|
|
443
|
+
const ids: number[] = [];
|
|
444
|
+
for (let c = 0; c < s.communityCount; c++) if (iget(s.communityNodeCount, c) > 0) ids.push(c);
|
|
445
|
+
buildSortedCommunityIds(ids, opts, s.communityTotalSize, s.communityNodeCount);
|
|
395
446
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
447
|
+
const newId = new Int32Array(s.communityCount).fill(-1);
|
|
448
|
+
ids.forEach((c, i) => {
|
|
449
|
+
newId[c] = i;
|
|
450
|
+
});
|
|
451
|
+
for (let i = 0; i < s.nodeCommunity.length; i++)
|
|
452
|
+
s.nodeCommunity[i] = iget(newId, iget(s.nodeCommunity, i));
|
|
399
453
|
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
454
|
+
const remappedCount: number = ids.length;
|
|
455
|
+
const newTotalSize = new Float64Array(remappedCount);
|
|
456
|
+
const newNodeCount = new Int32Array(remappedCount);
|
|
457
|
+
const newInternalEdgeWeight = new Float64Array(remappedCount);
|
|
458
|
+
const newTotalStrength = new Float64Array(remappedCount);
|
|
459
|
+
const newTotalOutStrength = new Float64Array(remappedCount);
|
|
460
|
+
const newTotalInStrength = new Float64Array(remappedCount);
|
|
461
|
+
accumulateNodeAggregates(
|
|
462
|
+
s.graph,
|
|
463
|
+
s.nodeCommunity,
|
|
464
|
+
s.n,
|
|
465
|
+
newTotalSize,
|
|
466
|
+
newNodeCount,
|
|
467
|
+
newInternalEdgeWeight,
|
|
468
|
+
newTotalStrength,
|
|
469
|
+
newTotalOutStrength,
|
|
470
|
+
newTotalInStrength,
|
|
471
|
+
);
|
|
472
|
+
accumulateInternalEdgeWeights(s.graph, s.nodeCommunity, s.n, newInternalEdgeWeight);
|
|
404
473
|
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
const newTotalSize = new Float64Array(remappedCount);
|
|
414
|
-
const newNodeCount = new Int32Array(remappedCount);
|
|
415
|
-
const newInternalEdgeWeight = new Float64Array(remappedCount);
|
|
416
|
-
const newTotalStrength = new Float64Array(remappedCount);
|
|
417
|
-
const newTotalOutStrength = new Float64Array(remappedCount);
|
|
418
|
-
const newTotalInStrength = new Float64Array(remappedCount);
|
|
419
|
-
accumulateNodeAggregates(
|
|
420
|
-
graph,
|
|
421
|
-
nodeCommunity,
|
|
422
|
-
n,
|
|
423
|
-
newTotalSize,
|
|
424
|
-
newNodeCount,
|
|
425
|
-
newInternalEdgeWeight,
|
|
426
|
-
newTotalStrength,
|
|
427
|
-
newTotalOutStrength,
|
|
428
|
-
newTotalInStrength,
|
|
429
|
-
);
|
|
430
|
-
accumulateInternalEdgeWeights(graph, nodeCommunity, n, newInternalEdgeWeight);
|
|
431
|
-
|
|
432
|
-
communityCount = remappedCount;
|
|
433
|
-
communityTotalSize = newTotalSize;
|
|
434
|
-
communityNodeCount = newNodeCount;
|
|
435
|
-
communityInternalEdgeWeight = newInternalEdgeWeight;
|
|
436
|
-
communityTotalStrength = newTotalStrength;
|
|
437
|
-
communityTotalOutStrength = newTotalOutStrength;
|
|
438
|
-
communityTotalInStrength = newTotalInStrength;
|
|
439
|
-
}
|
|
474
|
+
s.communityCount = remappedCount;
|
|
475
|
+
s.communityTotalSize = newTotalSize;
|
|
476
|
+
s.communityNodeCount = newNodeCount;
|
|
477
|
+
s.communityInternalEdgeWeight = newInternalEdgeWeight;
|
|
478
|
+
s.communityTotalStrength = newTotalStrength;
|
|
479
|
+
s.communityTotalOutStrength = newTotalOutStrength;
|
|
480
|
+
s.communityTotalInStrength = newTotalInStrength;
|
|
481
|
+
}
|
|
440
482
|
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
for (let i = 0; i < n; i++) comms[iget(nodeCommunity, i)]!.push(i);
|
|
445
|
-
return comms;
|
|
446
|
-
}
|
|
483
|
+
/* ------------------------------------------------------------------ */
|
|
484
|
+
/* Factory: thin wrapper that wires state to extracted functions */
|
|
485
|
+
/* ------------------------------------------------------------------ */
|
|
447
486
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
487
|
+
export function makePartition(graph: GraphAdapter): Partition {
|
|
488
|
+
const n: number = graph.n;
|
|
489
|
+
const nodeCommunity = new Int32Array(n);
|
|
490
|
+
for (let i = 0; i < n; i++) nodeCommunity[i] = i;
|
|
491
|
+
|
|
492
|
+
const s: PartitionState = {
|
|
493
|
+
graph,
|
|
494
|
+
n,
|
|
495
|
+
nodeCommunity,
|
|
496
|
+
communityCount: n,
|
|
497
|
+
communityTotalSize: new Float64Array(n),
|
|
498
|
+
communityNodeCount: new Int32Array(n),
|
|
499
|
+
communityInternalEdgeWeight: new Float64Array(n),
|
|
500
|
+
communityTotalStrength: new Float64Array(n),
|
|
501
|
+
communityTotalOutStrength: new Float64Array(n),
|
|
502
|
+
communityTotalInStrength: new Float64Array(n),
|
|
503
|
+
candidateCommunities: new Int32Array(n),
|
|
504
|
+
candidateCommunityCount: 0,
|
|
505
|
+
neighborEdgeWeightToCommunity: new Float64Array(n),
|
|
506
|
+
outEdgeWeightToCommunity: new Float64Array(n),
|
|
507
|
+
inEdgeWeightFromCommunity: new Float64Array(n),
|
|
508
|
+
isCandidateCommunity: new Uint8Array(n),
|
|
509
|
+
};
|
|
454
510
|
|
|
455
511
|
return {
|
|
456
512
|
n,
|
|
457
513
|
get communityCount() {
|
|
458
|
-
return communityCount;
|
|
514
|
+
return s.communityCount;
|
|
459
515
|
},
|
|
460
516
|
nodeCommunity,
|
|
461
517
|
get communityTotalSize() {
|
|
462
|
-
return communityTotalSize;
|
|
518
|
+
return s.communityTotalSize;
|
|
463
519
|
},
|
|
464
520
|
get communityNodeCount() {
|
|
465
|
-
return communityNodeCount;
|
|
521
|
+
return s.communityNodeCount;
|
|
466
522
|
},
|
|
467
523
|
get communityInternalEdgeWeight() {
|
|
468
|
-
return communityInternalEdgeWeight;
|
|
524
|
+
return s.communityInternalEdgeWeight;
|
|
469
525
|
},
|
|
470
526
|
get communityTotalStrength() {
|
|
471
|
-
return communityTotalStrength;
|
|
527
|
+
return s.communityTotalStrength;
|
|
472
528
|
},
|
|
473
529
|
get communityTotalOutStrength() {
|
|
474
|
-
return communityTotalOutStrength;
|
|
530
|
+
return s.communityTotalOutStrength;
|
|
475
531
|
},
|
|
476
532
|
get communityTotalInStrength() {
|
|
477
|
-
return communityTotalInStrength;
|
|
533
|
+
return s.communityTotalInStrength;
|
|
478
534
|
},
|
|
479
535
|
resizeCommunities(newCount: number): void {
|
|
480
|
-
ensureCommCapacity(newCount);
|
|
481
|
-
communityCount = newCount;
|
|
536
|
+
ensureCommCapacity(s, newCount);
|
|
537
|
+
s.communityCount = newCount;
|
|
482
538
|
},
|
|
483
|
-
initializeAggregates,
|
|
484
|
-
accumulateNeighborCommunityEdgeWeights,
|
|
485
|
-
getCandidateCommunityCount: (): number => candidateCommunityCount,
|
|
486
|
-
getCandidateCommunityAt: (i: number): number => iget(candidateCommunities, i),
|
|
539
|
+
initializeAggregates: () => initAggregates(s),
|
|
540
|
+
accumulateNeighborCommunityEdgeWeights: (v: number) => accumulateNeighborWeights(s, v),
|
|
541
|
+
getCandidateCommunityCount: (): number => s.candidateCommunityCount,
|
|
542
|
+
getCandidateCommunityAt: (i: number): number => iget(s.candidateCommunities, i),
|
|
487
543
|
getNeighborEdgeWeightToCommunity: (c: number): number =>
|
|
488
|
-
fget(neighborEdgeWeightToCommunity, c) || 0,
|
|
489
|
-
getOutEdgeWeightToCommunity: (c: number): number => fget(outEdgeWeightToCommunity, c) || 0,
|
|
490
|
-
getInEdgeWeightFromCommunity: (c: number): number => fget(inEdgeWeightFromCommunity, c) || 0,
|
|
491
|
-
deltaModularityUndirected,
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
544
|
+
fget(s.neighborEdgeWeightToCommunity, c) || 0,
|
|
545
|
+
getOutEdgeWeightToCommunity: (c: number): number => fget(s.outEdgeWeightToCommunity, c) || 0,
|
|
546
|
+
getInEdgeWeightFromCommunity: (c: number): number => fget(s.inEdgeWeightFromCommunity, c) || 0,
|
|
547
|
+
deltaModularityUndirected: (v: number, newC: number, gamma?: number) =>
|
|
548
|
+
computeDeltaModularityUndirected(s, v, newC, gamma),
|
|
549
|
+
deltaModularityDirected: (v: number, newC: number, gamma?: number) =>
|
|
550
|
+
computeDeltaModularityDirected(s, v, newC, gamma),
|
|
551
|
+
deltaCPM: (v: number, newC: number, gamma?: number) => computeDeltaCPM(s, v, newC, gamma),
|
|
552
|
+
moveNodeToCommunity: (v: number, newC: number) => moveNode(s, v, newC),
|
|
553
|
+
compactCommunityIds: (opts?: CompactOptions) => compactIds(s, opts),
|
|
554
|
+
getCommunityMembers(): number[][] {
|
|
555
|
+
const comms: number[][] = new Array(s.communityCount);
|
|
556
|
+
for (let i = 0; i < s.communityCount; i++) comms[i] = [];
|
|
557
|
+
for (let i = 0; i < n; i++) comms[iget(nodeCommunity, i)]!.push(i);
|
|
558
|
+
return comms;
|
|
559
|
+
},
|
|
560
|
+
getCommunityTotalSize: (c: number): number =>
|
|
561
|
+
c < s.communityTotalSize.length ? fget(s.communityTotalSize, c) : 0,
|
|
562
|
+
getCommunityNodeCount: (c: number): number =>
|
|
563
|
+
c < s.communityNodeCount.length ? iget(s.communityNodeCount, c) : 0,
|
|
499
564
|
graph: undefined,
|
|
500
565
|
};
|
|
501
566
|
}
|