Академический Документы
Профессиональный Документы
Культура Документы
It is hereby certified that the work which is being presented in the B. Tech Mini Project Report
entitled "MAZE SOLVER" in partial fulfilment of the requirements for the award of the
degree of Bachelor of Technology and submitted in the Department of Computer Science &
Engineering of Shri Mata Vaishno Devi University , Katra ,J&K is an authentic record of our
own work carried out during a period from August to November 2018 under the guidance of
Mr. Manoj Verma
We hereby declare that the Project Report entitled “MAZE SOLVER” is an authentic record of our
own work during the period from August,2018 to November,2018 for the award of degree of
Engineering.
( Project Coordinator)
ii
ABSTRACT
Many great ideas in artificial intelligence languish in textbooks for decades because we don’t have
the computational power to apply them. Pathfinding algorithm addresses the problem of finding the
shortest path from source to destination and avoiding obstacles. One of the greatest challenges in
the design of realistic Artificial Intelligence (AI) in computer games is agent movement. Pathfinding
strategies are usually employed as the core of any AI movement system.
Mazes are a simplified form of navigation. Developments used in efficient maze solving have
helped other navigation problems. This can be used as a form of navigation to achieve the shortest
path for the situation like:
Medical attention
Rescue operation
To meet urgent requirements
This project report is about using path finding algorithms to solve a maze, given as an image, and
comparing the efficiency of these algorithms. Efficiency is measured for various parameters to find
the optimum path finding algorithm.
Various algorithms have been developed to find the most efficient path in the minimum time
between nodes. Some of these algorithms are A*, Dijkstra, Breadth First, Depth First. These
algorithms can’t be directly applied to solve mazes as mazes are in the image form. First images
with maze should be converted to a graph on which these algorithms can be applied. Time required
and the number of nodes explored is recorded for each algorithm to compare them.
iii
ACKNOWLEDGEMENT
Team effort together with precious words of encouragement and guidance makes daunting tasks
achievable. It is a pleasure to acknowledge the direct and implied help we have received at various
stages in the task of developing the project. It would not have been possible to develop such a
project without the furtherance on part of numerous individuals. We find it impossible to express
our thanks to each one of them in words, for it seems too trivial when compare to the profound
encouragement that they extended to us.
Our sincere thanks to Mr. Manoj Verma for believing in us and providing motivation all through.
Without his guidance, this project would not be such a success.
At last, we thank the almighty, who had given the strength to complete this project on time.
Finally, we would like to thank our parents, all friends, and well-wishers for their valuable help and
encouragement throughout the project.
_______________________________________________________________________________
iv
TABLE OF CONTENTS
CANDIDATE DECLARATION ii
ABSTRACT iii
ACKNOWLEDGEMENT iv
TABLE OF CONTENTS v - vi
LIST OF FIGURES vii
LIST OF TABLES viii
v
3.2.4 A* Algorithm 29
3.2.5 Leftturn 36
Chapter 4: Result 40 – 44
4.1 Command Line Output 40
4.1.1 Syntax 40
4.1.2 Output 40
4.2 GRAPH 42
4.2.1 Scatter Plot Graph 42
4.2.2 Axis 42
4.2.3 Output 42
Chapter 5: Conclusion 45 – 48
5.1 Mazes 45
5.2 Tables 45
5.2.1 Time Taken 45
5.2.2 Nodes Explored 46
5.2.3 Length Of Path Found 47
5.3 Conclusion 48
vi
LIST OF FIGURES
vii
LIST OF TABLES
viii
CHAPTER 1: INTRODUCTION
Path finding generally refers to find the shortest route between two end points. Examples of
such problems include transit planning, telephone traffic routing, maze navigation and robot
path planning. As the importance of game industry increases, pathfinding has become a
popular and frustrating problem in game industry. Games like role-playing games and real-
time strategy games often have characters sent on missions from their current location to a
predetermined or player determined destination. The most common issue of pathfinding in a
video game is how to avoid obstacles cleverly and seek out the most efficient path over
different terrain. Pathfinding uses are also evident in networking where optimum path from
start node to the end node is required. In maps, when the direction from one place to the
another is required, pathfinding algorithms are used.
Pathfinding could be used to give answers to the question “How do I get from source to
destination?”. In most cases, the path from source (current point) to the destination (next
point) could possibly include several different solutions, but if possible, the solution needs
to cover the following goals:
Mazes are problems with obstacles, a start node and an end node. The solution to the maze is
the path from start node to the end node avoiding all the obstacles. Pathfinding algorithms
can be used to solve the mazes.
Various algorithms have been developed to find the most efficient path in the minimum time
between nodes. Some of these algorithms are A*, Dijkstra, Breadth First, Depth First.
These algorithms can’t be directly applied to solve mazes as mazes are in the image form.
First images with maze should be converted to a graph on which these algorithms can be
applied. Time required and the number of nodes explored is recorded for each algorithm to
compare them.
1
An example of a maze with its solution is shown in figure 1.1.
Many great ideas in artificial intelligence languish in textbooks for decades because we
don’t have the computational power to apply them. That’s what happened with neural
networks, a technique inspired by our brains’ wiring that has recently succeeded in
translating languages and driving cars. Now, another old idea—improving neural
networks not through teaching, but through evolution—is revealing its potential. Five
new papers from Uber in San Francisco, California, demonstrate the power of so-called
neuro evolution to play video games, solve mazes, and even make a simulated robot walk.
At Uber, such applications might include driving autonomous cars, setting customer
prices, or routing vehicles to passengers.
2
Python is a good programming language for beginners. It is a high-level language,
which means a programmer can focus on what to do instead of how to do it. Writing
programs in Python takes less time than in some other languages.
Python drew inspiration from other programming languages like C, C++, Java, Perl,
and Lisp.
Python has a very easy-to-read syntax. Some of Python's syntax comes from C,
because that is the language that Python was written in. But Python uses whitespace
to delimit code: spaces or tabs are used to organize code into groups. This is different
from C. In C, there is a semicolon at the end of each line and curly braces ({}) are
used to group code. Using whitespace to delimit code makes Python a very easy-to-
read language.
Its standard library is made up of many functions that come with Python when it is
installed. On the Internet there are many other libraries available that make it
possible for the Python language to do more things. These libraries make it a
powerful language; it can do many different things.
Web development
Game programming
Desktop GUIs
Scientific programming
Network programming
3
The Python interpreter and the extensive standard library are freely available in source
or binary form for all Mini platforms from the Python Web site and extensive
standard library are free, https://www.python.org/, and may be freely distributed. The
same site also contains distributions of and pointers to many free third-party Python
modules, programs and tools, and additional documentation.
The Python interpreter is easily extended with new functions and data types
implemented in C or C++ (or other languages callable from C). Python is also suitable
as an extension language for customizable applications. Shown in figure 1.2 is the
Python Console.
Matplotlib tries to make easy things easy and hard things possible. You can generate
plots, histograms, power spectra, bar charts, errorcharts, scatterplots, etc, with just a
few lines of code. Shown in figure 1.3 are some on the mstplotlib plots.
4
.
Pillow is a fork of PIL (Python Image Library), started and maintained by Alex
Clark and Contributors. It was based on the PIL code, and then evolved to a better,
modern and friendlier version of PIL. It adds support for opening, manipulating, and
saving many different image file formats. A lot of things work the same way as the
original PIL.
The filetypes that are supported by Pillow are: BMP EPS GIF IM JPEG MSP PCX
PNG PPM TIFF WebP ICO PSD PDF Some of the file types, you only have the
possibility to read, and others you can only write. To see the full list of supported
file types, and more information about them, take a look at the handbook for Pillow.
The Python Imaging Library adds image processing capabilities to your Python
interpreter. This library provides extensive file format support, an efficient internal
representation, and fairly powerful image processing capabilities.
The core image library is designed for fast access to data stored in a few basic pixel
formats. It should provide a solid foundation for a general image processing tool.
Let’s look at a few possible uses of this library.
For debugging, there’s also a show () method which saves an image to disk
and calls an external display utility.
1.3 REQUIREMENTS
Python version 2.7
PIL library of the python
mathplotlib library of python
Environment variable must be set for python
Supported Operating Systems: Windows 7 or upper, any linux distribution
and MacOS
6
CHAPTER 2: BACKGROUND
A maze is a puzzled way which consists of different branch of passages where the aim of the
solver is to reach the destination by finding the most efficient route within the shortest possible
time. Artificial Intelligence plays a vital role in defining the best possible way of solving any
maze effectively. Graph theory appears as an efficient tool while designing proficient maze
solving techniques. Graph is a representation or collection of sets of nodes and edges and
graph theory is the mathematical structure used to model pair wise relations between these
nodes within the graph. By proper interpretation and mathematical modelling, it is possible to
figure out the shortest distance between any of the two nodes. This concept is deployed in
solving unknown maze consisting of multiple cells. Depending on the number of cells, maze
dimension may be 8×8, 16×16 or 32×32. Each cell can be considered as a node which is
isolated by walls or edges. This is nothing but the interpretation of graphs onto a maze. This
analogy between graph and maze provides the necessary foundation in developing maze
solving algorithms.
There are a number of different maze solving algorithms, that is, automated methods for
the solving of mazes:
Fibonacci Heap
Dijkstra
Depth first algorithm
Breadth first algorithm
A* algorithm
In this work we have introduced a new method of maze solving for any kind of mazes.
In order to solve a complex line maze, the main problem arises is to map the whole
maze. Without mapping the whole maze, robot cannot find the shortest path. So, our
main target is to map the whole maze and then find the shortest path.
In mobile robotics, maze solving problem is one of the most common problems and to
solve this problem an autonomous robot is used. Mazes can be of different kinds, like-
without any loops, having loops, grid system or without grid system. Numerous
7
methods and algorithms have been developed having their own merits and techniques
such as flood fill algorithm, breadth first-search, Prim’s algorithm etc. But they all need
to know the position of the goal. So, they are not appropriate for solving mazes where
the goal is unknown until discovering.
These equations are the final equations which lead us to the exact length of a straight
line from wheel encoder reading of a line follower robot. This equation also shows that
if we know the minimum deviation for turn (h) and other constants with the total turn,
we can predict the path distance to a fair approximation without even knowing the
travelled distance. That means, for rough calculation of distance, wheel encoder is not
needed at all.
Objective
Objective is to find the best algorithm for path finding problem by comparing the real
time applications of various algorithms based on various parameters.
Type of Research
Quantitative Analysis will be performed on the observed data to compare the result of
various algorithms. Time required, distance covered and many other factors are
quantized and analyzed to get result.
Sampling Method
The research sampling method that will be used in this study is random sampling to
obtain a more scientific result that could be used to represent as many cases as possible.
Perfect Mazes, Braid Mazes and Combo Mazes will be used to replicate various real-
life problems.
8
Different algorithms perform better in different cases, so it is important to identify those
cases and check for as many cases as possible. Randomly selected problems will be
applied on all algorithms to simulate real time scenario.
Method Approach
Algorithms will be tested on different parameters to compare them. Parameters used
are:
1. Time Required
2. Distance Covered
3. Space Required
4. Iterations Change
All these parameters will be used in conjunction to check efficiency of algorithms.
Data Analysis
Descriptive statistics quantitative data analysis will be used by plotting the result on
charts and tables for graphic representation and easier comparison of data from various
types of mazes of different algorithms.
Limitations
Mazes with more than 100 megapixels will require more than 16GB of ram.
[3] “Three Fastest Shortest Path Algorithms on Real Road Networks: Data Structures
and Procedures.”: It is well known that computing shortest paths over a network is
an important task in many network and transportation related analyses. Choosing an
adequate algorithm from the numerous algorithms reported in the literature is a
critical step in many applications involving real road networks. In a recent study, a
set of three shortest path algorithms that run fastest on real road networks has been
identified. These three algorithms are: the graph growth algorithm implemented with
two queues, the Dijkstra algorithm implemented with approximate buckets, and the
Dijkstra algorithm implemented with double buckets.
[4] A comprehensive and comparative study of maze-solving techniques by
implementing graph theory.”: Solving a 3-D square maze through an autonomous
robot is gaining immense popularity among the robotics aspirants. Without
deploying Artificial Intelligence technique it’s not possible to do this task efficiently.
Several algorithms which originate from graph theory (GT) and non-graph theory
9
(NGT) are currently being used to program the robot or mice. This paper has
elucidated how graph theory can be used to solve mazes. With adequate investigation
it is verified how graph theory dominates over non-graph theory algorithms. The
process of generating maze solving algorithm from graph theory is also explained.
To compare the algorithms efficiency, they are simulated artificially and a
comprehensive study is done by interpreting the statistics of interest.
[5] “Path finding in games.”: Commercial games can be an excellent testbed to artificial
intelligence (AI) research, being a middle ground between synthetic, highly
abstracted academic benchmarks, and more intricate problems from real life. Among
the many AI techniques and problems relevant to games, such as learning, planning,
and natural language processing, pathfinding stands out as one of the most common
applications of AI research to games. This document surveys the recent work in
pathfinding in games, identify challenges and potential directions for future work.
[6] “Computing the shortest path: A search meets graph theory.”: This paper proposes
shortest path algorithms that use A* search in combination with a new graph-
theoretic lower-bounding technique based on landmarks and the triangle inequality.
This algorithm compute optimal shortest paths and work on any directed graph. The
results show that the most efficient of this new algorithm outperforms previous
algorithms, in particular A* search with Euclidean bounds, by a wide margin on road
networks and on some synthetic problem families.
[7] A*-based pathfinding in modern computer games.”: Pathfinding in computer games
has been investigated for many years. It is probably the most popular but frustrating
game artificial intelligence (AI) problem in game industry. Various search
algorithms, such as Dijkstra’s algorithm, bread first search algorithm and depth first
search algorithm, were created to solve the shortest path problem until the emergence
of A* algorithm as a provably optimal solution for pathfinding. Since it was created,
it has successfully attracted attention of thousands of researchers to put effort into it.
A long list of A*-based algorithms and techniques were generated. This paper
reviews a number of popular A*-based algorithms and techniques from different
perspectives. It aims to explore the relationship between various A*-based
algorithms.
[8] “Heuristic search viewed as path finding in a graph.”: This paper presents a particular
model of heuristic search as a path-finding problem in a directed graph. A class of
graph-searching procedures is described which uses a heuristic function to guide
10
search. Heuristic functions are estimates of the number of edges that remain to be
traversed in reaching a goal node. A number of theoretical results for this model, and
the intuition for these results, are presented. They relate the efficiency of search to
the accuracy of the heuristic function. The results also explore efficiency as a
consequence of the reliance or weight placed on the heuristics used.
[9] “Pathfinding of 2D & 3D game real-time strategy with depth direction A∗ algorithm
for multi-layer.”: The shortest path analysis is artificial intelligent which developed
capability about think cause and effect, learning and thinking like human. Heuristic
technique is method for solving a problem which gets result or not. It may return
unexpected value which depends on each problem. 3D game Realtime strategy uses
shortest path analysis control path for movement of character, wheeled vehicle,
animals, and fantasy buildings. It uses path for movement ever time, both in sea, terra
and sky (three layers). The position of 3D object use refers 2D coordinate. This
research proposes two essences. It proposes comparison rapidity, intelligence and
efficiency about seven path finding algorithms which is principle algorithm are
familiar. These algorithms used in game computer extensively as follows Depth First
Search, Iterative Deepening, Breadth First Search, Dijkstra's Algorithm, Best First
Search, A-Star Algorithm (A∗), Iterative Deepening A∗. Besides, this research
proposes Depth Direction A∗ algorithm method which use linear graph theory to
cooperate with A∗ Algorithm and increase efficiency to avoid barrier object on maps
and search for shortest path of multi-layer.
11
CHAPTER 3: DESCRIPTION
Mazes are problems with obstacles, a start node and an end node. The solution to the
maze is the path from start node to the end node avoiding all the obstacles. Pathfinding
algorithms can be used to solve the mazes.
12
ii. else create node only if no path above and below.
e. if node is created
i. if topnode available, connect to topnode.
ii. else if there is path below add to topnode.
4. Find the white pixel at the last row of the image.
a. If the white pixel is not found close the program.
b. If the white pixel is found, set it as end node and connect
it to the top node.
This algorithm, set intersection pixel and corner pixel as the node instead of setting
all white pixel as node to reduce the space required to store graph. As the size of image
increases, space required for graph increases exponentially thus reducing space
requirement is imperative. Consider the image shown in 3.1, it satisfies all the criteria
set for image.
For this 10x10 image, the graph created will have 23 nodes including the start and the
end node as shown in Figure 3.2.
13
Figure 3.2: Graph For The Maze
On the graph created from the image, path finding algorithms can be applied to solve
the maze.
3.1.2 CODE FOR CONVERTING IMAGE TO GRAPH
class Maze:
class Node:
def init (self, position):
self.Position = position
self.Neighbours = [None, None, None, None]
#self.Weights = [0, 0, 0, 0]
width = im.size[0]
height = im.size[1]
data = list(im.getdata(0))
self.start = None
self.end = None
14
count = 0
# Start row
for x in range (1, width - 1):
if data[x] > 0:
self.start = Maze.Node((0,x))
topnodes[x] = self.start
count += 1
break
rowoffset = y * width
rowaboveoffset = rowoffset - width
rowbelowoffset = rowoffset + width
leftnode = None
n = None
if cur == False:
15
# ON WALL - No action
continue
if prv == True:
if nxt == True:
# PATH PATH PATH
# Create node only if paths above or below
if data[rowaboveoffset + x] > 0 or data[rowbelowoffset + x] > 0:
n = Maze.Node((y,x))
leftnode.Neighbours[1] = n
n.Neighbours[3] = leftnode
leftnode = n
else:
# PATH PATH WALL
# Create path at end of corridor
n = Maze.Node((y,x))
leftnode.Neighbours[1] = n
n.Neighbours[3] = leftnode
leftnode = None
else:
if nxt == True:
# WALL PATH PATH
# Create path at start of corridor
n = Maze.Node((y,x))
leftnode = n
else:
# WALL PATH WALL
# Create node only if in dead end
if (data[rowaboveoffset + x] == 0) or (data[rowbelowoffset + x] == 0):
#print ("Create Node in dead end")
n = Maze.Node((y,x))
# If clear below, put this new node in the top row for the next connection
if (data[rowbelowoffset + x] > 0):
topnodes[x] = n
else:
topnodes[x] = None
count += 1
# End row
rowoffset = (height - 1) * width
for x in range (1, width - 1):
if data[rowoffset + x] > 0:
self.end = Maze.Node((height - 1,x))
t = topnodes[x]
t.Neighbours[2] = self.end
self.end.Neighbours[0] = t
count += 1
break
self.count = count
self.width = width
self.height = height
3.2 ALGORITHMS
Five path finding algorithms are implemented to solve the maze.
17
data structures. It starts at the tree root (or some arbitrary node of a graph, sometimes
referred to as a 'search key') and explores the neighbor nodes first, before moving to
the next level neighbors.
Breadth First Search (BFS) algorithm traverses a graph in a breadth ward motion and
uses a queue to remember to get the next vertex to start a search, when a dead end
occurs in any iteration.
Breadth-first search is an algorithm used for searching tree or graph data structures. It
starts at the tree root (or some arbitrary node of a graph, sometimes referred to as a
'search key'[1]) and explores the neighbour nodes first, before moving to the next level
neighbours.
Rule 1 − Visit the adjacent unvisited vertex. Mark it as visited. Display it.
Insert it in a queue.
Rule 2 − If no adjacent vertex is found, remove the first vertex from the queue.
1. Start by putting any one of the graph's vertices at the back of a queue.
2. Take the front item of the queue and add it to the visited list.
3. Create a list of that vertex's adjacent nodes. Add the ones which aren't in the
visited list to the back of the queue.
4. Keep repeating steps 2 and 3 until the queue is empty.
Code:
def solve(maze):
start = maze.start
end = maze.end
width = maze.width
queue = deque([start])
count = 0
completed = False
while queue:
19
count += 1
current = queue.pop()
if current == end:
completed = True
break
for n in current.Neighbours:
if n != None:
if visited[npos] == False:
queue.appendleft(n)
visited[npos] = True
prev[npos] = current
path = deque()
current = end
path.appendleft(current)
Below is the output inluding the node count and time taken by the breadth first
algorithm in figure 3.4.
20
Figure 3.4: Output From Solving Tiny Maze By Breadth-First Algorithm
Rule 1 − Visit the adjacent unvisited vertex. Mark it as visited. Display it. Push it
in a stack.
Rule 2 − If no adjacent vertex is found, pop up a vertex from the stack. (It will pop
up all the vertices from the stack, which do not have adjacent vertices.)
Code :
def solve(maze):
start = maze.start
end = maze.end
width = maze.width
stack = deque([start])
22
completed = False
while stack:
count += 1
current = stack.pop()
if current == end:
completed = True
break
#import code
#code.interact(local=locals())
for n in current.Neighbours:
if n != None:
if visited[npos] == False:
stack.append(n)
prev[npos] = current
path = deque()
current = end
path.appendleft(current)
23
current = prev[current.Position[0] * width + current.Position[1]]
Below is the output including the node count and time taken by the depth first
algorithm in figure 3.5.
For a given source node in the graph, the algorithm finds the shortest path between
that node and every other. It can also be used for finding the shortest paths from a
single node to a single destination node by stopping the algorithm once the shortest
path to the destination node has been determined. For example, if the nodes of the
graph represent cities and edge path costs represent driving distances between pairs
of cities connected by a direct road, Dijkstra's algorithm can be used to find the
24
shortest route between one city and all other cities. As a result, the shortest path
algorithm is widely used in network routing protocols, most notably IS-
IS (Intermediate System to Intermediate System) and Open Shortest Path First
(OSPF). It is also employed as a subroutine in other algorithms such as Johnson's.
Dijkstra's original algorithm does not use a min-priority queue and runs in time
(where is the number of nodes). The idea of this algorithm is also given in Leyzorek
et al. 1957. The implementation based on a min-priority queue implemented by a
Fibonacci heap and running in (where is the number of edges) is due to Fredman &
Tarjan 1984. This is asymptotically the fastest known single-source shortest-path
algorithm for arbitrary directed graphs with unbounded non-negative weights.
However, specialized cases (such as bounded/integer weights, directed acyclic graphs
etc.) can indeed be improved further as detailed in Specialized variants.
1. Initialization of all nodes with distance "infinite"; initialization of the starting node
with 0
2. Marking of the distance of the starting node as permanent, all other distances as
temporarily.
3. Setting of starting node as active.
4. Calculation of the temporary distances of all neighbour nodes of the active node by
summing up its distance with the weights of the edges.
5. If such a calculated distance of a node is smaller as the current one, update the
distance and set the current node as intercessor. This step is also called update and is
Dijkstra's central idea.
6. Setting of the node with the minimal temporary distance as active. Mark its distance
as permanent.
7. Repeating of steps 4 to 7 until there aren't any nodes left with a permanent distance,
which neighbours still have temporary distances.
Code:
from FibonacciHeap import FibHeap
from priority_queue import FibPQ, HeapPQ, QueuePQ
25
def solve(maze):
# Width is used for indexing, total is used for array sizes
width = maze.width
total = maze.width * maze.height
# Visited holds true/false on whether a node has been seen already. Used to stop us
returning to nodes multiple times
visited = [False] * total
# Previous holds a link to the previous node in the path. Used at the end for
reconstructing the route
prev = [None] * total
# Distances holds the distance to any node taking the best known path so far. Better
paths replace worse ones as we find them.
# We start with all distances at infinity
infinity = float("inf")
distances = [infinity] * total
# This index holds all priority queue nodes as they are created. We use this to
decrease the key of a specific node when a shorter path is found.
# This isn't hugely memory efficient, but likely to be faster than a dictionary or
26
similar.
nodeindex = [None] * total
# To begin, we set the distance to the start to zero (we're there) and add it into the
unvisited queue
distances[start.Position[0] * width + start.Position[1]] = 0
startnode = FibHeap.Node(0, start)
nodeindex[start.Position[0] * width + start.Position[1]] = startnode
unvisited.insert(startnode)
# Begin Dijkstra - continue while there are unvisited nodes in the queue
while len(unvisited) > 0:
count += 1
if distances[uposindex] == infinity:
break
27
for v in u.Neighbours:
if v != None:
vpos = v.Position
vposindex = vpos[0] * width + vpos[1]
if visited[vposindex] == False:
# The extra distance from where we are (upos) to the neighbour (vpos) -
this is manhattan distance
# https://en.wikipedia.org/wiki/Taxicab_geometry
d = abs(vpos[0] - upos[0]) + abs(vpos[1] - upos[1])
visited[uposindex] = True
# We want to reconstruct the path. We start at end, and then go prev[end] and follow
28
all the prev[] links until we're back at the start
from collections import deque
path = deque()
current = end
while (current != None):
path.appendleft(current)
current = prev[current.Position[0] * width + current.Position[1]]
Below is the output including the node count and time taken by the Dijkstra
algorithm in figure 3.6.
3.2.4 A* ALGORITHM
A* is an informed search algorithm, or a best-first search, meaning that it solves
problems by searching among all possible paths to the solution (goal) for the one that
incurs the smallest cost (least distance travelled, shortest time, etc.), and among these
paths it first considers the ones that appear to lead most quickly to the solution.
29
It is formulated in terms of weighted graphs: starting from a specific node of a graph,
it constructs a tree of paths starting from that node, expanding paths one step at a time,
until one of its paths ends at the predetermined goal node.
At each iteration of its main loop, A* needs to determine which of its partial paths to
expand into one or more longer paths. It does so base on an estimate of the cost (total
weight) still to go to the goal node. Specifically, A* selects the path that minimizes
where n is the last node on the path, g(n) is the cost of the path from the start node
to n, and h(n) is a heuristic that estimates the cost of the cheapest path from n to the
goal.
The heuristic is problem-specific. For the algorithm to find the actual shortest path,
the heuristic function must be admissible, meaning that it never overestimates the
actual cost to get to the nearest goal node.
The algorithm described so far gives us only the length of the shortest path. To find
the actual sequence of steps, the algorithm can be easily revised so that each node on
the path keeps track of its predecessor. After this algorithm is run, the ending node
will point to its predecessor, and so on, until some node's predecessor is the start node.
As an example, when searching for the shortest route on a map, h(x) might represent
the straight-line distance to the goal, since that is physically the smallest possible
distance between any two points.
If the heuristic h satisfies the additional condition h(x) ≤ d(x, y) + h(y) for every
edge (x, y) of the graph (where d denotes the length of that edge), then h is
called monotone, or consistent. In such a case, A* can be implemented more
efficiently—roughly speaking, no node needs to be processed more than once
30
(see closed set below)—and A* is equivalent to running Dijkstra's algorithm with
the reduced cost d'(x, y) = d(x, y) + h(y) − h(x).
3 Take from the open list the node node_current with the lowest
14 } else {
17 }
20 }
22 }
31
Code :
def solve(maze):
width = maze.width
start = maze.start
startpos = start.Position
end = maze.end
endpos = end.Position
infinity = float("inf")
# unvisited = FibHeap()
unvisited = HeapPQ()
32
# unvisited = FibPQ()
# unvisited = QueuePQ()
unvisited.insert(startnode)
count = 0
completed = False
count += 1
n = unvisited.removeminimum()
u = n.value
upos = u.Position
if distances[uposindex] == infinity:
break
if upos == endpos:
33
completed = True
break
for v in u.Neighbours:
if v != None:
vpos = v.Position
if visited[vposindex] == False:
# New distance is the distance of the path from the start, through U, to V.
newdistance = distances[uposindex] + d
# V to the end. We use manhattan again because A* works well when the
g cost and f cost are balanced.
# https://en.wikipedia.org/wiki/Taxicab_geometry
# Notice that we don't include f cost in this first check. We want to know
that the path *to* our node V is shortest
vnode = nodeindex[vposindex]
34
if vnode == None:
# priority than some other nodes. The order we visit nodes is a trade-
off between a short path, and moving
unvisited.insert(vnode)
nodeindex[vposindex] = vnode
distances[vposindex] = newdistance
prev[vposindex] = u
else:
# As above, we decrease the node since we've found a new path. But
we include the f cost, the distance remaining.
distances[vposindex] = newdistance
prev[vposindex] = u
visited[uposindex] = True
path = deque()
35
current = end
path.appendleft(current)
Below is the output inluding the node count and time taken by the A* algorithm in
figure 3.7.
3.2.5 LEFTTURN
Leftturn algorithm directs that whenever a choice is encountered always move left
first. While searching for node in graph, program will encounter many situations
where it has to choose one path, and according to leftturn algorithm program in such
case should always move to left.
Code:
from collections import deque
36
def solve(maze):
path = deque([maze.start])
current = maze.start.Neighbours[2]
if current == None:
return path
heading = 2 # South
startpos = maze.start.Position
endpos = maze.end.Position
count = 1
completed = False
while True:
path.append(current)
count += 1
position = current.Position
if position == startpos or position == endpos:
if position == endpos:
completed = True
break
37
n = current.Neighbours
if n[heading] != None:
current = n[heading]
continue
Below is the output including the node count and time taken by the Left-Turn
algorithm in figure 3.8.
38
Figure 3.9: Output from solving tiny maze by Left-Turn Algorithm
39
CHAPTER 4: RESULT
After the execution of the algorithms on the image to convert it to a graph and find the solution
of the maze. Various parameters are printed on the command line and the solution of the maze
is saved as an image.
4.1.1 SYNTAX
To execute the program using command line, following syntax is used:
python solve.py –m <algorithm_name> <input_image.png> <output_image.png>
<algorithm_name>: depthfirst, breadthfirst, dijkstra, astar, leftturn can be used to
specify the algorithm to apply.
<input_image.png>: Name or address of the input image containing maze is supplied
to the program.
<output_image.png>: Name or address of the output image on which the solution of
the maze is saved.
4.1.2 OUTPUT
After executing the program from the command line using the syntax, various
parameters informing of the performance of the algorithm is displayed on the
command line as shown in the figure 4.1 below.
Node Count: Number of nodes on the graph created form the image containing
maze.
Time Elapsed: Time taken to convert the image to graph.
Starting Solve: Name of the algorithm applied to solve the maze.
Nodes Explored: Number of nodes explored by the algorithm before reaching
the solution.
Path Found Length: Length of the path found by the algorithm which is the
solution of the maze.
Time Elapsed: Time taken by the algorithm to solve the maze.
On solving the maze, an image will be saved with the solution of the maze highlighted
with blue color as shown in figure 4.2
The image will be saved with name provided in the syntax of the command line on
the current directory.
41
4.2 GRAPH
To compare the performance of the algorithms a graph is drawn using the matplotlib library
of python. Matplotlib library provides the functionality to create various types of visual graph
such as scatter plot, bar graph, line graph etc.
A scatter plot graph is used to compare the performance of the algorithms using the
matplotlib library of python.
A scatter plot (also called a scatterplot, scatter graph, scatter chart, scatter gram, or
scatter diagram) is a type of plot or mathematical diagram using Cartesian coordinates
to display values for typically two variables for a set of data. If the points are color-
coded, one additional variable can be displayed. The data are displayed as a collection
of points, each having the value of one variable determining the position on the
horizontal axis and the value of the other variable determining the position on the
vertical axis.
Scatter plot is optimal for this purpose as it represents value of two variables for
multiple objects or algorithms which are independent of one another.
4.2.2 AXIS
A scatter plot graph is drawn after executing the program on an image of maze. The
two axes of the program will represent:
Y-axis: The number of nodes searched by the algorithm to solve the maze.
4.2.3 OUTPUT
To plot the graph, all algorithms are first executed and then the graph is plotted using
the parameters obtained from executing the algorithms, the command prompt after
executing all algorithms is shown in figure 4.3
42
Figure 4.3: Parameters Obtained From Executing The Algorithms
43
Figure 4.4: Using Coloured Dots To Notify The Name Of The Algorithm
The graph shows the time taken by the algorithm to solve the maze and the nodes
explored by the algorithm to solve the maze of various algorithms comparative to one
another. This makes it easy to compare these parameters of algorithms to one another.
The lower the point is, the less nodes it will explore to solve the maze and the more
towards the left the point is, the less time it will require to solve the maze thus the
algorithms whose point is lower and more towards the left is optimum.
44
CHAPTER 5: CONCLUSION
After comparing the performance of all algorithms, various conclusions are drawn from the
data obtained from executing the image containing maze with various algorithms.
5.1 MAZES
5.2 TABLES
After applying the algorithms to various mazes of different types multiple times and taking
the average of all values for a maze, the results observed are presented in a table. Various
tables are used to show various parameters of the algorithms.
In tables, mazes with prefix P are the Perfect Mazes and those with prefix B are the Braid
Mazes.
Time Taken parameter represents the time taken by the algorithm to solve the maze.
Lower the value of this parameter, better the algorithm as less time will be taken to
solve the maze.
Table 5.1 shows the time taken by the algorithms to solve the maze for various mazes.
45
B(400x400) 0.312 0.342 1.529 2.309 0.530
P(2000x2000) 6.210 2.000 46.489 45.679 7.218
B(2000x2000) 8.003 1.013 57.945 70.083 9.0620
From the table, it can be observed that the depth first search algorithm take the least
amount of time to solve a maze followed by breadth first search algorithms whereas
Dijkstra algorithm takes the most time to solve the maze.
The order of the time taken by the algorithm to solve the maze is:
Nodes Explored parameter represents the number of nodes explored by the algorithm
to find the solution of the maze. Lower the value of this parameter, better the
algorithm as less computations are done to solve the maze.
Table 5.2 shows the nodes explored by the algorithms to solve the maze for various
mazes.
P(10x10) 19 14 12 20 19
P(15x15) 37 27 27 37 35
P(40x40) 294 164 252 290 265
46
From the table, it can be observed that the depth first search algorithm explores least
number of nodes to find the solution of the maze followed by leftturn whereas breadth
first search algorithm explores most nodes to find the solution of the maze.
The order of nodes explored by the algorithm to solve the maze is:
Length of path found parameter represents the length of the path found or the length
of the solution of the maze for various algorithms. Lower the value of this
parameter, better the algorithm.
Table 5.3 shows the length of the path found by the various algorithms for various
mazes.
P(10x10) 9 14 9 9 19
P(15x15) 17 23 17 17 35
From the table, it can be observed that Dijkstra algorithm find the most optimum
path or the shortest path followed by a star algorithm whereas leftturn algorithm find
the least optimum path or the longest path.
The order of length of the path found by the algorithm is:
47
BFS < Dijkstra < A* < DFS < Leftturn
5.3 CONCLUSION
From the tables, algorithms can be evaluated in three parameters time taken, nodes explored
and length of path found. Performance of algorithms in different parameter is different thus
it is not possible to find one algorithm which is better at all parameters.
When compared on time taken by the algorithm to solve the maze, depth first search algorithm
takes least amount of time to solve the maze followed by breadth first search. The Dijkstra
and a star algorithm takes most time to solve the maze. Thus, for time taken depth first search
is best.
When compared on nodes explored by the algorithm to solve the maze, depth first search
algorithm explores least nodes to solve the maze followed by leftturn. The breadth first search
explores most nodes to solve the maze. Thus, for nodes explored depth first search is best
When compared on length of the path found, breadth first search algorithms found the
optimum path or shortest path followed by Dijkstra and a star whereas leftturn found the least
optimum path. Thus, for length of the path found breadth first algorithm is best.
48
REFERENCES
49