SocialTransitionStrategy.java 12.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/*
 * Copyright (c) 2005-2010 KOM – Multimedia Communications Lab
 *
 * This file is part of PeerfactSim.KOM.
 * 
 * PeerfactSim.KOM is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * any later version.
 * 
 * PeerfactSim.KOM is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with PeerfactSim.KOM.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
Björn Richerzhagen's avatar
Björn Richerzhagen committed
27
import java.util.LinkedHashSet;
28
29
30
31
32
33
34
35
36
37
38
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Random;
import java.util.Set;
import java.util.Vector;

import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
39
import de.tud.kom.p2psim.api.topology.Topology;
40
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
41
42
43
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.PositionVector;
44
import de.tudarmstadt.maki.simonstrator.api.Binder;
45
46
47
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
48
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
49
50
51
52

/**
 * This is a {@link TransitionStrategy} for the Social Case. It will be try to
 * build groups based on the {@link SocialView} information. For this, it tries
53
54
55
 * to assignment the given objects to the given {@link AttractionPoint}s. For
 * the {@link SocialView}, it is required a {@link #socialId}, to find the right
 * {@link SocialView}.
56
57
58
59
60
61
62
63
64
65
66
 * 
 * <br>
 * 
 * The Strategy has the parameter of {@link #socialFactor},
 * {@link #minPauseTime} and {@link #maxPauseTime}. The socialFactor should be a
 * value between 0 and 1. It gives the probability for a social based transition
 * or the transition to a random {@link AttractionPoint}. If the social based
 * transition is selected, then will be used a scoring to find the right
 * {@link AttractionPoint}. For that, it will be used only the AttractionPoints,
 * of the hosts, which are in the same SocialCluster or are SocialNeighbors. For
 * this AttractionPoints it will be find the highest scoring, which is to found
67
 * in score. .
68
69
70
71
72
73
74
75
76
77
78
79
 * 
 * <br>
 * 
 * After the finding of the next {@link AttractionPoint}, it will be scheduled
 * an Event, with a delay between min- and maxPauseTime. After this delay, it
 * will be tried to assign a new {@link AttractionPoint} like the described
 * above.
 * 
 * 
 * @author Christoph Muenker
 * @version 1.0, 02.07.2013
 */
80
81
public class SocialTransitionStrategy
		implements ITransitionStrategy, EventHandler {
82
83
84
85
86

	private String socialId = null;

	private SocialView socialView;

87
	private List<SimLocationActuator> comps = new Vector<SimLocationActuator>();
88
89
90

	private List<AttractionPoint> aPoints = new Vector<AttractionPoint>();

91
	private Map<SimLocationActuator, AttractionPoint> assignments = new HashMap<SimLocationActuator, AttractionPoint>();
92

93
	private Set<SimLocationActuator> arrivedAtAttractionPoint = new LinkedHashSet<>();
94

95
	private Map<SimLocationActuator, Set<AttractionPoint>> favoritePlaces = new HashMap<SimLocationActuator, Set<AttractionPoint>>();
96

97
	private Map<SimLocationActuator, SimHost> mapMsHost = new HashMap<SimLocationActuator, SimHost>();
98

99
	private Map<SimHost, SimLocationActuator> mapHostMs = new HashMap<SimHost, SimLocationActuator>();
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125

	private double minPauseTime = Simulator.MINUTE_UNIT * 0.5;

	private double maxPauseTime = Simulator.MINUTE_UNIT * 100;

	private double socialFactor = 0.8;

	private long numberOfFavoritePlaces = 4;

	private Random rand;

	private PositionVector worldDimension;

	private boolean init = false;

	public SocialTransitionStrategy() {
		this.rand = Randoms.getRandom(SocialTransitionStrategy.class);
	}

	private void init() {
		if (!init) {
			if (socialId == null) {
				throw new ConfigurationException(
						"SocialId is not set, to find the needed SocialView!");
			}

126
127
			socialView = Binder.getComponentOrNull(Topology.class)
					.getSocialView(socialId);
128
129
130
131
132
133
134
135
136
137
138

			if (socialView == null) {
				throw new ConfigurationException(
						"Cannot find the right socialView. Is the socialId correct?");
			}

			if (minPauseTime > maxPauseTime) {
				throw new ConfigurationException(
						"MinPauseTime should be smaller then maxPauseTime.");
			}

139
140
			worldDimension = Binder.getComponentOrNull(Topology.class)
					.getWorldDimensions();
141
142
143
144
145
146
147
148
149
			init = true;
		}
	}

	public void setSocialId(String socialId) {
		this.socialId = socialId;
	}

	@Override
150
	public Map<SimLocationActuator, AttractionPoint> getAssignments() {
151
152
153
		// FIXME why new? return new HashMap<MovementSupported,
		// AttractionPoint>(assignments);
		return assignments;
154
155
156
157
158
159
160
	}

	@Override
	public void setAttractionPoints(List<AttractionPoint> attractionPoints) {
		init();
		aPoints.addAll(attractionPoints);
	}
161

162
163
164
165
	@Override
	public List<AttractionPoint> getAllAttractionPoints() {
		return aPoints;
	}
166
167

	@Override
168
	public void addComponent(SimLocationActuator ms) {
169
170
171
172
173
174
175
176
		comps.add(ms);
		mappingHost(ms);
		// assign the ms to an attractionPoint, which is near to the ms
		// position.
		// TODO: needed? We do Transition as next, and this will delete the
		// assignment..
		AttractionPoint nearest = aPoints.iterator().next();
		for (AttractionPoint aPoint : aPoints) {
177
178
			if (nearest.distanceTo(ms.getRealPosition()) > aPoint
					.distanceTo(ms.getRealPosition())) {
179
180
181
182
183
184
185
186
187
				nearest = aPoint;
			}
		}
		assignments.put(ms, nearest);

		assignFavoritePlaces(ms);

		doTransition(ms);
	}
188

189
190
191
192
193
194
	@Override
	public void updateTargetAttractionPoint(SimLocationActuator comp,
			AttractionPoint attractionPoint) {
		arrivedAtAttractionPoint.remove(comp);
		assignments.put(comp, attractionPoint);
	}
195

Björn Richerzhagen's avatar
Björn Richerzhagen committed
196
	@Override
197
	public void reachedAttractionPoint(SimLocationActuator ms) {
Björn Richerzhagen's avatar
Björn Richerzhagen committed
198
199
200
201
202
		if (!arrivedAtAttractionPoint.contains(ms)) {
			Event.scheduleWithDelay(getPauseTime(), this, ms, 0);
			arrivedAtAttractionPoint.add(ms);
		}
	}
203

204
	public void doTransition(SimLocationActuator ms) {
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
		List<AttractionPoint> apFavorites = getFavoritePlaces(ms);
		List<AttractionPoint> apFriends = getFriendsPlaces(ms);
		List<AttractionPoint> apClusters = getClusterPlaces(ms);
		List<AttractionPoint> apRandom = getRandomPlaces(ms,
				(int) Math.max(aPoints.size() * 0.2, 5));

		AttractionPoint ap = null;
		if (rand.nextDouble() < socialFactor) {
			ap = findHighestScore(ms, apFavorites, apFriends, apClusters,
					apRandom);
		} else {
			List<AttractionPoint> aps = new ArrayList<AttractionPoint>();
			aps.addAll(apRandom);
			aps.addAll(apFavorites);
			ap = aps.get(rand.nextInt(apRandom.size()));
		}
		assignments.put(ms, ap);
Björn Richerzhagen's avatar
Björn Richerzhagen committed
222
		arrivedAtAttractionPoint.remove(ms);
223
224
	}

225
	private AttractionPoint findHighestScore(SimLocationActuator ms,
226
227
			List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
			List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
228
		Set<AttractionPoint> aps = new LinkedHashSet<AttractionPoint>();
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
		aps.addAll(apFavorites);
		aps.addAll(apFriends);
		aps.addAll(apClusters);
		aps.addAll(apRandom);

		double maxScore = 0;
		AttractionPoint maxAp = null;
		for (AttractionPoint ap : aps) {
			double score = score(ms, ap, apFavorites, apFriends, apClusters,
					apRandom);
			// System.out.println(score);
			if (score > maxScore) {
				maxScore = score;
				maxAp = ap;
			}
		}
		return maxAp;
	}

	/**
249
	 * Score the given AttractionPoint for the given SimLocationActuator. <br>
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
	 * (clusterScore/#NodesInAp + friendsScore + 1/#NodesInAp) * socialFactor +
	 * (distanceScore + penalty) + (1-socialFactor) <br>
	 * 
	 * clusterScore = 1 if one is in the same cluster in this AP<br>
	 * friendsScore = 1 if one friend is in the same AP<br>
	 * penalty = -1 if AP the actually AP is <br>
	 * distance = 1 - (distance / maxDistance)
	 * 
	 * @param ms
	 * @param ap
	 * @param apFavorites
	 * @param apFriends
	 * @param apClusters
	 * @param apRandom
	 * @return
	 */
266
	private double score(SimLocationActuator ms, AttractionPoint ap,
267
268
			List<AttractionPoint> apFavorites, List<AttractionPoint> apFriends,
			List<AttractionPoint> apClusters, List<AttractionPoint> apRandom) {
269
		double distance = ms.getRealPosition().distanceTo(ap);
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
		double distanceScore = 1 - (distance / worldDimension.getLength());

		double clusterScore = 0;
		double friendsScore = 0;
		if (apClusters.contains(ap)) {
			if (occurence(ap, apClusters) > 3) {
				// occurence give the number of other peers in this AP
				clusterScore = 1.0 / (occurence(ap, apClusters) - 1);
			} else {
				clusterScore = 1.0;
			}
		}
		if (apFriends.contains(ap)) {
			if (occurence(ap, apFriends) > 3) {
				// occurence give the number of other peers in this AP
				friendsScore = 1.0 / (occurence(ap, apFriends) - 1);
			} else {
				friendsScore = 1.0;
			}
		}
		// penalty for distance
		double penalty = 0;
		if (ap.equals(assignments.get(ms))) {
			penalty = -1;
		}

296
297
		return (clusterScore / assignedToAp(ap) + friendsScore
				+ 1.0 / assignedToAp(ap)) * socialFactor
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314

				+ (distanceScore + penalty) * (1 - socialFactor);
	}

	// counts the number of the AttractionPoint in the list
	private int occurence(AttractionPoint ap, List<AttractionPoint> aps) {
		int i = 0;
		for (AttractionPoint a : aps) {
			if (a.equals(ap)) {
				i++;
			}
		}
		return i;
	}

	private int assignedToAp(AttractionPoint ap) {
		int i = 1;
315
		for (Entry<SimLocationActuator, AttractionPoint> entry : assignments
316
317
318
319
320
321
322
323
				.entrySet()) {
			if (entry.getValue().equals(ap)) {
				i++;
			}
		}
		return i;
	}

324
	private List<AttractionPoint> getRandomPlaces(SimLocationActuator ms,
325
			int number) {
326
		Collections.shuffle(aPoints, rand);
327
328
329
330
331
332
333
334
335
		List<AttractionPoint> result = new Vector<AttractionPoint>();
		Iterator<AttractionPoint> iAP = aPoints.iterator();
		for (int i = 0; i < number && iAP.hasNext(); i++) {
			result.add(iAP.next());
		}

		return result;
	}

336
	private List<AttractionPoint> getClusterPlaces(SimLocationActuator ms) {
337
338
339
340
		List<AttractionPoint> result = new Vector<AttractionPoint>();
		SimHost msHost = mapMsHost.get(ms);

		for (SimHost host : socialView.getCluster(msHost)) {
341
			SimLocationActuator temp = mapHostMs.get(host);
342
343
344
345
346
347
348
349
			if (assignments.get(temp) != null) {
				result.add(assignments.get(temp));
			}
		}

		return result;
	}

350
	private List<AttractionPoint> getFriendsPlaces(SimLocationActuator ms) {
351
352
353
354
		List<AttractionPoint> result = new Vector<AttractionPoint>();
		SimHost msHost = mapMsHost.get(ms);

		for (SimHost host : socialView.getNeighbors(msHost)) {
355
			SimLocationActuator temp = mapHostMs.get(host);
356
357
358
359
360
361
362
363
			if (assignments.get(temp) != null) {
				result.add(assignments.get(temp));
			}
		}

		return result;
	}

364
	private List<AttractionPoint> getFavoritePlaces(SimLocationActuator ms) {
365
366
367
		return new Vector<AttractionPoint>(favoritePlaces.get(ms));
	}

368
	private void assignFavoritePlaces(SimLocationActuator ms) {
369
		Set<AttractionPoint> msFavoritePlaces = new LinkedHashSet<AttractionPoint>();
370
371
372
373
374
375
376
377
378
379
380
		LinkedList<AttractionPoint> temp = new LinkedList<AttractionPoint>(
				aPoints);
		Collections.shuffle(temp, rand);
		for (int i = 0; i < numberOfFavoritePlaces; i++) {
			if (!temp.isEmpty()) {
				msFavoritePlaces.add(temp.removeFirst());
			}
		}
		favoritePlaces.put(ms, msFavoritePlaces);
	}

381
	private void mappingHost(SimLocationActuator ms) {
382
383
384
385
386
387
388
389
390
391
		SimHostComponent comp = (SimHostComponent) ms;
		SimHost host = comp.getHost();

		assert host != null;

		mapHostMs.put(host, ms);
		mapMsHost.put(ms, host);
	}

	protected long getPauseTime() {
392
393
		return (long) ((rand.nextDouble() * (maxPauseTime - minPauseTime))
				+ minPauseTime);
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
	}

	public void setMinPauseTime(long minPauseTime) {
		if (minPauseTime < 0) {
			throw new ConfigurationException(
					"MinPauseTime should be bigger then 0!");
		}
		this.minPauseTime = minPauseTime;
	}

	public void setMaxPauseTime(long maxPauseTime) {
		if (maxPauseTime < 0) {
			throw new ConfigurationException(
					"MaxPauseTime should be bigger then 0!");
		}
		this.maxPauseTime = maxPauseTime;
	}

	@Override
	public void eventOccurred(Object se, int type) {
414
415
416
		if (arrivedAtAttractionPoint.contains(se)) {
			doTransition((SimLocationActuator) se);
		}
417
418
419
420
421
422
423
424
425
426
427
	}

	public void setSocialFactor(double socialFactor) {
		if (socialFactor < 0 || socialFactor > 1) {
			throw new ConfigurationException(
					"socialFactor should be between 0 and 1!");
		}
		this.socialFactor = socialFactor;
	}

}