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.put(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.put(id, maxDist);
}
}
// Second step - compute actual SLOM values
DoubleMinMax slomminmax = new DoubleMinMax();
WritableDataStore<Double> sloms = DataStoreUtil.makeStorage(relation.getDBIDs(), DataStoreFactory.HINT_STATIC, Double.class);
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.get(neighbor);
cnt++;
}
double slom;
if(cnt > 0) {
// With and without the object itself:
double avgPlus = (sum + modifiedDistance.get(id)) / (cnt + 1);
double avg = sum / cnt;
double beta = 0;
for(DBID neighbor : neighbors) {
final double dist = modifiedDistance.get(neighbor).doubleValue();
if(dist > avgPlus) {
beta += 1;
}
else if(dist < avgPlus) {
beta -= 1;
}
}
// Include object itself
if(!neighbors.contains(id)) {
final double dist = modifiedDistance.get(id).doubleValue();
if(dist > avgPlus) {
beta += 1;
}
else if(dist < avgPlus) {