function z_star = run_opt ( f_name, n )

%*****************************************************************************80
%
%% RUN_OPT runs a finite dimensional optimization problem.
%
%  Discussion:
%
%    The problem is based on a discretization of a Mayer problem in
%    optimal control.
%
%    f_name points to a user-supplied function with a single input argument n.
%
%    n is a discretization parameter. The finite-dimensional problem arises
%    by treating the (scalar) control as piecewise constant.
%
%    The function referenced by f_name must define the elements of
%    the underlying optimal control problem.  See 'zermelo' as an example.
%
%  Modified:
%
%    04 February 2010
%
%  Author:
%
%    Gene Cliff
%

%
%  F_NAME sets some of the problem data in PAR.
%
  PAR = feval ( str2func ( f_name ), n );
%
%  Those elements of PAR that were not set are given default values.
%
  if isfield(PAR, 'initial_guess')
    z0 = PAR.initial_guess(:);
  else
   z0 = zeros(length(PAR.ta)-1,1);
  end

  if isfield(PAR, 'LB')
    LB = PAR.LB*ones(size(z0));
  else
    LB = [];
  end

  if isfield(PAR, 'UB')
    UB = PAR.UB*ones(size(z0));
  else
    UB = [];
  end
%
%  Choose settings for the optimizer.
%  Note, in particular, the "UseParallel" setting, which tells FMINCON to
%  take advantage of the parallel workers.
%
  OPT = optimset ( optimset('fmincon'), ...
                       'LargeScale','off', ...
                       'Algorithm', 'active-set', ...
                       'Display' , 'iter', ...
                       'UseParallel', 'Always');

  h_cost = @(z) general_cost( z, PAR);
  h_cnst = @(z) general_constraint( z, PAR);
%
%  Run the optimization algorithm
%
  [ z_star, f_star, exit ] = ...
                  fmincon(h_cost, z0, [], [], [], [], LB, UB, h_cnst, OPT);
%
%  On successful conclusion, display the plot.
%
  if exit >=0 && isfield(PAR, 'plot')
    feval(PAR.plot, z_star, PAR)
  end

  return
end

