
12
Administrator

After updating and rebuilding today, the following test is failing for
me:
function retval = f (p)
x = p(1);
y = p(2);
z = p(3);
w = p(4);
retval = zeros (4, 1);
retval(1) = 3*x + 4*y + exp (z + w)  1.007;
retval(2) = 6*x  4*y + exp (3*z + w)  11;
retval(3) = x^4  4*y^2 + 6*z  8*w  20;
retval(4) = x^2 + 2*y^3 + z  w  4;
endfunction
test
x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
tol = 1.0e5;
[x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
assert (info > 0);
assert (norm (x  x_opt, Inf) < tol);
assert (norm (fval) < tol);
octave> info
info = 1
octave> norm (x  x_opt, Inf), tol
ans = 1.6079e05
tol = 1.0000e05
octave> norm (fval), tol
ans = 1.0665e04
tol = 1.0000e05
I'm not sure, but it looks like this line
## Replace fun with a guarded version.
fun = @(x) guarded_eval (fun, x);
should be
## Replace fun with a guarded version.
fcn = @(x) guarded_eval (fcn, x);
as fun is not defined before this point, or used after it.
Also, in the default settings section
x = optimset ("MaxIter", 400, "MaxFunEvals", Inf, \
"Jacobian", "off", "TolX", 1e7, "TolF", 1e7,
"OutputFcn", [], "Updating", "on", "FunValCheck", "off");
return;
wouldn't it be better to set the default tolerances based on something
like sqrt (eps (class (x))? Or, if fsolve should still work when
passed integer matrices, maybe something like
if (isa (x, "single"))
tol = sqrt (eps, "single");
else
tol = sqrt (eps);
endif
?
jwe


On Tue, Jan 27, 2009 at 5:31 PM, John W. Eaton < [hidden email]> wrote:
> After updating and rebuilding today, the following test is failing for
> me:
>
> function retval = f (p)
> x = p(1);
> y = p(2);
> z = p(3);
> w = p(4);
> retval = zeros (4, 1);
> retval(1) = 3*x + 4*y + exp (z + w)  1.007;
> retval(2) = 6*x  4*y + exp (3*z + w)  11;
> retval(3) = x^4  4*y^2 + 6*z  8*w  20;
> retval(4) = x^2 + 2*y^3 + z  w  4;
> endfunction
>
> test
> x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
> tol = 1.0e5;
> [x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
> assert (info > 0);
> assert (norm (x  x_opt, Inf) < tol);
> assert (norm (fval) < tol);
>
> octave> info
> info = 1
> octave> norm (x  x_opt, Inf), tol
> ans = 1.6079e05
> tol = 1.0000e05
> octave> norm (fval), tol
> ans = 1.0665e04
> tol = 1.0000e05
>
That's weird, because I get something different:
octave:5> info
info = 1
octave:6> norm(xx_opt, Inf)
ans = 4.1002e07
octave:7> norm (fval)
ans = 3.4606e06
Do you have qrupdate linked to Octave? That could maybe explain the
differences...
otherwise, we can check per line where the numbers start diverting.
> I'm not sure, but it looks like this line
>
> ## Replace fun with a guarded version.
> fun = @(x) guarded_eval (fun, x);
>
> should be
>
> ## Replace fun with a guarded version.
> fcn = @(x) guarded_eval (fcn, x);
>
> as fun is not defined before this point, or used after it.
>
OK, of course.
> Also, in the default settings section
>
> x = optimset ("MaxIter", 400, "MaxFunEvals", Inf, \
> "Jacobian", "off", "TolX", 1e7, "TolF", 1e7,
> "OutputFcn", [], "Updating", "on", "FunValCheck", "off");
> return;
>
> wouldn't it be better to set the default tolerances based on something
> like sqrt (eps (class (x))? Or, if fsolve should still work when
> passed integer matrices, maybe something like
>
> if (isa (x, "single"))
> tol = sqrt (eps, "single");
> else
> tol = sqrt (eps);
> endif
>
Originally, I used default settings exactly like this. However, I was
not sure how to reflect this in the default options, so I changed it
to fixed tolerances. If you have a better idea...
cheers

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On Tuesday, January 27, 2009, at 02:57PM, "Jaroslav Hajek" < [hidden email]> wrote:
>On Tue, Jan 27, 2009 at 5:31 PM, John W. Eaton < [hidden email]> wrote:
>> After updating and rebuilding today, the following test is failing for
>> me:
>>
>> function retval = f (p)
>> x = p(1);
>> y = p(2);
>> z = p(3);
>> w = p(4);
>> retval = zeros (4, 1);
>> retval(1) = 3*x + 4*y + exp (z + w)  1.007;
>> retval(2) = 6*x  4*y + exp (3*z + w)  11;
>> retval(3) = x^4  4*y^2 + 6*z  8*w  20;
>> retval(4) = x^2 + 2*y^3 + z  w  4;
>> endfunction
>>
>> test
>> x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
>> tol = 1.0e5;
>> [x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
>> assert (info > 0);
>> assert (norm (x  x_opt, Inf) < tol);
>> assert (norm (fval) < tol);
>>
>> octave> info
>> info = 1
>> octave> norm (x  x_opt, Inf), tol
>> ans = 1.6079e05
>> tol = 1.0000e05
>> octave> norm (fval), tol
>> ans = 1.0665e04
>> tol = 1.0000e05
>>
>
>That's weird, because I get something different:
>octave:5> info
>info = 1
>octave:6> norm(xx_opt, Inf)
>ans = 4.1002e07
>octave:7> norm (fval)
>ans = 3.4606e06
>
>Do you have qrupdate linked to Octave? That could maybe explain the
>differences...
>otherwise, we can check per line where the numbers start diverting.
I do not have qrupdate, but get something slightly smaller than did jwe.
octave> norm (x  x_opt, Inf)
ans = 1.5482e4
Would it be helpful for me to deeper to determine why the optimization terminated?
Ben


On Tue, Jan 27, 2009 at 9:10 PM, Ben Abbott < [hidden email]> wrote:
>
> On Tuesday, January 27, 2009, at 02:57PM, "Jaroslav Hajek" < [hidden email]> wrote:
>>On Tue, Jan 27, 2009 at 5:31 PM, John W. Eaton < [hidden email]> wrote:
>>> After updating and rebuilding today, the following test is failing for
>>> me:
>>>
>>> function retval = f (p)
>>> x = p(1);
>>> y = p(2);
>>> z = p(3);
>>> w = p(4);
>>> retval = zeros (4, 1);
>>> retval(1) = 3*x + 4*y + exp (z + w)  1.007;
>>> retval(2) = 6*x  4*y + exp (3*z + w)  11;
>>> retval(3) = x^4  4*y^2 + 6*z  8*w  20;
>>> retval(4) = x^2 + 2*y^3 + z  w  4;
>>> endfunction
>>>
>>> test
>>> x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
>>> tol = 1.0e5;
>>> [x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
>>> assert (info > 0);
>>> assert (norm (x  x_opt, Inf) < tol);
>>> assert (norm (fval) < tol);
>>>
>>> octave> info
>>> info = 1
>>> octave> norm (x  x_opt, Inf), tol
>>> ans = 1.6079e05
>>> tol = 1.0000e05
>>> octave> norm (fval), tol
>>> ans = 1.0665e04
>>> tol = 1.0000e05
>>>
>>
>>That's weird, because I get something different:
>>octave:5> info
>>info = 1
>>octave:6> norm(xx_opt, Inf)
>>ans = 4.1002e07
>>octave:7> norm (fval)
>>ans = 3.4606e06
>>
>>Do you have qrupdate linked to Octave? That could maybe explain the
>>differences...
>>otherwise, we can check per line where the numbers start diverting.
>
> I do not have qrupdate, but get something slightly smaller than did jwe.
>
> octave> norm (x  x_opt, Inf)
> ans = 1.5482e4
>
> Would it be helpful for me to deeper to determine why the optimization terminated?
>
> Ben
>
Definitely. First of all, I suggest you try running with
optimset("Updating", "off").
In fact, I realize that for such small systems qrupdate is not even
used, so I don't understand where the differences come from. Perhaps
displaying the sequence of x could shed some light here...
cheers

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 27Jan2009, Jaroslav Hajek wrote:
 On Tue, Jan 27, 2009 at 9:10 PM, Ben Abbott < [hidden email]> wrote:
 >
 > On Tuesday, January 27, 2009, at 02:57PM, "Jaroslav Hajek" < [hidden email]> wrote:
 >>On Tue, Jan 27, 2009 at 5:31 PM, John W. Eaton < [hidden email]> wrote:
 >>> After updating and rebuilding today, the following test is failing for
 >>> me:
 >>>
 >>> function retval = f (p)
 >>> x = p(1);
 >>> y = p(2);
 >>> z = p(3);
 >>> w = p(4);
 >>> retval = zeros (4, 1);
 >>> retval(1) = 3*x + 4*y + exp (z + w)  1.007;
 >>> retval(2) = 6*x  4*y + exp (3*z + w)  11;
 >>> retval(3) = x^4  4*y^2 + 6*z  8*w  20;
 >>> retval(4) = x^2 + 2*y^3 + z  w  4;
 >>> endfunction
 >>>
 >>> test
 >>> x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
 >>> tol = 1.0e5;
 >>> [x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
 >>> assert (info > 0);
 >>> assert (norm (x  x_opt, Inf) < tol);
 >>> assert (norm (fval) < tol);
 >>>
 >>> octave> info
 >>> info = 1
 >>> octave> norm (x  x_opt, Inf), tol
 >>> ans = 1.6079e05
 >>> tol = 1.0000e05
 >>> octave> norm (fval), tol
 >>> ans = 1.0665e04
 >>> tol = 1.0000e05
 >>>
 >>
 >>That's weird, because I get something different:
 >>octave:5> info
 >>info = 1
 >>octave:6> norm(xx_opt, Inf)
 >>ans = 4.1002e07
 >>octave:7> norm (fval)
 >>ans = 3.4606e06
 >>
 >>Do you have qrupdate linked to Octave? That could maybe explain the
 >>differences...
 >>otherwise, we can check per line where the numbers start diverting.
 >
 > I do not have qrupdate, but get something slightly smaller than did jwe.
 >
 > octave> norm (x  x_opt, Inf)
 > ans = 1.5482e4
 >
 > Would it be helpful for me to deeper to determine why the optimization terminated?
 >
 > Ben
 >

 Definitely. First of all, I suggest you try running with
 optimset("Updating", "off").
 In fact, I realize that for such small systems qrupdate is not even
 used, so I don't understand where the differences come from. Perhaps
 displaying the sequence of x could shed some light here...
I inserted "x" at the top of the main while loop, and fn, tolf, n, xn,
tolf*n*xn, just before the spot where info is set to 1, and this is
what I see:
octave> [x, fval, info] = fsolve (@f, [1, 1, 2, 1], optimset ("updating", "off"));
x =
1
1
2
1
x =
0.95626
0.62802
1.70291
1.28386
x =
1.8090
1.2704
1.6532
1.3059
x =
1.6296
1.2151
1.5720
1.4385
x =
1.43941
0.95247
1.56360
1.41601
x =
1.10610
0.83547
1.54197
1.53893
x =
0.77262
0.59393
1.47167
1.52390
fn = 1.0665e04
tolf = 1.0000e07
n = 4
xn = 693.95
ans = 2.7758e04
octave> norm (fval), tol
ans = 1.0665e04
tol = 1.0000e05
octave> norm (x  x_opt, Inf), tol
ans = 1.6079e05
tol = 1.0000e05
octave> info
info = 1
Does that help?
jwe

Administrator

On Tuesday, January 27, 2009, at 03:18PM, "Jaroslav Hajek" < [hidden email]> wrote:
>On Tue, Jan 27, 2009 at 9:10 PM, Ben Abbott < [hidden email]> wrote:
>>
>> On Tuesday, January 27, 2009, at 02:57PM, "Jaroslav Hajek" < [hidden email]> wrote:
>>>On Tue, Jan 27, 2009 at 5:31 PM, John W. Eaton < [hidden email]> wrote:
>>>> After updating and rebuilding today, the following test is failing for
>>>> me:
>>>>
>>>> function retval = f (p)
>>>> x = p(1);
>>>> y = p(2);
>>>> z = p(3);
>>>> w = p(4);
>>>> retval = zeros (4, 1);
>>>> retval(1) = 3*x + 4*y + exp (z + w)  1.007;
>>>> retval(2) = 6*x  4*y + exp (3*z + w)  11;
>>>> retval(3) = x^4  4*y^2 + 6*z  8*w  20;
>>>> retval(4) = x^2 + 2*y^3 + z  w  4;
>>>> endfunction
>>>>
>>>> test
>>>> x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
>>>> tol = 1.0e5;
>>>> [x, fval, info] = fsolve (@f, [1, 1, 2, 1]);
>>>> assert (info > 0);
>>>> assert (norm (x  x_opt, Inf) < tol);
>>>> assert (norm (fval) < tol);
>>>>
>>>> octave> info
>>>> info = 1
>>>> octave> norm (x  x_opt, Inf), tol
>>>> ans = 1.6079e05
>>>> tol = 1.0000e05
>>>> octave> norm (fval), tol
>>>> ans = 1.0665e04
>>>> tol = 1.0000e05
>>>>
>>>
>>>That's weird, because I get something different:
>>>octave:5> info
>>>info = 1
>>>octave:6> norm(xx_opt, Inf)
>>>ans = 4.1002e07
>>>octave:7> norm (fval)
>>>ans = 3.4606e06
>>>
>>>Do you have qrupdate linked to Octave? That could maybe explain the
>>>differences...
>>>otherwise, we can check per line where the numbers start diverting.
>>
>> I do not have qrupdate, but get something slightly smaller than did jwe.
>>
>> octave> norm (x  x_opt, Inf)
>> ans = 1.5482e4
>>
>> Would it be helpful for me to deeper to determine why the optimization terminated?
>>
>> Ben
>>
>
>Definitely. First of all, I suggest you try running with
>optimset("Updating", "off").
>In fact, I realize that for such small systems qrupdate is not even
>used, so I don't understand where the differences come from. Perhaps
>displaying the sequence of x could shed some light here...
>
>cheers
Ok, I created a f.m file and copied the test function f() to it. I then placed the following in test_fsolve.m. I also modified fsolve to display niter, maxiter, nfev, naxfev, and info when the outer loop terminates.
optimset ("Updating", "off");
x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642, 1.52719341133957 ];
tol = 1.0e5;
[x, fval, info, output, fjac] = fsolve (@f, [1, 1, 2, 1]);
assert (info > 0);
assert (norm (fval), 0, tol);
assert (norm (x  x_opt, Inf), 0, tol);
When I run it I get the result below.
octave:7> test_fsolve
niter = 44
maxiter = 400
nfev = 96
maxfev = Inf
info = 1
x =
0.76726 0.59064 1.47190 1.52720
fval =
1.3495e07
2.5856e06
9.9090e05
1.1893e04
info = 1
output =
{
iterations = 44
funcCount = 96
}
fjac =
3.00172 3.99956 0.93820 0.94125
6.12890 4.04019 55.04481 18.56031
2.37122 5.88633 6.65752 14.65200
2.29959 3.16654 9.20376 4.21261
error: assert (norm (fval),0,tol) expected
0
but got
1.5482e04
maximum absolute error 0.000154825 exceeds tolerance 1e05
Comparing against the outer loop
while (niter < maxiter && nfev < maxfev && ! info)
... I have no idea why the loop terminated.
Ben

Administrator

On 28Jan2009, Jaroslav Hajek wrote:
 I've uploaded a patch that relaxes the strict scaling:


 this makes the results with default settings more plausible:
 function retval = f (p)
 x = p(1);
 y = p(2);
 z = p(3);
 w = p(4);
 retval = zeros (4, 1);
 retval(1) = 3*x + 4*y + exp (z + w)  1.007;
 retval(2) = 6*x  4*y + exp (3*z + w)  11;
 retval(3) = x^4  4*y^2 + 6*z  8*w  20;
 retval(4) = x^2 + 2*y^3 + z  w  4;
 endfunction

 x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642,
 1.52719341133957 ];
 tol = 1.0e5;
 [x, fval, info, out] = fsolve (@f, [1, 1, 2, 1])
 [x, fval, info, out] = fsolve (@f, [1, 1, 2, 1], optimset
 ("Updating", "off"))
In this test, what is the purpose of tol? I think that confused me as
well as I didn't notice at first that it is unused. Was it intended
to be used in some way?
 PS. I'll also commit the patch to make optimset/optimget case insensitive.
OK.
Thanks,
jwe


On Thu, Jan 29, 2009 at 8:57 PM, John W. Eaton < [hidden email]> wrote:
> On 28Jan2009, Jaroslav Hajek wrote:
>
>  I've uploaded a patch that relaxes the strict scaling:
> 
> 
>  this makes the results with default settings more plausible:
>  function retval = f (p)
>  x = p(1);
>  y = p(2);
>  z = p(3);
>  w = p(4);
>  retval = zeros (4, 1);
>  retval(1) = 3*x + 4*y + exp (z + w)  1.007;
>  retval(2) = 6*x  4*y + exp (3*z + w)  11;
>  retval(3) = x^4  4*y^2 + 6*z  8*w  20;
>  retval(4) = x^2 + 2*y^3 + z  w  4;
>  endfunction
> 
>  x_opt = [ 0.767297326653401, 0.590671081117440, 1.47190018629642,
>  1.52719341133957 ];
>  tol = 1.0e5;
>  [x, fval, info, out] = fsolve (@f, [1, 1, 2, 1])
>  [x, fval, info, out] = fsolve (@f, [1, 1, 2, 1], optimset
>  ("Updating", "off"))
>
> In this test, what is the purpose of tol? I think that confused me as
> well as I didn't notice at first that it is unused. Was it intended
> to be used in some way?
>
I think in the test tol is used in the subsequent assert statements.
Here, it remained just because I lazily copied the code.
Maybe the tests should be modified so that they reflect fsolve's
terminating condition. That needs querying the jacobian.
>  PS. I'll also commit the patch to make optimset/optimget case insensitive.
>
> OK.
>
I slightly hesitated with this  what, in your opinion, is the better
way to proceed?
1. let both optimset & optimget convert their args to lowercase.
2. leave optimset untouched, and write optimget in such a way that the
query is caseinsensitive.
1. is easier and faster, because 2. probably requires looping through
the fields, but does not preserve case of options set.
> Thanks,
>
> jwe
>

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 29Jan2009, Jaroslav Hajek wrote:
 On Thu, Jan 29, 2009 at 8:57 PM, John W. Eaton < [hidden email]> wrote:
 > On 28Jan2009, Jaroslav Hajek wrote:
 >
 >  PS. I'll also commit the patch to make optimset/optimget case insensitive.
 >
 > OK.
 >

 I slightly hesitated with this  what, in your opinion, is the better
 way to proceed?

 1. let both optimset & optimget convert their args to lowercase.
 2. leave optimset untouched, and write optimget in such a way that the
 query is caseinsensitive.

 1. is easier and faster, because 2. probably requires looping through
 the fields, but does not preserve case of options set.
I don't think that Matlab preserves the case of the options set, but
you do have to be able to set and query in a case insensitive way.
I think it always uses "TolX". But unless it is expected that users
will access the fields directory with struct indexing operations
then I don't see why the internal names have to use StudlyCaps. But
if it is necessary to be able to do things like
opts = optimget ();
opts.TolX = foobar;
fsolve (..., opts);
(and I guess I would expect there to be some code out there that works
this way) then I guess we are stuck with the exact names they choose.
jwe


On Thu, Jan 29, 2009 at 9:24 PM, John W. Eaton < [hidden email]> wrote:
> On 29Jan2009, Jaroslav Hajek wrote:
>
>  On Thu, Jan 29, 2009 at 8:57 PM, John W. Eaton < [hidden email]> wrote:
>  > On 28Jan2009, Jaroslav Hajek wrote:
>  >
>  >  PS. I'll also commit the patch to make optimset/optimget case insensitive.
>  >
>  > OK.
>  >
> 
>  I slightly hesitated with this  what, in your opinion, is the better
>  way to proceed?
> 
>  1. let both optimset & optimget convert their args to lowercase.
>  2. leave optimset untouched, and write optimget in such a way that the
>  query is caseinsensitive.
> 
>  1. is easier and faster, because 2. probably requires looping through
>  the fields, but does not preserve case of options set.
>
> I don't think that Matlab preserves the case of the options set, but
> you do have to be able to set and query in a case insensitive way.
>
>
> I think it always uses "TolX". But unless it is expected that users
> will access the fields directory with struct indexing operations
> then I don't see why the internal names have to use StudlyCaps.
OK.
> But if it is necessary to be able to do things like
>
> opts = optimget ();
> opts.TolX = foobar;
>
> fsolve (..., opts);
>
> (and I guess I would expect there to be some code out there that works
> this way) then I guess we are stuck with the exact names they choose.
>
> jwe
>
I think the options should only be accessed via optimget/optimset, so
we don't need to support code like the above. Fix is trivial, after
all.
cheers

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 29Jan2009, Jaroslav Hajek wrote:
 I think the options should only be accessed via optimget/optimset, so
 we don't need to support code like the above. Fix is trivial, after
 all.
Is there anything preventing users from doing things like
opts = optimget ();
opts.TolX = foobar;
fsolve (..., opts);
? If not, then I suspect we should allow this to work in Octave as
well. At least when the structure is returned this way, I think we
are stuck with the exact spelling of the structure fields that
Matlab's optimset uses.
jwe


On Thu, Jan 29, 2009 at 9:55 PM, John W. Eaton < [hidden email]> wrote:
> On 29Jan2009, Jaroslav Hajek wrote:
>
>  I think the options should only be accessed via optimget/optimset, so
>  we don't need to support code like the above. Fix is trivial, after
>  all.
>
> Is there anything preventing users from doing things like
>
> opts = optimget ();
> opts.TolX = foobar;
>
> fsolve (..., opts);
>
You mean something else that this won't work if we make the first
choice from my earlier list?
> ? If not, then I suspect we should allow this to work in Octave as
> well. At least when the structure is returned this way, I think we
> are stuck with the exact spelling of the structure fields that
> Matlab's optimset uses.
>
So, you're voting for choice 2? Make just optimget queries to be case
insensitive? I'm a little confused now.
> jwe
>

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 29Jan2009, Jaroslav Hajek wrote:
 So, you're voting for choice 2? Make just optimget queries to be case
 insensitive? I'm a little confused now.
No, they both need to be case insensitive. So all of
optimset ('tolx', ...)
optimset ('TolX', ...)
optimset ('TOLX', ...)
should work and set the same internal variable. Similarly, all of
optimget (opts, 'tolx')
optimget (opts, 'TolX')
optimget (opts, 'TOLX')
should work and retrieve the same internal variable value. But a call
like
x = optimset ();
should return a structure with the field 'TolX' (not 'tolx' or 'TOLX').
Otherwise, code like I showed earlier will fail, because accessing
structure fields directly is a casesensitive operation. And if there
is nothing preventing users from doing
opts = optimset ();
opts.TolX = foobar;
fsolve (..., opts);
then I'm sure they will do it. So we might as well allow this now
while we are thinking about it rather than wait for a bug report.
jwe


On Thu, Jan 29, 2009 at 10:09 PM, John W. Eaton < [hidden email]> wrote:
> On 29Jan2009, Jaroslav Hajek wrote:
>
>  So, you're voting for choice 2? Make just optimget queries to be case
>  insensitive? I'm a little confused now.
>
> No, they both need to be case insensitive. So all of
>
> optimset ('tolx', ...)
> optimset ('TolX', ...)
> optimset ('TOLX', ...)
>
> should work and set the same internal variable. Similarly, all of
>
> optimget (opts, 'tolx')
> optimget (opts, 'TolX')
> optimget (opts, 'TOLX')
>
> should work and retrieve the same internal variable value. But a call
> like
>
> x = optimset ();
>
This call returns an empty structure. What do you mean?
> should return a structure with the field 'TolX' (not 'tolx' or 'TOLX').
> Otherwise, code like I showed earlier will fail, because accessing
> structure fields directly is a casesensitive operation. And if there
> is nothing preventing users from doing
>
> opts = optimset ();
> opts.TolX = foobar;
>
> fsolve (..., opts);
>
> then I'm sure they will do it. So we might as well allow this now
> while we are thinking about it rather than wait for a bug report.
>
If you want to allow this, then I see no other way than make optimget
do a caseinsensitive lookup of the fields. In that case, it is
irrelevant what case will optimset use.
> jwe
>

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 29Jan2009, Jaroslav Hajek wrote:
 On Thu, Jan 29, 2009 at 10:09 PM, John W. Eaton < [hidden email]> wrote:
 > On 29Jan2009, Jaroslav Hajek wrote:
 >
 >  So, you're voting for choice 2? Make just optimget queries to be case
 >  insensitive? I'm a little confused now.
 >
 > No, they both need to be case insensitive. So all of
 >
 > optimset ('tolx', ...)
 > optimset ('TolX', ...)
 > optimset ('TOLX', ...)
 >
 > should work and set the same internal variable. Similarly, all of
 >
 > optimget (opts, 'tolx')
 > optimget (opts, 'TolX')
 > optimget (opts, 'TOLX')
 >
 > should work and retrieve the same internal variable value. But a call
 > like
 >
 > x = optimset ();
 >

 This call returns an empty structure. What do you mean?
Don't empty values specify defaults? Does anything prevent me from
using
x = optimset ();
x.TolX = ...;
x.SomeOtherOption = ...;
fsolve (..., x);
to set the options fields by doing direct structure field assignment
instead of using optimset to set the options?
 If you want to allow this, then I see no other way than make optimget
 do a caseinsensitive lookup of the fields. In that case, it is
 irrelevant what case will optimset use.
I don't understand what you mean by "it is irrelevant what case ...".
Doesn't optimset also have to work in a case insensitive way? But
when it returns the struct containing the optoins, the fields must
have the TolX style names, right? They can't be spelled any other
way, or code like I posted will fail.
I don't think I can explain any more clearly how I think thse
functions must work, so I guess you should just commit a patch and
I'll see if it works the way I expect.
jwe

Administrator

On 29Jan2009, John W. Eaton wrote:
 On 29Jan2009, Jaroslav Hajek wrote:

  > x = optimset ();
  >
 
  This call returns an empty structure. What do you mean?
OK, this may be part of the confusion. In Matlab, I think this
returns a structure with all the known options as fields, but each has
the value of an empty matrix. But in Octave, we are returning a
structure with no fields. Should we be compatible here? How would
optimset know about all options used by all optimization functions
that can accept options structures as arguments? I would prefer to
avoid embedding that knowlege directly in optimset if possible.
 I don't understand what you mean by "it is irrelevant what case ...".
 Doesn't optimset also have to work in a case insensitive way? But
 when it returns the struct containing the optoins, the fields must
 have the TolX style names, right? They can't be spelled any other
 way, or code like I posted will fail.
OK, it occurred to me that even if the structure is returned with the
TolX style names, doing something like
x.tolx = foobar;
will not actually fail. But this could cause some confusion. What
would a caseinsensitive optimget do if there are two field names that
differ only by case?
jwe


On Thu, Jan 29, 2009 at 10:38 PM, John W. Eaton < [hidden email]> wrote:
> On 29Jan2009, John W. Eaton wrote:
>
>  On 29Jan2009, Jaroslav Hajek wrote:
> 
>   > x = optimset ();
>   >
>  
>   This call returns an empty structure. What do you mean?
>
> OK, this may be part of the confusion. In Matlab, I think this
> returns a structure with all the known options as fields, but each has
> the value of an empty matrix. But in Octave, we are returning a
> structure with no fields. Should we be compatible here?
We've discussed this some time ago and IIRC you agreed with me. The
problem is that if
optimset always sets all possible optimization options (and there are
scors of them in Matlab),
the result is not visually inspectible (at least not in the console).
When I'm setting options for, say, fzero, like opts = optimset("TolX",
1e6, "MaxIter", 1e7),
when I display opts, I want to see what options I set. I'm not
interested in the fact that
MaxPCGIter and JacobianSparsityPattern or whatever are not set,
because they don't even make sense for fzero.
Maybe in the Matlab GUI, a struct with lots of empty ([]) fields can
be displayed so that the empty fields don't clutter the rest, but in
console, it hurts. The fact that Matlab is disregrading the console a
little is an old story.
What's more illogical, optimset ('fzero') and similar calls in fact do
*not* return the empty fields set, just like we do. Apparently here
someone thought a little more about it.
I say, don't copy this behaviour of Matlab. It's stupid.
See
http://www.nabble.com/3.2statusreporttd18740866.html#a18854563> How would
> optimset know about all options used by all optimization functions
> that can accept options structures as arguments? I would prefer to
> avoid embedding that knowlege directly in optimset if possible.
>
Unless you make the set of all possible options somehow accessible to optimset,
I don't think there's any way to make opt = optimset('tolx', 1e6)
actually set opt.TolX.
But I think there's a more elegant way than simply embedding a list somewhere.
I'll try to create a patch.
>  I don't understand what you mean by "it is irrelevant what case ...".
>  Doesn't optimset also have to work in a case insensitive way? But
>  when it returns the struct containing the optoins, the fields must
>  have the TolX style names, right? They can't be spelled any other
>  way, or code like I posted will fail.
>
> OK, it occurred to me that even if the structure is returned with the
> TolX style names, doing something like
>
> x.tolx = foobar;
>
> will not actually fail. But this could cause some confusion. What
> would a caseinsensitive optimget do if there are two field names that
> differ only by case?
>
Yes, there's no way around this. This is going to be ignored in Matlab, too.
> jwe
>

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz


On Fri, Jan 30, 2009 at 7:29 AM, Jaroslav Hajek < [hidden email]> wrote:
> On Thu, Jan 29, 2009 at 10:38 PM, John W. Eaton < [hidden email]> wrote:
>> On 29Jan2009, John W. Eaton wrote:
>>
>>  On 29Jan2009, Jaroslav Hajek wrote:
>> 
>>   > x = optimset ();
>>   >
>>  
>>   This call returns an empty structure. What do you mean?
>>
>> OK, this may be part of the confusion. In Matlab, I think this
>> returns a structure with all the known options as fields, but each has
>> the value of an empty matrix. But in Octave, we are returning a
>> structure with no fields. Should we be compatible here?
>
> We've discussed this some time ago and IIRC you agreed with me. The
> problem is that if
> optimset always sets all possible optimization options (and there are
> scors of them in Matlab),
> the result is not visually inspectible (at least not in the console).
> When I'm setting options for, say, fzero, like opts = optimset("TolX",
> 1e6, "MaxIter", 1e7),
> when I display opts, I want to see what options I set. I'm not
> interested in the fact that
> MaxPCGIter and JacobianSparsityPattern or whatever are not set,
> because they don't even make sense for fzero.
> Maybe in the Matlab GUI, a struct with lots of empty ([]) fields can
> be displayed so that the empty fields don't clutter the rest, but in
> console, it hurts. The fact that Matlab is disregrading the console a
> little is an old story.
> What's more illogical, optimset ('fzero') and similar calls in fact do
> *not* return the empty fields set, just like we do. Apparently here
> someone thought a little more about it.
> I say, don't copy this behaviour of Matlab. It's stupid.
>
> See
> http://www.nabble.com/3.2statusreporttd18740866.html#a18854563>
>
>> How would
>> optimset know about all options used by all optimization functions
>> that can accept options structures as arguments? I would prefer to
>> avoid embedding that knowlege directly in optimset if possible.
>>
>
> Unless you make the set of all possible options somehow accessible to optimset,
> I don't think there's any way to make opt = optimset('tolx', 1e6)
> actually set opt.TolX.
> But I think there's a more elegant way than simply embedding a list somewhere.
> I'll try to create a patch.
>
And here it is (attached).
Summary:
There is an internal function __all_opts__ that returns all
"registered" options sorted in alphabetical caseinsensitive order.
Options are registered by querying the default options from a
function. Octave's existing optim function are queried by default at
startup, and more can be added at runtime by giving the function names
as arguments (for instance from OctaveForge using PKG_ADD).
optimset and optimget always obtain the list of registered options
from this function, then for each option being set/get, they look up a
caseinsensitive match and replace if available, otherwise warn that
the option is unregistered.
This keeps both optimget & optimset case insensitive and also gives
warning for misspelled options.
Options directly assigned with incorrect casing (like "opts.tolx =
1e2") will be ignored (like in Matlab).
The only incompatibility with Matlab is that we won't add fields
corresponding to unset options, so that the resulting struct remains
readable.
Comments? OK to push?
cheers

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

Administrator

On 30Jan2009, Jaroslav Hajek wrote:
 On Fri, Jan 30, 2009 at 7:29 AM, Jaroslav Hajek < [hidden email]> wrote:
 > On Thu, Jan 29, 2009 at 10:38 PM, John W. Eaton < [hidden email]> wrote:
 >> On 29Jan2009, John W. Eaton wrote:
 >>
 >>  On 29Jan2009, Jaroslav Hajek wrote:
 >> 
 >>   > x = optimset ();
 >>   >
 >>  
 >>   This call returns an empty structure. What do you mean?
 >>
 >> OK, this may be part of the confusion. In Matlab, I think this
 >> returns a structure with all the known options as fields, but each has
 >> the value of an empty matrix. But in Octave, we are returning a
 >> structure with no fields. Should we be compatible here?
 >
 > We've discussed this some time ago and IIRC you agreed with me. The
 [...]
 > See
 > http://www.nabble.com/3.2statusreporttd18740866.html#a18854563OK. I'm not sure I completely understood how Matlab's optimset worked
then. But OK, it does seem clear to me that the intent is for these
options to be managed by the optimget and optimset funtions and not by
manipulating the structure elements directly. I guess we'll see how
many complaints we get for this incompatibility. If there are not too
many, I suppose we can tell people to use the optimget and optimset
functions. But we may have to reconsider if manipulating the struct
directly turns out to be common and there are lots of complaints.
 And here it is (attached).
 Summary:

 There is an internal function __all_opts__ that returns all
 "registered" options sorted in alphabetical caseinsensitive order.
 Options are registered by querying the default options from a
 function. Octave's existing optim function are queried by default at
 startup, and more can be added at runtime by giving the function names
 as arguments (for instance from OctaveForge using PKG_ADD).
I'm slightly confused here. What function accepts the function names
as arguments? Maybe instead of including the initial list directly in
fzero, fsolve lsqnonneg, these should also be added using PKG_ADD?
Then each of these functions would not have special treatment, and the
PKG_ADD line in each of them would serve as an example of how to
properly add an optimization function to the list.
 optimset and optimget always obtain the list of registered options
 from this function, then for each option being set/get, they look up a
 caseinsensitive match and replace if available, otherwise warn that
 the option is unregistered.

 This keeps both optimget & optimset case insensitive and also gives
 warning for misspelled options.
 Options directly assigned with incorrect casing (like "opts.tolx =
 1e2") will be ignored (like in Matlab).
 The only incompatibility with Matlab is that we won't add fields
 corresponding to unset options, so that the resulting struct remains
 readable.

 Comments? OK to push?
Yes. I see one other small problem. You have
## Display possibilities.
tmp = opts';
disp (struct (tmp{:}));
in optimset, but that prints
{
FunValCheck = Jacobian
MaxFunEvals = MaxIter
OutputFcn = TolFun
TolX = Updating
}
How about changing it to
## Display possibilities.
puts ("\nAll possible optimization options:\n\n");
printf (" %s\n", opts{:});
puts ("\n");
?
Other than that I think this is a good solution.
Thanks,
jwe


On Fri, Jan 30, 2009 at 4:55 PM, John W. Eaton < [hidden email]> wrote:
> On 30Jan2009, Jaroslav Hajek wrote:
>
>  On Fri, Jan 30, 2009 at 7:29 AM, Jaroslav Hajek < [hidden email]> wrote:
>  > On Thu, Jan 29, 2009 at 10:38 PM, John W. Eaton < [hidden email]> wrote:
>  >> On 29Jan2009, John W. Eaton wrote:
>  >>
>  >>  On 29Jan2009, Jaroslav Hajek wrote:
>  >> 
>  >>   > x = optimset ();
>  >>   >
>  >>  
>  >>   This call returns an empty structure. What do you mean?
>  >>
>  >> OK, this may be part of the confusion. In Matlab, I think this
>  >> returns a structure with all the known options as fields, but each has
>  >> the value of an empty matrix. But in Octave, we are returning a
>  >> structure with no fields. Should we be compatible here?
>  >
>  > We've discussed this some time ago and IIRC you agreed with me. The
>  [...]
>  > See
>  > http://www.nabble.com/3.2statusreporttd18740866.html#a18854563>
> OK. I'm not sure I completely understood how Matlab's optimset worked
> then. But OK, it does seem clear to me that the intent is for these
> options to be managed by the optimget and optimset funtions and not by
> manipulating the structure elements directly. I guess we'll see how
> many complaints we get for this incompatibility. If there are not too
> many, I suppose we can tell people to use the optimget and optimset
> functions. But we may have to reconsider if manipulating the struct
> directly turns out to be common and there are lots of complaints.
>
Technically, there is no incompatibility. In Matlab, you can also set
a field directly, and if you use invalid case, the field will be
silently ignored. We can only try to be smarter than Matlab, and, for
instance, check for the condition in optimget, but I think we should
discourage direct manipulation of the struct anyway.
>  And here it is (attached).
>  Summary:
> 
>  There is an internal function __all_opts__ that returns all
>  "registered" options sorted in alphabetical caseinsensitive order.
>  Options are registered by querying the default options from a
>  function. Octave's existing optim function are queried by default at
>  startup, and more can be added at runtime by giving the function names
>  as arguments (for instance from OctaveForge using PKG_ADD).
>
> I'm slightly confused here. What function accepts the function names
> as arguments?
__all_opts__ ('optimfunc')
will call optimfunc('defaults') and then add all the options.
> Maybe instead of including the initial list directly in
> fzero, fsolve lsqnonneg, these should also be added using PKG_ADD?
> Then each of these functions would not have special treatment, and the
> PKG_ADD line in each of them would serve as an example of how to
> properly add an optimization function to the list.
That's a good idea. I forgot Octave can have its own PKG_ADD commands.
This also simplifies the function nicely. So, right now,
optimization/PKG_ADD contains
__all_opts__ ("fzero", "fsolve", "lsqnonneg");
which registers all their options.
>
>  optimset and optimget always obtain the list of registered options
>  from this function, then for each option being set/get, they look up a
>  caseinsensitive match and replace if available, otherwise warn that
>  the option is unregistered.
> 
>  This keeps both optimget & optimset case insensitive and also gives
>  warning for misspelled options.
>  Options directly assigned with incorrect casing (like "opts.tolx =
>  1e2") will be ignored (like in Matlab).
>  The only incompatibility with Matlab is that we won't add fields
>  corresponding to unset options, so that the resulting struct remains
>  readable.
> 
>  Comments? OK to push?
>
> Yes. I see one other small problem. You have
>
> ## Display possibilities.
> tmp = opts';
> disp (struct (tmp{:}));
>
> in optimset, but that prints
>
> {
> FunValCheck = Jacobian
> MaxFunEvals = MaxIter
> OutputFcn = TolFun
> TolX = Updating
> }
>
> How about changing it to
>
> ## Display possibilities.
> puts ("\nAll possible optimization options:\n\n");
> printf (" %s\n", opts{:});
> puts ("\n");
>
> ?
>
Done.
> Other than that I think this is a good solution.
>
> Thanks,
>
> jwe
>
OK, I pushed the changeset.
regards

RNDr. Jaroslav Hajek
computing expert
Aeronautical Research and Test Institute (VZLU)
Prague, Czech Republic
url: www.highegg.matfyz.cz

12
