slide1 l.
Download
Skip this Video
Loading SlideShow in 5 Seconds..
Dave Reed PowerPoint Presentation
Download Presentation
Dave Reed

Loading in 2 Seconds...

play fullscreen
1 / 28

Dave Reed - PowerPoint PPT Presentation


  • 88 Views
  • Uploaded on

Dave Reed. AI as search problem states, state spaces uninformed search strategies depth first search depth first search with cycle checking breadth first search iterative deepening. AI as search. GOFAI philosophy: Problem Solving = Knowledge Representation + Search (a.k.a. deduction)

loader
I am the owner, or an agent authorized to act on behalf of the owner, of the copyrighted work described.
capcha
Download Presentation

PowerPoint Slideshow about 'Dave Reed' - florence


An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -
Presentation Transcript
slide1

Dave Reed

  • AI as search
    • problem states, state spaces
    • uninformed search strategies
      • depth first search
      • depth first search with cycle checking
      • breadth first search
      • iterative deepening
ai as search
AI as search
  • GOFAI philosophy:

Problem Solving = Knowledge Representation + Search (a.k.a. deduction)

  • to build a system to solve a problem:
    • define the problem precisely

i.e., describe initial situation, goals, …

    • analyze the problem
    • isolate and represent task knowledge
    • choose an appropriate problem solving technique

we'll look at a simple representation (states) first & focus on search

more advanced representation techniques will be explored later

example airline connections
Example: airline connections
  • suppose you are planning a trip from Omaha to Los Angeles

initial situation: located in Omaha

goal: located in Los Angeles

possible flights: Omaha  Chicago Denver  Los Angeles

Omaha  Denver Denver  Omaha

Chicago  Denver Los Angeles  Chicago

Chicago  Los Angeles Los Angeles  Denver

Chicago  Omaha

  • this is essentially the same problem as the earlier city connections
    • we could define special purpose predicates, recursive rules to plan route

flight(omaha, chicago). flight(denver, los_angeles).

. . .

route(City1, City2, [City1,City2]) :-

flight(City1, City2).

route(City1, City2, [City1|Rest]) :-

flight(City1, City3), route(City3, City2, Rest).

state spaces
State spaces
  • or, could define a more general solution framework

state : a situation or position

state space : the set of legal/attainable states for a given problem

      • a state space can be represented as a directed graph (nodes = states)
  • in general: to solve a problem
    • define a state space, then search for a path from start state to a goal state
example airline state space
Example: airline state space
  • define a state with:

loc(City)

  • define state transitions with:

move(loc(City1), loc(City2))

  • to find a route from Omaha to Los Angeles:
    • search for a sequence of transitions from start state to goal state:

loc(omaha)  loc(los_angeles)

%%% travel.pro Dave Reed 2/15/02

%%%

%%% This file contains the state space definition

%%% for air travel.

%%%

%%% loc(City): defines the state where the person

%%% is in the specified City.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

move(loc(omaha), loc(chicago)).

move(loc(omaha), loc(denver)).

move(loc(chicago), loc(denver)).

move(loc(chicago), loc(los_angeles)).

move(loc(chicago), loc(omaha)).

move(loc(denver), loc(los_angeles)).

move(loc(denver), loc(omaha)).

move(loc(los_angeles), loc(chicago)).

move(loc(los_angeles), loc(denver)).

example water jug problem
Example: water jug problem
  • Suppose you have two empty water jugs:
    • large jug can hold 4 gallons, small jug can hold 3 gallons
  • starting with empty jugs (and an endless supply of water),

want to end up with exactly 2 gallons in the large jug

  • state?
    • start state?
    • goal state?
  • transitions?
example water jug state space
Example: water jug state space
  • define a state with:

jugs(LargeJug, SmallJug)

  • define state transitions with:

move(jugs(J1,J2), jugs(J3,J4))

  • to solve the problem:
    • search for a sequence of transitions from start state to goal state:

jugs(0,0)  jugs(2,0)

%%% jugs.pro Dave Reed 2/15/02

%%%

%%% This file contains the state space definition

%%% for the Water Jug problem.

%%%

%%% jugs(J1, J2): J1 is the contents of the large

%%% (4 gallon) jug, and J2 is the contents of

%%% the small (3 gallon) jug.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

move(jugs(J1,J2), jugs(4,J2)) :-

J1 < 4.

move(jugs(J1,J2), jugs(J1,3)) :-

J2 < 3.

move(jugs(J1,J2), jugs(0,J2)) :-

J1 > 0.

move(jugs(J1,J2), jugs(J1,0)) :-

J2 > 0.

move(jugs(J1,J2), jugs(4,N)) :-

J2 > 0, J1 + J2 >= 4, N is J2 - (4 - J1).

move(jugs(J1,J2), jugs(N,3)) :-

J1 > 0, J1 + J2 >= 3, N is J1 - (3 - J2).

move(jugs(J1,J2), jugs(N,0)) :-

J2 > 0, J1 + J2 < 4, N is J1 + J2.

move(jugs(J1,J2), jugs(0,N)) :-

J1 > 0, J1 + J2 < 3, N is J1 + J2.

example 8 tiles puzzle
Example: 8-tiles puzzle
  • Consider the children's puzzle with 8 sliding tiles in a 3x3 board
    • a tile adjacent to the empty space can be shifted into that space
    • goal is to arrange the tiles in increasing order around the outside
  • state?
    • start state?
    • goal state?
  • transitions?
example 8 tiles state space
Example: 8-tiles state space
  • define a state with:

tiles(Row1,Row2,Row3)

  • define state transitions with:

move(tiles(R1,R2,R3),

tiles(R4,R5,R6)).

  • to solve the problem:
    • search for a sequence of transitions from start state to goal state:

tiles([1,2,3],[8,6,space],[7,5,4]) 

tiles([1,2,3],[8,space,4],[7,6,5])

%%% puzzle.pro Dave Reed 2/15/02

%%%

%%% This file contains an UGLY, BRUTE-FORCE state %%% space definition for the 8-puzzle problem.

%%%

%%% tiles(R1, R2, R3): each row is a list of three

%%% numbers (or space) specifying the tiles in

%%% that row.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

move(tiles([space,T1,T2],[T3,T4,T5],[T6,T7,T8]),

tiles([T1,space,T2],[T3,T4,T5],[T6,T7,T8])).

move(tiles([space,T1,T2],[T3,T4,T5],[T6,T7,T8]),

tiles([T3,T1,T2],[space,T4,T5],[T6,T7,T8])).

move(tiles([T1,space,T2],[T3,T4,T5],[T6,T7,T8]),

tiles([space,T1,T2],[T3,T4,T5],[T6,T7,T8])).

move(tiles([T1,space,T2],[T3,T4,T5],[T6,T7,T8]),

tiles([T1,T2,space],[T3,T4,T5],[T6,T7,T8])).

move(tiles([T1,space,T2],[T3,T4,T5],[T6,T7,T8]),

tiles([T1,T4,T2],[T3,space,T5],[T6,T7,T8])).

move(tiles([T1,T2,space],[T3,T4,T5],[T6,T7,T8]),

tiles([T1,space,T2],[T3,T4,T5],[T6,T7,T8])).

move(tiles([T1,T2,space],[T3,T4,T5],[T6,T7,T8]),

tiles([T1,T2,T5],[T3,T4,space],[T6,T7,T8])).

.

.

.

state space control
State space + control
  • once you formalize a problem by defining a state space:
    • you need a methodology for applying actions/transitions to search through the space (from start state to goal state)

i.e., you need a control strategy

  • control strategies can be: tentative or bold; informed or uninformed
    • a bold strategy picks an action/transition, does it, and commits
    • a tentative strategy burns no bridges
    • an informed strategy makes use of problem-specific knowledge (heuristics) to guide the search
    • an uninformed strategy is blind
uninformed strategies
Uninformed strategies
  • bold + uninformed:

STUPID!

  • tentative + uninformed:
    • depth first search (DFS)
    • breadth first search (BFS)

example: water jugs state space (drawn as a tree with duplicate nodes)

depth first search
Depth first search
  • basic idea:
    • if the current state is a goal, then SUCCEED
    • otherwise, move to a next state and DFS from there
    • if no next state (i.e., deadend), then BACKTRACK

%%% dfs.pro Dave Reed 2/15/02

%%%

%%% Depth first search

%%% dfs(Current, Goal): succeeds if there is

%%% a sequence of states that lead from

%%% Current to Goal

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dfs(Goal, Goal).

dfs(State, Goal) :-

move(State, NextState),

dfs(NextState, Goal).

  • note: Prolog computation is basically depth first search
    • if goal list is empty, SUCCEED
    • otherwise, find fact/rule that matches the first goal & replace the goal with the rule premises (if any)
    • if no matching fact/rule, then BACKTRACK
depth first search13
Depth first search
  • generally, want to not only know that a path exists, but what states are in that path
    • i.e., what actions lead from start state to goal state?

%%% dfs.pro Dave Reed 2/15/02

%%%

%%% Depth first search

%%% dfs(Current, Goal, Path): Path is a list

%%% of states that lead from Current to Goal

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dfs(Goal, Goal, [Goal]).

dfs(State, Goal, [State|Path]) :-

move(State, NextState),

dfs(NextState, Goal, Path).

  • add an argument to the dfs predicate, which "returns" the path
    • if current state is a goal, then path is just that state
    • otherwise, make a move and use recursion to find a path from that new state (but must add that state back onto path)
dfs examples
DFS examples

?- dfs(loc(omaha), loc(los_angeles), Path).

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles), loc(chicago), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles), loc(chicago), loc(denver), loc(los_angeles), loc(chicago), loc(...)|...]

Yes

all are legitimate paths, but not "optimal"

?- dfs(jugs(0,0), jugs(2,0), Path).

ERROR: Out of local stack

WHY?

?- dfs(tiles([1,2,3],[8,6,space],[7,5,4]), tiles([1,2,3],[8,space,4],[7,6,5]), Path).

ERROR: Out of local stack

WHY?

dfs and cycles
DFS and cycles
  • since DFS moves blindly down one path,
  • looping (cycles) is a SERIOUS problem
depth first search with cycle checking
Depth first search with cycle checking
  • it often pays to test for cycles (as in city connections example):
    • must keep track of the path so far
    • make sure current goal is not revisited

%%% dfsnocyc.pro Dave Reed 2/15/02

%%%

%%% Depth first search with cycle checking

%%% dfs_no_cycles(Current, Goal, Path): Path is a list

%%% of states that lead from Current to Goal

%%%

%%% dfs_nocyc_help(PathSoFar, Goal, Path): Path is a list

%%% of states that lead from the PathSoFar (with current

%%% state at the head) to Goal without duplicate states.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dfs_no_cycles(State, Goal, Path) :-

dfs_nocyc_help([State], Goal, RevPath),

reverse(RevPath, Path).

dfs_nocyc_help([Goal|PathSoFar], Goal, [Goal|PathSoFar]).

dfs_nocyc_help([State|PathSoFar], Goal, Path) :-

move(State, NextState),

not(member(NextState, [State|PathSoFar])),

dfs_nocyc_help([NextState,State|PathSoFar], Goal, Path).

examples w cycle checking
Examples w/ cycle checking

?- dfs_no_cycles(loc(omaha), loc(los_angeles), Path).

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(los_angeles)] ;

Path = [loc(omaha), loc(denver), loc(los_angeles)] ;

No

finds all paths that don’t have cycles

?- dfs_no_cycles(jugs(0,0), jugs(2,0), Path).

Path = [jugs(0, 0), jugs(4, 0), jugs(4, 3), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(..., ...)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(1, 3), jugs(4, 3), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(..., ...)|...]

Yes

finds solutions, but not optimal (SWI uses … for long answers)

?- dfs(tiles([1,2,3],[8,6,space],[7,5,4]), tiles([1,2,3],[8,space,4],[7,6,5]), Path).

ERROR: Out of local stack

but it takes longer…

breadth vs depth
Breadth vs. depth
  • even with cycle checking, DFS may not find the shortest solution
  • breadth first search (BFS)
    • extend the search one level at a time
      • i.e., from the start state, try every possible move (& remember them all)
      • if don't reach goal, then try every possible move from those states
      • . . .
    • requires keeping a list of partially expanded search paths
    • ensure breadth by treating the list as a queue
      • when want to expand shortest path: take off front, extend & add to back

[ omaha ]

[ chicagoomaha, denveromaha ]

[ denveromaha, denverchicagoomaha, los_angeleschicagoomaha, omahachicagoomaha ]

[ denverchicagoomaha, los_angeleschicagoomaha, omahachicagoomaha, los_angelesdenveromaha, omahadenveromaha ]

[ los_angeleschicagoomaha, omahachicagoomaha, los_angelesdenveromaha, omahadenveromaha, los_angelesdenverchicagoomaha, omahadenverchicagoomaha ]

breadth first search
Breadth first search

%%% bfs.pro Dave Reed 2/15/02

%%%

%%% Breadth first search

%%% bfs(Current, Goal, Path): Path is a list

%%% of states that lead from Current to Goal

%%%

%%% bfs_help(ListOfPaths, Goal, Path): Path is a list

%%% of states that lead from one of the paths in ListOfPaths

%%% (a list of lists) to Goal.

%%%

%%% extend(Path, ListOfPaths): ListOfPaths is the list of all

%%% possible paths obtainable by extending Path (at the head).

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bfs(State, Goal, Path) :-

bfs_help([[State]], Goal, RevPath),

reverse(RevPath, Path).

bfs_help([[Goal|Path]|_], Goal, [Goal|Path]).

bfs_help([Path|RestPaths], Goal, SolnPath) :-

extend(Path, NewPaths),

append(RestPaths, NewPaths, TotalPaths),

bfs_help(TotalPaths, Goal, SolnPath).

extend([State|Path], NewPaths) :-

bagof([NextState,State|Path], move(State,NextState), NewPaths), !.

extend(_, []).

  • bagof(X,p(X),List):
    • List is a list of all X's for which p(X) holds
    • equivalent to hitting ';' repeatedly to exhaust all answers, then putting them in a list
  • !
    • exclamation point is the cut operator
    • it cuts choice points, committing the interpreter to that match
bfs examples
BFS examples

?- bfs(loc(omaha), loc(los_angeles), Path).

Path = [loc(omaha), loc(chicago), loc(los_angeles)] ;

Path = [loc(omaha), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(los_angeles), loc(chicago), loc(los_angeles)]

Yes

finds shorter paths first, but no loop checking

?- bfs(jugs(0,0), jugs(2,0), Path).

Path = [jugs(0, 0), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(1, 3), jugs(1, 0), jugs(0, 1), jugs(4, 1), jugs(2, 3), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(4, 2), jugs(0, 2), jugs(2, 0)]

Yes

finds shorter paths first, but slow (& looping is possible)

?- bfs(tiles([1,2,3],[8,6,space],[7,5,4]), tiles([1,2,3],[8,space,4],[7,6,5]), Path).

Path = [tiles([1, 2, 3], [8, 6, space], [7, 5, 4]), tiles([1, 2, 3], [8, 6, 4], [7, 5, space]), tiles([1, 2, 3], [8, 6, 4], [7, space, 5]), tiles([1, 2, 3], [8, space, 4], [7, 6, 5])]

Yes

it works!

breadth first search w cycle checking
Breadth first search w/ cycle checking

%%% bfs.pro Dave Reed 2/15/02

%%% Breadth first search with cycle checking

%%% bfs(Current, Goal, Path): Path is a list of states

%%% that lead from Current to Goal with no duplicate states.

%%%

%%% bfs_help(ListOfPaths, Goal, Path): Path is a list

%%% of states that lead from one of the paths in ListOfPaths

%%% (a list of lists) to Goal with no duplicate states.

%%%

%%% extend(Path, ListOfPaths): ListOfPaths is the list of all

%%% possible paths obtainable by extending Path (at the head)

%%% with no duplicate states.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

bfs(State, Goal, Path) :-

bfs_help([[State]], Goal, RevPath), reverse(RevPath, Path).

bfs_help([[Goal|Path]|_], Goal, [Goal|Path]).

bfs_help([Path|RestPaths], Goal, SolnPath) :-

extend(Path, NewPaths),

append(RestPaths, NewPaths, TotalPaths),

bfs_help(TotalPaths, Goal, SolnPath).

extend([State|Path], NewPaths) :-

bagof([NextState,State|Path],

(move(State, NextState), not(member(NextState, [State|Path]))),

NewPaths), !.

extend(_, []).

since you are already having to store entire paths for BFS, cycle checking is easy

when extending, exclude states already on the path

examples w cycle checking22
Examples w/ cycle checking

?- bfs(loc(omaha), loc(los_angeles), Path).

Path = [loc(omaha), loc(chicago), loc(los_angeles)] ;

Path = [loc(omaha), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles)] ;

No

finds all paths without cycles, shorter paths first

?- bfs(jugs(0,0), jugs(2,0), Path).

Path = [jugs(0, 0), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(1, 3), jugs(1, 0), jugs(0, 1), jugs(4, 1), jugs(2, 3), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(4, 3), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(..., ...)]

Yes

finds 14 unique paths, shorter paths first

?- bfs(tiles([1,2,3],[8,6,space],[7,5,4]), tiles([1,2,3],[8,space,4],[7,6,5]), Path).

Path = [tiles([1, 2, 3], [8, 6, space], [7, 5, 4]), tiles([1, 2, 3], [8, 6, 4], [7, 5, space]), tiles([1, 2, 3], [8, 6, 4], [7, space, 5]), tiles([1, 2, 3], [8, space, 4], [7, 6, 5])]

Yes

same as before (by definition, shortest path will not have cycle)

dfs vs bfs
DFS vs. BFS
  • Advantages of DFS
    • requires less memory than BFS since only need to remember the current path
    • if lucky, can find a solution without examining much of the state space
    • with cycle-checking, looping can be avoided
  • Advantages of BFS
    • guaranteed to find a solution if one exists – in addition, finds optimal (shortest) solution first
    • will not get lost in a blind alley (i.e., does not require backtracking or cycle checking)
    • can add cycle checking with very little cost

note: just because BFS finds the optimal solution, it does not necessarily mean that it is the optimal control strategy!

iterative deepening
Iterative deepening
  • interesting hybrid: DFS with iterative deepening
    • alter DFS to have a depth bound
      • (i.e., search will fail if it extends beyond a specific depth bound)
    • repeatedly call DFS with increasing depth bounds until a solution is found
      • DFS with bound = 1
      • DFS with bound = 2
      • DFS with bound = 3
      • . . .
  • advantages:
    • yields the same solutions, in the same order, as BFS
    • doesn't have the extensive memory requirements of BFS
  • disadvantage:
    • lots of redundant search – each time the bound is increased, the entire search from the previous bound is redone!
depth first search with iterative deepening
Depth first search with iterative deepening

%%% dfsdeep.pro Dave Reed 2/15/02

%%% Depth first search with iterative deepening

%%% dfs_deep(Current, Goal, Path): Path is a list of states

%%% that lead from Current to Goal.

%%%

%%% dfs_deep_help(State, Goal, Path, DepthBound): Path is a

%%% list of states (length = DepthBound) that lead from

%%% State to Goal. THIS PREDICATE PERFORMS THE ITERATIVE

%%% DEEPENING BY INCREASING THE DEPTH BOUND BY 1 EACH TIME.

%%%

%%% dfs_bounded(State, Goal, Path, DepthBound): Path is a

%%% list of states (length = DepthBound) that lead from

%%% State to Goal. THIS PREDICATE PERFORMS THE BOUNDED DFS,

%%% REQUIRING A SOLUTION THAT IS EXACTLY DepthBound LONG.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dfs_deep(State, Goal, Path) :-

dfs_deep_help(State, Goal, Path, 1).

dfs_deep_help(State, Goal, Path, DepthBound) :-

dfs_bounded(State, Goal, Path, DepthBound).

dfs_deep_help(State, Goal, Path, DepthBound) :-

NewDepth is DepthBound + 1,

dfs_deep_help(State, Goal, Path, NewDepth).

dfs_bounded(Goal, Goal, [Goal], 1).

dfs_bounded(State, Goal, [State|Path], DepthBound) :-

DepthBound > 0,

move(State, NextState),

NewDepth is DepthBound - 1,

dfs_bounded(NextState, Goal, Path, NewDepth).

can even set up the bounds checking so that answers are not revisited on each pass – only report answer first time it is found

dfs w iterative deepening cycle checking
DFS w/ iterative deepening & cycle checking

%%% dfsdeep.pro Dave Reed 2/15/02

%%% Depth first search with iterative deepening & cycle checking

%%% dfs_deep(Current, Goal, Path): Path is a list of states

%%% that lead from Current to Goal, with no duplicate states.

%%%

%%% dfs_deep_help(State, Goal, Path, DepthBound): Path is a

%%% list of states (length = DepthBound) that lead from

%%% State to Goal, with no duplicate states. THIS PREDICATE

%%% PERFORMS THE ITERATIVE DEEPENING BY INCREASING THE DEPTH

%%% BOUND BY 1 EACH TIME.

%%%

%%% dfs_bounded(State, Goal, Path, DepthBound): Path is a

%%% list of states (length = DepthBound) that lead from

%%% State to Goal with no duplicate states. THIS PREDICATE

%%% PERFORMS THE BOUNDED DFS, REQUIRING A SOLUTION THAT IS

%%% EXACTLY DepthBound LONG.

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

dfs_no_cycles_deep(State, Goal, Path) :-

dfs_deep_help([State], Goal, RevPath, 1), reverse(RevPath, Path).

dfs_deep_help(PathSoFar, Goal, Path, DepthBound) :-

dfs_bounded(PathSoFar, Goal, Path, DepthBound).

dfs_deep_help(PathSoFar, Goal, Path, DepthBound) :-

NewDepth is DepthBound + 1,

dfs_deep_help(PathSoFar, Goal, Path, NewDepth).

dfs_bounded([Goal|PathSoFar], Goal, [Goal|PathSoFar], 1).

dfs_bounded([State|PathSoFar], Goal, Path, DepthBound) :-

DepthBound > 0,

move(State, NextState), not(member(NextState, [State|PathSoFar])) ,

NewDepth is DepthBound - 1,

dfs_bounded([NextState,State|PathSoFar], Goal, Path, NewDepth).

as with DFS, can add cycle checking by storing the current path and checking for duplicate states

examples w cycle checking27
Examples w/ cycle checking

?- dfs_no_cycles_deep(loc(omaha), loc(los_angeles), Path).

Path = [loc(omaha), loc(chicago), loc(los_angeles)] ;

Path = [loc(omaha), loc(denver), loc(los_angeles)] ;

Path = [loc(omaha), loc(chicago), loc(denver), loc(los_angeles)] ;

finds same answers as BFS, but hangs after last answer -- WHY?

?- dfs_no_cycles_deep(jugs(0,0), jugs(2,0), Path).

Path = [jugs(0, 0), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(1, 3), jugs(1, 0), jugs(0, 1), jugs(4, 1), jugs(2, 3), jugs(2, 0)] ;

Path = [jugs(0, 0), jugs(4, 0), jugs(4, 3), jugs(0, 3), jugs(3, 0), jugs(3, 3), jugs(4, 2), jugs(0, 2), jugs(..., ...)]

Yes

finds same answers as BFS, but similarly hangs

?- bfs(tiles([1,2,3],[8,6,space],[7,5,4]), tiles([1,2,3],[8,space,4],[7,6,5]), Path).

Path = [tiles([1, 2, 3], [8, 6, space], [7, 5, 4]), tiles([1, 2, 3], [8, 6, 4], [7, 5, space]), tiles([1, 2, 3], [8, 6, 4], [7, space, 5]), tiles([1, 2, 3], [8, space, 4], [7, 6, 5])]

Yes

finds same answers as BFS, noticeably faster

cost of iterative deepening
Cost of iterative deepening
  • just how costly is iterative deepening?

1st pass searches entire tree up to depth 1

2nd pass searches entire tree up to depth 2 (including depth 1)

3rd pass searches entire tree up to depth 3 (including depths 1 & 2)

  • in reality, this duplication is not very costly at all!
    • Theorem: Given a "full" tree with constant branching factor B, the number of nodes at any given level is greater than the number of nodes in all levels above.
      • e.g., Binary tree (B = 2): 1  2  4  8  16  32  64  128  …
    • repeating the search of all levels above for each pass merely doubles the amount of work for each pass.
    • in general, this repetition only increases the cost by a constant factor < (B+1)/(B-1)