Presentation is loading. Please wait.

Presentation is loading. Please wait.

David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 7: A Tale of Two Graphs (and.

Similar presentations


Presentation on theme: "David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 7: A Tale of Two Graphs (and."— Presentation transcript:

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

2 23 September 2003CS 201J Fall 20032 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: // // where // Nodes = { n1, n2, …, nm } // and // Edges = { {from_1, to_1}, // …, {from_n, to_n} } Graph ADT A B C D Nodes = { A, B, C, D } Edges = { { A, B }, { A, C }, { B, C }, { A, D } } { … } means its a set – order doesn’t matter

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

4 23 September 2003CS 201J Fall 20034 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 ] ] A B C D No edge from A to A Edge from B to C

5 23 September 2003CS 201J Fall 20035 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 … }

6 23 September 2003CS 201J Fall 20036 Rep Invariant class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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? Function from rep to boolean

7 23 September 2003CS 201J Fall 20037 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

8 23 September 2003CS 201J Fall 20038 Abstraction Function Function from rep to abstract notion (use notation from overview) AF (c) = where … 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: // // where // Nodes = { n1, n2, …, nm } // and // Edges = { {from_1, to_1}, // …, {from_n, to_n} }

9 23 September 2003CS 201J Fall 20039 Abstraction Function class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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 () } AF (c) = where The set of edges is the elements of the c.edges Vector

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

11 23 September 2003CS 201J Fall 200311 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 = class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } nodes.addElement (name); } How do we know this still satisfies the rep invariant?

12 23 September 2003CS 201J Fall 200312 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} } > class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } edges.addElement (new Edge (fnode, tnode)); } Would edges.addElement (new Edge (tnode, fnode)); be correct? How do we know this still satisfies the rep invariant?

13 23 September 2003CS 201J Fall 200313 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 class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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); } }

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

15 23 September 2003CS 201J Fall 200315 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 … }

16 23 September 2003CS 201J Fall 200316 Rep Invariant class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } 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 Function from rep to boolean

17 23 September 2003CS 201J Fall 200317 Abstraction Function 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 () } AF (c) = where class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects }

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

19 23 September 2003CS 201J Fall 200319 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 = nodes.addElement (new NodeNeighbors (name)); } How do we know this still satisfies the rep invariant? class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects }

20 23 September 2003CS 201J Fall 200320 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); } How do we know this still satisfies the rep invariant? class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } We need to implement lookupNode also.

21 23 September 2003CS 201J Fall 200321 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; } class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } Almost…but we have exposed our rep!

22 23 September 2003CS 201J Fall 200322 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?

23 23 September 2003CS 201J Fall 200323 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?

24 23 September 2003CS 201J Fall 200324 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

25 23 September 2003CS 201J Fall 200325 return n.neighbors; 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 return n.neighbors.copy (); class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects } NodeNeighbors n = lookupNode (node); } If we return a copy, the client doesn’t have access to the actual neighbors object in the representation.

26 23 September 2003CS 201J Fall 200326 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

27 23 September 2003CS 201J Fall 200327 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

28 23 September 2003CS 201J Fall 200328 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?

29 23 September 2003CS 201J Fall 200329 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); }

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


Download ppt "David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 7: A Tale of Two Graphs (and."

Similar presentations


Ads by Google