200 likes | 285 Views
Java Programming. Graphs. Graphs. A graph is a mathematical abstraction that includes Vertices an object in the graph Edges a connection between two vertices. Written as (V1, V 2) meaning there is a connection between V1 and V 2
E N D
Java Programming Graphs
Graphs • A graph is a mathematical abstraction that includes • Vertices • an object in the graph • Edges • a connection between two vertices. Written as (V1, V2) meaning there is a connection between V1 and V2 • Edges may be directed, in which case the edges are known as arcs. (V1, V2) then means FROM V1 TO V2. • A graph is a set of vertices and a set of arcs • G = (V, E) • V is a set of vertices • E is a set of edges
Example • Directed Graph Example: • V = {A,B,C,D,E} • E = {(A,E), (A,B), (B,A), (B,D), (C,E), (D,C), (E,B), (E,C), (E,D)} • G = (V, E)
Graphs : Definitions • Adjacency: • Assume that U and V are vertices in some graph. Vertex U is adjacent to vertex V if there is an arc (U, V) in the graph. • Loop: • any arc such that the first and second nodes of the arc are the same. • In-degree of V. • The number of arcs in the graph having V as the second vertex. • Out-degree of V. • The number of arcs in the graph having V as the first vertex. • Order of G: • the number of vertices. • Size of G: • the number of arcs. • Path: • A sequence of vertices such that for every pair of adjacent vertices in the sequence there is a corresponding arc in the graph. A sequence containing a single vertex is a also a path. • A sequence without repeated vertices is a simple path. • Path Length: • the number of arcs in the path. • Cycle: • A cycle is a path where the length is greater than zero and the first and last vertex are the same. A graph without any cycles is known as an acyclic graph.
Graphs • The order? • The size? • Is A adjacent to E? • Is E adjacent to A? • Out-degree of A? • In-degree of A? • Is there a loop? • Is [A, E, C, E] a path? • Is [A, B, A] a path? • Is the graph acyclic?
DirectedGraph Interface • Java doesn’t have a graph API. We define our own Graph interface.
DirectedGraph Interface • The Graph interface • The interface is generic and allows for vertices and edges of any type • The methods allow us to control the graph structure and inquire about relevant properties of the graph. public interface Graph<V,E> { public booleancontainsEdge(E e); public booleancontainsVertex(V v); public E addEdge(E e, V v1, V v2); public V addVertex(V v); public Collection<V> vertices(); public Collection<E> edges(); public Collection<V> getPredecessors(V v); public Collection<V> getSuccessors(V v); public intinDegree(V v); public intoutDegree(V v); public V getV1(E e); public V getV2(E e); public E getEdge(V v1, V v2); public E removeEdge(E e); public V removeVertex(V v); public int order(); public int size(); public String toString(Collection<E> edges); }
public abstract class AbstractGraph<V,E> implements Graph<V,E> { @Override public int size() { return edges().size(); } @Override public int order() { return vertices().size(); } @Override public booleancontainsEdge(E e) { return edges().contains(e); } @Override public booleancontainsVertex(V v) { return vertices().contains(v); } @Override public intinDegree(V v) { return getPredecessors(v).size(); } @Override public intoutDegree(V v) { return getSuccessors(v).size(); } }
public abstract class AbstractMapGraph<V, E> extends AbstractGraph<V,E> { protected Set<V> vertices; protected HashMap<E, Pair<V>> edges; protected class Pair<V> { V source, destination; Pair(V src, V dest) { this.source = src; this.destination = dest; } } public AbstractMapGraph() { vertices = new HashSet<>(); edges = new HashMap<>(); } public AbstractMapGraph(Graph<V, E> other) { this(); for (V v : other.vertices()) { addVertex(v); } for (E edge : other.edges()) { V v1 = other.getV1(edge); V v2 = other.getV2(edge); addEdge(edge, v1, v2); } } // other methods on following slides }
@Override public E addEdge(E e, V source, V destination) { if (getEdge(source, destination) != null) { throw new IllegalArgumentException(); } edges.put(e, new Pair(addVertex(source), addVertex(destination))); return e; } @Override public V addVertex(V v) { if (!containsVertex(v)) { vertices.add(v); } return v; } @Override public Collection<V> vertices() { return new java.util.LinkedList<>(vertices); } @Override public Collection<E> edges() { return new java.util.LinkedList<>(edges.keySet()); }
@Override public Collection<V> getPredecessors(V v) { List<V> predecessors = new LinkedList<>(); for (Pair<V> p : edges.values()) { if (v.equals(p.destination)) { predecessors.add(p.source); } } return predecessors; } @Override public Collection<V> getSuccessors(V v) { List<V> successors = new LinkedList<>(); for (Pair<V> p : edges.values()) { if (v.equals(p.source)) { successors.add(p.destination); } } return successors; }
Topological sort • Topological sort: a linear ordering of vertices in a directed graph such that for every arc (u, v) in the grahp, u comes before v in the ordering • Any ordering in which all the arrows go “right” is a valid solution. • Any directed graph with a cycle cannot be topologically sorted
Algorithm algorithm topologicalSort(G) { L ← An empty list S ← A list of all nodes in G with in-degree 0 while S is notempty do • M← S.removeFirst() L.append(M) foreach node N with an edge Efrom M to N do remove edge E from G if N has in-degree 0 then S.append(N) endif endforeach endwhile if the size of G is greater than 0 then return error (G is not acyclic) else return L
public class GraphUtilities { public static <V,E> List<V> topologicalSort(DirectedGraph<V,E> graph) { DirectedGraph<V, E> copy = new DirectedMapGraph<>(graph); List<V> nodeSet = new LinkedList<>(); for (V v : copy.vertices()) { if (copy.inDegree(v) == 0) { nodeSet.add(v); } } List<V> sorted = new ArrayList<>(); while (!nodeSet.isEmpty()) { V fromNode = nodeSet.remove(0); sorted.add(fromNode); for (V toNode : copy.getSuccessors(fromNode)) { E edge = copy.getEdge(fromNode, toNode); copy.removeEdge(edge); if (copy.inDegree(toNode) == 0) { nodeSet.add(toNode); } } } if (copy.size() > 0) { throw new IllegalStateException("Graph cannot be sorted"); } else { return sorted; } } }
(Minimum) Spanning Trees • Spanning Tree: Given a connected, undirected, weighted graph, a spanning tree is • a sub-graph • a tree (undirected graph where any two vertices are connected by exactly one simple path) • a tree that contains all vertices • One graph may have many spanning trees • Minimum spanning tree: • A spanning tree such that the sum of the edge weights of the tree is less than or equal to the sum of edge weights of every other spanning tree.
Prims Algorithm • A greedy algorithm that finds the minimum spanning tree of a connected, weighted undirected graph. algorithm prim(G) { MST ← An empty graph if(G.order() == 0) return MST; MST.addVertex(randomly selected vertex of G) while MST.order() < G.order() do • EDGE← an edge of G • (the smallest weighted edge where exactly • one of the vertices is in MST) • MST.addVertex(the vertex of EDGE that is not in MST) • MST.addEdge(EDGE, vertex 1 of EDGE, vertex 2 of EDGE) • endwhile return MST
Prim Example A 1 C C C C D D 2 2 2 4 4 F F F
Prim Example Minimum Spanning Tree A A A 1 1 B C B C 1 5 C 5 D D D 3 2 2 4 4 2 4 E F F F
Weighted Interface • We can define an interface that describes an object having a ‘weight’. • public interface Weighted<E extends Number> { • public E weight(); • public double doubleValue(); • }
public static <V, E extends Number> Weighted<E> chooseMinWeightEdge(Graph<V, Weighted<E>> graph, Graph<V, Weighted<E>> mst) { double minWeight = Double.POSITIVE_INFINITY; Weighted<E> selectedEdge = null; for(Weighted<E> edge : graph.edges()) { if(mst.containsVertex(graph.getV1(edge)) && !mst.containsVertex(graph.getV2(edge)) || mst.containsVertex(graph.getV2(edge)) && !mst.containsVertex(graph.getV1(edge))) { if(edge.weight().doubleValue() < minWeight) { selectedEdge = edge; minWeight = edge.weight().doubleValue(); } } } return selectedEdge; } public static <V, E extends Number> UndirectedGraph<V, Weighted<E>> minimumSpanningTreePrim(UndirectedGraph<V, Weighted<E>> graph) { UndirectedGraph<V, Weighted<E>> mst = new UndirectedMapGraph(); mst.addVertex(graph.vertices().iterator().next()); while(mst.order() < graph.order()) { Weighted<E> edge = chooseMinWeightEdge(graph, mst); V newVertex = mst.containsVertex(graph.getV1(edge)) ? graph.getV2(edge) : graph.getV1(edge); mst.addVertex(newVertex); mst.addEdge(edge, graph.getV1(edge), graph.getV2(edge)); } return mst; }