octave-maintainers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Patch to residue.m


From: Daniel J Sebald
Subject: Re: Patch to residue.m
Date: Mon, 31 Dec 2007 10:51:27 -0600
User-agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.3) Gecko/20041020

Ben Abbott wrote:

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.

Perhaps that is an issue.


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!

Well, the improvement from averaging probably isn't a surprise.  (And one might 
be able to look at the rooting formula and analytically show that the average 
is a good idea.)  The idea of then casting the poles is what worries me because 
maybe the user is dealing with a situation where he or she wouldn't want 
that... but...


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.


...but, now that I think of it, if you are saying there is a root of greater 
than one multiplicity I guess it makes sense that those poles should come back 
as being exactly the same value.


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.

I'm trying to remember back to whether there was ever a discussion here about 
this topic, i.e., when is something considered zero.


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.

Well, that doesn't mean that small = toler = 1e-12.  Perhaps some other value.  
I'm just trying to justify in my mind the need for two tolerance parameters vs. 
one.


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.

I think you are right.  The roots being off by o(1e-5) seems rather poor.  
Averaging gets to o(1e-15) and machine precision is o(1e-16)?  One would think 
maybe o(1e-10) or better is achievable.  Maybe you are trying to improve on 
something that should be addressed elsewhere, and if that where fixed your 
tolerance equations could be simplified.

And considering the cast to zero after multiplicity is determined seems worth 
investigating.

Dan


reply via email to

[Prev in Thread] Current Thread [Next in Thread]