source: src/main/java/parties/in4010/q12015/group5/Group5.java@ 126

Last change on this file since 126 was 126, checked in by Aron Hammond, 6 years ago

Added function to calculate opposition to MultiLateralAnalysis.java

Moved code to add RLBOA listeners to RLBOAUtils is misc package

Added input for strategyParameters to SessionPanel (gui)

!! close SessionInfo after tournament; this caused /tmp/ to fill up with GeniusData files

Our own package:

  • Added opponents and strategies that are mentioned in the report
  • Change class hierarchy, agents can now extend from RLBOAagentBilateral to inherit RL functionality.
  • States extend from AbstractState
File size: 8.8 KB
Line 
1package parties.in4010.q12015.group5;
2
3import java.util.List;
4
5import java.util.ArrayList;
6import java.util.HashMap;
7import java.util.Map;
8import java.util.Set;
9
10import genius.core.AgentID;
11import genius.core.Bid;
12import genius.core.actions.Accept;
13import genius.core.actions.Action;
14import genius.core.actions.Offer;
15import genius.core.bidding.BidDetails;
16import genius.core.boaframework.SortedOutcomeSpace;
17import genius.core.parties.AbstractNegotiationParty;
18import genius.core.parties.NegotiationInfo;
19import genius.core.utility.AdditiveUtilitySpace;
20
21/**
22 * NegotiationParty for Group 5. This agent moves closer to the estimated Nash
23 * point as time progresses. For an extended explanation of what our agent does,
24 * see our report.
25 */
26public class Group5 extends AbstractNegotiationParty {
27
28 /**
29 * All possible bids from the SortedOutcomeSpace.
30 */
31 private List<BidDetails> allOutcomes;
32
33 /**
34 * The last bid that has been made by any agent (including us).
35 */
36 private Bid lastBid;
37
38 /**
39 * The models that we build for every opponent.
40 */
41 private Map<Object, OpponentModel> opponentModels;
42
43 /**
44 * The SortedOutcomeSpace of our UtilitySpace.
45 */
46 private SortedOutcomeSpace sos;
47
48 /**
49 * The threshold above which we will always accept.
50 */
51 private double utilityThreshold;
52
53 /*
54 * (non-Javadoc)
55 *
56 * @see negotiator.parties.AbstractNegotiationParty#init(negotiator.utility.
57 * UtilitySpace, negotiator.Deadline, negotiator.session.TimeLineInfo, long,
58 * negotiator.AgentID)
59 */
60 @Override
61 public void init(NegotiationInfo info) {
62 super.init(info);
63 opponentModels = new HashMap<Object, OpponentModel>();
64 sos = new SortedOutcomeSpace(getUtilitySpace());
65 allOutcomes = sos.getAllOutcomes();
66
67 double minBid = sos.getMinBidPossible().getMyUndiscountedUtil();
68 utilityThreshold = 1 - (1 - minBid) * 0.1; // Get top 90%
69 }
70
71 /**
72 * All offers proposed by the other parties will be received as a message.
73 * You can use this information to your advantage, for example to predict
74 * their utility.
75 *
76 * @param sender
77 * The party that did the action.
78 * @param action
79 * The action that party did.
80 */
81 @Override
82 public void receiveMessage(AgentID sender, Action action) {
83 super.receiveMessage(sender, action);
84
85 try {
86 if (action instanceof Offer) {
87 lastBid = ((Offer) action).getBid();
88 updateModel(sender, lastBid);
89 } else if (action instanceof Accept) {
90 updateModel(sender, lastBid);
91 }
92 } catch (Exception e) {
93 e.printStackTrace();
94 }
95 }
96
97 /**
98 * Each round this method gets called and ask you to accept or offer. The
99 * first party in the first round is a bit different, it can only propose an
100 * offer.
101 *
102 * @param validActions
103 * Either a list containing both accept and offer or only offer.
104 * @return The chosen action.
105 */
106 @Override
107 public Action chooseAction(List<Class<? extends Action>> validActions) {
108 try {
109 Bid bid = generateBid();
110 if (acceptBid(bid))
111 return new Accept(getPartyId(), lastBid);
112 else {
113 lastBid = bid;
114 return new Offer(getPartyId(), new Bid(bid));
115 }
116 } catch (Exception e) {
117 e.printStackTrace();
118 // Accepting is always
119 // better than crashing
120 return new Accept(getPartyId(), lastBid);
121 }
122 }
123
124 /**
125 * Generates a new bid according to the bidding strategy. Finds a bid by
126 * looping through all bids and - Calculate the Nash score for the bid based
127 * on the opponent models. - Calculate own utility for the bid. - Take the
128 * weighted average of own utility and the Nash score. This weighted average
129 * starts at 100% own utility and moves to 100% theoretical Nash point. Of
130 * these the top 5 is chosen and from those the one with the highest utility
131 * is chosen.
132 *
133 * @return The preferred bid based on the chosen strategy.
134 * @throws Exception
135 */
136 private Bid generateBid() throws Exception {
137 Double time = timeline.getTime();
138 double ownFactor = 1 - (time * time); // 1 - x^2
139 double nashFactor = 1 - ownFactor;
140
141 // Get modeled utility spaces for opponents
142 Set<Object> opponents = opponentModels.keySet();
143 Map<Object, AdditiveUtilitySpace> opponentUtilSpaces = new HashMap<Object, AdditiveUtilitySpace>();
144 for (Object opponent : opponents) {
145 opponentUtilSpaces.put(opponent, opponentModels.get(opponent).getUtilitySpace());
146 }
147
148 // weightedAverages contains the top 5 weighted averages found
149 Map<BidDetails, Double> weightedAverages = new HashMap<BidDetails, Double>();
150 weightedAverages.put(null, 0.);
151 for (BidDetails bid : allOutcomes) {
152 // First find the minimum in order to know which one we should
153 // replace if we find a better one.
154 double min = Double.MAX_VALUE;
155 BidDetails minBid = null;
156 for (BidDetails mapBid : weightedAverages.keySet()) {
157 double mapAvg = weightedAverages.get(mapBid);
158 if (mapAvg <= min) {
159 min = mapAvg;
160 minBid = mapBid;
161 }
162 }
163
164 // If based on our utility alone we won't make it, break because:
165 // - Adding the opponents utilities to the nash will only decrease
166 // the value (because U <= 1)
167 // - The list is sorted in decreasing order so all next bids will be
168 // worse.
169 double ourUtil = bid.getMyUndiscountedUtil();
170 if (ownFactor * ourUtil + nashFactor * ourUtil < min)
171 break;
172
173 double nash = ourUtil;
174 for (Object opponent : opponents) {
175 AdditiveUtilitySpace opponentUtilSpace = opponentUtilSpaces.get(opponent);
176 nash *= opponentUtilSpace.getUtility(bid.getBid());
177 }
178
179 double weightedAverage = ownFactor * ourUtil + nashFactor * nash;
180 if (weightedAverage > min) {
181 if (weightedAverages.size() >= 5) {
182 weightedAverages.remove(minBid);
183 }
184
185 weightedAverages.put(bid, weightedAverage);
186 }
187 }
188
189 // Find the one that gives the highest utility of the top 5.
190 double max = 0;
191 BidDetails maxBid = null;
192 for (BidDetails mapBid : weightedAverages.keySet()) {
193 double mapUtil = mapBid.getMyUndiscountedUtil();
194 if (mapUtil > max) {
195 max = mapUtil;
196 maxBid = mapBid;
197 }
198 }
199
200 return maxBid.getBid();
201 }
202
203 // Accept when either:
204 // - It is above our minimum
205 // - It is better than we would bid
206 // - (late in the bidding), it is better than all the bids in the previous
207 // window
208 /**
209 * Decides whether to accept the last bid based on the bid that was
210 * generated by the bidding strategy. Acceptance strategy is as follows.
211 * Accept when either: - The bid is above our threshold This is a linear
212 * function from the top 100% of the space to the top 80% of the space - The
213 * bid is better than the bid generated by the strategy. - When 0.95 of the
214 * negotiation has passed, accept if we don't expect a better bid. This is
215 * the case if the bid is better than all the bids we have seen in the
216 * previous time window.
217 *
218 * @param bid
219 * The bid generated by the bidding strategy.
220 * @return Whether to accept the current bid.
221 * @throws Exception
222 */
223 private boolean acceptBid(Bid bid) throws Exception {
224 double time = timeline.getTime();
225 double minUtility = getUtilityThreshold(time / 0.5);
226 double lastUtility = (lastBid != null) ? utilitySpace.getUtility(lastBid) : 0;
227 double bidUtility = utilitySpace.getUtility(bid);
228 if (lastUtility >= minUtility || lastUtility >= bidUtility)
229 return true;
230
231 if (time >= 0.95) {
232 List<Bid> opponentBids = new ArrayList<Bid>();
233 for (Object opponent : opponentModels.keySet()) {
234 opponentBids.addAll(opponentModels.get(opponent).getBidHistory(1 - time));
235 }
236 double maxUtility = 0;
237 for (Bid oppBid : opponentBids) {
238 double utility = utilitySpace.getUtility(oppBid);
239 if (utility > maxUtility) {
240 maxUtility = utility;
241 }
242 }
243 if (bidUtility >= maxUtility)
244 return true;
245 }
246
247 return false;
248 }
249
250 /**
251 * Linear function from 1 to utilityThreshold, multiplied by the factor (to
252 * reach it sooner, for example)
253 *
254 * @param factor
255 * The factor by which to multiply
256 * @return The utilty above which we will always accept.
257 */
258 private double getUtilityThreshold(double factor) {
259 return 1 - (1 - utilityThreshold) * factor;
260 }
261
262 /**
263 * Updates the opponent model with the specified opponents new bid. If no
264 * model is yet present, one will be created and added to the list.
265 *
266 * @param opponent
267 * The opponent of which the model needs to be updated.
268 * @param newBid
269 * The new bid of the opponent
270 * @throws Exception
271 */
272 private void updateModel(AgentID opponent, Bid newBid) throws Exception {
273 OpponentModel opponentModel = opponentModels.get(opponent);
274 if (opponentModel == null) {
275 opponentModel = new OpponentModel(utilitySpace.getDomain(), newBid);
276 opponentModels.put(opponent, opponentModel);
277 } else {
278 opponentModel.updateModel(newBid);
279 }
280 }
281
282 /*
283 * (non-Javadoc)
284 *
285 * @see negotiator.parties.AbstractNegotiationParty#getDescription()
286 */
287 @Override
288 public String getDescription() {
289 return "I heard you like parties so we created a party to negotiate about your party";
290 }
291}
Note: See TracBrowser for help on using the repository browser.