All Downloads are FREE. Search and download functionalities are using the official Maven repository.

edu.uci.ics.jung.algorithms.metrics.TriadicCensus Maven / Gradle / Ivy

There is a newer version: 2.1.1
Show newest version
/*
 * Copyright (c) 2003, The JUNG Authors 
 *
 * All rights reserved.
 *
 * This software is open-source under the BSD license; see either
 * "license.txt" or
 * https://github.com/jrtom/jung/blob/master/LICENSE for a description.
 */
package edu.uci.ics.jung.algorithms.metrics;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import edu.uci.ics.jung.graph.DirectedGraph;
import edu.uci.ics.jung.graph.Graph;


/**
 * TriadicCensus is a standard social network tool that counts, for each of the 
 * different possible configurations of three vertices, the number of times
 * that that configuration occurs in the given graph.
 * This may then be compared to the set of expected counts for this particular
 * graph or to an expected sample. This is often used in p* modeling.
 * 

* To use this class, *

 * long[] triad_counts = TriadicCensus(dg);
 * 
* where dg is a DirectedGraph. * ith element of the array (for i in [1,16]) is the number of * occurrences of the corresponding triad type. * (The 0th element is not meaningful; this array is effectively 1-based.) * To get the name of the ith triad (e.g. "003"), * look at the global constant array c.TRIAD_NAMES[i] *

* Triads are named as * (number of pairs that are mutually tied) * (number of pairs that are one-way tied) * (number of non-tied pairs) * in the triple. Since there are be only three pairs, there is a finite * set of these possible triads. *

* In fact, there are exactly 16, conventionally sorted by the number of * realized edges in the triad: *

* * * * * * * * * * * * * * * * * * *
Descriptions of the different types of triads
Number Configuration Notes
1003The empty triad
2012
3102
4021D"Down": the directed edges point away
5021U"Up": the directed edges meet
6021C"Circle": one in, one out
7111D"Down": 021D but one edge is mutual
8111U"Up": 021U but one edge is mutual
9030T"Transitive": two point to the same vertex
10030C"Circle": A→B→C→A
11201
12120D"Down": 021D but the third edge is mutual
13120U"Up": 021U but the third edge is mutual
14120C"Circle": 021C but the third edge is mutual
15210
16300The complete
*

* This implementation takes O( m ), m is the number of edges in the graph. *
* It is based on * * A subquadratic triad census algorithm for large sparse networks * with small maximum degree * Vladimir Batagelj and Andrej Mrvar, University of Ljubljana * Published in Social Networks. * @author Danyel Fisher * @author Tom Nelson - converted to jung2 * */ public class TriadicCensus { // NOTE THAT THIS RETURNS STANDARD 1-16 COUNT! // and their types public static final String[] TRIAD_NAMES = { "N/A", "003", "012", "102", "021D", "021U", "021C", "111D", "111U", "030T", "030C", "201", "120D", "120U", "120C", "210", "300" }; public static final int MAX_TRIADS = TRIAD_NAMES.length; /** * Returns an array whose ith element (for i in [1,16]) is the number of * occurrences of the corresponding triad type in g. * (The 0th element is not meaningful; this array is effectively 1-based.) * * @param g the graph whose properties are being measured * @param the vertex type * @param the edge type * @return an array encoding the number of occurrences of each triad type */ public static long[] getCounts(DirectedGraph g) { long[] count = new long[MAX_TRIADS]; List id = new ArrayList(g.getVertices()); // apply algorithm to each edge, one at at time for (int i_v = 0; i_v < g.getVertexCount(); i_v++) { V v = id.get(i_v); for(V u : g.getNeighbors(v)) { int triType = -1; if (id.indexOf(u) <= i_v) continue; Set neighbors = new HashSet(g.getNeighbors(u)); neighbors.addAll(g.getNeighbors(v)); neighbors.remove(u); neighbors.remove(v); if (g.isSuccessor(v,u) && g.isSuccessor(u,v)) { triType = 3; } else { triType = 2; } count[triType] += g.getVertexCount() - neighbors.size() - 2; for (V w : neighbors) { if (shouldCount(g, id, u, v, w)) { count [ triType ( triCode(g, u, v, w) ) ] ++; } } } } int sum = 0; for (int i = 2; i <= 16; i++) { sum += count[i]; } int n = g.getVertexCount(); count[1] = n * (n-1) * (n-2) / 6 - sum; return count; } /** * This is the core of the technique in the paper. Returns an int from 0 to * 63 which encodes the presence of all possible links between u, v, and w * as bit flags: WU = 32, UW = 16, WV = 8, VW = 4, UV = 2, VU = 1 * * @param g the graph for which the calculation is being made * @param u a vertex in g * @param v a vertex in g * @param w a vertex in g * @param the vertex type * @param the edge type * @return an int encoding the presence of all links between u, v, and w */ public static int triCode(Graph g, V u, V v, V w) { int i = 0; i += link(g, v, u ) ? 1 : 0; i += link(g, u, v ) ? 2 : 0; i += link(g, v, w ) ? 4 : 0; i += link(g, w, v ) ? 8 : 0; i += link(g, u, w ) ? 16 : 0; i += link(g, w, u ) ? 32 : 0; return i; } protected static boolean link(Graph g, V a, V b) { return g.isPredecessor(b, a); } /** * @param triCode the code returned by {@code triCode()} * @return the string code associated with the numeric type */ public static int triType( int triCode ) { return codeToType[ triCode ]; } /** * For debugging purposes, this is copied straight out of the paper which * means that they refer to triad types 1-16. */ protected static final int[] codeToType = { 1, 2, 2, 3, 2, 4, 6, 8, 2, 6, 5, 7, 3, 8, 7, 11, 2, 6, 4, 8, 5, 9, 9, 13, 6, 10, 9, 14, 7, 14, 12, 15, 2, 5, 6, 7, 6, 9, 10, 14, 4, 9, 9, 12, 8, 13, 14, 15, 3, 7, 8, 11, 7, 12, 14, 15, 8, 14, 13, 15, 11, 15, 15, 16 }; /** * Return true iff this ordering is canonical and therefore we should build statistics for it. * * @param g the graph whose properties are being examined * @param id a list of the vertices in g; used to assign an index to each * @param u a vertex in g * @param v a vertex in g * @param w a vertex in g * @param the vertex type * @param the edge type * @return true if index(u) < index(w), or if index(v) < index(w) < index(u) * and v doesn't link to w; false otherwise */ protected static boolean shouldCount(Graph g, List id, V u, V v, V w) { int i_u = id.indexOf(u); int i_w = id.indexOf(w); if (i_u < i_w) return true; int i_v = id.indexOf(v); if ((i_v < i_w) && (i_w < i_u) && (!g.isNeighbor(w,v))) return true; return false; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy