# HG changeset patch # User Jaroslav Hajek # Date 1233307713 -3600 # Node ID 0f13b720e3b134793bfb8381fe6022c2230187ca # Parent 4385bb503467d6cbd834378dd4023b1f5052b858 implement registering of optimization options diff --git a/scripts/ChangeLog b/scripts/ChangeLog --- a/scripts/ChangeLog +++ b/scripts/ChangeLog @@ -0,0 +1,7 @@ +2009-01-30 Jaroslav Hajek + + * optimization/__all_opts__.m: New source. + * optimization/optimset.m: Implement checking for registered options. + * optimization/optimget.m: Ditto. + * optimzation/fsolve.m: Fix misspelled option. + diff --git a/scripts/optimization/__all_opts__.m b/scripts/optimization/__all_opts__.m new file mode 100644 --- /dev/null +++ b/scripts/optimization/__all_opts__.m @@ -0,0 +1,77 @@ +## Copyright (C) 2009 VZLU Prague +## +## This file is part of Octave. +## +## Octave is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or (at +## your option) any later version. +## +## Octave is distributed in the hope that it will be useful, but +## WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +## General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with Octave; see the file COPYING. If not, see +## . + +## -*- texinfo -*- +## @deftypefn {Function File} {} __all_opts__ () +## internal function. Queries all options from all known optimization +## functions and returns a list of possible values. +## @end deftypefn + +function names = __all_opts__ (varargin) + + ## add more here as necessary + persistent funcs = {"fzero", "fsolve", "lsqnonneg"}; + + persistent saved_names = {}; + + ## guard against recursive calls + persistent recursive = false; + + if (recursive) + names = {}; + return; + else + if (isempty (saved_names)) + regquery = funcs; + else + regquery = {}; + endif + if (nargin > 0) + regquery = [regquery, varargin]; + endif + + if (isempty (regquery)) + names = saved_names; + else + recursive = true; + ## query all options from all known functions. These will call optimset, + ## which will in turn call us, but we won't answer. + names = saved_names; + for i = 1:length (regquery) + try + opts = optimset (regquery{i}); + fn = fieldnames (opts).'; + names = [names, fn]; + catch + # throw the error as a warning. + warning (lasterr ()); + end_try_catch + endfor + recursive = false; + names = unique (names); + lnames = unique (tolower (names)); + if (length (lnames) < length (names)) + ## This is bad. + error ("__all_opts__: duplicate options with inconsistent case."); + endif + saved_names = names; + endif + endif + +endfunction + diff --git a/scripts/optimization/fsolve.m b/scripts/optimization/fsolve.m --- a/scripts/optimization/fsolve.m +++ b/scripts/optimization/fsolve.m @@ -77,7 +77,7 @@ ## Get default options if requested. if (nargin == 1 && ischar (fcn) && strcmp (fcn, 'defaults')) x = optimset ("MaxIter", 400, "MaxFunEvals", Inf, \ - "Jacobian", "off", "TolX", 1.5e-8, "TolF", 1.5e-8, + "Jacobian", "off", "TolX", 1.5e-8, "TolFun", 1.5e-8, "OutputFcn", [], "Updating", "on", "FunValCheck", "off"); return; endif diff --git a/scripts/optimization/optimget.m b/scripts/optimization/optimget.m --- a/scripts/optimization/optimget.m +++ b/scripts/optimization/optimget.m @@ -1,4 +1,5 @@ ## Copyright (C) 2008 Jaroslav Hajek +## Copyright (C) 2009 VZLU Prague ## ## This file is part of Octave. ## @@ -27,6 +28,18 @@ function retval = optimget (options, parname, default) + if (nargin < 2 || nargin > 4 || ! isstruct (options) || ! ischar (parname)) + print_usage (); + endif + + opts = __all_opts__ (); + idx = lookup (opts, parname, "i"); + + if (idx > 0 && strcmpi (parname, opts{idx})) + parname = opts{idx}; + else + warning ("unrecognized option: %s", parname) + endif if (isfield (options, parname)) retval = options.(parname); elseif (nargin > 2) diff --git a/scripts/optimization/optimset.m b/scripts/optimization/optimset.m --- a/scripts/optimization/optimset.m +++ b/scripts/optimization/optimset.m @@ -1,4 +1,5 @@ ## Copyright (C) 2007 John W. Eaton +## Copyright (C) 2009 VZLU Prague ## ## This file is part of Octave. ## @@ -29,15 +30,7 @@ nargs = nargin (); ## Add more as needed. - persistent opts = { - "Display", "\"off\"|\"iter\"|{\"final\"}|\"notify\""; - "FunValCheck", "{\"off\"}|\"on\""; - "MaxFunEvals", "positive integer"; - "MaxIter", "positive integer"; - "OutputFun", "function|{[]}"; - "TolFun", "positive scalar"; - "TolX", "positive scalar" - }; + opts = __all_opts__ (); if (nargs == 0) if (nargout == 0) @@ -63,10 +56,19 @@ old = varargin{1}; new = varargin{2}; fnames = fieldnames (old); + ## skip validation if we're in the internal query + validation = ! isempty (opts); for [val, key] = new - mask = strcmpi (fnames, key); - if (any (mask)) - key = fnames (mask); + if (validation) + ## Case insensitive lookup in all options. + i = lookup (opts, key, "i"); + ## Validate option. + if (i > 0 && strcmpi (opts{i}, key)) + ## Use correct case. + key = opts{i}; + else + warning ("unrecognized option: %s", key); + endif endif old.(key) = val; endfor