package edu.cmu.graphchi.preprocessing;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
/**
* Translates vertices from original id to internal-id and
* vice versa. GraphChi translates original ids to "modulo-shifted"
* ids and thus effectively shuffles the vertex ids. This will lead
* likely to a balanced edge distribution over the space of vertex-ids,
* and thus roughly equal amount of edges in each shard. With this
* trick, we do not need to first count the edge distribution and divide
* the shard intervals based on that but can skip that step. As a downside,
* the vertex ids need to be translated back and forth.
* @author Aapo Kyrola, akyrola@cs.cmu.edu
*/
public class VertexIdTranslate {
private int vertexIntervalLength;
private int numShards;
protected VertexIdTranslate() {
}
public VertexIdTranslate(int vertexIntervalLength, int numShards) {
this.vertexIntervalLength = vertexIntervalLength;
this.numShards = numShards;
}
/**
* Translates original vertex id to internal vertex id
* @param origId
* @return
*/
public int forward(int origId) {
return (origId % numShards) * vertexIntervalLength + origId / numShards;
}
/**
* Translates internal id to original id
* @param transId
* @return
*/
public int backward(int transId) {
final int shard = transId / vertexIntervalLength;
final int off = transId % vertexIntervalLength;
return off * numShards + shard;
}
public int getVertexIntervalLength() {
return vertexIntervalLength;
}
public int getNumShards() {
return numShards;
}
public String stringRepresentation() {
return "vertex_interval_length=" + vertexIntervalLength + "\nnumShards=" + numShards + "\n";
}
public static VertexIdTranslate fromString(String s) {
if ("none".equals(s)) {
return identity();
}
String[] lines = s.split("\n");
int vertexIntervalLength = -1;
int numShards = -1;
for(String ln : lines) {
if (ln.startsWith("vertex_interval_length=")) {
vertexIntervalLength = Integer.parseInt(ln.split("=")[1]);
} else if (ln.startsWith("numShards=")) {
numShards = Integer.parseInt(ln.split("=")[1]);
}
}
if (vertexIntervalLength < 0 || numShards < 0) throw new RuntimeException("Illegal format: " + s);
return new VertexIdTranslate(vertexIntervalLength, numShards);
}
public static VertexIdTranslate fromFile(File f) throws IOException {
int len = (int) f.length();
byte[] b = new byte[len];
FileInputStream fis = new FileInputStream(f);
fis.read(b);
fis.close();
return VertexIdTranslate.fromString(new String(b));
}
public static VertexIdTranslate identity() {
return new VertexIdTranslate() {
@Override
public int forward(int origId) {
return origId;
}
@Override
public int backward(int transId) {
return transId;
}
@Override
public int getVertexIntervalLength() {
return -1;
}
@Override
public int getNumShards() {
return -1;
}
@Override
public String stringRepresentation() {
return "none";
}
};
}
}