broadwick.graph.algorithms.ShortestPath.java Source code

Java tutorial

Introduction

Here is the source code for broadwick.graph.algorithms.ShortestPath.java

Source

/*
 * Copyright 2013 University of Glasgow.
 *
 * Licensed 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 broadwick.graph.algorithms;

import broadwick.graph.Edge;
import broadwick.graph.EdgeType;
import edu.uci.ics.jung.algorithms.shortestpath.DijkstraDistance;
import broadwick.graph.Graph;
import broadwick.graph.Vertex;
import edu.uci.ics.jung.algorithms.shortestpath.DijkstraShortestPath;
import java.util.List;
import org.apache.commons.collections15.Transformer;

/**
 * Calculates distances in a specified graph, using Dijkstra's single-source-shortest-path algorithm. All edge weights
 * in the graph must be nonnegative; otherwise an
 * <code>IllegalArgumentException</code> will be thrown.
 * @param <V> the vertex type.
 * @param <E> the edge type.
 */
public class ShortestPath<V extends Vertex, E extends Edge<V>> {

    /**
     * Create a ShortestPath instance.
     * @param graph the network/graph on which we will be looking for shortest paths.
     */
    public ShortestPath(final Graph<V, E> graph) {

        if (EdgeType.DIRECTED.equals(graph.getEdgeType())) {
            jungGraph = new edu.uci.ics.jung.graph.DirectedSparseMultigraph<>();
        } else if (EdgeType.UNDIRECTED.equals(graph.getEdgeType())) {
            jungGraph = new edu.uci.ics.jung.graph.UndirectedSparseMultigraph<>();
        } else {
            throw new IllegalArgumentException("Could not create ShortestPath object for unknown grpah type.");
        }
        for (E edge : graph.getEdges()) {
            jungGraph.addEdge(edge, edge.getSource(), edge.getDestination());
        }

        weightTransformer = new EdgeWeightTransformer();
    }

    /**
     * Returns the length of a shortest path from the source to the target vertex, or null if the target is not
     * reachable from the source. If either vertex is not in the graph for which this instance was created, throws
     * <code>IllegalArgumentException</code>.
     * @param source the source
     * @param target the target
     * @return the distance from source to target
     */
    public final double calculateDistance(final V source, final V target) {

        final DijkstraDistance<V, E> distance = new DijkstraDistance<>(jungGraph, weightTransformer);
        final Number d = distance.getDistance(source, target);
        return d == null ? 0 : d.doubleValue();
    }

    /**
     * Returns a List of the edges on the shortest path from source to target, in order of their occurrence on this
     * path. If either vertex is not in the graph for which this instance was created, throws IllegalArgumentException
     * @param source the vertex from which distances are measured
     * @param target the number of vertics for which to measure distances
     * @return a list of edges that comprise the shortest path from source to target.
     */
    public final List<E> getEdgesInPath(final V source, final V target) {
        final DijkstraShortestPath<V, E> path = new DijkstraShortestPath<>(jungGraph);
        return path.getPath(source, target);
    }

    private edu.uci.ics.jung.graph.AbstractTypedGraph<V, E> jungGraph;
    private final Transformer<E, Number> weightTransformer;

    /**
     * Transformer class to transform the edge of a graph to a double (it's weight).
     */
    private class EdgeWeightTransformer implements Transformer<E, Number> {

        @Override
        public Number transform(final E edge) {
            // all nonnull values are instances of broadwick.graph.Edge
            if (edge != null) {
                return ((Edge) edge).getWeight();
            } else {
                return 1.0;
            }
        }
    }
}