Download as docx, pdf, or txt
Download as docx, pdf, or txt
You are on page 1of 14

Experiment-1

Aim: Write a program to conduct uninformed and informed search.

Theory:
An uninformed search is a searching technique that has no additional information about the distance
from the current state to the goal.

Informed Search is another technique that has additional information about the estimate distance from
the current state to the goal.

Basis of Informed search Uninformed search


comparison

Basic Uses knowledge to find the No use of knowledge


knowledge steps to the solution.

Efficiency Highly efficient as consumes Efficiency is mediatory


less time and cost.

Cost Low Comparatively high

Performance Finds the solution more Speed is slower than the informed
quickly. search.

Algorithms Heuristic depth-first and Depth-first search, breadth-first


breadth-first search, and A* search, and lowest cost first search
search
Experiment-1.1

Aim: Write a program to conduct Breadth First Search (Uninformed search) for a graph.

Program
#include<iostream>
#include <list>
using namespace std;
// This class represents a directed graph using
// adjacency list representation class
Graph
{
int V; // No. of vertices

// Pointer to an array containing adjacency


// lists list<int>
*adj;
public:
Graph(int V); // Constructor

// function to add an edge to graph void


addEdge(int v, int w);

// prints BFS traversal from a given source s void


BFS(int s);
};

Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)


{
adj[v].push_back(w); // Add w to v’s list.
}

void Graph::BFS(int s)
{
// Mark all the vertices as not visited bool
*visited = new bool[V];
for(int i = 0; i < V; i++) visited[i]
= false;

// Create a queue for BFS


list<int> queue;

// Mark the current node as visited and enqueue it


visited[s] = true;
queue.push_back(s);

// 'i' will be used to get all adjacent


// vertices of a vertex
list<int>::iterator i;

while(!queue.empty())
{
// Dequeue a vertex from queue and print it s =
queue.front();
cout << s << " ";
queue.pop_front();

// Get all adjacent vertices of the dequeued


// vertex s. If a adjacent has not been visited,
// then mark it visited and enqueue it
for (i = adj[s].begin(); i != adj[s].end(); ++i)
{
if (!visited[*i])
{
visited[*i] = true;
queue.push_back(*i);
}
}
}
}

// Driver program to test methods of graph class int


main()
{
// Create a graph given in the above diagram
Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);

cout << "Following is Breadth First Traversal "


<< "(starting from vertex 2) \n";
g.BFS(2);

return 0;
}
Output
Experiment-1.2

Aim: Write a program to conduct uninformed search (Depth First Search).

Program
#include<bits/stdc++.h> using
namespace std;
// Graph class represents a directed graph
// using adjacency list representation class Graph
{
int V; // No. of vertices

// Pointer to an array containing


// adjacency lists list<int>* adj;

// A recursive function used by DFS void


DFSUtil(int v, bool visited[]);

public:
Graph(int V); // Constructor
// function to add an edge to graph

void addEdge(int v, int w);


// DFS traversal of the vertices
// reachable from v void DFS(int
v);
};

Graph::Graph(int V)
{
this->V = V;
adj = new list<int>[V];
}

void Graph::addEdge(int v, int w)


{
adj[v].push_back(w); // Add w to v’s list.
}

void Graph::DFSUtil(int v, bool visited[])


{
// Mark the current node as visited and
// print it visited[v] = true;
cout << v << " ";

// Recur for all the vertices adjacent


// to this vertex list<int>::iterator
i;
for (i = adj[v].begin(); i != adj[v].end(); ++i) if (!
visited[*i])
DFSUtil(*i, visited);
}

// DFS traversal of the vertices reachable from v.


// It uses recursive DFSUtil() void
Graph::DFS(int v)
{
// Mark all the vertices as not visited bool* visited
= new bool[V];
for (int i = 0; i < V; i++) visited[i] =
false;

// Call the recursive helper function


// to print DFS traversal DFSUtil(v,
visited);
}

// Driver code int main()


{
// Create a graph given in the above diagram Graph g(4);
g.addEdge(0, 1);
g.addEdge(0, 2);
g.addEdge(1, 2);
g.addEdge(2, 0);
g.addEdge(2, 3);
g.addEdge(3, 3);

cout << "Following is Depth First Traversal" " (starting


from vertex 2) \n";
g.DFS(2);

return 0;
}
Output
Experiment-1.3

Aim: Implementation of Informed Search (Best First Search).

Program
#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> pi;

vector<vector<pi> > graph;

// Function for adding edges to graph


void addedge(int x, int y, int cost)
{
graph[x].push_back(make_pair(cost, y));
graph[y].push_back(make_pair(cost, x));
}

// Function For Implementing Best First Search


// Gives output path having lowest cost
void best_first_search(int source, int target, int n)
{
vector<bool> visited(n, false);
// MIN HEAP priority queue
priority_queue<pi, vector<pi>, greater<pi> > pq;
// sorting in pq gets done by first value of pair pq.
push(make_pair(0, source));
visited = true;

while (!pq.empty()) {
int x = pq.top().second;
// Displaying the path having lowest cost
cout << x << " ";
pq.pop();
if (x == target) break;

for (int i = 0; i < graph[x].size(); i++)


{
if (!visited[graph[x][i].second])
{
visited[graph[x][i].second] = true;
pq.push(graph[x][i]);
}
}
}
}

// Driver code to test above methods


int main()
{
// No. of Nodes int v = 14;
graph.resize(v);

// The nodes shown in above example(by alphabets) are


// implemented using integers addedge(x,y,cost); addedge(0, 1, 3);
addedge(0, 2, 6);
addedge(0, 3, 5);
addedge(1, 4, 9);
addedge(1, 5, 8);
addedge(2, 6, 12);
addedge(2, 7, 14);
addedge(3, 8, 7);
addedge(8, 9, 5);
addedge(8, 10, 6);
addedge(9, 11, 1);
addedge(9, 12, 10);
addedge(9, 13, 2);

int source = 0; int target = 9;

// Function call best_first_search(source, target, v);

return 0;
}

Output
Experiment-1.4

Aim: Implementation of Informed Search Strategy (A* Search).

Program
#include <iostream>
#include <cmath>
#include <list>
#include <vector>
#include <algorithm>

class Vector2
{
int x, y;
public:
Vector2(int _x, int _y) : x(_x), y(_y) {}
Vector2() = default;
Vector2 operator +(const Vector2& other)
{
Vector2 temp;
temp.x = this->x + other.x;
temp.y = this->y + other.y;
return temp;
}
int getX() const { return x; }
int getY() const { return y; }

friend class Map;


};

struct Node
{
Vector2 position;
int G, H, F;
Node* parent = nullptr;

Node() = default;
Node(const Node& other) = default;
Node(Vector2 pos):position(pos) {};

void calc(const Vector2& endPos) {


H = static_cast<int>((abs(static_cast<double>(position.getX() - endPos.getX())) +
abs(static_cast<double>(position.getY() - endPos.getY()))));
G = parent ? parent->G + 1 : 1;
F = G + H;
}

bool operator==(const Node& other) const {


return (position.getX() == other.position.getX() && position.getY() ==
other.position.getY());
}
bool operator!=(const Node& other) const {
return !(*this == other);
}
bool operator<(const Node& other) const {
return(F < other.F);
}
};

class Map
{
std::vector<char> data;
int size;
public:
Map() = default;
Map(int _size) : size(_size) {
data.resize(size * size);
for (int i = 0; i < size * size; ++i) data[i] = '.';
}
void display() const{
for (int i = 1; i <= size * size; ++i) {
std::cout << data[i - 1] << " ";
if (!(i % size)) std::cout << "\n";
}
}
bool getIfInDanger(Vector2 position) const {
if (position.y < 0) position.y = 0;
if (position.x < 0) position.x = 0;
if (position.y >= 20) position.y = size - 1;
if (position.x >= 20) position.x = size - 1;
return(data[position.getX() + (position.getY() * size)] == 'X');
}
void setElement(char&& asda, Vector2 position) {
data[position.getX() + (position.getY() * size)] = asda;
}
};

class Solver
{
Vector2 startPos, endPos;
std::vector<Vector2> directions;
Map map;
public:
Solver(Vector2 _startPos, Vector2 _endPos, int size) : startPos(_startPos),
endPos(_endPos){
Map temp(size);
map = temp;

map.setElement('X', Vector2(14, 15));


map.setElement('X',Vector2(15,15));
map.setElement('X', Vector2(16, 15));
map.setElement('X', Vector2(16, 14));
map.setElement('X', Vector2(16, 13));

directions.resize(8);
directions[0] = Vector2(-1, 1);
directions[1] = Vector2(-1, 0);
directions[2] = Vector2(-1, -1);
directions[3] = Vector2(0, 1);
directions[4] = Vector2(0, -1);
directions[5] = Vector2(1, 1);
directions[6] = Vector2(1, 0);
directions[7] = Vector2(1, -1);
}
bool aStar() {
Node startNode(startPos);
Node goalNode(Vector2(endPos.getX(), endPos.getY()));

if (map.getIfInDanger(startNode.position) || map.getIfInDanger(goalNode.position)) {
std::cout << "Either the start of this map is obstructed or so is the end.";
return false;
}

std::list<Node> openList;
std::list<Node> closedList;

startNode.calc(endPos);
openList.push_back(startNode);

while (!openList.empty()) {
auto current = Node(*std::min_element(openList.begin(), openList.end()));

current.calc(endPos);

closedList.push_back(current);
openList.remove(current);
if (current == goalNode) break;

for (auto& direction : directions) {


Node successor(direction + current.position);

if (map.getIfInDanger(successor.position) || successor.position.getX() > 20 - 1 ||


successor.position.getY() > 20 - 1 || successor.position.getX() < 0 ||
successor.position.getY() < 0 ||
std::find(closedList.begin(), closedList.end(), successor) != closedList.end()) {
continue;
}

successor.calc(endPos);
auto inOpen = std::find(openList.begin(), openList.end(), successor);
if (inOpen == openList.end()) {
successor.parent = &closedList.back();
successor.calc(endPos);

openList.push_back(successor);
}
else
if (successor.G < inOpen->G) successor.parent = &closedList.back();
}
}

if (!openList.size()) {
std::cout << "No path has been found\n";
return false;
}

auto inClosed = std::find(closedList.begin(), closedList.end(), goalNode);


if (inClosed != closedList.end()) {
while (*inClosed != startNode) {
map.setElement('Y',inClosed->position);
*inClosed = *inClosed->parent;
}
}

map.display();
return true;
}
};

int main()
{
Solver solve(Vector2(0,0),Vector2(19,19), 20);
solve.aStar();
}
Output

You might also like