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

org.jgrapht.GraphTests Maven / Gradle / Ivy

There is a newer version: 1.5.2
Show newest version
/*
 * (C) Copyright 2003-2017, by Barak Naveh, Dimitrios Michail 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 org.jgrapht.alg.*;
import org.jgrapht.alg.cycle.*;
import org.jgrapht.graph.*;

/**
 * A collection of utilities to test for various graph properties.
 * 
 * @author Barak Naveh
 * @author Dimitrios Michail
 */
public abstract class GraphTests
{

    /**
     * Test whether a graph is empty. An empty graph on n nodes consists of n isolated vertices with
     * no edges.
     * 
     * @param graph the input graph
     * @param  the graph vertex type
     * @param  the graph edge type
     * @return true if the graph is empty, false otherwise
     */
    public static  boolean isEmpty(Graph graph)
    {
        Objects.requireNonNull(graph, "Graph cannot be null");
        return graph.edgeSet().isEmpty();
    }

    /**
     * Check if a graph is simple. A graph is simple if it has no self-loops and multiple edges.
     * 
     * @param graph a graph
     * @param  the graph vertex type
     * @param  the graph edge type
     * @return true if a graph is simple, false otherwise
     */
    public static  boolean isSimple(Graph graph)
    {
        Objects.requireNonNull(graph, "Graph cannot be null");
        if (graph instanceof AbstractBaseGraph) {
            AbstractBaseGraph abg = (AbstractBaseGraph) graph;
            if (!abg.isAllowingLoops() && !abg.isAllowingMultipleEdges()) {
                return true;
            }
        }
        // no luck, we have to check
        boolean isDirected = graph instanceof DirectedGraph;
        for (V v : graph.vertexSet()) {
            Iterable edgesOf;
            if (isDirected) {
                edgesOf = ((DirectedGraph) graph).outgoingEdgesOf(v);
            } else {
                edgesOf = graph.edgesOf(v);
            }
            Set neighbors = new HashSet<>();
            for (E e : edgesOf) {
                V u = Graphs.getOppositeVertex(graph, e, v);
                if (u.equals(v) || !neighbors.add(u)) {
                    return false;
                }
            }
        }

        return true;
    }

    /**
     * Test whether a graph is complete. A complete undirected graph is a simple graph in which
     * every pair of distinct vertices is connected by a unique edge. A complete directed graph is a
     * directed graph in which every pair of distinct vertices is connected by a pair of unique
     * edges (one in each direction).
     * 
     * @param graph the input graph
     * @param  the graph vertex type
     * @param  the graph edge type
     * @return true if the graph is complete, false otherwise
     */
    public static  boolean isComplete(Graph graph)
    {
        Objects.requireNonNull(graph, "Graph cannot be null");
        int n = graph.vertexSet().size();
        int allEdges;
        if (graph instanceof DirectedGraph) {
            allEdges = Math.multiplyExact(n, n - 1);
        } else if (graph instanceof UndirectedGraph) {
            if (n % 2 == 0) {
                allEdges = Math.multiplyExact(n / 2, n - 1);
            } else {
                allEdges = Math.multiplyExact(n, (n - 1) / 2);
            }
        } else {
            throw new IllegalArgumentException("Graph must be directed or undirected");
        }
        return graph.edgeSet().size() == allEdges && isSimple(graph);
    }

    /**
     * Test whether an undirected graph is connected.
     * 
     * 

* This method does not performing any caching, instead recomputes everything from scratch. In * case more control is required use {@link ConnectivityInspector} directly. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * @return true if the graph is connected, false otherwise * @see ConnectivityInspector */ public static boolean isConnected(UndirectedGraph graph) { Objects.requireNonNull(graph, "Graph cannot be null"); return new ConnectivityInspector<>(graph).isGraphConnected(); } /** * Test whether a directed graph is weakly connected. * *

* This method does not performing any caching, instead recomputes everything from scratch. In * case more control is required use {@link ConnectivityInspector} directly. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * @return true if the graph is weakly connected, false otherwise * @see ConnectivityInspector */ public static boolean isWeaklyConnected(DirectedGraph graph) { Objects.requireNonNull(graph, "Graph cannot be null"); return new ConnectivityInspector<>(graph).isGraphConnected(); } /** * Test whether a directed graph is strongly connected. * *

* This method does not performing any caching, instead recomputes everything from scratch. In * case more control is required use {@link KosarajuStrongConnectivityInspector} directly. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * @return true if the graph is strongly connected, false otherwise * @see KosarajuStrongConnectivityInspector */ public static boolean isStronglyConnected(DirectedGraph graph) { Objects.requireNonNull(graph, "Graph cannot be null"); return new KosarajuStrongConnectivityInspector<>(graph).isStronglyConnected(); } /** * Test whether an undirected graph is a tree. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * @return true if the graph is tree, false otherwise */ public static boolean isTree(UndirectedGraph graph) { return (graph.edgeSet().size() == (graph.vertexSet().size() - 1)) && isConnected(graph); } /** * Test whether a graph is bipartite. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * @return true if the graph is bipartite, false otherwise */ public static boolean isBipartite(Graph graph) { if (isEmpty(graph)) { return true; } try { // at most n^2/4 edges if (Math.multiplyExact(4, graph.edgeSet().size()) > Math .multiplyExact(graph.vertexSet().size(), graph.vertexSet().size())) { return false; } } catch (ArithmeticException e) { // ignore } Set unknown = new HashSet<>(graph.vertexSet()); Set odd = new HashSet<>(); Deque queue = new LinkedList<>(); while (!unknown.isEmpty()) { if (queue.isEmpty()) { queue.add(unknown.iterator().next()); } V v = queue.removeFirst(); unknown.remove(v); for (E e : graph.edgesOf(v)) { V n = Graphs.getOppositeVertex(graph, e, v); if (unknown.contains(n)) { queue.add(n); if (!odd.contains(v)) { odd.add(n); } } else if (!(odd.contains(v) ^ odd.contains(n))) { return false; } } } return true; } /** * Test whether a partition of the vertices into two sets is a bipartite partition. * * @param graph the input graph * @param firstPartition the first vertices partition * @param secondPartition the second vertices partition * @return true if the partition is a bipartite partition, false otherwise * @param the graph vertex type * @param the graph edge type */ public static boolean isBipartitePartition( Graph graph, Set firstPartition, Set secondPartition) { Objects.requireNonNull(graph, "Graph cannot be null"); Objects.requireNonNull(firstPartition, "First partition cannot be null"); Objects.requireNonNull(secondPartition, "Second partition cannot be null"); if (graph.vertexSet().size() != firstPartition.size() + secondPartition.size()) { return false; } for (V v : graph.vertexSet()) { Set otherPartition; if (firstPartition.contains(v)) { otherPartition = secondPartition; } else if (secondPartition.contains(v)) { otherPartition = firstPartition; } else { // v does not belong to any of the two partitions return false; } for (E e : graph.edgesOf(v)) { V other = Graphs.getOppositeVertex(graph, e, v); if (!otherPartition.contains(other)) { return false; } } } return true; } /** * Test whether a graph is Eulerian. An undirected graph is Eulerian if it is connected and each * vertex has an even degree. A directed graph is Eulerian if it is strongly connected and each * vertex has the same incoming and outgoing degree. Test whether a graph is Eulerian. An * Eulerian graph is a graph * containing an Eulerian cycle. * * @param graph the input graph * @param the graph vertex type * @param the graph edge type * * @return true if the graph is Eulerian, false otherwise * @see HierholzerEulerianCycle#isEulerian(Graph) */ public static boolean isEulerian(Graph graph) { Objects.requireNonNull(graph, "Graph cannot be null"); return new HierholzerEulerianCycle().isEulerian(graph); } } // End GraphTests.java





© 2015 - 2024 Weber Informatics LLC | Privacy Policy