public OutlierResult run(Relation<O> relation) {
    DistanceQuery<O> dq = relation.getDistanceQuery(getDistanceFunction());
    final double logPerp = FastMath.log(perplexity);

    ModifiableDoubleDBIDList dlist = DBIDUtil.newDistanceDBIDList(relation.size() - 1);
    DoubleDBIDListMIter di = dlist.iter();
    double[] p = new double[relation.size() - 1];
    FiniteProgress prog = LOG.isVerbose() ? new FiniteProgress("SOS scores", relation.size(), LOG) : null;
    WritableDoubleDataStore scores = DataStoreUtil.makeDoubleStorage(relation.getDBIDs(), DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_DB, 1.);
    for(DBIDIter it = relation.iterDBIDs(); it.valid(); it.advance()) {
      // Build sorted neighbors list.
      dlist.clear();
      for(DBIDIter i2 = relation.iterDBIDs(); i2.valid(); i2.advance()) {
        if(DBIDUtil.equal(it, i2)) {
          continue;
        }
        dlist.add(dq.distance(it, i2), i2);
      }
      dlist.sort();
      // Compute affinities
      computePi(it, di, p, perplexity, logPerp);
      // Normalization factor:
      double s = sumOfProbabilities(it, di, p);
      if(s > 0) {
        nominateNeighbors(it, di, p, 1. / s, scores);
      }
      LOG.incrementProcessed(prog);
    }
    LOG.ensureCompleted(prog);
    // Find minimum and maximum.
    DoubleMinMax minmax = new DoubleMinMax();
    for(DBIDIter it2 = relation.iterDBIDs(); it2.valid(); it2.advance()) {
      minmax.put(scores.doubleValue(it2));
    }
    DoubleRelation scoreres = new MaterializedDoubleRelation("Stoachastic Outlier Selection", "sos-outlier", scores, relation.getDBIDs());
    OutlierScoreMeta meta = new ProbabilisticOutlierScore(minmax.getMin(), minmax.getMax(), 0.);
    return new OutlierResult(meta, scoreres);
  }
public OutlierResult run ( Relation < O > relation ) { DistanceQuery < O > dq = relation . getDistanceQuery ( getDistanceFunction ( ) ) ; final double logPerp = FastMath . log ( perplexity ) ; ModifiableDoubleDBIDList dlist = DBIDUtil . newDistanceDBIDList ( relation . size ( ) - 1 ) ; DoubleDBIDListMIter di = dlist . iter ( ) ; double [ ] p = new double [ relation . size ( ) - 1 ] ; FiniteProgress prog = LOG . isVerbose ( ) ? new FiniteProgress ( "SOS scores" , relation . size ( ) , LOG ) : null ; WritableDoubleDataStore scores = DataStoreUtil . makeDoubleStorage ( relation . getDBIDs ( ) , DataStoreFactory . HINT_HOT | DataStoreFactory . HINT_DB , 1. ) ; for ( DBIDIter it = relation . iterDBIDs ( ) ; it . valid ( ) ; it . advance ( ) ) { dlist . clear ( ) ; for ( DBIDIter i2 = relation . iterDBIDs ( ) ; i2 . valid ( ) ; i2 . advance ( ) ) { if ( DBIDUtil . equal ( it , i2 ) ) { continue ; } dlist . add ( dq . distance ( it , i2 ) , i2 ) ; } dlist . sort ( ) ; computePi ( it , di , p , perplexity , logPerp ) ; double s = sumOfProbabilities ( it , di , p ) ; if ( s > 0 ) { nominateNeighbors ( it , di , p , 1. / s , scores ) ; } LOG . incrementProcessed ( prog ) ; } LOG . ensureCompleted ( prog ) ; DoubleMinMax minmax = new DoubleMinMax ( ) ; for ( DBIDIter it2 = relation . iterDBIDs ( ) ; it2 . valid ( ) ; it2 . advance ( ) ) { minmax . put ( scores . doubleValue ( it2 ) ) ; } DoubleRelation scoreres = new MaterializedDoubleRelation ( "Stoachastic Outlier Selection" , "sos-outlier" , scores , relation . getDBIDs ( ) ) ; OutlierScoreMeta meta = new ProbabilisticOutlierScore ( minmax . getMin ( ) , minmax . getMax ( ) , 0. ) ; return new OutlierResult ( meta , scoreres ) ; }
Run the algorithm.

@param relation data relation
@return outlier detection result