1 | package negotiator.boaframework.acceptanceconditions.anac2013;
|
---|
2 |
|
---|
3 | import java.io.Serializable;
|
---|
4 | import java.util.ArrayList;
|
---|
5 | import java.util.List;
|
---|
6 | import java.util.Map;
|
---|
7 |
|
---|
8 | import genius.core.NegotiationResult;
|
---|
9 | import genius.core.bidding.BidDetails;
|
---|
10 | import genius.core.boaframework.AcceptanceStrategy;
|
---|
11 | import genius.core.boaframework.Actions;
|
---|
12 | import genius.core.boaframework.NegotiationSession;
|
---|
13 | import genius.core.boaframework.OfferingStrategy;
|
---|
14 | import genius.core.boaframework.OpponentModel;
|
---|
15 | import genius.core.boaframework.SortedOutcomeSpace;
|
---|
16 | import negotiator.boaframework.offeringstrategy.anac2013.inoxAgent.SaveHelper;
|
---|
17 |
|
---|
18 | /**
|
---|
19 | * This Acceptance Condition will break when the reservation value seems to be a
|
---|
20 | * better alternative, and accept when the opponents offer is better than ours
|
---|
21 | * or when the opponents offer is higher than a time dependent function.
|
---|
22 | *
|
---|
23 | * @author Ruben van Zessen, Mariana Branco
|
---|
24 | */
|
---|
25 | public class AC_InoxAgent extends AcceptanceStrategy {
|
---|
26 | /** Discount factor of the domain */
|
---|
27 | private double discountFactor;
|
---|
28 | /** Median utility in the sorted outcome space */
|
---|
29 | private double medianutil;
|
---|
30 |
|
---|
31 | /** Time of the previous iteration */
|
---|
32 | private double lastTime = 0.0;
|
---|
33 | /** List of time differences between iterations */
|
---|
34 | private ArrayList<Double> timeList = new ArrayList<Double>();
|
---|
35 |
|
---|
36 | /** A check whether the median has been set yet */
|
---|
37 | private boolean medianDecided = false;
|
---|
38 | /** A check whether the median is the true median or a saved value */
|
---|
39 | private boolean realmedian = true;
|
---|
40 |
|
---|
41 | /** Previously obtained utility */
|
---|
42 | private double prevRes = 0.0;
|
---|
43 | /** Number of previous negotiations */
|
---|
44 | private int prevNegos = 0;
|
---|
45 |
|
---|
46 | /** Estimated number of rounds left in the negotiation */
|
---|
47 | private int roundsLeft = Integer.MAX_VALUE;
|
---|
48 |
|
---|
49 | /**
|
---|
50 | * Empty constructor.
|
---|
51 | */
|
---|
52 | public AC_InoxAgent() {
|
---|
53 | }
|
---|
54 |
|
---|
55 | /**
|
---|
56 | * Regular constructor.
|
---|
57 | *
|
---|
58 | * Sets initial values and loads old data if available.
|
---|
59 | */
|
---|
60 | public AC_InoxAgent(NegotiationSession negoSession, OfferingStrategy strat, OpponentModel oppModel) {
|
---|
61 | this.negotiationSession = negoSession;
|
---|
62 | this.offeringStrategy = strat;
|
---|
63 | this.opponentModel = oppModel;
|
---|
64 | discountFactor = negotiationSession.getDiscountFactor();
|
---|
65 |
|
---|
66 | Serializable oldData = loadData();
|
---|
67 | if (oldData != null) {
|
---|
68 | SaveHelper prevData = (SaveHelper) oldData;
|
---|
69 | medianutil = prevData.getResult();
|
---|
70 | prevRes = prevData.getResult();
|
---|
71 | prevNegos = prevData.getNumber();
|
---|
72 | realmedian = false;
|
---|
73 | }
|
---|
74 | }
|
---|
75 |
|
---|
76 | /**
|
---|
77 | * Initialization function.
|
---|
78 | *
|
---|
79 | * Does the same as the regular constructor.
|
---|
80 | */
|
---|
81 | @Override
|
---|
82 | public void init(NegotiationSession negoSession, OfferingStrategy strat, OpponentModel oppModel,
|
---|
83 | Map<String, Double> parameters) throws Exception {
|
---|
84 | this.negotiationSession = negoSession;
|
---|
85 | this.offeringStrategy = strat;
|
---|
86 | this.opponentModel = oppModel;
|
---|
87 | discountFactor = negotiationSession.getDiscountFactor();
|
---|
88 | if (discountFactor == 0.0) {
|
---|
89 | discountFactor = 1.0;
|
---|
90 | }
|
---|
91 |
|
---|
92 | Serializable oldData = loadData();
|
---|
93 | if (oldData != null) {
|
---|
94 | SaveHelper prevData = (SaveHelper) oldData;
|
---|
95 | medianutil = prevData.getResult();
|
---|
96 | prevRes = prevData.getResult();
|
---|
97 | prevNegos = prevData.getNumber();
|
---|
98 | realmedian = false;
|
---|
99 | }
|
---|
100 | }
|
---|
101 |
|
---|
102 | /**
|
---|
103 | * Method which returns the action selected by this acceptance strategy.
|
---|
104 | */
|
---|
105 | @Override
|
---|
106 | public Actions determineAcceptability() {
|
---|
107 | // Determine the median if required
|
---|
108 | if (!medianDecided || (roundsLeft <= 4 && !realmedian)) {
|
---|
109 | SortedOutcomeSpace outcomespace = new SortedOutcomeSpace(negotiationSession.getUtilitySpace());
|
---|
110 | int opplocation = outcomespace.getIndexOfBidNearUtility(
|
---|
111 | negotiationSession.getOpponentBidHistory().getFirstBidDetails().getMyUndiscountedUtil());
|
---|
112 | List<BidDetails> alloutcomes = outcomespace.getAllOutcomes();
|
---|
113 | medianutil = alloutcomes.get((int) Math.floor(((double) opplocation) / 2)).getMyUndiscountedUtil();
|
---|
114 | medianDecided = true;
|
---|
115 | }
|
---|
116 |
|
---|
117 | // Read time and receiveMessage round estimation
|
---|
118 | double time = negotiationSession.getTime();
|
---|
119 | updateRoundsLeft(time);
|
---|
120 |
|
---|
121 | // Determine utility of our worst bid
|
---|
122 | double nextMyBidUtil = 1.0;
|
---|
123 | if (negotiationSession.getOwnBidHistory().getWorstBidDetails() != null) {
|
---|
124 | nextMyBidUtil = negotiationSession
|
---|
125 | .getDiscountedUtility(negotiationSession.getOwnBidHistory().getWorstBidDetails().getBid(), time);
|
---|
126 | }
|
---|
127 |
|
---|
128 | // Determine utility of the opponent bid to be evaluated
|
---|
129 | double lastOpponentBidUtil = negotiationSession
|
---|
130 | .getDiscountedUtility(negotiationSession.getOpponentBidHistory().getLastBid(), time);
|
---|
131 |
|
---|
132 | // Break if we are making an offer that is worse than the reservation
|
---|
133 | // value
|
---|
134 | if (nextMyBidUtil < negotiationSession.getUtilitySpace().getReservationValueWithDiscount(time)) {
|
---|
135 | return Actions.Break;
|
---|
136 | // Accept if the opponents offer is better than the one we are about
|
---|
137 | // to make (or very close to it in discounted domains)
|
---|
138 | } else if (nextMyBidUtil <= lastOpponentBidUtil + 0.05 * (1 - discountFactor)) {
|
---|
139 | return Actions.Accept;
|
---|
140 | // Accept if the opponents offer is better than the utility from
|
---|
141 | // acceptUtil()
|
---|
142 | } else if (lastOpponentBidUtil >= acceptUtil(time)) {
|
---|
143 | return Actions.Accept;
|
---|
144 | // Break if the reservation value appears to be more attractive than
|
---|
145 | // continuing negotiation
|
---|
146 | } else if (!realmedian && medianutil * Math.pow(discountFactor, time) < negotiationSession.getUtilitySpace()
|
---|
147 | .getReservationValueUndiscounted()) {
|
---|
148 | return Actions.Break;
|
---|
149 | }
|
---|
150 | // Reject and make our own offer if none of the above conditions were
|
---|
151 | // fulfilled
|
---|
152 | return Actions.Reject;
|
---|
153 | }
|
---|
154 |
|
---|
155 | /**
|
---|
156 | * Method that returns the minimal utility at which we accept an opponents
|
---|
157 | * offer. The function used depends on time and the opponents best
|
---|
158 | * discounted offer.
|
---|
159 | *
|
---|
160 | * @param t
|
---|
161 | * Normalized current time in the negotiation
|
---|
162 | */
|
---|
163 | public double acceptUtil(double t) {
|
---|
164 | double finalVal = negotiationSession.getDiscountedUtility(negotiationSession.getOpponentBidHistory()
|
---|
165 | .getBestDiscountedBidDetails(negotiationSession.getUtilitySpace()).getBid(), t);
|
---|
166 | finalVal = Math.max(Math.max(finalVal, negotiationSession.getUtilitySpace().getReservationValueWithDiscount(t)),
|
---|
167 | medianutil * Math.pow(discountFactor, t));
|
---|
168 |
|
---|
169 | if (roundsLeft < 8) {
|
---|
170 | return finalVal;
|
---|
171 | }
|
---|
172 | double startVal = Math.pow(discountFactor, t);
|
---|
173 | double power = 27;
|
---|
174 | if (discountFactor != 1.0) {
|
---|
175 | power = power * 0.3 * discountFactor;
|
---|
176 | }
|
---|
177 | double ut = startVal - (startVal - (finalVal)) * Math.pow(t, power);
|
---|
178 | return ut;
|
---|
179 | }
|
---|
180 |
|
---|
181 | /**
|
---|
182 | * Method used to estimate the number of rounds that are left by using the
|
---|
183 | * time between iteration for the last 10 rounds.
|
---|
184 | */
|
---|
185 | private void updateRoundsLeft(double t) {
|
---|
186 | timeList.add(t - lastTime);
|
---|
187 | lastTime = t;
|
---|
188 | if (timeList.size() >= 10) {
|
---|
189 | if (timeList.size() > 10) {
|
---|
190 | timeList.remove(0);
|
---|
191 | }
|
---|
192 |
|
---|
193 | double sum = 0;
|
---|
194 | for (int i = 0; i < timeList.size(); i++) {
|
---|
195 | sum += timeList.get(i);
|
---|
196 | }
|
---|
197 | roundsLeft = (int) ((1 - t) * timeList.size() / sum);
|
---|
198 | }
|
---|
199 | }
|
---|
200 |
|
---|
201 | /**
|
---|
202 | * Method used for saving results between sessions.
|
---|
203 | */
|
---|
204 | public void endNegotiation(NegotiationResult result) {
|
---|
205 | if (result.isAgreement()) {
|
---|
206 | double saveRes = (prevRes * prevNegos + result.getMyDiscountedUtility()) / (prevNegos + 1);
|
---|
207 | storeData(new SaveHelper(saveRes, prevNegos + 1));
|
---|
208 | } else {
|
---|
209 | double saveRes = (prevRes * prevNegos + medianutil) / (prevNegos + 1);
|
---|
210 | storeData(new SaveHelper(saveRes, prevNegos + 1));
|
---|
211 | }
|
---|
212 | }
|
---|
213 |
|
---|
214 | @Override
|
---|
215 | public String getName() {
|
---|
216 | return "2013 - InoxAgent";
|
---|
217 | }
|
---|
218 | } |
---|