Вы находитесь на странице: 1из 57

CANDIDATE’S DECLARATION

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

Karuna Goyal Prerna Verma Samarthya Gupta


15BCS012 15BCS028 15BCS038

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.

Mr. Manoj Verma

( 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.

Karuna Goyal Prerna Verma Samarthya Gupta


15BCS012 15BCS028 15BCS038

_______________________________________________________________________________

iv
TABLE OF CONTENTS

CANDIDATE DECLARATION ii
ABSTRACT iii
ACKNOWLEDGEMENT iv
TABLE OF CONTENTS v - vi
LIST OF FIGURES vii
LIST OF TABLES viii

Chapter 1: Introduction 1–6


1.1 Scope Of Work 2
1.2 Technologies Used 2
1.2.1 Python 2.7 2
1.2.2 Mathplotlib Library 4
1.2.3 Pillow Library 5
1.2.3.1 Image Archives 5
1.2.3.2 Image Display 6
1.2.3.3 Image Processing 6
1.3 Requirements 6
Chapter 2: Background 7 – 11
2.1 Literature Survey 7
2.2 Research Methodology 8
2.3 Related Works 9
Chapter 3: Description 12 – 38
3.1 Converting Image To Graph 12
3.1.1 Algorithm 1: Image To Graph 12
3.1.2 Code For Converting Image To Graph 14
3.2 Algorithms 17
3.2.1 Breadth First Search 17
3.2.2 Depth First Search 21
3.2.3 Dijkstra’s Algorithm 24

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

Figure 1.1 Example Of Solved Maze 2


Figure 1.2 Python Console 4
Figure 1.3 Matplotlib Example Plots 5
Figure 3.1 A Typical Maze 13
Figure 3.2 Graph For The Maze 14
Figure 3.3 BFS Traversal 18
Figure 3.4 Output From Solving Tiny Maze By Breadth-First Algorithm 21
Figure 3.5 DFS Traversal 21
Figure 3.6 Output From Solving Tiny Maze By Depth-First Algorithm 24
Figure 3.7 Output From Solving Tiny Maze By Dijkstra Algorithm 29
Figure 3.8 Output From Solving Tiny Maze By A* Algorithm 36
Figure 3.9 Output From Solving Tiny Maze By Left-Turn Algorithm 39
Figure 4.1 Command Line After Execution 40
Figure 4.2 Solved Maze 41
Figure 4.3 Parameters Obtained From Executing The Algorithms 43
Figure 4.4 Using Coloured Dots To Notify The Name Of The Algorithm 44

vii
LIST OF TABLES

Table 5.1 Time, In Seconds, Taken To Solve The Maze 45


Table 5.2 Nodes Explored To Solve The Image 46
Table 5.3 Length Of The Path Found 47

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:

1. The way to get from source A to destination B.


2. The way to get around obstacles in the way.
3. The way to find the shortest possible path.
4. The way to find the path quickly.

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.

Figure 1.1: Example Of Solved Maze

1.1 SCOPE OF WORK

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.

1.2 TECHNOLOGIES USED

1.2.1 PYTHON 2.7

Python is an open source programming language. Python was made to be easy-to-read


and powerful. A Dutch programmer named Guido van Rossum made Python in 1991.
He named it after the television show Monty Python's Flying Circus. Many Python
examples and tutorials include jokes from the show.

Python is an interpreted language. Interpreted languages do not need to be compiled to


run. A program called an interpreter runs Python code on almost any kind of
computer. This means that a programmer can change the code and quickly see the
results. This also means Python is slower than a compiled language like C, because it
is not running machine code directly.

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.

Python is used by hundreds of thousands of programmers and is used in many places.


Sometimes only Python code is used for a program, but most of the time it is used
to do simple jobs while another programming language is used to do more
complicated tasks.

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.

Some things that Python is often used for are:

 Web development
 Game programming
 Desktop GUIs
 Scientific programming
 Network programming

Python is an easy to learn, powerful programming language. It has efficient high-level


data structures and a simple but effective approach to object-oriented programming.
Python’s elegant syntax and dynamic typing, together with its interpreted nature, make
it an ideal language for scripting and rapid application development in many areas on
most platforms.

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.

Figure 1.2: Python Console

1.2.2 MATPLOTLIB LIBRARY

Matplotlib is a python 2D plotting library which produces publication quality figures


in a variety of hardcopy formats and interactive environments across platforms.
matplotlib can be used in python scripts, the python and ipython shell, web application
servers, and six graphical user interface toolkits.

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
.

Figure 1.3: Matplotlib Example Plots

1.2.3 PILLOW LIBRARY

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.

1.2.3.1 IMAGE ARCHIVES


The Python Imaging Library is ideal for image archival and batch processing
applications. You can use the library to create thumbnails, convert between
file formats, print images, etc.
The current version identifies and reads a large number of formats. Write
5
support is intentionally restricted to the most commonly used interchange and
presentation formats.

1.2.3.2 IMAGE DISPLAY


The current release includes Tk PhotoImage and BitmapImage interfaces, as
well as a Windows DIB interface that can be used with PythonWin and other
Windows-based toolkits. Many other GUI toolkits come with some kind of
PIL support.

For debugging, there’s also a show () method which saves an image to disk
and calls an external display utility.

1.2.3.3 IMAGE PROCESSING


The library contains basic image processing functionality, including point
operations, filtering with a set of built-in convolution kernels, and colour space
conversions.
The library also supports image resizing, rotation and arbitrary affine
transforms.
There’s a histogram method allowing you to pull some statistics out of an
image. This can be used for automatic contrast enhancement, and for global
statistical analysis.

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

2.1 LITERATURE SURVEY

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.

n = [(NR + NL − 1) × X2h + Xh + nn]× eR+ FRL × NL (For right wheel).

n = [(NR + NL − 1) × X2h + Xh + nn]× eL+ FLL × NR (For left wheel).

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.

Cyborg intelligence is a convergence of machine and biological intelligence, which is


capable of integrating the two heterogeneous intelligences at multiple levels [1, 2].

2.2 RESEARCH METHODOLOGY

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.

2.3 Related Works

[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.

3.1 CONVERTING IMAGE TO GRAPH


Mazes are in the image file format and to apply path finding algorithms images
containing maze must be converted to graph.
Python’s PILLOW library is used for this. Image is first received as input which must
satisfy the following conditions:
1) Image should be black and white.
2) Start node must be at the top row and the end node must be at the bottom row.
3) Image should be a maze with at least one solution.
With the help of PILLOW every pixel of the image can be identified. Black pixel
represents obstacle and white pixel represents the valid path.
The Algorithm 1 is then applied on the image to convert it to a graph:

3.1.1 ALGORITHM 1: IMAGE TO GRAPH


1. Find the white pixel at the top 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 the start node of the
graph and add it to topnode.
2. Set prv=false, cur=false, nxt=first pixel from next row.
3. Traverse image’s pixel from left to right row by row.
a. Set prv=cur, cur=nxt, nxt=next pixel from image.
b. if cur is black, go to 3
c. if prv is white
i. if nxt is white, create node if there is path above and
below, connect it to leftnode and set it as leftnode.
ii. else create node and connect it to leftnode.
d. else
i. if next is white, create node and set it as leftnode.

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.

Figure 3.1: A Typical Maze

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]

def init (self, im):

width = im.size[0]
height = im.size[1]
data = list(im.getdata(0))

self.start = None
self.end = None

# Top row buffer


topnodes = [None] * width

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

for y in range (1, height - 1):


#print ("row", str(y)) # Uncomment this line to keep a track of row progress

rowoffset = y * width
rowaboveoffset = rowoffset - width
rowbelowoffset = rowoffset + width

# Initialise previous, current and next values


prv = False
cur = False
nxt = data[rowoffset + 1] > 0

leftnode = None

for x in range (1, width - 1):


# Move prev, current and next onwards. This way we read from the image
once per pixel, marginal optimisation
prv = cur
cur = nxt
nxt = data[rowoffset + x + 1] > 0

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 node isn't none, we can assume we can connect N-S somewhere


if n != None:
16
# Clear above, connect to waiting top node
if (data[rowaboveoffset + x] > 0):
t = topnodes[x]
t.Neighbours[2] = n
n.Neighbours[0] = t

# 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.

3.2.1 BREADTH FIRST SEARCH


Breadth-first search (BFS) is an algorithm for traversing or searching tree or graph

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.

Figure 3.3: BFS Traversal

As in the example given above, BFS algorithm traverses from A to B to E to F first


then to C and G lastly to Din figure 3.3. It employs the following rules.

 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.

 Rule 3 − Repeat Rule 1 and Rule 2 until the queue is empty.


18
The algorithm works as follows:

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:

from collections import deque

def solve(maze):

start = maze.start

end = maze.end

width = maze.width

queue = deque([start])

shape = (maze.height, maze.width)

prev = [None] * (maze.width * maze.height)

visited = [False] * (maze.width * maze.height)

count = 0

completed = False

visited[start.Position[0] * width + start.Position[1]] = True

while queue:

19
count += 1

current = queue.pop()

if current == end:

completed = True

break

for n in current.Neighbours:

if n != None:

npos = n.Position[0] * width + n.Position[1]

if visited[npos] == False:

queue.appendleft(n)

visited[npos] = True

prev[npos] = current

path = deque()

current = end

while (current != None):

path.appendleft(current)

current = prev[current.Position[0] * width + current.Position[1]]

return [path, [count, len(path), completed]]

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

3.2.2 DEPTH FIRST SEARCH


Depth-first search (DFS) is an algorithm for traversing or searching tree or graph data
structures. One starts at the root (selecting some arbitrary node as the root in the case
of a graph) and explores as far as possible along each branch before backtracking
Depth First Search (DFS) algorithm traverses a graph in a depth ward motion and
uses a stack to remember to get the next vertex to start a search, when a dead end
occurs in any iteration.

Figure 3.5: DFS Traversal


21
As in the example given above, DFS algorithm traverses from S to A to D to G to E
to B first, then to F and lastly to C in figure 3.4. It employs the following rules.

 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.)

 Rule 3 − Repeat Rule 1 and Rule 2 until the stack is empty.

The DFS algorithm works as follows:

1. Start by putting any one of the graph's vertices on top of a stack.


2. Take the top item of the stack 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 top of stack.
4. Keep repeating steps 2 and 3 until the stack is empty.

Code :

from collections import deque

def solve(maze):

start = maze.start

end = maze.end

width = maze.width

stack = deque([start])

shape = (maze.height, maze.width)

prev = [None] * (maze.width * maze.height)

visited = [False] * (maze.width * maze.height)

22
completed = False

while stack:

count += 1

current = stack.pop()

if current == end:

completed = True

break

visited[current.Position[0] * width + current.Position[1]] = True

#import code

#code.interact(local=locals())

for n in current.Neighbours:

if n != None:

npos = n.Position[0] * width + n.Position[1]

if visited[npos] == False:

stack.append(n)

prev[npos] = current

path = deque()

current = end

while (current != None):

path.appendleft(current)

23
current = prev[current.Position[0] * width + current.Position[1]]

return [path, [count, len(path), completed]]

Below is the output including the node count and time taken by the depth first
algorithm in figure 3.5.

Figure 3.6: Output From Solving Tiny Maze By Depth-First Algorithm

3.2.3 DIJKSTRA’S ALGORITHM


Dijkstra's algorithm is an algorithm for finding the shortest paths between nodes in a
graph. It was conceived by computer scientist Edsger W. Dijkstra in 1956 and
published three years later. The algorithm exists in many variants; Dijkstra's original
variant found the shortest path between two nodes, but a more common variant fixes
a single node as the "source" node and finds shortest paths from the source to all other
nodes in the graph, producing a shortest-path tree.

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.

In some fields, artificial intelligence in particular, Dijkstra's algorithm or a variant of


it is known as uniform cost search and formulated as an instance of the more general
idea of best-first search. Dijkstra’s Algorithm consisted’s of the following steps:

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

# Start node, end node


start = maze.start
startpos = start.Position
end = maze.end
endpos = end.Position

# 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

# The priority queue. There are multiple implementations in priority_queue.py


# unvisited = FibHeap()
unvisited = HeapPQ()
# unvisited = FibPQ()
# unvisited = QueuePQ()

# 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)

# Zero nodes visited, and not completed yet.


count = 0
completed = False

# Begin Dijkstra - continue while there are unvisited nodes in the queue
while len(unvisited) > 0:
count += 1

# Find current shortest path point to explore


n = unvisited.removeminimum()

# Current node u, all neighbours will be v


u = n.value
upos = u.Position
uposindex = upos[0] * width + upos[1]

if distances[uposindex] == infinity:
break

# If upos == endpos, we're done!


if upos == endpos:
completed = True
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])

# New path cost to v is distance to u + extra


newdistance = distances[uposindex] + d

# If this new distance is the new shortest path to v


if newdistance < distances[vposindex]:
vnode = nodeindex[vposindex]
# v isn't already in the priority queue - add it
if vnode == None:
vnode = FibHeap.Node(newdistance, v)
unvisited.insert(vnode)
nodeindex[vposindex] = vnode
distances[vposindex] = newdistance
prev[vposindex] = u
# v is already in the queue - decrease its key to re-prioritise it
else:
unvisited.decreasekey(vnode, newdistance)
distances[vposindex] = newdistance
prev[vposindex] = u

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]]

return [path, [count, len(path), completed]]

Below is the output including the node count and time taken by the Dijkstra
algorithm in figure 3.6.

Figure 3.7: Output From Solving Tiny Maze By Dijkstra Algorithm

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.

Typical implementations of A* use a priority queue to perform the repeated selection


of minimum (estimated) cost nodes to expand. This priority queue is known as
the open set or fringe. At each step of the algorithm, the node with the
lowest f(x) value is removed from the queue, the f and g values of its neighbours are
updated accordingly, and these neighbours are added to the queue. The algorithm
continues until a goal node has a lower f value than any node in the queue (or until the
queue is empty).[a] The f value of the goal is then the length of the shortest path,
since h at the goal is zero in an admissible heuristic.

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).

Following is the pseudocode for A* Algorithm:

1 Put node_start in the OPEN list with f(node_start) = h(node_start) (initialization)

2 while the OPEN list is not empty {

3 Take from the open list the node node_current with the lowest

4 f(node_current) = g(node_current) + h(node_current)

5 if node_current is node_goal we have found the solution; break

6 Generate each state node_successor that come after node_current

7 for each node_successor of node_current {

8 Set successor_current_cost = g(node_current) + w(node_current, node_successor)

9 if node_successor is in the OPEN list { 10 if g(node_successor) ≤


successor_current_cost continue (to line 20) 11 } else if node_successor is in the
CLOSED list {

12 if g(node_successor) ≤ successor_current_cost continue (to line 20)

13 Move node_successor from the CLOSED list to the OPEN list

14 } else {

15 Add node_successor to the OPEN list 16 Set h(node_successor) to be the heuristic


distance to node_goal

17 }

18 Set g(node_successor) = successor_current_cost

19 Set the parent of node_successor to node_current

20 }

21 Add node_current to the CLOSED list

22 }

23 if(node_current != node_goal) exit with error (the OPEN list is empty)

31
Code :

from FibonacciHeap import FibHeap

from priority_queue import FibPQ, HeapPQ, QueuePQ

# This implementatoin of A* is almost identical to the Dijkstra implementation. So for


clarity I've removed all comments, and only added those

# Specifically showing the difference between dijkstra and A*

def solve(maze):

width = maze.width

total = maze.width * maze.height

start = maze.start

startpos = start.Position

end = maze.end

endpos = end.Position

visited = [False] * total

prev = [None] * total

infinity = float("inf")

distances = [infinity] * total

# The priority queue. There are multiple implementations in priority_queue.py

# unvisited = FibHeap()

unvisited = HeapPQ()

32
# unvisited = FibPQ()

# unvisited = QueuePQ()

nodeindex = [None] * total

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)

count = 0

completed = False

while len(unvisited) > 0:

count += 1

n = unvisited.removeminimum()

u = n.value

upos = u.Position

uposindex = upos[0] * width + upos[1]

if distances[uposindex] == infinity:

break

if upos == endpos:

33
completed = True

break

for v in u.Neighbours:

if v != None:

vpos = v.Position

vposindex = vpos[0] * width + vpos[1]

if visited[vposindex] == False:

d = abs(vpos[0] - upos[0]) + abs(vpos[1] - upos[1])

# New path cost to v is distance to u + extra. Some descriptions of A* call


this the g cost.

# New distance is the distance of the path from the start, through U, to V.

newdistance = distances[uposindex] + d

# A* includes a remaining cost, the f cost. In this case we use manhattan


distance to calculate the distance from

# 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

remaining = abs(vpos[0] - endpos[0]) + abs(vpos[1] - endpos[1])

# 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

if newdistance < distances[vposindex]:

vnode = nodeindex[vposindex]

34
if vnode == None:

# V goes into the priority queue with a cost of g + f. So if it's moving


closer to the end, it'll get higher

# priority than some other nodes. The order we visit nodes is a trade-
off between a short path, and moving

# closer to the goal.

vnode = FibHeap.Node(newdistance + remaining, v)

unvisited.insert(vnode)

nodeindex[vposindex] = vnode

# The distance *to* the node remains just g, no f included.

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.

unvisited.decreasekey(vnode, newdistance + remaining)

# The distance *to* the node remains just g, no f included.

distances[vposindex] = newdistance

prev[vposindex] = u

visited[uposindex] = True

from collections import deque

path = deque()

35
current = end

while (current!= None):

path.appendleft(current)

current = prev[current.Position[0] * width + current.Position[1]]

return [path, [count, len(path), completed]]

Below is the output inluding the node count and time taken by the A* algorithm in
figure 3.7.

Figure 3.8: Output From Solving Tiny Maze By A* Algorithm

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

turn = 1 # Turning left, -1 for right

startpos = maze.start.Position
endpos = maze.end.Position

# N E S W - just a helpful reminder


#0123

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 - turn) % 4] != None:


heading = (heading - turn) % 4
current = n[heading]
continue

if n[heading] != None:
current = n[heading]
continue

if n[(heading + turn) % 4] != None:


heading = (heading + turn) % 4
current = n[heading]
continue
if n[(heading + 2) % 4] != None:
heading = (heading + 2) % 4
current = n[heading]
continue
completed = False
break
return [path, [count, len(path), completed]]

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 COMMAND LINE OUTPUT

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.

Figure 4.1: Command Line After Execution


40
Parameters on the command line are:

 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.

These parameters will be helpful in comparing the performance of the algorithms on


solving 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

Figure 4.2: Solved Maze

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.

4.2.1 SCATTER PLOT GRAPH

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:

X-axis: The time taken by the algorithm to solve the maze.

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

X (Time taken) and Y (Nodes explored) value of various algorithms will be


represented using coloured dots with a legend to notify the name of the algorithm as
shown in figure 4.4

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

Two types of mazes are used in this program:

 Perfect Maze: Those mazes which have only one solution.


 Braid Maze: Those mazes which have more than one solution.

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.

5.2.1 TIME TAKEN

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.

Table 5.1: Time, In Seconds, Taken To Solve The Maze


Maze BFS DFS A* Dijkstra Leftturn
P(10x10) 0.000 0.000 0.000 0.000 0.000
P(15x15) 0.000 0.000 0.016 0.015 0.000
P(40x40) 0.000 0.000 0.0159 0.0150 0.000
B(200x200) 0.078 0.062 0.467 0.452 0.050

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:

DFS < BFS < Leftturn < A* < Dijkstra

5.2.2 NODES EXPLORED

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.

Table 5.2: Nodes Explored To Solve The Image


Maze BFS DFS A* Dijkstra Leftturn

P(10x10) 19 14 12 20 19
P(15x15) 37 27 27 37 35
P(40x40) 294 164 252 290 265

B(200x200) 6268 3944 4969 6296 589


B(400x400) 26311 26868 15136 26526 1971
P(2000x2000) 512k 152k 462k 511k 582k

B(2000x2000) 613k 67k 392k 616k 13k

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:

DFS < Leftturn < Dijkstra < A* < BFS

5.2.3 LENGTH OF PATH FOUND

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.

Table 5.3: Length Of The Path Found

Maze BFS DFS A* Dijkstra Leftturn

P(10x10) 9 14 9 9 19

P(15x15) 17 23 17 17 35

P(40x40) 119 119 119 119 265

B(200x200) 193 1082 197 197 589

B(400x400) 319 1478 324 324 1971

P(2000x2000) 8650 8650 8650 8650 582k

B(2000x2000) 1433 17411 1505 1488 12931

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.

For time taken:

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.

DFS < BFS < Leftturn < A* < Dijkstra

For nodes explored:

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

DFS < Leftturn < Dijkstra < A* < BFS

For length of the path found:

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.

BFS < Dijkstra < A* < DFS < Leftturn

48
REFERENCES

[1] Wu Z. The convergence of machine and biological intelligence. IEEE


Intelligent Systems. 2013;28(5):28–43.
[2] Wu Z, Pan G, Zheng N. Cyborg intelligence. IEEE Intelligent Systems.
2013;28(5):31–33.
[3] Zhan, F. Benjamin. "Three fastest shortest path algorithms on real road networks:
Data structures and procedures." Journal of geographic information and decision
analysis 1.1 (1997): 69-82.
[4] Sadik, A. M., Dhali, M. A., Farid, H. M., Rashid, T. U., & Syeed, A. "A
comprehensive and comparative study of maze-solving techniques by implementing
graph theory". In Artificial Intelligence and Computational Intelligence (AICI), 2010
International Conference on (Vol. 1, pp. 52-56). IEEE.
[5] Botea, Adi, Bruno Bouzy, Michael Buro, Christian Bauckhage, and Dana Nau.
"Pathfinding in games." In Dagstuhl Follow-Ups, vol. 6. Schloss Dagstuhl-Leibniz-
Zentrum fuer Informatik, 2013.
[6] Goldberg, A.V. and Harrelson, C., 2005, January. Computing the shortest path: A
search meets graph theory. In Proceedings of the sixteenth annual ACM-SIAM
symposium on Discrete algorithms (pp. 156-165). Society for Industrial and Applied
Mathematics.
[7] Cui, Xiao, and Hao Shi. "A*-based pathfinding in modern computer games."
International Journal of Computer Science and Network Security 11.1 (2011): 125-
130.
[8] Pohl, Ira. "Heuristic search viewed as path finding in a graph." Artificial intelligence
1, no. 3-4 (1970): 193-204.
[9] Khantanapoka, Khammapun, and Krisana Chinnasarn. "Pathfinding of 2D & 3D
game real-time strategy with depth direction A∗ algorithm for multi-layer." Natural
Language Processing, 2009. SNLP'09. Eighth International Symposium on. IEEE,
2009.

49

Вам также может понравиться