From 8dd159ade388680b3b469dd34852772b5d62d859 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Mon, 28 Oct 2024 22:04:12 +0530 Subject: [PATCH 01/10] Update Explaination.md --- AlphaBetaPruning/Explaination.md | 46 ++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/AlphaBetaPruning/Explaination.md b/AlphaBetaPruning/Explaination.md index 2c42c68..8542e61 100644 --- a/AlphaBetaPruning/Explaination.md +++ b/AlphaBetaPruning/Explaination.md @@ -39,13 +39,38 @@ Here's how the code would execute these moves: # Initial total is 0 total = 0 +# Define the minimax function +def minimax(total, is_maximizing, alpha, beta): + # Base case: If total reaches or exceeds 20, return a high value for winning, low for losing + if total >= 20: + return 1 if is_maximizing else -1 + + if is_maximizing: + max_eval = -float('inf') + for i in range(1, 4): # AI can add 1, 2, or 3 + eval = minimax(total + i, False, alpha, beta) + max_eval = max(max_eval, eval) + alpha = max(alpha, eval) + if beta <= alpha: + break + return max_eval + else: + min_eval = float('inf') + for i in range(1, 4): # Human can add 1, 2, or 3 + eval = minimax(total + i, True, alpha, beta) + min_eval = min(min_eval, eval) + beta = min(beta, eval) + if beta <= alpha: + break + return min_eval + # Game loop while True: # Human's turn - human_move = int(input("Enter your move (1, 2, or 3): ")) # Let's say the human enters 1 - total += human_move # total becomes 1 - print(f"After your move, total is {total}") # Prints "After your move, total is 1" - if total >= 20: # The total is not 20 or more, so the game continues + human_move = int(input("Enter your move (1, 2, or 3): ")) + total += human_move + print(f"After your move, total is {total}") + if total >= 20: print("You win!") break @@ -53,18 +78,17 @@ while True: print("AI is making its move...") ai_move = 1 max_eval = -float('inf') - for i in range(1, 4): # For each possible move (1, 2, or 3) - eval = minimax(total + i, False, -float('inf'), float('inf')) # Call minimax to get the evaluation of the move - if eval > max_eval: # If the evaluation is greater than max_eval, update max_eval and ai_move + for i in range(1, 4): + eval = minimax(total + i, False, -float('inf'), float('inf')) + if eval > max_eval: max_eval = eval ai_move = i - total += ai_move # Add the AI's move to the total. Let's say the AI adds 3, so total becomes 4 - print(f"AI adds {ai_move}. Total is {total}") # Prints "AI adds 3. Total is 4" - if total >= 20: # The total is not 20 or more, so the game continues + total += ai_move + print(f"AI adds {ai_move}. Total is {total}") + if total >= 20: print("AI wins!") break -# The game continues in this way until the total reaches or exceeds 20 ``` In this example, the AI wins because the total reaches 20 after the AI's move. The AI uses the Minimax algorithm with Alpha-Beta pruning to decide its moves, always choosing the move that maximizes its score assuming that the human player is also playing optimally. From e3b267f0c570846d4672243a60ca5b5578157c15 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 29 Oct 2024 10:06:27 +0530 Subject: [PATCH 02/10] Update GameOf20.py --- AlphaBetaPruning/GameOf20.py | 96 +++++++++++++++--------------------- 1 file changed, 41 insertions(+), 55 deletions(-) diff --git a/AlphaBetaPruning/GameOf20.py b/AlphaBetaPruning/GameOf20.py index 0b26caf..94d5218 100644 --- a/AlphaBetaPruning/GameOf20.py +++ b/AlphaBetaPruning/GameOf20.py @@ -1,66 +1,52 @@ -# The minimax function is the heart of the AI. It recursively calculates the optimal move for the AI. -def minimax(total, turn, alpha, beta): - # Base case: if total is 20, it's a draw, so return 0 - if total == 20: - return 0 - # Base case: if total is more than 20, the last player to move loses - elif total > 20: - if turn: # If it's the AI's turn, AI loses, so return -1 - return -1 - else: # If it's the human's turn, human loses, so return 1 - return 1 +def minimax(total, is_ai_turn, alpha, beta): + # Base case: If total is 20 or more, the game is over + if total >= 20: + return -1 if is_ai_turn else 1 if total > 20 else 0 # -1 if AI loses, 1 if AI wins, 0 if draw + + # Set initial evaluation depending on whose turn it is + best_eval = -float('inf') if is_ai_turn else float('inf') + + # Explore each possible move (1, 2, or 3) + for i in range(1, 4): + eval = minimax(total + i, not is_ai_turn, alpha, beta) # Recursive call for the next move + + # Maximize if it's AI's turn, else minimize + if is_ai_turn: + best_eval = max(best_eval, eval) + alpha = max(alpha, eval) + else: + best_eval = min(best_eval, eval) + beta = min(beta, eval) + + # Alpha-beta pruning to cut off unnecessary branches + if beta <= alpha: + break + return best_eval - # If it's the AI's turn, we want to maximize the score - if turn: - max_eval = -float('inf') # Initialize max_eval to negative infinity - for i in range(1, 4): # For each possible move (1, 2, or 3) - # Recursively call minimax for the next state of the game - eval = minimax(total + i, False, alpha, beta) - max_eval = max(max_eval, eval) # Update max_eval if necessary - alpha = max(alpha, eval) # Update alpha if necessary - if beta <= alpha: # If beta is less than or equal to alpha, break the loop (alpha-beta pruning) - break - return max_eval # Return the maximum evaluation - # If it's the human's turn, we want to minimize the score - else: - min_eval = float('inf') # Initialize min_eval to positive infinity - for i in range(1, 4): # For each possible move (1, 2, or 3) - # Recursively call minimax for the next state of the game - eval = minimax(total + i, True, alpha, beta) - min_eval = min(min_eval, eval) # Update min_eval if necessary - beta = min(beta, eval) # Update beta if necessary - if beta <= alpha: # If beta is less than or equal to alpha, break the loop (alpha-beta pruning) - break - return min_eval # Return the minimum evaluation - -# The total score of the game is initially 0 -total = 0 +total = 0 # Initialize total score # Game loop -while True: - # Get the human player's move from input and add it to the total +while total < 20: + # Human player's move human_move = int(input("Enter your move (1, 2, or 3): ")) - while human_move not in [1, 2, 3]: # If the move is not valid, ask for input again - print("Invalid move. Please enter 1, 2, or 3.") - human_move = int(input("Enter your move (1, 2, or 3): ")) + while human_move not in [1, 2, 3]: # Validate input + human_move = int(input("Invalid move. Enter 1, 2, or 3: ")) total += human_move - print(f"After your move, total is {total}") - if total >= 20: # If the total is 20 or more after the human's move, the human wins + print(f"Total after your move: {total}") + + # Check if human wins + if total >= 20: print("You win!") break - # If the game is not over, it's the AI's turn + # AI's turn print("AI is making its move...") - ai_move = 1 - max_eval = -float('inf') - for i in range(1, 4): # For each possible move (1, 2, or 3) - # Call minimax to get the evaluation of the move - eval = minimax(total + i, False, -float('inf'), float('inf')) - if eval > max_eval: # If the evaluation is greater than max_eval, update max_eval and ai_move - max_eval = eval - ai_move = i - total += ai_move # Add the AI's move to the total - print(f"AI adds {ai_move}. Total is {total}") - if total >= 20: # If the total is 20 or more after the AI's move, the AI wins + # Select the best move by calling minimax on each possible option + best_move = max((minimax(total + i, False, -float('inf'), float('inf')), i) for i in range(1, 4))[1] + total += best_move + print(f"AI adds {best_move}. Total is {total}") + + # Check if AI wins + if total >= 20: print("AI wins!") break From d13c4bdaef65d55fb79f4b31557a43e23946aae9 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 09:44:40 +0530 Subject: [PATCH 03/10] Update TicTacToe_DFS.py --- TicTacToe/TicTacToe_DFS.py | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/TicTacToe/TicTacToe_DFS.py b/TicTacToe/TicTacToe_DFS.py index da6aea9..991b005 100644 --- a/TicTacToe/TicTacToe_DFS.py +++ b/TicTacToe/TicTacToe_DFS.py @@ -17,27 +17,27 @@ def is_draw(self): return False return True - def is_game_over(self): - # Step 3: Check if the game is over + def is_game_over(self, board=None): + if board is None: + board = self.board # Default to the current board state # Check rows - for row in self.board: + for row in board: if row.count(row[0]) == len(row) and row[0] != ' ': return row[0] # Check columns - for col in zip(*self.board): + for col in zip(*board): if col.count(col[0]) == len(col) and col[0] != ' ': return col[0] - # Check diagonals - if self.board[0][0] == self.board[1][1] == self.board[2][2] != ' ': - return self.board[0][0] - if self.board[0][2] == self.board[1][1] == self.board[2][0] != ' ': - return self.board[0][2] + if board[0][0] == board[1][1] == board[2][2] != ' ': + return board[0][0] + if board[0][2] == board[1][1] == board[2][0] != ' ': + return board[0][2] return False def dfs(self, board, depth, player): # Step 5: DFS logic to choose the best move - winner = self.is_game_over() + winner = self.is_game_over(board) if winner: if winner == 'X': # AI wins return {'score': 1} @@ -46,12 +46,8 @@ def dfs(self, board, depth, player): elif self.is_draw(): return {'score': 0} # Draw - if player == 'X': - best = {'score': -float('inf')} - symbol = 'X' - else: - best = {'score': float('inf')} - symbol = 'O' + best = {'score': -float('inf')} if player == 'X' else {'score': float('inf')} + symbol = 'X' if player == 'X' else 'O' for i in range(3): for j in range(3): @@ -62,10 +58,10 @@ def dfs(self, board, depth, player): score['row'] = i score['col'] = j - if player == 'X': + if player == 'X': # Maximize for AI if score['score'] > best['score']: best = score - else: + else: # Minimize for opponent if score['score'] < best['score']: best = score return best @@ -84,6 +80,7 @@ def play(self): break if self.player == 'X': + print("AI is making a move...") best_move = self.dfs(self.board, 0, 'X') self.board[best_move['row']][best_move['col']] = 'X' else: @@ -102,5 +99,6 @@ def play(self): self.player = 'O' if self.player == 'X' else 'X' + game = TicTacToe() game.play() From 8fb340619dd341108fef842d16261e498470aa27 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:16:53 +0530 Subject: [PATCH 04/10] Update LogisticReg.py --- Logistic_Regression/LogisticReg.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/Logistic_Regression/LogisticReg.py b/Logistic_Regression/LogisticReg.py index 66bc58b..1d744cc 100644 --- a/Logistic_Regression/LogisticReg.py +++ b/Logistic_Regression/LogisticReg.py @@ -1,5 +1,5 @@ -import matplotlib.pyplot as plt import numpy as np +import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler @@ -7,22 +7,28 @@ def sigmoid(z): return 1.0 / (1.0 + np.exp(-z)) -def logistic_regression(X, y, num_iterations=200, learning_rate=0.001): +def cost_function(h, y): + return (-y * np.log(h) - (1 - y) * np.log(1 - h)).mean() + +def gradient(X, h, y): + return np.dot(X.T, (h - y)) / y.shape[0] + +def logistic_regression(X, y, num_iterations=5000, learning_rate=0.1): weights = np.zeros(X.shape[1]) for _ in range(num_iterations): z = np.dot(X, weights) h = sigmoid(z) - gradient_val = np.dot(X.T, (h - y)) / y.shape[0] + gradient_val = gradient(X, h, y) weights -= learning_rate * gradient_val return weights # Load Iris dataset iris = load_iris() -X = iris.data[:, :2] # Use only the first two features (sepal length and width) +X = iris.data[:, :2] # Use only the first two features y = (iris.target != 0) * 1 # Convert to binary classification # Split the dataset -X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=9) +X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # Standardize features sc = StandardScaler() @@ -38,7 +44,6 @@ def logistic_regression(X, y, num_iterations=200, learning_rate=0.001): # Print accuracy print(f'Accuracy: {np.mean(y_pred == y_test):.4f}') - # Plot decision boundary x_min, x_max = X_train_std[:, 0].min() - 1, X_train_std[:, 0].max() + 1 y_min, y_max = X_train_std[:, 1].min() - 1, X_train_std[:, 1].max() + 1 @@ -53,7 +58,4 @@ def logistic_regression(X, y, num_iterations=200, learning_rate=0.001): plt.title('Logistic Regression Decision Boundaries') plt.xlabel('Sepal length') plt.ylabel('Sepal width') - plt.savefig('plot.png') - - From 4eb2382855b75d4c9a13d9c958338b0eafe3320d Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:44:40 +0530 Subject: [PATCH 05/10] Rename naiveBayes.py to naiveBayes_Gaussian_method.py --- .../{naiveBayes.py => naiveBayes_Gaussian_method.py} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename NaiveBayesClassifeir/{naiveBayes.py => naiveBayes_Gaussian_method.py} (99%) diff --git a/NaiveBayesClassifeir/naiveBayes.py b/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py similarity index 99% rename from NaiveBayesClassifeir/naiveBayes.py rename to NaiveBayesClassifeir/naiveBayes_Gaussian_method.py index 496c93d..ce63d69 100644 --- a/NaiveBayesClassifeir/naiveBayes.py +++ b/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py @@ -54,4 +54,4 @@ def _pdf(self, class_idx, x): # Print classification report print("\nClassification Report:") -print(classification_report(y_test, y_pred, target_names=class_names)) \ No newline at end of file +print(classification_report(y_test, y_pred, target_names=class_names)) From 52472c482f7375d15723ce34eb11ac55532f76a8 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:45:44 +0530 Subject: [PATCH 06/10] Update Explaination.md --- NaiveBayesClassifeir/Explaination.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NaiveBayesClassifeir/Explaination.md b/NaiveBayesClassifeir/Explaination.md index 6d542b5..8178f24 100644 --- a/NaiveBayesClassifeir/Explaination.md +++ b/NaiveBayesClassifeir/Explaination.md @@ -1,5 +1,5 @@ -## Naive Bayes Classifier +## Naive Bayes Classifier using Gaussian method The Naive Bayes classifier is a simple and effective classification algorithm that uses probabilities and Bayes' theorem to predict the class of an instance. The 'naive' part comes from the assumption that all features are independent of each other, which is not always the case in real-world data, but it simplifies the calculations and often works well in practice. From 76c14b0895449b7d7d327349e1c7a935f972e243 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 10:48:54 +0530 Subject: [PATCH 07/10] Rename Explaination.md to Explainationudinggaussian.md --- .../{Explaination.md => Explainationudinggaussian.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename NaiveBayesClassifeir/{Explaination.md => Explainationudinggaussian.md} (100%) diff --git a/NaiveBayesClassifeir/Explaination.md b/NaiveBayesClassifeir/Explainationudinggaussian.md similarity index 100% rename from NaiveBayesClassifeir/Explaination.md rename to NaiveBayesClassifeir/Explainationudinggaussian.md From 86511d79e7c0d9106892352a9c6388fd17b79a13 Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 3 Dec 2024 14:20:21 +0530 Subject: [PATCH 08/10] Update ReadMe.md --- ReadMe.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReadMe.md b/ReadMe.md index 8a8f40d..eb9870c 100644 --- a/ReadMe.md +++ b/ReadMe.md @@ -27,7 +27,7 @@ pip install -r requirements.txt ## Usage -1. Can be used for the AI_ML Lab for the course 21AI52 at RVCE +1. Can be used for the AI_ML Lab for the course 21AI52 and IS353IA ## Contributing From 91c3610e79a7ada3fc2f49436687f28319dfa33b Mon Sep 17 00:00:00 2001 From: JDeep1234 <132117873+JDeep1234@users.noreply.github.com> Date: Wed, 4 Dec 2024 09:40:02 +0530 Subject: [PATCH 09/10] Update naiveBayes_Gaussian_method.py --- NaiveBayesClassifeir/naiveBayes_Gaussian_method.py | 1 + 1 file changed, 1 insertion(+) diff --git a/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py b/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py index ce63d69..5e76b27 100644 --- a/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py +++ b/NaiveBayesClassifeir/naiveBayes_Gaussian_method.py @@ -7,6 +7,7 @@ X, y = iris.data, iris.target class_names = iris.target_names + class NaiveBayes: def fit(self, X, y): self._classes = np.unique(y) From 5b8505e59d73318104ba653c28b8d149d601ccee Mon Sep 17 00:00:00 2001 From: JDeep <132117873+JDeep1234@users.noreply.github.com> Date: Tue, 24 Dec 2024 10:26:17 +0530 Subject: [PATCH 10/10] Update HillClimbSearchEval.py --- HillClimbSearch/HillClimbSearchEval.py | 73 ++++++++++---------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/HillClimbSearch/HillClimbSearchEval.py b/HillClimbSearch/HillClimbSearchEval.py index e60d299..f97be36 100644 --- a/HillClimbSearch/HillClimbSearchEval.py +++ b/HillClimbSearch/HillClimbSearchEval.py @@ -1,50 +1,35 @@ -import numpy as np +def hill_climbing(func, start, step=0.01, max_iter=1000): + x = start + for _ in range(max_iter): + fx = func(x) + fx_positive = func(x + step) + fx_negative = func(x - step) -def hill_climbing(func, start, step_size=0.01, max_iterations=1000): - current_position = start - current_value = func(current_position) - - for i in range(max_iterations): - next_position_positive = current_position + step_size - next_value_positive = func(next_position_positive) - - next_position_negative = current_position - step_size - next_value_negative = func(next_position_negative) - - if next_value_positive > current_value and next_value_positive >= next_value_negative: - current_position = next_position_positive - current_value = next_value_positive - elif next_value_negative > current_value and next_value_negative > next_value_positive: - current_position = next_position_negative - current_value = next_value_negative + if fx_positive > fx and fx_positive >= fx_negative: + x += step + elif fx_negative > fx and fx_negative > fx_positive: + x -= step else: break - - return current_position, current_value + return x, func(x) -# Get the function from the user -while True: - func_str = input("\nEnter a function of x: ") - try: - # Test the function with a dummy value - x = 0 - eval(func_str) - break - except Exception as e: - print(f"Invalid function. Please try again. Error: {e}") - -# Convert the string into a function -func = lambda x: eval(func_str) +if __name__ == "__main__": + while True: + try: + func_str = input("Enter a function of x (e.g., -(x-2)**2 + 4): ") + func = eval(f"lambda x: {func_str}") # Convert string to function + func(0) # Test the function with x = 0 + break + except Exception as e: + print(f"Invalid function. Please try again. Error: {e}") -# Get the starting point from the user -while True: - start_str = input("\nEnter the starting value to begin the search: ") - try: - start = float(start_str) - break - except ValueError: - print("Invalid input. Please enter a number.") + while True: + try: + start = float(input("Enter the starting value (e.g., 0): ")) + break + except ValueError: + print("Invalid input. Please enter a valid number.") -maxima, max_value = hill_climbing(func, start) -print(f"The maxima is at x = {maxima}") -print(f"The maximum value obtained is {max_value}") + max_x, max_val = hill_climbing(func, start) + print(f"Maxima found at x = {max_x}") + print(f"Maximum value = {max_val}")