24.09., 9:00 - 11:00: Due to updates GitLab will be unavailable for some minutes between 09:00 and 11:00.

Commit 3caca386 authored by Benedikt Zoennchen's avatar Benedikt Zoennchen

refactoring of the event driven schemes such that the whole control is at the scheme itself.

parent a05afafa
......@@ -20,6 +20,7 @@ import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerGradient;
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerNelderMead;
import org.vadere.simulator.models.osm.optimization.StepCircleOptimizerPowell;
import org.vadere.simulator.models.osm.updateScheme.ParallelWorkerOSM;
import org.vadere.simulator.models.osm.updateScheme.UpdateSchemeOSM;
import org.vadere.simulator.models.osm.updateScheme.UpdateSchemeOSM.CallMethod;
import org.vadere.simulator.models.potential.PotentialFieldModel;
import org.vadere.simulator.models.potential.fields.IPotentialFieldTarget;
......@@ -36,24 +37,20 @@ import org.vadere.state.scenario.Topography;
import org.vadere.state.types.OptimizationType;
import org.vadere.state.types.UpdateType;
import org.vadere.util.geometry.shapes.VPoint;
import org.vadere.util.io.ListUtils;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.PriorityQueue;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
@ModelClass(isMainModel = true)
public class OptimalStepsModel implements MainModel, PotentialFieldModel, DynamicElementRemoveListener<Pedestrian> {
private UpdateSchemeOSM updateSchemeOSM;
private AttributesOSM attributesOSM;
private AttributesAgent attributesPedestrian;
private Random random;
......@@ -65,7 +62,6 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
private Topography topography;
private double lastSimTimeInSec;
private int pedestrianIdCounter;
private PriorityQueue<PedestrianOSM> pedestrianEventsQueue;
private ExecutorService executorService;
private List<Model> models = new LinkedList<>();
public OptimalStepsModel() {
......@@ -81,6 +77,9 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
this.topography = topography;
this.random = random;
this.attributesPedestrian = attributesPedestrian;
this.updateSchemeOSM = UpdateSchemeOSM.create(attributesOSM.getUpdateType(), topography, random);
this.topography.addElementAddedListener(Pedestrian.class, updateSchemeOSM);
this.topography.addElementRemovedListener(Pedestrian.class, updateSchemeOSM);
final SubModelBuilder subModelBuilder = new SubModelBuilder(modelAttributesList, topography,
attributesPedestrian, random);
......@@ -121,14 +120,6 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
this.speedAdjusters.add(new SpeedAdjusterWeidmann());
}
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN) {
this.pedestrianEventsQueue = new PriorityQueue<>(100,
new ComparatorPedestrianOSM());
} else {
// not needed and should not be used in this case
this.pedestrianEventsQueue = null;
}
if (attributesOSM.getUpdateType() == UpdateType.PARALLEL) {
this.executorService = Executors.newFixedThreadPool(8);
} else {
......@@ -193,72 +184,9 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
@Override
public void update(final double simTimeInSec) {
final double timeStepInSec = simTimeInSec - this.lastSimTimeInSec;
// event driven update
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN
&& !pedestrianEventsQueue.isEmpty()) {
while (pedestrianEventsQueue.peek().getTimeOfNextStep() < simTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll();
ped.update(timeStepInSec, simTimeInSec, CallMethod.EVENT_DRIVEN);
pedestrianEventsQueue.add(ped);
}
} else {
// time step length
// parallel update
if (attributesOSM.getUpdateType() == UpdateType.PARALLEL) {
parallelCall(timeStepInSec);
} else {
List<PedestrianOSM> pedestrians = ListUtils.select(
topography.getElements(Pedestrian.class), PedestrianOSM.class);
// random shuffle update
if (attributesOSM.getUpdateType() == UpdateType.SHUFFLE) {
Collections.shuffle(pedestrians, this.random);
}
// default is fixed order sequential update
for (PedestrianOSM pedestrian : pedestrians) {
pedestrian.update(timeStepInSec, -1, CallMethod.SEQUENTIAL);
}
}
this.lastSimTimeInSec = simTimeInSec;
}
}
private void parallelCall(double timeStepInSec) {
CallMethod[] callMethods = {CallMethod.SEEK, CallMethod.MOVE, CallMethod.CONFLICTS, CallMethod.STEPS};
List<Future<?>> futures;
for (CallMethod callMethod : callMethods) {
futures = new LinkedList<>();
for (final PedestrianOSM pedestrian : ListUtils.select(
topography.getElements(Pedestrian.class), PedestrianOSM.class)) {
Runnable worker = new ParallelWorkerOSM(callMethod, pedestrian,
timeStepInSec);
futures.add(executorService.submit(worker));
}
collectFutures(futures);
}
}
private void collectFutures(final List<Future<?>> futures) {
try {
for (Future<?> future : futures) {
future.get();
}
} catch (ExecutionException e) {
e.printStackTrace();
}
// restore interruption in order to stop simulation
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
double timeStepInSec = simTimeInSec - this.lastSimTimeInSec;
updateSchemeOSM.update(timeStepInSec, simTimeInSec);
lastSimTimeInSec = simTimeInSec;
}
/*
......@@ -280,10 +208,6 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
pedestrian.setPosition(position);
if (attributesOSM.getUpdateType() == UpdateType.EVENT_DRIVEN) {
this.pedestrianEventsQueue.add(pedestrian);
}
return pedestrian;
}
......@@ -308,11 +232,7 @@ public class OptimalStepsModel implements MainModel, PotentialFieldModel, Dynami
}
@Override
public void elementRemoved(Pedestrian ped) {
PedestrianOSM osmPed = (PedestrianOSM) ped;
pedestrianEventsQueue.remove(osmPed);
// System.out.printf("Remove ped %s from pedestrianEventsQueue%n", ped.getId());
}
public void elementRemoved(Pedestrian ped) {}
@Override
public SourceControllerFactory getSourceControllerFactory() {
......
......@@ -34,7 +34,6 @@ public class PedestrianOSM extends Pedestrian {
private final AttributesOSM attributesOSM;
private final transient StepCircleOptimizer stepCircleOptimizer;
private final transient UpdateSchemeOSM updateScheme;
private final transient Topography topography;
private final double stepLength;
private final double stepDeviation;
......@@ -77,7 +76,6 @@ public class PedestrianOSM extends Pedestrian {
this.potentialFieldObstacle = potentialFieldObstacle;
this.potentialFieldPedestrian = potentialFieldPedestrian;
this.stepCircleOptimizer = stepCircleOptimizer;
this.updateScheme = createUpdateScheme(attributesOSM.getUpdateType(), this);
this.speedAdjusters = speedAdjusters;
this.relevantPedestrians = new HashSet<>();
......@@ -95,31 +93,12 @@ public class PedestrianOSM extends Pedestrian {
this.minStepLength = 0;
}
this.lastPosition = getPosition();
this.nextPosition = getPosition();
this.strides = new LinkedList<>();
}
private static UpdateSchemeOSM createUpdateScheme(UpdateType updateType, PedestrianOSM pedestrian) {
UpdateSchemeOSM result;
switch (updateType) {
case EVENT_DRIVEN:
result = new UpdateSchemeEventDriven(pedestrian);
break;
case PARALLEL:
result = new UpdateSchemeParallel(pedestrian);
break;
case SEQUENTIAL:
result = new UpdateSchemeSequential(pedestrian);
break;
default:
result = new UpdateSchemeSequential(pedestrian);
}
return result;
}
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
/*public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
double lastSimTimeInSec = currentTimeInSec - timeStepInSec;
// clear the old strides to avoid large linked lists
......@@ -128,7 +107,7 @@ public class PedestrianOSM extends Pedestrian {
}
this.updateScheme.update(timeStepInSec, currentTimeInSec, callMethod);
}
}*/
public void updateNextPosition() {
......
......@@ -18,7 +18,7 @@ public class ParallelWorkerOSM implements Runnable {
@Override
public void run() {
ped.update(timeStepInSec, -1, callMethod);
//ped.update(timeStepInSec, -1, callMethod);
}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Topography;
/**
* @author Benedikt Zoennchen
*/
public class UpdateSchemeCLParellel extends UpdateSchemeParallel {
public UpdateSchemeCLParellel(@NotNull final Topography pedestrian) {
super(pedestrian);
}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import java.util.Comparator;
import java.util.PriorityQueue;
public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
private final PedestrianOSM pedestrian;
private final Topography topography;
private PriorityQueue<PedestrianOSM> pedestrianEventsQueue;
public UpdateSchemeEventDriven(PedestrianOSM pedestrian) {
this.pedestrian = pedestrian;
public UpdateSchemeEventDriven(@NotNull final Topography topography) {
this.topography = topography;
this.pedestrianEventsQueue = new PriorityQueue<>(100, new ComparatorPedestrianOSM());
this.pedestrianEventsQueue.addAll(topography.getElements(PedestrianOSM.class));
}
@Override
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
public void update(final double timeStepInSec, final double currentTimeInSec) {
for(PedestrianOSM pedestrianOSM : topography.getElements(PedestrianOSM.class)) {
pedestrianOSM.clearStrides();
}
if(!pedestrianEventsQueue.isEmpty()) {
// default is fixed order sequential update
while (pedestrianEventsQueue.peek().getTimeOfNextStep() < currentTimeInSec) {
PedestrianOSM ped = pedestrianEventsQueue.poll();
update(ped, currentTimeInSec);
pedestrianEventsQueue.add(ped);
}
}
}
private void update(@NotNull final PedestrianOSM pedestrian, final double currentTimeInSec) {
// for the first step after creation, timeOfNextStep has to be initialized
if (pedestrian.getTimeOfNextStep() == 0) {
pedestrian.setTimeOfNextStep(currentTimeInSec);
......@@ -24,4 +47,29 @@ public class UpdateSchemeEventDriven implements UpdateSchemeOSM {
pedestrian.setTimeOfNextStep(pedestrian.getTimeOfNextStep() + pedestrian.getDurationNextStep());
}
@Override
public void elementRemoved(@NotNull final Pedestrian element) {
pedestrianEventsQueue.remove(element);
}
@Override
public void elementAdded(final Pedestrian element) {
pedestrianEventsQueue.add((PedestrianOSM) element);
}
/**
* Compares the time of the next possible move.
*/
private class ComparatorPedestrianOSM implements Comparator<PedestrianOSM> {
@Override
public int compare(PedestrianOSM ped1, PedestrianOSM ped2) {
// TODO [priority=low] [task=refactoring] use Double.compare() oder compareTo()
if (ped1.getTimeOfNextStep() < ped2.getTimeOfNextStep()) {
return -1;
} else {
return 1;
}
}
}
}
package org.vadere.simulator.models.osm.updateScheme;
public interface UpdateSchemeOSM {
import org.jetbrains.annotations.NotNull;
import org.vadere.state.scenario.DynamicElementAddListener;
import org.vadere.state.scenario.DynamicElementRemoveListener;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.state.types.UpdateType;
public enum CallMethod {
import java.util.Random;
public interface UpdateSchemeOSM extends DynamicElementRemoveListener<Pedestrian>, DynamicElementAddListener<Pedestrian> {
enum CallMethod {
SEEK, MOVE, CONFLICTS, STEPS, RETRY, SEQUENTIAL, EVENT_DRIVEN
}
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod);
void update(double timeStepInSec, double currentTimeInSec);
static UpdateSchemeOSM create(@NotNull final UpdateType updateType, @NotNull final Topography topography, final Random random) {
switch (updateType) {
case SEQUENTIAL: return new UpdateSchemeSequential(topography);
case PARALLEL: return new UpdateSchemeParallel(topography);
case EVENT_DRIVEN: return new UpdateSchemeEventDriven(topography);
case SHUFFLE: return new UpdateSchemeShuffle(topography, random);
default: throw new IllegalArgumentException(updateType + " is not supported.");
}
}
}
package org.vadere.simulator.models.osm.updateScheme;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Agent;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import org.vadere.util.geometry.Vector2D;
import org.vadere.util.io.ListUtils;
public class UpdateSchemeParallel implements UpdateSchemeOSM {
private final PedestrianOSM pedestrian;
private boolean isMoving;
private ExecutorService executorService;
private final Topography topography;
private Set<Pedestrian> movedPedestrians;
public UpdateSchemeParallel(PedestrianOSM pedestrian) {
this.pedestrian = pedestrian;
public UpdateSchemeParallel(@NotNull final Topography topography) {
this.topography = topography;
this.executorService = Executors.newSingleThreadExecutor();
this.movedPedestrians = new HashSet<>();
}
@Override
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
public void update(double timeStepInSec, double currentTimeInSec) {
movedPedestrians.clear();
CallMethod[] callMethods = {CallMethod.SEEK, CallMethod.MOVE, CallMethod.CONFLICTS, CallMethod.STEPS};
List<Future<?>> futures;
for (CallMethod callMethod : callMethods) {
futures = new LinkedList<>();
for (final PedestrianOSM pedestrian : ListUtils.select(topography.getElements(Pedestrian.class), PedestrianOSM.class)) {
Runnable worker = () -> update(pedestrian, timeStepInSec, currentTimeInSec, callMethod);
futures.add(executorService.submit(worker));
}
collectFutures(futures);
}
}
private void collectFutures(final List<Future<?>> futures) {
try {
for (Future<?> future : futures) {
future.get();
}
} catch (ExecutionException e) {
e.printStackTrace();
}
// restore interruption in order to stop simulation
catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void update(@NotNull final PedestrianOSM pedestrian, final double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
pedestrian.clearStrides();
switch (callMethod) {
case SEEK:
updateParallelSeek(timeStepInSec);
updateParallelSeek(pedestrian, timeStepInSec);
break;
case RETRY:
updateParallelSeek(0.0);
updateParallelSeek(pedestrian,0.0);
case MOVE:
updateParallelMove(timeStepInSec);
updateParallelMove(pedestrian, timeStepInSec);
break;
case CONFLICTS:
updateParallelConflicts(timeStepInSec);
updateParallelConflicts(pedestrian, timeStepInSec);
break;
case STEPS:
updateParallelSteps(timeStepInSec);
updateParallelSteps(pedestrian, timeStepInSec);
break;
default:
throw new UnsupportedOperationException();
}
}
protected void updateParallelSeek(double timeStepInSec) {
protected void updateParallelSeek(@NotNull final PedestrianOSM pedestrian, double timeStepInSec) {
pedestrian.setTimeCredit(pedestrian.getTimeCredit() + timeStepInSec);
pedestrian.setDurationNextStep(pedestrian.getStepSize() / pedestrian.getDesiredSpeed());
if (pedestrian.getTimeCredit() > pedestrian.getDurationNextStep()) {
pedestrian.updateNextPosition();
this.isMoving = true;
} else {
this.isMoving = false;
movedPedestrians.add(pedestrian);
}
}
private void updateParallelMove(double timeStepInSec) {
if (isMoving) {
private void updateParallelMove(@NotNull final PedestrianOSM pedestrian, double timeStepInSec) {
if (movedPedestrians.contains(pedestrian)) {
pedestrian.setLastPosition(pedestrian.getPosition());
pedestrian.setPosition(pedestrian.getNextPosition());
}
}
private void updateParallelConflicts(double timeStepInSec) {
if (isMoving) {
List<Agent> others = getCollisionPedestrians();
private void updateParallelConflicts(@NotNull final PedestrianOSM pedestrian, double timeStepInSec) {
if (movedPedestrians.contains(pedestrian)) {
List<Agent> others = getCollisionPedestrians(pedestrian);
boolean undoStep = false;
......@@ -83,8 +123,8 @@ public class UpdateSchemeParallel implements UpdateSchemeOSM {
}
}
private void updateParallelSteps(double timeStepInSec) {
if (isMoving) {
private void updateParallelSteps(@NotNull final PedestrianOSM pedestrian, double timeStepInSec) {
if (movedPedestrians.contains(pedestrian)) {
// did not want to make a step
if (pedestrian.getNextPosition().equals(pedestrian.getLastPosition())) {
pedestrian.setTimeCredit(0);
......@@ -107,7 +147,7 @@ public class UpdateSchemeParallel implements UpdateSchemeOSM {
}
}
private List<Agent> getCollisionPedestrians() {
private List<Agent> getCollisionPedestrians(@NotNull final PedestrianOSM pedestrian) {
LinkedList<Agent> result = new LinkedList<>();
for (Agent ped : pedestrian.getRelevantPedestrians()) {
......@@ -122,4 +162,11 @@ public class UpdateSchemeParallel implements UpdateSchemeOSM {
return result;
}
@Override
public void elementAdded(Pedestrian element) {}
@Override
public void elementRemoved(Pedestrian element) {}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.simulator.models.osm.PedestrianOSM;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import java.util.Collection;
public class UpdateSchemeSequential implements UpdateSchemeOSM {
private final PedestrianOSM pedestrian;
private final Topography topography;
public UpdateSchemeSequential(PedestrianOSM pedestrian) {
this.pedestrian = pedestrian;
public UpdateSchemeSequential(@NotNull Topography topography) {
this.topography = topography;
}
@Override
public void update(double timeStepInSec, double currentTimeInSec, CallMethod callMethod) {
public void update(double timeStepInSec, double currentTimeInSec) {
update(topography.getElements(Pedestrian.class), timeStepInSec);
}
protected void update(@NotNull final Collection<Pedestrian> pedestrianOSMS, final double timeStepInSec) {
for (Pedestrian pedestrian : pedestrianOSMS) {
update((PedestrianOSM) pedestrian, timeStepInSec);
//pedestrian.update(timeStepInSec, -1, CallMethod.SEQUENTIAL);
}
}
protected void update(@NotNull final PedestrianOSM pedestrian, final double timeStepInSec) {
pedestrian.clearStrides();
pedestrian.setTimeCredit(pedestrian.getTimeCredit() + timeStepInSec);
pedestrian.setDurationNextStep(pedestrian.getStepSize() / pedestrian.getDesiredSpeed());
......@@ -21,4 +38,10 @@ public class UpdateSchemeSequential implements UpdateSchemeOSM {
pedestrian.setDurationNextStep(pedestrian.getStepSize() / pedestrian.getDesiredSpeed());
}
}
@Override
public void elementAdded(Pedestrian element) {}
@Override
public void elementRemoved(Pedestrian element) {}
}
package org.vadere.simulator.models.osm.updateScheme;
import org.jetbrains.annotations.NotNull;
import org.vadere.state.scenario.Pedestrian;
import org.vadere.state.scenario.Topography;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public class UpdateSchemeShuffle extends UpdateSchemeSequential {
private final Random random;
public UpdateSchemeShuffle(@NotNull final Topography topography, final Random random) {
super(topography);
this.random = random;
}
@Override
protected void update(@NotNull Collection<Pedestrian> pedestrianOSMS, double timeStepInSec) {
List<Pedestrian> shuffledList = new ArrayList<>(pedestrianOSMS.size());
shuffledList.addAll(pedestrianOSMS);
Collections.shuffle(shuffledList, random);
super.update(shuffledList, timeStepInSec);
}
}
......@@ -44,7 +44,13 @@ public class PedestrianPositionProcessor extends DataProcessor<TimestepPedestria
@Override
public String[] toStrings(TimestepPedestrianIdKey key) {
VPoint p = this.getValue(key);
return new String[]{Double.toString(p.x), Double.toString(p.y)};
if(p == null) {
System.out.println("wtf?");
return new String[]{Double.toString(0), Double.toString(0)};
}
else {
return new String[]{Double.toString(p.x), Double.toString(p.y)};
}
//return new String[]{Double.toString(p.x), Double.toString(p.y)};
}
}
......@@ -4,5 +4,5 @@ package org.vadere.state.scenario;
* Called when dynamic elements are added to the dynamic element container.
*/
public interface DynamicElementAddListener<T extends DynamicElement> {
public void elementAdded(T element);
void elementAdded(T element);
}
......@@ -4,5 +4,5 @@ package org.vadere.state.scenario;
* Called when dynamic elements are removed from the dynamic element container.
*/
public interface DynamicElementRemoveListener<T extends DynamicElement> {
public void elementRemoved(T element);
void elementRemoved(T element);
}
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