||CS 371 - Introduction to Artificial Intelligence
Due: Wednesday 9/26 at the beginning of class
Note: Work is to be done in pairs
Stochastic Local Optimization
1. Rook Jumping Maze Generation:
Representation - generate and print a random Rook Jumping Maze (RJM).
Additionally, make use of the HW3 code resources, so that this exercise
amounts to initializing and printing a RookJumpingMaze implementation of the
State interface. You won't be using the State interface methods at
this point, but you'll focus on the constructor and overriding the toString
method. Submit a file with the correct input/output behavior as
Evaluation - breadth-first search from start state, printing state
depths (including goal state depth). Now implement the energy()
function of the State interface. Use a form of breadth-first search to
note each location's minimum depth in the search tree. Hint: You
need not use your previous search code. Coding a simple breadth-first
search within the RookJumpingMaze class will allow you to easily do
repeated-state elimination. initialize the depth of the initial
location to 0, and all others to a negative constant representing
"unreached" status. Replace "unreached" values with search depths (one
greater than current depth) as child locations are being added to the queue,
and not adding children to the queue that have already been visited (have
non-negative depth). Submit a file with the correct input/output
behavior as MazeEvaluation.java.
- Choose one:
Hill Descent - stochastic local search in space of maze
configurations, stepping to random neighboring configuration if the
minimum goal state depth does not decrease. Submit a file with the
correct input/output behavior as MazeDescent.java.
Hill Descent with Random Uphill Steps - same as
Descent but allowing uphill steps with a small probability.
Submit a file with the correct input/output behavior as
Simulated Annealing - similar to
Descent with Random Uphill Steps, but with better, more complex
uphill step policy. Submit a file with the correct input/output
behavior as MazeAnneal.java.
2. Choose Your Own Optimization Adventures: Implement
the 3 following problems using the State interface and write a test program
that demonstrates the effectiveness of one of our stochastic local optimization
techniques for the problem. (If there are other optimization problems you
would like to try, please see me.) Print the energy of the minimum energy
state at intervals during and at the end of the optimization. Limit the
time for each run to 1 minute. You'll want to use even shorter runs as you
develop, test, and debug.
- Scheduling Problem: Apply simulated annealing
to the following problem: Given a number of students wishing to take
a number of classes which can be assigned to a number of time slots, assign
classes to time slots in such a way as to minimize schedule conflicts.
You will create a class SchedulingProblem which implements State.
Its constructor will take a number of students, the number of classes a
student takes, a number of classes offered, and a number of time slots
(e.g. 240 students with 5 classes each, 100 classes offered, 12 time slots).
Each randomly generated instance of the problem will associate each student
with the given number of different random classes. Each class will
be associated with a random time slot. For the purposes of the State
interface, next causes a class to be randomly reassigned to a different
time slot. Energy is the sum of the student conflicts. The
number of conflicts for a student is the number of their classes they cannot
attend given the current schedule. (For the example above, if all
of a student's classes are scheduled at the same time, the student has
4 conflicts.) With parameters that generate problems which will likely not have a
zero-conflict schedule, demonstrate the performance of simulated annealing
versus iterative improvement with only downhill steps.
- Traveling Salesman Problem with River: (From "Numerical Recipes in
C" by Press et al) Uniformly and randomly distribute n points
(i.e. "cities") within a unit square. Represent a circuit (or "tour") of
these cities as a permutation in an appropriate list data structure.
(Assume that one returns to the first city after visiting the last city.)
Compute the "energy" of a tour state as the total distance of the circuit plus
a fixed cost for each time the tour crosses a north-south "river" which
divides the square vertically in half. The initial state constructor
should take n as a parameter. Graphically display the solution,
with tour lines in black and the river line in blue. Hint:
Generate each next state by taking a random segment of the tour and reversing
the order (e.g. ABCDEF -> ADCBEF or ABCDEF -> FECDBA).
In doing so, one need not recompute the cost of the whole tour, but only
the paths that have changed. Call your class RiverTSProblem.java.
- Tree Planting Problem: Suppose one has n trees and an plot
that is circular in which the trees should be planted. Further suppose
that it is desired that the trees should have maximal separation from each
other and from the borders of the plot. Construct the initial state with
n trees positioned randomly. Compute the next state by taking a
single tree and moving it by a small amount randomly (e.g. according to a
small Gaussian distribution; see java.util.Random.nextGaussian()). If a
tree moves outside of the plot, move it to the closest point within the plot.
Experiment with different energy function choices. For each tree,
compute the minimum distance to the plot borders and all other trees.
Then have the energy function return some function of these distances (e.g.
the negated minimum, the mean, etc.). Which energy function gives you the most
satisfactory result? Graphically display the solution, showing the plot
outline, and the trees as filled green circles with radii being the minimum of
all the minimum distances. Call your class TreeProblem.java.
Hopefully, in looking at these problems, you'll see the wide applicability of
such optimization algorithms. Often, the most challenging aspect of such
optimization is devising a good, efficient next state generator that gives
beneficial structure to the state space, rather than merely bouncing randomly
from one state to another. Good next state generators both allow one to
traverse the entire state space, and immediately sample states that are similar
in quality to the current state.