Commit cf4ab731 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

testing parallel event driven update.

parent 750034d9
......@@ -104,6 +104,9 @@ public class MeshPanel<P extends IPoint, V extends IVertex<P>, E extends IHalfEd
this(mesh, f -> false, width, height, f -> Color.WHITE);
}
public MeshRenderer<P, V, E, F> getMeshRenderer() {
return meshRenderer;
}
@Override
public void paint(Graphics g) {
......@@ -120,7 +123,7 @@ public class MeshPanel<P extends IPoint, V extends IVertex<P>, E extends IHalfEd
jFrame.setSize((int)width+10, (int)height+10);
jFrame.add(this);
jFrame.setTitle(title);
jFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
jFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
setVisible(true);
jFrame.setVisible(true);
repaint();
......
......@@ -119,7 +119,7 @@ public class MeshRenderer<P extends IPoint, V extends IVertex<P>, E extends IHal
Color c = graphics.getColor();
Stroke stroke = graphics.getStroke();
synchronized (mesh) {
faces = mesh.clone().getFaces();
faces = mesh.getFaces();
}
graphics.translate(-bound.getMinX() * scale, -bound.getMinY() * scale);
......@@ -141,7 +141,10 @@ public class MeshRenderer<P extends IPoint, V extends IVertex<P>, E extends IHal
graphics.setColor(colorFunction.apply(face));
graphics.fill(polygon);
}
else {
graphics.setColor(Color.WHITE);
graphics.fill(polygon);
}
if(alertPred.test(face)) {
graphics.setColor(Color.RED);
......@@ -176,4 +179,7 @@ public class MeshRenderer<P extends IPoint, V extends IVertex<P>, E extends IHal
return image;
}
public void setMesh(IMesh<P, V, E, F> mesh) {
this.mesh = mesh;
}
}
package org.vadere.meshing.mesh.triangulation.triangulator;
import org.vadere.meshing.mesh.gen.IncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IFace;
import org.vadere.meshing.mesh.inter.IHalfEdge;
import org.vadere.meshing.mesh.inter.IIncrementalTriangulation;
import org.vadere.meshing.mesh.inter.IMesh;
import org.vadere.meshing.mesh.inter.IPointLocator;
import org.vadere.meshing.mesh.inter.IVertex;
import org.vadere.util.geometry.shapes.IPoint;
......@@ -41,6 +44,16 @@ public class PointSetTriangulator<P extends IPoint, V extends IVertex<P>, E exte
this.points = points;
}
/**
* <p>The default constructor.</p>
*
* @param points the collection of points P
*/
public PointSetTriangulator(final Collection<P> points, IMesh<P, V, E, F> mesh) {
this.triangulation = new IncrementalTriangulation<>(mesh, IPointLocator.Type.JUMP_AND_WALK, points);
this.points = points;
}
@Override
public IIncrementalTriangulation<P, V, E, F> generate() {
triangulation.init();
......
......@@ -9,6 +9,7 @@ import org.vadere.state.scenario.Obstacle;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.util.geometry.shapes.VLine;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.logging.Logger;
import java.util.List;
......@@ -19,12 +20,15 @@ import java.util.List;
public class PotentialEvaluationFunction implements UnivariateRealFunction,
MultivariateRealFunction, MultivariateFunction {
private static Logger logger = Logger.getLogger(PotentialEvaluationFunction.class);
/** The pedestrian. */
private final PedestrianOSM pedestrian;
/** The step size. */
private double stepSize;
private double minStepSize;
private static int evaluationCounter = 0;
public int counter;
......@@ -73,6 +77,10 @@ public class PotentialEvaluationFunction implements UnivariateRealFunction,
VPoint pedPos = pedestrian.getPosition();
VPoint newPos = new VPoint(stepSize * Math.cos(angle) + pedPos.x,
stepSize * Math.sin(angle) + pedPos.y);
evaluationCounter++;
/*if(evaluationCounter % 100 == 0) {
logger.debugf("#evaluations: " + evaluationCounter);
}*/
return pedestrian.getPotential(newPos);
}
......@@ -145,6 +153,10 @@ public class PotentialEvaluationFunction implements UnivariateRealFunction,
final double tolInsideCircle = 0.00001;
if (sqx + sqy <= sqss + tolInsideCircle) {
result = pedestrian.getPotential(newPos);
evaluationCounter++;
/*if(evaluationCounter % 100 == 0) {
logger.debugf("#evaluations: " + evaluationCounter);
}*/
}
counter++;
return result;
......
......@@ -7,12 +7,15 @@ import org.apache.commons.math.optimization.MultivariateRealOptimizer;
import org.apache.commons.math.optimization.direct.DirectSearchOptimizer;
import org.apache.commons.math.optimization.direct.NelderMead;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.VCircle;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.logging.Logger;
import java.awt.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
/**
......@@ -25,9 +28,11 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
.getLogger(StepCircleOptimizerNelderMead.class);
private final Random random;
private Map<PedestrianOSM, VPoint> lastSolution;
public StepCircleOptimizerNelderMead(Random random) {
this.random = random;
this.lastSolution = new HashMap<>();
}
@Override
......@@ -35,7 +40,6 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
double stepSize = ((VCircle) reachableArea).getRadius();
List<VPoint> positions = StepCircleOptimizerDiscrete.getReachablePositions(pedestrian, (VCircle)reachableArea, random);
PotentialEvaluationFunction potentialEvaluationFunction = new PotentialEvaluationFunction(pedestrian);
potentialEvaluationFunction.setStepSize(stepSize);
......@@ -48,14 +52,24 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
double step = stepSize / 2;
double threshold = 0.0001;
MultivariateRealOptimizer optimizer = new NelderMead();
NelderMead optimizer = new NelderMead();
try {
/*if(lastSolution.containsKey(pedestrian)) {
VPoint optimum = lastSolution.get(pedestrian).add(pedestrian.getPosition());
if(isLocalMinimum(potentialEvaluationFunction, (VCircle) reachableArea, optimum)) {
logger.info("quick solution found.");
return optimum;
}
}*/
//minimum = position;
double[][] simplex = new double[][] {{0, 0}, {step, step}, {step, -step}};
((DirectSearchOptimizer) optimizer).setStartConfiguration(simplex);
optimizer.setStartConfiguration(simplex);
optimizer.setConvergenceChecker(new NelderMeadConvergenceChecker());
newMinimum = optimizer.optimize(potentialEvaluationFunction, GoalType.MINIMIZE, minimum).getPoint();
newMinimum = optimizer.optimize(potentialEvaluationFunction, GoalType.MINIMIZE, position).getPoint();
//logger.info("["+0+","+0+"],["+step+","+step+"],["+step+","+(-step)+")]");
newMinimumValue = potentialEvaluationFunction.value(newMinimum);
int counter = 0;
......@@ -93,7 +107,9 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
simplex[2][0] = Math.min(step, outerDistance) * outerDirection.getX();
simplex[2][1] = Math.min(step, outerDistance) * outerDirection.getY();
((DirectSearchOptimizer) optimizer).setStartConfiguration(simplex);
//logger.info("["+simplex[0][0]+","+simplex[0][1]+"],["+simplex[1][0]+","+simplex[1][1]+"],["+simplex[2][0]+","+simplex[2][1]+")]");
optimizer.setStartConfiguration(simplex);
optimizer.setConvergenceChecker(new NelderMeadConvergenceChecker());
newMinimum = optimizer.optimize(potentialEvaluationFunction,
......@@ -105,6 +121,7 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
if ((minimumValue > newMinimumValue && Math.abs(minimumValue - newMinimumValue) > threshold)) {
minimumValue = newMinimumValue;
minimum = newMinimum;
//logger.info("new min: ["+minimum[0]+","+minimum[1]+"]");
}
}
......@@ -113,6 +130,8 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
logger.error(e);
}
// System.out.println(potentialEvaluationFunction.counter);
//logger.info("["+(minimum[0]-pedestrian.getPosition().getX())+","+(minimum[1]-pedestrian.getPosition().getY())+"]");
//lastSolution.put(pedestrian, new VPoint(minimum[0]-pedestrian.getPosition().getX(), minimum[1]-pedestrian.getPosition().getY()));
return new VPoint(minimum[0], minimum[1]);
}
......@@ -120,4 +139,18 @@ public class StepCircleOptimizerNelderMead implements StepCircleOptimizer {
public StepCircleOptimizer clone() {
return new StepCircleOptimizerNelderMead(random);
}
private boolean isLocalMinimum(PotentialEvaluationFunction evaluationFunction, VCircle stepDisc, VPoint optimum) throws FunctionEvaluationException {
double delta = 0.0001;
double angle = 0.05 * 2 * Math.PI;
double value = evaluationFunction.getValue(optimum);
for(double angleDelta = 0; angleDelta <= 2 * Math.PI; angleDelta += angle) {
VPoint newPoint = optimum.add(new VPoint(delta, 0).rotate(angleDelta));
if(stepDisc.contains(newPoint) && evaluationFunction.getValue(newPoint) < value) {
return false;
}
}
return evaluationFunction.getValue(stepDisc.getCenter()) > value;
}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.meshing.mesh.gen.MeshPanel;
import org.vadere.meshing.mesh.gen.PFace;
import org.vadere.meshing.mesh.gen.PHalfEdge;
import org.vadere.meshing.mesh.gen.PMesh;
import org.vadere.meshing.mesh.gen.PVertex;
import org.vadere.meshing.mesh.triangulation.triangulator.PointSetTriangulator;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.DataPoint;
import org.vadere.util.geometry.LinkedCellsGrid;
import org.vadere.util.geometry.shapes.IPoint;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.geometry.shapes.VRectangle;
import org.vadere.util.logging.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
......@@ -18,16 +31,25 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
private LinkedCellsGrid<PedestrianOSM> linkedCellsGrid;
private boolean[][] locked;
private double pedestrianPotentialWidth;
private Map<PedestrianOSM, PVertex<PedestrianPoint>> map;
private PMesh<PedestrianPoint> mesh;
private MeshPanel<PedestrianPoint, PVertex<PedestrianPoint>, PHalfEdge<PedestrianPoint>, PFace<PedestrianPoint>> panel;
public UpdateSchemeEventDrivenParallel(@NotNull final Topography topography, @NotNull final double pedestrianPotentialWidth) {
super(topography);
this.topography = topography;
this.pedestrianPotentialWidth = pedestrianPotentialWidth;
this.map = new HashMap<>();
}
@Override
public void update(final double timeStepInSec, final double currentTimeInSec) {
int count = 0;
// construct delaunay triangulation
/*for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) {
pedestrianOSM.clearStrides();
......@@ -54,8 +76,32 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
int counter = 1;
// event driven update ignores time credits
do{
mesh = new PMesh<>((x, y) -> new PedestrianPoint(new VPoint(x,y), null));
Collection<PedestrianPoint> pedPoints = topography.getElements(PedestrianOSM.class)
.stream()
.map(ped -> new PedestrianPoint(ped.getPosition(), ped))
.collect(Collectors.toList());
PointSetTriangulator<PedestrianPoint, PVertex<PedestrianPoint>, PHalfEdge<PedestrianPoint>, PFace<PedestrianPoint>> triangulator
= new PointSetTriangulator<>(pedPoints, mesh);
triangulator.generate();
if(panel == null) {
panel = new MeshPanel<>(mesh, 1000, 1000);
panel.display();
}
else {
panel.getMeshRenderer().setMesh(mesh);
}
for(PVertex<PedestrianPoint> pedestrianPoint : mesh.getVertices()) {
map.put(mesh.getPoint(pedestrianPoint).pedestrianOSM, pedestrianPoint);
}
panel.repaint();
double stepSize = Math.max(maxStepSize, maxDesiredSpeed * timeStepInSec);
linkedCellsGrid = new LinkedCellsGrid<>(new VRectangle(topography.getBounds()), 2*(pedestrianPotentialWidth + stepSize));
linkedCellsGrid = new LinkedCellsGrid<>(new VRectangle(topography.getBounds()), (pedestrianPotentialWidth));
locked = new boolean[linkedCellsGrid.getGridWidth()][linkedCellsGrid.getGridHeight()];
List<PedestrianOSM> parallelUpdatablePeds = new ArrayList<>();
......@@ -65,32 +111,163 @@ public class UpdateSchemeEventDrivenParallel extends UpdateSchemeEventDriven {
PedestrianOSM ped = pedestrianEventsQueue.poll();
int[] gridPos = linkedCellsGrid.gridPos(ped.getPosition());
if(!locked[gridPos[0]][gridPos[1]]) {
boolean requiresUpdate = requireUpdate(ped);
if(!locked[gridPos[0]][gridPos[1]] && requiresUpdate) {
parallelUpdatablePeds.add(ped);
}
else {
else if(requiresUpdate) {
unUpdatablePedsd.add(ped);
}
for(int y = -1; y <= 1; y++) {
for(int x = -1; x <= 1; x++) {
int col = Math.min(locked.length-1, Math.max(0, gridPos[0]+x));
int row = Math.min(locked[0].length-1, Math.max(0, gridPos[1]+y));
locked[col][row] = true;
if(requiresUpdate) {
for(int y = -1; y <= 1; y++) {
for(int x = -1; x <= 1; x++) {
int col = Math.min(locked.length-1, Math.max(0, gridPos[0]+x));
int row = Math.min(locked[0].length-1, Math.max(0, gridPos[1]+y));
locked[col][row] = true;
}
}
}
if(!requiresUpdate) {
double stepDuration = ped.getDurationNextStep();
ped.setTimeOfNextStep(ped.getTimeOfNextStep() + stepDuration);
pedestrianEventsQueue.add(ped);
count++;
}
}
logger.info("update " + parallelUpdatablePeds.size() + " in parallel in round " + counter + ".");
parallelUpdatablePeds.parallelStream().forEach(ped -> {
//logger.info("update " + parallelUpdatablePeds.size() + " in parallel in round " + counter + ".");
parallelUpdatablePeds.stream().forEach(ped -> {
//logger.info(ped.getTimeOfNextStep());
//System.out.println(ped.getId());
update(ped, currentTimeInSec);
});
pedestrianEventsQueue.addAll(unUpdatablePedsd);
pedestrianEventsQueue.addAll(parallelUpdatablePeds);
counter++;
} while (!pedestrianEventsQueue.isEmpty() && pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec);
logger.info("avoided updates: " + count);
}
private boolean requireUpdate(PedestrianOSM pedestrianOSM) {
PVertex<PedestrianPoint> vertex = map.get(pedestrianOSM);
if(mesh.getPoint(vertex).hasChanged()) {
return true;
}
for(PVertex<PedestrianPoint> v : mesh.getAdjacentVertexIt(vertex)) {
if(mesh.getPoint(v).hasChanged()) {
return true;
}
}
return false;
}
private class PedestrianPoint implements IPoint {
private final PedestrianOSM pedestrianOSM;
private final VPoint point;
public PedestrianPoint(VPoint point, PedestrianOSM pedestrianOSM) {
this.point = point;
this.pedestrianOSM = pedestrianOSM;
}
private boolean hasChanged() {
//System.out.println(pedestrianOSM.getFootSteps().getFootSteps().size());
return pedestrianOSM.getFootSteps().isEmpty() || pedestrianOSM.getFootSteps().getFootSteps().peekLast().length() > 0;
}
@Override
public double getX() {
return point.getX();
}
@Override
public double getY() {
return point.getY();
}
@Override
public IPoint add(IPoint point) {
return this.point.add(point);
}
@Override
public IPoint addPrecise(IPoint point) {
return this.point.addPrecise(point);
}
@Override
public IPoint subtract(IPoint point) {
return this.point.subtract(point);
}
@Override
public IPoint multiply(IPoint point) {
return this.point.multiply(point);
}
@Override
public IPoint scalarMultiply(double factor) {
return this.point.scalarMultiply(factor);
}
@Override
public IPoint rotate(double radAngle) {
return this.point.rotate(radAngle);
}
@Override
public double scalarProduct(IPoint point) {
return this.point.scalarProduct(point);
}
@Override
public IPoint norm() {
return this.point.norm();
}
@Override
public IPoint norm(double len) {
return this.point.norm(len);
}
@Override
public IPoint normZeroSafe() {
return this.point.normZeroSafe();
}
@Override
public double distance(IPoint other) {
return this.point.distance(other);
}
@Override
public double distance(double x, double y) {
return this.point.distance(x, y);
}
@Override
public double distanceSq(IPoint other) {
return this.point.distanceSq(other);
}
@Override
public double distanceSq(double x, double y) {
return this.point.distanceSq(x, y);
}
@Override
public double distanceToOrigin() {
return this.point.distanceToOrigin();
}
@Override
public PedestrianPoint clone() {
return new PedestrianPoint(this.point, pedestrianOSM.clone());
}
}
}
......@@ -46,7 +46,7 @@ public interface UpdateSchemeOSM extends DynamicElementRemoveListener<Pedestrian
case EVENT_DRIVEN: return new UpdateSchemeEventDriven(topography);
case SHUFFLE: return new UpdateSchemeShuffle(topography, random);
//TODO: magic number!
case EVENT_DRIVEN_PARALLEL: return new UpdateSchemeEventDrivenParallel(topography, 0.6);
case EVENT_DRIVEN_PARALLEL: return new UpdateSchemeEventDrivenParallel(topography, 1.4);
default: throw new IllegalArgumentException(updateType + " is not supported.");
}
}
......
......@@ -4,6 +4,7 @@ import org.jetbrains.annotations.NotNull;
import org.vadere.util.geometry.GeometryUtils;
import org.vadere.util.geometry.shapes.ICircleSector;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.logging.Logger;
import java.util.List;
import java.util.Random;
......@@ -22,12 +23,14 @@ public class PSO {
private double gBest;
private double gLastBest;
private VPoint gBestLocation;
private final Function<VPoint, Double> f;
private final Function<VPoint, Double> evaluationFunction;
private int iterationCounter;
private final double maxVelocity;
private final double minAngle;
private final double maxAngle;
private int improvementIterations;
private static Logger logger = Logger.getLogger(PSO.class);
private static int evaluationCounter = 0;
public PSO(
@NotNull final Function<VPoint, Double> f,
......@@ -37,7 +40,7 @@ public class PSO {
@NotNull final Random random,
@NotNull final double maxVelocity,
@NotNull final List<VPoint> swarmPositions) {
this.f = f;
this.evaluationFunction = f;
this.random = random;
this.circle = circle;
this.gBest = Double.MAX_VALUE;
......@@ -113,7 +116,11 @@ public class PSO {
particle.setVelocity(particle.getVelocity().scalarMultiply(-0.5));
particle.setLocation(circle.getClosestIntersectionPoint(currentLocation, particle.getLocation(), particle.getLocation()).orElse(particle.getLocation()));
}
particle.setFitnessValue(f.apply(particle.getLocation()));
particle.setFitnessValue(evaluationFunction.apply(particle.getLocation()));
evaluationCounter++;
if(evaluationCounter % 100 == 0) {
logger.debugf("#evaluations: " + evaluationCounter);
}
}
/**
......@@ -219,7 +226,7 @@ public class PSO {
/*private Particle locationToParticle(@NotNull final VPoint location) {
double vMag = random.nextDouble() * maxVelocity;
VPoint velocity = location.subtract(circle.getCenter()).setMagnitude(vMag).limit(maxVelocity);
double fitnessValue = f.apply(location);
double fitnessValue = evaluationFunction.apply(location);
return new Particle(location, velocity, fitnessValue);
}*/
......@@ -229,7 +236,11 @@ public class PSO {
VPoint v = new VPoint(Math.cos(vDelta), Math.sin(vDelta)).setMagnitude(vMag);
VPoint velocity = v.subtract(location).scalarMultiply(0.5).limit(maxVelocity);
double fitnessValue = f.apply(location);
double fitnessValue = evaluationFunction.apply(location);
evaluationCounter++;
/*if(evaluationCounter % 100 == 0) {
logger.debugf("#evaluations: " + evaluationCounter);
}*/
return new Particle(location, velocity, fitnessValue);
}
}
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