source: src/main/java/parties/in4010/q12015/group15/Group15.java@ 126

Last change on this file since 126 was 47, checked in by Tim Baarslag, 6 years ago

BOA agents get their getUtilitySpace() from the API, not the info object anymore

File size: 9.8 KB
Line 
1package parties.in4010.q12015.group15;
2
3import java.util.List;
4
5import java.util.ArrayList;
6import java.util.Random;
7
8import genius.core.AgentID;
9import genius.core.Bid;
10import genius.core.actions.Accept;
11import genius.core.actions.Action;
12import genius.core.actions.DefaultAction;
13import genius.core.actions.Offer;
14import genius.core.bidding.BidDetails;
15import genius.core.boaframework.Actions;
16import genius.core.boaframework.SortedOutcomeSpace;
17import genius.core.issue.Issue;
18import genius.core.misc.Range;
19import genius.core.parties.AbstractNegotiationParty;
20import genius.core.parties.NegotiationInfo;
21import genius.core.protocol.DefaultMultilateralProtocol;
22import genius.core.protocol.StackedAlternatingOffersProtocol;
23import genius.core.utility.AdditiveUtilitySpace;
24
25/**
26 * Negotiation party for Group15. Group members: Fabio Izzi, Kristin Fjola
27 * Tomasdottir, Valentina Bollini
28 *
29 * The bidding strategy is a version of time dependent concession with trade off
30 * using opponent modeling.
31 *
32 * We look at all offers in a certain range of utility. That range starts high
33 * (0.95 - 1) and lowers with time. First 2/3 of the time we choose an offer
34 * from that range with the lowest combined Hamming distance to all opponents
35 * based on their last bid. Last 1/3 of the time we choose an offer from that
36 * range using opponent modeling.
37 */
38public class Group15 extends AbstractNegotiationParty {
39
40 private double MIN_UTILITY_TO_OFFER;
41 private double OFFER_GROUP_SIZE;
42 private double TIME_TO_SWITCH_TO_OMS;
43 private double TIME_TO_LOWER_MIN_UTILITY;
44
45 // Bidding strategy
46 private Bid lastBid;
47 private List<Bid> bidsOffered = new ArrayList<>();
48 private SortedOutcomeSpace outcomeSpace;
49 private double lastTimeMinUtilityWasLowered;
50 private boolean isUsingOMS;
51 private int rounds = 0;
52
53 // BOA elements
54 private OpponentModel om;
55 private OMStrategy oms;
56 private AcceptanceStrategy as;
57
58 // Time measurements
59 long ourStartTime = 0;
60 long roundStartTime = 0;
61 double timeCount = 0.0;
62 double ourTotalTime = 0;
63 double roundTotalTime = 0;
64
65 public Group15() {
66 }
67
68 @Override
69 public void init(NegotiationInfo info) {
70 super.init(info);
71
72 outcomeSpace = new SortedOutcomeSpace(getUtilitySpace());
73 outcomeSpace.generateAllBids(getUtilitySpace());
74
75 MIN_UTILITY_TO_OFFER = 0.95; // Start offering the highest utility for
76 // us
77 OFFER_GROUP_SIZE = 0.05; // Look at offers in a range of max-min=0.05
78 TIME_TO_SWITCH_TO_OMS = 2 / 3.0; // After 2/3 of the time we are
79 // confident in our OM
80 TIME_TO_LOWER_MIN_UTILITY = (2 / 3.0) / 6.0; // 6 steps of lowering
81 // minUtil by 0.05 to
82 // get to utility 0.7
83 lastTimeMinUtilityWasLowered = timeline.getTime(); // Keep track of when
84 // to lower min
85 // utility (concede)
86 isUsingOMS = false; // Start by not using OMS
87
88 // BOA elements
89 om = new OpponentModel((AdditiveUtilitySpace) getUtilitySpace());
90 as = new AcceptanceStrategy((AdditiveUtilitySpace) getUtilitySpace());
91 oms = new OMStrategy(om, (AdditiveUtilitySpace) getUtilitySpace());
92 }
93
94 /**
95 * @param validActions
96 * : Either a list containing both accept and offer or only
97 * offer.
98 * @return The chosen action.
99 */
100 @Override
101 public Action chooseAction(List<Class<? extends Action>> validActions) {
102 System.out.println("---- BS Choose action ---");
103 rounds++;
104 System.out.println("Round: " + rounds);
105 double roundTime = measureAverageRoundTime();
106
107 // Accept if offer is good enough according to our AS
108 if (validActions.contains(Accept.class)
109 && as.determineAcceptability(lastBid, timeline, roundTime).equals(Actions.Accept)) {
110 return new Accept(getPartyId(), lastBid);
111 }
112
113 // If we're the first one to make an offer
114 if (!validActions.contains(Accept.class)) {
115 try {
116 return getFirstBid();
117 } catch (Exception e) {
118 System.out.println("Could not generate first bid");
119 e.printStackTrace();
120 }
121 }
122
123 // Concede to lower minimum utility if a certain time has passed
124 if ((timeline.getTime() - lastTimeMinUtilityWasLowered) >= TIME_TO_LOWER_MIN_UTILITY) {
125 lowerMinUtility();
126 }
127
128 List<BidDetails> possibleBids = getPossibleBids();
129 Bid bestBid = null;
130
131 // Switch to using OMS when we're confident in the OM
132 if (!isUsingOMS && timeline.getTime() >= TIME_TO_SWITCH_TO_OMS) {
133 switchToOms();
134 }
135
136 // First we use Hamming Distance, then Opponent Modeling
137 if (!isUsingOMS) {
138 bestBid = getBidWithSmallestHammingDistance(possibleBids);
139 } else {
140 bestBid = oms.getBestBid(possibleBids);
141 }
142
143 // If something goes wrong in the bidding strategy or if we already
144 // offered all bids in the interval
145 // we offer a random bid within our utility demand
146 if (bestBid == null) {
147 bestBid = getRandomBidInInterval(MIN_UTILITY_TO_OFFER, MIN_UTILITY_TO_OFFER + OFFER_GROUP_SIZE);
148 }
149
150 System.out.println("---- BS Choose action ---");
151 System.out.println("My BID offered: " + bestBid);
152 try {
153 System.out.println("My BID Util: " + utilitySpace.getUtility(bestBid));
154 } catch (Exception e) {
155 e.printStackTrace();
156 }
157
158 return new Offer(getPartyId(), bestBid);
159 }
160
161 /**
162 * Lowers the minimum utility that we want to offer by a constant
163 */
164 public void lowerMinUtility() {
165 MIN_UTILITY_TO_OFFER -= OFFER_GROUP_SIZE;
166 lastTimeMinUtilityWasLowered = timeline.getTime();
167 System.out.println("Lowering MIN_UTILITY_TO_OFFER to: " + MIN_UTILITY_TO_OFFER + " in round: " + rounds);
168 }
169
170 /**
171 * @return the bid we want to offer when we're the first one to make a bid
172 * @throws Exception
173 */
174 public Action getFirstBid() throws Exception {
175 // As our first bid we want to offer our best bid possible
176 return new Offer(getPartyId(), utilitySpace.getMaxUtilityBid());
177 }
178
179 /**
180 * @return all possible bids in the range of our min utility + constant
181 */
182 public List<BidDetails> getPossibleBids() {
183 Range range = new Range(MIN_UTILITY_TO_OFFER, MIN_UTILITY_TO_OFFER + OFFER_GROUP_SIZE);
184 List<BidDetails> possibleBids = outcomeSpace.getBidsinRange(range);
185 return possibleBids;
186 }
187
188 /**
189 * Switches from using Hamming distance to choose a bid to use our opponent
190 * modeling instead
191 */
192 private void switchToOms() {
193 isUsingOMS = true;
194 MIN_UTILITY_TO_OFFER = 0.95; // We might choose other offers than before
195 TIME_TO_LOWER_MIN_UTILITY = (1 / 3.0) / 6.0; // Only 1/3 of the time is
196 // left and we want to
197 // concede to utility
198 // 0.7
199 lastTimeMinUtilityWasLowered = timeline.getTime();
200 System.out.println("CHANGING TO OMS in round: " + rounds);
201 System.out.println("Setting min utility to: " + MIN_UTILITY_TO_OFFER);
202 }
203
204 /**
205 * @param all
206 * possible bids in some range
207 * @return bid with smallest sum of Hamming distance to all opponents from
208 * the list of bids
209 */
210 private Bid getBidWithSmallestHammingDistance(List<BidDetails> bids) {
211 System.out.println("---- BS Hamming ----");
212 Bid bestBid = null; // If it doesn't succeed to calc Hamming distance
213 int smallestDist = Integer.MAX_VALUE;
214
215 for (BidDetails b : bids) {
216 if (bidsOffered.contains(b.getBid())) { // Don't offer same bid
217 // twice
218 System.out.println("Has offered bid before: " + b.getBid());
219 continue;
220 }
221 int totalDist = 0;
222
223 for (String opponent : om.getOpponents()) {
224 totalDist += getHammingDistance(b.getBid(), om.getLastBidFromAgent(opponent));
225 }
226
227 if (totalDist < smallestDist) {
228 smallestDist = totalDist;
229 bestBid = b.getBid();
230 }
231 }
232 System.out.println("Smallest dist found: " + smallestDist);
233
234 bidsOffered.add(bestBid);
235 return bestBid;
236 }
237
238 /**
239 * @param bid1
240 * @param bid2
241 * @return Hamming distance between bid1 and bid2
242 */
243 private int getHammingDistance(Bid bid1, Bid bid2) {
244 int dist = 0;
245 List<Issue> issues = bid1.getIssues();
246 for (Issue issue : issues) {
247 int indexOfIssue = issues.indexOf(issue) + 1;
248 try {
249 if (!bid1.getValue(indexOfIssue).equals(bid2.getValue(indexOfIssue))) {
250 dist++;
251 }
252 } catch (Exception e) {
253 System.out.println("BS Could not calculate Hamming distance between " + bid1 + " and " + bid2);
254 e.printStackTrace();
255 }
256 }
257
258 return dist;
259 }
260
261 /**
262 * @return average time in seconds for each round
263 */
264 public double measureAverageRoundTime() {
265 timeCount++;
266 double roundAvgTime = 0;
267 if (roundStartTime != 0) {
268 long roundEndTime = System.nanoTime();
269 long roundTime = roundEndTime - roundStartTime;
270 double roundTimeSeconds = (double) roundTime / 1000000000.0;
271 roundTotalTime += roundTimeSeconds;
272 roundAvgTime = (roundTotalTime / (timeCount - 1));
273 }
274 ourStartTime = System.nanoTime();
275 roundStartTime = System.nanoTime();
276
277 return roundAvgTime;
278 }
279
280 /**
281 * @param min
282 * utility wanted
283 * @param max
284 * utility wanted
285 * @return random bid with utility between min and max
286 */
287 private Bid getRandomBidInInterval(double min, double max) {
288 System.out.println("WARNING: Offering random bid in range: " + min + " - " + max);
289 Random rand = new Random();
290 double randomUtility = min + (max - min) * rand.nextDouble();
291 BidDetails bidDetails = outcomeSpace.getBidNearUtility(randomUtility);
292 return bidDetails.getBid();
293 }
294
295 /**
296 *
297 * @param sender
298 * The party that did the action.
299 * @param action
300 * The action that party did.
301 */
302 @Override
303 public void receiveMessage(AgentID sender, Action action) {
304 System.out.println("--- BS receive msg ---");
305 super.receiveMessage(sender, action);
306 System.out
307 .println("Receive " + action.getClass() + " at time: " + timeline.getTime() + " from agent " + sender);
308 if (action instanceof Offer && sender != null) {
309 lastBid = DefaultAction.getBidFromAction(action);
310 om.updateModel(sender.toString(), lastBid, rounds);
311 }
312 }
313
314 @Override
315 public String getDescription() {
316 return "Multi Party Negotiation Agent Group 15";
317 }
318
319 @Override
320 public Class<? extends DefaultMultilateralProtocol> getProtocol() {
321 return StackedAlternatingOffersProtocol.class;
322 }
323
324}
Note: See TracBrowser for help on using the repository browser.