0% found this document useful (0 votes)
22 views18 pages

AI Lab File Main

The document contains a collection of algorithms and their implementations, including A* algorithm, water jug problem, 8 puzzle problem, graph coloring, breadth-first and depth-first search, and hill climbing. Each section provides code examples and explanations for solving specific computational problems. The document serves as a resource for understanding various algorithmic approaches in programming.

Uploaded by

kishugupta001
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
22 views18 pages

AI Lab File Main

The document contains a collection of algorithms and their implementations, including A* algorithm, water jug problem, 8 puzzle problem, graph coloring, breadth-first and depth-first search, and hill climbing. Each section provides code examples and explanations for solving specific computational problems. The document serves as a resource for understanding various algorithmic approaches in programming.

Uploaded by

kishugupta001
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

INDEX

S. No. Program Name Page No.

1 Implementation of A*
algorithm

2 Write a C program to
find sum and average
of three numbers.

3 Solution for water jug


problem

4 Solving 8 puzzle
problem

5 Graph Coloring

6 Implementation of
Breadth First Search
and Depth First Search

7 Hill Climbing
implementation
Q 1. Implementation of A* algorithm

Code:

import heapq

def a_star_search(graph, start, goal, heuristic):


​ open_set = [(heuristic[start], 0, start)]
​ came_from = {}
​ g_score = {node: float('inf') for node in graph}
​ g_score[start] = 0

​ while open_set:
​ _, current_g, current = heapq.heappop(open_set)

​ if current == goal:
​ path = []
​ while current in came_from:
​ path.append(current)
​ current = came_from[current]
​ path.append(start)
​ return path[::-1]

​ for neighbor, weight in graph[current].items():
​ tentative_g = g_score[current] + weight

​ if tentative_g < g_score[neighbor]:
​ came_from[neighbor] = current
​ g_score[neighbor] = tentative_g
​ f_score = tentative_g + heuristic[neighbor]
​ heapq.heappush(open_set, (f_score, tentative_g, neighbor))

​ return None

# Example usage
if __name__ == "__main__":
​ # Sample graph represented as an adjacency list with weights
​ graph = {
​ 'A': {'B': 1, 'C': 4},
​ 'B': {'A': 1, 'C': 2, 'D': 5},
​ 'C': {'A': 4, 'B': 2, 'D': 1},
​ 'D': {'B': 5, 'C': 1}
​ }

​ # Sample heuristic values (straight-line distance to goal)


​ heuristic = {
​ 'A': 7,
​ 'B': 6,
​ 'C': 2,
​ 'D': 0
​ }

​ path = a_star_search(graph, 'A', 'D', heuristic)


​ print(f"Path found: {path}")

Output:
Q2. Implementation of AO* algorithm

Code:

import heapq

def a_star_search(graph, start, goal, heuristic):


​ open_set = [(heuristic[start], 0, start)]
​ came_from = {}
​ g_score = {node: float('inf') for node in graph}
​ g_score[start] = 0

​ while open_set:
​ _, current_g, current = heapq.heappop(open_set)

​ if current == goal:
​ path = []
​ while current in came_from:
​ path.append(current)
​ current = came_from[current]
​ path.append(start)
​ return path[::-1]

​ for neighbor, weight in graph[current].items():
​ tentative_g = g_score[current] + weight

​ if tentative_g < g_score[neighbor]:
​ came_from[neighbor] = current
​ g_score[neighbor] = tentative_g
​ f_score = tentative_g + heuristic[neighbor]
​ heapq.heappush(open_set, (f_score, tentative_g, neighbor))

​ return None

# Example usage
if __name__ == "__main__":
​ # Sample graph represented as an adjacency list with weights
​ graph = {
​ 'A': {'B': 1, 'C': 4},
​ 'B': {'A': 1, 'C': 2, 'D': 5},
​ 'C': {'A': 4, 'B': 2, 'D': 1},
​ 'D': {'B': 5, 'C': 1}
​ }

​ # Sample heuristic values (straight-line distance to goal)


​ heuristic = {
​ 'A': 7,
​ 'B': 6,
​ 'C': 2,
​ 'D': 0
​ }

​ path = a_star_search(graph, 'A', 'D', heuristic)


​ print(f"Path found: {path}")

Output:
Q3. Solution for water jug problem

Code:

def water_jug_problem(capacity_a, capacity_b, target):


​ visited = set()
​ queue = [(0, 0, [])]

​ while queue:
​ jug_a, jug_b, path = queue.pop(0)

​ if jug_a == target or jug_b == target:
​ return path + [(jug_a, jug_b)]

​ if (jug_a, jug_b) in visited:
​ continue

​ visited.add((jug_a, jug_b))

​ # Fill jug A
​ if jug_a < capacity_a:
​ queue.append((capacity_a, jug_b, path + [(jug_a, jug_b)]))

​ # Fill jug B
​ if jug_b < capacity_b:
​ queue.append((jug_a, capacity_b, path + [(jug_a, jug_b)]))

​ # Empty jug A
​ if jug_a > 0:
​ queue.append((0, jug_b, path + [(jug_a, jug_b)]))

​ # Empty jug B
​ if jug_b > 0:
​ queue.append((jug_a, 0, path + [(jug_a, jug_b)]))

​ # Pour from A to B
​ if jug_a > 0 and jug_b < capacity_b:
​ pour = min(jug_a, capacity_b - jug_b)
​ queue.append((jug_a - pour, jug_b + pour, path + [(jug_a, jug_b)]))

​ # Pour from B to A
​ if jug_b > 0 and jug_a < capacity_a:
​ pour = min(jug_b, capacity_a - jug_a)
​ queue.append((jug_a + pour, jug_b - pour, path + [(jug_a, jug_b)]))

​ return None

# Example usage
if __name__ == "__main__":
​ solution = water_jug_problem(4, 3, 2)
​ print("Solution path:")
​ for step in solution:
​ print(f"Jug A: {step[0]}, Jug B: {step[1]}")

Output:
Q4. Solving 8 puzzle problem

Code:

class EightPuzzle:
​ def __init__(self, initial_state, goal_state):
​ self.initial_state = initial_state
​ self.goal_state = goal_state

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

​ def get_possible_moves(self, state):


​ blank_i, blank_j = self.find_blank(state)
​ moves = []

​# Up
​if blank_i > 0:
​ new_state = [row[:] for row in state]
​ new_state[blank_i][blank_j], new_state[blank_i-1][blank_j] =
new_state[blank_i-1][blank_j], new_state[blank_i][blank_j]
​ moves.append(new_state)

​ # Down
​ if blank_i < 2:
​ new_state = [row[:] for row in state]
​ new_state[blank_i][blank_j], new_state[blank_i+1][blank_j] =
new_state[blank_i+1][blank_j], new_state[blank_i][blank_j]
​ moves.append(new_state)

​# Left
​if blank_j > 0:
​ new_state = [row[:] for row in state]
​ new_state[blank_i][blank_j], new_state[blank_i][blank_j-1] =
new_state[blank_i][blank_j-1], new_state[blank_i][blank_j]
​ moves.append(new_state)

​ # Right
​ if blank_j < 2:
​ new_state = [row[:] for row in state]
​ new_state[blank_i][blank_j], new_state[blank_i][blank_j+1] =
new_state[blank_i][blank_j+1], new_state[blank_i][blank_j]
​ moves.append(new_state)

​ return moves

​ def state_to_string(self, state):


​ return ''.join(str(state[i][j]) for i in range(3) for j in range(3))

​ def solve_bfs(self):
​ queue = [(self.initial_state, [])]
​ visited = set([self.state_to_string(self.initial_state)])

​ while queue:
​ state, path = queue.pop(0)

​ if state == self.goal_state:
​ return path + [state]

​ for next_state in self.get_possible_moves(state):
​ state_str = self.state_to_string(next_state)
​ if state_str not in visited:
​ visited.add(state_str)
​ queue.append((next_state, path + [state]))

​ return None

# Example usage
if __name__ == "__main__":
​ initial_state = [
​ [1, 2, 3],
​ [4, 0, 6],
​ [7, 5, 8]
​ ]

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

​ puzzle = EightPuzzle(initial_state, goal_state)


​ solution = puzzle.solve_bfs()

​ if solution:
​ print(f"Solution found in {len(solution)-1} steps:")
​ for i, state in enumerate(solution):
​ print(f"Step {i}:")
​ for row in state:
​ print(row)
​ print()
​ else:
​ print("No solution found.")

Output:
Q5. Graph Coloring

Code:

def graph_coloring(graph, colors):


​ color_assignment = {}

​ def is_safe(vertex, color):


​ for neighbor in graph[vertex]:
​ if neighbor in color_assignment and color_assignment[neighbor] ==
color:
​ return False
​ return True

​ def backtrack(vertex_index):
​ if vertex_index == len(graph):
​ return True

​ vertex = list(graph.keys())[vertex_index]

​ for color in colors:
​ if is_safe(vertex, color):
​ color_assignment[vertex] = color

​ if backtrack(vertex_index + 1):
​ return True

​ color_assignment.pop(vertex, None)

​ return False

​ if backtrack(0):
​ return color_assignment
​ return None

# Example usage
if __name__ == "__main__":
​ # Sample graph represented as an adjacency list
​ graph = {
​ 'A': ['B', 'C'],
​ 'B': ['A', 'C', 'D'],
​ 'C': ['A', 'B', 'D'],
​ 'D': ['B', 'C']
​ }

​ # Available colors
​ colors = ['Red', 'Green', 'Blue']

​ solution = graph_coloring(graph, colors)

​ if solution:
​ print("Graph coloring solution:")
​ for vertex, color in solution.items():
​ print(f"Vertex {vertex}: {color}")
​ else:
​ print("No solution found.")

Output:
Q6. Implementation of Breadth First Search and Depth First Search

Code:

def graph_coloring(graph, colors):


​ color_assignment = {}

​ def is_safe(vertex, color):


​ for neighbor in graph[vertex]:
​ if neighbor in color_assignment and color_assignment[neighbor] ==
color:
​ return False
​ return True

​ def backtrack(vertex_index):
​ if vertex_index == len(graph):
​ return True

​ vertex = list(graph.keys())[vertex_index]

​ for color in colors:
​ if is_safe(vertex, color):
​ color_assignment[vertex] = color

​ if backtrack(vertex_index + 1):
​ return True

​ color_assignment.pop(vertex, None)

​ return False

​ if backtrack(0):
​ return color_assignment
​ return None

# Example usage
if __name__ == "__main__":
​ # Sample graph represented as an adjacency list
​ graph = {
​ 'A': ['B', 'C'],
​ 'B': ['A', 'C', 'D'],
​ 'C': ['A', 'B', 'D'],
​ 'D': ['B', 'C']
​ }

​ # Available colors
​ colors = ['Red', 'Green', 'Blue']

​ solution = graph_coloring(graph, colors)

​ if solution:
​ print("Graph coloring solution:")
​ for vertex, color in solution.items():
​ print(f"Vertex {vertex}: {color}")
​ else:
​ print("No solution found.")

def dfs(graph, start):


​ visited = set()
​ path = []
​ def dfs_recursive(vertex):
​ visited.add(vertex)
​ path.append(vertex)

​ for neighbor in graph[vertex]:
​ if neighbor not in visited:
​ dfs_recursive(neighbor)

​ dfs_recursive(start)
​ return path

# Example usage
if __name__ == "__main__":
​ # Sample graph represented as an adjacency list
​ graph = {
​ 'A': ['B', 'C'],
​ 'B': ['A', 'D', 'E'],
​ 'C': ['A', 'F'],
​ 'D': ['B'],
​ 'E': ['B', 'F'],
​ 'F': ['C', 'E']
​ }

​ traversal_path = dfs(graph, 'A')


​ print(f"DFS traversal: {traversal_path}")

Output:
Q7. Hill Climbing implementation

Code:

def hill_climbing(problem, heuristic, max_iterations=1000):


​ current = problem.initial_state

​ for _ in range(max_iterations):
​ neighbors = problem.get_neighbors(current)
​ if not neighbors:
​ break

​ # Find the neighbor with the best value according to heuristic
​ neighbor_values = [(n, heuristic(n)) for n in neighbors]
​ best_neighbor, best_value = max(neighbor_values, key=lambda x: x[1])

​ # If the best neighbor is not better than current, we've reached a local
maximum
​ if heuristic(current) >= best_value:
​ break

​ current = best_neighbor

​ return current

class HillClimbingProblem:
​ def __init__(self, initial_state):
​ self.initial_state = initial_state

​ def get_neighbors(self, state):
​ # This should be implemented for specific problems
​ pass

# Example of a simple numeric optimization problem


class SimpleOptimizationProblem(HillClimbingProblem):
​ def get_neighbors(self, state):
​ # Generate neighbors by adding or subtracting 1 from each dimension
​ neighbors = []
​ for i in range(len(state)):
​ neighbor1 = list(state)
​ neighbor1[i] += 1
​ neighbors.append(tuple(neighbor1))

​ neighbor2 = list(state)
​ neighbor2[i] -= 1
​ neighbors.append(tuple(neighbor2))

​ return neighbors

# Example usage
if __name__ == "__main__":
​ # Define a simple heuristic function (to be maximized)
​ # This one represents a 2D function with a peak at (5, 7)
​ def heuristic(state):
​ x, y = state
​ return -(x-5)**2 - (y-7)**2

​ # Starting from point (0, 0)


​ problem = SimpleOptimizationProblem((0, 0))

​ solution = hill_climbing(problem, heuristic)


​ print(f"Hill climbing result: {solution}")
​ print(f"Function value at solution: {heuristic(solution)}")

Output:

You might also like