Ai Lab Manual
Ai Lab Manual
Rule-Based Reasoning
Rule-based reasoning is a method of reasoning that uses a set of "if-then" rules (production rules)
to derive conclusions or take actions. It is commonly used in expert systems and AI for decision
making.
Key Characteristics:
Uses rules in the form: IF condition(s) THEN action/conclusion.
Conditions are often based on facts or data.
Can handle chaining of rules (forward or backward chaining).
More procedural and operational compared to propositional logic.
Example:
Rules:
IF it is raining THEN the ground is wet.
IF the ground is wet THEN carry an umbrella.
Facts:
It is raining.
Reasoning:
From the first rule and fact, conclude the ground is wet.
From the second rule and conclusion, decide to carry an umbrella.
expr2 = (~P) | Q # ¬P ∨ Q
# Check equivalence
print ("Equivalent:", Equivalent (expr1, expr2). simplify())
# Simplify expression
expr = (P | Q) & (~P | Q)
print ("Simplified:", simplify_logic(expr))
# Check tautology
tautology = P | ~P
print ("Is tautology:", simplify_logic(tautology) == True)
Extend the rule-based system to include additional conditions for diagnosing diseases.
symptoms = {
"fever": True,
"cough": True,
"shortness_of_breath": True, new symptom
"loss_of_taste": False # new symptom
}
def diagnose(symptoms):
if symptoms["fever"] and symptoms["cough"] and symptoms["shortness_of_breath"]:
return "Possible COVID-19"
elif symptoms["fever"] and symptoms["loss_of_taste"]:
return "Possible COVID-19 Variant"
else:
return "Diagnosis unclear"
print(diagnose(symptoms))
Write a Prolog program that defines family relationships and infers parent-child
relationships.
% Define some family facts: parent (Parent, Child).
parent (john, mary).
parent (jane, mary).
parent (mary, susan).
parent (mary, tom).
parent (susan, alice).
% Define father and mother for clarity (optional)
father (john, mary).
mother (jane, mary).
mother (mary, susan).
mother (mary, tom).
mother (susan, alice).
% Define child relationship (child is inverse of parent)
child (Child, Parent): - parent (Parent, Child).
% Example queries you can run:
%? - parent (john, mary).
%? - child (mary, john).
%? - child (alice, susan).
Implement a Python script that dynamically takes user input to evaluate logical
expressions.
from sympy import symbols, sympify, to_cnf
expr_str = input ("Enter logical expression (use & |, ~, >>): ")
# Extract symbols from input
symbols_in_expr = set (filter (str.isalpha, expr_str.replace(' ', '')))
symbs = symbols (. join(symbols_in_expr))
sym_dict = {str(s): s for s in symbs}
try:
expr = sympify (expr_str, locals=sym_dict)
print ("Original:", expr)
print ("Simplified:", expr.simplify())
print ("CNF:", to_cnf (expr, simplify=True))
except Exception as e:
print ("Error:", e)
Explain the difference between BFS and DFS with examples.
BFS (Breadth-First Search)
Approach: Explores all neighbors of a node before moving to the next level.
Data structure: Uses a queue (FIFO).
Traversal order: Level by level.
Use case: Finding the shortest path in unweighted graphs.
Example:
A
/\
B C
/ \
D E
BFS starting at A:
Visit order → A → B, C → D, E
DFS (Depth-First Search)
Approach: Explores as far as possible along one branch before backtracking.
Data structure: Uses a stack (LIFO) or recursion.
Traversal order: Deep along a path before exploring siblings.
Use case: Topological sorting, cycle detection.
Example:
Same graph, DFS starting at A:
Possible visit order → A → B → D → C → E
Modify the BFS and DFS implementations to find the shortest path in an
unweighted graph.
from collections import deque
def bfs_shortest_path (graph, start, goal):
queue = deque ([(start, [start]])
visited = {start}
while queue:
node, path = queue. popleft ()
if node == goal:
return path
for neighbor in graph.get (node, []):
if neighbor not in visited:
visited.add(neighbor)
queue.append((neighbor, path + [neighbor]))
return None
Compare the execution times of BFS and DFS on a large dataset.
Time Complexity O (V + E) O (V + E)