source: src/main/java/parties/in4010/q12015/group20/Group20.java@ 1

Last change on this file since 1 was 1, checked in by Wouter Pasman, 6 years ago

Initial import : Genius 9.0.0

File size: 13.3 KB
Line 
1package parties.in4010.q12015.group20;
2
3import java.util.ArrayList;
4import java.util.Collection;
5import java.util.HashMap;
6import java.util.Iterator;
7import java.util.List;
8
9import genius.core.AgentID;
10import genius.core.Bid;
11import genius.core.actions.Accept;
12import genius.core.actions.Action;
13import genius.core.actions.ActionWithBid;
14import genius.core.actions.DefaultAction;
15import genius.core.actions.Offer;
16import genius.core.issue.Issue;
17import genius.core.issue.IssueDiscrete;
18import genius.core.issue.Value;
19import genius.core.issue.ValueDiscrete;
20import genius.core.parties.AbstractNegotiationParty;
21import genius.core.parties.NegotiationInfo;
22import genius.core.utility.AdditiveUtilitySpace;
23import genius.core.utility.EvaluatorDiscrete;
24
25/**
26 * This is your negotiation party.
27 */
28public class Group20 extends AbstractNegotiationParty {
29
30 // Max > Min
31 private final static double MINUTILSCORE = 0.7;
32 private final static double MAXUTILSCORE = 0.8;
33
34 private Action lastOpponentAction = null;
35 private Double[] ourWeights; // store weights of issues
36 private Bid lastOpOffer = null;
37 private HashMap<Integer, Double[]> choices = new HashMap<Integer, Double[]>(); // store
38 // evaluation
39 // values
40 // for
41 // every
42 // issue
43 private HashMap<Integer, Integer[]> agentIssues = new HashMap<Integer, Integer[]>(); // store
44 // evaluation
45 // values
46 // for
47 // every
48 // issue:
49 // <issueID,
50 // values>
51 private Double[] agentWeights = null; // save weights of opponents'
52 // preference
53
54 /**
55 * Initialization function
56 */
57 @Override
58 public void init(NegotiationInfo info) {
59 super.init(info);
60 agentWeights = new Double[utilitySpace.getDomain().getIssues().size()];
61
62 /*******
63 * reservation value is 0, I believe, read somewhere in the assignment
64 ******/
65 int numIssues = utilitySpace.getDomain().getIssues().size(); // total
66 // number
67 // of
68 // issues
69 ourWeights = new Double[numIssues];
70
71 /********** Store evaluation value for each choice ************/
72 List<Issue> issues = utilitySpace.getDomain().getIssues();
73
74 /**************
75 * initialize on the 1st round, every value equals to 1
76 ***************/
77 for (Issue lIssue : issues) {
78 int issueID = lIssue.getNumber();
79 IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue; // TODO add
80 // non
81 // discrete
82 Integer[] evals = new Integer[lIssueDiscrete.getNumberOfValues()];
83 for (int i = 0; i < lIssueDiscrete.getNumberOfValues(); i++) {
84 evals[i] = 1; // initialize every value to 1
85 }
86 agentIssues.put(issueID, evals);
87 }
88
89 for (Issue lIssue : issues) {
90 int issueID = lIssue.getNumber();
91 agentWeights[issueID - 1] = 1.0 / issues.size(); // initialize the
92 // opponents'
93 // weight
94 ourWeights[issueID - 1] = ((AdditiveUtilitySpace) utilitySpace).getWeight(issueID); // save
95 // weights
96 // of
97 // issues
98 // into
99 // weights[]
100
101 IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue;
102 Double[] evals = new Double[lIssueDiscrete.getNumberOfValues()];
103 EvaluatorDiscrete evaluator = (EvaluatorDiscrete) ((AdditiveUtilitySpace) utilitySpace)
104 .getEvaluator(issueID);
105
106 for (int i = 0; i < lIssueDiscrete.getNumberOfValues(); i++) {
107 ValueDiscrete value = lIssueDiscrete.getValue(i);
108 Double eval = evaluator.getDoubleValue(value); // evaluation of
109 // each choice,
110 // such as
111 // "cocktail","beer
112 // only"
113 evals[i] = eval; // evals[i] is like 5,25,10,....
114 }
115
116 choices.put(issueID, evals);
117 }
118 }
119
120 /**
121 * Each round this method gets called and ask you to accept or offer. The
122 * first party in the first round is a bit different, it can only propose an
123 * offer.
124 *
125 * @param validActions
126 * Either a list containing both accept and offer or only offer.
127 * @return The chosen action.
128 */
129 public Action chooseAction(List<Class<? extends Action>> validActions) {
130 Action action = null;
131
132 try {
133 if (lastOpponentAction == null) {
134 action = createBidAction();
135 }
136
137 if (lastOpponentAction instanceof Offer) {
138 Bid partnerBid = ((Offer) lastOpponentAction).getBid();
139
140 if (isAcceptable(partnerBid)) {
141 return new Accept(getPartyId(), partnerBid);
142 }
143 action = createBidAction();
144 }
145 } catch (Exception e) {
146 System.out.println("Exception in ChooseAction:" + e.getMessage());
147 // !!!!best guess if things go
148 // wrong.
149 return new Accept(getPartyId(), ((ActionWithBid) lastOpponentAction).getBid());
150 }
151 return action;
152 }
153
154 /**
155 * All offers proposed by the other parties will be received as a message.
156 * These offers are used to build a predicted preference profile
157 *
158 * @param sender
159 * The party that did the action.
160 * @param action
161 * The action that party did.
162 */
163 @Override
164 public void receiveMessage(AgentID sender, Action action) {
165 super.receiveMessage(sender, action);
166 if (action != null && action instanceof Offer) {
167 lastOpponentAction = (Offer) action;
168
169 Bid opponentBid = DefaultAction.getBidFromAction(action);
170 predictPreferences(opponentBid);
171 lastOpOffer = opponentBid; // save the offer of opponent
172 }
173
174 }
175
176 /**
177 * Predict opponents preferences using Frequency Analysis Heuristic Instead
178 * of two preferences, generate a preference profile for all the opponents
179 *
180 * @param agentID
181 * @param agentBid
182 */
183 private void predictPreferences(Bid agentBid) {
184 /********** save issues of the opponent ***********/
185 List<Issue> opponentIssues = agentBid.getIssues();
186
187 /***************** update each round ********************/
188 for (Issue lIssue : opponentIssues) {
189 int issueID = lIssue.getNumber(); // issueID starts from 1
190 IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue; // TODO add
191 // non
192 // discrete
193 lIssueDiscrete.getNumberOfValues();
194 int valIndex = 0; // valIndex starts from 0
195
196 try {
197 valIndex = lIssueDiscrete.getValueIndex((ValueDiscrete) agentBid.getValue(issueID)); // find
198 // index
199 // of
200 // value
201 // in
202 // issue
203
204 /*********** refresh weights *********/
205 if (lastOpOffer != null && lastOpOffer.getValue(issueID).equals(agentBid.getValue(issueID))) {
206 Double[] newWeights = refreshWeight(agentWeights, issueID, 0.1).clone();
207 agentWeights = newWeights.clone();
208 }
209 } catch (Exception e) {
210 e.printStackTrace();
211 }
212
213 if (agentIssues.containsKey(issueID)) {
214
215 Integer[] values = agentIssues.get(issueID).clone();
216 values[valIndex] = values[valIndex] + 1; // every time the bid
217 // appeared, give it
218 // plus 1 value
219 if (agentIssues.containsKey(issueID)) {
220 agentIssues.put(issueID, values.clone());
221 }
222 }
223 }
224
225 }
226
227 /**
228 * Create a bid or accept
229 *
230 * @return Created action can be offer or accept action
231 */
232 private Action createBidAction() {
233 Bid nextBid = null;
234
235 try {
236 nextBid = getOurNewBid();
237 } catch (Exception e) {
238 System.out.println("Problem with received bid:" + e + ". cancelling bidding");
239 }
240
241 if (nextBid == null) {
242 System.out.println("Should not happen.");
243 return (new Accept(getPartyId(), ((ActionWithBid) lastOpponentAction).getBid()));
244 }
245 return (new Offer(getPartyId(), nextBid));
246 }
247
248 /**
249 * Checks if we want to accept a bid. Accepting is based on the given bid
250 * having a higher utility value than that we currently have as a minimum
251 *
252 * @param partnerBid
253 * the bid we want to check
254 * @return true or false
255 * @throws Exception
256 */
257 private boolean isAcceptable(Bid partnerBid) throws Exception {
258 boolean isAccept = false;
259 double acceptUtil = getMinUtilValue();
260 if (acceptUtil < utilitySpace.getUtility(partnerBid)) {
261 isAccept = true;
262 }
263 return isAccept;
264 }
265
266 /**
267 * Get the minimum utility value based on the current negotiation time
268 *
269 * @return minimum utility
270 */
271 private double getMinUtilValue() {
272 return MINUTILSCORE + (timeline.getTime() * (MAXUTILSCORE - MINUTILSCORE));
273 }
274
275 /**
276 * Get a new bid
277 *
278 * @return a new bid being a combination of opponets possible max utility
279 * adjusted to our min utility score.
280 * @throws Exception
281 */
282 private Bid getOurNewBid() throws Exception {
283 Bid maxOppBid = createMaxOpponentBid();
284 compromiseBid(maxOppBid);
285 return maxOppBid;
286
287 }
288
289 /**
290 * Create the maximum possible bid for the opponents based on the predicted
291 * preference profile that was formed of them.
292 *
293 * @return Bid with maximum utility score for all opponents
294 * @throws Exception
295 */
296 private Bid createMaxOpponentBid() throws Exception {
297 Bid bid = null;
298 Collection<Integer[]> valueList = agentIssues.values();
299 int i = 1;
300 HashMap<Integer, Value> tmpValues = new HashMap<Integer, Value>();
301 for (Iterator iterator = valueList.iterator(); iterator.hasNext(); i++) {
302 int maxIndex = getIndexMaxValue((Integer[]) iterator.next());
303 ValueDiscrete maxPreValue = ((IssueDiscrete) ((AdditiveUtilitySpace) utilitySpace).getIssue(i - 1))
304 .getValue(maxIndex);
305 tmpValues.put(i, maxPreValue);
306 }
307
308 bid = new Bid(utilitySpace.getDomain(), tmpValues);
309 return bid;
310 }
311
312 /**
313 * Get the index of the element with the maximum
314 *
315 * @param primArray
316 * @return index of maxvalue from primarray
317 */
318 private int getIndexMaxValue(Integer[] primArray) {
319 int max = -1;
320 int index = -1;
321 for (int i = 0; i < primArray.length; i++) {
322 if (primArray[i] > max) {
323 max = primArray[i];
324 index = i;
325 }
326 }
327 return index;
328 }
329
330 /**
331 * Given a Bid, increase the bid until we get to a value that is acceptable
332 * for us. The issue to change is chosen where our weight is high while the
333 * predicted opponents weight is low. This makes it so that for us there is
334 * a high change in utility while for the opponent the change is minimal.
335 *
336 * @param maxOppBid
337 * Bid to adjust
338 * @throws Exception
339 */
340 private void compromiseBid(Bid maxOppBid) throws Exception {
341 ArrayList<Double> diffList = getDiffList();
342 int issueId;
343 while (utilitySpace.getUtility(maxOppBid) < getMinUtilValue()) {
344 issueId = getMaxID(diffList);
345 ValueDiscrete newValue = getMaxIssueValue(issueId);
346 maxOppBid = maxOppBid.putValue(issueId, newValue);
347 }
348 }
349
350 /**
351 * Get the maximal value for a certain discrete issue
352 *
353 * @param issueId
354 * @return maximum vallue for issueID
355 */
356 private ValueDiscrete getMaxIssueValue(int issueId) {
357 Double max = Double.MIN_VALUE;
358 int idx = -1;
359 Double[] values = choices.get(issueId);
360 for (int i = 0; i < values.length; i++) {
361 if (values[i] > max) {
362 max = values[i];
363 idx = i;
364 }
365 }
366 return ((IssueDiscrete) ((AdditiveUtilitySpace) utilitySpace).getIssue(issueId - 1)).getValue(idx);
367 }
368
369 /**
370 * Returns the ID of maximum difference, and sets that index to minimal
371 * value
372 *
373 * @param diffList
374 * @return ID of the issue (starts at 1)
375 */
376 private int getMaxID(ArrayList<Double> diffList) {
377 int id = -1;
378 double maxDiff = Double.MIN_VALUE;
379
380 for (int i = 0; i < diffList.size(); i++) {
381 if (diffList.get(i) > maxDiff) {
382 id = i + 1;
383 maxDiff = diffList.get(i);
384 }
385 }
386
387 diffList.set(id - 1, -1.0);
388
389 return id;
390 }
391
392 /**
393 * Creates a differences list of the differences between our domain weights
394 * and the predicted weights of the opponents.
395 *
396 * @return list of differences in weight
397 */
398 private ArrayList<Double> getDiffList() {
399 ArrayList<Double> diffList = new ArrayList<Double>();
400 for (int j = 0; j < agentWeights.length; j++) {
401 diffList.add(ourWeights[j] - agentWeights[j] + 1);
402 }
403 return diffList;
404 }
405
406 /**
407 * Refresh and update opponents weights
408 *
409 * @param opWeights
410 * @param issueID
411 * @param n
412 * @return
413 */
414 public Double[] refreshWeight(Double[] opWeights, int issueID, double n) {
415 opWeights[issueID - 1] = opWeights[issueID - 1] + n; // issueID starts
416 // from 1
417 Double[] newWeights = opWeights.clone();
418 double sum = 0;
419
420 for (int i = 0; i < newWeights.length; i++) {
421 sum += newWeights[i];
422 }
423
424 for (int i = 0; i < newWeights.length; i++) {
425 newWeights[i] = newWeights[i] / sum;
426 }
427
428 return newWeights;
429 }
430
431 /**
432 * Returns the predicted utility function for a opponent
433 *
434 * @param agentID
435 * @param bid
436 * @return
437 * @throws Exception
438 */
439 public double predictUtility(AgentID agentID, Bid bid) throws Exception {
440 double opUtility = 0;
441 List<Issue> issueList = bid.getIssues();
442
443 for (Issue lIssue : issueList) {
444 int issueID = lIssue.getNumber(); // issueID starts from 1
445 IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue;
446 Integer[] values = agentIssues.get(issueID).clone();
447 double sumValues = 0;
448
449 for (int i = 0; i < values.length; i++) {
450 if (values[i] == null)
451 values[i] = 1; // or other values, to escape
452 // nullpointerexception;
453 sumValues += values[i];
454 }
455
456 int valIndex = lIssueDiscrete.getValueIndex((ValueDiscrete) bid.getValue(issueID));
457 opUtility += agentWeights[issueID - 1] * values[valIndex] / sumValues;
458
459 }
460
461 return opUtility;
462
463 }
464
465 @Override
466 public String getDescription() {
467 return "Party group 20";
468 }
469
470}
Note: See TracBrowser for help on using the repository browser.