Rafael Gonzalez Write Up

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 4

Implementing Selection sort into A*

Rafael Gonzalez
2/25/2022

1. Introduction
This assignment focused on the implementation of A* into an AI system that would solve
a given rush hour state. A* is a traversal technique that makes use of a sorted list and a
heuristic to find an optimal path from the initial state to the goal state. The algorithm used
to decide the pathing for A* is as follows: f(n) = g(n) + h(n). Where g(n) is the number of
steps taken to get to the current state, h(n) is the number used to determine how close the
current state is to the desired goal state. The complexity for this is exponential unless
|h(n) – h(n*)| <= O(log h*(n)). With this in mind, it becomes increasingly important to
have a reliable algorithm to determine which states are closer to the goal than others. By
doing so ideally, the least amount of nodes are explored and thereby reducing the
computation necessary by the computer and thereby time spent waiting.

2. Methods/Approaches
The most complex part of this entire project interestingly enough is coming up with how
to represent the rush hour board in the code. While there are a few different ways to
represent a board I found the best solution for myself was to create a dictionary. The
dictionary is made up of 3 components. First, the key which identifies each car. The key
is made up of each car’s primary identifying ID. the values associated with the key are
the cars, x, y, orientation, length, and whether it’s a goal car or not respectively. This
dictionary represents the board at every given state. With representation established next
was parsing the board, simple enough this was just using the built-in python CSV library,
taking the CSV reading it and pushing the values into the appropriate places, and then
adding them to a dictionary. Now with the first board state loaded and ready to go came
how to create the following board states. Before beginning on any coding the importance
lay in determining the expected outcomes. From board1.board the first board state returns
3 distinct moves; car 1 moves 1 back, car 4 moves 1 forward and car 5 moves 1 up. This
all with the understanding that each car will only move one space and one time per board
state. With that then I began programming, setting up the possible moves function. This
function is designed to take any given board state and create a list of possible moves
given that state. Limiting to the board boundaries. Of course, now there is the issue of
other cars on the board, from here the function taken spaces are used. This is used to
determine the set taken spaces on any given board state. Combining taken spaces and
possible moves it is determined from board state 1 the initial one parsed from the CSV
there are 3 distinct moves. Comparing these to the ones I found before and I had a
functioning first creation of board states.
This began the work now in the main. First I created a while loop that would end only
based on whether the goal state had been reached. At first, I figured iterating over a
normal queue would work, I set up a queue popped an item off, and ran with it. At this
juncture, I only attacked board states to the queue. Running through some pretty
self-explanatory steps the board would be changed and copied to an altogether new board
then re-appended to the queue. The first thing I picked up from here was to create a
priority queue. Attaching a number which would determine which board state should go
first. Starting with the h(n) = 0 and of course g(n) = to the number of moves made to get
to a given board state. From here the queue became a series of tuples. The items in the
queue had 3 elements, a key which was the f(n). The board state itself was the second
item, the final item being the moves taken to achieve that state. With this, the heuristic
could be made. The moves made were attached as a list of tuples themselves, taking the
length of this was the easiest way to determine how many steps had been taken and this
became the identifier for which item in the queue should go first.

From here came the step of skipping certain states. Given that my possible moves were
independent of any previous moves taken by any board state it was really easy to simply
get stuck in a loop of moving one car forward and back. This was obviously not very
optimal. So another list was implemented of just straight board states. Each state was one
previously visited in the code. Before any step was taken after the popping of the first
item off in the queue it was determined whether that board state had already been
explored. If the board state was explored it was thrown away and the next was taken.
With the boards now able to run it really became a deal of setting up a proper goal state
finder so that the code would eventually stop running. This was as simple as finding the
goal car, which just meant searching across the cars to determine whether it was the goal
car. From here it just became determining where that car was.

With the code now able to run at h(n) = 0 it was time to come up with a heuristic. Which
started as just straight linear but I decided it would heavily cut down on time if I also
determined how many cars would be in the way of the goal car as well. Thus
implementing a taken_spaces_infront which just determined what spaces were taken that
were not the goal cars taken spaces. Then determining if any of those were in the car’s
path. With that, I was able to solve the board1 in 21 moves, but for whatever reason
board 39 looped forever.

3. Results
Able to complete board1 but not board39. I was not entirely sure but I believe it came
down to exploring too many nodes. I think that my heuristic was too simple to properly
dive deeper through one set of moves and so board39 simply would go on for far too
long. I wasn’t sure how to increase the effectiveness of the heuristic, it was why I initially
began implementing the moves in front to reduce the importance of certain states. The
only thing I can think of is writing some code to prioritize the movement of the goal car
over all others, but I was unsure how to implement that.

4. Complications
These were numerous and usually pretty stupid. My first complication came with simply
creating the board state. I overthought myself figuring I had to show the entire board at
first and eventually came to the conclusion that all that mattered was determining where
the cars were in any given space. Next came the looping and cutting down on
unnecessary expansion. I spent the most time carefully making sure that each board
created was able to get into the queue be retrieved be changed or be kicked off depending
on whether it had been visited or not.
I had a significant amount of trouble simply just debugging the steps of creating new
board states and determining the goal car’s location. Most of this came down to minor
errors and logical typos. Things like not properly updating sections of the code given
changes earlier in the code.
The heuristic itself became an important and thoroughly overthought step. I think most of
my complications came down to fundamental ignorance. Whether it was because I didn’t
realize how to properly implement something, such as the sorting method, as well as how
to update code around that. To simply not understanding the fundamental simplicities of
certain things. Such as the heuristic which I thought would be much more complicated
than initially considered.

5. Conclusion
The assignment was to implement A* to solve a problem by traversing a set of options
and determining which were the best. This came down to 1 creating a board that the code
can understand. 2 creating a method to run through that board and get sets of possible
moves. 3 creating new boards based on possible moves. 4 determining the value of
traveling to certain boards, whether there was any point, whether to skip over them etc.
It really comes down to an effectively weighted heuristic. Something that properly
determines how important certain aspects are to reaching the goal state. While not
implemented in my code I believe fundamentally that heavily weighting the movement as
well as prioritizing the movement of the goal car may have been a better approach to this
problem. Sadly fault all my own I simply didn’t have the time to come to that conclusion
and also rewrite my code to a point where it was usable.

6. Acknowledgments
Almost too many to name, but some of the biggest collaborators for me were. Professor
Huelsman, Alexander Cary Whipple, Youseff Elshaarawy, Gabriel Humphery, John
Pignato, and likely some more I am forgetting. Alex acted most as a sounding board for
ideas as well as really helping me figure out how to work through certain parts of code.
Helping in the development, of course, was Professor Huelsman. John Pignato and
Gabriel Humphery both also helped in development. Gabriel helped initially explain the
heuristic side of things, John Pignator gave a useful pointer for implementing A*.
Youseff I collaborated with lightly in helping figure out how to set up the board and
determine the all-important heuristics.

You might also like