package iamrescue.routing.dijkstra; import iamrescue.agent.ISimulationTimer; import iamrescue.belief.IAMWorldModel; import iamrescue.routing.AbstractRoutingModule; import iamrescue.routing.IRoutingAlgorithm; import iamrescue.routing.costs.IRoutingCostFunction; import iamrescue.routing.queries.IRoutingLocation; import iamrescue.routing.queries.RoutingLocation; import iamrescue.routing.util.LeastRecentlyUsedMap; import iamrescue.util.PositionXY; import java.util.List; import rescuecore2.misc.Pair; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.worldmodel.EntityListener; public class SimpleDijkstrasRoutingModule extends AbstractRoutingModule implements EntityListener { private static final int DEFAULT_HISTORY = 10; private boolean usingCache = false; private LeastRecentlyUsedMap<IRoutingLocation, IRoutingAlgorithm> pathCache = new LeastRecentlyUsedMap<IRoutingLocation, IRoutingAlgorithm>( DEFAULT_HISTORY); private IRoutingLocation lastLocation = null; private IRoutingAlgorithm lastAlgorithm = null; public SimpleDijkstrasRoutingModule(IAMWorldModel worldModel, IRoutingCostFunction routingCostFunction, ISimulationTimer timer) { super(worldModel, routingCostFunction, timer); } /** * @return True iff this module keeps a history of past searches. */ public boolean isUsingCache() { return usingCache; } /** * @param usingCache * Whether the routing module should cache previous results * (speeds up repeated searches from same origin, but slows down * new searches). */ public void setUsingCache(boolean usingCache) { this.usingCache = usingCache; this.lastLocation = null; } /** * @return Max size of cache */ public int getCacheMaxCapacity() { return pathCache.getMaxCapacity(); } /** * @param maxCapacity * How many searches should be cached. */ public void setCacheMaxCapacity(int maxCapacity) { pathCache.setMaximumCapacity(maxCapacity); } /** * @param from */ /* * protected IRoutingAlgorithm obtainSolver(StandardEntity from, int * positionExtra) { * * IRoutingAlgorithm shortestPath; * * if (usingCache) { CacheKey key = new CacheKey(from, positionExtra); * * // Check if we need to build graph again. shortestPath = * pathCache.get(key); if (shortestPath == null) { shortestPath = * createSolver(from, positionExtra); pathCache.put(key, shortestPath); } } * else { shortestPath = createSolver(from, positionExtra); } * * return shortestPath; } */ protected IRoutingAlgorithm createSolver(IRoutingLocation from) { if (!usingCache) { lastLocation = from; } Pair<List<Integer>, List<Double>> initial = computeSearchNodes(from); return new DijkstrasShortestPath(graph, initial.first(), initial .second()); } @Override protected void graphChanged() { pathCache.clear(); lastLocation = null; } /* * (non-Javadoc) * * @see newrouting.AbstractRoutingModule#obtainSolver(util.PositionXY) */ @Override protected IRoutingAlgorithm obtainSolver(IRoutingLocation from) { // This is needed in case the position of an agent is updated. from = convertToAbsolute(from); IRoutingAlgorithm shortestPath; if (usingCache) { // Check if we need to build graph again. shortestPath = pathCache.get(from); if (shortestPath == null) { shortestPath = createSolver(from); pathCache.put(from, shortestPath); } } else { if (lastLocation != null && lastLocation.equals(from)) { shortestPath = lastAlgorithm; } else { shortestPath = createSolver(from); lastAlgorithm = shortestPath; } } return shortestPath; } /** * @param from * @return */ private IRoutingLocation convertToAbsolute(IRoutingLocation from) { StandardEntity entity = worldModel.getEntity(from.getID()); PositionXY position = new PositionXY(entity.getLocation(worldModel)); while (entity instanceof Human) { entity = worldModel.getEntity(((Human) entity).getPosition()); } return new RoutingLocation(entity.getID(), position); } }