In this assignment you will extend your
ProblemSolver framework
for automated problem solving. You will proceed in two general stages,
corresponding to the framework's
Model and its
View:
- First, you will add classes to the framework.solution
package that support breadth-first and depth-first state space
search and informed search as described in the lecture
presentations in the menu at left. Some provided classes are
complete and some require you to provide some
implementation. Specifically, you will implement:
- The state space search algorithm
- The state space expand algorithm
- The "number of tiles out of place" 8-puzzle heuristic
- The "sum of distances out of place" 8-puzzle heuristic
- The constructor for the A* solver object
Each of these will be rigorously tested apart from any GUI.
- Once you are sure your new solving classes work, you will add
controls to your ProblemGUI constructor (in
the framework.ui package) so that the user can request that
the problem be solved, step through a generated solution, and
change benchmarks where appropriate.
There also will be extra credit available.
First, be sure that your
ProblemSolver framework is up to date
with all of the additions required by Assignment 4 on
Graphical User
Interfaces and the Lab Exercises 8 and 9 on
Graphs.
The assignment and labs are accessible from the menu at left.
If your
ProblemSolver meets their requirements, you can continue
with the following steps.
Now that your problem solver works correctly, you will add these
controls and their requirements to your current graphical user
interface (GUI):
- Buttons labeled Solve and Next
- Drop-down lists labeled Search Type
and Benchmarks
- A bordered text area labeled Statistics
- The search type can be either breadth-first, depth-first,
best-first, or A* search
- The benchmarks, if they exist, can be selected by name,
otherwise they are empty
Below is a possible layout for the FWGC problem. Note:
- The user has clicked Search Type to reveal the search
options
- There is a
control for benchmarks but it is empty
You need not copy this
layout exactly; you can style and position the controls however you
like.
- Use ChoiceBox (in javafx.scene.control) for
drop-down selections.
- In the ProblemGUI
constructor create two StateSpaceSolver objects:
one for BFS and one for DFS. Also create a BestFirstSolver
and AStarSolver object.
- Maintain an instance field, say solver,
of type Solver and have the value change listener for your
search selection control appropriately set solver to one of
the four solver objects. Then use solver when initiating
searches and extracting solution information.
- The Solver method that initiates the search
is solve. The event handler for the Solve button
should call this method on the solver object. This way, the
search appropriate for the object's type will be done.
- The Solver class maintains search statistics that you can
obtain using its getStatistics method. Statistics can be
displayed in a JavaFX Label, which has methods for setting
size, padding and borders.
- The Solver class produces a Solution object from
which you can extract solution states for display in
your Next button event handler.
- To highlight move buttons while stepping through states in a
solution, find the button using the State
class's getMove method that gives the name of the move
producing a state, then use the button's setStyle method to
change its appearance.
- Bindings are useful for managing the disabling of buttons. For
example, to make the Next button enabled whenever
the Solve button is disabled, use:
- To use benchmarks in ProblemGUI:
- Create a selection control (e.g. ChoiceBox) and give
it benchmark options like this:
Each benchmark's toString method will be used to label
the selection options.
-
Suppose the selection control's name is "benchmarkOptions."
In its value listener, obtain the selected
benchmark like this:
The resulting Benchmark object has the information
needed to update the Problem object's initial and
current state before updating the display.
- The benchmark control should be disabled when the user is
stepping through a generated solution. The bind method
is useful for this.
This section describes the behavior of the new controls.
Below is a GUI for the 8-puzzle. Note that benchmark options are
visible. The options are labeled with the benchmark name and minimum
number of moves required.
The benchmark names and minimum solution lengths are obtained from
the
Problem object for the GUI.
Here the user has partially (manually) solved benchmark "
8-Puz
1" and is about to select the benchmark "
8-Puz 7":
When the user changes benchmarks:
- The current state displays the new benchmark, and
- The move count is reset to zero
Here the user has completed the selection of benchmark "
8-Puz 7":
Here the user has switched to A* search and
clicked
Solve. Note that benchmark selection is disabled while
the user steps through the solution.
This step requires you to provide the constructor for
the
AStarSolver class. However, this constructor is just a
slight modification of the
BestFirstSolver constructor, as
described in the
Informed Search lecture.
The files are available
under
Files in the menu.
-
Add the
AStarSolver.java file to your framework.solution
package under Source Packages
-
Add the AStarSolverTest.java file to your framework.solution
package under Test Packages
After adding these, your
Source Packages and
Test
Packages should look as shown here:
Complete the
AStarSolver constructor and
run the
AStarSolverTest.java file. You should get
the results shown below.
This step does not require any new code. The files are available
under
Files in the menu.
-
Add the
BestFirstSolver.java file to your framework.solution
package under Source Packages
-
Add the BestFirstSolverTest.java file to your framework.solution
package under Test Packages
After adding these, your
Source Packages and
Test
Packages should look as shown here:
Run the
BestFirstSolverTest.java file. You should get
results similar to those shown below.
Add the code below to your
PuzzleState class and complete
the
tilesOutOfPlace and
sumManhattan methods.
8-puzzle heuristics are discussed in the
Informed Search
lecture under
8-Puzzle Heuristic and
Comparing
Heuristics.
To test your 8-puzzle heuristics, add
the
PuzzleHeuristicTest.java class, available under
Files
in the menu, to the
domains.puzzle class under
Test
Packages:
Running the
PuzzleHeuristicTest.java class should produce:
The
expand method in
Solver.java is
abstract.
GraphSolver, which extends
Solver, provides an
implementation of
expand that simply returns a vertex's
adjacency list in a graph representation of the problem.
In general,
expand(u) simply returns a list of vertices that are
one move away from
u in the problem's state space.
In this step, you will extend
Solver with
a
StateSpaceSolver class that implements
expand without a
graph representation.
Add the
StateSpaceSolver.java class, available
under
Files in the menu, to your
framework.solution
package:
StateSpaceSolver requires that you implement the
expand
method, which you should do now.
The lecture on
State Space Search describes how to use the
problem's
Mover object to accomplish this.
StateSpaceSolver, like
GraphSolver, is an abstract class
with two subclasses,
BFSStateSpaceSolver
and
DFSStateSpaceSolver, that perform breadth-first and
depth-first searches of the problem state space, respectively.
Add these subclasses, which are complete and available from the menu,
to
framework.solution:
The test of the state space solver is similar to that for the graph
solver.
Add the
StateSpaceSolverTest.java class, available from the
menu, to your
Test Packages:
Run the
StateSpaceSolverTest.java class, which is similar to the
GraphSolverTest.java class and will get similar
results. However, since it does not have to create graphs, it is faster:
In this step, implement and test the generic search algorithm described
in the
State Space Search lecture.
The substeps are accessible from the menu at left.
In testing your search, you may encounter
Out of Memory
errors. Here are some possible causes:
- Not clearing the queue at the beginning of the
search. Doing multiple tests during one run without clearing
at initiation could fill up the queue.
- Calling containsValue() for the vertices
hashmap instead of containsKey()
-
If state space search works for the farmer problem but not the
puzzle problem, then the issue may be with either PuzzleState
or PuzzleMover. PuzzleState
may not have valid equals and hashCode
methods, or PuzzleMover, which you were supposed to write test
cases for in an earlier assignment, has bugs.
Add the
Statistics.java class (available under
Files in
the menu) to your
framework.solution package:
Statistics.java is complete.
Add the abstract
Solver.java class (available under
Files
in the menu) to your
framework.solution package:
Solver.java is complete except for the
search method,
which you should implement now.
The
search method and the algorithm it implements are described
in detail in the
State Space Search lecture.
Test your
search method by extending
Solver for graph
search. This involves adding the files below to your framework. They
are complete and available under
Files in the menu.
-
Add the
files GraphSolver.java, BFSGraphSolver.java,
and DFSGraphSolver.java to your framework.solution
package under Source Packages
-
Add the GraphSolverTest.java file to your framework.solution
package under Test Packages
After adding these, your
Source Packages and
Test
Packages should look as shown here:
Run the
GraphSolverTest.java file. You should get the
results shown below. Since the tests run through the 8-puzzle
benchmarks, the test could take 10-20 seconds.
The lecture presentations on State Space Search and Informed
State Space Search, in the menu at left, are directly relevant to
this assignment.
The previous assignment on Graphical User Interfaces, in the
menu at left, is directly relevant to this assignment.
The previous labs exercises on Graphs, in the menu at left, are
directly relevant to this assignment.
As with the previous assignment,
- Make sure your identifying information is in the class comments
of all your files
- Export your ProblemSolver project to
ProblemSolver.zip.
- Submit ProblemSolver.zip by going to
and clicking Submission under Assignment:
Automated Problem Solving.
Note the general
Submission Policy in the menu at left.
Your project will be inspected, tested, and run by the lab instructor. Grading criteria:
- (15 points) Successful execution of the tests:
- GraphSolverTest.java
- StateSpaceSolverTest.java
- PuzzleHeuristicTest.java
- BestFirstSolverTest.java
- AStarSolverTest.java
- (15 points) Successful modification of ProblemGUI
and implementation of the stated requirements
for automated problem solving. As in the previous assignment, your
GUI will be run by launching your ProblemTabPaneTest class.
- (8 points) Extra credit: Successful implementation and
demonstration of the 15-Puzzle, a tab for which must be added
to ProblemTabPane.