#! /usr/bin/env python3 # def quartic_gradient1 ( ): #*****************************************************************************80 # ## quartic_gradient1() applies gradient descent to the quartic function. # # Discussion: # # f (x) = 2 * x**4 - 4 * x**2 + x + 20 # f'(x) = 8 * x**3 - 8 * x + 1 # # We seek a minimizer of f(x) in the range -2 <= x <= 2. # # Licensing: # # This code is distributed under the GNU LGPL license. # # Modified: # # 22 September 2019 # # Author: # # John Burkardt # from gradient_descent1 import gradient_descent1 import matplotlib.pyplot as plt import numpy as np print ( '' ) print ( 'quartic_gradient1:' ) print ( ' Seek minimizer of a quartic scalar function f(x)' ) # # Plot the function. # xmin = -2.0 xmax = +2.0; xp = np.linspace ( xmin, xmax, 101 ) fp = quartic_f ( xp ) plt.plot ( xp, fp, linewidth = 3 ) plt.plot ( [ xmin, xmax ], [ 0, 0 ], 'k', linewidth = 3 ) plt.grid ( True ) plt.xlabel ( '<-- X -->' ) plt.ylabel ( '<-- F(X) -->' ) plt.title ( 'Quartic function', fontsize = 16 ) filename = 'quartic.png' plt.savefig ( filename ) print ( '' ) print ( ' Graphics saved as "%s"' % ( filename ) ) plt.show ( ) plt.close ( ) # # Choose a random initial guess. # r = 0.05 dxtol = 0.00001 dftol = 0.001 itmax = 100 for x0 in [ -1.6, 1.8 ]: print ( '' ) print ( ' %12.8g %12.8g %12.8g' % ( x0, quartic_f ( x0 ), quartic_df ( x0 ) ) ) x, it = gradient_descent1 ( quartic_f, quartic_df, x0, r, dxtol, dftol, itmax ) print ( ' %12.8g %12.8g %12.8g' % ( x, quartic_f ( x ), quartic_df ( x ) ) ) # # Plot the function with initial point and local minimizer # xvec = np.linspace ( xmin, xmax, 101 ) fxvec = quartic_f ( xvec ) plt.plot ( xvec, fxvec, linewidth = 3 ) plt.plot ( [ x0, x0 ], [ 0, quartic_f ( x0 ) ], 'b', linewidth = 3 ) plt.plot ( x0, 0.0, 'bo', markersize = 10 ) plt.plot ( x0, quartic_f ( x0 ), 'bo', markersize = 10 ) plt.plot ( [ x, x ], [ 0, quartic_f ( x ) ], 'r', linewidth = 3 ) plt.plot ( x, 0.0, 'ro', markersize = 10 ) plt.plot ( x, quartic_f ( x ), 'ro', markersize = 10 ) plt.plot ( [ xmin, xmax ], [ 0, 0 ], 'k', linewidth = 3 ) plt.grid ( True ) plt.xlabel ( '<-- X -->' ) plt.ylabel ( '<-- F(X) -->' ) plt.title ( 'Initial point in blue, local minimizer in red', fontsize = 16 ) plt.show ( ) plt.close ( ) # # Terminate. # print ( '' ) print ( 'quartic_gradient1:' ) print ( ' Normal end of execution.' ) return def quartic_f ( x ): #*****************************************************************************80 # ## quartic_f() evaluates the quartic function. # f = 2.0 * x**4 - 4.0 * x**2 + x + 20.0 return f def quartic_df ( x ): #*****************************************************************************80 # ## quartic_df() evaluates the derivative of the quartic function. # df = 8.0 * x**3 - 8.0 * x + 1.0 return df if ( __name__ == '__main__' ): quartic_gradient1 ( )