source: anac2020/agentxx/src/main/java/geniusweb/exampleparties/newagentgg/AgentGG.java@ 3

Last change on this file since 3 was 1, checked in by wouter, 4 years ago

#1910 added anac2020 parties

File size: 15.3 KB
Line 
1package geniusweb.exampleparties.newagentgg;
2
3import geniusweb.actions.Accept;
4import geniusweb.actions.Action;
5import geniusweb.actions.Offer;
6import geniusweb.actions.PartyId;
7import geniusweb.bidspace.AllBidsList;
8import geniusweb.issuevalue.Bid;
9import geniusweb.issuevalue.Value;
10import geniusweb.party.Capabilities;
11import geniusweb.party.DefaultParty;
12import geniusweb.party.inform.*;
13import geniusweb.profile.PartialOrdering;
14import geniusweb.profileconnection.ProfileConnectionFactory;
15import geniusweb.profileconnection.ProfileInterface;
16import geniusweb.progress.Progress;
17import geniusweb.progress.ProgressRounds;
18import tudelft.utilities.logging.Reporter;
19
20import javax.websocket.DeploymentException;
21import java.io.IOException;
22import java.util.*;
23import java.util.logging.Level;
24
25import static java.lang.Math.max;
26
27/**
28 * Translated version of Genius ANAC 2019 AgentGG originally written by Shaobo
29 * Xu and Peihao Ren of University of Southampton. This party requires a partial
30 * ordering as input (notice that most profiles are also partial ordering
31 * anyway).
32 */
33public class AgentGG extends DefaultParty {
34
35 private ImpMap impMap;
36 private ImpMap opponentImpMap;
37 private double offerLowerRatio = 1.0;
38 private double offerHigherRatio = 1.1;
39 private double MAX_IMPORTANCE;
40 private double MIN_IMPORTANCE;
41 private double MEDIAN_IMPORTANCE;
42 private Bid MAX_IMPORTANCE_BID;
43 private Bid MIN_IMPORTANCE_BID;
44 private Bid receivedBid;
45 private double reservationImportanceRatio;
46 private boolean offerRandomly = true;
47
48 private double startTime;
49 private boolean maxOppoBidImpForMeGot = false;
50 private double maxOppoBidImpForMe;
51 private double estimatedNashPoint;
52 private Bid lastReceivedBid;
53 private boolean initialTimePass = false;
54
55 // new for GeniusWeb
56 private ProfileInterface profileint;
57 private PartyId me;
58 private Progress progress;
59 private Action lastReceivedAction = null;
60 private final Random rand = new Random();
61 private AllBidsList allbids; // all bids in domain.
62
63 public AgentGG() {
64 super();
65 }
66
67 public AgentGG(Reporter reporter) {
68 super(reporter);
69 }
70
71 @Override
72 public void notifyChange(Inform info) {
73 try {
74 if (info instanceof Settings) {
75 init((Settings) info);
76 } else if (info instanceof ActionDone) {
77 lastReceivedAction = ((ActionDone) info).getAction();
78 if (lastReceivedAction instanceof Offer) {
79 this.receivedBid = ((Offer) lastReceivedAction).getBid();
80 }
81 } else if (info instanceof YourTurn) {
82 Action action = chooseAction();
83 getConnection().send(action);
84 if (progress instanceof ProgressRounds) {
85 progress = ((ProgressRounds) progress).advance();
86 }
87 } else if (info instanceof Finished) {
88 getReporter().log(Level.INFO, "Final ourcome:" + info);
89 }
90 } catch (Exception e) {
91 throw new RuntimeException("Failed to handle info", e);
92 }
93 }
94
95 @Override
96 public Capabilities getCapabilities() {
97 return new Capabilities(new HashSet<>(Arrays.asList("SAOP")));
98 }
99
100 @Override
101 public String getDescription() {
102 return "ANAC 2019 AgentGG translated to GeniusWeb. Requires partial profile. Use frequency counting to estimate important opponent values. ";
103 }
104
105 /***************
106 * private
107 *
108 * @throws DeploymentException
109 *********************/
110
111 private void init(Settings info) throws IOException, DeploymentException {
112 this.me = info.getID();
113 this.progress = info.getProgress();
114
115 this.profileint = ProfileConnectionFactory
116 .create(info.getProfile().getURI(), getReporter());
117 PartialOrdering partialprofile = (PartialOrdering) profileint
118 .getProfile();
119 allbids = new AllBidsList(partialprofile.getDomain());
120
121 // Create empty my import map
122 this.impMap = new ImpMap(partialprofile);
123 // and opponent's value map. CHECK why is the opponent map not initially
124 // empty?
125 this.opponentImpMap = new ImpMap(partialprofile);
126
127 // Wouter we use SimpleLinearOrdering (from shaop party) to get sorted
128 // bids from our profile.
129 List<Bid> orderedbids = new SimpleLinearOrdering(
130 profileint.getProfile()).getBids();
131
132 // Update my importance map
133 this.impMap.self_update(orderedbids);
134
135 // Get maximum, minimum, median bid
136 this.getMaxAndMinBid();
137 this.getMedianBid(orderedbids);
138
139 // Get the reservation value, converted to the percentage of importance
140 this.reservationImportanceRatio = this.getReservationRatio();
141
142 getReporter().log(Level.INFO,
143 "reservation ratio: " + this.reservationImportanceRatio);
144 getReporter().log(Level.INFO,
145 "my max importance bid: " + this.MAX_IMPORTANCE_BID);
146 getReporter().log(Level.INFO,
147 "my max importance: " + this.MAX_IMPORTANCE);
148 getReporter().log(Level.INFO,
149 "my min importance bid: " + this.MIN_IMPORTANCE_BID);
150 getReporter().log(Level.INFO,
151 "my min importance: " + this.MIN_IMPORTANCE);
152 getReporter().log(Level.INFO,
153 "my median importance: " + this.MEDIAN_IMPORTANCE);
154 getReporter().log(Level.INFO,
155 "Party " + me + " has finished initialization");
156 }
157
158 private Action chooseAction() {
159 double time = progress.get(System.currentTimeMillis());
160
161 // Start competition
162 if (!(this.lastReceivedAction instanceof Offer))
163 return new Offer(me, this.MAX_IMPORTANCE_BID);
164
165 // The ratio of the other party's offer to me
166 double impRatioForMe = (this.impMap.getImportance(this.receivedBid)
167 - this.MIN_IMPORTANCE)
168 / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
169
170 // Accept the terms of the offer, which is higher than my threshold
171 if (impRatioForMe >= this.offerLowerRatio) {
172 getReporter().log(Level.INFO, "\n\naccepted agent: Agent" + me);
173 getReporter().log(Level.INFO, "last bid: " + this.receivedBid);
174 getReporter().log(Level.INFO,
175 "\ncurrent threshold: " + this.offerLowerRatio);
176 getReporter().log(Level.INFO, "\n\n");
177 return new Accept(me, this.receivedBid);
178 }
179
180 // When the opponent's importance is around 1.0, how much can he get.
181 // Finding the endpoints of the Pareto boundary
182 if (!maxOppoBidImpForMeGot)
183 this.getMaxOppoBidImpForMe(time, 3.0 / 1000.0);
184
185 // Update opponent importance table
186 if (time < 0.3)
187 this.opponentImpMap.opponent_update(this.receivedBid);
188
189 // Strategy
190 this.getThreshold(time);
191
192 // Last round
193 if (time >= 0.9989) {
194 double ratio = (this.impMap.getImportance(this.receivedBid)
195 - this.MIN_IMPORTANCE)
196 / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
197 if (ratio > this.reservationImportanceRatio + 0.2) {
198 return new Accept(me, receivedBid);
199 }
200 }
201
202 getReporter().log(Level.INFO,
203 "high threshold: " + this.offerHigherRatio);
204 getReporter().log(Level.INFO, "low threshold: " + this.offerLowerRatio);
205 getReporter().log(Level.INFO,
206 "estimated nash: " + this.estimatedNashPoint);
207 getReporter().log(Level.INFO,
208 "reservation: " + this.reservationImportanceRatio);
209
210 Bid bid = getNeededRandomBid(this.offerLowerRatio,
211 this.offerHigherRatio);
212 this.lastReceivedBid = this.receivedBid;
213 return new Offer(me, bid);
214 }
215
216 /**
217 * Get our optimal value (Pareto optimal boundary point) when the utility of
218 * the other party is around 1.0 The opponent may first report the same bid
219 * several times, ignore it, and start timing at different times. For
220 * durations (such as 20 rounds), choose the bid with the highest importance
221 * for me. Since the bid of the other party must be very important to the
222 * other party at this time, it can meet our requirements.
223 */
224 private void getMaxOppoBidImpForMe(double time, double timeLast) {
225 double thisBidImp = this.impMap.getImportance(this.receivedBid);
226 if (thisBidImp > this.maxOppoBidImpForMe)
227 this.maxOppoBidImpForMe = thisBidImp;
228
229 if (this.initialTimePass) {
230 if (time - this.startTime > timeLast) {
231 double maxOppoBidRatioForMe = (this.maxOppoBidImpForMe
232 - this.MIN_IMPORTANCE)
233 / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
234 this.estimatedNashPoint = (1 - maxOppoBidRatioForMe) / 1.7
235 + maxOppoBidRatioForMe; // 1.414 是圆,2是直线
236 this.maxOppoBidImpForMeGot = true;
237 }
238 } else {
239 if (this.lastReceivedBid != this.receivedBid) {
240 this.initialTimePass = true;
241 this.startTime = time;
242 }
243 }
244 }
245
246 /**
247 * Get upper and lower thresholds based on time
248 */
249 private void getThreshold(double time) {
250 if (time < 0.01) {
251 // The first 10 rounds of 0.9999, in order to adapt to some special
252 // domains
253 this.offerLowerRatio = 0.9999;
254 } else if (time < 0.02) {
255 // 10 ~ 20 rounds of 0.99, in order to adapt to some special domains
256 this.offerLowerRatio = 0.99;
257 } else if (time < 0.2) {
258 // 20 ~ 200 rounds reported high price, dropped to 0.9
259 this.offerLowerRatio = 0.99 - 0.5 * (time - 0.02);
260 } else if (time < 0.5) {
261 this.offerRandomly = false;
262 // 200 ~ 500 rounds gradually reduce the threshold to 0.5 from the
263 // estimated Nash point
264 double p2 = 0.3 * (1 - this.estimatedNashPoint)
265 + this.estimatedNashPoint;
266 this.offerLowerRatio = 0.9
267 - (0.9 - p2) / (0.5 - 0.2) * (time - 0.2);
268 } else if (time < 0.9) {
269 // 500 ~ 900 rounds quickly decrease the threshold to 0.2 from the
270 // estimated Nash point
271 double p1 = 0.3 * (1 - this.estimatedNashPoint)
272 + this.estimatedNashPoint;
273 double p2 = 0.15 * (1 - this.estimatedNashPoint)
274 + this.estimatedNashPoint;
275 this.offerLowerRatio = p1 - (p1 - p2) / (0.9 - 0.5) * (time - 0.5);
276 } else if (time < 0.98) {
277 // Compromise 1
278 double p1 = 0.15 * (1 - this.estimatedNashPoint)
279 + this.estimatedNashPoint;
280 double p2 = 0.05 * (1 - this.estimatedNashPoint)
281 + this.estimatedNashPoint;
282 double possibleRatio = p1 - (p1 - p2) / (0.98 - 0.9) * (time - 0.9);
283 this.offerLowerRatio = max(possibleRatio,
284 this.reservationImportanceRatio + 0.3);
285 } else if (time < 0.995) {
286 // Compromise 2 980 ~ 995 rounds
287 double p1 = 0.05 * (1 - this.estimatedNashPoint)
288 + this.estimatedNashPoint;
289 double p2 = 0.0 * (1 - this.estimatedNashPoint)
290 + this.estimatedNashPoint;
291 double possibleRatio = p1
292 - (p1 - p2) / (0.995 - 0.98) * (time - 0.98);
293 this.offerLowerRatio = max(possibleRatio,
294 this.reservationImportanceRatio + 0.25);
295 } else if (time < 0.999) {
296 // Compromise 3 995 ~ 999 rounds
297 double p1 = 0.0 * (1 - this.estimatedNashPoint)
298 + this.estimatedNashPoint;
299 double p2 = -0.35 * (1 - this.estimatedNashPoint)
300 + this.estimatedNashPoint;
301 double possibleRatio = p1
302 - (p1 - p2) / (0.9989 - 0.995) * (time - 0.995);
303 this.offerLowerRatio = max(possibleRatio,
304 this.reservationImportanceRatio + 0.25);
305 } else {
306 double possibleRatio = -0.4 * (1 - this.estimatedNashPoint)
307 + this.estimatedNashPoint;
308 this.offerLowerRatio = max(possibleRatio,
309 this.reservationImportanceRatio + 0.2);
310 }
311 this.offerHigherRatio = this.offerLowerRatio + 0.1;
312 }
313
314 /**
315 * Get the ratio of the reservation value to the importance matrix. ASSUMES
316 * The imgMap has been initialized.
317 *
318 */
319 private double getReservationRatio() throws IOException {
320 double medianBidRatio = (this.MEDIAN_IMPORTANCE - this.MIN_IMPORTANCE)
321 / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
322 Bid resBid = this.profileint.getProfile().getReservationBid();
323 double resValue = 0.1;
324 if (resBid != null) {
325 resValue = this.impMap.getImportance(resBid);
326 }
327 return resValue * medianBidRatio / 0.5;
328 }
329
330 /**
331 * Get the maximum and minimum importance values and corresponding offers
332 */
333 private void getMaxAndMinBid() {
334 HashMap<String, Value> lValues1 = new HashMap<>();
335 HashMap<String, Value> lValues2 = new HashMap<>();
336 for (Map.Entry<String, List<impUnit>> entry : this.impMap.entrySet()) {
337 Value value1 = entry.getValue().get(0).valueOfIssue;
338 Value value2 = entry.getValue()
339 .get(entry.getValue().size() - 1).valueOfIssue;
340 String issue = entry.getKey();
341 lValues1.put(issue, value1);
342 lValues2.put(issue, value2);
343 }
344 this.MAX_IMPORTANCE_BID = new Bid(lValues1);
345 this.MIN_IMPORTANCE_BID = new Bid(lValues2);
346 this.MAX_IMPORTANCE = this.impMap
347 .getImportance(this.MAX_IMPORTANCE_BID);
348 this.MIN_IMPORTANCE = this.impMap
349 .getImportance(this.MIN_IMPORTANCE_BID);
350 }
351
352 /**
353 * Get the import value corresponding to the median bid in bid ranking
354 *
355 * @param orderedbids a list of bids, ordered from low to high utility.
356 */
357 private void getMedianBid(List<Bid> orderedbids) {
358
359 int median = (orderedbids.size() - 1) / 2;
360 int median2 = -1;
361 if (orderedbids.size() % 2 == 0) {
362 median2 = median + 1;
363 }
364 int current = 0;
365 for (Bid bid : orderedbids) {
366 current += 1;
367 if (current == median) {
368 this.MEDIAN_IMPORTANCE = this.impMap.getImportance(bid);
369 if (median2 == -1)
370 break;
371 }
372 if (current == median2) {
373 this.MEDIAN_IMPORTANCE += this.impMap.getImportance(bid);
374 break;
375 }
376 }
377 if (median2 != -1)
378 this.MEDIAN_IMPORTANCE /= 2;
379 }
380
381// /**
382// * 更新对手的最大及最小Importance的值及对应OFFER
383// */
384// private void getOpponentMaxAndMinBid() {
385// HashMap<Integer, Value> lValues1 = new HashMap<>();
386// HashMap<Integer, Value> lValues2 = new HashMap<>();
387// for (Map.Entry<Issue, List<impUnit>> entry : this.opponentImpMap.entrySet()) {
388// Value value1 = entry.getValue().get(0).valueOfIssue;
389// Value value2 = entry.getValue().get(entry.getValue().size() - 1).valueOfIssue;
390// int issueNumber = entry.getKey().getNumber();
391// lValues1.put(issueNumber, value1);
392// lValues2.put(issueNumber, value2);
393// }
394// Bid OPPONENT_MAX_IMPORTANCE_BID = new Bid(this.getDomain(), lValues1);
395// Bid OPPONENT_MIN_IMPORTANCE_BID = new Bid(this.getDomain(), lValues2);
396// this.OPPONENT_MAX_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MAX_IMPORTANCE_BID);
397// this.OPPONENT_MIN_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MIN_IMPORTANCE_BID);
398// }
399
400 /**
401 * Get eligible random bids. Generate k bids randomly, select bids within
402 * the threshold range, and return the bid with the highest opponent import.
403 *
404 * @param lowerRatio Generate a lower limit for the random bid
405 * @param upperRatio Generate random bid upper limit
406 * @return Bid
407 * @throws IOException
408 */
409 private Bid getNeededRandomBid(double lowerRatio, double upperRatio) {
410 final long k = 2 * this.allbids.size().longValue();
411 double lowerThreshold = lowerRatio
412 * (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE)
413 + this.MIN_IMPORTANCE;
414 double upperThreshold = upperRatio
415 * (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE)
416 + this.MIN_IMPORTANCE;
417
418 for (int t = 0; t < 3; t++) {
419 double highest_opponent_importance = 0.0;
420 Bid returnedBid = null;
421 for (int i = 0; i < k; i++) {
422 Bid bid = generateRandomBid();
423 double bidImportance = this.impMap.getImportance(bid);
424 double bidOpponentImportance = this.opponentImpMap
425 .getImportance(bid);
426 if (bidImportance >= lowerThreshold
427 && bidImportance <= upperThreshold) {
428 if (this.offerRandomly)
429 return bid; // Randomly bid for the first 0.2 time
430 if (bidOpponentImportance > highest_opponent_importance) {
431 highest_opponent_importance = bidOpponentImportance;
432 returnedBid = bid;
433 }
434 }
435 }
436 if (returnedBid != null) {
437 return returnedBid;
438 }
439 }
440 // If something goes wrong and no suitable bid is found, then a higher
441 // than the lower limit
442 while (true) {
443 Bid bid = generateRandomBid();
444 if (this.impMap.getImportance(bid) >= lowerThreshold) {
445 return bid;
446 }
447 }
448 }
449
450 private Bid generateRandomBid() {
451 return allbids.get(rand.nextInt(allbids.size().intValue()));
452 }
453
454}
Note: See TracBrowser for help on using the repository browser.