diff --git a/homework8/Homework8_Q5.py b/homework8/Homework8_Q5.py new file mode 100644 index 0000000..258ad0d --- /dev/null +++ b/homework8/Homework8_Q5.py @@ -0,0 +1,81 @@ +import numpy as np +import matplotlib.pyplot as plt + +# --- FUNCTION DEFINITION CORRECTED HERE --- +def g(t): + """ + Calculates g(t) = t^4 - 3t^3 + 2t^2 in a vectorized way. + It handles both single float inputs and NumPy array inputs. + If an element's absolute value is too large, it returns infinity + to prevent overflow and handle plotting of diverging paths. + """ + # Use np.where for a vectorized if-else statement. + # This correctly handles both scalar and array inputs. + return np.where(np.abs(t) > 1e10, # Condition + np.inf, # Value if condition is True + t**4 - 3*t**3 + 2*t**2) # Value if condition is False + +# Define the gradient (derivative) of g(t) +def grad_g(t): + # This function is only called with scalars in our loop, + # but it's good practice for it to be vectorization-safe as well. + # Standard arithmetic operations are already vectorized in NumPy. + return 4*t**3 - 9*t**2 + 4*t + +# Implement the gradient descent algorithm +def gradient_descent(x0, alpha, iterations=100): + history = [x0] + x = x0 + for _ in range(iterations): + grad = grad_g(x) + + if np.isinf(x) or np.isnan(x) or np.abs(x) > 1e9: + print(f"Divergence detected for alpha = {alpha}. Stopping early.") + break + + x = x - alpha * grad + history.append(x) + if not np.isinf(x) and not np.isnan(x) and np.abs(x) <= 1e9: + print(f"Alpha: {alpha:<.2f}, Current x: {x:<.2f}, g(x): {g(x):<.2f}") + return history + +# --- Main part of the experiment --- + +# Set an initial point +initial_xs = [-1.0, 0.5, 0.65, 2.5] + +# Define a list of different alpha values to test +alphas_to_test = [0.05, 0.15, 0.25, 0.4, 0.5, 0.6] + +# Run the experiment for each alpha value and plot the results +for initial_x in initial_xs: + print(f"Running gradient descent from initial x = {initial_x}") + # Create a plot + plt.figure(figsize=(14, 8)) + + # Plot the function g(t) for context + t_plot = np.linspace(-1.5, 3.5, 400) + plt.plot(t_plot, g(t_plot), 'k-', label='g(t) = t^4 - 3t^3 + 2t^2', linewidth=2) + for alpha in alphas_to_test: + history = gradient_descent(initial_x, alpha) + history_np = np.array(history) + plt.plot(history_np, g(history_np), 'o-', label=f'alpha = {alpha}', markersize=4, alpha=0.8) + + # Add stationary points + minima1 = 0.0 + minima2 = (9 + np.sqrt(17)) / 8 + maxima = (9 - np.sqrt(17)) / 8 + plt.plot(minima1, g(minima1), 'g*', markersize=15, label=f'Local Minimum at t={minima1:.2f}') + plt.plot(minima2, g(minima2), 'g*', markersize=15, label=f'Local Minimum at t≈{minima2:.2f}') + plt.plot(maxima, g(maxima), 'rX', markersize=10, label=f'Local Maximum at t≈{maxima:.2f}') + + # Final plot formatting + plt.title('Gradient Descent Convergence for Different Step Sizes (alpha, initial x={})'.format(initial_x)) + plt.xlabel('t') + plt.ylabel('g(t)') + plt.legend() + plt.grid(True) + plt.ylim(-1, 5) + plt.xlim(-1.5, 3.5) + plt.savefig(f'Homework8_Q5_Gradient_Descent_Convergence_x={initial_x}.png') + diff --git a/homework8/Homework8_Q5.txt b/homework8/Homework8_Q5.txt new file mode 100644 index 0000000..5df70ac --- /dev/null +++ b/homework8/Homework8_Q5.txt @@ -0,0 +1,28 @@ +Running gradient descent from initial x = -1.0 +Alpha: 0.05, Current x: -0.00, g(x): 0.00 +Alpha: 0.15, Current x: 1.64, g(x): -0.62 +Divergence detected for alpha = 0.25. Stopping early. +Divergence detected for alpha = 0.4. Stopping early. +Divergence detected for alpha = 0.5. Stopping early. +Divergence detected for alpha = 0.6. Stopping early. +Running gradient descent from initial x = 0.5 +Alpha: 0.05, Current x: 0.00, g(x): 0.00 +Alpha: 0.15, Current x: 0.00, g(x): 0.00 +Alpha: 0.25, Current x: 0.00, g(x): 0.00 +Alpha: 0.40, Current x: -0.00, g(x): 0.00 +Alpha: 0.50, Current x: 0.02, g(x): 0.00 +Alpha: 0.60, Current x: 0.18, g(x): 0.05 +Running gradient descent from initial x = 0.65 +Alpha: 0.05, Current x: 1.64, g(x): -0.62 +Alpha: 0.15, Current x: 1.64, g(x): -0.62 +Alpha: 0.25, Current x: 1.64, g(x): -0.62 +Alpha: 0.40, Current x: 1.51, g(x): -0.57 +Alpha: 0.50, Current x: 0.01, g(x): 0.00 +Divergence detected for alpha = 0.6. Stopping early. +Running gradient descent from initial x = 2.5 +Alpha: 0.05, Current x: 1.64, g(x): -0.62 +Alpha: 0.15, Current x: 0.00, g(x): 0.00 +Divergence detected for alpha = 0.25. Stopping early. +Divergence detected for alpha = 0.4. Stopping early. +Divergence detected for alpha = 0.5. Stopping early. +Divergence detected for alpha = 0.6. Stopping early. diff --git a/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=-1.0.png b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=-1.0.png new file mode 100644 index 0000000..de457e9 Binary files /dev/null and b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=-1.0.png differ diff --git a/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.5.png b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.5.png new file mode 100644 index 0000000..8ff7452 Binary files /dev/null and b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.5.png differ diff --git a/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.65.png b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.65.png new file mode 100644 index 0000000..cf8786f Binary files /dev/null and b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=0.65.png differ diff --git a/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=2.5.png b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=2.5.png new file mode 100644 index 0000000..173f627 Binary files /dev/null and b/homework8/Homework8_Q5_Gradient_Descent_Convergence_x=2.5.png differ