function gradient_descent_nonlinear_test ( )

%*****************************************************************************80
%
%% gradient_descent_nonlinear_test() tests gradient descent for nonlinear f.
%
%  Discussion:
%
%    The quartic function is
%    f(x) = 2.0 * x ^ 4 - 4.0 * x ^ 2 + x + 20.0
%
%    We seek a minimizer of f(x) in the range -2 <= x <= 2.
%
%    The gradient_descent0() method uses a very simple version of
%    the algorithm.
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    27 July 2022
%
%  Author:
%
%    John Burkardt
%
  a = -2.0;
  b = +2.0;

  fprintf ( 1, '\n' );
  fprintf ( 1, 'gradient_descent_nonlinear_test():\n' );
  fprintf ( 1, '  Seek local minimizer of a scalar function quartic(x)\n' );
  fprintf ( 1, '  Minimizer is probably in the interval [%g,%g]\n', a, b );
  fprintf ( 1, '  Use a very simple version of the gradient descent method.\n' );
%
%  Plot the function.
%
  figure ( )
  xvec = linspace ( a, b, 101 );
  fxvec = quartic ( xvec );
  hold ( 'on' );
  plot ( xvec, fxvec, 'linewidth', 3 );
  plot ( [ a, b ], [ 0, 0 ], 'k', 'linewidth', 3 );
  hold ( 'off' );
  grid ( 'on' );
  xlabel ( '<-- X -->' );
  ylabel ( '<-- F(X) -->' );
  title ( 'Quartic function', 'fontsize', 16 );
  filename = 'quartic.png';
  print ( '-dpng', filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Graphics saved in "%s"\n', filename );
%
%  Choose a random initial guess, or choose x = -1.5.
%
  x0 = a + ( b - a ) * rand ( );
  x0 = - 1.5;
%
%  Maximum number of iterations.
%
  itmax = 40;
%
%  Choose a small learning rate.
%
  alpha = 0.005;
%
%  Seek minimizer.
%
  x = gradient_descent_nonlinear ( @(x)quartic(x), ...
    @(x)quartic_df(x), x0, itmax, alpha );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Initial x = %g,  f(x) = %g, f''(x) = %g\n', ...
    x0, quartic ( x0 ), quartic_df(x0) );
  fprintf ( 1, '  Final x = %g,  f(x) = %g, f''(x) = %g\n', ...
    x, quartic ( x ), quartic_df(x) );
%
%  Plot the function with initial point and local minimizer.
%
  figure ( )
  xvec = linspace ( a, b, 101 );
  fxvec = quartic ( xvec );
  hold ( 'on' )
  plot ( xvec, fxvec, 'linewidth', 3 );
  plot ( [ x0, x0 ], [ 0, quartic(x0) ], 'b', 'linewidth', 3 );
  plot ( x0,  0.0, 'bo', 'markersize', 10 );
  plot ( x0,  quartic ( x0 ), 'bo', 'markersize', 10 );
  plot ( [ x, x ], [ 0, quartic(x) ], 'r', 'linewidth', 3 );
  plot ( x,  0.0, 'ro', 'markersize', 10 );
  plot ( x,  quartic ( x ), 'ro', 'markersize', 10 );
  plot ( [ a, b ], [ 0, 0 ], 'k', 'linewidth', 3 );
  hold ( 'off' )
  grid ( 'on' );
  xlabel ( '<-- X -->' );
  ylabel ( '<-- F(X) -->' );
  title ( 'Initial point blue, minimizer red', 'fontsize', 16 );
  filename = 'quartic_minimizer.png';
  print ( '-dpng', filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Graphics saved in "%s"\n', filename );

  return
end
function value = quartic ( x )

%*****************************************************************************80
%
%% quartic() evaluates a quartic function.
%
%  Discussion:
%
%    The quartic function is
%    f(x) = 2.0 * x ^ 4 - 4.0 * x ^ 2 + x + 20.0
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    27 July 2022
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    real X: the evaluation point.
%
%  Output:
%
%    real VALUE: the function value.
%
  value = 2.0 * x.^4 - 4.0 * x.^2 + x + 20.0;

  return
end
function value = quartic_df ( x )

%*****************************************************************************80
%
%% quartic_df() evaluates the derivative of a quartic function.
%
%  Discussion:
%
%    The quartic function is
%    f(x) = 2.0 * x ^ 4 - 4.0 * x ^ 2 + x + 20.0
%
%    The quartic function is
%    f'(x) = 8.0 * x ^ 3 - 8.0 * x + 1
%
%  Licensing:
%
%    This code is distributed under the MIT license.
%
%  Modified:
%
%    27 July 2022
%
%  Author:
%
%    John Burkardt
%
%  Input:
%
%    real X: the evaluation point.
%
%  Output:
%
%    real VALUE: the derivative value.
%
  value = 8.0 * x.^3 - 8.0 * x + 1.0;

  return
end



