Recursion L - PowerPoint PPT Presentation

1 / 42
About This Presentation
Title:

Recursion L

Description:

Draw image in bottom left quadrant. g.drawImage(Image, x, y size/2, size/2, ... Goal: To get from the top left corner (0, 0) to the bottom right corner (3, 7) ... – PowerPoint PPT presentation

Number of Views:74
Avg rating:3.0/5.0
Slides: 43
Provided by: citG7
Category:

less

Transcript and Presenter's Notes

Title: Recursion L


1
  • Recursion (LO, Chapter 12)
  • Recursion is just another way to implement
    repetition. Compare
  • while (n gt 0)
  • System.out.println(n)
  • n--
  • and
  • void countDown(int n)
  • if (n gt 0)
  • System.out.println(n)
  • countDown(n-1)
  • But it is a very powerful way to implement
    repetition!

2
  • Recursion (cont.)
  • Examples
  • Factorial
  • Fibonacci
  • Towers of Hanoi Recursively move piles of disks
  • Quicksort Recursively sort subarrays
  • Nested pictures Recursively draw smaller
    pictures
  • (Binary) tree traversal TreeSet iteration
  • Expression evaluation Recursively evaluate
    subexpressions
  • Region growing (MineSweeper, Bubblet and AtariGo)
  • Maze searching (backtrack search)
  • Shortest path problems
  • Program compilation
  • ...

3
  • Factorial
  • The factorial of a nonnegative integer n, denoted
    n!, is the product of the positive integers less
    than or equal to n. E.g., 5! 5 4 3 2 1
    120. Equivalently, 0! 1, n! n(n-1)! (for
    n gt 0). The factorial numbers are thus 1, 1, 2,
    6, 24, 120, 720, 5040, ...
  • int factorial(int n) // recursive definition
  • if (n 0)
  • return 1
  • else
  • return n factorial(n-1)
  • Abbreviate factorial by f
  • f(4) 4 f(3) 4 (3 f(2)) 4 (3 (2
    f(1)))
  • 4 (3 (2 (1 f(0))))
  • 4 (3 (2 (1 1))) ... 24
  • (Here the recursion is unnecessary.)

4
  • Fibonacci
  • The Fibonacci numbers are formed by starting with
    0 and 1 and then adding the latest two numbers to
    get the next one. Equivalently, f(0) 0, f(1)
    1, f(n) f(n-2) f(n-1) (for n gt 1). The
    Fibonacci numbers are thus 0, 1, 1, 2, 3, 5, 8,
    13, 21, 34, 55, 89, ...
  • int fibonacci(int n) // naive recursive
    definition
  • if (n lt 1)
  • return n
  • else
  • return fibonacci(n-2) fibonacci(n-1)
  • f(5) f(3) f(4) (f(1) f(2)) (f(2)
    f(3))
  • (1 (f(0) f(1))) ((f(0) f(1))
    (f(1) f(2)))
  • (1 (0 1)) ((0 1) (1 (f(0)
    f(1))))
  • 2 (1 (1 (0 1))) ...
  • 5
  • (Here the recursion is unacceptably inefficient.
    Consider the tree for f(10). This is an
    exponential computation.)

5
  • Fibonacci (cont.)
  • int fibonacci(int n)
  • return f(0, 1, n)
  • int f(int prev, int curr, int n) // efficient
    recursion
  • if (n 0)
  • return prev
  • else
  • return f(curr, prevcurr, n-1)
  • Now there is no repeated computation, this is a
    linear computation
  • f(0, 1, 6) f(1, 1, 5) f(1, 2, 4) f(2, 3, 3)
  • f(3, 5, 2) f(5, 8, 1) f(8, 13,
    0) 8

6
  • Recursion (cont.)
  • Every recursive method must have the following
    properties
  • A termination condition (e.g., n 0, n lt 1 ),
    cf. basis for induction.
  • Every recursive call must strictly approach the
    termination condition (e.g., factorial(n-1),
    fibonacci(n-2), fibonacci(n-1) ), f(curr, prev,
    curr, n-1), cf. induction step in proof
    by induction.
  • Recursion is analogous to induction.
  • Recursive methods can be proved correct by
    induction.

7
  • Towers of Hanoi
  • (Ref. E. Rouse Ball, Mathematical Recreations )
  • How to move the pile of n disks from peg 1 to
    peg 3, one disk at a time, so that a larger disk
    is never above a smaller disk?

1
2
3
8
  • Towers of Hanoi (cont.)
  • If n 0, we are finished, and don't need to do
    anything at all.
  • Otherwise, suppose we are moving n disks from
    peg i to peg k
  •  Move n-1 disks from peg i to peg j
  •  Move 1 disk (the largest of the n) from peg i
    to peg k
  •  Move (the top, smaller) n-1 disks from peg j
    to peg k
  • Successive states
  • ABC on peg 1
  • BC on peg 1
    A on peg 3
  • C on peg 1 B on peg 2 A
    on peg 3
  • C on peg 1 AB on peg 2
  • AB on peg 2
    C on peg 3
  • A on peg 1 B on peg 2 C
    on peg 3
  • A on peg 1
    BC on peg 3

  • ABC on peg 3

9
  • Towers of Hanoi (cont.)
  • / Moves n disks from from to to using other /
  • void move(int n, int from, int other, int to)
  • if (n gt 0)
  • move(n-1, from, to, other)
  • System.out.println("Move disk from "
    from
  • " to " to)
  • move(n-1, other, from, to)
  • The initial call is, say
  • move(3, 1, 2, 3)
  • Note
  • Termination condition n 0
  • Each recursive call strictly approaches the
    termination condition move(n-1, from, to,
    other) (n-1 lt n)

10
  • Towers of Hanoi (cont.)
  • Output
  • Move disk (A) from 1 to 3
  • Move disk (B) from 1 to 2
  • Move disk (A) from 3 to 2
  • Move disk (C) from 1 to 3
  • Move disk (A) from 2 to 1
  • Move disk (B) from 2 to 3
  • Move disk (A) from 1 to 3
  • Exercise Write a recursive method to move n disks
    from one peg to another under these rules when
    there are 4 pegs available in total. Try to find
    a method that takes as few moves as possible.
  • (Clearly this can be done in fewer moves than
    when there are only 3 pegs available. But no
    algorithm has been proved to always take the
    minimum possible number of moves for 4 or more
    pegs. Indeed, the minimum possible number of
    moves is unknown for arbitrary n and 4 or more
    pegs.)

11
  • Quicksort (repeated)
  • public void quicksort(String a, int m, int n)
  • if (m lt n)
  • // Partition am..n about a "pivot"
    element x
  • // (Omitted here...)
  • // Recursively sort the "small" and "large"
    subarrays of a
  • // independently
  • quicksort(a, m, j) // sort am..j
  • quicksort(a, i, n) // sort ai..n
  • Note
  • Termination condition m gt n
  • Each call strictly approaches the termination
    condition  quicksort(a, m, j) (where j lt n),
     quicksort(a, i, n), (where m lt i )


12
  • Nested images I

13
  • Nested images I (cont.)
  • class ImagePane extends JPanel
  • public void paintComponent(Graphics g)
  • Image image
  • Toolkit.getDefaultToolkit().getImage("g
    avarnie.jpg")
  • drawPicture(g, 6, size, image)
  • private void drawPicture(Graphics g, int n,
    int size,
  • Image image)
  • if (n gt 0)
  • g.drawImage(image, 0, 0, size, size,
    this)
  • drawPicture(g, n-1, size/2, image)

14
  • Nested images II (Lewis Loftus, pp. 451453)
  • (See LL, Figure 12.5, p.452)
  • void drawPicture(int size, Graphics g)
  • if (size gt STOP)
  • // Separate picture into four quadrants
  • g.drawLine(size/2, 0, size/2, size)
  • g.drawLine(0, size/2, size, size/2)
  • // Draw three images in different
    quadrants
  • g.drawImage(world, size/2OFFSET,
    0OFFSET,
  • size/2-(OFFSET2), size/2-(OFFSET2),
    this)
  • g.drawImage(everest, 0OFFSET,
    size/2OFFSET,
  • size/2-(OFFSET2), size/2-(OFFSET2),
    this)
  • g.drawImage(goat, size/2OFFSET,
    size/2OFFSET,
  • size/2-(OFFSET2), size/2-(OFFSET2),
    this)
  • // Draw the entire picture again in other
    quadrant
  • drawPicture(size/2, page)

15
  • Nested images II (cont.)
  • import java.applet.Applet
  • import java.awt.
  • public class NestedImages extends Applet
  • private final int SIZE 300 // Size of
    applet
  • private final int STOP 20 // Smallest
    picture size
  • private final int OFFSET 2 // Picture
    offset from border
  • private Image world, everest, goat
  • public void init()
  • world getImage(getDocumentBase(),
    "world.gif")
  • / Similarly for images everest and goat
    /
  • setSize(SIZE, SIZE)
  • public void paint(Graphics g)
  • drawPicture(SIZE, g)
  • private void drawPicture(int size, Graphics
    g) ...

16
  • Nested images III (Abelson Sussman, SICP,
    Section 2.2.4)
  • (See SICP, Figure 2.14)

Image
Top
Top
Right
Image
Image
Image
Right
Top
Right
17
  • Nested images III (cont.)
  • void drawMain(Image image, int x, int y, int
    size, Graphics g)
  • if (size gt STOP)
  • // Draw image in bottom left quadrant
  • g.drawImage(Image, x, ysize/2, size/2,
    size/2, this)
  • // Draw recursive pictures in other three
    quadrants
  • drawTop(image, x, y, size/2, g)
  • drawMain(image, xsize/2, y, size/2, g)
  • drawRight(image, xsize/2, ysize/2,
    size/2, g)
  • Note that the code exactly mirrors the pattern.

18
  • Nested images III (cont.)
  • void drawTop(Image image, int x, int y, int size,
    Graphics g)
  • if (size gt STOP)
  • // Draw images in bottom quadrants
  • g.drawImage(Image, x, ysize/2, size/2,
    size/2, this)
  • g.drawImage(Image, xsize/2, ysize/2,
    size/2, size/2,
  • this)
  • // Draw recursive pictures in top
    quadrants
  • drawTop(image, x, y, size/2, g)
  • drawTop(image, xsize/2, y, size/2, g)
  • Exercise 1 Write method drawRight.
  • Exercise 2 Complete and test an application with
    a suitable image.

19
  • Binary tree traversal
  • The easiest way to visit the nodes of a binary
    search tree in their natural order is
    recursively
  • void traverse(Entry t)
  • if (t ! null)
  • // Traverse left subtree
  • traverse(t.left)
  • // Visit node
  • System.out.print(t.key)
  • // Visit right subtree
  • traverse(t.right)
  • Note
  • Termination condition t null
  • Recursive calls strictly approach termination
    condition, as subtrees have strictly fewer nodes
    than the whole tree.

20
  • Expression evaluation
  • (To be completed...)

21
  • Region growing
  • A bitmap
  • 00000000011001111000000001111
  • 01110011011100111110000011100
  • 01111010000001111111110011000
  • 01111010001111111100110011000
  • 01111010000001111100011011000
  • 01111010000001111100111011100
  • 01111010000000011110000011110
  • 01111110011000000000100011110
  • What is the area of the "island" containing a
    given point, (row, col)? I.e., write a method
    which takes a bitmap and a point as arguments,
    and returns the number of ones connected to the
    given point.
  • (We interpret ones as "land" and zeros as "sea".)
  • (This problem arises in MineHunt, Bubblet,
    AtariGo, ...)

22
  • Region growing (cont.)
  • We need to look outward from the given point to
    each neighbour that we have not yet seen.
  • Initially, assign all elements of an auxiliary
    boolean array, seen, to false (unseen). (Array
    seen is just a representation of a set of
    points.)
  • Main method
  • // Returns the number of unvisited points in the
    island
  • // containing point (row, col).
  • int area (int row, int col)
  • int area 0
  • if (gridrowcol 1 ! seenrowcol)
  • area
  • seenrowcol true
  • for each neighbour (r, c) of (row, col)
  • area area(r, c)
  • return area

23
  • Region growing (cont.)
  • Note An alternative solution to this problem was
    given in the lecture notes on the collection
    framework. The problem can be solved equally
    easily iteratively or recursively. (Though the
    recursive solution is arguably simpler.)
  • Exercise Modify either solution to return the set
    of points in the region.

24
  • Maze Solving (LL, pp.455459)
  • Maze input
  • 4 8 // number of rows and columns
  • 1 1 0 1 1 1 1 0 // 0 blocked, 1 free
  • 0 1 1 1 0 1 0 1
  • 0 1 0 1 0 1 1 1
  • 1 1 1 0 0 1 0 1
  • Goal To get from the top left corner (0, 0) to
    the bottom right corner (3, 7).
  • Solution At each unvisited position, try going
    down, right, up, left, and repeating, in turn.
  • 7 7 0 7 7 7 1 0 // 1 still free
  • 0 7 7 7 0 7 0 1 // 3 visited
  • 0 3 0 3 0 7 7 7 // 7 visited and on path
  • 1 3 3 0 0 3 0 7

25
  • Maze Solving (cont.)
  • Maze representation
  • final int NROWS 4, NCOLS 8
  • final int grid new intNROWSNCOLS
  • Main algorithm
  • // Finds a path (if any) from (row, col) through
    unvisited
  • // squares to the destination (NROWS-1,NCOLS-1).
  • boolean solve (int row, int col)
  • boolean done false
  • if (valid(row, col)) // Unvisited position
  • gridrowcol 3 // Mark position visited
  • if (goal(row, col)) // Destination reached?
  • done true
  • else

26
  • Maze Solving (cont.)
  • // ... continuation
  • if (! done)
  • done solve(row, col1) // Try
    right
  • if (! done)
  • done solve(row-1, col) // Try
    up
  • if (! done)
  • done solve(row, col-1) // Try
    left
  • if (done)
  • gridrowcol 7 // Mark
    position on path
  • return done
  • Initial call

27
  • Maze Solving (cont.)
  • Auxiliary methods
  • boolean valid (int row, int col)
  • return (0 lt row row lt NROWS
  • 0 lt col col lt NCOLS
  • gridrowcol 1) // position is
    FREE
  • // and
    UNVISITED
  • boolean goal (int row, int col)
  • return (row NROWS-1 col NCOLS-1)
  • Exercise Write a method to print the coordinates
    of the elements of the path from the start, (0,
    0), to the goal, (nrows-1, ncols-1).
  • See sample programs on Web site. Program OnePath
    completes this implementation. Program AllPaths
    makes minor changes to count the total number of
    paths.

28
  • General path finding algorithm
  • (To be completed...)

29
  • Counting rook paths on a chess board
  • Find the number of non-intersecting rook paths
    from the top left square of an mxn chess board to
    the bottom right square of the board. E.g., for
    mn2, there are 2 paths, for m2, n3 there are
    4 paths, for mn3 there are 12 paths.
  • This can be solved by a simple generalisation of
    the all-paths version of the maze solving
    program.
  • See the example program RookPaths on the Web
    site.
  • See the following Web site for extensive
    information on this recreational problem
  • http//pauillac.inria.fr/algo/bsolve/constant/cnnt
    v/gammel/gammel.html
  • Exercise (difficult) Modify the program RookPaths
    so that it can count the number of solutions on
    an 8x8 board in an acceptable time.

30
  • Graph coloring
  • A map
  • The corresponding graph

1
2
0
3
6
4
1
2
0
3
6
4
5
31
  • Graph coloring (cont.)
  • Problem Given n colors, can we assign a different
    color to each region (vertex) so that adjacent
    regions (vertices) are assigned different colors?
  • Answer (Haken and Appel, ca. 1970) For a planar
    map, with n 4, yes!
  • But how?
  • Graph representation
  • 0 1 6 // nbrs0 lt1, 6gt
  • 1 0 2 6 // nbrs1 lt0, 2, 6gt
  • 2 1 3 6 // ...
  • 3 2 4 6
  • 4 3 6
  • 5
  • 6 0 1 2 3 4 // nvertices 7

32
  • Graph coloring (cont.)
  • Graph representation (cont.)
  • private int ncolors // Maximum number of colors
    available
  • private int nvertices // Number of vertices in
    graph
  • private int nbrs
  • // List of neighbours of vertices 0, 1, ...,
    nvertices-1
  • private int colors
  • // Color of vertices 0, 1, ..., nvertices-1
  • // For all v, 0 lt colorsv lt ncolors
  • // Initially, colorsv 0, for 0 lt v lt
    nvertices

33
  • Graph coloring (cont.)
  • Main algorithm
  • // Assuming vertices 0,...,v-1 are already
    consistently colored,
  • // tests whether there is a consistent assignment
    of colors
  • // to vertices v,...,nvertices-1.
  • public boolean solve (int v)
  • if (goal(v)) // All vertices consistently
    colored?
  • return true
  • else
  • // Try to color vertex v with each color c in
    turn
  • for (int c 0 c lt ncolors c)
  • if (valid(v, c))
  • colorsv c
  • if (solve(v1))
  • return true

34
  • Graph coloring (cont.)
  • Auxiliary methods
  • private boolean goal (int v)
  • return (v nvertices)
  • // Tests whether c is different from the colors
    of all preceding
  • // neigbours of v.
  • private boolean valid (int v, int c)
  • for (int i 0 i lt nbrsv.length i)
  • int u nbrsvi
  • if (u lt v colorsu c)
  • return false
  • return true

35
  • Backtrack Search Single solution (not
    examinable)
  • The maze solving and graph colouring problems are
    examples of backtrack search for a single
    solution. There are many other examples.
  • Backtrack search arises whenever there is a need
    to make repeated choices (or assignments) subject
    to some consistency condition, possibly requiring
    undoing previous choices (or assignments). This
    "undoing", followed by a different choice (or
    assignment) is called backtracking.
  • Backtrack search is most easily implemented
    recursively, as in the previous examples.
  • It can be recognised whenever there is an
    apparent need for arbitrarily deeply nested
    loops.
  • for each choice for position 0
  • for each valid choice for position 1
  • for each valid choice for position 2
  • ...
  • for each valid choice for position n
  • Print the choices for all positions,
    and exit

36
  • Backtrack Search Single solution (cont.)
  • Corresponding recursive schema
  • // Assuming valid choices for positions
    0,...,k-1, finds a
  • // consistent assignment of choices for positions
    k,...,n-1.
  • boolean solve (int k)
  • if (choice0..k-1 is a solution) // e.g.,
    k n
  • return true
  • else
  • for each valid choice c for position k,
  • given choice0..k-1
  • choicek c
  • if (solve(k1))
  • return true
  • return false

37
  • Backtrack Search All solutions (not examinable)
  • Backtrack search is often required to generate
    all solutions to some combinatorial problem, as
    in the rook paths problem (or the nested loops
    example). In this case we need a slight variant
    to the general schema.
  • // Assuming valid choices for positions
    0,...,k-1, finds all
  • // consistent assignment of choices for positions
    k,...,n-1.
  • void solve (int k)
  • if (choice0..k-1 is a solution) // e.g.,
    k n
  • print, process or count choice0..k-1
  • else
  • for each valid choice c for position k,
  • given choice0..k-1
  • choicek c
  • solve(k1)
  • Again, initially, call solve(0).

38
  • Backtrack Search Iterative version (not
    examinable)
  • Backtrack search can also be implemented
    iteratively, e.g., to generate all solutions
  • k 0
  • S0 set of possibilities for choice0
  • while (k gt 0)
  • while (Sk is not empty) // advance
  • Choose c in Sk and remove it
  • choicek c
  • if (choice0..k is a solution) // e.g.,
    k n-1
  • Print, process or count choice0..k
  • else
  • k k 1
  • Sk set of possibilities for
    choicek,
  • given choice0..k-1
  • k k - 1 // backtrack

39
  • Backtrack Search Iterative version (cont.)
  • This iterative schema may run faster than the
    corresponding recursive schema, but only by a
    small constant factor, and is more complex since
    the array S0..n-1 of sets of possible choices
    needs to be explicitly maintained.
  • Exercise Write an iterative schema for the
    iterative search to find a single solution to
    such a combinatorial problem.
  • Exercise Re-implement either solution to the Maze
    problem iteratively.

40
  • Backtrack Search Least solution (not examinable)
  • Often we wish to find the least or cheapest
    solution. This requires a variation on the
    all-solutions schema
  • float minCost infinity // cost of current
    min-cost solution
  • Value solution // current min-cost
    solution
  • Value choice new ValueMAX // current
    partial solution
  • void solve (int k, float cost)
  • if choice0..k-1 is a solution // new
    min-cost solution
  • minCost cost
  • solution copy(choice)
  • else
  • // Try each choice c for position k in
    turn
  • for each valid choice c for position k
  • given choice0..k-1
  • newCost f(cost, k, c) // cost of
    new partial soln
  • if (newCost lt minCost)
  • choicek c

41
  • Backtrack Search Shortest solution (not
    examinable)
  • We may adapt this schema to find the shortest
    path to a solution (cost is the number of moves)
    in a state-space exploration problem such as
    Traffic.
  • int minMoves infinity // length of current
    shortest solution
  • Move solution // current shortest
    solution
  • Move choice new MoveMAX // current partial
    solution
  • void solve (int k, Position pos, int nMoves)
  • if p is the goal position // new shortest
    solution
  • minMoves nMoves
  • solution copy(choice)
  • else
  • for each valid move m from position pos
  • newPos apply move m to position pos
  • if we have not been to newPos before
    (on this path)
  • nMoves
  • if nMoves lt minMoves
  • choicek m // new partial
    solution

42
  • Backtrack Search Shortest solution (cont.)
  • Initially, call solve(0, initialPos, 0). The
    solution is array solution, length minMoves.
  • Basically, this is a classical AI problem, and
    efficient solutions are still discussed in AI
    courses.
  • Warning There could be errors in the above
    schema.
  • Note It may be simpler to solve this problem by
    breadth-first search, using an explicit queue of
    positions to be expanded, as with the first
    solution to the island area problem.
Write a Comment
User Comments (0)
About PowerShow.com