Teena Ai File
Teena Ai File
Theory:
The two-jug problem is a classic AI search problem where we must measure a
specific amount of water using two jugs of different capacities, following a set of
constraints. In this experiment, we have a 3-liter jug and a 5-liter jug, and our goal
is to measure exactly 4 liters using systematic steps. The problem can be solved
using state-space search algorithms like BFS or DFS, where each state represents
the water levels in both jugs. The solution involves filling, transferring, and
emptying water until we reach the desired amount.
Program :
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> goal = {4, 0};
vector<string> options = {
"1. Add Jug A water to Jug B",
"2. Add Jug B water to Jug A",
"3. Empty Jug A",
"4. Empty Jug B",
"5. Fill Jug A",
"6. Fill Jug B"
};
while (true) {
cout << "Current State: A=" << jugs[0] << ", B=" << jugs[1] <<
endl;
if (jugs == goal) {
cout << "Success!" << endl;
break;
}
switch (choice) {
case 1: swap(1); break;
case 2: swap(0); break;
case 3: empty(0); break;
case 4: empty(1); break;
case 5: fill(0); break;
case 6: fill(1); break;
default: cout << "Invalid choice" << endl;
}
}
return 0;
}
Output:
LEARNING :
Through the program, we learned how search algorithms can be applied towards
solving real-world problems. We were able to solve the two jugs water measuring
problem by exhaustively searching through all its possible states and following a simple
decision process to reach a desired result. This practical exercise illustrates the
importance of state space search in AI by showing that even with only simple loops and
conditionals, one can put together an algorithm that convincingly solves a problem.
CONCLUSION
The generalized program clearly shows how search algorithms can be used to
measure a specific amount of water with any two jugs of different capacities. It
also strengthens our knowledge in the area of search algorithms while
underlining the importance of developing flexible solutions that could work with
a whole range of inputs.
Experiment – 2
Aim:
8 Puzzle Problem
Theory:
One of the most famous puzzles is the 8-puzzle, which features a 3 × 3 grid with
one space empty and nine tiles numbered from 1 to 8. The latter can be slid into
the empty space, allowing them to be rearranged. The problem will consist of
changing the puzzle from the given configuration to a target configuration with a
series of valid movements. Thus, one is to find the sequence of moves that would
bring the puzzle into its goal configuration. So, the solution implies an
examination of various move sequences, usually represented by a tree whose
branches would correspond to the possible move from some state. Some other
efficient methods of solution are algorithms of Breadth- First Search and А*,
which search through prospective solutions in an orderly fashion
Program:
#include <iostream>
using namespace std;
const int S = 3;
int main() {
int matrix[S][S];
cout << "Enter numbers from 1 to 8 in any order (use 0 for the blank
space):\n";
if (x == -1 || y == -1) {
cout << "Error: No blank space (0) found in matrix.\n";
return 1;
}
char move;
while (true) {
printM(matrix, x, y);
cout << "Enter move (U/D/L/R): ";
cin >> move;
int x1 = x, y1 = y;
switch (move) {
case 'U':
case 'u':
if (x > 0) x1--;
else cout << "Invalid move!\n";
break;
case 'D':
case 'd':
if (x < S - 1) x1++;
else cout << "Invalid move!\n";
break;
case 'L':
case 'l':
if (y > 0) y1--;
else cout << "Invalid move!\n";
break;
case 'R':
case 'r':
if (y < S - 1) y1++;
else cout << "Invalid move!\n";
break;
default:
cout << "Invalid input! Use U, D, L, or R.\n";
continue;
}
return 0;
}
OUTPUT:
LEARNING:
State-Space Search: The concept it introduces is a consideration of all feasible
states in finding an optimum solution, wherein each configuration takes the form
of a particular state.It provides an algorithmic thinking process that, in a very
simple way, the puzzle shows how search algorithms like BFS or A* could be
employed in scientific and engineering applications to systematically explore
possibilities for the solution of complex problems. Optimization: The need is
stressed that finding a solution is not all; instead, one needs to find the most
efficient solution, which gives an optimum number of moves needed to achieve
this.
CONCLUSION
The 8-puzzle problem is a very straightforward and effective technique through
which to learn the rudiments in problem-solving and designing strategies for
related algorithms. Solving this puzzle actually deepens the basic understanding
of state-space explorations, search algorithms, and optimization techniques. Still,
the methods applied for 8-puzzle solving are relevant to far more serious
problems within the computer science and artificial intelligence field.
Experiment:3
Program:
l = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
m = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
def find_blank(tile):
for i in range(3):
for j in range(3):
if tile[i][j] == 0:
return i, j
return -1, -1
def down(tile):
a, b = find_blank(tile)
if a == 2:
print("Move down not possible")
else:
tile[a][b], tile[a + 1][b] = tile[a + 1][b], tile[a][b]
def up(tile):
a, b = find_blank(tile)
if a == 0:
print("Move up not possible")
else:
tile[a][b], tile[a - 1][b] = tile[a - 1][b], tile[a][b]
def right(tile):
a, b = find_blank(tile)
if b == 2:
print("Move right not possible")
else:
tile[a][b], tile[a][b + 1] = tile[a][b + 1], tile[a][b]
def left(tile):
a, b = find_blank(tile)
if b == 0:
print("Move left not possible")
else:
tile[a][b], tile[a][b - 1] = tile[a][b - 1], tile[a][b]
while l != m:
print("\nCurrent State:")
for row in l:
print(row)
current_heuristic = heuristic(l)
print("Heuristic Value:", current_heuristic)
if choice == 1:
up(l)
elif choice == 2:
down(l)
elif choice == 3:
right(l)
elif choice == 4:
left(l)
else:
print("Invalid choice")
continue
new_heuristic = heuristic(l)
Output :
LEARNING
Through this program, we learned how heuristic-based search can efficiently
optimize problem-solving in constraint-based environments. Unlike exhaustive
search methods, Hill Climbing intelligently selects moves that improve the
solution. The experiment highlighted both the strengths (fast convergence) and
limitations (getting stuck in local optima) of local search techniques. Additionally,
we explored strategies like random restarts and simulated annealing, which help
overcome local minima and improve solution quality.
CONCLUSION
The Hill Climbing algorithm provides an effective way to solve the 8 puzzle
problem by iteratively improving tile arrangements based on heuristic evaluation.
This experiment deepened our understanding of heuristic search techniques and
demonstrated how local search methods can be applied to optimization and
constraint satisfaction problems. However, due to its tendency to get trapped in
local optima, better alternatives like A search* or Simulated Annealing may be
preferred for more complex scenarios.
EXPERIMENT 4
Aim: Implementing BFS and DFS
Theory:
Breadth-First Search (BFS) and Depth-First Search (DFS) are
fundamental
algorithms used for traversing graphs.
● BFS:
○ Explores all neighbors at the present depth
before moving to the next level.
○ Uses a queue (FIFO) to track nodes.
○ Guarantees the shortest path in an unweighted graph.
● DFS:
○ Explores a path as deeply as possible
before backtracking.
○ Uses a stack (LIFO) or recursion for traversal.
○ May not always find the shortest path but is
useful for exploring deeper structures.
Program: BFS
#include <iostream>
#include <queue>
using namespace std;
int main() {
int visited[4] = {0}; // Array to track visited nodes
int i = 1; // Starting node
while (!q.empty()) {
int node = q.front();
q.pop();
return 0;
}
OUTPUT:
DFS:
#include <iostream>
#include <vector>
using namespace std;
vector<bool> visited(n,false);
Output:
LEARNING :
Through this program, we learned how BFS and DFS operate in graph
traversal. BFS explores layer by layer, ensuring the shortest path in
unweighted graphs, while DFS explores deeply first, making it useful for problems
like topological sorting and backtracking.
CONCLUSION : Both BFS and DFS effectively traversed the graph. BFS provided
a level-wise traversal, whereas DFS explored paths deeply before
backtracking. This experiment reinforced our understanding of
fundamental search algorithms and their use in solving graph-related problems.
Experiment -5
Initialization: Start by adding the initial node to the open set with its f(n).
Loop: While the open set is not empty, the node with the lowest f(n) value is
removed from the queue.
Goal Check: If this node is the goal, the algorithm terminates and returns the
discovered path.
Node Expansion: Otherwise, expand the node (find all its neighbors),
calculating g, h, and f values for each neighbor. Add each neighbor to the open
set if it's not already present, or if a better path to this neighbor is found.
Repeat: The loop repeats until the goal is reached or if there are no more nodes
in the open set, indicating no available path.
Program :
OUTPUT :
Learning
The A* (A-star) algorithm is a powerful and widely used pathfinding technique
that teaches several core principles in artificial intelligence and algorithm design.
It combines two key components: the actual cost from the start node to the
current node (g(n)) and a heuristic estimate of the cost from the current node to
the goal (h(n)). This combination allows A* to efficiently find the shortest path
between two points on a graph or grid.
Optimization : A* is highly optimized compared to uninformed search algorithms
Speed vs. Accuracy: A* smartly trades off between speed and accuracy using f(n)
= g(n) + h(n).
Heuristic Quality: A good heuristic drastically reduces time and memory by
exploring fewer nodes.
Conclusion :
The A* algorithm stands out as a powerful and intelligent approach to
pathfinding and graph traversal.While A* is powerful, it’s not without its
limitations. The memory consumption can be significant, as it needs to maintain
all explored and unexplored nodes in memory. Furthermore, the choice of
heuristic heavily influences the algorithm's performance; a poor heuristic can
lead to inefficient exploration and increased computation.
Experiment -6
Program:
Output :
Learning :
The AO* algorithm teaches how to solve problems using AND-OR graphs, where
solutions may require fulfilling multiple conditions (AND) or choosing among
alternatives (OR). Unlike traditional pathfinding, AO* works on goal trees .it
efficiently navigates such graphs using heuristics to guide the search toward the
most promising solution, avoiding exhaustive exploration. By recursively
evaluating subproblems and selectively expanding only the most relevant paths,
AO* emphasizes optimal decision-making in structured problem spaces. It
teaches the importance of heuristic design, optimal substructure, and intelligent
pruning, offering insights into building goal-driven, cost-effective, and scalable AI
systems.
Conclusion :
In conclusion, the AO* algorithm stands out as an efficient and intelligent
approach for solving problems in AND-OR graphs . Its ability to handle AND and
OR nodes allows for flexibility and efficiency in various applications, from gaming
to robotics and natural language processing.