source: anac2020/AzarAgent/src/main/java/geniusweb/exampleparties/simpleshaop/ShaopParty.java@ 77

Last change on this file since 77 was 31, checked in by wouter, 3 years ago

#3

File size: 20.2 KB
Line 
1package geniusweb.exampleparties.simpleshaop;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.util.ArrayList;
6import java.util.Arrays;
7import java.util.Collections;
8import java.util.HashSet;
9import java.util.List;
10import java.util.Random;
11import java.util.logging.Level;
12
13import javax.websocket.DeploymentException;
14
15import geniusweb.actions.Accept;
16import geniusweb.actions.Action;
17import geniusweb.actions.Comparison;
18import geniusweb.actions.ElicitComparison;
19import geniusweb.actions.EndNegotiation;
20import geniusweb.actions.Offer;
21import geniusweb.actions.PartyId;
22import geniusweb.bidspace.AllBidsList;
23import geniusweb.inform.ActionDone;
24import geniusweb.inform.Finished;
25import geniusweb.inform.Inform;
26import geniusweb.inform.Settings;
27import geniusweb.inform.YourTurn;
28import geniusweb.issuevalue.Bid;
29import geniusweb.issuevalue.Domain;
30import geniusweb.party.Capabilities;
31import geniusweb.party.DefaultParty;
32import geniusweb.profile.Profile;
33import geniusweb.profileconnection.ProfileConnectionFactory;
34import geniusweb.profileconnection.ProfileInterface;
35import geniusweb.progress.Progress;
36import geniusweb.progress.ProgressRounds;
37import tudelft.utilities.logging.Reporter;
38
39/**
40 * This Agent work on partial preference and use the GravityAgent ( ANAC 2019
41 * competition ) user model to model user and use Frequency method to model our
42 * opponent.
43 *
44 * @author Arash Ebrahinezhad
45 *
46 * Arash.ebrah@gmail.com arash.ebrah@nit.ac.ir
47 */
48public class ShaopParty extends DefaultParty {
49
50 private Random rand = new Random();
51
52 private int numberOfSameConsecutiveBidInMyBids = 0;
53 private double eCost; // Elicitation Cost
54 private double rValue; // Reservation Value
55 private FrequencyModel opModel; // Opponent Model
56 private boolean myConcessionEnough = false;
57 private GravityEs myModel2; // User Model
58 private Bid receivedBid = null; // Last Received bid
59 ArrayList<Bid> oppBids = new ArrayList<Bid>(); // All Bids that received from Opponent
60 ArrayList<Bid> myBids = new ArrayList<Bid>(); // All Bids that we sent to opponent
61 private List<Bid> bidOrder;
62 private int allBidSize;
63 private List<Double> expectedValue; // توزیع احتمالاتی بیدهای در بین بیدهای مرتب شده
64
65 // Time depending bidding strategy : boulware or conceder
66 private double e = 0.8;
67 private static final double k = 0;
68 private int afterRank = 2; // How many rank after our estimation bid rank must be checked
69 private int beforeRank = 1; // How many rank before our estimation bid rank must be checked
70 private double agreementSimilarityThreshold; // threshold of similarity for acceptance Strategy
71 private double opponentConcesionRate = 0.08; // our expected opponent concession rate
72 private int howManyRankMustBeChecked = 5; // threshold of bid rank which we mast to check if Estimation rank satisfy
73 // the condition
74
75 double Pagreement; // the threshold of bid agreement by opponent we must to select ( control our
76 // concession strategy )
77
78 ////////////////////////////////////////////////////////////////////////////////////////////
79 private Bid reservationBid;
80 private PartyId me;
81 protected ProfileInterface profileint;
82 private Progress progress;
83
84 private USpace utilitySpace;
85 private Profile profile;
86 private Domain domain;
87 private AllBidsList allBids;
88 private double totalBother = 0;
89 private SimpleLinearOrdering estimatedProfile = null;
90 ////////////////////////////////////////////////////////////////////////////////////////////
91
92 public ShaopParty() {
93 }
94
95 public ShaopParty(Reporter reporter) {
96 super(reporter); // for debugging
97 }
98
99 private void init(Settings info) throws IOException, DeploymentException {
100
101 Settings settings = info;
102 this.profileint = ProfileConnectionFactory.create(settings.getProfile().getURI(), getReporter());
103 this.me = settings.getID();
104 this.progress = settings.getProgress();
105
106 this.profile = profileint.getProfile();
107 this.domain = this.profile.getDomain();
108 utilitySpace = new USpace(this.domain);
109 allBids = new AllBidsList(profileint.getProfile().getDomain());
110
111 if (reservationBid != null) // if the reservation bid does not exist so we accept opponent bid with more
112 // probability
113 agreementSimilarityThreshold = 0.85;
114 else
115 agreementSimilarityThreshold = 0.7;
116
117 estimatedProfile = new SimpleLinearOrdering(profile);
118 List<Bid> bOr = new ArrayList<Bid>();
119 if (estimatedProfile.getBids().size() == 2) { // if ordered bids size equal 2, add reservation value or random
120 // Bid
121
122 bOr.add(estimatedProfile.getBids().get(0));
123
124 if (reservationBid != null && !reservationBid.equals(estimatedProfile.getBids().get(0))
125 && !reservationBid.equals(estimatedProfile.getBids().get(1)))
126 bOr.add(reservationBid);
127 else
128 while (true) {
129 long i = rand.nextInt(allBids.size().intValue());
130 Bid randBid = allBids.get(BigInteger.valueOf(i));
131 if (!randBid.equals(estimatedProfile.getBids().get(0))
132 && !randBid.equals(estimatedProfile.getBids().get(1))) {
133 bOr.add(randBid);
134 break;
135 }
136 }
137
138 bOr.add(estimatedProfile.getBids().get(1));
139
140 estimatedProfile = new SimpleLinearOrdering(domain, bOr);
141
142 }
143
144 bidOrder = estimatedProfile.getBids();
145
146 try { // if elicitation cost is set, catch it, else set it 0.1
147 eCost = (double) settings.getParameters().get("elicitationcost");
148 } catch (Exception e) {
149 eCost = 0.1; // if elicitation cost is not set, we set it to 0.1
150 }
151
152 try { // if reservation Bid is set, catch it, else set it null
153 reservationBid = profile.getReservationBid();
154 } catch (Exception e) {
155 reservationBid = null;
156 }
157
158 opModel = new FrequencyModel(utilitySpace);
159
160 allBidSize = allBids.size().intValue();
161 expectedValue = new ArrayList<Double>();
162 initExpectedValue();
163
164 myModel2 = new GravityEs(domain, bidOrder);
165
166 // myModel = new WinkyA2(domain, bidOrder, profileint);
167
168 if (reservationBid != null) // if reservation bid is set, set the reservation value to utility of it
169 rValue = myModel2.getUtilityForBid(reservationBid); // این قسمت شاید تغییر کند
170 else
171 rValue = 0;
172
173 }
174
175 public void initExpectedValue() {
176 for (int i = 0; i < bidOrder.size() - 1; i++)
177 expectedValue.add(1.0 / (bidOrder.size() - 1));
178
179 }
180
181 private void updateExpectedUtility() {
182 expectedValue.clear();
183 for (int i = 0; i < bidOrder.size() - 1; i++)
184 expectedValue.add(1.0 / (bidOrder.size() - 1));
185 }
186
187 @Override
188 public void notifyChange(Inform info) {
189 try {
190 if (info instanceof Settings) {
191 init((Settings) info);
192 } else if (info instanceof ActionDone) {
193 Action otheract = ((ActionDone) info).getAction();
194 if (otheract instanceof Offer) {
195 receivedBid = ((Offer) otheract).getBid();
196 opModel.updateLearner(receivedBid);
197 } else if (otheract instanceof Comparison) {
198 totalBother += eCost; // شاید این قسمت تغییر کند
199 estimatedProfile = estimatedProfile.with(((Comparison) otheract).getBid(),
200 ((Comparison) otheract).getWorse());
201 bidOrder = estimatedProfile.getBids(); // After each elicitation update bidOrder
202 updateExpectedUtility();
203 myModel2 = myModel2.updateGravityModel(bidOrder); // After each elicitation update User Model
204 if (reservationBid != null)
205 rValue = myModel2.getUtilityForBid(reservationBid); // After each elicitation update reservation
206 // value
207 myTurn(true);
208 }
209 } else if (info instanceof YourTurn) {
210 myTurn(false);
211 } else if (info instanceof Finished) {
212 getReporter().log(Level.INFO, "Final ourcome:" + info);
213 }
214 } catch (Exception e) {
215 throw new RuntimeException("Failed to handle info", e);
216 }
217 }
218
219 @Override
220 public Capabilities getCapabilities() {
221 return new Capabilities(new HashSet<>(Arrays.asList("SHAOP")), Collections.singleton(Profile.class));
222 }
223
224 @Override
225 public String getDescription() {
226 return "Azar Agent ANAC 2020";
227 }
228
229 /**
230 * Called when it's (still) our turn and we should take some action. Also
231 * Updates the progress if necessary.
232 */
233 void myTurn(boolean elicitation) throws IOException {
234
235 Action action = null;
236
237 if (!elicitation && !myConcessionEnough) {
238 double t = progress.get(System.currentTimeMillis());
239 Pagreement = getPagreement(t);
240 }
241
242 // Elicitation Strategy and Bidding Strategy
243 // log2("--------------------------------<Elicitation
244 // start>------------------------------------"+Pagreement);
245 MyBidDetails bidDetail = null;
246
247 if (totalBother < 0.6 /* 1-rValue */ ) { // تا زمانی که به مقدار رزرویشن نرسیدیم، الیسیتیشن رو ادامه بده
248 bidDetail = getBestBidInKnownSet(Pagreement, elicitation);
249
250 MyBidDetails bidDetailPrim = getBestBidInUnKnownSet(Pagreement);
251
252 // Only for log!!!
253 // String s = " Is this ("+bidDetailPrim.getEu()+" - "+eCost+" >
254 // "+bidDetail.getEu() + ") True?";
255 // s +=( (bidDetailPrim.getEu() - eCost > bidDetail.getEu()) ) ? " True =>
256 // Elicit" : " False => not Elicit";
257 // log2( s );
258
259 if (bidDetailPrim.getEu() - eCost > bidDetail.getEu())
260 action = new ElicitComparison(me, bidDetailPrim.getBid(), estimatedProfile.getBids());
261
262 } else {
263 // log2("Elicitation total bother is more than 0.6 !!!");
264 }
265 // log2("---------------------------------<Elicitation
266 // End>-------------------------------------\n\n");
267
268 if (bidDetail == null) {
269 if (reservationBid != null)
270 bidDetail = new MyBidDetails(reservationBid, 0.5);
271 else if (bidOrder.size() > 10)
272 bidDetail = new MyBidDetails(bidOrder.get(bidOrder.size() / 2), 1.0);
273 else
274 bidDetail = new MyBidDetails(bidOrder.get(bidOrder.size() - 1), 1.0);
275 }
276
277 if (action == null && receivedBid != null) {
278 if (isGood(receivedBid, bidDetail.getBid()))
279 action = new Accept(me, receivedBid);
280
281 if (progress instanceof ProgressRounds)
282 progress = ((ProgressRounds) progress).advance();
283
284 }
285
286 if (action == null) {
287 Bid myBid = bidDetail.getBid();
288
289 if (myModel2.getUtilityForBid(myBid) > rValue) {
290
291 if (myBids.isEmpty())
292 myBids.add(myBid);
293 if (!myBids.contains(myBid))
294 myBids.add(myBid);
295
296 if (myBids.size() > 1)
297 if (myBids.get(myBids.size() - 1).equals(myBids.get(myBids.size() - 2)))
298 numberOfSameConsecutiveBidInMyBids++;
299 else
300 numberOfSameConsecutiveBidInMyBids = 0;
301
302 action = new Offer(me, myBid);
303 } else
304 action = new EndNegotiation(me);
305
306 }
307
308 getConnection().send(action);
309
310 }
311
312 // ***************************************************************************************
313
314 /**
315 * Acceptance Strategy
316 *
317 * @param reBid the last received bid from opponent
318 *
319 * @param nextBid the next bid that we prepare to send to opponent
320 *
321 * @return true if we must accept opponent offer and false vice versa
322 */
323 private boolean isGood(Bid reBid, Bid nextBid) {
324
325 if (oppBids.isEmpty() || !oppBids.contains(reBid)) // اگر این بید را قبلا دریافت نکرده باشیم اضافه کن
326 oppBids.add(reBid);
327
328 if (myModel2.getUtilityForBid(reBid) < rValue)
329 return false;
330
331 if (reBid.equals(nextBid))
332 return true;
333
334 if (myBids.contains(reBid))
335 return true;
336
337 if (myModel2.getUtilityForBid(reBid) >= myModel2.getUtilityForBid(nextBid))
338 return true;
339
340 for (Bid b : myBids)
341 if (myModel2.getUtilityForBid(reBid) >= myModel2.getUtilityForBid(b) + 0.07)
342 return true;
343
344 double currentAgreementSimilarityThreshold = ((1 - Pagreement) > agreementSimilarityThreshold)
345 ? (1 - Pagreement)
346 : agreementSimilarityThreshold;
347
348 return (getAcceptanceProbability(reBid, nextBid) > currentAgreementSimilarityThreshold ? true : false)
349 && myModel2.getUtilityForBid(reBid) > rValue;
350
351 }
352
353 /**
354 *
355 * @param reBid Last Received Bid From Opponent
356 * @param nextBid the next bid that we prepare send to opponent
357 *
358 * @return double value that determine maximum similarity (1-distance) value of
359 * received bid from opponent to our sent bids
360 */
361 private double getAcceptanceProbability(Bid reBid, Bid nextBid) {
362
363 double t = Double.MAX_VALUE;
364
365 double reBidU = myModel2.getUtilityForBid(reBid);
366
367 // for ( Bid b : oppBids ) {
368 for (Bid b : myBids) {
369 double temp = 1 - Math.abs(myModel2.getUtilityForBid(b) - reBidU);
370 if (temp < t) {
371 t = temp;
372 }
373 }
374
375 double nextBidU = myModel2.getUtilityForBid(nextBid);
376 if ((1 - Math.abs(nextBidU - reBidU)) < t)
377 return (1 - Math.abs(nextBidU - reBidU));
378
379 return t;
380
381 }
382
383 /**
384 *
385 * @param the Agreement probability of the bid that we want decide about its
386 * elicitation must be more than it.
387 *
388 * @return the best bid and its utility (MyBidDetails object) in the set of bids
389 * which we know about its order.
390 */
391 private MyBidDetails getBestBidInKnownSet(double Pagreement1, boolean elicitation) {
392
393 for (int i = bidOrder.size() - 1; i > 0; i--) {
394 double Pat = getAgreementProbability(bidOrder.get(i));
395 if (Pat >= Pagreement1
396 && myModel2.getUtilityForBid(bidOrder.get(i)) > myModel2.getUtilityForBid(bidOrder.get(i)) / 2) {
397 if (myBids.size() > 1)
398 if (myModel2.getUtilityForBid(myBids.get(myBids.size() - 1))
399 - myModel2.getUtilityForBid(bidOrder.get(i)) > 0.3)
400 if (myModel2.getUtilityForBid(bidOrder.get(i)) - 0.3 > 0)
401 return new MyBidDetails(bidOrder.get(i), myModel2.getUtilityForBid(bidOrder.get(i)) - 0.3);
402 else
403 return new MyBidDetails(null, 0.0);
404
405 return new MyBidDetails(bidOrder.get(i), myModel2.getUtilityForBid(bidOrder.get(i)));
406 }
407 }
408
409 return new MyBidDetails(null, 0.0);
410
411 /*
412 * if ( myBids.size() > 0 ) {
413 *
414 * if( myModel2.getUtilityForBid( myBids.get( myBids.size()-1
415 * ))-(numberOfSameConsecutiveBidInMyBids*0.1) > 0 ) return new
416 * MyBidDetails(myBids.get( myBids.size()-1 ), myModel2.getUtilityForBid(
417 * myBids.get( myBids.size()-1 ))-(numberOfSameConsecutiveBidInMyBids*0.1) );
418 * else return new MyBidDetails(myBids.get( myBids.size()-1 ), 0.0 );
419 *
420 * } else return new MyBidDetails(bidOrder.get( bidOrder.size()-1 ),
421 * myModel2.getUtilityForBid( bidOrder.get( bidOrder.size()-1 )) );
422 */
423
424 }
425
426 /**
427 *
428 * @param Pagreement2 the Agreement probability of the bid that we want decide
429 * about its elicitation must be more than it.
430 *
431 * @return the best bid in the bids set that we don't know about their orders
432 * respect to if we would elicit it.
433 */
434 private MyBidDetails getBestBidInUnKnownSet(double Pagreement2) {
435
436 /*
437 * for decrease the size of variety Check the probabilities we check only bids
438 * with high estimation rank and high utility
439 */
440
441 int estimateBidRank = 0;
442
443 double EEu = 0;
444 Bid bestBid = null;
445
446 for (Bid bid : allBids) {
447
448 if (!bidOrder.contains(bid)) {
449
450 double Pat = getAgreementProbability(bid);
451
452 if (Pat > Pagreement2 /* && myModel2.getUtilityForBid(bid) > bidThreshold */ ) {
453
454 estimateBidRank = getEstimateBidRank(bid);
455
456 if (estimateBidRank >= (bidOrder.size() - 1) - howManyRankMustBeChecked) {
457
458 double tempEu = getNewEu(estimateBidRank, bid);
459
460 double tempEEu = tempEu/* Pat */;
461
462 if (tempEEu > EEu) {
463 EEu = tempEEu;
464 bestBid = bid;
465 }
466
467 }
468 }
469 }
470
471 }
472 if (bestBid != null)
473 return new MyBidDetails(bestBid, EEu);
474
475 else
476 return new MyBidDetails(null, 0.0);
477
478 }
479
480 /**
481 *
482 * @param bid the bid we want estimate about its bid rank with our current
483 * knowledge
484 * @return estimated bid rank
485 */
486 private int getEstimateBidRank(Bid bid) {
487
488 double tempU = myModel2.getUtilityForBid(bid);
489
490 int rank = 0;
491 for (Bid b : bidOrder) {
492
493 double bU = myModel2.getUtilityForBid(b);
494
495 if (tempU <= bU) {
496 break;
497 } else
498 rank++;
499
500 }
501 if (rank == 0)
502 rank = 1;
503
504 return rank;
505
506 }
507
508 /**
509 *
510 * @param rank the rank of the bid that we estimate with current knowledge
511 * @param bid the bid which we want estimate its utility if it is elicited
512 * @return the our expected utility of bid that if we would elicite it
513 */
514 private double getNewEu(int rank, Bid bid) {
515
516 expectedValue.clear();
517 expectedValue = getNewExpectedValue(rank);
518
519 double newEU = 0;
520 int bidOrderSize2 = bidOrder.size();
521
522 if (rank == bidOrderSize2 - 1)
523 return myModel2.getUtilityForBid(bid);
524
525 int aJ = 0;
526 for (int j = rank; j <= Integer.min(rank + afterRank, bidOrderSize2 - 1); j++) { // ما بعد
527
528 List<Bid> bidOrderProbability2 = new ArrayList<Bid>();
529
530 for (Bid b : bidOrder)
531 bidOrderProbability2.add(b);
532
533 double probabilityBelong = expectedValue.get(j - 1);// *bidOrderSize2;
534
535 bidOrderProbability2.add(j, bid);
536
537 GravityEs modelProbability2 = new GravityEs(domain, bidOrderProbability2);
538
539 newEU += probabilityBelong * (modelProbability2.getUtilityForBid(bid));
540 aJ++;
541 }
542 if (rank > 1) {
543 for (int j = rank - 1; j > Integer.min(Integer.max(0, aJ - 1), Integer.max(0, rank - beforeRank)); j--) { // ما
544 // قبل
545
546 List<Bid> bidOrderProbability1 = new ArrayList<Bid>();
547
548 for (Bid b : bidOrder)
549 bidOrderProbability1.add(b);
550
551 double probabilityBelong = expectedValue.get(j - 1);// *bidOrderSize2;
552 bidOrderProbability1.add(j, bid);
553
554 GravityEs modelProbability1 = new GravityEs(domain, bidOrderProbability1);
555
556 newEU += probabilityBelong * (modelProbability1.getUtilityForBid(bid));
557
558 }
559 }
560
561 return newEU;
562
563 }
564
565 /**
566 *
567 * @param rank the rank of the bid that we estimate with current knowledge
568 * @return probability distribution of bid in variety ranks, that we want decide
569 * about its elicitation
570 */
571 private List<Double> getNewExpectedValue(int rank) {
572
573 double certainty = (double) bidOrder.size() / allBidSize;
574
575 List<Double> expectedValue = new ArrayList<Double>();
576 for (int i = 0; i < bidOrder.size(); i++)
577 expectedValue.add(1.0 / (bidOrder.size() - 1));
578
579 double temp1 = expectedValue.size();
580 for (int i = rank; i > 0; i--) {
581 double ttemp = expectedValue.get(i - 1);
582 expectedValue.remove(i - 1);
583 expectedValue.add(i - 1, (temp1 * certainty) + ttemp);
584 temp1--;
585 }
586
587 double temp2 = expectedValue.size() - 1;
588 for (int i = rank + 1; i <= expectedValue.size(); i++) {
589 double ttemp = expectedValue.get(i - 1);
590 expectedValue.remove(i - 1);
591 expectedValue.add(i - 1, (temp2 * certainty) + ttemp);
592 temp2--;
593 }
594
595 double n = 0;
596 for (double t : expectedValue)
597 n += t;
598
599 for (int i = 0; i < expectedValue.size(); i++) {
600 double tTemp = expectedValue.get(i);
601 expectedValue.remove(i);
602 expectedValue.add(i, tTemp / n);
603 }
604
605 return expectedValue;
606
607 }
608
609 private double f(double t) {
610 if (e == 0)
611 return k;
612 double ft = k + (1 - k) * Math.pow(t, 1 / e);
613
614 return ft;
615 }
616
617 /**
618 *
619 * @param t Time (if we want use time for compute concession rate)
620 * @return double value that the agent must be found a bid that has Agreement
621 * Probability more than it.
622 */
623 private double getPagreement(double t) {
624
625 // if ( reservationBid != null || t <= 0.7 )
626 return Pagreement + 0.01;
627 // else
628 // return Pagreement+0.01; // 0.02
629 // return 1 - ( myEstimateMin + (myEstimateMax - myEstimateMin) * (1 - f(t)) );
630 }
631
632 /**
633 *
634 * Opponent Model
635 *
636 * @param bid the bid want to know its agreement probability with opponent
637 *
638 * @return double value which determine opponent agreement probability of the
639 * bid
640 *
641 */
642 private double getAgreementProbability(Bid bid) {
643
644 if (oppBids.isEmpty()) { // if we don't got any bid from opponent
645 return 1.0;
646 }
647 if (myBids.contains(bid)) { // if we sent this bid before
648 return opponentConcesionRate * progress.get(System.currentTimeMillis());
649 }
650 if (oppBids.contains(bid)) { // if this bid is one of previous bids that we got from opponent
651 return 1.0;
652 }
653
654 double t = Double.MAX_VALUE;
655
656 for (Bid b : oppBids) {
657
658 double temp = 1 - Math.abs(opModel.getOpponentUtilitySpace().getUtility(b)
659 - opModel.getOpponentUtilitySpace().getUtility(bid));
660
661 if (temp < t) {
662 t = temp;
663 }
664
665 }
666
667 return t;
668
669 }
670
671 // **********************************************************
672 // **********************************************************
673 // **********************************************************
674 // *********************** Test *************************
675 // **********************************************************
676 // **********************************************************
677 // **********************************************************
678
679 private void log(Object o) {
680
681 System.err.println(o);
682
683 }
684
685 private void log2(Object o) {
686
687 System.out.println(o);
688
689 }
690
691}
Note: See TracBrowser for help on using the repository browser.