1 | package agents.anac.y2019.winkyagent;
|
---|
2 |
|
---|
3 | import java.util.*;
|
---|
4 |
|
---|
5 | import genius.core.AgentID;
|
---|
6 | import genius.core.Bid;
|
---|
7 | import genius.core.actions.Accept;
|
---|
8 | import genius.core.actions.Action;
|
---|
9 | import genius.core.actions.Offer;
|
---|
10 | import genius.core.issue.Issue;
|
---|
11 | import genius.core.issue.IssueDiscrete;
|
---|
12 | import genius.core.issue.Value;
|
---|
13 | import genius.core.issue.ValueDiscrete;
|
---|
14 | import genius.core.parties.AbstractNegotiationParty;
|
---|
15 | import genius.core.parties.NegotiationInfo;
|
---|
16 | import genius.core.timeline.DiscreteTimeline;
|
---|
17 | import genius.core.uncertainty.BidRanking;
|
---|
18 |
|
---|
19 | public class winkyAgent extends AbstractNegotiationParty {
|
---|
20 |
|
---|
21 | private Bid lastReceivedBid = null;
|
---|
22 | private Map<Bid, Double> receiveBids = new HashMap<Bid, Double>();
|
---|
23 | private List<Bid> bidOrder = null;
|
---|
24 | int utilitySize = 0;
|
---|
25 | int ranklistSize = 0;
|
---|
26 | double receivehighestUtility = 0.0;//接收过的最高出价的效用
|
---|
27 | List<Issue> issueList = null;//issue列表
|
---|
28 | int issueSize = 0;//issue个数
|
---|
29 | int valueSum = 0;//value个数
|
---|
30 | double initUtility = 0.0;//value初始效用
|
---|
31 | Map<ValueDiscrete, Double> valueCorrespond = new HashMap<ValueDiscrete, Double>();//value和对应效用
|
---|
32 | ValueDiscrete[] values = null;//value数组
|
---|
33 | double learningRate;
|
---|
34 | List<Map.Entry<Bid, Double>> list = new ArrayList<>();//对receiveBids按照效用进行排序后得到的list
|
---|
35 | boolean listSort = true;
|
---|
36 | boolean lastBidTag = true;
|
---|
37 |
|
---|
38 | @Override
|
---|
39 | public void init(NegotiationInfo info) {
|
---|
40 |
|
---|
41 | super.init(info);
|
---|
42 | utilitySize = (int) utilitySpace.getDomain().getNumberOfPossibleBids();//一共可能有多少种出价
|
---|
43 | bidOrder = userModel.getBidRanking().getBidOrder();
|
---|
44 | ranklistSize = bidOrder.size();
|
---|
45 | issueList = utilitySpace.getDomain().getIssues();
|
---|
46 | issueSize = issueList.size();
|
---|
47 | double[] results = new double[ranklistSize];//给定bid效用数组
|
---|
48 | for (int i = 0; i < ranklistSize; i++) { //results数组初始化赋值
|
---|
49 | results[i] = getBidOrderUtility(bidOrder.get(i));
|
---|
50 | }
|
---|
51 |
|
---|
52 | int[] valueSize = new int[issueSize];//第i个问题有j种选择
|
---|
53 | for (int i = 0; i < issueSize; i++) {
|
---|
54 | Issue issue = issueList.get(i);
|
---|
55 | IssueDiscrete issued = (IssueDiscrete) issue;//某个issue的value
|
---|
56 | valueSize[i] = issued.getNumberOfValues();
|
---|
57 | valueSum += valueSize[i];
|
---|
58 | }
|
---|
59 | initUtility = 1.0 / valueSum; //value初始化的值
|
---|
60 | learningRate = initUtility / 10.0;
|
---|
61 |
|
---|
62 | values = new ValueDiscrete[valueSum];//value数组
|
---|
63 | int valuesIndexCnt = 0;
|
---|
64 | while (valuesIndexCnt < valueSum) { //初始化values数组和map valueCorrespond
|
---|
65 | for (int i = 0; i < issueSize; i++) {
|
---|
66 | Issue issue = issueList.get(i);
|
---|
67 | IssueDiscrete issued = (IssueDiscrete) issue;//某个issue的value
|
---|
68 | for (int j = 0; j < issued.getNumberOfValues(); j++) {
|
---|
69 | values[valuesIndexCnt] = issued.getValue(j); //初始化values数组
|
---|
70 | valueCorrespond.put(values[valuesIndexCnt], initUtility); //初始化map valueCorrespond
|
---|
71 | valuesIndexCnt++;
|
---|
72 | }
|
---|
73 | }
|
---|
74 | }
|
---|
75 |
|
---|
76 | int[][] features = new int[ranklistSize][valueSum];//bidOrder训练集
|
---|
77 | for (int i = 0; i < ranklistSize; i++) {
|
---|
78 | HashMap<Integer, Value> valueHashMap = bidOrder.get(i).getValues();
|
---|
79 | int vhmSize = valueHashMap.size();
|
---|
80 | // for(int z=1;z<=vhmSize;z++){
|
---|
81 | // log(z+" "+valueHashMap.get(z));
|
---|
82 | // }
|
---|
83 | int p = 1;
|
---|
84 | for (int j = 0; j < valueSum; j++) {
|
---|
85 | Value valueTemp = values[j];
|
---|
86 | Value valueOfbidOrder = valueHashMap.get(p);
|
---|
87 | if (valueTemp.equals(valueOfbidOrder) && p <= vhmSize) {
|
---|
88 | features[i][j] = 1;
|
---|
89 | p++;
|
---|
90 | } else {
|
---|
91 | features[i][j] = 0;
|
---|
92 | }
|
---|
93 | }
|
---|
94 | // log("\n");
|
---|
95 | }
|
---|
96 |
|
---|
97 | double[] parameters = new double[valueSum];//训练得到的value值
|
---|
98 | for (int i = 0; i < valueSum; i++) {
|
---|
99 | parameters[i] = initUtility;
|
---|
100 | }
|
---|
101 |
|
---|
102 | for (int i = 0; i < ranklistSize * valueSum; i++) { //训练
|
---|
103 | BGD(features, results, learningRate, parameters);
|
---|
104 | }
|
---|
105 | }
|
---|
106 |
|
---|
107 |
|
---|
108 | private void BGD(int[][] features, double[] results, double learningRate, double[] parameters) {
|
---|
109 | for (int t = 0; t < valueSum; t++) {
|
---|
110 | double sum = 0.0;
|
---|
111 | double parametersSum = 0.0;
|
---|
112 | for (int j = 0; j < results.length; j++) {
|
---|
113 | for (int i = 0; i < valueSum; i++) {
|
---|
114 | parametersSum += parameters[i] * features[j][i];
|
---|
115 | }
|
---|
116 | parametersSum = parametersSum - results[j];
|
---|
117 | parametersSum = parametersSum * features[j][t];
|
---|
118 | sum += parametersSum;
|
---|
119 | }
|
---|
120 | double updateValue = 2 * learningRate * sum / results.length;
|
---|
121 | parameters[t] = parameters[t] - updateValue;
|
---|
122 | valueCorrespond.put(values[t], parameters[t]);
|
---|
123 |
|
---|
124 | }
|
---|
125 | // double totalLoss = 0;
|
---|
126 | // for (int j = 0; j < results.length; j++) {
|
---|
127 | // totalLoss = totalLoss + Math.pow((parameters[0] * features[j][0] + parameters[1] * features[j][1]
|
---|
128 | // + parameters[2] * features[j][2] + parameters[3] - results[j]), 2);
|
---|
129 | // }
|
---|
130 | // System.out.println(parameters[0] + " " + parameters[1] + " " + parameters[2] + " " + parameters[3]);
|
---|
131 | // System.out.println("totalLoss:" + totalLoss);
|
---|
132 | }
|
---|
133 |
|
---|
134 | private double linearEstUtility(Bid bid) {
|
---|
135 | double linearUtility = 0.0;
|
---|
136 | HashMap<Integer, Value> valueHashMap = bid.getValues();
|
---|
137 | int vhmSize = valueHashMap.size();
|
---|
138 | int p = 1;
|
---|
139 | for (int j = 0; j < valueSum; j++) {
|
---|
140 | Value valueTemp = values[j];
|
---|
141 | Value valueOfbidOrder = valueHashMap.get(p);
|
---|
142 | if (valueTemp.equals(valueOfbidOrder) && p <= vhmSize) {
|
---|
143 | linearUtility += valueCorrespond.get(valueTemp);
|
---|
144 | p++;
|
---|
145 | }
|
---|
146 | }
|
---|
147 | return linearUtility;
|
---|
148 | }
|
---|
149 |
|
---|
150 | private double getBidOrderUtility(Bid bid) //估计已知出价效用,等分
|
---|
151 | {
|
---|
152 | BidRanking bidRanking = getUserModel().getBidRanking();
|
---|
153 | Double min = bidRanking.getLowUtility();
|
---|
154 | double max = bidRanking.getHighUtility();
|
---|
155 |
|
---|
156 | int i = bidOrder.indexOf(bid);
|
---|
157 |
|
---|
158 | // index:0 has utility min, index n-1 has utility max
|
---|
159 | return min + i * (max - min) / (double) (ranklistSize - 1);
|
---|
160 | }
|
---|
161 |
|
---|
162 |
|
---|
163 | @Override
|
---|
164 | public Action chooseAction(List<Class<? extends Action>> validActions) {
|
---|
165 |
|
---|
166 | int round = ((DiscreteTimeline) timeline).getRound();
|
---|
167 | int tround = ((DiscreteTimeline) timeline).getTotalRounds();
|
---|
168 | double receiveBidUtility = 0.0;
|
---|
169 | double bidOrderMax = userModel.getBidRanking().getHighUtility();
|
---|
170 | Bid bid;
|
---|
171 | if (round < tround * 0.7) {
|
---|
172 | if (round > 10 && receiveBids.size() < 7) {
|
---|
173 | int temp = (int) Math.ceil(ranklistSize * 0.1);
|
---|
174 | int randz = rand.nextInt(temp);
|
---|
175 | bid = bidOrder.get(ranklistSize - 1 - randz);
|
---|
176 | log("receiveBid<7,bidOrder: " + getBidOrderUtility(bid));
|
---|
177 | return new Offer(getPartyId(), bid);
|
---|
178 | }
|
---|
179 | bid = generateBid(7, bidOrderMax);
|
---|
180 | return new Offer(getPartyId(), bid);
|
---|
181 | } else if (round < tround * 0.98) {
|
---|
182 | if (receiveBids.size() < 10) {
|
---|
183 | int temp = (int) Math.ceil(ranklistSize * 0.15);
|
---|
184 | int randz = rand.nextInt(temp);
|
---|
185 | bid = bidOrder.get(ranklistSize - 1 - randz);
|
---|
186 | log("receiveBid<10,bidOrder: " + getBidOrderUtility(bid));
|
---|
187 | return new Offer(getPartyId(), bid);
|
---|
188 | }
|
---|
189 | bid = generateBid(9, bidOrderMax);
|
---|
190 | return new Offer(getPartyId(), bid);
|
---|
191 | } else if (round < tround * 0.99) {
|
---|
192 | receiveBidUtility = linearEstUtility(lastReceivedBid);
|
---|
193 | if (listSort) {
|
---|
194 | sortReceive();
|
---|
195 | listSort = false;
|
---|
196 | for (Map.Entry<Bid, Double> entry : list) {
|
---|
197 | System.out.println(entry);
|
---|
198 | }
|
---|
199 | log(receivehighestUtility + "\n");
|
---|
200 | }
|
---|
201 | if (receiveBidUtility > (receivehighestUtility - 0.03)) {
|
---|
202 | return new Accept(getPartyId(), lastReceivedBid);
|
---|
203 | }
|
---|
204 | bid = generateReceiveBid();
|
---|
205 | log("receive bid Utility: " + linearEstUtility(lastReceivedBid) + " accept阈值: " + (receivehighestUtility - 0.07) + "\n");
|
---|
206 | return new Offer(getPartyId(), bid);
|
---|
207 | } else if (round < tround * 0.995) {
|
---|
208 | receiveBidUtility = linearEstUtility(lastReceivedBid);
|
---|
209 | if (receiveBidUtility > (receivehighestUtility - 0.07)) {
|
---|
210 | return new Accept(getPartyId(), lastReceivedBid);
|
---|
211 | }
|
---|
212 | bid = generateReceiveBid();
|
---|
213 | log("receive bid Utility: " + linearEstUtility(lastReceivedBid) + " accept阈值: " + (receivehighestUtility - 0.11) + "\n");
|
---|
214 | return new Offer(getPartyId(), bid);
|
---|
215 | } else if (round == (tround-1)) {
|
---|
216 | return new Accept(getPartyId(), lastReceivedBid);
|
---|
217 |
|
---|
218 | } else {
|
---|
219 | receiveBidUtility = linearEstUtility(lastReceivedBid);
|
---|
220 | if (receiveBidUtility > (receivehighestUtility - 0.1)) {
|
---|
221 | return new Accept(getPartyId(), lastReceivedBid);
|
---|
222 | }
|
---|
223 | bid = generateReceiveBid();
|
---|
224 | log("receive bid Utility: " + linearEstUtility(lastReceivedBid) + " accept阈值: " + (receivehighestUtility - 0.15) + "\n");
|
---|
225 | return new Offer(getPartyId(), bid);
|
---|
226 | }
|
---|
227 | }
|
---|
228 |
|
---|
229 |
|
---|
230 | public Bid generateBid(int zcnt, double bidOrderMax) {
|
---|
231 | Bid randomBid = null;
|
---|
232 | if (lastReceivedBid == null) {
|
---|
233 | randomBid = userModel.getBidRanking().getMaximalBid();
|
---|
234 | } else if (zcnt == 7) {
|
---|
235 | if (bidOrderMax > 0.9) {
|
---|
236 | do {
|
---|
237 | randomBid = generateRandomBid();
|
---|
238 | } while (linearEstUtility(randomBid) < 0.82);
|
---|
239 | } else if (bidOrderMax > 0.8) {
|
---|
240 | do {
|
---|
241 | randomBid = generateRandomBid();
|
---|
242 | } while (linearEstUtility(randomBid) < 0.75);
|
---|
243 | } else {
|
---|
244 | do {
|
---|
245 | randomBid = generateRandomBid();
|
---|
246 | } while (linearEstUtility(randomBid) < 0.7);
|
---|
247 | }
|
---|
248 | } else if (zcnt == 9) {
|
---|
249 | if (bidOrderMax > 0.9) {
|
---|
250 | do {
|
---|
251 | randomBid = generateRandomBid();
|
---|
252 | } while (linearEstUtility(randomBid) < 0.8);
|
---|
253 | } else if (bidOrderMax > 0.8) {
|
---|
254 | do {
|
---|
255 | randomBid = generateRandomBid();
|
---|
256 | } while (linearEstUtility(randomBid) < 0.7);
|
---|
257 | } else {
|
---|
258 | do {
|
---|
259 | randomBid = generateRandomBid();
|
---|
260 | } while (linearEstUtility(randomBid) < 0.68);
|
---|
261 | }
|
---|
262 | }
|
---|
263 |
|
---|
264 | log(((DiscreteTimeline) timeline).getRound() + "generateBid: " + linearEstUtility(randomBid) + "\n");
|
---|
265 | return randomBid;
|
---|
266 | }
|
---|
267 |
|
---|
268 | private Bid generateReceiveBid() {
|
---|
269 | Bid bid;
|
---|
270 |
|
---|
271 | int listSelectUtility = (int) Math.ceil(list.size() * 0.03);
|
---|
272 | double temp = list.get(listSelectUtility - 1).getValue();
|
---|
273 |
|
---|
274 | if (temp < 0.7) {
|
---|
275 | temp = 0.7;
|
---|
276 | do {
|
---|
277 | bid = generateRandomBid();
|
---|
278 | } while (linearEstUtility(bid) < temp);
|
---|
279 | log(((DiscreteTimeline) timeline).getRound() + " generateRandomBid: " + linearEstUtility(bid) + " temp:" + temp);
|
---|
280 | return bid;
|
---|
281 | } else {
|
---|
282 | if (lastBidTag) {
|
---|
283 | int rand1 = rand.nextInt(listSelectUtility);
|
---|
284 | bid = list.get(rand1).getKey();
|
---|
285 | lastBidTag = false;
|
---|
286 | log(((DiscreteTimeline) timeline).getRound() + " generateReceiveBid: " + linearEstUtility(bid) + " temp:" + temp);
|
---|
287 | return bid;
|
---|
288 | } else {
|
---|
289 | do {
|
---|
290 | bid = generateRandomBid();
|
---|
291 | } while (linearEstUtility(bid) < temp);
|
---|
292 | lastBidTag = true;
|
---|
293 | log(((DiscreteTimeline) timeline).getRound() + " generateRandomBid: " + linearEstUtility(bid) + " temp:" + temp);
|
---|
294 | return bid;
|
---|
295 | }
|
---|
296 | }
|
---|
297 |
|
---|
298 | }
|
---|
299 |
|
---|
300 | @Override
|
---|
301 | public void receiveMessage(AgentID sender, Action action) {
|
---|
302 | super.receiveMessage(sender, action);
|
---|
303 | if (action instanceof Offer) {
|
---|
304 | lastReceivedBid = ((Offer) action).getBid();
|
---|
305 | double lastReceivedBidUtility = linearEstUtility(lastReceivedBid);
|
---|
306 | receiveBids.put(lastReceivedBid, lastReceivedBidUtility);
|
---|
307 | if (lastReceivedBidUtility > receivehighestUtility) {
|
---|
308 | receivehighestUtility = lastReceivedBidUtility;
|
---|
309 | }
|
---|
310 | }
|
---|
311 | }
|
---|
312 |
|
---|
313 | private void sortReceive() { //将收到的出价进行排序
|
---|
314 | for (Map.Entry<Bid, Double> entry : receiveBids.entrySet()) {
|
---|
315 | list.add(entry); //将map中的元素放入list中
|
---|
316 | }
|
---|
317 |
|
---|
318 | list.sort(new Comparator<Map.Entry<Bid, Double>>() {
|
---|
319 | @Override
|
---|
320 | public int compare(Map.Entry<Bid, Double> o1, Map.Entry<Bid, Double> o2) {
|
---|
321 | double result = o2.getValue() - o1.getValue();
|
---|
322 | if (result > 0)
|
---|
323 | return 1;
|
---|
324 | else if (result == 0)
|
---|
325 | return 0;
|
---|
326 | else
|
---|
327 | return -1;
|
---|
328 | }
|
---|
329 | //逆序(从大到小)排列,正序为“return o1.getValue()-o2.getValue”
|
---|
330 | });
|
---|
331 | }
|
---|
332 |
|
---|
333 | @Override
|
---|
334 | public String getDescription() {
|
---|
335 | return "ANAC2019";
|
---|
336 | }
|
---|
337 |
|
---|
338 | private static void log(String s) {
|
---|
339 | System.out.println(s);
|
---|
340 | }
|
---|
341 |
|
---|
342 | }
|
---|
343 |
|
---|