package geniusweb.bidspace; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import geniusweb.issuevalue.Value; import geniusweb.issuevalue.ValueSet; import geniusweb.profile.utilityspace.ValueSetUtilities; /** * Tool class to collect all relevant info about one issue (from LinearAdditive) * in one class. Used for internally grouping data for more efficient * processing. This class may change in the future, not recommended for direct * use. *

* immutable */ public class IssueInfo { private final String name; private final ValueSet values; private final Interval interval; private final Map weightedUtils; /** * * @param name the issue name * @param values the {@link ValueSet} of the issue * @param utils the {@link ValueSetUtilities} of the issue profile * @param weight the weight of the {@link ValueSetUtilities} * @param precision the precision to compute with. Basically the number of * decimal places used for the computations. * */ public IssueInfo(String name, ValueSet values, ValueSetUtilities utils, BigDecimal weight, int precision) { this.name = name; this.values = values; this.weightedUtils = computeWeightedUtils(utils, weight, precision); this.interval = getRange(); } public ValueSet getValues() { return values; } public String getName() { return name; } /** * * @return weighted minimum and maximum utility achievable with this issue, * rounded to the requested precision. */ public Interval getInterval() { return interval; } /** * * @param isMax if true the max {@link Value} is returned, else the min is * returned. * @return the extreme value, either the minimum if isMax=false or maximum * if isMax=true */ public Value getExtreme(boolean isMax) { BigDecimal extremeutil = null; Value extremeval = null; for (Value val : values) { BigDecimal util = weightedUtils.get(val); if (extremeval == null) { extremeutil = weightedUtils.get(val); extremeval = val; } else { if (isMax) { if (util.compareTo(extremeutil) > 0) { extremeutil = util; extremeval = val; } } else { if (util.compareTo(extremeutil) < 0) { extremeutil = util; extremeval = val; } } } } return extremeval; } /** * @param val the issue value to be evaluated * @return weighted utility of given value, rounded to nearest value with * the requested precision number of digits. */ public BigDecimal getWeightedUtil(Value val) { return weightedUtils.get(val); } /** * * @param interval an {@link Interval} of utility values. * @return all values that are inside the interval. */ protected List subset(Interval interval) { List selection = new ArrayList<>(); for (Value value : values) { if (interval.contains(getWeightedUtil(value))) selection.add(value); } return selection; } /** * Faster way to determine subset size, it does not create a list * * @param interval an {@link Interval} of utility values. * @return size of the subset that you will get from calling subset */ protected int subsetSize(Interval interval) { int n = 0; for (Value value : values) if (interval.contains(getWeightedUtil(value))) n = n + 1; return n; } /** * @return the {@link Interval} (minimum and maximum) of the utility of the * weighted utility of this issue, properly rounded to the * {@link #precision}/ * */ private Interval getRange() { BigDecimal min = BigDecimal.ONE; BigDecimal max = BigDecimal.ZERO; for (Value value : values) { BigDecimal util = getWeightedUtil(value); if (util.compareTo(min) < 0) min = util; if (util.compareTo(max) > 0) max = util; } return new Interval(min, max); } private Map computeWeightedUtils( ValueSetUtilities utilities, BigDecimal w, int prec) { Map map = new HashMap<>(); for (Value val : values) { map.put(val, utilities.getUtility(val).multiply(w).setScale(prec, RoundingMode.HALF_UP)); } return map; } }