private Pair<DBIDVar,Double> singleIteration(Relation<V> relationx,Relation<? extends NumberVector> relationy){
  final int dim=RelationUtil.dimensionality(relationx);
  final int dimy=RelationUtil.dimensionality(relationy);
  assert (dim == 2);
  KNNQuery<V> knnQuery=QueryUtil.getKNNQuery(relationx,getDistanceFunction(),k + 1);
  ArrayModifiableDBIDs ids=DBIDUtil.newArray(relationx.getDBIDs());
  ids.sort();
  double[][] X=new double[ids.size()][6];
  double[][] F=new double[ids.size()][ids.size()];
  double[][] Y=new double[ids.size()][dimy];
{
    int i=0;
    for (DBIDIter id=ids.iter(); id.valid(); id.advance(), i++) {
{
        V vec=relationx.get(id);
        double la=vec.doubleValue(0);
        double lo=vec.doubleValue(1);
        X[i][0]=1.0;
        X[i][1]=la;
        X[i][2]=lo;
        X[i][3]=la * lo;
        X[i][4]=la * la;
        X[i][5]=lo * lo;
      }
{
        final NumberVector vecy=relationy.get(id);
        for (int d=0; d < dimy; d++) {
          double idy=vecy.doubleValue(d);
          Y[i][d]=idy;
        }
      }
{
        KNNList neighbors=knnQuery.getKNNForDBID(id,k + 1);
        ModifiableDBIDs neighborhood=DBIDUtil.newArray(neighbors.size());
        for (DBIDIter neighbor=neighbors.iter(); neighbor.valid(); neighbor.advance()) {
          if (DBIDUtil.equal(id,neighbor)) {
            continue;
          }
          neighborhood.add(neighbor);
        }
        F[i][i]=1.0;
        final int nweight=-1 / neighborhood.size();
        for (DBIDIter iter=neighborhood.iter(); iter.valid(); iter.advance()) {
          int pos=ids.binarySearch(iter);
          assert (pos >= 0);
          F[pos][i]=nweight;
        }
      }
    }
  }
  double[][] common=times(transposeTimesTranspose(X,F),F);
  double[][] b=times(inverse(times(common,X)),times(common,Y));
  double[][] sigmaMat=times(F,minusEquals(times(X,b),times(F,Y)));
  final double sigma_sum_square=normF(sigmaMat) / (relationx.size() - 6 - 1);
  final double norm=1 / Math.sqrt(sigma_sum_square);
  double[][] E=timesEquals(times(F,minus(Y,times(X,b))),norm);
  DBIDVar worstid=DBIDUtil.newVar();
  double worstscore=Double.NEGATIVE_INFINITY;
  int i=0;
  for (DBIDIter id=ids.iter(); id.valid(); id.advance(), i++) {
    double err=squareSum(getRow(E,i));
    if (err > worstscore) {
      worstscore=err;
      worstid.set(id);
    }
  }
  return new Pair<>(worstid,Math.sqrt(worstscore));
}

private Pair < DBIDVar , Double > singleIteration ( Relation < V > relationx , Relation < ? extends NumberVector > relationy ) { final int dim = RelationUtil . dimensionality ( relationx ) ; final int dimy = RelationUtil . dimensionality ( relationy ) ; assert ( dim == 2 ) ; KNNQuery < V > knnQuery = QueryUtil . getKNNQuery ( relationx , getDistanceFunction ( ) , k + 1 ) ; ArrayModifiableDBIDs ids = DBIDUtil . newArray ( relationx . getDBIDs ( ) ) ; ids . sort ( ) ; double [ ] [ ] X = new double [ ids . size ( ) ] [ 6 ] ; double [ ] [ ] F = new double [ ids . size ( ) ] [ ids . size ( ) ] ; double [ ] [ ] Y = new double [ ids . size ( ) ] [ dimy ] ; { int i = 0 ; for ( DBIDIter id = ids . iter ( ) ; id . valid ( ) ; id . advance ( ) , i ++ ) { { V vec = relationx . get ( id ) ; double la = vec . doubleValue ( 0 ) ; double lo = vec . doubleValue ( 1 ) ; X [ i ] [ 0 ] = 1.0 ; X [ i ] [ 1 ] = la ; X [ i ] [ 2 ] = lo ; X [ i ] [ 3 ] = la * lo ; X [ i ] [ 4 ] = la * la ; X [ i ] [ 5 ] = lo * lo ; } { final NumberVector vecy = relationy . get ( id ) ; for ( int d = 0 ; d < dimy ; d ++ ) { double idy = vecy . doubleValue ( d ) ; Y [ i ] [ d ] = idy ; } } { KNNList neighbors = knnQuery . getKNNForDBID ( id , k + 1 ) ; ModifiableDBIDs neighborhood = DBIDUtil . newArray ( neighbors . size ( ) ) ; for ( DBIDIter neighbor = neighbors . iter ( ) ; neighbor . valid ( ) ; neighbor . advance ( ) ) { if ( DBIDUtil . equal ( id , neighbor ) ) { continue ; } neighborhood . add ( neighbor ) ; } F [ i ] [ i ] = 1.0 ; final int nweight = - 1 / neighborhood . size ( ) ; for ( DBIDIter iter = neighborhood . iter ( ) ; iter . valid ( ) ; iter . advance ( ) ) { int pos = ids . binarySearch ( iter ) ; assert ( pos >= 0 ) ; F [ pos ] [ i ] = nweight ; } } } } double [ ] [ ] common = times ( transposeTimesTranspose ( X , F ) , F ) ; double [ ] [ ] b = times ( inverse ( times ( common , X ) ) , times ( common , Y ) ) ; double [ ] [ ] sigmaMat = times ( F , minusEquals ( times ( X , b ) , times ( F , Y ) ) ) ; final double sigma_sum_square = normF ( sigmaMat ) / ( relationx . size ( ) - 6 - 1 ) ; final double norm = 1 / Math . sqrt ( sigma_sum_square ) ; double [ ] [ ] E = timesEquals ( times ( F , minus ( Y , times ( X , b ) ) ) , norm ) ; DBIDVar worstid = DBIDUtil . newVar ( ) ; double worstscore = Double . NEGATIVE_INFINITY ; int i = 0 ; for ( DBIDIter id = ids . iter ( ) ; id . valid ( ) ; id . advance ( ) , i ++ ) { double err = squareSum ( getRow ( E , i ) ) ; if ( err > worstscore ) { worstscore = err ; worstid . set ( id ) ; } } return new Pair < > ( worstid , Math . sqrt ( worstscore ) ) ; }
run a single iteration of the gls - sod modeling step
