public AStarBidirection setApproximation(WeightApproximator approx) {
        weightApprox = new BalancedWeightApproximator(approx);
        return this;
    }
@Test
    void infeasibleApproximator_noException() {
        // An infeasible approximator means that the weight of the entries polled from the priority queue does not
        // increase monotonically. Here we deliberately choose the approximations and edge distances such that the fwd
        // search first explores the 0-1-2-3-4 branch, then polls node 10 which causes an update for node 2, but the
        // search stops before node 2 is polled again such that nodes 3 and 4 cannot be updated, because the bwd search
        // already arrived and the stopping criterion is fulfilled. Node 2 still remains in the queue at this point.
        // This means the resulting path contains the invalid search tree branch 2(old)-3-4 and is not the shortest path,
        // because the SPTEntry for node 3 still points to the outdated/deleted entry for node 2.
        // We do not expect an exception, though, because for an infeasible approximator we cannot expect optimal paths.
        DecimalEncodedValue speedEnc = new DecimalEncodedValueImpl("speed", 2, 1, true);
        EncodingManager em = EncodingManager.start().add(speedEnc).build();
        BaseGraph graph = new BaseGraph.Builder(em).create();
        // 0-1----2-3-4----5-6-7-8-9
        //    \  /
        //     10
        graph.edge(0, 1).set(speedEnc, 1, 0).setDistance(100);
        // the distance 1-2 is longer than 1-10-2
        // we deliberately use 2-1 as storage direction, even though the edge points from 1 to 2, because this way
        // we can reproduce the 'Calculating time should not require to read speed from edge in wrong direction' error
        // from #2600
        graph.edge(2, 1).setDistance(300).set(speedEnc, 0, 1);
        graph.edge(2, 3).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(3, 4).set(speedEnc, 1, 0).setDistance(100);
        // distance 4-5 is very long
        graph.edge(4, 5).set(speedEnc, 1, 0).setDistance(10_000);
        graph.edge(5, 6).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(6, 7).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(7, 8).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(8, 9).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(1, 10).set(speedEnc, 1, 0).setDistance(100);
        graph.edge(10, 2).set(speedEnc, 1, 0).setDistance(100);

        Weighting weighting = new SpeedWeighting(speedEnc);
        AStarBidirection algo = new AStarBidirection(graph, weighting, TraversalMode.NODE_BASED);
        algo.setApproximation(new InfeasibleApproximator());
        Path path = algo.calcPath(0, 9);
        // the path is not the shortest path, but the suboptimal one we get for this approximator
        assertEquals(11_000, path.getDistance());
        assertEquals(IntArrayList.from(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), path.calcNodes());

        // this returns the correct path
        Dijkstra dijkstra = new Dijkstra(graph, weighting, TraversalMode.NODE_BASED);
        Path optimalPath = dijkstra.calcPath(0, 9);
        assertEquals(10_900, optimalPath.getDistance());
        assertEquals(IntArrayList.from(0, 1, 10, 2, 3, 4, 5, 6, 7, 8, 9), optimalPath.calcNodes());
    }