Patch to residue.m

Ben Abbott bpabbott at mac.com
Mon Dec 31 03:26:11 CST 2007


On Dec 31, 2007, at 12:04 PM, Daniel J Sebald wrote:

> Ben Abbott wrote:
>> Please consider this patch to residue.m which improves its  
>> accuracy  when pole multiplicity exists.
>> To capture the improvement, the test scripts were also modified to  
>> be  more stringent.
>
> Ben,
>
> This looks like not too much of a change.  Still, a few questions.   
> Why the change?  What motivated this?  Just improving your code?  Or  
> did you find an example that was failing?  (If so, give us the  
> example.)
>
> Observations:
>
> 1) Extra space in "group of pole  multiplicity,"
>
> 2)  p_group = cumsum (e == 1);
>   for ng = 1:max(p_group)
>
> Since (e == 1) is strictly non-negative, rather than max(p_group) it  
> could be p_group(end).  That is more efficient, but of course the  
> polynomial order is quite small so it doesn't really matter.

I'd not come across the "end" functionality before. Very cool! ... I  
was unhappy with p_group(numel(p_group)).

>
> 3)  Could you explain the reasoning of the various tolerance  
> parameters in the code?  For example, I see this code for  
> determining if a pole is zero or not:
>
> small = max (abs (p));
> small = max ([small, 1] ) * 1e-12 * (1 + numel (p))^2;
> p(abs (p) < small) = 0;
>
> I'm don't understand what the (1 + numel (p))^2 does.  The more  
> poles there are, the larger the tolerance becomes?  Also, might you  
> want to define 1e-12 with respect to the machine precision, say
>
> small = max ([small, 1]) * eps*1e4 * (1 + numel (p))^2;

Good point.

> (On my machine,
>
> octave:14> eps
> ans =  2.2204e-16
>
> so that eps*1e4 is about 1e-12.
> Why is it important to cast poles to 0?  Is there something later in  
> the code that depends on that?

I don't find the part concerning zero, pure real, pure imaginary poles  
well thought out. However, since it was there before, and others have  
expressed a desire for such checks, I've left it alone. In any event,  
the tolerance is small enough that I don't think it makes any  
numerical difference.

> Now, here is the part I'm not so comfortable with.  There is the  
> code above that says a pole is zero if it is within ~1e-12 of zero.   
> But shortly thereafter the code does this:
>
> [e, indx] = mpoles (p, toler, 1);
>
> where poles within "toler" (in the code it is set to 0.001) are  
> equal.  One case is a more strict requirement to be declared 0 than  
> the other case of declaring two poles equal.  It's just slightly  
> strange.  Doesn't that seem a contradiction somehow?

The problem is that as multiplicity increases, the location of the  
poles become numerically difficult to determine. When the multiplicity  
is unity, a relative tolerance of 1e-12 is possible. However, as the  
multiplicity increases, numerical errors increase as well. The values  
of "toler" and "small" were determined by empirical means (experience  
and testing). I tried to make them as small as was comfortable.

However, I must admit your questions have made me re-examine this  
subject, and it does appear that the checks for zero valued, real  
valued, and imaginary valued poles  should be done *after* the  
multiplicity has been determined ... if they are to be done at all.

> I'm not sure I'm comfortable with averaging the poles either:
>
>   p(m) = mean (p(m));
>
> From a practical standpoint it may be a good idea, but from a  
> numerical standpoint it seems a little unorthodox.  I'd say let the  
> numerical effects remain and let the end user decide what to do.   
> Why is this needed?

I'll give a very simple example.

octave:20> p = [3;3;3];
octave:21> a = poly(p)
a =

     1   -9   27  -27

octave:22> roots(a)
ans =

    3.0000 + 0.0000i
    3.0000 + 0.0000i
    3.0000 - 0.0000i

octave:23> roots(a)-p
ans =

   3.3231e-05 + 0.0000e+00i
   -1.6615e-05 + 2.8778e-05i
   -1.6615e-05 - 2.8778e-05i

octave:24> mean(roots(a))-p
ans =

    1.7764e-15
    1.7764e-15
    1.7764e-15

Thus the error from "roots" is about 1e-5 for each root. However, the  
error for the average is about 10 orders of magnitude less!

To be honest, I began from your position and was sure that taking the  
mean would not ensure an improvement in the result. Doug was certain  
otherwise. So I decided to justify my skepticism by designing an  
example, where I stacked the cards in my favor.

To my surprise, I failed. All tests confirmed Doug's conclusion. If  
you can devise an example that succeeds where I failed, I'd love to  
see it!

>  I suppose you are dealing with finding higher order residues,

Yes.

> but could you compute the mean value for use in the rest of the  
> routine but leave the values non-averaged when returned from the  
> routine?  What is the user expecting?

No, at least I don't think so. The residues and poles are uniquely  
paired. The returned residues should be paired with the returned  
poles. Regarding what the user expects, a better question would be  
what does the documentation reflect, and is it consistent with Matlab.  
Regarding the returned variable, they are consistent with the  
documentation and with Matlab.

> I guess my main concerns are 1) is there a standard way of dealing  
> with "nearly zero" in Octave?  Should "toler" be replaced by "small"?

Regarding "near zero" ... I don't know how to properly determine what  
is "nearly zero", but would appreciate anyone telling us/me how.

Regarding, "toler" and "small" these two have two different purposes.  
"toler" is used to determine the pole multiplicity and "small" is used  
to round off to zero, pure real, or pure imaginary values. If "toler"  
is replace by "small" there will be no multiplicity of poles. So I  
don't think that is practical.

What we really need is numerically more accurate method for  
determining the roots. This entire discussion is the consequence of  
inaccurate roots. So if we are to address the ills of residue.m, a  
better roots.m will be needed, in my opinion anyway.

Ben

p.s. I'll incorporate the changes and post an update to the patch.





-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://www.cae.wisc.edu/pipermail/octave-maintainers/attachments/20071231/71394f8d/attachment-0001.html 


More information about the Octave-maintainers mailing list