source: src/main/java/negotiator/boaframework/sharedagentstate/anac2011/TheNegotiatorSAS.java

Last change on this file was 127, checked in by Wouter Pasman, 6 years ago

#41 ROLL BACK of rev.126 . So this version is equal to rev. 125

File size: 10.3 KB
Line 
1package negotiator.boaframework.sharedagentstate.anac2011;
2
3import java.util.ArrayList;
4import java.util.Arrays;
5import java.util.Collections;
6import java.util.HashMap;
7import java.util.List;
8
9import genius.core.Bid;
10import genius.core.bidding.BidDetails;
11import genius.core.bidding.BidDetailsStrictSorterUtility;
12import genius.core.boaframework.NegotiationSession;
13import genius.core.boaframework.SharedAgentState;
14import genius.core.issue.Issue;
15import genius.core.issue.IssueDiscrete;
16import genius.core.issue.Value;
17import genius.core.issue.ValueDiscrete;
18import genius.core.misc.Pair;
19import genius.core.misc.Queue;
20
21/**
22 * This is the shared code of the acceptance condition and bidding strategy of
23 * ANAC 2011 TheNegotiator. The code was taken from the ANAC2011 TheNegotiator
24 * and adapted to work within the BOA framework.
25 *
26 * @author Mark Hendrikx
27 */
28public class TheNegotiatorSAS extends SharedAgentState {
29
30 private final boolean TEST_EQUIVALENCE = false;
31
32 private NegotiationSession negotiationSession;
33
34 private final double totalTime = 180;
35 private final double[] endPhases1 = { 140.0 / totalTime, 35.0 / totalTime,
36 5.0 / totalTime };
37 private double[] endPhases2;
38 private double[] maxThresArray1;
39 private double[] maxThresArray2;
40 private int propArray[];
41 private ArrayList<BidDetails> possibleBids;
42
43 // queue holding last 30 lapsed time
44 private Queue queue = new Queue();
45 private double lastTime;
46 // queue size
47 private int queueSize;
48 private double discount;
49
50 private int phase;
51 private double threshold;
52 private int movesLeft;
53
54 public TheNegotiatorSAS(NegotiationSession negoSession) {
55 negotiationSession = negoSession;
56 NAME = "TheNegotiator";
57 possibleBids = new ArrayList<BidDetails>();
58 createAllBids();
59 if (TEST_EQUIVALENCE) {
60 Collections.sort(possibleBids, new BidDetailsStrictSorterUtility());
61 } else {
62 Collections.sort(possibleBids);
63 }
64
65 endPhases2 = new double[3];
66 Arrays.fill(endPhases2, 0);
67
68 maxThresArray1 = new double[4];
69 Arrays.fill(maxThresArray1, 0);
70
71 maxThresArray2 = new double[4];
72 Arrays.fill(maxThresArray2, 0);
73
74 propArray = new int[3];
75 Arrays.fill(propArray, 0);
76
77 queueSize = 15;
78 lastTime = 0;
79 discount = negoSession.getDiscountFactor();
80
81 // no discounts
82 calculateEndPhaseThresholds();
83
84 // discounts
85 if (negotiationSession.getDiscountFactor() != 0) {
86 calculatePropArray();
87 calculateEndPhases();
88 }
89 }
90
91 public ArrayList<BidDetails> getPossibleBids() {
92 return possibleBids;
93 }
94
95 /**
96 * Calculates the time which should be spend on each phase based on the
97 * distribution of the utilities of the bids.
98 */
99 public void calculateEndPhases() {
100 int sum = 0;
101 for (int i = 0; i < propArray.length; i++) {
102 sum += propArray[i];
103 }
104
105 endPhases2[0] = discount
106 + (((double) propArray[0] / (double) sum) * (1 - discount));
107 endPhases2[1] = (((double) propArray[1] / (double) sum) * (1 - discount));
108 endPhases2[2] = (((double) propArray[2] / (double) sum) * (1 - discount));
109 }
110
111 /**
112 * Returns the current phase of the negotiation.
113 *
114 * @return phase of the negotiation
115 */
116 public int calculateCurrentPhase(double time) {
117
118 int phase = 1;
119 double[] endPhases = endPhases1;
120
121 if (discount != 0 && time > discount) {
122 endPhases = endPhases2;
123 }
124
125 if (time > (endPhases[1] + endPhases[0])) {
126 double lapsedTime = time - lastTime;
127 queue.enqueue(lapsedTime);
128 if (queue.size() > queueSize) {
129 queue.dequeue();
130 }
131 phase = 3;
132 } else if (time > endPhases[0]) {
133 phase = 2;
134 }
135 lastTime = time;
136
137 this.phase = phase;
138 return phase;
139 }
140
141 /**
142 * Returns the time dependent threshold which specifies how good a bid of an
143 * opponent should be to be accepted. This threshold is also used as a
144 * minimum for the utility of the bid of our agent.
145 *
146 * @return threshold
147 */
148 public double calculateThreshold(double time) {
149 int phase = calculateCurrentPhase(time);
150 double threshold = 0.98; // safe value
151 double[] maxThresArray = maxThresArray1;
152 double[] endPhases = endPhases1;
153
154 if (discount != 0 && time > discount) {
155 maxThresArray = maxThresArray2;
156 endPhases = endPhases2;
157 }
158 double discountActive = discount;
159 if (time <= discount) {
160 discountActive = 0;
161 }
162
163 switch (phase) {
164 case 1:
165 threshold = maxThresArray[0]
166 - ((time - discountActive) / (endPhases[0] - discountActive))
167 * (maxThresArray[0] - maxThresArray[1]);
168 break;
169 case 2:
170 threshold = maxThresArray[1]
171 - (((time - endPhases[0]) / (endPhases[1])) * (maxThresArray[1] - maxThresArray[2]));
172 break;
173 case 3:
174 threshold = maxThresArray[2]
175 - (((time - endPhases[0] - endPhases[1]) / (endPhases[2])) * (maxThresArray[2] - maxThresArray[3]));
176 break;
177 }
178 this.threshold = threshold;
179 return threshold;
180 }
181
182 public int calculateMovesLeft() {
183 int movesLeft = -1;
184
185 if (queue.isEmpty()) {
186 movesLeft = 500; // to avoid an error
187 } else {
188 Double[] lapsedTimes = queue.toArray();
189 double total = 0;
190 for (int i = 0; i < queueSize; i++) {
191 if (lapsedTimes[i] != null) {
192 total += lapsedTimes[i];
193 }
194 }
195 movesLeft = (int) Math.floor((1.0 - negotiationSession.getTime())
196 / (total / (double) queueSize));
197 }
198 this.movesLeft = movesLeft;
199 return movesLeft;
200 }
201
202 public void calculateEndPhaseThresholds() {
203 maxThresArray1[0] = possibleBids.get(0).getMyUndiscountedUtil();
204 int size = possibleBids.size();
205 maxThresArray1[3] = possibleBids.get(size - 1).getMyUndiscountedUtil();
206 double range = maxThresArray1[0] - maxThresArray1[3];
207 maxThresArray1[1] = maxThresArray1[0] - ((1.0 / 8) * range);
208 maxThresArray1[2] = maxThresArray1[0] - ((3.0 / 8) * range);
209 }
210
211 /**
212 * Calculate how many possible bids are within a certain threshold interval.
213 * This is done for all the bins (phases).
214 */
215 public void calculatePropArray() {
216 double max = calculateThreshold(discount); // 0.0001 is just to be sure
217 // :)
218 double min = possibleBids.get(possibleBids.size() - 1)
219 .getMyUndiscountedUtil();
220 double range = max - min;
221 double rangeStep = range / 3;
222
223 for (int i = 0; i < possibleBids.size(); i++) {
224 double util = possibleBids.get(i).getMyUndiscountedUtil();
225
226 // calculate if a utility of a bid is within a certain interval.
227 // Intervals should be calculated!!!!
228 if (util >= max - rangeStep && util <= max) {
229 propArray[0]++;
230 } else if (util >= max - 2 * rangeStep && util < max - rangeStep) {
231 propArray[1]++;
232 } else if (util >= max - 3 * rangeStep
233 && util < max - 2 * rangeStep) {
234 propArray[2]++;
235 }
236 }
237 // find the maximum possible utility within a bin (plus the lowest bid
238 // of the last bin)
239 maxThresArray2[0] = max;
240
241 if (propArray[0] == 0) {
242 maxThresArray2[1] = possibleBids.get(0).getMyUndiscountedUtil();
243 } else {
244 maxThresArray2[1] = possibleBids.get(propArray[0] - 1)
245 .getMyUndiscountedUtil(); // -1 to correct for array offset
246 // of zero
247 }
248
249 if (propArray[0] == 0 && propArray[1] == 0) {
250 maxThresArray2[2] = possibleBids.get(0).getMyUndiscountedUtil();
251
252 } else {
253 maxThresArray2[2] = possibleBids.get(
254 propArray[0] + propArray[1] - 1).getMyUndiscountedUtil();
255 }
256 maxThresArray2[3] = min;
257 }
258
259 public int[] getPropArray() {
260 return propArray;
261 }
262
263 public int getPhase() {
264 return phase;
265 }
266
267 public double getThreshold() {
268 return threshold;
269 }
270
271 public int getMovesLeft() {
272 return movesLeft;
273 }
274
275 /**
276 * Create all possible bids using a call to the recursive Cartestian product
277 * options generator.
278 */
279 private void createAllBids() {
280 List<Issue> issues = negotiationSession.getUtilitySpace().getDomain()
281 .getIssues();
282
283 ArrayList<IssueDiscrete> discreteIssues = new ArrayList<IssueDiscrete>();
284
285 for (Issue issue : issues) {
286 discreteIssues.add((IssueDiscrete) issue);
287 }
288
289 ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>> result = generateAllBids(
290 discreteIssues, 0);
291
292 for (ArrayList<Pair<Integer, ValueDiscrete>> bidSet : result) {
293 HashMap<Integer, Value> values = new HashMap<Integer, Value>();
294 for (Pair<Integer, ValueDiscrete> pair : bidSet) {
295 values.put(pair.getFirst(), pair.getSecond());
296 }
297 try {
298 Bid bid = new Bid(negotiationSession.getUtilitySpace()
299 .getDomain(), values);
300 double utility = negotiationSession.getUtilitySpace()
301 .getUtility(bid);
302 possibleBids.add(new BidDetails(bid, utility, -1.0));
303 } catch (Exception e) {
304 e.printStackTrace();
305 }
306 }
307 }
308
309 /**
310 * The recursive Cartestian product options generator. Generates all
311 * possible bids.
312 *
313 * @param issueList
314 * @param i
315 * , parameter used in the recursion
316 * @return a list of a list with pairs of integer (issue at stake) and a
317 * value (the chosen option)
318 */
319 private ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>> generateAllBids(
320 ArrayList<IssueDiscrete> issueList, int i) {
321
322 // stop condition
323 if (i == issueList.size()) {
324 // return a list with an empty list
325 ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>> result = new ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>>();
326 result.add(new ArrayList<Pair<Integer, ValueDiscrete>>());
327 return result;
328 }
329
330 ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>> result = new ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>>();
331 ArrayList<ArrayList<Pair<Integer, ValueDiscrete>>> recursive = generateAllBids(
332 issueList, i + 1); // recursive call
333
334 // for each element of the first list of input
335 for (int j = 0; j < issueList.get(i).getValues().size(); j++) {
336 // add the element to all combinations obtained for the rest of the
337 // lists
338 for (int k = 0; k < recursive.size(); k++) {
339 // copy a combination from recursive
340 ArrayList<Pair<Integer, ValueDiscrete>> newList = new ArrayList<Pair<Integer, ValueDiscrete>>();
341 for (Pair<Integer, ValueDiscrete> set : recursive.get(k)) {
342 newList.add(set);
343 }
344 // add element of the first list
345 ValueDiscrete value = issueList.get(i).getValues().get(j);
346 int issueNr = issueList.get(i).getNumber();
347 newList.add(new Pair<Integer, ValueDiscrete>(issueNr, value));
348
349 // add new combination to result
350 result.add(newList);
351 }
352 }
353 return result;
354 }
355}
Note: See TracBrowser for help on using the repository browser.