source: src/main/java/agents/anac/y2019/kakesoba/KakeSoba.java@ 346

Last change on this file since 346 was 204, checked in by Katsuhide Fujita, 5 years ago

Fixed errors of ANAC2019 agents

  • Property svn:executable set to *
File size: 12.7 KB
Line 
1package agents.anac.y2019.kakesoba;
2
3import genius.core.Bid;
4import genius.core.BidIterator;
5import genius.core.Domain;
6import genius.core.actions.*;
7import genius.core.issue.Issue;
8import genius.core.issue.IssueDiscrete;
9import genius.core.issue.ValueDiscrete;
10import genius.core.parties.AbstractNegotiationParty;
11import genius.core.parties.NegotiationInfo;
12import genius.core.uncertainty.AdditiveUtilitySpaceFactory;
13import genius.core.uncertainty.BidRanking;
14import genius.core.utility.AbstractUtilitySpace;
15import genius.core.utility.AdditiveUtilitySpace;
16import genius.core.utility.EvaluatorDiscrete;
17import genius.core.timeline.Timeline.Type;
18
19import java.util.*;
20
21/**
22 * KakeSoba
23 */
24public class KakeSoba extends AbstractNegotiationParty {
25 private int nrChosenActions = 0; // number of times chosenAction was called.
26 private boolean isFirstParty;
27 private boolean isDebug = false;
28 private boolean isInvalid = false;
29 private Map<String, Map<String, Double>> counts = new HashMap<String, Map<String, Double>>();
30
31 @Override
32 public void init(NegotiationInfo info) {
33 super.init(info);
34
35 if (!(utilitySpace instanceof AdditiveUtilitySpace)) {
36 System.out.println("This agent displays more interesting behavior with a additive utility function; now it simply generates random bids.");
37 isInvalid = true;
38 return;
39 }
40
41 AdditiveUtilitySpace additiveUtilitySpace = (AdditiveUtilitySpace) utilitySpace;
42 for (Issue issue : additiveUtilitySpace.getDomain().getIssues()) {
43 if (!(issue instanceof IssueDiscrete)) {
44 System.out.println("This agent displays more interesting behavior with a discrete issue domain; now it simply generates random bids.");
45 isInvalid = true;
46 return;
47 }
48 Map<String, Double> h = new HashMap<String, Double>();
49 for (ValueDiscrete value : ((IssueDiscrete)issue).getValues()) {
50 h.put(value.getValue(), 0.0D);
51 }
52 counts.put(issue.getName(), h);
53 }
54 }
55
56 public Action chooseAction(List<Class<? extends Action>> validActions) {
57 double t = this.getTimeLine().getTime();
58 nrChosenActions++;
59
60 if (this.isInvalid) {
61 return new Offer(getPartyId(), generateRandomBid());
62 }
63
64 if (!(getLastReceivedAction() instanceof Offer) && !(getLastReceivedAction() instanceof Accept)){
65 isFirstParty = true;
66 }
67
68 if (getLastReceivedAction() instanceof Offer) {
69 Bid receivedBid = ((Offer) getLastReceivedAction()).getBid();
70
71 if (isAcceptableBid(receivedBid, t)) {
72 return new Accept(getPartyId(), receivedBid);
73 }
74
75 if (timeline.getType() == Type.Rounds) {
76 if (!isFirstParty && timeline.getCurrentTime() >= timeline.getTotalTime() - 1) {
77 if (this.utilitySpace.getUtilityWithDiscount(receivedBid, t) > this.utilitySpace.getReservationValueWithDiscount(t)) {
78 return new Accept(getPartyId(), receivedBid);
79 }
80 }
81 }
82 }
83
84 if (isDebug) {
85 System.out.println(getPartyId() + ": " + getError());
86 System.out.println(getPartyId() + ": " + counts);
87 System.out.println(getPartyId() + ": " + utilitySpace);
88 }
89
90 if(nrChosenActions == 1) {
91 try {
92 Bid bid = getUtilitySpace().getMaxUtilityBid();
93 countBid(bid);
94 return new Offer(getPartyId(), bid);
95 } catch (Exception e) {
96 e.printStackTrace();
97 }
98 }
99
100 Bid bid = generateBid(t);
101 countBid(bid);
102 return new Offer(getPartyId(), bid);
103 }
104
105 private void countBid(Bid bid, double weight) {
106 for (Issue issue : bid.getIssues()) {
107 Map<String, Double> h = counts.get(issue.getName());
108 String value = ((ValueDiscrete) bid.getValue(issue)).getValue();
109 h.put(value, h.get(value) + weight);
110 }
111 }
112
113 private void countBid(Bid bid) { countBid(bid, 1.0D); }
114
115 private double getError() {
116 double error = 0.0D;
117
118 AdditiveUtilitySpace additiveUtilitySpace = (AdditiveUtilitySpace) utilitySpace;
119 for (Issue issue : additiveUtilitySpace.getDomain().getIssues()) {
120 Map<String, Double> h = counts.get(issue.getName());
121 EvaluatorDiscrete evaluator = (EvaluatorDiscrete) additiveUtilitySpace.getEvaluator(issue);
122 double max = h.values().stream().mapToDouble(Double::doubleValue).max().getAsDouble();
123 for (ValueDiscrete value : ((IssueDiscrete) issue).getValues()) {
124 error += Math.abs((h.get(value.getValue()) / max) - evaluator.getDoubleValue(value));
125 }
126 }
127 return error;
128 }
129
130 private double getErrorWithNewBid(Bid bid) {
131 double error;
132
133 countBid(bid, 1.0D);
134 error = getError();
135 countBid(bid, -1.0D);
136
137 return error;
138 }
139
140 private Bid generateBid(double t) {
141 BidIterator bidIterator = new BidIterator(this.getDomain());
142
143 Bid bestBid;
144 try {
145 bestBid = utilitySpace.getMaxUtilityBid();
146 } catch (Exception e) {
147 bestBid = bidIterator.next();
148 }
149 double minError = getErrorWithNewBid(bestBid);
150 while (bidIterator.hasNext()) {
151 Bid bid = bidIterator.next();
152 if (!isProposableBid(bid, t)) {
153 continue;
154 }
155 double error = getErrorWithNewBid(bid);
156 if (error < minError) {
157 bestBid = bid;
158 minError = error;
159 }
160 }
161 return bestBid;
162 }
163
164 private boolean isProposableBid(Bid bid, double t) {
165 double utility ;
166 try {
167 utility = utilitySpace.getUtilityWithDiscount(bid, t);
168 } catch (Exception e) {
169 utility = -1.0D;
170 }
171
172 return getLowerBound(t) <= utility && utility <= getUpperBound(t) && utility >= utilitySpace.getReservationValueWithDiscount(t);
173 }
174
175 private boolean isAcceptableBid(Bid bid, double t) {
176 double utility ;
177 try {
178 utility = utilitySpace.getUtilityWithDiscount(bid, t);
179 } catch (Exception e) {
180 utility = -1.0D;
181 }
182
183 return getLowerBound(t) <= utility && utility >= utilitySpace.getReservationValueWithDiscount(t);
184 }
185
186 private double getUpperBound(double t) {
187 return 1.0D;
188 }
189
190 private double getLowerBound(double t) {
191 return 0.85D;
192 }
193
194 public AbstractUtilitySpace estimateUtilitySpace() {
195 List<Movement> TabuList = new ArrayList<Movement>();
196 AdditiveUtilitySpace additiveUtilitySpace = generateRandomUtilitySpace();
197 AdditiveUtilitySpace hallOfFame = additiveUtilitySpace;
198 double hallOfFameScore = getScore(hallOfFame, false);
199
200 if (this.isInvalid) {
201 return defaultUtilitySpaceEstimator(getDomain(), userModel);
202 }
203
204 int domainSize = 0;
205 for (Issue issue : this.getDomain().getIssues()) {
206 domainSize += ((IssueDiscrete) issue).getValues().size() + 1;
207 }
208
209 int numOfMovement = 5000;
210 final double wightRate = this.getDomain().getIssues().size() * 1.0D / domainSize;
211
212 for (int i = 0; i < numOfMovement; i ++) {
213 Map<Movement, AdditiveUtilitySpace> moveToNeighbors = new HashMap<Movement, AdditiveUtilitySpace>();
214
215 for (int j = 0; j < domainSize; j ++) {
216 Movement movement = new Movement(this.getDomain(), wightRate);
217 while (TabuList.contains(movement)) {
218 movement = new Movement(this.getDomain(), wightRate);
219 }
220 moveToNeighbors.put(movement, getNeighbor(additiveUtilitySpace, movement));
221 }
222
223 Iterator<Map.Entry<Movement, AdditiveUtilitySpace>> iterator = moveToNeighbors.entrySet().iterator();
224 Map.Entry<Movement, AdditiveUtilitySpace> bestEntry = iterator.next();
225 double bestScore = -100.0D;
226 while (iterator.hasNext()) {
227 Map.Entry<Movement, AdditiveUtilitySpace> entry = iterator.next();
228 double score = getScore(entry.getValue(), false);
229 if (score > bestScore) {
230 bestEntry = entry;
231 bestScore = score;
232 }
233 }
234
235 additiveUtilitySpace = bestEntry.getValue();
236 if (bestScore > hallOfFameScore) {
237 hallOfFame = additiveUtilitySpace;
238 hallOfFameScore = bestScore;
239 }
240
241 TabuList.add(bestEntry.getKey());
242 if (TabuList.size() > Math.sqrt(domainSize) / 2) {
243 TabuList.remove(0);
244 }
245
246 if (isDebug) {
247 getScore(additiveUtilitySpace, true);
248 }
249 }
250
251 if (isDebug) {
252 getScore(additiveUtilitySpace, true);
253 }
254
255 return hallOfFame;
256 }
257
258 private double getScore(AdditiveUtilitySpace additiveUtilitySpace, boolean isPrint) {
259 BidRanking bidRank = this.userModel.getBidRanking();
260
261 Map<Bid, Integer> realRanks = new HashMap<Bid, Integer>();
262 List<Double> estimatedUtils = new ArrayList<Double>();
263 for (Bid bid : bidRank.getBidOrder()) {
264 realRanks.put(bid, realRanks.size());
265 estimatedUtils.add(additiveUtilitySpace.getUtility(bid));
266 }
267 Collections.sort(estimatedUtils);
268
269 Map<Bid, Integer> estimatedRanks = new HashMap<Bid, Integer>();
270 for (Bid bid : bidRank.getBidOrder()) {
271 estimatedRanks.put(bid, estimatedUtils.indexOf(additiveUtilitySpace.getUtility(bid)));
272 }
273
274 double errors = 0;
275 for (Bid bid : bidRank.getBidOrder()) {
276 errors += Math.pow(realRanks.get(bid) - estimatedRanks.get(bid), 2);
277 }
278
279 double spearman = 1.0D - 6.0D * errors / (Math.pow(realRanks.size(), 3) - realRanks.size());
280 double lowDiff = Math.abs(bidRank.getLowUtility().doubleValue() - additiveUtilitySpace.getUtility(bidRank.getMinimalBid()));
281 double highDiff = Math.abs(bidRank.getHighUtility().doubleValue() - additiveUtilitySpace.getUtility(bidRank.getMaximalBid()));
282 if(isPrint) {
283 System.out.println("spearman = " + spearman + ", lowDiff = " + lowDiff + ", highDiff = " + highDiff);
284 }
285
286 return spearman * 10.0D + (1.0D - lowDiff) + (1.0D - highDiff);
287 }
288
289
290 private AdditiveUtilitySpace generateRandomUtilitySpace() {
291 AdditiveUtilitySpaceFactory additiveUtilitySpaceFactory = new AdditiveUtilitySpaceFactory(this.getDomain());
292
293 for (IssueDiscrete issue : additiveUtilitySpaceFactory.getIssues()) {
294 additiveUtilitySpaceFactory.setWeight(issue, this.rand.nextDouble());
295
296 for (ValueDiscrete value : issue.getValues()) {
297 additiveUtilitySpaceFactory.setUtility(issue, value, this.rand.nextDouble());
298 }
299 }
300
301 normalize(additiveUtilitySpaceFactory);
302 return additiveUtilitySpaceFactory.getUtilitySpace();
303 }
304
305 private AdditiveUtilitySpace getNeighbor(AdditiveUtilitySpace current, Movement movement) {
306 double speed = 1.0D;
307 AdditiveUtilitySpaceFactory neighbor = getAdditiveUtilitySpaceFactoryFrom(current);
308
309 IssueDiscrete issue = neighbor.getIssues().get(movement.getIssueID());
310 if (movement.getIsWeight()) {
311 if (rand.nextBoolean()) {
312 neighbor.setWeight(issue, current.getWeight(issue) + speed * rand.nextDouble() / neighbor.getIssues().size());
313 } else {
314 neighbor.setWeight(issue, Math.abs(current.getWeight(issue) - speed * rand.nextDouble() / neighbor.getIssues().size()));
315 }
316
317 } else {
318 double averageEval = 0;
319 for (ValueDiscrete v : issue.getValues()) {
320 averageEval += ((EvaluatorDiscrete)current.getEvaluator(issue)).getDoubleValue(v);
321 }
322 averageEval /= issue.getValues().size();
323
324 ValueDiscrete value = issue.getValue(movement.getValueID());
325 double eval = ((EvaluatorDiscrete)current.getEvaluator(issue)).getDoubleValue(value);
326 if (rand.nextBoolean()) {
327 neighbor.setUtility(issue, value, eval + speed * averageEval * rand.nextDouble());
328 } else {
329 neighbor.setUtility(issue, value, Math.abs(eval - speed * averageEval * rand.nextDouble()));
330 }
331 }
332
333 normalize(neighbor);
334 return neighbor.getUtilitySpace();
335 }
336
337 private AdditiveUtilitySpaceFactory getAdditiveUtilitySpaceFactoryFrom(AdditiveUtilitySpace additiveUtilitySpace){
338 AdditiveUtilitySpaceFactory additiveUtilitySpaceFactory = new AdditiveUtilitySpaceFactory(getDomain());
339 for (IssueDiscrete issue : additiveUtilitySpaceFactory.getIssues()) {
340 additiveUtilitySpaceFactory.setWeight(issue, additiveUtilitySpace.getWeight(issue));
341 for (ValueDiscrete value : issue.getValues()) {
342 additiveUtilitySpaceFactory.setUtility(issue, value, ((EvaluatorDiscrete) additiveUtilitySpace.getEvaluator(issue)).getDoubleValue(value));
343 }
344 }
345 return additiveUtilitySpaceFactory;
346 }
347
348 private void normalize(AdditiveUtilitySpaceFactory additiveUtilitySpaceFactory){
349 additiveUtilitySpaceFactory.normalizeWeights();
350
351 for (IssueDiscrete issue : additiveUtilitySpaceFactory.getIssues()) {
352 double max = issue.getValues().stream().map(value -> additiveUtilitySpaceFactory.getUtility(issue, value)).max(Double::compareTo).get();
353 for (ValueDiscrete value : issue.getValues()) {
354 double eval = additiveUtilitySpaceFactory.getUtility(issue, value);
355 additiveUtilitySpaceFactory.setUtility(issue, value, eval / max);
356 }
357 }
358 }
359
360 public String getDescription() {
361 return "KakeSoba";
362 }
363
364
365 private class Movement {
366 private int issueID;
367 private int valueID;
368 private boolean isWeight;
369
370 public Movement(int issueID, int valueID) {
371 this.issueID = issueID;
372 this.valueID = valueID;
373 this.isWeight = false;
374 }
375
376 public Movement(int issueID) {
377 this.issueID = issueID;
378 this.valueID = 0;
379 this.isWeight = true;
380 }
381
382 public Movement(Domain domain, double wightRate) {
383 List<Issue> issues = domain.getIssues();
384 this.issueID = rand.nextInt(issues.size());
385
386 if (rand.nextDouble() > wightRate) {
387 this.isWeight = true;
388 this.valueID = 0;
389 } else {
390 this.isWeight = false;
391 this.valueID = rand.nextInt(((IssueDiscrete) issues.get(this.issueID)).getNumberOfValues());
392 }
393 }
394
395 private int getIssueID() {
396 return this.issueID;
397 }
398
399 private int getValueID() {
400 return this.valueID;
401 }
402
403 private boolean getIsWeight() {
404 return this.isWeight;
405 }
406 }
407}
Note: See TracBrowser for help on using the repository browser.