Search Algorithm Assignment !

Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 12

Assignment 1

Name - Anurag Kumar Q id - 20030197


Subject - Search Algorithm Branch/ Semester - CSE AIML / 7th

# Write a code to find the mother vertex

graph = {
'A': ['B', 'C', 'D', 'F'],
'B': ['C', 'D'],
'C': ['F'],
'D': [],
'F': []
# 0:[],
# 1:[0,4],
# 2:[5],
# 3:[1,2,6],
# 4:[3],
# 5:[0],
# 6:[]
}

def is_mother_vertex(graph, v):

visited = set()
dfs(graph, v, visited)

for vertex in graph:


if vertex not in visited:
return False

return True

def dfs(graph, v, visited):

visited.add(v)
for neighbor in graph[v]:
if neighbor not in visited:
dfs(graph, neighbor, visited)

mother_vertex = None
for vertex in list(graph.keys()):
if is_mother_vertex(graph, vertex):
mother_vertex = vertex
break

if mother_vertex is not None:


print("The mother vertex is", mother_vertex)
else:
print("There is no mother vertex.")

Output -
The mother vertex is A
# Write a code to implement eight puzzle algorithm

import heapq

class PuzzleNode:
def __init__(self, state, parent=None, move=None, cost=0):
self.state = state
self.parent = parent
self.move = move
self.cost = cost
self.heuristic = self.calculate_heuristic()

def calculate_heuristic(self):
total_distance = 0
for i in range(3):
for j in range(3):
if self.state[i][j] != 0:
goal_row, goal_col = divmod(self.state[i][j] - 1, 3)
total_distance += abs(i - goal_row) + abs(j - goal_col)
return total_distance

def __lt__(self, other):


return (self.cost + self.heuristic) < (other.cost + other.heuristic)

def get_neighbors(node):
neighbors = []
empty_row, empty_col = find_empty_space(node.state)

moves = [(0, 1), (0, -1), (1, 0), (-1, 0)]


for move in moves:
new_row, new_col = empty_row + move[0], empty_col + move[1]
if 0 <= new_row < 3 and 0 <= new_col < 3:
new_state = [list(row) for row in node.state]
new_state[empty_row][empty_col], new_state[new_row][new_col] = new_state[new_row]
[new_col], 0
neighbors.append(PuzzleNode(tuple(map(tuple, new_state)), parent=node, move=(new_row,
new_col), cost=node.cost + 1))

return neighbors

def find_empty_space(state):
for i in range(3):
for j in range(3):
if state[i][j] == 0:
return i, j

def is_goal(state):
return state == ((1, 2, 3), (4, 5, 6), (7, 8, 0))

def solve_puzzle(initial_state):
initial_node = PuzzleNode(tuple(map(tuple, initial_state)))
priority_queue = [initial_node]
visited = set()

while priority_queue:
current_node = heapq.heappop(priority_queue)

if current_node.state in visited:
continue

visited.add(current_node.state)

if is_goal(current_node.state):
path = []
while current_node:
path.append(current_node.state)
current_node = current_node.parent
return reversed(path)

neighbors = get_neighbors(current_node)
for neighbor in neighbors:
heapq.heappush(priority_queue, neighbor)

return None

initial_state = [[1, 2, 3], [4, 0, 5], [7, 8, 6]]


solution = solve_puzzle(initial_state)

if solution:
print("Solution found:")
for step, state in enumerate(solution):
print(f"Step {step + 1}:")
for row in state:
print(row)
print()
else:
print("No solution found.")

Output -
Solution found:
Step 1:
(1, 2, 3)
(4, 0, 5)
(7, 8, 6)

Step 2:
(1, 2, 3)
(4, 5, 0)
(7, 8, 6)

Step 3:
(1, 2, 3)
(4, 5, 6)
(7, 8, 0)
# Write a code to implement types of hill climbing

import random

def simple_hill_climbing(initial_state, max_iterations):


current_state = initial_state

for _ in range(max_iterations):
neighbors = get_neighbors(current_state)
best_neighbor = max(neighbors, key=evaluate_fitness)

if evaluate_fitness(best_neighbor) <= evaluate_fitness(current_state):


break

current_state = best_neighbor

return current_state

def steepest_ascent_hill_climbing(initial_state, max_iterations):


current_state = initial_state

for _ in range(max_iterations):
neighbors = get_neighbors(current_state)
best_neighbor = max(neighbors, key=evaluate_fitness)

if evaluate_fitness(best_neighbor) <= evaluate_fitness(current_state):


break

current_state = best_neighbor

return current_state

def get_neighbors(state):
return [state + 1, state - 1]

def evaluate_fitness(state):
return -abs(state - 5)

initial_state = random.randint(0, 10)


max_iterations = 100

print("Simple Hill Climbing:")


result_simple = simple_hill_climbing(initial_state, max_iterations)
print("Final State:", result_simple)
print("Fitness:", evaluate_fitness(result_simple))
print()

print("Steepest-Ascent Hill Climbing:")


result_steepest = steepest_ascent_hill_climbing(initial_state, max_iterations)
print("Final State:", result_steepest)
print("Fitness:", evaluate_fitness(result_steepest))

Output -

Simple Hill Climbing:


Final State: 5
Fitness: 0

Steepest-Ascent Hill Climbing:


Final State: 5
Fitness: 0
# Write generative algorithm to solve traveling salesman problem

import random
import numpy as np

class TSPGeneticAlgorithm:
def __init__(self, num_cities, population_size, generations, mutation_rate):
self.num_cities = num_cities
self.population_size = population_size
self.generations = generations
self.mutation_rate = mutation_rate
self.distances = np.zeros((num_cities, num_cities))
self.generate_random_distances()
self.population = self.initialize_population()

def generate_random_distances(self):
for i in range(self.num_cities):
for j in range(i + 1, self.num_cities):
self.distances[i][j] = self.distances[j][i] = random.randint(1, 100)

def initialize_population(self):
return [np.random.permutation(self.num_cities) for _ in range(self.population_size)]

def evaluate_fitness(self, route):


total_distance = sum(self.distances[route[i]][route[i + 1]] for i in range(self.num_cities - 1))
total_distance += self.distances[route[-1]][route[0]]
return 1 / total_distance

def crossover(self, parent1, parent2):


crossover_point = random.randint(1, self.num_cities - 1)
child = np.zeros(self.num_cities, dtype=int)
child[:crossover_point] = parent1[:crossover_point]
idx = crossover_point
for gene in parent2:
if gene not in child:
child[idx] = gene
idx += 1
if idx == self.num_cities:
break
return child

def mutate(self, route):


if random.random() < self.mutation_rate:
idx1, idx2 = random.sample(range(self.num_cities), 2)
route[idx1], route[idx2] = route[idx2], route[idx1]

def evolve_population(self):
new_population = []
best_route = max(self.population, key=self.evaluate_fitness)
new_population.append(best_route)
while len(new_population) < self.population_size:
parent1, parent2 = random.sample(self.population, 2)
child = self.crossover(parent1, parent2)
self.mutate(child)
new_population.append(child)
self.population = new_population

def find_best_route(self):
for _ in range(self.generations):
self.evolve_population()
return max(self.population, key=self.evaluate_fitness)

num_cities = 10
population_size = 100
generations = 1000
mutation_rate = 0.01

tsp_genetic_algorithm = TSPGeneticAlgorithm(num_cities, population_size, generations,


mutation_rate)
best_route = tsp_genetic_algorithm.find_best_route()

print("Best Route:", best_route)


print("Best Fitness:", tsp_genetic_algorithm.evaluate_fitness(best_route))

Output -

Best Route: [8 7 5 9 6 2 4 3 1 0]
Best Fitness: 0.004016064257028112
# Web spidering / Scrolling

class Node:
def __init__(self, node_id, data_size):
self.node_id = node_id
self.data = bytearray(data_size)

def process_large_graph(nodes):
for node in nodes:
process_data(node.data)

def process_data(data):
pass

def main():
num_nodes = 5
data_size_per_node = 100 * 1024 * 1024

nodes = [Node(node_id=i, data_size=data_size_per_node) for i in range(num_nodes)]

process_large_graph(nodes)

if __name__ == "__main__":
main()
# Perform Iterative_deepening on a graph

graph = {
1: [2, 3, 4],
2: [5, 6, 7],
3: [8],
4: [9, 10],
5: [11, 12],
6: [13],
7: [14],
8: [15],
9: [15, 16],
10: [17]
}

def iterative_deepening_dfs(start, goal):


for depth_limit in range(1, len(graph)):
visited = set()
path = []
if depth_limited_dfs(start, goal, depth_limit, visited, path):
return path
return None

def depth_limited_dfs(current, goal, depth_limit, visited, path):


if current == goal:
path.append(current)
return True

if depth_limit <= 0:
return False

visited.add(current)
path.append(current)

for neighbor in graph.get(current, []):


if neighbor not in visited:
if depth_limited_dfs(neighbor, goal, depth_limit - 1, visited, path):
return True

path.pop()
return False

start_node = 1
goal_node = 15
result = iterative_deepening_dfs(start_node, goal_node)

if result:
print(f"Path from {start_node} to {goal_node}: {result}")
else:
print(f"No path found from {start_node} to {goal_node} within depth limit.")
Output -

Path from 1 to 15: [1, 3, 8, 15]

You might also like