docs: public OutlierResult run(Relation<O> relation) {
      final DistanceQuery<O> distanceQuery = relation.getDistanceQuery(getDistanceFunction());
      final KNNQuery<O> knnQuery = relation.getKNNQuery(distanceQuery, k);
  
      FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("kNN distance for objects", relation.size(), LOG) : null;
  
      WritableDoubleDataStore knnDist = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
      WritableDBIDDataStore neighbor = DataStoreUtil.makeDBIDStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
      DBIDVar var = DBIDUtil.newVar();
      // Find nearest neighbors, and store the distances.
      for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
        final KNNList knn = knnQuery.getKNNForDBID(it, k);
        knnDist.putDouble(it, knn.getKNNDistance());
        neighbor.put(it, knn.assignVar(knn.size() - 1, var));
        LOG.incrementProcessed(prog);
      }
      LOG.ensureCompleted(prog);
  
      prog = LOG.isVerbose() ? new FiniteProgress("kNN distance descriptor", relation.size(), LOG) : null;
      WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_DB);
      DoubleMinMax minmax = new DoubleMinMax();
      for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
        // Distance
        double d = knnDist.doubleValue(it);
        // Distance of neighbor
        double nd = knnDist.doubleValue(neighbor.assignVar(it, var));
        double knndd = nd > 0 ? d / nd : d > 0 ? Double.POSITIVE_INFINITY : 1.;
        scores.put(it, knndd);
        minmax.put(knndd);
        LOG.incrementProcessed(prog);
      }
      LOG.ensureCompleted(prog);
      DoubleRelation scoreres = new MaterializedDoubleRelation("kNN Data Descriptor", "knndd-outlier", scores, relation.getDBIDs());
      OutlierScoreMeta meta = new BasicOutlierScoreMeta(minmax.getMin(), minmax.getMax(), 0., Double.POSITIVE_INFINITY, 1.);
      return new OutlierResult(meta, scoreres);
    }