@@ -0,0 +1,2224 @@
+package org.grouplens.lenskit.knn;%0A%0Aimport it.unimi.dsi.fastutil.longs.AbstractLongComparator;%0Aimport it.unimi.dsi.fastutil.longs.LongArrays;%0A%0Aimport org.grouplens.lenskit.data.vector.MutableSparseVector;%0Aimport org.grouplens.lenskit.data.vector.SparseVector;%0A%0Aimport com.google.common.primitives.Doubles;%0A%0A/**%0A * @author Michael Ekstrand %3Cekstrand@cs.umn.edu%3E%0A *%0A */%0Apublic class SpearmanRankCorrelation implements%0A        OptimizableVectorSimilarity%3CSparseVector%3E %7B%0A    private PearsonCorrelation pearson = new PearsonCorrelation();%0A    %0A    public SpearmanRankCorrelation(int thresh) %7B%0A        if (thresh %3E 0)%0A            pearson = new SignificanceWeightedPearsonCorrelation(thresh);%0A        else%0A            pearson = new PearsonCorrelation();%0A    %7D%0A    %0A    public SpearmanRankCorrelation() %7B%0A        this(0);%0A    %7D%0A    %0A    static SparseVector rank(final SparseVector vec) %7B%0A        long%5B%5D ids = vec.keySet().toLongArray();%0A        // sort ID set by value (decreasing)%0A        LongArrays.quickSort(ids, new AbstractLongComparator() %7B%0A            @Override%0A            public int compare(long k1, long k2) %7B%0A                return Doubles.compare(vec.get(k2), vec.get(k1));%0A            %7D%0A        %7D);%0A        %0A        final int n = ids.length;%0A        final double%5B%5D values = new double%5Bn%5D;%0A        MutableSparseVector rank = vec.mutableCopy();%0A        // assign ranks to each item%0A        for (int i = 0; i %3C n; i++) %7B%0A            rank.set(ids%5Bi%5D, i+1);%0A            values%5Bi%5D = vec.get(ids%5Bi%5D);%0A        %7D%0A        %0A        // average ranks for items with same values%0A        int i = 0;%0A        while (i %3C n) %7B%0A            int j;%0A            for (j = i+1; j %3C n; j++) %7B%0A                if (values%5Bj%5D != values%5Bi%5D)%0A                    break;%0A            %7D%0A            if (j - i %3E 1) %7B%0A                double r2 = (rank.get(ids%5Bi%5D) + rank.get(ids%5Bj-1%5D)) / (j - i);%0A                for (int k = i; k %3C j; k++)%0A                    rank.set(ids%5Bk%5D, r2);%0A            %7D%0A            i = j;%0A        %7D%0A        %0A        // Make a sparse vector out of it%0A        return rank;%0A    %7D%0A%0A    @Override%0A    public double similarity(SparseVector vec1, SparseVector vec2) %7B%0A        return pearson.similarity(rank(vec1), rank(vec2));%0A    %7D%0A%7D%0A

Implement Spearman rank correlation