- Project Outline
- Project Introduction
- Question 1: Finding Fixed Food Dot using Depth First Search
- Question 2: Breadth First Search
- Question 3: Varying the Cost Function
- Question 4: A* search
- Question 5: Finding All the Corners
- Question 6: Corners Problem: Heuristic
- Question 7: Eating All The Dots
- Question 8: Suboptimal Search
- Contributors
In this problem, pacman should find a path to reach a Food Dot, each step will cost pacman 1. We implemented the Depth First Search algorithm in
search.py
in the corresponding function.
We create a DFSNode
class to store the state | action | parent, of each state in the problem.
In addition, we created the function get_path
in DFSNode
, allowing us to reconstruct the path from root to that node.
-
Is the exploration order what you
would have expected?
yes it is
-
Does Pacman actually go to all the explored squares on his way to the
goal?
No, there might exists an explored square that is not located on the root-to-goal path
-
Is a 130 a least cost solution for
mediumMaze
? If not, think about what depth-first search is doing wrong.
No, it is not a least cost solution, DFS returns the first path root-to-goal that it finds without it being an optimal solution
$ python pacman.py -l tinyMaze -p SearchAgent
$ python pacman.py -l mediumMaze -p SearchAgent
$ python pacman.py -l bigMaze -p SearchAgent
In this problem, pacman should find a path to reach a Food Dot, each step will cost pacman 1. We implemented the Breadth First Search algorithm in
search.py
in the corresponding function.
We create a BFSNode
class to store the state | action | parent, of each state in the problem.
In addition, we created the function get_path
in BFSNode
, allowing us to reconstruct the path from root to that node.
-
Does BFS find a least cost solution?
yes it does
$ python pacman.py -l mediumMaze -p SearchAgent -a fn=bfs
$ python pacman.py -l bigMaze -p SearchAgent -a fn=bfs -z .5
$ python eightpuzzle.py
BFS found a path of 5 moves: ['up', 'right', 'up', 'left', 'left'] After 1 move: up
Press return for the next state... After 2 moves: right
Press return for the next state... After 3 moves: up
Press return for the next state... After 4 moves: left
Press return for the next state... After 5 moves: left
In this problem, pacman should find a path to reach a Food Dot, each step will cost pacman some value pre-defined by the
costFn
function.
We implemented the Uniform Cost Search algorithm in search.py
in the corresponding function.
We create a UCSSearchProblemNode
class to store the state | action | parent and the cost of the path from the root to that node, of each state in the problem i.e. g(n)
.
In addition, we created the function get_path
in UCSSearchProblemNode
, allowing us to reconstruct the path from root to that node.
$ python pacman.py -l mediumMaze -p SearchAgent -a fn=ucs
$ python pacman.py -l mediumDottedMaze -p StayEastSearchAgent
$ python pacman.py -l mediumScaryMaze -p StayWestSearchAgent
We implemented the A* search algorithm in search.py
in the corresponding function.
We create a AStarNode
class to store the state | action | parent and the cost of the path from the root to that node, of each state in the problem + the heuristic value of that state i.e. g(n) + h(n)
.
$ python pacman.py -l bigMaze -z .5 -p SearchAgent -a fn=astar,heuristic=manhattanHeuristic
-
What happens on
openMaze
for the various search strategies?- DFS:
DFS is not optimal, it will not find the shortest path to the goal, it will find the first path to the goal.
- Path found with total cost of 298 in 0.0 seconds
- Search nodes expanded: 576
- Pacman emerges victorious! Score: 212
- BFS:
BFS is optimal, it will find the shortest path to the goal.
- Path found with total cost of 54 in 0.0 seconds
- Search nodes expanded: 682
- Pacman emerges victorious! Score: 456
- UCS:
UCS is optimal, it will find the shortest path to the goal.
- Path found with total cost of 54 in 0.0 seconds
- Search nodes expanded: 682
- Pacman emerges victorious! Score: 456
- A*
A* is optimal, it will find the shortest path to the goal.
- Path found with total cost of 54 in 0.0 seconds
- Search nodes expanded: 550
- Pacman emerges victorious! Score: 456
- DFS:
In this problem, pacman should find a path to reach all the Corners in the maze, each step will cost pacman some value pre-defined by the costFn
function.
We used
self.startState = self.CornersState(self.startingPosition, [False, False, False, False])as a representation of the start state, where the boolean values represent if the corner is visited or not.
We implemented the CornersProblem
class in searchAgents.py
to represent the problem.
Inside that class we created a CornersState
class to represent the state of the problem, which is a tuple of the current position and boolean values representing if the corner is visited or not.
We implemented the getSuccessors
function to return the successors of the current state, the isGoalState
function to check if the current state is the goal state and the getStartState
function to return the start state of the problem.
$ python pacman.py -l tinyCorners -p SearchAgent -a fn=bfs,prob=CornersProblem
$ python pacman.py -l mediumCorners -p SearchAgent -a fn=bfs,prob=CornersProblem
In this problem, we implemented the
cornersHeuristic
function in searchAgents.py
to return the heuristic value of the current state.
We created a Admissible
and Consistent
heuristic function heuristic_found_by_ga_for_corners_problem
found in searchAgents.py
-
We used a genetic algorithm to find the best heuristic function.
In
genetic_algorithm.py
you can modify on which maze you want to train ("tinyCorners", "mediumCorners", "bigCorners")
To run:python install -r requirements.txt
python genetic_algorithm.py -p CornersProblem -l mediumCorners
- Encoding A chromosome is a set of 0 and 1 (i.e.
- Fitness Function To evaluate the fitness of a chromosome, we ran aStarSrarch on the problem where the heuristic used is
- Selection We used
- Crossover We used
- Mutation We used
- Stopping Criteria We used
- Results We ran the genetic algorithm for 30 generations and the best heuristic function we found is:
010011
) where each digit, represent whether its corresponding heuristic is used.
The full list of heuristic functions is:HEURISTICS_LIST = [ manhattan_distance, euclidean_distance, diagonal_distance, max_heuristic, min_heuristic, null_heuristic ]
How? look at the below example:010011
means thateuclidean_distance, min_heuristic, null_heuristic
are being used
new_heuristic
and we returned:
(1/nodes_expanded)*(10**c)
Where c is a small integer just to make even small changes in nodes_expanded a more valuable thing to the algorithm
new_heuristic
is defined as follow (pseudo code):def new_heuristic(start, goal): set_of_heuristic_allowed = extract_allowed_heuristics(chromosome) values = [h(start, goal) for h in set_of_heuristic_allowed] return method_of_joining_heuristics(values)
where
method_of_joining_heuristics
is one of:method_of_joining_heuristics = { 'max' : max, 'min' : min, 'mean' : lambda x: sum(x)/len(x), 'mode' : lambda x: max(set(x), key=x.count), 'median' : lambda x: median(x), 'range': lambda x: max(x) - min(x), }
ranking selection
to select the best heuristic functions.single point crossover
to create new heuristic functions. Crossover probability is 0.8.bitstring mutation
to mutate the heuristic functions allowed. Mutation probability is 0.2.number of generations
as a stopping criteria. We ran the genetic algorithm for 30 generations.Best solution: (1, 1, 1, 1, 1, 1)
Best Fitness: 1
Best Cost (number of nodes expanded): 741
Best solution is made of: RANGE( manhattan_distance, euclidean_distance, diagonal_distance, max_heuristic, min_heuristic, null_heuristic, )
Where
RANGE = lambda x: max(x) - min(x)
thus the best heuristic combination is
RANGE( manhattan_distance, euclidean_distance, diagonal_distance, max_heuristic, min_heuristic, null_heuristic, )
-
In
searchAgents.py
in the functioncornerHeuristic
, we generated all the permutations of the cornerns i.e. ((c1, c2, c3, c4), (c2, c4, c1, c3) . . .)
Then for each of those permutations we used ourheuristic_found_by_ga_for_corners_problem
to calculate the total path cost of that permutation. Then we return the minimum path cost of a permutation.
Pseudo Code:min_cost = infinity for permutation in permutations_of_corners: cost = 0 for i in range(len(permutations_of_corners)-1): cost += heuristic_found_by_ga_for_corners_problem(perm[i], perm[i+1]) if cost < min_cost: min_cost = cost
$ python pacman.py -l mediumCorners -p AStarCornersAgent -z 0.5
$ python pacman.py -l bigCorners -p AStarCornersAgent -z 0.5
In this problem, we implemented the
foodHeuristic
function in searchAgents.py
to return the heuristic value of the current state.
We created a Admissible
and Consistent
heuristic function.
The function is
heuristic_found_by_ga_for_food_problem
We created a
exactDistanceUsingAStar(start, goal)
function that returns the actual cost of the path from the start to the goal using the AStarSearch
algorithm and heuristic_found_by_ga_for_food_problem
Then we found
closest_food
and furthest_food
using heuristic_found_by_ga_for_food_problem
Then we returned the heuristic value as:
return exactDistanceUsingAStar(start, closest_food) + heuristic_found_by_ga_for_food_problem(closest_food, furthest_food)We ran the genetic algorithm for 30 generations using
python install -r requirements.txt
python genetic_algorithm.py -p FoodSearchProblem -l trickySearchand the best heuristic function we found is:
Best solution: (0, 0, 1, 1, 1, 0) Best Fitness: 24 Best Cost (number of nodes expanded): 4089 Best solution is made of: MAX( diagonal_distance, max_heuristic, min_heuristic, )
$ python pacman.py -l trickySearch -p AStarFoodSearchAgent
$ python pacman.py -l mediumSearch -p AStarFoodSearchAgent
In this section, we created an agent that always greedily eats the closest dot. Using
ClosestDotSearchAgent
in searchAgents.py, we implemented a function that finds a path to the closest dot findPathToClosestDot
We used BFS
to find the path to the closest dot using AnyFoodSearchProblem
as gameState for BFS
.
We modified in AnyFoodSearchProblem
the function isGoalState
to return true if the current state is a food.
$ python pacman.py -l bigSearch -p ClosestDotSearchAgent
$ python pacman.py -l mediumSearch -p ClosestDotSearchAgent
- Charbel Fayad - charbel.fayad01@lau.edu - 202102394
- Manel Roumaissa Benabid - manelroumaissa.benabid@lau.edu - 201906232
This project is licensed under the MIT License - see the LICENSE.md file for details