Commit 049e341a authored by Julian Zobel's avatar Julian Zobel
Browse files

Dynamic random attraction points generator!

Also refactored assignement and transition strategies to use the APs given and stored in the generator, removed all attraction point references doubled in movement models, transitions, and assignemdn strategies.
parent a886bf18
......@@ -158,10 +158,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
*/
localMovementStrategy
.setScaleFactor(timeBetweenMoveOperation / (double) Time.SECOND);
List<AttractionPoint> attractionPoints = attractionGenerator
.getAttractionPoints();
transition.setAttractionPoints(attractionPoints);
transition.addAttractionAssignmentListener(this);
// This adds the mobile hosts (smartphones/users) to the transition
......@@ -197,13 +194,7 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
public AttractionPoint getTargetLocation(SimLocationActuator actuator) {
return transition.getAssignment(actuator);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints()
throws UnsupportedOperationException {
return transition.getAllAttractionPoints();
}
private void checkConfiguration() {
if (localMovementStrategy == null) {
throw new ConfigurationException(
......@@ -362,6 +353,6 @@ public class ModularMovementModel implements MovementModel, EventHandler, Attrac
* @return
*/
public List<AttractionPoint> getAttractionPoints() {
return new Vector<AttractionPoint>(transition.getAllAttractionPoints());
return new Vector<AttractionPoint>(IAttractionGenerator.attractionPoints);
}
}
......@@ -78,8 +78,7 @@ public class ModularMultiTypeMovementModel extends ModularMovementModel
suppressListenerNotify = true;
for(ITransitionStrategy strategy : supportedTransitions.values())
{
strategy.setAttractionPoints(transition.getAllAttractionPoints());
{
strategy.addAttractionAssignmentListener(this);
for (SimLocationActuator ms : moveableHosts) {
strategy.addComponent(ms);
......
/*
* 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.attraction;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import de.tud.kom.p2psim.api.scenario.ConfigurationException;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Randoms;
import de.tudarmstadt.maki.simonstrator.api.Time;
import de.tudarmstadt.maki.simonstrator.api.component.network.NetworkComponent.NetInterfaceName;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
import de.tudarmstadt.maki.simonstrator.api.util.XMLConfigurableConstructor;
/**
* Implementation of the interface {@link AttractionGenerator}.
*
* Generates the given number of {@link AttractionPoint}s
*
* @author Julian Zobel
* @version 0.0
*/
public class RandomDynamicAttractionGenerator implements IAttractionGenerator {
private Random rand;
private PositionVector worldDimension;
private int minNumberOfAttractionPoints;
private int maxNumberOfAttractionPoints;
private long minDynamicIntervall;
private long maxDynamicIntervall;
private double minimumDistance = 100;
private double maximumRadius = 100;
private double minimumRadius = 10;
@XMLConfigurableConstructor({"minNumberOfAttractionPoints", "maxNumberOfAttractionPoints", "minimumRadius",
"maximumRadius", "minDynamicIntervall", "maxDynamicIntervall" })
public RandomDynamicAttractionGenerator(int minNumberOfAttractionPoints, int maxNumberOfAttractionPoints,
double minimumRadius, double maximumRadius, long minDynamicIntervall, long maxDynamicIntervall ) {
this.rand = Randoms.getRandom(RandomDynamicAttractionGenerator.class);
this.worldDimension = Binder.getComponentOrNull(Topology.class)
.getWorldDimensions();
if (minNumberOfAttractionPoints <= 0) {
throw new ConfigurationException(
"NumberOfAttractionPoints should be at least 1!");
}
if(minNumberOfAttractionPoints > maxNumberOfAttractionPoints) {
throw new ConfigurationException(
"Minimum and maximum numbers of attraction points not correctly set!");
}
this.minNumberOfAttractionPoints = minNumberOfAttractionPoints;
this.maxNumberOfAttractionPoints = maxNumberOfAttractionPoints;
this.minDynamicIntervall = minDynamicIntervall;
this.maxDynamicIntervall = maxDynamicIntervall;
attractionPoints.clear();
createAttractionPoints();
}
@Override
public List<AttractionPoint> getAttractionPoints() {
return attractionPoints;
}
private int randomNumberOfAttractionPoints() {
return minNumberOfAttractionPoints + rand.nextInt((maxNumberOfAttractionPoints - minNumberOfAttractionPoints) + 1);
}
private void scheduleDynamicEvent(AttractionPoint attractionPoint) {
long r = (long) (rand.nextDouble() * (maxDynamicIntervall - minDynamicIntervall)) + minDynamicIntervall;
Event.scheduleWithDelay(r, new EventHandler() {
@Override
public void eventOccurred(Object content, int type) {
// maybe was already removed...
if(attractionPoints.contains(attractionPoint)) {
attractionPoints.remove(attractionPoint);
createAttractionPoints();
}
}
}, null, 0);
}
protected void createAttractionPoints() {
int numberOfAttractionPoints = randomNumberOfAttractionPoints();
// do nothing if this is the required amount of attraction points
if(numberOfAttractionPoints == attractionPoints.size()) {
return;
}
// remove until this number fits
else if(numberOfAttractionPoints < attractionPoints.size()) {
int deltaAP = attractionPoints.size() - numberOfAttractionPoints;
for(int i = 0; i < deltaAP; i++)
{
int random = rand.nextInt(attractionPoints.size());
attractionPoints.remove(random);
}
return;
}
// add more attraction points until it fits
else {
int deltaAP = numberOfAttractionPoints - attractionPoints.size();
for(int i = 0; i < deltaAP; i++)
{
AttractionPoint newAP = createAttractionPoint();
scheduleDynamicEvent(newAP);
attractionPoints.add(newAP);
}
}
}
private AttractionPoint createAttractionPoint() {
// make a break counter to prevent more than 10 iterations and an infinity loop in general.
int c = 20;
create: for(int i = 0; i < c; i++) {
PositionVector posVec = createPosVec();
// set the radius of this attraction point
// minimum radius is 10 meters
double radius = Math.max(minimumRadius, rand.nextDouble() * maximumRadius);
if(i < c) {
// check if the attraction points would be completely within world dimensions (including radius!)
if((posVec.getX() + radius) >= worldDimension.getX() || (posVec.getY() + radius) >= worldDimension.getY()
|| (posVec.getX() - radius) <= 0 || (posVec.getY() - radius) <= 0) {
continue create;
}
// is within world dimensions, so continue checking against other attraction points
else {
for (AttractionPoint ap : attractionPoints) {
// if this point is closer than the given minimum distance to another point, or the radii of the points would overlap,
// or if the radius would exceed the simulation area
// then discard this attraction point and create a new one
if(posVec.distanceTo(ap) < minimumDistance || (posVec.distanceTo(ap) - radius - ap.getRadius()) < 0) {
continue create;
}
}
}
}
else {
radius = 10;
}
AttractionPoint aPoint = new AttractionPointImpl("AP-" + rand.nextInt(), posVec);
aPoint.setRadius(radius);
return aPoint;
}
return null;
}
private PositionVector createPosVec() {
double x = rand.nextDouble() * worldDimension.getX();
double y = rand.nextDouble() * worldDimension.getY();
return new PositionVector(x, y);
}
/**
* Set a minimum distance between the randomly generated attraction points
* @param distance
*/
public void setMinimumDistance(double distance) {
this.minimumDistance = distance;
}
}
......@@ -44,9 +44,7 @@ import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.Attraction
public abstract class AbstractAttractionBasedTransitionStrategy implements ITransitionStrategy {
protected Random rnd = Randoms.getRandom(AbstractAttractionBasedTransitionStrategy.class);
protected Set<AttractionPoint> attractionPoints = new LinkedHashSet<>();
protected Map<SimLocationActuator, AttractionPoint> assignments = new LinkedHashMap<>();
protected Map<SimLocationActuator, AttractionPoint> lastAssignments = new LinkedHashMap<>();
......@@ -76,18 +74,6 @@ public abstract class AbstractAttractionBasedTransitionStrategy implements ITran
listeners.remove(listener);
}
@Override
public void setAttractionPoints(
Collection<AttractionPoint> attractionPoints) {
this.attractionPoints.clear();
this.attractionPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return Collections.unmodifiableSet(attractionPoints);
}
/**
* Notify all listeners of an updated attraction point assignment for the given component
*
......
......@@ -28,6 +28,7 @@ import de.tud.kom.p2psim.api.common.SimHost;
import de.tud.kom.p2psim.api.common.SimHostComponent;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
/**
......@@ -57,14 +58,14 @@ public class FixedAssignmentStrategy extends AbstractAttractionBasedTransitionSt
// No assignments been done before.
if (assignments.isEmpty()) {
AttractionPoint aPoint = attractionPoints.iterator().next();
AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next();
assignments.put(ms, aPoint);
mappingGroupId(ms, aPoint);
}
// GroupId is not mapped.
else if (!mappingGroupIdAP.containsKey(mappingMSHost.get(ms)
.getProperties().getGroupID())) {
for (AttractionPoint actAP : attractionPoints) {
for (AttractionPoint actAP : IAttractionGenerator.attractionPoints) {
if (!mappingAPGroupId.containsKey(actAP)) {
assignments.put(ms, actAP);
mappingGroupId(ms, actAP);
......
......@@ -46,21 +46,6 @@ public interface ITransitionStrategy {
public void removeAttractionAssignmentListener(AttractionAssignmentListener listener);
/**
* Should be called first, to add the Attraction Points for the assignment!
*
* @param attractionPoints
*/
public void setAttractionPoints(
Collection<AttractionPoint> attractionPoints);
/**
* Return a set of all attraction points
*
* @return
*/
public Set<AttractionPoint> getAllAttractionPoints();
/**
* Add the object and assign the MS to an {@link AttractionPoint}.
*
......
......@@ -26,6 +26,7 @@ import java.util.List;
import java.util.Map;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.ModularMovementModel;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.Time;
......@@ -94,13 +95,28 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
@Override
public void eventOccurred(Object content, int type) {
if(type == EVENT_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
this.addComponent(comp);
if(type == EVENT_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
if(roamingStates.get(comp) == roamingTransitionState.TRANSITION) {
System.out.println("already in transition state!");
}
else {
this.addComponent(comp);
}
}
else if(type == EVENT_ROAMING_PAUSE_ENDED) {
SimLocationActuator comp = (SimLocationActuator) content;
this.roamAroundAttractionPoint(comp);
SimLocationActuator comp = (SimLocationActuator) content;
AttractionPoint currentAttractionPoint = this.assignments.get(comp);
if(!IAttractionGenerator.attractionPoints.contains(currentAttractionPoint)) {
System.out.println("Assigned AP not available!");
this.addComponent(comp);
}
else {
this.roamAroundAttractionPoint(comp);
}
}
}
......@@ -108,7 +124,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
private AttractionPoint getNewAttractionPoint(SimLocationActuator component) {
double score = rnd.nextDouble();
List<AttractionPoint> candidates = new LinkedList<>();
for (AttractionPoint ap : attractionPoints) {
for (AttractionPoint ap : IAttractionGenerator.attractionPoints) {
if (ap.getWeight() >= score) {
if(lastAssignments.get(component) == null || !ap.equals(lastAssignments.get(component))) {
candidates.add(ap);
......@@ -116,7 +132,7 @@ public class InAreaRoamingTransitionStrategy extends AbstractAttractionBasedTran
}
}
if (candidates.isEmpty()) {
candidates.addAll(attractionPoints);
candidates.addAll(IAttractionGenerator.attractionPoints);
}
AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
return assignment;
......
......@@ -40,12 +40,10 @@ public class ManualAssignmentStrategy implements ITransitionStrategy
listeners.remove(listener);
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
aPoints.addAll(attractionPoints);
}
@Override
public Set<AttractionPoint> getAllAttractionPoints() {
return aPoints;
}
......
......@@ -5,6 +5,7 @@ import java.util.Map;
import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.BasicAttractionPoint;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Monitor;
......@@ -48,7 +49,7 @@ public class RandomInAreaTransitionStrategy extends AbstractAttractionBasedTrans
if(!assignments.containsKey(ms))
{
AttractionPoint aPoint = attractionPoints.iterator().next();
AttractionPoint aPoint = IAttractionGenerator.attractionPoints.iterator().next();
assignments.put(ms, aPoint);
currentTarget.put(ms, nextRandomPosition(aPoint, defaultRadius));
currentSearchRadius.put(ms, defaultRadius);
......
......@@ -38,6 +38,7 @@ import de.tud.kom.p2psim.api.topology.Topology;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.api.topology.social.SocialView;
import de.tud.kom.p2psim.impl.simengine.Simulator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tud.kom.p2psim.impl.topology.util.PositionVector;
import de.tudarmstadt.maki.simonstrator.api.Binder;
import de.tudarmstadt.maki.simonstrator.api.Event;
......@@ -131,12 +132,6 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
public void setSocialId(String socialId) {
this.socialId = socialId;
}
@Override
public void setAttractionPoints(Collection<AttractionPoint> attractionPoints) {
init();
super.setAttractionPoints(attractionPoints);
}
@Override
public void addComponent(SimLocationActuator ms) {
......@@ -146,8 +141,8 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
// position.
// TODO: needed? We do Transition as next, and this will delete the
// assignment..
AttractionPoint nearest = attractionPoints.iterator().next();
for (AttractionPoint aPoint : attractionPoints) {
AttractionPoint nearest = IAttractionGenerator.attractionPoints.iterator().next();
for (AttractionPoint aPoint : IAttractionGenerator.attractionPoints) {
if (nearest.distanceTo(ms.getRealPosition()) > aPoint
.distanceTo(ms.getRealPosition())) {
nearest = aPoint;
......@@ -181,7 +176,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
List<AttractionPoint> apFriends = getFriendsPlaces(ms);
List<AttractionPoint> apClusters = getClusterPlaces(ms);
List<AttractionPoint> apRandom = getRandomPlaces(ms,
(int) Math.max(attractionPoints.size() * 0.2, 5));
(int) Math.max(IAttractionGenerator.attractionPoints.size() * 0.2, 5));
AttractionPoint ap = null;
if (rnd.nextDouble() < socialFactor) {
......@@ -299,7 +294,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
private List<AttractionPoint> getRandomPlaces(SimLocationActuator ms,
int number) {
List<AttractionPoint> result = new Vector<AttractionPoint>(attractionPoints);
List<AttractionPoint> result = new Vector<AttractionPoint>(IAttractionGenerator.attractionPoints);
Collections.shuffle(result, rnd);
return result.subList(0, Math.min(result.size(), number));
}
......@@ -339,7 +334,7 @@ public class SocialTransitionStrategy extends AbstractAttractionBasedTransitionS
private void assignFavoritePlaces(SimLocationActuator ms) {
Set<AttractionPoint> msFavoritePlaces = new LinkedHashSet<AttractionPoint>();
LinkedList<AttractionPoint> temp = new LinkedList<AttractionPoint>(
attractionPoints);
IAttractionGenerator.attractionPoints);
Collections.shuffle(temp, rnd);
for (int i = 0; i < numberOfFavoritePlaces; i++) {
if (!temp.isEmpty()) {
......
......@@ -23,6 +23,7 @@ package de.tud.kom.p2psim.impl.topology.movement.modularosm.transition;
import java.util.LinkedList;
import java.util.List;
import de.tud.kom.p2psim.api.topology.movement.SimLocationActuator;
import de.tud.kom.p2psim.impl.topology.movement.modularosm.attraction.IAttractionGenerator;
import de.tudarmstadt.maki.simonstrator.api.Event;
import de.tudarmstadt.maki.simonstrator.api.EventHandler;
import de.tudarmstadt.maki.simonstrator.api.component.sensor.location.AttractionPoint;
......@@ -50,13 +51,13 @@ public class WeightedTransitionStrategy extends AbstractAttractionBasedTransitio
private AttractionPoint getNewAssignment(SimLocationActuator component) {
double score = rnd.nextDouble();
List<AttractionPoint> candidates = new LinkedList<>();
for (AttractionPoint ap : attractionPoints) {
for (AttractionPoint ap : IAttractionGenerator.attractionPoints) {
if (ap.getWeight() >= score) {
candidates.add(ap);
}
}
if (candidates.isEmpty()) {
candidates.addAll(attractionPoints);
candidates.addAll(IAttractionGenerator.attractionPoints);
}
AttractionPoint assignment = candidates.get(rnd.nextInt(candidates.size()));
notifyListenersOfAssignmentUpdate(component, assignment);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment