org.jgrapht.GraphTests Maven / Gradle / Ivy
/*
* (C) Copyright 2003-2020, by Barak Naveh, Dimitrios Michail and Contributors.
*
* JGraphT : a free Java graph-theory library
*
* See the CONTRIBUTORS.md file distributed with this work for additional
* information regarding copyright ownership.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0, or the
* GNU Lesser General Public License v2.1 or later
* which is available at
* http://www.gnu.org/licenses/old-licenses/lgpl-2.1-standalone.html.
*
* SPDX-License-Identifier: EPL-2.0 OR LGPL-2.1-or-later
*/
package org.jgrapht;
import org.jgrapht.alg.connectivity.*;
import org.jgrapht.alg.cycle.*;
import org.jgrapht.alg.interfaces.*;
import org.jgrapht.alg.partition.*;
import org.jgrapht.alg.planar.*;
import java.util.*;
import java.util.stream.*;
/**
* A collection of utilities to test for various graph properties.
*
* @author Barak Naveh
* @author Dimitrios Michail
* @author Joris Kinable
* @author Alexandru Valeanu
*/
public abstract class GraphTests
{
private static final String GRAPH_CANNOT_BE_NULL = "Graph cannot be null";
private static final String GRAPH_MUST_BE_DIRECTED_OR_UNDIRECTED =
"Graph must be directed or undirected";
private static final String GRAPH_MUST_BE_UNDIRECTED = "Graph must be undirected";
private static final String GRAPH_MUST_BE_DIRECTED = "Graph must be directed";
private static final String GRAPH_MUST_BE_WEIGHTED = "Graph must be weighted";
/**
* 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 (parallel)
* 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);
GraphType type = graph.getType();
if (type.isSimple()) {
return true;
}
// no luck, we have to check
for (V v : graph.vertexSet()) {
Set neighbors = new HashSet<>();
for (E e : graph.outgoingEdgesOf(v)) {
V u = Graphs.getOppositeVertex(graph, e, v);
if (u.equals(v) || !neighbors.add(u)) {
return false;
}
}
}
return true;
}
/**
* Check if a graph has self-loops. A self-loop is an edge with the same source and target
* vertices.
*
* @param graph a graph
* @param the graph vertex type
* @param the graph edge type
* @return true if a graph has self-loops, false otherwise
*/
public static boolean hasSelfLoops(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isAllowingSelfLoops()) {
return false;
}
// no luck, we have to check
for (E e : graph.edgeSet()) {
if (graph.getEdgeSource(e).equals(graph.getEdgeTarget(e))) {
return true;
}
}
return false;
}
/**
* Check if a graph has multiple edges (parallel edges), that is, whether the graph contains two
* or more edges connecting the same pair of vertices.
*
* @param graph a graph
* @param the graph vertex type
* @param the graph edge type
* @return true if a graph has multiple edges, false otherwise
*/
public static boolean hasMultipleEdges(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isAllowingMultipleEdges()) {
return false;
}
// no luck, we have to check
for (V v : graph.vertexSet()) {
Set neighbors = new HashSet<>();
for (E e : graph.outgoingEdgesOf(v)) {
V u = Graphs.getOppositeVertex(graph, e, v);
if (!neighbors.add(u)) {
return true;
}
}
}
return false;
}
/**
* 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.getType().isDirected()) {
allEdges = Math.multiplyExact(n, n - 1);
} else if (graph.getType().isUndirected()) {
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 if the inspected graph is connected. A graph is connected when, while ignoring edge
* directionality, there exists a path between every pair of vertices. In a connected graph,
* there are no unreachable vertices. When the inspected graph is a directed graph, this
* method returns true if and only if the inspected graph is weakly connected. An empty
* graph is not considered 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(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new ConnectivityInspector<>(graph).isConnected();
}
/**
* Tests if the inspected graph is biconnected. A biconnected graph is a connected graph on two
* or more vertices having no cutpoints.
*
*
* This method does not performing any caching, instead recomputes everything from scratch. In
* case more control is required use
* {@link org.jgrapht.alg.connectivity.BiconnectivityInspector} directly.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is biconnected, false otherwise
* @see org.jgrapht.alg.connectivity.BiconnectivityInspector
*/
public static boolean isBiconnected(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new BiconnectivityInspector<>(graph).isBiconnected();
}
/**
* 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(Graph graph)
{
return isConnected(graph);
}
/**
* Test whether a 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.
*
*
* In case of undirected graphs this method delegated to {@link #isConnected(Graph)}.
*
* @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(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
if (graph.getType().isUndirected()) {
return isConnected(graph);
} else {
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(Graph graph)
{
if (!graph.getType().isUndirected()) {
throw new IllegalArgumentException(GRAPH_MUST_BE_UNDIRECTED);
}
return (graph.edgeSet().size() == (graph.vertexSet().size() - 1)) && isConnected(graph);
}
/**
* Test whether an undirected graph is a forest. A forest is a set of disjoint trees. By
* definition, any acyclic graph is a forest. This includes the empty graph and the class of
* tree graphs.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is forest, false otherwise
*/
public static boolean isForest(Graph graph)
{
if (!graph.getType().isUndirected()) {
throw new IllegalArgumentException(GRAPH_MUST_BE_UNDIRECTED);
}
if (graph.vertexSet().isEmpty()) // null graph is not a forest
return false;
int nrConnectedComponents = new ConnectivityInspector<>(graph).connectedSets().size();
return graph.edgeSet().size() + nrConnectedComponents == graph.vertexSet().size();
}
/**
* Test whether a graph is overfull.
* A graph is overfull if $|E|>\Delta(G)\lfloor |V|/2 \rfloor$, where $\Delta(G)$ is the
* maximum degree of the graph.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is overfull, false otherwise
*/
public static boolean isOverfull(Graph graph)
{
int maxDegree = graph.vertexSet().stream().mapToInt(graph::degreeOf).max().getAsInt();
return graph.edgeSet().size() > maxDegree * Math.floor(graph.vertexSet().size() / 2.0);
}
/**
* Test whether an undirected graph is a
* split graph. A split graph is a graph
* in which the vertices can be partitioned into a clique and an independent set. Split graphs
* are a special class of chordal graphs. Given the degree sequence $d_1 \geq,\dots,\geq d_n$ of
* $G$, a graph is a split graph if and only if : \[\sum_{i=1}^m d_i = m (m - 1) + \sum_{i=m +
* 1}^nd_i\], where $m = \max_i \{d_i\geq i-1\}$. If the graph is a split graph, then the $m$
* vertices with the largest degrees form a maximum clique in $G$, and the remaining vertices
* constitute an independent set. See Brandstadt, A., Le, V., Spinrad, J. Graph Classes: A
* Survey. Philadelphia, PA: SIAM, 1999. for details.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is a split graph, false otherwise
*/
public static boolean isSplit(Graph graph)
{
requireUndirected(graph);
if (!isSimple(graph) || graph.vertexSet().isEmpty())
return false;
List degrees = new ArrayList<>(graph.vertexSet().size());
degrees
.addAll(graph.vertexSet().stream().map(graph::degreeOf).collect(Collectors.toList()));
Collections.sort(degrees, Collections.reverseOrder()); // sort degrees descending order
// Find m = \max_i \{d_i\geq i-1\}
int m = 1;
for (; m < degrees.size() && degrees.get(m) >= m; m++) {
}
m--;
int left = 0;
for (int i = 0; i <= m; i++)
left += degrees.get(i);
int right = m * (m + 1);
for (int i = m + 1; i < degrees.size(); i++)
right += degrees.get(i);
return left == right;
}
/**
* 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
* @see BipartitePartitioning#isBipartite()
*/
public static boolean isBipartite(Graph graph)
{
return new BipartitePartitioning<>(graph).isBipartite();
}
/**
* 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
* @see BipartitePartitioning#isValidPartitioning(PartitioningAlgorithm.Partitioning)
*/
@SuppressWarnings("unchecked")
public static boolean isBipartitePartition(
Graph graph, Set extends V> firstPartition, Set extends V> secondPartition)
{
return new BipartitePartitioning<>(graph)
.isValidPartitioning(
new PartitioningAlgorithm.PartitioningImpl<>(
Arrays.asList((Set) firstPartition, (Set) secondPartition)));
}
/**
* Tests whether a graph is cubic. A
* graph is cubic if all vertices have degree 3.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is cubic, false otherwise
*/
public static boolean isCubic(Graph graph)
{
for (V v : graph.vertexSet())
if (graph.degreeOf(v) != 3)
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);
}
/**
* Checks whether a graph is chordal. A
* chordal graph is one in which all cycles of four or more vertices have a chord, which is
* an edge that is not part of the cycle but connects two vertices of the cycle.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is chordal, false otherwise
* @see ChordalityInspector#isChordal()
*/
public static boolean isChordal(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new ChordalityInspector<>(graph).isChordal();
}
/**
* Checks whether a graph is weakly
* chordal.
*
* The following definitions are equivalent:
*
* - A graph is weakly chordal (weakly triangulated) if neither it nor its complement contains
* a chordless cycles with five
* or more vertices.
* - A 2-pair in a graph is a pair of non-adjacent vertices $x$, $y$ such that every chordless
* path has exactly two edges. A graph is weakly chordal if every connected
* induced subgraph $H$ that is not
* a complete graph, contains a 2-pair.
*
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is weakly chordal, false otherwise
* @see WeakChordalityInspector#isWeaklyChordal()
*/
public static boolean isWeaklyChordal(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new WeakChordalityInspector<>(graph).isWeaklyChordal();
}
/**
* Tests whether an undirected graph meets Ore's condition to be Hamiltonian.
*
* Let $G$ be a (finite and simple) graph with $n \geq 3$ vertices. We denote by $deg(v)$ the
* degree of a vertex $v$ in $G$, i.e. the number of incident edges in $G$ to $v$. Then, Ore's
* theorem states that if $deg(v) + deg(w) \geq n$ for every pair of distinct non-adjacent
* vertices $v$ and $w$ of $G$, then $G$ is Hamiltonian.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph meets Ore's condition, false otherwise
* @see org.jgrapht.alg.tour.PalmerHamiltonianCycle
*/
public static boolean hasOreProperty(Graph graph)
{
requireUndirected(graph);
final int n = graph.vertexSet().size();
if (!graph.getType().isSimple() || n < 3)
return false;
List vertexList = new ArrayList<>(graph.vertexSet());
for (int i = 0; i < vertexList.size(); i++) {
for (int j = i + 1; j < vertexList.size(); j++) {
V v = vertexList.get(i);
V w = vertexList.get(j);
if (!v.equals(w) && !graph.containsEdge(v, w)
&& graph.degreeOf(v) + graph.degreeOf(w) < n)
return false;
}
}
return true;
}
/**
* Tests whether an undirected graph is triangle-free (i.e. no three distinct vertices form a
* triangle of edges).
*
* The implementation of this method uses {@link GraphMetrics#getNumberOfTriangles(Graph)}.
*
* @param graph the input graph
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is triangle-free, false otherwise
*/
public static boolean isTriangleFree(Graph graph)
{
return GraphMetrics.getNumberOfTriangles(graph) == 0;
}
/**
* Checks that the specified graph is perfect. Due to the Strong Perfect Graph Theorem Berge
* Graphs are the same as perfect Graphs. The implementation of this method is delegated to
* {@link org.jgrapht.alg.cycle.BergeGraphInspector}
*
* @param graph the graph reference to check for being perfect or not
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is perfect, false otherwise
*/
public static boolean isPerfect(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new BergeGraphInspector().isBerge(graph);
}
/**
* Checks that the specified graph is planar. A graph is
* planar if it can be drawn on a
* two-dimensional plane without any of its edges crossing. The implementation of the method is
* delegated to the {@link org.jgrapht.alg.planar.BoyerMyrvoldPlanarityInspector}. Also, use
* this class to get a planar embedding of the graph in case it is planar, or a Kuratowski
* subgraph as a certificate of nonplanarity.
*
* @param graph the graph to test planarity of
* @param the graph vertex type
* @param the graph edge type
* @return true if the graph is planar, false otherwise
* @see PlanarityTestingAlgorithm
* @see BoyerMyrvoldPlanarityInspector
*/
public static boolean isPlanar(Graph graph)
{
Objects.requireNonNull(graph, GRAPH_CANNOT_BE_NULL);
return new BoyerMyrvoldPlanarityInspector<>(graph).isPlanar();
}
/**
* Checks whether the {@code graph} is a Kuratowski
* subdivision. Effectively checks whether the {@code graph} is a $K_{3,3}$ subdivision or
* $K_{5}$ subdivision
*
* @param graph the graph to test
* @param the graph vertex type
* @param the graph edge type
* @return true if the {@code graph} is a Kuratowski subdivision, false otherwise
*/
public static boolean isKuratowskiSubdivision(Graph graph)
{
return isK33Subdivision(graph) || isK5Subdivision(graph);
}
/**
* Checks whether the {@code graph} is a $K_{3,3}$ subdivision.
*
* @param graph the graph to test
* @param the graph vertex type
* @param the graph edge type
* @return true if the {@code graph} is a $K_{3,3}$ subdivision, false otherwise
*/
public static boolean isK33Subdivision(Graph graph)
{
List degree3 = new ArrayList<>();
// collect all vertices with degree 3
for (V vertex : graph.vertexSet()) {
int degree = graph.degreeOf(vertex);
if (degree == 3) {
degree3.add(vertex);
} else if (degree != 2) {
return false;
}
}
if (degree3.size() != 6) {
return false;
}
V vertex = degree3.remove(degree3.size() - 1);
Set reachable = reachableWithDegree(graph, vertex, 3);
if (reachable.size() != 3) {
return false;
}
degree3.removeAll(reachable);
return reachable.equals(reachableWithDegree(graph, degree3.get(0), 3))
&& reachable.equals(reachableWithDegree(graph, degree3.get(1), 3));
}
/**
* Checks whether the {@code graph} is a $K_5$ subdivision.
*
* @param graph the graph to test
* @param the graph vertex type
* @param the graph edge type
* @return true if the {@code graph} is a $K_5$ subdivision, false otherwise
*/
public static boolean isK5Subdivision(Graph graph)
{
Set degree5 = new HashSet<>();
for (V vertex : graph.vertexSet()) {
int degree = graph.degreeOf(vertex);
if (degree == 4) {
degree5.add(vertex);
} else if (degree != 2) {
return false;
}
}
if (degree5.size() != 5) {
return false;
}
for (V vertex : degree5) {
Set reachable = reachableWithDegree(graph, vertex, 4);
if (reachable.size() != 4 || !degree5.containsAll(reachable)
|| reachable.contains(vertex))
{
return false;
}
}
return true;
}
/**
* Uses BFS to find all vertices of the {@code graph} which have a degree {@code degree}. This
* method doesn't advance to new nodes after it finds a node with a degree {@code degree}
*
* @param graph the graph to search in
* @param startVertex the start vertex
* @param degree the degree of desired vertices
* @param the graph vertex type
* @param the graph edge type
* @return all vertices of the {@code graph} reachable from {@code startVertex}, which have
* degree {@code degree}
*/
private static Set reachableWithDegree(Graph graph, V startVertex, int degree)
{
Set visited = new HashSet<>();
Set reachable = new HashSet<>();
Queue queue = new ArrayDeque<>();
queue.add(startVertex);
while (!queue.isEmpty()) {
V current = queue.poll();
visited.add(current);
for (E e : graph.edgesOf(current)) {
V opposite = Graphs.getOppositeVertex(graph, e, current);
if (visited.contains(opposite)) {
continue;
}
if (graph.degreeOf(opposite) == degree) {
reachable.add(opposite);
} else {
queue.add(opposite);
}
}
}
return reachable;
}
/**
* Checks that the specified graph is directed and throws a customized
* {@link IllegalArgumentException} if it is not. Also checks that the graph reference is not
* {@code null} and throws a {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for beeing directed and not null
* @param message detail message to be used in the event that an exception is thrown
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if directed and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is not directed
*/
public static Graph requireDirected(Graph graph, String message)
{
if (graph == null)
throw new NullPointerException(GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isDirected()) {
throw new IllegalArgumentException(message);
}
return graph;
}
/**
* Checks that the specified graph is directed and throws an {@link IllegalArgumentException} if
* it is not. Also checks that the graph reference is not {@code null} and throws a
* {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for beeing directed and not null
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if directed and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is not directed
*/
public static Graph requireDirected(Graph graph)
{
return requireDirected(graph, GRAPH_MUST_BE_DIRECTED);
}
/**
* Checks that the specified graph is undirected and throws a customized
* {@link IllegalArgumentException} if it is not. Also checks that the graph reference is not
* {@code null} and throws a {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for being undirected and not null
* @param message detail message to be used in the event that an exception is thrown
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if undirected and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is not undirected
*/
public static Graph requireUndirected(Graph graph, String message)
{
if (graph == null)
throw new NullPointerException(GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isUndirected()) {
throw new IllegalArgumentException(message);
}
return graph;
}
/**
* Checks that the specified graph is undirected and throws an {@link IllegalArgumentException}
* if it is not. Also checks that the graph reference is not {@code null} and throws a
* {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for being undirected and not null
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if undirected and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is not undirected
*/
public static Graph requireUndirected(Graph graph)
{
return requireUndirected(graph, GRAPH_MUST_BE_UNDIRECTED);
}
/**
* Checks that the specified graph is directed or undirected and throws a customized
* {@link IllegalArgumentException} if it is not. Also checks that the graph reference is not
* {@code null} and throws a {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for beeing directed or undirected and not null
* @param message detail message to be used in the event that an exception is thrown
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if directed and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is mixed
*/
public static Graph requireDirectedOrUndirected(Graph graph, String message)
{
if (graph == null)
throw new NullPointerException(GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isDirected() && !graph.getType().isUndirected()) {
throw new IllegalArgumentException(message);
}
return graph;
}
/**
* Checks that the specified graph is directed and throws an {@link IllegalArgumentException} if
* it is not. Also checks that the graph reference is not {@code null} and throws a
* {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for beeing directed and not null
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if directed and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is mixed
*/
public static Graph requireDirectedOrUndirected(Graph graph)
{
return requireDirectedOrUndirected(graph, GRAPH_MUST_BE_DIRECTED_OR_UNDIRECTED);
}
/**
* Checks that the specified graph is weighted and throws a customized
* {@link IllegalArgumentException} if it is not. Also checks that the graph reference is not
* {@code null} and throws a {@link NullPointerException} if it is.
*
* @param graph the graph reference to check for being weighted and not null
* @param the graph vertex type
* @param the graph edge type
* @return {@code graph} if directed and not {@code null}
* @throws NullPointerException if {@code graph} is {@code null}
* @throws IllegalArgumentException if {@code graph} is not weighted
*/
public static Graph requireWeighted(Graph graph)
{
if (graph == null)
throw new NullPointerException(GRAPH_CANNOT_BE_NULL);
if (!graph.getType().isWeighted()) {
throw new IllegalArgumentException(GRAPH_MUST_BE_WEIGHTED);
}
return graph;
}
}