source: anac2020/ShineAgent/src/main/java/shineagent/ShineParty.java@ 1

Last change on this file since 1 was 1, checked in by wouter, 4 years ago

#1910 added anac2020 parties

File size: 10.0 KB
Line 
1package shineagent;
2import geniusweb.issuevalue.*;
3import java.io.IOException;
4import java.math.BigInteger;
5import java.util.*;
6import java.util.logging.*;
7
8import geniusweb.actions.Accept;
9import geniusweb.actions.Action;
10import geniusweb.actions.Comparison;
11import geniusweb.actions.ElicitComparison;
12import geniusweb.actions.Offer;
13import geniusweb.actions.PartyId;
14import geniusweb.bidspace.AllBidsList;
15import geniusweb.party.Capabilities;
16import geniusweb.party.DefaultParty;
17import geniusweb.party.inform.ActionDone;
18import geniusweb.party.inform.Finished;
19import geniusweb.party.inform.Inform;
20import geniusweb.party.inform.Settings;
21import geniusweb.party.inform.YourTurn;
22import geniusweb.profileconnection.ProfileConnectionFactory;
23import geniusweb.profileconnection.ProfileInterface;
24import geniusweb.progress.Progress;
25import geniusweb.progress.ProgressRounds;
26import tudelft.utilities.logging.Reporter;
27
28/**
29 * Shine Agent Main Class
30 */
31public class ShineParty extends DefaultParty {
32 private static final double acceptQualityThreshold = 0.85;
33 private static final double acceptQualityThresholdMin = 0.55;
34 private static final double acceptDistanceThreshold = 0.15;
35 private static final double newOfferDistanceThreshold = 0.15;
36 private static final int numberOfTurnsToElicit = 1;
37 private Bid lastReceivedBid = null; // we ignore all others
38 private PartyId me;
39 private final Random random = new Random();
40 protected ProfileInterface profileint;
41 private Progress progress;
42 private SimpleLinearOrdering myEstimatedProfile = null;
43 private SimpleLinearOrdering opponentEstimatedProfile = null;
44 //private IssueCounter opponentIssueCounter = null;
45 private Bid reservationBid = null;
46 private int turnsWithElicitPassed = 0;
47
48
49 public ShineParty() {
50 }
51
52 public ShineParty(Reporter reporter) {
53 super(reporter); // for debugging
54 }
55
56 @Override
57 public void notifyChange(Inform info) {
58 try {
59 if (info instanceof Settings) {
60 Settings settings = (Settings) info;
61 this.profileint = ProfileConnectionFactory
62 .create(settings.getProfile().getURI(), getReporter());
63 this.me = settings.getID();
64 this.progress = settings.getProgress();
65 } else if (info instanceof ActionDone) {
66 Action otheract = ((ActionDone) info).getAction();
67 if (otheract instanceof Offer) {
68 lastReceivedBid = ((Offer) otheract).getBid();
69 } else if (otheract instanceof Comparison) {
70 myEstimatedProfile = myEstimatedProfile.with(
71 ((Comparison) otheract).getBid(),
72 ((Comparison) otheract).getWorse());
73 myTurn();
74 }
75 } else if (info instanceof YourTurn) {
76 myTurn();
77 } else if (info instanceof Finished) {
78 getReporter().log(Level.INFO, "Final ourcome:" + info);
79 }
80 } catch (Exception e) {
81 throw new RuntimeException("Failed to handle info", e);
82 }
83 }
84
85 @Override
86 public Capabilities getCapabilities() {
87 return new Capabilities(new HashSet<>(Arrays.asList("SHAOP")));
88 }
89
90 @Override
91 public String getDescription() {
92 return "Shine Agent :)";
93 }
94
95 /**
96 * Called when it's (still) our turn and we should take some action. Also
97 * Updates the progress if necessary.
98 */
99 private void myTurn() throws IOException {
100 Action action = null;
101 if (myEstimatedProfile == null) {
102 myEstimatedProfile = new SimpleLinearOrdering(
103 profileint.getProfile());
104 reservationBid = profileint.getProfile().getReservationBid();
105 }
106
107 if (lastReceivedBid != null) {
108 processOpponentBid(lastReceivedBid);
109 double lastBidQuality = getBidQuality(lastReceivedBid, myEstimatedProfile);
110
111 // then we do the action now, no need to ask user
112 if (myEstimatedProfile.contains(lastReceivedBid))
113 {
114 if (lastBidQuality >= getBidQuality(reservationBid, myEstimatedProfile) && lastBidQuality >= getCurrentThreshold(acceptQualityThreshold, acceptQualityThresholdMin))
115 action = new Accept(me, lastReceivedBid);
116 }
117 else {
118 // we did not yet assess the received bid
119
120 Bid closestBid = getClosestBid(myEstimatedProfile, lastReceivedBid);
121 if(hammingDistance(closestBid, lastReceivedBid) < acceptDistanceThreshold)
122 {
123 if (getBidQuality(closestBid, myEstimatedProfile) >= getCurrentThreshold(acceptQualityThreshold, acceptQualityThresholdMin))
124 action = new Accept(me, lastReceivedBid);
125 else
126 {
127 action = newOffer();
128 }
129 }
130 else
131 {
132 if(turnsWithElicitPassed >= numberOfTurnsToElicit)
133 {
134 action = new ElicitComparison(me, lastReceivedBid,
135 myEstimatedProfile.getBids());
136
137 turnsWithElicitPassed = 0;
138 }
139 else
140 {
141 ++turnsWithElicitPassed;
142 action = newOffer();
143 }
144
145 }
146 }
147 if (progress instanceof ProgressRounds) {
148 progress = ((ProgressRounds) progress).advance();
149 }
150 }
151
152 if (action == null)
153 action = newOffer();
154
155 getConnection().send(action);
156 }
157
158 private void processOpponentBid(Bid inputBid) throws IOException {
159
160 if(opponentEstimatedProfile == null)
161 {
162 List<Bid> oneBidList = new ArrayList<>();
163 oneBidList.add(inputBid);
164 opponentEstimatedProfile = new SimpleLinearOrdering(profileint.getProfile().getDomain(), oneBidList);
165 }
166
167 /*if(opponentIssueCounter == null)
168 opponentIssueCounter = new IssueCounter(profileint.getProfile().getDomain());*/
169
170 //Insert new bid to opponent profile & Counter. This assumes all previous bids are worst, as the opponent learning it's own preferences as well.
171 opponentEstimatedProfile = opponentEstimatedProfile.with(inputBid, opponentEstimatedProfile.getBids());
172 //opponentIssueCounter.addElement(inputBid);
173 }
174
175 private Bid getClosestBid(SimpleLinearOrdering profile, Bid inputBid) throws IOException {
176 Bid closestBid = null;
177 double closestDist = 1.1;
178 for(Bid currBid : profile.getBids())
179 {
180 if(closestDist > hammingDistance(currBid, inputBid))
181 {
182 closestBid = currBid;
183 closestDist = hammingDistance(currBid, inputBid);
184 }
185 }
186 return closestBid;
187 }
188
189 private Offer randomBid() throws IOException {
190 AllBidsList bidspace = new AllBidsList(
191 profileint.getProfile().getDomain());
192 long i = random.nextInt(bidspace.size().intValue());
193 Bid bid = bidspace.get(BigInteger.valueOf(i));
194 return new Offer(me, bid);
195 }
196
197 private Offer newOffer() throws IOException {
198 Bid selectedBid = null;
199 double myBidQuality = 0.0;
200 double opponentBidQuality = 0.0;
201 double myBidDistanceToOpponent = 1.0;
202 double myBidScore = 0.0;
203 RandomCollection<Bid> weightedBids = new RandomCollection<>();
204 for(Bid currBid : myEstimatedProfile.getBids())
205 {
206 myBidQuality = getBidQuality(currBid, myEstimatedProfile);
207
208 //Drop bad offers
209 if(myBidQuality < getBidQuality(reservationBid, myEstimatedProfile) || myBidQuality < getCurrentThreshold(acceptQualityThreshold, acceptQualityThresholdMin))
210 continue;
211
212 if(opponentEstimatedProfile != null)
213 {
214 //Calculate bid score using the opponent profile
215 for(Bid currOpponentBid : opponentEstimatedProfile.getBids())
216 {
217 myBidDistanceToOpponent = hammingDistance(currBid, currOpponentBid);
218 opponentBidQuality = getBidQuality(currOpponentBid, opponentEstimatedProfile);
219
220 //Drop not similar bids
221 if(myBidDistanceToOpponent > newOfferDistanceThreshold)
222 continue;
223
224 //Weight by opponent quality & distance
225 myBidScore += (1 - myBidDistanceToOpponent) * opponentBidQuality;
226 }
227 }
228
229 //Add a default score good bids with no information in opponent profile
230 if(myBidScore <= 0.0)
231 myBidScore = 0.1;
232
233 //Weight by quality for the party
234 myBidScore = myBidScore * myBidQuality;
235 weightedBids.add(myBidScore, currBid);
236 myBidScore = 0.0;
237 }
238
239 if(weightedBids.isEmpty())
240 {
241 return new Offer(me, myEstimatedProfile.getBids().get(0));
242 }
243
244 Bid weightedBid = weightedBids.next();
245 AllBidsList allBids = new AllBidsList(myEstimatedProfile.getDomain());
246 List<Bid> similarBids = new ArrayList<Bid>();
247 for(Bid bid : allBids)
248 {
249 if(hammingDistance(bid, weightedBid) >= 0.1)
250 continue;
251
252 similarBids.add(bid);
253 }
254
255 return new Offer(me, similarBids.get(random.nextInt(similarBids.size())));
256 }
257
258
259 /**
260 * Calculate an index stating how good is this bid to this profile, between 0 (worst) to 1 (best)
261 * @param bid
262 * @param profile
263 * @return
264 */
265 private double getBidQuality(Bid bid, SimpleLinearOrdering profile) {
266 //TODO: Implement by threshold
267 if (bid == null)
268 return 0.0;
269
270 return profile.getUtility(bid).doubleValue();
271 }
272
273 private double getMinMaxDistance(String issue) throws IOException
274 {
275 ValueSet vs1 = profileint.getProfile().getDomain().getValues(issue);
276 NumberValue minValue = (NumberValue) vs1.get(0);
277 NumberValue maxValue = (NumberValue) vs1.get(1);
278 return (maxValue.getValue().doubleValue() - minValue.getValue().doubleValue());
279 }
280
281 /**
282 * Returns a score between 0 to 1 that determine how much the bids are similar
283 * 0 - identical, 1 - totally different
284 * @param bid1
285 * @param bid2
286 * @return
287 * @throws IOException
288 */
289 private double hammingDistance(Bid bid1, Bid bid2) throws IOException {
290 double similarityIndex = 0.0;
291 for(Map.Entry<String, Value> valueEntry1 : bid1.getIssueValues().entrySet())
292 {
293 Value value1 = valueEntry1.getValue();
294 Value value2 = bid2.getValue(valueEntry1.getKey());
295
296 //Find out the type of bid value (range or discrete)
297 if(value1 instanceof NumberValue)
298 {
299 double valueDist = Math.abs((((NumberValue)value1).getValue().doubleValue() - ((NumberValue)value2).getValue().doubleValue()));
300 similarityIndex += (valueDist / getMinMaxDistance(valueEntry1.getKey()));
301 } else {
302 if(!valueEntry1.getValue().equals(value2))
303 {
304 similarityIndex++;
305 }
306 }
307 }
308 return (similarityIndex / bid1.getIssueValues().entrySet().size());
309 }
310
311 private double getCurrentThreshold(double threshold, double minValue)
312 {
313 if (!(progress instanceof ProgressRounds))
314 return threshold;
315
316 int currentRound = ((ProgressRounds) progress).getCurrentRound();
317 int totalRounds = ((ProgressRounds) progress).getTotalRounds();
318 if(totalRounds == 0)
319 totalRounds++;
320 return (1 - currentRound / totalRounds) * (threshold - minValue) + minValue;
321 }
322
323}
Note: See TracBrowser for help on using the repository browser.