[1] | 1 | package geniusweb.bagga.dicehaggler;
|
---|
| 2 |
|
---|
| 3 | import java.io.IOException;
|
---|
| 4 | import java.util.ArrayList;
|
---|
| 5 | import java.util.Arrays;
|
---|
| 6 | import java.util.Collections;
|
---|
| 7 | import java.util.Comparator;
|
---|
| 8 | import java.util.Dictionary;
|
---|
| 9 | import java.util.HashSet;
|
---|
| 10 | import java.util.Hashtable;
|
---|
| 11 | import java.util.List;
|
---|
| 12 | import java.util.logging.Level;
|
---|
| 13 |
|
---|
| 14 | import javax.websocket.DeploymentException;
|
---|
| 15 |
|
---|
| 16 | import geniusweb.actions.Accept;
|
---|
| 17 | import geniusweb.actions.Action;
|
---|
| 18 | import geniusweb.actions.Comparison;
|
---|
| 19 | import geniusweb.actions.ElicitComparison;
|
---|
| 20 | import geniusweb.actions.Offer;
|
---|
| 21 | import geniusweb.actions.PartyId;
|
---|
| 22 | import geniusweb.bidspace.AllBidsList;
|
---|
[43] | 23 | import geniusweb.inform.ActionDone;
|
---|
| 24 | import geniusweb.inform.Finished;
|
---|
| 25 | import geniusweb.inform.Inform;
|
---|
| 26 | import geniusweb.inform.Settings;
|
---|
| 27 | import geniusweb.inform.YourTurn;
|
---|
[1] | 28 | import geniusweb.issuevalue.Bid;
|
---|
| 29 | import geniusweb.issuevalue.Domain;
|
---|
| 30 | import geniusweb.party.Capabilities;
|
---|
| 31 | import geniusweb.party.DefaultParty;
|
---|
| 32 | import geniusweb.profile.PartialOrdering;
|
---|
| 33 | import geniusweb.profileconnection.ProfileConnectionFactory;
|
---|
| 34 | import geniusweb.profileconnection.ProfileInterface;
|
---|
| 35 | import geniusweb.progress.Progress;
|
---|
| 36 | import geniusweb.progress.ProgressRounds;
|
---|
| 37 | import tudelft.utilities.logging.Reporter;
|
---|
| 38 |
|
---|
| 39 | public class TheDiceHaggler extends DefaultParty {
|
---|
| 40 |
|
---|
| 41 | private long startTime;
|
---|
| 42 | private long endTime;
|
---|
| 43 | private Action lastReceivedAction;
|
---|
| 44 | private Bid receivedBid;
|
---|
| 45 | private Progress progress;
|
---|
| 46 | private PartyId me;
|
---|
| 47 | private ProfileInterface profileint;
|
---|
| 48 | private AllBidsList allbids;
|
---|
| 49 | private PartialOrdering partialprofile;
|
---|
| 50 | private List<Bid> givenPartialOrderedBids;
|
---|
| 51 | private List<Bid> opponentBidHistory = new ArrayList<Bid>();
|
---|
| 52 | private double time;
|
---|
| 53 | private DH_OpponentModel om;
|
---|
| 54 |
|
---|
| 55 | private Domain domain;
|
---|
| 56 |
|
---|
| 57 | private boolean elicitCounter = true;
|
---|
| 58 | private double fixedUtility = 0.98;
|
---|
[43] | 59 | private double dynamicUtility = 1D; // would change over time
|
---|
[1] | 60 | private double reservationThresholdUtility = 0.85;
|
---|
| 61 |
|
---|
| 62 | private Dictionary<String, DH_Issue> utilSpace = new Hashtable<String, DH_Issue>();
|
---|
| 63 | private Dictionary<String, DH_Issue> opponentModel = new Hashtable<String, DH_Issue>();
|
---|
| 64 | private DH_UserModel userM;
|
---|
| 65 | private DH_BiddingStrategy bs;
|
---|
[43] | 66 | private SimpleLinearOrdering estimatedProfile = null;
|
---|
[1] | 67 |
|
---|
| 68 | public TheDiceHaggler() {
|
---|
| 69 | super();
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | public TheDiceHaggler(Reporter reporter) {
|
---|
| 73 | super(reporter);
|
---|
| 74 | }
|
---|
| 75 |
|
---|
| 76 | private void init(Settings info) throws IOException, DeploymentException {
|
---|
| 77 | startTime = System.currentTimeMillis();
|
---|
| 78 | this.me = info.getID();
|
---|
| 79 | this.progress = info.getProgress();
|
---|
| 80 | endTime = progress.getTerminationTime().getTime();
|
---|
[43] | 81 | this.profileint = ProfileConnectionFactory.create(info.getProfile().getURI(), getReporter());
|
---|
| 82 | this.partialprofile = (PartialOrdering) profileint.getProfile(); // patial profile also contains the reservation
|
---|
| 83 | // bid
|
---|
[1] | 84 |
|
---|
[43] | 85 | allbids = new AllBidsList(this.partialprofile.getDomain()); // total number of possible bids.. all permutations
|
---|
[1] | 86 | // Wouter we use SimpleLinearOrdering (from shaop party) to get sorted
|
---|
| 87 | // bids from our profile.
|
---|
| 88 | this.domain = this.partialprofile.getDomain();
|
---|
| 89 | this.time = getTime(System.currentTimeMillis());
|
---|
[43] | 90 | // System.out.println("time "+ time+ " in ms: "+System.currentTimeMillis());
|
---|
| 91 | System.out.println("############### Now Time is : " + time + " #############");
|
---|
[1] | 92 | givenPartialOrderedBids = new SimpleLinearOrdering(this.partialprofile).getBids();
|
---|
| 93 |
|
---|
| 94 | om = new DH_OpponentModel(this.domain);
|
---|
| 95 | opponentModel = om.initializeOpponentModel();
|
---|
| 96 |
|
---|
| 97 | userM = new DH_UserModel(this.domain, givenPartialOrderedBids);
|
---|
| 98 | utilSpace = userM.estimateutilityspace();
|
---|
| 99 |
|
---|
| 100 | bs = new DH_BiddingStrategy();
|
---|
| 101 | }
|
---|
| 102 |
|
---|
| 103 | @Override
|
---|
| 104 | public void notifyChange(Inform info) {
|
---|
| 105 | try {
|
---|
| 106 | if (info instanceof Settings) {
|
---|
| 107 | System.out.println("............. Initializing Settings ...........");
|
---|
| 108 | init((Settings) info);
|
---|
| 109 | } else if (info instanceof ActionDone) {
|
---|
| 110 | System.out.println("............. Some action has been done ...........");
|
---|
| 111 |
|
---|
| 112 | lastReceivedAction = ((ActionDone) info).getAction();
|
---|
| 113 | if (lastReceivedAction instanceof Offer) {
|
---|
| 114 | System.out.println("............. Opponent has sent an Offer ...........");
|
---|
| 115 | this.receivedBid = ((Offer) lastReceivedAction).getBid();
|
---|
| 116 |
|
---|
| 117 | opponentBidHistory.add(this.receivedBid);
|
---|
| 118 | opponentModel = om.updateOpponentModel(time, opponentBidHistory);
|
---|
[43] | 119 | } else if (lastReceivedAction instanceof Comparison) {
|
---|
[1] | 120 | System.out.println("............. COB party has done the comparison ...........");
|
---|
| 121 |
|
---|
[43] | 122 | estimatedProfile = estimatedProfile.with(((Comparison) lastReceivedAction).getBid(),
|
---|
| 123 | ((Comparison) lastReceivedAction).getWorse()); // getWorse is a list of worst bids than the
|
---|
| 124 | // given bid
|
---|
[1] | 125 |
|
---|
| 126 | System.out.println(" ...... So, let's estimate the user space again .....");
|
---|
| 127 | userM = new DH_UserModel(domain, estimatedProfile.getBids());
|
---|
| 128 | utilSpace = userM.estimateutilityspace();
|
---|
| 129 |
|
---|
| 130 | System.out.println(" ...... Now, we choose the action based on updated user model");
|
---|
| 131 | chooseAction();
|
---|
| 132 | }
|
---|
| 133 | } else if (info instanceof YourTurn) {
|
---|
| 134 | System.out.println(" ....... HEy! it's my turn to make an action....");
|
---|
| 135 | chooseAction();
|
---|
| 136 |
|
---|
| 137 | } else if (info instanceof Finished) {
|
---|
| 138 | getReporter().log(Level.INFO, "Final outcome:" + info);
|
---|
| 139 | }
|
---|
| 140 | } catch (Exception e) {
|
---|
| 141 | throw new RuntimeException("Failed to handle info", e);
|
---|
| 142 | }
|
---|
| 143 | }
|
---|
| 144 |
|
---|
| 145 | private void chooseAction() throws IOException {
|
---|
| 146 | this.time = getTime(System.currentTimeMillis());
|
---|
| 147 | Action action = null;
|
---|
[43] | 148 |
|
---|
[1] | 149 | if (estimatedProfile == null) {
|
---|
[43] | 150 | estimatedProfile = new SimpleLinearOrdering(profileint.getProfile());
|
---|
[1] | 151 | }
|
---|
[43] | 152 |
|
---|
[1] | 153 | // Start competition
|
---|
[43] | 154 |
|
---|
[1] | 155 | if (receivedBid == null) {
|
---|
| 156 | Bid offeredBid = determineOpeningBid();
|
---|
[43] | 157 | System.out.println("At time " + time + " , I offer an opening bid with util: "
|
---|
| 158 | + DH_UserModel.getUtility(offeredBid, utilSpace));
|
---|
[1] | 159 | action = new Offer(me, offeredBid);
|
---|
[43] | 160 | } else {
|
---|
| 161 | // if less than 5% of the total possible bids are given in the partial order and
|
---|
| 162 | // the variance in pairwise correlations is too large, then do elicitation
|
---|
| 163 | if (elicitCounter && givenPartialOrderedBids.size() < 0.05 * totalNumberOfPossibleBids()
|
---|
| 164 | && userM.checkVariance()) {
|
---|
| 165 | // decide which bids to compare with what..and then do the elicitation
|
---|
| 166 | System.out.println("HEY LISTEN! at time " + time + "I am going to ask the user to compare these bids");
|
---|
[1] | 167 | action = new ElicitComparison(me, getMyNextBid(time), givenPartialOrderedBids);
|
---|
| 168 | elicitCounter = false;
|
---|
[43] | 169 | } else if (isAcceptable(receivedBid)) {
|
---|
| 170 | System.out.println("At time " + time + " ,I accept the received bid with util: "
|
---|
| 171 | + DH_UserModel.getUtility(receivedBid, utilSpace));
|
---|
[1] | 172 | action = new Accept(me, receivedBid);
|
---|
| 173 | }
|
---|
| 174 | if (progress instanceof ProgressRounds) {
|
---|
| 175 | progress = ((ProgressRounds) progress).advance();
|
---|
| 176 | }
|
---|
| 177 | }
|
---|
| 178 | if (action == null) {
|
---|
| 179 | Bid offeredBid = bs.generateBid(time, domain, utilSpace, opponentModel, opponentBidHistory, allbids);
|
---|
[43] | 180 | System.out.println("At time " + time + " , I offer a bid with util: "
|
---|
| 181 | + DH_UserModel.getUtility(offeredBid, utilSpace));
|
---|
| 182 | action = new Offer(me, offeredBid);
|
---|
[1] | 183 | }
|
---|
| 184 | getConnection().send(action);
|
---|
| 185 |
|
---|
| 186 | }
|
---|
| 187 |
|
---|
[43] | 188 | private double getTime(long currentTimeMillis) {
|
---|
[1] | 189 | // TODO Auto-generated method stub
|
---|
| 190 | long duration = endTime - startTime;
|
---|
| 191 | long delta = currentTimeMillis - startTime;
|
---|
| 192 | Double ratio = delta / (double) duration;
|
---|
| 193 | return ratio;
|
---|
| 194 | }
|
---|
| 195 |
|
---|
| 196 | //
|
---|
| 197 | // private List<Bid> getListOfTwoMostVariedBids(List<Bid> givenBids) {
|
---|
| 198 | //
|
---|
| 199 | // List<Bid> list = new ArrayList<>();
|
---|
| 200 | // double sum = 0D;
|
---|
| 201 | // for( Bid bid: givenBids) {
|
---|
| 202 | // sum += DH_UserModel.getUtility(bid, utilSpace);
|
---|
| 203 | // }
|
---|
| 204 | // double mean = sum/givenBids.size();
|
---|
| 205 | //
|
---|
| 206 | // double maxSum = 0D;
|
---|
| 207 | // Bid topVariedBid = null;
|
---|
| 208 | // Bid secondTopBid = null;
|
---|
| 209 | // int index = 0;
|
---|
| 210 | // int topIndex = 0;
|
---|
| 211 | // for( Bid bid: givenBids) {
|
---|
| 212 | // index++;
|
---|
| 213 | // if(maxSum < Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2)) {
|
---|
| 214 | // maxSum = Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2);
|
---|
| 215 | // topVariedBid = bid;
|
---|
| 216 | // topIndex = index;
|
---|
| 217 | // }
|
---|
| 218 | // }
|
---|
| 219 | // givenBids.remove(topIndex);
|
---|
| 220 | // for( Bid bid: givenBids) {
|
---|
| 221 | // if(maxSum < Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2)) {
|
---|
| 222 | // maxSum = Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2);
|
---|
| 223 | // secondTopBid = bid;
|
---|
| 224 | // }
|
---|
| 225 | // }
|
---|
| 226 | // list.add(topVariedBid);
|
---|
| 227 | // list.add(secondTopBid);
|
---|
| 228 | // return list;
|
---|
| 229 | // }
|
---|
| 230 | //
|
---|
| 231 | // private boolean checkVariance(List<Bid> givenBids) {
|
---|
| 232 | // double sum = 0D;
|
---|
| 233 | // for( Bid bid: givenBids) {
|
---|
| 234 | // sum += DH_UserModel.getUtility(bid, utilSpace);
|
---|
| 235 | // }
|
---|
| 236 | // double mean = sum/givenBids.size();
|
---|
| 237 | //
|
---|
| 238 | // double sum1 = 0D;
|
---|
| 239 | // for( Bid bid: givenBids) {
|
---|
| 240 | // sum1 += Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2);
|
---|
| 241 | // }
|
---|
| 242 | // double variance = sum1/(givenBids.size()-1);
|
---|
| 243 | // return (variance > 0.6);
|
---|
| 244 | // }
|
---|
| 245 |
|
---|
| 246 | private Bid getMyNextBid(double time) {
|
---|
| 247 | return bs.generateBid(time, domain, utilSpace, opponentModel, opponentBidHistory, allbids);
|
---|
| 248 | }
|
---|
| 249 |
|
---|
| 250 | private boolean isAcceptable(Bid receivedBid) {
|
---|
| 251 | this.time = getTime(System.currentTimeMillis());
|
---|
| 252 |
|
---|
[43] | 253 | DH_TargetUtility t_u = new DH_TargetUtility(domain, time, opponentBidHistory, opponentModel,
|
---|
| 254 | allbids.size().intValue());
|
---|
[1] | 255 |
|
---|
[43] | 256 | // time = progress.get(System.currentTimeMillis());
|
---|
| 257 | if (time >= 0.7) {
|
---|
[1] | 258 | System.out.println("time is greater than 0.7, let's calculate the dynamic threshold");
|
---|
| 259 | try {
|
---|
| 260 | dynamicUtility = t_u.calculateTargetValue();
|
---|
[43] | 261 | System.out.println("at time t = " + time + "the dynamic threshold utility is: " + dynamicUtility);
|
---|
| 262 | if (dynamicUtility < reservationThresholdUtility)
|
---|
| 263 | dynamicUtility = reservationThresholdUtility;
|
---|
| 264 | } catch (Exception e) {
|
---|
[1] | 265 | e.printStackTrace();
|
---|
| 266 | }
|
---|
| 267 | }
|
---|
| 268 | double myFutureBidUtility = DH_UserModel.getUtility(getMyNextBid(time), utilSpace);
|
---|
| 269 | double lastReceivedBidUtility = DH_UserModel.getUtility(getMyNextBid(time), utilSpace);
|
---|
| 270 |
|
---|
| 271 | boolean accept;
|
---|
[43] | 272 | if ((time < 0.4 && lastReceivedBidUtility >= fixedUtility) || (time >= 0.4 && time < 0.5
|
---|
| 273 | & lastReceivedBidUtility >= DH_UserModel.getUtility(getOpponentBestBidDetails(), utilSpace))
|
---|
| 274 | // why dynamic threshold is not considered here.. because my future bid utility
|
---|
| 275 | // will always be higher than that my threshold value
|
---|
| 276 | || (time >= 0.5 && time < 0.6 & lastReceivedBidUtility >= myFutureBidUtility
|
---|
| 277 | & lastReceivedBidUtility > bestOfQquantileOpponentBids(0.9))
|
---|
| 278 | // best out of the bottom 90% of the received bids in the ordered utility from
|
---|
| 279 | // high to less
|
---|
| 280 | || (time >= 0.6 && time < 0.7 && lastReceivedBidUtility >= myFutureBidUtility
|
---|
| 281 | && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.8))
|
---|
| 282 | // best out of the bottom 80% of the received bids
|
---|
| 283 | || (time >= 0.7 && time < 0.8 && lastReceivedBidUtility >= dynamicUtility
|
---|
| 284 | && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.7))
|
---|
| 285 | // best out of the bottom 70% of the bids
|
---|
| 286 | || (time >= 0.8 && time < 0.9 && lastReceivedBidUtility >= dynamicUtility
|
---|
| 287 | && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.6))
|
---|
| 288 | // best out of the bottom 60% of the bids
|
---|
| 289 | || (time >= 0.9 && lastReceivedBidUtility >= dynamicUtility)) {
|
---|
[1] | 290 | accept = true;
|
---|
[43] | 291 | } else {
|
---|
| 292 | System.out
|
---|
| 293 | .println("At time " + time + " , I am going to reject the received offer and propose a new offer");
|
---|
[1] | 294 | accept = false;
|
---|
| 295 | }
|
---|
| 296 |
|
---|
| 297 | return accept;
|
---|
| 298 | }
|
---|
| 299 |
|
---|
| 300 | private double bestOfQquantileOpponentBids(double q) {
|
---|
[43] | 301 | List<Bid> sortedOpponentHistory = getSortedHistory(opponentBidHistory); // in an increasing order
|
---|
[1] | 302 | double util = 0D;
|
---|
[43] | 303 | // int k = (int) (Math.ceil((1-q) * sortedOpponentHistory.size()) - 1); //if the
|
---|
| 304 | // list is in a decreasing order
|
---|
| 305 | int k = (int) (Math.ceil((q) * sortedOpponentHistory.size()) - 1); // if the list is in an increasing order
|
---|
[1] | 306 |
|
---|
[43] | 307 | util = DH_UserModel.getUtility(sortedOpponentHistory.get(k), utilSpace);
|
---|
| 308 | System.out
|
---|
| 309 | .println("Q = " + q + " size = " + sortedOpponentHistory.size() + " index = " + k + " util = " + util);
|
---|
[1] | 310 | return util;
|
---|
| 311 | }
|
---|
| 312 |
|
---|
| 313 | private List<Bid> getSortedHistory(List<Bid> opponentBidHistory2) {
|
---|
| 314 | System.out.println("I am going to get the sorted opponent history");
|
---|
[43] | 315 | List<Bid> sortedOpponentHistory = new ArrayList<Bid>(); // in an ascending order
|
---|
[1] | 316 | Collections.sort(sortedOpponentHistory, new Comparator<Bid>() {
|
---|
| 317 | @Override
|
---|
[43] | 318 | public int compare(Bid b1, Bid b2) {
|
---|
[1] | 319 | if (b1 == null || b2 == null)
|
---|
| 320 | throw new NullPointerException();
|
---|
| 321 | if (b1.equals(b2))
|
---|
| 322 | return 0;
|
---|
| 323 | if (DH_UserModel.getUtility(b1, utilSpace) > DH_UserModel.getUtility(b2, utilSpace))
|
---|
| 324 | return -1;
|
---|
| 325 | else if (DH_UserModel.getUtility(b1, utilSpace) < DH_UserModel.getUtility(b2, utilSpace))
|
---|
| 326 | return 1;
|
---|
| 327 | else
|
---|
| 328 | return ((Integer) b1.hashCode()).compareTo(b2.hashCode());
|
---|
| 329 | }
|
---|
| 330 | });
|
---|
[43] | 331 | for (Bid l : sortedOpponentHistory) {
|
---|
[1] | 332 | System.out.println(DH_UserModel.getUtility(l, utilSpace));
|
---|
| 333 | }
|
---|
| 334 | return sortedOpponentHistory;
|
---|
| 335 | }
|
---|
| 336 |
|
---|
| 337 | private Bid getOpponentBestBidDetails() {
|
---|
| 338 | double max = Double.NEGATIVE_INFINITY;
|
---|
| 339 | Bid bestBid = null;
|
---|
| 340 | for (Bid b : opponentBidHistory) {
|
---|
| 341 | double utility = DH_UserModel.getUtility(b, utilSpace);
|
---|
| 342 | if (utility >= max) {
|
---|
| 343 | max = utility;
|
---|
| 344 | bestBid = b;
|
---|
| 345 | }
|
---|
| 346 | }
|
---|
| 347 | return bestBid;
|
---|
| 348 | }
|
---|
| 349 |
|
---|
| 350 | private Bid determineOpeningBid() {
|
---|
[43] | 351 | // maximum bid in the given user domain
|
---|
| 352 | return givenPartialOrderedBids.get(givenPartialOrderedBids.size() - 1);
|
---|
[1] | 353 | }
|
---|
| 354 |
|
---|
| 355 | @Override
|
---|
| 356 | public Capabilities getCapabilities() {
|
---|
[70] | 357 | return new Capabilities(new HashSet<>(Arrays.asList("SHAOP")), Collections.singleton(PartialOrdering.class));
|
---|
[1] | 358 | }
|
---|
| 359 |
|
---|
| 360 | @Override
|
---|
| 361 | public String getDescription() {
|
---|
| 362 | return "The Dice Haggler 2020";
|
---|
| 363 | }
|
---|
| 364 |
|
---|
| 365 | private int totalNumberOfPossibleBids() {
|
---|
| 366 | int num = 1;
|
---|
[43] | 367 | for (String i : domain.getIssues()) {
|
---|
[1] | 368 | num *= domain.getValues(i).size().intValue();
|
---|
| 369 | }
|
---|
[43] | 370 | // System.out.println("I count total bids = " + num + " and real value is: "+
|
---|
| 371 | // allbids.size());
|
---|
[1] | 372 | return num;
|
---|
| 373 |
|
---|
| 374 | }
|
---|
| 375 | }
|
---|