function cvt_1d_nonuniform ( )

%*****************************************************************************80
%
%% CVT_1D_NONUNIFORM computes a CVT using a nonuniform density.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    30 March 2004
%
%  Author:
%
%    John Burkardt
%
%  Parameters:
%
%    Input, integer M, the spatial dimension, which must be 1
%    for this code.
%
%    Input, integer N, the number of generators.
%    A nice value to start with is 10.
%
%    Input, integer DENSITY_FUNCTION,
%    0: s -> s
%    1: s -> sqrt(s)
%    2: s -> s^(1/3)
%    3: s -> s^(1/4)
%    4: s -> log ( e / ( e - s * ( e - 1 ) ) );
%    5: s -> 0.5+atan(50*(x-0.5))/pi;
%
%    Input, integer SAMPLE_FUNCTION_INIT,
%    0: initialize generators using the MATLAB RAND function;
%    1: initialize generators to a uniform grid;
%    2: initialize all generators to zero.
%
%    Input, integer SAMPLE_NUM_CVT, the number of sample points
%    generated on each iteration.  This should be much more than
%    the number of generator points, say 20 to 100 times as much.
%
%    Input, integer SAMPLE_NUM_STEPS, the number of CVT iterations
%    carried out.  Things should have settled down after 100 steps.
%
%    Input, integer SEED, a seed for the random number generator.
%
  m = 1;
  n = 35;
  density_function = 5;
  sample_function_init = 0;
  sample_num_cvt = 100000;
  sample_num_steps = 100;
  seed = 123456789;

  timestamp ( );
  fprintf ( 1, '\n' );
  fprintf ( 1, 'CVT_1D_NONUNIFORM\n' );
  fprintf ( 1, '  MATLAB version\n' );
  fprintf ( 1, '\n' );

  fprintf ( 1, '\n' );
  fprintf ( 1, '  Spatial dimension M =        %d\n', m );
  fprintf ( 1, '  Number of generators N =     %d\n', n );

  if ( density_function == 0 )
    fprintf ( 1, '  s -> s.\n' );
  elseif ( density_function == 1 )
    fprintf ( 1, '  s -> sqrt(s).\n' );
  elseif ( density_function == 2 )
    fprintf ( 1, '  s -> s^(1/3).\n' );
  elseif ( density_function == 3 )
    fprintf ( 1, '  s -> s^(1/4).\n' );
  elseif ( density_function == 4 )
    euler = exp ( 1 );
    fprintf ( 1, '  s -> log ( e / ( e - s * ( e - 1 ) ) ).\n' );
  elseif ( density_function == 5 )
    fprintf ( 1, '  s -> 0.5+atan(50*(x-0.5))/pi.\n' );
  end 

  if ( sample_function_init == 0 )
    fprintf ( 1, '  Initialize using RAND (MATLAB intrinsic).\n' );
    generator(1:n,1) = rand ( 1, n )';
  elseif ( sample_function_init == 1 )
    fprintf ( 1, '  Initialize using uniform grid.\n' );
    generator(1:n,1) = linspace ( 0, 1, n )';
  elseif ( sample_function_init == 2 )
    fprintf ( 1, '  Initialize all points to 0.\n' );
    generator(1:n,1) = 0;
  end

  fprintf ( 1, '  The number of sampling points per iteration = %d\n', ...
    sample_num_cvt );
  fprintf ( 1, '  The number of iterations = %d\n', sample_num_steps );
  fprintf ( 1, '  Initial random number seed = %d\n', seed );
  fprintf ( 1, '\n' );
%
%  Initialize the plotting arrays.
%
  x(1:n,1:sample_num_steps+1) = zeros ( n, sample_num_steps+1 );

  x(1:n,1) = generator(1:n,1);

  y = ( 0 : sample_num_steps );

  for step = 1 : sample_num_steps

    generator_new(1:n,1) = zeros ( n, 1 );
    tally(1:n) = 0;

    for j = 1 : sample_num_cvt
%
%  Generate a random sampling point S.
%  Unless the density function is #0, the sampling point will be
%  biased by a nonuniform density function.
%
      s = rand ( 1, 1 );

      if ( density_function == 0 )

      elseif ( density_function == 1 )
        s = sqrt ( s );
      elseif ( density_function == 2 )
        s = s^(1.0/3.0);
      elseif ( density_function == 3 )
        s = s^(1.0/4.0);
      elseif ( density_function == 4 )
        s = log ( euler / ( euler - s * ( euler - 1 ) ) );
      elseif ( density_function == 5 )
        s = 0.5+atan(50*(s-0.5))/pi;
      end 
%
%  Find the nearest cell generator.
%
      nearest = 1;
      dist = abs ( generator(1,1) - s );
     
      for k = 2 : n
        if ( abs ( generator(k,1) - s ) < dist )
          nearest = k;
          dist = abs ( generator(k,1) - s );
        end 
      end
%
%  Add S to the sum of all points in its generator.
%
      generator_new(nearest,1) = generator_new(nearest,1) + s;
      tally(nearest) = tally(nearest) + 1;

    end
%
%  Dividing each generator's sum by the number of points in the sum
%  produces the updated position of the generator.
%
    for j = 1 : n
      if ( tally(j) ~= 0 )
        generator(j,1) = generator_new(j,1) / tally(j);
      end
    end

    x(1:n,step+1) = generator(1:n,1);
  
  end
%
%  Plot the evolution of the locations of the generators.
%
  clf;

  for k = 1 : n
    plot ( x(k,1:sample_num_steps+1), y, 'LineWidth', 3 )
    hold on;
  end
  grid on

  hold off;

  title ( 'Evolution of generator locations during iteration.', 'FontSize', 16 );
  xlabel ( 'Generator positions', 'FontSize', 16 );
  ylabel ( 'Iterations', 'FontSize', 16 ); 

  fprintf ( 1, '\n' );
  fprintf ( 1, 'CVT_1D_NONUNIFORM\n' );
  fprintf ( 1, '  Normal end of execution.\n' );

  fprintf ( 1, '\n' );
  timestamp ( );

  return
end
function timestamp ( )

%*****************************************************************************80
%
%% TIMESTAMP prints the current YMDHMS date as a timestamp.
%
%  Licensing:
%
%    This code is distributed under the GNU LGPL license.
%
%  Modified:
%
%    14 February 2003
%
%  Author:
%
%    John Burkardt
%
  t = now;
  c = datevec ( t );
  s = datestr ( c, 0 );
  fprintf ( 1, '%s\n', s );

  return
end
