source: src/main/java/agents/anac/y2019/agentgp/etc/NegotiationInfo.java@ 326

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

Add ANAC 2019 agents (2)

  • Property svn:executable set to *
File size: 19.3 KB
Line 
1package agents.anac.y2019.agentgp.etc;
2
3import java.io.File;
4import java.io.FileWriter;
5import java.io.IOException;
6import java.util.ArrayList;
7import java.util.Collections;
8import java.util.Comparator;
9import java.util.HashMap;
10import java.util.List;
11import java.util.Map;
12import genius.core.list.Tuple;
13//import list.Tuple;
14
15import java.util.Map.Entry;
16import java.util.Random;
17
18import genius.core.Bid;
19import genius.core.issue.Issue;
20import genius.core.issue.IssueDiscrete;
21import genius.core.issue.IssueInteger;
22import genius.core.issue.Value;
23import genius.core.issue.ValueDiscrete;
24import genius.core.issue.ValueInteger;
25import genius.core.utility.AbstractUtilitySpace;
26
27public class NegotiationInfo {
28 private AbstractUtilitySpace utilitySpace; // 効用空間
29 private ArrayList<Issue> issues; // 論点
30 private ArrayList<Object> opponents; // 自身以外の交渉参加者のList
31 private ArrayList<Bid> MyBidHistory = null; // 提案履歴
32 private ArrayList<Bid> BOBHistory = null; // BestOfferedBidの更新履歴
33 private ArrayList<Bid> PBList = null; // BestPopularBidのリスト
34 private HashMap<Object, Integer> opponentsAcceptNum; // acceptした回数
35 private HashMap<Object, ArrayList<Bid>> opponentsBidHistory = null; // 提案履歴
36 private HashMap<Object, Double> opponentsAverage; // 平均
37 private HashMap<Object, Double> opponentsVariance; // 分散
38 private HashMap<Object, Double> opponentsSum; // 和
39 private HashMap<Object, Double> opponentsPowSum; // 二乗和
40 private HashMap<Object, Double> opponentsStandardDeviation; // 標準偏差
41 private HashMap<Issue, HashMap<Value, Double>> valueRelativeUtility = null; // 自身の効用空間における各論点値の相対効用値行列(線形効用空間用)
42 private HashMap<Issue, HashMap<Value, Integer>> allValueFrequency = null; // 全員分の頻度行列
43 private HashMap<Object, HashMap<Issue, HashMap<Value, Integer>>> opponentsValueFrequency = null; // 交渉者別の頻度行列
44 private HashMap<Object, HashMap<Issue, ArrayList<Tuple<Value,Integer>>>> opponentsValueOrdinalScale = null; // 交渉者別の各issueごとの順序尺度
45 private double BOU = 0.0; // BestOfferedUtility 2者間交渉以外では使わない
46 private double MPBU = 0.0; // MaxPopularBidUtility
47 private double time_scale = 0.0; // 自分の手番が回ってくる時間間隔
48 private int round = 0; // 自分の手番数
49 private int negotiatorNum = 3; // 交渉者数(不具合が生じた場合に備えて3人で初期化)
50 private boolean isLinerUtilitySpace = true; // 線形効用空間であるかどうか
51
52 private boolean isPrinting = false;
53
54 public NegotiationInfo(AbstractUtilitySpace utilitySpace, boolean isPrinting) {
55 // 初期化
56 this.isPrinting = isPrinting;
57 this.utilitySpace = utilitySpace;
58 issues = (ArrayList<Issue>) utilitySpace.getDomain().getIssues();
59 opponents = new ArrayList<Object>();
60 MyBidHistory = new ArrayList<>();
61 BOBHistory = new ArrayList<>();
62 PBList = new ArrayList<>();
63 opponentsAcceptNum = new HashMap<Object, Integer>();
64 opponentsBidHistory = new HashMap<Object, ArrayList<Bid>>();
65 opponentsAverage = new HashMap<Object, Double>();
66 opponentsVariance = new HashMap<Object, Double>();
67 opponentsSum = new HashMap<Object, Double>();
68 opponentsPowSum = new HashMap<Object, Double>();
69 opponentsStandardDeviation = new HashMap<Object, Double>();
70 valueRelativeUtility = new HashMap<Issue, HashMap<Value, Double>> ();
71 allValueFrequency = new HashMap<Issue, HashMap<Value, Integer>> ();
72 opponentsValueFrequency = new HashMap<Object, HashMap<Issue, HashMap<Value, Integer>>> ();
73 opponentsValueOrdinalScale = new HashMap<Object, HashMap<Issue, ArrayList<Tuple<Value,Integer>>>>();
74
75 try { initAllValueFrequency(); }
76 catch (Exception e1) {
77 System.out.println("全員分の頻度行列の初期化に失敗しました");
78 e1.printStackTrace();
79 }
80 try { initValueRelativeUtility(); }
81 catch (Exception e) {
82 System.out.println("相対効用行列の初期化に失敗しました");
83 e.printStackTrace();
84 }
85
86 if(this.isPrinting){ System.out.println("NegotiationInfo:success"); }
87 }
88
89 public void initOpponent(Object sender) {
90 initNegotiatingInfo(sender); // 交渉情報を初期化
91 try {
92 initOpponentsValueFrequency(sender);
93 initOpponentValueOrdinalScale(sender);
94 opponentsAcceptNum.put(sender, 0);
95 } // senderの頻度行列を初期化
96 catch (Exception e) {
97 System.out.println("交渉参加者の頻度行列の初期化に失敗しました");
98 e.printStackTrace();
99 }
100 opponents.add(sender); // 交渉参加者にsenderを追加
101 }
102
103
104 public void updateInfo(Object sender, Bid offeredBid) {
105 try { updateNegotiatingInfo(sender, offeredBid); } // 交渉情報の更新
106 catch (Exception e1) {
107 System.out.println("交渉情報の更新に失敗しました");
108 e1.printStackTrace();
109 }
110 try {
111 updateFrequencyList(sender, offeredBid);
112 updateOrdinalScale(sender, offeredBid);
113 } // senderの頻度行列の更新
114 catch (Exception e) {
115 System.out.println("頻度行列の更新に失敗しました");
116 e.printStackTrace();
117 }
118 }
119
120 private void initNegotiatingInfo(Object sender) {
121 opponentsBidHistory.put(sender, new ArrayList<Bid>());
122 opponentsAverage.put(sender, 0.0);
123 opponentsVariance.put(sender, 0.0);
124 opponentsSum.put(sender, 0.0);
125 opponentsPowSum.put(sender, 0.0);
126 opponentsStandardDeviation.put(sender, 0.0);
127 }
128
129 private void initOpponentsValueFrequency(Object sender) throws Exception{
130 opponentsValueFrequency.put(sender, new HashMap<Issue, HashMap<Value, Integer>>()); // senderの頻度行列の初期化
131 for(Issue issue:issues){
132 opponentsValueFrequency.get(sender).put(issue, new HashMap<Value, Integer>()); // 頻度行列における論点行の初期化
133 ArrayList<Value> values = getValues(issue);
134 for(Value value:values){ opponentsValueFrequency.get(sender).get(issue).put(value, 0); } // 論点行の要素出現数の初期化
135 }
136 }
137
138 public void initOpponentValueOrdinalScale(Object sender) throws Exception{
139 opponentsValueOrdinalScale.put(sender, new HashMap<Issue, ArrayList<Tuple<Value, Integer>>>()); // senderの頻度行列の初期化
140 for(Issue issue:issues){
141 opponentsValueOrdinalScale.get(sender).put(issue, new ArrayList<Tuple<Value, Integer>>()); // 頻度行列における論点行の初期化
142 }
143 }
144
145 // 全員分の頻度行列の初期化
146 private void initAllValueFrequency() throws Exception{
147 ArrayList<Value> values = null;
148 for(Issue issue:issues){
149 allValueFrequency.put(issue, new HashMap<Value, Integer>()); // 論点行の初期化
150 values = getValues(issue);
151 for(Value value:values){ allValueFrequency.get(issue).put(value, 0); } // 論点行の要素の初期化
152 }
153 }
154
155 // 相対効用行列の初期化
156 private void initValueRelativeUtility() throws Exception{
157 ArrayList<Value> values = null;
158 for(Issue issue:issues){
159 valueRelativeUtility.put(issue, new HashMap<Value, Double>()); // 論点行の初期化
160 values = getValues(issue);
161 for(Value value:values){ valueRelativeUtility.get(issue).put(value, 0.0); } // 論点行の要素の初期化
162 }
163 }
164
165 // 相対効用行列の導出
166 public void setValueRelativeUtility(Bid maxBid) throws Exception {
167 ArrayList<Value> values = null;
168 Bid currentBid = null;
169 for(Issue issue:issues){
170 currentBid = new Bid(maxBid);
171 values = getValues(issue);
172 for(Value value:values){
173 currentBid = currentBid.putValue(issue.getNumber(), value);
174 valueRelativeUtility.get(issue).put(value, utilitySpace.getUtility(currentBid) - utilitySpace.getUtility(maxBid));
175 }
176 }
177 }
178
179 public void updateNegotiatingInfo(Object sender, Bid offeredBid) throws Exception {
180 opponentsBidHistory.get(sender).add(offeredBid); // 提案履歴
181
182 double util = utilitySpace.getUtility(offeredBid);
183 opponentsSum.put(sender, opponentsSum.get(sender) + util); // 和
184 opponentsPowSum.put(sender, opponentsPowSum.get(sender) + Math.pow(util, 2)); // 二乗和
185
186 int round_num = opponentsBidHistory.get(sender).size();
187 opponentsAverage.put(sender, opponentsSum.get(sender) / round_num); // 平均
188 opponentsVariance.put(sender, (opponentsPowSum.get(sender) / round_num) - Math.pow(opponentsAverage.get(sender), 2)); // 分散
189
190 if(opponentsVariance.get(sender) < 0){opponentsVariance.put(sender, 0.0);}
191 opponentsStandardDeviation.put(sender, Math.sqrt(opponentsVariance.get(sender))); // 標準偏差
192
193 if(util > BOU){
194 BOBHistory.add(offeredBid); // BOUの更新履歴に追加
195 BOU = util; // BOUの更新
196 }
197 }
198 public void updateAcceptNum(Object sender){
199 opponentsAcceptNum.put(sender, opponentsAcceptNum.get(sender)+1);
200 }
201
202 public HashMap<Issue, ArrayList<Tuple<Value,Integer>>> getValueOrdinalScale(){
203 //AcceptNumが多いエージェントを選びやすくしてる。
204 int allAcceptNum = 0;
205 for (Object agent : opponentsAcceptNum.keySet()) {
206 allAcceptNum += opponentsAcceptNum.get(agent);
207 }
208 Object selectedAgent = null;
209 if(allAcceptNum != 0){
210 double rand = Math.random();
211 int acceptNum = 0;
212 for (Object agent : opponentsAcceptNum.keySet()) {
213 acceptNum += opponentsAcceptNum.get(agent);
214 if(rand <= acceptNum/allAcceptNum){
215 selectedAgent = agent;
216 break;
217 }
218 }
219 }
220 else{
221 int rand = (new Random()).nextInt(opponents.size());
222 int acceptNum = 0;
223 for (Object agent : opponentsAcceptNum.keySet()) {
224 acceptNum++;
225 if(rand <= acceptNum){
226 selectedAgent = agent;
227 break;
228 }
229 }
230 }
231 //nullを返すことはないはず。
232 return opponentsValueOrdinalScale.get(selectedAgent);
233 }
234
235 // 頻度行列を更新
236 private void updateFrequencyList(Object sender, Bid offeredBid) throws Exception{
237 for(Issue issue:issues){
238 Value value = offeredBid.getValue(issue.getNumber());
239 opponentsValueFrequency.get(sender).get(issue).put(value, opponentsValueFrequency.get(sender).get(issue).get(value) + 1); // リストを更新
240 allValueFrequency.get(issue).put(value, allValueFrequency.get(issue).get(value) + 1); // リストを更新
241 }
242 }
243 // 順序尺度行列を更新
244 private void updateOrdinalScale(Object sender, Bid offeredBid) throws Exception{
245 for(Issue issue:issues){
246 Value value = offeredBid.getValue(issue.getNumber());
247 int i = 0;
248 for(Tuple<Value, Integer> tuple: opponentsValueOrdinalScale.get(sender).get(issue)){
249 if(tuple.get1().equals(value)){
250 opponentsValueOrdinalScale.get(sender).get(issue).set(i, new Tuple<Value, Integer>(value, tuple.get2()+1));
251 break;
252 }
253 i++;
254 }
255 if(opponentsValueOrdinalScale.get(sender).get(issue).size() == i)
256 opponentsValueOrdinalScale.get(sender).get(issue).add(new Tuple<Value, Integer>(value, 1));
257 }
258 }
259 // 順序尺度行列をソート
260 public void sortOrdinalScale() throws Exception{
261 for(Object opponent: opponents){
262 for(Issue issue:issues){
263 Tuple<Value, Integer> tuplePre = opponentsValueOrdinalScale.get(opponent).get(issue).get(opponentsValueOrdinalScale.get(opponent).get(issue).size()-1);
264 for (int i = opponentsValueOrdinalScale.get(opponent).get(issue).size() - 2; i >= 0; i--) {
265 if(opponentsValueOrdinalScale.get(opponent).get(issue).get(i).get2() < tuplePre.get2()){
266 opponentsValueOrdinalScale.get(opponent).get(issue).set(i+1,opponentsValueOrdinalScale.get(opponent).get(issue).get(i));
267 opponentsValueOrdinalScale.get(opponent).get(issue).set(i, tuplePre);
268 }
269 tuplePre = opponentsValueOrdinalScale.get(opponent).get(issue).get(i);
270 }
271 }
272 }
273 }
274
275 // 交渉者数を返す
276 public void updateOpponentsNum(int num) { negotiatorNum = num; }
277
278 // 線形効用空間でない場合
279 public void utilitySpaceTypeisNonLiner() { isLinerUtilitySpace = false; }
280
281 // 自身の提案情報の更新
282 public void updateMyBidHistory(Bid offerBid) { MyBidHistory.add(offerBid); }
283
284 // 提案時間間隔を返す
285 public void updateTimeScale(double time) {
286 round = round + 1;
287 time_scale = time / round;
288 }
289
290 // PopularBidListを返す
291 public void updatePBList(Bid popularBid) throws Exception {
292 if(!PBList.contains(popularBid)){ // 一意に記録
293 PBList.add(popularBid);
294 MPBU = Math.max(MPBU, utilitySpace.getUtility(popularBid));
295 Collections.sort(PBList, new UtilityComparator()); // ソート
296
297 if(isPrinting){
298 System.out.println("ranking");
299 for(int i=0; i<PBList.size();i++){ System.out.println(utilitySpace.getUtility(PBList.get(i))); }
300 System.out.println("Size:" + PBList.size() + ", Min:" + utilitySpace.getUtility(PBList.get(0)) + ", Max:" + utilitySpace.getUtility(PBList.get(PBList.size()-1)) + ", Opponents:" + opponents);
301 }
302 }
303 }
304
305 public class UtilityComparator implements Comparator<Bid> {
306 public int compare(Bid a, Bid b) {
307 try {
308 double u1 = utilitySpace.getUtility(a);
309 double u2 = utilitySpace.getUtility(b);
310 if (u1 < u2) { return 1; }
311 if (u1 == u2) { return 0; }
312 if (u1 > u2) { return -1; }
313 } catch (Exception e) {
314 System.out.println("効用値に基づくソートに失敗しました");
315 e.printStackTrace();
316 }
317 return 0; // 例外処理
318 }
319 }
320
321 // 平均
322 public double getAverage(Object sender) { return opponentsAverage.get(sender); }
323
324 // 分散
325 public double getVariancer(Object sender) { return opponentsVariance.get(sender); }
326
327 // 標準偏差
328 public double getStandardDeviation(Object sender) { return opponentsStandardDeviation.get(sender); }
329
330 // 相手の提案履歴の要素数を返す
331 public int getPartnerBidNum(Object sender) { return opponentsBidHistory.get(sender).size(); }
332
333 // 相手の提案履歴の頻度を返す
334 public HashMap<Issue, HashMap<Value, Integer>> getHistory(Object sender) { return opponentsValueFrequency.get(sender); }
335
336 // 自身のラウンド数を返す
337 public int getRound() { return round; }
338
339 // 交渉者数を返す
340 public int getNegotiatorNum () { return negotiatorNum; }
341
342 // 相対効用行列を返す
343 public HashMap<Issue, HashMap<Value, Double>> getValueRelativeUtility(){return valueRelativeUtility; }
344
345 // 線形効用空間であるかどうかを返す
346 public boolean isLinerUtilitySpace () { return isLinerUtilitySpace; }
347
348 // 論点一覧を返す
349 public ArrayList<Issue> getIssues() { return issues; }
350
351 // BestOfferedUtilityを返す
352 public double getBOU() { return BOU; }
353
354 // MaxPopularBidUtilityを返す
355 public double getMPBU() { return MPBU; }
356
357 // 交渉者全体のBOBHistoryを返す
358 public ArrayList<Bid> getBOBHistory() { return BOBHistory; }
359
360 // PBListを返す
361 public ArrayList<Bid> getPBList() { return PBList; }
362
363 // 提案時間間隔を返す
364 public double getTimeScale() { return time_scale; }
365
366 // 論点における取り得る値の一覧を返す
367 public ArrayList<Value> getValues(Issue issue) {
368 ArrayList<Value> values = new ArrayList<Value>();
369 switch(issue.getType()) {
370 case DISCRETE:
371 List<ValueDiscrete> valuesDis = ((IssueDiscrete)issue).getValues();
372 for(Value value:valuesDis){ values.add(value); }
373 break;
374 case INTEGER:
375 int min_value = ((IssueInteger)issue).getLowerBound();
376 //int min_value = ((IssueInteger)issue).getUpperBound();
377 int max_value = ((IssueInteger)issue).getUpperBound();
378 for(int j=min_value; j<=max_value; j++){
379 ValueInteger valueObject = new ValueInteger(j);
380 values.add((Value)valueObject);
381 }
382 break;
383 default: try {
384 throw new Exception("issue type "+ issue.getType()+" not supported by Atlas3");
385 } catch (Exception e) {
386 System.out.println("論点の取り得る値の取得に失敗しました");
387 e.printStackTrace();
388 }
389 }
390 return values;
391 }
392
393 // 交渉相手の一覧を返す
394 public ArrayList<Object> getOpponents() { return opponents; }
395
396 // FrequencyListの頻度に基づき,要素を返す
397 public Value getValuebyFrequencyList(Object sender, Issue issue) {
398 int current_f = 0;
399 int max_f = 0; // 最頻出要素の出現数
400 Value max_value = null; // 最頻出要素
401 ArrayList<Value> randomOrderValues = getValues(issue);
402 Collections.shuffle(randomOrderValues); // ランダムに並び替える(毎回同じ順番で評価した場合,出現数が同値の場合に返却値が偏るため)
403
404 for(Value value:randomOrderValues){
405 current_f = opponentsValueFrequency.get(sender).get(issue).get(value);
406 // 最頻出要素を記録
407 if(max_value == null || current_f > max_f){
408 max_f = current_f;
409 max_value = value;
410 }
411 }
412 return max_value;
413 }
414
415 // 全員分のFrequencyListの頻度に基づき,要素を返す
416 public Value getValuebyAllFrequencyList(Issue issue) {
417 int current_f = 0;
418 int max_f = 0; // 最頻出要素の出現数
419 Value max_value = null; // 最頻出要素
420 ArrayList<Value> randomOrderValues = getValues(issue);
421 Collections.shuffle(randomOrderValues); // ランダムに並び替える(毎回同じ順番で評価した場合,出現数が同値の場合に返却値が偏るため)
422
423 for(Value value:randomOrderValues){
424 current_f = allValueFrequency.get(issue).get(value);
425 // 最頻出要素を記録
426 if(max_value == null || current_f > max_f){
427 max_f = current_f;
428 max_value = value;
429 }
430 }
431 return max_value;
432 }
433
434 public void saveFrequency(){
435 try{
436 File file = new File("opponentBid.txt");
437 FileWriter filewriter = new FileWriter(file);
438
439 for(Object opponent: opponents){
440 for(Issue issue: issues){
441 filewriter.write(opponent.toString()+"\n");
442 HashMap<Value, Integer> values = opponentsValueFrequency.get(opponent).get(issue);
443 // List 生成 (ソート用)
444 List<Map.Entry<Value,Integer>> entries = new ArrayList<Map.Entry<Value ,Integer>>(values.entrySet());
445 Collections.sort(entries, new Comparator<Map.Entry<Value,Integer>>() {
446 @Override
447 public int compare(
448 Entry<Value,Integer> entry1, Entry<Value,Integer> entry2) {
449 return ((Integer)entry2.getValue()).compareTo((Integer)entry1.getValue());
450 }
451 });
452
453 // 内容を表示
454 for (Entry<Value,Integer> s : entries) {
455 filewriter.write(s.getKey() + " , " + s.getValue()+"\n");
456 }
457 }
458 }
459 filewriter.close();
460 }catch(IOException e){
461 System.out.println(e);
462 }
463 }
464 //public void saveSort(){
465 // try{
466 // File file = new File("sortBid.txt");
467 // FileWriter filewriter = new FileWriter(file);
468 // filewriter.write("save sort"+"\n");
469 //
470 // //for(Object opponent: opponents){
471 // //filewriter.write(opponent.toString()+"\n");
472 // //for(Issue issue: issues){
473 // //filewriter.write(issue.toString()+"\n");
474 // //ArrayList<Tuple<Value, Integer>> values = opponentsValueOrdinalScale.get(opponent).get(issue);
475 // // 内容を表示
476 // //for (Tuple<Value,Integer> s : values) {
477 // //System.out.print("("+s.get1()+","+s.get2()+"):");
478 // //}
479 // //}
480 // //System.out.println("");
481 // //}
482 // for (Bid s : MyBidHistory) {
483 // filewriter.write(s + " , " + (1-utilitySpace.getUtility(s))+"\n");
484 // }
485 // filewriter.close();
486 // }catch(IOException e){
487 // System.out.println(e);
488 // }
489 //}
490}
Note: See TracBrowser for help on using the repository browser.