CPSC 322 - Homework Assignment 2 - October 22, 2004

CPSC 322 - Homework Assignment 3

For handin purposes, this is asgn3

Due by 6:00AM, Friday, October 29, 2004


Before we get started, allow me to set some guidelines for turning in
homework assignments.  You've had ample time to get your computing
accounts sorted out and figure out how the handin program works, so
beginning with this assignment we won't be accepting submissions that
are emailed to us unless handin crashes.

Next, if you're working with someone else, the two of you should submit
only one set of solutions.  Make sure the names, student numbers, and 
email addresses of both contributors are at the top of the file.  It 
doesn't matter which account you submit from as long as the information
for both contributors is included.  But don't submit duplicate solution
sets from two different accounts...it just makes more work for your TAs.
Thanks.

When your TAs are marking their homework, they're using Linux boxes to
look at what you've submitted.  So if you write the assignment in an
environment other than Linux, please try to format what you write in 
such a way that it is easily readable in Linux.  If you need additional
guidance on this issue, be sure to talk to one of your TAs about it.

There may be more guidelines forthcoming from your TAs, so stay tuned.
Now let the fun begin.

Below you'll find the CILOG knowledge base and predicates for the
8-tile puzzle that we've been using as an example in class.
This CILOG code will be the basis for the learning and discovery
opportunities which follow.

neighbors([2,8,3,1,0,4,7,6,5],[[2,8,3,0,1,4,7,6,5],[2,0,3,1,8,4,7,6,5],[2,8,3,1,4,0,7,6,5]]).
neighbors([2,8,3,0,1,4,7,6,5],[[0,8,3,2,1,4,7,6,5],[2,8,3,7,1,4,0,6,5]]).
neighbors([2,0,3,1,8,4,7,6,5],[[0,2,3,1,8,4,7,6,5],[2,3,0,1,8,4,7,6,5]]).
neighbors([2,8,3,1,4,0,7,6,5],[[2,8,0,1,4,3,7,6,5],[2,8,3,1,4,5,7,6,0]]).
neighbors([0,8,3,2,1,4,7,6,5],[[8,0,3,2,1,4,7,6,5]]).
neighbors([2,8,3,7,1,4,0,6,5],[[2,8,3,7,1,4,6,0,5]]).
neighbors([0,2,3,1,8,4,7,6,5],[[1,2,3,0,8,4,7,6,5]]).
neighbors([2,3,0,1,8,4,7,6,5],[[2,3,4,1,8,0,7,6,5]]).
neighbors([2,8,0,1,4,3,7,6,5],[[2,0,8,1,4,3,7,6,5]]).
neighbors([2,8,3,1,4,5,7,6,0],[[2,8,3,1,4,5,7,0,6]]).

neighbors([8,0,3,2,1,4,7,6,5],[[8,3,0,2,1,4,7,6,5],[8,1,3,2,0,4,7,6,5]]).
neighbors([2,8,3,7,1,4,6,0,5],[[2,8,3,7,0,4,6,1,5],[2,8,3,7,1,4,6,5,0]]).
neighbors([1,2,3,0,8,4,7,6,5],[[1,2,3,8,0,4,7,6,5],[1,2,3,7,8,4,0,6,5]]).
neighbors([2,3,4,1,8,0,7,6,5],[[2,3,4,1,0,8,7,6,5],[2,3,4,1,8,5,7,6,0]]).
neighbors([2,0,8,1,4,3,7,6,5],[[0,2,8,1,4,3,7,6,5],[2,4,8,1,0,3,7,6,5]]).
neighbors([2,8,3,1,4,5,7,0,6],[[2,8,3,1,4,5,0,7,6],[2,8,3,1,0,5,7,4,6]]).

neighbors([8,3,0,2,1,4,7,6,5],[]).
neighbors([8,1,3,2,0,4,7,6,5],[]).
neighbors([2,8,3,7,0,4,6,1,5],[]).
neighbors([2,8,3,7,1,4,6,5,0],[]).
neighbors([1,2,3,8,0,4,7,6,5],[]).
neighbors([1,2,3,7,8,4,0,6,5],[]).
neighbors([2,3,4,1,0,8,7,6,5],[]).
neighbors([2,3,4,1,8,5,7,6,0],[]).
neighbors([0,2,8,1,4,3,7,6,5],[]).
neighbors([2,4,8,1,0,3,7,6,5],[]).
neighbors([2,8,3,1,4,5,0,7,6],[]).
neighbors([2,8,3,1,0,5,7,4,6],[]).

append([],Z,Z).
append([A|X],Y,[A|Z]) <- append(X,Y,Z).

is_goal([1,2,3,8,0,4,7,6,5]). 

search(F0) <- choose(Node,F0,F1) & 
              neighbors(Node,NN) &
              add_to_frontier(NN,F1,F2) &
              search(F2).

search(F0) <- choose(Node,F0,F1) & is_goal(Node).

choose(N,[N|Flist],Flist). 

add_to_frontier(Nodelist,Flist1,Flist2) <- append(Flist1,Nodelist,Flist2).


-------------------------------------------------------------------
Problem 1 (10 points):  Load the code above into CILOG and run it
with the query

cilog: ask search([[2,8,3,1,0,4,7,6,5]]). 

(Remember that the argument to the search predicate is a list of
nodes on the frontier and each node on the list is itself a list,
hence the double square brackets.)

Turn in the results of this query (there won't be much) so your 
TA knows that you got this to work.  Then, using all those new words
you've learned recently to talk about search, describe what kind of
search is going on here.  How can you tell?  (Hint:  It won't be
obvious from the results of your query.)   


-------------------------------------------------------------------
Problem 2 (10 points):  This problem will be a little bit more
challenging than the previous one.  Below are the arc costs for
our sample 8-tile puzzle.  For example, the very first relation
indicates that the cost of going from [2,8,3,1,0,4,7,6,5] to 
[2,8,3,0,1,4,7,6,5] is 2 (because Bubba had to move a tile 
sideways, remember?).

cost([2,8,3,1,0,4,7,6,5],[2,8,3,0,1,4,7,6,5],2).
cost([2,8,3,1,0,4,7,6,5],[2,0,3,1,8,4,7,6,5],1).
cost([2,8,3,1,0,4,7,6,5],[2,8,3,1,4,0,7,6,5],2).
cost([2,8,3,0,1,4,7,6,5],[0,8,3,2,1,4,7,6,5],1).
cost([2,8,3,0,1,4,7,6,5],[2,8,3,7,1,4,0,6,5],3).
cost([2,0,3,1,8,4,7,6,5],[0,2,3,1,8,4,7,6,5],2).
cost([2,0,3,1,8,4,7,6,5],[2,3,0,1,8,4,7,6,5],2).
cost([2,8,3,1,4,0,7,6,5],[2,8,0,1,4,3,7,6,5],1).
cost([2,8,3,1,4,0,7,6,5],[2,8,3,1,4,5,7,6,0],3).
cost([0,8,3,2,1,4,7,6,5],[8,0,3,2,1,4,7,6,5],2).
cost([2,8,3,7,1,4,0,6,5],[2,8,3,7,1,4,6,0,5],2).
cost([0,2,3,1,8,4,7,6,5],[1,2,3,0,8,4,7,6,5],3).
cost([2,3,0,1,8,4,7,6,5],[2,3,4,1,8,0,7,6,5],3).
cost([2,8,0,1,4,3,7,6,5],[2,0,8,1,4,3,7,6,5],2).
cost([2,8,3,1,4,5,7,6,0],[2,8,3,1,4,5,7,0,6],2).
cost([8,0,3,2,1,4,7,6,5],[8,3,0,2,1,4,7,6,5],2).
cost([8,0,3,2,1,4,7,6,5],[8,1,3,2,0,4,7,6,5],3).
cost([2,8,3,7,1,4,6,0,5],[2,8,3,7,0,4,6,1,5],1).
cost([2,8,3,7,1,4,6,0,5],[2,8,3,7,1,4,6,5,0],2).
cost([1,2,3,0,8,4,7,6,5],[1,2,3,8,0,4,7,6,5],2).
cost([1,2,3,0,8,4,7,6,5],[1,2,3,7,8,4,0,6,5],3).
cost([2,3,4,1,8,0,7,6,5],[2,3,4,1,0,8,7,6,5],2).
cost([2,3,4,1,8,0,7,6,5],[2,3,4,1,8,5,7,6,0],3).
cost([2,0,8,1,4,3,7,6,5],[0,2,8,1,4,3,7,6,5],2).
cost([2,0,8,1,4,3,7,6,5],[2,4,8,1,0,3,7,6,5],3).
cost([2,8,3,1,4,5,7,0,6],[2,8,3,1,4,5,0,7,6],2).
cost([2,8,3,1,4,5,7,0,6],[2,8,3,1,0,5,7,4,6],1).

Add this cost information to the knowledge base, and then
make the necessary modifications to the CILOG search code
so that it performs a lowest-cost-first search in solving
the 8-tile puzzle.  Call your search predicate "costsearch" 
so we can distinguish it from the the generic search
predicate.  Turn in a little transcript of your
interaction with CILOG to show your grader that it all
works.  Also, turn in a copy of your revised program
so that your grader can test it with a different knowledge
base.


-------------------------------------------------------------------
Problem 3 (20 points):  Now ignore all that cost information...
heck, you can just delete it all from your knowledge base.
You're now going to implement a simple heuristic search.
Use CILOG to implement a heuristic function that counts the
number of tiles out of place (including the "blank tile"), as 
discussed in class, and then modify the CILOG search code to 
use this heuristic knowledge to perform a best-first search
in solving the 8-tile puzzle.  Just as a reminder, we assumed in
class that a board with fewer tiles out of place is closer to the 
goal than one with more tiles out of place.  That may not be
correct, but it's sufficient for the purposes of this exercise.

Call your search predicate "bestsearch" this time to avoid confusion.
Again, turn in a little transcript of your interaction with CILOG to 
show your grader that it all works.  And just like before, turn in a 
copy of your revised program so that your grader can test it with a 
different knowledge base and maybe even a different evaluation function.

Oh, by the way, call your evaluation function (or more accurately,
your evaluation predicate) "h", as in h(n).  But your predicate should
take two arguments and work like this:

   h(Board,N) is true if N is the number of tiles in Board (including
              the blank tile) that are out of place.


-------------------------------------------------------------------
Problem 4 (10 points):  That was fun, wasn't it?  Now take the modified
CILOG code from problem 3 that performs a best-first search and modify
it even more so that it returns a path from the start node to the goal
(but in reverse order) instead of just a yes/no answer.  

Your search predicate, which you'll name "pathsearch", should work just 
like we specified in class.  That is,

  pathsearch(F,Path) is true if Path is a list of nodes from the start
  node to the goal node (but in reverse order) that passes through one
  of the nodes on the frontier F.  And keep in mind that a node on
  the frontier is represented by a list of nodes that represent a path
  from the start node to that node on the frontier (yes, in reverse order).
  Go back to the powerpoint slides or the textbook (pages 123-124) 
  to refresh your memory about what path search does.  

Finally, one last time, turn in a little 
transcript of your interaction with CILOG as well as a copy of your 
revised program (the whole program, not just the modified parts).


Last revised: October 22, 2004