/*
* Copyright 2008 Network Engine for Objects in Lund AB [neotechnology.com]
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.neo4j.graphalgo.centrality;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
import org.neo4j.graphalgo.CommonEvaluators;
import org.neo4j.graphalgo.CostEvaluator;
import org.neo4j.graphalgo.impl.centrality.EigenvectorCentrality;
import org.neo4j.graphalgo.impl.centrality.EigenvectorCentralityPower;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import common.Neo4jAlgoTestCase;
public abstract class EigenvectorCentralityTest extends Neo4jAlgoTestCase
{
protected void assertCentrality(
EigenvectorCentralityPower eigenvectorCentralityPower, String nodeId,
Double value )
{
assertTrue( eigenvectorCentralityPower.getCentrality(
graph.getNode( nodeId ) ).equals( value ) );
}
/**
* @param eigenvectorCentralityPower
* @param nodeId
* Id of the node
* @param value
* The correct value
* @param precision
* Precision factor (ex. 0.01)
*/
protected void assertApproximateCentrality(
EigenvectorCentrality eigenvectorCentrality, String nodeId,
Double value, Double precision )
{
Double centrality = eigenvectorCentrality.getCentrality( graph
.getNode( nodeId ) );
assertTrue( centrality < value * (1 + precision)
&& centrality > value * (1 - precision) );
}
public abstract EigenvectorCentrality getEigenvectorCentrality(
Direction relationDirection, CostEvaluator<Double> costEvaluator,
Set<Node> nodeSet, Set<Relationship> relationshipSet, double precision );
@Test
public void testRun()
{
graph.makeEdgeChain( "a,b,c,d" );
graph.makeEdges( "b,a,c,a" );
EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
Direction.OUTGOING, new CostEvaluator<Double>()
{
public Double getCost( Relationship relationship,
Direction direction )
{
return 1.0;
}
}, graph.getAllNodes(), graph.getAllEdges(), 0.01 );
// eigenvectorCentrality.setMaxIterations( 100 );
assertApproximateCentrality( eigenvectorCentrality, "a", 0.693, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "b", 0.523, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "c", 0.395, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "d", 0.298, 0.01 );
}
/**
* Same as above, but inverted direction.
*/
@Test
public void testDirection()
{
graph.makeEdgeChain( "d,c,b,a" );
graph.makeEdges( "a,b,a,c" );
EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
Direction.INCOMING, new CostEvaluator<Double>()
{
public Double getCost( Relationship relationship,
Direction direction )
{
return 1.0;
}
}, graph.getAllNodes(), graph.getAllEdges(), 0.01 );
// eigenvectorCentrality.setMaxIterations( 100 );
assertApproximateCentrality( eigenvectorCentrality, "a", 0.693, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "b", 0.523, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "c", 0.395, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "d", 0.298, 0.01 );
}
/**
* Some weighted relationships.
*/
@Test
public void testWeight()
{
graph.makeEdgeChain( "a,b", "cost", 1.0 );
graph.makeEdgeChain( "b,c", "cost", 1.0 );
graph.makeEdgeChain( "c,d", "cost", 1.0 );
graph.makeEdgeChain( "c,b", "cost", 0.1 );
graph.makeEdgeChain( "c,a", "cost", 0.1 );
EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
Direction.OUTGOING, CommonEvaluators.doubleCostEvaluator( "cost" ), graph
.getAllNodes(), graph.getAllEdges(), 0.01 );
// eigenvectorCentrality.setMaxIterations( 100 );
assertApproximateCentrality( eigenvectorCentrality, "a", 0.0851, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "b", 0.244, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "c", 0.456, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "d", 0.852, 0.01 );
}
/**
* Same network as above, but with direction BOTH and weights in different
* directions are given by a map.
*/
@Test
public void testWeightAndDirection()
{
graph.makeEdgeChain( "a,b" );
graph.makeEdgeChain( "b,c" );
graph.makeEdgeChain( "c,d" );
graph.makeEdgeChain( "c,a" );
final Map<String,Double> costs = new HashMap<String,Double>();
costs.put( "a,b", 1.0 );
costs.put( "b,c", 1.0 );
costs.put( "c,d", 1.0 );
costs.put( "c,b", 0.1 );
costs.put( "c,a", 0.1 );
EigenvectorCentrality eigenvectorCentrality = getEigenvectorCentrality(
Direction.BOTH, new CostEvaluator<Double>()
{
public Double getCost( Relationship relationship,
Direction direction )
{
String start = graph
.getNodeId( relationship.getStartNode() );
String end = graph.getNodeId( relationship.getEndNode() );
if ( direction == Direction.INCOMING )
{
// swap
String tmp = end;
end = start;
start = tmp;
}
Double value = costs.get( start + "," + end );
if ( value == null )
{
return 0.0;
}
return value;
}
}, graph.getAllNodes(), graph.getAllEdges(), 0.01 );
// eigenvectorCentrality.setMaxIterations( 100 );
assertApproximateCentrality( eigenvectorCentrality, "a", 0.0851, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "b", 0.244, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "c", 0.456, 0.01 );
assertApproximateCentrality( eigenvectorCentrality, "d", 0.852, 0.01 );
}
}