Commit e8e1c066 authored by gsavin's avatar gsavin

Update clustering coefficient computation.

parent 1240daac
......@@ -251,7 +251,7 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.4</version>
<version>4.3.1</version>
<optional>false</optional>
</dependency>
<dependency>
......
......@@ -35,25 +35,26 @@ import java.util.List;
import org.graphstream.algorithm.Toolkit;
import org.graphstream.graph.Graph;
import org.graphstream.graph.Node;
import org.graphstream.graph.implementations.AdjacencyListGraph;
import org.graphstream.graph.implementations.SingleGraph;
import org.junit.Test;
import static org.junit.Assert.*;
public class TestToolkit {
/**
* A graph used to test clique methods
* A graph used to test clique methods
*/
public static Graph toyCliqueGraph() {
// B-----E H
// /|\ /|\
// / | \ / | \
// A--+--D--F--G--I
// \ | /
// \|/
// C
//
// This graph has 6 maximal cliques:
// [A, B, C, D], [B, D, E], [D, E, F], [E, F, G], [H], [G, I]
// B-----E H
// /|\ /|\
// / | \ / | \
// A--+--D--F--G--I
// \ | /
// \|/
// C
//
// This graph has 6 maximal cliques:
// [A, B, C, D], [B, D, E], [D, E, F], [E, F, G], [H], [G, I]
Graph g = new SingleGraph("cliques");
g.addNode("A").addAttribute("xy", 0, 1);
......@@ -86,7 +87,7 @@ public class TestToolkit {
}
/**
* Unit tests for {@link Toolkit#isClique(java.util.Collection)},
* Unit tests for {@link Toolkit#isClique(java.util.Collection)},
* {@link Toolkit#isClique(java.util.Collection)},
* {@link Toolkit#isMaximalClique(java.util.Collection)},
* {@link Toolkit#getMaximalCliqueIterator(Graph)},
......@@ -96,7 +97,7 @@ public class TestToolkit {
@Test
public void testCliques() {
Graph g = toyCliqueGraph();
int d = Toolkit.getDegeneracy(g, null);
assertEquals(3, d);
List<Node> ordering = new ArrayList<Node>();
......@@ -112,7 +113,7 @@ public class TestToolkit {
assertTrue(ordering.contains(g.getNode("B")));
assertTrue(ordering.contains(g.getNode("C")));
assertTrue(ordering.contains(g.getNode("D")));
int cliqueCount = 0;
int totalNodeCount = 0;
List<Node> maximumClique = new ArrayList<Node>();
......@@ -126,11 +127,40 @@ public class TestToolkit {
}
assertEquals(6, cliqueCount);
assertEquals(16, totalNodeCount);
assertEquals(4, maximumClique.size());
assertTrue(maximumClique.contains(g.getNode("A")));
assertTrue(maximumClique.contains(g.getNode("B")));
assertTrue(maximumClique.contains(g.getNode("C")));
assertTrue(maximumClique.contains(g.getNode("D")));
assertTrue(maximumClique.contains(g.getNode("D")));
}
@Test
public void testClusteringCoefficient() {
AdjacencyListGraph g = new AdjacencyListGraph("g");
double cc;
g.addNode("A");
g.addNode("B");
g.addNode("C");
g.addNode("D");
g.addEdge("AB", "A", "B");
g.addEdge("AC", "A", "C");
g.addEdge("AD", "A", "D");
cc = Toolkit.clusteringCoefficient(g.getNode("A"));
assertTrue(cc == 0);
g.addEdge("BC", "B", "C");
cc = Toolkit.clusteringCoefficient(g.getNode("A"));
assertTrue(cc == 1.0 / 3.0);
g.addEdge("BD", "B", "D");
g.addEdge("CD", "C", "D");
cc = Toolkit.clusteringCoefficient(g.getNode("A"));
assertTrue(cc == 1.0);
}
}
......@@ -372,49 +372,47 @@ public class Toolkit extends
}
/**
* Clustering coefficient for one node of the graph.
* Clustering coefficient for one node of the graph. For a node i with
* degree k, if Ni is the neighborhood of i (a set of nodes), clustering
* coefficient of i is defined as the count of edge e_uv with u,v in Ni
* divided by the maximum possible count, ie. k * (k-1) / 2.
*
* This method only works with undirected graphs.
*
* @param node
* The node to compute the clustering coefficient for.
* @return The clustering coefficient for this node.
* @complexity O(d^2) where d is the degree of the given node.
* @reference D. J. Watts and Steven Strogatz (June 1998).
* "Collective dynamics of 'small-world' networks" . Nature 393
* (6684): 440–442
*/
public static double clusteringCoefficient(Node node) {
double coef = 0.0;
int n = node.getDegree();
if (n > 1) {
// Collect the neighbour nodes.
Node[] nodes = new Node[n];
HashSet<Edge> set = new HashSet<Edge>();
int i = 0;
for (Edge edge : node.getEdgeSet())
nodes[i++] = edge.getOpposite(node);
// Count the number of edges between these nodes.
//
// Collect the neighbor nodes.
//
for (int i = 0; i < n; i++)
nodes[i] = node.getEdge(i).getOpposite(node);
for (i = 0; i < n; ++i) // For all neighbour nodes.
{
for (int j = 0; j < n; ++j) // For all other nodes of this
// clique.
{
//
// Check all edge possibilities
//
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j)
if (j != i) {
Edge e = nodes[j].getEdgeToward(nodes[i].getId());
if (e != null) {
// if( ! set.contains( e ) )
set.add(e);
}
if (e != null && e.getSourceNode() == nodes[j])
coef++;
}
}
}
double ne = set.size();
double max = (n * (n - 1)) / 2.0;
coef = ne / max;
coef /= (n * (n - 1)) / 2.0;
}
return coef;
......@@ -1346,9 +1344,9 @@ public class Toolkit extends
* The adjacency matrix of a graph is a <i>n</i> times <i>n</i> matrix
* {@code a}, where <i>n</i> is the number of nodes of the graph. The
* element {@code a[i][j]} of this matrix is equal to the number of edges
* from the node {@code graph.getNode(i)} to the node
* {@code graph.getNode(j)}. An undirected edge between i-th and j-th node
* is counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
* from the node {@code graph.getNode(i)} to the node {@code
* graph.getNode(j)}. An undirected edge between i-th and j-th node is
* counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
*
* @param graph
* A graph.
......@@ -1380,9 +1378,9 @@ public class Toolkit extends
* The adjacency matrix of a graph is a <i>n</i> times <i>n</i> matrix
* {@code a}, where <i>n</i> is the number of nodes of the graph. The
* element {@code a[i][j]} of this matrix is equal to the number of edges
* from the node {@code graph.getNode(i)} to the node
* {@code graph.getNode(j)}. An undirected edge between i-th and j-th node
* is counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
* from the node {@code graph.getNode(i)} to the node {@code
* graph.getNode(j)}. An undirected edge between i-th and j-th node is
* counted twice: in {@code a[i][j]} and in {@code a[j][i]}.
*
* @param graph
* A graph
......@@ -1406,12 +1404,12 @@ public class Toolkit extends
* number of edges of the graph. The coefficients {@code a[i][j]} of this
* matrix have the following values:
* <ul>
* <li>-1 if {@code graph.getEdge(j)} is directed and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of
* {@code graph.getEdge(j)}.</li>
* <li>-1 if {@code graph.getEdge(j)} is directed and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of {@code
* graph.getEdge(j)}.</li>
* <li>0 otherwise.
* </ul>
* In the special case when the j-th edge is a loop connecting the i-th node
......@@ -1449,12 +1447,12 @@ public class Toolkit extends
* number of edges of the graph. The coefficients {@code a[i][j]} of this
* matrix have the following values:
* <ul>
* <li>-1 if {@code graph.getEdge(j)} is directed and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and
* {@code graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of
* {@code graph.getEdge(j)}.</li>
* <li>-1 if {@code graph.getEdge(j)} is directed and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getEdge(j)} is undirected and {@code
* graph.getNode(i)} is its source.</li>
* <li>1 if {@code graph.getNode(i)} is the target of {@code
* graph.getEdge(j)}.</li>
* <li>0 otherwise.</li>
* </ul>
* In the special case when the j-th edge is a loop connecting the i-th node
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment