// Find the minimum:
protected void computeAverageChainingDistances(KNNQuery<O> knnq, DistanceQuery<O> dq, DBIDs ids, WritableDoubleDataStore acds) {
    FiniteProgress lrdsProgress = LOG.isVerbose() ? new FiniteProgress("Computing average chaining distances", ids.size(), LOG) : null;
    // Compute the chaining distances.
    // We do <i>not</i> bother to materialize the chaining order.
    for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
      final KNNList neighbors = knnq.getKNNForDBID(iter, k);
      final int r = neighbors.size();
      DoubleDBIDListIter it1 = neighbors.iter(), it2 = neighbors.iter();
      // Store the current lowest reachability.
      final double[] mindists = new double[r];
      for(int i = 0; it1.valid(); it1.advance(), ++i) {
        mindists[i] = DBIDUtil.equal(it1, iter) ? Double.NaN : it1.doubleValue();
      }
      double acsum = 0.;
      for(int j = ((r < k) ? r : k) - 1; j > 0; --j) {
        // Find the minimum:
        int minpos = -1;
        double mindist = Double.NaN;
        for(int i = 0; i < mindists.length; ++i) {
          double curdist = mindists[i];
          // Both values could be NaN, deliberately.
          if(curdist == curdist && !(curdist > mindist)) {
            minpos = i;
            mindist = curdist;
          }
        }
        acsum += mindist * j; // Weighted sum, decreasing weights
        mindists[minpos] = Double.NaN;
        it1.seek(minpos);
        // Update distances
        it2.seek(0);
        for(int i = 0; it2.valid(); it2.advance(), ++i) {
          final double curdist = mindists[i];
          if(curdist != curdist) {
            continue; // NaN = processed!
          }
          double newdist = dq.distance(it1, it2);
          if(newdist < curdist) {
            mindists[i] = newdist;
          }
        }
      }
      acds.putDouble(iter, acsum / (r * 0.5 * (r - 1.)));
      LOG.incrementProcessed(lrdsProgress);
    }
    LOG.ensureCompleted(lrdsProgress);
  }
double acsum = 0.;
for(int j = ((r < k) ? r : k) - 1; j > 0; --j) {
// Find the minimum:
int minpos = -1;
double mindist = Double.NaN;
final KNNList neighbors = knnq.getKNNForDBID(iter, k);
final int r = neighbors.size();
DoubleDBIDListIter it1 = neighbors.iter(), it2 = neighbors.iter();
// Store the current lowest reachability.
final double[] mindists = new double[r];
for(int i = 0; it1.valid(); it1.advance(), ++i) {
mindists[i] = DBIDUtil.equal(it1, iter) ? Double.NaN : it1.doubleValue();
}
double acsum = 0.;
for(int j = ((r < k) ? r : k) - 1; j > 0; --j) {
// Find the minimum:
int minpos = -1;
double mindist = Double.NaN;
for(int i = 0; i < mindists.length; ++i) {
double curdist = mindists[i];
// Both values could be NaN, deliberately.
if(curdist == curdist && !(curdist > mindist)) {
minpos = i;
mindist = curdist;
}
}
protected void computeAverageChainingDistances(KNNQuery<O> knnq, DistanceQuery<O> dq, DBIDs ids, WritableDoubleDataStore acds) {
FiniteProgress lrdsProgress = LOG.isVerbose() ? new FiniteProgress("Computing average chaining distances", ids.size(), LOG) : null;
// Compute the chaining distances.
// We do <i>not</i> bother to materialize the chaining order.
for(DBIDIter iter = ids.iter(); iter.valid(); iter.advance()) {
final KNNList neighbors = knnq.getKNNForDBID(iter, k);
final int r = neighbors.size();
DoubleDBIDListIter it1 = neighbors.iter(), it2 = neighbors.iter();
// Store the current lowest reachability.
final double[] mindists = new double[r];
for(int i = 0; it1.valid(); it1.advance(), ++i) {
mindists[i] = DBIDUtil.equal(it1, iter) ? Double.NaN : it1.doubleValue();
}
double acsum = 0.;
for(int j = ((r < k) ? r : k) - 1; j > 0; --j) {
// Find the minimum:
int minpos = -1;
double mindist = Double.NaN;
for(int i = 0; i < mindists.length; ++i) {
double curdist = mindists[i];
// Both values could be NaN, deliberately.
if(curdist == curdist && !(curdist > mindist)) {
minpos = i;
mindist = curdist;
}
}
acsum += mindist * j; // Weighted sum, decreasing weights
mindists[minpos] = Double.NaN;
it1.seek(minpos);
// Update distances
it2.seek(0);
for(int i = 0; it2.valid(); it2.advance(), ++i) {
final double curdist = mindists[i];
if(curdist != curdist) {
continue; // NaN = processed!
}