package edu.ucsb.jpregel.system;
import static java.lang.System.err;
import static java.lang.System.exit;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
/**
*
* The value associated with each vertex, v, is:
* 1. the minimum distance to vertex v
* 2. the vertexId of vertex u, where edge (u, v) is on a shortest path to v.
* Since these 2 items constitute a Message, vertexValue's type is Message.
*
* @author Pete Cappello
*/
public class VertexShortestPath extends VertexImpl<Integer, Message<Integer, Integer>, Integer, Integer>
{
private static final Combiner sCombiner = new CombinerMinInteger();
private static final MessageQ<Integer,Integer> mq= new MessageQ<Integer, Integer>(sCombiner);
private static final ThreadLocal< StringBuilder> uniqueNum = new ThreadLocal<StringBuilder>() {
@Override
protected StringBuilder initialValue() {
return new StringBuilder();
}
};
public VertexShortestPath( Integer vertexId, Map<Integer, Integer> edgeMap, int numOutgoingEdges )
{
super( vertexId, edgeMap, numOutgoingEdges );
initialValue( vertexId);
combiner = sCombiner;
}
public VertexShortestPath( Integer vertexId, Map<Integer, Integer> edgeMap )
{
super( vertexId, edgeMap );
initialValue( vertexId);
combiner = sCombiner;
}
public VertexShortestPath() {}
@Override
public VertexImpl make( String line )
{
StringTokenizer stringTokenizer = new StringTokenizer( line );
if ( ! stringTokenizer.hasMoreTokens() )
{
err.println( "ShortestPathVertex.make: Empty lines are not allowed." );
exit( 1 );
}
int vertexId = Integer.parseInt( stringTokenizer.nextToken() );
Map<Integer, Integer> edgeMap = new HashMap<Integer, Integer>();
while( stringTokenizer.hasMoreTokens() )
{
int target = Integer.parseInt( stringTokenizer.nextToken() );
int weight = Integer.parseInt( stringTokenizer.nextToken() );
edgeMap.put( target, weight );
}
return new VertexShortestPath( vertexId, edgeMap );
}
@Override
public void compute()
{
// compute currently known shortest path from source to me
int minDistance = isSource() ? 0 : Integer.MAX_VALUE;
Message<Integer, Integer> minDistanceMessage = new Message<Integer, Integer>( getVertexId(), minDistance );
for ( Message<Integer, Integer> message : getMessageQ() )
{
if ( message.getMessageValue() < minDistanceMessage.getMessageValue() )
{
minDistanceMessage = message;
}
}
if ( minDistanceMessage.getMessageValue() < getVertexValue().getMessageValue() )
{ // There is a shorter path to me
setVertexValue( minDistanceMessage ); // update my value: the shortest path to me
// To each target vertex: The shortest known path to you via me just got shorter
for ( Integer targetVertexId : getEdgeTargets() )
{
Integer edgeValue = getEdgeMap().get( targetVertexId );
Message message = new Message( getVertexId(), minDistanceMessage.getMessageValue() + edgeValue );
sendMessage( targetVertexId, message );
}
// aggregate number of messages sent in this step & this problem
// aggregateOutputProblemAggregator( new IntegerSumAggregator( getEdgeMapSize() ));
// aggregateOutputStepAggregator( new IntegerSumAggregator( getEdgeMapSize() ));
}
}
@Override
public String output() {
String toString = "";
if ( getVertexId().intValue() >= getNumVertices() - 10 )
{
StringBuilder stringBuilder = uniqueNum.get();
stringBuilder.append(getVertexId());
stringBuilder.append(" : ");
stringBuilder.append(getVertexValue().getVertexId());
stringBuilder.append(" - ");
stringBuilder.append(getVertexValue().getMessageValue());
toString = stringBuilder.toString();
stringBuilder.setLength(0);
}
return toString;
}
@Override
public boolean isInitiallyActive() { return isSource(); }
public boolean isSource() { return getVertexId() == 1; }
public void initialValue(Integer vertexId) {
setVertexValue( new Message<Integer, Integer>( vertexId, Integer.MAX_VALUE ) );
}
@Override
public Factory<MessageQ> getMessageQType() {
return mq;
}
}