Title: CS1321: Introduction to Programming
1CS1321Introduction to Programming
- Georgia Institute of Technology
- College of Computing
- Lecture 20
- March 21, 2002
2Agenda
1. Tail Recursion 2. Graphs
3Tail or Accumulator-Style Functions
4Outline
- Prerequisites
- Recursion
- Structures
- Graphs
- Objectives
- Need for Accumulation
- Accumulator Style Functions
- Transforming Recursive Functions
- Reference
- HTDP Chapters 31, 32
5Background
- 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
6Example Numerical Integration
- Given the values of a function f(x)
- Compute the integral F(x) ? f(i), i 0 x
7First 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
8First 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
)
9First Solution Concept
(
9
)
(
9
)
10First Solution Concept
(
42
9
)
(
42
42 9
)
11First Solution Concept
(
28
42
9
)
(
28
28 42
28 42 9
)
12First 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
)
13First 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)))))
14Test 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)))
15accumulate.scm
16What 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
17Better 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
18Better Solution Concept
Add to the Rest
(
82
0
69
93
28
58
66
30
28
42
9
)
19Better Solution Concept
Add to the Rest
(
82
0
69
82
93
28
58
66
30
28
42
9
)
20Better Solution Concept
Add to the Rest
(
82
0
69
82
69 82
93
28
58
66
30
28
42
9
)
21Better Solution Concept
Add to the Rest
(
82
0
69
82
69 82
93
28
93 69 82
58
66
30
28
42
9
)
22Better 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
)
23Better Solution Concept
496
(
9
)
(
505
)
24Better Solution Concept
454
(
42
9
)
(
496
505
)
25Better Solution Concept
426
(
28
42
9
)
(
454
496
505
)
26Better Solution Concept
I dont seem to be working half as hard
396
(
30
28
42
9
(
)
426
454
496
505
)
27accumulate.scm
28A 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.
29Augmentative 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.
30Tail 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
31Tail 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.
32Tail 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
33Tail 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.
34Tail 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.)
35Tail 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
36Hints
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
37Hints
(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.
38Example
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))))
39Example
(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.
40Notes 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
41Footnote
- 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.
42Recall (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.
43For 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)))
44Generalized 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)))
45Dissecting 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
46Commentary 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
47Example
Write a function to add all numbers from 0 to
N. Write this using augmentative recursion and
tail recursion.
tail.scm
48Questions?
49Intro to Graphs
50Outline
- Prerequisites
- List manipulation
- Objectives
- Basic Graph Terminology
- Depth-First Search
- Reference
- HTDP Section 28.1
51Graphs
- 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?
52Graph 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).
53Graph 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.
54Graph 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
55Graph 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
56Graph 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.
57Graph 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.
58Graph 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.
59Graph 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.
60Graph 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.
61Graph 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.
62Quick 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.
63Graph Examples
64(No Transcript)
65(No Transcript)
66(No Transcript)
67(No Transcript)
68Map 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.)
69Graph/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)
71Summary 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)
74More Examples
Visit www.theyrule.net
75Representing Graphs
Lets take a simple graph, and try to draw a
Scheme-like list that represents its data.
76Representing 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
77Uses 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
78Searching 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.
79Searching Graphs
We need to keep these problems in mind...
For now, however, lets consider searches that
are simple and dont have this problem.
80Hierarchical 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
81Hierarchical 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
82Hierarchical 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
83Hierarchical 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
84Hierarchical 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
85Depth 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
86Depth 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
87Comparison
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
88Comparison
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
89Comparison
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
90DFS - 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
91Implementing 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
92Implementing 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)))))
93Improving 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 . . .
94Improving 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)))
95dfs.scm
96Questions?
97(No Transcript)