15 150 fall 2020 lecture 12
play

15-150 Fall 2020 Lecture 12 Stephen Brookes Midterm 1 Tuesday, - PowerPoint PPT Presentation

15-150 Fall 2020 Lecture 12 Stephen Brookes Midterm 1 Tuesday, October 13 No class that day MIT study says if you get more Zs, youll get more As Font of all knowledge? Australian researchers developed a typeface to help students


  1. 15-150 Fall 2020 Lecture 12 Stephen Brookes Midterm 1 Tuesday, October 13 No class that day MIT study says if you get more Z’s, you’ll get more A’s

  2. Font of all knowledge? Australian researchers developed a typeface to help students cramming for exams. A study found a small increase in the amount remembered. The font has a back slant and gaps. “If something is too easy to read, it doesn’t create a memory trace.” Study for the Midterm!

  3. and now… • Generalizing the subset-sum problem • Developing specs and code together • A lesson in program design We’re dealing with functions for problems that need careful specifications We may be informal (“positive integer x”) or more formal (“x > 0”) But whatever we do, MUST be clear

  4. making change • Given a non-negative integer n, a list L of positive integers, and a constraint p : int list -> bool • Is there a sublist of L that satisfies p and adds up to n?

  5. making change • Given a non-negative integer n, a list L of positive integers, and a constraint p : int list -> bool • Is there a sublist of L that satisfies p and adds up to n? fun sublists L = foldr ( fn (x, S) => S @ (map ( fn A => x::A) S)) [ [ ] ] L

  6. making change • Given a non-negative integer n, a list L of positive integers, and a constraint p : int list -> bool • Is there a sublist of L that satisfies p and adds up to n? fun sublists L = foldr ( fn (x, S) => S @ (map ( fn A => x::A) S)) [ [ ] ] L val sublists = fn : 'a list -> 'a list list - sublists [1,2,3]; val it = [[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]] : int list list

  7. badchange : int * int list -> (int list -> bool) -> bool A non-recursive function that returns a boolean

  8. badchange : int * int list -> (int list -> bool) -> bool A non-recursive function that returns a boolean fun exists q = foldl ( fn (x, t) => q x orelse t) false val sum = foldl ( op + ) 0

  9. badchange : int * int list -> (int list -> bool) -> bool A non-recursive function that returns a boolean fun exists q = foldl ( fn (x, t) => q x orelse t) false val sum = foldl ( op + ) 0 fun badchange (n, L) p = exists ( fn A => sum A = n andalso p A) (sublists L)

  10. badchange : int * int list -> (int list -> bool) -> bool A non-recursive function that returns a boolean fun exists q = foldl ( fn (x, t) => q x orelse t) false val sum = foldl ( op + ) 0 fun badchange (n, L) p = exists ( fn A => sum A = n andalso p A) (sublists L) badchange satisfies the spec

  11. badchange : int * int list -> (int list -> bool) -> bool A non-recursive function that returns a boolean fun exists q = foldl ( fn (x, t) => q x orelse t) false val sum = foldl ( op + ) 0 fun badchange (n, L) p = exists ( fn A => sum A = n andalso p A) (sublists L) badchange satisfies the spec but it’s inefficient!

  12. critique badchange (300, [1,2,3,...,24]) ( fn _ => true ) ========>* true (VERY SLOW!)

  13. critique badchange (300, [1,2,3,...,24]) ( fn _ => true ) ========>* true (VERY SLOW!) brute force search • generates the list of all sublists • and tests them, sequentially

  14. critique badchange (300, [1,2,3,...,24]) ( fn _ => true ) ========>* true (VERY SLOW!) brute force search • generates the list of all sublists (2 24 ) • and tests them, sequentially

  15. critique badchange (300, [1,2,3,...,24]) ( fn _ => true ) ========>* true (VERY SLOW!) brute force search • generates the list of all sublists (2 24 ) • and tests them, sequentially … only the final sublist will work!

  16. critique badchange (300, [1,2,3,...,24]) ( fn _ => true ) ========>* true (VERY SLOW!) brute force search • generates the list of all sublists (2 24 ) • and tests them, sequentially … only the final sublist will work! 1 + 2 + … + 24 = 300

  17. specification “can we make change for (n, L) that satisfies p?” change : int * int list -> (int list -> bool) -> bool REQUIRES p is total , n ≥ 0, L a list of positive integers ENSURES change (n, L) p = true if there is a sublist A of L with sum A = n and p A = true change (n, L) p = false , otherwise + must be faster!

  18. a better strategy Avoid building the list of sublists • only call p on sublists with the correct sum Deal with special cases first • n = 0 • n > 0, L = [ ] For n > 0, L = x::R, use recursion ... the spec suggests this might be feasible!

  19. change : int * int list -> (int list -> bool) -> bool A recursive function that returns a boolean p [ ] fun change (0, L) p = | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then change (n-x, R) ( fn A => p(x::A)) orelse change (n, R) p else change (n, R) p

  20. change : int * int list -> (int list -> bool) -> bool A recursive function that returns a boolean p [ ] fun change (0, L) p = | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then change (n-x, R) ( fn A => p(x::A)) orelse change (n, R) p else change (n, R) p change (300, [1,2,3,...,24]) ( fn _ => true )

  21. change : int * int list -> (int list -> bool) -> bool A recursive function that returns a boolean p [ ] fun change (0, L) p = | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then change (n-x, R) ( fn A => p(x::A)) orelse change (n, R) p else change (n, R) p change (300, [1,2,3,...,24]) ( fn _ => true ) (very fast) ⟹ true

  22. equivalently fun change (0, L) p = p [ ] | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then case change (n-x, R) ( fn A => p(x::A)) of true => true | false => change (n, R) p else change (n, R) p (you’ll soon see why we mention this)

  23. type check change : int * int list -> (int list -> bool) -> bool fun change (0, L) p = p [ ] | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then change (n-x, R) ( fn A => p(x::A)) orelse change (n, R) p else change (n, R) p CHECK that each clause fits this type: the LHS patterns match types int * int list and int list -> bool, and give bindings such that, assuming change : int * int list -> (int list -> bool) -> bool, the RHS expression gets type bool

  24. spec check fun change (0, L) p = p [ ] | change (n, [ ]) p = false | change (n, x::R) p = if x <= n then change (n-x, R) ( fn A => p(x::A)) orelse change (n, R) p else change (n, R) p REQUIRES p is total , n ≥ 0, L a list of positive integers ENSURES change (n, L) p = true iff there is a sublist A of L with sum A = n and p A = true CHECK if requires holds for (n, L, p) and then requires holds for (n ’ , L ’ , p ’ ) change (n, L) p calls change (n ’ ,L ’ ) p ’ and original call satisfies ensures and recursive call satisfies ensures

  25. benefits • The type check shows that the function has the intended type(!) - Use type check to guide the code design - ML will give same type (or a more general one) • The spec check is basically a sketch of an inductive correctness proof - Use spec check to guide the code design - Will then be easy to give a fully detailed proof of correctness

  26. correctness For all positive integer lists L, n ≥ 0, and total functions p : int list -> bool, change (n, L) p = true if there is a sublist A of L with sum A = n and p A = true change (n, L) p = false , otherwise • PROOF: induction on L why?

  27. examples change (10, [5,2,5]) ( fn _ => true ) = true change (210, [1,2,3,...,20]) ( fn _ => true ) ⟹ * true (FAST!) change (10, [10,5,2,5]) ( fn A => length(A)>1) = true change (10, [10,5,2]) ( fn A => length(A)>1) = false

  28. the right question? change : int * int list -> (int list -> bool) -> bool

  29. the right question? change : int * int list -> (int list -> bool) -> bool I s there a sublist that adds to 300?

  30. the right question? change : int * int list -> (int list -> bool) -> bool I s there a val it = true sublist that (YES) adds to 300?

  31. the right question? change : int * int list -> (int list -> bool) -> bool I s there a val it = true sublist that (YES) adds to 300? What is it?

  32. the right question? change : int * int list -> (int list -> bool) -> bool I s there a val it = true sublist that (YES) adds to 300? Y ou What is it? didn’t ask

  33. boolean blindness • A truth value only gives a bit of information • From the context, we know true (yes) means “it’s possible to make change...” • But what if we want more information ? • “a list that works, if there is one”

  34. boolean blindness • A truth value only gives a bit of information • From the context, we know true (yes) means “it’s possible to make change...” • But what if we want more information ? • “a list that works, if there is one” NEED a function that computes a suitable sublist, if there is one

  35. boolean blindness • A truth value only gives a bit of information • From the context, we know true (yes) means “it’s possible to make change...” • But what if we want more information ? • “a list that works, if there is one” NEED PLAN a function that a function that computes a suitable sublist, returns an if there is one (int list) option

Recommend


More recommend