changeset 8647:06f5dd901f30

implement registering of optimization options
author Jaroslav Hajek <highegg@gmail.com>
date Fri, 30 Jan 2009 21:24:29 +0100
parents e01c6355304f
children ff61b53eb294
files scripts/ChangeLog scripts/optimization/PKG_ADD scripts/optimization/__all_opts__.m scripts/optimization/fsolve.m scripts/optimization/optimget.m scripts/optimization/optimset.m
diffstat 6 files changed, 102 insertions(+), 15 deletions(-) [+]
line wrap: on
line diff
--- a/scripts/ChangeLog	Fri Jan 30 21:17:13 2009 +0100
+++ b/scripts/ChangeLog	Fri Jan 30 21:24:29 2009 +0100
@@ -1,3 +1,11 @@
+2009-01-30  Jaroslav Hajek  <highegg@gmail.com>
+
+	* optimization/__all_opts__.m: New source.
+	* optimization/optimset.m: Implement checking for registered options.
+	* optimization/optimget.m: Ditto.
+	* optimization/fsolve.m: Fix misspelled option.
+	* optimization/PKG_ADD: New startup file.
+
 2009-01-30  Kai Habel  <kai.habel@gmx.de>
 
 	* plot/__go_draw_axes__.m: Add support for transparent surfaces.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/optimization/PKG_ADD	Fri Jan 30 21:24:29 2009 +0100
@@ -0,0 +1,2 @@
+__all_opts__ ("fzero", "fsolve", "lsqnonneg");
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scripts/optimization/__all_opts__.m	Fri Jan 30 21:24:29 2009 +0100
@@ -0,0 +1,58 @@
+## 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
+## <http://www.gnu.org/licenses/>.
+
+## -*- 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)
+  
+  persistent saved_names = {};
+
+  ## guard against recursive calls.
+  persistent recursive = false;
+
+  if (nargin == 0)
+    names = saved_names;
+  else
+    ## 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:nargin
+      try
+        opts = optimset (varargin{i});
+        fn = fieldnames (opts).';
+        names = [names, fn];
+      catch
+        # throw the error as a warning.
+        warning (lasterr ());
+      end_try_catch
+    endfor
+    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
+
+endfunction
+
--- a/scripts/optimization/fsolve.m	Fri Jan 30 21:17:13 2009 +0100
+++ b/scripts/optimization/fsolve.m	Fri Jan 30 21:24:29 2009 +0100
@@ -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
--- a/scripts/optimization/optimget.m	Fri Jan 30 21:17:13 2009 +0100
+++ b/scripts/optimization/optimget.m	Fri Jan 30 21:24:29 2009 +0100
@@ -1,4 +1,5 @@
 ## Copyright (C) 2008 Jaroslav Hajek <highegg@gmail.com>
+## 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)
--- a/scripts/optimization/optimset.m	Fri Jan 30 21:17:13 2009 +0100
+++ b/scripts/optimization/optimset.m	Fri Jan 30 21:24:29 2009 +0100
@@ -1,4 +1,5 @@
 ## Copyright (C) 2007 John W. Eaton
+## Copyright (C) 2009 VZLU Prague
 ##
 ## This file is part of Octave.
 ##
@@ -29,21 +30,14 @@
   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)
       ## Display possibilities.
-      tmp = opts';
-      disp (struct (tmp{:}));
+      puts ("\nAll possible optimization options:\n\n");
+      printf ("  %s\n", opts{:});
+      puts ("\n");
     else
       ## Return empty structure.
       ## We're incompatible with Matlab at this point.
@@ -63,10 +57,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
@@ -83,3 +86,6 @@
   endif
 
 endfunction
+
+%!assert (optimget (optimset ('tolx', 1e-2), 'tOLx'), 1e-2)
+%!assert (isfield (optimset ('tolFun', 1e-3), 'TolFun'))