All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jgrapht.alg.KShortestPathsIterator Maven / Gradle / Ivy

/* ==========================================
 * JGraphT : a free Java graph-theory library
 * ==========================================
 *
 * Project Info:  http://jgrapht.sourceforge.net/
 * Project Creator:  Barak Naveh (http://sourceforge.net/users/barak_naveh)
 *
 * (C) Copyright 2003-2010, by Barak Naveh and Contributors.
 *
 * This program and the accompanying materials are dual-licensed under
 * either
 *
 * (a) the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation, or (at your option) any
 * later version.
 *
 * or (per the licensee's choosing)
 *
 * (b) the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation.
 */
/* -------------------------
 * KShortestPathsIterator.java
 * -------------------------
 * (C) Copyright 2007-2010, by France Telecom
 *
 * Original Author:  Guillaume Boulmier and Contributors.
 * Contributor(s):   John V. Sichi
 *
 * $Id$
 *
 * Changes
 * -------
 * 05-Jun-2007 : Initial revision (GB);
 * 05-Jul-2007 : Added support for generics (JVS);
 * 06-Dec-2010 : Bugfixes (GB);
 *
 */
package org.jgrapht.alg;

import java.util.*;

import org.jgrapht.*;


/**
 * Helper class for {@link KShortestPaths}.
 *
 * @author Guillaume Boulmier
 * @since July 5, 2007
 */
class KShortestPathsIterator
    implements Iterator>
{
    

    /**
     * End vertex.
     */
    private V endVertex;

    /**
     * Graph on which shortest paths are searched.
     */
    private Graph graph;

    /**
     * Number of paths stored at each end vertex.
     */
    private int k;

    /**
     * Vertices whose ranking shortest paths have been modified during the
     * previous pass.
     */
    private Set prevImprovedVertices;

    /**
     * Stores the paths that improved the vertex in the previous pass.
     */
    private Map> prevSeenDataContainer;

    /**
     * Stores the vertices that have been seen during iteration and (optionally)
     * some additional traversal info regarding each vertex. Key = vertex, value
     * = RankingPathElementList list of calculated paths.
     */
    private Map> seenDataContainer;

    /**
     * Start vertex.
     */
    private V startVertex;

    private boolean startVertexEncountered;

    /**
     * Stores the number of the path.
     */
    private int passNumber = 1;

    

    /**
     * @param graph graph on which shortest paths are searched.
     * @param startVertex start vertex of the calculated paths.
     * @param endVertex end vertex of the calculated paths.
     * @param maxSize number of paths stored at end vertex of the graph.
     */
    public KShortestPathsIterator(
        Graph graph,
        V startVertex,
        V endVertex,
        int maxSize)
    {
        assertKShortestPathsIterator(graph, startVertex);

        this.graph = graph;
        this.startVertex = startVertex;
        this.endVertex = endVertex;

        this.k = maxSize;

        this.seenDataContainer = new HashMap>();
        this.prevSeenDataContainer =
            new HashMap>();

        this.prevImprovedVertices = new HashSet();
    }

    

    /**
     * @return true if at least one path has been improved during
     * the previous pass, false otherwise.
     */
    public boolean hasNext()
    {
        if (!this.startVertexEncountered) {
            encounterStartVertex();
        }

        return !(this.prevImprovedVertices.isEmpty());
    }

    /**
     * Returns the list of vertices whose path has been improved during the
     * current pass. Complexity =
     *
     * 
    *
  • O(m*k*(m+n)) where k is the maximum number * of shortest paths to compute, m is the number of edges of * the graph and n is the number of vertices of the graph
  • *
* * @see java.util.Iterator#next() */ public Set next() { if (!this.startVertexEncountered) { encounterStartVertex(); } // at the i-th pass the shortest paths with i edges are calculated. if (hasNext()) { Set improvedVertices = new HashSet(); for ( Iterator iter = this.prevImprovedVertices.iterator(); iter.hasNext();) { V vertex = iter.next(); if (!vertex.equals(this.endVertex)) { updateOutgoingVertices(vertex, improvedVertices); } } savePassData(improvedVertices); this.passNumber++; return improvedVertices; } throw new NoSuchElementException(); } /** * Unsupported. * * @see java.util.Iterator#remove() */ public void remove() { throw new UnsupportedOperationException(); } /** * Returns the path elements of the ranking shortest paths with less than * nMaxHops edges between the start vertex and the end vertex. * * @param endVertex end vertex. * * @return list of RankingPathElement, or null of * no path exists between the start vertex and the end vertex. */ RankingPathElementList getPathElements(V endVertex) { return this.seenDataContainer.get(endVertex); } private void assertKShortestPathsIterator(Graph graph, V startVertex) { if (graph == null) { throw new NullPointerException("graph is null"); } if (startVertex == null) { throw new NullPointerException("startVertex is null"); } } /** * The first time we see a vertex, make up a new entry for it. * * @param vertex a vertex which has just been encountered. * @param edge the edge via which the vertex was encountered. * * @return the new entry. */ private RankingPathElementList createSeenData(V vertex, E edge) { V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); RankingPathElementList oppositeData = this.prevSeenDataContainer.get(oppositeVertex); // endVertex in argument to ensure that stored paths do not disconnect // the end-vertex RankingPathElementList data = new RankingPathElementList( this.graph, this.k, oppositeData, edge, this.endVertex); return data; } /** * Returns an iterator to loop over outgoing edges Edge of the * vertex. * * @param vertex * * @return . */ private Iterator edgesOfIterator(V vertex) { if (this.graph instanceof DirectedGraph) { return ((DirectedGraph) this.graph).outgoingEdgesOf(vertex) .iterator(); } else { return this.graph.edgesOf(vertex).iterator(); } } /** * Initializes the list of paths at the start vertex and adds an empty path. */ private void encounterStartVertex() { RankingPathElementList data = new RankingPathElementList( this.graph, this.k, new RankingPathElement( this.startVertex)); this.seenDataContainer.put(this.startVertex, data); this.prevSeenDataContainer.put(this.startVertex, data); // initially the only vertex whose value is considered to have changed // is the start vertex this.prevImprovedVertices.add(this.startVertex); this.startVertexEncountered = true; } private void savePassData(Set improvedVertices) { for (Iterator iter = improvedVertices.iterator(); iter.hasNext();) { V vertex = iter.next(); RankingPathElementList pathElementList = this.seenDataContainer.get(vertex); RankingPathElementList improvedPaths = new RankingPathElementList( this.graph, pathElementList.maxSize, vertex); for ( Iterator> pathIter = pathElementList.iterator(); pathIter.hasNext();) { RankingPathElement path = pathIter.next(); if (path.getHopCount() == this.passNumber) { // the path has just been computed. improvedPaths.pathElements.add(path); } } this.prevSeenDataContainer.put(vertex, improvedPaths); } this.prevImprovedVertices = improvedVertices; } /** * Try to add the first paths to the specified vertex. These paths reached * the specified vertex and ended with the specified edge. A new * intermediary path is stored in the paths list of the specified vertex * provided that the path can be extended to the end-vertex. * * @param vertex vertex reached by a path. * @param edge edge reaching the vertex. */ private boolean tryToAddFirstPaths(V vertex, E edge) { // the vertex has not been reached yet RankingPathElementList data = createSeenData(vertex, edge); if (!data.isEmpty()) { this.seenDataContainer.put(vertex, data); return true; } return false; } /** * Try to add new paths for the vertex. These new paths reached the * specified vertex and ended with the specified edge. A new intermediary * path is stored in the paths list of the specified vertex provided that * the path can be extended to the end-vertex. * * @param vertex a vertex which has just been encountered. * @param edge the edge via which the vertex was encountered. */ private boolean tryToAddNewPaths(V vertex, E edge) { RankingPathElementList data = this.seenDataContainer.get(vertex); V oppositeVertex = Graphs.getOppositeVertex(this.graph, edge, vertex); RankingPathElementList oppositeData = this.prevSeenDataContainer.get(oppositeVertex); return data.addPathElements(oppositeData, edge); } /** *

Updates outgoing vertices of the vertex. For each outgoing vertex, the * new paths are obtained by concatenating the specified edge to the * calculated paths of the specified vertex. If the weight of a new path is * greater than the weight of any path stored so far at the outgoing vertex * then the path is not added, otherwise it is added to the list of paths in * increasing order of weight.

* * Complexity = * *
    *
  • O(d(v)*k*(m+n)) where d(v) is the outgoing * degree of the specified vertex, k is the maximum number of * shortest paths to compute, m is the number of edges of the * graph and n is the number of vertices of the graph
  • *
* * @param vertex * @param improvedVertices */ private void updateOutgoingVertices(V vertex, Set improvedVertices) { // try to add new paths for the target vertices of the outgoing edges // of the vertex in argument. for (Iterator iter = edgesOfIterator(vertex); iter.hasNext();) { E edge = iter.next(); V vertexReachedByEdge = Graphs.getOppositeVertex(this.graph, edge, vertex); // check if the path does not loop over the start vertex. if (!vertexReachedByEdge.equals(this.startVertex)) { if (this.seenDataContainer.containsKey(vertexReachedByEdge)) { boolean relaxed = tryToAddNewPaths(vertexReachedByEdge, edge); if (relaxed) { improvedVertices.add(vertexReachedByEdge); } } else { boolean relaxed = tryToAddFirstPaths(vertexReachedByEdge, edge); if (relaxed) { improvedVertices.add(vertexReachedByEdge); } } } } } } // End KShortestPathsIterator.java




© 2015 - 2024 Weber Informatics LLC | Privacy Policy