source: exampleparties/anac2019/winkyagent/src/main/java/geniusweb/exampleparties/anac2019/winkyagent/WinkyAgent.java@ 29

Last change on this file since 29 was 29, checked in by bart, 3 years ago

some minor fixes

File size: 13.7 KB
Line 
1package geniusweb.exampleparties.anac2019.winkyagent;
2
3import java.io.IOException;
4import java.util.ArrayList;
5import java.util.Arrays;
6import java.util.Collections;
7import java.util.Comparator;
8import java.util.HashMap;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Map;
12import java.util.Random;
13import java.util.logging.Level;
14
15import javax.websocket.DeploymentException;
16
17import geniusweb.actions.Accept;
18import geniusweb.actions.Action;
19import geniusweb.actions.Offer;
20import geniusweb.actions.PartyId;
21import geniusweb.bidspace.AllBidsList;
22import geniusweb.inform.ActionDone;
23import geniusweb.inform.Finished;
24import geniusweb.inform.Inform;
25import geniusweb.inform.Settings;
26import geniusweb.inform.YourTurn;
27import geniusweb.issuevalue.Bid;
28import geniusweb.issuevalue.DiscreteValue;
29import geniusweb.issuevalue.DiscreteValueSet;
30import geniusweb.issuevalue.Domain;
31import geniusweb.issuevalue.Value;
32import geniusweb.party.Capabilities;
33import geniusweb.party.DefaultParty;
34import geniusweb.profile.DefaultPartialOrdering;
35import geniusweb.profile.PartialOrdering;
36import geniusweb.profileconnection.ProfileConnectionFactory;
37import geniusweb.profileconnection.ProfileInterface;
38import geniusweb.progress.ProgressRounds;
39import tudelft.utilities.logging.Reporter;
40
41/**
42 * This is translated version of WinkyAgent, winner from ANAC2019. Authors Siqi
43 * Chen and Jie Lin Tianjin University China.
44 *
45 * <p>
46 * IMPORTANT This party requires a {@link ProgressRounds}, and the domain must
47 * contain only {@link DiscreteValue}s.
48 * <p>
49 * WARNING this contains poor code and is here just for comparison and testing.
50 */
51public class WinkyAgent extends DefaultParty {
52
53 private Bid lastReceivedBid = null;
54 private Map<Bid, Double> receiveBids = new HashMap<Bid, Double>();
55 private List<Bid> bidOrder = null;
56 int utilitySize = 0;
57 int ranklistSize = 0;
58 double receivehighestUtility = 0.0;// 接收过的最高出价的效用
59 List<String> issueList = null;// issue列表
60 int issueSize = 0;// issue个数
61 int valueSum = 0;// value个数
62 double initUtility = 0.0;// value初始效用
63 Map<DiscreteValue, Double> valueCorrespond = new HashMap<DiscreteValue, Double>();// value和对应效用
64 DiscreteValue[] values = null;// value数组
65 double learningRate;
66 List<Map.Entry<Bid, Double>> list = new ArrayList<>();// 对receiveBids按照效用进行排序后得到的list
67 boolean listSort = true;
68 boolean lastBidTag = true;
69
70 // new fields
71 private PartyId me;
72 private ProgressRounds progress;
73 private PartialOrdering partialprofile;
74 private AllBidsList allbids; // all bids in the domain.
75 private final Random rand = new Random();
76 private SimpleLinearOrdering simpleOrdering;
77
78 public WinkyAgent() {
79 super();
80 }
81
82 public WinkyAgent(Reporter reporter) {
83 super(reporter);
84 }
85
86 @Override
87 public void notifyChange(Inform info) {
88 try {
89 if (info instanceof Settings) {
90 init((Settings) info);
91 } else if (info instanceof ActionDone) {
92 Action lastReceivedAction = ((ActionDone) info).getAction();
93 if (lastReceivedAction instanceof Offer) {
94 receivOffer((Offer) lastReceivedAction);
95 }
96 } else if (info instanceof YourTurn) {
97 Action action = chooseAction();
98 getConnection().send(action);
99 progress = progress.advance();
100 } else if (info instanceof Finished) {
101 getReporter().log(Level.INFO, "Final ourcome:" + info);
102 }
103 } catch (Exception e) {
104 throw new RuntimeException("Failed to handle info", e);
105 }
106 }
107
108 @Override
109 public Capabilities getCapabilities() {
110 return new Capabilities(new HashSet<>(Arrays.asList("SAOP")),
111 Collections.singleton(DefaultPartialOrdering.class));
112 }
113
114 @Override
115 public String getDescription() {
116 return "ANAC 2019 WinkyAgent translated to GeniusWeb. Requires partial profile. ";
117 }
118
119 private void receivOffer(Offer action) {
120 lastReceivedBid = action.getBid();
121 double lastReceivedBidUtility = linearEstUtility(lastReceivedBid);
122 receiveBids.put(lastReceivedBid, lastReceivedBidUtility);
123 if (lastReceivedBidUtility > receivehighestUtility) {
124 receivehighestUtility = lastReceivedBidUtility;
125 }
126
127 }
128
129 private void init(Settings info) throws IOException, DeploymentException {
130 this.me = info.getID();
131 this.progress = (ProgressRounds) info.getProgress();
132
133 ProfileInterface profileint = ProfileConnectionFactory
134 .create(info.getProfile().getURI(), getReporter());
135 partialprofile = (PartialOrdering) profileint.getProfile();
136 Domain domain = partialprofile.getDomain();
137 allbids = new AllBidsList(domain);
138
139 utilitySize = allbids.size().intValue();// 一共可能有多少种出价
140 simpleOrdering = new SimpleLinearOrdering(partialprofile);
141 bidOrder = simpleOrdering.getBids();
142 ranklistSize = bidOrder.size();
143 // THIS FIXES THE ORDER OF THE ISSUES, BACKCOMPATIBILITY issue numbers
144 issueList = new ArrayList<String>(domain.getIssues());
145 issueSize = issueList.size();
146 double[] results = new double[ranklistSize];// Array of given utility
147 for (int i = 0; i < ranklistSize; i++) { // results array initialization
148 results[i] = getBidOrderUtility(bidOrder.get(i));
149 }
150
151 int[] valueSize = new int[issueSize];// 第i个问题有j种选择
152 for (int i = 0; i < issueSize; i++) {
153 String issued = issueList.get(i);
154 valueSize[i] = domain.getValues(issued).size().intValue();
155 valueSum += valueSize[i];
156 }
157 initUtility = 1.0 / valueSum; // value初始化的值
158 learningRate = initUtility / 10.0;
159
160 values = new DiscreteValue[valueSum];// value数组
161 int valuesIndexCnt = 0;
162 while (valuesIndexCnt < valueSum) { // 初始化values数组和map valueCorrespond
163 for (int i = 0; i < issueSize; i++) {
164 String issued = issueList.get(i);
165 DiscreteValueSet availableVals = (DiscreteValueSet) domain
166 .getValues(issued);
167 for (int j = 0; j < availableVals.size().intValue(); j++) {
168 values[valuesIndexCnt] = availableVals.getValues().get(j); // 初始化values数组
169 valueCorrespond.put(values[valuesIndexCnt], initUtility); // 初始化map
170 // valueCorrespond
171 valuesIndexCnt++;
172 }
173 }
174 }
175
176 // bidOrder training set
177 // makes a flat list 2D list
178 // each element is for one of the bids.
179 // valueSum values, in order
180 // of iss1val1, iss1val2,...,iss2val1,iss2val2,...,
181 // issNval1,...,isNvalM.
182 // this fills the features array with 1's
183 // if the bid contains that particular value.
184 int[][] features = new int[ranklistSize][valueSum];
185
186 // Wouter: original code was bugged. #1766. Putting a fix here.
187 for (int bidnr = 0; bidnr < ranklistSize; bidnr++) {
188 Bid bid = bidOrder.get(bidnr);
189 int featurenr = 0;
190 for (String issue : issueList) {
191 Value thisbidvalue = bid.getValue(issue);
192 for (Value value : domain.getValues(issue)) {
193 features[bidnr][featurenr++] = thisbidvalue.equals(value)
194 ? 1
195 : 0;
196 }
197 }
198
199 }
200
201 double[] parameters = new double[valueSum];// Training value
202 for (int i = 0; i < valueSum; i++) {
203 parameters[i] = initUtility;
204 }
205
206 for (int i = 0; i < ranklistSize * valueSum; i++) { // training
207 BGD(features, results, learningRate, parameters);
208 }
209 }
210
211 private void BGD(int[][] features, double[] results, double learningRate,
212 double[] parameters) {
213 for (int t = 0; t < valueSum; t++) {
214 double sum = 0.0;
215 double parametersSum = 0.0;
216 for (int j = 0; j < results.length; j++) {
217 for (int i = 0; i < valueSum; i++) {
218 parametersSum += parameters[i] * features[j][i];
219 }
220 parametersSum = parametersSum - results[j];
221 parametersSum = parametersSum * features[j][t];
222 sum += parametersSum;
223 }
224 double updateValue = 2 * learningRate * sum / results.length;
225 parameters[t] = parameters[t] - updateValue;
226 /**
227 * ValueCorrespond is bugged, because it uses issuevalues as key
228 * while issuevalues may be not unique (multiple issues may have the
229 * same value, eg "yes" and "no".
230 */
231 valueCorrespond.put(values[t], parameters[t]);
232
233 }
234
235 }
236
237 private double linearEstUtility(Bid bid) {
238 double linearUtility = 0.0;
239
240 // Wouter the original code was buggy. Replaced with this better
241 // version. This code is still buggy because of the valueCorrespond
242 // issue.
243 // that issue was not fixed.
244 int featurenr = 0;
245 for (String issue : issueList) {
246 Value thisbidvalue = bid.getValue(issue);
247 for (Value value : partialprofile.getDomain().getValues(issue)) {
248 if (thisbidvalue != null && thisbidvalue.equals(value)) {
249 linearUtility += valueCorrespond.get(value);
250 }
251 featurenr++;
252 }
253 }
254 return linearUtility;
255 }
256
257 /**
258 *
259 * @param bid
260 * @return Estimate known bid utility, equally divided. Seems equal to
261 * {@link SimpleLinearOrdering#getUtility(Bid)}
262 */
263 private double getBidOrderUtility(Bid bid) {
264 return simpleOrdering.getUtility(bid).doubleValue();
265 }
266
267 private Action chooseAction() {
268 int round = progress.getCurrentRound();
269 int tround = progress.getTotalRounds();
270 double receiveBidUtility = 0.0;
271 double bidOrderMax = 1;// getHighUtility();
272 Bid bid;
273 if (round < tround * 0.7) {
274 if (round > 10 && receiveBids.size() < 7) {
275 int temp = (int) Math.ceil(ranklistSize * 0.1);
276 int randz = rand.nextInt(temp);
277 bid = bidOrder.get(ranklistSize - 1 - randz);
278 log("receiveBid<7,bidOrder: " + getBidOrderUtility(bid));
279 return new Offer(me, bid);
280 }
281 bid = generateBid(7, bidOrderMax);
282 return new Offer(me, bid);
283 } else if (round < tround * 0.98) {
284 if (receiveBids.size() < 10) {
285 int temp = (int) Math.ceil(ranklistSize * 0.15);
286 int randz = rand.nextInt(temp);
287 bid = bidOrder.get(ranklistSize - 1 - randz);
288 log("receiveBid<10,bidOrder: " + getBidOrderUtility(bid));
289 return new Offer(me, bid);
290 }
291 bid = generateBid(9, bidOrderMax);
292 return new Offer(me, bid);
293 } else if (round < tround * 0.99) {
294 receiveBidUtility = linearEstUtility(lastReceivedBid);
295 if (listSort) {
296 sortReceive();
297 listSort = false;
298 for (Map.Entry<Bid, Double> entry : list) {
299 System.out.println(entry);
300 }
301 log(receivehighestUtility + "\n");
302 }
303 if (receiveBidUtility > (receivehighestUtility - 0.03)) {
304 return new Accept(me, lastReceivedBid);
305 }
306 bid = generateReceiveBid();
307 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
308 + " accept阈值: " + (receivehighestUtility - 0.07) + "\n");
309 return new Offer(me, bid);
310 } else if (round < tround * 0.995) {
311 receiveBidUtility = linearEstUtility(lastReceivedBid);
312 if (receiveBidUtility > (receivehighestUtility - 0.07)) {
313 return new Accept(me, lastReceivedBid);
314 }
315 bid = generateReceiveBid();
316 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
317 + " accept阈值: " + (receivehighestUtility - 0.11) + "\n");
318 return new Offer(me, bid);
319 } else if (round == (tround - 1)) {
320 return new Accept(me, lastReceivedBid);
321
322 } else {
323 receiveBidUtility = linearEstUtility(lastReceivedBid);
324 if (receiveBidUtility > (receivehighestUtility - 0.1)) {
325 return new Accept(me, lastReceivedBid);
326 }
327 bid = generateReceiveBid();
328 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
329 + " accept阈值: " + (receivehighestUtility - 0.15) + "\n");
330 return new Offer(me, bid);
331 }
332 }
333
334 public Bid generateBid(int zcnt, double bidOrderMax) {
335 Bid randomBid = null;
336 if (lastReceivedBid == null) {
337 List<Bid> b = simpleOrdering.getBids();
338 randomBid = b.get(b.size() - 1);// max bid
339 } else if (zcnt == 7) {
340 if (bidOrderMax > 0.9) {
341 do {
342 randomBid = generateRandomBid();
343 } while (linearEstUtility(randomBid) < 0.82);
344 } else if (bidOrderMax > 0.8) {
345 do {
346 randomBid = generateRandomBid();
347 } while (linearEstUtility(randomBid) < 0.75);
348 } else {
349 do {
350 randomBid = generateRandomBid();
351 } while (linearEstUtility(randomBid) < 0.7);
352 }
353 } else if (zcnt == 9) {
354 if (bidOrderMax > 0.9) {
355 do {
356 randomBid = generateRandomBid();
357 } while (linearEstUtility(randomBid) < 0.8);
358 } else if (bidOrderMax > 0.8) {
359 do {
360 randomBid = generateRandomBid();
361 } while (linearEstUtility(randomBid) < 0.7);
362 } else {
363 do {
364 randomBid = generateRandomBid();
365 } while (linearEstUtility(randomBid) < 0.68);
366 }
367 }
368
369 log(progress.getCurrentRound() + "generateBid: "
370 + linearEstUtility(randomBid));
371 return randomBid;
372 }
373
374 private Bid generateReceiveBid() {
375 Bid bid;
376
377 int listSelectUtility = (int) Math.ceil(list.size() * 0.03);
378 double temp = list.get(listSelectUtility - 1).getValue();
379
380 if (temp < 0.7) {
381 temp = 0.7;
382 do {
383 bid = generateRandomBid();
384 } while (linearEstUtility(bid) < temp);
385 log(progress.getCurrentRound() + " generateRandomBid: "
386 + linearEstUtility(bid) + " temp:" + temp);
387 return bid;
388 } else {
389 if (lastBidTag) {
390 int rand1 = rand.nextInt(listSelectUtility);
391 bid = list.get(rand1).getKey();
392 lastBidTag = false;
393 log(progress.getCurrentRound() + " generateReceiveBid: "
394 + linearEstUtility(bid) + " temp:" + temp);
395 return bid;
396 } else {
397 do {
398 bid = generateRandomBid();
399 } while (linearEstUtility(bid) < temp);
400 lastBidTag = true;
401 log(progress.getCurrentRound() + " generateRandomBid: "
402 + linearEstUtility(bid) + " temp:" + temp);
403 return bid;
404 }
405 }
406
407 }
408
409 private void sortReceive() { // 将收到的出价进行排序
410 for (Map.Entry<Bid, Double> entry : receiveBids.entrySet()) {
411 list.add(entry); // 将map中的元素放入list中
412 }
413
414 list.sort(new Comparator<Map.Entry<Bid, Double>>() {
415 @Override
416 public int compare(Map.Entry<Bid, Double> o1,
417 Map.Entry<Bid, Double> o2) {
418 double result = o2.getValue() - o1.getValue();
419 if (result > 0)
420 return 1;
421 else if (result == 0)
422 return 0;
423 else
424 return -1;
425 }
426 // 逆序(从大到小)排列,正序为“return o1.getValue()-o2.getValue”
427 });
428 }
429
430 private void log(String s) {
431 getReporter().log(Level.INFO, s);
432 }
433
434 private Bid generateRandomBid() {
435 return allbids.get(rand.nextInt(allbids.size().intValue()));
436 }
437
438}
Note: See TracBrowser for help on using the repository browser.