Presentation is loading. Please wait.

Presentation is loading. Please wait.

Lecture 7: A Tale of Two Graphs CS201j: Engineering Software

Similar presentations


Presentation on theme: "Lecture 7: A Tale of Two Graphs CS201j: Engineering Software"— Presentation transcript:

1 David Evans http://www.cs.virginia.edu/~evans
Lecture 7: A Tale of Two Graphs CS201j: Engineering Software University of Virginia Computer Science David Evans

2 Graph ADT Nodes = { A, B, C, D } Edges = { { A, B }, { A, C },
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 19 September 2002 CS 201J Fall 2002

3 Representation Ideas Set of Nodes, Set of Edges
B 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 19 September 2002 CS 201J Fall 2002

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

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 19 September 2002 CS 201J Fall 2002

6 Rep Invariant Is this precise enough?
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? 19 September 2002 CS 201J Fall 2002

7 Rep Invariant && no duplicates in c.nodes
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 19 September 2002 CS 201J Fall 2002

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 … 19 September 2002 CS 201J Fall 2002

9 Abstraction Function AF (c) = < Nodes, Edges > where
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 19 September 2002 CS 201J Fall 2002

10 Implementing Constructor
class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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? 19 September 2002 CS 201J Fall 2002

11 Implementing addNode public void addNode (String name) {
class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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? 19 September 2002 CS 201J Fall 2002

12 Implementing addEdge edges.addElement (new Edge (fnode, tnode)); }
class Edge { String node1, node 2; } class Graph { Vector nodes; // A Vector of String objects Vector edges; // A Vector of Edge object … } 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? 19 September 2002 CS 201J Fall 2002

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

14 Representation Ideas Set of Nodes, Set of Edges
B 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 19 September 2002 CS 201J Fall 2002

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 19 September 2002 CS 201J Fall 2002

16 Rep Invariant RI (c) = c.nodes != null && !c.nodes.containsNull
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 19 September 2002 CS 201J Fall 2002

17 Abstraction Function AF (c) = < Nodes, Edges > where
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 () } 19 September 2002 CS 201J Fall 2002

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

19 Implementing addNode public void addNode (String name) {
class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects 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? 19 September 2002 CS 201J Fall 2002

20 Implementing addEdge NodeNeighbors n1 = lookupNode (fnode);
class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects 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? 19 September 2002 CS 201J Fall 2002

21 Implementing getNeighbors
class NodeNeighbors { String node; StringSet neighbors; } class Graph { Vector nodes; // A Vector of NodeNeighbors objects 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! 19 September 2002 CS 201J Fall 2002

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? 19 September 2002 CS 201J Fall 2002

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? 19 September 2002 CS 201J Fall 2002

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 19 September 2002 CS 201J Fall 2002

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

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 19 September 2002 CS 201J Fall 2002

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 19 September 2002 CS 201J Fall 2002

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

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); } 19 September 2002 CS 201J Fall 2002

30 Picking Implementations
Focus on complexity of implementation Your time is more valuable than the computer’s! 19 September 2002 CS 201J Fall 2002

31 PS4 - Design PS2: you used an ADT we provided
PS3: you implemented an ADT PS4: you will design and implement ADTs to solve a problem First part: just design (due Thursday) Second part: implementation (due Oct 3) 19 September 2002 CS 201J Fall 2002

32 Design Break a problem into components Each component should:
Abstract data types Each component should: Make sense on its own Be independent from other components Be small enough to understand and implement This is hard. Designing well takes lots of practice. 19 September 2002 CS 201J Fall 2002

33 Charge PS4: Design Document
Due next Thursday No code to write yet – just think carefully about your design Tuesday: design, modular dependency diagrams (read Ch 13) Wednesday, 8pm: AC’s will hold recitation on useful programming techniques 19 September 2002 CS 201J Fall 2002


Download ppt "Lecture 7: A Tale of Two Graphs CS201j: Engineering Software"

Similar presentations


Ads by Google