package geniusweb.bagga.dicehaggler; import java.io.IOException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Dictionary; import java.util.HashSet; import java.util.Hashtable; import java.util.List; import java.util.logging.Level; import javax.websocket.DeploymentException; import geniusweb.actions.Accept; import geniusweb.actions.Action; import geniusweb.actions.Comparison; import geniusweb.actions.ElicitComparison; import geniusweb.actions.Offer; import geniusweb.actions.PartyId; import geniusweb.bidspace.AllBidsList; import geniusweb.inform.ActionDone; import geniusweb.inform.Finished; import geniusweb.inform.Inform; import geniusweb.inform.Settings; import geniusweb.inform.YourTurn; import geniusweb.issuevalue.Bid; import geniusweb.issuevalue.Domain; import geniusweb.party.Capabilities; import geniusweb.party.DefaultParty; import geniusweb.profile.PartialOrdering; import geniusweb.profileconnection.ProfileConnectionFactory; import geniusweb.profileconnection.ProfileInterface; import geniusweb.progress.Progress; import geniusweb.progress.ProgressRounds; import tudelft.utilities.logging.Reporter; public class TheDiceHaggler extends DefaultParty { private long startTime; private long endTime; private Action lastReceivedAction; private Bid receivedBid; private Progress progress; private PartyId me; private ProfileInterface profileint; private AllBidsList allbids; private PartialOrdering partialprofile; private List givenPartialOrderedBids; private List opponentBidHistory = new ArrayList(); private double time; private DH_OpponentModel om; private Domain domain; private boolean elicitCounter = true; private double fixedUtility = 0.98; private double dynamicUtility = 1D; // would change over time private double reservationThresholdUtility = 0.85; private Dictionary utilSpace = new Hashtable(); private Dictionary opponentModel = new Hashtable(); private DH_UserModel userM; private DH_BiddingStrategy bs; private SimpleLinearOrdering estimatedProfile = null; public TheDiceHaggler() { super(); } public TheDiceHaggler(Reporter reporter) { super(reporter); } private void init(Settings info) throws IOException, DeploymentException { startTime = System.currentTimeMillis(); this.me = info.getID(); this.progress = info.getProgress(); endTime = progress.getTerminationTime().getTime(); this.profileint = ProfileConnectionFactory.create(info.getProfile().getURI(), getReporter()); this.partialprofile = (PartialOrdering) profileint.getProfile(); // patial profile also contains the reservation // bid allbids = new AllBidsList(this.partialprofile.getDomain()); // total number of possible bids.. all permutations // Wouter we use SimpleLinearOrdering (from shaop party) to get sorted // bids from our profile. this.domain = this.partialprofile.getDomain(); this.time = getTime(System.currentTimeMillis()); // System.out.println("time "+ time+ " in ms: "+System.currentTimeMillis()); System.out.println("############### Now Time is : " + time + " #############"); givenPartialOrderedBids = new SimpleLinearOrdering(this.partialprofile).getBids(); om = new DH_OpponentModel(this.domain); opponentModel = om.initializeOpponentModel(); userM = new DH_UserModel(this.domain, givenPartialOrderedBids); utilSpace = userM.estimateutilityspace(); bs = new DH_BiddingStrategy(); } @Override public void notifyChange(Inform info) { try { if (info instanceof Settings) { System.out.println("............. Initializing Settings ..........."); init((Settings) info); } else if (info instanceof ActionDone) { System.out.println("............. Some action has been done ..........."); lastReceivedAction = ((ActionDone) info).getAction(); if (lastReceivedAction instanceof Offer) { System.out.println("............. Opponent has sent an Offer ..........."); this.receivedBid = ((Offer) lastReceivedAction).getBid(); opponentBidHistory.add(this.receivedBid); opponentModel = om.updateOpponentModel(time, opponentBidHistory); } else if (lastReceivedAction instanceof Comparison) { System.out.println("............. COB party has done the comparison ..........."); estimatedProfile = estimatedProfile.with(((Comparison) lastReceivedAction).getBid(), ((Comparison) lastReceivedAction).getWorse()); // getWorse is a list of worst bids than the // given bid System.out.println(" ...... So, let's estimate the user space again ....."); userM = new DH_UserModel(domain, estimatedProfile.getBids()); utilSpace = userM.estimateutilityspace(); System.out.println(" ...... Now, we choose the action based on updated user model"); chooseAction(); } } else if (info instanceof YourTurn) { System.out.println(" ....... HEy! it's my turn to make an action...."); chooseAction(); } else if (info instanceof Finished) { getReporter().log(Level.INFO, "Final outcome:" + info); } } catch (Exception e) { throw new RuntimeException("Failed to handle info", e); } } private void chooseAction() throws IOException { this.time = getTime(System.currentTimeMillis()); Action action = null; if (estimatedProfile == null) { estimatedProfile = new SimpleLinearOrdering(profileint.getProfile()); } // Start competition if (receivedBid == null) { Bid offeredBid = determineOpeningBid(); System.out.println("At time " + time + " , I offer an opening bid with util: " + DH_UserModel.getUtility(offeredBid, utilSpace)); action = new Offer(me, offeredBid); } else { // if less than 5% of the total possible bids are given in the partial order and // the variance in pairwise correlations is too large, then do elicitation if (elicitCounter && givenPartialOrderedBids.size() < 0.05 * totalNumberOfPossibleBids() && userM.checkVariance()) { // decide which bids to compare with what..and then do the elicitation System.out.println("HEY LISTEN! at time " + time + "I am going to ask the user to compare these bids"); action = new ElicitComparison(me, getMyNextBid(time), givenPartialOrderedBids); elicitCounter = false; } else if (isAcceptable(receivedBid)) { System.out.println("At time " + time + " ,I accept the received bid with util: " + DH_UserModel.getUtility(receivedBid, utilSpace)); action = new Accept(me, receivedBid); } if (progress instanceof ProgressRounds) { progress = ((ProgressRounds) progress).advance(); } } if (action == null) { Bid offeredBid = bs.generateBid(time, domain, utilSpace, opponentModel, opponentBidHistory, allbids); System.out.println("At time " + time + " , I offer a bid with util: " + DH_UserModel.getUtility(offeredBid, utilSpace)); action = new Offer(me, offeredBid); } getConnection().send(action); } private double getTime(long currentTimeMillis) { // TODO Auto-generated method stub long duration = endTime - startTime; long delta = currentTimeMillis - startTime; Double ratio = delta / (double) duration; return ratio; } // // private List getListOfTwoMostVariedBids(List givenBids) { // // List list = new ArrayList<>(); // double sum = 0D; // for( Bid bid: givenBids) { // sum += DH_UserModel.getUtility(bid, utilSpace); // } // double mean = sum/givenBids.size(); // // double maxSum = 0D; // Bid topVariedBid = null; // Bid secondTopBid = null; // int index = 0; // int topIndex = 0; // for( Bid bid: givenBids) { // index++; // if(maxSum < Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2)) { // maxSum = Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2); // topVariedBid = bid; // topIndex = index; // } // } // givenBids.remove(topIndex); // for( Bid bid: givenBids) { // if(maxSum < Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2)) { // maxSum = Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2); // secondTopBid = bid; // } // } // list.add(topVariedBid); // list.add(secondTopBid); // return list; // } // // private boolean checkVariance(List givenBids) { // double sum = 0D; // for( Bid bid: givenBids) { // sum += DH_UserModel.getUtility(bid, utilSpace); // } // double mean = sum/givenBids.size(); // // double sum1 = 0D; // for( Bid bid: givenBids) { // sum1 += Math.pow(DH_UserModel.getUtility(bid, utilSpace) - mean, 2); // } // double variance = sum1/(givenBids.size()-1); // return (variance > 0.6); // } private Bid getMyNextBid(double time) { return bs.generateBid(time, domain, utilSpace, opponentModel, opponentBidHistory, allbids); } private boolean isAcceptable(Bid receivedBid) { this.time = getTime(System.currentTimeMillis()); DH_TargetUtility t_u = new DH_TargetUtility(domain, time, opponentBidHistory, opponentModel, allbids.size().intValue()); // time = progress.get(System.currentTimeMillis()); if (time >= 0.7) { System.out.println("time is greater than 0.7, let's calculate the dynamic threshold"); try { dynamicUtility = t_u.calculateTargetValue(); System.out.println("at time t = " + time + "the dynamic threshold utility is: " + dynamicUtility); if (dynamicUtility < reservationThresholdUtility) dynamicUtility = reservationThresholdUtility; } catch (Exception e) { e.printStackTrace(); } } double myFutureBidUtility = DH_UserModel.getUtility(getMyNextBid(time), utilSpace); double lastReceivedBidUtility = DH_UserModel.getUtility(getMyNextBid(time), utilSpace); boolean accept; if ((time < 0.4 && lastReceivedBidUtility >= fixedUtility) || (time >= 0.4 && time < 0.5 & lastReceivedBidUtility >= DH_UserModel.getUtility(getOpponentBestBidDetails(), utilSpace)) // why dynamic threshold is not considered here.. because my future bid utility // will always be higher than that my threshold value || (time >= 0.5 && time < 0.6 & lastReceivedBidUtility >= myFutureBidUtility & lastReceivedBidUtility > bestOfQquantileOpponentBids(0.9)) // best out of the bottom 90% of the received bids in the ordered utility from // high to less || (time >= 0.6 && time < 0.7 && lastReceivedBidUtility >= myFutureBidUtility && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.8)) // best out of the bottom 80% of the received bids || (time >= 0.7 && time < 0.8 && lastReceivedBidUtility >= dynamicUtility && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.7)) // best out of the bottom 70% of the bids || (time >= 0.8 && time < 0.9 && lastReceivedBidUtility >= dynamicUtility && lastReceivedBidUtility > bestOfQquantileOpponentBids(0.6)) // best out of the bottom 60% of the bids || (time >= 0.9 && lastReceivedBidUtility >= dynamicUtility)) { accept = true; } else { System.out .println("At time " + time + " , I am going to reject the received offer and propose a new offer"); accept = false; } return accept; } private double bestOfQquantileOpponentBids(double q) { List sortedOpponentHistory = getSortedHistory(opponentBidHistory); // in an increasing order double util = 0D; // int k = (int) (Math.ceil((1-q) * sortedOpponentHistory.size()) - 1); //if the // list is in a decreasing order int k = (int) (Math.ceil((q) * sortedOpponentHistory.size()) - 1); // if the list is in an increasing order util = DH_UserModel.getUtility(sortedOpponentHistory.get(k), utilSpace); System.out .println("Q = " + q + " size = " + sortedOpponentHistory.size() + " index = " + k + " util = " + util); return util; } private List getSortedHistory(List opponentBidHistory2) { System.out.println("I am going to get the sorted opponent history"); List sortedOpponentHistory = new ArrayList(); // in an ascending order Collections.sort(sortedOpponentHistory, new Comparator() { @Override public int compare(Bid b1, Bid b2) { if (b1 == null || b2 == null) throw new NullPointerException(); if (b1.equals(b2)) return 0; if (DH_UserModel.getUtility(b1, utilSpace) > DH_UserModel.getUtility(b2, utilSpace)) return -1; else if (DH_UserModel.getUtility(b1, utilSpace) < DH_UserModel.getUtility(b2, utilSpace)) return 1; else return ((Integer) b1.hashCode()).compareTo(b2.hashCode()); } }); for (Bid l : sortedOpponentHistory) { System.out.println(DH_UserModel.getUtility(l, utilSpace)); } return sortedOpponentHistory; } private Bid getOpponentBestBidDetails() { double max = Double.NEGATIVE_INFINITY; Bid bestBid = null; for (Bid b : opponentBidHistory) { double utility = DH_UserModel.getUtility(b, utilSpace); if (utility >= max) { max = utility; bestBid = b; } } return bestBid; } private Bid determineOpeningBid() { // maximum bid in the given user domain return givenPartialOrderedBids.get(givenPartialOrderedBids.size() - 1); } @Override public Capabilities getCapabilities() { return new Capabilities(new HashSet<>(Arrays.asList("SHAOP")), Collections.singleton(PartialOrdering.class)); } @Override public String getDescription() { return "The Dice Haggler 2020"; } private int totalNumberOfPossibleBids() { int num = 1; for (String i : domain.getIssues()) { num *= domain.getValues(i).size().intValue(); } // System.out.println("I count total bids = " + num + " and real value is: "+ // allbids.size()); return num; } }