diff --git a/hw1-conjugate-gradient/optimizer.py b/hw1-conjugate-gradient/optimizer.py index a22b22b1..3282633b 100644 --- a/hw1-conjugate-gradient/optimizer.py +++ b/hw1-conjugate-gradient/optimizer.py @@ -1 +1,71 @@ import numpy as np +import matplotlib.pyplot as plt +from matplotlib import cm +from mpl_toolkits.mplot3d import Axes3D +import scipy.optimize + +# Global variables (in capital letters) + +# Initial guess to minimizer +GUESS = np.array([4,4]) + +# This array will contain the steps of the minimizer on its way to the minimum +STEPS = GUESS.reshape(-1,2) + +# This function fills the STEPS array, and is used as input to scipy.optimize.minimize +def my_callback(xk): + global STEPS + STEPS = np.vstack((STEPS, np.array(xk))) + +# This function returns the minimum value of the function func given as input +# The second input is the initial guess of the minimum +def find_minimum(func, guess): + result = scipy.optimize.minimize(func, x0 = guess, method='BFGS', callback=my_callback) + return result.x + +# This function implements S(x) as given in the exercise sheet +def quadratic_function(x): + + # create column vector of input array + x.reshape(-1, 1) + + # create matrix and vector coefficients of S(x) given in exercise sheet + mat = np.array([[4, 0], [1, 3]]) + vec = np.array([0, 1]).transpose() + + # return S(x) + return (x.transpose() @ mat) @ x - x.transpose() @ vec + + +# This function plots the S(x) surface and includes the path taken by the minimizer +def plotting(): + fig = plt.figure(figsize=(14,8)) + axe = fig.add_subplot(111, projection="3d") + num_of_points = 100 + xmax = ymax = -10 + xmin = ymin = 10 + X, Y = np.meshgrid(np.linspace(xmin,xmax,num_of_points), np.linspace(ymin,ymax,num_of_points)) + Z = np.zeros_like(X) + for i in range(0,num_of_points): + for j in range(0, num_of_points): + Z[i,j] = quadratic_function( np.array([X[i,j], Y[i,j]]) ) + sp = axe.plot_surface(X, Y, Z, cmap=cm.coolwarm) + axe.view_init(60, 100) + fig.colorbar(sp) + + step_value = np.zeros(STEPS.shape[0]) + for i in range(0, STEPS.shape[0]): + step_value[i] = quadratic_function( np.array([STEPS[i, 0], STEPS[i, 1]]) ) + axe.plot(STEPS[:,0], STEPS[:,1], step_value, 'r*--') + + axe.set_xlabel('x', fontsize=15) + axe.set_ylabel('y', fontsize=15) + axe.set_zlabel(' S(x,y)', fontsize=15) + axe.zaxis.set_rotate_label(False) + plt.savefig("plot.png") + plt.show() + +result = find_minimum(quadratic_function, GUESS) +print("The (approximated) minimum value is found at position (x,y) = ", result) +print("The (approximated) minimum value is ", quadratic_function(result)) +plotting()