source: src/main/java/agents/anac/y2016/agenthp2/AgentHP2_main.java

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

Initial import : Genius 9.0.0

File size: 14.1 KB
Line 
1package agents.anac.y2016.agenthp2;
2
3import java.util.ArrayList;
4import java.util.HashMap;
5import java.util.List;
6
7import genius.core.AgentID;
8import genius.core.Bid;
9import genius.core.actions.Accept;
10import genius.core.actions.Action;
11import genius.core.actions.ActionWithBid;
12import genius.core.actions.Inform;
13import genius.core.actions.Offer;
14import genius.core.parties.AbstractNegotiationParty;
15import genius.core.parties.NegotiationInfo;
16import genius.core.utility.AbstractUtilitySpace;
17
18/**
19 * AgentHP2 main class
20 *
21 * @author Hiroyuki Shinohara
22 * @date 2016/03/30
23 */
24public class AgentHP2_main extends AbstractNegotiationParty {
25
26 private int partyNum = 0; // 交渉参加者合計人数
27 private int issueNum = 0; // 論点数
28 private int targetID = 0; // 判断対象の提案者ID
29 private Bid targetBid = null; // 判断対象の提案
30 private double reservationValue = 0.0; // 予約値
31 private double discountFactor = 0.0; // 割引係数
32 private AbstractUtilitySpace myUtilitySpace = null; // 自身の効用関数保存用
33 private double underlimitUtility = 1.0; // 効用値の下限値(時間で変化)
34 private HashMap<String, Integer> participantList; // 参加者名と配列要素数の対応格納Hash
35 private double sumUtility[]; // 相手の提案の自分にとっての効用値合計
36 private int othersOfferCount[]; // 参加者それぞれの累計提案数
37 private module_AHP AHPEvaluator = null; // AHPクラス用インスタンス
38 private boolean isExpectedUtilitySpace = false; // 効用空間予測の初回実行済み判断フラグ
39 private int nextExpectTiming = 0; // 次の効用空間予測タイミング
40 private double expectUtilitySpaceTimingArray[]; // 効用空間の予測タイミング格納用配列
41 private double sumAHPEvalationForOpponent[]; // 相手の提案の相手に取ってのAHP評価値の合計
42 private double sumAHPEvalationForOpponent2[]; // 相手の提案の相手に取ってのAHP評価値の二乗の合計
43 private double estimateAHPEvaluationMax[]; // 交渉相手の予測最大AHP評価値
44 private double maximumConcessionDegree = 0.0; // 最大でどこまで譲歩するか
45 private module_BidGenerate bidGenerater = null; // Bid作成クラス用インスタンス
46 private ArrayList<Bid> offeredBidList[] = null; // 交渉相手からの提案一時保存用
47
48 /**
49 * 初期化(geniusから呼び出し)
50 *
51 * @param utilitySpace
52 * 自分の効用空間
53 * @param deadlines
54 * 交渉の制限時間
55 * @param timeline
56 * 経過時間(0~1)
57 * @param randomSeed
58 * 乱数用シード
59 * @param agentID
60 * 自分の表示名
61 */
62 @Override
63 public void init(NegotiationInfo info) {
64
65 // 親クラス初期化メソッド
66 super.init(info);
67
68 // 最低効用値取得
69 reservationValue = utilitySpace.getReservationValueUndiscounted();
70
71 // 割引係数取得
72 discountFactor = utilitySpace.getDiscountFactor();
73
74 // 自身の効用関数取得
75 myUtilitySpace = utilitySpace;
76
77 // 初期化
78 partyNum = 0;
79 issueNum = 0;
80 targetID = 0;
81 targetBid = null;
82 underlimitUtility = 0.0;
83 participantList = null;
84 sumUtility = null;
85 othersOfferCount = null;
86 AHPEvaluator = null;
87 isExpectedUtilitySpace = false;
88 expectUtilitySpaceTimingArray = null;
89 nextExpectTiming = 0;
90 sumAHPEvalationForOpponent = null;
91 sumAHPEvalationForOpponent2 = null;
92 estimateAHPEvaluationMax = null;
93 offeredBidList = null;
94
95 // 論点数取得
96 issueNum = utilitySpace.getDomain().getIssues().size();
97
98 // 参加者名と配列要素数対応Hash作成
99 participantList = new HashMap<String, Integer>();
100
101 // 提案作成最低効用値初期値
102 underlimitUtility = 1.0;
103
104 // 効用空間予測タイミング作成
105 int expectTimingNum = 50;
106 expectUtilitySpaceTimingArray = new double[expectTimingNum];
107 for (int i = 0; i < expectTimingNum; i++) {
108 expectUtilitySpaceTimingArray[i] = (i + 1.0) / (double) expectTimingNum;
109 }
110
111 // Bid作成クラス読み込み
112 bidGenerater = new module_BidGenerate(utilitySpace);
113
114 // 最大でどこまで譲歩するか決定
115 maximumConcessionDegree = 0.35;
116 if (1.0 - maximumConcessionDegree < reservationValue) {
117 maximumConcessionDegree = 1.0 - reservationValue;
118 }
119 }
120
121 /**
122 * 自分の番に呼ばれ,AcceptかOfferか選択
123 *
124 * @param validActions
125 * 選べる行動のクラスが格納されている(Accept or Offer)
126 * @return 選んだ行動のクラス(Accept or Offer)
127 */
128 @Override
129 public Action chooseAction(List<Class<? extends Action>> validActions) {
130
131 if (timeline.getTime() > expectUtilitySpaceTimingArray[nextExpectTiming]) {
132
133 // 自分以外の参加者人数
134 int otherCount = partyNum - 1;
135
136 // 効用空間予測更新
137 for (int i = 0; i < otherCount; i++) {
138 AHPEvaluator.updateExpectUtilitySpace(i);
139 }
140
141 // 次の更新タイミングへ
142 nextExpectTiming += 1;
143
144 // 効用関数の初回予測時のみ実行
145 if (!isExpectedUtilitySpace) {
146
147 // 効用関数予測済みフラグON
148 isExpectedUtilitySpace = true;
149
150 // 効用関数予測前の提案のAHP評価値をまとめて合計に加算
151 for (int i = 0; i < otherCount; i++) {
152 int listSize = offeredBidList[i].size();
153 for (int j = 0; j < listSize; j++) {
154 updateAHPEvaluationSum(i, offeredBidList[i].get(j));
155 }
156 }
157 }
158 }
159
160 // 効用関数予測済みなら歩み寄り度合い更新
161 if (isExpectedUtilitySpace) {
162 makeConcessionParameterByAHP();
163 }
164
165 // 承諾が可能な時
166 if (validActions.contains(Accept.class)) {
167
168 // 承諾判断
169 double probability = getAcceptableProbability();
170 if (probability >= Math.random() || probability >= 0.90) {
171 return new Accept(getPartyId(), ((ActionWithBid) getLastReceivedAction()).getBid());
172 }
173 }
174
175 // 提案作成
176 Bid nextBid = null;
177 if (isExpectedUtilitySpace && underlimitUtility < 1.0) {
178
179 // Bid作成
180 nextBid = generateOfferBid();
181
182 // 予測作成前&譲歩前は最大効用Bid
183 } else {
184 nextBid = bidGenerater.getMaximumEvaluationBid();
185 }
186
187 // 判断対象に自分のOfferBidを設定
188 targetBid = nextBid;
189
190 // 提案
191 return new Offer(getPartyId(), nextBid);
192 }
193
194 /**
195 * 他の参加者のすべての行動(Accept or Offer)がメッセージとして受信
196 *
197 * @param sender
198 * 行動者の情報
199 * @param action
200 * 行動内容(Accept,Offer,Inform)
201 */
202 @Override
203 public void receiveMessage(AgentID sender, Action action) {
204
205 // オーバーライドのため
206 super.receiveMessage(sender, action);
207
208 // 初回のみ呼び出し
209 if (action.getClass() == Inform.class) {
210
211 // 交渉参加合計人数取得
212 partyNum = (int) ((Inform) action).getValue();
213
214 // 配列&Hash初期化
215 initHashArray(partyNum);
216
217 // AHPクラス呼び出し
218 AHPEvaluator = new module_AHP(utilitySpace, partyNum);
219
220 } else {
221
222 // 参加者に対応する配列要素番号取得
223 int partyID = getSenderID(sender.toString());
224 if (partyID < 0) {
225 partyID = participantList.size();
226 participantList.put(sender.toString(), partyID);
227 }
228
229 // senderが誰かの提案を拒否してofferした時
230 if (action.getClass() == Offer.class) {
231
232 // 相手の提案を取得し判断対象に設定 & 提案者ID保存
233 Offer received_offer = (Offer) action;
234 targetBid = received_offer.getBid();
235 targetID = partyID;
236
237 // senderが誰かの提案をAcceptした時
238 } else if (action.getClass() == Accept.class) {
239
240 // 提案者ID保存
241 // senderがacceptした時はtargetBidを提案したとする
242 targetID = partyID;
243 }
244
245 // 提案内容の数え上げ
246 AHPEvaluator.countBid(partyID, targetBid);
247
248 // 各交渉相手の提案回数をカウント
249 othersOfferCount[partyID]++;
250
251 // 効用値合計更新
252 double util = getMyUtility(targetBid);
253 sumUtility[partyID] += util;
254
255 // 交渉相手の効用関数予測済みかで処理分岐
256 if (isExpectedUtilitySpace) {
257
258 // 相手の提案の推定譲歩度合い(相手から見たAHP評価値)合計更新
259 updateAHPEvaluationSum(partyID, targetBid);
260
261 } else {
262
263 // 交渉相手の効用関数が未予測なので提案をリストに保存
264 offeredBidList[partyID].add(targetBid);
265 }
266 }
267 }
268
269 /**
270 * 同意確率を計算
271 *
272 * @return double 同意確率
273 */
274 private double getAcceptableProbability() {
275
276 double probability = 0.0;
277 double time = timeline.getTime();
278 double offeredUtility = getMyUtility(targetBid);
279 double offeredAHPEvaluation = 0.0;
280
281 // 以下の条件では必ず承諾
282 // 1. 効用が一定以上
283 // 2. 交渉の残り時間がギリギリ
284 // 3. 提案の効用が現在の提案作成基準値以上
285 if (offeredUtility >= 0.90 || time >= 0.99 || offeredUtility >= underlimitUtility) {
286 return 1.0;
287 }
288
289 // 効用空間予測が完了している時
290 if (isExpectedUtilitySpace) {
291
292 // 提案の提案者から見たAHP評価値を取得
293 offeredAHPEvaluation = AHPEvaluator.getAHPEvaluationForOpponents(targetID, targetBid);
294
295 // 譲歩率を元に承諾確率計算
296 double tmp1 = (Math.pow(time, 5.0) / (5.0 * discountFactor));
297 tmp1 += (offeredAHPEvaluation - estimateAHPEvaluationMax[targetID]) + (offeredUtility - underlimitUtility);
298
299 // 承諾確率を決定
300 probability = tmp1;
301 }
302
303 return probability;
304 }
305
306 /**
307 * 提案作成
308 *
309 * @return Bid 提案
310 */
311 private Bid generateOfferBid() {
312
313 Bid nextBid = null;
314 int createBidNum = 10;
315 Bid tmpBidArray[] = new Bid[createBidNum];
316
317 // 作成Bidの効用範囲作成
318 double upperLimitUtility = underlimitUtility + 0.05;
319 double lowerLimitUtility = underlimitUtility - 0.05;
320 if (upperLimitUtility > 1.0) {
321 upperLimitUtility = 1.0;
322 }
323 if (lowerLimitUtility < reservationValue) {
324 lowerLimitUtility = reservationValue;
325 }
326
327 // 効用値が範囲内のBidを複数作成
328 for (int i = 0; i < createBidNum; i++) {
329 Bid tmp = null;
330 double util = 0.0;
331 int loop = 100;
332 do {
333 tmp = generateRandomBid();
334 util = getUtility(tmp);
335 if (--loop <= 0) {
336 loop = 100;
337 lowerLimitUtility -= 0.01;
338 upperLimitUtility += 0.01;
339 }
340
341 } while (tmp != null && (util < lowerLimitUtility || util > upperLimitUtility));
342 tmpBidArray[i] = tmp;
343 }
344
345 // 作成BidをAHPにて評価し一番評価値の高いものを採用
346 double evalValue = 0.0;
347 for (int i = 0; i < createBidNum; i++) {
348 double tmp = AHPEvaluator.getAHPEvaluation(tmpBidArray[i]);
349 if (tmp > evalValue) {
350 evalValue = tmp;
351 nextBid = tmpBidArray[i];
352 }
353 }
354
355 // エラー対策
356 if (nextBid == null) {
357 nextBid = tmpBidArray[0];
358 }
359
360 return nextBid;
361 }
362
363 /**
364 * Hashと配列初期化用
365 *
366 * @param int
367 * 交渉参加人数
368 */
369 private void initHashArray(int partyNum) {
370
371 // 自分以外の参加人数
372 int otherCount = partyNum - 1;
373
374 // 相手提案の効用値合計格納配列作成
375 sumUtility = new double[otherCount];
376 for (int i = 0; i < otherCount; i++) {
377 sumUtility[i] = 0.0;
378 }
379
380 // 参加者の累計提案数格納配列作成
381 othersOfferCount = new int[otherCount];
382 for (int i = 0; i < otherCount; i++) {
383 othersOfferCount[i] = 0;
384 }
385
386 // 相手にとってのAHP評価値合計格納用配列作成
387 sumAHPEvalationForOpponent = new double[otherCount];
388 sumAHPEvalationForOpponent2 = new double[otherCount];
389 for (int i = 0; i < otherCount; i++) {
390 sumAHPEvalationForOpponent[i] = 0.0;
391 sumAHPEvalationForOpponent2[i] = 0.0;
392 }
393
394 // 譲歩関数用
395 estimateAHPEvaluationMax = new double[otherCount];
396 for (int i = 0; i < otherCount; i++) {
397 estimateAHPEvaluationMax[i] = 0.0;
398 }
399
400 // 提案保存用List作成
401 offeredBidList = new ArrayList[otherCount];
402 for (int i = 0; i < otherCount; i++) {
403 offeredBidList[i] = new ArrayList<Bid>();
404 }
405 }
406
407 /**
408 * 参加者名から対応する配列要素数を取得
409 *
410 * @param String
411 * 参加者名
412 * @return int 配列要素数
413 */
414 private int getSenderID(String name) {
415
416 int id = -1;
417 if (participantList.containsKey(name)) {
418 id = participantList.get(name);
419 }
420
421 return id;
422 }
423
424 /**
425 * AHPによる評価値を利用した譲歩関数
426 */
427 private void makeConcessionParameterByAHP() {
428
429 int otherCount = partyNum - 1;
430 double time = timeline.getTime();
431 double minEstimateMax = 1.0;
432
433 // 承諾判定用パラメータ作成
434 for (int i = 0; i < otherCount; i++) {
435
436 double average = sumAHPEvalationForOpponent[i] / othersOfferCount[i];
437 double average2 = sumAHPEvalationForOpponent2[i] / othersOfferCount[i];
438 double variance = average2 - average * average;
439
440 // 交渉相手から引き出せるAHP評価値の予測最大
441 estimateAHPEvaluationMax[i] = average + ((1.0 - average) * Math.sqrt(12.0) * variance);
442
443 // 予測最大値の小さい方(将来的に譲歩が少ない方)を保存(0除算警戒)
444 if (minEstimateMax > estimateAHPEvaluationMax[i] && estimateAHPEvaluationMax[i] > 0.0) {
445 minEstimateMax = estimateAHPEvaluationMax[i];
446 }
447 }
448
449 // 提案作成用基準効用値作成
450 double tmpUtility = 1.0 - maximumConcessionDegree
451 * Math.pow(time, (Math.pow(discountFactor, 3.0) / Math.pow(minEstimateMax, 1.0)));
452 if (underlimitUtility > tmpUtility) {
453 underlimitUtility = tmpUtility;
454 }
455 }
456
457 /**
458 * 指定されたBidの自身の効用値を取得
459 *
460 * @param Bid
461 * 効用値を取得したいBid
462 * @return double 指定されたBidの効用値
463 */
464 private double getMyUtility(Bid getTargetBid) {
465
466 double utility = 0.0;
467 try {
468 utility = myUtilitySpace.getUtility(getTargetBid);
469 } catch (Exception e) {
470 System.out.println("Get My Utility Target Bid Is Wrong");
471 System.out.println("Wrong Bid Content: " + targetBid.toString());
472 }
473
474 return utility;
475 }
476
477 /**
478 * 提案の提案者からみたAHP評価値(=提案の推定譲歩度合い)の合計を更新
479 *
480 * @param int
481 * 参加者ID
482 * @param Bid
483 * 更新対象のBid
484 */
485 private void updateAHPEvaluationSum(int partyID, Bid updateTarget) {
486
487 double ahpEval = AHPEvaluator.getAHPEvaluationForOpponents(partyID, updateTarget);
488 sumAHPEvalationForOpponent[partyID] += ahpEval;
489 sumAHPEvalationForOpponent2[partyID] += ahpEval * ahpEval;
490 }
491
492 @Override
493 public String getDescription() {
494 return "ANAC2016";
495 }
496}
Note: See TracBrowser for help on using the repository browser.