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

Last change on this file since 52 was 52, checked in by ruud, 14 months ago

Fixed small issues in domaineditor.

File size: 13.8 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 terminate(); // stop this party and free resources.
103 }
104 } catch (Exception e) {
105 throw new RuntimeException("Failed to handle info", e);
106 }
107 }
108
109 @Override
110 public Capabilities getCapabilities() {
111 return new Capabilities(new HashSet<>(Arrays.asList("SAOP")),
112 Collections.singleton(DefaultPartialOrdering.class));
113 }
114
115 @Override
116 public String getDescription() {
117 return "ANAC 2019 WinkyAgent translated to GeniusWeb. Requires partial profile. ";
118 }
119
120 private void receivOffer(Offer action) {
121 lastReceivedBid = action.getBid();
122 double lastReceivedBidUtility = linearEstUtility(lastReceivedBid);
123 receiveBids.put(lastReceivedBid, lastReceivedBidUtility);
124 if (lastReceivedBidUtility > receivehighestUtility) {
125 receivehighestUtility = lastReceivedBidUtility;
126 }
127
128 }
129
130 private void init(Settings info) throws IOException, DeploymentException {
131 this.me = info.getID();
132 this.progress = (ProgressRounds) info.getProgress();
133
134 ProfileInterface profileint = ProfileConnectionFactory
135 .create(info.getProfile().getURI(), getReporter());
136 partialprofile = (PartialOrdering) profileint.getProfile();
137 Domain domain = partialprofile.getDomain();
138 allbids = new AllBidsList(domain);
139
140 utilitySize = allbids.size().intValue();// 一共可能有多少种出价
141 simpleOrdering = new SimpleLinearOrdering(partialprofile);
142 bidOrder = simpleOrdering.getBids();
143 ranklistSize = bidOrder.size();
144 // THIS FIXES THE ORDER OF THE ISSUES, BACKCOMPATIBILITY issue numbers
145 issueList = new ArrayList<String>(domain.getIssues());
146 issueSize = issueList.size();
147 double[] results = new double[ranklistSize];// Array of given utility
148 for (int i = 0; i < ranklistSize; i++) { // results array initialization
149 results[i] = getBidOrderUtility(bidOrder.get(i));
150 }
151
152 int[] valueSize = new int[issueSize];// 第i个问题有j种选择
153 for (int i = 0; i < issueSize; i++) {
154 String issued = issueList.get(i);
155 valueSize[i] = domain.getValues(issued).size().intValue();
156 valueSum += valueSize[i];
157 }
158 initUtility = 1.0 / valueSum; // value初始化的值
159 learningRate = initUtility / 10.0;
160
161 values = new DiscreteValue[valueSum];// value数组
162 int valuesIndexCnt = 0;
163 while (valuesIndexCnt < valueSum) { // 初始化values数组和map valueCorrespond
164 for (int i = 0; i < issueSize; i++) {
165 String issued = issueList.get(i);
166 DiscreteValueSet availableVals = (DiscreteValueSet) domain
167 .getValues(issued);
168 for (int j = 0; j < availableVals.size().intValue(); j++) {
169 values[valuesIndexCnt] = availableVals.getValues().get(j); // 初始化values数组
170 valueCorrespond.put(values[valuesIndexCnt], initUtility); // 初始化map
171 // valueCorrespond
172 valuesIndexCnt++;
173 }
174 }
175 }
176
177 // bidOrder training set
178 // makes a flat list 2D list
179 // each element is for one of the bids.
180 // valueSum values, in order
181 // of iss1val1, iss1val2,...,iss2val1,iss2val2,...,
182 // issNval1,...,isNvalM.
183 // this fills the features array with 1's
184 // if the bid contains that particular value.
185 int[][] features = new int[ranklistSize][valueSum];
186
187 // Wouter: original code was bugged. #1766. Putting a fix here.
188 for (int bidnr = 0; bidnr < ranklistSize; bidnr++) {
189 Bid bid = bidOrder.get(bidnr);
190 int featurenr = 0;
191 for (String issue : issueList) {
192 Value thisbidvalue = bid.getValue(issue);
193 for (Value value : domain.getValues(issue)) {
194 features[bidnr][featurenr++] = thisbidvalue.equals(value)
195 ? 1
196 : 0;
197 }
198 }
199
200 }
201
202 double[] parameters = new double[valueSum];// Training value
203 for (int i = 0; i < valueSum; i++) {
204 parameters[i] = initUtility;
205 }
206
207 for (int i = 0; i < ranklistSize * valueSum; i++) { // training
208 BGD(features, results, learningRate, parameters);
209 }
210 }
211
212 private void BGD(int[][] features, double[] results, double learningRate,
213 double[] parameters) {
214 for (int t = 0; t < valueSum; t++) {
215 double sum = 0.0;
216 double parametersSum = 0.0;
217 for (int j = 0; j < results.length; j++) {
218 for (int i = 0; i < valueSum; i++) {
219 parametersSum += parameters[i] * features[j][i];
220 }
221 parametersSum = parametersSum - results[j];
222 parametersSum = parametersSum * features[j][t];
223 sum += parametersSum;
224 }
225 double updateValue = 2 * learningRate * sum / results.length;
226 parameters[t] = parameters[t] - updateValue;
227 /**
228 * ValueCorrespond is bugged, because it uses issuevalues as key
229 * while issuevalues may be not unique (multiple issues may have the
230 * same value, eg "yes" and "no".
231 */
232 valueCorrespond.put(values[t], parameters[t]);
233
234 }
235
236 }
237
238 private double linearEstUtility(Bid bid) {
239 double linearUtility = 0.0;
240
241 // Wouter the original code was buggy. Replaced with this better
242 // version. This code is still buggy because of the valueCorrespond
243 // issue.
244 // that issue was not fixed.
245 int featurenr = 0;
246 for (String issue : issueList) {
247 Value thisbidvalue = bid.getValue(issue);
248 for (Value value : partialprofile.getDomain().getValues(issue)) {
249 if (thisbidvalue != null && thisbidvalue.equals(value)) {
250 linearUtility += valueCorrespond.get(value);
251 }
252 featurenr++;
253 }
254 }
255 return linearUtility;
256 }
257
258 /**
259 *
260 * @param bid
261 * @return Estimate known bid utility, equally divided. Seems equal to
262 * {@link SimpleLinearOrdering#getUtility(Bid)}
263 */
264 private double getBidOrderUtility(Bid bid) {
265 return simpleOrdering.getUtility(bid).doubleValue();
266 }
267
268 private Action chooseAction() {
269 int round = progress.getCurrentRound();
270 int tround = progress.getTotalRounds();
271 double receiveBidUtility = 0.0;
272 double bidOrderMax = 1;// getHighUtility();
273 Bid bid;
274 if (round < tround * 0.7) {
275 if (round > 10 && receiveBids.size() < 7) {
276 int temp = (int) Math.ceil(ranklistSize * 0.1);
277 int randz = rand.nextInt(temp);
278 bid = bidOrder.get(ranklistSize - 1 - randz);
279 log("receiveBid<7,bidOrder: " + getBidOrderUtility(bid));
280 return new Offer(me, bid);
281 }
282 bid = generateBid(7, bidOrderMax);
283 return new Offer(me, bid);
284 } else if (round < tround * 0.98) {
285 if (receiveBids.size() < 10) {
286 int temp = (int) Math.ceil(ranklistSize * 0.15);
287 int randz = rand.nextInt(temp);
288 bid = bidOrder.get(ranklistSize - 1 - randz);
289 log("receiveBid<10,bidOrder: " + getBidOrderUtility(bid));
290 return new Offer(me, bid);
291 }
292 bid = generateBid(9, bidOrderMax);
293 return new Offer(me, bid);
294 } else if (round < tround * 0.99) {
295 receiveBidUtility = linearEstUtility(lastReceivedBid);
296 if (listSort) {
297 sortReceive();
298 listSort = false;
299 for (Map.Entry<Bid, Double> entry : list) {
300 System.out.println(entry);
301 }
302 log(receivehighestUtility + "\n");
303 }
304 if (receiveBidUtility > (receivehighestUtility - 0.03)) {
305 return new Accept(me, lastReceivedBid);
306 }
307 bid = generateReceiveBid();
308 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
309 + " accept阈值: " + (receivehighestUtility - 0.07) + "\n");
310 return new Offer(me, bid);
311 } else if (round < tround * 0.995) {
312 receiveBidUtility = linearEstUtility(lastReceivedBid);
313 if (receiveBidUtility > (receivehighestUtility - 0.07)) {
314 return new Accept(me, lastReceivedBid);
315 }
316 bid = generateReceiveBid();
317 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
318 + " accept阈值: " + (receivehighestUtility - 0.11) + "\n");
319 return new Offer(me, bid);
320 } else if (round == (tround - 1)) {
321 return new Accept(me, lastReceivedBid);
322
323 } else {
324 receiveBidUtility = linearEstUtility(lastReceivedBid);
325 if (receiveBidUtility > (receivehighestUtility - 0.1)) {
326 return new Accept(me, lastReceivedBid);
327 }
328 bid = generateReceiveBid();
329 log("receive bid Utility: " + linearEstUtility(lastReceivedBid)
330 + " accept阈值: " + (receivehighestUtility - 0.15) + "\n");
331 return new Offer(me, bid);
332 }
333 }
334
335 public Bid generateBid(int zcnt, double bidOrderMax) {
336 Bid randomBid = null;
337 if (lastReceivedBid == null) {
338 List<Bid> b = simpleOrdering.getBids();
339 randomBid = b.get(b.size() - 1);// max bid
340 } else if (zcnt == 7) {
341 if (bidOrderMax > 0.9) {
342 do {
343 randomBid = generateRandomBid();
344 } while (linearEstUtility(randomBid) < 0.82);
345 } else if (bidOrderMax > 0.8) {
346 do {
347 randomBid = generateRandomBid();
348 } while (linearEstUtility(randomBid) < 0.75);
349 } else {
350 do {
351 randomBid = generateRandomBid();
352 } while (linearEstUtility(randomBid) < 0.7);
353 }
354 } else if (zcnt == 9) {
355 if (bidOrderMax > 0.9) {
356 do {
357 randomBid = generateRandomBid();
358 } while (linearEstUtility(randomBid) < 0.8);
359 } else if (bidOrderMax > 0.8) {
360 do {
361 randomBid = generateRandomBid();
362 } while (linearEstUtility(randomBid) < 0.7);
363 } else {
364 do {
365 randomBid = generateRandomBid();
366 } while (linearEstUtility(randomBid) < 0.68);
367 }
368 }
369
370 log(progress.getCurrentRound() + "generateBid: "
371 + linearEstUtility(randomBid));
372 return randomBid;
373 }
374
375 private Bid generateReceiveBid() {
376 Bid bid;
377
378 int listSelectUtility = (int) Math.ceil(list.size() * 0.03);
379 double temp = list.get(listSelectUtility - 1).getValue();
380
381 if (temp < 0.7) {
382 temp = 0.7;
383 do {
384 bid = generateRandomBid();
385 } while (linearEstUtility(bid) < temp);
386 log(progress.getCurrentRound() + " generateRandomBid: "
387 + linearEstUtility(bid) + " temp:" + temp);
388 return bid;
389 } else {
390 if (lastBidTag) {
391 int rand1 = rand.nextInt(listSelectUtility);
392 bid = list.get(rand1).getKey();
393 lastBidTag = false;
394 log(progress.getCurrentRound() + " generateReceiveBid: "
395 + linearEstUtility(bid) + " temp:" + temp);
396 return bid;
397 } else {
398 do {
399 bid = generateRandomBid();
400 } while (linearEstUtility(bid) < temp);
401 lastBidTag = true;
402 log(progress.getCurrentRound() + " generateRandomBid: "
403 + linearEstUtility(bid) + " temp:" + temp);
404 return bid;
405 }
406 }
407
408 }
409
410 private void sortReceive() { // 将收到的出价进行排序
411 for (Map.Entry<Bid, Double> entry : receiveBids.entrySet()) {
412 list.add(entry); // 将map中的元素放入list中
413 }
414
415 list.sort(new Comparator<Map.Entry<Bid, Double>>() {
416 @Override
417 public int compare(Map.Entry<Bid, Double> o1,
418 Map.Entry<Bid, Double> o2) {
419 double result = o2.getValue() - o1.getValue();
420 if (result > 0)
421 return 1;
422 else if (result == 0)
423 return 0;
424 else
425 return -1;
426 }
427 // 逆序(从大到小)排列,正序为“return o1.getValue()-o2.getValue”
428 });
429 }
430
431 private void log(String s) {
432 getReporter().log(Level.INFO, s);
433 }
434
435 private Bid generateRandomBid() {
436 return allbids.get(rand.nextInt(allbids.size().intValue()));
437 }
438
439}
Note: See TracBrowser for help on using the repository browser.