From: <i7...@us...> - 2010-12-21 16:44:28
|
Revision: 8028 http://octave.svn.sourceforge.net/octave/?rev=8028&view=rev Author: i7tiol Date: 2010-12-21 16:44:20 +0000 (Tue, 21 Dec 2010) Log Message: ----------- Allow named parameters to be arrays. Split bounds setting to lower and upper bounds. Modified Paths: -------------- trunk/octave-forge/main/optim/DESCRIPTION trunk/octave-forge/main/optim/inst/__dfdp__.m trunk/octave-forge/main/optim/inst/__lm_svd__.m trunk/octave-forge/main/optim/inst/__nonlin_residmin__.m trunk/octave-forge/main/optim/inst/dcdp.m trunk/octave-forge/main/optim/inst/dfdp.m trunk/octave-forge/main/optim/inst/dfpdp.m trunk/octave-forge/main/optim/inst/dfxpdp.m trunk/octave-forge/main/optim/inst/nonlin_residmin.m Modified: trunk/octave-forge/main/optim/DESCRIPTION =================================================================== --- trunk/octave-forge/main/optim/DESCRIPTION 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/DESCRIPTION 2010-12-21 16:44:20 UTC (rev 8028) @@ -5,7 +5,7 @@ Maintainer: The Octave Community Title: Optimzation. Description: Non-linear optimization toolkit. -Depends: octave (>= 2.9.7), miscellaneous (>= 1.0.10), struct (>= 1.0.8) +Depends: octave (>= 2.9.7), miscellaneous (>= 1.0.11), struct (>= 1.0.8) Autoload: yes License: GPL version 2 or later and GFDL Url: http://octave.sf.net Modified: trunk/octave-forge/main/optim/inst/__dfdp__.m =================================================================== --- trunk/octave-forge/main/optim/inst/__dfdp__.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/__dfdp__.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -51,28 +51,31 @@ diff_onesided = false (n, 1); end - if (isfield (hook, 'bounds')) - bounds = hook.bounds; + if (isfield (hook, 'lbound')) + lbound = hook.lbound; else - bounds = ones (n, 2); - bounds(:, 1) = -Inf; - bounds(:, 2) = Inf; + lbound = - Inf (n, 1); end + if (isfield (hook, 'ubound')) + ubound = hook.ubound; + else + ubound = Inf (n, 1); + end + if (isfield (hook, 'plabels')) plabels = hook.plabels; else - plabels = num2cell ((1:n).'); + plabels = cell2cell (num2cell ((1:n).'), 1); end else fixed = false (n, 1); diff_onesided = fixed; diffp = .001 * ones (n, 1); - bounds = ones (n, 2); - bounds(:, 1) = -Inf; - bounds(:, 2) = Inf; - plabels = num2cell ((1:n).'); + lbound = - Inf (n, 1); + ubound = Inf (n, 1); + plabels = cell2cell (num2cell ((1:n).'), 1); end prt = zeros (m, n); % initialise Jacobian to Zero @@ -91,11 +94,11 @@ %% p may be slightly out of bounds due to inaccuracy, or exactly at %% the bound -> single sided interval - idxvl = p <= bounds(:, 1); - idxvg = p >= bounds(:, 2); - p1(idxvl) = min (p(idxvl) + absdel(idxvl), bounds(idxvl, 2)); + idxvl = p <= lbound; + idxvg = p >= ubound; + p1(idxvl) = min (p(idxvl) + absdel(idxvl), ubound(idxvl, 1)); idxd(idxvl) = false; - p1(idxvg) = max (p(idxvg) - absdel(idxvg), bounds(idxvg, 1)); + p1(idxvg) = max (p(idxvg) - absdel(idxvg), lbound(idxvg, 1)); idxd(idxvg) = false; idxs = ~(fixed | idxd); % single sided interval @@ -109,19 +112,19 @@ % versions %% remaining single sided intervals, violating a bound -> take largest %% possible direction of single sided interval - idxvs(idxnvs) = p1(idxnvs) < bounds(idxnvs, 1) | ... - p1(idxnvs) > bounds(idxnvs, 2); - del1 = p(idxvs) - bounds(idxvs, 1); - del2 = bounds(idxvs, 2) - p(idxvs); + idxvs(idxnvs) = p1(idxnvs) < lbound(idxnvs, 1) | ... + p1(idxnvs) > ubound(idxnvs, 1); + del1 = p(idxvs) - lbound(idxvs, 1); + del2 = ubound(idxvs, 1) - p(idxvs); idx1g2 = del1 > del2; idx1g2w(idxvs) = idx1g2; idx1le2w(idxvs) = ~idx1g2; - p1(idx1g2w) = max (p(idx1g2w) - absdel(idx1g2w), bounds(idx1g2w, 1)); + p1(idx1g2w) = max (p(idx1g2w) - absdel(idx1g2w), lbound(idx1g2w, 1)); p1(idx1le2w) = min (p(idx1le2w) + absdel(idx1le2w), ... - bounds(idx1le2w, 2)); + ubound(idx1le2w, 1)); %% double sided interval - p1(idxnvd) = min (p(idxnvd) + absdel(idxnvd), bounds(idxnvd, 2)); - p2(idxnvd) = max (p(idxnvd) - absdel(idxnvd), bounds(idxnvd, 1)); + p1(idxnvd) = min (p(idxnvd) + absdel(idxnvd), ubound(idxnvd, 1)); + p2(idxnvd) = max (p(idxnvd) - absdel(idxnvd), lbound(idxnvd, 1)); del(idxs) = p1(idxs) - p(idxs); del(idxd) = p1(idxd) - p2(idxd); Modified: trunk/octave-forge/main/optim/inst/__lm_svd__.m =================================================================== --- trunk/octave-forge/main/optim/inst/__lm_svd__.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/__lm_svd__.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -38,8 +38,8 @@ n_gencstr = hook.n_gencstr; % number of non-linear constraints eq_idx = hook.eq_idx; % logical index of equality constraints in all % constraints - bounds = hook.bounds; % bounds, subset of linear inequality - % constraints in mc and vc + lbound = hook.lbound; % bounds, subset of linear inequality + ubound = hook.ubound; % constraints in mc and vc %% passed values of constraints for initial parameters pin_cstr = hook.pin_cstr; @@ -80,7 +80,8 @@ %% some useful variables derived from passed variables n_lcstr = size (vc, 1); have_constraints_except_bounds = ... - n_lcstr + n_gencstr > sum (reshape (~isinf (bounds), [], 1)); + n_lcstr + n_gencstr > ... + sum (lbound ~= -Inf) + sum (ubound ~= Inf); n = length (pin); wtl = wt(:); @@ -98,7 +99,7 @@ warning ('initial parameters violate equality constraints'); end end - idx = bounds(:, 1) == bounds(:, 2); + idx = lbound == ubound; if (any (idx)) warning ('lower and upper bounds identical for some parameters, fixing the respective parameters'); fixed(idx) = true; @@ -106,18 +107,18 @@ if (all (fixed)) error ('no free parameters'); end - lidx = pin < bounds(:, 1); - uidx = pin > bounds(:, 2); + lidx = pin < lbound; + uidx = pin > ubound; if (any (lidx | uidx) && have_constraints_except_bounds) warning ('initial parameters outside bounds, not corrected since other constraints are given'); else if (any (lidx)) warning ('some initial parameters set to lower bound'); - pin(lidx) = bounds(lidx, 1); + pin(lidx, 1) = lbound(lidx, 1); end if (any (uidx)) warning ('some initial parameters set to upper bound'); - pin(uidx) = bounds(uidx, 2); + pin(uidx, 1) = ubound(uidx, 1); end end if (n_gencstr > 0 && any (~isinf (maxstep))) @@ -425,12 +426,12 @@ %% --- but only if no further constraints are given, otherwise %% the inaccuracy in honoring them might increase by this if (~have_constraints_except_bounds) - lidx = p < bounds(:, 1); - uidx = p > bounds(:, 2); - p(lidx) = bounds(lidx, 1); - p(uidx) = bounds(uidx, 2); - chg(lidx) = p(lidx) - pprev(lidx); - chg(uidx) = p(uidx) - pprev(uidx); + lidx = p < lbound; + uidx = p > ubound; + p(lidx, 1) = lbound(lidx, 1); + p(uidx, 1) = ubound(uidx, 1); + chg(lidx, 1) = p(lidx, 1) - pprev(lidx, 1); + chg(uidx, 1) = p(uidx, 1) - pprev(uidx, 1); end %% f = F (p); Modified: trunk/octave-forge/main/optim/inst/__nonlin_residmin__.m =================================================================== --- trunk/octave-forge/main/optim/inst/__nonlin_residmin__.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/__nonlin_residmin__.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -37,13 +37,15 @@ if (nargin == 1 && ischar (f) && strcmp (f, "defaults")) p = optimset ("param_config", [], \ "param_order", [], \ + "param_dims", [], \ "f_inequc_pstruct", false, \ "f_equc_pstruct", false, \ "f_pstruct", false, \ "df_inequc_pstruct", false, \ "df_equc_pstruct", false, \ "dfdp_pstruct", false, \ - "bounds", [], \ + "lbound", [], \ + "ubound", [], \ "dfdp", [], \ "cpiv", @ cpiv_bard, \ "max_fract_change", [], \ @@ -84,6 +86,7 @@ pconf = optimget (settings, "param_config"); pord = optimget (settings, "param_order"); + pdims = optimget (settings, "param_dims"); f_inequc_pstruct = optimget (settings, "f_inequc_pstruct", false); f_equc_pstruct = optimget (settings, "f_equc_pstruct", false); f_pstruct = optimget (settings, "f_pstruct", false); @@ -92,7 +95,8 @@ f_inequc_pstruct); df_equc_pstruct = optimget (settings, "df_equc_pstruct", \ f_equc_pstruct); - bounds = optimget (settings, "bounds"); + lbound = optimget (settings, "lbound"); + ubound = optimget (settings, "ubound"); dfdp = optimget (settings, "dfdp"); if (ischar (dfdp)) dfdp = str2func (dfdp); endif max_fract_change = optimget (settings, "max_fract_change"); @@ -101,6 +105,11 @@ diff_onesided = optimget (settings, "diff_onesided"); fixed = optimget (settings, "fixed"); + any_vector_conf = ! (isempty (lbound) && isempty (ubound) && \ + isempty (max_fract_change) && \ + isempty (fract_prec) && isempty (diffp) && \ + isempty (diff_onesided) && isempty (fixed)); + ## collect constraints [mc, vc, f_genicstr, df_gencstr, user_df_gencstr] = \ __collect_constraints__ (optimget (settings, "inequc")); @@ -117,34 +126,97 @@ if (! user_df_genecstr) df_equc_pstruct = false; endif ## some settings require a parameter order - if (isempty (pord)) - if ((pin_struct || ! isempty (pconf) || f_inequc_pstruct || \ - f_equc_pstruct || f_pstruct || dfdp_pstruct || \ - df_inequc_pstruct || df_equc_pstruct || mc_struct || \ - emc_struct)) - error ("given settings require specification of parameter order"); + if ((pin_struct || ! isempty (pconf) || f_inequc_pstruct || \ + f_equc_pstruct || f_pstruct || dfdp_pstruct || \ + df_inequc_pstruct || df_equc_pstruct || mc_struct || \ + emc_struct)) + if (isempty (pord)) + if (pin_struct) + if (any_vector_conf || \ + ! (f_pstruct && \ + (f_inequc_pstruct || isempty (f_genicstr)) && \ + (f_equc_pstruct || isempty (f_genecstr)) && \ + (dfdp_pstruct || isempty (dfdp)) && \ + (df_inequc_pstruct || ! user_df_gencstr) && \ + (df_equc_pstruct || ! user_df_genecstr) && \ + (mc_struct || isempty (mc)) && \ + (emc_struct || isempty (emc)))) + error ("no parameter order specified and constructing a parameter order from the structure of initial parameters can not be done since not all configuration or given functions are structure based"); + else + pord = fieldnames (pin); + endif + else + error ("given settings require specification of parameter order or initial parameters in the form of a structure"); + endif endif - else pord = pord(:); - if (rows (unique (pord)) < rows (pord)) + if (pin_struct && ! all (arefields (pin, pord))) + error ("some initial parameters lacking"); + endif + if ((nnames = rows (unique (pord))) < rows (pord)) error ("duplicate parameter names in 'param_order'"); endif + if (isempty (pdims)) + if (pin_struct) + pdims = cellfun \ + (@ size, fields2cell (pin, pord), "UniformOutput", false); + else + pdims = num2cell (ones (nnames, 2), 2); + endif + else + pdims = pdims(:); + if (pin_struct && \ + ! all (cellfun (@ (x, y) prod (size (x)) == prod (y), \ + struct2cell (pin), pdims))) + error ("given param_dims and dimensions of initial parameters do not match"); + endif + endif + if (nnames != rows (pdims)) + error ("lengths of 'param_order' and 'param_dims' not equal"); + endif + pnel = cellfun (@ prod, pdims); + ppartidx = cumsum (pnel); + ppartidx = [[1; ppartidx(1:end-1)+1], ppartidx]; + if (any (pnel > 1)) + pnonscalar = true; + cpnel = num2cell (pnel); + prepidx = cat (1, cellfun \ + (@ (x, n) x(ones (1, n), 1), \ + num2cell ((1:nnames).'), cpnel, \ + "UniformOutput", false){:}); + epord = pord(prepidx, 1); + psubidx = cat (1, cellfun \ + (@ (n) (1:n).', cpnel, \ + "UniformOutput", false){:}); + else + pnonscalar = false; # some less expensive interfaces later + prepidx = (1:nnames).'; + epord = pord; + psubidx = ones (nnames, 1); + endif + else + pord = []; # spares checks for given but not needed endif - if (! pin_struct) + if (pin_struct) + np = sum (pnel); + else np = length (pin); - else - np = length (pord); + if (! isempty (pord) && np != sum (pnel)) + error ("number of initial parameters not correct"); + endif endif - plabels = num2cell ((1:np).'); + plabels = cell2cell (num2cell ((1:np).'), 1); if (! isempty (pord)) - plabels = cat (2, plabels, pord); + plabels = cat (2, plabels, cell2cell (epord, 1), \ + cell2cell (num2cell (psubidx), 1)); endif ## some useful vectors zerosvec = zeros (np, 1); NAvec = NA (np, 1); + Infvec = Inf (np, 1); falsevec = false (np, 1); sizevec = [np, 1]; @@ -154,10 +226,9 @@ ## parameter-related configuration is either allowed by a structure ## or by vectors - if (! (isempty (bounds) && isempty (max_fract_change) && \ - isempty (fract_prec) && isempty (diffp) && \ - isempty (diff_onesided) && isempty (fixed))) - error ("if param_config is given, its potential items must not be configured in another way"); + if (any_vector_conf) + error ("if param_config is given, its potential items must not \ + be configured in another way"); endif ## supplement parameter names lacking in param_config @@ -167,52 +238,119 @@ pconf = structcat (1, fields2cell (pconf, pord){:}); - bounds = zeros (np, 2); - bounds(:, 1) = -Inf; - bounds(:, 2) = Inf; - if (isfield (pconf, "bounds")) - bounds(! fieldempty (pconf, "bounds"), :) = cat (1, pconf.bounds); + ## in the following, use reshape with explicit dimensions (instead + ## of x(:)) so that errors are thrown if a configuration item has + ## incorrect number of elements + + lbound = - Infvec; + if (isfield (pconf, "lbound")) + idx = ! fieldempty (pconf, "lbound"); + if (pnonscalar) + lbound (idx(prepidx), 1) = \ + cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).lbound}.', \ + cpnel(idx), "UniformOutput", false){:}); + else + lbound(idx, 1) = cat (1, pconf.lbound); + endif endif + ubound = Infvec; + if (isfield (pconf, "ubound")) + idx = ! fieldempty (pconf, "ubound"); + if (pnonscalar) + ubound (idx(prepidx), 1) = \ + cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).ubound}.', \ + cpnel(idx), "UniformOutput", false){:}); + else + ubound(idx, 1) = cat (1, pconf.ubound); + endif + endif + max_fract_change = fract_prec = NAvec; if (isfield (pconf, "max_fract_change")) - max_fract_change(! fieldempty (pconf, "max_fract_change")) = \ - [pconf.max_fract_change]; + idx = ! fieldempty (pconf, "max_fract_change"); + if (pnonscalar) + max_fract_change(idx(prepidx)) = \ + cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).max_fract_change}.', \ + cpnel(idx), \ + "UniformOutput", false){:}); + else + max_fract_change(idx) = [pconf.max_fract_change]; + endif endif if (isfield (pconf, "fract_prec")) - fract_prec(! fieldempty (pconf, "fract_prec")) = \ - [pconf.fract_prec]; + idx = ! fieldempty (pconf, "fract_prec"); + if (pnonscalar) + fract_prec(idx(prepidx)) = \ + cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).fract_prec}.', cpnel(idx), \ + "UniformOutput", false){:}); + else + fract_prec(idx) = [pconf.fract_prec]; + endif endif diffp = zerosvec; diffp(:) = diffp_default; if (isfield (pconf, "diffp")) - diffp(! fieldempty (pconf, "diffp")) = [pconf.diffp]; + idx = ! fieldempty (pconf, "diffp"); + if (pnonscalar) + diffp(idx(prepidx)) = \ + cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).diffp}.', cpnel(idx), \ + "UniformOutput", false){:}); + else + diffp(idx) = [pconf.diffp]; + endif endif diff_onesided = fixed = falsevec; if (isfield (pconf, "diff_onesided")) - diff_onesided(! fieldempty (pconf, "diff_onesided")) = \ - logical ([pconf.diff_onesided]); + idx = ! fieldempty (pconf, "diff_onesided"); + if (pnonscalar) + diff_onesided(idx(prepidx)) = \ + logical \ + (cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).diff_onesided}.', cpnel(idx), \ + "UniformOutput", false){:})); + else + diff_onesided(idx) = logical ([pconf.diff_onesided]); + endif endif if (isfield (pconf, "fixed")) - fixed(! fieldempty (pconf, "fixed")) = logical ([pconf.fixed]); + idx = ! fieldempty (pconf, "fixed"); + if (pnonscalar) + fixed(idx(prepidx)) = \ + logical \ + (cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + {pconf(idx).fixed}.', cpnel(idx), \ + "UniformOutput", false){:})); + else + fixed(idx) = logical ([pconf.fixed]); + endif endif else ## use supplied configuration vectors - if (isempty (bounds)) - bounds = zeros (np, 2); - bounds(:, 1) = -Inf; - bounds(:, 2) = Inf; - elseif (any (size (bounds) != [np, 2])) + if (isempty (lbound)) + lbound = - Infvec; + elseif (any (size (lbound) != sizevec)) error ("bounds: wrong dimensions"); endif + if (isempty (ubound)) + ubound = Infvec; + elseif (any (size (ubound) != sizevec)) + error ("bounds: wrong dimensions"); + endif + if (isempty (max_fract_change)) max_fract_change = NAvec; elseif (any (size (max_fract_change) != sizevec)) @@ -256,10 +394,10 @@ endif endif - ## guaranty all (bounds(:, 1) <= bounds(:, 2)) - tp = bounds((idx = bounds(:, 1) > bounds(:, 2)), 2); - bounds(idx, 2) = bounds(idx, 1); - bounds(idx, 1) = tp; + ## guaranty all (lbound <= ubound) + if (any (lbound > ubound)) + error ("some lower bounds larger than upper bounds"); + endif #### consider whether initial parameters and functions are based on #### parameter structures or parameter vectors; wrappers for call to @@ -267,16 +405,27 @@ ## initial parameters if (pin_struct) - if (! all (arefields (pin, pord))) - error ("some initial parameters lacking"); + if (pnonscalar) + pin = cat (1, cellfun (@ (x, n) reshape (x, n, 1), \ + fields2cell (pin, pord), cpnel, \ + "UniformOutput", false){:}); + else + pin = cat (1, fields2cell (pin, pord){:}); endif - pin = cat (1, fields2cell (pin, pord){:}); endif ## model function if (f_pstruct) - f = @ (p, varargin) \ - f (cell2struct (num2cell (p), pord, 1), varargin{:}); + if (pnonscalar) + f = @ (p, varargin) \ + f (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), \ + pord, 1), varargin{:}); + else + f = @ (p, varargin) \ + f (cell2struct (num2cell (p), pord, 1), varargin{:}); + endif endif f_pin = f (pin); if (isfield (hook, "observations")) @@ -292,18 +441,37 @@ dfdp = @ (p, hook) __dfdp__ (p, f, hook); endif if (dfdp_pstruct) - dfdp = @ (p, hook) \ - cat (2, \ - fields2cell \ - (dfdp (cell2struct (num2cell (p), pord, 1), hook), \ - pord){:}); + if (pnonscalar) + dfdp = @ (p, hook) \ + cat (2, \ + fields2cell \ + (dfdp (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), \ + pord, 1), hook), \ + pord){:}); + else + dfdp = @ (p, hook) \ + cat (2, \ + fields2cell \ + (dfdp (cell2struct (num2cell (p), pord, 1), hook), \ + pord){:}); + endif endif ## function for general inequality constraints if (f_inequc_pstruct) - f_genicstr = @ (p, varargin) \ - f_genicstr \ - (cell2struct (num2cell (p), pord, 1), varargin{:}); + if (pnonscalar) + f_genicstr = @ (p, varargin) \ + f_genicstr (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), \ + pord, 1), varargin{:}); + else + f_genicstr = @ (p, varargin) \ + f_genicstr \ + (cell2struct (num2cell (p), pord, 1), varargin{:}); + endif endif ## note this stage @@ -311,19 +479,39 @@ ## jacobian of general inequality constraints if (df_inequc_pstruct) - df_gencstr = @ (p, func, idx, hook) \ - cat (2, \ - fields2cell \ - (df_gencstr (cell2struct (num2cell (p), pord, 1), \ - func, idx, hook), \ - pord){:}); + if (pnonscalar) + df_gencstr = @ (p, func, idx, hook) \ + cat (2, \ + fields2cell \ + (df_gencstr \ + (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), pord, 1), \ + func, idx, hook), \ + pord){:}); + else + df_gencstr = @ (p, func, idx, hook) \ + cat (2, \ + fields2cell \ + (df_gencstr (cell2struct (num2cell (p), pord, 1), \ + func, idx, hook), \ + pord){:}); + endif endif ## function for general equality constraints if (f_equc_pstruct) - f_genecstr = @ (p, varargin) \ - f_genecstr \ - (cell2struct (num2cell (p), pord, 1), varargin{:}); + if (pnonscalar) + f_genecstr = @ (p, varargin) \ + f_genecstr (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), \ + pord, 1), varargin{:}); + else + f_genecstr = @ (p, varargin) \ + f_genecstr \ + (cell2struct (num2cell (p), pord, 1), varargin{:}); + endif endif ## note this stage @@ -331,12 +519,24 @@ ## jacobian of general equality constraints if (df_equc_pstruct) - df_genecstr = @ (p, func, idx, hook) \ - cat (2, \ - fields2cell \ - (df_genecstr (cell2struct (num2cell (p), pord, 1), \ - func, idx, hook), \ - pord){:}); + if (pnonscalar) + df_genecstr = @ (p, func, idx, hook) \ + cat (2, \ + fields2cell \ + (df_genecstr \ + (cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), pord, 1), \ + func, idx, hook), \ + pord){:}); + else + df_genecstr = @ (p, func, idx, hook) \ + cat (2, \ + fields2cell \ + (df_genecstr (cell2struct (num2cell (p), pord, 1), \ + func, idx, hook), \ + pord){:}); + endif endif ## linear inequality constraints @@ -347,7 +547,7 @@ endif smc = mc; mc = zeros (np, rows (vc)); - mc(idx, :) = cat (1, fields2cell (smc, pord(idx)){:}); + mc(idx(prepidx), :) = cat (1, fields2cell (smc, pord(idx)){:}); endif ## linear equality constraints @@ -358,21 +558,50 @@ endif semc = emc; emc = zeros (np, rows (evc)); - emc(idx, :) = cat (1, fields2cell (semc, pord(idx)){:}); + emc(idx(prepidx), :) = cat (1, fields2cell (semc, pord(idx)){:}); endif ## parameter-related configuration for jacobi functions if (dfdp_pstruct || df_inequc_pstruct || df_equc_pstruct) - s_diffp = cell2struct (num2cell (diffp), pord, 1); - s_diff_onesided = cell2struct (num2cell (diff_onesided), pord, 1); - s_orig_bounds = cell2struct (num2cell (bounds, 2), pord, 1); - s_plabels = cell2struct (cell2cell (plabels, 1), pord, 1); - s_orig_fixed = cell2struct (num2cell (fixed), pord, 1); + if(pnonscalar) + s_diffp = cell2struct \ + (cellfun (@ reshape, partarray (diffp, ppartidx), \ + pdims, "UniformOutput", false), pord, 1); + s_diff_onesided = cell2struct \ + (cellfun (@ reshape, partarray (diff_onesided, ppartidx), \ + pdims, "UniformOutput", false), pord, 1); + s_orig_lbound = cell2struct \ + (cellfun (@ reshape, partarray (lbound, ppartidx), \ + pdims, "UniformOutput", false), pord, 1); + s_orig_ubound = cell2struct \ + (cellfun (@ reshape, partarray (ubound, ppartidx), \ + pdims, "UniformOutput", false), pord, 1); + s_plabels = cell2struct \ + (cell2cell \ + (cat (2, cellfun \ + (@ (x) cellfun \ + (@ reshape, partarray (cat (1, x{:}), ppartidx), \ + pdims, "UniformOutput", false), \ + cell2cell (plabels, 2), "UniformOutput", false){:}), \ + 1), \ + pord, 1); + s_plabels = cell2struct (cell2cell (plabels, 1), pord, 1); + s_orig_fixed = cell2struct \ + (cellfun (@ reshape, partarray (fixed, ppartidx), \ + pdims, "UniformOutput", false), pord, 1); + else + s_diffp = cell2struct (num2cell (diffp), pord, 1); + s_diff_onesided = cell2struct (num2cell (diff_onesided), pord, 1); + s_orig_lbound = cell2struct (num2cell (lbound), pord, 1); + s_orig_ubound = cell2struct (num2cell (ubound), pord, 1); + s_plabels = cell2struct (cell2cell (plabels, 1), pord, 1); + s_orig_fixed = cell2struct (num2cell (fixed), pord, 1); + endif endif #### some further values and checks - if (any (fixed & (pin < bounds(:, 1) | pin > bounds(:, 2)))) + if (any (fixed & (pin < lbound | pin > ubound))) warning ("some fixed parameters outside bounds"); endif @@ -435,7 +664,8 @@ backend = map_backend (backend); #### handle fixing of parameters - orig_bounds = bounds; + orig_lbound = lbound; + orig_ubound = ubound; orig_fixed = fixed; if (all (fixed)) error ("no free parameters"); @@ -482,7 +712,8 @@ ## _last_ of all, vectors of parameter-related configuration, ## including "fixed" itself - bounds = bounds(nonfixed, :); + lbound = lbound(nonfixed, :); + ubound = ubound(nonfixed, :); max_fract_change = max_fract_change(nonfixed); fract_prec = fract_prec(nonfixed); fixed = fixed(nonfixed); @@ -494,19 +725,20 @@ if (dfdp_pstruct) dfdp = @ (p, hook) \ dfdp (p, cell2fields \ - ({s_diffp, s_diff_onesided, s_orig_bounds, s_plabels, \ + ({s_diffp, s_diff_onesided, s_orig_lbound, \ + s_orig_ubound, s_plabels, \ cell2fields(num2cell(hook.fixed), pord(nonfixed), \ 1, s_orig_fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); else dfdp = @ (p, hook) \ dfdp (p, cell2fields \ - ({diffp, diff_onesided, orig_bounds, plabels, \ - assign(orig_fixed, nonfixed, hook.fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + ({diffp, diff_onesided, orig_lbound, orig_ubound, \ + plabels, assign(orig_fixed, nonfixed, hook.fixed)}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); endif @@ -514,19 +746,21 @@ if (df_inequc_pstruct) df_gencstr = @ (p, func, idx, hook) \ df_gencstr (p, func, idx, cell2fields \ - ({s_diffp, s_diff_onesided, s_orig_bounds, s_plabels, \ + ({s_diffp, s_diff_onesided, s_orig_lbound, \ + s_orig_ubound, s_plabels, \ cell2fields(num2cell(hook.fixed), pord(nonfixed), \ 1, s_orig_fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); else df_gencstr = @ (p, func, idx, hook) \ df_gencstr (p, func, idx, cell2fields \ - ({diffp, diff_onesided, orig_bounds, plabels, \ + ({diffp, diff_onesided, orig_lbound, \ + orig_ubound, plabels, \ assign(orig_fixed, nonfixed, hook.fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); endif @@ -534,19 +768,21 @@ if (df_equc_pstruct) df_genecstr = @ (p, func, idx, hook) \ df_genecstr (p, func, idx, cell2fields \ - ({s_diffp, s_diff_onesided, s_orig_bounds, s_plabels, \ + ({s_diffp, s_diff_onesided, s_orig_lbound, \ + s_orig_ubound, s_plabels, \ cell2fields(num2cell(hook.fixed), pord(nonfixed), \ 1, s_orig_fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); else df_genecstr = @ (p, func, idx, hook) \ df_genecstr (p, func, idx, cell2fields \ - ({diffp, diff_onesided, orig_bounds, plabels, \ + ({diffp, diff_onesided, orig_lbound, \ + orig_ubound, plabels, \ assign(orig_fixed, nonfixed, hook.fixed)}, \ - {"diffp", "diff_onesided", "bounds", "plabels", \ - "fixed"}, \ + {"diffp", "diff_onesided", "lbound", "ubound", \ + "plabels", "fixed"}, \ 2, hook)); endif @@ -554,10 +790,10 @@ ## include bounds into linear inequality constraints tp = eye (sum (nonfixed)); - lidx = ! isinf (bounds(:, 1)); - uidx = ! isinf (bounds(:, 2)); + lidx = lbound != - Inf; + uidx = ubound != Inf; mc = cat (2, mc, tp(:, lidx), - tp(:, uidx)); - vc = cat (1, vc, - bounds(lidx, 1), bounds(uidx, 2)); + vc = cat (1, vc, - lbound(lidx, 1), ubound(uidx, 1)); ## concatenate linear inequality and equality constraints mc = cat (2, mc, emc); @@ -644,7 +880,8 @@ hook.df_cstr = df_cstr; hook.n_gencstr = n_gencstr; hook.eq_idx = eq_idx; - hook.bounds = bounds; + hook.lbound = lbound; + hook.ubound = ubound; ## passed values of constraints for initial parameters hook.pin_cstr = pin_cstr; @@ -671,7 +908,14 @@ [p, resid, cvg, outp] = backend (f, pin, hook); if (pin_struct) - p = cell2struct (num2cell (p), pord, 1); + if (pnonscalar) + p = cell2struct \ + (cellfun (@ reshape, partarray (p, ppartidx), \ + pdims, "UniformOutput", false), \ + pord, 1); + else + p = cell2struct (num2cell (p), pord, 1); + endif endif endfunction Modified: trunk/octave-forge/main/optim/inst/dcdp.m =================================================================== --- trunk/octave-forge/main/optim/inst/dcdp.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/dcdp.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -31,7 +31,8 @@ hook.f = f; if (nargin > 4) - hook.bounds = bounds; + hook.lbounds = bounds(:, 1); + hook.ubounds = bounds(:, 2); end hook.diffp = abs (dp); Modified: trunk/octave-forge/main/optim/inst/dfdp.m =================================================================== --- trunk/octave-forge/main/optim/inst/dfdp.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/dfdp.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -59,7 +59,8 @@ hook.f = f; if (nargin > 5) - hook.bounds = bounds; + hook.lbound = bounds(:, 1); + hook.ubound = bounds(:, 2); end hook.diffp = abs (dp); Modified: trunk/octave-forge/main/optim/inst/dfpdp.m =================================================================== --- trunk/octave-forge/main/optim/inst/dfpdp.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/dfpdp.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -37,9 +37,9 @@ %% (useful in optimization if some parameters are not optimized, but %% are 'fixed'). %% - %% hook.bounds: Two-column matrix of parameter bounds (or -Inf or - %% +Inf, respectively) to be respected in finite differencing. The - %% consistency of this matrix is not checked. + %% hook.lbound, hook.ubound: vectors of lower and upper parameter + %% bounds (or -Inf or +Inf, respectively) to be respected in finite + %% differencing. The consistency of bounds is not checked. %% This is an interface to __dfdp__.m. Modified: trunk/octave-forge/main/optim/inst/dfxpdp.m =================================================================== --- trunk/octave-forge/main/optim/inst/dfxpdp.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/dfxpdp.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -37,9 +37,9 @@ %% (useful in optimization if some parameters are not optimized, but %% are 'fixed'). %% - %% hook.bounds: Two-column matrix of parameter bounds (or -Inf or - %% +Inf, respectively) to be respected in finite differencing. The - %% consistency of this matrix is not checked. + %% hook.lbound, hook.ubound: vectors of lower and upper parameter + %% bounds (or -Inf or +Inf, respectively) to be respected in finite + %% differencing. The consistency of bounds is not checked. %% This is an interface to __dfdp__.m. Modified: trunk/octave-forge/main/optim/inst/nonlin_residmin.m =================================================================== --- trunk/octave-forge/main/optim/inst/nonlin_residmin.m 2010-12-18 18:12:40 UTC (rev 8027) +++ trunk/octave-forge/main/optim/inst/nonlin_residmin.m 2010-12-21 16:44:20 UTC (rev 8028) @@ -75,18 +75,19 @@ ## parameters, reshaped to a column vector, @code{fixed}: logical vector ## indicating which parameters are not optimized, so these partial ## derivatives need not be computed and can be set to zero, -## @code{diffp}, @code{diff_onesided}, @code{bounds}: identical to the -## user settings of this name, @code{plabels}: 2-dimensional cell-array -## with labels for parameters, one row for each parameter, the row -## contains one entry with the numerical index ot this parameter. The -## default jacobian function will call the model function with the -## second argument set with fields @code{f}: as the @code{f} passed to -## the jacobian function, @code{plabels}: row of @code{plabels} as -## passed to the jacobian function corresponding to current parameter, -## @code{side}: @code{0} for one-sided interval, @code{1} or @code{2}, -## respectively, for the sides of a two-sided interval, and -## @code{parallel}: logical scalar indicating parallel computation of -## partial derivatives. +## @code{diffp}, @code{diff_onesided}, @code{lbound}, @code{ubound}: +## identical to the user settings of this name, @code{plabels}: +## 1-dimensional cell-array of column-cell-arrays, each column with +## labels for all parameters, the first column contains the numerical +## indices of the parameters. The default jacobian function will call +## the model function with the second argument set with fields @code{f}: +## as the @code{f} passed to the jacobian function, @code{plabels}: +## cell-array of 1x1 cell-arrays with the entries of the +## column-cell-arrays of @code{plabels} as passed to the jacobian +## function corresponding to current parameter, @code{side}: @code{0} +## for one-sided interval, @code{1} or @code{2}, respectively, for the +## sides of a two-sided interval, and @code{parallel}: logical scalar +## indicating parallel computation of partial derivatives. ## ## @code{diffp}: column vector of fractional intervals (doubled for ## central intervals) supposed to be used by jacobian functions @@ -102,8 +103,8 @@ ## done independently of the backend, but the backend may choose to fix ## additional parameters under certain conditions. ## -## @code{bounds}: 2-column matrix of bounds for parameters. Default: -## @code{-Inf} and @code{+Inf} for the first and second column, +## @code{lbound}, @code{ubound}: column vectors of lower and upper +## bounds for parameters. Default: @code{-Inf} and @code{+Inf}, ## respectively. The bounds are non-strict, i.e. parameters are allowed ## to be exactly equal to a bound. The default jacobian function will ## respect bounds (but no further inequality constraints) in finite @@ -178,8 +179,11 @@ ## ## Structure-based parameter handling ## -## The setting @code{param_order}, a cell-array of parameter names, is a -## prerequisite for any kind of structure-based parameter handling. +## The setting @code{param_order} is a cell-array with names of the +## optimized parameters. If not given, and initial parameters are a +## structure, all parameters in the structure are optimized. It is an +## error if @code{param_order} is not given and there are any +## non-structure-based configuration items or functions. ## ## The initial parameters @var{pin} can be given as a structure ## containing at least all fields named in @code{param_order}. In this @@ -202,17 +206,28 @@ ## matrix in fields under the respective parameter names can be given. ## In this case, rows containing only zeros need not be given. ## -## The vector/matrix-based settings @code{bounds}, @code{fixed}, -## @code{diffp}, @code{diff_onesided}, @code{fract_prec}, and -## @code{max_fract_change} can be replaced by the setting +## The vector-based settings @code{lbound}, @code{ubound}, +## @code{fixed}, @code{diffp}, @code{diff_onesided}, @code{fract_prec}, +## and @code{max_fract_change} can be replaced by the setting ## @code{param_config}. It is a structure that can contain fields named ## in @code{param_order}. For each such field, there may be subfields -## with the same names as the above vector/matrix-based settings, but -## containing a scalar value (or a two-element row vector in the case of -## bounds) for the respective parameter. If @code{param_config} is -## specified, none of the above vector/matrix-based settings may be -## used. +## with the same names as the above vector-based settings, but +## containing a scalar value for the respective parameter. If +## @code{param_config} is specified, none of the above +## vector/matrix-based settings may be used. ## +## Additionally, named parameters are allowed to be non-scalar real +## arrays. In this case, their dimensions are given by the setting +## @code{param_dims}, a cell-array of dimension vectors, each containing +## at least two dimensions; if not given, dimensions are taken from the +## initial parameters, if these are given in a structure. Any +## vector-based settings or not structure-based linear constraints then +## must correspond to an order of parameters with all parameters +## reshaped to vectors and concatenated in the user-given order of +## parameter names. Structure-based settings or structure-based initial +## parameters must contain arrays with dimensions reshapable to those of +## the respective parameters. +## ## Description of backends (currently only one) ## ## "lm_svd_feasible" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |