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

org.jgrapht.Graphs Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
/*
 * (C) Copyright 2003-2017, by Barak Naveh and Contributors.
 *
 * JGraphT : a free Java graph-theory library
 *
 * 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.
 */
package org.jgrapht;

import java.util.*;
import java.util.function.*;

import org.jgrapht.graph.*;

/**
 * A collection of utilities to assist with graph manipulation.
 *
 * @author Barak Naveh
 * @since Jul 31, 2003
 */
public abstract class Graphs
{
    /**
     * Creates a new edge and adds it to the specified graph similarly to the
     * {@link Graph#addEdge(Object, Object)} method.
     *
     * @param g the graph for which the edge to be added
     * @param sourceVertex source vertex of the edge
     * @param targetVertex target vertex of the edge
     * @param weight weight of the edge
     * @param  the graph vertex type
     * @param  the graph edge type
     *
     * @return The newly created edge if added to the graph, otherwise 
     * null.
     *
     * @see Graph#addEdge(Object, Object)
     */
    public static  E addEdge(Graph g, V sourceVertex, V targetVertex, double weight)
    {
        EdgeFactory ef = g.getEdgeFactory();
        E e = ef.createEdge(sourceVertex, targetVertex);

        // we first create the edge and set the weight to make sure that
        // listeners will see the correct weight upon addEdge.

        assert (g instanceof WeightedGraph) : g.getClass();
        ((WeightedGraph) g).setEdgeWeight(e, weight);

        return g.addEdge(sourceVertex, targetVertex, e) ? e : null;
    }

    /**
     * Adds the specified source and target vertices to the graph, if not already included, and
     * creates a new edge and adds it to the specified graph similarly to the
     * {@link Graph#addEdge(Object, Object)} method.
     *
     * @param g the graph for which the specified edge to be added
     * @param sourceVertex source vertex of the edge
     * @param targetVertex target vertex of the edge
     * @param  the graph vertex type
     * @param  the graph edge type
     *
     * @return The newly created edge if added to the graph, otherwise 
     * null.
     */
    public static  E addEdgeWithVertices(Graph g, V sourceVertex, V targetVertex)
    {
        g.addVertex(sourceVertex);
        g.addVertex(targetVertex);

        return g.addEdge(sourceVertex, targetVertex);
    }

    /**
     * Adds the specified edge to the graph, including its vertices if not already included.
     *
     * @param targetGraph the graph for which the specified edge to be added
     * @param sourceGraph the graph in which the specified edge is already present
     * @param edge edge to add
     * @param  the graph vertex type
     * @param  the graph edge type
     *
     * @return true if the target graph did not already contain the specified edge.
     */
    public static  boolean addEdgeWithVertices(Graph targetGraph, Graph sourceGraph, E edge)
    {
        V sourceVertex = sourceGraph.getEdgeSource(edge);
        V targetVertex = sourceGraph.getEdgeTarget(edge);

        targetGraph.addVertex(sourceVertex);
        targetGraph.addVertex(targetVertex);

        return targetGraph.addEdge(sourceVertex, targetVertex, edge);
    }

    /**
     * Adds the specified source and target vertices to the graph, if not already included, and
     * creates a new weighted edge and adds it to the specified graph similarly to the
     * {@link Graph#addEdge(Object, Object)} method.
     *
     * @param g the graph for which the specified edge to be added
     * @param sourceVertex source vertex of the edge
     * @param targetVertex target vertex of the edge
     * @param weight weight of the edge
     * @param  the graph vertex type
     * @param  the graph edge type
     *
     * @return The newly created edge if added to the graph, otherwise 
     * null.
     */
    public static  E addEdgeWithVertices(Graph g, V sourceVertex, V targetVertex, double weight)
    {
        g.addVertex(sourceVertex);
        g.addVertex(targetVertex);

        return addEdge(g, sourceVertex, targetVertex, weight);
    }

    /**
     * Adds all the vertices and all the edges of the specified source graph to the specified
     * destination graph. First all vertices of the source graph are added to the destination graph.
     * Then every edge of the source graph is added to the destination graph. This method returns
     * true if the destination graph has been modified as a result of this operation,
     * otherwise it returns false.
     *
     * 

* The behavior of this operation is undefined if any of the specified graphs is modified while * operation is in progress. *

* * @param destination the graph to which vertices and edges are added * @param source the graph used as source for vertices and edges to add * @param the graph vertex type * @param the graph edge type * * @return true if and only if the destination graph has been changed as a result * of this operation. */ public static boolean addGraph(Graph destination, Graph source) { boolean modified = addAllVertices(destination, source.vertexSet()); modified |= addAllEdges(destination, source, source.edgeSet()); return modified; } /** * Adds all the vertices and all the edges of the specified source digraph to the specified * destination digraph, reversing all of the edges. If you want to do this as a linked view of * the source graph (rather than by copying to a destination graph), use * {@link EdgeReversedGraph} instead. * *

* The behavior of this operation is undefined if any of the specified graphs is modified while * operation is in progress. *

* * @param destination the graph to which vertices and edges are added * @param source the graph used as source for vertices and edges to add * @param the graph vertex type * @param the graph edge type * * @see EdgeReversedGraph */ public static void addGraphReversed( DirectedGraph destination, DirectedGraph source) { addAllVertices(destination, source.vertexSet()); for (E edge : source.edgeSet()) { destination.addEdge(source.getEdgeTarget(edge), source.getEdgeSource(edge)); } } /** * Adds a subset of the edges of the specified source graph to the specified destination graph. * The behavior of this operation is undefined if either of the graphs is modified while the * operation is in progress. {@link #addEdgeWithVertices} is used for the transfer, so source * vertexes will be added automatically to the target graph. * * @param destination the graph to which edges are to be added * @param source the graph used as a source for edges to add * @param edges the edges to be added * @param the graph vertex type * @param the graph edge type * * @return true if this graph changed as a result of the call */ public static boolean addAllEdges( Graph destination, Graph source, Collection edges) { boolean modified = false; for (E e : edges) { V s = source.getEdgeSource(e); V t = source.getEdgeTarget(e); destination.addVertex(s); destination.addVertex(t); modified |= destination.addEdge(s, t, e); } return modified; } /** * Adds all of the specified vertices to the destination graph. The behavior of this operation * is undefined if the specified vertex collection is modified while the operation is in * progress. This method will invoke the {@link Graph#addVertex(Object)} method. * * @param destination the graph to which edges are to be added * @param vertices the vertices to be added to the graph * @param the graph vertex type * @param the graph edge type * * @return true if graph changed as a result of the call * * @throws NullPointerException if the specified vertices contains one or more null vertices, or * if the specified vertex collection is * null. * * @see Graph#addVertex(Object) */ public static boolean addAllVertices( Graph destination, Collection vertices) { boolean modified = false; for (V v : vertices) { modified |= destination.addVertex(v); } return modified; } /** * Returns a list of vertices that are the neighbors of a specified vertex. If the graph is a * multigraph vertices may appear more than once in the returned list. * * @param g the graph to look for neighbors in * @param vertex the vertex to get the neighbors of * @param the graph vertex type * @param the graph edge type * * @return a list of the vertices that are the neighbors of the specified vertex. */ public static List neighborListOf(Graph g, V vertex) { List neighbors = new ArrayList<>(); for (E e : g.edgesOf(vertex)) { neighbors.add(getOppositeVertex(g, e, vertex)); } return neighbors; } /** * Returns a list of vertices that are the direct predecessors of a specified vertex. If the * graph is a multigraph, vertices may appear more than once in the returned list. * * @param g the graph to look for predecessors in * @param vertex the vertex to get the predecessors of * @param the graph vertex type * @param the graph edge type * * @return a list of the vertices that are the direct predecessors of the specified vertex. */ public static List predecessorListOf(DirectedGraph g, V vertex) { List predecessors = new ArrayList<>(); Set edges = g.incomingEdgesOf(vertex); for (E e : edges) { predecessors.add(getOppositeVertex(g, e, vertex)); } return predecessors; } /** * Returns a list of vertices that are the direct successors of a specified vertex. If the graph * is a multigraph vertices may appear more than once in the returned list. * * @param g the graph to look for successors in * @param vertex the vertex to get the successors of * @param the graph vertex type * @param the graph edge type * * @return a list of the vertices that are the direct successors of the specified vertex. */ public static List successorListOf(DirectedGraph g, V vertex) { List successors = new ArrayList<>(); Set edges = g.outgoingEdgesOf(vertex); for (E e : edges) { successors.add(getOppositeVertex(g, e, vertex)); } return successors; } /** * Returns an undirected view of the specified graph. If the specified graph is directed, * returns an undirected view of it. If the specified graph is already undirected, just returns * it. * * @param g the graph for which an undirected view is to be returned * @param the graph vertex type * @param the graph edge type * * @return an undirected view of the specified graph, if it is directed, or or the specified * graph itself if it is already undirected. * * @throws IllegalArgumentException if the graph is neither DirectedGraph nor UndirectedGraph. * * @see AsUndirectedGraph */ public static UndirectedGraph undirectedGraph(Graph g) { if (g instanceof DirectedGraph) { return new AsUndirectedGraph<>((DirectedGraph) g); } else if (g instanceof UndirectedGraph) { return (UndirectedGraph) g; } else { throw new IllegalArgumentException( "Graph must be either DirectedGraph or UndirectedGraph"); } } /** * Tests whether an edge is incident to a vertex. * * @param g graph containing e and v * @param e edge in g * @param v vertex in g * @param the graph vertex type * @param the graph edge type * * @return true iff e is incident on v */ public static boolean testIncidence(Graph g, E e, V v) { return (g.getEdgeSource(e).equals(v)) || (g.getEdgeTarget(e).equals(v)); } /** * Gets the vertex opposite another vertex across an edge. * * @param g graph containing e and v * @param e edge in g * @param v vertex in g * @param the graph vertex type * @param the graph edge type * * @return vertex opposite to v across e */ public static V getOppositeVertex(Graph g, E e, V v) { V source = g.getEdgeSource(e); V target = g.getEdgeTarget(e); if (v.equals(source)) { return target; } else if (v.equals(target)) { return source; } else { throw new IllegalArgumentException("no such vertex: " + v.toString()); } } /** * Removes the given vertex from the given graph. If the vertex to be removed has one or more * predecessors, the predecessors will be connected directly to the successors of the vertex to * be removed. * * @param graph graph to be mutated * @param vertex vertex to be removed from this graph, if present * @param the graph vertex type * @param the graph edge type * * @return true if the graph contained the specified vertex; false otherwise. */ public static boolean removeVertexAndPreserveConnectivity(DirectedGraph graph, V vertex) { if (!graph.containsVertex(vertex)) { return false; } if (vertexHasPredecessors(graph, vertex)) { List predecessors = Graphs.predecessorListOf(graph, vertex); List successors = Graphs.successorListOf(graph, vertex); for (V predecessor : predecessors) { addOutgoingEdges(graph, predecessor, successors); } } graph.removeVertex(vertex); return true; } /** * Filters vertices from the given graph and subsequently removes them. If the vertex to be * removed has one or more predecessors, the predecessors will be connected directly to the * successors of the vertex to be removed. * * @param graph graph to be mutated * @param predicate a non-interfering stateless predicate to apply to each vertex to determine * if it should be removed from the graph * @param the graph vertex type * @param the graph edge type * * @return true if at least one vertex has been removed; false otherwise. */ public static boolean removeVerticesAndPreserveConnectivity( DirectedGraph graph, Predicate predicate) { List verticesToRemove = new ArrayList<>(); for (V node : graph.vertexSet()) { if (predicate.test(node)) { verticesToRemove.add(node); } } return removeVertexAndPreserveConnectivity(graph, verticesToRemove); } /** * Removes all the given vertices from the given graph. If the vertex to be removed has one or * more predecessors, the predecessors will be connected directly to the successors of the * vertex to be removed. * * @param graph to be mutated * @param vertices vertices to be removed from this graph, if present * @param the graph vertex type * @param the graph edge type * * @return true if at least one vertex has been removed; false otherwise. */ public static boolean removeVertexAndPreserveConnectivity( DirectedGraph graph, Iterable vertices) { boolean atLeastOneVertexHasBeenRemoved = false; for (V vertex : vertices) { if (removeVertexAndPreserveConnectivity(graph, vertex)) { atLeastOneVertexHasBeenRemoved = true; } } return atLeastOneVertexHasBeenRemoved; } /** * Add edges from one source vertex to multiple target vertices. Whether duplicates are created * depends on the underlying {@link DirectedGraph} implementation. * * @param graph graph to be mutated * @param source source vertex of the new edges * @param targets target vertices for the new edges * @param the graph vertex type * @param the graph edge type */ public static void addOutgoingEdges(DirectedGraph graph, V source, Iterable targets) { if (!graph.containsVertex(source)) { graph.addVertex(source); } for (V target : targets) { if (!graph.containsVertex(target)) { graph.addVertex(target); } graph.addEdge(source, target); } } /** * Add edges from multiple source vertices to one target vertex. Whether duplicates are created * depends on the underlying {@link DirectedGraph} implementation. * * @param graph graph to be mutated * @param target target vertex for the new edges * @param sources source vertices for the new edges * @param the graph vertex type * @param the graph edge type */ public static void addIncomingEdges(DirectedGraph graph, V target, Iterable sources) { if (!graph.containsVertex(target)) { graph.addVertex(target); } for (V source : sources) { if (!graph.containsVertex(source)) { graph.addVertex(source); } graph.addEdge(source, target); } } /** * Check if a vertex has any direct successors. * * @param graph the graph to look for successors * @param vertex the vertex to look for successors * @param the graph vertex type * @param the graph edge type * * @return true if the vertex has any successors, false otherwise */ public static boolean vertexHasSuccessors(DirectedGraph graph, V vertex) { return !graph.outgoingEdgesOf(vertex).isEmpty(); } /** * Check if a vertex has any direct predecessors. * * @param graph the graph to look for predecessors * @param vertex the vertex to look for predecessors * @param the graph vertex type * @param the graph edge type * * @return true if the vertex has any predecessors, false otherwise */ public static boolean vertexHasPredecessors(DirectedGraph graph, V vertex) { return !graph.incomingEdgesOf(vertex).isEmpty(); } } // End Graphs.java




© 2015 - 2024 Weber Informatics LLC | Privacy Policy