arela
Version:
AI-powered CTO with multi-agent orchestration, code summarization, visual testing (web + mobile) for blazing fast development.
116 lines • 3.55 kB
JavaScript
/**
* Modularity calculations for slice cohesion
*/
/**
* Calculate cohesion score for a community (0-100)
* Cohesion = internal edges / (internal edges + external edges) * 100
*/
export function calculateCohesion(community, graph) {
const internal = countInternalEdges(community, graph);
const external = countExternalEdges(community, graph);
const total = internal + external;
if (total === 0) {
return 100; // Isolated community
}
return (internal / total) * 100;
}
/**
* Calculate overall modularity of the clustering
*/
export function calculateModularityScore(communities, graph) {
const m = graph.edges.length;
if (m === 0)
return 0;
let Q = 0;
for (const community of communities) {
if (community.nodes.length === 0)
continue;
const eIn = countInternalEdges(community, graph);
const degree = getTotalDegree(community, graph);
Q += eIn / m - Math.pow(degree / (2 * m), 2);
}
return Q;
}
/**
* Count edges within a community
*/
function countInternalEdges(community, graph) {
const nodeSet = new Set(community.nodes);
let count = 0;
for (const edge of graph.edges) {
if (nodeSet.has(edge.from) && nodeSet.has(edge.to)) {
count += edge.weight;
}
}
return count;
}
/**
* Count edges going out of a community
*/
function countExternalEdges(community, graph) {
const nodeSet = new Set(community.nodes);
let count = 0;
for (const edge of graph.edges) {
const fromIn = nodeSet.has(edge.from);
const toIn = nodeSet.has(edge.to);
if ((fromIn && !toIn) || (!fromIn && toIn)) {
count += edge.weight;
}
}
return count;
}
/**
* Get total degree of nodes in a community
*/
function getTotalDegree(community, graph) {
let totalDegree = 0;
for (const nodeId of community.nodes) {
const node = graph.nodes.find((n) => n.id === nodeId);
if (node) {
totalDegree += node.degree;
}
}
return totalDegree;
}
/**
* Calculate coupling between two communities
*/
export function calculateCoupling(comm1, comm2, graph) {
const set1 = new Set(comm1.nodes);
const set2 = new Set(comm2.nodes);
let edges = 0;
for (const edge of graph.edges) {
if ((set1.has(edge.from) && set2.has(edge.to)) ||
(set1.has(edge.to) && set2.has(edge.from))) {
edges += edge.weight;
}
}
return edges;
}
/**
* Calculate average cohesion across all communities
*/
export function calculateAverageCohesion(communities, graph) {
if (communities.length === 0)
return 0;
const totalCohesion = communities.reduce((sum, comm) => sum + calculateCohesion(comm, graph), 0);
return totalCohesion / communities.length;
}
/**
* Get statistics about communities
*/
export function getCommunitiesStats(communities, graph) {
const sizes = communities.map((c) => c.nodes.length);
const cohesions = communities.map((c) => calculateCohesion(c, graph));
return {
count: communities.length,
avgSize: sizes.reduce((a, b) => a + b, 0) / communities.length,
minSize: Math.min(...sizes),
maxSize: Math.max(...sizes),
avgCohesion: cohesions.reduce((a, b) => a + b, 0) / communities.length,
minCohesion: Math.min(...cohesions),
maxCohesion: Math.max(...cohesions),
modularity: calculateModularityScore(communities, graph),
};
}
//# sourceMappingURL=modularity.js.map