function p3_ex2 ( )

%*****************************************************************************80
%
%% p3_ex2 carries out project 3 exercise 2.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    02 April 2019
%
%  Author:
%
%    John Burkardt
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'p3_ex2\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '  Support Vector Machine.\n' );

  data = load ( 'jet_engines.txt' );
  
  rpm = data(:,2);
  vib = data(:,3);
  grade = data(:,4);

  n = length ( rpm );
%
%  Part 1: Report and plot the data.
%
  rpm_min = min ( rpm );
  rpm_max = max ( rpm );
  r = ( rpm - rpm_min ) / ( rpm_max - rpm_min );
  vib_min = min ( vib );
  vib_max = max ( vib );
  v = ( vib - vib_min ) / ( vib_max - vib_min );

  good = find ( grade == +1.0 );
  bad = find ( grade == -1.0 );
  n_good = length ( good );
  n_bad = length ( bad );
  bad_rpm_mean = mean ( rpm(bad) );
  bad_vib_mean = mean ( vib(bad) );
  good_rpm_mean = mean ( rpm(good) );
  good_vib_mean = mean ( vib(good) );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Data analysis\n' );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Number of engines = %d\n', n );
  fprintf ( 1, '  %d good engines, and %d bad engines\n', n_good, n_bad );
  fprintf ( 1, '  %g <= RPM <= %g\n', rpm_min, rpm_max );
  fprintf ( 1, '  %g <= VIB <= %g\n', vib_min, vib_max );
  fprintf ( 1, '  GOOD: mean RPM = %g, mean VIB = %g\n', good_rpm_mean, good_vib_mean );
  fprintf ( 1, '  BAD:  mean RPM = %g, mean VIB = %g\n', bad_rpm_mean, bad_vib_mean );
  fprintf ( 1, '  %g <= VIB <= %g\n', vib_min, vib_max );

  plot ( rpm(good), vib(good), 'b+', rpm(bad), vib(bad), 'ro' )
  xlabel ( '<-- RPM -->' );
  ylabel ( '<-- VIB -->' );
  title ( 'Jet Engine Ratings' );
  grid ( 'on' );
  filename = 'p3_ex2_data.png';
  print ( '-dpng', filename );
  fprintf ( 1, '  Graphics saved as "%s"\n', filename );
%
%  Part 2: Set up the SVM problem for quadprog()
%
  H = 0.5 * [ ...
    1.0, 0.0, 0.0; ...
    0.0, 1.0, 0.0; ...
    0.0, 0.0, 0.0 ];

  f = zeros ( 3, 1 );

  A = - diag ( grade ) * [ rpm, vib, ones(n,1) ];
  c = -1.0 * ones ( n, 1 );

  options = optimoptions ( @quadprog, 'Display', 'off' );

  wb = quadprog ( H, f, A, c, [], [], [], [], [], options );
%
%  Extract the coefficients and print.
%
  w = wb(1:2);
  b = wb(3);

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Table 2: SVM classifier:\n' );
  fprintf ( 1, '  f(x) = %g x1 + %g x2 + %g\n', w(1), w(2), b );
%
%  Plot.
%
  figure ( 2 )
  hold on
  plot ( rpm(good), vib(good), 'b+');
  plot ( rpm(bad), vib(bad), 'ro' );
  px = [ rpm_min, rpm_max ];
  py = [ (-b-w(1)*rpm_min)/w(2), (-b-w(1)*rpm_max)/w(2) ];
  plot ( px, py, 'k-', 'linewidth', 3 );
  px = [ rpm_min, rpm_max ];
  py = [ (-b-1-w(1)*rpm_min)/w(2), (-b-1-w(1)*rpm_max)/w(2) ];
  plot ( px, py, 'r-', 'linewidth', 3 );
  px = [ rpm_min, rpm_max ];
  py = [ (-b+1-w(1)*rpm_min)/w(2), (-b+1-w(1)*rpm_max)/w(2) ];
  plot ( px, py, 'b-', 'linewidth', 3 );
  hold off
  xlabel ( '<-- RPM -->' );
  ylabel ( '<-- VIB -->' );
  title ( 'SVM for Jet Engine Ratings (MATLAB)' );
  grid ( 'on' );
  filename = 'p3_ex2_svm.png';
  print ( '-dpng', filename );
  fprintf ( 1, '\n' );
  fprintf ( 1, '  Graphics saved as "%s"\n', filename );
%
%  Terminate.
%
  fprintf ( 1, '\n' );
  fprintf ( 1, 'p3_ex2\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  return
end
