package yi.iu.imgdb.learn.absrgn;

import java.util.*;


/**
 * Abstract Region Promising bi-relationship Selector (ARPS).  Select those
 * relationship that appear the most in the positive image instances.
 */

public class ARPSMostAppearances implements AbsRgnPromisingBiRelSelector{

  /**
   * Select those relationship that appear the most in the positive image
   * instances.  For example, if the intersections of abstract region type i
   * and abstract region type j appear a lot in the positive image instances,
   * we may want to consider select them
   *
   * @param candidates
   * @param n
   * @return
   */
  public AbsRgnProbMap[][] select(AbsRgnProbMap[][]
                                            candidates,
                                            boolean[] pos_inst_flag, int n) {

    int img_n = candidates.length;
    int cand_n = candidates[0].length;

    // for each possible relationship, get a score
    final double[] scores = new double[cand_n];
    for (int i = 0; i < cand_n; i++) {
      // group the regions for the overlapping candidate
      AbsRgnProbMap[] cands = new AbsRgnProbMap[img_n];
      for (int j = 0; j < img_n; j++) {
        cands[j] = candidates[j][i];
      }
      scores[i] = score(cands, pos_inst_flag);
      System.out.println("score for relation candidate " + i + " : " + scores[i]);
    }

    // sort the relation candidates according to their scores
    Integer[] cand_index = new Integer[cand_n];
    for (int i = 0; i < cand_n; i++)
      cand_index[i] = new Integer(i);
    Arrays.sort(cand_index, new Comparator() {
      /**
       * Get the one with highest score first
       * @param o1
       * @param o2
       * @return
       */
      public int compare(Object o1, Object o2) {
        double score1 = scores[ ((Integer) o1).intValue()];
        double score2 = scores[  ((Integer) o2).intValue()];
        if (score1 < score2) return 1;
        else if (score1 > score2) return -1;
        else return 0;
      }
    });

    // return the top n candidates
    AbsRgnProbMap[][] tops = new AbsRgnProbMap[img_n][n];
    for (int i = 0; i < n; i++) {
      int index = ((Integer)cand_index[i]).intValue();
      System.out.println("top " + i + ": index " + index + ", score = " + scores[index]);
      for (int j = 0; j < img_n; j++) {
        tops[j][i] = candidates[j][index];
      }
    }
    return tops;
  }

  /**
   * Given the abstract regions for a relation candiate, generate a promising
   * score.  The higher, the better.  For each image, there are several regions
   * correspondings to the abstract region candidate, each one having a
   * probability score.
   * This mothod picks the highest probability for each image.  (it basically
   * represents how likely that image having this kind of abstract region).
   * Then calculate the average probability from all the positive images as
   * the score of the relationship candidate
   * @param absrgns
   * @param pos_inst_flag
   * @return
   */
  public double score(AbsRgnProbMap[] absrgns, boolean[] pos_inst_flag) {
    double sum = 0;
    int count = 0;
    for (int i=0; i<absrgns.length; i++) {
      if (!pos_inst_flag[i]) continue;
      double prob = (absrgns[i] == null) ? 0 : absrgns[i].getMaxProbability();
      sum += prob;
      count ++;
    }
    return sum/count;
  }

  public double score(double[] probs, boolean[] pos_inst_flag) {
    double sum = 0;
    int count = 0;
    for (int i=0; i<probs.length; i++) {
      if (!pos_inst_flag[i]) continue;
      double prob = probs[i];
      sum += prob;
      count ++;
    }
    return sum/count;
  }

}