All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.graphaware.reco.generic.result.PartialScore Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2013-2016 GraphAware
 *
 * This file is part of the GraphAware Framework.
 *
 * GraphAware Framework is free software: you can redistribute it and/or modify it under the terms of
 * the GNU General Public License as published by the Free Software Foundation, either
 * version 3 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, see
 * .
 */

package com.graphaware.reco.generic.result;

import com.graphaware.reco.generic.util.AtomicFloat;

import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * A contribution to the total score of a particular recommendation that has been discovered. Typically, there will
 * be a single {@link PartialScore} for each {@link com.graphaware.reco.generic.engine.RecommendationEngine}
 * (i.e., logical reason) that has discovered a particular recommendation.
 * 

* For example, when building a "people you should be friends with" recommendation engine, for each recommendation discovered, * there would be one {@link PartialScore} representing "friends in common" score contribution, * and another {@link PartialScore} representing "common interests" score contribution. *

* The total numerical value of the contribution can be obtained by {@link #getValue()} and is kept up-to-date at all times. *

* Optionally, details about the actual contribution, such as the number of and the names of friends in common, are encapsulated * by {@link PartialScore} in the form of {@link com.graphaware.reco.generic.result.Reason}s. *

* Please note that {@link com.graphaware.reco.generic.transform.ScoreTransformer}s can be applied to the {@link PartialScore} * and change the total score only. In these cases, the value returned by {@link #getValue()} could end up being different from * the sum of individual {@link com.graphaware.reco.generic.result.Reason}s values. *

* This class is thread-safe. */ public class PartialScore { private final AtomicFloat value = new AtomicFloat(0); private final Set reasons = Collections.newSetFromMap(new ConcurrentHashMap()); /** * Create a new partial score with value = 0 and no further details. */ public PartialScore() { } /** * Create a new partial score with the given value and no further details. * * @param value of this partial score's contribution to the total score. Can be negative in case of penalties, for instance. */ public PartialScore(float value) { add(value, null); } /** * Create a new partial score with the given value and details about the value. The value and details will become an immutable * {@link com.graphaware.reco.generic.result.Reason}. Additionally, the value will become the total value of * this partial score and can be later modified, for example, by {@link com.graphaware.reco.generic.transform.ScoreTransformer}s. * * @param value of this partial score's contribution to the total score. Can be negative in case of penalties, for instance. * @param details about the value as arbitrary key-value pairs. */ public PartialScore(float value, Map details) { add(value, details); } /** * Add a number to the total value of this partial score with no additional details. * * @param value to add. */ public void add(float value) { this.value.addAndGet(value); } /** * Add a number to the total value of this partial score with additional details about the value. The value and details * will become an immutable {@link com.graphaware.reco.generic.result.Reason}. Additionally, the value will be added to * the total value of this partial score, which can be later modified, for example, by {@link com.graphaware.reco.generic.transform.ScoreTransformer}s. * * @param value to add. * @param details about the value as arbitrary key-value pairs. */ public void add(float value, Map details) { add(value); addReason(value, details); } /** * Add the contents (value and details) of another partial score to this partial score. * * @param partialScore to add. */ public void add(PartialScore partialScore) { add(partialScore.getValue()); addReasons(partialScore.getReasons()); } /** * Add a reason to this partial score. The reason is built from the provided value and details, iff the details aren't null. * Calling this method with null details has no effect. Please note that the total value of this partial score * remains unchanged, which is why this method is (and must remain) private. * * @param value of the reason to add. * @param details of the reason to add. */ private void addReason(float value, Map details) { if (details == null) { return; } add(new Reason(value, details)); } /** * Add a reason to this partial score. Please note that the total value of this partial score remains unchanged, * which is why this method is (and must remain) private. * * @param reason to add. */ private void add(Reason reason) { reasons.add(reason); } /** * Add reasons to this partial score. Please note that the total value of this partial score remains unchanged, * which is why this method is (and must remain) private. * * @param reasons to add. */ private void addReasons(Set reasons) { for (Reason reason : reasons) { add(reason); } } /** * Get the total value of this partial score. * * @return value. */ public float getValue() { return value.get(); } /** * Set a new total value of this partial score. Intended to be used by {@link com.graphaware.reco.generic.transform.ScoreTransformer}s. * Will not change anything about the already encapsulated {@link com.graphaware.reco.generic.result.Reason}s. * * @param value new total value. * @param details of the transformation. */ public void setNewValue(float value, Map details) { add(-(this.value.get() - value), details); } /** * Get the reasons encapsulated by this partial score. * * @return reasons, may be empty but will never be null. */ public Set getReasons() { return reasons; } /** * {@inheritDoc} */ @Override public String toString() { if (reasons.isEmpty()) { return String.valueOf(value); } StringBuilder result = new StringBuilder("{value:").append(value); for (Reason reason : reasons) { result.append(", ").append(reason); } result.append("}"); return result.toString(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy