Amity University, Noida Aset (Cse) Batch: 2020-2024: Course Code: CSE401 Course: Artificial Intelligence

Download as pdf or txt
Download as pdf or txt
You are on page 1of 31

Amity University, Noida

ASET (CSE)
Batch : 2020-2024

Course Code: CSE401

Course: Arti cial Intelligence

Lab File

Submitted To: Submitted By:

Dr. Garima Agarwaal


Dr. Shailendra Narayan Singh
Ayush Deep
Mani Aggarwal
A230520543
A2305220140
6cse -4x
6CSE1-Y

B.Tech. CSE 6th Semester

AMITY UNIVERSITY UTTAR PRADESH

GAUTAM BUDH NAGAR

fi

EXPERIMENT-1

Objective: Write a program to implement the Tic-Tac-Toe game problem

Software Used: Python

Theory: Tic-tac-toe who take turns marking the spaces in a 3×3 grid. The player who succeeds in
placing three of their marks in a horizontal, vertical, or diagonal row wins the game. Players soon
discover that the best play from both parties leads to a draw. Hence, tic-tac-toe is most often played
by young children, who often have not yet discovered the optimal strategy. Because of the
simplicity of tic-tac-toe, it is often used as a pedagogical tool for teaching the concepts of good
sportsmanship and the branch of artificial intelligence that deals with the searching of game trees. It
is straightforward to write a computer program to play tic-tac-toe perfectly or to enumerate the 765
essentially different positions (the state space complexity) or the 26,830 possible games up to
rotations and reflections (the game tree complexity) on this space. The game can be generalized to
an m,n,k-game in which two players alternate placing stones of their own colour on an m×n board,
with the goal of getting k of their own colour in a row. Tic-tac-toe is the (3,3,3)-game. Tic-tac-toe is
the game where n equals 3 and d equals 2. If played properly, the game will end in a draw, making
tic-tac-toe a futile game.

Code:

# Tic-Tac-Toe Program using

# random number in Python

# importing all necessary libraries

import numpy as np

import random

from time import sleep

# Creates an empty board

def create_board():

return(np.array([[0, 0, 0],

[0, 0, 0],

[0, 0, 0]]))

# Check for empty places on board

def possibilities(board):

l = []

for i in range(len(board)):

for j in range(len(board)):

if board[i][j] == 0:

l.append((i, j))

return(l)

# Select a random place for the player

def random_place(board, player):

selection = possibilities(board)

current_loc = random.choice(selection)

board[current_loc] = player

return(board)

# Checks whether the player has three

# of their marks in a horizontal row

def row_win(board, player):

for x in range(len(board)):

win = True

for y in range(len(board)):

if board[x, y] != player:

win = False

continue

if win == True:

return(win)

return(win)

# Checks whether the player has three

# of their marks in a vertical row

def col_win(board, player):

for x in range(len(board)):

win = True

for y in range(len(board)):

if board[y][x] != player:

win = False

continue

if win == True:

return(win)

return(win)

# Checks whether the player has three

# of their marks in a diagonal row

def diag_win(board, player):

win = True

for x in range(len(board)):

if board[x, x] != player:

win = False

return(win)

# Evaluates whether there is

# a winner or a tie

def evaluate(board):

winner = 0

for player in [1, 2]:

if (row_win(board, player) or

col_win(board,player) or

diag_win(board,player)):

winner = player

if np.all(board != 0) and winner == 0:

winner = -1

return winner

# Main function to start the game

def play_game():

board, winner, counter = create_board(), 0, 1

print(board)

while winner == 0:

for player in [1, 2]:

board = random_place(board, player)

print("Board after " + str(counter) + " move")

print(board)

counter += 1

winner = evaluate(board)

if winner != 0:

break

if winner == -1:

return("DRAW")

return(winner)

# Driver Code

print("Winner is: " + str("DRAW" if play_game() == -1 else play_game()))

OUTPUT

EXPERIMENT-2
Objective: Write a program to implement a Single Player Game

Software Used: Python

Theory:

N-Puzzle or sliding puzzle is a popular puzzle that consists of N tiles where N can be 8, 15, 24 and
so on. In our example N = 8. The puzzle is divided into sqrt(N+1) rows and sqrt(N+1) columns. E.g.
15-Puzzle will have 4 rows and 4 columns and an 8-Puzzle will have 3 rows and 3 columns. The
puzzle consists of N tiles and one empty space where the tiles can be moved. Start and Goal
configurations (also called state) of the puzzle are provided. The puzzle can be solved by moving
the tiles one by one in the single empty space and thus achieving the Goal configuration.

Code:

class Node:

def __init__(self,data,level,fval):

self.data = data

self.level = level

self.fval = fval

def generate_child(self):

x,y = self.find(self.data,'_')

val_list = [[x,y-1],[x,y+1],[x-1,y],[x+1,y]]

children = []

for i in val_list:

child = self.shuffle(self.data,x,y,i[0],i[1])

if child is not None:

child_node = Node(child,self.level+1,0)

children.append(child_node)

return children

def shuffle(self,puz,x1,y1,x2,y2):

if x2 >= 0 and x2 < len(self.data) and y2 >= 0 and y2 < len(self.data):

temp_puz = []

temp_puz = self.copy(puz)

temp = temp_puz[x2][y2]

temp_puz[x2][y2] = temp_puz[x1][y1]

temp_puz[x1][y1] = temp

return temp_puz

else:

return None

def copy(self,root):

temp = []

for i in root:

t = []

for j in i:

t.append(j)

temp.append(t)

return temp

def find(self,puz,x):

for i in range(0,len(self.data)):

for j in range(0,len(self.data)):

if puz[i][j] == x:

return i,j

class Puzzle:

def __init__(self,size):

self.n = size

self.open = []

self.closed = []

def accept(self):

puz = []

for i in range(0,self.n):

temp = input().split(" ")

puz.append(temp)

return puz

def f(self,start,goal):

return self.h(start.data,goal)+start.level

def h(self,start,goal):

temp = 0

for i in range(0,self.n):

for j in range(0,self.n):

if start[i][j] != goal[i][j] and start[i][j] != '_':

temp += 1

return temp

def process(self):

print("Enter the start state matrix \n")

start = self.accept()

print("Enter the goal state matrix \n")

goal = self.accept()

start = Node(start,0,0)

start.fval = self.f(start,goal)

self.open.append(start)

print("\n\n")

while True:

cur = self.open[0]

print("")

print(" | ")

print(" | ")

print(" \\\'/ \n")

for i in cur.data:

for j in i:

print(j,end=" ")

print("")

if(self.h(cur.data,goal) == 0):

break

for i in cur.generate_child():

i.fval = self.f(i,goal)

self.open.append(i)

self.closed.append(cur)

del self.open[0]

self.open.sort(key = lambda x:x.fval,reverse=False)

puz = Puzzle(3)

puz.process()

OUTPUT:

EXPERIMENT-3
Objective: Write a program to implement BFS for water jug problem using Python.

Software Used: Python

Theory:

Breadth-First Search for a graph is similar to Breadth-First Traversal of a tree. The only catch here
is, unlike trees, graphs may contain cycles, so we may come to the same node again. To avoid
processing a node more than once, we use a Boolean visited array. For simplicity, it is assumed that
all vertices are reachable from the starting vertex. For example, in the following graph, we start
traversal from vertex 2. When we come to vertex 0, we look for all adjacent vertices of it. 2 is also
an adjacent vertex of 0. If we don’t mark visited vertices, then 2 will be processed again and it will
become a non-terminating process. A Breadth-First Traversal of the following graph is 2, 0, 3, 1.

Code:

# 3 water jugs capacity -> (x,y,z) where x>y>z

# initial state (12,0,0)

# final state (6,6,0)

capacity = (12,8,5)

# Maximum capacities of 3 jugs -> x,y,z

x = capacity[0]

y = capacity[1]

z = capacity[2]

# to mark visited states

memory = {}

# store solution path

ans = []

def get_all_states(state):

# Let the 3 jugs be called a,b,c

a = state[0]

b = state[1]

c = state[2]

if(a==6 and b==6):

ans.append(state)

return True

# if current state is already visited earlier

if((a,b,c) in memory):

return False

memory[(a,b,c)] = 1

#empty jug a

if(a>0):

#empty a into b

if(a+b<=y):

if( get_all_states((0,a+b,c)) ):

ans.append(state)

return True

else:

if( get_all_states((a-(y-b), y, c)) ):

ans.append(state)

return True

#empty a into c

if(a+c<=z):

if( get_all_states((0,b,a+c)) ):

ans.append(state)

return True

else:

if( get_all_states((a-(z-c), b, z)) ):

ans.append(state)

return True

#empty jug b

if(b>0):

#empty b into a

if(a+b<=x):

if( get_all_states((a+b, 0, c)) ):

ans.append(state)

return True

else:

if( get_all_states((x, b-(x-a), c)) ):

ans.append(state)

return True

#empty b into c

if(b+c<=z):

if( get_all_states((a, 0, b+c)) ):

ans.append(state)

return True

else:

if( get_all_states((a, b-(z-c), z)) ):

ans.append(state)

return True

#empty jug c

if(c>0):

#empty c into a

if(a+c<=x):

if( get_all_states((a+c, b, 0)) ):

ans.append(state)

return True

else:

if( get_all_states((x, b, c-(x-a))) ):

ans.append(state)

return True

#empty c into b

if(b+c<=y):

if( get_all_states((a, b+c, 0)) ):

ans.append(state)

return True

else:

if( get_all_states((a, y, c-(y-b))) ):

ans.append(state)

return True

return False

initial_state = (12,0,0)

print("Starting work...\n")

get_all_states(initial_state)

ans.reverse()

for i in ans:

print(i)

OUTPUT:

EXPERIMENT-3

Objective: Write a program to implement A* algorithm in python

Software Used: Python

Theory: A* Search algorithm is one of the best and popular techniques used in path-finding and
graph traversals. Consider a square grid having many obstacles and we are given a starting cell and
a target cell. We want to reach the target cell (if possible) from the starting cell as quickly as
possible. Here A* Search Algorithm comes to the rescue. What A* Search Algorithm does is that at
each step it picks the node according to a value ‘f’ which is a parameter equal to the sum of two
other parameters – ‘g’ and ‘h’. At each step it picks the node/cell having the lowest ‘f’, and process
that node/cell. We define ‘g’ and ‘h’ as simply as possible below:

g = the movement cost to move from the starting point to a given square on the grid, following the
path generated to get there.

h = the estimated movement cost to move from that given square on the grid to the final destination.
This is often referred to as the heuristic, which is nothing but a kind of smart guess. We really don’t
know the actual distance until we find the path, because all sorts of things can be in the way (walls,
water, etc.). There can be many ways to calculate this ‘h’.


Code:

class Node():

"""A node class for A* Pathfinding"""

def __init__(self, parent=None, position=None):

self.parent = parent

self.position = position

self.g = 0

self.h = 0

self.f = 0

def __eq__(self, other):

return self.position == other.position

def astar(maze, start, end):

"""Returns a list of tuples as a path from the given start to the given end in the given maze"""

# Create start and end node

start_node = Node(None, start)

start_node.g = start_node.h = start_node.f = 0

end_node = Node(None, end)

end_node.g = end_node.h = end_node.f = 0

# Initialize both open and closed list

open_list = []

closed_list = []

# Add the start node

open_list.append(start_node)

# Loop until you find the end

while len(open_list) > 0:

# Get the current node

current_node = open_list[0]

current_index = 0

for index, item in enumerate(open_list):

if item.f < current_node.f:

current_node = item

current_index = index

# Pop current off open list, add to closed list

open_list.pop(current_index)

closed_list.append(current_node)

# Found the goal

if current_node == end_node:

path = []

current = current_node

while current is not None:

path.append(current.position)

current = current.parent

return path[::-1] # Return reversed path

# Generate children

children = []

for new_position in [(0, -1), (0, 1), (-1, 0), (1, 0), (-1, -1), (-1, 1), (1, -1), (1, 1)]: # Adjacent
squares

# Get node position

node_position = (current_node.position[0] + new_position[0], current_node.position[1] +


new_position[1])

# Make sure within range

if node_position[0] > (len(maze) - 1) or node_position[0] < 0 or node_position[1] >


(len(maze[len(maze)-1]) -1) or node_position[1] < 0:

continue

# Make sure walkable terrain

if maze[node_position[0]][node_position[1]] != 0:

continue

# Create new node

new_node = Node(current_node, node_position)

# Append

children.append(new_node)

# Loop through children

for child in children:

# Child is on the closed list

for closed_child in closed_list:

if child == closed_child:

continue

# Create the f, g, and h values

child.g = current_node.g + 1

child.h = ((child.position[0] - end_node.position[0]) ** 2) + ((child.position[1] -


end_node.position[1]) ** 2)

child.f = child.g + child.h

# Child is already in the open list

for open_node in open_list:

if child == open_node and child.g > open_node.g:

continue

# Add the child to the open list

open_list.append(child)

def main():

maze = [[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 1, 0, 0, 0, 0, 0],

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]

start = (0, 0)

end = (7, 6)

path = astar(maze, start, end)

print("The required path is:\n")

print(path)

if __name__ == '__main__':

main()

OUTPUT

EXPERIMENT-5
Objective: Implement a Brute Force solution to the knapsack problem in python

Software Used: Python

Theory: The knapsack problem or rucksack problem is a problem in combinatorial optimization:


Given a set of items, each with a weight and a value, determine the number of each item to include
in a collection so that the total weight is less than or equal to a given limit and the total value is as
large as possible. It derives its name from the problem faced by someone who is constrained by a
fixed-size knapsack and must fill it with the most valuable items.

Code:

class Bounty:

def __init__(self, value, weight, volume):

self.value, self.weight, self.volume = value, weight, volume

panacea = Bounty(4000, 0.3, 0.025)

ichor = Bounty(2800, 0.2, 0.015)

gold = Bounty(3500, 2.0, 0.002)

sack = Bounty( 0, 25.0, 0.25)

best = Bounty( 0, 0, 0)

current = Bounty( 0, 0, 0)

best_amounts = (0, 0, 0)

max_panacea = int(min(sack.weight // panacea.weight, sack.volume // panacea.volume))

max_ichor = int(min(sack.weight // ichor.weight, sack.volume // ichor.volume))

max_gold = int(min(sack.weight // gold.weight, sack.volume // gold.volume))

for npanacea in range(max_panacea):

for nichor in range(max_ichor):

for ngold in range(max_gold):

current.value = npanacea * panacea.value + nichor * ichor.value + ngold * gold.value

current.weight = npanacea * panacea.weight + nichor * ichor.weight + ngold * gold.weight

current.volume = npanacea * panacea.volume + nichor * ichor.volume + ngold *


gold.volume

if current.value > best.value and current.weight <= sack.weight and \

current.volume <= sack.volume:

best = Bounty(current.value, current.weight, current.volume)

best_amounts = (npanacea, nichor, ngold)

print ("Maximum value achievable is", best.value)

print ("This is achieved by carrying (one solution) %d panacea, %d ichor and %d gold" % \

(best_amounts[0], best_amounts[1], best_amounts[2]))

print ("The weight to carry is %4.1f and the volume used is %5.3f" % (best.weight, best.volume))

EXPERIMENT-6
Objective: Implement Graph colouring problem using python

Software Used: Python

Theory: In graph theory, graph colouring is a special case of graph labelling; it is an assignment of
labels traditionally called "colours" to elements of a graph subject to certain constraints. In its
simplest form, it is a way of colouring the vertices of a graph such that no two adjacent vertices are
of the same colour; this is called a vertex colouring. Similarly, an edge colouring assigns a colour to
each edge so that no two adjacent edges are of the same colour, and a face colouring of a planar
graph assigns a colour to each face or region so that no two faces that share a boundary have the
same colour. Vertex colouring is the starting point of graph colouring. Other colouring problems can
be transformed into a vertex version. For example, an edge colouring of a graph is just a vertex
colouring of its line graph, and a face colouring of a plane graph is just a vertex colouring of its
dual.

Code:

colors = ['Red', 'Blue', 'Green', 'Yellow', 'Black']

states = ['Andhra', 'Karnataka', 'TamilNadu', 'Kerala']

neighbors = {}

neighbors['Andhra'] = ['Karnataka', 'TamilNadu']

neighbors['Karnataka'] = ['Andhra', 'TamilNadu', 'Kerala']

neighbors['TamilNadu'] = ['Andhra', 'Karnataka', 'Kerala']

neighbors['Kerala'] = ['Karnataka', 'TamilNadu']

colors_of_states = {}

def promising(state, color):

for neighbor in neighbors.get(state):

color_of_neighbor = colors_of_states.get(neighbor)

if color_of_neighbor == color:

return False

return True

def get_color_for_state(state):

for color in colors:

if promising(state, color):

return color

def main():

for state in states:

colors_of_states[state] = get_color_for_state(state)

print (colors_of_states)

main()

OUTPUT

EXPERIMENT-7
Objective: Write a program to implement DFS using python

Software Used: - Python

Theory: -Depth First Traversal (or Search) for a graph is like Depth First Traversal of a tree. The
only catch here is, unlike trees, graphs may contain cycles, so we may come to the same node again.
In the following graph, we start traversal from vertex 2. When we come to vertex 0, we look for all
adjacent vertices of it. 2 is also an adjacent vertex of 0. If we don’t mark visited vertices, then 2 will
be processed again and it will become a non-terminating process. A Depth First Traversal of the
following graph is 2, 0, 1, 3.

Code: -
from collections import defaultdict

class Graph:

def __init__(self):

self.graph = defaultdict(list)

def addEdge(self,u,v):

self.graph[u].append(v)

def DFSUtil(self,v,visited):

visited[v]= True

print (v)

for i in self.graph[v]:

if visited[i] == False:

self.DFSUtil(i, visited)

def DFS(self,v):

visited = [False]*(len(self.graph))

self.DFSUtil(v,visited)

g = Graph()

g.addEdge(0, 1)

g.addEdge(0, 2)

g.addEdge(1, 2)

g.addEdge(2, 0)

g.addEdge(2, 3)

g.addEdge(3, 3)

print ("Following is DFS from (starting from vertex 2)")

g.DFS(2)

OUTPUT

EXPERIMENT-8

Objective: Tokenisation of word and sentences with the help of Natural Language ToolKit (NLTK)
Package

Software Used: - Python

Theory: - NLTK is a leading platform for building Python programs to work with human language
data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet,
along with a suite of text processing libraries for classification, tokenization, stemming, tagging,
parsing, and semantic reasoning, wrappers for industrial-strength NLP libraries, and an
active discussion forum.

NLTK has been called “a wonderful tool for teaching, and working in, computational linguistics
using Python,” and “an amazing library to play with natural language.”

Natural Language Processing with Python provides a practical introduction to programming for
language processing. Written by the creators of NLTK, it guides the reader through the
fundamentals of writing Python programs, working with corpora, categorizing text, analysing
linguistic structure, and more.

Code:-

import nltk
from nltk.tokenize import word_tokenize
nltk.download('punkt')
text = "God is Great! I won a lottery."
print(word_tokenize(text))
from nltk.tokenize import sent_tokenize
text = "God is Great! I won a lottery."
print(sent_tokenize(text))

EXPERIMENT-9
Objective: -Design an XOR truth table using Python

Software Used: - Python

Theory: - A Logic gate is an elementary building block of any digital circuits. It takes one or two
inputs and produces output based on those inputs. Outputs may be high (1) or low (0). Logic gates
are implemented using diodes or transistors. The XOR gate gives an output of 1 if either both inputs
are different, it gives 0 if they are same.

Code: -

def XOR (a, b):

if a != b:

return 1

else:

return 0

# Driver code

if __name__=='__main__':

print(XOR(5, 5))

print("------------------------------------------")

print(" | XOR Truth Table | Result |")

print(" A = False, B = False | A AND B =",XOR(False,False)," | ")

print(" A = False, B = True | A AND B =",XOR(False,True)," | ")

print(" A = True, B = False | A AND B =",XOR(True,False)," | ")

print(" A = True, B = True | A AND B =",XOR(True,True)," | ")

OUTPUT:


EXPERIMENT-10

Objective: - Study of SCIKIT fuzzy

Software Used: - Python

Theory: -

The above figure represents a basic Fuzzy Clustering

Scikit-Fuzzy is a collection of fuzzy logic algorithms intended for use in the SciPy Stack, written in
the Python computing language. This SciKit is developed by the SciPy community. Scikit-Fuzzy is
a Python package based on SciPy that allows implementing all the most important fuzzy logic
algorithms (including fuzzy C-means). In this example, we continue using the MNIST dataset, but
with a major focus on fuzzy partitioning.

To perform the clustering, Scikit-Fuzzy implements the cmeans method (in the skfuzzy. cluster
package) which requires a few mandatory parameters: data, which must be an array D ∈ ℜN × M
(N is the number of features; therefore, the array used with Scikit-Learn must be transposed); c, the
number of clusters; the coefficient m, error, which is the maximum tolerance; and maxiter, which is
the maximum number of iterations.

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy