David Evans CS201J: Engineering Software University of Virginia Computer Science Lecture 6: Reasoning about Data Abstractions
16 September 2003CS 201J Fall Requests By 5pm tomorrow send any questions you have about Java programming to –We’ll go over questions raised in class Thursday or section Friday Please don’t harass the Assistant Coaches! –If they are not in Small Hall, don’t bother them with 201J questions. They have their own work to do also.
16 September 2003CS 201J Fall Rep Invariant The Representation Invariant expresses properties all legitimate objects of the ADT must satisfy I : C → Boolean Function from concrete representation to a Boolean. Helps us reason about correctness of methods independently
16 September 2003CS 201J Fall Reasoning with Rep Invariants Prove all objects satisfy the invariant before leaving the implementation code Assume all objects passed in satisfy the invariant REQUIRES: Rep Invariant is true for this (and any other reachable ADT objects) EFFECTS: Rep Invariant is true for all new and modified ADT object on exit.
16 September 2003CS 201J Fall Preserving the Rep Invariant Abstract Type Concrete Representation class implementation clients down up StringSet () Constructors must initialize this in a way that satisfies the rep invariant insert (String s) up Mutators: assume rep invariant holds on entry, ensure that it holds on all exits Cannot manipulate rep directly
16 September 2003CS 201J Fall Rep Invariant for StringSet public class StringSet { // OVERVIEW: StringSets are unbounded, // mutable sets of Strings. // A typical StringSet is {x1,..., xn} // Representation: private Vector rep; // RepInvariant (c) = //c contains no duplicates //&& c != null && all elements are Strings
16 September 2003CS 201J Fall Implementing Insert public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } } Possibly correct implementation: we need to know how to map rep to abstraction notation to know if this_post = this_pre U { s }
16 September 2003CS 201J Fall Abstraction Function The Abstraction Function maps a concrete state to an abstract state: AF : C → A Function from concrete representation to the abstract notation introduced in overview specification. Range is concrete states for which rep invariant is true
16 September 2003CS 201J Fall Abstraction Function for StringSet public class StringSet { // OVERVIEW: StringSets are unbounded, // mutable sets of Strings. // A typical StringSet is {x1,..., xn} // Representation: private Vector rep; // AF (c) = // { AF String (c.rep[i]) | 0 <= i < c.rep.size () }
16 September 2003CS 201J Fall Correctness of Insert public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } } Use abstraction function to show if add implements its specification, the AF (rep_post) = AF (rep_pre) U { AF String ( s)}
16 September 2003CS 201J Fall Correctness of Insert Path 1: isIn (s) is true this is not modified, this_post = this_pre public boolean isIn (String s) // EFFECTS: Returns true iff s is an element of this. So, if isIn (s) returns true, we know s this_pre. s x x s = x Hence, this_post = this_pre = this_pre s AF (rep_post) = AF (rep_pre) U { AF String (s)} public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } }
16 September 2003CS 201J Fall Correctness of Insert Path 2: isIn (s) is false this_post = this_pre.add (s) If isIn (s) returns false, we know s this_pre. So, we need to know that AF ( rep_pre.add(s) ) = AF ( rep_pre ) U { AF String (s)} What does add do? public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } }
16 September 2003CS 201J Fall Correctness of Insert boolean add (Object o) // Modifies: this // Effects: Appends o to the end of this. // this_post.size = this_pre.size + 1 // this_post[i] = this_pre[i] //forall 0 <= i < this_pre.size // this_post[this_pre.size] = o public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } }
16 September 2003CS 201J Fall Correctness of Insert java.util.Vector.add (Object o) // Modifies: this // Effects: Adds o to the end of this. // this_post.size = this_pre.size + 1 // this_post[i] = this_pre[i] //forall 0 <= i < this_pre.sze // this_post[this_pre.size] = o public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } } So, after rep.add (s) : rep_post.size = rep_pre.size + 1 rep_post[i] = rep_pre[i] forall 0 <= i < rep_pre.size rep_post[rep_pre.size] = s
16 September 2003CS 201J Fall Correctness of Insert public void insert (String s) { // MODIFIES: this // EFFECTS: Adds s to the elements of this: // this_post = this_pre U { s } if (!isIn (s)) { rep.add (s); } } rep_post.size == rep_pre.size + 1 rep_post[i] = rep_pre[i] forall 0 <= i < rep_pre.size rep_post[rep_pre.size] = s AF (rep_post) = { AF String (rep_post[i]) | 0 <= i < rep_post.size } = { rep_post[0], rep_post[1], …, rep_post[rep_post.size – 1] } = { rep_pre[0], rep_pre[1], …, rep_pre[rep_post.size – 1], s } = AF ( rep_pre ) U { s } AF (c) = { AF String (c.rep[i]) | 0 <= i < c.rep.size () }
16 September 2003CS 201J Fall Reality Check Writing abstraction functions, rep invariants, testing code thoroughly, reasoning about correctness, etc. for a big program is a ridiculous amount of work! Does anyone really do this? –Yes (and a lot more), but usually only when its really important to get things right: Cost per line of code: –Small, unimportant projects: $1-5/line –WindowsNT: about $100/line –FAA’s Automation System ( ): $900/line
16 September 2003CS 201J Fall PS2 Wagering Strategy How did you decide what to wager? How should you have decided what to wager?
16 September 2003CS 201J Fall Commerce School Strategy If p is the probability your code is correct, Expected Return = wp – 2w (1-p) = 3wp - 2w If p < 2/3, maximize with w = 0. If p = 2/3, expected return is 0 regardless of wager. If p > 2/3, expected return increases with w, bet maximum.
16 September 2003CS 201J Fall Psychological Strategies Expected return is a bad model, since the value is non-linear –If my ps was worth 90 without wager, 1/3 change of getting a 50 is not worth 2/3 chance of getting 110. Dave is probably crazy for asking such a question, so I have no clue how this will be graded
16 September 2003CS 201J Fall Why Confidence Matters? Incorrect code, no confidence –Worthless, no one can use it (but if they do, they get what they deserve) Correct code, no confidence –Worthless, no one can use it (but if they do, they get lucky) Incorrect code, high confidence –Dangerous! Correct code, high confidence –Valuable
16 September 2003CS 201J Fall Easy way to get 100 on PS 2: Get full credit for questions 1-4 Answer question 5 (specify name trends) badly (0): static public void main (String args[]) // REQUIRES: false // EFFECTS: Prints out a correct proof of // P = NP.
16 September 2003CS 201J Fall Remaining Answers 6.Implement program that satisfies spec: 7.Testing Strategy No testing necessary, no way to satisfy requires 8.Bet: 20 static public void main (String args[]) { // REQUIRES: false // EFFECTS: Prints out a correct proof of P = NP. System.err.println (“Ha ha ha!”) } Note: I didn’t actually want you to do this!
16 September 2003CS 201J Fall Charge Remember to your Java programming questions to PS3 is due 1 week from today –I have office hours now