/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package edu.uci.jforests.eval.ranking;

/**
 * Graded Average Precision (GAP)
 *
 */

/**
 * @author Yasser Ganjisaffar 
 */

public class GAPEval {

	public static final int GAIN_LEVELS = 5;
	private static double[] g_cumulative = { 0, 0.25, 0.50, 0.75, 1.0 };

	private static int[] getCountPerGrade(int[] labels) {
		int[] countPerGrade = new int[GAIN_LEVELS];
		for (int label : labels) {
			countPerGrade[label]++;
		}
		return countPerGrade;
	}

	private static double getMaxExpectedPrecision(int[] labels) {
		int[] countPerGrade = getCountPerGrade(labels);
		double denom = 0;
		for (int i = 1; i < GAIN_LEVELS; i++) {
			denom += countPerGrade[i] * g_cumulative[i];
		}
		return denom;
	}

	public static double getGAP(int[] labels) {
		double denom = getMaxExpectedPrecision(labels);
		double numerator = 0;
		for (int n = 0; n < labels.length; n++) {
			double sum = 0;
			for (int m = 0; m <= n; m++) {
				if (labels[m] > 0) {
					sum += g_cumulative[(int) Math.min(labels[m], labels[n])];
				}
			}
			numerator += sum / (n + 1);
		}
		return numerator / denom;
	}
	
	public static double getDeltaGAP(int[] labels, int[][] cumulativeLabelCount, int p, int q, double maxExpectedPrecision) {
		double numerator = 0;
		int label_p = labels[p];
		int label_q = labels[q];
		double sum1 = 0;
		double sum2 = 0;		
		if (label_q > 0) {
			for (int i = 1; i < GAIN_LEVELS; i++) {
				if (label_q > i) {
					if (p > 0) {
						sum1 += cumulativeLabelCount[p - 1][i] * g_cumulative[i];
					}
					sum2 -= cumulativeLabelCount[q][i] * g_cumulative[i];
				} else {
					if (p > 0) {
						sum1 += cumulativeLabelCount[p - 1][i] * g_cumulative[label_q];
					}
					sum2 -= cumulativeLabelCount[q][i] * g_cumulative[label_q];
				}
			}
			sum1 += g_cumulative[label_q];
		}
		if (label_p > 0) {
			for (int i = 1; i < GAIN_LEVELS; i++) {
				if (label_p > i) {
					if (p > 0) {
						sum1 -= cumulativeLabelCount[p - 1][i] * g_cumulative[i];
					}
					sum2 += cumulativeLabelCount[q][i] * g_cumulative[i];
				} else {
					if (p > 0) {
						sum1 -= cumulativeLabelCount[p - 1][i] * g_cumulative[label_p];
					}
					sum2 += cumulativeLabelCount[q][i] * g_cumulative[label_p];
				}
			}			
			sum1 -= g_cumulative[label_p];
		}

		numerator += sum1 / (p + 1);
		numerator += sum2 / (q + 1);

		for (int n = p + 1; n <= q - 1; n++) {
			if (labels[n] > 0) {
				double deltaQN = (label_q < labels[n] ? g_cumulative[label_q] : g_cumulative[labels[n]]);
				double deltaPN = (label_p < labels[n] ? g_cumulative[label_p] : g_cumulative[labels[n]]);
				numerator += (deltaQN - deltaPN) / (n + 1);
			}
		}

		return Math.abs(numerator) / maxExpectedPrecision;
	}

	public static double[] getMaxExpectedPrecisionForAllQueries(double[] labels, int[] boundaries, int[][] labelCounts)
			throws Exception {
		double[] maxExpectedPrecision = new double[boundaries.length - 1];

		for (int q = 0; q < boundaries.length - 1; q++) {
			maxExpectedPrecision[q] = 0;
			for (int i = 1; i < GAIN_LEVELS; i++) {
				maxExpectedPrecision[q] += labelCounts[q][i] * g_cumulative[i];
			}
		}
		return maxExpectedPrecision;
	}
	
}

 

Ads help maintain this website.