package agents; import java.util.ArrayList; import agents.bayesianopponentmodel.BayesianOpponentModel; import agents.bayesianopponentmodel.OpponentModel; import agents.bayesianopponentmodel.OpponentModelUtilSpace; import genius.core.Agent; import genius.core.AgentParam; import genius.core.Bid; import genius.core.BidIterator; import genius.core.actions.Accept; import genius.core.actions.Action; import genius.core.actions.EndNegotiation; import genius.core.actions.Offer; import genius.core.analysis.BidPoint; import genius.core.analysis.BidSpace; import genius.core.tournament.VariablesAndValues.AgentParameterVariable; import genius.core.utility.AdditiveUtilitySpace; /** * Wrapper for opponentmodelspace, so that it is a neat utilityspace that we can * give to the bidspace. * * @author wouter * */ public class BayesianAgentForAuction extends Agent { protected Action messageOpponent; protected Bid myLastBid = null; protected Action myLastAction = null; protected Bid fOpponentPreviousBid = null; protected enum ROLE { CENTER, PROVIDER, IRRELEVANT }; public enum PHASE { FIRST_PHASE, SECOND_PHASE }; protected enum ACTIONTYPE { START, OFFER, ACCEPT, BREAKOFF }; private enum STRATEGY { SMART, SERIAL, RESPONSIVE, RANDOM, TIT_FOR_TAT, AUCTION }; private STRATEGY fStrategy = STRATEGY.AUCTION; private boolean fMarketPreassure = false; protected int fSmartSteps; protected OpponentModel fOpponentModel; protected OpponentModel[] fOpponentModels = null; protected double CONCESSIONFACTOR = 0.04; private static final double ALLOWED_UTILITY_DEVIATION = 0.01; protected static final int NUMBER_OF_SMART_STEPS = 0; protected ArrayList myPreviousBids; private boolean fDebug = false; protected PHASE fPhase = null; protected ROLE fRole; // Class constructor public BayesianAgentForAuction() { super(); } @Override public String getVersion() { return "2.0"; } /** Dummy variables, for testing only. W.Pasman 19aug08 */ public static ArrayList getParameters() { ArrayList parameters = new ArrayList(); parameters.add(new AgentParam(BayesianAgentForAuction.class.getName(), "reservation", 0., 1.)); parameters.add(new AgentParam(BayesianAgentForAuction.class.getName(), "starting_utility", 0., 1.)); parameters.add(new AgentParam(BayesianAgentForAuction.class.getName(), "role", -1., 3.)); parameters.add(new AgentParam(BayesianAgentForAuction.class.getName(), "phase", -1., 1.)); parameters.add(new AgentParam(BayesianAgentForAuction.class.getName(), "opponent", -1., 1.)); return parameters; } public void init() { messageOpponent = null; myLastAction = null; fSmartSteps = 0; myPreviousBids = new ArrayList(); fOpponentPreviousBid = null; if ((getParameterValues().isEmpty()) || (getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "phase", new Double(-1.), new Double(1.)))) .getValue() < 0)) fPhase = PHASE.FIRST_PHASE; else fPhase = PHASE.SECOND_PHASE; if (getParameterValues().isEmpty()) fRole = ROLE.IRRELEVANT; else if ((getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "role", -1., 3.))).getValue() < 0)) fRole = ROLE.PROVIDER; else if (getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "role", -1., 3.))).getValue() < 2) { fRole = ROLE.CENTER; CONCESSIONFACTOR = 0.06; } else fRole = ROLE.IRRELEVANT; if ((fPhase == PHASE.FIRST_PHASE) && (fOpponentModels == null)) prepareOpponentModel(); if (fRole == ROLE.CENTER) { int index = Double.valueOf( getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "opponent", -1., 1.))).getValue()) .intValue(); fOpponentModel = fOpponentModels[index]; } } protected void prepareOpponentModel() { fOpponentModels = new BayesianOpponentModel[2]; fOpponentModels[0] = new BayesianOpponentModel( (AdditiveUtilitySpace) utilitySpace); fOpponentModels[1] = new BayesianOpponentModel( (AdditiveUtilitySpace) utilitySpace); fOpponentModel = fOpponentModels[0]; } // Class methods public void ReceiveMessage(Action opponentAction) { messageOpponent = opponentAction; } protected Action proposeInitialBid() throws Exception { Bid lBid = null; switch (fRole) { case CENTER: switch (fPhase) { case FIRST_PHASE: lBid = getMaxUtilityBid(); break; case SECOND_PHASE: double lSecondBest = getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "reservation", 0., 1.))).getValue(); lBid = getTradeOff(lSecondBest); break; } break; case PROVIDER: switch (fPhase) { case FIRST_PHASE: double lReservationValue = utilitySpace.getReservationValue();// parametervalues.get("reservation"); lBid = getTradeOff(lReservationValue); break; case SECOND_PHASE: lBid = getMaxUtilityBid(); break; } break; case IRRELEVANT: switch (fPhase) { case FIRST_PHASE: // if(fRole=ROLE.) lBid = getMaxUtilityBid(); break; case SECOND_PHASE: double lSecondBest = getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "starting_utility", 0., 1.))).getValue(); lBid = getTradeOff(lSecondBest); break; } break; } // Return (one of the) possible bid(s) with maximal utility. fSmartSteps = NUMBER_OF_SMART_STEPS; myLastBid = lBid; return new Offer(getAgentID(), lBid); } /** * * @param pOppntBid * @return a counterbid that has max util for us and an opponent utility * that is equal to 1-estimated utility of opponent's last bid. Or, * if that bid was done already before, another bid that has same * utility in our space as that counterbid. * @throws Exception */ protected Bid getNextBidAuction(Bid pOppntBid) throws Exception { if (pOppntBid == null) throw new NullPointerException("pOpptBid=null"); if (myLastBid == null) throw new Exception("myLastBid==null"); log("Get next bid ..."); Bid lBid = null; switch (fRole) { case CENTER: switch (fPhase) { case FIRST_PHASE: lBid = getNextBidSmart(pOppntBid); break; case SECOND_PHASE: double lSecondBest = getParameterValues().get( new AgentParameterVariable(new AgentParam( BayesianAgentForAuction.class.getName(), "reservation", 0., 1.))).getValue(); lBid = getTradeOff(lSecondBest); break; } break; case PROVIDER: switch (fPhase) { case FIRST_PHASE: double lReservationValue = utilitySpace.getReservationValue();// parametervalues.get("reservation"); lBid = getTradeOff(lReservationValue); break; case SECOND_PHASE: lBid = getNextBidSmart(pOppntBid); break; } break; case IRRELEVANT: switch (fPhase) { case FIRST_PHASE: lBid = getNextBidSmart(pOppntBid); break; case SECOND_PHASE: lBid = getNextBidSmart(pOppntBid); break; } break; } return lBid; } /** * * @param pOppntBid * @return a counterbid that has max util for us and an opponent utility * that is equal to 1-estimated utility of opponent's last bid. Or, * if that bid was done already before, another bid that has same * utility in our space as that counterbid. * @throws Exception */ private Bid getNextBid(Bid pOppntBid) throws Exception { if (pOppntBid == null) throw new NullPointerException("pOpptBid=null"); if (myLastBid == null) throw new Exception("myLastBid==null"); log("Get next bid ..."); BidSpace bs = new BidSpace((AdditiveUtilitySpace) utilitySpace, new OpponentModelUtilSpace(fOpponentModel), true, true); // System.out.println("Bidspace:\n"+bs); // compute opponent's concession double opponentConcession = 0.; if (fOpponentPreviousBid == null) opponentConcession = 0; else { double opponentUtil = fOpponentModel .getNormalizedUtility(pOppntBid); double opponentFirstBidUtil = fOpponentModel .getNormalizedUtility(fOpponentModel.fBiddingHistory.get(0)); opponentConcession = opponentUtil - opponentFirstBidUtil; } log("opponent Concession:" + opponentConcession); // determine our bid point double OurFirstBidOppUtil = fOpponentModel .getNormalizedUtility(myPreviousBids.get(0)); double OurTargetBidOppUtil = OurFirstBidOppUtil - opponentConcession; if (OurTargetBidOppUtil > 1) OurTargetBidOppUtil = 1.; if (OurTargetBidOppUtil < OurFirstBidOppUtil) OurTargetBidOppUtil = OurFirstBidOppUtil; log("our target opponent utility=" + OurTargetBidOppUtil); // find the target on the pareto curve double targetUtil = bs.ourUtilityOnPareto(OurTargetBidOppUtil); BidPoint bp = bs.getNearestBidPoint(targetUtil, OurTargetBidOppUtil, .5, 1, myPreviousBids); log("found bid " + bp); return bp.getBid(); } /** * get a new bid (not done before) that has ourUtility for us. * * @param ourUtility * @return the bid with max opponent utility that is close to ourUtility. or * null if there is no such bid. */ Bid getNewBidWithUtil(double ourUtility, BidSpace bs) { BidPoint bestbid = null; double bestbidutil = 0; for (BidPoint p : bs.bidPoints) { if (Math.abs(ourUtility - p.getUtilityA()) < ALLOWED_UTILITY_DEVIATION && p.getUtilityB() > bestbidutil && !myPreviousBids.contains(p.getBid())) { bestbid = p; bestbidutil = p.getUtilityB(); } } if (bestbid == null) return null; return bestbid.getBid(); } /** * Wouter: Try to find a bid that has same utility for ourself but max * utility for opponent. * * @author Dmytro * @param pBid * @return * @throws Exception */ protected Bid getSmartBid(Bid pBid) throws Exception { Bid lBid = null; double lExpectedUtility = -1; double lUtility = utilitySpace.getUtility(pBid); BidIterator lIter = new BidIterator(utilitySpace.getDomain()); // int i=1; while (lIter.hasNext()) { Bid tmpBid = lIter.next(); // System.out.println(tmpBid); // System.out.println(String.valueOf(i++)); if (Math.abs(utilitySpace.getUtility(tmpBid) - lUtility) < ALLOWED_UTILITY_DEVIATION) { // double lTmpSim = fSimilarity.getSimilarity(tmpBid, // pOppntBid); double lTmpExpecteUtility = fOpponentModel .getNormalizedUtility(tmpBid); if (lTmpExpecteUtility > lExpectedUtility) { lExpectedUtility = lTmpExpecteUtility; lBid = tmpBid; } } } return lBid; // check if really found a better bid. if not return null /* * if(fOpponentModel.getNormalizedUtility(lBid)>(fOpponentModel. * getNormalizedUtility(pBid)+0.04)) return lBid; else return null; */ } protected Bid getNextBidSmart(Bid pOppntBid) throws Exception { double lMyUtility, lOppntUtility, lTargetUtility; // Both parties have made an initial bid. Compute associated utilities // from my point of view. lMyUtility = utilitySpace.getUtility(myLastBid); lOppntUtility = utilitySpace.getUtility(pOppntBid); if (fSmartSteps >= NUMBER_OF_SMART_STEPS) { lTargetUtility = getTargetUtility(lMyUtility, lOppntUtility); fSmartSteps = 0; } else { lTargetUtility = lMyUtility; fSmartSteps++; } if (lTargetUtility < utilitySpace.getReservationValue()) return null; else return getTradeOff(lTargetUtility); } protected Bid getTradeOff(double pUtility) throws Exception { if (pUtility < utilitySpace.getReservationValue()) return null; Bid lBid = null; double lExpectedUtility = -100; BidIterator lIter = new BidIterator(utilitySpace.getDomain()); // int i=1; while (lIter.hasNext()) { Bid tmpBid = lIter.next(); // System.out.println(tmpBid); // System.out.println(String.valueOf(i++)); if (fMarketPreassure) if (fNegotiation.getOpponentUtility(this, tmpBid) < 0.3) continue; if (Math.abs(utilitySpace.getUtility(tmpBid) - pUtility) < ALLOWED_UTILITY_DEVIATION) { // double lTmpSim = fSimilarity.getSimilarity(tmpBid, // pOppntBid); double lTmpExpecteUtility = fNegotiation.getOpponentUtility( this, tmpBid); // fOpponentModel.getExpectedUtility(tmpBid); if (lTmpExpecteUtility > lExpectedUtility) { lExpectedUtility = lTmpExpecteUtility; lBid = tmpBid; } } } // while return lBid; } protected Bid proposeNextBid(Bid pOppntBid) throws Exception { Bid lBid = null; switch (fStrategy) { case TIT_FOR_TAT: lBid = getNextBid(pOppntBid); break; case SMART: lBid = getNextBidSmart(pOppntBid); break; case AUCTION: lBid = getNextBidAuction(pOppntBid); break; default: throw new Exception("unknown strategy " + fStrategy); } myLastBid = lBid; return lBid; } public double getOpponentUtility(Bid bid) throws Exception { return fOpponentModel.getExpectedUtility(bid); } public Action chooseAction() { Action lAction = null; ACTIONTYPE lActionType; Bid lOppntBid = null; try { lActionType = getActionType(messageOpponent); switch (lActionType) { case OFFER: // Offer received from opponent lOppntBid = ((Offer) messageOpponent).getBid(); // if (fOpponentModel.haveSeenBefore(lOppntBid)) { // lAction=myLastAction; break; } // double lDistance = calculateEuclideanDistanceUtilitySpace(); // if(myLastAction==null) dumpDistancesToLog(0); System.out.print("Updating beliefs ..."); if (myPreviousBids.size() < 8) fOpponentModel.updateBeliefs(lOppntBid); // dumpDistancesToLog(fRound++); System.out.println("Done!"); if (myLastAction == null) // Other agent started, lets propose my initial bid. lAction = proposeInitialBid(); else { double offeredutil = utilitySpace.getUtility(lOppntBid); double time = timeline.getTime(); double P = Paccept(offeredutil, time); log("time=" + time + " offeredutil=" + offeredutil + " accept probability P=" + P); if (utilitySpace.getUtility(lOppntBid) * 1.05 >= utilitySpace .getUtility(myLastBid) /* || .05*P>Math.random() */) { // Opponent bids equally, or outbids my previous bid, so // lets accept lAction = new Accept(getAgentID(), lOppntBid); log("randomly accepted"); } else { Bid lnextBid = proposeNextBid(lOppntBid); if (lnextBid == null) { lAction = new EndNegotiation(getAgentID()); } else { lAction = new Offer(getAgentID(), lnextBid); // Propose counteroffer. Get next bid. // Check if utility of the new bid is lower than // utility of the opponent's last bid // if yes then accept last bid of the opponent. if (utilitySpace.getUtility(lOppntBid) * 1.05 >= utilitySpace .getUtility(lnextBid)) { // Opponent bids equally, or outbids my previous // bid, so lets accept lAction = new Accept(getAgentID(), lOppntBid); log("opponent's bid higher than util of my last bid! accepted"); } } } // remember current bid of the opponent as its previous bid fOpponentPreviousBid = lOppntBid; } break; case ACCEPT: case BREAKOFF: // nothing left to do. Negotiation ended, which should be // checked by // Negotiator... break; default: // I am starting, but not sure whether Negotiator checks this, // so // lets check also myLastAction... if (myLastAction == null) { // dumpDistancesToLog(fRound++); lAction = proposeInitialBid(); } else // simply repeat last action lAction = myLastAction; break; } } catch (Exception e) { log("Exception in chooseAction:" + e.getMessage()); e.printStackTrace(); lAction = new Offer(getAgentID(), myLastBid); } myLastAction = lAction; { myPreviousBids.add(((Offer) myLastAction).getBid()); myLastBid = ((Offer) myLastAction).getBid(); } return lAction; } protected ACTIONTYPE getActionType(Action lAction) { ACTIONTYPE lActionType = ACTIONTYPE.START; if (lAction instanceof Offer) lActionType = ACTIONTYPE.OFFER; else if (lAction instanceof Accept) lActionType = ACTIONTYPE.ACCEPT; else if (lAction instanceof EndNegotiation) lActionType = ACTIONTYPE.BREAKOFF; return lActionType; } private double getTargetUtility(double myUtility, double oppntUtility) { return myUtility - getConcessionFactor(); } private double getConcessionFactor() { // The more the agent is willing to concess on its aspiration value, the // higher this factor. return CONCESSIONFACTOR; } /** * Prints out debug information only if the fDebug = true * * @param pMessage * - debug informaton to print */ private void log(String pMessage) { if (fDebug) System.out.println(pMessage); } /** * This function determines the accept probability for an offer. At t=0 it * will prefer high-utility offers. As t gets closer to 1, it will accept * lower utility offers with increasing probability. it will never accept * offers with utility 0. * * @param u * is the utility * @param t * is the time as fraction of the total available time (t=0 at * start, and t=1 at end time) * @return the probability of an accept at time t * @throws Exception * if you use wrong values for u or t. * */ protected double Paccept(double u, double t1) throws Exception { double t = t1 * t1 * t1; // get more relaxed more to the end. if (u < 0 || u > 1.05) throw new Exception("utility " + u + " outside [0,1]"); if (t < 0 || t > 1) throw new Exception("time " + t + " outside [0,1]"); if (u > 1.) u = 1.; if (t == 0.5) return u; return (u - 2. * u * t + 2. * (-1. + t + Math.sqrt(sq(-1. + t) + u * (-1. + 2 * t)))) / (-1. + 2 * t); } private double sq(double x) { return x * x; } /* * private double calculateEuclideanDistanceUtilitySpace(double[] * pLearnedUtil, double[] pOpponentUtil) { double lDistance = 0; try { * for(int i=0;ipLearnedUtil * [j])&&(pOpponentUtil[i]>pOpponentUtil[j]))|| * ((pLearnedUtil[i]tmpWeight2Learned * )&&(tmpWeightOriginal>tmpWeight2Original))|| * ((tmpWeightLearned pLearnedSpace = new HashMap(); * BidIterator lIter = new BidIterator( utilitySpace.getDomain()); i=0; * while(lIter.hasNext()) { Bid lBid = lIter.next(); try { pLearnedUtil[i] * =fOpponentModel.getNormalizedUtility(lBid); // pLearnedSpace.put(lBid, * new Double(pLearnedUtil[i])); * * } catch (Exception e) { e.printStackTrace(); } i++; } double * pOpponentUtil[] = new * double[(int)(utilitySpace.getDomain().getNumberOfPossibleBids())]; // * HashMap pOpponentSpace = new HashMap(); lIter = * new BidIterator( utilitySpace.getDomain()); i=0; while(lIter.hasNext()) { * Bid lBid = lIter.next(); try { pOpponentUtil[i] = * fNegotiation.getOpponentUtility(this, lBid); // pOpponentSpace.put(lBid, * new Double(pOpponentUtil[i])); } catch (Exception e) { * e.printStackTrace(); } i++; } * * double lEuclideanDistUtil = * calculateEuclideanDistanceUtilitySpace(pLearnedUtil,pOpponentUtil); * double lEuclideanDistWeights = * calculateEuclideanDistanceWeghts(lExpectedWeights); double * lRankingDistUtil = 0; * if((int)(utilitySpace.getDomain().getNumberOfPossibleBids())>100000) * lRankingDistUtil = * calculateRankingDistanceUtilitySpaceMonteCarlo(pLearnedUtil, * pOpponentUtil); else lRankingDistUtil = * calculateRankingDistanceUtilitySpace(pLearnedUtil, pOpponentUtil); double * lRankingDistWeights = calculateRankingDistanceWeghts(lExpectedWeights); * double lPearsonDistUtil = * calculatePearsonDistanceUtilitySpace(pLearnedUtil,pOpponentUtil); double * lPearsonDistWeights = calculatePearsonDistanceWeghts(lExpectedWeights); * SimpleElement lLearningPerformance = new * SimpleElement("learning_performance"); * lLearningPerformance.setAttribute("round", String.valueOf(pRound)); * lLearningPerformance.setAttribute("euclidean_distance_utility_space", * String.valueOf(lEuclideanDistUtil)); * lLearningPerformance.setAttribute("euclidean_distance_weights", * String.valueOf(lEuclideanDistWeights)); * lLearningPerformance.setAttribute("ranking_distance_utility_space", * String.valueOf(lRankingDistUtil)); * lLearningPerformance.setAttribute("ranking_distance_weights", * String.valueOf(lRankingDistWeights)); * lLearningPerformance.setAttribute("pearson_distance_utility_space", * String.valueOf(lPearsonDistUtil)); * lLearningPerformance.setAttribute("pearson_distance_weights", * String.valueOf(lPearsonDistWeights)); System.out.println("Done!"); * System.out.println(lLearningPerformance.toString()); * fNegotiation.addAdditionalLog(lLearningPerformance); * * } */ public final Bid getMaxUtilityBid() throws Exception { Bid maxBid = null; double maxutil = 0.; BidIterator bidit = new BidIterator(utilitySpace.getDomain()); if (bidit.hasNext()) maxBid = bidit.next(); else throw new Exception("The domain does not contain any bids!"); while (bidit.hasNext()) { Bid thisBid = bidit.next(); if (fMarketPreassure) if (fNegotiation.getOpponentUtility(this, thisBid) < 0.3) continue; double thisutil = utilitySpace.getUtility(thisBid); if (thisutil > maxutil) { maxutil = thisutil; maxBid = thisBid; } } return maxBid; } }