# HG changeset patch # User John W. Eaton # Date 1540234197 14400 # Mon Oct 22 14:49:57 2018 -0400 # Node ID 4121dd6a923a40cc08c7eefba36528e494991e9e # Parent a11f920ff84d1236fa76367af1d37347f0012e16 lsqcurvefit: accept single problem structure argument * lsqcurvefit.m: For compatibility with Matlab, accept single structure argument defining problem. Extract fields into varargin array, set nargs, and continue as if arguments were passed individually. New test. diff --git a/inst/lsqcurvefit.m b/inst/lsqcurvefit.m --- a/inst/lsqcurvefit.m +++ b/inst/lsqcurvefit.m @@ -18,6 +18,7 @@ ## @deftypefn {Function File} {} lsqcurvefit (@var{fun}, @var{x0}, @var{xdata}, @var{ydata}) ## @deftypefnx {Function File} {} lsqcurvefit (@var{fun}, @var{x0}, @var{xdata}, @var{ydata}, @var{lb}, @var{ub}) ## @deftypefnx {Function File} {} lsqcurvefit (@var{fun}, @var{x0}, @var{xdata}, @var{ydata}, @var{lb}, @var{ub}, @var{options}) +## @deftypefnx {Function File} {} lsqcurvefit (@var{problem}) ## @deftypefnx {Function File} {[@var{x}, @var{resnorm}, @var{residual}, @var{exitflag}, @var{output}, @var{lambda}, @var{jacobian}] =} lsqcurvefit (@dots{}) ## Solve nonlinear least-squares (nonlinear data-fitting) problems ## @example @@ -29,6 +30,37 @@ ## ## The first four input arguments must be provided with non-empty initial guess @var{x0}. For a given input @var{xdata}, @var{ydata} is the observed output. ## @var{ydata} must be the same size as the vector (or matrix) returned by @var{fun}. The optional bounds @var{lb} and @var{ub} should be the same size as @var{x0}. +## +## @code{lsqcurvefit} may also be called with a single structure argument +## with the following fields: +## +## @table @code +## @item objective +## The objective function. +## +## @item x0 +## The initial point. +## +## @item xdata +## Input data. +## +## @item ydata +## Observed output. +## +## @item lb +## Lower bound for @var{x}. +## +## @item ub +## Upper bound for @var{x}. +## +## @item solver +## Must be set to @qcode{"lsqcurvefit"}. +## +## @item options +## A structure returned from @code{optimset} or an empty matrix to +## indicate that defaults should be used. +## @end table +## ## @var{options} can be set with @code{optimset}. ## Follwing Matlab compatible options ## are recognized: @@ -148,6 +180,34 @@ function varargout = lsqcurvefit (vararg return; endif + if (nargs == 1) + problem = varargin{1}; + varargin = cell (1, 7); + if (! isstruct (problem)) + error ("lsqcurvefit: PROBLEM must be a structure"); + endif + if (! strcmp (problem.solver, "lsqcurvefit")) + error ('lsqcurvefit: problem.solver must be set to "lsqcurvefit"'); + endif + varargin{1} = problem.objective; + varargin{2} = problem.x0; + varargin{3} = problem.xdata; + varargin{4} = problem.ydata; + if (isfield (problem, "lb")) + varargin{5} = problem.lb; + endif + if (isfield (problem, "ub")) + varargin{6} = problem.ub; + endif + varargin{7} = problem.options; + if (isfield (problem, "options")) + varargin{7} = problem.options; + else + options = []; + endif + nargs = 7; + endif + if (nargs < 4 || nargs==5 || nargs > 7) print_usage (); endif @@ -289,6 +349,19 @@ endfunction %! assert (resnorm, 3.2419e-004, 1e-8) %! assert(residual, [-2.7283e-003, 8.8079e-003, -6.8307e-004, -1.0432e-002, -5.1366e-003, 1.0172e-002], 1e-5) +%!test +%! problem.solver = "lsqcurvefit"; +%! problem.objective = @(p,x) p(1) + p(2)*exp(-x); +%! problem.x0 = [1, 1]; +%! problem.xdata = [0 .3 .8 1.1 1.6 2.3]; +%! problem.ydata = [.82 .72 .63 .60 .55 .50]; +%! problem.lb = [0, 0]; +%! problem.options = optimset('TolFun',1e-100); +%! [p, resnorm, residual] = lsqcurvefit (problem); +%! assert (p, [ 0.47595; 0.34132], 1e-5) +%! assert (resnorm, 3.2419e-004, 1e-8) +%! assert(residual, [-2.7283e-003, 8.8079e-003, -6.8307e-004, -1.0432e-002, -5.1366e-003, 1.0172e-002], 1e-5) + %!demo %! %% Example for user specified Jacobian.