for(DBID id : relation.iterDBIDs()) {
double sum = 0;
double maxDist = 0;
int cnt = 0;
final DBIDs neighbors = npred.getNeighborDBIDs(id);
for(DBID neighbor : neighbors) {
if(id.equals(neighbor)) {
continue;
}
double dist = distFunc.distance(id, neighbor).doubleValue();
sum += dist;
cnt++;
maxDist = Math.max(maxDist, dist);
}
if(cnt > 1) {
modifiedDistance.putDouble(id, ((sum - maxDist) / (cnt - 1)));
}
else {
// Use regular distance when the d-tilde trick is undefined.
// Note: this can be 0 when there were no neighbors.
modifiedDistance.putDouble(id, maxDist);
}
}
// Second step - compute actual SLOM values
DoubleMinMax slomminmax = new DoubleMinMax();
WritableDoubleDataStore sloms = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC);
for(DBID id : relation.iterDBIDs()) {
double sum = 0;
int cnt = 0;
final DBIDs neighbors = npred.getNeighborDBIDs(id);
for(DBID neighbor : neighbors) {
if(neighbor.equals(id)) {
continue;
}
sum += modifiedDistance.doubleValue(neighbor);
cnt++;
}
double slom;
if(cnt > 0) {
// With and without the object itself:
double avgPlus = (sum + modifiedDistance.doubleValue(id)) / (cnt + 1);
double avg = sum / cnt;
double beta = 0;
for(DBID neighbor : neighbors) {
final double dist = modifiedDistance.doubleValue(neighbor);
if(dist > avgPlus) {
beta += 1;
}
else if(dist < avgPlus) {
beta -= 1;
}
}
// Include object itself
if(!neighbors.contains(id)) {
final double dist = modifiedDistance.doubleValue(id);
if(dist > avgPlus) {
beta += 1;
}
else if(dist < avgPlus) {