source: src/main/java/genius/core/Bid.java@ 256

Last change on this file since 256 was 187, checked in by Tim Baarslag, 6 years ago

CustomUtilitySpacePartyExample now works for all settings

File size: 8.4 KB
Line 
1package genius.core;
2
3import java.util.List;
4
5import java.util.ArrayList;
6import java.util.Collection;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.Map;
10import java.util.Map.Entry;
11import java.util.Set;
12
13import java.io.Serializable;
14
15import javax.xml.bind.annotation.XmlAttribute;
16import javax.xml.bind.annotation.XmlElement;
17import javax.xml.bind.annotation.XmlElementRef;
18import javax.xml.bind.annotation.XmlRootElement;
19import javax.xml.bind.annotation.adapters.XmlAdapter;
20import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
21
22import genius.core.analysis.pareto.IssueValue;
23import genius.core.issue.Issue;
24import genius.core.issue.Value;
25
26/**
27 * A bid is a set of tuples [idnumber,value], where idnumber is the unique
28 * number of the issue, and value is the picked alternative.
29 * <p>
30 * Bid is a immutable. But you can create modified copies using
31 * {@link #putValue(int, Value)}.
32 *
33 * Bid should be considered final so do not extend this.
34 *
35 * @author Dmytro Tykhonov, Koen Hindriks
36 */
37@XmlRootElement
38public class Bid implements Serializable {
39
40 /**
41 *
42 */
43 private static final long serialVersionUID = -7723017380013100614L;
44
45 private final Domain fDomain;
46
47 /**
48 * the bid values for each IssueID
49 */
50 @XmlElement(name = "values")
51 @XmlJavaTypeAdapter(MyMapAdapter.class)
52 private HashMap<Integer, Value> fValues;
53
54 /**
55 * Only for (de)serialization
56 */
57 private Bid() {
58 fDomain = null; // keep Java happy. Serializer shall overwrite anyway
59 }
60
61 /**
62 * Create a new empty bid of which the values still must be set.
63 *
64 * @param domain
65 * the domain for this bid
66 */
67 public Bid(Domain domain) {
68 fDomain = domain;
69 fValues = new HashMap<Integer, Value>();
70 }
71
72 /**
73 * createFrom a new bid in a domain. There is only this constructor because we require that ALL
74 * values in the domain get assigned a value.
75 *
76 * @param domainP
77 * the domain in which the bid is done
78 * @param bidP
79 * HashMap, which is a set of pairs [issueID,value]
80 */
81 public Bid(Domain domainP, HashMap<Integer, Value> bidP) {
82 this.fDomain = domainP;
83 fValues = bidP;
84 }
85
86 /**
87 * create bid from set of {@link IssueValue}s
88 *
89 * @param domain
90 * the {@link Domain}
91 * @param values
92 * a {@link Collection} of {@link IssueValue}s
93 */
94 public Bid(Domain domain, Collection<IssueValue> values) {
95 if (domain == null)
96 throw new NullPointerException("null domain");
97 if (values == null)
98 throw new NullPointerException("null values");
99
100 this.fDomain = domain;
101 fValues = new HashMap<>();
102 for (IssueValue iv : values) {
103 fValues.put(iv.getIssue().getNumber(), iv.getValue());
104 }
105 }
106
107 /**
108 * This method clones the given bid.
109 *
110 * @param bid
111 * the bid to clone
112 */
113 public Bid(Bid bid) {
114
115 fDomain = bid.fDomain;
116 fValues = (HashMap<Integer, Value>) bid.fValues.clone();
117 }
118
119 /**
120 * @param issueNr
121 * number of an issue.
122 * @return the picked value for given issue idnumber
123 * @throws IllegalArgumentException
124 * if there exist no issue with the given number.
125 */
126 public Value getValue(int issueNr) {
127 Value v = fValues.get(issueNr);
128 if (v == null) {
129 if (fDomain.getIssues().get(issueNr) == null)
130 throw new IllegalArgumentException("Bid.getValue: issue " + issueNr + " does not exist at all");
131 throw new IllegalStateException("There is no evaluator for issue " + issueNr);
132 }
133 return v;
134 }
135
136 /**
137 * @param issue the issue
138 * @return the picked value for given issue
139 * @throws IllegalArgumentException
140 * if there exist no issue with the given number.
141 */
142 public Value getValue(Issue issue)
143 {
144 return getValue(issue.getNumber());
145 }
146
147 /**
148 * @param issue the issue corresponding to the value.
149 * This is needed because the same values can occur multiple times in a bid
150 * @param value
151 * @return Whether this bid has a value selected for an issue
152 */
153 public boolean containsValue(Issue issue, Value value)
154 {
155 return getValue(issue).equals(value);
156 }
157
158 /**
159 * @param issueId
160 * unique ID of an issue.
161 * @param pValue
162 * value of the issue.
163 * @return new Bid as the current bid but with the value of the issue with
164 * the given issueID to the given value
165 * @throws IllegalArgumentException
166 * if there exist no issue with the given number.
167 */
168 public Bid putValue(int issueId, Value pValue) {
169 if (fValues.get(issueId).getType() != pValue.getType()) {
170 // FIXME
171 // if (fDomain.getIssue(issueId).getType() != pValue.getType()) {
172 throw new IllegalArgumentException("expected value of type " + fDomain.getIssues().get(issueId).getType()
173 + " but got " + pValue + " of type " + pValue.getType());
174 }
175 HashMap<Integer, Value> newValues = new HashMap<Integer, Value>(fValues);
176 newValues.put(issueId, pValue);
177 return new Bid(fDomain, newValues);
178 }
179
180 public String toString() {
181 String s = "Bid[";
182 Set<Entry<Integer, Value>> value_set = fValues.entrySet();
183 Iterator<Entry<Integer, Value>> value_it = value_set.iterator();
184 int i = 0;
185 while (value_it.hasNext()) {
186 int ind = ((Entry<Integer, Value>) value_it.next()).getKey();
187 Object tmpobj = fDomain.getObjectivesRoot().getObjective(ind);
188 if (tmpobj != null) {
189 String issueName = fDomain.getObjectivesRoot().getObjective(ind).getName();
190 s += (i++ > 0 ? ", " : "") + issueName + ": " + fValues.get(ind);
191 } else {
192 System.out.println("objective with index " + ind + " does not exist");
193 }
194 }
195 s = s + "]";
196 return s;
197 }
198
199 /**
200 * @return A CSV version of the bid, useful for logging.
201 */
202 public String toStringCSV()
203 {
204 String s = "";
205 Set<Entry<Integer, Value>> value_set = fValues.entrySet();
206 Iterator<Entry<Integer, Value>> value_it = value_set.iterator();
207 int i = 0;
208 while (value_it.hasNext())
209 {
210 int ind = ((Entry<Integer, Value>) value_it.next()).getKey();
211 s += (i++ > 0 ? ";" : "") + fValues.get(ind);
212 }
213 return s;
214 }
215
216 /**
217 * @param pBid
218 * to which this bid must be compared.
219 * @return true if the values of this and the given bid are equal.
220 */
221 public boolean equals(Bid pBid) {
222 if (pBid == null)
223 return false;
224 return fValues.equals(pBid.fValues);
225 }
226
227 /*
228 * (non-Javadoc)
229 *
230 * @see java.lang.Object#equals(java.lang.Object)
231 */
232 @Override
233 public boolean equals(Object obj) {
234 if (obj instanceof Bid)
235 return equals((Bid) obj);
236 return false;
237 }
238
239 /**
240 * @return a (copy of ) the list of all values in this bid. FIXME we really
241 * should return an immutable {@link Map} here but that may break
242 * many agents.
243 */
244
245 public HashMap<Integer, Value> getValues() {
246 return new HashMap<Integer, Value>(fValues);
247 }
248
249 // Reyhan: add this method
250 public List<Issue> getIssues() {
251 return fDomain.getIssues();
252 }
253
254 public Domain getDomain() {
255 return fDomain;
256 }
257
258 /**
259 * Counts the number of equal values with another bid (assuming they are defined on the same domain)
260 */
261 public int countEqualValues(Bid b)
262 {
263 int count = 0;
264 for (Integer v : fValues.keySet())
265 {
266 if (this.fValues.get(v).equals(b.fValues.get(v)))
267 count++;
268 }
269 return count;
270 }
271
272 @Override
273 public int hashCode() {
274 int code = 0;
275 for (Entry<Integer, Value> lEntry : fValues.entrySet()) {
276 code = code + lEntry.getValue().hashCode();
277 }
278 return code;// fValues.hashCode();
279 }
280
281}
282
283class MyMapAdapter extends XmlAdapter<Temp, Map<Integer, Value>> {
284
285 @Override
286 public Temp marshal(Map<Integer, Value> arg0) throws Exception {
287 Temp temp = new Temp();
288 for (Entry<Integer, Value> entry : arg0.entrySet()) {
289 temp.entry.add(new Item(entry.getKey(), entry.getValue()));
290 }
291 return temp;
292 }
293
294 @Override
295 public Map<Integer, Value> unmarshal(Temp arg0) throws Exception {
296 Map<Integer, Value> map = new HashMap<Integer, Value>();
297 for (Item item : arg0.entry) {
298 map.put(item.key, item.value);
299 }
300 return map;
301 }
302
303}
304
305class Temp {
306 @XmlElement(name = "issue")
307 public List<Item> entry;
308
309 public Temp() {
310 entry = new ArrayList<Item>();
311 }
312
313}
314
315@XmlRootElement
316class Item {
317 @XmlAttribute(name = "index")
318 public Integer key;
319
320 @XmlElementRef
321 public Value value;
322
323 public Item() {
324 }
325
326 public Item(Integer key, Value val) {
327 this.key = key;
328 this.value = val;
329 }
330}
Note: See TracBrowser for help on using the repository browser.