protected void runPAMOptimization(DistanceQuery<V> distQ,DBIDs ids,ArrayModifiableDBIDs medoids,WritableIntegerDataStore assignment){
  WritableDoubleDataStore nearest=DataStoreUtil.makeDoubleStorage(ids,DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
  WritableDoubleDataStore second=DataStoreUtil.makeDoubleStorage(ids,DataStoreFactory.HINT_HOT | DataStoreFactory.HINT_TEMP);
  double tc=assignToNearestCluster(medoids,ids,nearest,second,assignment,distQ);
  if (LOG.isStatistics()) {
    LOG.statistics(new DoubleStatistic(KEY + ".iteration-" + 0+ ".cost",tc));
  }
  IndefiniteProgress prog=LOG.isVerbose() ? new IndefiniteProgress("PAM iteration",LOG) : null;
  DBIDVar bestid=DBIDUtil.newVar();
  DBIDArrayIter m=medoids.iter();
  int iteration=1;
  double[] cost=new double[k];
  for (; maxiter <= 0 || iteration <= maxiter; iteration++) {
    LOG.incrementProcessed(prog);
    double best=Double.POSITIVE_INFINITY;
    int bestcluster=-1;
    for (DBIDIter h=ids.iter(); h.valid(); h.advance()) {
      final int pm=assignment.intValue(h);
      m.seek(pm);
      double hdist=nearest.doubleValue(h);
      if (DBIDUtil.equal(m,h) || hdist <= 0.) {
        continue;
      }
      Arrays.fill(cost,-hdist);
      for (DBIDIter j=ids.iter(); j.valid(); j.advance()) {
        if (DBIDUtil.equal(h,j)) {
          continue;
        }
        final int pj=assignment.intValue(j);
        final double distcur=nearest.doubleValue(j);
        final double distsec=second.doubleValue(j);
        final double dist_h=distQ.distance(h,j);
        if (dist_h < distcur) {
          for (int pi=0; pi < k; pi++) {
            if (pi == pj) {
              cost[pi]+=((dist_h < distsec) ? dist_h : distsec) - distcur;
            }
 else {
              cost[pi]+=dist_h - distcur;
            }
          }
        }
 else {
          if (dist_h < distsec) {
            cost[pj]+=dist_h - distcur;
          }
 else {
            cost[pj]+=distsec - distcur;
          }
        }
      }
      for (int pi=0; pi < k; pi++) {
        if (cost[pi] < best) {
          best=cost[pi];
          bestid.set(h);
          bestcluster=pi;
        }
      }
    }
    if (best >= 0.) {
      break;
    }
    medoids.set(bestcluster,bestid);
    double nc=assignToNearestCluster(medoids,ids,nearest,second,assignment,distQ);
    if (LOG.isStatistics()) {
      LOG.statistics(new DoubleStatistic(KEY + ".iteration-" + iteration+ ".cost",nc));
    }
    if (nc > tc) {
      if (nc - tc < 1e-7 * tc) {
        LOG.warning("PAM failed to converge (numerical instability?)");
        break;
      }
      LOG.warning("PAM failed to converge: costs increased by: " + (nc - tc) + " exepected a decrease by "+ best);
      break;
    }
    tc=nc;
  }
  LOG.setCompleted(prog);
  if (LOG.isStatistics()) {
    LOG.statistics(new LongStatistic(KEY + ".iterations",iteration));
    LOG.statistics(new DoubleStatistic(KEY + ".iteration-" + iteration+ ".cost",tc));
  }
}

protected void runPAMOptimization ( DistanceQuery < V > distQ , DBIDs ids , ArrayModifiableDBIDs medoids , WritableIntegerDataStore assignment ) { WritableDoubleDataStore nearest = DataStoreUtil . makeDoubleStorage ( ids , DataStoreFactory . HINT_HOT | DataStoreFactory . HINT_TEMP ) ; WritableDoubleDataStore second = DataStoreUtil . makeDoubleStorage ( ids , DataStoreFactory . HINT_HOT | DataStoreFactory . HINT_TEMP ) ; double tc = assignToNearestCluster ( medoids , ids , nearest , second , assignment , distQ ) ; if ( LOG . isStatistics ( ) ) { LOG . statistics ( new DoubleStatistic ( KEY + ".iteration-" + 0 + ".cost" , tc ) ) ; } IndefiniteProgress prog = LOG . isVerbose ( ) ? new IndefiniteProgress ( "PAM iteration" , LOG ) : null ; DBIDVar bestid = DBIDUtil . newVar ( ) ; DBIDArrayIter m = medoids . iter ( ) ; int iteration = 1 ; double [ ] cost = new double [ k ] ; for ( ; maxiter <= 0 || iteration <= maxiter ; iteration ++ ) { LOG . incrementProcessed ( prog ) ; double best = Double . POSITIVE_INFINITY ; int bestcluster = - 1 ; for ( DBIDIter h = ids . iter ( ) ; h . valid ( ) ; h . advance ( ) ) { final int pm = assignment . intValue ( h ) ; m . seek ( pm ) ; double hdist = nearest . doubleValue ( h ) ; if ( DBIDUtil . equal ( m , h ) || hdist <= 0. ) { continue ; } Arrays . fill ( cost , - hdist ) ; for ( DBIDIter j = ids . iter ( ) ; j . valid ( ) ; j . advance ( ) ) { if ( DBIDUtil . equal ( h , j ) ) { continue ; } final int pj = assignment . intValue ( j ) ; final double distcur = nearest . doubleValue ( j ) ; final double distsec = second . doubleValue ( j ) ; final double dist_h = distQ . distance ( h , j ) ; if ( dist_h < distcur ) { for ( int pi = 0 ; pi < k ; pi ++ ) { if ( pi == pj ) { cost [ pi ] += ( ( dist_h < distsec ) ? dist_h : distsec ) - distcur ; } else { cost [ pi ] += dist_h - distcur ; } } } else { if ( dist_h < distsec ) { cost [ pj ] += dist_h - distcur ; } else { cost [ pj ] += distsec - distcur ; } } } for ( int pi = 0 ; pi < k ; pi ++ ) { if ( cost [ pi ] < best ) { best = cost [ pi ] ; bestid . set ( h ) ; bestcluster = pi ; } } } if ( best >= 0. ) { break ; } medoids . set ( bestcluster , bestid ) ; double nc = assignToNearestCluster ( medoids , ids , nearest , second , assignment , distQ ) ; if ( LOG . isStatistics ( ) ) { LOG . statistics ( new DoubleStatistic ( KEY + ".iteration-" + iteration + ".cost" , nc ) ) ; } if ( nc > tc ) { if ( nc - tc < 1e-7 * tc ) { LOG . warning ( "PAM failed to converge (numerical instability?)" ) ; break ; } LOG . warning ( "PAM failed to converge: costs increased by: " + ( nc - tc ) + " exepected a decrease by " + best ) ; break ; } tc = nc ; } LOG . setCompleted ( prog ) ; if ( LOG . isStatistics ( ) ) { LOG . statistics ( new LongStatistic ( KEY + ".iterations" , iteration ) ) ; LOG . statistics ( new DoubleStatistic ( KEY + ".iteration-" + iteration + ".cost" , tc ) ) ; } }
run the pam optimization phase .
