// Find the best concepts for each of the expansion models.
for (int modelNum = 0; modelNum < builders.size(); modelNum++) {
// Get information about this expansion model.
int curGramSize = gramSizes.get(modelNum);
MRFBuilder curBuilder = builders.get(modelNum);
int curFbDocs = fbDocList.get(modelNum);
int curFbTerms = fbTermList.get(modelNum);
// Gather Accumulators we're actually going to use for feedback purposes.
Accumulator[] fbResults = new Accumulator[Math.min(results.length, curFbDocs)];
for (int i = 0; i < Math.min(results.length, curFbDocs); i++) {
fbResults[i] = results[i];
}
// Sort the Accumulators by docid.
Arrays.sort(fbResults, new Accumulator.DocnoComparator());
// Get docnos that correspond to the accumulators.
int[] docSet = Accumulator.accumulatorsToDocnos(fbResults);
// Get document vectors for results.
IntDocVector[] docVecs = env.documentVectors(docSet);
// Extract vocabulary from results.
VocabFrequencyPair[] vocab = null;
try {
vocab = getVocabulary(docVecs, curGramSize);
} catch (IOException e) {
throw new RuntimeException("Error: Unable to fetch the vocabulary!");
}
// Priority queue for the concepts associated with this builder.
PriorityQueue<Accumulator> sortedConcepts = new PriorityQueue<Accumulator>();
// Score each concept.
for (int conceptID = 0; conceptID < vocab.length; conceptID++) {
if (maxCandidates > 0 && conceptID >= maxCandidates) {
break;
}
// The current concept.
String concept = vocab[conceptID].getKey();
String[] concepts = concept.split(" ");
MarkovRandomField conceptMRF = curBuilder.buildMRF(concepts);
MRFDocumentRanker ranker = new MRFDocumentRanker(conceptMRF, docSet, docSet.length);
Accumulator[] conceptResults = ranker.rank();
Arrays.sort(conceptResults, new Accumulator.DocnoComparator());
float score = 0.0f;
for (int i = 0; i < conceptResults.length; i++) {
if (fbResults[i].docno != conceptResults[i].docno) {
throw new RetrievalException("Error: Mismatch occured in getExpandedMRF!");
}
score += Math.exp(fbResults[i].score + conceptResults[i].score);
}
int size = sortedConcepts.size();
if (size < curFbTerms || sortedConcepts.peek().score < score) {
if (size == curFbTerms) {
sortedConcepts.poll(); // Remove worst concept.
}
sortedConcepts.add(new Accumulator(conceptID, score));
}
}
// Compute the weights of the expanded terms.
int numTerms = Math.min(curFbTerms, sortedConcepts.size());
float totalWt = 0.0f;
Accumulator[] bestConcepts = new Accumulator[numTerms];
for (int i = 0; i < numTerms; i++) {
Accumulator a = sortedConcepts.poll();
bestConcepts[i] = a;
totalWt += a.score;
}
// Add cliques corresponding to best expansion concepts.
for (int i = 0; i < numTerms; i++) {
Accumulator a = bestConcepts[i];
// Construct the MRF corresponding to this concept.
String[] concepts = vocab[a.docno].getKey().split(" ");
MarkovRandomField conceptMRF = curBuilder.buildMRF(concepts);
// Normalized score.
float normalizedScore = a.score / totalWt;
// Add cliques.