// [0]: # bins; [1]: which bin for this feature
String[] tokens = conceptBinParams.split("\\s+");
if (tokens.length != 2) {
throw new RetrievalException(
"For impact binning, should specify # bins(as a fraction of # total cliques) and which bin for this feature");
}
// K
double numBins = Math.floor(Double.parseDouble(tokens[0]));
// 1-indexed!!!!
int whichBin = Integer.parseInt(tokens[1]);
if (sanityCheck.containsKey(conceptBinType + " " + numBins + " " + whichBin + " "
+ all_concepts + " " + featureID + " " + thePruner + " " + width + " " + scoreFunction)) {
throw new RetrievalException("Bin " + whichBin
+ " has been used by this concept type before " + conceptBinType + " " + numBins + " "
+ all_concepts + " " + featureID + " " + thePruner + " " + width + " " + scoreFunction);
} else {
sanityCheck.put(conceptBinType + " " + numBins + " " + whichBin + " " + all_concepts + " "
+ featureID + " " + thePruner + " " + width + " " + scoreFunction, "1");
}
if (conceptBinType.equals("default")) {
// concept importance in descending order
int[] order_descending = new int[order.length];
for (int i = 0; i < order_descending.length; i++) {
order_descending[i] = order[order.length - i - 1];
}
int[] cascadeCliques = null;
// if there are 5 bigram concepts, if there are 3 bins, the last bin will take concepts 3,
// 4, 5
if (numBins == whichBin && order_descending.length > numBins) {
cascadeCliques = new int[order_descending.length - (int) numBins + 1];
for (int j = whichBin - 1; j < order_descending.length; j++) { // 0-indexed
cascadeCliques[j - whichBin + 1] = order_descending[j];
}
} else {
cascadeCliques = new int[1];
if ((whichBin - 1) < order_descending.length) {
cascadeCliques[0] = order_descending[whichBin - 1];
} else {
return new int[0];
}
}
// sort by clique numbers
double[] cascadeCliques_sorted_by_clique_number = new double[cascadeCliques.length];
int[] order1 = new int[cascadeCliques.length];
for (int j = 0; j < order1.length; j++) {
order1[j] = j;
cascadeCliques_sorted_by_clique_number[j] = cascadeCliques[j];
}
ivory.smrf.model.constrained.ConstraintModel.Quicksort(
cascadeCliques_sorted_by_clique_number, order1, 0, order1.length - 1);
for (int j = 0; j < cascadeCliques_sorted_by_clique_number.length; j++) {
cascadeCliques[j] = (int) cascadeCliques_sorted_by_clique_number[j];
}
return cascadeCliques;
}
else if (conceptBinType.equals("impact")) {
double totalCliques = (double) (conceptWeights.length);
double base = Math.pow((totalCliques + 1), (1 / numBins));
double firstBinSize = base - 1;
if (firstBinSize < 1) {
firstBinSize = 1;
}
int start = 0;
int end = (int) (Math.round(firstBinSize));
double residual = firstBinSize - end;
for (int i = 2; i <= whichBin; i++) {
start = end;
double v = firstBinSize * Math.pow(base, (i - 1));
double v_plus_residual = v + residual;
double v_round = Math.round(v_plus_residual);
residual = v_plus_residual - v_round;
end += (int) v_round;
}
if (start >= totalCliques) {
return new int[0];
}
if (end > totalCliques) {
end = (int) totalCliques;
}
int[] cascadeCliques = new int[end - start];
// concept importance in descending order
int[] order_descending = new int[order.length];
for (int i = 0; i < order_descending.length; i++) {
order_descending[i] = order[order.length - i - 1];
}
for (int i = start; i < end; i++) {
cascadeCliques[i - start] = order_descending[i];
}
// sort by clique numbers
double[] cascadeCliques_sorted_by_clique_number = new double[cascadeCliques.length];
int[] order1 = new int[cascadeCliques.length];
for (int j = 0; j < order1.length; j++) {
cascadeCliques_sorted_by_clique_number[j] = cascadeCliques[j];
order1[j] = j;
}
ivory.smrf.model.constrained.ConstraintModel.Quicksort(
cascadeCliques_sorted_by_clique_number, order1, 0, order1.length - 1);
for (int j = 0; j < cascadeCliques_sorted_by_clique_number.length; j++) {
cascadeCliques[j] = (int) cascadeCliques_sorted_by_clique_number[j];
}
return cascadeCliques;
}
} else {
throw new RetrievalException("Not yet supported " + conceptBinType);
}
return null;
}