001 package aima.util; 002 003 import java.util.ArrayList; 004 import java.util.Hashtable; 005 import java.util.List; 006 007 /** 008 * Represents a directed labeled graph. Vertices are represented by their unique 009 * labels and labeled edges by means of nested hashtables. Variant of class 010 * {@code aima.util.Table}. This version is more dynamic, it requires no 011 * initialization and can add new items whenever needed. 012 * 013 * @author R. Lunde 014 */ 015 public class LabeledGraph<VertexLabelType, EdgeLabelType> { 016 017 /** 018 * Lookup for edge label information. Contains an entry for every vertex 019 * label. 020 */ 021 private final Hashtable<VertexLabelType, Hashtable<VertexLabelType, EdgeLabelType>> globalEdgeLookup; 022 /** List of the labels of all vertices within the graph. */ 023 private final List<VertexLabelType> vertexLabels; 024 025 /** Creates a new empty graph. */ 026 public LabeledGraph() { 027 globalEdgeLookup = new Hashtable<VertexLabelType, Hashtable<VertexLabelType, EdgeLabelType>>(); 028 vertexLabels = new ArrayList<VertexLabelType>(); 029 } 030 031 /** 032 * Adds a new vertex to the graph if it is not already present. 033 */ 034 public void addVertex(VertexLabelType v) { 035 checkForNewVertex(v); 036 } 037 038 /** 039 * Adds a directed labeled edge to the graph. The end points of the edge are 040 * specified by vertex labels. New vertices are automatically identified and 041 * added to the graph. 042 */ 043 public void set(VertexLabelType from, VertexLabelType to, EdgeLabelType el) { 044 Hashtable<VertexLabelType, EdgeLabelType> localEdgeLookup = checkForNewVertex(from); 045 localEdgeLookup.put(to, el); 046 checkForNewVertex(to); 047 } 048 049 /** Handles new vertices. */ 050 private Hashtable<VertexLabelType, EdgeLabelType> checkForNewVertex( 051 VertexLabelType v) { 052 Hashtable<VertexLabelType, EdgeLabelType> result = globalEdgeLookup 053 .get(v); 054 if (result == null) { 055 result = new Hashtable<VertexLabelType, EdgeLabelType>(); 056 globalEdgeLookup.put(v, result); 057 vertexLabels.add(v); 058 } 059 return result; 060 } 061 062 /** Removes an edge from the graph. */ 063 public void remove(VertexLabelType from, VertexLabelType to) { 064 Hashtable<VertexLabelType, EdgeLabelType> localEdgeLookup = globalEdgeLookup 065 .get(from); 066 if (localEdgeLookup != null) 067 localEdgeLookup.remove(to); 068 } 069 070 /** 071 * Returns the label of the edge between the specified vertices and null if 072 * there is no edge between them. 073 */ 074 public EdgeLabelType get(VertexLabelType from, VertexLabelType to) { 075 Hashtable<VertexLabelType, EdgeLabelType> localEdgeLookup = globalEdgeLookup 076 .get(from); 077 return localEdgeLookup == null ? null : localEdgeLookup.get(to); 078 } 079 080 /** 081 * Returns the labels of those vertices which can be obtained by following 082 * the edges starting at the specified vertex. 083 */ 084 public List<VertexLabelType> getSuccessors(VertexLabelType v) { 085 List<VertexLabelType> result = new ArrayList<VertexLabelType>(); 086 Hashtable<VertexLabelType, EdgeLabelType> localEdgeLookup = globalEdgeLookup 087 .get(v); 088 if (localEdgeLookup != null) 089 result.addAll(localEdgeLookup.keySet()); 090 return result; 091 } 092 093 /** Returns the labels of all vertices within the graph. */ 094 public List<VertexLabelType> getVertexLabels() { 095 return vertexLabels; 096 } 097 098 /** Checks whether the given label is the label of one of the vertices. */ 099 public boolean isVertexLabel(VertexLabelType v) { 100 return globalEdgeLookup.get(v) != null; 101 } 102 103 /** Removes all vertices and all edges from the graph. */ 104 public void clear() { 105 vertexLabels.clear(); 106 globalEdgeLookup.clear(); 107 } 108 }