source: src/main/java/agents/anac/y2016/agenthp2/module_AHP.java@ 326

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

Initial import : Genius 9.0.0

File size: 15.4 KB
Line 
1package agents.anac.y2016.agenthp2;
2
3import java.util.HashMap;
4
5import genius.core.Bid;
6import genius.core.issue.ISSUETYPE;
7import genius.core.issue.Issue;
8import genius.core.issue.IssueDiscrete;
9import genius.core.issue.IssueInteger;
10import genius.core.utility.AbstractUtilitySpace;
11
12/**
13 * AHP Evaluation class
14 *
15 * @author Hiroyuki Shinohara
16 * @date 2016/03/30
17 */
18public class module_AHP {
19
20 private int issueNum; // 効用空間の論点数
21 private AbstractUtilitySpace myUtilitySpace; // 自分の効用空間
22 private int issueElementCount[]; // 論点内の要素数
23 private HashMap<String, Integer>[][] valueCountHash; // 提案内出現回数カウント用Hash
24 private HashMap<String, Double>[][] expectUtilSpaceHash; // 予測効用空間保存用Hash
25 private double expectIssueWeightArray[][]; // 予測論点間重み保存用配列
26 private double geometricAverageMatrix[][]; // 幾何平均計算用一対比較行列格納用配列
27 private int pairComparisonSize; // 一対比較の段階数
28 private double pairComparisonResultArray[]; // 一対比較の結果参照用配列
29 private int pairComparisonThresholdArray[]; // 一対比較の出現数閾値格納用配列
30 private int valueCountMaxArray[]; // 論点ごと選択肢最大出現回数格納用配列
31 private double evaluationUtilityWeightArray[]; // AHP評価値に利用する参加者ごとの効用値重み格納用配列
32 private ISSUETYPE issueTypeArray[]; // 論点ごとの論点タイプの保存用配列
33
34 /**
35 * コンストラクタ(配列等初期化)
36 *
37 * @param UtilitySpace
38 * 効用空間
39 * @param int 参加者数
40 */
41 public module_AHP(AbstractUtilitySpace utilitySpace, int participantNum) {
42
43 // 論点数取得
44 issueNum = utilitySpace.getDomain().getIssues().size();
45
46 // 効用空間保存
47 myUtilitySpace = utilitySpace;
48
49 // 自分以外の参加人数
50 int otherCount = participantNum - 1;
51
52 // 予測効用保存&提案カウント用Hash作成
53 // 各論点タイプを保存
54 valueCountHash = new HashMap[otherCount][issueNum];
55 expectUtilSpaceHash = new HashMap[otherCount][issueNum];
56 issueTypeArray = new ISSUETYPE[issueNum];
57 for (int i = 0; i < otherCount; i++) {
58 for (Issue tmp : utilitySpace.getDomain().getIssues()) {
59
60 // 論点番号取得
61 int issue_num = tmp.getNumber();
62
63 // 論点タイプ保存
64 issueTypeArray[issue_num - 1] = tmp.getType();
65
66 // Hash作成
67 expectUtilSpaceHash[i][issue_num - 1] = new HashMap<String, Double>();
68 valueCountHash[i][issue_num - 1] = new HashMap<String, Integer>();
69 switch (tmp.getType()) {
70
71 // 論点が離散値の場合
72 case DISCRETE:
73 IssueDiscrete tmpDiscrete = (IssueDiscrete) tmp;
74 for (int j = 0; j < tmpDiscrete.getNumberOfValues(); j++) {
75 expectUtilSpaceHash[i][issue_num - 1].put(tmpDiscrete
76 .getValue(j).toString(), 0.0);
77 valueCountHash[i][issue_num - 1].put(tmpDiscrete
78 .getValue(j).toString(), 0);
79 }
80 break;
81
82 // 論点が連続値の場合
83 case INTEGER:
84 IssueInteger tmpInteger = (IssueInteger) tmp;
85 int lowest = tmpInteger.getLowerBound();
86 int highest = tmpInteger.getUpperBound();
87 for (int j = lowest; j <= highest; j++) {
88 expectUtilSpaceHash[i][issue_num - 1].put(
89 String.valueOf(j), 0.0);
90 valueCountHash[i][issue_num - 1].put(String.valueOf(j),
91 0);
92 }
93 break;
94
95 case OBJECTIVE:
96 case REAL:
97 case UNKNOWN:
98 default:
99 break;
100 }
101 }
102 }
103
104 // 論点内要素数保存配列作成
105 issueElementCount = new int[issueNum];
106 for (Issue tmp : utilitySpace.getDomain().getIssues()) {
107 switch (tmp.getType()) {
108
109 // 論点が離散値の場合
110 case DISCRETE:
111 issueElementCount[tmp.getNumber() - 1] = ((IssueDiscrete) tmp)
112 .getNumberOfValues();
113 break;
114
115 // 論点が連続値の場合
116 case INTEGER:
117 issueElementCount[tmp.getNumber() - 1] = ((IssueInteger) tmp)
118 .getUpperBound()
119 - ((IssueInteger) tmp).getLowerBound()
120 + 1;
121 break;
122
123 case OBJECTIVE:
124 case REAL:
125 case UNKNOWN:
126 default:
127 break;
128 }
129 }
130
131 // 予測効用空間の論点間重み格納配列作成
132 expectIssueWeightArray = new double[otherCount][issueNum];
133
134 // 一対比較の段階数設定&閾値格納用配列作成&結果配列作成
135 pairComparisonSize = 9; // 1,3,5,7,9 + 偶数値
136 pairComparisonThresholdArray = new int[pairComparisonSize + 1]; // 閾値なので+1
137 // |A1|A2|A3|:数値3,閾値4
138 pairComparisonResultArray = new double[pairComparisonSize];
139 for (int j = 1; j <= pairComparisonSize; j++) {
140 pairComparisonResultArray[j - 1] = (double) j
141 / (double) pairComparisonSize;
142 }
143
144 // 幾何平均用一対比較行列格納配列作成
145 int tmpMax = issueNum;
146 for (int i = 0; i < issueElementCount.length; i++) {
147 if (tmpMax < issueElementCount[i]) {
148 tmpMax = issueElementCount[i];
149 }
150 }
151 geometricAverageMatrix = new double[tmpMax][tmpMax];
152
153 // 論点ごと要素カウント最大格納用配列作成
154 valueCountMaxArray = new int[issueNum];
155
156 // AHP評価値用効用重み配列作成
157 evaluationUtilityWeightArray = new double[otherCount];
158 for (int i = 0; i < otherCount; i++) {
159 evaluationUtilityWeightArray[i] = 1.0 / (double) otherCount;
160 }
161 }
162
163 /**
164 * 相手からのBidの内容をカウント
165 *
166 * @param int 参加者番号(0〜)
167 * @param Bid
168 * カウント対象Bid
169 */
170 public void countBid(int partyID, Bid targetBid) {
171
172 // Bidの内容を論点ごとにHashにカウント
173 for (int i = 1; i <= issueNum; i++) {
174 try {
175 if (valueCountHash[partyID][i - 1].containsKey(targetBid
176 .getValue(i).toString())) {
177 int tmp = valueCountHash[partyID][i - 1].get(targetBid
178 .getValue(i).toString());
179 valueCountHash[partyID][i - 1].put(targetBid.getValue(i)
180 .toString(), tmp + 1);
181 }
182 } catch (Exception e) {
183 System.out.println("Offerd Bid From Party " + partyID
184 + " Is Wrong");
185 System.out
186 .println("Wrong Bid Content: " + targetBid.toString());
187 }
188 }
189 }
190
191 /**
192 * 相手の効用空間予測更新(一対比較&幾何平均)
193 *
194 * @param int 参加者番号(0〜)
195 */
196 public void updateExpectUtilitySpace(int partyID) {
197
198 // 論点内項目の評価値予測
199 for (int i = 0; i < issueNum; i++) {
200
201 // 論点内要素のカウントを配列に格納
202 int arrayKey = 0;
203 int elementCount[] = new int[issueElementCount[i]];
204 for (String key : valueCountHash[partyID][i].keySet()) {
205
206 int count = valueCountHash[partyID][i].get(key);
207 elementCount[arrayKey++] = count;
208 }
209
210 // 数え上げ結果を元にした論点内の各要素への重要度の割り当て
211 double elementPairComparisonArray[] = new double[issueElementCount[i]];
212 switch (issueTypeArray[i]) {
213
214 // 論点が離散値の場合
215 case DISCRETE:
216
217 // 評価が最大と予想される要素(=最大の出現数の要素)のカウントも保存
218 int tmpMax = 0;
219 for (int k = 0; k < elementCount.length; k++) {
220 if (tmpMax < elementCount[k]) {
221 tmpMax = elementCount[k];
222 }
223 }
224 valueCountMaxArray[i] = tmpMax;
225
226 // 論点内要素評価値予測のための一対比較(重要度割り当て)
227 setPairComparisonArray(elementCount, elementPairComparisonArray);
228
229 break;
230
231 // 論点が連続値の場合
232 case INTEGER:
233
234 // 連続値の前半と後半それぞれの出現数の和を取得
235 int elementSize = elementCount.length;
236 int sum_former = 0,
237 sum_latter = 0;
238 for (int k = 0; k < elementSize; k++) {
239 if ((elementSize / 2) > k) {
240 sum_former += elementCount[k];
241 } else {
242 sum_latter += elementCount[k];
243 }
244 }
245
246 // 前半の方が出現数の総和が多い: 連続値に効用は反比例(1.0→0.0)
247 if (sum_former > sum_latter) {
248
249 // 評価が最大の要素(=最小の連続値)のカウントも保存
250 valueCountMaxArray[i] = elementCount[0];
251
252 // 最小の連続値には重要度9を割り当て,最大の連続値には重要度1を割り当て(9→1)
253 double offset = pairComparisonResultArray[pairComparisonSize - 1]
254 - pairComparisonResultArray[0];
255 for (int j = elementSize - 1; j >= 0; j--) {
256 elementPairComparisonArray[elementSize - j - 1] = pairComparisonResultArray[0]
257 + (offset * (double) j / (double) (elementSize - 1));
258 }
259
260 // 後半の方が出現数の総和が多い: 連続値に効用は比例(0.0→1.0)
261 } else {
262
263 // 評価が最大の要素(=最大の連続値)のカウントも保存
264 valueCountMaxArray[i] = elementCount[elementSize - 1];
265
266 // 最小の連続値には重要度1を割り当て,最大の連続値には重要度9を割り当て(1→9)
267 double offset = pairComparisonResultArray[pairComparisonSize - 1]
268 - pairComparisonResultArray[0];
269 for (int j = elementSize - 1; j >= 0; j--) {
270 elementPairComparisonArray[j] = pairComparisonResultArray[0]
271 + (offset * (double) j / (double) (elementSize - 1));
272 }
273 }
274
275 break;
276
277 case OBJECTIVE:
278 case REAL:
279 case UNKNOWN:
280 default:
281 break;
282 }
283
284 // 一対比較結果を幾何平均で論点内要素評価値予測(最大1になるよう正規化)
285 double elementGeometricAverageArray[] = new double[issueElementCount[i]];
286 setGeometricAverageArray(issueElementCount[i],
287 elementPairComparisonArray, elementGeometricAverageArray);
288 double maxGeometricAverage = 0.0;
289 for (int j = 0; j < issueElementCount[i]; j++) {
290 if (maxGeometricAverage < elementGeometricAverageArray[j]) {
291 maxGeometricAverage = elementGeometricAverageArray[j];
292 }
293 }
294 for (int j = 0; j < issueElementCount[i]; j++) {
295 elementGeometricAverageArray[j] /= maxGeometricAverage;
296 }
297
298 // 予測評価値をHashに保存
299 arrayKey = 0;
300 for (String key : valueCountHash[partyID][i].keySet()) {
301 expectUtilSpaceHash[partyID][i].put(key,
302 elementGeometricAverageArray[arrayKey++]);
303 }
304 }
305
306 // 論点間重み予測のための一対比較
307 double weightPairComparisonArray[] = new double[issueNum];
308 setPairComparisonArray(valueCountMaxArray, weightPairComparisonArray);
309
310 // 一対比較結果を幾何平均で論点間重み予測(総和1になるよう正規化)
311 setGeometricAverageArray(issueNum, weightPairComparisonArray,
312 expectIssueWeightArray[partyID]);
313 double sumGeometricAverage = 0.0;
314 for (int i = 0; i < issueNum; i++) {
315 sumGeometricAverage += expectIssueWeightArray[partyID][i];
316 }
317 for (int i = 0; i < issueNum; i++) {
318 expectIssueWeightArray[partyID][i] /= sumGeometricAverage;
319 }
320
321 // log
322 /*
323 * System.out.println("Party ID = "+partyID); for(int
324 * i=0;i<issueNum;i++){ System.out.println("Issue " + (i+1) +
325 * " Count = " + valueCountHash[partyID][i].toString());
326 * System.out.println("Issue " + (i+1) + " Expect = " +
327 * expectUtilSpaceHash[partyID][i].toString());
328 * System.out.println("Issue " + (i+1) + " Weitght = " +
329 * expectIssueWeightArray[partyID][i]); }
330 */
331 }
332
333 /**
334 * 一対比較結果取得
335 *
336 * @param int[] 一対比較対象配列
337 * @param double[] 一対比較結果配列
338 */
339 private void setPairComparisonArray(int targetArray[],
340 double pairComparison[]) {
341
342 int arraySize = targetArray.length;
343
344 // 一対比較対象の最大値&最小値取得
345 int tmpMaxCount = -1;
346 int tmpMinCount = -1;
347 for (int i = 0; i < arraySize; i++) {
348 if (tmpMaxCount == -1 || tmpMaxCount < targetArray[i]) {
349 tmpMaxCount = targetArray[i];
350 }
351 if (tmpMinCount == -1 || tmpMinCount > targetArray[i]) {
352 tmpMinCount = targetArray[i];
353 }
354 }
355 if (tmpMaxCount - tmpMinCount <= pairComparisonSize)
356 tmpMinCount = 0;
357
358 // 一対比較閾値格納用配列作成(段階数+1が閾値の数)
359 // [最小,最大]の範囲を分割
360 // 重要度割り当て用範囲を一定でなく重み付け
361 double tmpRangeLimit = tmpMaxCount - tmpMinCount;
362 double rangeWeightArray[] = { 0.00, 0.05, 0.10, 0.20, 0.30, 0.40, 0.55,
363 0.70, 0.85, 1.00 }; // 偶数利用+重要度5-9に重み
364 for (int i = 0; i <= pairComparisonSize; i++) {
365 pairComparisonThresholdArray[i] = (int) ((double) tmpRangeLimit * rangeWeightArray[i]);
366 pairComparisonThresholdArray[i] += tmpMinCount;
367 }
368
369 // 一対比較
370 for (int i = 0; i < arraySize; i++) {
371
372 int tmp = targetArray[i];
373 for (int j = 0; j < pairComparisonSize; j++) {
374 if (tmp >= pairComparisonThresholdArray[j]
375 && tmp <= pairComparisonThresholdArray[j + 1]) {
376 pairComparison[i] = pairComparisonResultArray[j];
377 break;
378 }
379 }
380 }
381 }
382
383 /**
384 * 重要度割り当て(一対比較)結果より幾何平均計算
385 *
386 * @param int 一対比較行列サイズ
387 * @param double[] 一対比較結果配列
388 * @param double[] 幾何平均格納用配列
389 */
390 private void setGeometricAverageArray(int matrixSize,
391 double pairComparison[], double geometricAverage[]) {
392
393 // 一対比較結果より一対比較行列作成
394 for (int i = 0; i < matrixSize; i++) {
395 for (int j = 0; j < matrixSize; j++) {
396 geometricAverageMatrix[i][j] = pairComparison[i]
397 / pairComparison[j];
398 }
399 }
400
401 // 一対比較行列の行方向に幾何平均計算
402 for (int i = 0; i < matrixSize; i++) {
403 double multiply = 1.0;
404 for (int j = 0; j < matrixSize; j++) {
405 multiply *= geometricAverageMatrix[i][j];
406 }
407 geometricAverage[i] = Math.pow(multiply, 1.0 / matrixSize);
408 }
409 }
410
411 /**
412 * AHPの評価値取得
413 *
414 * @param Bid
415 * 評価対象提案
416 * @return double AHP評価値
417 */
418 public double getAHPEvaluation(Bid targetBid) {
419
420 // 予測効用の重み付き総和をAHP評価値
421 double evaluationValue = 0.0;
422 for (int i = 0; i < evaluationUtilityWeightArray.length; i++) {
423 evaluationValue += getExpectUtility(i, targetBid)
424 * evaluationUtilityWeightArray[i];
425 }
426
427 return evaluationValue;
428 }
429
430 /**
431 * 提案の予測効用値を計算
432 *
433 * @param int 参加者番号(0〜)
434 * @param Bid
435 * 提案
436 * @return double 予測効用値
437 */
438 public double getExpectUtility(int partyID, Bid targetBid) {
439
440 double utility = 0.0;
441 if (targetBid != null) {
442
443 for (int i = 1; i <= issueNum; i++) {
444
445 try {
446 // 相手の提案を元に予測効用空間から効用を取得し重み掛けて加算
447 String valName = targetBid.getValue(i).toString();
448 utility += (expectUtilSpaceHash[partyID][i - 1]
449 .get(valName) * expectIssueWeightArray[partyID][i - 1]);
450
451 } catch (Exception e) {
452 System.out
453 .println("Get Expect Utility Target Bid Is Wrong");
454 System.out.println("Wrong Bid Content: "
455 + targetBid.toString());
456 }
457 }
458 }
459
460 return utility;
461 }
462
463 /**
464 * 特定の参加者から見たAHP評価値取得
465 *
466 * @param Bid
467 * 評価対象Bid
468 * @param int 参加者番号(0〜)
469 * @return double 特定の参加者から見たAHP評価値
470 */
471 public double getAHPEvaluationForOpponents(int partyID, Bid targetBid) {
472
473 double evaluationValue = 0.0;
474 double weight = 1.0 / (double) evaluationUtilityWeightArray.length; // 重みは一定
475
476 // 指定交渉相手以外の予測効用を重み付き加算
477 for (int i = 0; i < evaluationUtilityWeightArray.length; i++) {
478 if (i != partyID) {
479 evaluationValue += getExpectUtility(i, targetBid) * weight;
480 }
481 }
482
483 // 自分の効用値を重み付き加算
484 double myUtility = 0.0;
485 try {
486 myUtility = myUtilitySpace.getUtility(targetBid);
487 } catch (Exception e) {
488 System.out.println("Get My Utility Target Bid Is Wrong");
489 System.out.println("Wrong Bid Content: " + targetBid.toString());
490 }
491 evaluationValue += myUtility * weight;
492
493 return evaluationValue;
494 }
495}
Note: See TracBrowser for help on using the repository browser.