package cz.agents.agentpolis.darptestbed.siminfrastructure.planner; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import cz.agents.agentpolis.darptestbed.simulator.initializator.osm.NodeExtendedFunction; import cz.agents.agentpolis.siminfrastructure.planner.TripPlannerException; import cz.agents.agentpolis.siminfrastructure.planner.path.AStarShortestPath; import cz.agents.agentpolis.siminfrastructure.planner.path.AStarShortestPath.Heuristic; import cz.agents.agentpolis.siminfrastructure.planner.trip.TripItem; import cz.agents.agentpolis.siminfrastructure.planner.trip.Trips; import cz.agents.agentpolis.siminfrastructure.planner.trip.VehicleTrip; import cz.agents.agentpolis.siminfrastructure.planner.utils.PlannerEdge; import cz.agents.agentpolis.simmodel.environment.model.citymodel.transportnetwork.GraphType; import cz.agents.agentpolis.utils.key.Key; import org.jgrapht.graph.DirectedWeightedMultigraph; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; public class TestbedAStarPlanner implements TestbedPlanner, Heuristic<Long> { private final NodeExtendedFunction nodeExtendedFunction; private final DirectedWeightedMultigraph<Long, PlannerEdge> highwayGraph; private final GraphType highwayGraphType; LoadingCache<Key, Double> distanceCache = CacheBuilder.newBuilder().maximumSize(100000) .build(new CacheLoader<Key, Double>() { public Double load(Key key) { return nodeExtendedFunction.computeDistanceBetweenNodes(key.firstPartOfKey, key.secondPartOfKey); } }); Cache<Key, List<PlannerEdge>> pathCache = CacheBuilder.newBuilder().maximumSize(100000).build(); public TestbedAStarPlanner(NodeExtendedFunction nodeExtendedFunction, DirectedWeightedMultigraph<Long, PlannerEdge> highwayGraph, GraphType highwayGraphType) { super(); this.nodeExtendedFunction = nodeExtendedFunction; this.highwayGraph = highwayGraph; this.highwayGraphType = highwayGraphType; } @Override public Trips findTrip(String vehicleId, long startNodeById, long destinationNodeById) throws TripPlannerException { return createVehicleTrip(vehicleId, findPath(startNodeById, destinationNodeById, highwayGraph)); } @Override public double getHeuristicEstimate(Long current, Long goal) { try { return distanceCache.get(new Key(current, goal)); } catch (ExecutionException e) { } throw new UnsupportedOperationException(); } public Trips createVehicleTrip(String vehicleId, List<PlannerEdge> foundPath) { if (foundPath.isEmpty()) { return new Trips(); } PlannerEdge plannerEdge = foundPath.get(0); LinkedList<TripItem> trip = new LinkedList<TripItem>(); trip.add(new TripItem(plannerEdge.fromPosition)); trip.add(new TripItem(plannerEdge.toPosition)); for (int i = 1; i < foundPath.size(); i++) { plannerEdge = foundPath.get(i); trip.add(new TripItem(plannerEdge.toPosition)); } if (vehicleId == null) { vehicleId = ""; } Trips trips = new Trips(); trips.addTrip(new VehicleTrip(trip, highwayGraphType, vehicleId)); return trips; } private List<PlannerEdge> findPath(final long startNodeById, final long destinationNodeById, final DirectedWeightedMultigraph<Long, PlannerEdge> plannerGraph) throws TripPlannerException { Key fromToNodeKey = new Key(startNodeById, destinationNodeById); final Heuristic<Long> heuristic = this; List<PlannerEdge> cachedPath; try { cachedPath = pathCache.get(fromToNodeKey, new Callable<List<PlannerEdge>>() { @Override public List<PlannerEdge> call() throws TripPlannerException { List<PlannerEdge> plannerEdges = null; AStarShortestPath<Long, PlannerEdge> shortestPath = null; try { shortestPath = new AStarShortestPath<Long, PlannerEdge>(plannerGraph, startNodeById, destinationNodeById, heuristic); } catch (IllegalArgumentException exception) { throw new TripPlannerException(startNodeById, destinationNodeById); } catch (NoSuchElementException e) { throw new TripPlannerException(startNodeById, destinationNodeById); } plannerEdges = shortestPath.getPathEdgeList(); if (plannerEdges == null) { throw new TripPlannerException(startNodeById, destinationNodeById); } return plannerEdges; } }); } catch (ExecutionException e) { throw new TripPlannerException(startNodeById, destinationNodeById); } List<PlannerEdge> plannerEdges = new ArrayList<PlannerEdge>(); for (PlannerEdge edge : cachedPath) { plannerEdges.add(new PlannerEdge(edge.fromPosition, edge.toPosition, edge.distance)); } return plannerEdges; } }