source: src/main/java/agents/anac/y2019/agentgg/AgentGG.java

Last change on this file was 201, checked in by Katsuhide Fujita, 5 years ago

Add ANAC 2019 agents (2)

  • Property svn:executable set to *
File size: 14.4 KB
Line 
1package agents.anac.y2019.agentgg;
2
3import genius.core.AgentID;
4import genius.core.Bid;
5import genius.core.actions.Accept;
6import genius.core.actions.Action;
7import genius.core.actions.Offer;
8import genius.core.issue.Issue;
9import genius.core.issue.Value;
10import genius.core.parties.AbstractNegotiationParty;
11import genius.core.parties.NegotiationInfo;
12import genius.gui.session.SessionPanel;
13
14import javax.swing.*;
15import java.awt.*;
16import java.util.HashMap;
17import java.util.List;
18import java.util.Map;
19
20import static java.lang.Math.max;
21
22
23/**
24 *
25 */
26public class AgentGG extends AbstractNegotiationParty {
27
28 private ImpMap impMap;
29 private ImpMap opponentImpMap;
30 private double offerLowerRatio = 1.0;
31 private double offerHigherRatio = 1.1;
32 private double MAX_IMPORTANCE;
33 private double MIN_IMPORTANCE;
34 private double MEDIAN_IMPORTANCE;
35 private Bid MAX_IMPORTANCE_BID;
36 private Bid MIN_IMPORTANCE_BID;
37 private double OPPONENT_MAX_IMPORTANCE;
38 private double OPPONENT_MIN_IMPORTANCE;
39 private Bid receivedBid;
40 private Bid initialOpponentBid = null;
41 private double lastBidValue;
42 private double reservationImportanceRatio;
43 private boolean offerRandomly = true;
44
45 private double startTime;
46 private boolean maxOppoBidImpForMeGot = false;
47 private double maxOppoBidImpForMe;
48 private double estimatedNashPoint;
49 private Bid lastReceivedBid;
50 private boolean initialTimePass = false;
51
52
53 @Override
54 public void init(NegotiationInfo info) {
55 super.init(info);
56
57 // 创建 空的 我的importance map 以及对手的 value map
58 this.impMap = new ImpMap(userModel);
59 this.opponentImpMap = new ImpMap(userModel);
60
61
62 // 更新我的importance map
63 this.impMap.self_update(userModel);
64
65 // 获取最大、最小、中位数bid
66 this.getMaxAndMinBid();
67 this.getMedianBid();
68
69 // 获取reservation value,折算为importance的百分比
70 this.reservationImportanceRatio = this.getReservationRatio();
71
72 System.out.println("reservation ratio: " + this.reservationImportanceRatio);
73 System.out.println("my max importance bid: " + this.MAX_IMPORTANCE_BID);
74 System.out.println("my max importance: " + this.MAX_IMPORTANCE);
75 System.out.println("my min importance bid: " + this.MIN_IMPORTANCE_BID);
76 System.out.println("my min importance: " + this.MIN_IMPORTANCE);
77 System.out.println("my median importance: " + this.MEDIAN_IMPORTANCE);
78 System.out.println("Agent " + this.getPartyId() + " has finished initialization");
79 }
80
81 @Override
82 public Action chooseAction(List<Class<? extends Action>> list) {
83 double time = getTimeLine().getTime();
84
85 // 开始比赛
86 if (!(this.getLastReceivedAction() instanceof Offer)) return new Offer(getPartyId(), this.MAX_IMPORTANCE_BID);
87
88 // 对方报价对我来说的importance ratio
89 double impRatioForMe = (this.impMap.getImportance(this.receivedBid) - this.MIN_IMPORTANCE) / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
90
91 // 接受报价的条件,即高于我的threshold
92 if (impRatioForMe >= this.offerLowerRatio) {
93 System.out.println("\n\naccepted agent: Agent" + this.getPartyId());
94 System.out.println("last bid: " + this.receivedBid);
95 System.out.println("\ncurrent threshold: " + this.offerLowerRatio);
96 System.out.println("\n\n");
97 return new Accept(this.getPartyId(), this.receivedBid);
98 }
99
100 // 对手importance为1.0左右时,己方大致可以拿到多少。即寻找Pareto边界的端点
101 if (!maxOppoBidImpForMeGot) this.getMaxOppoBidImpForMe(time, 3.0 / 1000.0);
102
103 // 更新对手importance表
104 if (time < 0.3) this.opponentImpMap.opponent_update(this.receivedBid);
105
106 // 策略
107 this.getThreshold(time);
108
109 // 最后一轮
110 if (time >= 0.9989) {
111 double ratio = (this.impMap.getImportance(this.receivedBid) - this.MIN_IMPORTANCE) / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
112 if (ratio > this.reservationImportanceRatio + 0.2) {
113 return new Accept(getPartyId(), receivedBid);
114 }
115 }
116
117 System.out.println("high threshold: " + this.offerHigherRatio);
118 System.out.println("low threshold: " + this.offerLowerRatio);
119 System.out.println("estimated nash: " + this.estimatedNashPoint);
120 System.out.println("reservation: " + this.reservationImportanceRatio);
121 System.out.println();
122
123 Bid bid = getNeededRandomBid(this.offerLowerRatio, this.offerHigherRatio);
124 this.lastReceivedBid = this.receivedBid;
125 return new Offer(getPartyId(), bid);
126 }
127
128 @Override
129 public void receiveMessage(AgentID sender, Action act) {
130 super.receiveMessage(sender, act);
131 if (act instanceof Offer) {
132 Offer offer = (Offer) act;
133 this.receivedBid = offer.getBid();
134 }
135 }
136
137 @Override
138 public String getDescription() {
139 return "Well Played";
140 }
141
142 /**
143 * 获取对方utility为1.0左右时我方的最优值(Pareto最优边界点)
144 * 对方可能先报几次最高的相同bid,忽视,当不同时候开始计时。在持续时间内(如20轮),选择对我来说最高importance的bid。
145 * 由于此时对方的bid对对方而言importance一定很高,因此可以满足我方要求。
146 */
147 private void getMaxOppoBidImpForMe(double time, double timeLast) {
148 double thisBidImp = this.impMap.getImportance(this.receivedBid);
149 if (thisBidImp > this.maxOppoBidImpForMe) this.maxOppoBidImpForMe = thisBidImp;
150
151 if (this.initialTimePass) {
152 if (time - this.startTime > timeLast) {
153 double maxOppoBidRatioForMe = (this.maxOppoBidImpForMe - this.MIN_IMPORTANCE) / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
154 this.estimatedNashPoint = (1 - maxOppoBidRatioForMe) / 1.7 + maxOppoBidRatioForMe; // 1.414 是圆,2是直线
155 this.maxOppoBidImpForMeGot = true;
156 }
157 } else {
158 if (this.lastReceivedBid != this.receivedBid) {
159 this.initialTimePass = true;
160 this.startTime = time;
161 }
162 }
163 }
164
165 /**
166 * 根据时间获取阈值上下限
167 */
168 private void getThreshold(double time) {
169 if (time < 0.01) {
170 // 前10轮报0.9999,为了适应部分特殊的域
171 this.offerLowerRatio = 0.9999;
172 } else if (time < 0.02) {
173 // 10~20轮报0.99,为了适应部分特殊的域
174 this.offerLowerRatio = 0.99;
175 } else if (time < 0.2) {
176 // 20~200轮报高价,降至0.9
177 this.offerLowerRatio = 0.99 - 0.5 * (time - 0.02);
178 } else if (time < 0.5) {
179 this.offerRandomly = false;
180 // 200~500轮逐步降低阈值,降至距估计的Nash点0.5
181 double p2 = 0.3 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
182 this.offerLowerRatio = 0.9 - (0.9 - p2) / (0.5 - 0.2) * (time - 0.2);
183 } else if (time < 0.9) {
184 // 500~900轮快速降低阈值,降至距估计的Nash点0.2
185 double p1 = 0.3 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
186 double p2 = 0.15 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
187 this.offerLowerRatio = p1 - (p1 - p2) / (0.9 - 0.5) * (time - 0.5);
188 } else if (time < 0.98) {
189 // 妥协1
190 double p1 = 0.15 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
191 double p2 = 0.05 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
192 double possibleRatio = p1 - (p1 - p2) / (0.98 - 0.9) * (time - 0.9);
193 this.offerLowerRatio = max(possibleRatio, this.reservationImportanceRatio + 0.3);
194 } else if (time < 0.995) {
195 // 妥协2 980~995轮
196 double p1 = 0.05 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
197 double p2 = 0.0 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
198 double possibleRatio = p1 - (p1 - p2) / (0.995 - 0.98) * (time - 0.98);
199 this.offerLowerRatio = max(possibleRatio, this.reservationImportanceRatio + 0.25);
200 } else if (time < 0.999) {
201 // 妥协3 995~999轮
202 double p1 = 0.0 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
203 double p2 = -0.35 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
204 double possibleRatio = p1 - (p1 - p2) / (0.9989 - 0.995) * (time - 0.995);
205 this.offerLowerRatio = max(possibleRatio, this.reservationImportanceRatio + 0.25);
206 } else {
207 double possibleRatio = -0.4 * (1 - this.estimatedNashPoint) + this.estimatedNashPoint;
208 this.offerLowerRatio = max(possibleRatio, this.reservationImportanceRatio + 0.2);
209 }
210 this.offerHigherRatio = this.offerLowerRatio + 0.1;
211 }
212
213 /**
214 * 获取reservation value对应到importance matrix中的比例
215 */
216 private double getReservationRatio() {
217 double medianBidRatio = (this.MEDIAN_IMPORTANCE - this.MIN_IMPORTANCE) / (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE);
218 return this.utilitySpace.getReservationValue() * medianBidRatio / 0.5;
219 }
220
221 /**
222 * 获取最大、最小importance的值及对应offer
223 */
224 private void getMaxAndMinBid() {
225 HashMap<Integer, Value> lValues1 = new HashMap<>();
226 HashMap<Integer, Value> lValues2 = new HashMap<>();
227 for (Map.Entry<Issue, List<impUnit>> entry : this.impMap.entrySet()) {
228 Value value1 = entry.getValue().get(0).valueOfIssue;
229 Value value2 = entry.getValue().get(entry.getValue().size() - 1).valueOfIssue;
230 int issueNumber = entry.getKey().getNumber();
231 lValues1.put(issueNumber, value1);
232 lValues2.put(issueNumber, value2);
233 }
234 this.MAX_IMPORTANCE_BID = new Bid(this.getDomain(), lValues1);
235 this.MIN_IMPORTANCE_BID = new Bid(this.getDomain(), lValues2);
236 this.MAX_IMPORTANCE = this.impMap.getImportance(this.MAX_IMPORTANCE_BID);
237 this.MIN_IMPORTANCE = this.impMap.getImportance(this.MIN_IMPORTANCE_BID);
238 }
239
240
241 /**
242 * 获取bid ranking 中的中位数bid对应的importance值
243 */
244 private void getMedianBid() {
245 int median = (this.userModel.getBidRanking().getSize() - 1) / 2;
246 int median2 = -1;
247 if (this.userModel.getBidRanking().getSize() % 2 == 0) {
248 median2 = median + 1;
249 }
250 int current = 0;
251 for (Bid bid : this.userModel.getBidRanking()) {
252 current += 1;
253 if (current == median) {
254 this.MEDIAN_IMPORTANCE = this.impMap.getImportance(bid);
255 if (median2 == -1) break;
256 }
257 if (current == median2) {
258 this.MEDIAN_IMPORTANCE += this.impMap.getImportance(bid);
259 break;
260 }
261 }
262 if (median2 != -1) this.MEDIAN_IMPORTANCE /= 2;
263 }
264
265// /**
266// * 更新对手的最大及最小Importance的值及对应OFFER
267// */
268// private void getOpponentMaxAndMinBid() {
269// HashMap<Integer, Value> lValues1 = new HashMap<>();
270// HashMap<Integer, Value> lValues2 = new HashMap<>();
271// for (Map.Entry<Issue, List<impUnit>> entry : this.opponentImpMap.entrySet()) {
272// Value value1 = entry.getValue().get(0).valueOfIssue;
273// Value value2 = entry.getValue().get(entry.getValue().size() - 1).valueOfIssue;
274// int issueNumber = entry.getKey().getNumber();
275// lValues1.put(issueNumber, value1);
276// lValues2.put(issueNumber, value2);
277// }
278// Bid OPPONENT_MAX_IMPORTANCE_BID = new Bid(this.getDomain(), lValues1);
279// Bid OPPONENT_MIN_IMPORTANCE_BID = new Bid(this.getDomain(), lValues2);
280// this.OPPONENT_MAX_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MAX_IMPORTANCE_BID);
281// this.OPPONENT_MIN_IMPORTANCE = this.opponentImpMap.getImportance(OPPONENT_MIN_IMPORTANCE_BID);
282// }
283
284
285 /**
286 * 获取符合条件的随机bid。随机生成k个bid,选取其中在阈值范围内的bids,返回其中对手importance最高的一个bid。
287 *
288 * @param lowerRatio 生成随机bid的importance下限
289 * @param upperRatio 生成随机bid的importance上限
290 * @return Bid
291 */
292 private Bid getNeededRandomBid(double lowerRatio, double upperRatio) {
293 double lowerThreshold = lowerRatio * (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE) + this.MIN_IMPORTANCE;
294 double upperThreshold = upperRatio * (this.MAX_IMPORTANCE - this.MIN_IMPORTANCE) + this.MIN_IMPORTANCE;
295 for (int t = 0; t < 3; t++) {
296 long k = 2*this.getDomain().getNumberOfPossibleBids();
297 double highest_opponent_importance = 0.0;
298 Bid returnedBid = null;
299 for (int i = 0; i < k; i++) {
300 Bid bid = this.generateRandomBid();
301 double bidImportance = this.impMap.getImportance(bid);
302 double bidOpponentImportance = this.opponentImpMap.getImportance(bid);
303 if (bidImportance >= lowerThreshold && bidImportance <= upperThreshold) {
304 if (this.offerRandomly) return bid; // 前0.2时间随机给bid即可
305 if (bidOpponentImportance > highest_opponent_importance) {
306 highest_opponent_importance = bidOpponentImportance;
307 returnedBid = bid;
308 }
309 }
310 }
311 if (returnedBid != null) {
312 return returnedBid;
313 }
314 }
315 // 如果出现了问题,没找到合适的bid,就随即返回一个高于下限的
316 while (true) {
317 Bid bid = generateRandomBid();
318 if (this.impMap.getImportance(bid) >= lowerThreshold) {
319 return bid;
320 }
321 }
322 }
323
324 public static void main(String[] args) {
325 final JFrame gui = new JFrame();
326 gui.setLayout(new BorderLayout());
327 gui.getContentPane().add(new SessionPanel(), BorderLayout.CENTER);
328 gui.pack();
329 gui.setVisible(true);
330 }
331
332}
Note: See TracBrowser for help on using the repository browser.