[202] | 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 |
|
---|