package org.rdfhdt.hdt.triples.impl;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.rdfhdt.hdt.compact.bitmap.Bitmap;
import org.rdfhdt.hdt.compact.bitmap.Bitmap375;
import org.rdfhdt.hdt.compact.bitmap.BitmapFactory;
import org.rdfhdt.hdt.compact.sequence.Sequence;
import org.rdfhdt.hdt.compact.sequence.SequenceFactory;
import org.rdfhdt.hdt.compact.sequence.SequenceLog64;
import org.rdfhdt.hdt.compact.sequence.SequenceLog64Map;
import org.rdfhdt.hdt.listener.ProgressListener;
import org.rdfhdt.hdt.util.BitUtil;
import org.rdfhdt.hdt.util.StopWatch;
import org.rdfhdt.hdt.util.io.CountInputStream;
import org.rdfhdt.hdt.util.listener.IntermediateListener;
import org.rdfhdt.hdt.util.listener.ListenerUtil;
class PredicateIndexArray implements PredicateIndex {
BitmapTriples triples;
Sequence array;
Bitmap bitmap;
public PredicateIndexArray(BitmapTriples triples) {
this.triples = triples;
}
private final long calculatePos(int pred) {
if(pred<=1) {
return 0;
}
return bitmap.select1(pred-1)+1;
}
public long getNumOcurrences(int pred) {
return bitmap.select1(pred)-bitmap.select1(pred-1);
}
public long getOccurrence(int pred, long occ) {
return array.get(calculatePos(pred)+occ-1);
}
public void load(InputStream input) throws IOException {
bitmap = BitmapFactory.createBitmap(input);
bitmap.load(input, null);
array = SequenceFactory.createStream(input);
array.load(input, null);
}
@Override
public void save(OutputStream out) throws IOException {
bitmap.save(out, null);
array.save(out, null);
}
@Override
public void generate(ProgressListener listener) {
IntermediateListener iListener = new IntermediateListener(listener);
StopWatch st = new StopWatch();
SequenceLog64 predCount = new SequenceLog64(BitUtil.log2(triples.seqY.getNumberOfElements()));
long maxCount = 0;
for(long i=0;i<triples.seqY.getNumberOfElements(); i++) {
// Read value
long val = triples.seqY.get(i);
// Grow if necessary
if(predCount.getNumberOfElements()<val) {
predCount.resize(val);
}
// Increment
long count = predCount.get(val-1)+1;
maxCount = count>maxCount ? count : maxCount;
predCount.set(val-1, count);
ListenerUtil.notifyCond(iListener, "Counting appearances of predicates", i, triples.seqY.getNumberOfElements(), 20000);
}
predCount.aggresiveTrimToSize();
// Convert predicate count to bitmap
Bitmap375 bitmap = new Bitmap375(triples.seqY.getNumberOfElements());
long tempCountPred=0;
for(long i=0;i<predCount.getNumberOfElements();i++) {
tempCountPred += predCount.get(i);
bitmap.set(tempCountPred-1,true);
ListenerUtil.notifyCond(iListener, "Creating Predicate bitmap", i, predCount.getNumberOfElements(), 100000);
}
bitmap.set(triples.seqY.getNumberOfElements()-1, true);
System.out.println("Predicate Bitmap in " + st.stopAndShow());
st.reset();
predCount=null;
// Create predicate index
SequenceLog64 array = new SequenceLog64(BitUtil.log2(triples.seqY.getNumberOfElements()), triples.seqY.getNumberOfElements());
array.resize(triples.seqY.getNumberOfElements());
SequenceLog64 insertArray = new SequenceLog64(BitUtil.log2(triples.seqY.getNumberOfElements()), bitmap.countOnes());
insertArray.resize(bitmap.countOnes());
for(long i=0;i<triples.seqY.getNumberOfElements(); i++) {
long predicateValue = triples.seqY.get(i);
long insertBase = predicateValue==1 ? 0 : bitmap.select1(predicateValue-1)+1;
long insertOffset = insertArray.get(predicateValue-1);
insertArray.set(predicateValue-1, insertOffset+1);
array.set(insertBase+insertOffset, i);
ListenerUtil.notifyCond(iListener, "Generating predicate references", i, triples.seqY.getNumberOfElements(), 100000);
}
this.array = array;
this.bitmap = bitmap;
System.out.println("Count predicates in "+st.stopAndShow());
}
@Override
public void mapIndex(CountInputStream input, File f, ProgressListener listener) throws IOException {
bitmap = BitmapFactory.createBitmap(input);
bitmap.load(input, null);
array = new SequenceLog64Map(input, f);
}
}