[1] | 1 | package agents;
|
---|
| 2 |
|
---|
| 3 | import java.util.HashMap;
|
---|
| 4 | import java.util.List;
|
---|
| 5 |
|
---|
| 6 | import genius.core.Agent;
|
---|
| 7 | import genius.core.Bid;
|
---|
| 8 | import genius.core.SupportedNegotiationSetting;
|
---|
| 9 | import genius.core.actions.Accept;
|
---|
| 10 | import genius.core.actions.Action;
|
---|
| 11 | import genius.core.actions.EndNegotiation;
|
---|
| 12 | import genius.core.actions.Offer;
|
---|
| 13 | import genius.core.issue.ISSUETYPE;
|
---|
| 14 | import genius.core.issue.Issue;
|
---|
| 15 | import genius.core.issue.IssueDiscrete;
|
---|
| 16 | import genius.core.issue.Value;
|
---|
| 17 | import genius.core.issue.ValueDiscrete;
|
---|
| 18 | import genius.core.issue.ValueReal;
|
---|
| 19 | import genius.core.utility.AdditiveUtilitySpace;
|
---|
| 20 | import genius.core.utility.EvaluatorDiscrete;
|
---|
| 21 | import genius.core.utility.EvaluatorReal;
|
---|
| 22 |
|
---|
| 23 | /**
|
---|
| 24 | *
|
---|
| 25 | * @author Dmytro Tykhonov & Koen Hindriks
|
---|
| 26 | */
|
---|
| 27 |
|
---|
| 28 | public class ABMPAgent2 extends Agent {
|
---|
| 29 |
|
---|
| 30 | private Action messageOpponent;
|
---|
| 31 | // private int nrOfIssues;
|
---|
| 32 | private Bid myLastBid = null;
|
---|
| 33 | private Action myLastAction = null;
|
---|
| 34 |
|
---|
| 35 | // private double[] fIssueWeight;
|
---|
| 36 | private enum ACTIONTYPE {
|
---|
| 37 | START, OFFER, ACCEPT, BREAKOFF
|
---|
| 38 | };
|
---|
| 39 |
|
---|
| 40 | private double fOldTargetUtility;
|
---|
| 41 | // Paraters used in ABMP strategy
|
---|
| 42 | // TODO: Include these parameters as agent parameters in agent's utility
|
---|
| 43 | // template.
|
---|
| 44 | // QUESTION: How to do that nicely, since these parameters are strategy
|
---|
| 45 | // specific?
|
---|
| 46 | private static final double NEGOTIATIONSPEED = 0.1; // TODO: Probably still
|
---|
| 47 | // somewhere a bug. When
|
---|
| 48 | // you set this too low
|
---|
| 49 | // (e.g. 0.05), no deal
|
---|
| 50 | // is reached and no
|
---|
| 51 | // concession is done!
|
---|
| 52 | private static final double CONCESSIONFACTOR = 1;
|
---|
| 53 | private static final double CONFTOLERANCE = 0;
|
---|
| 54 | private static final double UTIlITYGAPSIZE = 0.02; // Accept when utility
|
---|
| 55 | // gap is <=
|
---|
| 56 | // UTILITYGAPSIZE.
|
---|
| 57 |
|
---|
| 58 | // CHECK: Utility gap size needed since concession steps get VERY small when
|
---|
| 59 | // opponent's last bid utility is
|
---|
| 60 | // close to own last bid utility.
|
---|
| 61 |
|
---|
| 62 | // Code is independent from AMPO vs CITY case, but some specifics about
|
---|
| 63 | // using this case as test are specified below.
|
---|
| 64 | // ****************************************************************************************************
|
---|
| 65 | // AMPO VS CITY: Outcome space has size of about 7 milion.
|
---|
| 66 | // ****************************************************************************************************
|
---|
| 67 | // ********************************************************
|
---|
| 68 | // *******************************************
|
---|
| 69 | // CHECK: ABMP gets stuck on the Car Example with a negotiation speed of
|
---|
| 70 | // less than 0.05!!
|
---|
| 71 | // ABMP "gets stuck" on AMPO vs CITY. The search through the space is not
|
---|
| 72 | // effective in discrete outcome
|
---|
| 73 | // spaces. Even with very high negotiation speed parameters (near 1) no bid
|
---|
| 74 | // can be found with the target utility
|
---|
| 75 | // at a certain point. In a discrete space, the evaluation distance between
|
---|
| 76 | // two different values on an
|
---|
| 77 | // issue need to be taken into account, which may differ from value to
|
---|
| 78 | // value... In such spaces one strategy
|
---|
| 79 | // would be to consider which combination of concessions on a set of issues
|
---|
| 80 | // would provide
|
---|
| 81 | // ********************************************************
|
---|
| 82 | // *******************************************
|
---|
| 83 |
|
---|
| 84 | /** Creates a new instance of MyAgent */
|
---|
| 85 |
|
---|
| 86 | public ABMPAgent2() {
|
---|
| 87 | super();
|
---|
| 88 | }
|
---|
| 89 |
|
---|
| 90 | @Override
|
---|
| 91 | public void init() {
|
---|
| 92 | super.init();
|
---|
| 93 | messageOpponent = null;
|
---|
| 94 | myLastBid = null;
|
---|
| 95 | myLastAction = null;
|
---|
| 96 | fOldTargetUtility = 1;
|
---|
| 97 |
|
---|
| 98 | }
|
---|
| 99 |
|
---|
| 100 | public void ReceiveMessage(Action opponentAction) {
|
---|
| 101 | messageOpponent = opponentAction;
|
---|
| 102 | }
|
---|
| 103 |
|
---|
| 104 | private Action proposeInitialBid() throws Exception {
|
---|
| 105 | Bid lBid;
|
---|
| 106 |
|
---|
| 107 | // Return (one of the) possible bid(s) with maximal utility.
|
---|
| 108 | lBid = utilitySpace.getMaxUtilityBid();
|
---|
| 109 | lBid = getBidRandomWalk(utilitySpace.getUtility(lBid) * 0.95,
|
---|
| 110 | utilitySpace.getUtility(lBid));
|
---|
| 111 | myLastBid = lBid;
|
---|
| 112 | return new Offer(this.getAgentID(), lBid);
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 | private Action proposeNextBid(Bid lOppntBid) {
|
---|
| 116 | Bid lBid = null;
|
---|
| 117 | double lMyUtility, lOppntUtility = 1, lTargetUtility;
|
---|
| 118 | // Both parties have made an initial bid. Compute associated utilities
|
---|
| 119 | // from my point of view.
|
---|
| 120 | lMyUtility = fOldTargetUtility;// utilitySpace.getUtility(myLastBid);
|
---|
| 121 | try {
|
---|
| 122 | lOppntUtility = utilitySpace.getUtility(lOppntBid);
|
---|
| 123 | } catch (Exception e) {
|
---|
| 124 | e.printStackTrace();
|
---|
| 125 | }
|
---|
| 126 | lTargetUtility = getTargetUtility(lMyUtility, lOppntUtility);
|
---|
| 127 | try {
|
---|
| 128 | lBid = getBidABMPsimple(lTargetUtility);
|
---|
| 129 | } catch (Exception e) {
|
---|
| 130 | e.printStackTrace();
|
---|
| 131 | }
|
---|
| 132 | myLastBid = lBid;
|
---|
| 133 | fOldTargetUtility = lTargetUtility;
|
---|
| 134 | return new Offer(this.getAgentID(), lBid);
|
---|
| 135 | }
|
---|
| 136 |
|
---|
| 137 | public Action chooseAction() {
|
---|
| 138 | Action lAction = null;
|
---|
| 139 | ACTIONTYPE lActionType;
|
---|
| 140 | Bid lOppntBid = null;
|
---|
| 141 |
|
---|
| 142 | lActionType = getActionType(messageOpponent);
|
---|
| 143 | switch (lActionType) {
|
---|
| 144 | case OFFER: // Offer received from opponent
|
---|
| 145 | try {
|
---|
| 146 | lOppntBid = ((Offer) messageOpponent).getBid();
|
---|
| 147 | if (myLastAction == null)
|
---|
| 148 | // Other agent started, lets propose my initial bid.
|
---|
| 149 | lAction = proposeInitialBid();
|
---|
| 150 | // DT Accept if utility gap is smaller than my target utility
|
---|
| 151 | // (instead of actual utility of my previous bid)
|
---|
| 152 | else if (utilitySpace.getUtility(lOppntBid) >= /*
|
---|
| 153 | * (utilitySpace.
|
---|
| 154 | * getUtility
|
---|
| 155 | * (myLastBid))
|
---|
| 156 | */fOldTargetUtility
|
---|
| 157 | - UTIlITYGAPSIZE)
|
---|
| 158 | // Opponent bids equally, or outbids my previous bid, so
|
---|
| 159 | // lets accept.
|
---|
| 160 | lAction = new Accept(getAgentID(), lOppntBid);
|
---|
| 161 | else
|
---|
| 162 | // Propose counteroffer. Get next bid.
|
---|
| 163 | lAction = proposeNextBid(lOppntBid);
|
---|
| 164 | } catch (Exception e) {
|
---|
| 165 | e.printStackTrace();
|
---|
| 166 | }
|
---|
| 167 | break;
|
---|
| 168 | case ACCEPT: // Presumably, opponent accepted last bid, but let's
|
---|
| 169 | // check...
|
---|
| 170 | /*
|
---|
| 171 | * lOppntBid = ((Accept) messageOpponent).getBid(); if
|
---|
| 172 | * (lOppntBid.equals(myLastBid)) lAction = new Accept(this,
|
---|
| 173 | * myLastBid); else lAction = new Offer(this, myLastBid); break;
|
---|
| 174 | */
|
---|
| 175 | case BREAKOFF:
|
---|
| 176 | // nothing left to do. Negotiation ended, which should be checked by
|
---|
| 177 | // Negotiator...
|
---|
| 178 | break;
|
---|
| 179 | default:
|
---|
| 180 | // I am starting, but not sure whether Negotiator checks this, so
|
---|
| 181 | // lets check also myLastAction...
|
---|
| 182 | if (myLastAction == null)
|
---|
| 183 | try {
|
---|
| 184 | lAction = proposeInitialBid();
|
---|
| 185 | } catch (Exception e) {
|
---|
| 186 | e.printStackTrace();
|
---|
| 187 | }
|
---|
| 188 | else
|
---|
| 189 | // simply repeat last action
|
---|
| 190 | lAction = myLastAction;
|
---|
| 191 | break;
|
---|
| 192 | }
|
---|
| 193 |
|
---|
| 194 | myLastAction = lAction;
|
---|
| 195 | return lAction;
|
---|
| 196 | }
|
---|
| 197 |
|
---|
| 198 | private ACTIONTYPE getActionType(Action lAction) {
|
---|
| 199 | ACTIONTYPE lActionType = ACTIONTYPE.START;
|
---|
| 200 |
|
---|
| 201 | if (lAction instanceof Offer)
|
---|
| 202 | lActionType = ACTIONTYPE.OFFER;
|
---|
| 203 | else if (lAction instanceof Accept)
|
---|
| 204 | lActionType = ACTIONTYPE.ACCEPT;
|
---|
| 205 | else if (lAction instanceof EndNegotiation)
|
---|
| 206 | lActionType = ACTIONTYPE.BREAKOFF;
|
---|
| 207 | return lActionType;
|
---|
| 208 | }
|
---|
| 209 |
|
---|
| 210 | /*
|
---|
| 211 | * public void loadUtilitySpace(String fileName) {
|
---|
| 212 | *
|
---|
| 213 | * utilitySpace = new
|
---|
| 214 | * SimpleUtilitySpace(getNegotiationTemplate().getDomain(), fileName);
|
---|
| 215 | *
|
---|
| 216 | * nrOfIssues = getNegotiationTemplate().getDomain().getNumberOfIssues();
|
---|
| 217 | * fIssueWeight = new double[nrOfIssues]; for (int i=0; i<nrOfIssues; i++) {
|
---|
| 218 | * fIssueWeight[i] = this.utilitySpace.getWeight(i); } }
|
---|
| 219 | */
|
---|
| 220 | // ABMP Specific Code
|
---|
| 221 |
|
---|
| 222 | private Bid getBidABMPsimple(double targetUtility) throws Exception {
|
---|
| 223 | int nrOfIssues = utilitySpace.getDomain().getIssues().size();
|
---|
| 224 | double[] lIssueWeight = new double[nrOfIssues];
|
---|
| 225 | int i = 0;
|
---|
| 226 | for (Issue lIssue : utilitySpace.getDomain().getIssues()) {
|
---|
| 227 | lIssueWeight[i] = ((AdditiveUtilitySpace) utilitySpace)
|
---|
| 228 | .getWeight(lIssue.getNumber());
|
---|
| 229 | i++;
|
---|
| 230 | }
|
---|
| 231 | List<Issue> lIssues = utilitySpace.getDomain().getIssues();
|
---|
| 232 | Value[] lIssueIndex = new Value[nrOfIssues];
|
---|
| 233 | double[] lIssueAlpha = new double[nrOfIssues];
|
---|
| 234 | double[] lBE = new double[nrOfIssues];
|
---|
| 235 | double[] lBTE = new double[nrOfIssues];
|
---|
| 236 | double[] lTE = new double[nrOfIssues];
|
---|
| 237 | double lUtility = 0, lNF = 0, lAlpha, lUtilityGap, lTotalConcession = 0;
|
---|
| 238 |
|
---|
| 239 | // ASSUMPTION: Method computes a second bid. Method proposeInitialBid is
|
---|
| 240 | // used to compute first bid.
|
---|
| 241 | lUtilityGap = targetUtility - utilitySpace.getUtility(myLastBid);
|
---|
| 242 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 243 | lBE[i] = (Double) (((AdditiveUtilitySpace) utilitySpace)
|
---|
| 244 | .getEvaluator(lIssues.get(i).getNumber()).getEvaluation(
|
---|
| 245 | ((AdditiveUtilitySpace) utilitySpace), myLastBid, lIssues
|
---|
| 246 | .get(i).getNumber()));
|
---|
| 247 | }
|
---|
| 248 |
|
---|
| 249 | // STEP 1: Retrieve issue value for last bid and compute concession on
|
---|
| 250 | // each issue.
|
---|
| 251 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 252 | lAlpha = (1 - lIssueWeight[i]) * lBE[i]; // CHECK: (1 - lBE[i]);
|
---|
| 253 | // This factor is not
|
---|
| 254 | // right??
|
---|
| 255 | lNF = lNF + lIssueWeight[i] * lAlpha;
|
---|
| 256 | lIssueAlpha[i] = lAlpha;
|
---|
| 257 | }
|
---|
| 258 |
|
---|
| 259 | // Compute basic target evaluations per issue
|
---|
| 260 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 261 | lBTE[i] = lBE[i] + (lIssueAlpha[i] / lNF) * lUtilityGap;
|
---|
| 262 | }
|
---|
| 263 |
|
---|
| 264 | // STEP 2: Add configuration tolerance for opponent's bid
|
---|
| 265 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 266 | lUtility = (Double) (((AdditiveUtilitySpace) utilitySpace)
|
---|
| 267 | .getEvaluator(lIssues.get(i).getNumber()).getEvaluation(
|
---|
| 268 | ((AdditiveUtilitySpace) utilitySpace),
|
---|
| 269 | ((Offer) messageOpponent).getBid(), lIssues.get(i)
|
---|
| 270 | .getNumber()));
|
---|
| 271 | lTE[i] = (1 - CONFTOLERANCE) * lBTE[i] + CONFTOLERANCE * lUtility;
|
---|
| 272 | }
|
---|
| 273 |
|
---|
| 274 | // STEP 3: Find bid in outcome space with issue target utilities
|
---|
| 275 | // corresponding with those computed above.
|
---|
| 276 | // ASSUMPTION: There is always a UNIQUE issue value with utility closest
|
---|
| 277 | // to the target evaluation.
|
---|
| 278 | // First determine new values for discrete-valued issues.
|
---|
| 279 | double lEvalValue;
|
---|
| 280 | int lNrOfRealIssues = 0;
|
---|
| 281 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 282 | lUtility = 1; // ASSUMPTION: Max utility = 1.
|
---|
| 283 | Issue lIssue = lIssues.get(i);// getNegotiationTemplate().getDomain().getIssue(i);
|
---|
| 284 | if (lIssue.getType() == ISSUETYPE.DISCRETE) {
|
---|
| 285 | IssueDiscrete lIssueDiscrete = (IssueDiscrete) lIssue;
|
---|
| 286 | for (int j = 0; j < lIssueDiscrete.getNumberOfValues(); j++) {
|
---|
| 287 | lEvalValue = ((EvaluatorDiscrete) ((AdditiveUtilitySpace) utilitySpace)
|
---|
| 288 | .getEvaluator(lIssues.get(i).getNumber()))
|
---|
| 289 | .getEvaluation(lIssueDiscrete.getValue(j));
|
---|
| 290 | if (Math.abs(lTE[i] - lEvalValue) < lUtility) {
|
---|
| 291 | lIssueIndex[i] = lIssueDiscrete.getValue(j);
|
---|
| 292 | lUtility = Math.abs(lTE[i] - lEvalValue);
|
---|
| 293 | }// if
|
---|
| 294 | }// for
|
---|
| 295 | lTotalConcession += lIssueWeight[i]
|
---|
| 296 | * (lBE[i] - ((EvaluatorDiscrete) ((AdditiveUtilitySpace) utilitySpace)
|
---|
| 297 | .getEvaluator(lIssues.get(i).getNumber()))
|
---|
| 298 | .getEvaluation((ValueDiscrete) lIssueIndex[i]));
|
---|
| 299 | } else if (lIssue.getType() == ISSUETYPE.REAL)
|
---|
| 300 | lNrOfRealIssues += 1;
|
---|
| 301 | }
|
---|
| 302 |
|
---|
| 303 | // TODO: Still need to integrate integer-valued issues somewhere here.
|
---|
| 304 | // Low priority.
|
---|
| 305 |
|
---|
| 306 | // STEP 4: RECOMPUTE size of remaining concession step
|
---|
| 307 | // Reason: Issue value may not provide exact match with basic target
|
---|
| 308 | // evaluation value.
|
---|
| 309 | // NOTE: This recomputation also includes any concession due to
|
---|
| 310 | // configuration tolerance parameter...
|
---|
| 311 | // First compute difference between actual concession on issue and
|
---|
| 312 | // target evaluation.
|
---|
| 313 | // TODO: Think about how to (re)distribute remaining concession over
|
---|
| 314 | // MULTIPLE real issues. In car example
|
---|
| 315 | // not important. Low priority.
|
---|
| 316 | double lRestUtitility = lUtilityGap + lTotalConcession;
|
---|
| 317 | // Distribute remaining utility of real issues. Integers still to be
|
---|
| 318 | // done. See above.
|
---|
| 319 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 320 | Issue lIssue = lIssues.get(i);// getNegotiationTemplate().getDomain().getIssue(i);
|
---|
| 321 | if (lIssue.getType() == ISSUETYPE.REAL) {
|
---|
| 322 | lTE[i] += lRestUtitility / lNrOfRealIssues;
|
---|
| 323 | EvaluatorReal lRealEvaluator = (EvaluatorReal) (((AdditiveUtilitySpace) utilitySpace)
|
---|
| 324 | .getEvaluator(lIssues.get(i).getNumber()));
|
---|
| 325 | double r = lRealEvaluator.getValueByEvaluation(lTE[i]);
|
---|
| 326 | lIssueIndex[i] = new ValueReal(r);
|
---|
| 327 | }
|
---|
| 328 | }
|
---|
| 329 | HashMap<Integer, Value> lValues = new HashMap<Integer, Value>();
|
---|
| 330 | for (i = 0; i < nrOfIssues; i++) {
|
---|
| 331 | lValues.put(lIssues.get(i).getNumber(), lIssueIndex[i]);
|
---|
| 332 | }
|
---|
| 333 | return new Bid(utilitySpace.getDomain(), lValues);
|
---|
| 334 | }
|
---|
| 335 |
|
---|
| 336 | private double getTargetUtility(double myUtility, double oppntUtility) {
|
---|
| 337 | return myUtility + getConcessionStep(myUtility, oppntUtility);
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | private double getNegotiationSpeed() {
|
---|
| 341 | return NEGOTIATIONSPEED;
|
---|
| 342 | }
|
---|
| 343 |
|
---|
| 344 | private double getConcessionFactor() {
|
---|
| 345 | // The more the agent is willing to concess on its aspiration value, the
|
---|
| 346 | // higher this factor.
|
---|
| 347 | return CONCESSIONFACTOR;
|
---|
| 348 | }
|
---|
| 349 |
|
---|
| 350 | private double getConcessionStep(double myUtility, double oppntUtility) {
|
---|
| 351 | double lConcessionStep = 0, lMinUtility = 0, lUtilityGap = 0;
|
---|
| 352 |
|
---|
| 353 | // Compute concession step
|
---|
| 354 | lMinUtility = 1 - getConcessionFactor();
|
---|
| 355 | lUtilityGap = (oppntUtility - myUtility);
|
---|
| 356 | lConcessionStep = getNegotiationSpeed() * (1 - lMinUtility / myUtility)
|
---|
| 357 | * lUtilityGap;
|
---|
| 358 | System.out.println(lConcessionStep);
|
---|
| 359 | return lConcessionStep;
|
---|
| 360 | }
|
---|
| 361 |
|
---|
| 362 | private Bid getBidRandomWalk(double lowerBound, double upperBoud)
|
---|
| 363 | throws Exception {
|
---|
| 364 | Bid lBid = null, lBestBid = null;
|
---|
| 365 |
|
---|
| 366 | // Return bid that gets closest to target utility in a "random walk"
|
---|
| 367 | // search.
|
---|
| 368 | lBestBid = utilitySpace.getDomain().getRandomBid(null);
|
---|
| 369 | while (true) {
|
---|
| 370 | lBid = utilitySpace.getDomain().getRandomBid(null);
|
---|
| 371 | if ((utilitySpace.getUtility(lBid) > lowerBound)
|
---|
| 372 | && (utilitySpace.getUtility(lBestBid) < upperBoud)) {
|
---|
| 373 | lBestBid = lBid;
|
---|
| 374 | break;
|
---|
| 375 | }
|
---|
| 376 |
|
---|
| 377 | }
|
---|
| 378 | return lBestBid;
|
---|
| 379 | }
|
---|
| 380 |
|
---|
| 381 | @Override
|
---|
| 382 | public SupportedNegotiationSetting getSupportedNegotiationSetting() {
|
---|
| 383 | return SupportedNegotiationSetting.getLinearUtilitySpaceInstance();
|
---|
| 384 | }
|
---|
| 385 |
|
---|
| 386 | @Override
|
---|
| 387 | public String getVersion() {
|
---|
| 388 | return "1.0";
|
---|
| 389 | }
|
---|
| 390 | }
|
---|