Question

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

Was it helpful?

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();
        }
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top