source: src/main/java/agents/anac/y2015/AgentHP/AgentHP.java

Last change on this file was 1, checked in by Wouter Pasman, 6 years ago

Initial import : Genius 9.0.0

File size: 22.4 KB
Line 
1package agents.anac.y2015.AgentHP;
2
3import java.util.HashMap;
4import java.util.List;
5
6import genius.core.AgentID;
7import genius.core.Bid;
8import genius.core.actions.Accept;
9import genius.core.actions.Action;
10import genius.core.actions.ActionWithBid;
11import genius.core.actions.Inform;
12import genius.core.actions.Offer;
13import genius.core.issue.Issue;
14import genius.core.issue.IssueDiscrete;
15import genius.core.issue.ValueDiscrete;
16import genius.core.parties.AbstractNegotiationParty;
17import genius.core.parties.NegotiationInfo;
18import genius.core.utility.AdditiveUtilitySpace;
19import genius.core.utility.EvaluatorDiscrete;
20
21/**
22 * This is your negotiation party.
23 */
24public class AgentHP extends AbstractNegotiationParty {
25
26 // 提案保存数最大
27 private int logMax = 500;
28
29 /* ここまではコンストラクタ内で初期化必要なし */
30
31 // 交渉参加者合計人数
32 private int partyNum = 0;
33
34 // 論点数
35 private int issueNum = 0;
36
37 // 判断対象の提案
38 private Bid targetBid = null;
39
40 // 予約値
41 private double reservationValue = 0.0;
42
43 // 効用値の下限値(時間で変化)
44 private double underlimitUtility = 1.0;
45
46 // 現在の提案保存数
47 private int logNum[];
48
49 // 提案ログの論点ごとの項目出現数格納Hash用テンプレ
50 private HashMap<String, Integer>[] TemplateLogBidCountHash;
51
52 // 提案ログから作成した予測効用空間用テンプレ
53 private HashMap<String, Double>[] TemplateLogBidValueHash;
54
55 // 提案ログ保存ハッシュ
56 private Bid[][] logBid;
57
58 // 提案ログの論点ごとの項目出現数格納Hash
59 private HashMap<String, Integer>[][] logBidCountHash;
60
61 // 提案ログから作成した予測効用空間格納Hash
62 private HashMap<String, Double>[][] logBidValueHash;
63
64 // 参加者名と配列要素数の対応格納Hash
65 private HashMap<String, Integer> participantList;
66
67 // 一対比較段数
68 private int compareSize = 0;
69
70 // 一対比較結果用配列
71 private double compareResultArray[];
72
73 // 予測した相手の論点ごとの重み格納用配列
74 private double issueWeightArray[][];
75
76 // 予測の更新回数
77 private int estimateCount[];
78
79 // 効用空間合算時の自分の重み
80 private double weightUtilSpace = 0.0;
81
82 // 合算効用空間Hash
83 private HashMap<String, Double>[] addupValueHash;
84
85 // 合算論点間重み配列
86 private double addupWeightArray[];
87
88 // 直近の合算タイミング
89 private int prevAddupTiming = 0;
90
91 // 相手の提案の自分にとっての効用値合計&効用値2乗合計
92 private double sumUtility[];
93 private double sumUtility2[];
94
95 // 承諾確率計算用
96 private double estimateMax = 0.0;
97 private double utilityBarometer = 0.0;
98
99 /**
100 * コンストラクタ(geniusから呼び出し)
101 *
102 * @param utilitySpace
103 * 自分の効用空間
104 * @param deadlines
105 * 交渉の制限時間
106 * @param timeline
107 * 経過時間(0~1)
108 * @param randomSeed
109 * 乱数用シード
110 */
111 @Override
112 public void init(NegotiationInfo info) {
113
114 // 親クラスコンストラクタ
115 super.init(info);
116
117 // 予約値取得
118 reservationValue = utilitySpace.getReservationValueUndiscounted();
119
120 // 初期化
121 partyNum = 0;
122 issueNum = 0;
123 targetBid = null;
124 underlimitUtility = 0.0;
125 logNum = null;
126 TemplateLogBidCountHash = null;
127 TemplateLogBidValueHash = null;
128 logBid = null;
129 logBidCountHash = null;
130 logBidValueHash = null;
131 participantList = null;
132 compareSize = 0;
133 compareResultArray = null;
134 issueWeightArray = null;
135 estimateCount = null;
136 weightUtilSpace = 0.0;
137 addupValueHash = null;
138 addupWeightArray = null;
139 prevAddupTiming = 0;
140 sumUtility = null;
141 sumUtility2 = null;
142 estimateMax = 0.0;
143 utilityBarometer = 0.0;
144
145 // 論点数取得
146 issueNum = utilitySpace.getDomain().getIssues().size();
147
148 // 提案保存Hashテンプレ&合算効用空間保存Hash作成
149 TemplateLogBidCountHash = new HashMap[issueNum];
150 TemplateLogBidValueHash = new HashMap[issueNum];
151 addupValueHash = new HashMap[issueNum];
152 for (Issue tmp : utilitySpace.getDomain().getIssues()) {
153
154 int issue_num = tmp.getNumber(); // 論点番号
155 IssueDiscrete tmpDiscrete = (IssueDiscrete) tmp;
156
157 TemplateLogBidValueHash[issue_num
158 - 1] = new HashMap<String, Double>();
159 TemplateLogBidCountHash[issue_num
160 - 1] = new HashMap<String, Integer>();
161 addupValueHash[issue_num - 1] = new HashMap<String, Double>();
162 for (int j = 0; j < tmpDiscrete.getNumberOfValues(); j++) {
163 TemplateLogBidValueHash[issue_num - 1]
164 .put(tmpDiscrete.getValue(j).toString(), 0.0);
165 TemplateLogBidCountHash[issue_num - 1]
166 .put(tmpDiscrete.getValue(j).toString(), 0);
167 addupValueHash[issue_num - 1]
168 .put(tmpDiscrete.getValue(j).toString(), 0.0);
169 }
170 }
171
172 // 参加者名と配列要素数対応Hash作成
173 participantList = new HashMap<String, Integer>();
174
175 // 提案作成最低効用値初期値
176 underlimitUtility = 1.0;
177
178 // 効用空間合算の自分の重み初期値
179 weightUtilSpace = 1.0;
180 }
181
182 /**
183 * 自分の番に呼ばれ,AcceptかOfferか選択
184 *
185 * @param validActions
186 * 選べる行動のクラスが格納されている(Accept or
187 * Offer)
188 * @return 選んだ行動のクラス(Accept or Offer)
189 */
190 @Override
191 public Action chooseAction(List<Class<? extends Action>> validActions) {
192
193 if (isEstimated(partyNum)) {
194
195 // 歩み寄り用係数作成
196 makeConcession();
197
198 // 予測効用空間を合算
199 addupUtilSpace(weightUtilSpace);
200 }
201
202 // 承諾が可能な時
203 if (validActions.contains(Accept.class)) {
204
205 // 承諾判断
206 if (getAcceptableProbability() > Math.random()) {
207 return new Accept(getPartyId(),
208 ((ActionWithBid) getLastReceivedAction()).getBid());
209 }
210 }
211
212 // 提案作成
213 Bid nextBid = null;
214 if (isEstimated(partyNum) && underlimitUtility < 1.0) {
215
216 // Bid作成
217 nextBid = generateOfferBid();
218
219 // 予測作成前&譲歩前は最大効用Bid
220 } else {
221 try {
222 nextBid = utilitySpace.getMaxUtilityBid();
223 } catch (Exception e) {
224 e.printStackTrace();
225 }
226 }
227
228 // 判断対象に自分のOfferBidを設定
229 targetBid = nextBid;
230
231 // ログ
232 // System.out.println("Time = "+timeline.getTime());
233 // System.out.println("UnderLimitUtil = "+underlimitUtility);
234 // System.out.println("AddupWeight = "+weightUtilSpace);
235 // System.out.println("Util(UnDiscount) = "+getUtility(nextBid));
236 // System.out.println("Util(Discount) =
237 // "+getUtilityWithDiscount(nextBid));
238
239 // 提案
240 return new Offer(getPartyId(), nextBid);
241 }
242
243 /**
244 * 他の参加者のすべての行動(Accept or
245 * Offer)がメッセージとして受信
246 *
247 * @param sender
248 * 行動者の情報
249 * @param action
250 * 行動内容(Accept,Offer,Inform)
251 */
252 @Override
253 public void receiveMessage(AgentID sender, Action action) {
254
255 // オーバーライドのため
256 super.receiveMessage(sender, action);
257
258 // 初回のみ呼び出し
259 if (action.getClass() == Inform.class) {
260
261 // 交渉参加合計人数取得
262 partyNum = (Integer) ((Inform) action).getValue();
263
264 // 配列&Hash初期化
265 initHashArray(partyNum);
266
267 } else {
268
269 // 参加者に対応する配列要素番号取得
270 int partyID = getSenderID(sender.toString());
271 if (partyID < 0) {
272 partyID = participantList.size();
273 participantList.put(sender.toString(), partyID);
274 estimateCount[partyID] = 0;
275 }
276
277 // senderが誰かの提案を拒否してofferした時
278 if (action.getClass() == Offer.class) {
279
280 // 相手の提案を取得し判断対象に設定
281 Offer received_offer = (Offer) action;
282 targetBid = received_offer.getBid();
283 }
284
285 // 提案ログ更新
286 // senderがacceptした時はtargetBidを提案したとする
287 if (logNum[partyID] < logMax) {
288
289 logBid[partyID][logNum[partyID]] = targetBid;
290 logNum[partyID]++;
291 }
292
293 // 効用値合計更新
294 double util = getUtility(targetBid);
295 sumUtility[partyID] += util;
296 sumUtility2[partyID] += util * util;
297
298 // 効用空間予測
299 if (logNum[partyID] == logMax) {
300
301 // 出現数一時格納Hash作成
302 HashMap<String, Integer>[] TmpCountHash = new HashMap[issueNum];
303 for (int i = 0; i < issueNum; i++) {
304 TmpCountHash[i] = new HashMap<String, Integer>(
305 TemplateLogBidCountHash[i]);
306 }
307
308 // ログから相手のValueの回数計測
309 for (int i = 0; i < logMax; i++) {
310 for (int j = 1; j <= issueNum; j++) {
311 try {
312 if (TmpCountHash[j - 1]
313 .containsKey(logBid[partyID][i].getValue(j)
314 .toString())) {
315 int tmp = TmpCountHash[j - 1]
316 .get(logBid[partyID][i].getValue(j)
317 .toString());
318 TmpCountHash[j - 1].put(logBid[partyID][i]
319 .getValue(j).toString(), tmp + 1);
320 }
321 } catch (Exception e) {
322 System.out.println("getValue Error !\n");
323 }
324 ;
325 }
326 }
327
328 // 偏りのあるデータを一部改変
329 for (int i = 0; i < issueNum; i++) {
330 int tmp = 0;
331 for (String key : logBidCountHash[partyID][i].keySet()) {
332 int count = TmpCountHash[i].get(key);
333 if (tmp < count) {
334 tmp = count;
335 }
336 }
337
338 if (tmp >= logMax) {
339 for (String key : logBidCountHash[partyID][i]
340 .keySet()) {
341 int count = TmpCountHash[i].get(key);
342 if (count < logMax) {
343 TmpCountHash[i].put(key,
344 logMax / compareSize + 1);
345 }
346 }
347 }
348 }
349
350 // 合計出現数に加算&issueごとの最大値も取得
351 int itemCountMax[] = new int[issueNum];
352 for (int i = 0; i < issueNum; i++) {
353 int tmpMax = 0;
354 for (String key : logBidCountHash[partyID][i].keySet()) {
355
356 int now_count = TmpCountHash[i].get(key);
357 int sum_count = logBidCountHash[partyID][i].get(key);
358 logBidCountHash[partyID][i].put(key,
359 (now_count + sum_count));
360
361 if (tmpMax < (now_count + sum_count)) {
362 tmpMax = (now_count + sum_count);
363 }
364 }
365 itemCountMax[i] = tmpMax;
366 }
367
368 // 論点内項目の一対比較
369 for (int i = 0; i < issueNum; i++) {
370
371 // 一対比較閾値格納用配列作成(段階数+1が閾値の数)
372 int compareArray[] = new int[compareSize + 1];
373 for (int j = 0; j <= compareSize; j++) {
374 compareArray[j] = (int) (itemCountMax[i]
375 * ((double) j / (double) compareSize));
376 }
377
378 // 一対比較結果をHashに格納
379 for (String key : logBidCountHash[partyID][i].keySet()) {
380 int tmp = logBidCountHash[partyID][i].get(key);
381 for (int k = 0; k < compareSize; k++) {
382 if (tmp >= compareArray[k]
383 && tmp <= compareArray[k + 1]) {
384 logBidValueHash[partyID][i].put(key,
385 compareResultArray[k]);
386 break;
387 }
388 }
389 }
390 }
391
392 // 論点ごとの重み作成のための一対比較
393 int tmpMax = 0;
394 for (int i = 0; i < issueNum; i++) {
395 if (tmpMax < itemCountMax[i]) {
396 tmpMax = itemCountMax[i];
397 }
398 }
399 int compareArray[] = new int[compareSize + 1];
400 for (int i = 0; i <= compareSize; i++) {
401 compareArray[i] = (int) (tmpMax
402 * ((double) i / (double) compareSize));
403 }
404 double tmpWeightArray[] = new double[issueNum];
405 for (int i = 0; i < issueNum; i++) {
406 int tmp = itemCountMax[i];
407 for (int j = 0; j < compareSize; j++) {
408 if (tmp >= compareArray[j]
409 && tmp <= compareArray[j + 1]) {
410 tmpWeightArray[i] = compareResultArray[j];
411 break;
412 }
413 }
414 }
415
416 // 幾何平均で論点ごとの重み作成
417 double averageMatrix[][] = new double[issueNum][issueNum];
418 for (int i = 0; i < issueNum; i++) {
419 for (int j = 0; j < issueNum; j++) {
420 averageMatrix[i][j] = tmpWeightArray[j]
421 / tmpWeightArray[i];
422 }
423 }
424 double sumMultiply = 0.0;
425 for (int i = 0; i < issueNum; i++) {
426 double multiply = 1.0;
427 for (int j = 0; j < issueNum; j++) {
428 multiply *= averageMatrix[i][j];
429 }
430 multiply = Math.pow(multiply, 1.0 / issueNum);
431 sumMultiply += multiply;
432 issueWeightArray[partyID][i] = multiply;
433 }
434 for (int i = 0; i < issueNum; i++) {
435 issueWeightArray[partyID][i] /= sumMultiply;
436 }
437
438 // 次のログ採取へ移行
439 logNum[partyID] = 0;
440 estimateCount[partyID]++;
441 }
442 }
443 }
444
445 /**
446 * 同意確率を計算
447 *
448 * @return double 同意確率
449 */
450 private double getAcceptableProbability() {
451
452 double probability = 0.0;
453 double time = timeline.getTime();
454 double offeredUtility = getUtility(targetBid);
455
456 // 自分にとって好条件 or
457 // 時間ギリギリなら他条件に関わらず承諾確定
458 if (offeredUtility >= 0.90 || time >= 0.95) {
459 return 1.0;
460 }
461
462 // 効用空間予測が完了している時
463 if (isEstimated(partyNum)) {
464
465 // 譲歩率を元に承諾確率計算
466 double tmp1 = (Math.pow(time, 5.0) / 5.0);
467 tmp1 += (offeredUtility - estimateMax)
468 + (offeredUtility - utilityBarometer);
469
470 // AHP評価値を元に承諾確率を計算
471 double tmp2 = (Math.pow(time, 5.0) / 5.0);
472 double ahpResult = getAHPEvaluation(targetBid);
473 tmp2 += (ahpResult - estimateMax) + (ahpResult - utilityBarometer);
474
475 // 相手の予測効用値を元に承諾確率を計算
476 double tmp3 = 0.0;
477 for (String name : participantList.keySet()) {
478 double otherUtil = getTargetUtility(name, targetBid);
479 if (otherUtil < offeredUtility) {
480 tmp3 += 1.0 / (partyNum - 1.0);
481 } else {
482 tmp3 -= 1.0 / (partyNum - 1.0);
483 }
484 }
485
486 // 承諾確率を決定
487 probability = tmp1 * 0.4 + tmp2 * 0.4 + tmp3 * 0.2;
488 }
489
490 return probability;
491 }
492
493 /**
494 * 提案作成
495 *
496 * @return Bid 提案
497 */
498 private Bid generateOfferBid() {
499
500 Bid nextBid = null;
501 int bidNum = 10;
502 Bid tmpBid[] = new Bid[bidNum];
503
504 // 作成Bidの効用値上限
505 double upperLimitUtility = underlimitUtility + 0.2;
506 if (upperLimitUtility > 1.0) {
507 upperLimitUtility = 1.0;
508 }
509
510 // 効用値が範囲内のBidを複数作成
511 for (int i = 0; i < bidNum; i++) {
512 Bid tmp = null;
513 double util = 0.0;
514 int loop = 100;
515 double tmpUnderlLimit = underlimitUtility;
516 do {
517 tmp = generateRandomBid();
518 util = getUtility(tmp);
519 if (--loop <= 0) {
520 loop = 100;
521 tmpUnderlLimit -= 0.001;
522 }
523 } while (tmp != null
524 && (util < tmpUnderlLimit || util > upperLimitUtility));
525 tmpBid[i] = tmp;
526 }
527
528 // 作成BidをAHPにて評価し一番評価値の高いものを採用
529 double evalValue = 0.0;
530 for (int i = 0; i < bidNum; i++) {
531 double tmp = getAHPEvaluation(tmpBid[i]);
532 if (tmp > evalValue) {
533 tmp = evalValue;
534 nextBid = tmpBid[i];
535 }
536 }
537
538 return nextBid;
539 }
540
541 /**
542 * Hashと配列初期化用
543 *
544 * @param int
545 * 交渉参加人数
546 */
547 private void initHashArray(int partyNum) {
548
549 // 自分以外の参加人数
550 int otherCount = partyNum - 1;
551
552 // 提案ログ現状数格納二次元配列作成
553 logNum = new int[otherCount];
554
555 // 提案ログ格納用二次元配列作成
556 logBid = new Bid[otherCount][logMax];
557
558 // 提案内出現回数カウントHash配列作成
559 logBidCountHash = new HashMap[otherCount][issueNum];
560 for (int i = 0; i < otherCount; i++) {
561 for (int j = 0; j < issueNum; j++) {
562 logBidCountHash[i][j] = new HashMap<String, Integer>(
563 TemplateLogBidCountHash[j]);
564 }
565 }
566
567 // 提案内出現回数カウントHash配列作成
568 logBidValueHash = new HashMap[otherCount][issueNum];
569 for (int i = 0; i < otherCount; i++) {
570 for (int j = 0; j < issueNum; j++) {
571 logBidValueHash[i][j] = new HashMap<String, Double>(
572 TemplateLogBidValueHash[j]);
573 }
574 }
575
576 // 予測効用空間の論点間重み格納配列作成
577 issueWeightArray = new double[otherCount][issueNum];
578
579 // 一対比較の段階数設定&結果配列作成
580 compareSize = issueNum;
581 compareResultArray = new double[compareSize];
582 for (int j = 1; j <= compareSize; j++) {
583 compareResultArray[j - 1] = (2.0 * j - 1.0)
584 / (2.0 * compareSize - 1.0);
585 }
586
587 // 予測の更新回数格納配列作成
588 estimateCount = new int[otherCount];
589 for (int i = 0; i < otherCount; i++) {
590 estimateCount[i] = 0;
591 }
592
593 // 合算した論点間重み格納配列作成
594 addupWeightArray = new double[issueNum];
595
596 // 相手提案の効用値合計格納配列作成
597 sumUtility = new double[otherCount];
598 sumUtility2 = new double[otherCount];
599 for (int i = 0; i < otherCount; i++) {
600 sumUtility[i] = 0.0;
601 sumUtility2[i] = 0.0;
602 }
603 }
604
605 /**
606 * 参加者名から対応する配列要素数を取得
607 *
608 * @param String
609 * 参加者名
610 * @return int 配列要素数
611 */
612 private int getSenderID(String name) {
613
614 int id = -1;
615 if (participantList.containsKey(name)) {
616 id = participantList.get(name);
617 }
618
619 return id;
620 }
621
622 /**
623 * 参加者全員分の予測が作成済みであるかどうか
624 *
625 * @param int
626 * 交渉参加人数
627 * @return boolean 作成済み=true
628 */
629 private boolean isEstimated(int partyNum) {
630
631 int otherCount = partyNum - 1;
632 boolean flag = true;
633 for (int i = 0; i < otherCount; i++) {
634 if (estimateCount[i] <= 0) {
635 flag = false;
636 break;
637 }
638 }
639
640 return flag;
641 }
642
643 /**
644 * 効用空間合算
645 *
646 * @param double
647 * 自分の重み
648 */
649 private void addupUtilSpace(double myWeight) {
650
651 // 合算更新の必要がない
652 // &予測が作成済みでない場合はreturn
653 int timing = 0;
654 for (int i = 0; i < partyNum - 1; i++) {
655 timing += estimateCount[i];
656 }
657 if (timing == prevAddupTiming || !isEstimated(partyNum)) {
658 return;
659 } else {
660 prevAddupTiming = timing;
661 }
662
663 // 自分以外の参加者の重み
664 double otherWeight = (1.0 - myWeight) / (partyNum - 1);
665
666 // 自分の効用空間値取得
667 for (Issue tmp : utilitySpace.getDomain().getIssues()) {
668
669 // 論点番号取得
670 int issue_num = tmp.getNumber();
671
672 // 論点の重み取得し重み付き格納
673 addupWeightArray[issue_num
674 - 1] = ((AdditiveUtilitySpace) utilitySpace)
675 .getWeight(issue_num) * myWeight;
676
677 // 論点内の項目事の値を取得
678 IssueDiscrete tmpDiscrete = (IssueDiscrete) tmp;
679 EvaluatorDiscrete evaluator = (EvaluatorDiscrete) ((AdditiveUtilitySpace) utilitySpace)
680 .getEvaluator(issue_num);
681 for (int j = 0; j < tmpDiscrete.getNumberOfValues(); j++) {
682
683 ValueDiscrete value = tmpDiscrete.getValue(j);
684 try {
685 addupValueHash[issue_num - 1].put(value.toString(),
686 evaluator.getEvaluation(value) * myWeight);
687 } catch (Exception e) {
688 e.printStackTrace();
689 }
690 }
691 }
692
693 // 他参加者の情報を重み付き格納
694 for (int i = 0; i < partyNum - 1; i++) {
695 for (int j = 0; j < issueNum; j++) {
696
697 // 論点間の重みを重み付き格納
698 addupWeightArray[j] += issueWeightArray[i][j] * otherWeight;
699
700 // 論点内の項目事の値を重み付き格納
701 for (String key : logBidValueHash[i][j].keySet()) {
702 double tmp1 = addupValueHash[j].get(key);
703 double tmp2 = logBidValueHash[i][j].get(key);
704 addupValueHash[j].put(key, tmp1 + tmp2 * otherWeight);
705 }
706 }
707 }
708 }
709
710 /**
711 * 自分以外の参加者の効用値予測を取得
712 *
713 * @param String
714 * 参加者名
715 * @param Bid
716 * 予測対象提案
717 * @return double 予測効用値
718 */
719 private double getTargetUtility(String name, Bid targetBid) {
720
721 int partyID = getSenderID(name);
722 double utility = 0.0;
723 if (targetBid != null && partyID >= 0) {
724
725 for (int i = 1; i <= issueNum; i++) {
726
727 try {
728 // 相手の提案を元に予測効用空間から効用を取得し重み掛けて加算
729 String valName = targetBid.getValue(i).toString();
730 utility += (logBidValueHash[partyID][i - 1].get(valName)
731 * issueWeightArray[partyID][i - 1]);
732
733 } catch (Exception e) {
734 System.out.println("getValue Error !\n");
735 }
736 ;
737 }
738 }
739
740 return utility;
741 }
742
743 /**
744 * AHPによる提案の評価値を取得
745 *
746 * @param Bid
747 * 予測対象提案
748 * @return double 予測評価値(効用値)
749 */
750 private double getAHPEvaluation(Bid targetBid) {
751
752 double utility = 0.0;
753 if (targetBid != null && isEstimated(partyNum)) {
754
755 for (int i = 1; i <= issueNum; i++) {
756
757 try {
758 // 合算した効用空間から効用を取得
759 String valName = targetBid.getValue(i).toString();
760 utility += (addupValueHash[i - 1].get(valName)
761 * addupWeightArray[i - 1]);
762
763 } catch (Exception e) {
764 System.out.println("getValue Error !\n");
765 }
766 ;
767 }
768 }
769
770 return utility;
771 }
772
773 /**
774 * 譲歩度合い設定
775 */
776 private void makeConcession() {
777
778 int otherCount = partyNum - 1;
779 double time = timeline.getTime();
780 double tremor = 1.0; // 行動のゆらぎ幅
781 double gt = 0.2; // 最高でどの程度まで譲歩するか(1.0-gt)まで
782
783 // 参加者全員の効用値合計
784 double allSum = 0.0;
785 double allSum2 = 0.0;
786 for (int i = 0; i < otherCount; i++) {
787 allSum += sumUtility[i];
788 allSum2 += sumUtility2[i];
789 }
790
791 // 現在の相手全員からの合計提案数
792 int round = 0;
793 for (int i = 0; i < otherCount; i++) {
794 round += estimateCount[i] * logMax + logNum[i];
795 }
796
797 // 平均
798 double mean = allSum / round;
799
800 // 分散
801 double variance = Math.sqrt(((allSum2) / round) - (mean * mean));
802 if (Double.isNaN(variance)) {
803 variance = 0.0;
804 }
805
806 // 行動の幅(論文でのd(t))
807 double width = Math.sqrt(12) * variance;
808 if (Double.isNaN(width)) {
809 width = 0.0;
810 }
811
812 // 最大効用の推定値
813 estimateMax = mean + ((1.0 - mean) * width);
814
815 // 歩み寄り速度調整用
816 double alpha = 1.0 + tremor + (7.0 * mean) - (2.0 * tremor * mean);
817 double beta = alpha + (Math.random() * tremor) - (tremor / 2);
818
819 // 歩み寄り後の最低効用値(仮)
820 // 1:承諾判断用,2:提案作成用
821 double tmpConsession1 = 1.0
822 - (Math.pow(time, alpha) * (1.0 - estimateMax));
823 double tmpConsession2 = 1.0
824 - (Math.pow(time, beta) * (1.0 - estimateMax));
825
826 // 歩み寄り度合い
827 double ratio1 = (width + gt) / (1.0 - tmpConsession1);
828 if (Double.isNaN(ratio1) || ratio1 > 2.0) {
829 ratio1 = 2.0;
830 }
831 double ratio2 = (width + gt) / (1.0 - tmpConsession2);
832 if (Double.isNaN(ratio2) || ratio2 > 2.0) {
833 ratio2 = 2.0;
834 }
835
836 // 提案作成用最低効用値作成
837 // 作成提案最低効用値と効用空間合算時の自分の重みに利用
838 double tmp = ratio2 * tmpConsession2 + (1.0 - ratio2);
839 if (tmp < underlimitUtility) {
840 underlimitUtility = tmp;
841 if (underlimitUtility < reservationValue) {
842 underlimitUtility = reservationValue;
843 }
844 weightUtilSpace = 1.0 - ((1.0 - tmp) * 2);
845 if (weightUtilSpace < 0.4) {
846 weightUtilSpace = 0.4;
847 }
848 }
849
850 // 承諾判断用効用値指標作成
851 utilityBarometer = ratio1 * tmpConsession1 + (1.0 - ratio1);
852 }
853
854 @Override
855 public String getDescription() {
856 return "ANAC2015";
857 }
858}
Note: See TracBrowser for help on using the repository browser.