package onetomany.bargainingchipsgame.players; import static java.lang.Math.pow; import java.util.concurrent.BlockingQueue; import genius.core.protocol.MultilateralProtocol; import onetomany.bargainingchipsgame.Bundle; import onetomany.bargainingchipsgame.OutcomeSpace; import onetomany.bargainingchipsgame.interactions.Accept; import onetomany.bargainingchipsgame.interactions.Offer; import onetomany.bargainingchipsgame.players.utilityfunction.UtilityFunction; /** * Boulware/Conceder tactics, by Tim Baarslag, adapted from [1]. Adapted by Mark * Hendrikx to use the SortedOutcomeSpace instead of BidHistory. Adapted by * David Festen for multilateral case. * * [1] S. Shaheen Fatima Michael Wooldridge Nicholas R. Jennings Optimal * Negotiation Strategies for Agents with Incomplete Information * http://eprints.ecs.soton.ac.uk/6151/1/atal01.pdf * * @author Tim Baarslag, Mark Hendrikx */ public abstract class AbstractTimeDependentNegotiationParty extends Agent { OutcomeSpace outcomeSpace; Bundle lastReceivedBid = null; public AbstractTimeDependentNegotiationParty(String name, UtilityFunction u, BlockingQueue in, BlockingQueue out, BlockingQueue cin, BlockingQueue cout) { super(name, u, in, out, cin, cout); outcomeSpace = new OutcomeSpace(null); } /** * When this class is called, it is expected that the Party chooses one of * the actions from the possible action list and returns an instance of the * chosen action. This class is only called if this * {@link genius.core.parties.NegotiationParty} is in the * {@link MultilateralProtocol#getRoundStructure(java.util.List, negotiator.session.Session)} * . * * @param possibleActions * List of all actions possible. * @return The chosen action */ @Override protected Offer sendOffer() { Bundle nextBid = getNextBid(); double lastUtil = lastReceivedBid != null ? u.getUtility(lastReceivedBid) : 0; double nextUtil = nextBid != null ? u.getUtility(nextBid) : 0; // Accept if (nextUtil < lastUtil) return new Accept(); // Counter offer based actions else return new Offer(nextBid); } /** * Get the next bid we should do */ protected Bundle getNextBid() { return outcomeSpace.getBidNearUtility(getTargetUtility(), u); } @Override protected void receiveOffer(Offer o) { lastReceivedBid = o.getBundle(); } /** * Gets the target utility for the next bid * * @return The target utility for the given time */ public double getTargetUtility() { // timeline runs from 0.0 to 1.0 // we have a slight offset because discrete timeline is 1-based, this // needs to be addressed int totalrounds = 20; double offset = 1d / totalrounds; double time = k / (totalrounds + 1); double target = 1d - f(time - offset); System.out.println("Target util: " + target); return target; } /** * From [1]: * * A wide range of time dependent functions can be defined by varying the * way in which f(t) is computed. However, functions must ensure that 0 <= * f(t) <= 1, f(0) = k, and f(1) = 1. * * That is, the offer will always be between the value range, at the * beginning it will give the initial constant and when the deadline is * reached, it will offer the reservation value. * * For e = 0 (special case), it will behave as a Hardliner. */ public double f(double t) { if (getE() == 0) { return 0; } return pow(t, 1 / getE()); } /** * Depending on the value of e, extreme sets show clearly different patterns * of behaviour [1]: * * 1. Boulware: For this strategy e < 1 and the initial offer is maintained * till time is almost exhausted, when the agent concedes up to its * reservation value. * * 2. Conceder: For this strategy e > 1 and the agent goes to its * reservation value very quickly. * * 3. When e = 1, the price is increased linearly. * * 4. When e = 0, the agent plays hardball. */ public abstract double getE(); @Override protected Offer sendOpeningOffer() { // TODO Auto-generated method stub return null; } @Override protected void receiveCoordinationMessage(CoordinationMessage cpoll) { // TODO Auto-generated method stub } }