CS1321: Introduction to Programming - PowerPoint PPT Presentation

1 / 97
About This Presentation
Title:

CS1321: Introduction to Programming

Description:

Pure (augmenting or 'head') recursion follows the functional paradigm ... Leaving these 'lying around' separate is a little tacky. ... – PowerPoint PPT presentation

Number of Views:43
Avg rating:3.0/5.0
Slides: 98
Provided by: BillL161
Category:

less

Transcript and Presenter's Notes

Title: CS1321: Introduction to Programming


1
CS1321Introduction to Programming
  • Georgia Institute of Technology
  • College of Computing
  • Lecture 20
  • March 21, 2002

2
Agenda
1. Tail Recursion 2. Graphs
3
Tail or Accumulator-Style Functions
4
Outline
  • Prerequisites
  • Recursion
  • Structures
  • Graphs
  • Objectives
  • Need for Accumulation
  • Accumulator Style Functions
  • Transforming Recursive Functions
  • Reference
  • HTDP Chapters 31, 32

5
Background
  • Pure (augmenting or head) recursion follows the
    functional paradigm
  • The recursion you have seen so far
  • Does not permit memory
  • Forgets useful intermediate results
  • Unnecessarily repeats large computations
  • We now consider ways to improve the efficiency of
    recursion
  • Passing extra parameters to remember useful
    details
  • Basically collecting partial results as we go!!
  • Frequently referred to as Tail Recursion

6
Example Numerical Integration
  • Given the values of a function f(x)
  • Compute the integral F(x) ? f(i), i 0 x

7
First Solution Concept
  • f(x) (82 69 93 28 58 66 30 28 42 9)
  • F(x) ? f(i) for i 0 -gt x
  • F(0) 82
  • F(1) 69 82
  • F(2) 93 69 82
  • F(7) 28 30 66 58 28 93 69 82
  • F(8) 42 28 30 66 58 28 93 69 82
  • F(9) 9 42 28 30 66 58 28 93 69
    82

8
First Solution Concept
(
82
69
93
28
58
66
30
28
42
Nothing interesting is going to happen until Ive
reached the bottom, so lets start there
9
)
9
First Solution Concept
(
9
)
(
9
)
10
First Solution Concept
(
42
9
)
(
42
42 9
)
11
First Solution Concept
(
28
42
9
)
(
28
28 42
28 42 9
)
12
First Solution Concept
Aha! Eureka! Every time I extend the list, I have
to (cons..) that item and also add it to each
item of the emerging list
(
30
28
42
9
(
)
30
30 28
30 28 42
30 28
)
13
First Attempt
  • integrate-1 (list of numbers) -gt (list of
    numbers)
  • convert list of values of f(x) to values of
    F(x)
  • F(x) sum f(x) i 0 -gt x
  • (define (integrate-1 lst)
  • (cond (empty? lst) empty
  • else (cons (first lst)
  • (add-to-each (first lst)
  • (integrate-1
    (rest lst))))))
  • add-to-each number (list of numbers) -gt
  • (list of
    numbers)
  • add n to each number on the list
  • (define (add-to-each n lst)
  • (cond (empty? lst) empty
  • else (cons ( (first lst) n)
  • (add-to-each n (rest
    lst)))))

14
Test Environment
  • (define test-data '(9.6 2.8 2.2 20 17.9 14.3 18.9
    16.8 15.7 19.7 16.2 8.9 18.1 4.6 16.3 5.8 0.3
    10.3 8.4 3.8))
  • (define (f x)
  • (random 100))
  • (define (big-list N)
  • (build-list N f))
  • test this with
  • (define ans (integrate-1 (big-list 800)))

15
accumulate.scm
16
What went wrong?
  • This worked fine for small lists
  • Rapidly gets out of hand for larger lists
  • Every time I extend the list, I have to go down
    the emerging list adding this number to each item
  • We actually wasted information as we went forward
    through the list
  • As we progress forwards, we should accumulate the
    value that needs to be added at each step on the
    way back

17
Better Solution Concept
  • f(x) (82 69 93 28 58 66 30 28 42 9)
  • F(x) ? f(i) for i 0 -gt x
  • F(0) 82
  • F(1) 69 82
  • F(2) 93 69 82
  • F(7) 28 30 66 58 28 93 69 82
  • F(8) 42 28 30 66 58 28 93 69 82
  • F(9) 9 42 28 30 66 58 28 93 69
    82

I could actually accumulate the amount I have to
add to the rest of the list as I go forward
through the list
18
Better Solution Concept
Add to the Rest
(
82
0
69
93
28
58
66
30
28
42
9
)
19
Better Solution Concept
Add to the Rest
(
82
0
69
82
93
28
58
66
30
28
42
9
)
20
Better Solution Concept
Add to the Rest
(
82
0
69
82
69 82
93
28
58
66
30
28
42
9
)
21
Better Solution Concept
Add to the Rest
(
82
0
69
82
69 82
93
28
93 69 82
58
66
30
28
42
9
)
22
Better Solution Concept
Add to the Rest
(
82
0
69
82
69 82
93
28
93 69 82
58
28 93 69 82
66
30
28
42
9
)
23
Better Solution Concept
496
(
9
)
(
505
)
24
Better Solution Concept
454
(
42
9
)
(
496
505
)
25
Better Solution Concept
426
(
28
42
9
)
(
454
496
505
)
26
Better Solution Concept
I dont seem to be working half as hard
396
(
30
28
42
9
(
)
426
454
496
505
)
27
accumulate.scm
28
A Different View
OK so we noted the cost of recursion can be
large, if its not designed well.
Each recursive call creates a new activation
frame. This implied that recursive solutions
could potentially take large amounts of memory.
29
Augmentative Recursion
Analysis The problem was that in order to find
whats returned from one function call, we had to
make a recursive call.
This required us to save frames for each
recursive call.
30
Tail Recursion
If we can solve the return result from each
level, the computer will not have to save each
activation frame. This approach is know as
tail recursion--its a technique that allows the
computer to optimize recursion so that it takes
less memory. Instead of postponing
multiplication 3 fact(2) we can instead
add extra parameters so that calculations can be
done entirely inside the frame.
Requires recursive call
31
Tail Recursion
We start with the usual function, but call a
helper function
(define (fact n) (fact-helper 1 n)) (define
(fact-helper product n) (cond ((zero? n)
product) (else (fact-helper ( product
n) (- n 1)))))
This is similar to our previous solution, but
look at the calculations--each term can be know
inside the frame.
32
Tail Recursion
We now have all the information needed to
calculate the result inside the frame, without
saving each recurse.
Requires recursive call
All-in-one
33
Tail Recursion
We can see the memory use of this approach by
tracing
(fact 3) (fact-helper 1 3) (fact-helper 3
2) (fact-helper 6 1) (fact-helper 6 0) gt6
Each frame completed, and is not necessary to
save.
34
Tail Recursion
(fact 3) (fact-helper 1 3) (fact-helper 3
2) (fact-helper 6 1) (fact-helper 6 0) gt6
Potentially, the activation stack could grow just
as we saw with augmentative recursion. But the
Scheme interpreter (and many compilers) can
optimize tail recursive expressions to constant
memory use. (In fact, Scheme interpreters are
required to optimize tail recursion.)
35
Tail Recursion
So tail recursion is nothing very different from
what youve seen before, except that Its
written with an awareness of memory use Each
calculation is independent of subsequent
recursive calls Extra parameters (usually)
are used to eliminate dependence on
calculations made in subsequent recursive
calls. In plain English, they hold partial
results!!
1
2
3
36
Hints
Cant write it tail recursively? Just try
this Write the function recursively. Identi
fy which calculations cannot be made entirely
within a single frame Add sufficient extra
parameters to eliminate the need to save
information in a stack
1
2
3
37
Hints
(define (foo sum count
ltterminationgt
count
One way to visualize this is
to think of the activation stack being tipped on
its side. Instead of a stack, you use a list of
parameters to store information.
38
Example
Recently, we considered a function that would
multiply numbers by adding repeatedly.
Reworked, we get
(define mult a b) (mult-iterative 0 a
b)) (define (mult-iterative result num1
num2) (if ( num2 0) result (mult-iterative
( result num1) num1 (- num2 1))))
39
Example
(define mult a b) (mult-iterative 0 a
b)) (define (mult-iterative result num1
num2) (if ( num2 0) result (mult-iterative
( result num1) num1 (- num2 1))))
(mult 3 4) (mult-it 0 3 4) (mult-it 3 3
3) (mult-it 6 3 2) (mult-it 9 3 1) (mult-it 12 3
0)
A trace confirms the reduced use of memory. None
of the mult-it calls need to be kept on the
activation stack they do not depend on each
other.
40
Notes On Terminology
The following questions are presented to suggest
further reading Whats a recursive process?
Whats a recursive procedure? Whats the
difference? See http//mitpress.mit.edu/sicp/f
ull-text/book-Z-H-11.html
41
Footnote
  • To solve problems using tail recursion, we
    normally develop at least two different
    functions.
  • In the integration example, these were (integrate
    lst) and (integrate-2 lst accum)
  • Leaving these lying around separate is a little
    tacky.
  • We use the idea of (local ) functions to clean
    this up.

42
Recall (local )
  • The syntax for a function using (local ) is as
    follows
  • (define (use-local )
  • (local ((ltdefinition-1gt)
  • (ltdefinition-2gt)
  • (ltdefinition-ngt))
  • ltexpressiongt ))
  • Where the definition list is encapsulated, and
    when the function is invoked by evaluating
  • (use-local ) it actually evaluates the body
    ltexpressiongt which then uses the encapsulated
    definitions.

43
For example
  • (define (integrate-2 lst accum)
  • (cond (empty? lst) empty
  • else (cons ( (first lst)
  • accum)
  • (integrate-2 (rest lst)
  • ( accum (first
    lst))))))
  • (define (integrate lst)
  • (integrate-2 lst 0))

Unchanged (integrate-2 ) absorbed into its
wrapper, (integrate ), and called by it
(define (integrate lst) (local ( (define
(integrate-2 lst accum) (cond (empty?
lst) empty else (cons ( (first
lst) accum)
(integrate-2 (rest lst)
( accum (first lst)))))))
(integrate-2 lst 0)))
44
Generalized template
  • Deciding that a function will benefit from an
    accumulator requires experience borne of much
    practice.
  • When you decide this is probably the case, (local
    ) provides an excellent template.
  • (define (ltold-fngt ltparamsgt)
  • (local (
  • (define (ltaux-fngt ltparamsgt ltaccumgt)
  • (cond (ltend?gt ltparamsgt)
  • else ltparamsgt ltaccumgt
  • (ltaux-fngt ltparamsgt ltaccumgt
    )))))
  • (ltaux-fngt ltparamsgt ltinitial-accgt)))

45
Dissecting this Template
What you really want
What you need to do the job efficiently
  • (define (ltold-fngt ltparamsgt)
  • (local (
  • (define (ltaux-fngt ltparamsgt ltaccumgt)
  • (cond (ltend?gt ltparamsgt)
  • else ltparamsgt ltaccumgt
  • (ltaux-fngt ltparamsgt
  • ltaccumgt )))))
  • (ltaux-fngt ltparamsgt ltinitial-accgt)))

Use parameters and accumulator as required
Call the new function with initial accumulator
value
Update accumulator value in the recursive call
46
Commentary on the Design Process
  • First, draw a picture of the problem
  • Write a normal recursive solution or focus on
    what your partial result at each stage will be
  • If you notice opportunities to avoid loss of
    useful information,
  • Start with the (local ) version of the template
  • Visualize how the accumulator computation will
    work
  • Figure out how to initialize the accumulation
  • Figure out how this affects the termination
    condition
  • Figure out how to update the accumulator for the
    recursive call

47
Example
Write a function to add all numbers from 0 to
N. Write this using augmentative recursion and
tail recursion.
tail.scm
48
Questions?
49
Intro to Graphs
50
Outline
  • Prerequisites
  • List manipulation
  • Objectives
  • Basic Graph Terminology
  • Depth-First Search
  • Reference
  • HTDP Section 28.1

51
Graphs
  • Have nothing to do with plotting data (i.e. a
    graph of the function y sin(x).
  • Are widely used to solve a large number of
    totally unrelated problems in CS, Engineering,
    Math, Business, etc.
  • Are studied in Graph Theory
  • So what do we mean by a graph?

52
Graph Terminology
What is a graph?
We can think of a graph as a combination of two
things a set of points (vertices) possibly in a
plane and a set of line segments
(edges). Sometimes, a graph is formally defined
as G (V, E) where G, V and E
represent Graph, Vertices (or points) and Edges
(the line segments).
53
Graph Terminology
A graph may be directed, meaning that the line
segments join points only in one direction.
A
B
F
C
D
E
Cant travel from E to D directly, only from D to
E on this edge.
54
Graph Terminology
A graph also might be undirected, meaning that
line segments join points from either direction.
A
B
F
C
D
E
An undirected or bidirectional graph
55
Graph Terminology
A graph also might be undirected, meaning that
line segments join points from either direction.
A
B
F
C
D
E
When you see edges with no arrows, you may
presume the graph is undirected, or bidirectional
56
Graph Terminology
When an edge connects two vertices or nodes, we
say that they are adjacent.
A
B
F
C
D
E
E is adjacent to F, A, B, and D, but not C.
Sure, you can still get to C from E, but not
directly.
57
Graph Terminology
Unlike trees, which are special types of graphs,
general graphs may have cycles, meaning that
children can be the parents of their ancestor
nodes.
A
B
E
C
Put another way, its possible to walk in circles
through a graph, if you dont keep track of where
youve been.
58
Graph Terminology
A collection of individual points (or edges) in a
graph may represent a path.
A path is just a way of getting from a start node
to another node.
59
Graph Terminology
In the wacky world of graphs, a node may be
connected even to itself.
Note
It seems odd, but since a graph is made of edges
and vertices, an edge just might connect a node
to itself.
60
Graph Terminology
We can also assign weights or values to edges.
3
8
12
5
9
25
7
12
In such a case, we have a weighted graph. The
weights can represent cost, distance, opportunity
costs--anything.
61
Graph Terminology
In the beginning, we will mainly concern
ourselves with unweighted graphs.
Well just be interested in establishing if
theres a connection or relationship between
nodes. We can later add weights to provide a
richer graph data set.
62
Quick Quiz
So far, weve worked with trees. Are trees
really just graphs? Consider the definition of a
graph...
Do trees have vertices and edges? Yup. Are
they graphs? Of course.
63
Graph Examples
64
(No Transcript)
65
(No Transcript)
66
(No Transcript)
67
(No Transcript)
68
Map of Distilleries in Scotland. Is this
a graph? (What is a graph?) Does this
provide useful information? Whats missing?
(Nothing Were only missing NSF Funding for
research on this graph.)
69
Graph/Network Uses
  • Graphs can also track the flows and movements of
    individuals in society.
  • E.g., Krempels map of Duisburg zoo visitors.
    The width of the lines indicates the number of
    visitors taking an edge.

(Note the Autobahn divides the zoo in half. Can
you see evidence of this in the graph?)
70
(No Transcript)
71
Summary Graphs (contd)
Graphs are also useful for modeling hierarchy
networks. A good example is the internet, with
various tiers of providers that link portions
of the net together. A graph can be used to
model the network relationship between computers.
72
(No Transcript)
73
(No Transcript)
74
More Examples
Visit www.theyrule.net
75
Representing Graphs
Lets take a simple graph, and try to draw a
Scheme-like list that represents its data.
76
Representing Graphs
(define graph '((A (B E F)) (B (A C D E)) (C
(B D)) (D (B C E)) (E (A B D F)) (F (A E))))
A
Caution Think of this is a flowchart and not a
graph.
B
E
F
E
D
E
F
C
A
A
77
Uses for Graphs
What practical use is such a data structure?
(define tech-graph '((Skiles (S-C Library DMS))
(S-C (Skiles CoC Rich Library )) (CoC (S-C Rich
)) (Rich (S-C CoC Library )) (Library (Skiles
S-C Rich DMS)) (DMS (Skiles Library ))))
Student Center
Skiles
A
B
We could use it to model map relationships, find
efficient paths, etc. More on this later...
CoC
F
C
DMSmith
D
E
Library
Rich
78
Searching Graphs
What good is a graph if you cant search it?
Our tree traversals proved useful, so can we
walk a graph using similar techniques?
Problem What if a node has more than one
child? Our previous algorithms just considered
three items node, left and right. Problem
What if we cycle?
Lets learn more about searching first.
79
Searching Graphs
We need to keep these problems in mind...
For now, however, lets consider searches that
are simple and dont have this problem.
80
Hierarchical search
We can also arrange knowledge into hierarchies.
Perhaps the most familiar is the zoological
hierarchy of kingdoms, phylum, genus, etc.
Lepidoptera
Butterfly
Moth
Monarch
Mourning Cloak
81
Hierarchical search
Hierarchies allow us to make statements about
items in the collection. For example, we can say
that a monarch is a butterfly, and a butterfly
is a lepidoptera.
Lepidoptera
Butterfly
Moth
Monarch
Mourning Cloak
82
Hierarchical search
Since most people are unfamiliar with insects
families, well instead switch to a more familiar
hierarchy the Flintstones.
Roxy
Chip
Bamm-Bamm
Pebbles
Fred
Wilma
Barney
Betty
83
Hierarchical search
Well also give attributes to this hierarchy
Chip
Roxy
Has dad
Has mom
Bamm-Bamm
Pebbles
Has dad
Has mom
Has mom
Has dad
Wilma
Barney
Betty
Fred
84
Hierarchical search
This allows us to do important research, like
asking who is Chips mother? Or who is
Chips grandfather on his mothers side?
Chip
Roxy
Has dad
Has mom
Bamm-Bamm
Pebbles
Has mom
Has dad
Has mom
Has dad
Betty
Wilma
Barney
Fred
85
Depth First Search
The simplest form of search in a hierarchical or
network structure is called "depth-first search".
We can write an algorithm for a depth-first
search on a binary tree DFS (depth first
search) 1. Look at the root 2. If it's
what you're looking for, then return success
3. If the root has no descendants, then return
failure 4. Call df-search on the subtree
whose root is the leftmost descendant and return
success if that search is successful 5. Call
df-search on the subtree whose root is the
rightmost descendant and return success if that
search is successful
86
Depth First Search
If this seems familiar, its because DFS is a
variation of one tree search we saw
recently preorder 1.visit the root
2.call preorder on the left subtree 3.call
preorder on the right subtree
87
Comparison
preorder 1.visit the root 2.call
preorder on the left subtree 3.call preorder
on the right subtree
DFS (depth first search) 1. Look at the
root 2. If it's what you're looking for,
then return success 3. If the root has no
descendants, then return failure 4. Call
df-search on the subtree whose root is the
leftmost descendant and return success if that
search is successful 5. Call df-search on
the subtree whose root is the rightmost
descendant and return success if that search is
successful
88
Comparison
preorder 1.visit the root 2.call
preorder on the left subtree 3.call preorder
on the right subtree
DFS (depth first search) 1. Look at the
root 2. If it's what you're looking for,
then return success 3. If the root has no
descendants, then return failure 4. Call
df-search on the subtree whose root is the
leftmost descendant and return success if that
search is successful 5. Call df-search on
the subtree whose root is the rightmost
descendant and return success if that search is
successful
89
Comparison
preorder 1.visit the root 2.call
preorder on the left subtree 3.call preorder
on the right subtree
Whats different?
DFS (depth first search) 1. Look at the
root 2. If it's what you're looking for,
then return success 3. If the root has no
descendants, then return failure 4. Call
df-search on the subtree whose root is the
leftmost descendant and return success if that
search is successful 5. Call df-search on
the subtree whose root is the rightmost
descendant and return success if that search is
successful
90
DFS - Preorder Differences
The big differences between the preorder
algorithm and the depth-first search algorithm
are these depth-first search stops
before searching the whole tree, if it finds what
it's looking for preorder traversal always
examines the entire tree with
depth-first search, searching the right subtree
occurs only if the search of the left subtree
failed to find what was being looked for with
preorder traversal, the right subtree is always
explored (this is sort of a corollary to the
first difference listed just above)
1
2
91
Implementing Depth-First Search
Lets first note how we might represent the trees
in Scheme
(define-struct node ( name mother father )
) (define harriet (make-node 'harriet false
false)) (define ozzie (make-node 'ozzie false
false)) (define betty (make-node 'betty false
false)) (define barney (make-node 'barney false
false)) (define fred (make-node 'fred false
false)) (define wilma (make-node 'wilma false
false))
Chip
Roxy
Bamm-Bamm
Pebbles
Wilma
Fred
Barney
Betty
92
Implementing Depth-First Search
We start with a function called dfs
(define (dfs target here) (cond (not
here) false (symbol? target (node-name
here)) true else (or (dfs
target (node-father here)) (dfs targer
(node-mother here)))))
93
Improving DFS
Now, just telling us true or false is not
entirely useful. We actually want to use a
hierarchical search to produce a list that shows
the relationship between items.
Well use tail recursion . . .
94
Improving DFS
(define (dfs-list who here) (local (
(define (dfs-aux who here answer)
(cond (not here) empty
(symbol? who (node-name here))
(cons (node-name here) answer)
else (local ((define mother-list
(dfs-aux who
(node-mother here)
(cons
(node-name here)
answer))))
(if (empty? mother-list)
(dfs-aux who
(node-father here)
(cons (node-name here)
answer))
mother-list)))))
(dfs-aux who here empty)))
95
dfs.scm
96
Questions?
97
(No Transcript)
Write a Comment
User Comments (0)
About PowerShow.com