Search code examples
javaalgorithmgraphjung

Calculate SimRank in Jung Graph?


I know that there is some resource online about SimRank but I can't find any code for implement SimRank for Jung Graph. Basically,in an undirected graph, SimRank Similarity between 2 nodes is defined as follow simrank formula

Then I have a jung Graph

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


public SimpleGraphView() {
    // Graph<V, E> where V is the type of the vertices and E is the type of the edges
    g = new UndirectedSparseGraph<Integer, String>();
    // Add some vertices. From above we defined these to be type Integer.
    g.addVertex((Integer)1);
    g.addVertex((Integer)2);
    g.addVertex((Integer)3); 

    g.addEdge("Edge-A", 1, 2); 
    g.addEdge("Edge-B", 2, 3);  
}

How I gonna implement this algorithm ? I know it is a recursive but I can limit the iteration if it is convient


Solution

  • An attempt of an implementation according to http://en.wikipedia.org/wiki/SimRank

    This has not been tested or verified extensively, but might in any case at least serve as a starting point.

    package stackoverflow;
    
    import java.util.ArrayList;
    import java.util.Collection;
    import java.util.LinkedHashMap;
    import java.util.List;
    import java.util.Locale;
    import java.util.Map;
    
    import edu.uci.ics.jung.graph.Graph;
    import edu.uci.ics.jung.graph.UndirectedSparseGraph;
    import edu.uci.ics.jung.graph.util.Pair;
    
    public class JUNGSimRank
    {
        public static void main(String[] args)
        {
            Graph<Integer, String> g =
                new UndirectedSparseGraph<Integer, String>();
    
            g.addVertex((Integer)1);
            g.addVertex((Integer)2);
            g.addVertex((Integer)3);
    
            g.addEdge("Edge-A", 1, 2);
            g.addEdge("Edge-B", 2, 3);
    
            Map<Pair<Integer>, Float> simRank = computeSimRank(g);
            print(g, simRank);
        }
    
    
        /**
         * Compute the SimRank for the vertices of the given graph.
         *
         * @param <V> The vertex type
         * @param g The graph
         * @return The SimRank, as a map from pairs of vertices to
         * their similarity
         */
        private static <V> Map<Pair<V>, Float> computeSimRank(Graph<V,?> g)
        {
            final int kMax = 5;
            final float C = 0.8f;
    
            Map<Pair<V>, Float> currentR = computeInitialSimRank(g);
            Map<Pair<V>, Float> nextR = new LinkedHashMap<Pair<V>, Float>();
            for (int k=0; k<kMax; k++)
            {
                for (V a : g.getVertices())
                {
                    for (V b : g.getVertices())
                    {
                        float sum = computeSum(g, a, b, currentR);
                        Pair<V> ab = new Pair<V>(a,b);
                        int sia = g.inDegree(a);
                        int sib = g.inDegree(b);
                        if (sia == 0 || sib == 0)
                        {
                            nextR.put(ab, 0.0f);
                        }
                        else
                        {
                            nextR.put(ab, C / (sia * sib) * sum);
                        }
                    }
                }
    
                //System.out.println("After iteration "+k);
                //print(g, nextR);
    
                Map<Pair<V>, Float> temp = nextR;
                nextR = currentR;
                currentR = temp;
            }
            return currentR;
        }
    
        /**
         * Compute the sum of all SimRank values of all incoming
         * neighbors of the given vertices
         *
         * @param <V> The vertex type
         * @param g The graph
         * @param a The first vertex
         * @param b The second vertex
         * @param simRank The current SimRank
         * @return The sum of the SimRank values of the
         * incoming neighbors of the given vertices
         */
        private static <V> float computeSum(
            Graph<V,?> g, V a, V b, Map<Pair<V>, Float> simRank)
        {
            Collection<V> ia = g.getPredecessors(a);
            Collection<V> ib = g.getPredecessors(b);
            float sum = 0;
            for (V iia : ia)
            {
                for (V ijb : ib)
                {
                    Pair<V> key = new Pair<V>(iia, ijb);
                    Float r = simRank.get(key);
                    sum += r;
                }
            }
            return sum;
        }
    
        /**
         * Compute the initial SimRank for the vertices of the given graph.
         * This initial SimRank for two vertices (a,b) is 0.0f when
         * a != b, and 1.0f when a == b
         *
         * @param <V> The vertex type
         * @param g The graph
         * @return The SimRank, as a map from pairs of vertices to
         * their similarity
         */
        private static <V> Map<Pair<V>, Float> computeInitialSimRank(Graph<V,?> g)
        {
            Map<Pair<V>, Float> R0 = new LinkedHashMap<Pair<V>, Float>();
            for (V a : g.getVertices())
            {
                for (V b : g.getVertices())
                {
                    Pair<V> ab = new Pair<V>(a,b);
                    if (a.equals(b))
                    {
                        R0.put(ab, 1.0f);
                    }
                    else
                    {
                        R0.put(ab, 0.0f);
                    }
                }
            }
            return R0;
        }
    
        /**
         * Print a table with the SimRank values
         *
         * @param <V> The vertex type
         * @param g The graph
         * @param simRank The SimRank
         */
        private static <V> void print(Graph<V,?> g, Map<Pair<V>, Float> simRank)
        {
            final int columnWidth = 8;
            final String format = "%4.3f";
    
            List<V> vertices = new ArrayList<V>(g.getVertices());
            System.out.printf("%"+columnWidth+"s", "");
            for (int j=0; j<vertices.size(); j++)
            {
                String s = String.valueOf(vertices.get(j));
                System.out.printf("%"+columnWidth+"s", s);
            }
            System.out.println();
    
            for (int i=0; i<vertices.size(); i++)
            {
                String s = String.valueOf(vertices.get(i));
                System.out.printf("%"+columnWidth+"s", s);
                for (int j=0; j<vertices.size(); j++)
                {
                    V a = vertices.get(i);
                    V b = vertices.get(j);
                    Pair<V> ab = new Pair<V>(a,b);
                    Float value = simRank.get(ab);
                    String vs = String.format(Locale.ENGLISH, format, value);
                    System.out.printf("%"+columnWidth+"s", vs);
                }
                System.out.println();
            }
        }
    
    }