NOTE: You may work in pairs on this assignment. Both team members received the same grade.
Required Writeup: In addition to the PROLOG program itself, provide both a theoretical and empirical analysis of your heuristic. The theoretical part should be based on the discussion of heuristics in the text. That is, discuss why it is a heuristic (rather than a deterministic algorithm), whether it is admissible and how informative it is. The empirical analysis should be based on experimental results. Try running the heuristic with different start and goal states and show that it remains both admissible and efficient. You may also wish to compare its performance against breadth-first search and also against a different heuristic (e.g., against the one described on heuristic homework assignment).
One of the key issues in designing a PROLOG solution to this problem is deciding on how to represent the puzzle. Another issue is how to describe all possible moves. Code your PROLOG solution into a single file and incorporate it into the heuristic search framework you used in the knight's tour problem. For example, if you name the file containing the solution to the sliding puzzle sliding.pl, your main program would look like this:
/* sliding.heur.pl -- main file for sliding tile puzzle */
setup :-
reconsult('sliding.pl'), /* moves and heuristic for sliding tile puzzle */
reconsult('bf.pl'), /* best-first search predicates */
reconsult('pq.pl'), /* priority queue predicates */
reconsult('set.pl'), /* set predicates */
reconsult('small_lib.pro'). /* miscellaneous predicates */
start :-
go([b,b,b,x,w,w,w],[w,w,w,_,_,_,_]). /* go from start to goal state */
unsafe(_):- fail. /* everything is safe */
precedes([_,_,_,_,X],[_,_,_,_,Y]) :- X =< Y. /* f(i) <= f(j) for states i, j */
Note that the precedes() predicate is necessary for the heuristic. It compares the values of f(n) = g(n) + h(n) for two states, i and j. The smaller value is given higher priority.
There are several subproblems that you must solve in order to obtain a solution to this problem:
To help with the backtracking problem, here's a select/3 predicate that is suitable for backtracking:
/** * select/3 selects an Item from OldList, giving NewList. By using * append, select/3 will return a different element each time it * is called, thus making it suitable for backtracking. */ select(Item,OldList,NewList) :- append(X,[Item|Tail], OldList), append(X,Tail,NewList).
Because it uses append, it will select a different Item from OldList each time it is backtracked on. To test this, trying running it and typing ';' after each solution.
For this problem, provide an analysis of Warnsdorf's heuristic comparable to the required writeup described with Choice 1.