docs: public OutlierResult run(Database database, Relation<O> relation) {
      DistanceQuery<O> distFunc = database.getDistanceQuery(relation, getDistanceFunction());
      KNNQuery<O> knnQuery = database.getKNNQuery(distFunc, k);
  
      // track the maximum value for normalization
      DoubleMinMax ldofminmax = new DoubleMinMax();
      // compute the ldof values
      WritableDoubleDataStore ldofs = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
  
      // compute LOF_SCORE of each db object
      if(LOG.isVerbose()) {
        LOG.verbose("Computing LDOFs");
      }
      FiniteProgress progressLDOFs = LOG.isVerbose() ? new FiniteProgress("LDOF for objects", relation.size(), LOG) : null;
  
      Mean dxp = new Mean(), Dxp = new Mean();
      for(DBIDIter iditer = relation.iterDBIDs(); iditer.valid(); iditer.advance()) {
        KNNList neighbors = knnQuery.getKNNForDBID(iditer, k);
        dxp.reset();
        Dxp.reset();
        DoubleDBIDListIter neighbor1 = neighbors.iter(),
            neighbor2 = neighbors.iter();
        for(; neighbor1.valid(); neighbor1.advance()) {
          // skip the point itself
          if(DBIDUtil.equal(neighbor1, iditer)) {
            continue;
          }
          dxp.put(neighbor1.doubleValue());
          for(neighbor2.seek(neighbor1.getOffset() + 1); neighbor2.valid(); neighbor2.advance()) {
            // skip the point itself
            if(DBIDUtil.equal(neighbor2, iditer)) {
              continue;
            }
            Dxp.put(distFunc.distance(neighbor1, neighbor2));
          }
        }
        double ldof = dxp.getMean() / Dxp.getMean();
        if(Double.isNaN(ldof) || Double.isInfinite(ldof)) {
          ldof = 1.0;
        }
        ldofs.putDouble(iditer, ldof);
        // update maximum
        ldofminmax.put(ldof);
  
        LOG.incrementProcessed(progressLDOFs);
      }
      LOG.ensureCompleted(progressLDOFs);
  
      // Build result representation.
      DoubleRelation scoreResult = new MaterializedDoubleRelation("LDOF Outlier Score", "ldof-outlier", ldofs, relation.getDBIDs());
      OutlierScoreMeta scoreMeta = new QuotientOutlierScoreMeta(ldofminmax.getMin(), ldofminmax.getMax(), 0.0, Double.POSITIVE_INFINITY, LDOF_BASELINE);
      return new OutlierResult(scoreMeta, scoreResult);
    }