source: profile/src/main/java/geniusweb/profile/utilityspace/PartsUtilities.java@ 24

Last change on this file since 24 was 24, checked in by bart, 4 years ago

Fixes an issue with processing maxPower of a vote. Javadoc maven plugin now uses latest version.

File size: 7.2 KB
Line 
1package geniusweb.profile.utilityspace;
2
3import java.math.BigDecimal;
4import java.util.Collections;
5import java.util.HashMap;
6import java.util.LinkedList;
7import java.util.List;
8import java.util.Map;
9
10import com.fasterxml.jackson.annotation.JsonAutoDetect;
11import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
12import com.fasterxml.jackson.annotation.JsonCreator;
13import com.fasterxml.jackson.annotation.JsonProperty;
14import com.fasterxml.jackson.annotation.JsonTypeName;
15
16import geniusweb.issuevalue.Value;
17import geniusweb.issuevalue.ValueSet;
18
19/**
20 * Contains utilities of a ProductOfValue of a {@link SumOfGroupsUtilitySpace}.
21 * So this is similar to a {@link DiscreteValueSetUtilities} but instead of
22 * issues this contains an (ordered) list of issues. This object serializes to
23 * something like <code>
24 * {"partsutils":
25 * {"issues":["issue1","issue2"],
26 * "utilslist":[{"values":["low","low"],"util":0.3},{"values":["high","high"],"util":0.9}]}}
27 </code> The issues field contains a list of N issues in the domain, The
28 * utilslist contains a list of dictionaries, with "values" containing a list of
29 * N issue values, in the same order as the issues list and with "util"
30 * containng the utility value of that set of values.
31 */
32@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
33@JsonTypeName("partsutils")
34public class PartsUtilities implements ValueSetUtilities {
35 private final List<String> issues;
36 // the real but not-serializable values (because Map can only have String
37 // keys in jackson)
38 private transient final Map<ProductOfValue, BigDecimal> utilities = new HashMap<>();
39 // copy only for serializing
40 private final List<PartUtil> utilslist = new LinkedList<>();
41
42 /**
43 *
44 * @param issues list of issues
45 * @param utils with keys: list of values and value: utility value for that
46 * list of values. All list-of-values missing from the map are
47 * assumed to have utility 0. This includes partial bids where
48 * list-of-values contain null objects.
49 */
50 public PartsUtilities(List<String> issues,
51 Map<ProductOfValue, BigDecimal> utils) {
52 if (issues == null || utils == null) {
53 throw new IllegalArgumentException(
54 "issues and utils must be not null");
55 }
56
57 this.issues = issues;
58 this.utilities.putAll(utils);
59
60 checkUtilities();
61 for (ProductOfValue pval : utils.keySet()) {
62 utilslist.add(new PartUtil(pval.getValues(), utils.get(pval)));
63 }
64 }
65
66 @JsonCreator
67 public PartsUtilities(@JsonProperty("issues") List<String> issues,
68 @JsonProperty("utilslist") List<PartUtil> utilslist) {
69 this(issues, list2map(utilslist));
70 }
71
72 /**
73 *
74 * @param pval the {@link ProductOfValue} value
75 * @return the utility of the value, in the same order as
76 * {@link #getIssues()}. Returns 0 if there is no utility set for
77 * the given combination of values. Notice, partial bids will
78 * usually have utility 0.
79 *
80 */
81 @Override
82 public BigDecimal getUtility(Value pval) {
83 BigDecimal val = utilities.get(pval);
84 if (val == null)
85 return BigDecimal.ZERO;
86 return val;
87 }
88
89 @Override
90 public String isFitting(ValueSet valueset) {
91 return null; // what can we tests here?
92 }
93
94 /**
95 * @return the issues that are contained here.
96 */
97 public List<String> getIssues() {
98 return issues;
99 }
100
101 /**
102 *
103 * @return map with all available values and their utilities. The map and
104 * its contents should all be immutable.
105 */
106 public Map<ProductOfValue, BigDecimal> getUtilities() {
107 return Collections.unmodifiableMap(utilities);
108 }
109
110 /**
111 *
112 * @param other another {@link PartsUtilities} map. The issues in the other
113 * map must be different from {@link #issues}.
114 * @return new PartsUtils, with the powermap of all combinations of one
115 * element from this and one from the other map, and with the
116 * utilities computed as the sum of thisvalue + othervalue.
117 */
118 public PartsUtilities add(PartsUtilities other) {
119 for (String issue : issues) {
120 if (other.issues.contains(issue)) {
121 throw new IllegalArgumentException(
122 "Issue " + issue + " exists already");
123 }
124 }
125
126 List<String> combinedissues = new LinkedList<String>(issues);
127 combinedissues.addAll(other.issues);
128
129 Map<ProductOfValue, BigDecimal> combinedvalues = new HashMap<>();
130 for (ProductOfValue productOfValue : this.utilities.keySet()) {
131 for (ProductOfValue otherProductOfValue : other.utilities
132 .keySet()) {
133 BigDecimal combinedutil = getUtility(productOfValue)
134 .add(other.getUtility(otherProductOfValue));
135 combinedvalues.put(productOfValue.merge(otherProductOfValue),
136 combinedutil);
137 }
138 }
139 return new PartsUtilities(combinedissues, combinedvalues);
140
141 }
142
143 @Override
144 public int hashCode() {
145 final int prime = 31;
146 int result = 1;
147 result = prime * result + ((issues == null) ? 0 : issues.hashCode());
148 result = prime * result
149 + ((utilities == null) ? 0 : utilities.hashCode());
150 return result;
151 }
152
153 @Override
154 public boolean equals(Object obj) {
155 if (this == obj)
156 return true;
157 if (obj == null)
158 return false;
159 if (getClass() != obj.getClass())
160 return false;
161 PartsUtilities other = (PartsUtilities) obj;
162 if (issues == null) {
163 if (other.issues != null)
164 return false;
165 } else if (!issues.equals(other.issues))
166 return false;
167 if (utilities == null) {
168 if (other.utilities != null)
169 return false;
170 } else if (!utilities.equals(other.utilities))
171 return false;
172 return true;
173 }
174
175 @Override
176 public String toString() {
177 return "PartsUtilities[" + issues + "," + utilities + "]";
178 }
179
180 private void checkUtilities() {
181 if (utilities.values().stream()
182 .anyMatch(v -> v == null || v.compareTo(BigDecimal.ZERO) < 0
183 || v.compareTo(BigDecimal.ONE) > 0)) {
184 throw new IllegalArgumentException(
185 "part weights must all be in [0,1]");
186 }
187 }
188
189 private static Map<ProductOfValue, BigDecimal> list2map(
190 List<PartUtil> list) {
191 Map<ProductOfValue, BigDecimal> map = new HashMap<>();
192 for (PartUtil partutil : list) {
193 map.put(new ProductOfValue(partutil.getValues()),
194 partutil.getUtil());
195 }
196 return map;
197 }
198
199 /**
200 *
201 * @return the max utility of all values contained here.
202 */
203 public BigDecimal getMaxUtility() {
204 BigDecimal maxutil = BigDecimal.ZERO;
205 for (ProductOfValue vakye : utilities.keySet()) {
206 if (utilities.get(vakye).compareTo(maxutil) > 0) {
207 maxutil = utilities.get(vakye);
208 }
209
210 }
211 return maxutil;
212 }
213
214}
215
216/**
217 * contains list of values, and the utility for this combi of values. The values
218 * make only sense with a corresponding list of issues, but that is managed in
219 * (see {@link PartsUtilities}.
220 * <p>
221 * immutable.
222 */
223@JsonAutoDetect(fieldVisibility = Visibility.ANY, getterVisibility = Visibility.NONE, setterVisibility = Visibility.NONE, isGetterVisibility = Visibility.NONE)
224class PartUtil {
225 private final List<Value> values;
226
227 private final BigDecimal util;
228
229 @JsonCreator
230 public PartUtil(@JsonProperty("values") List<Value> values,
231 @JsonProperty("util") BigDecimal util) {
232 this.values = values;
233 this.util = util;
234 }
235
236 public List<Value> getValues() {
237 return values;
238 }
239
240 public BigDecimal getUtil() {
241 return util;
242 }
243}
Note: See TracBrowser for help on using the repository browser.