AD3311 AI LAB MANUAL (1)
AD3311 AI LAB MANUAL (1)
LABORATORY
Branch :……………………………….
AD3311 ARTIFICIAL INTELLIGENCE LABORATORY
OBJECTIVES:
LIST OF EXPERIMENTS:
1. Implement basic search strategies – 8-Puzzle, 8 - Queens’s problem, Cryptarithmetic.
2. Implement A* and memory bounded A* algorithms
3. Implement Minimax algorithm for game playing (Alpha-Beta pruning)
4. Solve constraint satisfaction problems
5. Implement propositional model checking algorithms
6. Implement forward chaining, backward chaining, and resolution strategies
7. Build naïve Bayes models
8. Implement Bayesian networks and perform inferences
9. Mini-Project
TOTAL: 45 PERIODS
OUTCOMES:
At the end of this course, the students will be able to:
SOFTWARE:
PYTHON or Java Software
Exp No 1 Implement basic search strategies – 8-Puzzle problem and 8-Queen
DATE: problem.
import copy
count = 0
for i in range(n):
for j in range(n):
if ((mats[i][j]) and
(mats[i][j] != final[i][j])):
count += 1
return count
for i in range(n):
for j in range(n):
print("%d " % (mats[i][j]), end = " ")
print()
# Printing the path from the root node to the final node
def printPath(root):
if root == None:
return
printPath(root.parent)
printMatsrix(root.mats)
print()
if isSafe(new_tile_posi[0], new_tile_posi[1]):
# Main Code
# Initial configuration
# Value 0 is taken here as an empty space
initial = [ [ 1, 2, 3 ],
[ 5, 6, 0 ],
[ 7, 8, 4 ] ]
Output:
1 2 3
5 6 0
7 8 4
1 2 3
5 0 6
7 8 4
1 2 3
5 8 6
7 0 4
1 2 3
5 8 6
0 7 4
global N
N=4
def printSolution(board):
for i in range(N):
for j in range(N):
print (board[i][j],end=' ')
print()
return True
if isSafe(board, i, col):
# Place this queen in board[i][col]
board[i][col] = 1
if solveNQUtil(board, 0) == False:
print ("Solution does not exist")
return False
printSolution(board)
return True
output:
C) Crypt arithmetic solver
'''Crypt arithmetic puzzles are arithmetic problems made of letters instead of Numbers. The goal is to
replace each letter with a single, unique digit in order to make the arithmetic work out correctly.
Example: S E N D + M O R E = M O N E Y S E N D + M O R E
----------
MONEY
----------
Vales which satisfies this constraints
S = 9, E = 5, N = 6, D = 7, M = 1, O = 0, R = 8, Y = 2
'''
def find_value(word, assigned):
num = 0
for char in word:
num = num * 10
num += assigned[char]
return num
def is_valid_assignment(word1, word2, result, assigned):
# First letter of any word cannot be zero.
if assigned[word1[0]] == 0 or assigned[word2[0]] == 0 or assigned[
result[0]] == 0:
return False
return True
def _solve(word1, word2, result, letters, assigned, solutions):
if not letters:
if is_valid_assignment(word1, word2, result, assigned):
num1 = find_value(word1, assigned)
num2 = find_value(word2, assigned)
num_result = find_value(result, assigned)
if num1 + num2 == num_result:
solutions.append((f'{num1} + {num2} = {num_result}',
assigned.copy()))
return
for num in range(10):
if num not in assigned.values():
cur_letter = letters.pop()
assigned[cur_letter] = num
_solve(word1, word2, result, letters, assigned, solutions)
assigned.pop(cur_letter)
letters.append(cur_letter)
def solve(word1, word2, result):
letters = sorted(set(word1) | set(word2) | set(result))
if len(result) > max(len(word1), len(word2)) + 1 or len(letters) > 10:
print('0 Solutions!')
return
solutions = []
_solve(word1, word2, result, letters, {}, solutions)
if solutions:
print('\nSolutions:')
for soln in solutions:
print(f'{soln[0]}\t{soln[1]}')
if __name__ == '__main__':
print('CRYPTARITHMETIC PUZZLE SOLVER')
print('WORD1 + WORD2 = RESULT')
word1 = input('Enter WORD1: ').upper()
word2 = input('Enter WORD2: ').upper()
result = input('Enter RESULT: ').upper()
if not word1.isalpha() or not word2.isalpha() or not result.isalpha():
raise TypeError('Inputs should ony consists of alphabets.')
solve(word1, word2, result)
CRYPTARITHMETIC PUZZLE SOLVER
WORD1 + WORD2 = RESULT
Enter WORD1: SEND
Enter WORD2: MORE
Enter RESULT: MONEY
Solutions:
9567 + 1085 = 10652 {'Y': 2, 'S': 9, 'R': 8, 'O': 0, 'N': 6, 'M': 1, 'E':
5, 'D': 7}
Exp No 2 IMPLEMENT A* SEARCH ALGORITHM
DATE:
AIM:
To write a Java python program to Implement A* search algorithm.
ALGORITHM:
1. Initialize the open list
2. Initialize the closed list put the starting node on the open list (you can leave its f at zero)
3. while the open list is not empty
a) find the node with the least f on the open list, call it "q"
b) pop q off the open list
c) generate q's 8 successors and set their parents to q
d) for each successor
i) if successor is the goal, stop search
ii) else, compute both g and h for successor
successor.g = q.g + distance between successor and q
successor.h = distance from goal to
successor (This can be done using many ways, we will discuss three heuristics-Manhattan,
Diagonal and Euclidean Heuristics)
successor.f = successor.g + successor.h
iii) if a node with the same position as successor is in the OPEN list which has a lower f than
successor, skip this successor
iv) if a node with the same position as successor is in the CLOSED list which has
a lower f than successor, skip this successor otherwise, add the node to the open list end (for
loop)
e) push q on the closed list end (while loop)
PROGRAM:
public class Node implements Comparable<Node> {
// Id for readability of result purposes
private static int idCounter = 0;
public int id;
// Parent in the path
public Node parent = null;
public List<Edge> neighbors;
// Evaluation functions
public double f = Double.MAX_VALUE;
public double g = Double.MAX_VALUE;
// Hardcoded heuristic
public double h;
Node(double h){
this.h = h;
this.id = idCounter++;
this.neighbors = new ArrayList<>();
}
@Override
public int compareTo(Node n) {
return Double.compare(this.f, n.f);
}
public static class Edge {
Edge(int weight, Node node){
this.weight = weight;
this.node = node;
}
public int weight;
public Node node;
}
public void addBranch(int weight, Node node){
Edge newEdge = new Edge(weight, node);
neighbors.add(newEdge);
}
public double calculateHeuristic(Node target){
return this.h;
}
}
And here's the algorithm itself:
public static Node aStar(Node start, Node target){
for(int id : ids){
System.out.print(id + " ");
}
System.out.println("");
}
And now, let's construct a graph and call this method:
public static void main(String[] args) {
Node head = new Node(3);
head.g = 0;
Node n1 = new Node(2);
Node n2 = new Node(2);
Node n3 = new Node(2);
head.addBranch(1, n1);
head.addBranch(5, n2);
head.addBranch(2, n3);
n3.addBranch(1, n2);
Node n4 = new Node(1);
Node n5 = new Node(1);
Node target = new Node(0);
n1.addBranch(7, n4);
n2.addBranch(4, n5);
n3.addBranch(6, n4);
n4.addBranch(3, target);
n5.addBranch(1, n4);
n5.addBranch(3, target);
Node res = aStar(head, target);
printPath(res);
}
When we run this, we'll get the result printed out:
0 3 2 5 6.
CO-PO MAPPING:
CO3- PO2,PO3, PO5,PO9,PO10
RESULT:
Thus, the program has been written for implementing A* search algorithm in Java.
Exp No 3
DATE: IMPLEMENT ALPHA-BETA TREESEARCH
AIM:
To write a Java program to implement alpha-beta tree search.
ALGORITHM:
The Max player will only update the value of alpha.
o The Min player will only update the value of beta.
o While backtracking the tree, the node values will be passed to upper nodes instead of
values of alpha and beta.
o We will only pass the alpha, beta values to the child nodes.
o The main condition which required for alpha-beta pruning is:
α>=β
If the condition is true the successor of that node is pruned.
PROGRAM:
reply = chooseMove(!side,board,alpha,beta,depth+1,maxDepth);
board[move.intValue()] = 0;
if(side&&reply.getScore()>myBest.getScore()){
myBest.setMove(move.intValue());
myBest.setScore(reply.getScore());
alpha = reply.getScore();
}
else if(!side&&reply.getScore()<myBest.getScore()){
myBest.setMove(move.intValue());
myBest.setScore(reply.getScore());
beta = reply.getScore();
}
if(alpha>=beta){
return myBest;
}
}
return myBest;
}
CO-PO MAPPING:
CO3- PO2,PO3, PO5,PO9,PO10, PO12
RESULT:
Thus, the program has been written to implement alpha-beta treesearch in Java.
Exp No 4
SOLVE CONSTRAINT SATISFACTION PROBLEM
DATE:
AIM:
To write a Java program to implement backtracking algorithms for CSP.
ALGORITHM:
BT(Level)
If all variables assigned
PRINT Value of each Variable
RETURN or EXIT (RETURN for more solutions)
(EXIT for only one solution)
PickUnassignedVariable()
Variable[Level] := V
Assigned[V] := TRUE
for d := each member of Domain(V)
Value[V] := d
OK := TRUE
for each constraint C such that
V is a variable of C
and all other variables of C are assigned.
if C is not satisfied by the current set of assignments
OK := FALSE
if(OK)
BT(Level+1)
return
PROGRAM:
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
/**
* <h3>The Algorithm class</h3>
* <p>
* Given a CSP, use an algorithm in this class to solve it. It will output a result set.
* </p>
* <p>
* The algorithm is the backtracking algorithm with MRV heuristic. There are 2
backtracking methods. All the other methods are static methods
* for dealing with specific backtracking tasks.
* </p>
* @author adnan
*
*/
public class CSPAlgorithm {
private CSP csp;
/**
* Create the Algorithm object to be used to solve the CSP that is given to it
* @param csp
*/
public CSPAlgorithm(CSP csp) {
this.csp = csp;
}
private String getVariable(ArrayList<String> configOrder) {
int minVal, tmpVal;
String minVar = null;
//reverse the configOrder, thereby favouring the variables at the front of the list
Collections.reverse(configOrder);
minVal = Integer.MAX_VALUE; // some very large number
//Go through all the remaining variables in the order specified (that don't
have a value in config and figure out which one has the MRV)
no heuristic
for (String s : configOrder) {
if(csp.config.get(s).equalsIgnoreCase("")) {
tmpVal = 0;
//need to check ALL values for each variable
for(String adj: csp.constraintsTable.get(s)) {
for(String val: csp.constraintsTable.get(s).get(adj)) {
if(consistent(val, s)) {
tmpVal++;
}
}
}
}
}
//Return the variable that has the least number of legal values
return minVar;
}
private SET<String> orderDomainValue(String variable) {
//return the SET of domain values for the variable
return csp.domainTable.get(variable);
}
private boolean complete() {
for(String s: csp.config) {
//if we find a variable in the config with no value, then csp means
if(csp.config.get(s).equalsIgnoreCase(""))
return false;
}
//ALL variables in config have a value, so the configuration is complete
return true;
}
private boolean consistent(String value, String variable) {
//we need to get the constraint list for the variable
for(String constraints: csp.constraintsTable.get(variable)) {
//if the adjacency list member's value is equal to the variable's
System.out.print("csp.config: ");
for(String conf: csp.config) {
System.out.print(conf + " = " + csp.config.get(conf) + ", ");
}
System.out.println();
System.out.format("consistent: %s, %s, %s\n", constraints,
csp.config.get(constraints), csp.constraintsTable.get(variable).get(constraints).get(value));
if(csp.constraintsTable.get(variable).get(constraints).get(value) !=
null &&
!csp.config.get(constraints).equals("") &&
!(csp.constraintsTable.get(variable).get(constraints).get(value).contains(csp.config.get(con
straints)))) {
return false;
}
}
//consistency check passed according to the variable's adjacancy list
return true;
}
/**
* Backtracking with default ordering (alphabetical)
* @return
*/
ST<String, String> backtracking() {
ArrayList<String> configOrder = new ArrayList<String>();
for(String node: csp.G.vertices()) {
configOrder.add(node);
}
return this.backtracking(configOrder);
}
/**
* Backtracking with user-defined ordering of variables
*
* @param configOrder - the user defined ordering of variables
* @return
*/
ST<String, String> backtracking(ArrayList<String> configOrder) {
//recursion base case - check configuration completeness
if(this.complete())
return csp.config;
ST<String, String> result = null;
//get a variable
String v = this.getVariable(configOrder);
//get a SET of all the variable's values
SET<String> vu = this.orderDomainValue(v);
//loop through all the variable's values
for(String u: vu) {
//if(consistent(u, v, config, g)) {
if(this.consistent(u, v)) {
csp.config.put(v, u);
result = this.backtracking(configOrder);
if(result != null)
return result;
csp.config.put(v, "");
}
}
return null;
}
}
CO-PO MAPPING:
CO3-PO1,PO2,PO3, PO4, O8,,PO11,PO12
RESULT:
Thus, the program has been written to implement backtracking algorithms
forCSP in Java.
Exp No 5
IMPLEMENT PROPOSITIONAL MODEL CHECKING (DPLL
DATE: ALGORITHM)
Program
import re
class Literal: #CLass Literal, it has attributes name and sign to denote
whether the literal is positve or negative in use
def __init__(self,name, sign = True ):
self.name = str(name)
self.sign = sign
def __neg__(self): #returns a new literal with the same name but the
opposite sign of its parent literal
return Literal(self.name, False)
def __str__(self):
return str(self.name)
def __repr__(self): #returns the string of the literal name,( or the
string with a negative sign) each time the instance of the ltieral is called
if self.sign:
return '%r' %str(self.__str__())
else:
return '%r' %str("-" + self.__str__())
def CNFconvert(KB): #This function converts the Kb from a list of sets to a
list of list for easire computing
storage = []
for i in KB:
i = list(i)
for j in i:
j = str(j)
storage.append(i)
return storage
def VariableSet(KB): #This function finds all the used literals in the KB,
and in order to assist with running the DPLL
KB = eval((CNFconvert(KB).__str__()))
storage = []
for obj in KB:
for item in obj:
if item[0] == '-' and item[1:] not in storage:
storage.append(str(item[1:]))
elif item not in storage and item[0] != '-':
storage.append(str(item))
return storage
def Negativeofx(x): #This function is for holding the negative form of the
literal, for use in the DPLL algorithm
check = re.match("-",str(x))
if(check):
return str(x[1:])
else:
return "-"+str(x)
def pickX(literals,varList): #This function picks a literal from the variable
set and works with it as a node in the tree
for x in varList:
if x not in literals:
break
return x
def splitFalseLiterals(cnf,x):
holder = []
for item in cnf:
if x in item:
item.remove(x)
holder.append(item)
return holder
def splitTrueLiteral(cnf,x):
holder = []
for item in cnf:
if x in item:
continue
else:
holder.append(item)
return holder
def unitResolution(clauses):
literalholder = {} #dictionary for holding the literalholder and their
bool
i=0
# This part of the code goes through each and every clause until the all
literals in the KB are resolved
while i < len(clauses): #for each clause
newClauses = []
clause = clauses[i]
# picks a clause to work on
if(len(clause) == 1):
literal = str(clause[0])
pattern = re.match("-",literal)
# Populates the dictionary
if(pattern):
nx = literal[1:]
literalholder[nx] = False
else:
nx = "-"+literal
literalholder[literal] = True
# Checks for all other appearances o the literal or its opposite
int he KB
for item in clauses:
if item != clauses[i]:
if(nx in item):
item.remove(nx)
newClauses.append(item)
i=0
clauses = newClauses
# no unit clause
else:
i += 1
return literalholder, clauses
def dpll(clauses,varList):#recursively performs the dpll algorithm
literals, cnf = unitResolution(clauses)
if(cnf == []):
return literals
elif([] in cnf):
return "notsatisfiable"
else:
# pick a literal which isn't set yet but has an impact on the Kb, and
then work on it recursively
while True:
x = pickX(literals,varList)
x = str(x)
nx = Negativeofx(x)
ncnf = splitTrueLiteral(cnf,x)
ncnf = splitFalseLiterals(ncnf,nx)
if ncnf == cnf:
varList.remove(x)
else:
break
# does the same dpll recursively, but follows the true path for that
variable
case1 = dpll(ncnf,varList)
if(case1 != "notsatisfiable"):
copy = case1.copy()
copy.update(literals)
copy.update({x: True})
return copy
# does the dpll recursively, but follows the false path for that
variable
case1 = dpll(ncnf,varList)
if not case1:
copy = case1.copy()
copy.update(literals)
copy.update({x: False})
return copy
else:
return "notsatisfiable"
def DPLL(KB): #Finally restructures the output to fit the required output by
the assignment description
KB=eval((CNFconvert(KB).__str__()))
varList = VariableSet(KB)
result = dpll(KB, varList)
if result == 'notsatisfiable':
False
else:
for i in varList:
if i in result and result[i] == True:
result[i] = 'true'
elif i in result and result[i] == False:
result[i] = 'false'
else:
result[i] = 'free'
return [True, result]
A = Literal('A')
B = Literal('B')
C = Literal('C')
D = Literal('D')
KB = [{A,B},{A,-C},{-A,B,D}]
print (DPLL(KB))
[True, {'B': 'true', 'A': True, 'C': 'free', 'D': 'free'}]
Forward chaining:
global facts
global is_changed
is_changed = True
facts = [["vertebrate","duck"],["flying","duck"],["mammal","cat"]]
def assert_fact(fact):
global facts
global is_changed
if not fact in facts:
facts += [fact]
is_changed = True
while is_changed:
is_changed = False
for A1 in facts:
if A1[0] == "mammal":
assert_fact(["vertebrate",A1[1]])
if A1[0] == "vertebrate":
assert_fact(["animal",A1[1]])
if A1[0] == "vertebrate" and ["flying",A1[1]] in facts:
assert_fact(["bird",A1[1]])
print(facts)
Output:
[['vertebrate', 'duck'], ['flying', 'duck'], ['mammal', 'cat'], ['animal', 'duck'], ['bird', 'duck'],
['vertebrate', 'cat'], ['animal', 'cat']]
Exp No 7
Build native Bayes models
DATE:
In this step, we will pre-process/prepare the data so that we can use it efficiently in our code.
It is similar as we did in data-pre-processing. The code for this is given below:
Importing the libraries
import numpy as nm
import matplotlib.pyplot as mtp
import pandas as pd
# Splitting the dataset into the Training set and Test set
from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.25, random_state = 0)
# Feature Scaling
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
x_train = sc.fit_transform(x_train)
x_test = sc.transform(x_test)
In the above code, we have loaded the dataset into our program using "dataset =
pd.read_csv('user_data.csv'). The loaded dataset is divided into training and test set, and
then we have scaled the feature variable.
Output:
After the pre-processing step, now we will fit the Naive Bayes model to the Training set.
Below is the code for it:
In the above code, we have used the GaussianNB classifier to fit it to the training dataset.
We can also use other classifiers as per our requirement.
Output:
Out[6]:GaussianNB(priors=None,var_smoothing=1e-09)
Now we will predict the test set result. For this, we will create a new predictor
variable y_pred, and will use the predict function to make the predictions.
Output:
The above output shows the result for prediction vector y_pred and real vector y_test. We
can see that some predications are different from the real values, which are the incorrect
predictions.
Now we will check the accuracy of the Naive Bayes classifier using the Confusion matrix.
Below is the code for it:
Output:
5) Visualizing the training set result:
Next we will visualize the training set result using Naïve Bayes Classifier. Below is the code
for it:
Output:
In the above output we can see that the Naïve Bayes classifier has segregated the data points
with the fine boundary. It is Gaussian curve as we have used GaussianNB classifier in our
code.
Output:
The above output is final output for test set data. As we can see the classifier has created a
Gaussian curve to divide the "purchased" and "not purchased" variables. There are some
wrong predictions which we have calculated in Confusion matrix. But still it is pretty good
classifier.
Exp No 8
DATE: Implement Bayesian networks and perform inference
infer = VariableElimination(model)
posterior_p = infer.query(['Host'], evidence={'Guest': 2, 'Price': 2})
print(posterior_p)
nx.draw(model, with_labels=True)
plt.savefig('model.png')
plt.close()
Output:
AIM:
To write a Java program to implement backtracking algorithms for CSP.
ALGORITHM:
BT(Level)
If all variables assigned
PRINT Value of each Variable
RETURN or EXIT (RETURN for more solutions)
(EXIT for only one solution)
PickUnassignedVariable()
Variable[Level] := V
Assigned[V] := TRUE
for d := each member of Domain(V)
Value[V] := d
OK := TRUE
for each constraint C such that
V is a variable of C
and all other variables of C are assigned.
if C is not satisfied by the current set of assignments
OK := FALSE
if(OK)
BT(Level+1)
return
PROGRAM:
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.Collections;
/**
* <h3>The Algorithm class</h3>
* <p>
* Given a CSP, use an algorithm in this class to solve it. It will output a result set.
* </p>
* <p>
* The algorithm is the backtracking algorithm with MRV heuristic. There are 2
backtracking methods. All the other methods are static methods
* for dealing with specific backtracking tasks.
* </p>
* @author adnan
*
*/
public class CSPAlgorithm {
private CSP csp;
/**
* Create the Algorithm object to be used to solve the CSP that is given to it
* @param csp
*/
public CSPAlgorithm(CSP csp) {
this.csp = csp;
}
private String getVariable(ArrayList<String> configOrder) {
int minVal, tmpVal;
String minVar = null;
//reverse the configOrder, thereby favouring the variables at the front of the list
Collections.reverse(configOrder);
minVal = Integer.MAX_VALUE; // some very large number
//Go through all the remaining variables in the order specified (that don't
have a value in config and figure out which one has the MRV)
no heuristic
for (String s : configOrder) {
if(csp.config.get(s).equalsIgnoreCase("")) {
tmpVal = 0;
//need to check ALL values for each variable
for(String adj: csp.constraintsTable.get(s)) {
for(String val: csp.constraintsTable.get(s).get(adj)) {
if(consistent(val, s)) {
tmpVal++;
}
}
}
}
}
//Return the variable that has the least number of legal values
return minVar;
}
private SET<String> orderDomainValue(String variable) {
//return the SET of domain values for the variable
return csp.domainTable.get(variable);
}
private boolean complete() {
for(String s: csp.config) {
//if we find a variable in the config with no value, then csp means
if(csp.config.get(s).equalsIgnoreCase(""))
return false;
}
//ALL variables in config have a value, so the configuration is complete
return true;
}
private boolean consistent(String value, String variable) {
//we need to get the constraint list for the variable
for(String constraints: csp.constraintsTable.get(variable)) {
//if the adjacency list member's value is equal to the variable's
System.out.print("csp.config: ");
for(String conf: csp.config) {
System.out.print(conf + " = " + csp.config.get(conf) + ", ");
}
System.out.println();
System.out.format("consistent: %s, %s, %s\n", constraints,
csp.config.get(constraints), csp.constraintsTable.get(variable).get(constraints).get(value));
if(csp.constraintsTable.get(variable).get(constraints).get(value) !=
null &&
!csp.config.get(constraints).equals("") &&
!(csp.constraintsTable.get(variable).get(constraints).get(value).contains(csp.config.get(con
straints)))) {
return false;
}
}
//consistency check passed according to the variable's adjacancy list
return true;
}
/**
* Backtracking with default ordering (alphabetical)
* @return
*/
ST<String, String> backtracking() {
ArrayList<String> configOrder = new ArrayList<String>();
for(String node: csp.G.vertices()) {
configOrder.add(node);
}
return this.backtracking(configOrder);
}
/**
* Backtracking with user-defined ordering of variables
*
* @param configOrder - the user defined ordering of variables
* @return
*/
ST<String, String> backtracking(ArrayList<String> configOrder) {
//recursion base case - check configuration completeness
if(this.complete())
return csp.config;
ST<String, String> result = null;
//get a variable
String v = this.getVariable(configOrder);
//get a SET of all the variable's values
SET<String> vu = this.orderDomainValue(v);
//loop through all the variable's values
for(String u: vu) {
//if(consistent(u, v, config, g)) {
if(this.consistent(u, v)) {
csp.config.put(v, u);
result = this.backtracking(configOrder);
if(result != null)
return result;
csp.config.put(v, "");
}
}
return null;
}
CO-PO MAPPING:
CO3-PO1,PO2,PO3, PO4, O8,,PO11,PO12
RESULT:
Thus, the program has been written to implement backtracking algorithms
forCSP in Java.