tim sheard oregon graduate institute

30
Tim Sheard Oregon Graduate Institute Lecture 3: More Examples CSE 510 Section FSC CSE 510 Section FSC Winter 2004 Winter 2004

Upload: makoto

Post on 12-Jan-2016

21 views

Category:

Documents


0 download

DESCRIPTION

Fundamentals of. Staged Computation. Tim Sheard Oregon Graduate Institute. Lecture 3: More Examples. CSE 510 Section FSC Winter 2004. Assignments. The paper DSL Implementation Using Staging and Monads is now officially assigned. See the web page to obtain a copy. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Tim Sheard Oregon Graduate Institute

Tim SheardOregon Graduate Institute

Lecture 3: More Examples

CSE 510 Section FSCCSE 510 Section FSC

Winter 2004Winter 2004

Page 2: Tim Sheard Oregon Graduate Institute

2Cse583 Winterl 2002

Assignments

The paper DSL Implementation Using Staging and Monads is now officially assigned. See the web page to obtain a copy. A volunteer presenter is needed to

present the paper next Monday.

Homework 2, due in one week, is now assigned. See webpage for details Due in one week, Monday Jan 18

Page 3: Tim Sheard Oregon Graduate Institute

3Cse583 Winterl 2002

An Interesting Note

Some functions are code transformers plus : int -> <int> -> <int> plus x ycode = < ~(lift x) + ~ycode >

Others are code generators plus' : int -> <int -> int> plus' x = <fn y => ~(lift x) + y>

When do we use one? When do we use the other? Are they equivalent?

Page 4: Tim Sheard Oregon Graduate Institute

4Cse583 Winterl 2002

Transformers to generators

Code transformers can be made code generators with a “trick”

fun plus’’ n = <fn y => ~(plus n <y>)>;

-| plus’’ 3;

val it =

<(fn a = 3 %+ a)>

: <int -> int>

Page 5: Tim Sheard Oregon Graduate Institute

5Cse583 Winterl 2002

Another example: two versions

fun add3 0 y = y

| add3 n y = < 1 + ~(add3 (n-1) y)>;

fun add4 0 = <fn y => y>

| add4 n = <fn y => 1 + ~(add4 (n-1)) y>;

Page 6: Tim Sheard Oregon Graduate Institute

6Cse583 Winterl 2002

Exponentially large generated programs

fun even x = (x mod 2) = 0;

fun filter p [] = <[]>

| filter p (x::xs) =

<if ~p ~(lift x)

then ~(filter p xs)

else ~(lift x) :: ~(filter p xs)>;

-| filter <even> [3];

val it =

<if %even 3 then [] else [3]>

: <int list>

Note the repeated, related (here identical)

, recursive calls

Page 7: Tim Sheard Oregon Graduate Institute

7Cse583 Winterl 2002

But let the list grow-| filter <even> [1,2,3,4];val it = <if %even 1 then if %even 2 then if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 2 :: if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 1 :: if %even 2 then if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else [4] else 2 :: if %even 3 then if %even 4 then [] else [4] else 3 :: if %even 4 then [] else

[4]> : <int list>

Page 8: Tim Sheard Oregon Graduate Institute

8Cse583 Winterl 2002

Use let to share callsfun filter p [] = <[]>

| filter p (x::xs) =

<let val ys = ~(filter p xs)

in if ~p ~(lift x)

then ys

else ~(lift x) :: ys end>;

val ex2 = filter <even> [1,2,3,4];

-| val ex2 =

<let val a = []

val b = if %even 4 then a else 4 :: a

val c = if %even 3 then b else 3 :: b

val d = if %even 2 then c else 2 :: c

in if %even 1 then d else 1 :: d end>

Page 9: Tim Sheard Oregon Graduate Institute

9Cse583 Winterl 2002

Staged Shortest Path

Given a directed weighted graph G=(V,E)Two nodes a,b in V, The shortest path algorithm finds the minimum weighted path in G from the source a to the destination b.Where the weights are given by a weight function W

Page 10: Tim Sheard Oregon Graduate Institute

10Cse583 Winterl 2002

Representing Graphsfun g x =

case x of

1 => [2]

| 2 => [3,4]

| 3 => [5]

| 4 => [1,2,5]

| 5 => [4]

| _ => [];

3

2

1 4

5

Page 11: Tim Sheard Oregon Graduate Institute

11Cse583 Winterl 2002

Structure of functionfun shortestPath succ source dest marked weight = . . .

succ is the function associating to a vertex a list of successor vertexes, and encodes the topology of the graph

source is the source vertex; dest is the destination vertex; marked indicates which nodes have already

been visited by the algorithm; (weight x y) indicates the weight of the

edge (x,y).

Page 12: Tim Sheard Oregon Graduate Institute

12Cse583 Winterl 2002

Helper functions(* min : int -> int -> int *)fun min x z = if x '<' z then x else z ;

(* minimum : int list -> int *)fun minimum (x::xs) = (case xs of [] => x | _ => min x (minimum xs));

(* map : ('b -> 'a) -> 'b list -> 'a list *)fun map f [] = [] | map f (a::b) = (f a)::(map f b);

(* mem : int -> int list -> bool *)fun mem x [] = false | mem x (a::b) = if a=x then true else mem x b;

(* minus : int list -> int list -> int list *)fun minus [] ys = [] | minus (a::b) ys = if mem a ys then minus b ys else a::(minus b ys);

Page 13: Tim Sheard Oregon Graduate Institute

13Cse583 Winterl 2002

shortestPathfun shortestPath succ source dest marked weight =if source = dest then 0 else let val marked2 = (source::marked) val explore = (minus (succ source) marked2) fun short x = shortestPath succ x dest marked2 weight val path_weights = map (fn node => (short node) + (weight source node)) explore in case path_weights of [] => infinity | _ => (minimum path_weights) end;

Page 14: Tim Sheard Oregon Graduate Institute

14Cse583 Winterl 2002

Exampleval ex1 =

let fun weight x y = 1

in shortestPath g 3 2 [] weight end;

-| val ex1 = 3 : int3

2

1 4

5

Page 15: Tim Sheard Oregon Graduate Institute

15Cse583 Winterl 2002

Staging shortestPath The graph is knownThe source and destination are knownThe weight function is dynamic and won’t be known until later.

shortestPath :

graph -> int -> int -> int list ->

(int -> int -> int) -> int

shortestPath2 :

graph -> int -> int -> int list ->

<(int -> int -> int) -> int>

Page 16: Tim Sheard Oregon Graduate Institute

16Cse583 Winterl 2002

Stage helper functions

Staging the minimum function

liftMinimum : <int> list -> <int>

fun liftMinimum x =

case x of

[] => <infinity>

| (c::cs) => <min ~c ~(liftMinimum cs)>;

Page 17: Tim Sheard Oregon Graduate Institute

17Cse583 Winterl 2002

shortestPath2fun shortestPath2 succ source dest marked = <fn weight => ~(if source = dest then <0> else let val marked2 = source::marked val explore = (minus (succ source) marked) fun short x = shortestPath2 succ x dest marked2 val path_weights = map (fn node => < (~(short node) weight) + (weight ~(lift source) ~(lift node)) > ) explore in (liftMinimum path_weights) end ) >;

Note shortestPath2 is

in generator style

Page 18: Tim Sheard Oregon Graduate Institute

18Cse583 Winterl 2002

Results-| val ex2 = (shortestPath2 g 4 2 []);

val ex2 =

<(fn a =>

%min (%min (0 %+ a 1 2) (%infinity %+ a 4 1))

(%min (0 %+ a 4 2)

(%min (%infinity %+ a 4 5)

%infinity)))>

: <(int -> int -> int) -> int>

3

2

1 4

5

Page 19: Tim Sheard Oregon Graduate Institute

19Cse583 Winterl 2002

Unnest the calls to min

fun liftMinimum x =

case x of

[] => <infinity>

| [x] => x

| ( <infinity> :: cs) => liftMinimum cs

| (c::cs) => <let val y = ~(liftMinimum cs)

val z = ~c

in min z y end>;

Note special case for

singleton list

Page 20: Tim Sheard Oregon Graduate Institute

20Cse583 Winterl 2002

shortestPath2 againfun shortestPath2 succ source dest marked = <fn weight =>

~(if source = dest

then <0>

else let val marked2 = source::marked

val explore = (minus (succ source) marked)

fun short x = shortestPath2 succ x dest marked2

val path_weights =

map (fn node =>

let val recall = < ~(short node) weight>

val wght = <weight ~(lift source) ~(lift node)>

in <let val q = ~recall in q + ~wght end>

end)

explore

in (liftMinimum path_weights) end

) >;

Note the generated let

Page 21: Tim Sheard Oregon Graduate Institute

21Cse583 Winterl 2002

Results

val ex2 = (shortestPath2 g 4 2 []);

-| val ex2 =

<(fn a =>

let val b = %infinity %+ a 4 5

val c = 0 %+ a 4 2

val d = %min c b

val e = 0 %+ a 1 2

val f = e %+ a 4 1

in %min f d end)>

: <(int -> int -> int) -> int>

3

2

1 4

5

Page 22: Tim Sheard Oregon Graduate Institute

22Cse583 Winterl 2002

Extended example 2

Staged merge function for sorted listsUn-staged version

fun merge xs ys =

case xs of

[] => ys

| (z::zs) => case ys of

[] => xs

| w::ws => if z '<' (w:int)

then z::(merge zs ys)

else w::(merge xs ws);

Suppose xs is static and ys is dynamic

Page 23: Tim Sheard Oregon Graduate Institute

23Cse583 Winterl 2002

First staged attempt fun merge2 xs =

<fn ys =>

~(case xs of

[] => <ys>

| (z::zs) =>

<case ys of

[] => ~(lift xs)

| (w::ws) =>

if z '<' (w:int)

then z::(~(merge2 zs) ys)

else w::(~(merge2 xs) ws)

>)>;

Goes into an infinite loop. Why?

Page 24: Tim Sheard Oregon Graduate Institute

24Cse583 Winterl 2002

Second AttemptFirst some helper functions

fun reverse [] ys = ys

| reverse (x::xs) ys = (reverse xs (x::ys));

fun split2 (n:int) xs (small,big) =

case xs of

[] => (reverse small [], reverse big [])

| (z::zs) => if z '>' n

then split2 n zs (small,z::big)

else split2 n zs (z::small,big);

fun split n l = (split2 n l ([],[]));

Page 25: Tim Sheard Oregon Graduate Institute

25Cse583 Winterl 2002

Unstaged version using the helper functions

fun merge3 xs ys =

case xs of

[] => ys

| z::zs =>

(case ys of

[] => xs

| w::ws =>

if z '<' w

then z::(merge3 zs ys)

else let val (u,v) = split z ys

in

append u (z::(merge3 zs v))

end

);split avoids recursive

call on xs

u is all elements of

ys less than z

Page 26: Tim Sheard Oregon Graduate Institute

26Cse583 Winterl 2002

Staged Versionfun merge4 xs = <fn ys => ~(case xs of [] => <ys> | (b::bs) => <case ys of [] => ~(lift xs) | (w::ws) => if (~(lift b)) '<' w then (~(lift b))::(~(merge4 bs) ys) else let val (low,high) = split (~(lift b)) ys in append low (~(lift b)::(~(merge4 bs) high)) end >) >;

Page 27: Tim Sheard Oregon Graduate Institute

27Cse583 Winterl 2002

Not so-good, Generated code

-| merge4 [2,5];val it = <(fn a => (case a of [] => [2,5] | (c::b) => if 2 %'<' c then 2 :: (case a of [] => [5] | (k::j) => if 5 %'<' k then 5 :: a else let val (m,l) = %split 5 a in %append m (5 :: l) end) else let val (e,d) = %split 2 a in %append e (2 :: (case d of [] => [5] | (g::f) => if 5 %'<' g then 5 :: d else let val (i,h) = %split 5 d in %append i (5 :: h) end)) end))> : <int list -> int list>

Page 28: Tim Sheard Oregon Graduate Institute

28Cse583 Winterl 2002

Improve by use transformer style use let to share recursive call

fun merge5 xs ys = case xs of [] => ys| (b::bs) => <case ~ys of [] => ~(lift xs) | (w::ws) => let val tail = ~(merge5 bs ys) val (low,high) = split (~(lift b)) ~ys in if (~(lift b)) '<' w then (~(lift b)):: tail else append low (~(lift b):: tail) end >;fun f1 xs = <fn ys => ~(merge5 xs <ys>)>;

Page 29: Tim Sheard Oregon Graduate Institute

29Cse583 Winterl 2002

Better code-| f1 [2,3];val it = <(fn a => (case a of [] => [2,3] | (c::b) => let val d = case a of [] => [3] | (f::e) => let val (h,g) = %split 3 a in if 3 %'<' f then 3 :: a else %append h (3 :: a) end) val (j,i) = %split 2 a in if 2 %'<' c then 2 :: d else %append j (2 :: d) end))>

Page 30: Tim Sheard Oregon Graduate Institute

30Cse583 Winterl 2002

ReviewMultiple stage programs require nested brackets. Transformer style is often useful.Staged helper functions are often necessary.Generated programs must follow all paths of a generated if or case, even if the unstaged version will follow only one path.

Leads to possiblility of exponentially growing code. Can cause the generator not to terminate if recursive call

at first level doesn’t “get smaller”, even though it gets smaller (in the second stage) in the unstaged program.

Use let to share similar or related code to avoid this blowup.

Use let to avoid deeply nested function calls. Simplifies the structure, and won’t blow up the object level compiler by generating code in weird ways.