/* 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.strategies; import java.util.HashMap; import org.opentripplanner.common.model.T2; import org.opentripplanner.routing.core.LowerBoundGraph; import org.opentripplanner.routing.core.State; import org.opentripplanner.routing.core.RoutingRequest; import org.opentripplanner.routing.graph.Graph; import org.opentripplanner.routing.graph.Vertex; import org.opentripplanner.routing.location.StreetLocation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Intended primarily for testing of and experimentation with heuristics based on the triangle inequality and metric embeddings. * * A heuristic that performs a single-source / all destinations shortest path search in a weighted, directed graph whose shortest path metric is a * lower bound on path weight in our main, time-dependent graph. * * @author andrewbyrd */ public class LBGRemainingWeightHeuristic implements RemainingWeightHeuristic { private static final long serialVersionUID = 20110901L; private static Logger LOG = LoggerFactory.getLogger(LBGRemainingWeightHeuristic.class); private static HashMap<GraphAndDirection, LowerBoundGraph> lbgCache = new HashMap<GraphAndDirection, LowerBoundGraph>(); LowerBoundGraph lbg; Vertex target; double[] weights; public LBGRemainingWeightHeuristic(Graph g, RoutingRequest opt) { GraphAndDirection key = new GraphAndDirection(g, opt.isArriveBy()); this.lbg = lbgCache.get(key); if (this.lbg == null) { LOG.debug("no lower bound graph found for: {}", key); LOG.debug("BEGIN Making lower bound graph"); if (opt.isArriveBy()) this.lbg = new LowerBoundGraph(g, LowerBoundGraph.OUTGOING); else this.lbg = new LowerBoundGraph(g, LowerBoundGraph.INCOMING); LOG.debug("END Making lower bound graph"); lbgCache.put(key, this.lbg); } else { LOG.debug("reusing cached lower bound graph found for: {}", key); } } @Override public void initialize(State s, Vertex target) { recalculate(target); } @Override public double computeForwardWeight(State s, Vertex target) { return computeReverseWeight(s, target); } @Override public double computeReverseWeight(State s, Vertex target) { int index = s.getVertex().getIndex(); if (index < weights.length) { double h = weights[index]; // System.out.printf("h=%f at %s\n", h, s.getVertex()); return h == Double.POSITIVE_INFINITY ? 0 : h; } else return 0; } private void recalculate(Vertex target) { if (target != this.target) { this.target = target; if (target instanceof StreetLocation) this.weights = lbg.sssp((StreetLocation) target); else this.weights = lbg.sssp(target); } } private static class GraphAndDirection extends T2<Graph, Boolean> { private static final long serialVersionUID = 20110901L; public GraphAndDirection(Graph g, Boolean i) { super(g, i); } } @Override public void reset() {} @Override public void abort() {} }