source: src/main/java/agents/anac/y2017/madagent/MadAgent.java@ 46

Last change on this file since 46 was 46, checked in by Tim Baarslag, 6 years ago

agents get their getUtilitySpace() from the API, not the info object anymore

File size: 9.8 KB
Line 
1package agents.anac.y2017.madagent;
2
3import java.util.List;
4
5import java.util.ArrayList;
6import java.util.Comparator;
7import java.util.HashMap;
8import java.util.Random;
9
10import genius.core.AgentID;
11import genius.core.Bid;
12import genius.core.actions.Accept;
13import genius.core.actions.Action;
14import genius.core.actions.Offer;
15import genius.core.boaframework.SortedOutcomeSpace;
16import genius.core.parties.AbstractNegotiationParty;
17import genius.core.parties.NegotiationInfo;
18import genius.core.persistent.PersistentDataType;
19
20public class MadAgent extends AbstractNegotiationParty {
21
22 private static final Random RANDOM = new Random();
23 private static final int MAXIMUM_NUMBER_OF_TRIALS = 2000;
24
25 /*
26 * -------------------------------- RISK FUNCTION
27 * -------------------------------- f <- Round number to fake (Agent will
28 * fake in every f rounds) c <- Risk constant p <- Risk parameter Formula ->
29 * f = c / 2 ^ p We choose 5 as our parameter because we want our agent to
30 * be both aggressive and defensive
31 */
32 private static final double RISK_CONSTANT = 100000;
33 private static final double RISK_PARAMETER = 5; // Risk Parameter: 0, 1, 2,
34 // ..., 8, 9, 10
35 private static final int ROUND_NUMBER_TO_FAKE = (int) (RISK_CONSTANT
36 / Math.pow(2, RISK_PARAMETER));
37
38 private SortedOutcomeSpace sortedOutcomeSpace = null;
39 private Bid lastReceivedBid = null;
40 private Bid bestReceivedBid = null;
41 private Bid secondBestBid = null;
42 private String negotiationType = null;
43 private double negotiationLimit = 0;
44 private double numberOfRoundsPassed = 0;
45 private double timeToGetAlmostMad = 0;
46 private double timeToGetMad = 0;
47 private double threshold = 0.8;
48 private double currentThreshold = 0.8;
49 /* Variables for Opponent Modeling */
50 private int opponentTurn = 0; // Value to keep track opponents
51 private int myTurn = 0; // Random value to choose one of the opponents and
52 // use its preferences while generating bid
53 private int shiftBids[] = null; // Index for bidsPreferredByOpponents for
54 // each opponent
55 private OpponentModel[] opponentModels = null; // Opponent Model for each
56 // opponent.
57 private List<List<Bid>> bidsPreferredByOpponents = null; // bidsPrefferredByOpponents
58 // for each
59 // opponent
60
61 @Override
62 public void init(NegotiationInfo info) {
63 super.init(info);
64
65 System.out.println("Discount Factor is "
66 + getUtilitySpace().getDiscountFactor());
67 System.out.println("Reservation Value is "
68 + getUtilitySpace().getReservationValueUndiscounted());
69
70 sortedOutcomeSpace = new SortedOutcomeSpace(utilitySpace);
71 threshold *= 1.125;
72
73 shiftBids = new int[3];
74 opponentModels = new OpponentModel[3];
75 bidsPreferredByOpponents = new ArrayList<List<Bid>>();
76
77 // Filling the array with empty values to avoid 'Null Pointer Exception'
78 for (int i = 0; i < 3; i++) {
79 opponentModels[i] = new OpponentModel(utilitySpace, threshold);
80 bidsPreferredByOpponents.add(null);
81 }
82
83 try {
84 bestReceivedBid = utilitySpace.getMinUtilityBid();
85 } catch (Exception e) {
86 System.err.println("An exception thrown at init..");
87 }
88
89 negotiationType = info.getDeadline().getType().toString();
90 negotiationLimit = info.getDeadline().getValue();
91
92 /* This values will be used for adapting threshold */
93 timeToGetMad = negotiationLimit * 0.8; // Agent gets mad in the last 20%
94 // of the negotiation
95 timeToGetAlmostMad = negotiationLimit * 0.5; // Agent gets almost mad in
96 // the last 50% of the
97 // negotiation
98
99 if (getData().getPersistentDataType() != PersistentDataType.STANDARD)
100 throw new IllegalStateException("need standard persistent data");
101
102 /* Agent calculates the second best bid */
103 try {
104 calculateSecondBestBid();
105 } catch (Exception e) {
106 System.err.println(
107 "An exception thrown while calculating the second best bid..");
108 }
109 }
110
111 private void calculateSecondBestBid() throws Exception {
112 for (double u = utilitySpace
113 .getUtility(utilitySpace.getMaxUtilityBid()); true; u -= 0.01) {
114 secondBestBid = sortedOutcomeSpace.getBidNearUtility(u).getBid();
115
116 if (utilitySpace.getUtility(secondBestBid) != utilitySpace
117 .getUtility(utilitySpace.getMaxUtilityBid()))
118 break;
119 }
120 }
121
122 @Override
123 public void receiveMessage(AgentID sender, Action action) { // ...
124 // Opponent's
125 // turn ...
126 super.receiveMessage(sender, action);
127
128 /*
129 * If the action is an Offer, get the last received bid and use it to
130 * form Opponent Model
131 */
132 if (action instanceof Offer) {
133 lastReceivedBid = ((Offer) action).getBid();
134
135 opponentModels[2].offer(lastReceivedBid, numberOfRoundsPassed);
136 opponentModels[opponentTurn++ % 2].offer(lastReceivedBid,
137 numberOfRoundsPassed);
138 }
139 }
140
141 @Override
142 public Action chooseAction(List<Class<? extends Action>> validActions) { // ...
143 // Your
144 // agent's
145 // turn
146 // ...
147 numberOfRoundsPassed++;
148
149 if (lastReceivedBid == null) { // You are the starter party, offer the
150 // best possible bid
151 return new Offer(getPartyId(), getBestBidPossible());
152 } else { // You are not the starter party
153 /* Determine the best received bid */
154 if (utilitySpace.getUtility(lastReceivedBid) > utilitySpace
155 .getUtility(bestReceivedBid))
156 bestReceivedBid = lastReceivedBid;
157
158 /*
159 * If utility of the last received bid is higher than the threshold,
160 * accept the offer.
161 */
162 /* Else, offer a new bid. */
163 if (utilitySpace.getUtility(lastReceivedBid) > currentThreshold)
164 return new Accept(getPartyId(), lastReceivedBid);
165 else
166 return new Offer(getPartyId(), getBestBidPossible());
167 }
168 }
169
170 private Bid getBestBidPossible() {
171 try {
172 double currentStatus = getCurrentStatus();
173
174 if (currentStatus <= negotiationLimit * 0.05) { // First 5% of the
175 // negotiation
176 return secondBestBid;
177 } else if ((int) numberOfRoundsPassed % ROUND_NUMBER_TO_FAKE <= 10
178 && currentStatus <= negotiationLimit * 0.9) {
179 return getFakeBid();
180 } else {
181 myTurn = RANDOM.nextInt(3); // Generate random value among {0,
182 // 1, 2}
183 calculateCurrentThreshold(currentStatus);
184
185 if (currentStatus > negotiationLimit * 0.99 && utilitySpace
186 .getUtility(bestReceivedBid) >= currentThreshold)
187 return bestReceivedBid;
188 else
189 return getNiceBid(currentStatus);
190 }
191 } catch (Exception e) {
192 System.err.println("An exception thrown while generating bid..");
193 }
194
195 return generateRandomBid(); // This line will never be executed!!
196 }
197
198 /* Current status is the time/number of rounds passed */
199 private double getCurrentStatus() {
200 /* If the negotiation is time limited, use time as current status */
201 if (negotiationType.equals("TIME"))
202 return timeline.getTime() * timeline.getTotalTime();
203
204 /*
205 * If the negotiation is round limited, use number of rounds as current
206 * status
207 */
208 return numberOfRoundsPassed;
209 }
210
211 /*
212 * At first 90% of negotiation, agent generates a random bid to fake his
213 * opponent with certain frequency
214 */
215 private Bid getFakeBid() {
216 for (int trial = 1; trial <= MAXIMUM_NUMBER_OF_TRIALS; trial++) {
217 Bid bid = generateRandomBid();
218
219 /*
220 * The utility of the bid should be greater than 80% of the
221 * threshold
222 */
223 if (utilitySpace.getUtility(bid) >= threshold * 0.8)
224 return bid;
225 }
226
227 return generateRandomBid();
228 }
229
230 private void calculateCurrentThreshold(double currentStatus) {
231 /* Threshold value is updated according to the agent's boulware level */
232 threshold = opponentModels[myTurn].getNewThreshold();
233
234 if (numberOfRoundsPassed % 10 == 0) {
235 currentThreshold = threshold;
236 } else if (currentStatus > timeToGetAlmostMad) {
237 currentThreshold = threshold * 0.95;
238
239 if (currentStatus > timeToGetMad)
240 currentThreshold = threshold * 0.9;
241 }
242 }
243
244 /* Get a nice bid using Opponent Model */
245 private Bid getNiceBid(double currentStatus) throws Exception {
246 Bid bid = generateRandomBid();
247
248 /*
249 * Shift Bids is for shifting the index if the bid at the current index
250 * is not accepted by opponent
251 */
252 if (currentStatus > timeToGetAlmostMad) {
253 getBidsPreferredByOpponent();
254 bid = (bidsPreferredByOpponents.get(myTurn) != null)
255 ? bidsPreferredByOpponents.get(myTurn)
256 .get(shiftBids[myTurn]++ % bidsPreferredByOpponents
257 .get(myTurn).size())
258 : utilitySpace.getMaxUtilityBid();
259
260 if (utilitySpace.getUtility(bid) >= currentThreshold)
261 return bid;
262 else
263 shiftBids[myTurn] = 0;
264 }
265
266 for (int trial = 1; trial <= MAXIMUM_NUMBER_OF_TRIALS; trial++) {
267 bid = generateRandomBid();
268
269 if (utilitySpace.getUtility(bid) >= currentThreshold)
270 return bid;
271 }
272
273 /*
274 * If it cannot generate a random bid higher than current threshold in
275 * the maximum number of trials, it returns max utility bid
276 */
277 return utilitySpace.getMaxUtilityBid();
278 }
279
280 private void getBidsPreferredByOpponent() throws Exception {
281 opponentModels[myTurn].computeMostPreferredBid();
282
283 bidsPreferredByOpponents.set(myTurn, null);
284 bidsPreferredByOpponents.set(myTurn,
285 opponentModels[myTurn].getAcceptableBids());
286
287 sortBids(bidsPreferredByOpponents.get(myTurn));
288
289 /* If there is no element in the list, just add one */
290 if (bidsPreferredByOpponents.get(myTurn).size() == 0)
291 bidsPreferredByOpponents.get(myTurn)
292 .add(utilitySpace.getMaxUtilityBid());
293 }
294
295 private void sortBids(List<Bid> bids) {
296 bids.sort(new Comparator<Bid>() {
297 @Override
298 public int compare(Bid a, Bid b) {
299 if (utilitySpace.getUtility(a) < utilitySpace.getUtility(b))
300 return 1;
301 if (utilitySpace.getUtility(a) > utilitySpace.getUtility(b))
302 return -1;
303
304 return 0;
305 }
306 });
307 }
308
309 @Override
310 public String getDescription() {
311 return "ANAC2017";
312 }
313
314 @Override
315 public HashMap<String, String> negotiationEnded(Bid acceptedBid) {
316 System.out.println("Negotiation has ended..");
317 return null;
318 }
319}
Note: See TracBrowser for help on using the repository browser.