[127] | 1 | package agents.anac.y2014.DoNA;
|
---|
| 2 |
|
---|
| 3 | import java.util.ArrayList;
|
---|
| 4 | import java.util.HashMap;
|
---|
| 5 | import java.util.List;
|
---|
| 6 |
|
---|
| 7 | import genius.core.Bid;
|
---|
| 8 | import genius.core.Domain;
|
---|
| 9 | import genius.core.issue.Issue;
|
---|
| 10 | import genius.core.issue.IssueDiscrete;
|
---|
| 11 | import genius.core.issue.IssueInteger;
|
---|
| 12 | import genius.core.issue.IssueReal;
|
---|
| 13 | import genius.core.issue.Value;
|
---|
| 14 | import genius.core.issue.ValueInteger;
|
---|
| 15 | import genius.core.issue.ValueReal;
|
---|
| 16 | import genius.core.utility.AbstractUtilitySpace;
|
---|
| 17 |
|
---|
| 18 | /**
|
---|
| 19 | * Class for keeping the history of bids sent by our opponent, weighted
|
---|
| 20 | * according to the time they were sent.
|
---|
| 21 | *
|
---|
| 22 | * The sooner they are sent - the higher the weight.
|
---|
| 23 | *
|
---|
| 24 | * Also tries to estimate, from a given list of acceptable bids, the best one
|
---|
| 25 | * for our opponent, according to the sum of weights for each issue-value pair,
|
---|
| 26 | * in each bid from the range.
|
---|
| 27 | *
|
---|
| 28 | * Initialization, adding and maintaining the structure are based on work from
|
---|
| 29 | * 2012 competition, by Justin
|
---|
| 30 | */
|
---|
| 31 | public class OpponentBidHistory {
|
---|
| 32 |
|
---|
| 33 | private ArrayList<Bid> bidHistory;
|
---|
| 34 |
|
---|
| 35 | /**
|
---|
| 36 | * These arrays map issues to frequency-maps: For each issue, they keep a
|
---|
| 37 | * map that maps each possible value to the number of times it was offered
|
---|
| 38 | * by the opponent.
|
---|
| 39 | */
|
---|
| 40 | private ArrayList<ArrayList<Double>> opponentBidsStatisticsForReal;
|
---|
| 41 | private ArrayList<HashMap<Value, Double>> opponentBidsStatisticsDiscrete;
|
---|
| 42 | private ArrayList<ArrayList<Double>> opponentBidsStatisticsForInteger;
|
---|
| 43 |
|
---|
| 44 | private int maximumBidsStored = 1000000;
|
---|
| 45 | private Bid bid_maximum_from_opponent;// the bid with maximum utility
|
---|
| 46 | // proposed by the opponent so far.
|
---|
| 47 |
|
---|
| 48 | public OpponentBidHistory() {
|
---|
| 49 | this.bidHistory = new ArrayList<Bid>();
|
---|
| 50 | opponentBidsStatisticsForReal = new ArrayList<ArrayList<Double>>();
|
---|
| 51 | opponentBidsStatisticsDiscrete = new ArrayList<HashMap<Value, Double>>();
|
---|
| 52 | opponentBidsStatisticsForInteger = new ArrayList<ArrayList<Double>>();
|
---|
| 53 | }
|
---|
| 54 |
|
---|
| 55 | /**
|
---|
| 56 | * add a new opponent bid
|
---|
| 57 | *
|
---|
| 58 | * @author Justin
|
---|
| 59 | */
|
---|
| 60 | public void addBid(Bid bid, AbstractUtilitySpace utilitySpace) {
|
---|
| 61 | if (bidHistory.indexOf(bid) == -1) {
|
---|
| 62 | bidHistory.add(bid);
|
---|
| 63 | }
|
---|
| 64 | try {
|
---|
| 65 | if (bidHistory.size() == 1) {
|
---|
| 66 | this.bid_maximum_from_opponent = bidHistory.get(0);
|
---|
| 67 | } else {
|
---|
| 68 | if (utilitySpace.getUtility(bid) > utilitySpace
|
---|
| 69 | .getUtility(this.bid_maximum_from_opponent)) {
|
---|
| 70 | this.bid_maximum_from_opponent = bid;
|
---|
| 71 | }
|
---|
| 72 | }
|
---|
| 73 | } catch (Exception e) {
|
---|
| 74 | System.out.println("error in addBid method" + e.getMessage());
|
---|
| 75 | }
|
---|
| 76 | }
|
---|
| 77 |
|
---|
| 78 | public Bid getBestBidInHistory() {
|
---|
| 79 | return this.bid_maximum_from_opponent;
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | /**
|
---|
| 83 | * initialization
|
---|
| 84 | *
|
---|
| 85 | * @author Justin Changed by Eden Erez and Erel Segal haLevi (added weight
|
---|
| 86 | * 0.0)
|
---|
| 87 | */
|
---|
| 88 | public void initializeDataStructures(Domain domain) {
|
---|
| 89 | try {
|
---|
| 90 | List<Issue> issues = domain.getIssues();
|
---|
| 91 | for (Issue lIssue : issues) {
|
---|
| 92 | // For each issue, initialize a map from each possible value to
|
---|
| 93 | // integer. The integer is initially 0:
|
---|
| 94 |
|
---|
| 95 | switch (lIssue.getType()) {
|
---|
| 96 |
|
---|
| 97 | case DISCRETE:
|
---|
| 98 | IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue;
|
---|
| 99 | HashMap<Value, Double> discreteIssueValuesMap = new HashMap<Value, Double>();
|
---|
| 100 | for (int j = 0; j < lIssueDiscrete.getNumberOfValues(); j++) {
|
---|
| 101 | Value v = lIssueDiscrete.getValue(j);
|
---|
| 102 | discreteIssueValuesMap.put(v, 0.0);
|
---|
| 103 | }
|
---|
| 104 | opponentBidsStatisticsDiscrete.add(discreteIssueValuesMap);
|
---|
| 105 | break;
|
---|
| 106 |
|
---|
| 107 | case REAL:
|
---|
| 108 | IssueReal lIssueReal = (IssueReal) lIssue;
|
---|
| 109 | ArrayList<Double> numProposalsPerValue = new ArrayList<Double>();
|
---|
| 110 | int lNumOfPossibleValuesInThisIssue = lIssueReal
|
---|
| 111 | .getNumberOfDiscretizationSteps();
|
---|
| 112 | for (int i = 0; i < lNumOfPossibleValuesInThisIssue; i++) {
|
---|
| 113 | numProposalsPerValue.add(0.0);
|
---|
| 114 | }
|
---|
| 115 | opponentBidsStatisticsForReal.add(numProposalsPerValue);
|
---|
| 116 | break;
|
---|
| 117 |
|
---|
| 118 | case INTEGER:
|
---|
| 119 | IssueInteger lIssueInteger = (IssueInteger) lIssue;
|
---|
| 120 | ArrayList<Double> numOfValueProposals = new ArrayList<Double>();
|
---|
| 121 |
|
---|
| 122 | // number of possible value when issue is integer (we should
|
---|
| 123 | // add 1 in order to include all values)
|
---|
| 124 | int lNumOfPossibleValuesForThisIssue = lIssueInteger
|
---|
| 125 | .getUpperBound()
|
---|
| 126 | - lIssueInteger.getLowerBound()
|
---|
| 127 | + 1;
|
---|
| 128 | for (int i = 0; i < lNumOfPossibleValuesForThisIssue; i++) {
|
---|
| 129 | numOfValueProposals.add(0.0);
|
---|
| 130 | }
|
---|
| 131 | opponentBidsStatisticsForInteger.add(numOfValueProposals);
|
---|
| 132 | break;
|
---|
| 133 | }
|
---|
| 134 | }
|
---|
| 135 | } catch (Exception e) {
|
---|
| 136 | System.out.println("EXCEPTION in initializeDataAtructures");
|
---|
| 137 | }
|
---|
| 138 | }
|
---|
| 139 |
|
---|
| 140 | /**
|
---|
| 141 | * This function updates the opponent's Model by calling the
|
---|
| 142 | * updateStatistics method
|
---|
| 143 | *
|
---|
| 144 | * @author Eden Erez, Erel Segal haLevi
|
---|
| 145 | */
|
---|
| 146 | public void updateOpponentModel(Bid bidToUpdate, double weight,
|
---|
| 147 | AbstractUtilitySpace utilitySpace) {
|
---|
| 148 | this.addBid(bidToUpdate, utilitySpace);
|
---|
| 149 | if (this.bidHistory.size() <= this.maximumBidsStored) {
|
---|
| 150 | this.updateStatistics(bidToUpdate, weight, utilitySpace.getDomain());
|
---|
| 151 | }
|
---|
| 152 | }
|
---|
| 153 |
|
---|
| 154 | /**
|
---|
| 155 | * This function updates the statistics of the bids that were received from
|
---|
| 156 | * the opponent.
|
---|
| 157 | *
|
---|
| 158 | * New algorithm!
|
---|
| 159 | *
|
---|
| 160 | * @author Justin Changed by Eden Erez and Erel Segal haLevi (added weight)
|
---|
| 161 | * @since 2013-01
|
---|
| 162 | */
|
---|
| 163 | private void updateStatistics(Bid bidToUpdate, double weight, Domain domain) {
|
---|
| 164 | try {
|
---|
| 165 | List<Issue> issues = domain.getIssues();
|
---|
| 166 |
|
---|
| 167 | // counters for each type of the issues
|
---|
| 168 | int realIssueIndex = 0;
|
---|
| 169 | int discreteIssueIndex = 0;
|
---|
| 170 | int integerIssueIndex = 0;
|
---|
| 171 | for (Issue lIssue : issues) {
|
---|
| 172 | int issueNum = lIssue.getNumber();
|
---|
| 173 | Value v = bidToUpdate.getValue(issueNum);
|
---|
| 174 | switch (lIssue.getType()) {
|
---|
| 175 | case DISCRETE:
|
---|
| 176 | if (opponentBidsStatisticsDiscrete == null) {
|
---|
| 177 | System.out
|
---|
| 178 | .println("opponentBidsStatisticsDiscrete is NULL");
|
---|
| 179 | } else if (opponentBidsStatisticsDiscrete
|
---|
| 180 | .get(discreteIssueIndex) != null) {
|
---|
| 181 | double totalWeightPerValue = opponentBidsStatisticsDiscrete
|
---|
| 182 | .get(discreteIssueIndex).get(v);
|
---|
| 183 |
|
---|
| 184 | totalWeightPerValue += weight;
|
---|
| 185 | opponentBidsStatisticsDiscrete.get(discreteIssueIndex)
|
---|
| 186 | .put(v, totalWeightPerValue);
|
---|
| 187 | }
|
---|
| 188 | discreteIssueIndex++;
|
---|
| 189 | break;
|
---|
| 190 |
|
---|
| 191 | case REAL:
|
---|
| 192 |
|
---|
| 193 | IssueReal lIssueReal = (IssueReal) lIssue;
|
---|
| 194 | int lNumOfPossibleRealValues = lIssueReal
|
---|
| 195 | .getNumberOfDiscretizationSteps();
|
---|
| 196 | double lOneStep = (lIssueReal.getUpperBound() - lIssueReal
|
---|
| 197 | .getLowerBound()) / lNumOfPossibleRealValues;
|
---|
| 198 | double first = lIssueReal.getLowerBound();
|
---|
| 199 | double last = lIssueReal.getLowerBound() + lOneStep;
|
---|
| 200 | double valueReal = ((ValueReal) v).getValue();
|
---|
| 201 | boolean found = false;
|
---|
| 202 |
|
---|
| 203 | for (int i = 0; !found
|
---|
| 204 | && i < opponentBidsStatisticsForReal.get(
|
---|
| 205 | realIssueIndex).size(); i++) {
|
---|
| 206 | if (valueReal >= first && valueReal <= last) {
|
---|
| 207 | double countPerValue = opponentBidsStatisticsForReal
|
---|
| 208 | .get(realIssueIndex).get(i);
|
---|
| 209 |
|
---|
| 210 | countPerValue += weight;
|
---|
| 211 |
|
---|
| 212 | opponentBidsStatisticsForReal.get(realIssueIndex)
|
---|
| 213 | .set(i, countPerValue);
|
---|
| 214 | found = true;
|
---|
| 215 | }
|
---|
| 216 | first = last;
|
---|
| 217 | last = last + lOneStep;
|
---|
| 218 | }
|
---|
| 219 | // If no matching value was found, update the last cell
|
---|
| 220 | if (found == false) {
|
---|
| 221 | int i = opponentBidsStatisticsForReal.get(
|
---|
| 222 | realIssueIndex).size() - 1;
|
---|
| 223 | double countPerValue = opponentBidsStatisticsForReal
|
---|
| 224 | .get(realIssueIndex).get(i);
|
---|
| 225 |
|
---|
| 226 | countPerValue += weight;
|
---|
| 227 |
|
---|
| 228 | opponentBidsStatisticsForReal.get(realIssueIndex).set(
|
---|
| 229 | i, countPerValue);
|
---|
| 230 | }
|
---|
| 231 | realIssueIndex++;
|
---|
| 232 | break;
|
---|
| 233 |
|
---|
| 234 | case INTEGER:
|
---|
| 235 |
|
---|
| 236 | IssueInteger lIssueInteger = (IssueInteger) lIssue;
|
---|
| 237 | int valueInteger = ((ValueInteger) v).getValue();
|
---|
| 238 |
|
---|
| 239 | int valueIndex = valueInteger
|
---|
| 240 | - lIssueInteger.getLowerBound(); // For ex.
|
---|
| 241 | // LowerBound
|
---|
| 242 | // index is 0,
|
---|
| 243 | // and the lower
|
---|
| 244 | // bound is 2,
|
---|
| 245 | // the value is
|
---|
| 246 | // 4, so the
|
---|
| 247 | // index of 4
|
---|
| 248 | // would be 2
|
---|
| 249 | // which is
|
---|
| 250 | // exactly 4-2
|
---|
| 251 | double countPerValue = opponentBidsStatisticsForInteger
|
---|
| 252 | .get(integerIssueIndex).get(valueIndex);
|
---|
| 253 | countPerValue += weight;
|
---|
| 254 | opponentBidsStatisticsForInteger.get(integerIssueIndex)
|
---|
| 255 | .set(valueIndex, countPerValue);
|
---|
| 256 | integerIssueIndex++;
|
---|
| 257 | break;
|
---|
| 258 | }
|
---|
| 259 | }
|
---|
| 260 | } catch (Exception e) {
|
---|
| 261 | System.out.println("Exception in updateStatistics: "
|
---|
| 262 | + e.getMessage());
|
---|
| 263 | }
|
---|
| 264 | }
|
---|
| 265 |
|
---|
| 266 | /**
|
---|
| 267 | * choose a bid which is optimal for the opponent among a set of candidate
|
---|
| 268 | * bids.
|
---|
| 269 | *
|
---|
| 270 | * New algorithm!
|
---|
| 271 | *
|
---|
| 272 | * @author Eden Erez, Erel Segal haLevi
|
---|
| 273 | * @since 2013-01
|
---|
| 274 | */
|
---|
| 275 | public Bid ChooseBid(List<Bid> candidateBids, Domain domain)
|
---|
| 276 | throws Exception {
|
---|
| 277 | if (candidateBids.isEmpty()) {
|
---|
| 278 | System.out.println("test");
|
---|
| 279 | }
|
---|
| 280 | int indexOfBestCandidateBid = -1;
|
---|
| 281 | List<Issue> issues = domain.getIssues();
|
---|
| 282 | int realIndex = 0;
|
---|
| 283 | int discreteIndex = 0;
|
---|
| 284 | int integerIndex = 0;
|
---|
| 285 | double maxTotalWeightOfAllValuesInCandidateBids = 0;
|
---|
| 286 | for (int iCandidateBid = 0; iCandidateBid < candidateBids.size(); iCandidateBid++) {
|
---|
| 287 | double totalWeightOfAllValuesInCurrentCandidateBid = 0;
|
---|
| 288 | realIndex = discreteIndex = integerIndex = 0;
|
---|
| 289 | for (int iIssue = 0; iIssue < issues.size(); iIssue++) {
|
---|
| 290 | Value valueInCurrentIssueInCurrentCandidateBid = candidateBids
|
---|
| 291 | .get(iCandidateBid).getValue(
|
---|
| 292 | issues.get(iIssue).getNumber());
|
---|
| 293 | switch (issues.get(iIssue).getType()) {
|
---|
| 294 | case DISCRETE:
|
---|
| 295 | if (opponentBidsStatisticsDiscrete == null) {
|
---|
| 296 | System.out
|
---|
| 297 | .println("opponentBidsStatisticsDiscrete is NULL");
|
---|
| 298 | } else if (opponentBidsStatisticsDiscrete
|
---|
| 299 | .get(discreteIndex) != null) {
|
---|
| 300 | double totalWeightPerValue = opponentBidsStatisticsDiscrete
|
---|
| 301 | .get(discreteIndex)
|
---|
| 302 | .get(valueInCurrentIssueInCurrentCandidateBid);
|
---|
| 303 | totalWeightOfAllValuesInCurrentCandidateBid += totalWeightPerValue;
|
---|
| 304 | }
|
---|
| 305 | discreteIndex++;
|
---|
| 306 | break;
|
---|
| 307 | case REAL:
|
---|
| 308 | IssueReal lIssueReal = (IssueReal) issues.get(iIssue);
|
---|
| 309 | int lNumOfPossibleRealValues = lIssueReal
|
---|
| 310 | .getNumberOfDiscretizationSteps();
|
---|
| 311 | double lOneStep = (lIssueReal.getUpperBound() - lIssueReal
|
---|
| 312 | .getLowerBound()) / lNumOfPossibleRealValues;
|
---|
| 313 | double first = lIssueReal.getLowerBound();
|
---|
| 314 | double last = lIssueReal.getLowerBound() + lOneStep;
|
---|
| 315 | double valueReal = ((ValueReal) valueInCurrentIssueInCurrentCandidateBid)
|
---|
| 316 | .getValue();
|
---|
| 317 | boolean found = false;
|
---|
| 318 | for (int k = 0; !found
|
---|
| 319 | && k < opponentBidsStatisticsForReal.get(realIndex)
|
---|
| 320 | .size(); k++) {
|
---|
| 321 | if (valueReal >= first && valueReal <= last) {
|
---|
| 322 | double totalWeightPerValue = opponentBidsStatisticsForReal
|
---|
| 323 | .get(realIndex).get(k);
|
---|
| 324 | totalWeightOfAllValuesInCurrentCandidateBid += totalWeightPerValue;
|
---|
| 325 | found = true;
|
---|
| 326 | }
|
---|
| 327 | first = last;
|
---|
| 328 | last = last + lOneStep;
|
---|
| 329 | }
|
---|
| 330 | if (found == false) {
|
---|
| 331 | int k = opponentBidsStatisticsForReal.get(realIndex)
|
---|
| 332 | .size() - 1;
|
---|
| 333 | double totalWeightPerValue = opponentBidsStatisticsForReal
|
---|
| 334 | .get(realIndex).get(k);
|
---|
| 335 | totalWeightOfAllValuesInCurrentCandidateBid += totalWeightPerValue;
|
---|
| 336 | }
|
---|
| 337 | realIndex++;
|
---|
| 338 | break;
|
---|
| 339 |
|
---|
| 340 | case INTEGER:
|
---|
| 341 | IssueInteger lIssueInteger = (IssueInteger) issues
|
---|
| 342 | .get(iIssue);
|
---|
| 343 | int valueInteger = ((ValueInteger) valueInCurrentIssueInCurrentCandidateBid)
|
---|
| 344 | .getValue();
|
---|
| 345 | int valueIndex = valueInteger
|
---|
| 346 | - lIssueInteger.getLowerBound(); // For ex.
|
---|
| 347 | // LowerBound
|
---|
| 348 | // index is 0,
|
---|
| 349 | // and the lower
|
---|
| 350 | // bound is 2,
|
---|
| 351 | // the value is
|
---|
| 352 | // 4, so the
|
---|
| 353 | // index of 4
|
---|
| 354 | // would be 2
|
---|
| 355 | // which is
|
---|
| 356 | // exactly 4-2
|
---|
| 357 | double totalWeightPerValue = opponentBidsStatisticsForInteger
|
---|
| 358 | .get(integerIndex).get(valueIndex);
|
---|
| 359 | totalWeightOfAllValuesInCurrentCandidateBid += totalWeightPerValue;
|
---|
| 360 | integerIndex++;
|
---|
| 361 | break;
|
---|
| 362 | }
|
---|
| 363 | }
|
---|
| 364 | if (totalWeightOfAllValuesInCurrentCandidateBid > maxTotalWeightOfAllValuesInCandidateBids) {// choose
|
---|
| 365 | // the
|
---|
| 366 | // bid
|
---|
| 367 | // with
|
---|
| 368 | // the
|
---|
| 369 | // maximum
|
---|
| 370 | // maxValue
|
---|
| 371 | maxTotalWeightOfAllValuesInCandidateBids = totalWeightOfAllValuesInCurrentCandidateBid;
|
---|
| 372 | indexOfBestCandidateBid = iCandidateBid;
|
---|
| 373 | }
|
---|
| 374 | }
|
---|
| 375 | // System.out.println("indexOfBestCandidateBid: " +
|
---|
| 376 | // indexOfBestCandidateBid);
|
---|
| 377 | if (indexOfBestCandidateBid == -1)
|
---|
| 378 | return null;
|
---|
| 379 | return candidateBids.get(indexOfBestCandidateBid);
|
---|
| 380 | }
|
---|
| 381 |
|
---|
| 382 | /**
|
---|
| 383 | * @return the number of bids - without duplicates
|
---|
| 384 | */
|
---|
| 385 | public int getNumberOfDistinctBids() {
|
---|
| 386 | return bidHistory.size();
|
---|
| 387 | }
|
---|
| 388 |
|
---|
| 389 | }
|
---|