source: src/main/java/agents/bayesianopponentmodel/BayesianOpponentModelScalable.java@ 126

Last change on this file since 126 was 126, checked in by Aron Hammond, 6 years ago

Added function to calculate opposition to MultiLateralAnalysis.java

Moved code to add RLBOA listeners to RLBOAUtils is misc package

Added input for strategyParameters to SessionPanel (gui)

!! close SessionInfo after tournament; this caused /tmp/ to fill up with GeniusData files

Our own package:

  • Added opponents and strategies that are mentioned in the report
  • Change class hierarchy, agents can now extend from RLBOAagentBilateral to inherit RL functionality.
  • States extend from AbstractState
File size: 17.0 KB
Line 
1package agents.bayesianopponentmodel;
2
3import java.util.ArrayList;
4import java.util.List;
5
6import genius.core.Bid;
7import genius.core.issue.Issue;
8import genius.core.issue.IssueDiscrete;
9import genius.core.issue.IssueReal;
10import genius.core.utility.AdditiveUtilitySpace;
11import genius.core.utility.EVALFUNCTYPE;
12import genius.core.utility.EvaluatorDiscrete;
13import genius.core.utility.EvaluatorReal;
14
15/**
16 * Implementation of the scalable Bayesian Model.
17 *
18 * Opponent Modelling in Automated Multi-Issue Negotiation Using Bayesian
19 * Learning by K. Hindriks, D. Tykhonov
20 *
21 * KNOWN BUGS: 1. Opponent model does not take the opponent's strategy into
22 * account, in contrast to the original paper which depicts an assumption about
23 * the opponent'strategy which adapts over time.
24 *
25 * 2. The opponent model becomes invalid after a while as NaN occurs in some
26 * hypotheses, corrupting the overall estimation.
27 */
28public class BayesianOpponentModelScalable extends OpponentModel {
29
30 private AdditiveUtilitySpace fUS;
31 private ArrayList<ArrayList<WeightHypothesis2>> fWeightHyps;
32 private ArrayList<ArrayList<EvaluatorHypothesis>> fEvaluatorHyps;
33 // private ArrayList<EvaluatorHypothesis[]> fEvalHyps;
34 // public ArrayList<Bid> fBiddingHistory; // previous bids of the opponent,
35 // not our bids.
36 // private ArrayList<UtilitySpaceHypothesis> fUSHyps;
37 private double fPreviousBidUtility;
38 List<Issue> issues;
39 private double[] fExpectedWeights;
40
41 public BayesianOpponentModelScalable(AdditiveUtilitySpace pUtilitySpace) {
42 //
43
44 fPreviousBidUtility = 1;
45 fDomain = pUtilitySpace.getDomain();
46 issues = fDomain.getIssues();
47 fUS = pUtilitySpace;
48 fBiddingHistory = new ArrayList<Bid>();
49 fExpectedWeights = new double[pUtilitySpace.getDomain().getIssues()
50 .size()];
51 fWeightHyps = new ArrayList<ArrayList<WeightHypothesis2>>();
52 // generate all possible ordering combinations of the weights
53
54 initWeightHyps();
55 // generate all possible hyps of evaluation functions
56 fEvaluatorHyps = new ArrayList<ArrayList<EvaluatorHypothesis>>();
57 int lTotalTriangularFns = 4;
58 for (int i = 0; i < fUS.getNrOfEvaluators(); i++) {
59 ArrayList<EvaluatorHypothesis> lEvalHyps = new ArrayList<EvaluatorHypothesis>();
60
61 switch (fUS.getEvaluator(issues.get(i).getNumber()).getType()) {
62
63 case REAL:
64 lEvalHyps = new ArrayList<EvaluatorHypothesis>();
65 fEvaluatorHyps.add(lEvalHyps);
66 // EvaluatorReal lEval = (EvaluatorReal)(fUS.getEvaluator(i));
67 IssueReal lIssue = (IssueReal) (fDomain.getIssues().get(i));
68 // uphill
69 EvaluatorReal lHypEval = new EvaluatorReal();
70 lHypEval.setUpperBound(lIssue.getUpperBound());
71 lHypEval.setLowerBound(lIssue.getLowerBound());
72 lHypEval.setType(EVALFUNCTYPE.LINEAR);
73 lHypEval.addParam(1, (double) 1
74 / (lHypEval.getUpperBound() - lHypEval.getLowerBound()));
75 lHypEval.addParam(
76 0,
77 -lHypEval.getLowerBound()
78 / (lHypEval.getUpperBound() - lHypEval
79 .getLowerBound()));
80 EvaluatorHypothesis lEvaluatorHypothesis = new EvaluatorHypothesis(
81 lHypEval);
82 lEvaluatorHypothesis.setDesc("uphill");
83 lEvalHyps.add(lEvaluatorHypothesis);
84 // downhill
85 lHypEval = new EvaluatorReal();
86 lHypEval.setUpperBound(lIssue.getUpperBound());
87 lHypEval.setLowerBound(lIssue.getLowerBound());
88 lHypEval.setType(EVALFUNCTYPE.LINEAR);
89 lHypEval.addParam(1, -(double) 1
90 / (lHypEval.getUpperBound() - lHypEval.getLowerBound()));
91 lHypEval.addParam(0, (double) 1 + lHypEval.getLowerBound()
92 / (lHypEval.getUpperBound() - lHypEval.getLowerBound()));
93 lEvaluatorHypothesis = new EvaluatorHypothesis(lHypEval);
94 lEvalHyps.add(lEvaluatorHypothesis);
95 lEvaluatorHypothesis.setDesc("downhill");
96 for (int k = 1; k <= lTotalTriangularFns; k++) {
97 // triangular
98 lHypEval = new EvaluatorReal();
99 lHypEval.setUpperBound(lIssue.getUpperBound());
100 lHypEval.setLowerBound(lIssue.getLowerBound());
101 lHypEval.setType(EVALFUNCTYPE.TRIANGULAR);
102 lHypEval.addParam(0, lHypEval.getLowerBound());
103 lHypEval.addParam(1, lHypEval.getUpperBound());
104 double lMaxPoint = lHypEval.getLowerBound()
105 + (double) k
106 * (lHypEval.getUpperBound() - lHypEval
107 .getLowerBound())
108 / (lTotalTriangularFns + 1);
109 lHypEval.addParam(2, lMaxPoint);
110 lEvaluatorHypothesis = new EvaluatorHypothesis(lHypEval);
111 lEvalHyps.add(lEvaluatorHypothesis);
112 lEvaluatorHypothesis.setDesc("triangular "
113 + String.format("%1.2f", lMaxPoint));
114 }
115 for (int k = 0; k < lEvalHyps.size(); k++) {
116 lEvalHyps.get(k).setProbability(
117 (double) 1 / lEvalHyps.size());
118 }
119
120 break;
121 case DISCRETE:
122 lEvalHyps = new ArrayList<EvaluatorHypothesis>();
123 fEvaluatorHyps.add(lEvalHyps);
124 // EvaluatorReal lEval = (EvaluatorReal)(fUS.getEvaluator(i));
125 IssueDiscrete lDiscIssue = (IssueDiscrete) (fDomain.getIssues()
126 .get(i));
127 // uphill
128 EvaluatorDiscrete lDiscreteEval = new EvaluatorDiscrete();
129 for (int j = 0; j < lDiscIssue.getNumberOfValues(); j++)
130 lDiscreteEval.addEvaluation(lDiscIssue.getValue(j),
131 1000 * j + 1);
132 lEvaluatorHypothesis = new EvaluatorHypothesis(lDiscreteEval);
133 lEvaluatorHypothesis.setProbability((double) 1 / 3);
134 lEvaluatorHypothesis.setDesc("uphill");
135 lEvalHyps.add(lEvaluatorHypothesis);
136 // downhill
137 lDiscreteEval = new EvaluatorDiscrete();
138 for (int j = 0; j < lDiscIssue.getNumberOfValues(); j++)
139 lDiscreteEval
140 .addEvaluation(
141 lDiscIssue.getValue(j),
142 1000 * (lDiscIssue.getNumberOfValues() - j - 1) + 1);
143 lEvaluatorHypothesis = new EvaluatorHypothesis(lDiscreteEval);
144 lEvaluatorHypothesis.setProbability((double) 1 / 3);
145 lEvalHyps.add(lEvaluatorHypothesis);
146 lEvaluatorHypothesis.setDesc("downhill");
147 if (lDiscIssue.getNumberOfValues() > 2) {
148 lTotalTriangularFns = lDiscIssue.getNumberOfValues() - 1;
149 for (int k = 1; k < lTotalTriangularFns; k++) {
150 // triangular. Wouter: we need to CHECK this.
151 lDiscreteEval = new EvaluatorDiscrete();
152 for (int j = 0; j < lDiscIssue.getNumberOfValues(); j++)
153 if (j < k) {
154 lDiscreteEval.addEvaluation(
155 lDiscIssue.getValue(j), 1000 * j / k);
156 } else {
157 // lEval =
158 // (1.0-(double)(j-k)/(lDiscIssue.getNumberOfValues()-1.0-k));
159 lDiscreteEval.addEvaluation(
160 lDiscIssue.getValue(j),
161 1000
162 * (lDiscIssue
163 .getNumberOfValues()
164 - j - 1)
165 / (lDiscIssue
166 .getNumberOfValues()
167 - k - 1) + 1);
168 }
169 lEvaluatorHypothesis = new EvaluatorHypothesis(
170 lDiscreteEval);
171 lEvalHyps.add(lEvaluatorHypothesis);
172 lEvaluatorHypothesis.setDesc("triangular "
173 + String.valueOf(k));
174 }// for
175 }// if
176 for (int k = 0; k < lEvalHyps.size(); k++) {
177 lEvalHyps.get(k).setProbability(
178 (double) 1 / lEvalHyps.size());
179 }
180 break;
181 }// switch
182 }
183 for (int i = 0; i < fExpectedWeights.length; i++)
184 fExpectedWeights[i] = getExpectedWeight(i);
185
186 // printEvalsDistribution();
187 }
188
189 void initWeightHyps() {
190 int lWeightHypsNumber = 11;
191 for (int i = 0; i < fUS.getDomain().getIssues().size(); i++) {
192 ArrayList<WeightHypothesis2> lWeightHyps = new ArrayList<WeightHypothesis2>();
193 for (int j = 0; j < lWeightHypsNumber; j++) {
194 WeightHypothesis2 lHyp = new WeightHypothesis2(fDomain);
195 lHyp.setProbability((1.0 - ((double) j + 1.0)
196 / lWeightHypsNumber)
197 * (1.0 - ((double) j + 1.0) / lWeightHypsNumber)
198 * (1.0 - ((double) j + 1.0) / lWeightHypsNumber));
199 lHyp.setWeight((double) j / (lWeightHypsNumber - 1));
200 lWeightHyps.add(lHyp);
201 }
202 double lN = 0;
203 for (int j = 0; j < lWeightHypsNumber; j++) {
204 lN += lWeightHyps.get(j).getProbability();
205 }
206 for (int j = 0; j < lWeightHypsNumber; j++) {
207 lWeightHyps.get(j).setProbability(
208 lWeightHyps.get(j).getProbability() / lN);
209 }
210
211 fWeightHyps.add(lWeightHyps);
212 }
213 }
214
215 private double conditionalDistribution(double pUtility,
216 double pPreviousBidUtility) {
217 // TODO: check this condition
218 // if(pPreviousBidUtility<pUtility) return 0;
219 // else {
220 double lSigma = 0.25;
221 double x = (pPreviousBidUtility - pUtility) / pPreviousBidUtility;
222 double lResult = 1.0 / (lSigma * Math.sqrt(2.0 * Math.PI))
223 * Math.exp(-(x * x) / (2.0 * lSigma * lSigma));
224 return lResult;
225 // }
226 }
227
228 public double getExpectedEvaluationValue(Bid pBid, int pIssueNumber)
229 throws Exception {
230 double lExpectedEval = 0;
231 for (int j = 0; j < fEvaluatorHyps.get(pIssueNumber).size(); j++) {
232 lExpectedEval = lExpectedEval
233 + fEvaluatorHyps.get(pIssueNumber).get(j).getProbability()
234 * fEvaluatorHyps
235 .get(pIssueNumber)
236 .get(j)
237 .getEvaluator()
238 .getEvaluation(fUS, pBid,
239 issues.get(pIssueNumber).getNumber());
240 }
241 return lExpectedEval;
242
243 }
244
245 public double getExpectedWeight(int pIssueNumber) {
246 double lExpectedWeight = 0;
247 for (int i = 0; i < fWeightHyps.get(pIssueNumber).size(); i++) {
248 lExpectedWeight += fWeightHyps.get(pIssueNumber).get(i)
249 .getProbability()
250 * fWeightHyps.get(pIssueNumber).get(i).getWeight();
251 }
252 return lExpectedWeight;
253 }
254
255 private double getPartialUtility(Bid pBid, int pIssueIndex)
256 throws Exception {
257 // calculate partial utility w/o issue pIssueIndex
258 double u = 0;
259 for (int j = 0; j < fDomain.getIssues().size(); j++) {
260 if (pIssueIndex == j)
261 continue;
262 // calculate expected weight of the issue
263 double w = 0;
264 for (int k = 0; k < fWeightHyps.get(j).size(); k++)
265 w += fWeightHyps.get(j).get(k).getProbability()
266 * fWeightHyps.get(j).get(k).getWeight();
267 u = u + w * getExpectedEvaluationValue(pBid, j);
268 }
269 return u;
270 }
271
272 public void updateWeights() throws Exception {
273 Bid lBid = fBiddingHistory.get(fBiddingHistory.size() - 1);
274 ArrayList<ArrayList<WeightHypothesis2>> lWeightHyps = new ArrayList<ArrayList<WeightHypothesis2>>();
275 // make new hyps array
276 for (int i = 0; i < fWeightHyps.size(); i++) {
277 ArrayList<WeightHypothesis2> lTmp = new ArrayList<WeightHypothesis2>();
278 for (int j = 0; j < fWeightHyps.get(i).size(); j++) {
279 WeightHypothesis2 lHyp = new WeightHypothesis2(fUS.getDomain());
280 lHyp.setWeight(fWeightHyps.get(i).get(j).getWeight());
281 lHyp.setProbability(fWeightHyps.get(i).get(j).getProbability());
282 lTmp.add(lHyp);
283 }
284 lWeightHyps.add(lTmp);
285 }
286
287 // for(int k=0;k<5;k++) {
288 for (int j = 0; j < fDomain.getIssues().size(); j++) {
289 double lN = 0;
290 double lUtility = 0;
291 for (int i = 0; i < fWeightHyps.get(j).size(); i++) {
292 // if(!lBid.getValue(j).equals(lPreviousBid.getValue(j))) {
293 lUtility = fWeightHyps.get(j).get(i).getWeight()
294 * getExpectedEvaluationValue(lBid, j)
295 + getPartialUtility(lBid, j);
296 lN += fWeightHyps.get(j).get(i).getProbability()
297 * conditionalDistribution(lUtility, fPreviousBidUtility);
298 /*
299 * } else { lN += fWeightHyps.get(j).get(i).getProbability(); }
300 */
301 }
302 // 2. receiveMessage probabilities
303 for (int i = 0; i < fWeightHyps.get(j).size(); i++) {
304 // if(!lBid.getValue(j).equals(lPreviousBid.getValue(j))) {
305 lUtility = fWeightHyps.get(j).get(i).getWeight()
306 * getExpectedEvaluationValue(lBid, j)
307 + getPartialUtility(lBid, j);
308 lWeightHyps
309 .get(j)
310 .get(i)
311 .setProbability(
312 fWeightHyps.get(j).get(i).getProbability()
313 * conditionalDistribution(lUtility,
314 fPreviousBidUtility) / lN);
315 /*
316 * } else {
317 * lWeightHyps.get(j).get(i).setProbability(fWeightHyps.
318 * get(j).get(i).getProbability()/lN); }
319 */
320 }
321 }
322 // }
323 fWeightHyps = lWeightHyps;
324 }
325
326 public void updateEvaluationFns() throws Exception {
327 Bid lBid = fBiddingHistory.get(fBiddingHistory.size() - 1);
328 // make new hyps array
329 // for(int k=0;k<5;k++){
330 ArrayList<ArrayList<EvaluatorHypothesis>> lEvaluatorHyps = new ArrayList<ArrayList<EvaluatorHypothesis>>();
331 for (int i = 0; i < fEvaluatorHyps.size(); i++) {
332 ArrayList<EvaluatorHypothesis> lTmp = new ArrayList<EvaluatorHypothesis>();
333 for (int j = 0; j < fEvaluatorHyps.get(i).size(); j++) {
334 EvaluatorHypothesis lHyp = new EvaluatorHypothesis(
335 fEvaluatorHyps.get(i).get(j).getEvaluator());
336 lHyp.setDesc(fEvaluatorHyps.get(i).get(j).getDesc());
337 lHyp.setProbability(fEvaluatorHyps.get(i).get(j)
338 .getProbability());
339 lTmp.add(lHyp);
340 }
341 lEvaluatorHyps.add(lTmp);
342 }
343
344 // 1. calculate the normalization factor
345
346 for (int i = 0; i < fDomain.getIssues().size(); i++) {
347 // 1. calculate the normalization factor
348 double lN = 0;
349 for (int j = 0; j < fEvaluatorHyps.get(i).size(); j++) {
350 EvaluatorHypothesis lHyp = fEvaluatorHyps.get(i).get(j);
351 lN += lHyp.getProbability()
352 * conditionalDistribution(
353 getPartialUtility(lBid, i)
354 + getExpectedWeight(i)
355 * (lHyp.getEvaluator().getEvaluation(
356 fUS, lBid, issues.get(i)
357 .getNumber())),
358 fPreviousBidUtility);
359 }
360 // 2. receiveMessage probabilities
361 for (int j = 0; j < fEvaluatorHyps.get(i).size(); j++) {
362 EvaluatorHypothesis lHyp = fEvaluatorHyps.get(i).get(j);
363 lEvaluatorHyps
364 .get(i)
365 .get(j)
366 .setProbability(
367 lHyp.getProbability()
368 * conditionalDistribution(
369 getPartialUtility(lBid, i)
370 + getExpectedWeight(i)
371 * (lHyp.getEvaluator()
372 .getEvaluation(
373 fUS,
374 lBid,
375 issues.get(
376 i)
377 .getNumber())),
378 fPreviousBidUtility) / lN);
379 }
380 }
381 fEvaluatorHyps = lEvaluatorHyps;
382 // }
383 printEvalsDistribution();
384 }
385
386 public boolean haveSeenBefore(Bid pBid) {
387 for (Bid tmpBid : fBiddingHistory) {
388 if (pBid.equals(tmpBid))
389 return true;
390 }
391 return false;
392 }
393
394 public void updateBeliefs(Bid pBid) throws Exception {
395 if (!isCrashed()) {
396 if (haveSeenBefore(pBid))
397 return;
398 fBiddingHistory.add(pBid);
399
400 // do not receiveMessage the bids if it is the first bid
401 if (fBiddingHistory.size() > 1) {
402
403 // receiveMessage the weights
404 updateWeights();
405 // receiveMessage evaluation functions
406 updateEvaluationFns();
407 } else {
408 // do not receiveMessage the weights
409 // receiveMessage evaluation functions
410 updateEvaluationFns();
411 } // if
412
413 // System.out.println(getMaxHyp().toString());
414 // calculate utility of the next partner's bid according to the
415 // concession functions
416 fPreviousBidUtility = fPreviousBidUtility - 0.003;
417 for (int i = 0; i < fExpectedWeights.length; i++) {
418 fExpectedWeights[i] = getExpectedWeight(i);
419 }
420 findMinMaxUtility();
421 // printBestHyp();
422 }
423 }
424
425 /**
426 * Plan: cache the results for pBid in a Hash table. empty the hash table
427 * whenever updateWeights or updateEvaluationFns is called.
428 *
429 * @param pBid
430 * @return weeighted utility where weights represent likelihood of each
431 * hypothesis
432 * @throws Exception
433 */
434 public double getExpectedUtility(Bid pBid) throws Exception {
435 // calculate expected utility
436 double u = 0;
437 for (int j = 0; j < fDomain.getIssues().size(); j++) {
438 // calculate expected weight of the issue
439 double w = fExpectedWeights[j];
440 /*
441 * for(int k=0;k<fWeightHyps.get(j).size();k++) w +=
442 * fWeightHyps.get(
443 * j).get(k).getProbability()*fWeightHyps.get(j).get(
444 * k).getWeight();(
445 */
446 u = u + w * getExpectedEvaluationValue(pBid, j);
447 }
448
449 return u;
450 }
451
452 private void printBestHyp() {
453 double[] lBestWeights = new double[fUS.getDomain().getIssues().size()];
454 EvaluatorHypothesis[] lBestEvals = new EvaluatorHypothesis[fUS
455 .getDomain().getIssues().size()];
456 for (int i = 0; i < fUS.getDomain().getIssues().size(); i++) {
457 // find best weight
458 double lMaxWeightProb = -1;
459 for (int j = 0; j < fWeightHyps.get(i).size(); j++) {
460 if (fWeightHyps.get(i).get(j).getProbability() > lMaxWeightProb) {
461 lMaxWeightProb = fWeightHyps.get(i).get(j).getProbability();
462 lBestWeights[i] = fWeightHyps.get(i).get(j).getWeight();
463 }
464 }
465 // find best evaluation fn
466 double lMaxEvalProb = -1;
467 for (int j = 0; j < fEvaluatorHyps.get(i).size(); j++) {
468 if (fEvaluatorHyps.get(i).get(j).getProbability() > lMaxEvalProb) {
469 lMaxEvalProb = fEvaluatorHyps.get(i).get(j)
470 .getProbability();
471 lBestEvals[i] = fEvaluatorHyps.get(i).get(j);
472 }
473 }
474
475 }
476 /*
477 * //print all weights for(int
478 * i=0;i<fUS.getDomain().getIssues().size();i++) {
479 * System.out.print(String.format("%1.2f", getExpectedWeight(i))+";"); }
480 * //print all Evaluators for(int
481 * i=0;i<fUS.getDomain().getIssues().size();i++) {
482 * System.out.print(lBestEvals[i].getDesc()+";"); }
483 * System.out.println();
484 */
485 }
486
487 void printEvalsDistribution() {
488 /*
489 * for(int i=0;i<fUS.getDomain().getIssues().size();i++) { for(int
490 * j=0;j<fEvaluatorHyps.get(i).size();j++)
491 * System.out.print(String.format("%1.2f",
492 * fEvaluatorHyps.get(i).get(j).getProbability())+";");
493 * System.out.println(); }
494 */
495
496 }
497
498 public double getNormalizedWeight(Issue i, int startingNumber) {
499 double sum = 0;
500 for (Issue issue : fDomain.getIssues()) {
501 sum += getExpectedWeight(issue.getNumber() - startingNumber);
502 }
503 return (getExpectedWeight(i.getNumber() - startingNumber)) / sum;
504 }
505
506}
Note: See TracBrowser for help on using the repository browser.