
org.neo4j.graphalgo.impl.centrality.StressCentrality Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neo4j-graph-algo Show documentation
Show all versions of neo4j-graph-algo Show documentation
Graph algorithms for Neo4j.
/*
* Copyright (c) 2002-2016 "Neo Technology,"
* Network Engine for Objects in Lund AB [http://neotechnology.com]
*
* This file is part of Neo4j.
*
* Neo4j is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
package org.neo4j.graphalgo.impl.centrality;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.neo4j.graphalgo.impl.shortestpath.SingleSourceShortestPath;
import org.neo4j.graphalgo.impl.shortestpath.Util;
import org.neo4j.graphalgo.impl.shortestpath.Util.PathCounter;
import org.neo4j.graphalgo.impl.util.DoubleAdder;
import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
/**
* Implementation of stress centrality, which is defined as the number of
* shortest paths going through each node.
* @complexity Using a {@link SingleSourceShortestPath} algorithm with time
* complexity A, this algorithm runs in time O(n * (A + m)).
* Examples: This becomes O(n * m) for BFS search and O(n^2 * log(n)
* + n * m) for Dijkstra.
* @author Patrik Larsson
* @param
* The datatype used by the underlying
* {@link SingleSourceShortestPath} algorithm, i.e. the type the edge
* weights are represented by.
*/
public class StressCentrality extends
ShortestPathBasedCentrality
{
protected Double globalFactor;
/**
* Default constructor.
* @param singleSourceShortestPath
* Underlying singleSourceShortestPath.
* @param nodeSet
* A set containing the nodes for which centrality values should
* be computed.
*/
public StressCentrality(
SingleSourceShortestPath singleSourceShortestPath,
Set nodeSet )
{
super( singleSourceShortestPath, new DoubleAdder(), 0.0, nodeSet );
}
@Override
public void reset()
{
super.reset();
globalFactor = 1.0;
if ( singleSourceShortestPath.getDirection().equals( Direction.BOTH ) )
{
globalFactor = 0.5;
}
}
/**
* This recursively updates the node stress (number of paths through a
* node).
* @param node
* The start node
* @param skipFirstNode
* If true, the start node is not updated. Useful, since the
* first node in any path doesnt need to be updated.
* @param successors
* @param counter
* Object that can return the number of paths from the initial
* start node to any node.
* @param stresses
* A map used to limit the recursion where possible (dynamic
* programming)
* @return
*/
protected Double getAndUpdateNodeStress( Node node, boolean skipFirstNode,
Map> successors, PathCounter counter,
Map stresses )
{
Double stress = stresses.get( node );
if ( stress != null )
{
return stress;
}
stress = (double) 0;
List succs = successors.get( node );
if ( succs == null || succs.size() == 0 )
{
return (double) 0;
}
for ( Relationship relationship : succs )
{
Node otherNode = relationship.getOtherNode( node );
Double otherStress = getAndUpdateNodeStress( otherNode, false,
successors, counter, stresses );
stress += (otherStress + 1) * counter.getNumberOfPathsToNode( node );
}
if ( !skipFirstNode )
{
stresses.put( node, stress );
// When adding to the final result (and only then), take the global
// factor into account.
addCentralityToNode( node, stress * globalFactor );
}
return stress;
}
@Override
public void processShortestPaths( Node node,
SingleSourceShortestPath singleSourceShortestPath )
{
// Extract predecessors and successors
Map> predecessors = singleSourceShortestPath
.getPredecessors();
Map> successors = Util
.reversedPredecessors( predecessors );
PathCounter counter = new Util.PathCounter( predecessors );
// Recursively update the node dependencies
getAndUpdateNodeStress( node, true, successors, counter,
new HashMap() );
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy