Artificial Intelligence Lab instructions

advertisement
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Artificial Intelligence
Lab instructions
Mathias Broxvall, Lia Silva-Lopez, November 2011
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
General instructions
This text together with some files on the course web page describes the labs in the course Artificial Intelligence, given at Örebro University Autumn 2011.
In these labs you will first familiarise yourself with Python, an interpretative, incremental
programming language supporting functional and higher order programming. You will use this
language to write a number of artificial intelligence type of programs.
Platform
The labs are primarily intended to be performed under Windows in the University computer
halls. However, since Python and the tools used are freely available also for other platforms, you
are encouraged to download the language and tools if you want to work from home. If you want
to use another platform than the University classrooms you will find some useful information on
the course web page, however note that it is your own responsibility of making it work in case
you choose alternative platforms.
Program code
In order to solve the exercises you will use or build upon some existing code. All the files
needed to complete the labs can be found at the course web page and you can download it to
your computer during the labs.
You should also create a file template containing your name, lab group and educational
program. This template should be used for all code you present in this course.
Preparations
In order to benefit properly, you are expected to prepare well before each lab. Remember that this
is for your own benefit, and unprepared students may be denied assistance. These preparations
include:
1. To have read the exercises and any other material such as lab skeletons, or other source
files and instructions. If any of the exercise assignments or questions are unclear you
should be able to ask the instructor in the beginning of the session.
2. Go through the lecture notes covering the corresponding area.
3. You should have thought through how the exercises can be solved. This can be done, for
instance, by sketching up a rough structure (the design) of your program and to lookup
built-in functions in Python that may be used.
4. Considered what can possibly go wrong in your program and how you can fix it. Also
make plans for how you can test different parts of your program while writing it, and
finally how you can test the whole program.
1
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Examination
For the labs you may work individually or in pairs. Although you are encouraged to discuss
different solutions with your classmates you are not allowed to copy code or to show your code
to your class mates.
All labs should be handed on time lab.
Please note that this means that you will have to work outside the scheduled time in order to
finish in time, and that you are expected to be able to handle the programming environment and
to debug your own code.
The examination of each lab consists of two parts:
• Part one, is a demonstration of how your code works. This demonstration should be performed to the lab assistant, and will last up to 10 minutes, followed by a questioning round
of 5 minutes, where the assistant will ask a number of related questions. You and your
team mate for should be present this assignment. If your solution performs as expected,
you present it in a correct and concise way, and answer the questions appropriately, you
should be allowed to present the second part of the examination. Please note that it is
your own responsibility to make a rational use of your available 10 minutes to describe your solution, and present your code to the lab assistant. If your time is due,
and you have not finished explaining your solution and answering questions in a satisfying
way, or your code does not perform accordingly during this time, the result is a fail, so
punctuality and correctness are highly recommended.
• Part two, is a printed lab report describing the program and your solution. If you pass part
one, you will be allowed to present a report that should describe and motivate the solutions
you have used, the intentions behind your solution, and a description of each function you
have written as well as its parameters. You should provide an electronic version (in PDF
only) of this report. Only those that passed part one of the examination are allowed to
present part two.
To pass the labs, the following is required:
1. Part one of the lab should be presented before noon of due date. To do so, book a time with
the lab assistant, by sending an email with subject ”Oral Part lab xx”, where ”xx” is the
number of the lab, and include at least three preferred dates with time intervals. The lab
assistant will book your time and update the Calendar with any of your preferred dates.
This will be done around 5:30pm of that same day, if the email is received before 5pm. If
the email was received after 5pm, times will be assigned the next day. If for some reason
none of your preferred dates is feasible, the lab assistant will let you know ASAP. Check
the calendar for booking times in http://alturl.com/y52ab.
2. As for part two, labs are corrected within one week and returned at the next scheduled lab
occasion. The results of the correction can be either pass, completion or fail.
3. For a lab to be corrected it must be handed in time, after passing part one. Otherwise it
will automatically count as a completion.
2
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
4. If you have received completion on a lab, you must deliver the completed lab report within
two weeks. The correction of this ”completed” lab report will be done within a week and
will give either pass or fail. Please note that you can not receive a ”complete” more
than once!.
5. Please note that there is only one chance to present part one. Use it wisely.
6. Each group should perform, at least once, an oral presentation of the solution to an exercise
of one ot the labs. This is assigned from the beginning of the course.
The report must satisfy at least the following requirements:
• All questions in the exercise must be correctly answered and motivated. Only repeating
the question or providing a factually correct yes/no answer does not count as answering it.
• The solutions to exercises must be described in a concise and complete way.
• The report cannot be longer than 4 pages, unless you have a really good excuse.
If you have used any code from other sources than the lab skeletons (eg. Internet, books etc.)
you have to clearly mark this in the source code. Not doing so counts as attempted cheating and
you will be reported to the disciplinary board. Depending on the amount of borrowed code, the
instructor may fail the lab, so always discuss with the instructor before using any code that you
have not written yourself.
Due to the limited instructor time, all labs must be completed and passed within the allotted
time of the course, otherwise you will have to resubmit the labs the following year.
Finally, a short clarification of the expected work. Since this is a half-time course you are
expected to spend 20 hours/week on this course. This entails roughly 4 hours of lectures and
4 hours of preparations before the lectures, 4 hours of teacher assisted work and 9 hours of
preparations for the labs and labs done on your own time.
Examiner: Dr. Mathias Broxvall, mathias.broxvall@oru.se
Assistant: MSc. Lia Susana d.C. Silva Lopez, lia.silva@oru.se
3
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
4
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Lab 1 - An introduction to Python
This first lab assignment deals with generic python and functional programming problems.
Preparations: Before you start on this lab you should have read the document Artificial Intelligence - A Primer for the Labs and should be familiar with Python.
The following is a function that counts the number of times a string occurs in another string:
# Count the number of times string s1 is found in string s2
def countsubstring(s1,s2):
count = 0
for i in range(0,len(s2)-len(s1)+1):
if s1 == s2[i:i+len(s1)]:
count += 1
return count
For instance, countsubstring(’ab’,’cabalaba’) returns 2.
Exercise 1.1 - Recursion. Write a recursive version of the above function. To get the rest of a
string (i.e. everything but the first character), you can use s[1:]. Also think about what the
computational complexities of the two functions are.
Exercise 1.2 - Higher order functions. Write a higher-order function count that counts the
number of elements in a list that satisfy a given test. For instance:
count(lambda x: x>2, [1,2,3,4,5])
should return 3, as there are three elements in the list larger than 2. Solve this task without using
any existing higher-order function.
Exercise 1.3 - Brute force solution to the Knapsack problem. Write a function that allows you
to generate random problem instances for the knapsack program described in the text Artificial
Intelligence - A Primer for the Labs. This function should generate a list of items containing N
items that each have a unique name, a random size in the range 1 . . . 5 and a random value in the
range 1 . . . 10.
Next, you should perform performance measurements to see how long the given knapsack
solver take to solve different problem sizes. You should peform atleast 10 runs with different
randomly generated problem instances for the problem sizes 10,12,14,16,18,20 and 22. Use a
backpack size of 2.5 × N for each value problem size N . Please note that the method used to
generate random numbers can also affect performance, since different distributions of values can
make the initial conditions of the problem slightly more or less demanding.
How much longer time does it take to run this program when we increase the number of
items? Does the backpack size affect the answer?
Try running the above tests again with a backpack size of 1 × N and with 4.0 × N . Does
this affect the performance?
5
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Give a diagram that shows how the time required increases with problem size for the different backpack sizes.
To generate random numbers you should first use import random and can then use
random.randrange(start,stop) to generate random numbers in the range start,
start+1, ... stop-1.
You can measure the time it takes to run the program by using the class Timer from the
module timeit.
from timeit import *
def fn():
... code to execute ...
T=Timer(fn)
T.timeit(10)
The argument 10 to the function timeit is how many times to execute the function, which
makes timing fast functions much easier. Adjust the number so that you don’t have to wait
forever for your timing results to finish (this varies for different computers and different python
compiler).
Hint: Make a python script that runs the code for the different sizes and backsize sizes and
that prints only the total execution times. This will simplify this exercise for you.
Question 1.1 - Recursive search. What is the worst-case computational complexity of the given
knapsack solver? Explain what this means in practical terms! For example:
Exercise 1.4 - The Graph colouring problem. Assume that you are organising a party for N
people and have been given a list L of people who, for social reasons, should not sit at the same
table. Furthermore, assume that you have C tables (that are infinitly large).
Write a function layout(N,C,L) that can give a table placement (ie. a number from
0 . . . C − 1) for each guest such that there will be no social mishaps.
For simplicity we assume that you have a unique number 0 . . . N − 1 for each guest and
that the list of restrictions is of the form [(X,Y), ...] denoting guests X, Y that are not
allowed to sit together. Answer with a dictionary mapping each guest into a table assignment, if
there are no possible layouts of the guests you should answer False.
>>> layout(3,2,[(0,1),(0,2)])
{0: 0, 1: 1, 2: 1}
>>> layout(4,2,[(0,1),(0,2),(1,2),(0,3)])
False
>>> layout(4,3,[(0,1),(0,2),(1,2),(0,3)])
{0: 0, 1: 1, 2: 2, 3: 1}
6
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Hint: Your function should be recursive and at a given recursive depth d you should attempt
to find a table for guest number d. You can pass d in as an argument and include d in front of
each printout you make while debugging your program.
On each call to the function, keep track of the guests that have already been assigned to a
table and try to decide the placement for the guest d. Do this by considering each possible table t
and see if placing him at this table means that he is sitting at the same table as one of his enemies
that have already received a table placement. If not, assign (temporarily) guest d to table t and
call yourself recursively to find an assignement for guest d + 1. If your recursive call returns
successfully you have found a solution, otherwise try to assign d to the next possible table.
Hint: Try running your program on very small problem instances first, for instance the
simplest case with zero guests or with only one guest. Use both simple examples that possible
and examples that are not possible to find a layout for. For example:
# Two guests that dislike each other, but only one table
>>> layout(2,1,[(0,1)])
False
# Same example, but two tables
>>> layout(2,2,[(0,1)])
{0: 0, 1: 1}
Examination
To pass this lab you must first demonstrate each assignment to the assistant (pass part one of the
evaluation), and to hand in a detailed report together with the source code, as files sent by email
(pass two of the evaluation).
You should have one section in your report for each exercise (1.1 - 1.4) and for each question
(1.1).
Examination date: Latest Nov 17th
7
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Lab 2 - Search strategies
In this second lab assignment you will take a look at search algorithms to perform a few simple
tasks.
Preparations: Read through the lecture notes regarding search before you start on this lab.
You should know the difference between depth-first search, breath-first search and other search
methods such as A*.
In Figure 1 you will find a matrix (list of lists) that represents a simple labyrinth. 0 represents
a wall and 1 represents a passage. 2 represents a door that requires a key to be opened (for future
labs) and 3 represents a supply of keys.
labyrinth = \
[[0,0,0,0,0,0,1,0],
[0,1,0,1,1,1,1,0],
[0,1,1,1,0,1,0,0],
[0,1,0,0,0,0,0,0],
[0,1,1,0,1,1,3,0],
[0,0,1,1,1,0,0,0],
[0,1,2,0,1,1,1,0],
[0,1,0,0,0,0,0,0]]
############. ##
## ##. . . . ##
##. . . ## ####
##. ############
##. . ##. . .K##
####. . . ######
##. .D##
##
##. ############
Figure 1: Matrix (left) and printed (right) representation of a labyrinth
Exercise 2.1 - Arrays and formatting text. Write a function that takes a labyrinth matrix like
the one in Figure 1 as argument and draws it using the characters ## for walls, two spaces for
empty passages, D for doors and K for keys. This function should also accept a list of (x,y)
tuples that represent positions visited by a robot in the labyrinth, you should print the character
. at these points (note that you should print either a whitespace, D or K in addition to the dot).
You can use either the print statement and the formatting instructions to do this, or to
use sys.stdout.write to write strings without appended newlines. For the later approach
remember that you need to first use import sys in your code.
When you access the matrix, remember that the y axis (row) comes before the x axis (column): labyrinth[y][x].
Exercise 2.2 - Identifying free areas of the labyrinth. Write a function adjacent_passages
that takes a labyrinth matrix like the one above and the x and y coordinates for a place in the
labyrinth as arguments, and returns a list of the coordinates (tuples of x and y) of all adjacent
places (vertically and horizontally) that are passages (i.e. have value 1). For instance:
>>> adjacent_passages(labyrinth, 1, 1)
[(1, 2)]
>>> adjacent_passages(labyrinth, 6, 1)
8
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
[(6, 0), (5,1)]
Note that the function must handle all input coordinates in a consistent way, and not access
memory outside the size of the labyrinth array under any circumstance.
Hint: Test that your function gives the correct answer and does not crash when tested on the
corner poins (0,0), (7,0), (0,7), (7,7) as well as the opening points (6,0), (7,1)
and completly invalid points such as (42,11), (-1,117)
Now remains to find a path through the labyrinth from the previous exercise. Such a path
can be described as a list of (x,y)-coordinates.
As is common in many 2D computer games (and reality) we usually need to hold a key
before we can open a door. We also consume the keys when opening doors (unlike reality) but
can fortunatly find an infinite supply of keys just lying around on the floor. Your next exercise
it to take a path (list of (x,y) coordinates) and verify that the user holds picks up a key before
attempting to move through any doors.
Exercise 2.3 - Verifying a valid path. Write a function that can take a list [(x1,y1),(x2,y2),...]
containing the coordinates of a walk through the labyrinth and that can verify that a key is picked
up before attempting to walk through any doors. Assume that the user can only hold one key, and
that he automatically picks up the key when walking over any coordinate containing keys (the
keys in the labyrinth are not consumed by this). If the path attempts to go through a door without
holding a key then your function should return false, otherwise it should continue checking the
path but without holding a key.
Hint: Test your function on the labyrinth given above. It should not be possible to exist the
labyrinth with a straight path, but it should be possible if we first go over the key as showned in
the example printout.
Question 2.1 - Loop detection. What is loop detection and why is this necessary when searching through the labyrinth? How can you implement this in an efficient way? Does it matter if
the player comes back to the same place twice, but possibly with or without holding a key?
Next, it is time for you to do some more serious adventuring through labyrinths.
Start by downloading labyrinth.py containing a slightly larger labyrinth for these exercise.
Exercise 2.4 - Searching through the labyrinth. Write a recursive function that finds a way
through the labyrinth. The entrance is at (6,0) the exit at (1,15) for the big labyrinth. The
function should effectively perform a depth-first search.
The base case is obviously that the goal is reached, and should return the path leading there.
Therefore, you need to keep track of the path traversed so far.
In the recursive case, you need to try all possible ways you can take the next step, except for
those cases when you return to a state previously visited.
9
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Hint: A state needs to contain both the coordinate of the player as well as wheter or not he
holds a key (true/false).
Exercise 2.5 - A generic search method. Recall the search algorithm find_path_df from
the text Artificial Intelligence - A Primer for the Labs. One of the advantages of this method
is that you have a generic search algorithm, and only need to plugin the methods for knowing
which actions you can take and detecting if you have reached the goal or not.
Your task now is to complete this algorithm to use to perform the search through the labyrinth.
Compare the result with the recursive approach from previous exercise.
Exercise 2.6 - A better search. Write a function find_path_bf that implements a breadthfirst search using a queue. You will only need to change a few lines of the previous algorithm
for this.
Test the algorithm on the labyrinth we have used before. Compare the number of visited
nodes and the quality of the solution with the previous approaches. What is the difference? Can
you explain the advantages and disadvantages of this approach?
Question 2.2 - Comparing the search methods. Compute how many nodes where visited
during the depth respectively breadth first search. Which method was faster and which method
yielded the shortest path? Also compute/estimate the maximum amount of memory used by the
different version of the algorithms.
Investigate the different order in which the neighbors of a position is returned by your function adjacent_passages. How does this affect the cost and quality of the solutions generated by your search algorithms above?
Exercise 2.7 - A* search. Finally, you should write a new function that instead performs an A*
search through the labyrinth. As a path-cost function you should use the length of the current
path, and as a distance estimate use the Manhattan distance to the goal.
Compare the cost (in terms of visited nodes and maximum memory usage) of finding the
solution to the labyrinth using this algorithm compared to the two other search algorithms above.
Does your algorithm generate an optimal solution?
Question 2.3 - Admissible heuristics. What is an admissible heuristic? Why is this important
for A*? Is the Manhattan distance a valid heuristic for the problem above?
If you would have used instead a heurstic “key-greedy” that have as cost the manhattan distance plus ten if we do not yet hold a key. Would this “key-greedy” heuristic be admissible?
Question 2.4 - Comparing the search algorithms. Explain under what circumstances the three
10
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
different search algorithms you have tested are “best”. When should each one be used in favor
of the others?
Examination
To pass this lab you must first demonstrate each assignment to the assistant (pass part one of the
evaluation), and to hand in a detailed report together with the source code, as files sent by email
(pass two of the evaluation).
You should have one section in your report for each exercise (Exercise 2.1 - 2.7) and for
each question (Question 2.1 - 2.4).
Examination date: Latest Dec 1st
11
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
Lab 3 - A game playing AI
It is now time for you to develop your first full game AI, for the board game Reversi. This
game is also sometimes known as Othello. It is a two player game where the two players, black
and white, alternate in placing the black respectively white side of a flat disk in one of the 8x8
positions of the game board. When they place a disk on a position, they get to flip over all of
the opponents disks in a straight line (including diagonal lines) between this position and one of
the players already placed markers. It is only allowed to make moves that will flip over at least
one of the other players disk, and the game ends when one player can no longer make any more
moves. See Figure 2 for a picture of this game.
Start by downloading reversi.zip from the course web page. Unpack this archive and
you will find a Python file (reversi.py) and a number of image files (GIF) that are used to generate a visualization of your program. If you are working from home, you may need to install
tkinter, which is the de-facto standard python GUI toolkit1 .
Figure 2: The game Reversi, aka. Othello
Test run the game by loading reversi.py. You will now see the board and can play as human
versus a very bad AI. The AI that you have been given in this code skeleton randomly chooses
one of the possible moves that are legal from each position.
Question 3.1 - Loop detection. What is the maximum number of moves that can be done by
each player in this game? Do you need to handle loop detection when searching for the best
moves? Motivate your answer!
You can change which player(s) are human, and which are run by which AI by passing an instance of the classes to the function ReversiFrame(..,..). The two arguments correspond
1
Under Ubuntu, install python-tk for this
12
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
to each player, and if they are None it means that the player is human controlled, otherwise it
should be an instance of a class that implements the doMove function.
Exercise 3.1 - A greedy search algorithm. Start by implementing a greedy AI algorithm that
goes through each move it can do in the current state, and performs the move that would give
the highest score immediately. You should do this implementation by creating a new class, that
implements the doMove function to perform the best move. If there are multiple moves that
gives the same score, one of them should be choosen randomly.
Test to play against this AI, is it harder to win against this than the random AI? Also,
test to run your AI against the random AI at least 10 times and record which player was the
winner. How often does your AI win against the random AI? You can use the given function
verifyAIs for this.
If you read up on strategies for Reversi, you will find that beginners usally only play to flip
the most disks each move. This corresponds to your greedy AI above. Slightly more advanced
players learn to look ahead a few moves, to avoid giving the other player “free chances” to flip
many of your pieces.
Exercise 3.2 - The min-max algorithm. Next, you should implement a smarter AI that employs
the min-max algorithm to rank the score of each possible move that it can do. It should have a
look-ahead of atleast 3 half-moves (ply’s) and should run fast enough to be playable without
waiting “too long”. In case of multiple moves giving the same score a random choise should be
made. Again, this AI should be implemented in a new class.
Test to play against this AI, is it harder to win against this than the previous two AI’s? Test
to run your AI against both the random AI and the greedy AI atleast 10 times and record which
player was the winner. How often does your AI win against these two other AI’s.
Finally, if you have played Reversi alot, you have probably learned that certain positions on
the game board is better than the others (otherwise, you can read about strategies for this game
online). You should use this knowledge to develop a smarter heuristic, that makes the AI value
certain positions more and try to win these positions.
Exercise 3.3 - Adding a heuristic. You should make your min-max AI slightly more sophisticated by employing a heuristic that rewards certain positions.
Try a few different heuristics and compare them against each other and against the previously developed AI’s. Finally, test to play against your AI and make test runs to statistically
determine which AI and heuristic is the best.
Examination
This lab may be performed in groups of two or individually. To pass this lab you must first
demonstrate each assignment to the assistant (pass part one of the evaluation), and to hand in a
detailed report together with the source code, as files sent by email (pass two of the evaluation).
13
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
You should have one section in your report for each exercise (Exercise 3.1 - 3.3) and for
each question (Question 3.1).
Examination date: Latest Dec 15th
14
Artificial Intelligence - Lab Instructions
v2011.1, Örebro Universitet
PRELIMINARY Lab 4 - Neural Networks
This lab will be written and published on the course webpage before Dec 8th.
15
Download