package yi.iu.imgdb.learn.kmeans;

import java.util.*;

import yi.ds.*;
import yi.ds.sort.*;
import yi.iu.imgdb.learn.*;
import yi.ds.hash.*;

/**
 * ClosestNKMeansClassifier classify the given feature vector to the cloest N
 * K-Means
 */

public class ClosestNKMeansClassifier implements ImgDBClassifier {

  /**
   * N closest K-Means will be returned
   */
  int N;

  /**
   * The K-Means
   */
  KMeansModel m_models;

  /**
   * Cache the means
   */
  HashMap m_means;

  public ClosestNKMeansClassifier(int N) {
    this.N = N;

  }

  public void setModels(ObjImgModel model) {
    m_models = (KMeansModel)model;
    m_means = m_models.getMeans();
  }

  public DoubleScoreHashMap classify(double[] feature) {
    TopKeeper tops = new TopKeeper(N);
    for (Iterator i= m_means.keySet().iterator(); i.hasNext(); ) {
      Object key = i.next();
      double[] mean = (double[]) m_means.get(key);
      double distance = yi.math.VectorUtil.EuclideanDistance(mean, feature);
      tops.insert(key, -distance); // TopKeeper keeps the biggest
    }
    DoubleScoreHashMap objects = new DoubleScoreHashMap();
    Vector top_objs = tops.getTopObjects();
    double[] top_scores = tops.getTops();
    for (int i=0; i<top_scores.length; i++) {
      objects.putScore(top_objs.elementAt(i), -top_scores[i]);
    }
    return objects;
  }

  public DoubleScoreHashMap classify(Collection features) {
    DoubleScoreHashMap rsts = new DoubleScoreHashMap();
    for (Iterator i= features.iterator(); i.hasNext(); ) {
      double[] feature = (double[]) i.next();
      DoubleScoreHashMap rst = classify(feature);
      for (Iterator j= rst.keySet().iterator(); j.hasNext(); ) {
        Object obj = j.next();
        rsts.putScoreWhenHigher(obj, rst.getScore(obj));
      }
    }
    return rsts;
  }
}