/* This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (props, at your option) any later version. This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package org.opentripplanner.routing.algorithm; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertNotNull; import java.util.HashSet; import java.util.List; import java.util.Set; import org.junit.Before; import org.junit.Test; import org.opentripplanner.routing.algorithm.strategies.MultiTargetTerminationStrategy; import org.opentripplanner.routing.algorithm.strategies.SearchTerminationStrategy; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graph.SimpleConcreteEdge; import org.opentripplanner.routing.graph.SimpleConcreteVertex; import org.opentripplanner.routing.graph.Vertex; import org.opentripplanner.routing.location.StreetLocation; import org.opentripplanner.routing.spt.GraphPath; import org.opentripplanner.routing.spt.ShortestPathTree; import com.vividsolutions.jts.geom.Coordinate; public class AStarTest { private Graph _graph; @Before public void before() { _graph = new Graph(); vertex("56th_24th", 47.669457, -122.387577); vertex("56th_22nd", 47.669462, -122.384739); vertex("56th_20th", 47.669457, -122.382106); vertex("market_24th", 47.668690, -122.387577); vertex("market_ballard", 47.668683, -122.386096); vertex("market_22nd", 47.668686, -122.384749); vertex("market_leary", 47.668669, -122.384392); vertex("market_russell", 47.668655, -122.382997); vertex("market_20th", 47.668684, -122.382117); vertex("shilshole_24th", 47.668419, -122.387534); vertex("shilshole_22nd", 47.666519, -122.384744); vertex("shilshole_vernon", 47.665938, -122.384048); vertex("shilshole_20th", 47.664356, -122.382192); vertex("ballard_turn", 47.668509, -122.386069); vertex("ballard_22nd", 47.667624, -122.384744); vertex("ballard_vernon", 47.666422, -122.383158); vertex("ballard_20th", 47.665476, -122.382128); vertex("leary_vernon", 47.666863, -122.382353); vertex("leary_20th", 47.666682, -122.382160); vertex("russell_20th", 47.667846, -122.382128); edges("56th_24th", "56th_22nd", "56th_20th"); edges("56th_24th", "market_24th"); edges("56th_22nd", "market_22nd"); edges("56th_20th", "market_20th"); edges("market_24th", "market_ballard", "market_22nd", "market_leary", "market_russell", "market_20th"); edges("market_24th", "shilshole_24th", "shilshole_22nd", "shilshole_vernon", "shilshole_20th"); edges("market_ballard", "ballard_turn", "ballard_22nd", "ballard_vernon", "ballard_20th"); edges("market_leary", "leary_vernon", "leary_20th"); edges("market_russell", "russell_20th"); edges("market_22nd", "ballard_22nd", "shilshole_22nd"); edges("leary_vernon", "ballard_vernon", "shilshole_vernon"); edges("market_20th", "russell_20th", "leary_20th", "ballard_20th", "shilshole_20th"); } @Test public void testForward() { RoutingRequest options = new RoutingRequest(); options.setWalkSpeed(1.0); options.setRoutingContext(_graph, _graph.getVertex("56th_24th"), _graph.getVertex("leary_20th")); ShortestPathTree tree = new GenericAStar().getShortestPathTree(options); GraphPath path = tree.getPath(_graph.getVertex("leary_20th"), false); List<State> states = path.states; assertEquals(7, states.size()); assertEquals("56th_24th", states.get(0).getVertex().getLabel()); assertEquals("market_24th", states.get(1).getVertex().getLabel()); assertEquals("market_ballard", states.get(2).getVertex().getLabel()); assertEquals("market_22nd", states.get(3).getVertex().getLabel()); assertEquals("market_leary", states.get(4).getVertex().getLabel()); assertEquals("leary_vernon", states.get(5).getVertex().getLabel()); assertEquals("leary_20th", states.get(6).getVertex().getLabel()); } @Test public void testBack() { RoutingRequest options = new RoutingRequest(); options.setWalkSpeed(1.0); options.setArriveBy(true); options.setRoutingContext(_graph, _graph.getVertex("56th_24th"), _graph.getVertex("leary_20th")); ShortestPathTree tree = new GenericAStar().getShortestPathTree(options); GraphPath path = tree.getPath(_graph.getVertex("56th_24th"), false); List<State> states = path.states; assertTrue(states.size() == 6 || states.size() == 7); assertEquals("56th_24th", states.get(0).getVertex().getLabel()); int n; // we could go either way around the block formed by 56th, 22nd, market, and 24th. if (states.size() == 7) { assertEquals("market_24th", states.get(1).getVertex().getLabel()); assertEquals("market_ballard", states.get(2).getVertex().getLabel()); n = 0; } else { assertEquals("56th_22nd", states.get(1).getVertex().getLabel()); n = -1; } assertEquals("market_22nd", states.get(n + 3).getVertex().getLabel()); assertEquals("market_leary", states.get(n + 4).getVertex().getLabel()); assertEquals("leary_vernon", states.get(n + 5).getVertex().getLabel()); assertEquals("leary_20th", states.get(n + 6).getVertex().getLabel()); } @Test public void testForwardExtraEdges() { RoutingRequest options = new RoutingRequest(); options.setWalkSpeed(1.0); StreetLocation fromLocation = new StreetLocation(_graph, "near_shilshole_22nd", new Coordinate(-122.385050, 47.666620), "near_shilshole_22nd"); fromLocation.getExtra().add( new SimpleConcreteEdge(fromLocation, _graph.getVertex("shilshole_22nd"))); StreetLocation toLocation = new StreetLocation(_graph, "near_56th_20th", new Coordinate( -122.382347, 47.669518), "near_56th_20th"); toLocation.getExtra() .add(new SimpleConcreteEdge(_graph.getVertex("56th_20th"), toLocation)); options.setRoutingContext(_graph, fromLocation, toLocation); ShortestPathTree tree = new GenericAStar().getShortestPathTree(options); GraphPath path = tree.getPath(toLocation, false); List<State> states = path.states; assertEquals(9, states.size()); assertEquals("near_shilshole_22nd", states.get(0).getVertex().getLabel()); assertEquals("shilshole_22nd", states.get(1).getVertex().getLabel()); assertEquals("ballard_22nd", states.get(2).getVertex().getLabel()); assertEquals("market_22nd", states.get(3).getVertex().getLabel()); assertEquals("market_leary", states.get(4).getVertex().getLabel()); assertEquals("market_russell", states.get(5).getVertex().getLabel()); assertEquals("market_20th", states.get(6).getVertex().getLabel()); assertEquals("56th_20th", states.get(7).getVertex().getLabel()); assertEquals("near_56th_20th", states.get(8).getVertex().getLabel()); } @Test public void testBackExtraEdges() { RoutingRequest options = new RoutingRequest(); options.setWalkSpeed(1.0); options.setArriveBy(true); StreetLocation fromLocation = new StreetLocation(_graph, "near_shilshole_22nd", new Coordinate(-122.385050, 47.666620), "near_shilshole_22nd"); fromLocation.getExtra().add( new SimpleConcreteEdge(fromLocation, _graph.getVertex("shilshole_22nd"))); StreetLocation toLocation = new StreetLocation(_graph, "near_56th_20th", new Coordinate( -122.382347, 47.669518), "near_56th_20th"); toLocation.getExtra() .add(new SimpleConcreteEdge(_graph.getVertex("56th_20th"), toLocation)); options.setRoutingContext(_graph, fromLocation, toLocation); ShortestPathTree tree = new GenericAStar().getShortestPathTree(options); GraphPath path = tree.getPath(fromLocation, false); List<State> states = path.states; assertEquals(9, states.size()); assertEquals("near_shilshole_22nd", states.get(0).getVertex().getLabel()); assertEquals("shilshole_22nd", states.get(1).getVertex().getLabel()); assertEquals("ballard_22nd", states.get(2).getVertex().getLabel()); assertEquals("market_22nd", states.get(3).getVertex().getLabel()); assertEquals("market_leary", states.get(4).getVertex().getLabel()); assertEquals("market_russell", states.get(5).getVertex().getLabel()); assertEquals("market_20th", states.get(6).getVertex().getLabel()); assertEquals("56th_20th", states.get(7).getVertex().getLabel()); assertEquals("near_56th_20th", states.get(8).getVertex().getLabel()); } @Test public void testMultipleTargets() { RoutingRequest options = new RoutingRequest(); options.setWalkSpeed(1.0); options.setBatch(true); options.setRoutingContext(_graph, _graph.getVertex("56th_24th"), _graph.getVertex("leary_20th")); Set<Vertex> targets = new HashSet<Vertex>(); targets.add(_graph.getVertex("shilshole_22nd")); targets.add(_graph.getVertex("market_russell")); targets.add(_graph.getVertex("56th_20th")); targets.add(_graph.getVertex("leary_20th")); SearchTerminationStrategy strategy = new MultiTargetTerminationStrategy(targets); ShortestPathTree tree = new GenericAStar().getShortestPathTree(options, -1, strategy); for (Vertex v : targets) { GraphPath path = tree.getPath(v, false); assertNotNull("No path found for target " + v.getLabel(), path); } } /**** * Private Methods ****/ private SimpleConcreteVertex vertex(String label, double lat, double lon) { SimpleConcreteVertex v = new SimpleConcreteVertex(_graph, label, lat, lon); return v; } private void edges(String... vLabels) { for (int i = 0; i < vLabels.length - 1; i++) { Vertex vA = _graph.getVertex(vLabels[i]); Vertex vB = _graph.getVertex(vLabels[i + 1]); new SimpleConcreteEdge(vA, vB); new SimpleConcreteEdge(vB, vA); } } }