/** * Get the maximum value by which score difference between any two recommendations can be changed * by post processing. * * @param input input to the recommendation engine. Typically the person or item recommendations * are being computed for. * @param context additional information about the recommendation process. * @return maximum relative change. If unknown, {@link Float#POSITIVE_INFINITY} will be returned. */ private float maxRelativeChange(IN input, Context<OUT, IN> context) { float result = 0f; for (PostProcessor<OUT, IN> postProcessor : postProcessors) { float posInfluence = postProcessor.maxPositiveScore(input, context); float negInfluence = postProcessor.maxNegativeScore(input, context); if (posInfluence < 0) { throw new IllegalStateException( postProcessor + " has a negative influence score (" + posInfluence + "), should not be negative"); } if (negInfluence > 0) { throw new IllegalStateException( postProcessor + " has a positive influence score (" + negInfluence + "), should not be positive"); } if (Float.isInfinite(negInfluence) || Float.isInfinite(posInfluence)) { result = Float.POSITIVE_INFINITY; break; } result += Math.abs(negInfluence) + Math.abs(posInfluence); } return result; }
/** {@inheritDoc} */ @Override public Recommendations<OUT> doRecommend(IN input, Context<OUT, IN> context) { Recommendations<OUT> recommendations = new Recommendations<>(); for (RecommendationEngine<OUT, IN> engine : engines) { if (engine.participationPolicy(context).participate(input, context, recommendations)) { recommendations.merge(engine.recommend(input, context)); } } removeIrrelevant(input, context, recommendations); for (PostProcessor<OUT, IN> postProcessor : postProcessors) { postProcessor.postProcess(recommendations, input, context); } return recommendations; }