开发者

Fixing the singularity of a function

Assume you have a function like

F = lambda x: sin(x)/x

Evaluating F(0.0) would result in a divide by zero warning, and would not give the expected result of 1.0. Is it possible to write another function fix_singularity that would give the desired result when applied to the above function, so that

fix_singularity(F)(0.0) == 1.0

Or formally fix_singularity should pass the following tests:

import numpy as np

def test_fix_singularity():

    F = lambda x: np.sin(x)/x

    x = np.array((0.0, pi))

    np.testing.assert_array_almost_equal( F(x), [nan, 0] )

    np.testing.assert_array_almost_e开发者_Python百科qual( fix_singularity(F)(x), [1, 0] )

One possible implementation is

def fix_singularity(F):
    """ Fix the singularity of function F(x) """

    def L(x):
        f = F(x)
        i = np.isnan(f)
        f[i] = F(x[i] + 1e-16)
        return f

    return L

Are there better ways of doing this?

EDIT: Also how can I suppress the warning:

Warning: invalid value encountered in divide


numpy has a sinc() function, which is the normalised form of your function, i.e.

F = lambda x: sin(pi*x) / (pi*x)

It handles the case for x == 0.0 correctly,

In [16]: x = numpy.linspace(-1,1,11)

In [17]: print x
[-1.  -0.8 -0.6 -0.4 -0.2  0.   0.2  0.4  0.6  0.8  1. ]

To "unnormalize" do,

In [22]: s = numpy.sinc(x/numpy.pi)

In [23]: print s.round(2)
[ 0.84  0.9   0.94  0.97  0.99  1.    0.99  0.97  0.94  0.9   0.84]


If you are already using numpy then:

a = np.linspace(0.0,2*np.pi,100)
b = np.sin(a)/a

Will calculate without error leaving a NaN value in b[0]. You could then just replace it by the following if that's how you want to handle it:

b[np.isnan(b)] = 1.0

Update To suppress the warning, try:

np.seterr(divide='ignore') # Or possibly np.seterr(invalid='ignore')


In general you can't write a simple fix decorator as you might imagine. For example, a general function need not have a finite limiting value at a singularity as this particular example does.

Normal practice is to implement special handling on a case by case basis.


I'll try this

>>> def fix_singularity(F):
...     def L(x):
...         x1 = max(x,1e-16) if x >=0 else min(x,-1e-16)
...         return F(x1)
...     return L
...
>>> FS = fix_singularity(F)
>>> FS(0.0)
1.0
>>> FS(-1e-17)
1.0


I don't know if this would work for your exact purposes, but there's a python library called sage that can handle quite a bit of Calculus-type situations.


I believe sympy (symbolic python) can do limits, which is what you are really asking (that solution is only true as a limit). Regardless, you should check it out.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜