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

Last change on this file was 52, checked in by ruud, 14 months ago

Fixed small issues in domaineditor.

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