/*
 * LensKit, an open source recommender systems toolkit.
 * Copyright 2010-2012 Regents of the University of Minnesota and contributors
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 */
package org.grouplens.lenskit.vectors.similarity;

import static java.lang.Math.max;

import java.io.Serializable;

import javax.inject.Inject;

import org.grouplens.lenskit.core.Shareable;
import org.grouplens.lenskit.knn.params.WeightThreshold;
import org.grouplens.lenskit.vectors.SparseVector;

/**
 * Apply significance weighting to a similarity function. The threshold
 * is configured with the {@link WeightThreshold} parameter.
 *
 * <p>Significance weighting decreases the similarity between two vectors when
 * the number of common entities between the two vectors is low.  For a threshold
 * \(S\) and key sets \(K_1\) and \(K_2\), the similarity is multipled by
 * \[\frac{|K_1 \cap K_2|}{\mathrm{max}(|K_1 \cap K_2|, S)}\]
 *
 * <ul>
 * <li>Herlocker, J., Konstan, J.A., and Riedl, J. <a
 * href="http://dx.doi.org/10.1023/A:1020443909834">An Empirical Analysis of
 * Design Choices in Neighborhood-Based Collaborative Filtering Algorithms</a>.
 * <i>Information Retrieval</i> Vol. 5 Issue 4 (October 2002), pp. 287-310.</li>
 * </ul>
 *
 * @see WeightThreshold
 */
@Shareable
public class SignificanceWeightedVectorSimilarity implements VectorSimilarity, Serializable {

    private static final long serialVersionUID = 1L;

    private final int threshold;
    private final VectorSimilarity delegate;

    @Inject
    public SignificanceWeightedVectorSimilarity(@WeightThreshold int thresh,
                                                VectorSimilarity sim) {
        threshold = thresh;
        delegate = sim;
    }

    @Override
    public double similarity(SparseVector vec1, SparseVector vec2) {
        double s = delegate.similarity(vec1, vec2);
        int n = vec1.countCommonKeys(vec2);
        s *= n;
        return s / max(n, threshold);
    }

    @Override
    public boolean isSparse() {
        return delegate.isSparse();
    }

    @Override
    public boolean isSymmetric() {
        return delegate.isSymmetric();
    }

}

@@ -919,102 +919,8 @@
 y;%0A%0A
-import static java.lang.Math.max;%0A%0Aimport java.io.Serializable;%0A%0Aimport javax.inject.Inject;%0A%0A
 impo
@@ -993,19 +993,18 @@
 kit.
-knn.
 params.
+Sig
 Weig
@@ -1068,16 +1068,109 @@
 ector;%0A%0A
+import javax.inject.Inject;%0Aimport java.io.Serializable;%0A%0Aimport static java.lang.Math.max;%0A%0A
 /**%0A * A
@@ -2241,16 +2241,19 @@
 larity(@
+Sig
 WeightTh

Fix sig weight dependency