/* * Copyright (C) 2011 Virginia Tech Department of Computer Science * * 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 sofia.internal; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Set; // ------------------------------------------------------------------------- /** * A directed graph that is represented as a {@code HashMap} that maps each * vertex to a {@code HashSet} of the vertices that it has edges to. * * @param <V> the type of object that represents vertices in the graph * * @author Tony Allevato */ public class HashGraph<V> { //~ Instance/static variables ............................................. private HashMap<V, HashSet<V>> outEdges; private HashMap<V, HashSet<V>> inEdges; //~ Constructors .......................................................... // ---------------------------------------------------------- /** * Creates a new empty graph. */ public HashGraph() { outEdges = new HashMap<V, HashSet<V>>(); inEdges = new HashMap<V, HashSet<V>>(); } // ---------------------------------------------------------- /** * Adds a vertex to the graph if it does not already exist. This is mostly * useful when you need to add an isolated vertex (with no in- or * out-edges). * * @param vertex the vertex to add */ public void addVertex(V vertex) { if (!outEdges.containsKey(vertex)) { outEdges.put(vertex, new HashSet<V>()); } if (!inEdges.containsKey(vertex)) { inEdges.put(vertex, new HashSet<V>()); } } // ---------------------------------------------------------- /** * Adds a directed edge to the graph, also adding the vertices if they do * not exist. * * @param source the source vertex of the edge * @param destination the destination vertex of the edge */ public void addEdge(V source, V destination) { addVertex(source); addVertex(destination); outEdges.get(source).add(destination); inEdges.get(destination).add(source); } // ---------------------------------------------------------- /** * Removes an edge from the graph. * * @param source the source vertex of the edge * @param destination the destination vertex of the edge */ public void removeEdge(V source, V destination) { outEdges.get(source).remove(destination); inEdges.get(destination).remove(source); } // ---------------------------------------------------------- /** * Gets a value indicating whether there is an edge from the source to the * destination. * * @param source the source vertex * @param destination the destination * @return true if there is an edge, otherwise false */ public boolean pointsTo(V source, V destination) { if (outEdges.containsKey(source)) { return outEdges.get(source).contains(destination); } else { return false; } } // ---------------------------------------------------------- /** * Gets the collection of vertices to which the specified vertex points. * * @param vertex the vertex * @return the collection of vertices to which the specified vertex points */ public Collection<V> outVertexSet(V vertex) { HashSet<V> adjacent = outEdges.get(vertex); return adjacent != null ? adjacent : Collections.<V>emptySet(); } // ---------------------------------------------------------- /** * Gets the collection of vertices that point to the specified vertex. * * @param vertex the vertex * @return the collection of vertices that point to the specified vertex */ public Collection<V> inVertexSet(V vertex) { HashSet<V> adjacent = inEdges.get(vertex); return adjacent != null ? adjacent : Collections.<V>emptySet(); } // ---------------------------------------------------------- /** * Gets the set of vertices in the graph. * * @return the set of vertices in the graph */ public Set<V> vertexSet() { return outEdges.keySet(); } // ---------------------------------------------------------- /** * Gets a value indicating whether the specified vertex is a source (that * is, it has no edges coming into it). * * @param vertex the vertex * @return true if the vertex is a source, otherwise false */ public boolean isSource(V vertex) { return inEdges.get(vertex).isEmpty(); } // ---------------------------------------------------------- /** * Gets the set of source vertices in the graph; that is, vertices with no * incoming edges. * * @return the set of source vertices in the graph */ public Set<V> sourceVertexSet() { HashSet<V> sources = new HashSet<V>(); for (V vertex : vertexSet()) { if (isSource(vertex)) { sources.add(vertex); } } return sources; } // ---------------------------------------------------------- /** * Gets a value indicating whether the specified vertex is a sink (that is, * it has no edges going out of it). * * @param vertex the vertex * @return true if the vertex is a sink, otherwise false */ public boolean isSink(V vertex) { return outEdges.get(vertex).isEmpty(); } // ---------------------------------------------------------- /** * Gets the set of sink vertices in the graph; that is, vertices with no * outgoing edges. * * @return the set of sink vertices in the graph */ public Set<V> sinkVertexSet() { HashSet<V> sinks = new HashSet<V>(); for (V vertex : vertexSet()) { if (isSink(vertex)) { sinks.add(vertex); } } return sinks; } }