1 | package agents.anac.y2016.syagent;
|
---|
2 |
|
---|
3 | import java.util.ArrayList;
|
---|
4 | import java.util.Collections;
|
---|
5 | import java.util.HashMap;
|
---|
6 | import java.util.List;
|
---|
7 |
|
---|
8 | import genius.core.AgentID;
|
---|
9 | import genius.core.Bid;
|
---|
10 | import genius.core.issue.Issue;
|
---|
11 | import genius.core.issue.IssueDiscrete;
|
---|
12 | import genius.core.issue.IssueInteger;
|
---|
13 | import genius.core.issue.Value;
|
---|
14 | import genius.core.issue.ValueDiscrete;
|
---|
15 | import genius.core.utility.AbstractUtilitySpace;
|
---|
16 | import genius.core.utility.UtilitySpace;
|
---|
17 |
|
---|
18 | public class negotiationInfo {
|
---|
19 | /* Unchangeable Information */
|
---|
20 | private UtilitySpace utilitySpace; // 効用空間
|
---|
21 | private boolean isLinerUtilitySpace = true; // 線形効用空間であるかどうか
|
---|
22 | private List<Issue> issues; // 論点
|
---|
23 | private ArrayList<Object> opponents; // 自身以外の交渉参加者のsender
|
---|
24 | private int negotiatorNum = 0; // 交渉者数
|
---|
25 | private double rv = 0.0; // 留保価格の初期値
|
---|
26 | private double df = 1.0; // 割引係数
|
---|
27 |
|
---|
28 | /* Changeable Information */
|
---|
29 | private HashMap<Issue, HashMap<Value, Integer>> allFrequency = null; // 全員分の頻度
|
---|
30 |
|
---|
31 | /* My Negotiation Information */
|
---|
32 | private HashMap<Issue, HashMap<Value, Double>> valueRelativeUtility = null; // 自身の効用空間における各論点値の相対効用値行列(線形効用空間用)
|
---|
33 | private ArrayList<Bid> MyBidHistory = null; // 自分の提案履歴
|
---|
34 | private double MyBidAverage = 0.0;// 自分の平均
|
---|
35 | private int round = 0; // 自分の手番数
|
---|
36 |
|
---|
37 | /* Opponents Negotiation Information */
|
---|
38 | private HashMap<Object, ArrayList<Bid>> opponentsBidHistory = null; // 相手の提案履歴
|
---|
39 | private HashMap<Object, Double> opponentsAverage; // 相手の平均
|
---|
40 | private HashMap<Object, Double> opponentsVariance; // 相手の分散
|
---|
41 | private HashMap<Object, Double> opponentsSum; // 相手の和
|
---|
42 | private HashMap<Object, Double> opponentsPowSum; // 相手の二乗和
|
---|
43 | private HashMap<Object, Double> opponentsStandardDeviation; // 相手の標準偏差
|
---|
44 | private HashMap<Object, HashMap<Issue, HashMap<Value, Integer>>> opponentsFrequency = null; // 相手の頻度
|
---|
45 | private HashMap<Object, ArrayList<Bid>> opponentsAcceptBid = null; // 相手の受容履歴
|
---|
46 |
|
---|
47 | private boolean isPrinting = false; // デバッグ用
|
---|
48 |
|
---|
49 | public negotiationInfo(AbstractUtilitySpace utilitySpace, boolean isPrinting) {
|
---|
50 | /* Initialize Unchangeable Information */
|
---|
51 | this.utilitySpace = utilitySpace;
|
---|
52 | this.isPrinting = isPrinting;
|
---|
53 | issues = utilitySpace.getDomain().getIssues();
|
---|
54 | opponents = new ArrayList<Object>();
|
---|
55 | negotiatorNum = new Integer(0);
|
---|
56 | rv = utilitySpace.getReservationValue();
|
---|
57 | df = utilitySpace.getDiscountFactor();
|
---|
58 |
|
---|
59 | /* Initialize Changeable Information */
|
---|
60 | allFrequency = new HashMap<Issue, HashMap<Value, Integer>>();
|
---|
61 | try {
|
---|
62 | initAllValueFrequency();
|
---|
63 | } catch (Exception e1) {
|
---|
64 | System.out.println("全員の頻度行列の初期化に失敗しました");
|
---|
65 | e1.printStackTrace();
|
---|
66 | }
|
---|
67 |
|
---|
68 | /* Initialize My Negotiation Information */
|
---|
69 | valueRelativeUtility = new HashMap<Issue, HashMap<Value, Double>>();
|
---|
70 | try {
|
---|
71 | initValueRelativeUtility();
|
---|
72 | } catch (Exception e) {
|
---|
73 | System.out.println("相対効用行列の初期化に失敗しました");
|
---|
74 | e.printStackTrace();
|
---|
75 | }
|
---|
76 | MyBidHistory = new ArrayList<>();
|
---|
77 | MyBidAverage = new Double(0.0);
|
---|
78 | round = new Integer(0);
|
---|
79 |
|
---|
80 | /* Initialize Opponents Negotiation Information */
|
---|
81 | opponentsBidHistory = new HashMap<Object, ArrayList<Bid>>();
|
---|
82 | opponentsAverage = new HashMap<Object, Double>();
|
---|
83 | opponentsVariance = new HashMap<Object, Double>();
|
---|
84 | opponentsSum = new HashMap<Object, Double>();
|
---|
85 | opponentsPowSum = new HashMap<Object, Double>();
|
---|
86 | opponentsStandardDeviation = new HashMap<Object, Double>();
|
---|
87 | opponentsFrequency = new HashMap<Object, HashMap<Issue, HashMap<Value, Integer>>>();
|
---|
88 | opponentsAcceptBid = new HashMap<Object, ArrayList<Bid>>();
|
---|
89 | }
|
---|
90 |
|
---|
91 | /*** 初期化に関するメソッドたち ***/
|
---|
92 |
|
---|
93 | // 全員分の頻度の初期化
|
---|
94 | private void initAllValueFrequency() throws Exception {
|
---|
95 | ArrayList<Value> values = null;
|
---|
96 | for (Issue issue : issues) {
|
---|
97 | allFrequency.put(issue, new HashMap<Value, Integer>());
|
---|
98 | values = getValues(issue);
|
---|
99 | for (Value value : values) {
|
---|
100 | allFrequency.get(issue).put(value, 0);
|
---|
101 | }
|
---|
102 | }
|
---|
103 | }
|
---|
104 |
|
---|
105 | // 相対効用行列の初期化
|
---|
106 | private void initValueRelativeUtility() throws Exception {
|
---|
107 | ArrayList<Value> values = null;
|
---|
108 | for (Issue issue : issues) {
|
---|
109 | valueRelativeUtility.put(issue, new HashMap<Value, Double>()); // 論点(issue)行の初期化
|
---|
110 | values = getValues(issue);
|
---|
111 | for (Value value : values) {
|
---|
112 | valueRelativeUtility.get(issue).put(value, 0.0);
|
---|
113 | } // 論点(issue)行の要素の初期化
|
---|
114 | }
|
---|
115 | }
|
---|
116 |
|
---|
117 | // 相対効用行列の導出
|
---|
118 | public void setValueRelativeUtility(Bid maxBid) throws Exception {
|
---|
119 | ArrayList<Value> values = null;
|
---|
120 | Bid currentBid = null;
|
---|
121 | for (Issue issue : issues) {
|
---|
122 | currentBid = new Bid(maxBid);
|
---|
123 | values = getValues(issue);
|
---|
124 | for (Value value : values) {
|
---|
125 | currentBid = currentBid.putValue(issue.getNumber(), value);
|
---|
126 | valueRelativeUtility.get(issue).put(
|
---|
127 | value,
|
---|
128 | utilitySpace.getUtility(currentBid)
|
---|
129 | - utilitySpace.getUtility(maxBid));
|
---|
130 | }
|
---|
131 | }
|
---|
132 | }
|
---|
133 |
|
---|
134 | // 初出のsenderの情報を初期化
|
---|
135 | public void initOpponent(Object sender) {
|
---|
136 | opponents.add(sender); // 交渉参加者にsenderを追加
|
---|
137 | initNegotiationInfo(sender); // 交渉情報を初期化
|
---|
138 | try {
|
---|
139 | initOpponentsValueFrequency(sender);
|
---|
140 | } catch (Exception e) {
|
---|
141 | System.out.println("相手の頻度の初期化に失敗しました");
|
---|
142 | e.printStackTrace();
|
---|
143 | }
|
---|
144 | }
|
---|
145 |
|
---|
146 | // senderのNegotiationInfoの初期化
|
---|
147 | private void initNegotiationInfo(Object sender) {
|
---|
148 | opponentsBidHistory.put(sender, new ArrayList<Bid>());
|
---|
149 | opponentsAverage.put(sender, 0.0);
|
---|
150 | opponentsVariance.put(sender, 0.0);
|
---|
151 | opponentsSum.put(sender, 0.0);
|
---|
152 | opponentsPowSum.put(sender, 0.0);
|
---|
153 | opponentsStandardDeviation.put(sender, 0.0);
|
---|
154 | opponentsAcceptBid.put(sender, new ArrayList<Bid>());
|
---|
155 | }
|
---|
156 |
|
---|
157 | // 相手の頻度の初期化
|
---|
158 | private void initOpponentsValueFrequency(Object sender) throws Exception {
|
---|
159 | opponentsFrequency.put(sender,
|
---|
160 | new HashMap<Issue, HashMap<Value, Integer>>()); // senderの頻度の初期化
|
---|
161 | for (Issue issue : issues) {
|
---|
162 | opponentsFrequency.get(sender).put(issue,
|
---|
163 | new HashMap<Value, Integer>());
|
---|
164 | ArrayList<Value> values = getValues(issue);
|
---|
165 | for (Value value : values) {
|
---|
166 | opponentsFrequency.get(sender).get(issue).put(value, 0);
|
---|
167 | }
|
---|
168 | }
|
---|
169 | }
|
---|
170 |
|
---|
171 | /*** 更新に関するメソッドたち (void) ***/
|
---|
172 |
|
---|
173 | // 交渉者数を更新
|
---|
174 | public void updateOpponentsNum(int num) {
|
---|
175 | negotiatorNum = num;
|
---|
176 | }
|
---|
177 |
|
---|
178 | // 交渉情報の更新
|
---|
179 | public void updateInfo(Object sender, Bid offeredBid) {
|
---|
180 | try {
|
---|
181 | updateNegotiationInfo(sender, offeredBid);
|
---|
182 | } // 交渉情報の更新
|
---|
183 | catch (Exception e1) {
|
---|
184 | System.out.println("交渉情報の更新に失敗しました");
|
---|
185 | e1.printStackTrace();
|
---|
186 | }
|
---|
187 | try {
|
---|
188 | updateFrequency(sender, offeredBid);
|
---|
189 | } // senderの頻度の更新
|
---|
190 | catch (Exception e) {
|
---|
191 | System.out.println("頻度の更新に失敗しました");
|
---|
192 | e.printStackTrace();
|
---|
193 | }
|
---|
194 | }
|
---|
195 |
|
---|
196 | // 頻度を更新
|
---|
197 | private void updateFrequency(Object sender, Bid offeredBid)
|
---|
198 | throws Exception {
|
---|
199 | for (Issue issue : issues) {
|
---|
200 | Value value = offeredBid.getValue(issue.getNumber());
|
---|
201 | opponentsFrequency
|
---|
202 | .get(sender)
|
---|
203 | .get(issue)
|
---|
204 | .put(value,
|
---|
205 | opponentsFrequency.get(sender).get(issue)
|
---|
206 | .get(value) + 1); // リストを更新
|
---|
207 | allFrequency.get(issue).put(value,
|
---|
208 | allFrequency.get(issue).get(value) + 1); // リストを更新
|
---|
209 | }
|
---|
210 | }
|
---|
211 |
|
---|
212 | // 自身の提案情報の更新
|
---|
213 | public void updateMyBidHistory(Bid offerBid) {
|
---|
214 | MyBidHistory.add(offerBid);
|
---|
215 | MyBidAverage = (MyBidAverage * (MyBidHistory.size() - 1) + utilitySpace
|
---|
216 | .getUtility(offerBid)) / MyBidHistory.size();
|
---|
217 | }
|
---|
218 |
|
---|
219 | // round を数える
|
---|
220 | public void countRound() {
|
---|
221 | round++;
|
---|
222 | }
|
---|
223 |
|
---|
224 | // sender の NegotiationInfo を更新
|
---|
225 | public void updateNegotiationInfo(Object sender, Bid offeredBid)
|
---|
226 | throws Exception {
|
---|
227 |
|
---|
228 | opponentsBidHistory.get(sender).add(offeredBid); // 相手の提案履歴
|
---|
229 |
|
---|
230 | double util = utilitySpace.getUtility(offeredBid);
|
---|
231 |
|
---|
232 | opponentsSum.put(sender, opponentsSum.get(sender) + util); // 和の更新
|
---|
233 | opponentsPowSum.put(sender,
|
---|
234 | opponentsPowSum.get(sender) + Math.pow(util, 2)); // 二乗和の更新
|
---|
235 |
|
---|
236 | int round_num = opponentsBidHistory.get(sender).size();
|
---|
237 | opponentsAverage.put(sender, opponentsSum.get(sender) / round_num); // 平均の更新
|
---|
238 | opponentsVariance.put(sender, (opponentsPowSum.get(sender) / round_num)
|
---|
239 | - Math.pow(opponentsAverage.get(sender), 2)); // 分散の更新
|
---|
240 |
|
---|
241 | if (opponentsVariance.get(sender) < 0) {
|
---|
242 | opponentsVariance.put(sender, 0.0);
|
---|
243 | }
|
---|
244 | opponentsStandardDeviation.put(sender,
|
---|
245 | Math.sqrt(opponentsVariance.get(sender))); // 標準偏差の更新
|
---|
246 | }
|
---|
247 |
|
---|
248 | /*** 値を返すメソッドたち (return) ***/
|
---|
249 |
|
---|
250 | // sender の提案履歴を返す
|
---|
251 | public HashMap<Object, ArrayList<Bid>> getOpponentsBidHistory(Object sender) {
|
---|
252 | return opponentsBidHistory;
|
---|
253 | }
|
---|
254 |
|
---|
255 | // 自分の提案の平均を返す
|
---|
256 | public double getMyBidAverage() {
|
---|
257 | return MyBidAverage;
|
---|
258 | }
|
---|
259 |
|
---|
260 | // 線形効用空間でない場合
|
---|
261 | public void utilitySpaceTypeisNonLiner() {
|
---|
262 | isLinerUtilitySpace = false;
|
---|
263 | }
|
---|
264 |
|
---|
265 | // sender の平均を返す
|
---|
266 | public double getAverage(Object sender) {
|
---|
267 | return opponentsAverage.get(sender);
|
---|
268 | }
|
---|
269 |
|
---|
270 | // sender の分散を返す
|
---|
271 | public double getVariancer(Object sender) {
|
---|
272 | return opponentsVariance.get(sender);
|
---|
273 | }
|
---|
274 |
|
---|
275 | // sender の標準偏差を返す
|
---|
276 | public double getStandardDeviation(Object sender) {
|
---|
277 | return opponentsStandardDeviation.get(sender);
|
---|
278 | }
|
---|
279 |
|
---|
280 | // sender の提案履歴の要素数を返す
|
---|
281 | public int getPartnerBidNum(Object sender) {
|
---|
282 | return opponentsBidHistory.get(sender).size();
|
---|
283 | }
|
---|
284 |
|
---|
285 | // 自身のラウンド数を返す
|
---|
286 | public int getRound() {
|
---|
287 | return round;
|
---|
288 | }
|
---|
289 |
|
---|
290 | // 交渉者数を返す
|
---|
291 | public int getNegotiatorNum() {
|
---|
292 | return negotiatorNum;
|
---|
293 | }
|
---|
294 |
|
---|
295 | // 相対効用行列を返す
|
---|
296 | public HashMap<Issue, HashMap<Value, Double>> getValueRelativeUtility() {
|
---|
297 | return valueRelativeUtility;
|
---|
298 | }
|
---|
299 |
|
---|
300 | // 線形効用空間であるかどうかを返す
|
---|
301 | public boolean isLinerUtilitySpace() {
|
---|
302 | return isLinerUtilitySpace;
|
---|
303 | }
|
---|
304 |
|
---|
305 | // 論点一覧を返す
|
---|
306 | public List<Issue> getIssues() {
|
---|
307 | return issues;
|
---|
308 | }
|
---|
309 |
|
---|
310 | // 論点における取り得る値の一覧を返す
|
---|
311 | public ArrayList<Value> getValues(Issue issue) {
|
---|
312 | ArrayList<Value> values = new ArrayList<Value>();
|
---|
313 | switch (issue.getType()) {
|
---|
314 | case DISCRETE:
|
---|
315 | List<ValueDiscrete> valuesDis = ((IssueDiscrete) issue).getValues();
|
---|
316 | for (Value value : valuesDis) {
|
---|
317 | values.add(value);
|
---|
318 | }
|
---|
319 | break;
|
---|
320 | case INTEGER:
|
---|
321 | int min_value = ((IssueInteger) issue).getUpperBound();
|
---|
322 | int max_value = ((IssueInteger) issue).getUpperBound();
|
---|
323 | for (int j = min_value; j <= max_value; j++) {
|
---|
324 | Object valueObject = new Integer(j);
|
---|
325 | values.add((Value) valueObject);
|
---|
326 | }
|
---|
327 | break;
|
---|
328 | default:
|
---|
329 | try {
|
---|
330 | throw new Exception("issue type " + issue.getType()
|
---|
331 | + " not supported by SYAgent");
|
---|
332 | } catch (Exception e) {
|
---|
333 | System.out.println("論点の取り得る値の取得に失敗しました");
|
---|
334 | e.printStackTrace();
|
---|
335 | }
|
---|
336 | }
|
---|
337 | return values;
|
---|
338 | }
|
---|
339 |
|
---|
340 | // 交渉相手の一覧を返す
|
---|
341 | public ArrayList<Object> getOpponents() {
|
---|
342 | return opponents;
|
---|
343 | }
|
---|
344 |
|
---|
345 | // 論点の最頻値を返すメソッド
|
---|
346 | public Value getFrequentValue(Issue issue) {
|
---|
347 | Value maxValue = null; // 最頻値
|
---|
348 | int frequency = 0;// 要素の頻度
|
---|
349 | int maxFrequency = 0; // 最頻値の数
|
---|
350 | ArrayList<Value> values = getValues(issue);
|
---|
351 | Collections.shuffle(values);
|
---|
352 |
|
---|
353 | for (Value value : values) {
|
---|
354 | frequency = allFrequency.get(issue).get(value);
|
---|
355 | if (maxValue == null || frequency > maxFrequency) {
|
---|
356 | maxFrequency = frequency;
|
---|
357 | maxValue = value;
|
---|
358 | }
|
---|
359 | }
|
---|
360 | return maxValue;
|
---|
361 | }
|
---|
362 |
|
---|
363 | // df が 1.0 でないか 1.0 であるかを示す boolean を決定するメソッド
|
---|
364 | public boolean setDfFlag() {
|
---|
365 | if (df == 1.0) {
|
---|
366 | return false;// df == 1.0 (割引なし)
|
---|
367 | } else {
|
---|
368 | return true; // df != 1.0 (割引あり)
|
---|
369 | }
|
---|
370 |
|
---|
371 | }
|
---|
372 |
|
---|
373 | // rv が 0.0 か否かを示す boolean を決定するメソッド
|
---|
374 | public boolean setRvFlag() {
|
---|
375 | if (rv == 0.0) {
|
---|
376 | return false;// rv == 0.0 (留保価格なし)
|
---|
377 | } else {
|
---|
378 | return true; // rv != 0.0 (留保価格あり)
|
---|
379 | }
|
---|
380 | }
|
---|
381 |
|
---|
382 | // sender が accept した Bid の記録を更新
|
---|
383 | public void updateAcceptedBid(AgentID sender, Bid bidFromAction) {
|
---|
384 | opponentsAcceptBid.get(sender).add(bidFromAction);
|
---|
385 | }
|
---|
386 |
|
---|
387 | }
|
---|