Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 15

University of Barishal

Assignment

Course Title: Artificial Intelligence


Course Code: CSE-3205
Topic Name: Finding the Shortest Path using backtracking algorithm
forward checking algorithm &graph colouring

Submitted To: Dr. Tania Islam

Assistant Professor
Dept. of Computer Science Engineering,
University of Barishal

Submitted By:
Name: Lamia Begum
Roll: 19CSE030
Year: 3rd
Semester: 2nd
Session: 2019-20
Submission Date: 10/05/2024
Routes:

Shortest Path by Dijkstra’s Algotithm:


Code:
import sys

class Graph:

def __init__(self, vertices):

self.V = vertices

self.graph = [[0 for _ in range(vertices)] for _ in range(vertices)]

def min_distance(self, dist, spt_set):

min_dist = sys.maxsize

min_index = 0

for v in range(self.V):

if dist[v] < min_dist and spt_set[v] == False:

min_dist = dist[v]

min_index = v

return min_index

def dijkstra(self, src, dest):

dist = [sys.maxsize] * self.V

dist[src] = 0

spt_set = [False] * self.V


for _ in range(self.V):

u = self.min_distance(dist, spt_set)

spt_set[u] = True

for v in range(self.V):

if self.graph[u][v] > 0 and spt_set[v] == False and dist[v] > dist[u] + self.graph[u][v]:

dist[v] = dist[u] + self.graph[u][v]

return dist[dest]

# Given adjacency matrix

adj_matrix = [

[0, 50, 0, 0, 0, 0, 0],

[0, 0, 30, 0, 0, 0, 0],

[0, 0, 0, 20, 0, 0, 0],

[0, 0, 0, 0, 30, 40, 0],

[0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 40],

[0, 0, 0, 0, 50, 0, 0]

# Create graph from adjacency matrix

g = Graph(len(adj_matrix))
for i in range(len(adj_matrix)):

for j in range(len(adj_matrix[0])):

g.graph[i][j] = adj_matrix[i][j]

# Source and destination nodes

src_node = 0 # For node 'a'

dest_node = 6 # For node 'g'

# Find minimum distance

min_distance = g.dijkstra(src_node, dest_node)

print(f"The minimum distance between node {chr(src_node + ord('a'))} and node


{chr(dest_node + ord('a'))} is {min_distance}.")

Backtracking Algorith
backtraking isa problem-solving algorithmic technique that involves finding a solution
incrementally by trying different types and undoging them if they lead to a dead end.

It is commonly used in situations where you need to explore multiple possibilities to solve a
problem, like searching for a path in a maze or solving puzzles like .soduko When a dead end is
reached, the algorithm backtracks to the previous decision point and explores a different path
until a solution is found or all possibilities have been exhausted.

Applications of Backtracking Algorithm


Backtracking algorithms are used in a wide variety of applications, including:

 Solving puzzles

 Finding the shortest path through a maze

 Scheduling problems

 Resource allocation problems


 Network optimization problems

Code for back tracking algorithm:

Code in python

class Graph:

def __init__(self):

self.graph = {}

def add_edge(self, node, adjacent, weight):

if node not in self.graph:

self.graph[node] = []

self.graph[node].append((adjacent, weight))
def get_neighbors(self, node):

return self.graph.get(node, [])

def shortest_path(graph, start, end, path=[], cost=0, shortest=None):

path = path + [start]

if start == end:

return (path, cost)

for node, weight in graph.get_neighbors(start):

if node not in path:

if shortest is None or cost + weight < shortest[1]:

new_path, new_cost = shortest_path(graph, node, end, path, cost + weight,


shortest)

if new_path:

shortest = (new_path, new_cost)

return shortest

def main():

g = Graph()

g.add_edge("Barishal", "Bakergonj", 50)

g.add_edge("Bakergonj", "Lebukhali", 30)

g.add_edge("Lebukhali", "Pagla", 20)

g.add_edge("Pagla", "Patuakhali", 30)

g.add_edge("Pagla", "Dumki", 40)

g.add_edge("Dumki", "Boga", 40)


g.add_edge("Boga", "Patuakhali", 50)

start = "Barishal"

end = "Patuakhali"

shortest = shortest_path(g, start, end)

if shortest:

path, cost = shortest

print("Shortest path:", ' -> '.join(path))

print("Total cost:", cost)

else:

print("No path found!")

if __name__ == "__main__":

main()

Froward checking algorithm

The forward checking algorithm for solving constraint satisfaction problems is a popular and successful
alternative to backtracking. However, its success has largely been determined empirically, and there has
been limited work towards a real understanding of why and when forward checking is the superior
approach.

The "forward checking" algorithm is a technique used in constraint satisfaction problems (CSPs)
to reduce the search space and improve the efficiency of constraint propagation. Here's an
explanation of the algorithm and its applications:

1. Algorithm Overview:
o Forward checking is performed during the search for a solution to a CSP.
o It is applied after assigning a value to a variable.
o The algorithm checks the remaining variables to see if any of their domains are
reduced to empty due to the assignment.
o If a domain becomes empty, it indicates that the current assignment cannot be
extended to a solution, so the algorithm backtracks

Applications:

2. Constraint Satisfaction Problems: Forward checking is widely used in CSPs, such as


scheduling, timetabling, and resource allocation problems.
3. Sudoku: In Sudoku solving algorithms, forward checking helps prune the search space
by eliminating values from the domains of other variables based on the values assigned to
certain cells.
4. Map Coloring: When coloring a map such that adjacent regions have different colors,
forward checking helps in reducing the search space by eliminating colors from the
domains of neighboring regions based on the colors already assigned.
5. Job Scheduling: In job scheduling problems, forward checking can be used to ensure
that the constraints related to resource availability, job dependencies, and time constraints
are satisfied efficiently

class Graph:

def __init__(self):

self.graph = {}

def add_edge(self, node, adjacent, weight):

if node not in self.graph:

self.graph[node] = []

self.graph[node].append((adjacent, weight))

def get_neighbors(self, node):

return self.graph.get(node, [])


def shortest_path_with_forward_checking(graph, start, end):

frontier = [(start, [start], 0)] # (node, path, cost)

explored = set()

while frontier:

node, path, cost = frontier.pop(0)

explored.add(node)

if node == end:

return path, cost

for neighbor, weight in graph.get_neighbors(node):

if neighbor not in explored:

if neighbor == end:

return path + [neighbor], cost + weight

else:

frontier.append((neighbor, path + [neighbor], cost + weight))

return None, float('inf')

def main():

g = Graph()

g.add_edge("Barishal", "Bakergonj", 50)


g.add_edge("Bakergonj", "Lebukhali", 30)

g.add_edge("Lebukhali", "Pagla", 20)

g.add_edge("Pagla", "Patuakhali", 30)

g.add_edge("Pagla", "Dumki", 40)

g.add_edge("Dumki", "Boga", 40)

g.add_edge("Boga", "Patuakhali", 50)

start = "Barishal"

end = "Patuakhali"

path, cost = shortest_path_with_forward_checking(g, start, end)

if path:

print("Shortest path:", ' -> '.join(path))

print("Total cost:", cost)

else:

print("No path found!")

if __name__ == "__main__":

main()
Graph colouring code

class Graph:

def __init__(self):

self.graph = {}

def add_edge(self, node, adjacent, weight):

if node not in self.graph:

self.graph[node] = []

self.graph[node].append((adjacent, weight))

def get_neighbors(self, node):

return self.graph.get(node, [])


def graph_coloring(graph):

colors = {} # Dictionary to store the assigned colors for each node

color_index = 0

for node in graph.graph.keys():

if node not in colors:

colors[node] = color_index

color_index += 1

for neighbor, _ in graph.get_neighbors(node):

if neighbor not in colors:

# Assign the next available color to the neighbor

colors[neighbor] = color_index

color_index += 1

elif colors[neighbor] == colors[node]:

# If the neighbor has the same color as the node, assign a new color

colors[neighbor] = color_index

color_index += 1

return colors

def main():

g = Graph()

g.add_edge("Barishal", "Bakergonj", 50)


g.add_edge("Bakergonj", "Lebukhali", 30)

g.add_edge("Lebukhali", "Pagla", 20)

g.add_edge("Pagla", "Patuakhali", 30)

g.add_edge("Pagla", "Dumki", 40)

g.add_edge("Dumki", "Boga", 40)

g.add_edge("Boga", "Patuakhali", 50)

colors = graph_coloring(g)

print("Node\tColor")

for node, color in colors.items():

print(node, "\t", color)

if __name__ == "__main__":

main()

You might also like