// Catalano Graph Library
// The Catalano Framework
//
// Copyright © Diego Catalano, 2012-2016
// diego.catalano at live.com
//
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
package Catalano.Graph.Network;
import Catalano.Graph.AdjacencyMatrix;
import Catalano.Math.Matrix;
/**
* Hyperlink-Induced Topic Search.
* Hits is a link analysis algorithm that rates Web pages.
*
* @author Diego Catalano
*/
public class Hits {
private double epsilon = 0.001;
private double[] authority;
private double[] hubs;
private int it = 0;
/**
* Get epsilon value.
* @return Epsilon value.
*/
public double getEpsilon() {
return epsilon;
}
/**
* Set epsilon value.
* Epsilon value, is the stop criteria.
* @param epsilon Epsilon value.
*/
public void setEpsilon(double epsilon) {
if(epsilon == 0)
throw new IllegalArgumentException("The epsilon value must be different of zero.");
this.epsilon = epsilon;
}
/**
* Get number of iterations executed by the algorithm.
* @return Number of iterations.
*/
public int getNumberOfIterations() {
return it;
}
/**
* Get Authority.
* @return Authority.
*/
public double[] getAuthority() {
return authority;
}
/**
* Get Hubs.
* @return Hubs.
*/
public double[] getHubs() {
return hubs;
}
/**
* Initialize a new instance of the Hits class.
* @param matrix Adjacency matrix.
*/
public Hits(AdjacencyMatrix matrix) {
Compute(matrix);
}
/**
* Initialize a new instance of the Hits class.
* @param matrix Adjacency matrix.
* @param epsilon Epsilon value.
*/
public Hits(AdjacencyMatrix matrix, double epsilon){
setEpsilon(epsilon);
Compute(matrix);
}
/**
* Compute Hits.
* @param matrix Adjacency matrix.
*/
public void Compute(AdjacencyMatrix matrix){
//Basic weights.
double[] weights = Matrix.CreateMatrix1D(matrix.getData().length, 1D);
Compute(matrix, weights);
}
/**
* Compute Hits.
* @param matrix Adjacency matrix.
* @param weights Normalized weights.[0..1]
*/
public void Compute(AdjacencyMatrix matrix, double[] weights){
if(matrix.getData().length != weights.length)
throw new IllegalArgumentException("The matrix lenght must be the same lenght of the weights.");
//Initialize the matrix authority. mA = A' * A
double[][] mA = Matrix.Multiply(Matrix.Transpose(matrix.getData()), matrix.getData());
//Initialize the matrix hubs. mH = A * A'
double[][] mH = Matrix.MultiplyByTranspose(matrix.getData(), matrix.getData());
//Create Authority and Hubs weights.
authority = weights;
hubs = weights;
double maxDiff = Double.MAX_VALUE;
while(maxDiff > epsilon){
//Compute authority: a = A' * A * a
double[] a = Iteration(mA, authority);
//Compute hubs = h = A * A' * h
double[] h = Iteration(mH, hubs);
maxDiff = Convergency(authority, hubs, a, h);
authority = a;
hubs = h;
it++;
}
}
/**
* Equivalent like Multiply by Transpose, but with normalizations.
* @param m Matrix.
* @param a Vector to be transposed.
* @return Result.
*/
private double[] Iteration(double[][] m, double[] a){
double[] result = new double[a.length];
double sum = 0;
for (int i = 0; i < m.length; i++) {
double r = 0;
for (int j = 0; j < m[0].length; j++) {
r += m[i][j] * a[j];
}
result[i] = r;
sum += r;
}
//Normalize
for (int i = 0; i < result.length; i++) {
result[i] /= sum;
}
return result;
}
private double Convergency(double[] oldAuthority, double[] oldHubs, double[] authority, double[] hubs){
double maxDiff = Double.MAX_VALUE;
for (int i = 0; i < oldAuthority.length; i++) {
maxDiff = Math.min(maxDiff, Math.abs(oldAuthority[i] - authority[i]));
maxDiff = Math.min(maxDiff, Math.abs(oldHubs[i] - hubs[i]));
}
return maxDiff;
}
}
Ads help maintain this website.