source: src/main/java/agents/ai2014/group9/Group9.java@ 127

Last change on this file since 127 was 1, checked in by Wouter Pasman, 6 years ago

Initial import : Genius 9.0.0

File size: 12.3 KB
Line 
1package agents.ai2014.group9;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6
7import genius.core.AgentID;
8import genius.core.Bid;
9import genius.core.actions.Accept;
10import genius.core.actions.Action;
11import genius.core.actions.Offer;
12import genius.core.bidding.BidDetails;
13import genius.core.boaframework.SortedOutcomeSpace;
14import genius.core.issue.Issue;
15import genius.core.issue.IssueDiscrete;
16import genius.core.issue.IssueInteger;
17import genius.core.issue.IssueReal;
18import genius.core.issue.ValueDiscrete;
19import genius.core.issue.ValueInteger;
20import genius.core.issue.ValueReal;
21import genius.core.misc.Range;
22import genius.core.parties.AbstractNegotiationParty;
23import genius.core.parties.NegotiationInfo;
24
25public class Group9 extends AbstractNegotiationParty {
26 private SortedOutcomeSpace outcomeSpace;
27 private Bid lastBid = null;
28 private double lastBidUtility = 0;
29 private Bid myLastBid = null;
30 private double myLastUtility = 1;
31
32 private HashMap<Object, ArrayList<Bid>> partyBids;
33 private HashMap<Object, float[]> partyIssueWeights;
34 private HashMap<Object, HashMap<Integer, int[]>> partyIssueCounter;
35
36 @Override
37 public void init(NegotiationInfo info) {
38 super.init(info);
39 partyBids = new HashMap<Object, ArrayList<Bid>>();
40 partyIssueWeights = new HashMap<Object, float[]>();
41 partyIssueCounter = new HashMap<Object, HashMap<Integer, int[]>>();
42 outcomeSpace = new SortedOutcomeSpace(utilitySpace);
43 }
44
45 /**
46 * Each round this method gets called and ask you to accept or offer. The
47 * first party in the first round is a bit different, it can only propose an
48 * offer.
49 *
50 * @param validActions
51 * Either a list containing both accept and offer or only offer.
52 * @return The chosen action.
53 */
54 @Override
55 // Bidding and acceptance strategy
56 public Action chooseAction(List<Class<? extends Action>> validActions) {
57 // If a negotiating party makes an offer with >0.9 utility, we accept
58 // it.
59 if (lastBidUtility > 0.9) {
60 return new Accept(getPartyId(), lastBid);
61 }
62
63 Bid newBid = null;
64 double newBidUtility = 0;
65 // if I have never offered a bid before, bid my max utility bid
66 try {
67 if (!validActions.contains(Accept.class) || myLastBid == null) {
68 newBid = utilitySpace.getMaxUtilityBid();
69 newBidUtility = utilitySpace.getUtility(newBid);
70 myLastBid = newBid;
71 myLastUtility = newBidUtility;
72 return new Offer(getPartyId(), newBid);
73 }
74 } catch (Exception e) {
75 }
76
77 // I am a conceder, so calculate a utility threshold
78 double concederThreshold = 1;
79 if (timeline.getTime() > 0.75) {
80 double progress = (timeline.getTime() - 0.75) / (1.0 - 0.75);
81 concederThreshold = Math.sqrt(Math.sqrt(1.0 - progress)); // fourth
82 // root
83 }
84
85 // concede until I think I've conceded more than necessary for an equal
86 // gain outcome.
87 myLastUtility = getBidUtility(myLastBid);
88 boolean KS = true; // Kalai-Smorodinsky point
89 for (Object key : partyBids.keySet()) {
90 double approximate = approximateUtility(key, myLastBid);
91 double diff = Math.abs(myLastUtility - approximate);
92 if (diff > 0.2) {
93 KS = false;
94 }
95 }
96 // if the bid I made earlier qualifies as an estimated Kalai-Smorodinsky
97 // point, I'll offer that bid again.
98 if (KS && myLastUtility <= concederThreshold) {
99 return new Offer(getPartyId(), myLastBid);
100 }
101
102 // explore the bids with a personal utility slightly lower than my
103 // previous bid
104 List<BidDetails> myPossibleBids = outcomeSpace.getBidsinRange(new Range(myLastUtility, myLastUtility));
105 double i = 0.02;
106 if (myLastUtility <= concederThreshold) { // if the threshold is not yet
107 // relevant
108 while ((myPossibleBids.size() < 3) && (i < 1)) {
109 double lw = myLastUtility - i;
110 double up = myLastUtility;
111 myPossibleBids = outcomeSpace.getBidsinRange(new Range(lw, up));
112 i += 0.02;
113 }
114 } else {
115 while ((myPossibleBids.size() < 3) && (i < 1)) {
116 double lw = concederThreshold - i;
117 double up = concederThreshold;
118 myPossibleBids = outcomeSpace.getBidsinRange(new Range(lw, up));
119 i += 0.02;
120 }
121 }
122
123 // Check for each selected bid which one has the highest mutual utility
124 int bestBidIndex = 0;
125 double maxCommonUtility = 0;
126 for (int j = 1; j < myPossibleBids.size(); j++) {
127 Bid currentBid = myPossibleBids.get(j).getBid();
128 double commonUtility = 1;
129 try {
130 commonUtility = utilitySpace.getUtility(currentBid);
131 if (commonUtility == myLastUtility)
132 continue;
133 } catch (Exception e) {
134 }
135
136 for (Object key : partyBids.keySet()) {
137 commonUtility *= approximateUtility(key, currentBid);
138 }
139
140 if (commonUtility > maxCommonUtility) {
141 maxCommonUtility = commonUtility;
142 bestBidIndex = j;
143 }
144 }
145 newBid = myPossibleBids.get(bestBidIndex).getBid();
146 newBidUtility = getBidUtility(newBid);
147 // Bid the selected bid, unless its utility is lower than what we were
148 // offered.
149 if (newBidUtility < lastBidUtility) {
150 return new Accept(getPartyId(), lastBid);
151 } else {
152 myLastBid = newBid;
153 lastBid = myLastBid;
154 try {
155 lastBidUtility = utilitySpace.getUtility(lastBid);
156 } catch (Exception e) {
157 }
158 return new Offer(getPartyId(), newBid);
159 }
160 }
161
162 /**
163 * All offers proposed by the other parties will be received as a message.
164 * You can use this information to your advantage, for example to predict
165 * their utility.
166 *
167 * @param sender
168 * The party that did the action.
169 * @param action
170 * The action that party did.
171 */
172 @Override
173 public void receiveMessage(AgentID sender, Action action) {
174 // Here you can listen to other parties' messages
175 if (!partyBids.containsKey(sender) && sender != null) {
176 partyBids.put(sender, new ArrayList<Bid>());
177 }
178
179 // if another player sends an offer
180 if ((action instanceof Offer)) {
181 lastBid = ((Offer) action).getBid();
182 partyBids.get(sender).add(lastBid);
183 try {
184 lastBidUtility = utilitySpace.getUtility(lastBid);
185 } catch (Exception e) {
186 }
187 } else if (action instanceof Accept) {
188 // if another player accepts a bid, they like this bid.
189 if (lastBid != null)
190 partyBids.get(sender).add(lastBid);
191 }
192
193 CalculateOpponentUtilityParameters(sender);
194 }
195
196 // simple try catch prevention
197 private double getBidUtility(Bid b) {
198 if (b == null)
199 return 0;
200
201 try {
202 return utilitySpace.getUtility(b);
203 } catch (Exception e) {
204 }
205 return 0;
206 }
207
208 // calculate the parameters that we use to predict the opponents utilities
209 private void CalculateOpponentUtilityParameters(Object sender) {
210 float n = 0.1f;
211
212 if (!partyBids.containsKey(sender))
213 return;
214
215 ArrayList<Bid> bidList = partyBids.get(sender);
216 if (bidList.size() == 1) { // the first time
217 Bid first = bidList.get(0);
218
219 // initialize the arrays
220 List<Issue> issues = first.getIssues();
221 int issueSize = issues.size();
222 partyIssueWeights.put(sender, new float[issueSize]);
223 partyIssueCounter.put(sender, new HashMap<Integer, int[]>());
224
225 // go over each issue
226 for (int i = 0; i < issueSize; i++) {
227 Issue iss = first.getIssues().get(i);
228 int isn = iss.getNumber();
229 partyIssueWeights.get(sender)[i] = 1f / issueSize;
230
231 int numValues = 1;
232 int issueInd = 0;
233 try {
234 // get the correct issue type
235 if (iss instanceof IssueDiscrete) {
236 numValues = ((IssueDiscrete) iss).getValues().size();
237 ValueDiscrete val = (ValueDiscrete) first.getValue(isn);
238 issueInd = ((IssueDiscrete) iss).getValueIndex(val);
239 } else if (iss instanceof IssueInteger) {
240 numValues = ((IssueInteger) iss).getUpperBound() - ((IssueInteger) iss).getLowerBound() + 1;
241 ValueInteger val = (ValueInteger) first.getValue(isn);
242 issueInd = val.getValue() - ((IssueInteger) iss).getLowerBound();
243 } else if (iss instanceof IssueReal) {
244 // put them in 5 bins
245 numValues = 5;
246 ValueReal val = (ValueReal) first.getValue(isn);
247 double normalized = (((IssueReal) iss).getUpperBound() - val.getValue())
248 / (((IssueReal) iss).getUpperBound() - ((IssueReal) iss).getLowerBound());
249 issueInd = (int) Math.floor(normalized * 5);
250 if (issueInd >= 5)
251 issueInd = 4;
252 }
253 } catch (Exception e) {
254 }
255
256 partyIssueCounter.get(sender).put(isn, new int[numValues]);
257 partyIssueCounter.get(sender).get(isn)[issueInd] = 10;
258 // set counter to 10, we assume they start with their most
259 // important
260 }
261 } else if (bidList.size() >= 2) { // not the first time
262 int issueSize = bidList.get(0).getIssues().size();
263 int lastBidIndex = bidList.size() - 1;
264 float totalWeight = 0;
265
266 // go over each issue
267 for (int i = 0; i < issueSize; i++) {
268 Issue iss = bidList.get(lastBidIndex).getIssues().get(i);
269 int isn = iss.getNumber();
270
271 // add a small weight if the value changed
272 if (bidList.get(lastBidIndex).getIssues().get(i) != bidList.get(lastBidIndex - 1).getIssues().get(i)) {
273 partyIssueWeights.get(sender)[i] += n;
274 totalWeight += partyIssueWeights.get(sender)[i];
275 }
276
277 int issueInd = 0;
278 try {
279 // find which of the values this is
280 if (iss instanceof IssueDiscrete) {
281 issueInd = ((IssueDiscrete) iss)
282 .getValueIndex((ValueDiscrete) bidList.get(lastBidIndex).getValue(isn));
283 } else if (iss instanceof IssueInteger) {
284 issueInd = ((ValueInteger) bidList.get(lastBidIndex).getValue(isn)).getValue()
285 - ((IssueInteger) iss).getLowerBound();
286 } else if (iss instanceof IssueReal) {
287 double value = ((ValueReal) bidList.get(lastBidIndex).getValue(isn)).getValue();
288 double normalized = (((IssueReal) iss).getUpperBound() - value)
289 / (((IssueReal) iss).getUpperBound() - ((IssueReal) iss).getLowerBound());
290 issueInd = (int) Math.floor(normalized * 5);
291 if (issueInd >= 5)
292 issueInd = 4;
293 }
294 } catch (Exception e) {
295 }
296 // add 1 to the issue chosen
297 partyIssueCounter.get(sender).get(isn)[issueInd]++;
298 }
299 if (totalWeight == 0)
300 return;
301
302 // normalize
303 for (int i = 0; i < issueSize; i++) {
304 partyIssueWeights.get(sender)[i] /= totalWeight;
305 }
306 }
307 }
308
309 // given a bid, predict the utility for the opponent
310 private double approximateUtility(Object party, Bid bid) {
311 if (partyIssueCounter == null || party == null || bid == null)
312 return 0.5;
313
314 double totalUtility = 0;
315 // go over each issue
316 for (int i = 0; i < bid.getIssues().size(); i++) {
317 Issue iss = bid.getIssues().get(i);
318 if (iss == null)
319 continue;
320
321 int isn = iss.getNumber();
322
323 int issueInd = 0;
324 try {
325 // get the correct issue type
326 if (iss instanceof IssueDiscrete) {
327 issueInd = ((IssueDiscrete) iss).getValueIndex((ValueDiscrete) bid.getValue(isn));
328 } else if (iss instanceof IssueInteger) {
329 issueInd = ((ValueInteger) bid.getValue(isn)).getValue() - ((IssueInteger) iss).getLowerBound();
330 } else if (iss instanceof IssueReal) {
331 double value = ((ValueReal) bid.getValue(isn)).getValue();
332 double divider = ((IssueReal) iss).getUpperBound() - ((IssueReal) iss).getLowerBound();
333 if (divider == 0)
334 continue;
335 double normalized = (((IssueReal) iss).getUpperBound() - value) / divider;
336 issueInd = (int) Math.floor(normalized * 5);
337 if (issueInd >= 5)
338 issueInd = 4;
339 }
340 } catch (Exception e) {
341 }
342
343 if (!partyIssueCounter.containsKey(party))
344 continue;
345 if (!partyIssueCounter.get(party).containsKey(isn))
346 continue;
347 if (partyIssueCounter.get(party).get(isn) == null)
348 continue;
349
350 // get the max value
351 int maxCount = 1;
352 int numOptions = 0;
353 for (int j = 0; j < partyIssueCounter.get(party).get(isn).length; j++) {
354 maxCount = Math.max(maxCount, partyIssueCounter.get(party).get(isn)[j]);
355 if (partyIssueCounter.get(party).get(isn)[j] != 0)
356 numOptions++;
357 }
358
359 // get the weight and the value for this issue
360 double value = partyIssueCounter.get(party).get(isn)[issueInd] / (double) maxCount;
361
362 if (numOptions == 1 && value == 0.0) // for hardball players who
363 // only select 1 option
364 value = 0.5; // we dont know how you feel about this subject, so
365 // we assume 0.5
366 else if (value == 0.0)
367 value = 0.1; // you probably dont hate it, even though you
368 // didn't choose it
369
370 float weight = partyIssueWeights.get(party)[i];
371 totalUtility += value * weight;
372 }
373
374 if (totalUtility == 0) // something went wrong
375 return 0.5;
376 else
377 return totalUtility;
378 }
379
380 protected AgentID partyId = new AgentID("Group 9");
381
382 @Override
383 public String getDescription() {
384 return "ai2014 group9";
385 }
386
387}
Note: See TracBrowser for help on using the repository browser.