source: src/main/java/agents/anac/y2014/AgentQuest/AgentQuest.java

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

Initial import : Genius 9.0.0

File size: 17.9 KB
Line 
1package agents.anac.y2014.AgentQuest;
2
3import java.math.BigDecimal;
4import java.util.HashMap;
5import java.util.Iterator;
6import java.util.List;
7
8import genius.core.Agent;
9import genius.core.Bid;
10import genius.core.BidHistory;
11import genius.core.Domain;
12import genius.core.actions.Accept;
13import genius.core.actions.Action;
14import genius.core.actions.Offer;
15import genius.core.bidding.BidDetails;
16import genius.core.utility.AbstractUtilitySpace;
17
18/**
19 *
20 * @author Edwin Yaqub - (GWDG, Goettingen, Germany)
21 * @contact edwinyaqub@yahoo.com
22 *
23 */
24public class AgentQuest extends Agent {
25
26 private Action partnerAction;
27 private AbstractUtilitySpace myUtilitySpace;
28 private Bid myLastBid;
29 private Bid bestBid;
30 private Bid opponentLastBid;
31 private int hardlineCounter = 0;
32 private final int opponentMonitoringWindowSize = 10;
33 private int opponentMonitoringWindowIndex = 0;
34 private double opponentUtilityInWindowSofar = 0;
35 private final int lastMonitoringWindowCarryOnHardHeadednessValue = 3;
36 int counter = 0;
37 private Domain domain;
38 private BidHistory myBidHistory = new BidHistory();
39 private BidHistory opponentBidHistory = new BidHistory();
40 private int MAX_BIDS_TO_SAMPLE = 400;
41 private int MAX_BIDS_TO_STORE = 1000;
42 private int alpha = 4; // Acceptable threshold for opponent harheadedness:
43 // adjust between 1 and opponentMonitoringWindowSize
44 // to negotiate hard (low value) or soft (high
45 // value).
46 private double beta = 0.6d; // Acceptable threshold for conceding
47 // probability: adjust between 0 and 1 to
48 // negotiate hard (high value) or soft (low
49 // value).
50 private double defaultReservationValue = 0.25d;
51 private double meanResponseTimeOfOpponent = 0.0d;
52 private double lastResponseTime = 0.0d;
53
54 @Override
55 public void init() {
56 System.out.println("\n" + getName() + " version(" + getVersion()
57 + ") initializing...");
58 this.myUtilitySpace = super.utilitySpace;
59 this.domain = this.myUtilitySpace.getDomain();
60 if (this.myUtilitySpace.getReservationValue() != null
61 && this.myUtilitySpace.getReservationValue() > 0.0d) {
62 this.defaultReservationValue = this.myUtilitySpace
63 .getReservationValue().doubleValue();
64 }
65 }
66
67 @Override
68 public void ReceiveMessage(Action opponentAction) {
69 this.partnerAction = opponentAction;
70 }
71
72 @Override
73 public Action chooseAction() {
74 Action action = null;
75 try {
76 if (this.partnerAction == null) {
77 // I am initiator - send Bid with (known) highest Utility
78 double time = this.timeline.getTime();
79 addSampleBids(time);
80 addSampleBids(time); // Increase bid samples at our side so we
81 // dont loose on a low utility due to
82 // less samples in first round.
83 this.myLastBid = this.myBidHistory.getBestBidDetails().getBid();
84 action = new Offer(getAgentID(), this.myLastBid);
85 this.counter++;
86 this.lastResponseTime = time;
87 }
88
89 if (this.partnerAction instanceof Offer) {
90 this.counter++;
91 this.opponentMonitoringWindowIndex++;
92 double time = this.timeline.getTime();
93
94 // not the first round. measure mean response time and update
95 // last round's time
96 if (this.counter > 1) {
97 this.meanResponseTimeOfOpponent += (time
98 - this.lastResponseTime);
99 this.meanResponseTimeOfOpponent /= 2;
100 this.lastResponseTime = time;// reset lastResponseTime
101 } else { // this is first round
102 this.lastResponseTime = time;
103 addSampleBids(time); // increase bid samples from our side
104 // so we dont loose on a low utility
105 // due to less samples in first
106 // round.
107 }
108
109 addSampleBids(time);
110
111 if (this.myLastBid == null) {
112 this.myLastBid = this.myBidHistory.getBestBidDetails()
113 .getBid();
114 }
115
116 // Received an Offer from Opponent - process it, generate
117 // CounterOffer and decide whether Offer is acceptable or to
118 // send CounterOffer
119 Offer partnerOffer = (Offer) this.partnerAction;
120 Bid partnerBid = partnerOffer.getBid();
121
122 addOpponentBidToHistory(partnerBid, time);
123
124 // Save the first partner Bid (happens just one time):
125 if (this.opponentLastBid == null) {
126 this.opponentLastBid = partnerBid;
127 opponentUtilityInWindowSofar = this.myUtilitySpace
128 .getUtilityWithDiscount(this.opponentLastBid, time);
129 }
130
131 if (this.bestBid == null) {
132 // First bid from opponent (happens just one time)
133 this.bestBid = partnerBid;
134 }
135
136 double offeredUtilFromPartner = this.myUtilitySpace
137 .getUtilityWithDiscount(partnerBid, time);
138
139 // Tolerance measure:
140 if (this.opponentMonitoringWindowIndex > 1
141 && this.opponentMonitoringWindowIndex <= this.opponentMonitoringWindowSize) { // this.lastTenCounter
142 // >
143 // 0
144 // &&
145 // Maintaining mean utility of opponent's offer with
146 // opponent utility in window sofar:
147 opponentUtilityInWindowSofar += offeredUtilFromPartner;
148 opponentUtilityInWindowSofar /= 2;
149 if (offeredUtilFromPartner <= opponentUtilityInWindowSofar) {
150 if (this.hardlineCounter > this.opponentMonitoringWindowSize) {
151 this.hardlineCounter = this.lastMonitoringWindowCarryOnHardHeadednessValue;
152 } else {
153 this.hardlineCounter++;
154 }
155 } else {
156 if (this.hardlineCounter <= 0) {
157 this.hardlineCounter = 0;
158 } else {
159 this.hardlineCounter--;
160 }
161 }
162 }
163
164 // Saving opponent's bid as lastBid:
165 this.opponentLastBid = partnerBid;
166
167 // Maintain best Bid:
168 if (this.myUtilitySpace.getUtilityWithDiscount(partnerBid,
169 time) > this.myUtilitySpace
170 .getUtilityWithDiscount(this.bestBid, time)) {
171 this.bestBid = partnerBid;
172 }
173
174 if (genearteCounterOffer(partnerOffer, time) == null) {
175 // To deal with the unlikely case if we cant produce a
176 // counter offer.
177 action = new Accept(getAgentID(), opponentLastBid);
178 } else {
179 if (acceptOpponentOffer(partnerOffer, time)) {
180 action = new Accept(getAgentID(), opponentLastBid);
181 } else {
182 action = new Offer(getAgentID(), this.myLastBid);
183 }
184 }
185 }
186
187 if (this.opponentMonitoringWindowIndex == this.opponentMonitoringWindowSize) {
188 // reset the opponentMonitoringWindowIndex and hardlineCounter:
189 this.opponentMonitoringWindowIndex = 0;
190 if (this.hardlineCounter > this.opponentMonitoringWindowSize) {
191 this.hardlineCounter = this.lastMonitoringWindowCarryOnHardHeadednessValue;
192 }
193 if (this.hardlineCounter < 0) {
194 this.hardlineCounter = 0;
195 }
196 }
197 } catch (Exception e) {
198 e.printStackTrace();
199 action = new Accept(getAgentID(), opponentLastBid);
200 }
201
202 return action;
203 }
204
205 private void addOpponentBidToHistory(Bid partnerBid, double time) {
206 if (this.opponentBidHistory.size() < this.MAX_BIDS_TO_STORE) {
207 try {
208 this.opponentBidHistory
209 .add(new BidDetails(partnerBid, this.myUtilitySpace
210 .getUtilityWithDiscount(partnerBid, time)));
211 } catch (Exception e) {
212 e.printStackTrace();
213 }
214 } else {
215 // Make room by removing the worst 1 bid
216 this.opponentBidHistory = new BidHistory(this.opponentBidHistory
217 .getNBestBids(this.MAX_BIDS_TO_STORE - 1));
218 try {
219 this.opponentBidHistory
220 .add(new BidDetails(partnerBid, this.myUtilitySpace
221 .getUtilityWithDiscount(partnerBid, time)));
222 } catch (Exception e) {
223 e.printStackTrace();
224 }
225 }
226 this.myBidHistory.sortToUtility();
227 }
228
229 private void addSampleBids(double time) {
230 if (this.myBidHistory.size() < this.MAX_BIDS_TO_STORE) {
231 addBids(time);
232 } else {
233 // Make room by removing the worst 100 bids
234 this.myBidHistory = new BidHistory(
235 this.myBidHistory.getNBestBids(900));
236 addBids(time);
237 }
238 }
239
240 private void addBids(double time) {
241 for (int i = 0; i < this.MAX_BIDS_TO_SAMPLE; i++) {
242 Bid randomBid = this.domain.getRandomBid(null);
243 try {
244 this.myBidHistory
245 .add(new BidDetails(randomBid, this.myUtilitySpace
246 .getUtilityWithDiscount(randomBid, time)));
247 } catch (Exception e) {
248 e.printStackTrace();
249 }
250 }
251 this.myBidHistory.sortToUtility();
252 }
253
254 private BidDetails getCounterOffer(double time) {
255 List<BidDetails> myTop10Bids = this.myBidHistory.getNBestBids(10);
256 List<BidDetails> opponentTop10Bids = this.opponentBidHistory
257 .getNBestBids(10);
258 double[][] comparisonMatrix = new double[10][10];
259
260 for (int row = 0; row < opponentTop10Bids.size(); row++) {
261 BidDetails opponentBidDetails = opponentTop10Bids.get(row);
262 for (int col = 0; col < myTop10Bids.size(); col++) {
263 BidDetails myBidDetails = myTop10Bids.get(col);
264 // Compute Euclidean Distance between opponentBidDetails and
265 // myBidDetails:
266 try {
267 comparisonMatrix[row][col] = computeEuclideanDistancePerBid(
268 opponentBidDetails, myBidDetails, time);
269 } catch (Exception e) {
270 e.printStackTrace();
271 }
272 }
273 }
274 // Now traverse the comparisonMatrix, pick top 10 (least distanced) bids
275 // per row (preserving some diversity) and add to a BidHistory HashMap.
276 HashMap<Integer, BidDetails> hashMap = new HashMap<Integer, BidDetails>();
277 for (int row = 0; row < 10; row++) {
278 double closestBid = 99999.999;// some unrealistic number to
279 // initialize.
280 for (int col = 0; col < 10; col++) {
281 if (col > 0) {
282 if ((comparisonMatrix[row][col] < comparisonMatrix[row][col
283 - 1])
284 && (comparisonMatrix[row][col] < closestBid)) {
285 closestBid = comparisonMatrix[row][col];
286 if (hashMap.containsKey(row)) {
287 hashMap.remove(row);
288 hashMap.put(row, myTop10Bids.get(col));
289 }
290 }
291 } else {
292 closestBid = comparisonMatrix[row][col];
293 hashMap.put(row, myTop10Bids.get(col));
294 }
295 }
296 }
297 // Now find the bid with max utility for us
298 double startUtiliy = 0.0;
299 BidDetails selectedCounterOffer = null;
300 Iterator iter = hashMap.keySet().iterator();
301 while (iter.hasNext()) {
302 Integer key = (Integer) iter.next();
303 BidDetails bidDetails = hashMap.get(key);
304 double bidUtility = bidDetails.getMyUndiscountedUtil();
305 if (bidUtility > startUtiliy) {
306 startUtiliy = bidUtility;
307 selectedCounterOffer = bidDetails;
308 }
309 }
310 return selectedCounterOffer;
311 }
312
313 private double computeEuclideanDistancePerBid(BidDetails opponentBidDetails,
314 BidDetails myBidDetails, double time) throws Exception {
315 Bid opponentBid = opponentBidDetails.getBid();
316 Bid myBid = myBidDetails.getBid();
317 double sum = 0.0;
318 double opponentBidUtility;
319 double myBidUtility;
320 opponentBidUtility = this.myUtilitySpace
321 .getUtilityWithDiscount(opponentBid, time);
322 myBidUtility = this.myUtilitySpace.getUtilityWithDiscount(myBid, time);
323 sum = Math.pow((opponentBidUtility - myBidUtility), 2.0);
324 return Math.sqrt(sum);
325 }
326
327 private double getMyReservationValue(double time) {
328 if (this.myUtilitySpace.getReservationValue() != null
329 && this.myUtilitySpace
330 .getReservationValueWithDiscount(time) > 0.0d) {
331 return this.myUtilitySpace.getReservationValueWithDiscount(time);
332 } else {
333 return this.defaultReservationValue;
334 }
335 }
336
337 private Offer genearteCounterOffer(Offer opponentOffer, double time) {
338 Offer counterOffer = null;
339 if (time > 0.0d) {
340 // //Sets our counterOffer in this.myLastBid. Resort to last Bid
341 // until the following mechanism finds a different/conceding offer:
342 if (this.myUtilitySpace.getUtilityWithDiscount(this.myLastBid,
343 time) > this.myUtilitySpace.getUtilityWithDiscount(
344 this.myBidHistory.getBestBidDetails().getBid(),
345 time)) {
346 counterOffer = new Offer(getAgentID(), this.myLastBid);
347 } else {
348 BidHistory tempBidHistory = this.myBidHistory
349 .filterBetweenUtility(
350 this.myUtilitySpace.getUtilityWithDiscount(
351 this.myLastBid, time),
352 this.myUtilitySpace.getUtilityWithDiscount(
353 this.myBidHistory.getBestBidDetails()
354 .getBid(),
355 time));
356 if (tempBidHistory != null && tempBidHistory.size() > 0) {
357 tempBidHistory.sortToUtility();
358
359 if (tempBidHistory.getMedianUtilityBid() != null) {
360 this.myLastBid = tempBidHistory.getMedianUtilityBid()
361 .getBid();
362 counterOffer = new Offer(getAgentID(), this.myLastBid);
363
364 if (!this.myUtilitySpace.isDiscounted()) {
365 // Starting second level selection only for
366 // non-discounted domains
367 BidHistory anotherTempBidHistory = tempBidHistory
368 .filterBetweenUtility(
369 this.myUtilitySpace
370 .getUtilityWithDiscount(
371 tempBidHistory
372 .getMedianUtilityBid()
373 .getBid(),
374 time),
375 this.myUtilitySpace
376 .getUtilityWithDiscount(
377 tempBidHistory
378 .getBestBidDetails()
379 .getBid(),
380 time));
381 if (anotherTempBidHistory != null
382 && anotherTempBidHistory.size() > 0) {
383 if (anotherTempBidHistory
384 .getMedianUtilityBid() != null) {
385 this.myLastBid = anotherTempBidHistory
386 .getMedianUtilityBid().getBid();
387 counterOffer = new Offer(getAgentID(),
388 this.myLastBid);
389 }
390 }
391 // Ended second level selection
392 }
393 }
394 } else {
395 counterOffer = new Offer(getAgentID(), this.myLastBid);// retain
396 // last
397 // offer.
398 }
399 }
400
401 try {
402 // finds a different/conceding offer:
403 BigDecimal concessionProbability;
404 concessionProbability = Pconcede(
405 this.myUtilitySpace.getUtilityWithDiscount(
406 opponentOffer.getBid(), time),
407 this.timeline.getTime());
408
409 if ((this.hardlineCounter < this.alpha)
410 && (concessionProbability
411 .compareTo(new BigDecimal(this.beta)) > 0)) {
412 BidDetails tempBidDetails = null;
413 tempBidDetails = getCounterOffer(time);
414 Bid tempBid = tempBidDetails.getBid();
415 double bidUtility = this.myUtilitySpace
416 .getUtilityWithDiscount(tempBid, time);
417 if (bidUtility > this.myUtilitySpace
418 .getUtilityWithDiscount(this.bestBid, time)
419 && bidUtility >= this.getMyReservationValue(time)) {
420 counterOffer = new Offer(getAgentID(), tempBid);
421 this.myLastBid = tempBid;
422 } else if (this.myUtilitySpace.getUtilityWithDiscount(
423 this.bestBid,
424 time) >= this.getMyReservationValue(time)) {
425 counterOffer = new Offer(getAgentID(), this.bestBid);
426 this.myLastBid = this.bestBid;
427 }
428 } else {
429 if (this.counter > 1) // Not the first round.
430 {
431 if (this.myUtilitySpace.getUtilityWithDiscount(
432 this.bestBid, time) < this.myUtilitySpace
433 .getUtilityWithDiscount(this.myLastBid,
434 time)) {
435 counterOffer = new Offer(getAgentID(),
436 this.myLastBid);
437 } else if (this.myUtilitySpace.getUtilityWithDiscount(
438 this.bestBid,
439 time) >= this.getMyReservationValue(time)) {
440 counterOffer = new Offer(getAgentID(),
441 this.bestBid);
442 this.myLastBid = this.bestBid;
443 }
444 } else {
445 counterOffer = new Offer(getAgentID(), this.myLastBid);// will
446 // execute
447 // just once
448 // i.e., for
449 // round 1.
450 }
451 }
452 } catch (Exception e) {
453 e.printStackTrace();
454 }
455 } else {
456 try {
457 counterOffer = new Offer(getAgentID(), this.bestBid);
458 } catch (Exception e) {
459 e.printStackTrace();
460 }
461 }
462 return counterOffer;
463 }
464
465 private boolean acceptOpponentOffer(Offer opponentOffer, double time) {
466 boolean result = false;
467 double opponentOfferUtility;
468 double myOfferUtility;
469 double bestBidUtility;
470 if (opponentOffer != null) {
471 try {
472 opponentOfferUtility = this.myUtilitySpace
473 .getUtilityWithDiscount(opponentOffer.getBid(), time);
474 myOfferUtility = this.myUtilitySpace
475 .getUtilityWithDiscount(this.myLastBid, time);
476 bestBidUtility = this.myUtilitySpace
477 .getUtilityWithDiscount(this.bestBid, time);
478
479 if (opponentOfferUtility >= this.getMyReservationValue(time)
480 && (2.1d * this.meanResponseTimeOfOpponent
481 + time >= 1.0d)) {
482 if ((this.meanResponseTimeOfOpponent + time <= 1.0d)) {
483 this.myLastBid = this.bestBid; // most probably our last
484 // or last few counter
485 // offer(s)!
486 result = false;
487 } else {
488 result = true;
489 }
490 } else if (opponentOfferUtility >= 0.90d) {
491 result = true;
492 } else if ((opponentOfferUtility >= myOfferUtility)
493 && (opponentOfferUtility >= 0.85d) && time > 0.95d) {
494 result = true;
495 }
496
497 } catch (Exception e) {
498 e.printStackTrace();
499 }
500 }
501 return result;
502 }
503
504 @Override
505 public String getVersion() {
506 return "1.1";
507 }
508
509 @Override
510 public String getName() {
511 return "AgentQuest";
512 }
513
514 /**
515 * This function determines the accept probability for an offer. At t=0 it
516 * will prefer high-utility offers. As t gets closer to 1, it will accept
517 * lower utility offers with increasing probability. it will never accept
518 * offers with utility 0.
519 *
520 * @param u
521 * is the utility
522 * @param t
523 * is the time as fraction of the total available time (t=0 at
524 * start, and t=1 at end time)
525 * @return the probability of an accept at time t
526 * @throws Exception
527 * if you use wrong values for u or t.
528 *
529 * Function reused from Genius codebase.
530 */
531 public BigDecimal Pconcede(double u, double t1) throws Exception {
532 double t = t1 * t1 * t1; // steeper increase when deadline approaches.
533 if (u < 0 || u > 1.05)
534 throw new Exception("utility " + u + " outside [0,1]");
535 // normalization may be slightly off, therefore we have a broad boundary
536 // up to 1.05
537 if (t < 0 || t > 1)
538 throw new Exception("time " + t + " outside [0,1]");
539 if (u > 1.)
540 u = 1;
541 if (t == 0.5) {
542 if (!Double.isNaN(u)) {
543 return new BigDecimal(u);
544 } else
545 throw new NumberFormatException(u + "");
546 }
547 double value = (u - 2. * u * t
548 + 2. * (-1. + t + Math.sqrt(sq(-1. + t) + u * (-1. + 2 * t))))
549 / (-1. + 2 * t);
550
551 if (!Double.isNaN(value)) {
552 return new BigDecimal(value);
553 } else
554 throw new NumberFormatException(value + "");
555 }
556
557 public double sq(double x) {
558 return x * x;
559 }
560
561 @Override
562 public String getDescription() {
563 return "ANAC2014 compatible with non-linear utility spaces";
564 }
565
566}
Note: See TracBrowser for help on using the repository browser.