28
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

Dave Reed AI as search problem states, state spaces uninformed search strategies depth first search depth first search with cycle checking breadth

  • View
    215

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Dave Reed

AI as search problem states, state spaces uninformed search strategies

depth first searchdepth first search with cycle checkingbreadth first search iterative deepening

Page 2: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

AI as searchAI as searchGOFAI philosophy:

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

to build a system to solve a problem:1. define the problem precisely

i.e., describe initial situation, goals, …2. analyze the problem3. isolate and represent task knowledge4. 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

Page 3: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: airline connectionsExample: airline connectionssuppose 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 AngelesOmaha Denver Denver OmahaChicago Denver Los Angeles ChicagoChicago Los Angeles Los Angeles DenverChicago 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).

Page 4: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

State spacesState spacesor, could define a more general solution framework

state : a situation or position

state space : the set of legal/attainable states for a given problema state space can be represented as a directed graph (nodes =

states)

omaha

denver

chicago

los_angeles

in general: to solve a problem define a state space, then search for a path from start state to a goal state

Page 5: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: airline state spaceExample: airline state spacedefine 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)).

Page 6: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: water jug problemExample: water jug problemSuppose 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?

Page 7: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: water jug state spaceExample: water jug state space%%% 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.

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)

Page 8: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: 8-tiles puzzleExample: 8-tiles puzzleConsider 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

1 2 3

8 6

7 5 4

1 2 3

8 6 4

7 5

state?

• start state?

• goal state?

transitions?

1 2 3

8 6 4

7 5

1 2 3

8 4

7 6 5

Page 9: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Example: 8-tiles state spaceExample: 8-tiles state space%%% 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]))....

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])

Page 10: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

State space + controlState space + controlonce 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

Page 11: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Uninformed strategiesUninformed strategiesbold + uninformed:

STUPID!

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

jugs(0,0)

jugs(4,0) jugs(0,3)

jugs(0,0)jugs(4,3) jugs(1,3) jugs(0,0)jugs(4,3) jugs(3,0)

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

Page 12: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Depth first searchDepth first searchbasic 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

Page 13: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Depth first searchDepth first searchgenerally, 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)

Page 14: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

DFS examplesDFS 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

?- dfs(jugs(0,0), jugs(2,0), Path).ERROR: Out of local stack

?- 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

all are legitimate paths, but not "optimal"

WHY?

WHY?

Page 15: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

DFS and cyclesDFS and cyclessince DFS moves blindly down one path,

looping (cycles) is a SERIOUS problem

jugs(0,0)

jugs(4,0) jugs(0,3)

jugs(0,3) jugs(4,0) jugs(4,3) jugs(4,3)

jugs(0,0)jugs(4,3) jugs(1,3)

jugs(0,0)jugs(4,3) jugs(3,0)

Page 16: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Depth first search with cycle checkingDepth 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).

Page 17: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Examples w/ cycle checkingExamples 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

?- 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

?- 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

finds all paths that don’t have cycles

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

but it takes longer…

Page 18: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Breadth vs. depthBreadth vs. deptheven 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 ]

[ chicagoomaha, denveromaha ]

[ denveromaha, denverchicagoomaha, los_angeleschicagoomaha, omahachicagoomaha ]

[ denverchicagoomaha, los_angeleschicagoomaha, omahachicagoomaha, los_angelesdenveromaha, omahadenveromaha ]

[ los_angeleschicagoomaha, omahachicagoomaha, los_angelesdenveromaha, omahadenveromaha, los_angelesdenverchicagoomaha, omahadenverchicagoomaha ]

Page 19: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Breadth first searchBreadth 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

Page 20: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

BFS examplesBFS 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

?- 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

?- 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 shorter paths first, but no loop checking

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

it works!

Page 21: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Breadth first search w/ cycle checkingBreadth 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

Page 22: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Examples w/ cycle checkingExamples 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

?- 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

?- 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 all paths without cycles, shorter paths first

finds 14 unique paths, shorter paths first

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

Page 23: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

DFS vs. BFSDFS vs. BFSAdvantages 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!

Page 24: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Iterative deepeningIterative deepeninginteresting 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 foundDFS with bound = 1DFS with bound = 2DFS 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!

Page 25: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Depth first search with iterative deepeningDepth 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

Page 26: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

DFS w/ iterative deepening & cycle checkingDFS 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

Page 27: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Examples w/ cycle checkingExamples 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)] ;

?- 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

?- 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, but hangs after last answer -- WHY?

finds same answers as BFS, but similarly hangs

finds same answers as BFS, noticeably faster

Page 28: Dave Reed AI as search  problem states, state spaces  uninformed search strategies  depth first search  depth first search with cycle checking  breadth

Cost of iterative deepeningCost of iterative deepeningjust 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)