/*
* Copyright (C) 2015 RankSys (http://ranksys.org)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.ranksys.novdiv.reranking;
import es.uam.eps.ir.ranksys.core.Recommendation;
import es.uam.eps.ir.ranksys.fast.utils.topn.IntDoubleTopN;
import es.uam.eps.ir.ranksys.novdiv.reranking.PermutationReranker;
import static java.lang.Math.log;
import static java.lang.Math.min;
import static java.lang.Math.sqrt;
import java.util.List;
import org.apache.commons.math3.distribution.NormalDistribution;
import org.ranksys.core.util.tuples.Tuple2od;
/**
* Dithering re-ranker. It re-ranks the output of a recommendation by adding
* gaussian noise.
* <br>
* Check: https://buildingrecommenders.wordpress.com/2015/11/11/dithering/
*
* @author Saúl Vargas (Saul.Vargas@mendeley.com)
*
* @param <U> type of the users
* @param <I> type of the items
*/
public class DitheringReranker<U, I> extends PermutationReranker<U, I> {
private final double variance;
/**
* Constructor.
*
* @param variance variance of the gaussian noise to be added to the original
* recommendation scores.
*/
public DitheringReranker(double variance) {
this.variance = variance;
}
@Override
public int[] rerankPermutation(Recommendation<U, I> recommendation, int maxLength) {
List<Tuple2od<I>> items = recommendation.getItems();
int M = items.size();
int N = min(maxLength, M);
if (variance == 0.0) {
return getBasePerm(N);
}
NormalDistribution dist = new NormalDistribution(0.0, sqrt(variance));
IntDoubleTopN topN = new IntDoubleTopN(N);
for (int i = 0; i < M; i++) {
topN.add(M - i, log(i + 1) + dist.sample());
}
topN.sort();
return topN.stream()
.mapToInt(e -> M - e.v1)
.toArray();
}
}