1 | package negotiator.boaframework.offeringstrategy.anac2010;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.Map;
|
---|
5 | import java.util.Random;
|
---|
6 |
|
---|
7 | import genius.core.Bid;
|
---|
8 | import genius.core.bidding.BidDetails;
|
---|
9 | import genius.core.boaframework.NegotiationSession;
|
---|
10 | import genius.core.boaframework.NoModel;
|
---|
11 | import genius.core.boaframework.OMStrategy;
|
---|
12 | import genius.core.boaframework.OfferingStrategy;
|
---|
13 | import genius.core.boaframework.OpponentModel;
|
---|
14 | import genius.core.utility.AdditiveUtilitySpace;
|
---|
15 | import negotiator.boaframework.offeringstrategy.anac2010.IAMhaggler2010.BidSpace;
|
---|
16 | import negotiator.boaframework.offeringstrategy.anac2010.IAMhaggler2010.ConcessionFunction;
|
---|
17 | import negotiator.boaframework.offeringstrategy.anac2010.IAMhaggler2010.Pair;
|
---|
18 | import negotiator.boaframework.offeringstrategy.anac2010.IAMhaggler2010.SpecialTimeConcessionFunction;
|
---|
19 | import negotiator.boaframework.offeringstrategy.anac2010.IAMhaggler2010.TimeConcessionFunction;
|
---|
20 | import negotiator.boaframework.opponentmodel.DefaultModel;
|
---|
21 | import negotiator.boaframework.opponentmodel.IAMhagglerBayesianModel;
|
---|
22 |
|
---|
23 | /**
|
---|
24 | * This is the decoupled Offering Strategy for IAMhaggler2010 (ANAC2010). The
|
---|
25 | * code was taken from the ANAC2010 IAMhaggler2010 and adapted to work within
|
---|
26 | * the BOA framework.
|
---|
27 | *
|
---|
28 | * The default opponent model implementation selects the best bid for the
|
---|
29 | * opponent.
|
---|
30 | *
|
---|
31 | * Decoupling Negotiating Agents to Explore the Space of Negotiation Strategies
|
---|
32 | * T. Baarslag, K. Hindriks, M. Hendrikx, A. Dirkzwager, C.M. Jonker
|
---|
33 | */
|
---|
34 | public class IAMhaggler2010_Offering extends OfferingStrategy {
|
---|
35 |
|
---|
36 | /**
|
---|
37 | * The lowest target we have tried to use (initialised to 1).
|
---|
38 | */
|
---|
39 | private double lowestTarget = 1.0;
|
---|
40 |
|
---|
41 | /**
|
---|
42 | * The minimum discounting factor.
|
---|
43 | */
|
---|
44 | private final double minDiscounting = 0.1;
|
---|
45 |
|
---|
46 | /**
|
---|
47 | * The minimum beta value, which stops the agent from becoming too tough.
|
---|
48 | */
|
---|
49 | private final double minBeta = 0.01;
|
---|
50 |
|
---|
51 | /**
|
---|
52 | * The maximum beta value, which stops the agent from becoming too weak.
|
---|
53 | */
|
---|
54 | private double maxBeta = 2.0;
|
---|
55 |
|
---|
56 | /**
|
---|
57 | * The default value for beta, used when there is not enough information to
|
---|
58 | * perform the linear regression.
|
---|
59 | */
|
---|
60 | private double defaultBeta = 1;
|
---|
61 |
|
---|
62 | /**
|
---|
63 | * The minimum target value when the opponent is considered to be a
|
---|
64 | * hardhaed.
|
---|
65 | */
|
---|
66 | private final double hardHeadTarget = 0.8;
|
---|
67 |
|
---|
68 | protected ConcessionFunction cf;
|
---|
69 | protected ArrayList<Pair<Double, Double>> bestOpponentBidUtilityHistory;
|
---|
70 | private Bid bestOpponentBid;
|
---|
71 | private double bestOpponentUtility;
|
---|
72 | protected double utility0 = 0;
|
---|
73 | protected final double utility1 = 0.95;
|
---|
74 | protected static double MAXIMUM_ASPIRATION = 0.9;
|
---|
75 | protected BidSpace bidSpace;
|
---|
76 | protected BidDetails myLastBid = null;
|
---|
77 | protected Bid opponentPreviousBid = null;
|
---|
78 | protected final double acceptMultiplier = 1.02;
|
---|
79 | protected boolean opponentIsHardHead;
|
---|
80 |
|
---|
81 | @Override
|
---|
82 | public void init(NegotiationSession negoSession, OpponentModel model, OMStrategy oms,
|
---|
83 | Map<String, Double> parameters) throws Exception {
|
---|
84 | if (model instanceof DefaultModel) {
|
---|
85 | model = new IAMhagglerBayesianModel();
|
---|
86 | model.init(negoSession, null);
|
---|
87 | oms.setOpponentModel(model);
|
---|
88 | }
|
---|
89 |
|
---|
90 | this.opponentModel = model;
|
---|
91 |
|
---|
92 | this.omStrategy = oms;
|
---|
93 | this.negotiationSession = negoSession;
|
---|
94 | bestOpponentBidUtilityHistory = new ArrayList<Pair<Double, Double>>();
|
---|
95 | cf = new TimeConcessionFunction(TimeConcessionFunction.Beta.LINEAR, TimeConcessionFunction.BREAKOFF);
|
---|
96 | myLastBid = null;
|
---|
97 |
|
---|
98 | try {
|
---|
99 | bidSpace = new BidSpace((AdditiveUtilitySpace) this.negotiationSession.getUtilitySpace());
|
---|
100 | } catch (Exception e) {
|
---|
101 | e.printStackTrace();
|
---|
102 | }
|
---|
103 |
|
---|
104 | opponentIsHardHead = true;
|
---|
105 | int discreteCombinationCount = this.bidSpace.getDiscreteCombinationsCount();
|
---|
106 | if (this.bidSpace.isContinuousWeightsZero()) {
|
---|
107 | defaultBeta = Math.min(0.5, Math.max(0.0625, discreteCombinationCount * 0.001));
|
---|
108 | if (negotiationSession.getUtilitySpace().isDiscounted()) {
|
---|
109 | maxBeta = (2.0 + (4.0 * Math.min(0.5, negotiationSession.getUtilitySpace().getDiscountFactor())))
|
---|
110 | * defaultBeta;
|
---|
111 | } else {
|
---|
112 | maxBeta = 2.0 + 4.0 * defaultBeta;
|
---|
113 | }
|
---|
114 | }
|
---|
115 | }
|
---|
116 |
|
---|
117 | /*
|
---|
118 | * (non-Javadoc)
|
---|
119 | *
|
---|
120 | * @see agents.southampton.similarity.VariableConcessionSimilarityAgent#
|
---|
121 | * getTargetUtility(double, double)
|
---|
122 | */
|
---|
123 | protected double getTargetUtility(double myUtility, double oppntUtility) {
|
---|
124 | double currentTime = negotiationSession.getTime() * negotiationSession.getTimeline().getTotalTime() * 1000;
|
---|
125 | double beta = bidSpace.getBeta(bestOpponentBidUtilityHistory, negotiationSession.getTime(), utility0, utility1,
|
---|
126 | minDiscounting, minBeta, maxBeta, defaultBeta, currentTime, currentTime);
|
---|
127 |
|
---|
128 | cf = new SpecialTimeConcessionFunction(beta, defaultBeta, TimeConcessionFunction.DEFAULT_BREAKOFF);
|
---|
129 |
|
---|
130 | double target = 0;
|
---|
131 | try {
|
---|
132 | target = getConcession(negotiationSession.getUtilitySpace()
|
---|
133 | .getUtility(negotiationSession.getOwnBidHistory().getFirstBidDetails().getBid()));
|
---|
134 | } catch (Exception e) {
|
---|
135 | e.printStackTrace();
|
---|
136 | }
|
---|
137 |
|
---|
138 | lowestTarget = Math.min(target, lowestTarget);
|
---|
139 | if (opponentIsHardHead) {
|
---|
140 | return Math.max(hardHeadTarget, lowestTarget);
|
---|
141 | }
|
---|
142 | return lowestTarget;
|
---|
143 | }
|
---|
144 |
|
---|
145 | private void storeDataPoint(double utility) {
|
---|
146 | double time = negotiationSession.getTime();
|
---|
147 | // bestOpponentBidUtilityHistory.add(new Pair<Double,
|
---|
148 | // Double>(-Math.log(1 - ((utility - utility0) / (utility1 -
|
---|
149 | // utility0))), time));
|
---|
150 | bestOpponentBidUtilityHistory.add(new Pair<Double, Double>(utility, time));
|
---|
151 | }
|
---|
152 |
|
---|
153 | /**
|
---|
154 | * Handle an opponent's offer.
|
---|
155 | */
|
---|
156 | private BidDetails handleOffer(Bid opponentBid) throws Exception {
|
---|
157 | Bid chosenAction = null;
|
---|
158 |
|
---|
159 | if (myLastBid == null) {
|
---|
160 | // Special case to handle first action
|
---|
161 | Bid b = proposeInitialBid();
|
---|
162 | myLastBid = new BidDetails(b, negotiationSession.getUtilitySpace().getUtility(b),
|
---|
163 | negotiationSession.getTime());
|
---|
164 | chosenAction = b;
|
---|
165 | } else {
|
---|
166 | Bid plannedBid = proposeNextBid(opponentBid);
|
---|
167 | chosenAction = plannedBid;
|
---|
168 |
|
---|
169 | opponentPreviousBid = opponentBid;
|
---|
170 | }
|
---|
171 |
|
---|
172 | return new BidDetails(chosenAction, negotiationSession.getUtilitySpace().getUtility(chosenAction),
|
---|
173 | negotiationSession.getTime());
|
---|
174 | }
|
---|
175 |
|
---|
176 | protected Bid proposeInitialBid() {
|
---|
177 | Bid bid = null;
|
---|
178 |
|
---|
179 | try {
|
---|
180 | bid = bidSpace.getMaxUtilityBid();
|
---|
181 | } catch (Exception e) {
|
---|
182 | e.printStackTrace();
|
---|
183 | }
|
---|
184 | return bid;
|
---|
185 | }
|
---|
186 |
|
---|
187 | @Override
|
---|
188 | protected void finalize() throws Throwable {
|
---|
189 | // displayFrame.dispose();
|
---|
190 | super.finalize();
|
---|
191 | }
|
---|
192 |
|
---|
193 | protected Bid proposeNextBid(Bid opponentBid) {
|
---|
194 | BidDetails opponentHisBid = negotiationSession.getOpponentBidHistory().getLastBidDetails();
|
---|
195 | if (opponentHisBid != null) {
|
---|
196 | try {
|
---|
197 | if (opponentIsHardHead && negotiationSession.getOpponentBidHistory().size() > 0
|
---|
198 | && Math.abs(negotiationSession.getUtilitySpace()
|
---|
199 | .getUtility(negotiationSession.getOpponentBidHistory().getFirstBidDetails().getBid())
|
---|
200 | - opponentHisBid.getMyUndiscountedUtil()) > 0.02) {
|
---|
201 | opponentIsHardHead = false;
|
---|
202 | }
|
---|
203 | } catch (Exception e) {
|
---|
204 | e.printStackTrace();
|
---|
205 | }
|
---|
206 | }
|
---|
207 |
|
---|
208 | double myUtility = 0, opponentUtility = 0, targetUtility;
|
---|
209 | // Both parties have made an initial bid. Compute associated utilities
|
---|
210 | // from my point of view.
|
---|
211 | try {
|
---|
212 | myUtility = negotiationSession.getUtilitySpace().getUtility(myLastBid.getBid());
|
---|
213 | opponentUtility = negotiationSession.getUtilitySpace().getUtility(opponentBid);
|
---|
214 | if (opponentPreviousBid == null)
|
---|
215 | utility0 = opponentUtility;
|
---|
216 | } catch (Exception e) {
|
---|
217 | e.printStackTrace();
|
---|
218 | }
|
---|
219 | targetUtility = getTargetUtility(myUtility, opponentUtility);
|
---|
220 | Bid nextBid = getTradeOffExhaustive(targetUtility, opponentBid, 1000);
|
---|
221 |
|
---|
222 | return nextBid;
|
---|
223 | }
|
---|
224 |
|
---|
225 | private double getConcession(double startUtility) {
|
---|
226 | double currentTime = negotiationSession.getTimeline().getCurrentTime() * 1000;
|
---|
227 | double totalTime = negotiationSession.getTimeline().getTotalTime() * 1000;
|
---|
228 | return cf.getConcession(startUtility, Math.round(currentTime), totalTime);
|
---|
229 | }
|
---|
230 |
|
---|
231 | private Bid getBestBid(Bid opponentBid) {
|
---|
232 | double utility;
|
---|
233 | try {
|
---|
234 | utility = negotiationSession.getUtilitySpace().getUtility(opponentBid);
|
---|
235 | if (utility >= bestOpponentUtility) {
|
---|
236 | bestOpponentUtility = utility;
|
---|
237 | bestOpponentBid = opponentBid;
|
---|
238 | }
|
---|
239 | storeDataPoint(bestOpponentUtility);
|
---|
240 | } catch (Exception e) {
|
---|
241 | e.printStackTrace();
|
---|
242 | }
|
---|
243 | return bestOpponentBid;
|
---|
244 | }
|
---|
245 |
|
---|
246 | private Bid getTradeOffExhaustive(double ourUtility, Bid opponentBid, int count) {
|
---|
247 | // Project a point onto the bidspace...
|
---|
248 | Bid bestBidOpp = getBestBid(opponentBid);
|
---|
249 |
|
---|
250 | if (bestOpponentUtility * acceptMultiplier >= ourUtility) {
|
---|
251 | return bestBidOpp;
|
---|
252 | }
|
---|
253 |
|
---|
254 | // SHOULD FIX OM USAGE HERE!
|
---|
255 | ArrayList<BidDetails> bids = bidSpace.Project(bidSpace.getPoint(bestOpponentBid), ourUtility, count,
|
---|
256 | (AdditiveUtilitySpace) negotiationSession.getUtilitySpace(), opponentModel);
|
---|
257 | if (bids.size() == 0) {
|
---|
258 | return getTradeOffExhaustive(ourUtility, opponentBid, count + 10000);
|
---|
259 | }
|
---|
260 |
|
---|
261 | Bid bestBid = null;
|
---|
262 |
|
---|
263 | // double maxOpponentUtility = 0;
|
---|
264 | // for (Bid bid : bids) {
|
---|
265 | // try {
|
---|
266 | // double opponentUtility = opponentModel.getBidEvaluation(bid);
|
---|
267 | // if (opponentUtility > maxOpponentUtility) {
|
---|
268 | // maxOpponentUtility = opponentUtility;
|
---|
269 | // bestBid = bid;
|
---|
270 | // }
|
---|
271 | // } catch (Exception e) {
|
---|
272 | // e.printStackTrace();
|
---|
273 | // }
|
---|
274 | // }
|
---|
275 | if (opponentModel instanceof NoModel) {
|
---|
276 | Random random = new Random();
|
---|
277 | bestBid = bids.get(random.nextInt(bids.size())).getBid();
|
---|
278 | } else {
|
---|
279 | bestBid = omStrategy.getBid(bids).getBid();
|
---|
280 | }
|
---|
281 |
|
---|
282 | return bestBid;
|
---|
283 | }
|
---|
284 |
|
---|
285 | public BidDetails determineNextBid() {
|
---|
286 | BidDetails chosenAction = null;
|
---|
287 |
|
---|
288 | if (this.myLastBid == null) {
|
---|
289 | Bid bid = proposeInitialBid();
|
---|
290 | try {
|
---|
291 | chosenAction = new BidDetails(bid, negotiationSession.getUtilitySpace().getUtility(bid),
|
---|
292 | negotiationSession.getTime());
|
---|
293 | } catch (Exception e) {
|
---|
294 | e.printStackTrace();
|
---|
295 | }
|
---|
296 | } else {
|
---|
297 | try {
|
---|
298 | chosenAction = handleOffer(negotiationSession.getOpponentBidHistory().getLastBidDetails().getBid());
|
---|
299 | } catch (Exception e) {
|
---|
300 | e.printStackTrace();
|
---|
301 | }
|
---|
302 | }
|
---|
303 |
|
---|
304 | myLastBid = chosenAction;
|
---|
305 |
|
---|
306 | return chosenAction;
|
---|
307 | }
|
---|
308 |
|
---|
309 | @Override
|
---|
310 | public BidDetails determineOpeningBid() {
|
---|
311 | return determineNextBid();
|
---|
312 | }
|
---|
313 |
|
---|
314 | @Override
|
---|
315 | public String getName() {
|
---|
316 | return "2010 - IAMhaggler";
|
---|
317 | }
|
---|
318 | }
|
---|