/* Copyright 2010 by Sean Luke and George Mason University Licensed under the Academic Free License version 3.0 See the file "LICENSE" for more information */ package sim.field.network.stats.actorcentrality; import sim.field.network.stats.*; import sim.field.network.*; import sim.util.mantissa.linalg.*; /** * Bonacich's Power Centrality * * <p>C(alpha, beta)=alpha (I - beta R)^-1 R 1 * <br>where<ul> * <li>R = adjacency matrix (can be valued);</li> * <li>I = identity matrix;</li> * <li>1 = all 1s;</li> * <li>beta = attenuation parameter (a.k.a. decay rate);</li> * <li>alpha = scaling vector, set to normalize the score;</li> * </ul> * * <p>"The coefficient alpha acts as a scaling parameter, and is set here (following * Bonacich (1987)) such that the sum of squared scores is equal to the number of * vertices. This allows 1 to be used as a reference value for the ``middle'' of * the centrality range" * (<a href="http://pbil.univ-lyon1.fr/library/sna/html/bonpow.html">R documentation</a>). * * @author Gabriel Catalin Balan */ public class PowerPrestige extends NodeIndex { final double[] prestige; final double scalingDenominator; public PowerPrestige(final Network network, EdgeMetric metric){this(network, 1, metric);} public PowerPrestige(final Network network, double beta, EdgeMetric metric) { super(network); int n = network.allNodes.numObjs; prestige = new double[n]; Edge[][] adjM = network.getAdjacencyMatrix(); //I-betaR GeneralSquareMatrix I_bR = new GeneralSquareMatrix(n); //R1 = is a square matrix with val_ij = Sum_k(R_ik) for all j. //A simple column vector is enough, the rest is redundancy double[] Rsum = new double[n];// a column of R1 for(int i=0;i<n;i++) { double sum=0; Edge[] adjMi = adjM[i]; for(int j=0;j<n;j++) { Edge e = adjMi[j]; double val = (e==null? 0: metric.getWeight(e)); sum+=val; I_bR.setElement(i, j, (i==j?1:0)-beta* val); } Rsum[i]=sum; } SquareMatrix I_bR_1; try { I_bR_1 = I_bR.getInverse(0.0); //prestige = multiplyByR1(I_bR_1, Rsum) double sumsq = 0;//for scaling purposes for(int i=0;i<n;i++) { // double[] matrix_i = I_bR_1[i]; double sum = 0; for(int k=0;k<n;k++) sum+= I_bR_1.getElement(i,k)*Rsum[k]; prestige[i]=sum; sumsq += sum*sum; } scalingDenominator = Math.sqrt(sumsq/n);//remember, this will be used to divide the prestige values }catch(SingularMatrixException ex) { throw new RuntimeException("Singular Matrix"); } } public double getValue(final Object node) { Network.IndexOutIn inout = (Network.IndexOutIn)network.indexOutInHash.get(node); return prestige[inout.index]; } public double getValue(final int nodeIndex) { return prestige[nodeIndex]; } public double getMaxValue() { return scalingDenominator; } }