Recursive Backtracking Eric Roberts CS 106B January 25, 2013.

Slides:



Advertisements
Similar presentations
Chapter Objectives To learn about recursive data structures and recursive methods for a LinkedList class To understand how to use recursion to solve the.
Advertisements

Heuristic Search techniques
BackTracking Algorithms
Graphs Graphs are the most general data structures we will study in this course. A graph is a more general version of connected nodes than the tree. Both.
Announcements Assignment #4 is due tonight. Last lab program is going to be assigned this Wednesday. ◦ A backtracking problem.
8 Algorithms Foundations of Computer Science ã Cengage Learning.
CMPE 466 COMPUTER GRAPHICS Chapter 8 2D Viewing Instructor: D. Arifler Material based on - Computer Graphics with OpenGL ®, Fourth Edition by Donald Hearn,
Backtracking COP Backtracking  Backtracking is a technique used to solve problems with a large search space, by systematically trying and eliminating.
Lance Danzy Melinda Katanbafnezhad. The “A Mazing Problem” is a classical experiment from psychology where scientists carefully observe a rat going through.
© 2006 Pearson Addison-Wesley. All rights reserved14 A-1 Chapter 14 Graphs.
Unit 181 Recursion Definition Recursive Methods Example 1 How does Recursion work? Example 2 Problems with Recursion Infinite Recursion Exercises.
1 Recursion  Recursion is a fundamental programming technique that can provide an elegant solution certain kinds of problems  Chapter 11 of the book.
Algorithm Efficiency and Sorting
29-Jun-15 Recursion. 2 Definitions I A recursive definition is a definition in which the thing being defined occurs as part of its own definition Example:
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Recursion Chapter 7. Chapter 7: Recursion2 Chapter Objectives To understand how to think recursively To learn how to trace a recursive method To learn.
Chapter 2: Algorithm Discovery and Design
State-Space Searches. 2 State spaces A state space consists of –A (possibly infinite) set of states The start state represents the initial problem Each.
State-Space Searches.
Recursion Chapter 5.
Solving Puzzles Name(s): _______________________ Puzzle 1: Word Search
Functions in C++ Eric Roberts CS 106B January 9, 2013.
Introduction Tracking the corners Camera model and collision detection Keyframes Path Correction Controlling the entire path of a virtual camera In computer.
Artificial Intelligence Lecture 9. Outline Search in State Space State Space Graphs Decision Trees Backtracking in Decision Trees.
Problem Solving and Mazes
© The McGraw-Hill Companies, 2006 Chapter 4 Implementing methods.
Recursion Chapter 7. Chapter Objectives  To understand how to think recursively  To learn how to trace a recursive method  To learn how to write recursive.
Recursion Opening Discussion zWhat did we talk about last class? zDo you have any questions about the assignment? zWhat is a recursive function?
1 Wright State University, College of Engineering Dr. T. Doom, Computer Science & Engineering CS 241 Computer Programming II CS 241 – Computer Programming.
State-Space Searches. 2 State spaces A state space consists of A (possibly infinite) set of states The start state represents the initial problem Each.
CSC 205 Programming II Lecture 18 The Eight Queens Problem.
Graphs. Made up of vertices and arcs Digraph (directed graph) –All arcs have arrows that give direction –You can only traverse the graph in the direction.
CHAPTER 4 RECURSION. BASICALLY, A FUNCTION IS RECURSIVE IF IT INCLUDES A CALL TO ITSELF.
CHAPTER 4 RECURSION. BASICALLY, A METHOD IS RECURSIVE IF IT INCLUDES A CALL TO ITSELF.
Chapter 5 Recursion. Basically, a method is recursive if it includes a call to itself.
Module 3: Steering&Arrays #1 2000/01Scientific Computing in OOCourse code 3C59 Module 3: Algorithm steering elements If, elseif, else Switch and enumerated.
Backtracking and Games Eric Roberts CS 106B January 28, 2013.
DIFFERENTIAL EQUATIONS 10. DIFFERENTIAL EQUATIONS Unfortunately, it’s impossible to solve most differential equations in the sense of obtaining an explicit.
Building Java Programs Appendix R Recursive backtracking.
CPS Backtracking, Search, Heuristics l Many problems require an approach similar to solving a maze  Certain mazes can be solved using the “right-hand”
1 Recursion Recursion is a powerful programming technique that provides elegant solutions to certain problems. Chapter 11 focuses on explaining the underlying.
Chapter 6 Questions Quick Quiz
8.1 8 Algorithms Foundations of Computer Science  Cengage Learning.
Kruse/Ryba ch051 Object Oriented Data Structures Recursion Introduction to Recursion Principles of Recursion Backtracking: Postponing the Work Tree-Structured.
CSE 143 Lecture 13 Recursive Backtracking slides created by Ethan Apter
Recursion Chapter 17 Instructor: Scott Kristjanson CMPT 125/125 SFU Burnaby, Fall 2013.
Computer Science 1620 Sorting. cases exist where we would like our data to be in ascending (descending order) binary searching printing purposes selection.
Searching CSE 103 Lecture 20 Wednesday, October 16, 2002 prepared by Doug Hogan.
TOWERS OF HANOI. : If n = 1, move disk 1 from pole 'A' to pole 'B'. else: 1.First, move n-1 disks from pole 'A' to pole 'C', using pole 'B' as.
February 9, 2016Introduction to Artificial Intelligence Lecture 5: Perception & Action 1 Frege Notes In order to use many of the Java math functions in.
Searching and Sorting Searching algorithms with simple arrays
Backtracking, Search, Heuristics
Recursion Eric Roberts CS 106B.
Recursive Exploration II
Programming Abstractions
CSCI 104 Backtracking Search
Java Software Structures: John Lewis & Joseph Chase
7.4 Problem Solving with Recursion
Programming Abstractions
Chapter 12 Recursion (methods calling themselves)
adapted from Recursive Backtracking by Mike Scott, UT Austin
slides courtesy of Eric Roberts
State-Space Searches.
State-Space Searches.
State-Space Searches.
Announcements Assignment #4 is due tonight. Last lab program is going to be assigned this Wednesday. ◦ A backtracking problem.
CSC 205 – Java Programming II
Backtracking, Search, Heuristics
Presentation transcript:

Recursive Backtracking Eric Roberts CS 106B January 25, 2013

Solving a Maze A journey of a thousand miles begins with a single step. —Lao Tzu, 6 th century B.C.E. The example most often used to illustrate recursive backtracking is the problem of solving a maze, which has a long history in its own right. The most famous maze in history is the labyrinth of Daedalus in Greek mythology where Theseus slays the Minotaur. There are passing references to this story in Homer, but the best known account comes from Ovid in Metamorphoses.... When Minos, willing to conceal the shame That sprung from the reports of tatling Fame, Resolves a dark inclosure to provide, And, far from sight, the two-form’d creature hide. Great Daedalus of Athens was the man That made the draught, and form’d the wondrous plan; Where rooms within themselves encircled lye, With various windings, to deceive the eye.... Such was the work, so intricate the place, That scarce the workman all its turns cou’d trace; And Daedalus was puzzled how to find The secret ways of what himself design’d. These private walls the Minotaur include, Who twice was glutted with Athenian blood: But the third tribute more successful prov’d, Slew the foul monster, and the plague remov’d. When Theseus, aided by the virgin’s art, Had trac’d the guiding thread thro’ ev’ry part, He took the gentle maid, that set him free, And, bound for Dias, cut the briny sea. There, quickly cloy’d, ungrateful, and unkind, Left his fair consort in the isle behind... Metamorphoses —Ovid, 1 A.C.E.

The Right-Hand Rule   The most widely known strategy for solving a maze is called the right-hand rule, in which you put your right hand on the wall and keep it there until you find an exit. If Theseus applies the right-hand rule in this maze, the solution path looks like this. Unfortunately, the right-hand rule doesn’t work if there are loops in the maze that surround either the starting position or the goal. In this maze, the right-hand rule sends Theseus into an infinite loop. 

A Recursive View of Mazes  It is also possible to solve a maze recursively. Before you can do so, however, you have to find the right recursive insight. Consider the maze shown at the right. How can Theseus transform the problem into one of solving a simpler maze? The insight you need is that a maze is solvable only if it is possible to solve one of the simpler mazes that results from shifting the starting location to an adjacent square and taking the current square out of the maze completely.

A Recursive View of Mazes  Thus, the original maze is solvable only if one of the three mazes at the bottom of this slide is solvable. Each of these mazes is “simpler” because it contains fewer squares. The simple cases are: –Theseus is outside the maze –There are no directions left to try   

Enumerated Types in C++ It is often convenient to define new types in which the possible values are chosen from a small set of possibilities. Such types are called enumerated types. enum name { list of element names }; In C++, you define an enumerated type like this: The code for the maze program uses enum to define a new type consisting of the four compass points, as follows: enum Direction { NORTH, EAST, SOUTH, WEST }; You can then declare a variable of type Direction and use it along with the constants NORTH, EAST, SOUTH, and WEST.

/* * Class: Maze * * This class represents a two-dimensional maze contained in a rectangular * grid of squares. The maze is read in from a data file in which the * characters '+', '-', and '|' represent corners, horizontal walls, and * vertical walls, respectively; spaces represent open passageway squares. * The starting position is indicated by the character 'S'. For example, * the following data file defines a simple maze: * * * | | * * |S | | * */ class Maze { public: The Maze Class

/* * Class: Maze * * This class represents a two-dimensional maze contained in a rectangular * grid of squares. The maze is read in from a data file in which the * characters '+', '-', and '|' represent corners, horizontal walls, and * vertical walls, respectively; spaces represent open passageway squares. * The starting position is indicated by the character 'S'. For example, * the following data file defines a simple maze: * * * | | * * |S | | * */ class Maze { public: /* * Constructor: Maze * Usage: Maze maze(filename); * Maze maze(filename, gw); * * Constructs a new maze by reading the specified data file. If the * second argument is supplied, the maze is displayed in the center * of the graphics window. */ Maze(std::string filename); Maze(std::string filename, GWindow & gw); /* * Method: getStartPosition * Usage: Point start = maze.getStartPosition(); * * Returns a Point indicating the coordinates of the start square. */ Point getStartPosition(); The Maze Class

/* * Constructor: Maze * Usage: Maze maze(filename); * Maze maze(filename, gw); * * Constructs a new maze by reading the specified data file. If the * second argument is supplied, the maze is displayed in the center * of the graphics window. */ Maze(std::string filename); Maze(std::string filename, GWindow & gw); /* * Method: getStartPosition * Usage: Point start = maze.getStartPosition(); * * Returns a Point indicating the coordinates of the start square. */ Point getStartPosition(); /* * Method: isOutside * Usage: if (maze.isOutside(pt))... * * Returns true if the specified point is outside the boundary of the maze. */ bool isOutside(Point pt); /* * Method: wallExists * Usage: if (maze.wallExists(pt, dir))... * * Returns true if there is a wall in direction dir from the square at pt. */ bool wallExists(Point pt, Direction dir); /* * Method: markSquare * Usage: maze.markSquare(pt); * * Marks the specified square in the maze. */ void markSquare(Point pt); The Maze Class

/* * Method: isOutside * Usage: if (maze.isOutside(pt))... * * Returns true if the specified point is outside the boundary of the maze. */ bool isOutside(Point pt); /* * Method: wallExists * Usage: if (maze.wallExists(pt, dir))... * * Returns true if there is a wall in direction dir from the square at pt. */ bool wallExists(Point pt, Direction dir); /* * Method: markSquare * Usage: maze.markSquare(pt); * * Marks the specified square in the maze. */ void markSquare(Point pt); /* * Method: unmarkSquare * Usage: maze.unmarkSquare(pt); * * Unmarks the specified square in the maze. */ void unmarkSquare(Point pt); /* * Method: isMarked * Usage: if (maze.isMarked(pt))... * * Returns true if the specified square is marked. */ bool isMarked(Point pt); /* Private section goes here */ }; The Maze Class

/* * Function: solveMaze * Usage: solveMaze(maze, start); * * Attempts to generate a solution to the current maze from the specified * start point. The solveMaze function returns true if the maze has a * solution and false otherwise. The implementation uses recursion * to solve the submazes that result from marking the current square * and moving one step along each open passage. */ bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, adjacentPoint(start, dir))) { return true; } maze.unmarkSquare(start); return false; } The solveMaze Function

Tracing the solveMaze Function x   bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dir NORTHEASTSOUTH x xx x  xxx xx x x x x xx x xx xxxx x x x x x x x xx xxx  Don’t follow the recursion more than one level. Depend on the recursive leap of faith. dir start (3, 3) NORTHEASTSOUTH bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (3, 2) bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (3, 4)

Reflections on the Maze Problem The solveMaze program is a useful example of how to search all paths that stem from a branching series of choices. At each square, the solveMaze program calls itself recursively to find a solution from one step further along the path. To give yourself a better sense of why recursion is important in this problem, think for a minute or two about what it buys you and why it would be difficult to solve this problem iteratively. In particular, how would you answer the following questions: –What information does the algorithm need to remember as it proceeds with the solution, particularly about the options it has already tried? –In the recursive solution, where is this information kept? –How might you keep track of this information otherwise?

Consider a Specific Example How does the algorithm keep track of the “big picture” of what paths it still needs to explore? Suppose that the program has reached the following position: x x x x x 

Each Frame Remembers One Choice bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (3, 3) SOUTH x  bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (3, 4) EAST x x  bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (4, 4) EAST x xx  bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (3) NORTH x xx x  bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (5, 3) WEST x xxx x  bool solveMaze(Maze & maze, Point start) { if (maze.isOutside(start)) return true; if (maze.isMarked(start)) return false; maze.markSquare(start); for (Direction dir = NORTH; dir <= WEST; dir++) { if (!maze.wallExists(start, dir)) { if (solveMaze(maze, AdjPt(start, dir))) { return true; } maze.unmarkSquare(start); return false; } dirstart (4, 3) x x  x x x

Recursion and Concurrency 1 The recursive decomposition of a maze generates a series of independent submazes; the goal is to solve any one of them. If you had a multiprocessor computer, you could try to solve each of these submazes in parallel. This strategy is analogous to cloning yourself at each intersection and sending one clone down each path. Is this parallel strategy more efficient? 

The P = NP Question The question of whether a parallel solution is fundamentally faster than a sequential one is related to the biggest open problem in computer science, for which there is a $1M prize.

Exercise: Keeping Track of the Path As described in exercise 3 on page 418, it is possible to build a better version of solveMaze so that it keeps track of the solution path as the computation proceeds. Write a new function bool findSolutionPath(Maze & maze, Point start, Vector & path); that records the solution path in a vector of Point values passed as a reference parameter. The findSolutionPath function should return a Boolean value indicating whether the maze is solvable, just as solveMaze does.

The End