Principles Of AI Lab Exercises
import heapq

# Define a grid (0 represents empty, 1 represents obstacles)
grid = [
    [0, 0, 0, 0, 0],
    [0, 1, 1, 0, 0],
    [0, 0, 0, 0, 1],
    [0, 1, 1, 0, 0],
    [0, 0, 0, 0, 0],
]

# Define the start and goal positions
start = (0, 0)
goal = (4, 4)


# Define a heuristic function (Manhattan distance)
def heuristic(node, goal):
    return abs(node[0] - goal[0]) + abs(node[1] - goal[1])


# A* algorithm
def astar(grid, start, goal):
    open_list = [(0.0, start)]  # Priority queue (f-score, node)
    came_from = {}  # Dictionary to store the parent node of each node

    # Initialize g_score with all nodes set to infinity
    g_score = {
        (x, y): float("inf") for x in range(len(grid)) for y in range(len(grid[0]))
    }
    g_score[start] = 0

    f_score = {node: float("inf") for node in g_score}
    f_score[start] = heuristic(start, goal)

    while open_list:
        _, current = heapq.heappop(open_list)

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

        for neighbor in [(0, 1), (0, -1), (1, 0), (-1, 0)]:
            x, y = current[0] + neighbor[0], current[1] + neighbor[1]

            if 0 <= x < len(grid) and 0 <= y < len(grid[0]) and grid[x][y] == 0:
                tentative_g_score = g_score[current] + 1

                if tentative_g_score < g_score[(x, y)]:
                    came_from[(x, y)] = current
                    g_score[(x, y)] = tentative_g_score
                    f_score[(x, y)] = tentative_g_score + heuristic((x, y), goal)
                    heapq.heappush(open_list, (f_score[(x, y)], (x, y)))

    return None  # No path found


# Find the path
path = astar(grid, start, goal)

if path:
    print("Path found:")
    for node in path:
        print(node)
else:
    print("No path found.")

Programs/A_star.py
Esai-Keshav/principles-of-ai-lab
def bfs(graph, start):
    visited = set()
    queue = []
    visited.add(start)
    queue.append(start)

    while queue:
        node = queue.pop(0)
        print(node, end="\t")

        for neigh in graph[node]:
            if neigh not in visited:
                visited.add(neigh)
                queue.append(neigh)


if __name__ == "__main__":
    graph = {0: [1, 2], 1: [2], 2: [0, 3], 3: [3]}

    print("BFS starting from 2")
    bfs(graph, 2)

Programs/BFS(breath).py
Esai-Keshav/principles-of-ai-lab
# Define a depth-first search (DFS) function that traverses a graph.
# Parameters:
# - 'graph': The graph represented as an adjacency list.
# - 'start': The starting vertex for the DFS traversal.
# - 'visited': A set to keep track of visited vertices.


def dfs(graph, start, visited):
    # Check if the 'start' vertex has not been visited.
    if start not in visited:
        # Print the current 'start' vertex as part of the traversal.
        print(start, end=" ")
        # Mark the 'start' vertex as visited by adding it to the 'visited' set.
        visited.add(start)
        # Explore neighbors of the current 'start' vertex using recursion.
        for neighbor in graph[start]:
            dfs(graph, neighbor, visited)


# Example usage:
if __name__ == "__main__":
    # Define a sample graph as an adjacency list where letters represent vertices.
    graph = {
        "A": ["B", "C"],
        "B": ["A", "D", "E"],
        "C": ["A", "F"],
        "D": ["B"],
        "E": ["B", "F"],
        "F": ["C", "E"],
    }

    # Create an empty set 'visited' to keep track of visited vertices during DFS.
    visited = set()

    # Print a message indicating the start of the DFS traversal.
    print("Depth-First Traversal (starting from vertex 'A'):")

    # Call the 'dfs' function with the sample graph, starting vertex 'A', and the 'visited' set.
    dfs(graph, "A", visited)

Programs/DFS(depth).py
Esai-Keshav/principles-of-ai-lab
from itertools import permutations


def solve_cryptarithmetic(puzzle):
    letters = set("".join(puzzle))
    print(letters)
    if len(letters) > 10:
        return "Too many letters for unique digit assignment."

    for perm in permutations(range(10), len(letters)):
        if all(perm[puzzle[i].index(puzzle[i][0])] != 0 for i in range(len(puzzle))):
            mapping = dict(zip(letters, perm))
            num1 = int("".join([str(mapping[c]) for c in puzzle[0]]))
            num2 = int("".join([str(mapping[c]) for c in puzzle[1]]))
            num3 = int("".join([str(mapping[c]) for c in puzzle[2]]))

            if num1 + num2 == num3:
                return mapping

    return "No solution found."


def main():
    print("Example : \n First word + Second word = Third word")
    a = input("ENter the first word = ")
    b = input("ENter the second word = ")
    c = input("ENter the third word = ")
    puzzle = [a, b, c]
    solution = solve_cryptarithmetic(puzzle)
    print(solution)


main()

Programs/cryto_arthrmatic.py
Esai-Keshav/principles-of-ai-lab
class KnowledgeBase:
    def __init__(self):
        self.facts = set()

    def add_fact(self, fact):
        self.facts.add(fact)

    def remove_fact(self, fact):
        self.facts.discard(fact)

    def check_fact(self, fact):
        return fact in self.facts

    def display_facts(self):
        print("Facts in the Knowledge Base:")
        for fact in self.facts:
            print(fact)

    def to_first_order_logic(self):
        first_order_logic_facts = []

        for fact in self.facts:
            # Split the fact into words
            words = fact.split()

            # Check if the fact has the format: [subject] [is/are] [object(s)]
            if len(words) >= 3 and words[1] in ["is", "are"]:
                subject = words[0]
                predicate = words[2]
                objects = words[3:]

                # Create a first-order logic statement
                if len(objects) == 1:
                    first_order_logic = f"{predicate}({subject} {objects[0]})"
                else:
                    first_order_logic = f"{predicate}({subject} " + " ".join(objects) + ")"

                first_order_logic_facts.append(first_order_logic)

        return first_order_logic_facts

# Create a knowledge base
kb = KnowledgeBase()

# Accept facts from the user
print("Enter facts (one per line). Type 'q' to quit.")
while True:
    fact_str = input("Enter a fact: ")
    if fact_str.lower() == 'q':
        break

    kb.add_fact(fact_str)

# Check if a fact is in the knowledge base
check_fact_str = input("Enter a fact to check: ")
if kb.check_fact(check_fact_str):
    print(f"'{check_fact_str}' is a fact in the knowledge base.")
else:
    print(f"'{check_fact_str}' is not a fact in the knowledge base.")

# Display all facts in the knowledge base
kb.display_facts()

# Convert facts to first-order logic and display
first_order_logic_facts = kb.to_first_order_logic()
print("\nFacts in First-Order Logic:")
for fact in first_order_logic_facts:
    print(fact)

Programs/predicate-logic.py
Esai-Keshav/principles-of-ai-lab
class Node:
    def __init__(self, name):
        self.name = name
        self.edges = []

    def add_edge(self, relation, node):
        self.edges.append((relation, node))

    def __str__(self):
        return self.name


class SemanticNetwork:
    def __init__(self):
        self.nodes = []

    def add_node(self, name):
        node = Node(name)
        self.nodes.append(node)
        return node

    def __str__(self):
        result = "Semantic Network:\n"
        for node in self.nodes:
            result += f"{node} has relations:\n"
            for relation, related_node in node.edges:
                result += f"  - {relation}: {related_node}\n"
        return result


# Create a semantic network
semantic_net = SemanticNetwork()

while True:
    print("1. Add Node")
    print("2. Add Relationship")
    print("3. Exit")
    choice = input("Enter your choice: ")

    if choice == "1":
        node_name = input("Enter node name: ")
        semantic_net.add_node(node_name)
        print(f"Node '{node_name}' added.")
    elif choice == "2":
        node_name = input("Enter node name: ")
        relation = input("Enter relation: ")
        related_node_name = input("Enter related node name: ")

        # Find the nodes with the specified names
        node = next((n for n in semantic_net.nodes if n.name == node_name), None)
        related_node = next(
            (n for n in semantic_net.nodes if n.name == related_node_name), None
        )

        if node and related_node:
            node.add_edge(relation, related_node)
            print(
                f"Relationship added: {node_name} -> {relation} -> {related_node_name}"
            )
        else:
            print("One or both nodes not found.")
    elif choice == "3":
        break
    else:
        print("Invalid choice. Please try again.")

# Display the semantic network
print(semantic_net)

Programs/sematic_net.py
Esai-Keshav/principles-of-ai-lab