package uk.ac.rhul.cs.graph;
import uk.ac.rhul.cs.cl1.NullTaskMonitor;
import uk.ac.rhul.cs.cl1.TaskMonitor;
import uk.ac.rhul.cs.cl1.TaskMonitorSupport;
/**
* Calculates the transitivity (i.e. clustering coefficient) of a given graph
* or a given set of nodes in a graph.
*
* @author tamas
*/
public class TransitivityCalculator extends GraphAlgorithm implements TaskMonitorSupport {
public TransitivityCalculator() {
super();
}
public TransitivityCalculator(Graph graph) {
super(graph);
}
/** A task monitor where the algorithm will report its progress */
protected TaskMonitor monitor = new NullTaskMonitor();
/**
* Returns the average local transitivity of the graph.
*
* @todo not implemented yet
*/
public Double getAverageLocalTransitivity() {
// TODO
throw new RuntimeException("average local transitivity not implemented yet");
}
/**
* Returns the global transitivity of the graph.
*
* Global transitivity is defined as three times the number of triangles (or,
* simply the number of closed triplets) divided by the number of connected
* triplets.
*
* @return the transitivity or null if the calculation was interrupted
*/
public Double getGlobalTransitivity() {
long triangles = 0;
long triplets = 0;
int nodeCount = graph.getNodeCount();
int i;
shouldStop = false;
monitor.setPercentCompleted(0);
for (i = 0; i < nodeCount; i++) {
if (shouldStop)
return null;
int[] neis = graph.getAdjacentNodeIndicesArray(i, Directedness.ALL);
for (int j: neis) {
if (j <= i)
continue;
for (int k: neis) {
if (j < k && graph.areConnected(j, k))
triangles++;
}
}
triplets += (neis.length * (neis.length - 1)) / 2;
// TODO: this is not entirely exact here because each node should be
// weighted by the square of its degree
monitor.setPercentCompleted((int)(i * 100.0 / nodeCount));
}
monitor.setPercentCompleted(100);
return (triplets == 0) ? 0 : (3.0 * triangles / triplets);
}
/**
* Sets the graph that the calculation will run on.
*
* This method throws an <code>UnsupportedOperationException</code> for
* directed graphs.
*/
@Override
public void setGraph(Graph graph) {
if (graph.isDirected())
throw new UnsupportedOperationException(
"transitivity calculation works for undirected graphs only"
);
super.setGraph(graph);
}
/**
* Sets the task monitor where the algorithm will report its progress
*
* @param monitor the task monitor to use
*/
public void setTaskMonitor(TaskMonitor monitor) {
this.monitor = monitor;
}
}