David Evans cs.virginia/evans

30
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)

description

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 - PowerPoint PPT Presentation

Transcript of David Evans cs.virginia/evans

Page 1: David Evans cs.virginia/evans

David Evanshttp://www.cs.virginia.edu/evans

CS201J: Engineering SoftwareUniversity of VirginiaComputer Science

Lecture 7: A Tale of Two Graphs (and a tree)

Page 2: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 2

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} }

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

Page 3: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 3

Representation Ideas

• Set of Nodes, Set of Edgese.g., Nodes = { A, B, C, D }

Edges = { <A, B>, <A, C>, <A, D>, <B, C> }

• Set of Nodes and Neighborse.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

B

C

D

Page 4: David Evans cs.virginia/evans

23 September 2003 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 ] ]

A

B

C

DNo edge from A to A

Edge from B to C

Page 5: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 5

Implementation 1class 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

…}

Page 6: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 6

Rep Invariantclass 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

Page 7: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 7

Rep InvariantRI (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

Page 8: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 8

Abstraction Function

• Function from rep to abstract notion (use notation from overview)

AF (c) =

< Nodes, Edges >

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: // < Nodes, Edges > // where // Nodes = { n1, n2, …, nm } // and // Edges = { {from_1, to_1}, // …, {from_n, to_n} }

Page 9: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 9

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) = < Nodes, Edges > where

The set of edges is the elements of the c.edges Vector

Page 10: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 10

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?

Page 11: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 11

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 >

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?

Page 12: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 12

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?

Page 13: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 13

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); }}

Page 14: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 14

Representation Ideas

• Set of Nodes, Set of Edgese.g., Nodes = { A, B, C, D }

Edges = { <A, B>, <A, C>, <A, D>, <B, C> }

• Set of Nodes and Neighborse.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

B

C

D

Page 15: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 15

Implementation 2class 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 …}

Page 16: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 16

Rep Invariantclass 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.nodesc.nodes[i].neighbors does not contain

duplicates

Function from rep to boolean

Page 17: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 17

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) = < Nodes, Edges > where

class NodeNeighbors { String node; StringSet neighbors; }class Graph { Vector nodes; // A Vector of NodeNeighbors objects}

Page 18: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 18

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}

Page 19: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 19

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?

class NodeNeighbors { String node; StringSet neighbors; }class Graph { Vector nodes; // A Vector of NodeNeighbors objects}

Page 20: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 20

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 needto implementlookupNodealso.

Page 21: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 21

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!

Page 22: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 22

Rep ExposureWhat 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?

Page 23: David Evans cs.virginia/evans

23 September 2003 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?

Page 24: David Evans cs.virginia/evans

23 September 2003 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

Page 25: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 25

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’thave access to the actual neighbors objectin the representation.

Page 26: David Evans cs.virginia/evans

23 September 2003 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

Page 27: David Evans cs.virginia/evans

23 September 2003 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

Page 28: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 28

Performance Comparison

> time java GraphTest // Using Nodes/Edges impl1.220u 0.020s 0:01.25 99.2% > time java GraphTest // Using NodeNeighbors impl0.660u 0.040s 0:00.79 88.6%

Very rough comparison…but NodeNeighbors appearsto be twice as fast for this test case.

What is the test case doing?

Page 29: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 29

GraphTest.javapublic 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); } }}

Page 30: David Evans cs.virginia/evans

23 September 2003 CS 201J Fall 2003 30

Charge

When picking representations, focus on complexity of implementation

Your time is (usually) more valuable than the

computer’s!