Repository: graphhopper/graphhopper
Pull request #1900 (2020-02-12 08:15:40)

Allow using LM routing algo factory standalone
Creating the LM routing algo factory should require neither `LMPreparationHandler` nor `PrepareLandmarks`. This PR tries to decouple the corresponding code.


Patch:
diff --git a/core/src/main/java/com/graphhopper/routing/lm/LMPreparationHandler.java b/core/src/main/java/com/graphhopper/routing/lm/LMPreparationHandler.java
index ca61da9b7..06bfe8d19 100644
--- a/core/src/main/java/com/graphhopper/routing/lm/LMPreparationHandler.java
+++ b/core/src/main/java/com/graphhopper/routing/lm/LMPreparationHandler.java
@@ -18,13 +18,9 @@
 package com.graphhopper.routing.lm;
 
 import com.graphhopper.GraphHopperConfig;
-import com.graphhopper.routing.AlgorithmOptions;
-import com.graphhopper.routing.RoutingAlgorithm;
 import com.graphhopper.routing.RoutingAlgorithmFactory;
-import com.graphhopper.routing.RoutingAlgorithmFactorySimple;
 import com.graphhopper.routing.ch.CHPreparationHandler;
 import com.graphhopper.routing.util.HintsMap;
-import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
 import com.graphhopper.storage.StorableProperties;
 import com.graphhopper.storage.index.LocationIndex;
@@ -74,6 +70,9 @@ public class LMPreparationHandler {
 
         landmarkCount = ghConfig.getInt(Parameters.Landmark.COUNT, landmarkCount);
         activeLandmarkCount = ghConfig.getInt(Landmark.ACTIVE_COUNT_DEFAULT, Math.min(8, landmarkCount));
+        if (activeLandmarkCount > landmarkCount)
+            throw new IllegalArgumentException("Default value for active landmarks " + activeLandmarkCount
+                    + " should be less or equal to landmark count of " + landmarkCount);
         logDetails = ghConfig.getBool(Landmark.PREPARE + "log_details", false);
         minNodes = ghConfig.getInt(Landmark.PREPARE + "min_network_size", -1);
 
@@ -196,19 +195,24 @@ public class LMPreparationHandler {
      * hints
      */
     public RoutingAlgorithmFactory getAlgorithmFactory(HintsMap map) {
+        PrepareLandmarks preparation = getPreparation(map);
+        return preparation.getRoutingAlgorithmFactory().setDefaultActiveLandmarks(activeLandmarkCount);
+    }
+
+    private PrepareLandmarks getPreparation(HintsMap map) {
         if (preparations.isEmpty())
             throw new IllegalStateException("No LM preparations added yet");
 
         // if no weighting or vehicle is specified for this request and there is only one preparation, use it
         if ((map.getWeighting().isEmpty() || map.getVehicle().isEmpty()) && preparations.size() == 1) {
-            return new LMRoutingAlgorithmFactory(preparations.get(0), new RoutingAlgorithmFactorySimple());
+            return preparations.get(0);
         }
 
         List<String> lmProfiles = new ArrayList<>(preparations.size());
         for (final PrepareLandmarks p : preparations) {
             lmProfiles.add(p.getLMProfile().getName());
             if (p.getLMProfile().getWeighting().matches(map))
-                return new LMRoutingAlgorithmFactory(p, new RoutingAlgorithmFactorySimple());
+                return p;
         }
 
         // There are situations where we can use the requested encoder/weighting with an existing LM preparation, even
@@ -222,26 +226,6 @@ public class LMPreparationHandler {
                 "\nrequested: " + requestedString + "\navailable: " + lmProfiles);
     }
 
-    private static class LMRoutingAlgorithmFactory implements RoutingAlgorithmFactory {
-        private RoutingAlgorithmFactory defaultAlgoFactory;
-        private PrepareLandmarks p;
-
-        public LMRoutingAlgorithmFactory(PrepareLandmarks p, RoutingAlgorithmFactory defaultAlgoFactory) {
-            this.defaultAlgoFactory = defaultAlgoFactory;
-            this.p = p;
-        }
-
-        public RoutingAlgorithmFactory getDefaultAlgoFactory() {
-            return defaultAlgoFactory;
-        }
-
-        @Override
-        public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
-            RoutingAlgorithm algo = defaultAlgoFactory.createAlgo(g, opts);
-            return p.getPreparedRoutingAlgorithm(g, algo, opts);
-        }
-    }
-
     /**
      * This method calculates the landmark data for all profiles (optionally in parallel) or if already existent loads it.
      *
@@ -314,7 +298,7 @@ public class LMPreparationHandler {
                         "Couldn't find " + lmProfile.getName() + " in " + maximumWeights);
 
             PrepareLandmarks tmpPrepareLM = new PrepareLandmarks(ghStorage.getDirectory(), ghStorage,
-                    lmProfile, landmarkCount, activeLandmarkCount).
+                    lmProfile, landmarkCount).
                     setLandmarkSuggestions(lmSuggestions).
                     setMaximumWeight(maximumWeight).
                     setLogDetails(logDetails);
diff --git a/core/src/main/java/com/graphhopper/routing/lm/LMRoutingAlgorithmFactory.java b/core/src/main/java/com/graphhopper/routing/lm/LMRoutingAlgorithmFactory.java
new file mode 100644
index 000000000..27dcee818
--- /dev/null
+++ b/core/src/main/java/com/graphhopper/routing/lm/LMRoutingAlgorithmFactory.java
@@ -0,0 +1,90 @@
+/*
+ *  Licensed to GraphHopper GmbH under one or more contributor
+ *  license agreements. See the NOTICE file distributed with this work for
+ *  additional information regarding copyright ownership.
+ *
+ *  GraphHopper GmbH licenses this file to you under the Apache License,
+ *  Version 2.0 (the "License"); you may not use this file except in
+ *  compliance with the License. You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package com.graphhopper.routing.lm;
+
+import com.graphhopper.routing.AStar;
+import com.graphhopper.routing.*;
+import com.graphhopper.routing.weighting.Weighting;
+import com.graphhopper.storage.Graph;
+import com.graphhopper.util.Parameters;
+
+import static com.graphhopper.util.Parameters.Algorithms.*;
+import static com.graphhopper.util.Parameters.Algorithms.AltRoute.*;
+
+public class LMRoutingAlgorithmFactory implements RoutingAlgorithmFactory {
+    private final LandmarkStorage lms;
+    private final Weighting prepareWeighting;
+    private final int numBaseNodes;
+    private int defaultActiveLandmarks;
+
+    public LMRoutingAlgorithmFactory(LandmarkStorage lms) {
+        this.lms = lms;
+        this.prepareWeighting = lms.getWeighting();
+        this.numBaseNodes = lms.getBaseNodes();
+        this.defaultActiveLandmarks = Math.max(1, Math.min(lms.getLandmarkCount() / 2, 12));
+    }
+
+    public LMRoutingAlgorithmFactory setDefaultActiveLandmarks(int defaultActiveLandmarks) {
+        this.defaultActiveLandmarks = defaultActiveLandmarks;
+        return this;
+    }
+
+    @Override
+    public RoutingAlgorithm createAlgo(Graph g, AlgorithmOptions opts) {
+        if (!lms.isInitialized())
+            throw new IllegalStateException("Initialize landmark storage before creating algorithms");
+        int activeLM = Math.max(1, opts.getHints().getInt(Parameters.Landmark.ACTIVE_COUNT, defaultActiveLandmarks));
+        final String algoStr = opts.getAlgorithm();
+        final Weighting weighting = g.wrapWeighting(opts.getWeighting());
+        if (ASTAR.equalsIgnoreCase(algoStr)) {
+            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStar.EPSILON, 1);
+            AStar algo = new AStar(g, weighting, opts.getTraversalMode());
+            algo.setApproximation(getApproximator(g, activeLM, epsilon));
+            algo.setMaxVisitedNodes(opts.getMaxVisitedNodes());
+            return algo;
+        } else if (ASTAR_BI.equalsIgnoreCase(algoStr)) {
+            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
+            AStarBidirection algo = new AStarBidirection(g, weighting, opts.getTraversalMode());
+            algo.setApproximation(getApproximator(g, activeLM, epsilon));
+            algo.setMaxVisitedNodes(opts.getMaxVisitedNodes());
+            return algo;
+        } else if (ALT_ROUTE.equalsIgnoreCase(algoStr)) {
+            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
+            AlternativeRoute algo = new AlternativeRoute(g, weighting, opts.getTraversalMode());
+            algo.setMaxPaths(opts.getHints().getInt(MAX_PATHS, 2));
+            algo.setMaxWeightFactor(opts.getHints().getDouble(MAX_WEIGHT, 1.4));
+            algo.setMaxShareFactor(opts.getHints().getDouble(MAX_SHARE, 0.6));
+            algo.setMinPlateauFactor(opts.getHints().getDouble("alternative_route.min_plateau_factor", 0.2));
+            algo.setApproximation(getApproximator(g, activeLM, epsilon));
+            // landmark algorithm follows good compromise between fast response and exploring 'interesting' paths so we
+            // can decrease this exploration factor further (1->dijkstra, 0.8->bidir. A*)
+            algo.setMaxExplorationFactor(0.6);
+            algo.setMaxVisitedNodes(opts.getMaxVisitedNodes());
+            return algo;
+        } else {
+            throw new IllegalArgumentException("Landmarks algorithm only supports algorithm="
+                    + ASTAR + "," + ASTAR_BI + " or " + ALT_ROUTE + ", but got: " + algoStr);
+        }
+    }
+
+    private LMApproximator getApproximator(Graph g, int activeLM, double epsilon) {
+        return new LMApproximator(g, prepareWeighting, numBaseNodes, lms, activeLM, lms.getFactor(), false).
+                setEpsilon(epsilon);
+    }
+}
diff --git a/core/src/main/java/com/graphhopper/routing/lm/LandmarkStorage.java b/core/src/main/java/com/graphhopper/routing/lm/LandmarkStorage.java
index a773d4141..f3a822559 100644
--- a/core/src/main/java/com/graphhopper/routing/lm/LandmarkStorage.java
+++ b/core/src/main/java/com/graphhopper/routing/lm/LandmarkStorage.java
@@ -703,6 +703,10 @@ public class LandmarkStorage implements Storable<LandmarkStorage> {
         return landmarkWeightDA.getCapacity() + subnetworkStorage.getCapacity();
     }
 
+    int getBaseNodes() {
+        return graph.getNodes();
+    }
+
     /**
      * This class is used to calculate landmark location (equally distributed).
      * It derives from DijkstraBidirectionRef, but is only used as forward or backward search.
diff --git a/core/src/main/java/com/graphhopper/routing/lm/PrepareLandmarks.java b/core/src/main/java/com/graphhopper/routing/lm/PrepareLandmarks.java
index 82bc63095..9ce5e191b 100644
--- a/core/src/main/java/com/graphhopper/routing/lm/PrepareLandmarks.java
+++ b/core/src/main/java/com/graphhopper/routing/lm/PrepareLandmarks.java
@@ -17,7 +17,6 @@
  */
 package com.graphhopper.routing.lm;
 
-import com.graphhopper.routing.*;
 import com.graphhopper.routing.util.AbstractAlgoPreparation;
 import com.graphhopper.routing.util.spatialrules.SpatialRuleLookup;
 import com.graphhopper.routing.weighting.Weighting;
@@ -25,8 +24,6 @@ import com.graphhopper.storage.Directory;
 import com.graphhopper.storage.Graph;
 import com.graphhopper.storage.GraphHopperStorage;
 import com.graphhopper.util.Helper;
-import com.graphhopper.util.Parameters;
-import com.graphhopper.util.Parameters.Landmark;
 import com.graphhopper.util.StopWatch;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -45,17 +42,10 @@ public class PrepareLandmarks extends AbstractAlgoPreparation {
     private final Graph graph;
     private final LandmarkStorage lms;
     private final LMProfile lmProfile;
-    private int defaultActiveLandmarks;
 
-    public PrepareLandmarks(Directory dir, GraphHopperStorage graph, LMProfile lmProfile,
-                            int landmarks, int activeLandmarks) {
-        if (activeLandmarks > landmarks)
-            throw new IllegalArgumentException("Default value for active landmarks " + activeLandmarks
-                    + " should be less or equal to landmark count of " + landmarks);
+    public PrepareLandmarks(Directory dir, GraphHopperStorage graph, LMProfile lmProfile, int landmarks) {
         this.graph = graph;
-        this.defaultActiveLandmarks = activeLandmarks;
         this.lmProfile = lmProfile;
-
         lms = new LandmarkStorage(graph, dir, lmProfile, landmarks);
     }
 
@@ -124,8 +114,7 @@ public class PrepareLandmarks extends AbstractAlgoPreparation {
     @Override
     public void doSpecificWork() {
         StopWatch sw = new StopWatch().start();
-        LOGGER.info("Start calculating " + lms.getLandmarkCount() + " landmarks, default active lms:"
-                + defaultActiveLandmarks + ", weighting:" + lms.getLmSelectionWeighting() + ", " + Helper.getMemInfo());
+        LOGGER.info("Start calculating " + lms.getLandmarkCount() + " landmarks, weighting:" + lms.getLmSelectionWeighting() + ", " + Helper.getMemInfo());
 
         lms.createLandmarks();
         lms.flush();
@@ -135,40 +124,11 @@ public class PrepareLandmarks extends AbstractAlgoPreparation {
                 + ", nodes:" + graph.getNodes() + ", " + Helper.getMemInfo());
     }
 
-    public RoutingAlgorithm getPreparedRoutingAlgorithm(Graph qGraph, RoutingAlgorithm algo, AlgorithmOptions opts) {
-        int activeLM = Math.max(1, opts.getHints().getInt(Landmark.ACTIVE_COUNT, defaultActiveLandmarks));
-        if (algo instanceof AStar) {
-            if (!lms.isInitialized())
-                throw new IllegalStateException("Initialize landmark storage before creating algorithms");
-
-            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStar.EPSILON, 1);
-            AStar astar = (AStar) algo;
-            astar.setApproximation(new LMApproximator(qGraph, lmProfile.getWeighting(), this.graph.getNodes(), lms, activeLM, lms.getFactor(), false).
-                    setEpsilon(epsilon));
-            return algo;
-        } else if (algo instanceof AStarBidirection) {
-            if (!lms.isInitialized())
-                throw new IllegalStateException("Initialize landmark storage before creating algorithms");
-
-            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
-            AStarBidirection astarbi = (AStarBidirection) algo;
-            astarbi.setApproximation(new LMApproximator(qGraph, lmProfile.getWeighting(), this.graph.getNodes(), lms, activeLM, lms.getFactor(), false).
-                    setEpsilon(epsilon));
-            return algo;
-        } else if (algo instanceof AlternativeRoute) {
-            if (!lms.isInitialized())
-                throw new IllegalStateException("Initialize landmark storage before creating algorithms");
-
-            double epsilon = opts.getHints().getDouble(Parameters.Algorithms.AStarBi.EPSILON, 1);
-            AlternativeRoute altRoute = (AlternativeRoute) algo;
-            altRoute.setApproximation(new LMApproximator(qGraph, lmProfile.getWeighting(), this.graph.getNodes(), lms, activeLM, lms.getFactor(), false).
-                    setEpsilon(epsilon));
-            // landmark algorithm follows good compromise between fast response and exploring 'interesting' paths so we
-            // can decrease this exploration factor further (1->dijkstra, 0.8->bidir. A*)
-            altRoute.setMaxExplorationFactor(0.6);
-        }
-
-        return algo;
+    /**
+     * Convenience method to obtain a routing algo factory from the preparation.
+     */
+    public LMRoutingAlgorithmFactory getRoutingAlgorithmFactory() {
+        return new LMRoutingAlgorithmFactory(getLandmarkStorage());
     }
 
     /**


Test patch:
diff --git a/core/src/test/java/com/graphhopper/routing/lm/LMApproximatorTest.java b/core/src/test/java/com/graphhopper/routing/lm/LMApproximatorTest.java
index dc43386fe..d53caa687 100644
--- a/core/src/test/java/com/graphhopper/routing/lm/LMApproximatorTest.java
+++ b/core/src/test/java/com/graphhopper/routing/lm/LMApproximatorTest.java
@@ -69,7 +69,7 @@ public class LMApproximatorTest {
 
         Weighting weighting = new FastestWeighting(encoder);
 
-        PrepareLandmarks lm = new PrepareLandmarks(dir, graph, new LMProfile(weighting), 16, 8);
+        PrepareLandmarks lm = new PrepareLandmarks(dir, graph, new LMProfile(weighting), 16);
         lm.setMaximumWeight(10000);
         lm.doWork();
         LandmarkStorage landmarkStorage = lm.getLandmarkStorage();
diff --git a/core/src/test/java/com/graphhopper/routing/lm/PrepareLandmarksTest.java b/core/src/test/java/com/graphhopper/routing/lm/PrepareLandmarksTest.java
index cb49a1d7b..c25fe7e85 100644
--- a/core/src/test/java/com/graphhopper/routing/lm/PrepareLandmarksTest.java
+++ b/core/src/test/java/com/graphhopper/routing/lm/PrepareLandmarksTest.java
@@ -17,7 +17,10 @@
  */
 package com.graphhopper.routing.lm;
 
-import com.graphhopper.routing.*;
+import com.graphhopper.routing.AStar;
+import com.graphhopper.routing.AlgorithmOptions;
+import com.graphhopper.routing.Path;
+import com.graphhopper.routing.RoutingAlgorithm;
 import com.graphhopper.routing.profiles.BooleanEncodedValue;
 import com.graphhopper.routing.profiles.DecimalEncodedValue;
 import com.graphhopper.routing.querygraph.QueryGraph;
@@ -31,6 +34,8 @@ import com.graphhopper.storage.index.LocationIndex;
 import com.graphhopper.storage.index.LocationIndexTree;
 import com.graphhopper.storage.index.QueryResult;
 import com.graphhopper.util.Helper;
+import com.graphhopper.util.PMap;
+import com.graphhopper.util.Parameters;
 import org.junit.Before;
 import org.junit.Test;
 
@@ -41,6 +46,8 @@ import java.util.List;
 import java.util.Random;
 
 import static com.graphhopper.util.GHUtility.updateDistancesFor;
+import static com.graphhopper.util.Parameters.Algorithms.ASTAR;
+import static com.graphhopper.util.Parameters.Algorithms.ASTAR_BI;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertTrue;
 
@@ -133,18 +140,20 @@ public class PrepareLandmarksTest {
         // TODO should better select 0 and 224?
         assertEquals(Arrays.asList(224, 70), list);
 
-        AlgorithmOptions opts = AlgorithmOptions.start().weighting(weighting).traversalMode(tm).
-                build();
-
-        PrepareLandmarks prepare = new PrepareLandmarks(new RAMDirectory(), graph, lmProfile, 4, 2);
+        PrepareLandmarks prepare = new PrepareLandmarks(new RAMDirectory(), graph, lmProfile, 4);
         prepare.setMinimumNodes(2);
         prepare.doWork();
 
         AStar expectedAlgo = new AStar(graph, weighting, tm);
         Path expectedPath = expectedAlgo.calcPath(41, 183);
 
+        PMap hints = new PMap();
+        hints.put(Parameters.Landmark.ACTIVE_COUNT, 2);
+
         // landmarks with A*
-        RoutingAlgorithm oneDirAlgoWithLandmarks = prepare.getPreparedRoutingAlgorithm(graph, new AStar(graph, weighting, tm), opts);
+        RoutingAlgorithm oneDirAlgoWithLandmarks = prepare.getRoutingAlgorithmFactory().createAlgo(graph,
+                AlgorithmOptions.start().algorithm(ASTAR).weighting(weighting).traversalMode(tm).hints(hints).build());
+
         Path path = oneDirAlgoWithLandmarks.calcPath(41, 183);
 
         assertEquals(expectedPath.getWeight(), path.getWeight(), .1);
@@ -152,9 +161,8 @@ public class PrepareLandmarksTest {
         assertEquals(expectedAlgo.getVisitedNodes() - 133, oneDirAlgoWithLandmarks.getVisitedNodes());
 
         // landmarks with bidir A*
-        opts.getHints().put("lm.recalc_count", 50);
-        RoutingAlgorithm biDirAlgoWithLandmarks = prepare.getPreparedRoutingAlgorithm(graph,
-                new AStarBidirection(graph, weighting, tm), opts);
+        RoutingAlgorithm biDirAlgoWithLandmarks = prepare.getRoutingAlgorithmFactory().createAlgo(graph,
+                AlgorithmOptions.start().algorithm(ASTAR_BI).weighting(weighting).traversalMode(tm).hints(hints).build());
         path = biDirAlgoWithLandmarks.calcPath(41, 183);
         assertEquals(expectedPath.getWeight(), path.getWeight(), .1);
         assertEquals(expectedPath.calcNodes(), path.calcNodes());
@@ -165,8 +173,8 @@ public class PrepareLandmarksTest {
         QueryResult fromQR = index.findClosest(-0.0401, 0.2201, EdgeFilter.ALL_EDGES);
         QueryResult toQR = index.findClosest(-0.2401, 0.0601, EdgeFilter.ALL_EDGES);
         QueryGraph qGraph = QueryGraph.lookup(graph, fromQR, toQR);
-        RoutingAlgorithm qGraphOneDirAlgo = prepare.getPreparedRoutingAlgorithm(qGraph,
-                new AStar(qGraph, weighting, tm), opts);
+        RoutingAlgorithm qGraphOneDirAlgo = prepare.getRoutingAlgorithmFactory().createAlgo(qGraph,
+                AlgorithmOptions.start().algorithm(ASTAR).weighting(weighting).traversalMode(tm).hints(hints).build());
         path = qGraphOneDirAlgo.calcPath(fromQR.getClosestNode(), toQR.getClosestNode());
 
         expectedAlgo = new AStar(qGraph, weighting, tm);
@@ -186,7 +194,7 @@ public class PrepareLandmarksTest {
         Directory dir = new RAMDirectory(fileStr, true).create();
         Weighting weighting = new FastestWeighting(encoder);
         LMProfile lmProfile = new LMProfile(weighting);
-        PrepareLandmarks plm = new PrepareLandmarks(dir, graph, lmProfile, 2, 2);
+        PrepareLandmarks plm = new PrepareLandmarks(dir, graph, lmProfile, 2);
         plm.setMinimumNodes(2);
         plm.doWork();
 
@@ -198,7 +206,7 @@ public class PrepareLandmarksTest {
         assertEquals(4791, Math.round(plm.getLandmarkStorage().getFromWeight(0, 1) * expectedFactor));
 
         dir = new RAMDirectory(fileStr, true);
-        plm = new PrepareLandmarks(dir, graph, lmProfile, 2, 2);
+        plm = new PrepareLandmarks(dir, graph, lmProfile, 2);
         assertTrue(plm.loadExisting());
         assertEquals(expectedFactor, plm.getLandmarkStorage().getFactor(), 1e-6);
         assertEquals(Arrays.toString(new int[]{
diff --git a/core/src/test/java/com/graphhopper/routing/weighting/DirectedRoutingTest.java b/core/src/test/java/com/graphhopper/routing/weighting/DirectedRoutingTest.java
index 2d8090155..146a5035a 100644
--- a/core/src/test/java/com/graphhopper/routing/weighting/DirectedRoutingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/weighting/DirectedRoutingTest.java
@@ -122,7 +122,7 @@ public class DirectedRoutingTest {
             chGraph = graph.getCHGraph(chProfile);
         }
         if (prepareLM) {
-            lm = new PrepareLandmarks(dir, graph, lmProfile, 16, 8);
+            lm = new PrepareLandmarks(dir, graph, lmProfile, 16);
             lm.setMaximumWeight(1000);
             lm.doWork();
         }
@@ -141,8 +141,7 @@ public class DirectedRoutingTest {
             case CH_ASTAR:
                 return (BidirRoutingAlgorithm) pch.getRoutingAlgorithmFactory().createAlgo(graph, AlgorithmOptions.start().weighting(weighting).algorithm(ASTAR_BI).build());
             case LM:
-                AStarBidirection astarbi = new AStarBidirection(graph, graph.wrapWeighting(weighting), TraversalMode.EDGE_BASED);
-                return (BidirRoutingAlgorithm) lm.getPreparedRoutingAlgorithm(graph, astarbi, AlgorithmOptions.start().build());
+                return (BidirRoutingAlgorithm) lm.getRoutingAlgorithmFactory().createAlgo(graph, AlgorithmOptions.start().weighting(weighting).traversalMode(TraversalMode.EDGE_BASED).build());
             default:
                 throw new IllegalArgumentException("unknown algo " + algo);
         }
diff --git a/core/src/test/java/com/graphhopper/routing/weighting/RandomizedRoutingTest.java b/core/src/test/java/com/graphhopper/routing/weighting/RandomizedRoutingTest.java
index 22c777550..486cae5d2 100644
--- a/core/src/test/java/com/graphhopper/routing/weighting/RandomizedRoutingTest.java
+++ b/core/src/test/java/com/graphhopper/routing/weighting/RandomizedRoutingTest.java
@@ -4,6 +4,7 @@ import com.carrotsearch.hppc.IntArrayList;
 import com.carrotsearch.hppc.IntIndexedContainer;
 import com.graphhopper.Repeat;
 import com.graphhopper.RepeatRule;
+import com.graphhopper.routing.AStar;
 import com.graphhopper.routing.*;
 import com.graphhopper.routing.ch.PrepareContractionHierarchies;
 import com.graphhopper.routing.lm.LMProfile;
@@ -29,8 +30,7 @@ import java.util.*;
 
 import static com.graphhopper.routing.util.TraversalMode.EDGE_BASED;
 import static com.graphhopper.routing.util.TraversalMode.NODE_BASED;
-import static com.graphhopper.util.Parameters.Algorithms.ASTAR_BI;
-import static com.graphhopper.util.Parameters.Algorithms.DIJKSTRA_BI;
+import static com.graphhopper.util.Parameters.Algorithms.*;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
@@ -121,7 +121,7 @@ public class RandomizedRoutingTest {
             chGraph = graph.getCHGraph(chProfile);
         }
         if (prepareLM) {
-            lm = new PrepareLandmarks(dir, graph, new LMProfile(weighting), 16, 8);
+            lm = new PrepareLandmarks(dir, graph, new LMProfile(weighting), 16);
             lm.setMaximumWeight(10000);
             lm.doWork();
         }
@@ -144,11 +144,9 @@ public class RandomizedRoutingTest {
             case CH_ASTAR:
                 return pch.getRoutingAlgorithmFactory().createAlgo(graph instanceof QueryGraph ? graph : chGraph, AlgorithmOptions.start().weighting(weighting).algorithm(ASTAR_BI).build());
             case LM_BIDIR:
-                AStarBidirection astarbi = new AStarBidirection(graph, weighting, traversalMode);
-                return lm.getPreparedRoutingAlgorithm(graph, astarbi, AlgorithmOptions.start().build());
+                return lm.getRoutingAlgorithmFactory().createAlgo(graph, AlgorithmOptions.start().weighting(weighting).algorithm(ASTAR_BI).traversalMode(traversalMode).build());
             case LM_UNIDIR:
-                AStar astar = new AStar(graph, weighting, traversalMode);
-                return lm.getPreparedRoutingAlgorithm(graph, astar, AlgorithmOptions.start().build());
+                return lm.getRoutingAlgorithmFactory().createAlgo(graph, AlgorithmOptions.start().weighting(weighting).algorithm(ASTAR).traversalMode(traversalMode).build());
             case PERFECT_ASTAR:
                 AStarBidirection perfectastarbi = new AStarBidirection(graph, weighting, traversalMode);
                 perfectastarbi.setApproximation(new PerfectApproximator(graph, weighting, traversalMode, false));