Top Banner
1 Search Problems (read Chapters 3 and 4 of Russell and Norvig) Many (perhaps most) AI problems can be considered search problems. This can be modeled on geographical search. Start with a list of actions that can be taken at various geographical points on the map and their consequences, formulated as conditionals of the form ((precondition & action) -> result) (proclaim '(special *planning-conditionals*)) (defun pcond (precondition action) (list '-> (list '& precondition (concatenate 'string "go to " action)) action))
57

Search Problems

Jan 22, 2016

Download

Documents

viho

Search Problems. (read Chapters 3 and 4 of Russell and Norvig) Many (perhaps most) AI problems can be considered search problems. This can be modeled on geographical search. - PowerPoint PPT Presentation
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Search Problems

1

Search Problems

(read Chapters 3 and 4 of Russell and Norvig)

• Many (perhaps most) AI problems can be considered search problems.

• This can be modeled on geographical search.

• Start with a list of actions that can be taken at various geographical points on the map and their consequences, formulated as conditionals of the form

((precondition & action) -> result)

(proclaim '(special *planning-conditionals*))

(defun pcond (precondition action)

(list '-> (list '&

precondition

(concatenate 'string "go to " action))

action))

Page 2: Search Problems

2

Search Problems

(defun precond (condit) (second (second condit)))

(defun action (condit) (third (second condit)))

(defun result (condit) (third condit))

Page 3: Search Problems

3

Road Map of Romania

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Page 4: Search Problems

4

Find Bucharest

(setf *planning-conditionals*

(list

(pcond "Oradea" "Zerind")

(pcond "Oradea" "Sibiu")

(pcond "Arad" "Sibiu")

(pcond "Sibiu" ”Fagaras")

(pcond "Arad" "Timisoara")

(pcond "Timisoara" "Lugoj")

(pcond "Lugoj" "Mehadia")

(pcond "Mehadia" "Craiova")

(pcond "Craiova" "Rimnicu Vilcea")

(pcond "Rimnicu Vilcea" "Sibiu")

(pcond "Rimnicu Vilcea" "Pitesti")

(pcond "Pitesti" "Bucharest")

(pcond ”Fagaras" "Bucharest")

... ))

Page 5: Search Problems

5

Find Bucharest• Given a starting point, a route to Bucharest will consist of a list of actions which, if

performed in order, will end with our being in Bucharest.

• Routes can be characterized recursively:

• If there is a conditional ((town1 & action) -> town2) in *planning-conditionals* then (list action) is a route from town1 to town2.

• If there is a conditional ((town1 & action) -> town) in *planning-conditionals* and route is a route from town to town2, then (cons action route) is a route from town1 to town2.

Page 6: Search Problems

6

Find Bucharest• If we allow loops, there are infinitely many routes, so let us preclude loops.

• Non-circular routes that do not reuse actions in a list used-actions of actions can be characterized recursively:

• If there is a conditional ((town1 & action) -> town2) in *planning-conditionals* and action is not a member of used-actions, then (list action) is a non-circular route from town1 to town2.

• If there is a conditional ((town1 & action) -> town) in *planning-conditionals* and route is a non-circular route from town to town2 that does not reuse any members of (cons action used-actions) , then (cons action route) is a non-circular route from town1 to town2.

• A non-circular route from town1 to town2 is a non-circular route that does not reuse “go to town1”.

A B

C

D

E F

Page 7: Search Problems

7

Find Bucharest• To avoid circularity, we must keep track of the actions already tried and not try them

again. We also want to avoid going back through the starting point.

(defun find-routes-from (town1 town2 &optional used-actions)

(when (null used-actions) (setf used-actions (list (concatenate 'string "go to " town1))))

(let ((routes nil))

(dolist (condit *planning-conditionals*)

(when

(and (equal (precond condit) town1)

(not (mem (action condit) used-actions)))

(cond

((equal (result condit) town2) (push (list (action condit)) routes))

(t

(let ((subroutes

(find-routes-from (result condit) town2 (cons (action condit) used-actions))))

(dolist (subroute subroutes) (push (cons (action condit) subroute) routes)))))))

routes))

Page 8: Search Problems

8

Find Bucharest

(find-routes-from "Lugoj" "Bucharest")

(("go to Timisoara" "go to Arad" "go to Sibiu" "go to Fagaras" "go to Bucharest")

("go to Timisoara" "go to Arad" "go to Sibiu" "go to Rimnicu Vilcea" "go to Craiova" "go to Pitesti" "go to Bucharest")

("go to Timisoara" "go to Arad" "go to Sibiu" "go to Rimnicu Vilcea" "go to Pitesti" "go to Bucharest")

("go to Timisoara" "go to Arad" "go to Zerind" "go to Oradea" "go to Sibiu" "go to Fagaras" "go to Bucharest")

("go to Timisoara" "go to Arad" "go to Zerind" "go to Oradea" "go to Sibiu" "go to Rimnicu Vilcea" "go to Craiova" "go to Pitesti"

"go to Bucharest")

("go to Timisoara" "go to Arad" "go to Zerind" "go to Oradea" "go to Sibiu" "go to Rimnicu Vilcea" "go to Pitesti" "go to Bucharest")

("go to Mehadia" "go to Dobreta" "go to Craiova" "go to Rimnicu Vilcea" "go to Pitesti" "go to Bucharest")

("go to Mehadia" "go to Dobreta" "go to Craiova" "go to Rimnicu Vilcea" "go to Sibiu" "go to Fagaras" "go to Bucharest")

("go to Mehadia" "go to Dobreta" "go to Craiova" "go to Pitesti" "go to Rimnicu Vilcea" "go to Sibiu" "go to Fagaras" "go to Bucharest")

("go to Mehadia" "go to Dobreta" "go to Craiova" "go to Pitesti" "go to Bucharest"))

• We can also write the code to display the search as it goes along.

(defun indent (n) (dotimes (x n) (princ " .")))

Page 9: Search Problems

9(defun find-routes-from (town1 town2 &optional used-actions (indent 0))

(when (null used-actions) (setf used-actions (list (concatenate 'string "go to " town1))))

(when (zerop indent) (terpri))

(let ((routes nil))

(dolist (condit *planning-conditionals*)

(when (and(equal (precond condit) town1)

(not (mem (action condit) used-actions)))

(cond

((equal (result condit) town2)

(push (list (action condit)) routes)

(indent indent) (princ "Completing route with: ") (princ (action condit)) (terpri))

(t

(indent indent) (princ "Trying: ") (princ (action condit)) (terpri)

(let ((subroutes

(find-routes-from (result condit) town2 (cons (action condit) used-actions)

(1+ indent))))

(dolist (subroute subroutes) (push (cons (action condit) subroute) routes)))))))

routes))

Page 10: Search Problems

10(find-routes-from "Lugoj" "Bucharest")

Trying: go to Mehadia .Trying: go to Dobreta . .Trying: go to Craiova . . .Trying: go to Rimnicu Vilcea . . . .Trying: go to Sibiu . . . . .Trying: go to Fagaras . . . . . .Completing route with: go to Bucharest . . . . .Trying: go to Oradea . . . . . .Trying: go to Zerind . . . . . . .Trying: go to Arad . . . . . . . .Trying: go to Timisoara . . . . .Trying: go to Arad . . . . . .Trying: go to Zerind . . . . . . .Trying: go to Oradea . . . . . .Trying: go to Timisoara . . . .Trying: go to Pitesti . . . . .Completing route with: go to Bucharest . . .Trying: go to Pitesti . . . .Completing route with: go to Bucharest . . . .Trying: go to Rimnicu Vilcea . . . . .Trying: go to Sibiu . . . . . .Trying: go to Fagaras . . . . . . .Completing route with: go to Bucharest . . . . . .Trying: go to Oradea . . . . . . .Trying: go to Zerind . . . . . . . .Trying: go to Arad . . . . . . . . .Trying: go to Timisoara . . . . . .Trying: go to Arad . . . . . . .Trying: go to Zerind . . . . . . . .Trying: go to Oradea . . . . . . .Trying: go to Timisoara

Page 11: Search Problems

11

Find Bucharest• Sometimes we just want to find a single route

(defun find-route-from (town1 town2 &optional used-actions) (when (null used-actions) (setf used-actions (list (concatenate 'string "go to " town1)))) (dolist (condit *planning-conditionals*) (when (and (equal (precond condit) town1) (not (mem (action condit) used-actions))) (cond ((equal (result condit) town2) (return-from find-route-from (list (action condit)))) (t (let ((subroute (find-route-from (result condit) town2 (cons (action condit) used-actions)))) (when subroute (return-from find-route-from (cons (action condit) subroute)))))))))

Page 12: Search Problems

12• Reporting search

(defun find-route-from (town1 town2 &optional used-actions (indent 0)) (when (null used-actions) (setf used-actions (list (concatenate 'string "go to " town1)))) (when (zerop indent) (terpri)) (dolist (condit *planning-conditionals*) (when (and (equal (precond condit) town1) (not (mem (action condit) used-actions))) (cond ((equal (result condit) town2) (return-from find-route-from (list (action condit)))) (t (indent indent) (princ "Trying: ") (princ (action condit)) (terpri) (let ((subroute (find-route-from (result condit) town2 (cons (action condit) used-actions) (1+ indent)))) (when subroute (return-from find-route-from (cons (action condit) subroute)))))))))

Page 13: Search Problems

13

Going from Urziceni to Timisoara

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Page 14: Search Problems

14

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 15: Search Problems

15

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 16: Search Problems

16

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 17: Search Problems

17

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 18: Search Problems

18

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 19: Search Problems

19

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 20: Search Problems

20

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 21: Search Problems

21

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 22: Search Problems

22

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 23: Search Problems

23

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 24: Search Problems

24

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 25: Search Problems

25

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 26: Search Problems

26

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 27: Search Problems

27

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 28: Search Problems

28

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 29: Search Problems

29

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 30: Search Problems

30

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 31: Search Problems

31

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoarabreadth-first search

Page 32: Search Problems

32

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 33: Search Problems

33

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 34: Search Problems

34

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 35: Search Problems

35

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 36: Search Problems

36

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 37: Search Problems

37

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 38: Search Problems

38

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 39: Search Problems

39

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 40: Search Problems

40

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 41: Search Problems

41

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 42: Search Problems

42

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 43: Search Problems

43

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 44: Search Problems

44

Oradea

Zerind

Arad

Timisoara

Dobreta

Mehadia

Lugoj

Sibiu Fagaras

Rimnicu Vilcea

Pitesti

CralovaGiurgiu

BucharestUrziceni

Etorie

Hirsova

Vasiui

Iasi

Neamt

Going from Urziceni to Timisoara depth-first search search

Page 45: Search Problems

45

General Search• For breadth-first search, we must store all the "partial routes" of length n, then

systematically extend each one by adding a single additional step in as many ways as possible, and then repeat this indefinitely until we find a route from town1 to town2.

• A mechanism for doing this is to maintain a queue of partial routes. The members of the queue will be called "nodes. They are lists of actions, and it is convenient to make the first member of each list the town the route ends at.

• A search strategy is an algorithm for selecting which node on the queue to try extending next.

• Generally, the most efficient way of implementing search strategies is to use them to order the queue, and then always select the first member of the queue for expansion.

• So we will take a strategy to be a function which, when applied to a new node and an existing queue returns a new queue which results from inserting the node into the old queue in the appropriate place.

Page 46: Search Problems

46

General Search• Search for route from town1 to town2

• Initialize queue to (list (list town1))

• Initialize towns-tried to (list town1)

• Enter loop

– If the queue is empty, return from loop.

– Let node be the first element on the queue. Remove it from the queue. Let town0 be the first member (the "destination") of node.

– for each planning conditional ((town0 & go-to-town) -> town) where town is not a member of towns-tried, let new-route be the result of adding go-to-town to the route in node and:

• If town = town2, return new-route.

• Otherwise, add town to towns-tried, and add (cons town new-route) to the queue, ordering the queue according to the search strategy.

Page 47: Search Problems

47

General Search(defun SEARCH-FOR-ROUTE (town1 town2 strategy) (terpri) (princ town1) (terpri) (let ((queue (list (list town1))) (towns-tried (list town1))) (loop (when (null queue) (princ "No route found") (terpri) (return)) (let ((node (first queue))) (setf queue (cdr queue))

(indent (length (cdr node))) (princ "Trying: ") (princ (car node)) (terpri) (dolist (condit *planning-conditionals*) (let ((town (result condit))) (when (and (not (mem town towns-tried)) (equal (precond condit) (car node))) (cond ((equal town town2) (return-from search-for-route (reverse (cons (action condit) (cdr node))))) (t (push town towns-tried) (setf queue (funcall strategy (cons town (cons (action condit) (cdr node))) queue)))))))))))

Page 48: Search Problems

48

General Search

;; for depth-first search

(defun depth-first (node queue)

(cons node queue))

;; for breadth-first search

(defun breadth-first (node queue)

(reverse (cons node (reverse queue))))

Page 49: Search Problems

49

Depth-first Breadth-firstUrziceniTrying: Urziceni .Trying: Hirsova .Trying: Vaslui .Trying: Bucharest . .Trying: Eforie . .Trying: Iasi . .Trying: Giurgiu . .Trying: Pitesti . .Trying: Fagaras . . .Trying: Neamt . . .Trying: Craiova . . .Trying: Rimnicu Vilcea . . .Trying: Sibiu . . . .Trying: Dobreta . . . .Trying: Oradea . . . .Trying: Arad("go to Bucharest" "go to Fagaras" "go to Sibiu" "go to Arad" "go to Timisoara")

UrziceniTrying: Urziceni .Trying: Bucharest . .Trying: Fagaras . . .Trying: Sibiu . . . .Trying: Rimnicu Vilcea . . . . .Trying: Craiova . . . . . .Trying: Dobreta . . . . . . .Trying: Mehadia . . . . . . . .Trying: Lugoj("go to Bucharest" "go to Fagaras" "go to Sibiu" "go to Rimnicu Vilcea" "go to Craiova" "go to Dobreta" "go to Mehadia" "go to Lugoj" "go to Timisoara")

Page 50: Search Problems

50

General Search Using Structures

(defstruct (town-node (:print-function print-town-node)

(:conc-name nil))

(town-name nil)

(route-to nil)

(evaluation 0)

(parent-node nil))

(defun print-town-node (node stream depth)

(declare (ignore depth))

(princ (town-name node) stream))

defstruct automatically introduces a new function make-town-node, which is used as follows:

(make-town-node

:town-name name

:route-to route

:evaluation evaluation

:parent-node node)

Page 51: Search Problems

51

Defining structures also defines functions for accessing the slots. If town is a town-node,

(town-name town) returns the resident of the town-name slot.

If we had not set (:conc-name nil), we would have to access this using

(town-node-town-name nil).

We can use setf to set the values of the slots:

(setf (town-name town) “Bucharest”).

We cannot do that using setq.

Page 52: Search Problems

52General Search Using Structures

(defun SEARCH-FOR-ROUTE (town1 town2 strategy &optional display?) (when display? (terpri) (princ town1) (terpri)) (let ((queue (list (make-town-node :town-name town1))) (towns-tried (list town1))) (loop (when (null queue) (princ "No route found") (terpri) (return)) (let ((node (first queue))) (setf queue (cdr queue)) (when display? (indent (length (route-to node))) (princ "Trying: ")

(princ (town-name node)) (terpri)) (dolist (condit *planning-conditionals*) (let ((town (result condit))) (when (and (not (mem town towns-tried)) (equal (precond condit) (town-name node))) (cond ((equal (result condit) town2) (return-from search-for-route (reverse (cons (action condit) (route-to node))))) (t (push town towns-tried) (setf queue (funcall strategy (make-town-node :town-name town :route-to (cons (action condit) (route-to node)) :parent-node node) queue)))))))))))

Page 53: Search Problems

53

General Search Using Structures;; heuristic search orders the nodes on the queue in terms of their evaluations:(defun heuristic-search (node queue) (compute-evaluation node) (ordered-insert node queue #'(lambda (x y) (< (evaluation x) (evaluation y)))))

(defun ordered-insert (x queue R) "queue is a list ordered by R, and x is a new member to be inserted into the right position in the ordering. This returns the new ordered list." (let ((head nil) (tail queue)) (loop (when (null tail) (return (reverse (cons x head)))) (let ((y (first tail))) (cond ((funcall R y x) (push y head) (setf tail (cdr tail))) (t (push x tail) (dolist (z head) (push z tail)) (return tail)))))))

;; for breadth-first search:(defun compute-evaluation (node) (setf (evaluation node) (length (route-to node))))

Page 54: Search Problems

54

Optimal Search• Search for route from town1 to town2• Initialize queue to (list (make-town-node :town-name town1))

• Initialize towns-tried to (list town1)

• Enter loop

– If the queue is empty, return from loop.

– Let node be the first element on the queue. Remove it from the queue. Let town0 be the town-name of node.

– If town0 = town2, return the route-to the node.

– for each planning conditional ((town0 & go-to-town) -> town) where town is not a member of towns-tried, let new-route be the result of adding go-to-town to (route-to node) and add town to towns-tried, and add

(make-town-node :town-name town :route-to (cons (action condit) (route-to node)) :parent-node node)

to the queue, ordering by the quality of the route.

• If evaluations increase monotonically as you add nodes to routes, this will find an optimal route.

Page 55: Search Problems

55

Optimal Search(defun SEARCH-FOR-OPTIMAL-ROUTE (town1 town2 strategy &optional display?) (when display? (terpri) (princ town1) (terpri)) (let ((queue (list (make-town-node :town-name town1))) (towns-tried (list town1))) (loop (when (null queue) (princ "No route found") (terpri) (return)) (let ((node (first queue))) (when (equal (town-name node) town2) (return (reverse (route-to node)))) (setf queue (cdr queue)) (when display? (indent (length (route-to node))) (princ "Trying: ")

(princ (town-name node)) (terpri)) (dolist (condit *planning-conditionals*) (let ((town (result condit))) (when (and (not (mem town towns-tried)) (equal (precond condit) (town-name node))) ;; no conditional here (push town towns-tried) (setf queue (funcall strategy ;; generally heuristic-search (make-town-node :town-name town :route-to (cons (action condit) (route-to node)) :parent-node node) queue)))))))))

Page 56: Search Problems

56

Optimal Search

(proclaim '(special *distances*))

(setf *distances*

(list

'("Oradea" "Zerind" 71)

'("Arad" "Zerind" 75)

'("Oradea" "Sibiu" 151)

...))

(defun distance (town1 town2)

(third (find-if

#'(lambda (x)

(or (and (equal (first x) town1) (equal (second x) town2))

(and (equal (first x) town2) (equal (second x) town1))))

*distances*)))

Page 57: Search Problems

57

Optimal Search(defun compute-evaluation (node)

(setf (evaluation node)

(+ (distance (town-name node) (town-name (parent-node node)))

(evaluation (parent-node node)))))

(search-for-optimal-route "Urziceni" "Timisoara" #'heuristic-search)

("go to Bucharest" "go to Pitesti" "go to Rimnicu Vilcea" "go to Sibiu" "go to Arad" "go to Timisoara")

(search-for-route "Urziceni" "Timisoara" #'breadth-first)

("go to Bucharest" "go to Fagaras" "go to Sibiu" "go to Arad" "go to Timisoara")

(search-for-route "Urziceni" "Timisoara" #'depth-first)

("go to Bucharest" "go to Fagaras" "go to Sibiu" "go to Rimnicu Vilcea" "go to Craiova" "go to Dobreta" "go to Mehadia" "go to Lugoj" "go to Timisoara")