Changeset 25 for exampleparties/timedependentparty/src
- Timestamp:
- 10/08/20 10:17:25 (4 years ago)
- Location:
- exampleparties/timedependentparty/src
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
exampleparties/timedependentparty/src/main/java/geniusweb/exampleparties/timedependentparty/TimeDependentParty.java
r24 r25 4 4 import java.math.BigDecimal; 5 5 import java.math.BigInteger; 6 import java.math.RoundingMode; 6 7 import java.util.Arrays; 7 8 import java.util.HashSet; 9 import java.util.List; 8 10 import java.util.Random; 9 11 import java.util.logging.Level; 12 import java.util.stream.Collectors; 10 13 11 14 import geniusweb.actions.Accept; … … 13 16 import geniusweb.actions.Offer; 14 17 import geniusweb.actions.PartyId; 18 import geniusweb.actions.Vote; 19 import geniusweb.actions.Votes; 15 20 import geniusweb.inform.ActionDone; 16 21 import geniusweb.inform.Finished; 17 22 import geniusweb.inform.Inform; 23 import geniusweb.inform.OptIn; 18 24 import geniusweb.inform.Settings; 25 import geniusweb.inform.Voting; 19 26 import geniusweb.inform.YourTurn; 20 27 import geniusweb.issuevalue.Bid; … … 23 30 import geniusweb.profile.Profile; 24 31 import geniusweb.profile.utilityspace.LinearAdditive; 32 import geniusweb.profile.utilityspace.UtilitySpace; 25 33 import geniusweb.profileconnection.ProfileConnectionFactory; 26 34 import geniusweb.profileconnection.ProfileInterface; … … 35 43 * 2^31 (approx 1 billion bids). It may take excessive time and run out of time 36 44 * on bidspaces > 10000 bids. In special cases it may even run out of memory, 45 * 46 * <p> 47 * Supports parameters as follows 48 * <table summary="parameters"> 49 * <tr> 50 * <td>e</td> 51 * <td>e determines how fast the party makes concessions with time. Typically 52 * around 1. 0 means no concession, 1 linear concession, >1 faster than 53 * linear concession.</td> 54 * </tr> 55 * 56 * <tr> 57 * <td>minPower</td> 58 * <td>This value is used as minPower for placed {@link Vote}s. Default value is 59 * 1.</td> 60 * </tr> 61 * 62 * <tr> 63 * <td>maxPower</td> 64 * <td>This value is used as maxPower for placed {@link Vote}s. Default value is 65 * infinity.</td> 66 * </tr> 67 * 68 * </table> 69 * <p> 70 * TimeDependentParty requires a {@link UtilitySpace} 37 71 */ 38 72 public class TimeDependentParty extends DefaultParty { 39 73 40 private static final BigDecimal DEC0001 = new BigDecimal("0.0001");41 private static final BigDecimal DEC100 = new BigDecimal("100");42 74 private ProfileInterface profileint; 43 75 private LinearAdditive utilspace = null; // last received space … … 47 79 private ExtendedUtilSpace extendedspace; 48 80 private double e = 1.2; 81 private Votes lastvotes; 82 private Settings settings; 49 83 50 84 public TimeDependentParty() { … … 58 92 @Override 59 93 public Capabilities getCapabilities() { 60 return new Capabilities(new HashSet<>(Arrays.asList("SAOP" )));94 return new Capabilities(new HashSet<>(Arrays.asList("SAOP", "MOPAC"))); 61 95 } 62 96 … … 65 99 try { 66 100 if (info instanceof Settings) { 67 Settingssettings = (Settings) info;101 settings = (Settings) info; 68 102 this.profileint = ProfileConnectionFactory 69 103 .create(settings.getProfile().getURI(), getReporter()); … … 80 114 } 81 115 } 82 83 116 } else if (info instanceof ActionDone) { 84 117 Action otheract = ((ActionDone) info).getAction(); … … 88 121 } else if (info instanceof YourTurn) { 89 122 myTurn(); 90 if (progress instanceof ProgressRounds) {91 progress = ((ProgressRounds) progress).advance();92 }93 123 } else if (info instanceof Finished) { 94 124 getReporter().log(Level.INFO, "Final ourcome:" + info); 125 } else if (info instanceof Voting) { 126 lastvotes = vote((Voting) info); 127 getConnection().send(lastvotes); 128 } else if (info instanceof OptIn) { 129 getConnection().send(lastvotes); 95 130 } 96 } catch (Exception e) { 97 getReporter().log(Level.SEVERE, "Failed to handle info", e); 98 } 131 } catch (Exception ex) { 132 getReporter().log(Level.SEVERE, "Failed to handle info", ex); 133 } 134 updateRound(info); 99 135 } 100 136 … … 119 155 } 120 156 157 @Override 158 public String getDescription() { 159 return "Time-dependent conceder. Aims at utility u(t) = scale * t^(1/e) " 160 + "where t is the time (0=start, 1=end), e is the concession speed parameter (default 1.1), and scale such that u(0)=minimum and " 161 + "u(1) = maximum possible utility. Parameters minPower (default 1) and maxPower (default infinity) are used " 162 + "when voting"; 163 } 164 121 165 /******************* private support funcs ************************/ 166 167 /** 168 * Update {@link #progress}, depending on the protocol and last received 169 * {@link Inform} 170 * 171 * @param info the received info. 172 */ 173 private void updateRound(Inform info) { 174 if (settings == null) // not yet initialized 175 return; 176 String protocol = settings.getProtocol().getURI().getPath(); 177 178 switch (protocol) { 179 case "SAOP": 180 case "SHAOP": 181 if (!(info instanceof YourTurn)) 182 return; 183 break; 184 case "MOPAC": 185 if (!(info instanceof OptIn)) 186 return; 187 break; 188 default: 189 return; 190 } 191 // if we get here, round must be increased. 192 if (progress instanceof ProgressRounds) { 193 progress = ((ProgressRounds) progress).advance(); 194 } 195 196 } 122 197 123 198 private void myTurn() throws IOException { … … 153 228 private Bid makeBid() { 154 229 double time = progress.get(System.currentTimeMillis()); 155 BigDecimal utilityGoal = utilityGoal(time, getE()); 230 231 BigDecimal utilityGoal = getUtilityGoal(time, getE(), 232 extendedspace.getMin(), extendedspace.getMax()); 156 233 ImmutableList<Bid> options = extendedspace.getBids(utilityGoal); 157 234 if (options.size() == BigInteger.ZERO) { … … 166 243 /** 167 244 * 168 * @param t the time in [0,1] where 0 means start of nego and 1 the end of 169 * nego (absolute time/round limit) 170 * @param e the e value 245 * @param t the time in [0,1] where 0 means start of nego and 1 the 246 * end of nego (absolute time/round limit) 247 * @param e the e value that determinses how fast the party makes 248 * concessions with time. Typically around 1. 0 means no 249 * concession, 1 linear concession, >1 faster than linear 250 * concession. 251 * @param minUtil the minimum utility possible in our profile 252 * @param maxUtil the maximum utility possible in our profile 171 253 * @return the utility goal for this time and e value 172 254 */ 173 private BigDecimal utilityGoal(double t, double e) { 174 BigDecimal minUtil = extendedspace.getMin(); 175 BigDecimal maxUtil = extendedspace.getMax(); 176 177 double ft = 0; 255 protected BigDecimal getUtilityGoal(double t, double e, BigDecimal minUtil, 256 BigDecimal maxUtil) { 257 258 BigDecimal ft1 = BigDecimal.ONE; 178 259 if (e != 0) 179 ft = Math.pow(t, 1 / e); 180 // we subtract epsilon to correct possibly small round-up errors 181 return new BigDecimal(minUtil.doubleValue() 182 + (maxUtil.doubleValue() - minUtil.doubleValue()) * (1 - ft)) 183 .min(maxUtil).max(minUtil); 184 } 185 186 @Override 187 public String getDescription() { 188 return "Time-dependent conceder. Aims at utility u(t) = scale * t^(1/e) " 189 + "where t is the time (0=start, 1=end), e is a parameter (default 1.1), and scale such that u(0)=minimum and " 190 + "u(1) = maximum possible utility. "; 260 ft1 = BigDecimal.valueOf(1 - Math.pow(t, 1 / e)).setScale(6, 261 RoundingMode.HALF_UP); 262 return minUtil.add((maxUtil.subtract(minUtil).multiply(ft1))) 263 .min(maxUtil).max(minUtil); 264 } 265 266 /** 267 * @param voting the {@link Voting} object containing the options 268 * 269 * @return our next Votes. 270 */ 271 private Votes vote(Voting voting) throws IOException { 272 Object val = settings.getParameters().get("minPower"); 273 // max utility requires smallest possible group/power 274 Integer minpower = (val instanceof Integer) ? (Integer) val : 1; 275 val = settings.getParameters().get("maxPower"); 276 Integer maxpower = (val instanceof Integer) ? (Integer) val 277 : Integer.MAX_VALUE; 278 279 List<Vote> votes = voting.getBids().stream().distinct() 280 .filter(bid -> isGood(bid)) 281 .map(bid -> new Vote(me, bid, minpower, maxpower)) 282 .collect(Collectors.toList()); 283 return new Votes(me, votes); 284 } 285 286 /** 287 * @param bid the bid to check 288 * @return true iff bid is good for us. 289 */ 290 private boolean isGood(Bid bid) { 291 if (bid == null || profileint == null) 292 return false; 293 Profile profile; 294 try { 295 profile = profileint.getProfile(); 296 } catch (IOException ex) { 297 throw new IllegalStateException(ex); 298 } 299 // the profile MUST contain UtilitySpace 300 double time = progress.get(System.currentTimeMillis()); 301 return ((UtilitySpace) profile).getUtility(bid) 302 .compareTo(getUtilityGoal(time, getE(), extendedspace.getMin(), 303 extendedspace.getMax())) >= 0; 304 191 305 } 192 306 } -
exampleparties/timedependentparty/src/test/java/geniusweb/exampleparties/timedependentparty/TimeDependentPartyTest.java
r24 r25 17 17 import java.nio.file.Files; 18 18 import java.nio.file.Paths; 19 import java.util.LinkedList;20 import java.util.List;21 19 import java.util.logging.Level; 22 20 … … 29 27 30 28 import geniusweb.actions.Accept; 31 import geniusweb.actions.Action;32 29 import geniusweb.actions.EndNegotiation; 33 30 import geniusweb.actions.Offer; 34 31 import geniusweb.actions.PartyId; 35 32 import geniusweb.bidspace.AllBidsList; 36 import geniusweb.connection.ConnectionEnd;37 33 import geniusweb.inform.ActionDone; 38 34 import geniusweb.inform.Agreements; 39 35 import geniusweb.inform.Finished; 40 import geniusweb.inform.Inform;41 36 import geniusweb.inform.Settings; 42 37 import geniusweb.inform.YourTurn; … … 49 44 import geniusweb.references.ProfileRef; 50 45 import geniusweb.references.ProtocolRef; 51 import geniusweb.references.Reference;52 import tudelft.utilities.listener.DefaultListenable;53 46 import tudelft.utilities.logging.Reporter; 54 47 … … 62 55 private TimeDependentParty party; 63 56 private TestConnection connection = new TestConnection(); 64 private ProtocolRef protocol = mock(ProtocolRef.class);57 private ProtocolRef protocol = new ProtocolRef("SAOP"); 65 58 private ProgressRounds progress = mock(ProgressRounds.class); 66 59 private Parameters parameters = new Parameters(); … … 113 106 public void testInformConnection() { 114 107 party.connect(connection); 115 // agentshould not start acting just after an inform108 // Party should not start acting just after an inform 116 109 assertEquals(0, connection.getActions().size()); 117 110 } … … 143 136 144 137 @Test 145 public void test AgentHasFirstTurn() {138 public void testPartyHasFirstTurn() { 146 139 party.connect(connection); 147 140 party.notifyChange(settings); … … 153 146 154 147 @Test 155 public void test AgentAccepts() {148 public void testPartyAccepts() { 156 149 party.connect(connection); 157 150 party.notifyChange(settings); … … 166 159 167 160 @Test 168 public void test AgentLogsFinal() {161 public void testPartyLogsFinal() { 169 162 // this log output is optional, this is to show how to check log 170 163 Reporter reporter = mock(Reporter.class); … … 193 186 194 187 @Test 195 public void test AgentsUpdatesProgress() {188 public void testPartysUpdatesProgress() { 196 189 party.connect(connection); 197 190 party.notifyChange(settings); … … 204 197 public void testGetCapabilities() { 205 198 assertTrue(party.getCapabilities().getBehaviours().contains(SAOP)); 199 } 200 201 @Test 202 public void testUtilityTarget() { 203 TimeDependentParty tdp = new TimeDependentParty(); 204 BigDecimal N02 = new BigDecimal("0.2"); 205 BigDecimal N043 = new BigDecimal("0.42521212"); 206 BigDecimal goal = tdp.getUtilityGoal(0.1, 1.2, N02, N043); 207 assertTrue(goal.compareTo(N02) > 0); 208 assertTrue(goal.compareTo(N043) < 0); 206 209 } 207 210 … … 220 223 221 224 } 222 223 /**224 * A "real" connection object, because the party is going to subscribe etc, and225 * without a real connection we would have to do a lot of mocks that would make226 * the test very hard to read.227 *228 */229 class TestConnection extends DefaultListenable<Inform>230 implements ConnectionEnd<Inform, Action> {231 private List<Action> actions = new LinkedList<>();232 233 @Override234 public void send(Action action) throws IOException {235 actions.add(action);236 }237 238 @Override239 public Reference getReference() {240 return null;241 }242 243 @Override244 public URI getRemoteURI() {245 return null;246 }247 248 @Override249 public void close() {250 251 }252 253 @Override254 public Error getError() {255 return null;256 }257 258 public List<Action> getActions() {259 return actions;260 }261 262 }
Note:
See TracChangeset
for help on using the changeset viewer.