source: exampleparties/randomparty/src/main/java/geniusweb/exampleparties/randomparty/RandomParty.java

Last change on this file was 52, checked in by ruud, 13 months ago

Fixed small issues in domaineditor.

File size: 8.2 KB
Line 
1package geniusweb.exampleparties.randomparty;
2
3import java.io.IOException;
4import java.math.BigInteger;
5import java.util.Arrays;
6import java.util.Collections;
7import java.util.HashSet;
8import java.util.List;
9import java.util.Random;
10import java.util.Set;
11import java.util.logging.Level;
12import java.util.stream.Collectors;
13
14import geniusweb.actions.Accept;
15import geniusweb.actions.Action;
16import geniusweb.actions.LearningDone;
17import geniusweb.actions.Offer;
18import geniusweb.actions.PartyId;
19import geniusweb.actions.Vote;
20import geniusweb.actions.VoteWithValue;
21import geniusweb.actions.Votes;
22import geniusweb.actions.VotesWithValue;
23import geniusweb.bidspace.AllPartialBidsList;
24import geniusweb.inform.ActionDone;
25import geniusweb.inform.Finished;
26import geniusweb.inform.Inform;
27import geniusweb.inform.OptIn;
28import geniusweb.inform.OptInWithValue;
29import geniusweb.inform.Settings;
30import geniusweb.inform.Voting;
31import geniusweb.inform.YourTurn;
32import geniusweb.issuevalue.Bid;
33import geniusweb.party.Capabilities;
34import geniusweb.party.DefaultParty;
35import geniusweb.profile.PartialOrdering;
36import geniusweb.profile.Profile;
37import geniusweb.profile.utilityspace.UtilitySpace;
38import geniusweb.profileconnection.ProfileConnectionFactory;
39import geniusweb.profileconnection.ProfileInterface;
40import geniusweb.progress.Progress;
41import geniusweb.progress.ProgressRounds;
42import tudelft.utilities.logging.Reporter;
43
44/**
45 * A party that places random bids and accepts when it receives an offer with
46 * sufficient utility. This party is also a demo on how to support the various
47 * protocols, which causes this party to look a bit complex.
48 *
49 * <h2>parameters</h2>
50 * <table >
51 * <caption>parameters</caption>
52 * <tr>
53 * <td>minPower</td>
54 * <td>This value is used as minPower for placed {@link Vote}s. Default value is
55 * 2.</td>
56 * </tr>
57 * <tr>
58 * <td>maxPower</td>
59 * <td>This value is used as maxPower for placed {@link Vote}s. Default value is
60 * infinity.</td>
61 * </tr>
62 * </table>
63 */
64public class RandomParty extends DefaultParty {
65
66 private Bid lastReceivedBid = null;
67 private PartyId me;
68 private final Random random = new Random();
69 protected ProfileInterface profileint = null;
70 private Progress progress;
71 private Settings settings;
72 private Votes lastvotes;
73 private VotesWithValue lastvoteswithvalue;
74 private String protocol;
75
76 public RandomParty() {
77 }
78
79 public RandomParty(Reporter reporter) {
80 super(reporter); // for debugging
81 }
82
83 @Override
84 public void notifyChange(Inform info) {
85 try {
86 if (info instanceof Settings) {
87 Settings sett = (Settings) info;
88 this.me = sett.getID();
89 this.progress = sett.getProgress();
90 this.settings = sett;
91 this.protocol = sett.getProtocol().getURI().getPath();
92 if ("Learn".equals(protocol)) {
93 getConnection().send(new LearningDone(me));
94 } else {
95 this.profileint = ProfileConnectionFactory
96 .create(sett.getProfile().getURI(), getReporter());
97 }
98 } else if (info instanceof ActionDone) {
99 Action otheract = ((ActionDone) info).getAction();
100 if (otheract instanceof Offer) {
101 lastReceivedBid = ((Offer) otheract).getBid();
102 }
103 } else if (info instanceof YourTurn) {
104 makeOffer();
105 } else if (info instanceof Finished) {
106 getReporter().log(Level.INFO, "Final ourcome:" + info);
107 terminate(); // stop this party and free resources.
108 } else if (info instanceof Voting) {
109 switch (protocol) {
110 case "MOPAC":
111 lastvotes = vote((Voting) info);
112 getConnection().send(lastvotes);
113 break;
114 case "MOPAC2":
115 lastvoteswithvalue = voteWithValue((Voting) info);
116 getConnection().send(lastvoteswithvalue);
117 }
118 } else if (info instanceof OptIn) {
119 // just repeat our last vote.
120 getConnection().send(lastvotes);
121 } else if (info instanceof OptInWithValue) {
122 getConnection().send(lastvoteswithvalue);
123 }
124 } catch (Exception e) {
125 throw new RuntimeException("Failed to handle info", e);
126 }
127 updateRound(info);
128 }
129
130 @Override
131 public Capabilities getCapabilities() {
132 return new Capabilities(new HashSet<>(
133 Arrays.asList("SAOP", "AMOP", "MOPAC", "MOPAC2", "Learn")),
134 Collections.singleton(Profile.class));
135 }
136
137 @Override
138 public String getDescription() {
139 return "places random bids until it can accept an offer with utility >0.6. "
140 + "Parameters minPower and maxPower can be used to control voting behaviour.";
141 }
142
143 @Override
144 public void terminate() {
145 super.terminate();
146 if (this.profileint != null) {
147 this.profileint.close();
148 this.profileint = null;
149 }
150 }
151
152 /******************* private support funcs ************************/
153
154 /**
155 * Update {@link #progress}
156 *
157 * @param info the received info. Used to determine if this is the last info
158 * of the round
159 */
160 private void updateRound(Inform info) {
161 if (protocol == null)
162 return;
163 switch (protocol) {
164 case "SAOP":
165 case "SHAOP":
166 if (!(info instanceof YourTurn))
167 return;
168 break;
169 case "MOPAC":
170 if (!(info instanceof OptIn))
171 return;
172 break;
173 case "MOPAC2":
174 if (!(info instanceof OptInWithValue))
175 return;
176 break;
177 default:
178 return;
179 }
180 // if we get here, round must be increased.
181 if (progress instanceof ProgressRounds) {
182 progress = ((ProgressRounds) progress).advance();
183 }
184
185 }
186
187 /**
188 * send our next offer
189 */
190 private void makeOffer() throws IOException {
191 Action action;
192 if ((protocol.equals("SAOP") || protocol.equals("SHAOP"))
193 && isGood(lastReceivedBid)) {
194 action = new Accept(me, lastReceivedBid);
195 } else {
196 // for demo. Obviously full bids have higher util in general
197 AllPartialBidsList bidspace = new AllPartialBidsList(
198 profileint.getProfile().getDomain());
199 Bid bid = null;
200 for (int attempt = 0; attempt < 20 && !isGood(bid); attempt++) {
201 long i = random.nextInt(bidspace.size().intValue());
202 bid = bidspace.get(BigInteger.valueOf(i));
203 }
204 action = new Offer(me, bid);
205 }
206 getConnection().send(action);
207
208 }
209
210 /**
211 * @param bid the bid to check
212 * @return true iff bid is good for us.
213 */
214 private boolean isGood(Bid bid) {
215 if (bid == null)
216 return false;
217 Profile profile;
218 try {
219 profile = profileint.getProfile();
220 } catch (IOException e) {
221 throw new IllegalStateException(e);
222 }
223 if (profile instanceof UtilitySpace)
224 return ((UtilitySpace) profile).getUtility(bid).doubleValue() > 0.6;
225 if (profile instanceof PartialOrdering) {
226 return ((PartialOrdering) profile).isPreferredOrEqual(bid,
227 profile.getReservationBid());
228 }
229 return false;
230 }
231
232 /**
233 * @param voting the {@link Voting} object containing the options
234 *
235 * @return our next Votes.
236 */
237 private Votes vote(Voting voting) throws IOException {
238 Object val = settings.getParameters().get("minPower");
239 Integer minpower = (val instanceof Integer) ? (Integer) val : 2;
240 val = settings.getParameters().get("maxPower");
241 Integer maxpower = (val instanceof Integer) ? (Integer) val
242 : Integer.MAX_VALUE;
243
244 Set<Vote> votes = voting.getOffers().stream().distinct()
245 .filter(offer -> isGood(offer.getBid()))
246 .map(offer -> new Vote(me, offer.getBid(), minpower, maxpower))
247 .collect(Collectors.toSet());
248 return new Votes(me, votes);
249 }
250
251 /**
252 * @param voting the {@link Voting} object containing the options
253 *
254 * @return our next Votes. Returns only votes on good bids and tries to
255 * distribute vote values evenly over all good bids.
256 */
257 private VotesWithValue voteWithValue(Voting voting) throws IOException {
258 Object val = settings.getParameters().get("minPower");
259 Integer minpower = (val instanceof Integer) ? (Integer) val : 2;
260 val = settings.getParameters().get("maxPower");
261 Integer maxpower = (val instanceof Integer) ? (Integer) val
262 : Integer.MAX_VALUE;
263
264 List<Bid> goodbids = voting.getOffers().stream().distinct()
265 .filter(offer -> isGood(offer.getBid()))
266 .map(offer -> offer.getBid()).collect(Collectors.toList());
267
268 if (goodbids.isEmpty()) {
269 return new VotesWithValue(me, Collections.emptySet());
270 }
271 // extra difficulty now is to have the utility sum to exactly 100
272 int mostvalues = 100 / goodbids.size();
273 int value = 100 - mostvalues * (goodbids.size() - 1);
274 Set<VoteWithValue> votes = new HashSet<>();
275 for (Bid bid : goodbids) {
276 votes.add(new VoteWithValue(me, bid, minpower, maxpower, value));
277 value = mostvalues;
278 }
279 return new VotesWithValue(me, votes);
280 }
281
282}
Note: See TracBrowser for help on using the repository browser.