var minCom = Infinity;
/**
* This function calculates a measure to determine the degree of visual overlap between the communities.
* The area considered around a specific node is a square and determined by the
* filerArea. If this region contains nodes from only one community, the entropy value is 0, which means that the community
* structure is represented perfectly. If the region contains an equal mixture of all communities, the entropy value reaches
* a maximum, meaning that the community structure is not represented at all. This value is calculated for each node of the graph.
* For every node the entropy is starting at 0.
* @param {number} N Amount of nodes in the graph
* @param {number} M Amount of communities in the graph
* @param {Array} C Amount of nodes in a specific community
* @param {Array} nodes contains the nodes of the original graph
* @param {number} filterArea is the size of the area around the node
* @return {Array} array of objects, H[0] contains the global value, H[i != 0] contains local values for all other nodes.
*/
function Community_EntropyBased(N, M, C, nodes, filterArea)
{
//Global Visual Overlap Metric
var H_global = entropyMetric(M,percentage(N,C));
// Array of local Visual Overlap Metrics (defined by the size of the filter)
var H_local = localFilter(nodes, filterArea);
H_local[0] = {
x: 0,
y: 0,
comDistr: minCom//H_global
}
console.log(H_local)
return H_local;
/**
* This function calculates the percentage P(c) of nodes from community c
* @param {number} totalNodes Total Amount of Nodes (relativ to the Area)
* @param {Array} communityAmount Array of communities and the amount of nodes in them
* @returns {Array} result contains the percentage of nodes for each community
*/
function percentage(totalNodes,communityAmount) {
var result = [];
communityAmount.forEach(function (amount, community) {
result[community] = (amount/totalNodes);
});
return result;
}
/**
* This function calculates the visual overlap metric
* @param {number} communityCount Number of communities
* @param {Array} percentage percentage P(c) of nodes from community c
* @returns {number} result contains the average value of the visual overlap for the whole graph
*/
function entropyMetric(communityCount,percentage) {
var result = 0;
for (var i = 0; i < communityCount; i++) {
result = result + (percentage[i] * (Math.log(percentage[i])/Math.log(2)));
result = result * -1;
}
return result;
}
/**
* This function calculates the metric on the graph with a defined filter size (area at a specific node)
* @param {Array} nodes contains all nodes with different attributes
* @param {number} filterArea is the size of the square area around every node
* @returns {Array} H is an array containing the metric's result for every node of the graph
*/
function localFilter(nodes, filterArea) {
var region = filterArea;
//Array of Arrays
var communityAmount = [];
var H = [];
var i = 0;
for (var node in nodes)
{
i = i+1;
var nodesInsideRegion = [];
for (var n in nodes) {
if ((nodes[n].x <= nodes[node].x + region) && (nodes[n].x >= nodes[node].x - region)
&& (nodes[n].y <= nodes[node].y + region) && (nodes[n].y >= nodes[node].y - region)) {
nodesInsideRegion.push(nodes[n]);
}
}
communityAmount = countNodesInCommunities(nodesInsideRegion);
var p = localPercentage(communityAmount);
if(entropyMetric(communityAmount[0].length,p[1]) < minCom)
{
minCom = entropyMetric(communityAmount[0].length,p[1]);
}
H[i] = {
x: nodes[node].x,
y: nodes[node].y,
comDistr: entropyMetric(communityAmount[0].length,p[1])
};
}
return H;
}
/**
* This function returns the communities and the amount of nodes in the particular communities
* @param {Array} nodes contains all nodes of the graph
* @returns {Array} returns an array containing for every community the amount of nodes
*/
function countNodesInCommunities(nodes) {
//2D Array [Community, Amount of Nodes]
var communities = [];
var nodesInCommunities = [];
for (var n in nodes)
{
if(!communities.includes(nodes[n].module)){
communities.push(nodes[n].module);
nodesInCommunities.push(1);
}
else{
var pos = communities.indexOf(nodes[n].module);
nodesInCommunities[pos]= nodesInCommunities[pos] +1;
}
}
return [communities, nodesInCommunities];
}
/**
* This function calculates the local percentage P(c) of nodes from community c
* @param {Array} communityAmount is an array of arrays for communities and the amount of nodes in them [[communities], [nodesInCommunities]]
* @returns {Array} returns an array of arrays which contains for every community an percentage
*/
function localPercentage(communityAmount) {
var percent = [];
var totalNodes = 0;
// Calculate total amount of nodes
communityAmount[1].forEach(function (nodes) {
totalNodes = totalNodes + nodes;
});
for(var i = 0; i < communityAmount[0].length; i++){
percent.push ((communityAmount[1][i]/totalNodes));
}
return [communityAmount[0], percent];
}
}