/*
Copyright 2010 by Sean Luke and George Mason University
Licensed under the Academic Free License version 3.0
See the file "LICENSE" for more information
*/
package sim.field.network.stats;
import sim.field.network.*;
import sim.field.network.stats.actorcentrality.*;
import sim.util.*;
/**
* @author Gabriel Catalin Balan
*
*/
public class CentralizationStatistics
{
final double[] centralityIndices;
final double[] stdCentralityIndices;
final double avgCentrality;
final double stdAvgCentrality;
final double maxCentrality;
final double stdMaxCentrality;
final int n;
//TODO I could offer both normalized and non normalized variance and group centraolization
// by keeping maxValue
public CentralizationStatistics(final Network network, final NodeIndex metric)
{
n = network.allNodes.numObjs;
centralityIndices = new double[n];
stdCentralityIndices = new double[n];
double maxPossibleValue = metric.getMaxValue();
double max = Double.NEGATIVE_INFINITY;
double sum = 0;
double oneOverMax = 1d/maxPossibleValue;//multiplication is faster than division.
for(int i = 0; i< network.allNodes.numObjs;i++)
{
double value = metric.getValue(network.allNodes.objs[i]);
centralityIndices[i] = value;
stdCentralityIndices[i] = value*oneOverMax;
sum+=value;
if(max<value)
max=value;
}
avgCentrality = sum/n;
stdAvgCentrality = avgCentrality*oneOverMax;
maxCentrality = max;
stdMaxCentrality = max*oneOverMax;
}
/**
* The average node centrality is Group Centralization for metrics like
* <ul>
* <li>Information Centralization (Wasserman and Faust, page 197),</li>
* <li>Proximity Prestige (Wasserman and Faust, page 204),</li>
* <li>etc.</li>
* </ul>
*/
public double getCentralizationIndexMean(boolean useNormalization)
{
return useNormalization? stdAvgCentrality: avgCentrality;
}
/**
*
* @param unbiased according to (Wasserman and Faust, page 180), the sum of (avg - val_i)^2
* should be diveded by n. I also offer the unbiased variance (i.e. dividing by n-1).
*
*/
public double getCentralizationIndexVariance(boolean useNormalization, boolean unbiased)
{
double sum = 0;
double[] values;
double avg;
if(useNormalization)
{
values = stdCentralityIndices;
avg = stdAvgCentrality;
}
else
{
values = centralityIndices;
avg = avgCentrality;
}
for(int i = 0; i< n;i++)
{
double dif = avg - values[i];
sum+= dif*dif;
}
return sum/(unbiased? n-1:n);
}
/**
* Identifies the points with the smallest maximal distance to all other points.
*/
// TODO I should use a Centrality measure: 1/max geodesic.
public static Bag getGraphTheoreticCenter(final Network network)
{
double[][] distances = NetworkStatistics.getShortestPathsMatrix(network, UnitEdgeMetric.defaultInstance);
int n = network.allNodes.numObjs;
int[] maxGeodesics = new int[n];
int count=0;
int min = n;
for(int i=0;i<n;i++)
{
double[] distances_i = distances[i];
int maxG_i = 0;
for(int j=0; j<n;j++)
{
int dist_ij = (int)distances_i[j];
if(dist_ij>maxG_i)
maxG_i = dist_ij;
//I could also compare with min to skip the rest of the column
}
maxGeodesics[i]=maxG_i;
if(maxG_i>0 && maxG_i < min)//I do min>0 to avoid giving the price to an isolated node
{
min = maxG_i;
count=1;
}
else if (maxG_i == min)
count++;
}
if(min==n)
//all nodes are isolated, so we'll return'em all.
return new Bag(network.allNodes);
Bag b = new Bag(count);
for(int i=0;i<n;i++)
if(maxGeodesics[i]==min)
b.add(network.allNodes.objs[i]);
return b;
//I could have done it all in a single pass, by
//-using a linked list, but then there would be too many function calls OR
//-using a BAG, but then there might be resizes (arraycopy ops) OR
//-using a prealocated Bag (i.e. new Bag(n)), but then there would be waisted space
//
//BUT asymptotically speaking, another O(n) is irrelevant
}
double freemanDenominator;
boolean isFreeman = false;
public CentralizationStatistics(final Network network, final FreemanNodeIndex metric)
{
this(network, (NodeIndex)metric);
freemanDenominator = metric.getMaxCummulativeDifference();
isFreeman = true;
//while useNormalization is irrelevant for getGeneralCentralizationIndex, its not for variance
}
/**
* Computes Freeman's General Centralization Index (Wasserman and Faust, page 177)
*/
public double getGeneralCentralizationIndex()
{
if(!isFreeman)
throw new RuntimeException("Computable only for FreemanCentralityMeasures");
// return Sum(max - val_i) / max_sum = [n*max-Sum(val)]/max_sum
return (maxCentrality-avgCentrality)*n /freemanDenominator;
}
}