1 / 30

David Evans cs.virginia/evans

Lecture 7: A Tale of Two Graphs (and a tree). David Evans http://www.cs.virginia.edu/evans. CS201J: Engineering Software University of Virginia Computer Science. Graph ADT. public class Graph { // OVERVIEW: // A Graph is a mutable type that

takoda
Download Presentation

David Evans cs.virginia/evans

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Lecture 7: A Tale of Two Graphs (and a tree) David Evans http://www.cs.virginia.edu/evans CS201J: Engineering Software University of Virginia Computer Science

  2. Graph ADT public class Graph { // OVERVIEW: // A Graph is a mutable type that // represents an undirected // graph. It consists of nodes that are // named by Strings, and edges that // connect a pair of nodes. // A typical Graph is: // < Nodes, Edges > // where // Nodes = { n1, n2, …, nm } // and // Edges = { {from_1, to_1}, // …, {from_n, to_n} } B D A C Nodes = { A, B, C, D } Edges = { { A, B }, { A, C }, { B, C }, { A, D } } { … } means its a set – order doesn’t matter CS 201J Fall 2003

  3. B Representation Ideas D • Set of Nodes, Set of Edges e.g., Nodes = { A, B, C, D } Edges = { <A, B>, <A, C>, <A, D>, <B, C> } • Set of Nodes and Neighbors e.g., Graph = { <A, {B, C, D}>, <B, {A, C}>, <C, {A, B}>, <D, {A}> } Each entry is pair of node name, and names of nodes it is connected to. A C CS 201J Fall 2003

  4. Representation Ideas • Set of Nodes and Matrix of booleans e.g., Nodes = [ A, B, C, D ] Edges = [ [ 0 1 1 1 ] [ 1 0 1 0 ] [ 1 1 0 0 ] [ 1 0 0 0 ] ] B No edge from A to A D A C Edge from B to C CS 201J Fall 2003

  5. Implementation 1 class Edge { // OVERVIEW: Record type for representing an edge. String node1, node 2; Edge (String n1, String n2) { node1 = n1; node2 = n2; } } class Graph { // OVERVIEW: A Graph is a mutable type that represents an … Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } CS 201J Fall 2003

  6. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Rep Invariant Function from rep to boolean RI (c) = c.nodes != null && c.edges != null && !c.nodes.containsNull && !c.edges.containsNull && elements of c.nodes are String objects && elements of c.edges are Edge objects && no duplicates in c.nodes && no duplicates in c.edges && every node mentioned in c.edges is also in c.nodes Is this precise enough? CS 201J Fall 2003

  7. Rep Invariant RI (c) = c.nodes != null && c.edges != null && !c.nodes.containsNull && !c.edges.containsNull && elements of c.nodes are String objects && elements of c.edges are Edge objects && no duplicates in c.nodes // No duplicate edges, node1/node2 are interchangable: && ((c.edges[i].node1 = c.edges[j].node1 && c.edges[i].node2 = c.edges[j].node2) || (c.edges[i].node1 = c.edges[j].node2 && c.edges[i].node2 = c.edges[j].node1))  i == j && every node mentioned in c.edges is also in c.nodes CS 201J Fall 2003

  8. Abstraction Function public class Graph { // OVERVIEW: // A Graph is a mutable type that // represents an undirected // graph. It consists of nodes that are // named by Strings, and edges that // connect a pair of nodes. // A typical Graph is: // < Nodes, Edges > // where // Nodes = { n1, n2, …, nm } // and // Edges = { {from_1, to_1}, // …, {from_n, to_n} } • Function from rep to abstract notion (use notation from overview) AF (c) = < Nodes, Edges > where … CS 201J Fall 2003

  9. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Abstraction Function AF (c) = < Nodes, Edges > where Nodes = { c.nodes[i] | 0 <= i < c.nodes.size () } The set of nodes is the elements of the c.nodes Vector Edges = { { c.edges[i].node1, c.edges[i].node2 } | 0 <= i < c.edges.size () } The set of edges is the elements of the c.edges Vector CS 201J Fall 2003

  10. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Implementing Constructor • public Graph () • // EFFECTS: Initializes this to a graph with no nodes or • // edges: < {}, {} >. • nodes = new Vector (); • edges = new Vector (); • } • How do we know this satisfies the rep invariant? CS 201J Fall 2003

  11. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Implementing addNode • public void addNode (String name) { • // REQUIRES: name is not the name of a node in this • // MODIFIES: this • // EFFECTS: adds a node named name to this: • // this_post = < this_pre.nodes U { name }, this_pre.edges > • nodes.addElement (name); • } • How do we know this still satisfies the rep invariant? CS 201J Fall 2003

  12. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Implementing addEdge • public void addEdge (String fnode, String tnode) • // REQUIRES: fnode and tnode are names of nodes in this. • // MODIFIES: this • // EFFECTS: Adds an edge from fnode to tnode to this: • // this_post = < this_pre.nodes, • // this_pre.edges U { {fnode, tnode} } > • edges.addElement (new Edge (fnode, tnode)); • } • How do we know this still satisfies the rep invariant? • Would • edges.addElement (new Edge (tnode, fnode)); • be correct? CS 201J Fall 2003

  13. class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } Implementing getNeighbors • public StringSet getNeighbors (String node) • // REQUIRES: node is a node in this • // EFFECTS: Returns the StringSet consisting of all nodes in this • // that are directly connected to node: • // \result = { n | {node, n} is in this.edges • StringSet res = new StringSet (); • Enumeration edgeenum = edges.elements (); • while (edgeenum.hasMoreElements ()) { • Edge e = (Edge) edgeenum.nextElement (); • if (e.node1.equals (node)) { res.insert (e.node2); } • else if (e.node2.equals (node)) { res.insert (e.node1); } • } CS 201J Fall 2003

  14. B Representation Ideas D • Set of Nodes, Set of Edges e.g., Nodes = { A, B, C, D } Edges = { <A, B>, <A, C>, <A, D>, <B, C> } • Set of Nodes and Neighbors e.g., Graph = { <A, {B, C, D}>, <B, {A, C}>, <C, {A, B}>, <D, {A}> } Each entry is pair of node name, and names of nodes it is connected to. A C CS 201J Fall 2003

  15. Implementation 2 class NodeNeighbors { // OVERVIEW: Record type for representing an edge. String node; StringSet neighbors; // A Set of String objects NodeNeighbors (String n) { node = n; neighbors = new StringSet (); } } class Graph { // OVERVIEW: A Graph is a mutable type that represents an … Vector nodes; // A Vector of NodeNeighbors objects … } CS 201J Fall 2003

  16. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Rep Invariant Function from rep to boolean RI (c) = c.nodes != null && !c.nodes.containsNull && elements of c.nodes are NodeNeighbors objects && no duplicates in c.nodes && for each node in c.nodes, each node in c.nodes[i].neighbors is a node in c.nodes c.nodes[i].neighbors does not contain duplicates CS 201J Fall 2003

  17. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Abstraction Function AF (c) = < Nodes, Edges > where Nodes = { c.nodes[i].node | 0 <= i < c.nodes.size () } The set of nodes is the elements of the c.nodes Vector Edges = { { c.nodes[i].node, c.nodes[i].neighbors[e] } | 0 <= i < c.nodes.size (), 0 <= e <= c.nodes[i].neighbors.size () } CS 201J Fall 2003

  18. class NodeNeighbors { String node; Vector neighbors; // A Vector of String objects } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Implementing Constructor • public Graph () • // EFFECTS: Initializes this to a graph with no nodes or • // edges: < {}, {} >. • nodes = new Vector (); • } CS 201J Fall 2003

  19. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Implementing addNode • public void addNode (String name) { • // REQUIRES: name is not the name of a node in this • // MODIFIES: this • // EFFECTS: adds a node named name to this: • // this_post = < this_pre.nodes U { name }, this_pre.edges > • nodes.addElement (new NodeNeighbors (name)); • } • How do we know this still satisfies the rep invariant? CS 201J Fall 2003

  20. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Implementing addEdge • public void addEdge (String fnode, String tnode) • // REQUIRES: fnode and tnode are names of nodes in this. • // MODIFIES: this • // EFFECTS: Adds an edge from fnode to tnode to this: • // this_post = < this_pre.nodes, • // this_pre.edges U { {fnode, tnode} } > • NodeNeighbors n1 = lookupNode (fnode); • NodeNeighbors n2 = lookupNode (tnode); • n1.neighbors.insert (tnode); • n2.neighbors.insert (fnode); • } We need to implement lookupNode also. • How do we know this still satisfies the rep invariant? CS 201J Fall 2003

  21. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Implementing getNeighbors • public StringSet getNeighbors (String node) • // REQUIRES: node is a node in this • // EFFECTS: Returns the StringSet consisting of all nodes in this • // that are directly connected to node: • // \result = { n | {node, n} is in this.edges • NodeNeighbors n = lookupNode (node); • return n.neighbors; • } Almost…but we have exposed our rep! CS 201J Fall 2003

  22. Rep Exposure What if client does this? Graph g = new Graph (); g.addNode (“A”); g.addNode (“B”); g.addEdge (“A”, “B”); StringSet neighbors = g.getNeighbors (“A”); neighbors.insert (“C”); Does the rep invariant for g still hold? CS 201J Fall 2003

  23. Rep Exposure • If mutable components of the representation are accessible to clients, the implementation exposes the rep! • Clients can mutate the representation directly – without using data type operations Why is this bad? CS 201J Fall 2003

  24. Problems with Rep Exposure • Client mutations could break the rep invariant • Client code may break if ADT implementation changes • No longer possible to reason about the invariant being true by just checking the ADT implementation CS 201J Fall 2003

  25. class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Implementing getNeighbors • public StringSet getNeighbors (String node) • // REQUIRES: node is a node in this • // EFFECTS: Returns the StringSet consisting of all nodes in this • // that are directly connected to node: • // \result = { n | {node, n} is in this.edges • NodeNeighbors n = lookupNode (node); • } • return n.neighbors; • return n.neighbors.copy (); If we return a copy, the client doesn’t have access to the actual neighbors object in the representation. CS 201J Fall 2003

  26. Which implementation is better? • Depends what we care about • Code complexity • Normally the most important criteria • Nodes/Edges: getNeighbors is harder • NodeNeighbors: toString is harder, addEdge a little harder • Memory Use • Nodes/Edges: 2 vectors, each edge requires 2 strings • NodeNeighbors: 1 vector, number of nodes StringSets, each edge requires 1 string CS 201J Fall 2003

  27. Which implementation is better? • Performance • Both have poor performance: linear search through all the nodes to find one • NodeNeighbors getNeighbors does less work • Other methods Nodes/Edges usually less work • If we expect clients to call getNeighbors a lot, NodeNeighbors might be better CS 201J Fall 2003

  28. Performance Comparison > time java GraphTest // Using Nodes/Edges impl 1.220u 0.020s 0:01.25 99.2% > time java GraphTest // Using NodeNeighbors impl 0.660u 0.040s 0:00.79 88.6% Very rough comparison…but NodeNeighbors appears to be twice as fast for this test case. What is the test case doing? CS 201J Fall 2003

  29. GraphTest.java public class GraphTest { static public void main (String args[]) { Graph g = new Graph (); int numnodes = 1000; for (int i = 0; i < numnodes; i++) { g.addNode ("node" + i); } for (int i = 0; i < numnodes - 1; i++) { g.addEdge ("node" + i, "node" + (i + 1)); } for (int i = 0; i < numnodes - 2; i++) { g.addEdge ("node" + i, "node" + (i + 2)); } for (int i = 0; i < numnodes; i++) { StringSet neighbors = g.getNeighbors ("node" + i); } } } CS 201J Fall 2003

  30. Charge When picking representations, focus on complexity of implementation Your time is (usually) more valuable than the computer’s! CS 201J Fall 2003

More Related