source: src/main/java/agents/anac/y2018/ateamagent/ATeamAgent.java@ 346

Last change on this file since 346 was 345, checked in by Tim Baarslag, 4 years ago

Fixed agent 2018 descriptions

File size: 12.9 KB
Line 
1package agents.anac.y2018.ateamagent;
2
3import java.util.List;
4
5import java.util.ArrayList;
6import java.util.Comparator;
7import java.util.HashMap;
8import java.util.Iterator;
9import java.util.LinkedList;
10import java.util.Map;
11import java.util.TreeMap;
12import java.util.TreeSet;
13
14import genius.core.AgentID;
15import genius.core.Bid;
16import genius.core.Domain;
17import genius.core.actions.Accept;
18import genius.core.actions.Action;
19import genius.core.actions.Offer;
20import genius.core.issue.Issue;
21import genius.core.issue.Value;
22import genius.core.parties.AbstractNegotiationParty;
23import genius.core.parties.NegotiationInfo;
24
25class OpponentBidEvaluator
26{
27 private Map<String, List<Bid>> bidsPerOpponent;
28
29 public OpponentBidEvaluator()
30 {
31 bidsPerOpponent = new TreeMap<String, List<Bid>>();
32 }
33
34 public void registerBid(AgentID agentId, Bid bid)
35 {
36 String agentName = agentId.toString();
37 if (bidsPerOpponent.containsKey(agentName)==false)
38 {
39 bidsPerOpponent.put(agentName, new LinkedList<>());
40 }
41 bidsPerOpponent.get(agentName).add(bid);
42 }
43
44 public Double EstimateBidUtility(AgentID agentID, Bid bid){
45
46 List<Double> estimateBidIssues = EstimateBid(agentID,bid);
47 int numIssues = estimateBidIssues.size();
48 Double totalValue = 0.0;
49 for (int issueIndex = 0; issueIndex < numIssues; issueIndex++)
50 totalValue += estimateBidIssues.get(issueIndex);
51
52 // return avarage issues value
53 return totalValue/numIssues;
54
55 }
56
57
58 public List<Double> EstimateBid(AgentID agentID, Bid bid)
59 {
60 String agentName;
61 if (agentID == null)
62 {
63 agentName = (String)bidsPerOpponent.keySet().toArray()[0];
64 }
65 else
66 {
67 agentName = agentID.toString();
68 }
69
70 List<Bid> previousBids = this.bidsPerOpponent.get(agentName);
71 int numPrevBids = previousBids.size();
72 int numIssues = bid.getIssues().size();
73 List<Double> bidPercentages = new ArrayList<Double>(numIssues);
74 for (int issueIndex = 1; issueIndex <= numIssues; ++issueIndex) {
75 int count = 0;
76 Value bidIssueValue = bid.getValue(issueIndex);
77 // Cycle through previous bids and check percentage
78 for (int prevBidIndex = 0; prevBidIndex < numPrevBids; ++prevBidIndex) {
79 String prevBidValue = previousBids.get(prevBidIndex).getValue(issueIndex).toString();
80 if (prevBidValue.equals(bidIssueValue.toString())) {
81 ++count;
82 }
83 }
84 bidPercentages.add(1.0 * count / numPrevBids);
85 }
86 return bidPercentages;
87 }
88}
89public class ATeamAgent extends AbstractNegotiationParty {
90 private final String description = "anac2018/ateamagent";
91 private OpponentBidEvaluator opponentBidEvaluator;
92 private Bid lastReceivedOffer; // offer on the table
93 private Bid previousOffer;
94 private Bid myLastOffer;
95 private Bid lastBidGeneratedByMe;
96
97 private double timeInterval = 0.0D;
98 private double threshold = 1.0;
99
100 private int HISTORY_SAVE = 5;
101
102 private List<Bid> history; // last K bids
103
104 TreeMap<Bid, Double> allpossbids;
105
106 @Override
107 public void init(NegotiationInfo info) {
108 super.init(info);
109
110 GenerteAllSortedBids();
111 history = new LinkedList<Bid>();
112 lastReceivedOffer = null; // offer on the table
113 previousOffer = null;
114 myLastOffer = null;
115 lastBidGeneratedByMe = getMaxUtilityBid();
116 opponentBidEvaluator = new OpponentBidEvaluator();
117
118 }
119
120 private void GenerteAllSortedBids(){
121
122 Map<Bid, Double> random = new HashMap<Bid, Double>();
123 allpossbids = new TreeMap<Bid, Double>(new BidUtilComparator(random));
124
125 int i;
126 //generate all possible bids
127 for (i =0 ; i < this.utilitySpace.getDomain().getNumberOfPossibleBids(); i++)
128 {
129 Bid newbid = null;
130 do {
131 newbid = generateRandomBid();}
132 while (random.containsKey(newbid));
133 random.put(newbid, this.getUtility(newbid));
134 allpossbids.put(newbid, this.getUtility(newbid));
135 }
136
137 }
138
139 private int check_commom_issues(Bid newbid, HashMap<Integer, Value> bidvalues) //returns list of values, with the common
140 {
141 Domain d = this.utilitySpace.getDomain();
142 List<Issue> issues = d.getIssues();
143
144 int commonissues = 0;
145
146 if (!issues.isEmpty() && previousOffer != null) {
147
148 Iterator var5 = issues.iterator();
149
150 while (var5.hasNext()) {
151 Issue issue = (Issue) var5.next();
152
153 if (newbid.getValue(issue.getNumber()) == previousOffer.getValue(issue.getNumber())) {
154 commonissues++;
155 bidvalues.put(issue.getNumber(), newbid.getValue(issue.getNumber()));
156 }
157 }
158 }
159 return commonissues;
160 }
161
162
163 // generate next bid -
164 // what can we learn from agent history? we know which offer it accepted at time t. so we can offer that
165 // same offer at time t and it would accept, but before time t we can try bids that are with lower util for him.
166 // can we tell the opponents util??
167
168 //if the issue isnt already in the bd, get the best value for it.
169
170 private Bid improve_common_bid(HashMap<Integer, Value> common_issues) {
171
172 TreeSet <Bid> bidset = new TreeSet<Bid>(allpossbids.descendingKeySet());
173
174 Iterator iterator;
175 iterator = bidset.iterator();
176
177 while (iterator.hasNext()) {
178 Bid newbid = (Bid)iterator.next();
179 if(is_common(newbid,common_issues)&& (this.getUtility(newbid) > this.getUtility(lastReceivedOffer)) )
180 return newbid;
181 }
182
183 return null;
184 }
185
186 private boolean is_common(Bid a, HashMap<Integer, Value> common_issues)
187 {
188 Domain d = this.utilitySpace.getDomain();
189 List<Issue> issues = d.getIssues();
190
191 Bid bid = null;
192
193 for (Issue lIssue : issues) {
194 if((common_issues.containsKey(lIssue.getNumber())) && a.getValue(lIssue.getNumber())
195 != common_issues.get(lIssue.getNumber()))
196 return false;
197 }
198
199 return true;
200 }
201
202 private Bid generateMyNextBid(HashMap<Integer, Value> bidvalues) {
203
204 Bid bid = null;
205
206 // allow the upper 10% of the sorted bids we have left to see if any gives good estimation for opponent utility
207 int max_tries = (int)(0.1 * allpossbids.size());
208
209 if (allpossbids.size() > 1)
210 {
211 bid = allpossbids.lastKey();
212 //walk from best to worst bid, and estimate if the probability that the opponent will accept this bid is bigger than 0.5
213 boolean lookForBetter = true;
214 Bid testBid = bid;
215 while (lookForBetter & (testBid != null ) && max_tries > 0) {
216 // Estimate opponent utility based on past bid
217 if (opponentBidEvaluator.EstimateBidUtility(null, testBid) < 0.5f) {
218 testBid = allpossbids.lowerKey(testBid);
219 --max_tries;
220 }
221 else {
222 // test bid seems good for opponent (>0.5 estimated utility)
223 // suggest this bid
224 bid = testBid;
225 lookForBetter = false;
226 }
227 }
228
229 lastBidGeneratedByMe = bid;
230 allpossbids.remove(bid);
231
232 }
233 else if (allpossbids.size() == 1)
234 {
235 bid = this.getMaxUtilityBid();
236 lastBidGeneratedByMe = bid;
237 }
238
239 return bid;
240 }
241
242 /**
243 * When this function is called, it is expected that the Party chooses one of the actions from the possible
244 * action list and returns an instance of the chosen action.
245 *
246 * @param list
247 * @return
248 */
249 @Override
250 public Action chooseAction(List<Class<? extends Action>> list) {
251 // According to Stacked Alternating Offers Protocol list includes
252 // Accept, Offer and EndNegotiation actions only.
253 double time = getTimeLine().getTime(); // Gets the time, running from t = 0 (start) to t = 1 (deadline).
254
255 // Update thresold
256 threshold = this.getUtilityWithDiscount(getMaxUtilityBid()) * 0.8;
257 // Get the time interval so we can estimate next best bid
258 if (timeInterval == 0 && time > 0)
259 {
260 timeInterval = time;
261 }
262
263 // for the first 0.5 of the time suggest max bid.
264 // we either get what we want or get bids from opponent so we can learn estimated utility
265 if (lastReceivedOffer == null || time < 0.5) {
266
267 Bid bestBid = this.getMaxUtilityBid();
268 return new Offer(this.getPartyId(), this.getMaxUtilityBid());
269 }
270
271 if (lastReceivedOffer != null
272 && myLastOffer != null
273 && isAcceptable(lastReceivedOffer, time)) {
274 // Accepts the bid on the table in this phase,
275 // if the utility of the bid is higher than Example Agent's last bid.
276 return new Accept(this.getPartyId(), lastReceivedOffer);
277 }
278 else
279 {
280 HashMap<Integer, Value> bidcommonvalues = new HashMap<Integer, Value>();
281 if (check_commom_issues(lastReceivedOffer, bidcommonvalues) > 0) //returns list of values, with the common
282 {
283 //add our values in issues that are not common
284 //check bid not in history
285 myLastOffer = improve_common_bid(bidcommonvalues);
286 if (myLastOffer == null)
287 myLastOffer = generateMyNextBid(bidcommonvalues);
288 else if (!isAcceptable(myLastOffer, time)) //the threshold
289 myLastOffer = generateMyNextBid(bidcommonvalues);
290
291 //List<Double> estimate = opponentBidEvaluator.EstimateBid(null, myLastOffer);
292 return new Offer(this.getPartyId(), myLastOffer);
293 } else {
294 //no common issues - check if bid is good and if so accept
295 //else generate my new bid
296 //this takes into considreration reservation value, discount factor and the time passed
297 myLastOffer = generateMyNextBid(bidcommonvalues);
298 return new Offer(this.getPartyId(), myLastOffer);
299 }
300 }
301
302 }
303
304 private boolean isBetterThanNextTurnBest(Bid bid)
305 {
306 double bidUtility = this.utilitySpace.getUtilityWithDiscount(bid, this.getTimeLine());
307 double nextTimeFrame = this.getTimeLine().getTime() + this.timeInterval;
308 Bid bestBid = this.getMaxUtilityBid();
309 double nextBestUtility = this.utilitySpace.getUtilityWithDiscount(bestBid, nextTimeFrame);
310 return bidUtility > nextBestUtility;
311 }
312 private boolean isAcceptable(Bid bid, double time) {
313 double lastOfferUtility = this.utilitySpace.getUtilityWithDiscount(bid, time);
314 double minimalReasonableUtility = this.utilitySpace.getReservationValue();
315 double myLastOfferUtility = this.utilitySpace.getUtilityWithDiscount(myLastOffer, time);
316 if (minimalReasonableUtility < lastOfferUtility && // is rational
317 (lastOfferUtility > myLastOfferUtility || // better than my last offer
318 isBetterThanNextTurnBest(lastReceivedOffer))) {
319 return true;
320 }
321 else {
322 return false;
323 }
324
325 }
326
327 private void addHistory(Bid newbid) {
328 if (history.size() <= HISTORY_SAVE) {
329 history.add(newbid);
330 history.remove(0);
331 } else
332 history.add(newbid);
333 }
334
335
336 /**
337 * This method is called to inform the party that another NegotiationParty chose an Action.
338 *
339 * @param sender
340 * @param act
341 */
342 @Override
343 public void receiveMessage(AgentID sender, Action act) {
344 super.receiveMessage(sender, act);
345
346 if (act instanceof Offer) { // sender is making an offer
347 Offer offer = (Offer) act;
348
349 previousOffer = lastReceivedOffer;
350 // storing last received offer
351 lastReceivedOffer = offer.getBid();
352 addHistory(offer.getBid());
353 opponentBidEvaluator.registerBid(sender, ((Offer) act).getBid());
354 }
355 }
356
357 /**
358 * A human-readable description for this party.
359 *
360 * @return
361 */
362 @Override
363 public String getDescription() {
364 return "ANAC2018";
365 }
366
367 private Bid getMaxUtilityBid() {
368 try {
369 return this.utilitySpace.getMaxUtilityBid();
370 } catch (Exception e) {
371 e.printStackTrace();
372 }
373 return null;
374 }
375
376//end of class
377
378}
379
380class BidUtilComparator implements Comparator<Bid> {
381
382 private Map<Bid, Double> map;
383
384 public BidUtilComparator(Map<Bid, Double> map) {
385 this.map = map;
386 }
387
388 @Override
389 public int compare(Bid a, Bid b) {
390 return (map.get(a).compareTo(map.get(b)));
391 }
392}
Note: See TracBrowser for help on using the repository browser.